netgen-6.2.1905/0000755000175000017500000000000013504650527012001 5ustar kurtkurtnetgen-6.2.1905/tutorials/0000755000175000017500000000000013504650527014027 5ustar kurtkurtnetgen-6.2.1905/tutorials/cubemcyl.geo0000644000175000017500000000062713504650527016333 0ustar kurtkurt# ## Cube minus Cylinder # algebraic3d solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid cyl = cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.03); # cut off small cylinder from cube: solid main = cube and not cyl; tlo main; netgen-6.2.1905/tutorials/ellipsoid.geo0000644000175000017500000000017313504650527016510 0ustar kurtkurt# ## An elliptic cylinder # algebraic3d solid test = ellipsoid (0, 0, 0; 2, 0, 0; 0, 1, 0; 0, 0, 1) -maxh=0.5; tlo test; netgen-6.2.1905/tutorials/sphereincube.geo0000644000175000017500000000063613504650527017204 0ustar kurtkurtalgebraic3d # # Example with two sub-domains: # solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid sph = sphere (0.5, 0.5, 0.5; 0.3); solid rest = cube and not sph; tlo rest -transparent -col=[0,0,1]; tlo sph -col=[1,0,0]; netgen-6.2.1905/tutorials/ellipticcone.geo0000644000175000017500000000154013504650527017175 0ustar kurtkurt# ## An elliptic cone # # An elliptic cone, given by the point c = (c x , c y , c z ) at the base of the cone along the main axis, # the vectors v and w of the long and short axis of the ellipse, respectively, # the height of the cone, h, and ratio of base long axis length to top long axis length, r: # ellipticcone (c x , c y , c z ; v x , v y , v z ; w x , w y , w z; h; r) # Note: The elliptic cone has to be truncated by planes similar to a cone or an elliptic cylinder. # When r =1, the truncated elliptic cone becomes an elliptic cylinder. # When r tends to zero, the truncated elliptic cone tends to a full elliptic cone. # However, when r = 0, the top part becomes a point(tip) and meshing fails! algebraic3d solid cutcone = ellipticcone ( 0, 0, 0; 5, 0, 0; 0, 2, 0; 5; 0.5) and plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 5; 0, 0, 1); tlo cutcone; netgen-6.2.1905/tutorials/lense.in2d0000644000175000017500000000240613504650527015715 0ustar kurtkurtsplinecurves2dv2 5 points 1 -1.0 -1.0 2 -1.0 1.0 3 0.0 1.0 4 1.0 1.0 5 1.0 -1.0 6 0.0 -1.0 segments 0 1 2 6 1 -bc=1 0 1 2 1 2 -bc=1 0 1 2 2 3 -bc=1 0 2 2 3 4 -bc=1 0 2 2 4 5 -bc=1 0 2 2 5 6 -bc=1 1 3 bsplinepoints 21 4 0 -1.0000 -0.0380 -0.9000 -0.0720 -0.8000 -0.1020 -0.7000 -0.1280 -0.6000 -0.1500 -0.5000 -0.1680 -0.4000 -0.1820 -0.3000 -0.1920 -0.2000 -0.1980 -0.1000 -0.2000 0 -0.1980 0.1000 -0.1920 0.2000 -0.1820 0.3000 -0.1680 0.4000 -0.1500 0.5000 -0.1280 0.6000 -0.1020 0.7000 -0.0720 0.8000 -0.0380 0.9000 0 1.0000 -bc=2 -maxh=0.1 3 2 bsplinepoints 21 3 0 -1.0000 0.0380 -0.9000 0.0720 -0.8000 0.1020 -0.7000 0.1280 -0.6000 0.1500 -0.5000 0.1680 -0.4000 0.1820 -0.3000 0.1920 -0.2000 0.1980 -0.1000 0.2000 0 0.1980 0.1000 0.1920 0.2000 0.1820 0.3000 0.1680 0.4000 0.1500 0.5000 0.1280 0.6000 0.1020 0.7000 0.0720 0.8000 0.0380 0.9000 0 1.0000 -bc=2 -maxh=0.1 materials 1 domain1 -maxh=0.2 2 domain2 -maxh=0.2 3 domain3 -maxh=0.2 netgen-6.2.1905/tutorials/ortho.geo0000644000175000017500000000016313504650527015656 0ustar kurtkurt# ## A cube # algebraic3d # cube consisting of 6 planes: solid cube = orthobrick (0, 0, 0; 1, 1, 1); tlo cube; netgen-6.2.1905/tutorials/lshape3d.geo0000644000175000017500000000063013504650527016225 0ustar kurtkurtalgebraic3d # ## 3D Lshape - domain # solid c1 = plane (-1, -1, 0; 0, 0, -1) and plane (-1, -1, 0; 0, -1, 0) and plane (-1, -1, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid f1 = plane (0, 0, 0; -1, 0, 0); solid f2 = plane (0, 0, 0; 0, 1, 0); solid main = c1 and not (f1 and f2); tlo main; netgen-6.2.1905/tutorials/cone.geo0000644000175000017500000000033413504650527015447 0ustar kurtkurt# ## A cone # algebraic3d # Cone given by bottom circle and top circle # and cut by planes: solid cutcone = cone ( 0, 0, 0; 1; 3, 0, 0; 0.1 ) and plane (0, 0, 0; -1, 0, 0) and plane (3, 0, 0; 1, 0, 0); tlo cutcone; netgen-6.2.1905/tutorials/screw.step0000755000175000017500000025475013504650527016067 0ustar kurtkurtISO-10303-21; HEADER; FILE_DESCRIPTION(('a Product shape'),'1'); FILE_NAME('Euclid Shape Model','1998-09-10T11:25:01',('Author Name'),( 'MATRA-DATAVISION'),'OL-2.0B','EUCLID','Authorisation status'); FILE_SCHEMA(('AUTOMOTIVE_DESIGN_CC1 { 1 2 10303 214 -1 1 3 2}')); ENDSEC; DATA; #1 = PRODUCT_RELATED_PRODUCT_CATEGORY('Undefined Category','Undefined De scription',(#2)); #2 = PRODUCT('the product name','the product name','void',(#3)); #3 = MECHANICAL_CONTEXT('Mechanical',#4,'Assembly'); #4 = APPLICATION_CONTEXT('EUCLID'); #5 = APPLICATION_PROTOCOL_DEFINITION('CommitteeDraft','automotive_design ',1997,#4); #6 = SHAPE_DEFINITION_REPRESENTATION(#7,#11); #7 = PRODUCT_DEFINITION_SHAPE('void','void',#8); #8 = PRODUCT_DEFINITION('void','void',#9,#10); #9 = PRODUCT_DEFINITION_FORMATION('ID','void',#2); #10 = PRODUCT_DEFINITION_CONTEXT('as proposed',#4,'First_Design'); #11 = ADVANCED_BREP_SHAPE_REPRESENTATION('',(#12),#1236); #12 = MANIFOLD_SOLID_BREP('',#13); #13 = CLOSED_SHELL('',(#14,#257,#558,#709,#803,#874,#944,#1052,#1151, #1232)); #14 = ADVANCED_FACE('',(#15),#49,.F.); #15 = FACE_BOUND('',#16,.F.); #16 = EDGE_LOOP('',(#17,#136,#186,#214)); #17 = ORIENTED_EDGE('',*,*,#18,.T.); #18 = EDGE_CURVE('',#19,#21,#23,.T.); #19 = VERTEX_POINT('',#20); #20 = CARTESIAN_POINT('',(-27.8196811084,0.423702927757,5.43633)); #21 = VERTEX_POINT('',#22); #22 = CARTESIAN_POINT('',(-7.976546275424,0.423702927757,5.43633)); #23 = SURFACE_CURVE('',#24,(#48,#80),.PCURVE_S2.); #24 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#25,#26,#27,#28,#29,#30,#31,#32, #33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#44,#45,#46,#47), .UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(-9.753048731913, -8.657376849694,-4.328688424847,-2.164344212423,-1.082172106212, 0.E+000,1.082172106212,2.164344212423,4.328688424847,8.657376849694, 9.753048731913),.UNSPECIFIED.); #25 = CARTESIAN_POINT('',(-27.8196811084,0.423702927757,5.43633)); #26 = CARTESIAN_POINT('',(-27.44664177115,0.423702927757,5.566853116015) ); #27 = CARTESIAN_POINT('',(-27.07201055731,0.423702927757,5.693350129935) ); #28 = CARTESIAN_POINT('',(-25.21253263571,0.423702927757,6.298546031822) ); #29 = CARTESIAN_POINT('',(-23.71979442537,0.423702927757,6.713431512354) ); #30 = CARTESIAN_POINT('',(-21.51106042838,0.423702927757,7.221607932559) ); #31 = CARTESIAN_POINT('',(-20.78124758741,0.423702927757,7.372657524772) ); #32 = CARTESIAN_POINT('',(-19.696293462,0.423702927757,7.56017012803)); #33 = CARTESIAN_POINT('',(-19.33642071715,0.423702927757,7.616304970701) ); #34 = CARTESIAN_POINT('',(-18.61775332841,0.423702927757,7.702450972357) ); #35 = CARTESIAN_POINT('',(-18.25883772732,0.423702927757,7.731450038723) ); #36 = CARTESIAN_POINT('',(-17.89811369191,0.423702927757,7.731450038723) ); #37 = CARTESIAN_POINT('',(-17.53738965651,0.423702927757,7.731450038723) ); #38 = CARTESIAN_POINT('',(-17.17847405541,0.423702927757,7.702450972357) ); #39 = CARTESIAN_POINT('',(-16.45980666667,0.423702927757,7.616304970701) ); #40 = CARTESIAN_POINT('',(-16.09993392183,0.423702927757,7.56017012803) ); #41 = CARTESIAN_POINT('',(-15.01497979641,0.423702927757,7.372657524772) ); #42 = CARTESIAN_POINT('',(-14.28516695545,0.423702927757,7.221607932559) ); #43 = CARTESIAN_POINT('',(-12.07643295845,0.423702927757,6.713431512354) ); #44 = CARTESIAN_POINT('',(-10.58369474811,0.423702927757,6.298546031822) ); #45 = CARTESIAN_POINT('',(-8.724216826515,0.423702927757,5.693350129935) ); #46 = CARTESIAN_POINT('',(-8.349585612678,0.423702927757,5.566853116015) ); #47 = CARTESIAN_POINT('',(-7.976546275424,0.423702927757,5.43633)); #48 = PCURVE('',#49,#54); #49 = PLANE('',#50); #50 = AXIS2_PLACEMENT_3D('',#51,#52,#53); #51 = CARTESIAN_POINT('',(-2.898113691917,0.423702927757,7.93633)); #52 = DIRECTION('',(0.E+000,1.,0.E+000)); #53 = DIRECTION('',(0.E+000,0.E+000,1.)); #54 = DEFINITIONAL_REPRESENTATION('',(#55),#79); #55 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#56,#57,#58,#59,#60,#61,#62,#63, #64,#65,#66,#67,#68,#69,#70,#71,#72,#73,#74,#75,#76,#77,#78), .UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),(-9.753048731913, -8.657376849694,-4.328688424847,-2.164344212423,-1.082172106212, 0.E+000,1.082172106212,2.164344212423,4.328688424847,8.657376849694, 9.753048731913),.UNSPECIFIED.); #56 = CARTESIAN_POINT('',(-2.5,-24.92156741649)); #57 = CARTESIAN_POINT('',(-2.369476883985,-24.54852807923)); #58 = CARTESIAN_POINT('',(-2.242979870065,-24.1738968654)); #59 = CARTESIAN_POINT('',(-1.637783968178,-22.31441894379)); #60 = CARTESIAN_POINT('',(-1.222898487646,-20.82168073346)); #61 = CARTESIAN_POINT('',(-0.714722067441,-18.61294673646)); #62 = CARTESIAN_POINT('',(-0.563672475228,-17.88313389549)); #63 = CARTESIAN_POINT('',(-0.37615987197,-16.79817977008)); #64 = CARTESIAN_POINT('',(-0.320025029299,-16.43830702524)); #65 = CARTESIAN_POINT('',(-0.233879027643,-15.71963963649)); #66 = CARTESIAN_POINT('',(-0.204879961277,-15.3607240354)); #67 = CARTESIAN_POINT('',(-0.204879961277,-15.)); #68 = CARTESIAN_POINT('',(-0.204879961277,-14.63927596459)); #69 = CARTESIAN_POINT('',(-0.233879027643,-14.2803603635)); #70 = CARTESIAN_POINT('',(-0.320025029299,-13.56169297476)); #71 = CARTESIAN_POINT('',(-0.37615987197,-13.20182022991)); #72 = CARTESIAN_POINT('',(-0.563672475228,-12.1168661045)); #73 = CARTESIAN_POINT('',(-0.714722067441,-11.38705326353)); #74 = CARTESIAN_POINT('',(-1.222898487646,-9.178319266539)); #75 = CARTESIAN_POINT('',(-1.637783968178,-7.685581056201)); #76 = CARTESIAN_POINT('',(-2.242979870065,-5.826103134599)); #77 = CARTESIAN_POINT('',(-2.369476883985,-5.451471920761)); #78 = CARTESIAN_POINT('',(-2.5,-5.078432583508)); #79 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #80 = PCURVE('',#81,#86); #81 = TOROIDAL_SURFACE('',#82,8.25,54.873718663856); #82 = AXIS2_PLACEMENT_3D('',#83,#84,#85); #83 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-46.31367)); #84 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #85 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016)); #86 = DEFINITIONAL_REPRESENTATION('',(#87),#135); #87 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#88,#89,#90,#91,#92,#93,#94,#95, #96,#97,#98,#99,#100,#101,#102,#103,#104,#105,#106,#107,#108,#109, #110,#111,#112,#113,#114,#115,#116,#117,#118,#119,#120,#121,#122, #123,#124,#125,#126,#127,#128,#129,#130,#131,#132,#133,#134), .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(-9.753048731913, -9.309728335008,-8.866407938103,-8.423087541198,-7.979767144292, -7.536446747387,-7.093126350482,-6.649805953577,-6.206485556672, -5.763165159767,-5.319844762862,-4.876524365957,-4.433203969051, -3.989883572146,-3.546563175241,-3.103242778336,-2.659922381431, -2.216601984526,-1.773281587621,-1.329961190715,-0.88664079381, -0.443320396905,-3.552713678801E-015,0.443320396905,0.88664079381, 1.329961190715,1.773281587621,2.216601984526,2.659922381431, 3.103242778336,3.546563175241,3.989883572146,4.433203969051, 4.876524365957,5.319844762862,5.763165159767,6.206485556672, 6.649805953577,7.093126350482,7.536446747387,7.979767144292, 8.423087541198,8.866407938103,9.309728335008,9.753048731913), .UNSPECIFIED.); #88 = CARTESIAN_POINT('',(1.696124157963,-1.90983622455)); #89 = CARTESIAN_POINT('',(1.698012122136,-1.906942595099)); #90 = CARTESIAN_POINT('',(1.701959356034,-1.901155814072)); #91 = CARTESIAN_POINT('',(1.7084874644,-1.89248391648)); #92 = CARTESIAN_POINT('',(1.715711359905,-1.883824473771)); #93 = CARTESIAN_POINT('',(1.723736411497,-1.875190974748)); #94 = CARTESIAN_POINT('',(1.732699041614,-1.866586665031)); #95 = CARTESIAN_POINT('',(1.742767310299,-1.858016637247)); #96 = CARTESIAN_POINT('',(1.754151612829,-1.849486074495)); #97 = CARTESIAN_POINT('',(1.767118375587,-1.841000912303)); #98 = CARTESIAN_POINT('',(1.782009704244,-1.832567946628)); #99 = CARTESIAN_POINT('',(1.799271790701,-1.824195173621)); #100 = CARTESIAN_POINT('',(1.819496092675,-1.815892420892)); #101 = CARTESIAN_POINT('',(1.843483731328,-1.80767162354)); #102 = CARTESIAN_POINT('',(1.872335628537,-1.799549911231)); #103 = CARTESIAN_POINT('',(1.907592262986,-1.791552841646)); #104 = CARTESIAN_POINT('',(1.951530266856,-1.783707862826)); #105 = CARTESIAN_POINT('',(2.007543357991,-1.776058774724)); #106 = CARTESIAN_POINT('',(2.080862934592,-1.768674005145)); #107 = CARTESIAN_POINT('',(2.179681847184,-1.761668166881)); #108 = CARTESIAN_POINT('',(2.317050874271,-1.755240554276)); #109 = CARTESIAN_POINT('',(2.512524285783,-1.74974343193)); #110 = CARTESIAN_POINT('',(2.788441810662,-1.745797607263)); #111 = CARTESIAN_POINT('',(3.14159265359,-1.744297890708)); #112 = CARTESIAN_POINT('',(3.494743496518,-1.745797607263)); #113 = CARTESIAN_POINT('',(3.770661021397,-1.74974343193)); #114 = CARTESIAN_POINT('',(3.966134432908,-1.755240554276)); #115 = CARTESIAN_POINT('',(4.103503459996,-1.761668166881)); #116 = CARTESIAN_POINT('',(4.202322372587,-1.768674005145)); #117 = CARTESIAN_POINT('',(4.275641949188,-1.776058774724)); #118 = CARTESIAN_POINT('',(4.331655040323,-1.783707862826)); #119 = CARTESIAN_POINT('',(4.375593044193,-1.791552841646)); #120 = CARTESIAN_POINT('',(4.410849678643,-1.799549911231)); #121 = CARTESIAN_POINT('',(4.439701575852,-1.80767162354)); #122 = CARTESIAN_POINT('',(4.463689214504,-1.815892420892)); #123 = CARTESIAN_POINT('',(4.483913516478,-1.824195173621)); #124 = CARTESIAN_POINT('',(4.501175602935,-1.832567946628)); #125 = CARTESIAN_POINT('',(4.516066931592,-1.841000912303)); #126 = CARTESIAN_POINT('',(4.529033694351,-1.849486074495)); #127 = CARTESIAN_POINT('',(4.54041799688,-1.858016637247)); #128 = CARTESIAN_POINT('',(4.550486265566,-1.866586665031)); #129 = CARTESIAN_POINT('',(4.559448895683,-1.875190974748)); #130 = CARTESIAN_POINT('',(4.567473947275,-1.883824473771)); #131 = CARTESIAN_POINT('',(4.57469784278,-1.89248391648)); #132 = CARTESIAN_POINT('',(4.581225951145,-1.901155814072)); #133 = CARTESIAN_POINT('',(4.585173185044,-1.906942595099)); #134 = CARTESIAN_POINT('',(4.587061149217,-1.90983622455)); #135 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #136 = ORIENTED_EDGE('',*,*,#137,.T.); #137 = EDGE_CURVE('',#21,#138,#140,.T.); #138 = VERTEX_POINT('',#139); #139 = CARTESIAN_POINT('',(-10.50301396304,0.423702927757,2.93633)); #140 = SURFACE_CURVE('',#141,(#145,#152),.PCURVE_S2.); #141 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#142,#143,#144), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075049,1.)) REPRESENTATION_ITEM('') ); #142 = CARTESIAN_POINT('',(-7.976546275424,0.423702927757,5.43633)); #143 = CARTESIAN_POINT('',(-9.420242096928,0.423702927757,4.003957457804 )); #144 = CARTESIAN_POINT('',(-10.50301396304,0.423702927757,2.93633)); #145 = PCURVE('',#49,#146); #146 = DEFINITIONAL_REPRESENTATION('',(#147),#151); #147 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#148,#149,#150), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075049,1.)) REPRESENTATION_ITEM('') ); #148 = CARTESIAN_POINT('',(-2.5,-5.078432583508)); #149 = CARTESIAN_POINT('',(-3.932372542196,-6.522128405011)); #150 = CARTESIAN_POINT('',(-5.,-7.604900271125)); #151 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #152 = PCURVE('',#153,#158); #153 = CONICAL_SURFACE('',#154,7.5,0.785398163397); #154 = AXIS2_PLACEMENT_3D('',#155,#156,#157); #155 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-12.06367)); #156 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #157 = DIRECTION('',(-1.,-1.224606353822E-016,2.719172340232E-032)); #158 = DEFINITIONAL_REPRESENTATION('',(#159),#185); #159 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#160,#161,#162,#163,#164,#165, #166,#167,#168,#169,#170,#171,#172,#173,#174,#175,#176,#177,#178, #179,#180,#181,#182,#183,#184),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775, 0.323118155001,0.484677232501,0.646236310001,0.807795387502, 0.969354465002,1.130913542503,1.292472620003,1.454031697503, 1.615590775004,1.777149852504,1.938708930004,2.100268007505, 2.261827085005,2.423386162505,2.584945240006,2.746504317506, 2.908063395007,3.069622472507,3.231181550007,3.392740627508, 3.554299705008),.QUASI_UNIFORM_KNOTS.); #160 = CARTESIAN_POINT('',(6.157857476012,-17.5)); #161 = CARTESIAN_POINT('',(6.157304831179,-17.45613532843)); #162 = CARTESIAN_POINT('',(6.156192803831,-17.369034253)); #163 = CARTESIAN_POINT('',(6.154504167531,-17.24022922767)); #164 = CARTESIAN_POINT('',(6.15279455739,-17.11323215337)); #165 = CARTESIAN_POINT('',(6.15106358201,-16.98800586851)); #166 = CARTESIAN_POINT('',(6.149310841213,-16.86451413191)); #167 = CARTESIAN_POINT('',(6.147535924576,-16.74272172673)); #168 = CARTESIAN_POINT('',(6.145738411434,-16.62259438981)); #169 = CARTESIAN_POINT('',(6.143917870468,-16.5040987895)); #170 = CARTESIAN_POINT('',(6.142073859396,-16.38720249214)); #171 = CARTESIAN_POINT('',(6.140205924616,-16.27187393322)); #172 = CARTESIAN_POINT('',(6.138313600849,-16.15808238872)); #173 = CARTESIAN_POINT('',(6.136396410758,-16.04579794794)); #174 = CARTESIAN_POINT('',(6.134453864564,-15.93499148723)); #175 = CARTESIAN_POINT('',(6.132485459637,-15.82563464481)); #176 = CARTESIAN_POINT('',(6.130490680076,-15.7176997966)); #177 = CARTESIAN_POINT('',(6.128468996271,-15.61116003298)); #178 = CARTESIAN_POINT('',(6.126419864458,-15.50598913612)); #179 = CARTESIAN_POINT('',(6.124342726204,-15.40216155983)); #180 = CARTESIAN_POINT('',(6.122237008073,-15.29965240364)); #181 = CARTESIAN_POINT('',(6.120102120531,-15.19843741256)); #182 = CARTESIAN_POINT('',(6.11793745959,-15.09849288457)); #183 = CARTESIAN_POINT('',(6.116474085284,-15.03269491212)); #184 = CARTESIAN_POINT('',(6.11573722796,-15.)); #185 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #186 = ORIENTED_EDGE('',*,*,#187,.T.); #187 = EDGE_CURVE('',#138,#188,#190,.T.); #188 = VERTEX_POINT('',#189); #189 = CARTESIAN_POINT('',(-25.29321342079,0.423702927757,2.93633)); #190 = SURFACE_CURVE('',#191,(#195,#202),.PCURVE_S2.); #191 = LINE('',#192,#193); #192 = CARTESIAN_POINT('',(-2.898113691917,0.423702927757,2.93633)); #193 = VECTOR('',#194,1.); #194 = DIRECTION('',(-1.,0.E+000,0.E+000)); #195 = PCURVE('',#49,#196); #196 = DEFINITIONAL_REPRESENTATION('',(#197),#201); #197 = LINE('',#198,#199); #198 = CARTESIAN_POINT('',(-5.,0.E+000)); #199 = VECTOR('',#200,1.); #200 = DIRECTION('',(0.E+000,-1.)); #201 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #202 = PCURVE('',#203,#208); #203 = PLANE('',#204); #204 = AXIS2_PLACEMENT_3D('',#205,#206,#207); #205 = CARTESIAN_POINT('',(-2.898113691917,0.423702927757,2.93633)); #206 = DIRECTION('',(0.E+000,0.E+000,-1.)); #207 = DIRECTION('',(1.,0.E+000,0.E+000)); #208 = DEFINITIONAL_REPRESENTATION('',(#209),#213); #209 = LINE('',#210,#211); #210 = CARTESIAN_POINT('',(0.E+000,0.E+000)); #211 = VECTOR('',#212,1.); #212 = DIRECTION('',(-1.,0.E+000)); #213 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #214 = ORIENTED_EDGE('',*,*,#215,.T.); #215 = EDGE_CURVE('',#188,#19,#216,.T.); #216 = SURFACE_CURVE('',#217,(#221,#228),.PCURVE_S2.); #217 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#218,#219,#220), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075049,1.)) REPRESENTATION_ITEM('') ); #218 = CARTESIAN_POINT('',(-25.29321342079,0.423702927757,2.93633)); #219 = CARTESIAN_POINT('',(-26.3759852869,0.423702927757,4.003957457804) ); #220 = CARTESIAN_POINT('',(-27.8196811084,0.423702927757,5.43633)); #221 = PCURVE('',#49,#222); #222 = DEFINITIONAL_REPRESENTATION('',(#223),#227); #223 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#224,#225,#226), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075049,1.)) REPRESENTATION_ITEM('') ); #224 = CARTESIAN_POINT('',(-5.,-22.39509972887)); #225 = CARTESIAN_POINT('',(-3.932372542196,-23.47787159498)); #226 = CARTESIAN_POINT('',(-2.5,-24.92156741649)); #227 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #228 = PCURVE('',#153,#229); #229 = DEFINITIONAL_REPRESENTATION('',(#230),#256); #230 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#231,#232,#233,#234,#235,#236, #237,#238,#239,#240,#241,#242,#243,#244,#245,#246,#247,#248,#249, #250,#251,#252,#253,#254,#255),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775, 0.323118155001,0.484677232501,0.646236310001,0.807795387502, 0.969354465002,1.130913542503,1.292472620003,1.454031697503, 1.615590775004,1.777149852504,1.938708930004,2.100268007505, 2.261827085005,2.423386162505,2.584945240006,2.746504317506, 2.908063395007,3.069622472507,3.231181550007,3.392740627508, 3.554299705008),.QUASI_UNIFORM_KNOTS.); #231 = CARTESIAN_POINT('',(3.309040732809,-15.)); #232 = CARTESIAN_POINT('',(3.308303875485,-15.03269491212)); #233 = CARTESIAN_POINT('',(3.306840501179,-15.09849288457)); #234 = CARTESIAN_POINT('',(3.304675840238,-15.19843741256)); #235 = CARTESIAN_POINT('',(3.302540952696,-15.29965240364)); #236 = CARTESIAN_POINT('',(3.300435234565,-15.40216155983)); #237 = CARTESIAN_POINT('',(3.298358096311,-15.50598913612)); #238 = CARTESIAN_POINT('',(3.296308964498,-15.61116003298)); #239 = CARTESIAN_POINT('',(3.294287280694,-15.7176997966)); #240 = CARTESIAN_POINT('',(3.292292501133,-15.82563464481)); #241 = CARTESIAN_POINT('',(3.290324096205,-15.93499148723)); #242 = CARTESIAN_POINT('',(3.288381550011,-16.04579794794)); #243 = CARTESIAN_POINT('',(3.286464359921,-16.15808238872)); #244 = CARTESIAN_POINT('',(3.284572036153,-16.27187393322)); #245 = CARTESIAN_POINT('',(3.282704101374,-16.38720249214)); #246 = CARTESIAN_POINT('',(3.280860090302,-16.5040987895)); #247 = CARTESIAN_POINT('',(3.279039549336,-16.62259438981)); #248 = CARTESIAN_POINT('',(3.277242036193,-16.74272172673)); #249 = CARTESIAN_POINT('',(3.275467119556,-16.86451413191)); #250 = CARTESIAN_POINT('',(3.273714378759,-16.98800586851)); #251 = CARTESIAN_POINT('',(3.271983403379,-17.11323215337)); #252 = CARTESIAN_POINT('',(3.270273793238,-17.24022922767)); #253 = CARTESIAN_POINT('',(3.268585156938,-17.369034253)); #254 = CARTESIAN_POINT('',(3.26747312959,-17.45613532843)); #255 = CARTESIAN_POINT('',(3.266920484758,-17.5)); #256 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #257 = ADVANCED_FACE('',(#258),#272,.F.); #258 = FACE_BOUND('',#259,.F.); #259 = EDGE_LOOP('',(#260,#290,#335,#425,#515)); #260 = ORIENTED_EDGE('',*,*,#261,.T.); #261 = EDGE_CURVE('',#262,#264,#266,.T.); #262 = VERTEX_POINT('',#263); #263 = CARTESIAN_POINT('',(-25.29321342079,-2.076297072243,2.93633)); #264 = VERTEX_POINT('',#265); #265 = CARTESIAN_POINT('',(-10.50301396304,-2.076297072243,2.93633)); #266 = SURFACE_CURVE('',#267,(#271,#283),.PCURVE_S2.); #267 = LINE('',#268,#269); #268 = CARTESIAN_POINT('',(-32.89811369191,-2.076297072243,2.93633)); #269 = VECTOR('',#270,1.); #270 = DIRECTION('',(1.,0.E+000,0.E+000)); #271 = PCURVE('',#272,#277); #272 = PLANE('',#273); #273 = AXIS2_PLACEMENT_3D('',#274,#275,#276); #274 = CARTESIAN_POINT('',(-32.89811369191,-2.076297072243,7.93633)); #275 = DIRECTION('',(0.E+000,-1.,0.E+000)); #276 = DIRECTION('',(0.E+000,0.E+000,-1.)); #277 = DEFINITIONAL_REPRESENTATION('',(#278),#282); #278 = LINE('',#279,#280); #279 = CARTESIAN_POINT('',(5.,0.E+000)); #280 = VECTOR('',#281,1.); #281 = DIRECTION('',(0.E+000,1.)); #282 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #283 = PCURVE('',#203,#284); #284 = DEFINITIONAL_REPRESENTATION('',(#285),#289); #285 = LINE('',#286,#287); #286 = CARTESIAN_POINT('',(-30.,2.5)); #287 = VECTOR('',#288,1.); #288 = DIRECTION('',(1.,0.E+000)); #289 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #290 = ORIENTED_EDGE('',*,*,#291,.T.); #291 = EDGE_CURVE('',#264,#292,#294,.T.); #292 = VERTEX_POINT('',#293); #293 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633)); #294 = SURFACE_CURVE('',#295,(#299,#306),.PCURVE_S2.); #295 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#296,#297,#298), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075051,1.)) REPRESENTATION_ITEM('') ); #296 = CARTESIAN_POINT('',(-10.50301396304,-2.076297072243,2.93633)); #297 = CARTESIAN_POINT('',(-9.420242096928,-2.076297072243, 4.003957457804)); #298 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633)); #299 = PCURVE('',#272,#300); #300 = DEFINITIONAL_REPRESENTATION('',(#301),#305); #301 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#302,#303,#304), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075051,1.)) REPRESENTATION_ITEM('') ); #302 = CARTESIAN_POINT('',(5.,22.395099728875)); #303 = CARTESIAN_POINT('',(3.932372542196,23.477871594989)); #304 = CARTESIAN_POINT('',(2.5,24.921567416492)); #305 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #306 = PCURVE('',#153,#307); #307 = DEFINITIONAL_REPRESENTATION('',(#308),#334); #308 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#309,#310,#311,#312,#313,#314, #315,#316,#317,#318,#319,#320,#321,#322,#323,#324,#325,#326,#327, #328,#329,#330,#331,#332,#333),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775, 0.323118155001,0.484677232501,0.646236310001,0.807795387502, 0.969354465002,1.130913542503,1.292472620003,1.454031697503, 1.615590775004,1.777149852504,1.938708930004,2.100268007505, 2.261827085005,2.423386162505,2.584945240006,2.746504317506, 2.908063395007,3.069622472507,3.231181550007,3.392740627508, 3.554299705008),.QUASI_UNIFORM_KNOTS.); #309 = CARTESIAN_POINT('',(0.16744807922,-15.)); #310 = CARTESIAN_POINT('',(0.166711221896,-15.03269491212)); #311 = CARTESIAN_POINT('',(0.16524784759,-15.09849288457)); #312 = CARTESIAN_POINT('',(0.163083186648,-15.19843741256)); #313 = CARTESIAN_POINT('',(0.160948299106,-15.29965240364)); #314 = CARTESIAN_POINT('',(0.158842580975,-15.40216155983)); #315 = CARTESIAN_POINT('',(0.156765442722,-15.50598913612)); #316 = CARTESIAN_POINT('',(0.154716310909,-15.61116003298)); #317 = CARTESIAN_POINT('',(0.152694627104,-15.7176997966)); #318 = CARTESIAN_POINT('',(0.150699847543,-15.82563464481)); #319 = CARTESIAN_POINT('',(0.148731442616,-15.93499148723)); #320 = CARTESIAN_POINT('',(0.146788896422,-16.04579794794)); #321 = CARTESIAN_POINT('',(0.144871706331,-16.15808238872)); #322 = CARTESIAN_POINT('',(0.142979382563,-16.27187393322)); #323 = CARTESIAN_POINT('',(0.141111447784,-16.38720249214)); #324 = CARTESIAN_POINT('',(0.139267436712,-16.5040987895)); #325 = CARTESIAN_POINT('',(0.137446895746,-16.62259438981)); #326 = CARTESIAN_POINT('',(0.135649382603,-16.74272172673)); #327 = CARTESIAN_POINT('',(0.133874465967,-16.86451413191)); #328 = CARTESIAN_POINT('',(0.132121725169,-16.98800586851)); #329 = CARTESIAN_POINT('',(0.130390749789,-17.11323215337)); #330 = CARTESIAN_POINT('',(0.128681139649,-17.24022922767)); #331 = CARTESIAN_POINT('',(0.126992503349,-17.369034253)); #332 = CARTESIAN_POINT('',(0.125880476001,-17.45613532843)); #333 = CARTESIAN_POINT('',(0.125327831168,-17.5)); #334 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #335 = ORIENTED_EDGE('',*,*,#336,.T.); #336 = EDGE_CURVE('',#292,#337,#339,.T.); #337 = VERTEX_POINT('',#338); #338 = CARTESIAN_POINT('',(-17.89811369191,-2.076297072243, 7.731450038723)); #339 = SURFACE_CURVE('',#340,(#364,#391),.PCURVE_S2.); #340 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#341,#342,#343,#344,#345,#346, #347,#348,#349,#350,#351,#352,#353,#354,#355,#356,#357,#358,#359, #360,#361,#362,#363),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),( -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423, -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847 ,8.657376849694,9.753048731913),.UNSPECIFIED.); #341 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633)); #342 = CARTESIAN_POINT('',(-8.349585612678,-2.076297072243, 5.566853116015)); #343 = CARTESIAN_POINT('',(-8.724216826515,-2.076297072243, 5.693350129935)); #344 = CARTESIAN_POINT('',(-10.58369474811,-2.076297072243, 6.298546031822)); #345 = CARTESIAN_POINT('',(-12.07643295845,-2.076297072243, 6.713431512354)); #346 = CARTESIAN_POINT('',(-14.28516695545,-2.076297072243, 7.221607932559)); #347 = CARTESIAN_POINT('',(-15.01497979641,-2.076297072243, 7.372657524772)); #348 = CARTESIAN_POINT('',(-16.09993392183,-2.076297072243,7.56017012803 )); #349 = CARTESIAN_POINT('',(-16.45980666667,-2.076297072243, 7.616304970701)); #350 = CARTESIAN_POINT('',(-17.17847405541,-2.076297072243, 7.702450972357)); #351 = CARTESIAN_POINT('',(-17.53738965651,-2.076297072243, 7.731450038723)); #352 = CARTESIAN_POINT('',(-17.89811369191,-2.076297072243, 7.731450038723)); #353 = CARTESIAN_POINT('',(-18.25883772732,-2.076297072243, 7.731450038723)); #354 = CARTESIAN_POINT('',(-18.61775332841,-2.076297072243, 7.702450972357)); #355 = CARTESIAN_POINT('',(-19.33642071715,-2.076297072243, 7.616304970701)); #356 = CARTESIAN_POINT('',(-19.696293462,-2.076297072243,7.56017012803) ); #357 = CARTESIAN_POINT('',(-20.78124758741,-2.076297072243, 7.372657524772)); #358 = CARTESIAN_POINT('',(-21.51106042838,-2.076297072243, 7.221607932559)); #359 = CARTESIAN_POINT('',(-23.71979442537,-2.076297072243, 6.713431512354)); #360 = CARTESIAN_POINT('',(-25.21253263571,-2.076297072243, 6.298546031822)); #361 = CARTESIAN_POINT('',(-27.07201055731,-2.076297072243, 5.693350129935)); #362 = CARTESIAN_POINT('',(-27.44664177115,-2.076297072243, 5.566853116015)); #363 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633)); #364 = PCURVE('',#272,#365); #365 = DEFINITIONAL_REPRESENTATION('',(#366),#390); #366 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#367,#368,#369,#370,#371,#372, #373,#374,#375,#376,#377,#378,#379,#380,#381,#382,#383,#384,#385, #386,#387,#388,#389),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),( -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423, -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847 ,8.657376849694,9.753048731913),.UNSPECIFIED.); #367 = CARTESIAN_POINT('',(2.5,24.921567416492)); #368 = CARTESIAN_POINT('',(2.369476883985,24.548528079239)); #369 = CARTESIAN_POINT('',(2.242979870065,24.173896865401)); #370 = CARTESIAN_POINT('',(1.637783968178,22.314418943799)); #371 = CARTESIAN_POINT('',(1.222898487646,20.821680733461)); #372 = CARTESIAN_POINT('',(0.714722067441,18.612946736467)); #373 = CARTESIAN_POINT('',(0.563672475228,17.883133895499)); #374 = CARTESIAN_POINT('',(0.37615987197,16.798179770085)); #375 = CARTESIAN_POINT('',(0.320025029299,16.43830702524)); #376 = CARTESIAN_POINT('',(0.233879027643,15.719639636498)); #377 = CARTESIAN_POINT('',(0.204879961277,15.360724035404)); #378 = CARTESIAN_POINT('',(0.204879961277,15.)); #379 = CARTESIAN_POINT('',(0.204879961277,14.639275964596)); #380 = CARTESIAN_POINT('',(0.233879027643,14.280360363502)); #381 = CARTESIAN_POINT('',(0.320025029299,13.56169297476)); #382 = CARTESIAN_POINT('',(0.37615987197,13.201820229915)); #383 = CARTESIAN_POINT('',(0.563672475228,12.116866104502)); #384 = CARTESIAN_POINT('',(0.714722067441,11.387053263533)); #385 = CARTESIAN_POINT('',(1.222898487646,9.178319266539)); #386 = CARTESIAN_POINT('',(1.637783968178,7.685581056201)); #387 = CARTESIAN_POINT('',(2.242979870065,5.826103134599)); #388 = CARTESIAN_POINT('',(2.369476883985,5.451471920761)); #389 = CARTESIAN_POINT('',(2.5,5.078432583508)); #390 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #391 = PCURVE('',#392,#397); #392 = TOROIDAL_SURFACE('',#393,8.25,54.873718663856); #393 = AXIS2_PLACEMENT_3D('',#394,#395,#396); #394 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-46.31367)); #395 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #396 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016)); #397 = DEFINITIONAL_REPRESENTATION('',(#398),#424); #398 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#399,#400,#401,#402,#403,#404, #405,#406,#407,#408,#409,#410,#411,#412,#413,#414,#415,#416,#417, #418,#419,#420,#421,#422,#423),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(-9.753048731913,-9.309728335008, -8.866407938103,-8.423087541198,-7.979767144292,-7.536446747387, -7.093126350482,-6.649805953577,-6.206485556672,-5.763165159767, -5.319844762862,-4.876524365957,-4.433203969051,-3.989883572146, -3.546563175241,-3.103242778336,-2.659922381431,-2.216601984526, -1.773281587621,-1.329961190715,-0.88664079381,-0.443320396905, 0.E+000),.UNSPECIFIED.); #399 = CARTESIAN_POINT('',(4.837716811553,-1.90983622455)); #400 = CARTESIAN_POINT('',(4.839604775725,-1.906942595099)); #401 = CARTESIAN_POINT('',(4.843552009624,-1.901155814072)); #402 = CARTESIAN_POINT('',(4.85008011799,-1.89248391648)); #403 = CARTESIAN_POINT('',(4.857304013494,-1.883824473771)); #404 = CARTESIAN_POINT('',(4.865329065086,-1.875190974748)); #405 = CARTESIAN_POINT('',(4.874291695205,-1.866586665031)); #406 = CARTESIAN_POINT('',(4.884359963883,-1.858016637247)); #407 = CARTESIAN_POINT('',(4.895744266443,-1.849486074495)); #408 = CARTESIAN_POINT('',(4.908711029087,-1.841000912302)); #409 = CARTESIAN_POINT('',(4.923602358169,-1.832567946629)); #410 = CARTESIAN_POINT('',(4.940864443041,-1.824195173617)); #411 = CARTESIAN_POINT('',(4.961088750932,-1.815892420907)); #412 = CARTESIAN_POINT('',(4.985076367501,-1.807671623483)); #413 = CARTESIAN_POINT('',(5.013928347127,-1.799549911442)); #414 = CARTESIAN_POINT('',(5.04918467399,-1.79155284086)); #415 = CARTESIAN_POINT('',(5.09312382579,-1.783707865756)); #416 = CARTESIAN_POINT('',(5.149132632791,-1.776058763789)); #417 = CARTESIAN_POINT('',(5.222468198,-1.768674045956)); #418 = CARTESIAN_POINT('',(5.321227440292,-1.761668014571)); #419 = CARTESIAN_POINT('',(5.458819159968,-1.755241122705)); #420 = CARTESIAN_POINT('',(5.653461471425,-1.749741310524)); #421 = CARTESIAN_POINT('',(5.932480703933,-1.745805524459)); #422 = CARTESIAN_POINT('',(6.160197445577,-1.744780737041)); #423 = CARTESIAN_POINT('',(6.28318530718,-1.744797796227)); #424 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #425 = ORIENTED_EDGE('',*,*,#426,.T.); #426 = EDGE_CURVE('',#337,#427,#429,.T.); #427 = VERTEX_POINT('',#428); #428 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633)); #429 = SURFACE_CURVE('',#430,(#454,#481),.PCURVE_S2.); #430 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#431,#432,#433,#434,#435,#436, #437,#438,#439,#440,#441,#442,#443,#444,#445,#446,#447,#448,#449, #450,#451,#452,#453),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),( -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423, -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847 ,8.657376849694,9.753048731913),.UNSPECIFIED.); #431 = CARTESIAN_POINT('',(-7.976546275424,-2.076297072243,5.43633)); #432 = CARTESIAN_POINT('',(-8.349585612678,-2.076297072243, 5.566853116015)); #433 = CARTESIAN_POINT('',(-8.724216826515,-2.076297072243, 5.693350129935)); #434 = CARTESIAN_POINT('',(-10.58369474811,-2.076297072243, 6.298546031822)); #435 = CARTESIAN_POINT('',(-12.07643295845,-2.076297072243, 6.713431512354)); #436 = CARTESIAN_POINT('',(-14.28516695545,-2.076297072243, 7.221607932559)); #437 = CARTESIAN_POINT('',(-15.01497979641,-2.076297072243, 7.372657524772)); #438 = CARTESIAN_POINT('',(-16.09993392183,-2.076297072243,7.56017012803 )); #439 = CARTESIAN_POINT('',(-16.45980666667,-2.076297072243, 7.616304970701)); #440 = CARTESIAN_POINT('',(-17.17847405541,-2.076297072243, 7.702450972357)); #441 = CARTESIAN_POINT('',(-17.53738965651,-2.076297072243, 7.731450038723)); #442 = CARTESIAN_POINT('',(-17.89811369191,-2.076297072243, 7.731450038723)); #443 = CARTESIAN_POINT('',(-18.25883772732,-2.076297072243, 7.731450038723)); #444 = CARTESIAN_POINT('',(-18.61775332841,-2.076297072243, 7.702450972357)); #445 = CARTESIAN_POINT('',(-19.33642071715,-2.076297072243, 7.616304970701)); #446 = CARTESIAN_POINT('',(-19.696293462,-2.076297072243,7.56017012803) ); #447 = CARTESIAN_POINT('',(-20.78124758741,-2.076297072243, 7.372657524772)); #448 = CARTESIAN_POINT('',(-21.51106042838,-2.076297072243, 7.221607932559)); #449 = CARTESIAN_POINT('',(-23.71979442537,-2.076297072243, 6.713431512354)); #450 = CARTESIAN_POINT('',(-25.21253263571,-2.076297072243, 6.298546031822)); #451 = CARTESIAN_POINT('',(-27.07201055731,-2.076297072243, 5.693350129935)); #452 = CARTESIAN_POINT('',(-27.44664177115,-2.076297072243, 5.566853116015)); #453 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633)); #454 = PCURVE('',#272,#455); #455 = DEFINITIONAL_REPRESENTATION('',(#456),#480); #456 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#457,#458,#459,#460,#461,#462, #463,#464,#465,#466,#467,#468,#469,#470,#471,#472,#473,#474,#475, #476,#477,#478,#479),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,3,2,2,2,2,4),( -9.753048731913,-8.657376849694,-4.328688424847,-2.164344212423, -1.082172106212,0.E+000,1.082172106212,2.164344212423,4.328688424847 ,8.657376849694,9.753048731913),.UNSPECIFIED.); #457 = CARTESIAN_POINT('',(2.5,24.921567416492)); #458 = CARTESIAN_POINT('',(2.369476883985,24.548528079239)); #459 = CARTESIAN_POINT('',(2.242979870065,24.173896865401)); #460 = CARTESIAN_POINT('',(1.637783968178,22.314418943799)); #461 = CARTESIAN_POINT('',(1.222898487646,20.821680733461)); #462 = CARTESIAN_POINT('',(0.714722067441,18.612946736467)); #463 = CARTESIAN_POINT('',(0.563672475228,17.883133895499)); #464 = CARTESIAN_POINT('',(0.37615987197,16.798179770085)); #465 = CARTESIAN_POINT('',(0.320025029299,16.43830702524)); #466 = CARTESIAN_POINT('',(0.233879027643,15.719639636498)); #467 = CARTESIAN_POINT('',(0.204879961277,15.360724035404)); #468 = CARTESIAN_POINT('',(0.204879961277,15.)); #469 = CARTESIAN_POINT('',(0.204879961277,14.639275964596)); #470 = CARTESIAN_POINT('',(0.233879027643,14.280360363502)); #471 = CARTESIAN_POINT('',(0.320025029299,13.56169297476)); #472 = CARTESIAN_POINT('',(0.37615987197,13.201820229915)); #473 = CARTESIAN_POINT('',(0.563672475228,12.116866104502)); #474 = CARTESIAN_POINT('',(0.714722067441,11.387053263533)); #475 = CARTESIAN_POINT('',(1.222898487646,9.178319266539)); #476 = CARTESIAN_POINT('',(1.637783968178,7.685581056201)); #477 = CARTESIAN_POINT('',(2.242979870065,5.826103134599)); #478 = CARTESIAN_POINT('',(2.369476883985,5.451471920761)); #479 = CARTESIAN_POINT('',(2.5,5.078432583508)); #480 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #481 = PCURVE('',#482,#487); #482 = TOROIDAL_SURFACE('',#483,8.25,54.873718663856); #483 = AXIS2_PLACEMENT_3D('',#484,#485,#486); #484 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-46.31367)); #485 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #486 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016)); #487 = DEFINITIONAL_REPRESENTATION('',(#488),#514); #488 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#489,#490,#491,#492,#493,#494, #495,#496,#497,#498,#499,#500,#501,#502,#503,#504,#505,#506,#507, #508,#509,#510,#511,#512,#513),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.443320396905, 0.88664079381,1.329961190715,1.773281587621,2.216601984526, 2.659922381431,3.103242778336,3.546563175241,3.989883572146, 4.433203969051,4.876524365957,5.319844762862,5.763165159767, 6.206485556672,6.649805953577,7.093126350482,7.536446747387, 7.979767144292,8.423087541198,8.866407938103,9.309728335008, 9.753048731913),.QUASI_UNIFORM_KNOTS.); #489 = CARTESIAN_POINT('',(0.E+000,-1.744797796227)); #490 = CARTESIAN_POINT('',(0.122987861602,-1.744780737041)); #491 = CARTESIAN_POINT('',(0.350704603246,-1.745805524459)); #492 = CARTESIAN_POINT('',(0.629723835754,-1.749741310524)); #493 = CARTESIAN_POINT('',(0.824366147211,-1.755241122705)); #494 = CARTESIAN_POINT('',(0.961957866888,-1.761668014571)); #495 = CARTESIAN_POINT('',(1.06071710918,-1.768674045956)); #496 = CARTESIAN_POINT('',(1.134052674389,-1.776058763789)); #497 = CARTESIAN_POINT('',(1.190061481389,-1.783707865756)); #498 = CARTESIAN_POINT('',(1.23400063319,-1.79155284086)); #499 = CARTESIAN_POINT('',(1.269256960052,-1.799549911442)); #500 = CARTESIAN_POINT('',(1.298108939679,-1.807671623483)); #501 = CARTESIAN_POINT('',(1.322096556248,-1.815892420907)); #502 = CARTESIAN_POINT('',(1.342320864139,-1.824195173617)); #503 = CARTESIAN_POINT('',(1.359582949011,-1.832567946629)); #504 = CARTESIAN_POINT('',(1.374474278092,-1.841000912302)); #505 = CARTESIAN_POINT('',(1.387441040737,-1.849486074495)); #506 = CARTESIAN_POINT('',(1.398825343297,-1.858016637247)); #507 = CARTESIAN_POINT('',(1.408893611974,-1.866586665031)); #508 = CARTESIAN_POINT('',(1.417856242094,-1.875190974748)); #509 = CARTESIAN_POINT('',(1.425881293685,-1.883824473771)); #510 = CARTESIAN_POINT('',(1.43310518919,-1.89248391648)); #511 = CARTESIAN_POINT('',(1.439633297555,-1.901155814072)); #512 = CARTESIAN_POINT('',(1.443580531454,-1.906942595099)); #513 = CARTESIAN_POINT('',(1.445468495627,-1.90983622455)); #514 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #515 = ORIENTED_EDGE('',*,*,#516,.T.); #516 = EDGE_CURVE('',#427,#262,#517,.T.); #517 = SURFACE_CURVE('',#518,(#522,#529),.PCURVE_S2.); #518 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#519,#520,#521), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075051,1.)) REPRESENTATION_ITEM('') ); #519 = CARTESIAN_POINT('',(-27.8196811084,-2.076297072243,5.43633)); #520 = CARTESIAN_POINT('',(-26.3759852869,-2.076297072243,4.003957457804 )); #521 = CARTESIAN_POINT('',(-25.29321342079,-2.076297072243,2.93633)); #522 = PCURVE('',#272,#523); #523 = DEFINITIONAL_REPRESENTATION('',(#524),#528); #524 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#525,#526,#527), .UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((3,3),(0.E+000, 3.554299705008),.PIECEWISE_BEZIER_KNOTS.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1., 1.010587075051,1.)) REPRESENTATION_ITEM('') ); #525 = CARTESIAN_POINT('',(2.5,5.078432583508)); #526 = CARTESIAN_POINT('',(3.932372542196,6.522128405011)); #527 = CARTESIAN_POINT('',(5.,7.604900271125)); #528 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #529 = PCURVE('',#153,#530); #530 = DEFINITIONAL_REPRESENTATION('',(#531),#557); #531 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#532,#533,#534,#535,#536,#537, #538,#539,#540,#541,#542,#543,#544,#545,#546,#547,#548,#549,#550, #551,#552,#553,#554,#555,#556),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000,0.1615590775, 0.323118155001,0.484677232501,0.646236310001,0.807795387502, 0.969354465002,1.130913542503,1.292472620003,1.454031697503, 1.615590775004,1.777149852504,1.938708930004,2.100268007505, 2.261827085005,2.423386162505,2.584945240006,2.746504317506, 2.908063395007,3.069622472507,3.231181550007,3.392740627508, 3.554299705008),.QUASI_UNIFORM_KNOTS.); #532 = CARTESIAN_POINT('',(3.016264822422,-17.5)); #533 = CARTESIAN_POINT('',(3.015712177589,-17.45613532843)); #534 = CARTESIAN_POINT('',(3.014600150241,-17.369034253)); #535 = CARTESIAN_POINT('',(3.012911513941,-17.24022922767)); #536 = CARTESIAN_POINT('',(3.011201903801,-17.11323215337)); #537 = CARTESIAN_POINT('',(3.00947092842,-16.98800586851)); #538 = CARTESIAN_POINT('',(3.007718187623,-16.86451413191)); #539 = CARTESIAN_POINT('',(3.005943270986,-16.74272172673)); #540 = CARTESIAN_POINT('',(3.004145757844,-16.62259438981)); #541 = CARTESIAN_POINT('',(3.002325216878,-16.5040987895)); #542 = CARTESIAN_POINT('',(3.000481205806,-16.38720249214)); #543 = CARTESIAN_POINT('',(2.998613271026,-16.27187393322)); #544 = CARTESIAN_POINT('',(2.996720947259,-16.15808238872)); #545 = CARTESIAN_POINT('',(2.994803757168,-16.04579794794)); #546 = CARTESIAN_POINT('',(2.992861210974,-15.93499148723)); #547 = CARTESIAN_POINT('',(2.990892806047,-15.82563464481)); #548 = CARTESIAN_POINT('',(2.988898026486,-15.7176997966)); #549 = CARTESIAN_POINT('',(2.986876342681,-15.61116003298)); #550 = CARTESIAN_POINT('',(2.984827210868,-15.50598913612)); #551 = CARTESIAN_POINT('',(2.982750072614,-15.40216155983)); #552 = CARTESIAN_POINT('',(2.980644354484,-15.29965240364)); #553 = CARTESIAN_POINT('',(2.978509466942,-15.19843741256)); #554 = CARTESIAN_POINT('',(2.976344806,-15.09849288457)); #555 = CARTESIAN_POINT('',(2.974881431694,-15.03269491212)); #556 = CARTESIAN_POINT('',(2.97414457437,-15.)); #557 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #558 = ADVANCED_FACE('',(#559),#203,.F.); #559 = FACE_BOUND('',#560,.F.); #560 = EDGE_LOOP('',(#561,#562,#612,#660,#661)); #561 = ORIENTED_EDGE('',*,*,#187,.F.); #562 = ORIENTED_EDGE('',*,*,#563,.T.); #563 = EDGE_CURVE('',#138,#564,#566,.T.); #564 = VERTEX_POINT('',#565); #565 = CARTESIAN_POINT('',(-10.39811369191,-0.826297072243,2.93633)); #566 = SURFACE_CURVE('',#567,(#572,#583),.PCURVE_S2.); #567 = CIRCLE('',#568,7.5); #568 = AXIS2_PLACEMENT_3D('',#569,#570,#571); #569 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,2.93633)); #570 = DIRECTION('',(0.E+000,0.E+000,-1.)); #571 = DIRECTION('',(1.,0.E+000,0.E+000)); #572 = PCURVE('',#203,#573); #573 = DEFINITIONAL_REPRESENTATION('',(#574),#582); #574 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#575,#576,#577,#578,#579,#580 ,#581),.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2,2,2,2,1),( -2.094395102393,0.E+000,2.094395102393,4.188790204786,6.28318530718, 8.377580409573),.UNSPECIFIED.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5,1.,0.5,1.)) REPRESENTATION_ITEM(' ') ); #575 = CARTESIAN_POINT('',(-7.5,1.25)); #576 = CARTESIAN_POINT('',(-7.5,14.240381056767)); #577 = CARTESIAN_POINT('',(-18.75,7.745190528383)); #578 = CARTESIAN_POINT('',(-30.,1.25)); #579 = CARTESIAN_POINT('',(-18.75,-5.245190528383)); #580 = CARTESIAN_POINT('',(-7.5,-11.74038105676)); #581 = CARTESIAN_POINT('',(-7.5,1.25)); #582 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #583 = PCURVE('',#153,#584); #584 = DEFINITIONAL_REPRESENTATION('',(#585),#611); #585 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#586,#587,#588,#589,#590,#591, #592,#593,#594,#595,#596,#597,#598,#599,#600,#601,#602,#603,#604, #605,#606,#607,#608,#609,#610),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(6.11573722796,6.123348504288, 6.130959780616,6.138571056944,6.146182333273,6.153793609601, 6.161404885929,6.169016162257,6.176627438585,6.184238714913, 6.191849991242,6.19946126757,6.207072543898,6.214683820226, 6.222295096554,6.229906372882,6.237517649211,6.245128925539, 6.252740201867,6.260351478195,6.267962754523,6.275574030851, 6.28318530718),.QUASI_UNIFORM_KNOTS.); #586 = CARTESIAN_POINT('',(6.11573722796,-15.)); #587 = CARTESIAN_POINT('',(6.118274320069,-15.)); #588 = CARTESIAN_POINT('',(6.123348504288,-15.)); #589 = CARTESIAN_POINT('',(6.130959780616,-15.)); #590 = CARTESIAN_POINT('',(6.138571056944,-15.)); #591 = CARTESIAN_POINT('',(6.146182333273,-15.)); #592 = CARTESIAN_POINT('',(6.153793609601,-15.)); #593 = CARTESIAN_POINT('',(6.161404885929,-15.)); #594 = CARTESIAN_POINT('',(6.169016162257,-15.)); #595 = CARTESIAN_POINT('',(6.176627438585,-15.)); #596 = CARTESIAN_POINT('',(6.184238714913,-15.)); #597 = CARTESIAN_POINT('',(6.191849991242,-15.)); #598 = CARTESIAN_POINT('',(6.19946126757,-15.)); #599 = CARTESIAN_POINT('',(6.207072543898,-15.)); #600 = CARTESIAN_POINT('',(6.214683820226,-15.)); #601 = CARTESIAN_POINT('',(6.222295096554,-15.)); #602 = CARTESIAN_POINT('',(6.229906372882,-15.)); #603 = CARTESIAN_POINT('',(6.237517649211,-15.)); #604 = CARTESIAN_POINT('',(6.245128925539,-15.)); #605 = CARTESIAN_POINT('',(6.252740201867,-15.)); #606 = CARTESIAN_POINT('',(6.260351478195,-15.)); #607 = CARTESIAN_POINT('',(6.267962754523,-15.)); #608 = CARTESIAN_POINT('',(6.275574030851,-15.)); #609 = CARTESIAN_POINT('',(6.28064821507,-15.)); #610 = CARTESIAN_POINT('',(6.28318530718,-15.)); #611 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #612 = ORIENTED_EDGE('',*,*,#613,.T.); #613 = EDGE_CURVE('',#564,#264,#614,.T.); #614 = SURFACE_CURVE('',#615,(#620,#631),.PCURVE_S2.); #615 = CIRCLE('',#616,7.5); #616 = AXIS2_PLACEMENT_3D('',#617,#618,#619); #617 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,2.93633)); #618 = DIRECTION('',(0.E+000,0.E+000,-1.)); #619 = DIRECTION('',(1.,0.E+000,0.E+000)); #620 = PCURVE('',#203,#621); #621 = DEFINITIONAL_REPRESENTATION('',(#622),#630); #622 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#623,#624,#625,#626,#627,#628 ,#629),.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2,2,2,2,1),( -2.094395102393,0.E+000,2.094395102393,4.188790204786,6.28318530718, 8.377580409573),.UNSPECIFIED.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5,1.,0.5,1.)) REPRESENTATION_ITEM(' ') ); #623 = CARTESIAN_POINT('',(-7.5,1.25)); #624 = CARTESIAN_POINT('',(-7.5,14.240381056767)); #625 = CARTESIAN_POINT('',(-18.75,7.745190528383)); #626 = CARTESIAN_POINT('',(-30.,1.25)); #627 = CARTESIAN_POINT('',(-18.75,-5.245190528383)); #628 = CARTESIAN_POINT('',(-7.5,-11.74038105676)); #629 = CARTESIAN_POINT('',(-7.5,1.25)); #630 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #631 = PCURVE('',#153,#632); #632 = DEFINITIONAL_REPRESENTATION('',(#633),#659); #633 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#634,#635,#636,#637,#638,#639, #640,#641,#642,#643,#644,#645,#646,#647,#648,#649,#650,#651,#652, #653,#654,#655,#656,#657,#658),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(8.881784197001E-016, 7.611276328169E-003,1.522255265634E-002,2.28338289845E-002, 3.044510531267E-002,3.805638164084E-002,4.566765796901E-002, 5.327893429717E-002,6.089021062534E-002,6.850148695351E-002, 7.611276328168E-002,8.372403960985E-002,9.133531593801E-002, 9.894659226618E-002,0.106557868594,0.114169144923,0.121780421251, 0.129391697579,0.137002973907,0.144614250235,0.152225526563, 0.159836802892,0.16744807922),.QUASI_UNIFORM_KNOTS.); #634 = CARTESIAN_POINT('',(1.021405182655E-015,-15.)); #635 = CARTESIAN_POINT('',(2.53709210939E-003,-15.)); #636 = CARTESIAN_POINT('',(7.611276328169E-003,-15.)); #637 = CARTESIAN_POINT('',(1.522255265634E-002,-15.)); #638 = CARTESIAN_POINT('',(2.28338289845E-002,-15.)); #639 = CARTESIAN_POINT('',(3.044510531267E-002,-15.)); #640 = CARTESIAN_POINT('',(3.805638164084E-002,-15.)); #641 = CARTESIAN_POINT('',(4.566765796901E-002,-15.)); #642 = CARTESIAN_POINT('',(5.327893429717E-002,-15.)); #643 = CARTESIAN_POINT('',(6.089021062534E-002,-15.)); #644 = CARTESIAN_POINT('',(6.850148695351E-002,-15.)); #645 = CARTESIAN_POINT('',(7.611276328168E-002,-15.)); #646 = CARTESIAN_POINT('',(8.372403960985E-002,-15.)); #647 = CARTESIAN_POINT('',(9.133531593801E-002,-15.)); #648 = CARTESIAN_POINT('',(9.894659226618E-002,-15.)); #649 = CARTESIAN_POINT('',(0.106557868594,-15.)); #650 = CARTESIAN_POINT('',(0.114169144923,-15.)); #651 = CARTESIAN_POINT('',(0.121780421251,-15.)); #652 = CARTESIAN_POINT('',(0.129391697579,-15.)); #653 = CARTESIAN_POINT('',(0.137002973907,-15.)); #654 = CARTESIAN_POINT('',(0.144614250235,-15.)); #655 = CARTESIAN_POINT('',(0.152225526563,-15.)); #656 = CARTESIAN_POINT('',(0.159836802892,-15.)); #657 = CARTESIAN_POINT('',(0.16491098711,-15.)); #658 = CARTESIAN_POINT('',(0.16744807922,-15.)); #659 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #660 = ORIENTED_EDGE('',*,*,#261,.F.); #661 = ORIENTED_EDGE('',*,*,#662,.T.); #662 = EDGE_CURVE('',#262,#188,#663,.T.); #663 = SURFACE_CURVE('',#664,(#669,#680),.PCURVE_S2.); #664 = CIRCLE('',#665,7.5); #665 = AXIS2_PLACEMENT_3D('',#666,#667,#668); #666 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,2.93633)); #667 = DIRECTION('',(0.E+000,0.E+000,-1.)); #668 = DIRECTION('',(1.,0.E+000,0.E+000)); #669 = PCURVE('',#203,#670); #670 = DEFINITIONAL_REPRESENTATION('',(#671),#679); #671 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#672,#673,#674,#675,#676,#677 ,#678),.UNSPECIFIED.,.F.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2,2,2,2,1),( -2.094395102393,0.E+000,2.094395102393,4.188790204786,6.28318530718, 8.377580409573),.UNSPECIFIED.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5,1.,0.5,1.)) REPRESENTATION_ITEM(' ') ); #672 = CARTESIAN_POINT('',(-7.5,1.25)); #673 = CARTESIAN_POINT('',(-7.5,14.240381056767)); #674 = CARTESIAN_POINT('',(-18.75,7.745190528383)); #675 = CARTESIAN_POINT('',(-30.,1.25)); #676 = CARTESIAN_POINT('',(-18.75,-5.245190528383)); #677 = CARTESIAN_POINT('',(-7.5,-11.74038105676)); #678 = CARTESIAN_POINT('',(-7.5,1.25)); #679 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #680 = PCURVE('',#153,#681); #681 = DEFINITIONAL_REPRESENTATION('',(#682),#708); #682 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#683,#684,#685,#686,#687,#688, #689,#690,#691,#692,#693,#694,#695,#696,#697,#698,#699,#700,#701, #702,#703,#704,#705,#706,#707),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(2.97414457437,2.989367127026, 3.004589679683,3.019812232339,3.035034784995,3.050257337652, 3.065479890308,3.080702442964,3.095924995621,3.111147548277, 3.126370100933,3.14159265359,3.156815206246,3.172037758902, 3.187260311559,3.202482864215,3.217705416871,3.232927969528, 3.248150522184,3.26337307484,3.278595627497,3.293818180153, 3.309040732809),.QUASI_UNIFORM_KNOTS.); #683 = CARTESIAN_POINT('',(2.97414457437,-15.)); #684 = CARTESIAN_POINT('',(2.979218758589,-15.)); #685 = CARTESIAN_POINT('',(2.989367127026,-15.)); #686 = CARTESIAN_POINT('',(3.004589679683,-15.)); #687 = CARTESIAN_POINT('',(3.019812232339,-15.)); #688 = CARTESIAN_POINT('',(3.035034784995,-15.)); #689 = CARTESIAN_POINT('',(3.050257337652,-15.)); #690 = CARTESIAN_POINT('',(3.065479890308,-15.)); #691 = CARTESIAN_POINT('',(3.080702442964,-15.)); #692 = CARTESIAN_POINT('',(3.095924995621,-15.)); #693 = CARTESIAN_POINT('',(3.111147548277,-15.)); #694 = CARTESIAN_POINT('',(3.126370100933,-15.)); #695 = CARTESIAN_POINT('',(3.14159265359,-15.)); #696 = CARTESIAN_POINT('',(3.156815206246,-15.)); #697 = CARTESIAN_POINT('',(3.172037758902,-15.)); #698 = CARTESIAN_POINT('',(3.187260311559,-15.)); #699 = CARTESIAN_POINT('',(3.202482864215,-15.)); #700 = CARTESIAN_POINT('',(3.217705416871,-15.)); #701 = CARTESIAN_POINT('',(3.232927969528,-15.)); #702 = CARTESIAN_POINT('',(3.248150522184,-15.)); #703 = CARTESIAN_POINT('',(3.26337307484,-15.)); #704 = CARTESIAN_POINT('',(3.278595627497,-15.)); #705 = CARTESIAN_POINT('',(3.293818180153,-15.)); #706 = CARTESIAN_POINT('',(3.303966548591,-15.)); #707 = CARTESIAN_POINT('',(3.309040732809,-15.)); #708 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #709 = ADVANCED_FACE('',(#710),#482,.F.); #710 = FACE_BOUND('',#711,.T.); #711 = EDGE_LOOP('',(#712,#713,#781)); #712 = ORIENTED_EDGE('',*,*,#426,.T.); #713 = ORIENTED_EDGE('',*,*,#714,.F.); #714 = EDGE_CURVE('',#715,#427,#717,.T.); #715 = VERTEX_POINT('',#716); #716 = CARTESIAN_POINT('',(-17.89811369191,-10.82629707224,5.43633)); #717 = SURFACE_CURVE('',#718,(#723,#752),.PCURVE_S2.); #718 = CIRCLE('',#719,10.); #719 = AXIS2_PLACEMENT_3D('',#720,#721,#722); #720 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,5.43633)); #721 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #722 = DIRECTION('',(1.,0.E+000,0.E+000)); #723 = PCURVE('',#482,#724); #724 = DEFINITIONAL_REPRESENTATION('',(#725),#751); #725 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#726,#727,#728,#729,#730,#731, #732,#733,#734,#735,#736,#737,#738,#739,#740,#741,#742,#743,#744, #745,#746,#747,#748,#749,#750),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(1.570796326795,1.636499440232, 1.70220255367,1.767905667108,1.833608780545,1.899311893983, 1.96501500742,2.030718120858,2.096421234296,2.162124347733, 2.227827461171,2.293530574608,2.359233688046,2.424936801483, 2.490639914921,2.556343028359,2.622046141796,2.687749255234, 2.753452368671,2.819155482109,2.884858595547,2.950561708984, 3.016264822422),.QUASI_UNIFORM_KNOTS.); #726 = CARTESIAN_POINT('',(0.E+000,-1.90983622455)); #727 = CARTESIAN_POINT('',(2.190103781253E-002,-1.90983622455)); #728 = CARTESIAN_POINT('',(6.570311343758E-002,-1.90983622455)); #729 = CARTESIAN_POINT('',(0.131406226875,-1.90983622455)); #730 = CARTESIAN_POINT('',(0.197109340313,-1.90983622455)); #731 = CARTESIAN_POINT('',(0.26281245375,-1.90983622455)); #732 = CARTESIAN_POINT('',(0.328515567188,-1.90983622455)); #733 = CARTESIAN_POINT('',(0.394218680625,-1.90983622455)); #734 = CARTESIAN_POINT('',(0.459921794063,-1.90983622455)); #735 = CARTESIAN_POINT('',(0.525624907501,-1.90983622455)); #736 = CARTESIAN_POINT('',(0.591328020938,-1.90983622455)); #737 = CARTESIAN_POINT('',(0.657031134376,-1.90983622455)); #738 = CARTESIAN_POINT('',(0.722734247813,-1.90983622455)); #739 = CARTESIAN_POINT('',(0.788437361251,-1.90983622455)); #740 = CARTESIAN_POINT('',(0.854140474689,-1.90983622455)); #741 = CARTESIAN_POINT('',(0.919843588126,-1.90983622455)); #742 = CARTESIAN_POINT('',(0.985546701564,-1.90983622455)); #743 = CARTESIAN_POINT('',(1.051249815001,-1.90983622455)); #744 = CARTESIAN_POINT('',(1.116952928439,-1.90983622455)); #745 = CARTESIAN_POINT('',(1.182656041876,-1.90983622455)); #746 = CARTESIAN_POINT('',(1.248359155314,-1.90983622455)); #747 = CARTESIAN_POINT('',(1.314062268752,-1.90983622455)); #748 = CARTESIAN_POINT('',(1.379765382189,-1.90983622455)); #749 = CARTESIAN_POINT('',(1.423567457814,-1.90983622455)); #750 = CARTESIAN_POINT('',(1.445468495627,-1.90983622455)); #751 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #752 = PCURVE('',#153,#753); #753 = DEFINITIONAL_REPRESENTATION('',(#754),#780); #754 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#755,#756,#757,#758,#759,#760, #761,#762,#763,#764,#765,#766,#767,#768,#769,#770,#771,#772,#773, #774,#775,#776,#777,#778,#779),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(1.570796326795,1.636499440232, 1.70220255367,1.767905667108,1.833608780545,1.899311893983, 1.96501500742,2.030718120858,2.096421234296,2.162124347733, 2.227827461171,2.293530574608,2.359233688046,2.424936801483, 2.490639914921,2.556343028359,2.622046141796,2.687749255234, 2.753452368671,2.819155482109,2.884858595547,2.950561708984, 3.016264822422),.QUASI_UNIFORM_KNOTS.); #755 = CARTESIAN_POINT('',(1.570796326795,-17.5)); #756 = CARTESIAN_POINT('',(1.592697364607,-17.5)); #757 = CARTESIAN_POINT('',(1.636499440232,-17.5)); #758 = CARTESIAN_POINT('',(1.70220255367,-17.5)); #759 = CARTESIAN_POINT('',(1.767905667108,-17.5)); #760 = CARTESIAN_POINT('',(1.833608780545,-17.5)); #761 = CARTESIAN_POINT('',(1.899311893983,-17.5)); #762 = CARTESIAN_POINT('',(1.96501500742,-17.5)); #763 = CARTESIAN_POINT('',(2.030718120858,-17.5)); #764 = CARTESIAN_POINT('',(2.096421234296,-17.5)); #765 = CARTESIAN_POINT('',(2.162124347733,-17.5)); #766 = CARTESIAN_POINT('',(2.227827461171,-17.5)); #767 = CARTESIAN_POINT('',(2.293530574608,-17.5)); #768 = CARTESIAN_POINT('',(2.359233688046,-17.5)); #769 = CARTESIAN_POINT('',(2.424936801483,-17.5)); #770 = CARTESIAN_POINT('',(2.490639914921,-17.5)); #771 = CARTESIAN_POINT('',(2.556343028359,-17.5)); #772 = CARTESIAN_POINT('',(2.622046141796,-17.5)); #773 = CARTESIAN_POINT('',(2.687749255234,-17.5)); #774 = CARTESIAN_POINT('',(2.753452368671,-17.5)); #775 = CARTESIAN_POINT('',(2.819155482109,-17.5)); #776 = CARTESIAN_POINT('',(2.884858595547,-17.5)); #777 = CARTESIAN_POINT('',(2.950561708984,-17.5)); #778 = CARTESIAN_POINT('',(2.994363784609,-17.5)); #779 = CARTESIAN_POINT('',(3.016264822422,-17.5)); #780 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #781 = ORIENTED_EDGE('',*,*,#782,.F.); #782 = EDGE_CURVE('',#337,#715,#783,.T.); #783 = SURFACE_CURVE('',#784,(#789,#796),.PCURVE_S2.); #784 = CIRCLE('',#785,54.873718663856); #785 = AXIS2_PLACEMENT_3D('',#786,#787,#788); #786 = CARTESIAN_POINT('',(-17.89811369191,7.423702927757,-46.31367)); #787 = DIRECTION('',(1.,0.E+000,0.E+000)); #788 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016)); #789 = PCURVE('',#482,#790); #790 = DEFINITIONAL_REPRESENTATION('',(#791),#795); #791 = LINE('',#792,#793); #792 = CARTESIAN_POINT('',(0.E+000,0.E+000)); #793 = VECTOR('',#794,1.); #794 = DIRECTION('',(0.E+000,-1.)); #795 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #796 = PCURVE('',#392,#797); #797 = DEFINITIONAL_REPRESENTATION('',(#798),#802); #798 = LINE('',#799,#800); #799 = CARTESIAN_POINT('',(6.28318530718,0.E+000)); #800 = VECTOR('',#801,1.); #801 = DIRECTION('',(0.E+000,-1.)); #802 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #803 = ADVANCED_FACE('',(#804),#392,.F.); #804 = FACE_BOUND('',#805,.T.); #805 = EDGE_LOOP('',(#806,#872,#873)); #806 = ORIENTED_EDGE('',*,*,#807,.F.); #807 = EDGE_CURVE('',#292,#715,#808,.T.); #808 = SURFACE_CURVE('',#809,(#814,#843),.PCURVE_S2.); #809 = CIRCLE('',#810,10.); #810 = AXIS2_PLACEMENT_3D('',#811,#812,#813); #811 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,5.43633)); #812 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #813 = DIRECTION('',(1.,0.E+000,0.E+000)); #814 = PCURVE('',#392,#815); #815 = DEFINITIONAL_REPRESENTATION('',(#816),#842); #816 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#817,#818,#819,#820,#821,#822, #823,#824,#825,#826,#827,#828,#829,#830,#831,#832,#833,#834,#835, #836,#837,#838,#839,#840,#841),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.125327831168,0.191030944606, 0.256734058043,0.322437171481,0.388140284918,0.453843398356, 0.519546511794,0.585249625231,0.650952738669,0.716655852106, 0.782358965544,0.848062078981,0.913765192419,0.979468305857, 1.045171419294,1.110874532732,1.176577646169,1.242280759607, 1.307983873045,1.373686986482,1.43939009992,1.505093213357, 1.570796326795),.QUASI_UNIFORM_KNOTS.); #817 = CARTESIAN_POINT('',(4.837716811553,-1.90983622455)); #818 = CARTESIAN_POINT('',(4.859617849365,-1.90983622455)); #819 = CARTESIAN_POINT('',(4.90341992499,-1.90983622455)); #820 = CARTESIAN_POINT('',(4.969123038428,-1.90983622455)); #821 = CARTESIAN_POINT('',(5.034826151866,-1.90983622455)); #822 = CARTESIAN_POINT('',(5.100529265303,-1.90983622455)); #823 = CARTESIAN_POINT('',(5.166232378741,-1.90983622455)); #824 = CARTESIAN_POINT('',(5.231935492178,-1.90983622455)); #825 = CARTESIAN_POINT('',(5.297638605616,-1.90983622455)); #826 = CARTESIAN_POINT('',(5.363341719053,-1.90983622455)); #827 = CARTESIAN_POINT('',(5.429044832491,-1.90983622455)); #828 = CARTESIAN_POINT('',(5.494747945929,-1.90983622455)); #829 = CARTESIAN_POINT('',(5.560451059366,-1.90983622455)); #830 = CARTESIAN_POINT('',(5.626154172804,-1.90983622455)); #831 = CARTESIAN_POINT('',(5.691857286241,-1.90983622455)); #832 = CARTESIAN_POINT('',(5.757560399679,-1.90983622455)); #833 = CARTESIAN_POINT('',(5.823263513117,-1.90983622455)); #834 = CARTESIAN_POINT('',(5.888966626554,-1.90983622455)); #835 = CARTESIAN_POINT('',(5.954669739992,-1.90983622455)); #836 = CARTESIAN_POINT('',(6.020372853429,-1.90983622455)); #837 = CARTESIAN_POINT('',(6.086075966867,-1.90983622455)); #838 = CARTESIAN_POINT('',(6.151779080304,-1.90983622455)); #839 = CARTESIAN_POINT('',(6.217482193742,-1.90983622455)); #840 = CARTESIAN_POINT('',(6.261284269367,-1.90983622455)); #841 = CARTESIAN_POINT('',(6.28318530718,-1.90983622455)); #842 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #843 = PCURVE('',#153,#844); #844 = DEFINITIONAL_REPRESENTATION('',(#845),#871); #845 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#846,#847,#848,#849,#850,#851, #852,#853,#854,#855,#856,#857,#858,#859,#860,#861,#862,#863,#864, #865,#866,#867,#868,#869,#870),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.125327831168,0.191030944606, 0.256734058043,0.322437171481,0.388140284918,0.453843398356, 0.519546511794,0.585249625231,0.650952738669,0.716655852106, 0.782358965544,0.848062078981,0.913765192419,0.979468305857, 1.045171419294,1.110874532732,1.176577646169,1.242280759607, 1.307983873045,1.373686986482,1.43939009992,1.505093213357, 1.570796326795),.QUASI_UNIFORM_KNOTS.); #846 = CARTESIAN_POINT('',(0.125327831168,-17.5)); #847 = CARTESIAN_POINT('',(0.147228868981,-17.5)); #848 = CARTESIAN_POINT('',(0.191030944606,-17.5)); #849 = CARTESIAN_POINT('',(0.256734058043,-17.5)); #850 = CARTESIAN_POINT('',(0.322437171481,-17.5)); #851 = CARTESIAN_POINT('',(0.388140284918,-17.5)); #852 = CARTESIAN_POINT('',(0.453843398356,-17.5)); #853 = CARTESIAN_POINT('',(0.519546511794,-17.5)); #854 = CARTESIAN_POINT('',(0.585249625231,-17.5)); #855 = CARTESIAN_POINT('',(0.650952738669,-17.5)); #856 = CARTESIAN_POINT('',(0.716655852106,-17.5)); #857 = CARTESIAN_POINT('',(0.782358965544,-17.5)); #858 = CARTESIAN_POINT('',(0.848062078981,-17.5)); #859 = CARTESIAN_POINT('',(0.913765192419,-17.5)); #860 = CARTESIAN_POINT('',(0.979468305857,-17.5)); #861 = CARTESIAN_POINT('',(1.045171419294,-17.5)); #862 = CARTESIAN_POINT('',(1.110874532732,-17.5)); #863 = CARTESIAN_POINT('',(1.176577646169,-17.5)); #864 = CARTESIAN_POINT('',(1.242280759607,-17.5)); #865 = CARTESIAN_POINT('',(1.307983873045,-17.5)); #866 = CARTESIAN_POINT('',(1.373686986482,-17.5)); #867 = CARTESIAN_POINT('',(1.43939009992,-17.5)); #868 = CARTESIAN_POINT('',(1.505093213357,-17.5)); #869 = CARTESIAN_POINT('',(1.548895288982,-17.5)); #870 = CARTESIAN_POINT('',(1.570796326795,-17.5)); #871 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #872 = ORIENTED_EDGE('',*,*,#336,.T.); #873 = ORIENTED_EDGE('',*,*,#782,.T.); #874 = ADVANCED_FACE('',(#875),#81,.F.); #875 = FACE_BOUND('',#876,.T.); #876 = EDGE_LOOP('',(#877,#878)); #877 = ORIENTED_EDGE('',*,*,#18,.T.); #878 = ORIENTED_EDGE('',*,*,#879,.F.); #879 = EDGE_CURVE('',#19,#21,#880,.T.); #880 = SURFACE_CURVE('',#881,(#886,#915),.PCURVE_S2.); #881 = CIRCLE('',#882,10.); #882 = AXIS2_PLACEMENT_3D('',#883,#884,#885); #883 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,5.43633)); #884 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #885 = DIRECTION('',(1.,0.E+000,0.E+000)); #886 = PCURVE('',#81,#887); #887 = DEFINITIONAL_REPRESENTATION('',(#888),#914); #888 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#889,#890,#891,#892,#893,#894, #895,#896,#897,#898,#899,#900,#901,#902,#903,#904,#905,#906,#907, #908,#909,#910,#911,#912,#913),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(3.266920484758,3.398326711633, 3.529732938508,3.661139165383,3.792545392259,3.923951619134, 4.055357846009,4.186764072884,4.318170299759,4.449576526634, 4.58098275351,4.712388980385,4.84379520726,4.975201434135, 5.10660766101,5.238013887885,5.369420114761,5.500826341636, 5.632232568511,5.763638795386,5.895045022261,6.026451249136, 6.157857476012),.QUASI_UNIFORM_KNOTS.); #889 = CARTESIAN_POINT('',(1.696124157963,-1.90983622455)); #890 = CARTESIAN_POINT('',(1.739926233588,-1.90983622455)); #891 = CARTESIAN_POINT('',(1.827530384838,-1.90983622455)); #892 = CARTESIAN_POINT('',(1.958936611713,-1.90983622455)); #893 = CARTESIAN_POINT('',(2.090342838588,-1.90983622455)); #894 = CARTESIAN_POINT('',(2.221749065464,-1.90983622455)); #895 = CARTESIAN_POINT('',(2.353155292339,-1.90983622455)); #896 = CARTESIAN_POINT('',(2.484561519214,-1.90983622455)); #897 = CARTESIAN_POINT('',(2.615967746089,-1.90983622455)); #898 = CARTESIAN_POINT('',(2.747373972964,-1.90983622455)); #899 = CARTESIAN_POINT('',(2.878780199839,-1.90983622455)); #900 = CARTESIAN_POINT('',(3.010186426715,-1.90983622455)); #901 = CARTESIAN_POINT('',(3.14159265359,-1.90983622455)); #902 = CARTESIAN_POINT('',(3.272998880465,-1.90983622455)); #903 = CARTESIAN_POINT('',(3.40440510734,-1.90983622455)); #904 = CARTESIAN_POINT('',(3.535811334215,-1.90983622455)); #905 = CARTESIAN_POINT('',(3.66721756109,-1.90983622455)); #906 = CARTESIAN_POINT('',(3.798623787966,-1.90983622455)); #907 = CARTESIAN_POINT('',(3.930030014841,-1.90983622455)); #908 = CARTESIAN_POINT('',(4.061436241716,-1.90983622455)); #909 = CARTESIAN_POINT('',(4.192842468591,-1.90983622455)); #910 = CARTESIAN_POINT('',(4.324248695466,-1.90983622455)); #911 = CARTESIAN_POINT('',(4.455654922341,-1.90983622455)); #912 = CARTESIAN_POINT('',(4.543259073592,-1.90983622455)); #913 = CARTESIAN_POINT('',(4.587061149217,-1.90983622455)); #914 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #915 = PCURVE('',#153,#916); #916 = DEFINITIONAL_REPRESENTATION('',(#917),#943); #917 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#918,#919,#920,#921,#922,#923, #924,#925,#926,#927,#928,#929,#930,#931,#932,#933,#934,#935,#936, #937,#938,#939,#940,#941,#942),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(3.266920484758,3.398326711633, 3.529732938508,3.661139165383,3.792545392259,3.923951619134, 4.055357846009,4.186764072884,4.318170299759,4.449576526634, 4.58098275351,4.712388980385,4.84379520726,4.975201434135, 5.10660766101,5.238013887885,5.369420114761,5.500826341636, 5.632232568511,5.763638795386,5.895045022261,6.026451249136, 6.157857476012),.QUASI_UNIFORM_KNOTS.); #918 = CARTESIAN_POINT('',(3.266920484758,-17.5)); #919 = CARTESIAN_POINT('',(3.310722560383,-17.5)); #920 = CARTESIAN_POINT('',(3.398326711633,-17.5)); #921 = CARTESIAN_POINT('',(3.529732938508,-17.5)); #922 = CARTESIAN_POINT('',(3.661139165383,-17.5)); #923 = CARTESIAN_POINT('',(3.792545392259,-17.5)); #924 = CARTESIAN_POINT('',(3.923951619134,-17.5)); #925 = CARTESIAN_POINT('',(4.055357846009,-17.5)); #926 = CARTESIAN_POINT('',(4.186764072884,-17.5)); #927 = CARTESIAN_POINT('',(4.318170299759,-17.5)); #928 = CARTESIAN_POINT('',(4.449576526634,-17.5)); #929 = CARTESIAN_POINT('',(4.58098275351,-17.5)); #930 = CARTESIAN_POINT('',(4.712388980385,-17.5)); #931 = CARTESIAN_POINT('',(4.84379520726,-17.5)); #932 = CARTESIAN_POINT('',(4.975201434135,-17.5)); #933 = CARTESIAN_POINT('',(5.10660766101,-17.5)); #934 = CARTESIAN_POINT('',(5.238013887885,-17.5)); #935 = CARTESIAN_POINT('',(5.369420114761,-17.5)); #936 = CARTESIAN_POINT('',(5.500826341636,-17.5)); #937 = CARTESIAN_POINT('',(5.632232568511,-17.5)); #938 = CARTESIAN_POINT('',(5.763638795386,-17.5)); #939 = CARTESIAN_POINT('',(5.895045022261,-17.5)); #940 = CARTESIAN_POINT('',(6.026451249136,-17.5)); #941 = CARTESIAN_POINT('',(6.114055400386,-17.5)); #942 = CARTESIAN_POINT('',(6.157857476012,-17.5)); #943 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #944 = ADVANCED_FACE('',(#945),#153,.T.); #945 = FACE_BOUND('',#946,.T.); #946 = EDGE_LOOP('',(#947,#948,#949,#950,#951,#952,#953,#954,#955,#956, #957,#980,#1051)); #947 = ORIENTED_EDGE('',*,*,#613,.T.); #948 = ORIENTED_EDGE('',*,*,#291,.T.); #949 = ORIENTED_EDGE('',*,*,#807,.T.); #950 = ORIENTED_EDGE('',*,*,#714,.T.); #951 = ORIENTED_EDGE('',*,*,#516,.T.); #952 = ORIENTED_EDGE('',*,*,#662,.T.); #953 = ORIENTED_EDGE('',*,*,#215,.T.); #954 = ORIENTED_EDGE('',*,*,#879,.T.); #955 = ORIENTED_EDGE('',*,*,#137,.T.); #956 = ORIENTED_EDGE('',*,*,#563,.T.); #957 = ORIENTED_EDGE('',*,*,#958,.T.); #958 = EDGE_CURVE('',#564,#959,#961,.T.); #959 = VERTEX_POINT('',#960); #960 = CARTESIAN_POINT('',(-12.89811369191,-0.826297072243,0.43633)); #961 = SEAM_CURVE('',#962,(#966,#973),.PCURVE_S2.); #962 = LINE('',#963,#964); #963 = CARTESIAN_POINT('',(-25.39811369191,-0.826297072243,-12.06367)); #964 = VECTOR('',#965,1.); #965 = DIRECTION('',(-0.707106781187,-2.436019915756E-016, -0.707106781187)); #966 = PCURVE('',#153,#967); #967 = DEFINITIONAL_REPRESENTATION('',(#968),#972); #968 = LINE('',#969,#970); #969 = CARTESIAN_POINT('',(6.28318530718,0.E+000)); #970 = VECTOR('',#971,1.); #971 = DIRECTION('',(0.E+000,1.)); #972 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #973 = PCURVE('',#153,#974); #974 = DEFINITIONAL_REPRESENTATION('',(#975),#979); #975 = LINE('',#976,#977); #976 = CARTESIAN_POINT('',(0.E+000,0.E+000)); #977 = VECTOR('',#978,1.); #978 = DIRECTION('',(0.E+000,1.)); #979 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #980 = ORIENTED_EDGE('',*,*,#981,.F.); #981 = EDGE_CURVE('',#959,#959,#982,.T.); #982 = SURFACE_CURVE('',#983,(#988,#1017),.PCURVE_S2.); #983 = CIRCLE('',#984,5.); #984 = AXIS2_PLACEMENT_3D('',#985,#986,#987); #985 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,0.43633)); #986 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #987 = DIRECTION('',(1.,0.E+000,0.E+000)); #988 = PCURVE('',#153,#989); #989 = DEFINITIONAL_REPRESENTATION('',(#990),#1016); #990 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#991,#992,#993,#994,#995,#996, #997,#998,#999,#1000,#1001,#1002,#1003,#1004,#1005,#1006,#1007,#1008 ,#1009,#1010,#1011,#1012,#1013,#1014,#1015),.UNSPECIFIED.,.F.,.F.,(4 ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4),(0.E+000, 0.285599332145,0.571198664289,0.856797996434,1.142397328578, 1.427996660723,1.713595992867,1.999195325012,2.284794657156, 2.570393989301,2.855993321445,3.14159265359,3.427191985734, 3.712791317879,3.998390650023,4.283989982168,4.569589314312, 4.855188646457,5.140787978601,5.426387310746,5.711986642891, 5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.); #991 = CARTESIAN_POINT('',(1.33226762955E-016,-12.5)); #992 = CARTESIAN_POINT('',(9.519977738151E-002,-12.5)); #993 = CARTESIAN_POINT('',(0.285599332145,-12.5)); #994 = CARTESIAN_POINT('',(0.571198664289,-12.5)); #995 = CARTESIAN_POINT('',(0.856797996434,-12.5)); #996 = CARTESIAN_POINT('',(1.142397328578,-12.5)); #997 = CARTESIAN_POINT('',(1.427996660723,-12.5)); #998 = CARTESIAN_POINT('',(1.713595992867,-12.5)); #999 = CARTESIAN_POINT('',(1.999195325012,-12.5)); #1000 = CARTESIAN_POINT('',(2.284794657156,-12.5)); #1001 = CARTESIAN_POINT('',(2.570393989301,-12.5)); #1002 = CARTESIAN_POINT('',(2.855993321445,-12.5)); #1003 = CARTESIAN_POINT('',(3.14159265359,-12.5)); #1004 = CARTESIAN_POINT('',(3.427191985734,-12.5)); #1005 = CARTESIAN_POINT('',(3.712791317879,-12.5)); #1006 = CARTESIAN_POINT('',(3.998390650023,-12.5)); #1007 = CARTESIAN_POINT('',(4.283989982168,-12.5)); #1008 = CARTESIAN_POINT('',(4.569589314312,-12.5)); #1009 = CARTESIAN_POINT('',(4.855188646457,-12.5)); #1010 = CARTESIAN_POINT('',(5.140787978601,-12.5)); #1011 = CARTESIAN_POINT('',(5.426387310746,-12.5)); #1012 = CARTESIAN_POINT('',(5.711986642891,-12.5)); #1013 = CARTESIAN_POINT('',(5.997585975035,-12.5)); #1014 = CARTESIAN_POINT('',(6.187985529798,-12.5)); #1015 = CARTESIAN_POINT('',(6.28318530718,-12.5)); #1016 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1017 = PCURVE('',#1018,#1023); #1018 = CYLINDRICAL_SURFACE('',#1019,5.); #1019 = AXIS2_PLACEMENT_3D('',#1020,#1021,#1022); #1020 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-16.60362)); #1021 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #1022 = DIRECTION('',(1.,0.E+000,0.E+000)); #1023 = DEFINITIONAL_REPRESENTATION('',(#1024),#1050); #1024 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1025,#1026,#1027,#1028,#1029, #1030,#1031,#1032,#1033,#1034,#1035,#1036,#1037,#1038,#1039,#1040, #1041,#1042,#1043,#1044,#1045,#1046,#1047,#1048,#1049), .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4), (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578, 1.427996660723,1.713595992867,1.999195325012,2.284794657156, 2.570393989301,2.855993321445,3.14159265359,3.427191985734, 3.712791317879,3.998390650023,4.283989982168,4.569589314312, 4.855188646457,5.140787978601,5.426387310746,5.711986642891, 5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.); #1025 = CARTESIAN_POINT('',(0.E+000,-17.03995)); #1026 = CARTESIAN_POINT('',(9.519977738151E-002,-17.03995)); #1027 = CARTESIAN_POINT('',(0.285599332145,-17.03995)); #1028 = CARTESIAN_POINT('',(0.571198664289,-17.03995)); #1029 = CARTESIAN_POINT('',(0.856797996434,-17.03995)); #1030 = CARTESIAN_POINT('',(1.142397328578,-17.03995)); #1031 = CARTESIAN_POINT('',(1.427996660723,-17.03995)); #1032 = CARTESIAN_POINT('',(1.713595992867,-17.03995)); #1033 = CARTESIAN_POINT('',(1.999195325012,-17.03995)); #1034 = CARTESIAN_POINT('',(2.284794657156,-17.03995)); #1035 = CARTESIAN_POINT('',(2.570393989301,-17.03995)); #1036 = CARTESIAN_POINT('',(2.855993321445,-17.03995)); #1037 = CARTESIAN_POINT('',(3.14159265359,-17.03995)); #1038 = CARTESIAN_POINT('',(3.427191985734,-17.03995)); #1039 = CARTESIAN_POINT('',(3.712791317879,-17.03995)); #1040 = CARTESIAN_POINT('',(3.998390650023,-17.03995)); #1041 = CARTESIAN_POINT('',(4.283989982168,-17.03995)); #1042 = CARTESIAN_POINT('',(4.569589314312,-17.03995)); #1043 = CARTESIAN_POINT('',(4.855188646457,-17.03995)); #1044 = CARTESIAN_POINT('',(5.140787978601,-17.03995)); #1045 = CARTESIAN_POINT('',(5.426387310746,-17.03995)); #1046 = CARTESIAN_POINT('',(5.711986642891,-17.03995)); #1047 = CARTESIAN_POINT('',(5.997585975035,-17.03995)); #1048 = CARTESIAN_POINT('',(6.187985529798,-17.03995)); #1049 = CARTESIAN_POINT('',(6.28318530718,-17.03995)); #1050 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1051 = ORIENTED_EDGE('',*,*,#958,.F.); #1052 = ADVANCED_FACE('',(#1053),#1018,.T.); #1053 = FACE_BOUND('',#1054,.T.); #1054 = EDGE_LOOP('',(#1055,#1128,#1149,#1150)); #1055 = ORIENTED_EDGE('',*,*,#1056,.F.); #1056 = EDGE_CURVE('',#1057,#1057,#1059,.T.); #1057 = VERTEX_POINT('',#1058); #1058 = CARTESIAN_POINT('',(-12.89811369191,-0.826297072243,-33.64357)); #1059 = SURFACE_CURVE('',#1060,(#1065,#1094),.PCURVE_S2.); #1060 = CIRCLE('',#1061,5.); #1061 = AXIS2_PLACEMENT_3D('',#1062,#1063,#1064); #1062 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-33.64357)); #1063 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #1064 = DIRECTION('',(1.,0.E+000,0.E+000)); #1065 = PCURVE('',#1018,#1066); #1066 = DEFINITIONAL_REPRESENTATION('',(#1067),#1093); #1067 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1068,#1069,#1070,#1071,#1072, #1073,#1074,#1075,#1076,#1077,#1078,#1079,#1080,#1081,#1082,#1083, #1084,#1085,#1086,#1087,#1088,#1089,#1090,#1091,#1092), .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4), (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578, 1.427996660723,1.713595992867,1.999195325012,2.284794657156, 2.570393989301,2.855993321445,3.14159265359,3.427191985734, 3.712791317879,3.998390650023,4.283989982168,4.569589314312, 4.855188646457,5.140787978601,5.426387310746,5.711986642891, 5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.); #1068 = CARTESIAN_POINT('',(0.E+000,17.03995)); #1069 = CARTESIAN_POINT('',(9.519977738151E-002,17.03995)); #1070 = CARTESIAN_POINT('',(0.285599332145,17.03995)); #1071 = CARTESIAN_POINT('',(0.571198664289,17.03995)); #1072 = CARTESIAN_POINT('',(0.856797996434,17.03995)); #1073 = CARTESIAN_POINT('',(1.142397328578,17.03995)); #1074 = CARTESIAN_POINT('',(1.427996660723,17.03995)); #1075 = CARTESIAN_POINT('',(1.713595992867,17.03995)); #1076 = CARTESIAN_POINT('',(1.999195325012,17.03995)); #1077 = CARTESIAN_POINT('',(2.284794657156,17.03995)); #1078 = CARTESIAN_POINT('',(2.570393989301,17.03995)); #1079 = CARTESIAN_POINT('',(2.855993321445,17.03995)); #1080 = CARTESIAN_POINT('',(3.14159265359,17.03995)); #1081 = CARTESIAN_POINT('',(3.427191985734,17.03995)); #1082 = CARTESIAN_POINT('',(3.712791317879,17.03995)); #1083 = CARTESIAN_POINT('',(3.998390650023,17.03995)); #1084 = CARTESIAN_POINT('',(4.283989982168,17.03995)); #1085 = CARTESIAN_POINT('',(4.569589314312,17.03995)); #1086 = CARTESIAN_POINT('',(4.855188646457,17.03995)); #1087 = CARTESIAN_POINT('',(5.140787978601,17.03995)); #1088 = CARTESIAN_POINT('',(5.426387310746,17.03995)); #1089 = CARTESIAN_POINT('',(5.711986642891,17.03995)); #1090 = CARTESIAN_POINT('',(5.997585975035,17.03995)); #1091 = CARTESIAN_POINT('',(6.187985529798,17.03995)); #1092 = CARTESIAN_POINT('',(6.28318530718,17.03995)); #1093 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1094 = PCURVE('',#1095,#1100); #1095 = CONICAL_SURFACE('',#1096,4.53995,0.785398163397); #1096 = AXIS2_PLACEMENT_3D('',#1097,#1098,#1099); #1097 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-43.18352)); #1098 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #1099 = DIRECTION('',(-1.,-1.224606353822E-016,2.719172340232E-032)); #1100 = DEFINITIONAL_REPRESENTATION('',(#1101),#1127); #1101 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1102,#1103,#1104,#1105,#1106, #1107,#1108,#1109,#1110,#1111,#1112,#1113,#1114,#1115,#1116,#1117, #1118,#1119,#1120,#1121,#1122,#1123,#1124,#1125,#1126), .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4), (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578, 1.427996660723,1.713595992867,1.999195325012,2.284794657156, 2.570393989301,2.855993321445,3.14159265359,3.427191985734, 3.712791317879,3.998390650023,4.283989982168,4.569589314312, 4.855188646457,5.140787978601,5.426387310746,5.711986642891, 5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.); #1102 = CARTESIAN_POINT('',(1.554312234475E-016,-9.53995)); #1103 = CARTESIAN_POINT('',(9.519977738151E-002,-9.53995)); #1104 = CARTESIAN_POINT('',(0.285599332145,-9.53995)); #1105 = CARTESIAN_POINT('',(0.571198664289,-9.53995)); #1106 = CARTESIAN_POINT('',(0.856797996434,-9.53995)); #1107 = CARTESIAN_POINT('',(1.142397328578,-9.53995)); #1108 = CARTESIAN_POINT('',(1.427996660723,-9.53995)); #1109 = CARTESIAN_POINT('',(1.713595992867,-9.53995)); #1110 = CARTESIAN_POINT('',(1.999195325012,-9.53995)); #1111 = CARTESIAN_POINT('',(2.284794657156,-9.53995)); #1112 = CARTESIAN_POINT('',(2.570393989301,-9.53995)); #1113 = CARTESIAN_POINT('',(2.855993321445,-9.53995)); #1114 = CARTESIAN_POINT('',(3.14159265359,-9.53995)); #1115 = CARTESIAN_POINT('',(3.427191985734,-9.53995)); #1116 = CARTESIAN_POINT('',(3.712791317879,-9.53995)); #1117 = CARTESIAN_POINT('',(3.998390650023,-9.53995)); #1118 = CARTESIAN_POINT('',(4.283989982168,-9.53995)); #1119 = CARTESIAN_POINT('',(4.569589314312,-9.53995)); #1120 = CARTESIAN_POINT('',(4.855188646457,-9.53995)); #1121 = CARTESIAN_POINT('',(5.140787978601,-9.53995)); #1122 = CARTESIAN_POINT('',(5.426387310746,-9.53995)); #1123 = CARTESIAN_POINT('',(5.711986642891,-9.53995)); #1124 = CARTESIAN_POINT('',(5.997585975035,-9.53995)); #1125 = CARTESIAN_POINT('',(6.187985529798,-9.53995)); #1126 = CARTESIAN_POINT('',(6.28318530718,-9.53995)); #1127 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1128 = ORIENTED_EDGE('',*,*,#1129,.F.); #1129 = EDGE_CURVE('',#959,#1057,#1130,.T.); #1130 = SEAM_CURVE('',#1131,(#1135,#1142),.PCURVE_S2.); #1131 = LINE('',#1132,#1133); #1132 = CARTESIAN_POINT('',(-12.89811369191,-0.826297072243,-16.60362)); #1133 = VECTOR('',#1134,1.); #1134 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #1135 = PCURVE('',#1018,#1136); #1136 = DEFINITIONAL_REPRESENTATION('',(#1137),#1141); #1137 = LINE('',#1138,#1139); #1138 = CARTESIAN_POINT('',(0.E+000,0.E+000)); #1139 = VECTOR('',#1140,1.); #1140 = DIRECTION('',(0.E+000,1.)); #1141 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1142 = PCURVE('',#1018,#1143); #1143 = DEFINITIONAL_REPRESENTATION('',(#1144),#1148); #1144 = LINE('',#1145,#1146); #1145 = CARTESIAN_POINT('',(6.28318530718,0.E+000)); #1146 = VECTOR('',#1147,1.); #1147 = DIRECTION('',(0.E+000,1.)); #1148 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1149 = ORIENTED_EDGE('',*,*,#981,.T.); #1150 = ORIENTED_EDGE('',*,*,#1129,.T.); #1151 = ADVANCED_FACE('',(#1152),#1095,.T.); #1152 = FACE_BOUND('',#1153,.T.); #1153 = EDGE_LOOP('',(#1154,#1209,#1230,#1231)); #1154 = ORIENTED_EDGE('',*,*,#1155,.F.); #1155 = EDGE_CURVE('',#1156,#1156,#1158,.T.); #1156 = VERTEX_POINT('',#1157); #1157 = CARTESIAN_POINT('',(-13.81821369191,-0.826297072243,-34.56367)); #1158 = SURFACE_CURVE('',#1159,(#1164,#1193),.PCURVE_S2.); #1159 = CIRCLE('',#1160,4.0799); #1160 = AXIS2_PLACEMENT_3D('',#1161,#1162,#1163); #1161 = CARTESIAN_POINT('',(-17.89811369191,-0.826297072243,-34.56367)); #1162 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #1163 = DIRECTION('',(1.,0.E+000,0.E+000)); #1164 = PCURVE('',#1095,#1165); #1165 = DEFINITIONAL_REPRESENTATION('',(#1166),#1192); #1166 = B_SPLINE_CURVE_WITH_KNOTS('',3,(#1167,#1168,#1169,#1170,#1171, #1172,#1173,#1174,#1175,#1176,#1177,#1178,#1179,#1180,#1181,#1182, #1183,#1184,#1185,#1186,#1187,#1188,#1189,#1190,#1191), .UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4), (0.E+000,0.285599332145,0.571198664289,0.856797996434,1.142397328578, 1.427996660723,1.713595992867,1.999195325012,2.284794657156, 2.570393989301,2.855993321445,3.14159265359,3.427191985734, 3.712791317879,3.998390650023,4.283989982168,4.569589314312, 4.855188646457,5.140787978601,5.426387310746,5.711986642891, 5.997585975035,6.28318530718),.QUASI_UNIFORM_KNOTS.); #1167 = CARTESIAN_POINT('',(1.632720936236E-016,-8.61985)); #1168 = CARTESIAN_POINT('',(9.519977738151E-002,-8.61985)); #1169 = CARTESIAN_POINT('',(0.285599332145,-8.61985)); #1170 = CARTESIAN_POINT('',(0.571198664289,-8.61985)); #1171 = CARTESIAN_POINT('',(0.856797996434,-8.61985)); #1172 = CARTESIAN_POINT('',(1.142397328578,-8.61985)); #1173 = CARTESIAN_POINT('',(1.427996660723,-8.61985)); #1174 = CARTESIAN_POINT('',(1.713595992867,-8.61985)); #1175 = CARTESIAN_POINT('',(1.999195325012,-8.61985)); #1176 = CARTESIAN_POINT('',(2.284794657156,-8.61985)); #1177 = CARTESIAN_POINT('',(2.570393989301,-8.61985)); #1178 = CARTESIAN_POINT('',(2.855993321445,-8.61985)); #1179 = CARTESIAN_POINT('',(3.14159265359,-8.61985)); #1180 = CARTESIAN_POINT('',(3.427191985734,-8.61985)); #1181 = CARTESIAN_POINT('',(3.712791317879,-8.61985)); #1182 = CARTESIAN_POINT('',(3.998390650023,-8.61985)); #1183 = CARTESIAN_POINT('',(4.283989982168,-8.61985)); #1184 = CARTESIAN_POINT('',(4.569589314312,-8.61985)); #1185 = CARTESIAN_POINT('',(4.855188646457,-8.61985)); #1186 = CARTESIAN_POINT('',(5.140787978601,-8.61985)); #1187 = CARTESIAN_POINT('',(5.426387310746,-8.61985)); #1188 = CARTESIAN_POINT('',(5.711986642891,-8.61985)); #1189 = CARTESIAN_POINT('',(5.997585975035,-8.61985)); #1190 = CARTESIAN_POINT('',(6.187985529798,-8.61985)); #1191 = CARTESIAN_POINT('',(6.28318530718,-8.61985)); #1192 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1193 = PCURVE('',#1194,#1199); #1194 = PLANE('',#1195); #1195 = AXIS2_PLACEMENT_3D('',#1196,#1197,#1198); #1196 = CARTESIAN_POINT('',(-15.85816369191,-0.826297072243,-34.56367)); #1197 = DIRECTION('',(0.E+000,-2.22044604925E-016,-1.)); #1198 = DIRECTION('',(0.E+000,1.,-2.22044604925E-016)); #1199 = DEFINITIONAL_REPRESENTATION('',(#1200),#1208); #1200 = ( BOUNDED_CURVE() B_SPLINE_CURVE(2,(#1201,#1202,#1203,#1204, #1205,#1206,#1207),.UNSPECIFIED.,.T.,.F.) B_SPLINE_CURVE_WITH_KNOTS((1,2 ,2,2,2,1),(-2.094395102393,0.E+000,2.094395102393,4.188790204786, 6.28318530718,8.377580409573),.UNSPECIFIED.) CURVE() GEOMETRIC_REPRESENTATION_ITEM() RATIONAL_B_SPLINE_CURVE((1.,0.5,1.,0.5, 1.,0.5,1.)) REPRESENTATION_ITEM('') ); #1201 = CARTESIAN_POINT('',(0.E+000,2.03995)); #1202 = CARTESIAN_POINT('',(-7.0665940898,2.03995)); #1203 = CARTESIAN_POINT('',(-3.5332970449,-4.0799)); #1204 = CARTESIAN_POINT('',(-9.99254292592E-016,-10.19975)); #1205 = CARTESIAN_POINT('',(3.5332970449,-4.0799)); #1206 = CARTESIAN_POINT('',(7.0665940898,2.03995)); #1207 = CARTESIAN_POINT('',(0.E+000,2.03995)); #1208 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1209 = ORIENTED_EDGE('',*,*,#1210,.F.); #1210 = EDGE_CURVE('',#1057,#1156,#1211,.T.); #1211 = SEAM_CURVE('',#1212,(#1216,#1223),.PCURVE_S2.); #1212 = LINE('',#1213,#1214); #1213 = CARTESIAN_POINT('',(-22.43806369191,-0.826297072243,-43.18352)); #1214 = VECTOR('',#1215,1.); #1215 = DIRECTION('',(-0.707106781187,-2.436019915756E-016, -0.707106781187)); #1216 = PCURVE('',#1095,#1217); #1217 = DEFINITIONAL_REPRESENTATION('',(#1218),#1222); #1218 = LINE('',#1219,#1220); #1219 = CARTESIAN_POINT('',(0.E+000,0.E+000)); #1220 = VECTOR('',#1221,1.); #1221 = DIRECTION('',(0.E+000,1.)); #1222 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1223 = PCURVE('',#1095,#1224); #1224 = DEFINITIONAL_REPRESENTATION('',(#1225),#1229); #1225 = LINE('',#1226,#1227); #1226 = CARTESIAN_POINT('',(6.28318530718,0.E+000)); #1227 = VECTOR('',#1228,1.); #1228 = DIRECTION('',(0.E+000,1.)); #1229 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','' ) ); #1230 = ORIENTED_EDGE('',*,*,#1056,.T.); #1231 = ORIENTED_EDGE('',*,*,#1210,.T.); #1232 = ADVANCED_FACE('',(#1233),#1194,.T.); #1233 = FACE_BOUND('',#1234,.T.); #1234 = EDGE_LOOP('',(#1235)); #1235 = ORIENTED_EDGE('',*,*,#1155,.T.); #1236 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3) GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#1239)) GLOBAL_UNIT_ASSIGNED_CONTEXT((#1237,#1238)) REPRESENTATION_CONTEXT('Cont ext #1','3D Context with UNIT and UNCERTAINTY') ); #1237 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) ); #1238 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) ); #1239 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-006),#1237,'dis tance_accuracy_value','Confusion accuracy'); ENDSEC; END-ISO-10303-21; netgen-6.2.1905/tutorials/torus.geo0000644000175000017500000000012713504650527015677 0ustar kurtkurt# ## a torus # algebraic3d solid tor = torus ( 0, 0, 0; 1, 0, 0; 2 ; 1 ); tlo tor; netgen-6.2.1905/tutorials/cube.geo0000644000175000017500000000046013504650527015441 0ustar kurtkurt# ## A cube # algebraic3d # cube consisting of 6 planes: solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); tlo cube; netgen-6.2.1905/tutorials/twocyl.geo0000644000175000017500000000047313504650527016050 0ustar kurtkurtalgebraic3d # # two intersecting cylinderes # solid cyl1 = cylinder ( 1, 0, 0; -1, 0, 0; 0.5 ) and plane (-1, 0, 0; -1, 0, 0) and plane (1, 0, 0; 1, 0, 0); solid cyl2 = cylinder ( 0, 1, 0.3; 0, -1, 0.3; 0.5 ) and plane (0, -1, 0; 0, -1, 0) and plane (0, 1, 0; 0, 1, 0); solid main = cyl1 or cyl2; tlo main; netgen-6.2.1905/tutorials/extrusion.geo0000644000175000017500000000223113504650527016561 0ustar kurtkurtalgebraic3d curve2d procurve1=(8; -1,0; -0.7,0.7; 0,1; 0.7,0.7; 1,0; 0.7,-0.7; 0,-1; -0.7,-0.7; 4; 3,1,2,3; 3,3,4,5; 3,5,6,7; 3,7,8,1); curve2d procurve2=(4; 1,1; 1,-1; -1,-1; -1,1; 4; 2,1,2; 2,2,3; 2,3,4; 2,4,1); curve3d pathcurve1=(9; 0,0,0; 10,0,5; 10,10,10; 10,20,15; 0,20,20; -10,20,25; -10,10,30; -10,0,35; 0,0,40; 4; 3,1,2,3; 3,3,4,5; 3,5,6,7; 3,7,8,9); curve3d pathcurve2=(2; 0,0,0; 0,10,0; 1; 2,1,2); curve3d pathcurve3=(3; 0,0,0; 10,0,5; 10,10,10; 1; 3,1,2,3); curve3d pathcurve4=(9; 0,0,0; 10,0,0; 10,10,0; 10,20,0; 0,20,0; -10,20,0; -10,10,0; -10,0,0; 0,0,0; 4; 3,1,2,3; 3,3,4,5; 3,5,6,7; 3,7,8,9); solid p1 = plane(1,0,0;-1,0,0); solid p2 = plane(10,9,10;0,1,0); solid p3 = plane(0,1,0;0,-1,0); solid p4 = plane(0,9,0;0,1,0); solid ob1 = orthobrick(-1,-5,-5;1,5,45); solid ext = extrusion(pathcurve1;procurve2;0,0,1) and not ob1; #solid ext = extrusion(pathcurve4;procurve2;0,0,1); #solid ext = extrusion(pathcurve3;procurve1;0,0,1) and p1 and p2; #solid ext = extrusion(pathcurve2;procurve2;0,0,1) and p3 and p4; solid sp = sphere(0,0,0;4); solid comb = sp or ext; #tlo ext; tlo comb;netgen-6.2.1905/tutorials/squarecircle.in2d0000644000175000017500000000214113504650527017265 0ustar kurtkurt# keyword for 2D geometry, version 2 splinecurves2dv2 # a global grading factor 2 # the points (point number, x and y coordinates) points 1 0 0 2 1 0 3 1 1 4 0 1 5 0.5 0.4 6 0.6 0.4 7 0.6 0.5 8 0.6 0.6 9 0.5 0.6 10 0.4 0.6 11 0.4 0.5 12 0.4 0.4 # boundary curves consisting of # dl dr np p1 p1 flaglist # with # dl ... sub-domain nr on left side # dr ... sub-domain nr on right side # np ... curve is given by 2 (or 3) points # p1, p2 ... points defining the curve # flagslist segments 1 0 2 1 2 -bc=1 1 0 2 2 3 -bc=1 1 0 2 3 4 -bc=1 1 0 2 4 1 -bc=1 2 1 3 5 6 7 -bc=2 2 1 3 7 8 9 -bc=2 2 1 3 9 10 11 -bc=2 2 1 3 11 12 5 -bc=2 materials 1 domain1 -maxh=0.2 2 domain2 -maxh=0.05 netgen-6.2.1905/tutorials/squarehole.in2d0000644000175000017500000000216013504650527016754 0ustar kurtkurt# keyword for 2D geometry, version 2 splinecurves2dv2 # a global grading factor 2 # the points (point number, x and y coordinates) points 1 0 0 2 1 0 3 1 1 4 0 1 5 0.5 0.4 6 0.6 0.4 7 0.6 0.5 8 0.6 0.6 9 0.5 0.6 10 0.4 0.6 11 0.4 0.5 12 0.4 0.4 # boundary curves consisting of # dl dr np p1 p1 flaglist # with # dl ... sub-domain nr on left side # dr ... sub-domain nr on right side # np ... curve is given by 2 (or 3) points # p1, p2 ... points defining the curve # flagslist segments 1 0 2 1 2 -bc=1 1 0 2 2 3 -bc=1 1 0 2 3 4 -bc=1 1 0 2 4 1 -bc=1 0 1 3 5 6 7 -bc=2 -maxh=0.05 0 1 3 7 8 9 -bc=2 -maxh=0.05 0 1 3 9 10 11 -bc=2 -maxh=0.05 0 1 3 11 12 5 -bc=2 -maxh=0.05 materials 1 domain1 -maxh=0.2 netgen-6.2.1905/tutorials/matrix.geo0000644000175000017500000000133113504650527016025 0ustar kurtkurt# # a matrix with holes # algebraic3d solid holes = sphere (0.3, 0.4, 0.4; 0.1) or sphere (0.7, 0.2, 0.8; 0.15) or sphere (0.8, 0.5, 0.4; 0.11) or sphere (0.6, 0.2, 0.8; 0.13) or sphere (0.4, 0.3, 0.6; 0.14) or sphere (0.6, 0.3, 0.4; 0.16) or sphere (0.2, 0.8, 0.6; 0.17) or sphere (0.4, 0.6, 0.5; 0.2); solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid rest = cube and not holes; # two sub-domains tlo holes -col=[1,0,0]; tlo rest -col=[0,0,1] -transparent; netgen-6.2.1905/tutorials/shell.geo0000644000175000017500000000025113504650527015630 0ustar kurtkurtalgebraic3d solid main = sphere (0, 0, 0; 1) and not sphere (0, 0, 0; 0.98); # or orthobrick (-0.4, -0.4, -0.4; 0.4, 0.4, 0.4); tlo main -maxh=0.02; netgen-6.2.1905/tutorials/sphere.geo0000644000175000017500000000011513504650527016006 0ustar kurtkurtalgebraic3d solid main = sphere (0, 0, 0; 1); tlo main; point (0, 0, 0); netgen-6.2.1905/tutorials/period.geo0000644000175000017500000000123613504650527016007 0ustar kurtkurt## ## Example with periodic boundary conditions ## by Joachim Schoeberl ## ## algebraic3d solid p1 = plane (0, 0, 0; 0, 0, -1); solid p2 = plane (1, 1, 1; 0, 0, 1); solid p3 = plane (0, 0, 0; 0, -1, 0); solid p4 = plane (1, 1, 1; 0, 1, 0); solid p5 = plane (0, 0, 0; -1, 0, 0); solid p6 = plane (1, 1, 1; 1, 0, 0); solid cube = p1 and p2 and p3 and p4 and p5 and p6; solid cyls = cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.3) or cylinder (0, 0.5, 0.2; 1, 0.5, 0.2; 0.1); solid matrix = cube and not cyls; solid inner = cube and cyls; tlo matrix -transparent; tlo inner -col=[1,0,0]; identify periodic p1 p2; identify periodic p3 p4; identify periodic p5 p6; netgen-6.2.1905/tutorials/revolution.geo0000644000175000017500000000027513504650527016735 0ustar kurtkurtalgebraic3d curve2d testcurve=(7; 1,0; 1,1; 1.5,1.5; 2,3; 2.5,1.5; 3,1; 3,0; 3; 3,1,2,3; 3,3,4,5; 3,5,6,7); solid something = revolution(0,0,0;1,0,0;testcurve); tlo something;netgen-6.2.1905/tutorials/square.in2d0000644000175000017500000000134013504650527016103 0ustar kurtkurt# keyword for 2D geometry, version 2 splinecurves2dv2 # a global grading factor 2 # the points (point number, x and y coordinates) points 1 0 0 -maxh=0.01 2 1 0 3 1 1 4 0 1 # boundary curves consisting of # dl dr np p1 p1 flaglist # with # dl ... sub-domain nr on left side # dr ... sub-domain nr on right side # np ... curve is given by 2 (or 3) points # p1, p2 ... points defining the curve # flagslist segments 1 0 2 1 2 -bc=1 -maxh=0.1 1 0 2 2 3 -bc=1 1 0 2 3 4 -bc=1 1 0 2 4 1 -bc=2 materials 1 domain1 -maxh=0.3 netgen-6.2.1905/tutorials/trafo.geo0000644000175000017500000000275313504650527015645 0ustar kurtkurtalgebraic3d # # a transformer # solid core = plane (-8, 0, 0; -1, 0, 0) and plane ( 8, 0, 0; 1, 0, 0) and plane ( 0, -6, 0; 0, -1, 0) and plane ( 0, 6, 0; 0, 1, 0) and plane ( 0, 0, -1; 0, 0, -1) and plane ( 0, 0, 1; 0, 0, 1) and not ( plane (-6, 0, 0; -1, 0, 0) and plane (-1, 0, 0; 1, 0, 0) and plane ( 0, -4, 0; 0, -1, 0) and plane ( 0, 4, 0; 0, 1, 0) ) and not ( plane ( 6, 0, 0; 1, 0, 0) and plane ( 1, 0, 0; -1, 0, 0) and plane ( 0, -4, 0; 0, -1, 0) and plane ( 0, 4, 0; 0, 1, 0) ); solid coil1 = cylinder (-7, -3, 0;-7, 3, 0; 3) and not cylinder (-7, -3, 0;-7, 3, 0; 2) and plane (0, -3, 0; 0, -1, 0) and plane (0, 3, 0; 0, 1, 0); solid coil2 = cylinder ( 0, -3, 0; 0, 3, 0; 3) and not cylinder ( 0, -3, 0; 0, 3, 0; 2) and plane (0, -3, 0; 0, -1, 0) and plane (0, 3, 0; 0, 1, 0); solid coil3 = cylinder ( 7, -3, 0; 7, 3, 0; 3) and not cylinder ( 7, -3, 0; 7, 3, 0; 2) and plane (0, -3, 0; 0, -1, 0) and plane (0, 3, 0; 0, 1, 0); solid box = plane (-12, 0, 0; -1, 0, 0) and plane ( 12, 0, 0; 1, 0, 0) and plane ( 0, 8, 0; 0, 1, 0) and plane ( 0,-8, 0; 0, -1, 0) and plane ( 0, 0, 5; 0, 0, 1) and plane ( 0, 0, -5; 0, 0, -1); solid air = box and not core and not coil1 and not coil2 and not coil3; tlo coil1 -col=[0,1,0]; tlo coil2 -col=[0,1,0]; tlo coil3 -col=[0,1,0]; tlo air -col=[0,0,1] -transparent; tlo core -col=[1,1,0]; netgen-6.2.1905/tutorials/boundarycondition.geo0000644000175000017500000000060413504650527020255 0ustar kurtkurtalgebraic3d solid p1 = plane (0.5, 0, 0; 1, 0, 0); # since surfaces of both bricks are identic they get the same bc id: solid brick1 = orthobrick (0,0,0; 1,1,1) and p1 -bc=1; solid brick2 = orthobrick (0,0,-1; 1,1,0) and p1 -bc=2; tlo brick1; tlo brick2; # override bc number: # all faces of solid p1 belonging to the boundary of tlo brick1 get bc=3 boundarycondition p1 brick1 3; netgen-6.2.1905/tutorials/manyholes2.geo0000644000175000017500000000070213504650527016603 0ustar kurtkurtalgebraic3d # ## CSG feature copy # # define a axis parallel brick: solid br = orthobrick (0, 0, 0; 20, 20, 1); # define reference cylinder: solid cyl1 = cylinder (0.5, 0.5, -1; 0.5, 0.5, 3; 0.2); # make copies: solid cylx = multitranslate (1, 0, 0; 19; cyl1); solid cyls = multitranslate (0, 1, 0; 19; cylx); solid main = br and not cyls; tlo main; # provide bounding-box for fastening bisection alg: boundingbox (-1, -1, -1; 21, 21, 2); netgen-6.2.1905/tutorials/frame.step0000644000175000017500000170775013504650527016037 0ustar kurtkurtISO-10303-21; HEADER; FILE_DESCRIPTION((''),'2;1'); FILE_NAME('PROESOURCE','2002-11-04T',('user-01'),(''), 'PRO/ENGINEER BY PARAMETRIC TECHNOLOGY CORPORATION, 2002060', 'PRO/ENGINEER BY PARAMETRIC TECHNOLOGY CORPORATION, 2002060',''); FILE_SCHEMA(('CONFIG_CONTROL_DESIGN')); ENDSEC; DATA; #1=DIRECTION('',(-1.E0,0.E0,0.E0)); #2=VECTOR('',#1,1.693725393319E1); #3=CARTESIAN_POINT('',(2.046862696660E1,0.E0,8.E0)); #4=LINE('',#3,#2); #5=DIRECTION('',(-1.E0,0.E0,0.E0)); #6=VECTOR('',#5,9.E0); #7=CARTESIAN_POINT('',(1.65E1,0.E0,2.5E0)); #8=LINE('',#7,#6); #9=CARTESIAN_POINT('',(1.8E1,0.E0,3.075E1)); #10=DIRECTION('',(0.E0,-1.E0,0.E0)); #11=DIRECTION('',(1.E0,0.E0,0.E0)); #12=AXIS2_PLACEMENT_3D('',#9,#10,#11); #14=CARTESIAN_POINT('',(1.8E1,0.E0,3.075E1)); #15=DIRECTION('',(0.E0,-1.E0,0.E0)); #16=DIRECTION('',(-1.E0,0.E0,0.E0)); #17=AXIS2_PLACEMENT_3D('',#14,#15,#16); #19=CARTESIAN_POINT('',(1.8E1,0.E0,1.25E0)); #20=DIRECTION('',(0.E0,-1.E0,0.E0)); #21=DIRECTION('',(1.E0,0.E0,0.E0)); #22=AXIS2_PLACEMENT_3D('',#19,#20,#21); #24=CARTESIAN_POINT('',(1.8E1,0.E0,1.25E0)); #25=DIRECTION('',(0.E0,-1.E0,0.E0)); #26=DIRECTION('',(-1.E0,0.E0,0.E0)); #27=AXIS2_PLACEMENT_3D('',#24,#25,#26); #29=CARTESIAN_POINT('',(1.2E1,0.E0,3.075E1)); #30=DIRECTION('',(0.E0,-1.E0,0.E0)); #31=DIRECTION('',(1.E0,0.E0,0.E0)); #32=AXIS2_PLACEMENT_3D('',#29,#30,#31); #34=CARTESIAN_POINT('',(1.2E1,0.E0,3.075E1)); #35=DIRECTION('',(0.E0,-1.E0,0.E0)); #36=DIRECTION('',(-1.E0,0.E0,0.E0)); #37=AXIS2_PLACEMENT_3D('',#34,#35,#36); #39=CARTESIAN_POINT('',(6.E0,0.E0,3.075E1)); #40=DIRECTION('',(0.E0,-1.E0,0.E0)); #41=DIRECTION('',(1.E0,0.E0,0.E0)); #42=AXIS2_PLACEMENT_3D('',#39,#40,#41); #44=CARTESIAN_POINT('',(6.E0,0.E0,3.075E1)); #45=DIRECTION('',(0.E0,-1.E0,0.E0)); #46=DIRECTION('',(-1.E0,0.E0,0.E0)); #47=AXIS2_PLACEMENT_3D('',#44,#45,#46); #49=CARTESIAN_POINT('',(1.2E1,0.E0,1.25E0)); #50=DIRECTION('',(0.E0,-1.E0,0.E0)); #51=DIRECTION('',(1.E0,0.E0,0.E0)); #52=AXIS2_PLACEMENT_3D('',#49,#50,#51); #54=CARTESIAN_POINT('',(1.2E1,0.E0,1.25E0)); #55=DIRECTION('',(0.E0,-1.E0,0.E0)); #56=DIRECTION('',(-1.E0,0.E0,0.E0)); #57=AXIS2_PLACEMENT_3D('',#54,#55,#56); #59=CARTESIAN_POINT('',(2.2875E1,0.E0,2.4E1)); #60=DIRECTION('',(0.E0,-1.E0,0.E0)); #61=DIRECTION('',(1.E0,0.E0,0.E0)); #62=AXIS2_PLACEMENT_3D('',#59,#60,#61); #64=CARTESIAN_POINT('',(2.2875E1,0.E0,2.4E1)); #65=DIRECTION('',(0.E0,-1.E0,0.E0)); #66=DIRECTION('',(-1.E0,0.E0,0.E0)); #67=AXIS2_PLACEMENT_3D('',#64,#65,#66); #69=CARTESIAN_POINT('',(2.2875E1,0.E0,1.8E1)); #70=DIRECTION('',(0.E0,-1.E0,0.E0)); #71=DIRECTION('',(1.E0,0.E0,0.E0)); #72=AXIS2_PLACEMENT_3D('',#69,#70,#71); #74=CARTESIAN_POINT('',(2.2875E1,0.E0,1.8E1)); #75=DIRECTION('',(0.E0,-1.E0,0.E0)); #76=DIRECTION('',(-1.E0,0.E0,0.E0)); #77=AXIS2_PLACEMENT_3D('',#74,#75,#76); #79=CARTESIAN_POINT('',(2.2875E1,0.E0,1.2E1)); #80=DIRECTION('',(0.E0,-1.E0,0.E0)); #81=DIRECTION('',(1.E0,0.E0,0.E0)); #82=AXIS2_PLACEMENT_3D('',#79,#80,#81); #84=CARTESIAN_POINT('',(2.2875E1,0.E0,1.2E1)); #85=DIRECTION('',(0.E0,-1.E0,0.E0)); #86=DIRECTION('',(-1.E0,0.E0,0.E0)); #87=AXIS2_PLACEMENT_3D('',#84,#85,#86); #89=CARTESIAN_POINT('',(2.2875E1,0.E0,6.E0)); #90=DIRECTION('',(0.E0,-1.E0,0.E0)); #91=DIRECTION('',(1.E0,0.E0,0.E0)); #92=AXIS2_PLACEMENT_3D('',#89,#90,#91); #94=CARTESIAN_POINT('',(2.2875E1,0.E0,6.E0)); #95=DIRECTION('',(0.E0,-1.E0,0.E0)); #96=DIRECTION('',(-1.E0,0.E0,0.E0)); #97=AXIS2_PLACEMENT_3D('',#94,#95,#96); #99=CARTESIAN_POINT('',(1.125E0,0.E0,2.4E1)); #100=DIRECTION('',(0.E0,-1.E0,0.E0)); #101=DIRECTION('',(1.E0,0.E0,0.E0)); #102=AXIS2_PLACEMENT_3D('',#99,#100,#101); #104=CARTESIAN_POINT('',(1.125E0,0.E0,2.4E1)); #105=DIRECTION('',(0.E0,-1.E0,0.E0)); #106=DIRECTION('',(-1.E0,0.E0,0.E0)); #107=AXIS2_PLACEMENT_3D('',#104,#105,#106); #109=CARTESIAN_POINT('',(1.125E0,0.E0,1.8E1)); #110=DIRECTION('',(0.E0,-1.E0,0.E0)); #111=DIRECTION('',(1.E0,0.E0,0.E0)); #112=AXIS2_PLACEMENT_3D('',#109,#110,#111); #114=CARTESIAN_POINT('',(1.125E0,0.E0,1.8E1)); #115=DIRECTION('',(0.E0,-1.E0,0.E0)); #116=DIRECTION('',(-1.E0,0.E0,0.E0)); #117=AXIS2_PLACEMENT_3D('',#114,#115,#116); #119=CARTESIAN_POINT('',(1.125E0,0.E0,1.2E1)); #120=DIRECTION('',(0.E0,-1.E0,0.E0)); #121=DIRECTION('',(1.E0,0.E0,0.E0)); #122=AXIS2_PLACEMENT_3D('',#119,#120,#121); #124=CARTESIAN_POINT('',(1.125E0,0.E0,1.2E1)); #125=DIRECTION('',(0.E0,-1.E0,0.E0)); #126=DIRECTION('',(-1.E0,0.E0,0.E0)); #127=AXIS2_PLACEMENT_3D('',#124,#125,#126); #129=DIRECTION('',(1.E0,0.E0,0.E0)); #130=VECTOR('',#129,1.E0); #131=CARTESIAN_POINT('',(2.5E1,0.E0,8.E0)); #132=LINE('',#131,#130); #133=DIRECTION('',(0.E0,0.E0,-1.E0)); #134=VECTOR('',#133,3.E0); #135=CARTESIAN_POINT('',(2.4E1,0.E0,7.E0)); #136=LINE('',#135,#134); #137=DIRECTION('',(-1.E0,0.E0,0.E0)); #138=VECTOR('',#137,1.6E1); #139=CARTESIAN_POINT('',(2.E1,0.E0,0.E0)); #140=LINE('',#139,#138); #141=DIRECTION('',(0.E0,0.E0,1.E0)); #142=VECTOR('',#141,3.E0); #143=CARTESIAN_POINT('',(0.E0,0.E0,4.E0)); #144=LINE('',#143,#142); #145=DIRECTION('',(-1.E0,0.E0,0.E0)); #146=VECTOR('',#145,1.E0); #147=CARTESIAN_POINT('',(-1.E0,0.E0,8.E0)); #148=LINE('',#147,#146); #149=DIRECTION('',(0.E0,0.E0,1.E0)); #150=VECTOR('',#149,3.75E0); #151=CARTESIAN_POINT('',(-2.E0,0.E0,8.E0)); #152=LINE('',#151,#150); #153=DIRECTION('',(1.E0,0.E0,0.E0)); #154=VECTOR('',#153,5.E-1); #155=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1)); #156=LINE('',#155,#154); #157=DIRECTION('',(0.E0,0.E0,1.E0)); #158=VECTOR('',#157,1.475E1); #159=CARTESIAN_POINT('',(0.E0,0.E0,1.325E1)); #160=LINE('',#159,#158); #161=DIRECTION('',(1.E0,0.E0,0.E0)); #162=VECTOR('',#161,1.6E1); #163=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1)); #164=LINE('',#163,#162); #165=DIRECTION('',(0.E0,0.E0,-1.E0)); #166=VECTOR('',#165,1.475E1); #167=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1)); #168=LINE('',#167,#166); #169=DIRECTION('',(-1.E0,0.E0,0.E0)); #170=VECTOR('',#169,5.E-1); #171=CARTESIAN_POINT('',(2.55E1,0.E0,1.225E1)); #172=LINE('',#171,#170); #173=DIRECTION('',(0.E0,0.E0,1.E0)); #174=VECTOR('',#173,3.75E0); #175=CARTESIAN_POINT('',(2.6E1,0.E0,8.E0)); #176=LINE('',#175,#174); #177=CARTESIAN_POINT('',(1.125E0,0.E0,6.E0)); #178=DIRECTION('',(0.E0,-1.E0,0.E0)); #179=DIRECTION('',(1.E0,0.E0,0.E0)); #180=AXIS2_PLACEMENT_3D('',#177,#178,#179); #182=CARTESIAN_POINT('',(1.125E0,0.E0,6.E0)); #183=DIRECTION('',(0.E0,-1.E0,0.E0)); #184=DIRECTION('',(-1.E0,0.E0,0.E0)); #185=AXIS2_PLACEMENT_3D('',#182,#183,#184); #187=CARTESIAN_POINT('',(6.E0,0.E0,1.25E0)); #188=DIRECTION('',(0.E0,-1.E0,0.E0)); #189=DIRECTION('',(1.E0,0.E0,0.E0)); #190=AXIS2_PLACEMENT_3D('',#187,#188,#189); #192=CARTESIAN_POINT('',(6.E0,0.E0,1.25E0)); #193=DIRECTION('',(0.E0,-1.E0,0.E0)); #194=DIRECTION('',(-1.E0,0.E0,0.E0)); #195=AXIS2_PLACEMENT_3D('',#192,#193,#194); #197=DIRECTION('',(1.E0,0.E0,0.E0)); #198=VECTOR('',#197,1.3E1); #199=CARTESIAN_POINT('',(5.5E0,0.E0,1.89375E1)); #200=LINE('',#199,#198); #201=DIRECTION('',(0.E0,0.E0,-1.E0)); #202=VECTOR('',#201,2.5625E0); #203=CARTESIAN_POINT('',(2.15E1,0.E0,2.45E1)); #204=LINE('',#203,#202); #205=DIRECTION('',(1.E0,0.E0,0.E0)); #206=VECTOR('',#205,9.E0); #207=CARTESIAN_POINT('',(7.5E0,0.E0,2.95E1)); #208=LINE('',#207,#206); #209=DIRECTION('',(0.E0,0.E0,1.E0)); #210=VECTOR('',#209,2.5625E0); #211=CARTESIAN_POINT('',(2.5E0,0.E0,2.19375E1)); #212=LINE('',#211,#210); #213=DIRECTION('',(0.E0,0.E0,-1.E0)); #214=VECTOR('',#213,8.125E-1); #215=CARTESIAN_POINT('',(2.15E1,0.E0,1.40625E1)); #216=LINE('',#215,#214); #217=DIRECTION('',(-1.E0,0.E0,0.E0)); #218=VECTOR('',#217,1.3E1); #219=CARTESIAN_POINT('',(1.85E1,0.E0,1.70625E1)); #220=LINE('',#219,#218); #221=DIRECTION('',(0.E0,0.E0,1.E0)); #222=VECTOR('',#221,8.125E-1); #223=CARTESIAN_POINT('',(2.5E0,0.E0,1.325E1)); #224=LINE('',#223,#222); #225=DIRECTION('',(1.E0,0.E0,0.E0)); #226=VECTOR('',#225,1.E0); #227=CARTESIAN_POINT('',(3.5E0,0.E0,1.225E1)); #228=LINE('',#227,#226); #229=DIRECTION('',(0.E0,0.E0,-1.E0)); #230=VECTOR('',#229,7.5E-1); #231=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1)); #232=LINE('',#231,#230); #233=DIRECTION('',(1.E0,0.E0,0.E0)); #234=VECTOR('',#233,1.2E1); #235=CARTESIAN_POINT('',(6.E0,0.E0,1.E1)); #236=LINE('',#235,#234); #237=DIRECTION('',(0.E0,0.E0,-1.E0)); #238=VECTOR('',#237,7.5E-1); #239=CARTESIAN_POINT('',(1.9E1,0.E0,1.175E1)); #240=LINE('',#239,#238); #241=DIRECTION('',(-1.E0,0.E0,0.E0)); #242=VECTOR('',#241,1.E0); #243=CARTESIAN_POINT('',(2.05E1,0.E0,1.225E1)); #244=LINE('',#243,#242); #245=CARTESIAN_POINT('',(6.E0,0.E0,9.E0)); #246=DIRECTION('',(0.E0,-1.E0,0.E0)); #247=DIRECTION('',(1.E0,0.E0,0.E0)); #248=AXIS2_PLACEMENT_3D('',#245,#246,#247); #250=CARTESIAN_POINT('',(6.E0,0.E0,9.E0)); #251=DIRECTION('',(0.E0,-1.E0,0.E0)); #252=DIRECTION('',(-1.E0,0.E0,0.E0)); #253=AXIS2_PLACEMENT_3D('',#250,#251,#252); #255=CARTESIAN_POINT('',(1.2E1,0.E0,9.E0)); #256=DIRECTION('',(0.E0,-1.E0,0.E0)); #257=DIRECTION('',(1.E0,0.E0,0.E0)); #258=AXIS2_PLACEMENT_3D('',#255,#256,#257); #260=CARTESIAN_POINT('',(1.2E1,0.E0,9.E0)); #261=DIRECTION('',(0.E0,-1.E0,0.E0)); #262=DIRECTION('',(-1.E0,0.E0,0.E0)); #263=AXIS2_PLACEMENT_3D('',#260,#261,#262); #265=CARTESIAN_POINT('',(1.8E1,0.E0,9.E0)); #266=DIRECTION('',(0.E0,-1.E0,0.E0)); #267=DIRECTION('',(1.E0,0.E0,0.E0)); #268=AXIS2_PLACEMENT_3D('',#265,#266,#267); #270=CARTESIAN_POINT('',(1.8E1,0.E0,9.E0)); #271=DIRECTION('',(0.E0,-1.E0,0.E0)); #272=DIRECTION('',(-1.E0,0.E0,0.E0)); #273=AXIS2_PLACEMENT_3D('',#270,#271,#272); #275=CARTESIAN_POINT('',(6.E0,0.E0,1.8E1)); #276=DIRECTION('',(0.E0,-1.E0,0.E0)); #277=DIRECTION('',(1.E0,0.E0,0.E0)); #278=AXIS2_PLACEMENT_3D('',#275,#276,#277); #280=CARTESIAN_POINT('',(6.E0,0.E0,1.8E1)); #281=DIRECTION('',(0.E0,-1.E0,0.E0)); #282=DIRECTION('',(-1.E0,0.E0,0.E0)); #283=AXIS2_PLACEMENT_3D('',#280,#281,#282); #285=CARTESIAN_POINT('',(1.2E1,0.E0,1.8E1)); #286=DIRECTION('',(0.E0,-1.E0,0.E0)); #287=DIRECTION('',(1.E0,0.E0,0.E0)); #288=AXIS2_PLACEMENT_3D('',#285,#286,#287); #290=CARTESIAN_POINT('',(1.2E1,0.E0,1.8E1)); #291=DIRECTION('',(0.E0,-1.E0,0.E0)); #292=DIRECTION('',(-1.E0,0.E0,0.E0)); #293=AXIS2_PLACEMENT_3D('',#290,#291,#292); #295=CARTESIAN_POINT('',(1.8E1,0.E0,1.8E1)); #296=DIRECTION('',(0.E0,-1.E0,0.E0)); #297=DIRECTION('',(1.E0,0.E0,0.E0)); #298=AXIS2_PLACEMENT_3D('',#295,#296,#297); #300=CARTESIAN_POINT('',(1.8E1,0.E0,1.8E1)); #301=DIRECTION('',(0.E0,-1.E0,0.E0)); #302=DIRECTION('',(-1.E0,0.E0,0.E0)); #303=AXIS2_PLACEMENT_3D('',#300,#301,#302); #305=DIRECTION('',(1.E0,0.E0,0.E0)); #306=VECTOR('',#305,3.E0); #307=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1)); #308=LINE('',#307,#306); #309=CARTESIAN_POINT('',(1.05E1,0.E0,1.25E0)); #310=DIRECTION('',(0.E0,-1.E0,0.E0)); #311=DIRECTION('',(0.E0,0.E0,-1.E0)); #312=AXIS2_PLACEMENT_3D('',#309,#310,#311); #314=DIRECTION('',(-1.E0,0.E0,0.E0)); #315=VECTOR('',#314,3.E0); #316=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0)); #317=LINE('',#316,#315); #318=CARTESIAN_POINT('',(7.5E0,0.E0,1.25E0)); #319=DIRECTION('',(0.E0,-1.E0,0.E0)); #320=DIRECTION('',(0.E0,0.E0,1.E0)); #321=AXIS2_PLACEMENT_3D('',#318,#319,#320); #323=CARTESIAN_POINT('',(1.61E0,0.E0,4.5E0)); #324=DIRECTION('',(0.E0,-1.E0,0.E0)); #325=DIRECTION('',(8.910741301059E-1,0.E0,4.538577912254E-1)); #326=AXIS2_PLACEMENT_3D('',#323,#324,#325); #328=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #329=VECTOR('',#328,4.263248410977E0); #330=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,4.046865146430E0)); #331=LINE('',#330,#329); #332=CARTESIAN_POINT('',(4.553039342392E0,0.E0,1.645354088550E0)); #333=DIRECTION('',(0.E0,-1.E0,0.E0)); #334=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #335=AXIS2_PLACEMENT_3D('',#332,#333,#334); #337=CARTESIAN_POINT('',(7.5E0,0.E0,7.5E0)); #338=DIRECTION('',(0.E0,-1.E0,0.E0)); #339=DIRECTION('',(-8.910741301059E-1,0.E0,-4.538577912254E-1)); #340=AXIS2_PLACEMENT_3D('',#337,#338,#339); #342=DIRECTION('',(0.E0,0.E0,-1.E0)); #343=VECTOR('',#342,3.15E-1); #344=CARTESIAN_POINT('',(6.9E-1,0.E0,7.815E0)); #345=LINE('',#344,#343); #346=CARTESIAN_POINT('',(1.25125E0,0.E0,7.5E0)); #347=DIRECTION('',(0.E0,-1.E0,0.E0)); #348=DIRECTION('',(-1.E0,0.E0,0.E0)); #349=AXIS2_PLACEMENT_3D('',#346,#347,#348); #351=DIRECTION('',(0.E0,0.E0,1.E0)); #352=VECTOR('',#351,3.15E-1); #353=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0)); #354=LINE('',#353,#352); #355=DIRECTION('',(1.E0,0.E0,0.E0)); #356=VECTOR('',#355,7.5E-1); #357=CARTESIAN_POINT('',(2.6875E0,0.E0,8.69E0)); #358=LINE('',#357,#356); #359=DIRECTION('',(0.E0,0.E0,1.E0)); #360=VECTOR('',#359,8.1E-1); #361=CARTESIAN_POINT('',(4.3125E0,0.E0,9.565E0)); #362=LINE('',#361,#360); #363=DIRECTION('',(-1.E0,0.E0,0.E0)); #364=VECTOR('',#363,3.875E0); #365=CARTESIAN_POINT('',(3.4375E0,0.E0,1.125E1)); #366=LINE('',#365,#364); #367=DIRECTION('',(0.E0,0.E0,-1.E0)); #368=VECTOR('',#367,8.1E-1); #369=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.0375E1)); #370=LINE('',#369,#368); #371=DIRECTION('',(1.E0,0.E0,0.E0)); #372=VECTOR('',#371,2.525E-1); #373=CARTESIAN_POINT('',(-4.375E-1,0.E0,8.69E0)); #374=LINE('',#373,#372); #375=DIRECTION('',(0.E0,0.E0,-1.E0)); #376=VECTOR('',#375,3.E0); #377=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1)); #378=LINE('',#377,#376); #379=CARTESIAN_POINT('',(1.25E0,0.E0,1.35E1)); #380=DIRECTION('',(0.E0,-1.E0,0.E0)); #381=DIRECTION('',(-1.E0,0.E0,0.E0)); #382=AXIS2_PLACEMENT_3D('',#379,#380,#381); #384=DIRECTION('',(0.E0,0.E0,1.E0)); #385=VECTOR('',#384,3.E0); #386=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1)); #387=LINE('',#386,#385); #388=CARTESIAN_POINT('',(1.25E0,0.E0,1.65E1)); #389=DIRECTION('',(0.E0,-1.E0,0.E0)); #390=DIRECTION('',(1.E0,0.E0,0.E0)); #391=AXIS2_PLACEMENT_3D('',#388,#389,#390); #393=DIRECTION('',(0.E0,0.E0,-1.E0)); #394=VECTOR('',#393,3.E0); #395=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1)); #396=LINE('',#395,#394); #397=CARTESIAN_POINT('',(1.25E0,0.E0,1.95E1)); #398=DIRECTION('',(0.E0,-1.E0,0.E0)); #399=DIRECTION('',(-1.E0,0.E0,0.E0)); #400=AXIS2_PLACEMENT_3D('',#397,#398,#399); #402=DIRECTION('',(0.E0,0.E0,1.E0)); #403=VECTOR('',#402,3.E0); #404=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1)); #405=LINE('',#404,#403); #406=CARTESIAN_POINT('',(1.25E0,0.E0,2.25E1)); #407=DIRECTION('',(0.E0,-1.E0,0.E0)); #408=DIRECTION('',(1.E0,0.E0,0.E0)); #409=AXIS2_PLACEMENT_3D('',#406,#407,#408); #411=DIRECTION('',(1.E0,0.E0,0.E0)); #412=VECTOR('',#411,3.E0); #413=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0)); #414=LINE('',#413,#412); #415=CARTESIAN_POINT('',(1.05E1,0.E0,9.E0)); #416=DIRECTION('',(0.E0,-1.E0,0.E0)); #417=DIRECTION('',(0.E0,0.E0,-1.E0)); #418=AXIS2_PLACEMENT_3D('',#415,#416,#417); #420=DIRECTION('',(-1.E0,0.E0,0.E0)); #421=VECTOR('',#420,3.E0); #422=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0)); #423=LINE('',#422,#421); #424=CARTESIAN_POINT('',(7.5E0,0.E0,9.E0)); #425=DIRECTION('',(0.E0,-1.E0,0.E0)); #426=DIRECTION('',(0.E0,0.E0,1.E0)); #427=AXIS2_PLACEMENT_3D('',#424,#425,#426); #429=DIRECTION('',(1.E0,0.E0,0.E0)); #430=VECTOR('',#429,3.E0); #431=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1)); #432=LINE('',#431,#430); #433=CARTESIAN_POINT('',(1.05E1,0.E0,1.8E1)); #434=DIRECTION('',(0.E0,-1.E0,0.E0)); #435=DIRECTION('',(0.E0,0.E0,-1.E0)); #436=AXIS2_PLACEMENT_3D('',#433,#434,#435); #438=DIRECTION('',(-1.E0,0.E0,0.E0)); #439=VECTOR('',#438,3.E0); #440=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1)); #441=LINE('',#440,#439); #442=CARTESIAN_POINT('',(7.5E0,0.E0,1.8E1)); #443=DIRECTION('',(0.E0,-1.E0,0.E0)); #444=DIRECTION('',(0.E0,0.E0,1.E0)); #445=AXIS2_PLACEMENT_3D('',#442,#443,#444); #447=DIRECTION('',(1.E0,0.E0,0.E0)); #448=VECTOR('',#447,3.E0); #449=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1)); #450=LINE('',#449,#448); #451=CARTESIAN_POINT('',(7.5E0,0.E0,3.075E1)); #452=DIRECTION('',(0.E0,1.E0,0.E0)); #453=DIRECTION('',(0.E0,0.E0,-1.E0)); #454=AXIS2_PLACEMENT_3D('',#451,#452,#453); #456=DIRECTION('',(-1.E0,0.E0,0.E0)); #457=VECTOR('',#456,3.E0); #458=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1)); #459=LINE('',#458,#457); #460=CARTESIAN_POINT('',(1.05E1,0.E0,3.075E1)); #461=DIRECTION('',(0.E0,1.E0,0.E0)); #462=DIRECTION('',(0.E0,0.E0,1.E0)); #463=AXIS2_PLACEMENT_3D('',#460,#461,#462); #465=DIRECTION('',(-1.E0,0.E0,0.E0)); #466=VECTOR('',#465,3.E0); #467=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1)); #468=LINE('',#467,#466); #469=CARTESIAN_POINT('',(1.65E1,0.E0,1.25E0)); #470=DIRECTION('',(0.E0,1.E0,0.E0)); #471=DIRECTION('',(0.E0,0.E0,1.E0)); #472=AXIS2_PLACEMENT_3D('',#469,#470,#471); #474=DIRECTION('',(1.E0,0.E0,0.E0)); #475=VECTOR('',#474,3.E0); #476=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0)); #477=LINE('',#476,#475); #478=CARTESIAN_POINT('',(1.35E1,0.E0,1.25E0)); #479=DIRECTION('',(0.E0,1.E0,0.E0)); #480=DIRECTION('',(0.E0,0.E0,-1.E0)); #481=AXIS2_PLACEMENT_3D('',#478,#479,#480); #483=DIRECTION('',(0.E0,0.E0,-1.E0)); #484=VECTOR('',#483,3.E0); #485=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1)); #486=LINE('',#485,#484); #487=CARTESIAN_POINT('',(2.275E1,0.E0,1.65E1)); #488=DIRECTION('',(0.E0,1.E0,0.E0)); #489=DIRECTION('',(-1.E0,0.E0,0.E0)); #490=AXIS2_PLACEMENT_3D('',#487,#488,#489); #492=DIRECTION('',(0.E0,0.E0,1.E0)); #493=VECTOR('',#492,3.E0); #494=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1)); #495=LINE('',#494,#493); #496=CARTESIAN_POINT('',(2.275E1,0.E0,1.35E1)); #497=DIRECTION('',(0.E0,1.E0,0.E0)); #498=DIRECTION('',(1.E0,0.E0,0.E0)); #499=AXIS2_PLACEMENT_3D('',#496,#497,#498); #501=DIRECTION('',(0.E0,0.E0,-1.E0)); #502=VECTOR('',#501,3.E0); #503=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1)); #504=LINE('',#503,#502); #505=CARTESIAN_POINT('',(2.275E1,0.E0,2.25E1)); #506=DIRECTION('',(0.E0,1.E0,0.E0)); #507=DIRECTION('',(-1.E0,0.E0,0.E0)); #508=AXIS2_PLACEMENT_3D('',#505,#506,#507); #510=DIRECTION('',(0.E0,0.E0,1.E0)); #511=VECTOR('',#510,3.E0); #512=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1)); #513=LINE('',#512,#511); #514=CARTESIAN_POINT('',(2.275E1,0.E0,1.95E1)); #515=DIRECTION('',(0.E0,1.E0,0.E0)); #516=DIRECTION('',(1.E0,0.E0,0.E0)); #517=AXIS2_PLACEMENT_3D('',#514,#515,#516); #519=DIRECTION('',(-1.E0,0.E0,0.E0)); #520=VECTOR('',#519,3.E0); #521=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0)); #522=LINE('',#521,#520); #523=CARTESIAN_POINT('',(1.65E1,0.E0,9.E0)); #524=DIRECTION('',(0.E0,1.E0,0.E0)); #525=DIRECTION('',(0.E0,0.E0,1.E0)); #526=AXIS2_PLACEMENT_3D('',#523,#524,#525); #528=DIRECTION('',(1.E0,0.E0,0.E0)); #529=VECTOR('',#528,3.E0); #530=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0)); #531=LINE('',#530,#529); #532=CARTESIAN_POINT('',(1.35E1,0.E0,9.E0)); #533=DIRECTION('',(0.E0,1.E0,0.E0)); #534=DIRECTION('',(0.E0,0.E0,-1.E0)); #535=AXIS2_PLACEMENT_3D('',#532,#533,#534); #537=DIRECTION('',(-1.E0,0.E0,0.E0)); #538=VECTOR('',#537,3.E0); #539=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1)); #540=LINE('',#539,#538); #541=CARTESIAN_POINT('',(1.65E1,0.E0,1.8E1)); #542=DIRECTION('',(0.E0,1.E0,0.E0)); #543=DIRECTION('',(0.E0,0.E0,1.E0)); #544=AXIS2_PLACEMENT_3D('',#541,#542,#543); #546=DIRECTION('',(1.E0,0.E0,0.E0)); #547=VECTOR('',#546,3.E0); #548=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1)); #549=LINE('',#548,#547); #550=CARTESIAN_POINT('',(1.35E1,0.E0,1.8E1)); #551=DIRECTION('',(0.E0,1.E0,0.E0)); #552=DIRECTION('',(0.E0,0.E0,-1.E0)); #553=AXIS2_PLACEMENT_3D('',#550,#551,#552); #555=DIRECTION('',(-1.E0,0.E0,0.E0)); #556=VECTOR('',#555,3.E0); #557=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1)); #558=LINE('',#557,#556); #559=CARTESIAN_POINT('',(1.35E1,0.E0,3.075E1)); #560=DIRECTION('',(0.E0,-1.E0,0.E0)); #561=DIRECTION('',(0.E0,0.E0,1.E0)); #562=AXIS2_PLACEMENT_3D('',#559,#560,#561); #564=DIRECTION('',(1.E0,0.E0,0.E0)); #565=VECTOR('',#564,3.E0); #566=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1)); #567=LINE('',#566,#565); #568=CARTESIAN_POINT('',(1.65E1,0.E0,3.075E1)); #569=DIRECTION('',(0.E0,-1.E0,0.E0)); #570=DIRECTION('',(0.E0,0.E0,-1.E0)); #571=AXIS2_PLACEMENT_3D('',#568,#569,#570); #573=DIRECTION('',(0.E0,0.E0,1.E0)); #574=VECTOR('',#573,3.1E-1); #575=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0)); #576=LINE('',#575,#574); #577=CARTESIAN_POINT('',(2.274875E1,0.E0,7.5E0)); #578=DIRECTION('',(0.E0,1.E0,0.E0)); #579=DIRECTION('',(1.E0,0.E0,-3.956251312695E-14)); #580=AXIS2_PLACEMENT_3D('',#577,#578,#579); #582=DIRECTION('',(2.292073341162E-14,0.E0,-1.E0)); #583=VECTOR('',#582,3.1E-1); #584=CARTESIAN_POINT('',(2.331E1,0.E0,7.81E0)); #585=LINE('',#584,#583); #586=DIRECTION('',(-1.E0,0.E0,0.E0)); #587=VECTOR('',#586,2.425E-1); #588=CARTESIAN_POINT('',(2.44325E1,0.E0,8.69E0)); #589=LINE('',#588,#587); #590=DIRECTION('',(0.E0,0.E0,-1.E0)); #591=VECTOR('',#590,8.E-1); #592=CARTESIAN_POINT('',(2.53125E1,0.E0,1.037E1)); #593=LINE('',#592,#591); #594=DIRECTION('',(1.E0,0.E0,0.E0)); #595=VECTOR('',#594,3.865E0); #596=CARTESIAN_POINT('',(2.05675E1,0.E0,1.125E1)); #597=LINE('',#596,#595); #598=DIRECTION('',(0.E0,0.E0,1.E0)); #599=VECTOR('',#598,8.E-1); #600=CARTESIAN_POINT('',(1.96875E1,0.E0,9.57E0)); #601=LINE('',#600,#599); #602=DIRECTION('',(-1.E0,0.E0,0.E0)); #603=VECTOR('',#602,7.4E-1); #604=CARTESIAN_POINT('',(2.13075E1,0.E0,8.69E0)); #605=LINE('',#604,#603); #606=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #607=VECTOR('',#606,4.263248410977E0); #608=CARTESIAN_POINT('',(2.307459332230E1,0.E0,4.046865146430E0)); #609=LINE('',#608,#607); #610=CARTESIAN_POINT('',(2.239E1,0.E0,4.5E0)); #611=DIRECTION('',(0.E0,1.E0,0.E0)); #612=DIRECTION('',(-8.910741301059E-1,0.E0,4.538577912254E-1)); #613=AXIS2_PLACEMENT_3D('',#610,#611,#612); #615=CARTESIAN_POINT('',(1.65E1,0.E0,7.5E0)); #616=DIRECTION('',(0.E0,1.E0,0.E0)); #617=DIRECTION('',(8.910741301059E-1,0.E0,-4.538577912254E-1)); #618=AXIS2_PLACEMENT_3D('',#615,#616,#617); #620=CARTESIAN_POINT('',(1.944696065761E1,0.E0,1.645354088550E0)); #621=DIRECTION('',(0.E0,1.E0,0.E0)); #622=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811866E-1)); #623=AXIS2_PLACEMENT_3D('',#620,#621,#622); #625=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #626=VECTOR('',#625,4.263248410977E0); #627=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,2.795313485357E1)); #628=LINE('',#627,#626); #629=CARTESIAN_POINT('',(1.61E0,0.E0,2.75E1)); #630=DIRECTION('',(0.E0,1.E0,0.E0)); #631=DIRECTION('',(8.910741301059E-1,0.E0,-4.538577912254E-1)); #632=AXIS2_PLACEMENT_3D('',#629,#630,#631); #634=CARTESIAN_POINT('',(7.5E0,0.E0,2.45E1)); #635=DIRECTION('',(0.E0,1.E0,0.E0)); #636=DIRECTION('',(-8.910741301059E-1,0.E0,4.538577912254E-1)); #637=AXIS2_PLACEMENT_3D('',#634,#635,#636); #639=CARTESIAN_POINT('',(4.553039342392E0,0.E0,3.035464591145E1)); #640=DIRECTION('',(0.E0,1.E0,0.E0)); #641=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #642=AXIS2_PLACEMENT_3D('',#639,#640,#641); #644=CARTESIAN_POINT('',(2.239E1,0.E0,2.75E1)); #645=DIRECTION('',(0.E0,-1.E0,0.E0)); #646=DIRECTION('',(-8.910741301059E-1,0.E0,-4.538577912254E-1)); #647=AXIS2_PLACEMENT_3D('',#644,#645,#646); #649=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #650=VECTOR('',#649,4.263248410977E0); #651=CARTESIAN_POINT('',(2.307459332230E1,0.E0,2.795313485357E1)); #652=LINE('',#651,#650); #653=CARTESIAN_POINT('',(1.944696065761E1,0.E0,3.035464591145E1)); #654=DIRECTION('',(0.E0,-1.E0,0.E0)); #655=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811866E-1)); #656=AXIS2_PLACEMENT_3D('',#653,#654,#655); #658=CARTESIAN_POINT('',(1.65E1,0.E0,2.45E1)); #659=DIRECTION('',(0.E0,-1.E0,0.E0)); #660=DIRECTION('',(8.910741301059E-1,0.E0,4.538577912254E-1)); #661=AXIS2_PLACEMENT_3D('',#658,#659,#660); #663=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0)); #664=DIRECTION('',(0.E0,0.E0,-1.E0)); #665=DIRECTION('',(-1.E0,0.E0,0.E0)); #666=AXIS2_PLACEMENT_3D('',#663,#664,#665); #668=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0)); #669=DIRECTION('',(0.E0,0.E0,-1.E0)); #670=DIRECTION('',(1.E0,0.E0,0.E0)); #671=AXIS2_PLACEMENT_3D('',#668,#669,#670); #673=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0)); #674=DIRECTION('',(0.E0,0.E0,-1.E0)); #675=DIRECTION('',(-1.E0,0.E0,0.E0)); #676=AXIS2_PLACEMENT_3D('',#673,#674,#675); #678=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0)); #679=DIRECTION('',(0.E0,0.E0,-1.E0)); #680=DIRECTION('',(1.E0,0.E0,0.E0)); #681=AXIS2_PLACEMENT_3D('',#678,#679,#680); #683=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0)); #684=DIRECTION('',(0.E0,0.E0,-1.E0)); #685=DIRECTION('',(-1.E0,0.E0,0.E0)); #686=AXIS2_PLACEMENT_3D('',#683,#684,#685); #688=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0)); #689=DIRECTION('',(0.E0,0.E0,-1.E0)); #690=DIRECTION('',(1.E0,0.E0,0.E0)); #691=AXIS2_PLACEMENT_3D('',#688,#689,#690); #693=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0)); #694=DIRECTION('',(0.E0,0.E0,-1.E0)); #695=DIRECTION('',(-1.E0,0.E0,0.E0)); #696=AXIS2_PLACEMENT_3D('',#693,#694,#695); #698=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0)); #699=DIRECTION('',(0.E0,0.E0,-1.E0)); #700=DIRECTION('',(1.E0,0.E0,0.E0)); #701=AXIS2_PLACEMENT_3D('',#698,#699,#700); #703=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0)); #704=DIRECTION('',(0.E0,0.E0,1.E0)); #705=DIRECTION('',(1.E0,0.E0,0.E0)); #706=AXIS2_PLACEMENT_3D('',#703,#704,#705); #708=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0)); #709=DIRECTION('',(0.E0,0.E0,1.E0)); #710=DIRECTION('',(-1.E0,0.E0,0.E0)); #711=AXIS2_PLACEMENT_3D('',#708,#709,#710); #713=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0)); #714=DIRECTION('',(0.E0,0.E0,1.E0)); #715=DIRECTION('',(1.E0,0.E0,0.E0)); #716=AXIS2_PLACEMENT_3D('',#713,#714,#715); #718=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0)); #719=DIRECTION('',(0.E0,0.E0,1.E0)); #720=DIRECTION('',(-1.E0,0.E0,0.E0)); #721=AXIS2_PLACEMENT_3D('',#718,#719,#720); #723=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0)); #724=DIRECTION('',(0.E0,0.E0,1.E0)); #725=DIRECTION('',(1.E0,0.E0,0.E0)); #726=AXIS2_PLACEMENT_3D('',#723,#724,#725); #728=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0)); #729=DIRECTION('',(0.E0,0.E0,1.E0)); #730=DIRECTION('',(-1.E0,0.E0,0.E0)); #731=AXIS2_PLACEMENT_3D('',#728,#729,#730); #733=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0)); #734=DIRECTION('',(0.E0,0.E0,1.E0)); #735=DIRECTION('',(1.E0,0.E0,0.E0)); #736=AXIS2_PLACEMENT_3D('',#733,#734,#735); #738=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0)); #739=DIRECTION('',(0.E0,0.E0,1.E0)); #740=DIRECTION('',(-1.E0,0.E0,0.E0)); #741=AXIS2_PLACEMENT_3D('',#738,#739,#740); #743=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0)); #744=VECTOR('',#743,1.029563014099E1); #745=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0)); #746=LINE('',#745,#744); #747=DIRECTION('',(-1.E0,0.E0,0.E0)); #748=VECTOR('',#747,2.E0); #749=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0)); #750=LINE('',#749,#748); #751=DIRECTION('',(-1.E0,0.E0,0.E0)); #752=VECTOR('',#751,2.E0); #753=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0)); #754=LINE('',#753,#752); #755=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0)); #756=VECTOR('',#755,1.029563014099E1); #757=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0)); #758=LINE('',#757,#756); #759=DIRECTION('',(-1.E0,0.E0,0.E0)); #760=VECTOR('',#759,3.895172754280E0); #761=CARTESIAN_POINT('',(3.75E0,2.E0,8.E0)); #762=LINE('',#761,#760); #763=DIRECTION('',(4.856429311786E-1,8.741572761215E-1,0.E0)); #764=VECTOR('',#763,6.863753427325E0); #765=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.E0)); #766=LINE('',#765,#764); #767=DIRECTION('',(1.E0,0.E0,0.E0)); #768=VECTOR('',#767,5.618394209466E-1); #769=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.E0)); #770=LINE('',#769,#768); #771=DIRECTION('',(0.E0,-1.E0,0.E0)); #772=VECTOR('',#771,6.E0); #773=CARTESIAN_POINT('',(4.5E0,8.75E0,8.E0)); #774=LINE('',#773,#772); #775=DIRECTION('',(-4.856429311786E-1,8.741572761215E-1,0.E0)); #776=VECTOR('',#775,6.863753427325E0); #777=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.E0)); #778=LINE('',#777,#776); #779=DIRECTION('',(1.E0,0.E0,0.E0)); #780=VECTOR('',#779,3.895172754280E0); #781=CARTESIAN_POINT('',(2.025E1,2.E0,8.E0)); #782=LINE('',#781,#780); #783=DIRECTION('',(0.E0,-1.E0,0.E0)); #784=VECTOR('',#783,6.E0); #785=CARTESIAN_POINT('',(1.95E1,8.75E0,8.E0)); #786=LINE('',#785,#784); #787=DIRECTION('',(-1.E0,0.E0,0.E0)); #788=VECTOR('',#787,5.618394209466E-1); #789=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.E0)); #790=LINE('',#789,#788); #791=DIRECTION('',(0.E0,0.E0,1.E0)); #792=VECTOR('',#791,2.5E-1); #793=CARTESIAN_POINT('',(1.9655E1,1.09375E1,8.E0)); #794=LINE('',#793,#792); #795=DIRECTION('',(0.E0,0.E0,1.E0)); #796=VECTOR('',#795,2.5E-1); #797=CARTESIAN_POINT('',(1.9845E1,1.09375E1,8.E0)); #798=LINE('',#797,#796); #799=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.25E0)); #800=DIRECTION('',(0.E0,0.E0,-1.E0)); #801=DIRECTION('',(-1.E0,0.E0,0.E0)); #802=AXIS2_PLACEMENT_3D('',#799,#800,#801); #804=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.25E0)); #805=DIRECTION('',(0.E0,0.E0,-1.E0)); #806=DIRECTION('',(1.E0,0.E0,0.E0)); #807=AXIS2_PLACEMENT_3D('',#804,#805,#806); #809=DIRECTION('',(0.E0,0.E0,1.E0)); #810=VECTOR('',#809,2.E0); #811=CARTESIAN_POINT('',(1.95875E1,1.05E1,8.E0)); #812=LINE('',#811,#810); #813=DIRECTION('',(0.E0,0.E0,1.E0)); #814=VECTOR('',#813,2.E0); #815=CARTESIAN_POINT('',(1.99125E1,1.05E1,8.E0)); #816=LINE('',#815,#814); #817=CARTESIAN_POINT('',(1.975E1,1.05E1,1.E1)); #818=DIRECTION('',(0.E0,0.E0,-1.E0)); #819=DIRECTION('',(-1.E0,0.E0,0.E0)); #820=AXIS2_PLACEMENT_3D('',#817,#818,#819); #822=CARTESIAN_POINT('',(1.975E1,1.05E1,1.E1)); #823=DIRECTION('',(0.E0,0.E0,-1.E0)); #824=DIRECTION('',(1.E0,0.E0,0.E0)); #825=AXIS2_PLACEMENT_3D('',#822,#823,#824); #827=DIRECTION('',(0.E0,1.E0,0.E0)); #828=VECTOR('',#827,5.E0); #829=CARTESIAN_POINT('',(2.375E1,1.5E0,1.E1)); #830=LINE('',#829,#828); #831=DIRECTION('',(-1.E0,0.E0,0.E0)); #832=VECTOR('',#831,1.75E0); #833=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1)); #834=LINE('',#833,#832); #835=DIRECTION('',(0.E0,1.E0,0.E0)); #836=VECTOR('',#835,5.E0); #837=CARTESIAN_POINT('',(2.2E1,1.5E0,1.E1)); #838=LINE('',#837,#836); #839=DIRECTION('',(0.E0,1.E0,0.E0)); #840=VECTOR('',#839,1.E1); #841=CARTESIAN_POINT('',(1.9E1,1.5E0,1.E1)); #842=LINE('',#841,#840); #843=DIRECTION('',(1.E0,0.E0,0.E0)); #844=VECTOR('',#843,2.E0); #845=CARTESIAN_POINT('',(1.9E1,1.15E1,1.E1)); #846=LINE('',#845,#844); #847=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0)); #848=VECTOR('',#847,1.029563014099E1); #849=CARTESIAN_POINT('',(2.1E1,1.15E1,1.E1)); #850=LINE('',#849,#848); #851=DIRECTION('',(0.E0,-1.E0,0.E0)); #852=VECTOR('',#851,1.E0); #853=CARTESIAN_POINT('',(2.6E1,2.5E0,1.E1)); #854=LINE('',#853,#852); #855=DIRECTION('',(-1.E0,0.E0,0.E0)); #856=VECTOR('',#855,1.972007605460E-1); #857=CARTESIAN_POINT('',(2.204720076055E1,7.E0,1.E1)); #858=LINE('',#857,#856); #859=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0)); #860=VECTOR('',#859,2.059126028197E0); #861=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,1.E1)); #862=LINE('',#861,#860); #863=DIRECTION('',(1.E0,0.E0,0.E0)); #864=VECTOR('',#863,1.197200760546E0); #865=CARTESIAN_POINT('',(1.985E1,9.5E0,1.E1)); #866=LINE('',#865,#864); #867=DIRECTION('',(0.E0,1.E0,0.E0)); #868=VECTOR('',#867,6.8E0); #869=CARTESIAN_POINT('',(1.95E1,2.35E0,1.E1)); #870=LINE('',#869,#868); #871=DIRECTION('',(-1.E0,0.E0,0.E0)); #872=VECTOR('',#871,1.3E0); #873=CARTESIAN_POINT('',(2.115E1,2.E0,1.E1)); #874=LINE('',#873,#872); #875=DIRECTION('',(0.E0,-1.E0,0.E0)); #876=VECTOR('',#875,4.3E0); #877=CARTESIAN_POINT('',(2.15E1,6.65E0,1.E1)); #878=LINE('',#877,#876); #879=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1)); #880=VECTOR('',#879,5.773502691896E0); #881=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1)); #882=LINE('',#881,#880); #883=CARTESIAN_POINT('',(6.45E0,1.5E0,2.975E1)); #884=DIRECTION('',(0.E0,-1.E0,0.E0)); #885=DIRECTION('',(-1.E0,0.E0,0.E0)); #886=AXIS2_PLACEMENT_3D('',#883,#884,#885); #888=CARTESIAN_POINT('',(6.45E0,1.5E0,2.975E1)); #889=DIRECTION('',(0.E0,-1.E0,0.E0)); #890=DIRECTION('',(1.E0,0.E0,0.E0)); #891=AXIS2_PLACEMENT_3D('',#888,#889,#890); #893=CARTESIAN_POINT('',(7.45E0,1.5E0,2.975E1)); #894=DIRECTION('',(0.E0,-1.E0,0.E0)); #895=DIRECTION('',(-1.E0,0.E0,0.E0)); #896=AXIS2_PLACEMENT_3D('',#893,#894,#895); #898=CARTESIAN_POINT('',(7.45E0,1.5E0,2.975E1)); #899=DIRECTION('',(0.E0,-1.E0,0.E0)); #900=DIRECTION('',(1.E0,0.E0,0.E0)); #901=AXIS2_PLACEMENT_3D('',#898,#899,#900); #903=DIRECTION('',(-1.E0,0.E0,0.E0)); #904=VECTOR('',#903,4.531373033403E0); #905=CARTESIAN_POINT('',(2.5E1,1.5E0,8.E0)); #906=LINE('',#905,#904); #907=DIRECTION('',(-1.E0,0.E0,0.E0)); #908=VECTOR('',#907,9.E0); #909=CARTESIAN_POINT('',(1.65E1,1.5E0,2.5E0)); #910=LINE('',#909,#908); #911=DIRECTION('',(-1.E0,0.E0,0.E0)); #912=VECTOR('',#911,4.531373033403E0); #913=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,8.E0)); #914=LINE('',#913,#912); #915=DIRECTION('',(0.E0,0.E0,1.E0)); #916=VECTOR('',#915,3.E0); #917=CARTESIAN_POINT('',(0.E0,1.5E0,4.E0)); #918=LINE('',#917,#916); #919=DIRECTION('',(-1.E0,0.E0,0.E0)); #920=VECTOR('',#919,1.6E1); #921=CARTESIAN_POINT('',(2.E1,1.5E0,0.E0)); #922=LINE('',#921,#920); #923=DIRECTION('',(0.E0,0.E0,-1.E0)); #924=VECTOR('',#923,3.E0); #925=CARTESIAN_POINT('',(2.4E1,1.5E0,7.E0)); #926=LINE('',#925,#924); #927=CARTESIAN_POINT('',(1.755E1,1.5E0,2.975E1)); #928=DIRECTION('',(0.E0,1.E0,0.E0)); #929=DIRECTION('',(1.E0,0.E0,0.E0)); #930=AXIS2_PLACEMENT_3D('',#927,#928,#929); #932=CARTESIAN_POINT('',(1.755E1,1.5E0,2.975E1)); #933=DIRECTION('',(0.E0,1.E0,0.E0)); #934=DIRECTION('',(-1.E0,0.E0,0.E0)); #935=AXIS2_PLACEMENT_3D('',#932,#933,#934); #937=CARTESIAN_POINT('',(1.655E1,1.5E0,2.975E1)); #938=DIRECTION('',(0.E0,1.E0,0.E0)); #939=DIRECTION('',(1.E0,0.E0,0.E0)); #940=AXIS2_PLACEMENT_3D('',#937,#938,#939); #942=CARTESIAN_POINT('',(1.655E1,1.5E0,2.975E1)); #943=DIRECTION('',(0.E0,1.E0,0.E0)); #944=DIRECTION('',(-1.E0,0.E0,0.E0)); #945=AXIS2_PLACEMENT_3D('',#942,#943,#944); #947=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0)); #948=DIRECTION('',(0.E0,-1.E0,0.E0)); #949=DIRECTION('',(1.E0,0.E0,0.E0)); #950=AXIS2_PLACEMENT_3D('',#947,#948,#949); #952=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0)); #953=DIRECTION('',(0.E0,-1.E0,0.E0)); #954=DIRECTION('',(-1.E0,0.E0,0.E0)); #955=AXIS2_PLACEMENT_3D('',#952,#953,#954); #957=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1)); #958=DIRECTION('',(0.E0,-1.E0,0.E0)); #959=DIRECTION('',(1.E0,0.E0,0.E0)); #960=AXIS2_PLACEMENT_3D('',#957,#958,#959); #962=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1)); #963=DIRECTION('',(0.E0,-1.E0,0.E0)); #964=DIRECTION('',(-1.E0,0.E0,0.E0)); #965=AXIS2_PLACEMENT_3D('',#962,#963,#964); #967=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1)); #968=DIRECTION('',(0.E0,-1.E0,0.E0)); #969=DIRECTION('',(1.E0,0.E0,0.E0)); #970=AXIS2_PLACEMENT_3D('',#967,#968,#969); #972=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1)); #973=DIRECTION('',(0.E0,-1.E0,0.E0)); #974=DIRECTION('',(-1.E0,0.E0,0.E0)); #975=AXIS2_PLACEMENT_3D('',#972,#973,#974); #977=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0)); #978=DIRECTION('',(0.E0,-1.E0,0.E0)); #979=DIRECTION('',(1.E0,0.E0,0.E0)); #980=AXIS2_PLACEMENT_3D('',#977,#978,#979); #982=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0)); #983=DIRECTION('',(0.E0,-1.E0,0.E0)); #984=DIRECTION('',(-1.E0,0.E0,0.E0)); #985=AXIS2_PLACEMENT_3D('',#982,#983,#984); #987=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1)); #988=DIRECTION('',(0.E0,-1.E0,0.E0)); #989=DIRECTION('',(1.E0,0.E0,0.E0)); #990=AXIS2_PLACEMENT_3D('',#987,#988,#989); #992=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1)); #993=DIRECTION('',(0.E0,-1.E0,0.E0)); #994=DIRECTION('',(-1.E0,0.E0,0.E0)); #995=AXIS2_PLACEMENT_3D('',#992,#993,#994); #997=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1)); #998=DIRECTION('',(0.E0,-1.E0,0.E0)); #999=DIRECTION('',(1.E0,0.E0,0.E0)); #1000=AXIS2_PLACEMENT_3D('',#997,#998,#999); #1002=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1)); #1003=DIRECTION('',(0.E0,-1.E0,0.E0)); #1004=DIRECTION('',(-1.E0,0.E0,0.E0)); #1005=AXIS2_PLACEMENT_3D('',#1002,#1003,#1004); #1007=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0)); #1008=DIRECTION('',(0.E0,-1.E0,0.E0)); #1009=DIRECTION('',(1.E0,0.E0,0.E0)); #1010=AXIS2_PLACEMENT_3D('',#1007,#1008,#1009); #1012=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0)); #1013=DIRECTION('',(0.E0,-1.E0,0.E0)); #1014=DIRECTION('',(-1.E0,0.E0,0.E0)); #1015=AXIS2_PLACEMENT_3D('',#1012,#1013,#1014); #1017=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0)); #1018=DIRECTION('',(0.E0,-1.E0,0.E0)); #1019=DIRECTION('',(1.E0,0.E0,0.E0)); #1020=AXIS2_PLACEMENT_3D('',#1017,#1018,#1019); #1022=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0)); #1023=DIRECTION('',(0.E0,-1.E0,0.E0)); #1024=DIRECTION('',(-1.E0,0.E0,0.E0)); #1025=AXIS2_PLACEMENT_3D('',#1022,#1023,#1024); #1027=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0)); #1028=DIRECTION('',(0.E0,-1.E0,0.E0)); #1029=DIRECTION('',(1.E0,0.E0,0.E0)); #1030=AXIS2_PLACEMENT_3D('',#1027,#1028,#1029); #1032=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0)); #1033=DIRECTION('',(0.E0,-1.E0,0.E0)); #1034=DIRECTION('',(-1.E0,0.E0,0.E0)); #1035=AXIS2_PLACEMENT_3D('',#1032,#1033,#1034); #1037=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1)); #1038=DIRECTION('',(0.E0,-1.E0,0.E0)); #1039=DIRECTION('',(1.E0,0.E0,0.E0)); #1040=AXIS2_PLACEMENT_3D('',#1037,#1038,#1039); #1042=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1)); #1043=DIRECTION('',(0.E0,-1.E0,0.E0)); #1044=DIRECTION('',(-1.E0,0.E0,0.E0)); #1045=AXIS2_PLACEMENT_3D('',#1042,#1043,#1044); #1047=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1)); #1048=DIRECTION('',(0.E0,-1.E0,0.E0)); #1049=DIRECTION('',(1.E0,0.E0,0.E0)); #1050=AXIS2_PLACEMENT_3D('',#1047,#1048,#1049); #1052=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1)); #1053=DIRECTION('',(0.E0,-1.E0,0.E0)); #1054=DIRECTION('',(-1.E0,0.E0,0.E0)); #1055=AXIS2_PLACEMENT_3D('',#1052,#1053,#1054); #1057=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1)); #1058=DIRECTION('',(0.E0,-1.E0,0.E0)); #1059=DIRECTION('',(1.E0,0.E0,0.E0)); #1060=AXIS2_PLACEMENT_3D('',#1057,#1058,#1059); #1062=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1)); #1063=DIRECTION('',(0.E0,-1.E0,0.E0)); #1064=DIRECTION('',(-1.E0,0.E0,0.E0)); #1065=AXIS2_PLACEMENT_3D('',#1062,#1063,#1064); #1067=DIRECTION('',(0.E0,0.E0,-1.E0)); #1068=VECTOR('',#1067,2.5625E0); #1069=CARTESIAN_POINT('',(2.15E1,1.5E0,2.45E1)); #1070=LINE('',#1069,#1068); #1071=DIRECTION('',(1.E0,0.E0,0.E0)); #1072=VECTOR('',#1071,1.3E1); #1073=CARTESIAN_POINT('',(5.5E0,1.5E0,1.89375E1)); #1074=LINE('',#1073,#1072); #1075=DIRECTION('',(0.E0,0.E0,1.E0)); #1076=VECTOR('',#1075,2.5625E0); #1077=CARTESIAN_POINT('',(2.5E0,1.5E0,2.19375E1)); #1078=LINE('',#1077,#1076); #1079=DIRECTION('',(1.E0,0.E0,0.E0)); #1080=VECTOR('',#1079,9.E0); #1081=CARTESIAN_POINT('',(7.5E0,1.5E0,2.95E1)); #1082=LINE('',#1081,#1080); #1083=DIRECTION('',(-1.E0,0.E0,0.E0)); #1084=VECTOR('',#1083,1.3E1); #1085=CARTESIAN_POINT('',(1.85E1,1.5E0,1.70625E1)); #1086=LINE('',#1085,#1084); #1087=DIRECTION('',(0.E0,0.E0,-1.E0)); #1088=VECTOR('',#1087,8.125E-1); #1089=CARTESIAN_POINT('',(2.15E1,1.5E0,1.40625E1)); #1090=LINE('',#1089,#1088); #1091=DIRECTION('',(-1.E0,0.E0,0.E0)); #1092=VECTOR('',#1091,1.E0); #1093=CARTESIAN_POINT('',(2.05E1,1.5E0,1.225E1)); #1094=LINE('',#1093,#1092); #1095=DIRECTION('',(0.E0,0.E0,-1.E0)); #1096=VECTOR('',#1095,7.5E-1); #1097=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1)); #1098=LINE('',#1097,#1096); #1099=DIRECTION('',(0.E0,0.E0,-1.E0)); #1100=VECTOR('',#1099,7.5E-1); #1101=CARTESIAN_POINT('',(5.E0,1.5E0,1.175E1)); #1102=LINE('',#1101,#1100); #1103=DIRECTION('',(1.E0,0.E0,0.E0)); #1104=VECTOR('',#1103,1.E0); #1105=CARTESIAN_POINT('',(3.5E0,1.5E0,1.225E1)); #1106=LINE('',#1105,#1104); #1107=DIRECTION('',(0.E0,0.E0,1.E0)); #1108=VECTOR('',#1107,8.125E-1); #1109=CARTESIAN_POINT('',(2.5E0,1.5E0,1.325E1)); #1110=LINE('',#1109,#1108); #1111=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0)); #1112=DIRECTION('',(0.E0,-1.E0,0.E0)); #1113=DIRECTION('',(1.E0,0.E0,0.E0)); #1114=AXIS2_PLACEMENT_3D('',#1111,#1112,#1113); #1116=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0)); #1117=DIRECTION('',(0.E0,-1.E0,0.E0)); #1118=DIRECTION('',(-1.E0,0.E0,0.E0)); #1119=AXIS2_PLACEMENT_3D('',#1116,#1117,#1118); #1121=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0)); #1122=DIRECTION('',(0.E0,-1.E0,0.E0)); #1123=DIRECTION('',(1.E0,0.E0,0.E0)); #1124=AXIS2_PLACEMENT_3D('',#1121,#1122,#1123); #1126=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0)); #1127=DIRECTION('',(0.E0,-1.E0,0.E0)); #1128=DIRECTION('',(-1.E0,0.E0,0.E0)); #1129=AXIS2_PLACEMENT_3D('',#1126,#1127,#1128); #1131=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0)); #1132=DIRECTION('',(0.E0,-1.E0,0.E0)); #1133=DIRECTION('',(1.E0,0.E0,0.E0)); #1134=AXIS2_PLACEMENT_3D('',#1131,#1132,#1133); #1136=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0)); #1137=DIRECTION('',(0.E0,-1.E0,0.E0)); #1138=DIRECTION('',(-1.E0,0.E0,0.E0)); #1139=AXIS2_PLACEMENT_3D('',#1136,#1137,#1138); #1141=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1)); #1142=DIRECTION('',(0.E0,-1.E0,0.E0)); #1143=DIRECTION('',(1.E0,0.E0,0.E0)); #1144=AXIS2_PLACEMENT_3D('',#1141,#1142,#1143); #1146=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1)); #1147=DIRECTION('',(0.E0,-1.E0,0.E0)); #1148=DIRECTION('',(-1.E0,0.E0,0.E0)); #1149=AXIS2_PLACEMENT_3D('',#1146,#1147,#1148); #1151=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1)); #1152=DIRECTION('',(0.E0,-1.E0,0.E0)); #1153=DIRECTION('',(1.E0,0.E0,0.E0)); #1154=AXIS2_PLACEMENT_3D('',#1151,#1152,#1153); #1156=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1)); #1157=DIRECTION('',(0.E0,-1.E0,0.E0)); #1158=DIRECTION('',(-1.E0,0.E0,0.E0)); #1159=AXIS2_PLACEMENT_3D('',#1156,#1157,#1158); #1161=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1)); #1162=DIRECTION('',(0.E0,-1.E0,0.E0)); #1163=DIRECTION('',(1.E0,0.E0,0.E0)); #1164=AXIS2_PLACEMENT_3D('',#1161,#1162,#1163); #1166=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1)); #1167=DIRECTION('',(0.E0,-1.E0,0.E0)); #1168=DIRECTION('',(-1.E0,0.E0,0.E0)); #1169=AXIS2_PLACEMENT_3D('',#1166,#1167,#1168); #1171=DIRECTION('',(0.E0,0.E0,-1.E0)); #1172=VECTOR('',#1171,2.886751345948E0); #1173=CARTESIAN_POINT('',(2.375E1,1.5E0,1.288675134595E1)); #1174=LINE('',#1173,#1172); #1175=DIRECTION('',(1.E0,0.E0,0.E0)); #1176=VECTOR('',#1175,2.25E0); #1177=CARTESIAN_POINT('',(2.375E1,1.5E0,1.E1)); #1178=LINE('',#1177,#1176); #1179=DIRECTION('',(0.E0,0.E0,1.E0)); #1180=VECTOR('',#1179,1.75E0); #1181=CARTESIAN_POINT('',(2.6E1,1.5E0,1.E1)); #1182=LINE('',#1181,#1180); #1183=DIRECTION('',(-1.E0,0.E0,0.E0)); #1184=VECTOR('',#1183,5.E-1); #1185=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1)); #1186=LINE('',#1185,#1184); #1187=DIRECTION('',(0.E0,0.E0,-1.E0)); #1188=VECTOR('',#1187,1.475E1); #1189=CARTESIAN_POINT('',(2.4E1,1.5E0,2.8E1)); #1190=LINE('',#1189,#1188); #1191=DIRECTION('',(1.E0,0.E0,0.E0)); #1192=VECTOR('',#1191,1.6E1); #1193=CARTESIAN_POINT('',(4.E0,1.5E0,3.2E1)); #1194=LINE('',#1193,#1192); #1195=DIRECTION('',(0.E0,0.E0,1.E0)); #1196=VECTOR('',#1195,1.475E1); #1197=CARTESIAN_POINT('',(0.E0,1.5E0,1.325E1)); #1198=LINE('',#1197,#1196); #1199=DIRECTION('',(1.E0,0.E0,0.E0)); #1200=VECTOR('',#1199,5.E-1); #1201=CARTESIAN_POINT('',(-1.5E0,1.5E0,1.225E1)); #1202=LINE('',#1201,#1200); #1203=DIRECTION('',(0.E0,0.E0,1.E0)); #1204=VECTOR('',#1203,1.75E0); #1205=CARTESIAN_POINT('',(-2.E0,1.5E0,1.E1)); #1206=LINE('',#1205,#1204); #1207=DIRECTION('',(1.E0,0.E0,0.E0)); #1208=VECTOR('',#1207,2.25E0); #1209=CARTESIAN_POINT('',(-2.E0,1.5E0,1.E1)); #1210=LINE('',#1209,#1208); #1211=DIRECTION('',(0.E0,0.E0,-1.E0)); #1212=VECTOR('',#1211,2.886751345948E0); #1213=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.288675134595E1)); #1214=LINE('',#1213,#1212); #1215=DIRECTION('',(1.E0,0.E0,0.E0)); #1216=VECTOR('',#1215,1.75E0); #1217=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.288675134595E1)); #1218=LINE('',#1217,#1216); #1219=DIRECTION('',(0.E0,0.E0,-1.E0)); #1220=VECTOR('',#1219,2.886751345948E0); #1221=CARTESIAN_POINT('',(2.E0,1.5E0,1.288675134595E1)); #1222=LINE('',#1221,#1220); #1223=DIRECTION('',(1.E0,0.E0,0.E0)); #1224=VECTOR('',#1223,3.E0); #1225=CARTESIAN_POINT('',(2.E0,1.5E0,1.E1)); #1226=LINE('',#1225,#1224); #1227=DIRECTION('',(1.E0,0.E0,0.E0)); #1228=VECTOR('',#1227,1.4E1); #1229=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0)); #1230=LINE('',#1229,#1228); #1231=DIRECTION('',(1.E0,0.E0,0.E0)); #1232=VECTOR('',#1231,3.E0); #1233=CARTESIAN_POINT('',(1.9E1,1.5E0,1.E1)); #1234=LINE('',#1233,#1232); #1235=DIRECTION('',(0.E0,0.E0,-1.E0)); #1236=VECTOR('',#1235,2.886751345948E0); #1237=CARTESIAN_POINT('',(2.2E1,1.5E0,1.288675134595E1)); #1238=LINE('',#1237,#1236); #1239=DIRECTION('',(-1.E0,0.E0,0.E0)); #1240=VECTOR('',#1239,1.75E0); #1241=CARTESIAN_POINT('',(2.375E1,1.5E0,1.288675134595E1)); #1242=LINE('',#1241,#1240); #1243=DIRECTION('',(0.E0,1.E0,0.E0)); #1244=VECTOR('',#1243,2.5E-1); #1245=CARTESIAN_POINT('',(6.35E0,1.25E0,2.975E1)); #1246=LINE('',#1245,#1244); #1247=DIRECTION('',(0.E0,1.E0,0.E0)); #1248=VECTOR('',#1247,2.5E-1); #1249=CARTESIAN_POINT('',(6.55E0,1.25E0,2.975E1)); #1250=LINE('',#1249,#1248); #1251=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0)); #1252=VECTOR('',#1251,1.154700538379E-1); #1253=CARTESIAN_POINT('',(6.45E0,1.192264973081E0,2.975E1)); #1254=LINE('',#1253,#1252); #1255=CARTESIAN_POINT('',(6.45E0,1.25E0,2.975E1)); #1256=DIRECTION('',(0.E0,1.E0,0.E0)); #1257=DIRECTION('',(-1.E0,0.E0,0.E0)); #1258=AXIS2_PLACEMENT_3D('',#1255,#1256,#1257); #1260=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0)); #1261=VECTOR('',#1260,1.154700538379E-1); #1262=CARTESIAN_POINT('',(6.45E0,1.192264973081E0,2.975E1)); #1263=LINE('',#1262,#1261); #1264=CARTESIAN_POINT('',(6.45E0,1.25E0,2.975E1)); #1265=DIRECTION('',(0.E0,-1.E0,0.E0)); #1266=DIRECTION('',(-1.E0,0.E0,0.E0)); #1267=AXIS2_PLACEMENT_3D('',#1264,#1265,#1266); #1269=DIRECTION('',(0.E0,1.E0,0.E0)); #1270=VECTOR('',#1269,2.5E-1); #1271=CARTESIAN_POINT('',(7.35E0,1.25E0,2.975E1)); #1272=LINE('',#1271,#1270); #1273=DIRECTION('',(0.E0,1.E0,0.E0)); #1274=VECTOR('',#1273,2.5E-1); #1275=CARTESIAN_POINT('',(7.55E0,1.25E0,2.975E1)); #1276=LINE('',#1275,#1274); #1277=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0)); #1278=VECTOR('',#1277,1.154700538379E-1); #1279=CARTESIAN_POINT('',(7.45E0,1.192264973081E0,2.975E1)); #1280=LINE('',#1279,#1278); #1281=CARTESIAN_POINT('',(7.45E0,1.25E0,2.975E1)); #1282=DIRECTION('',(0.E0,1.E0,0.E0)); #1283=DIRECTION('',(-1.E0,0.E0,0.E0)); #1284=AXIS2_PLACEMENT_3D('',#1281,#1282,#1283); #1286=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0)); #1287=VECTOR('',#1286,1.154700538379E-1); #1288=CARTESIAN_POINT('',(7.45E0,1.192264973081E0,2.975E1)); #1289=LINE('',#1288,#1287); #1290=CARTESIAN_POINT('',(7.45E0,1.25E0,2.975E1)); #1291=DIRECTION('',(0.E0,-1.E0,0.E0)); #1292=DIRECTION('',(-1.E0,0.E0,0.E0)); #1293=AXIS2_PLACEMENT_3D('',#1290,#1291,#1292); #1295=DIRECTION('',(0.E0,1.E0,0.E0)); #1296=VECTOR('',#1295,1.5E0); #1297=CARTESIAN_POINT('',(2.046862696660E1,0.E0,8.E0)); #1298=LINE('',#1297,#1296); #1299=CARTESIAN_POINT('',(2.046862696660E1,0.E0,7.E0)); #1300=DIRECTION('',(0.E0,1.E0,0.E0)); #1301=DIRECTION('',(0.E0,0.E0,1.E0)); #1302=AXIS2_PLACEMENT_3D('',#1299,#1300,#1301); #1304=DIRECTION('',(0.E0,1.E0,0.E0)); #1305=VECTOR('',#1304,1.5E0); #1306=CARTESIAN_POINT('',(2.146078370825E1,0.E0,6.875E0)); #1307=LINE('',#1306,#1305); #1308=CARTESIAN_POINT('',(2.046862696660E1,1.5E0,7.E0)); #1309=DIRECTION('',(0.E0,-1.E0,0.E0)); #1310=DIRECTION('',(9.921567416492E-1,0.E0,-1.25E-1)); #1311=AXIS2_PLACEMENT_3D('',#1308,#1309,#1310); #1313=CARTESIAN_POINT('',(1.65E1,0.E0,7.5E0)); #1314=DIRECTION('',(0.E0,1.E0,0.E0)); #1315=DIRECTION('',(9.921567416492E-1,0.E0,-1.25E-1)); #1316=AXIS2_PLACEMENT_3D('',#1313,#1314,#1315); #1318=DIRECTION('',(0.E0,-1.E0,0.E0)); #1319=VECTOR('',#1318,1.5E0); #1320=CARTESIAN_POINT('',(1.65E1,1.5E0,2.5E0)); #1321=LINE('',#1320,#1319); #1322=CARTESIAN_POINT('',(1.65E1,1.5E0,7.5E0)); #1323=DIRECTION('',(0.E0,-1.E0,0.E0)); #1324=DIRECTION('',(0.E0,0.E0,-1.E0)); #1325=AXIS2_PLACEMENT_3D('',#1322,#1323,#1324); #1327=CARTESIAN_POINT('',(7.5E0,1.5E0,7.5E0)); #1328=DIRECTION('',(0.E0,-1.E0,0.E0)); #1329=DIRECTION('',(-9.921567416492E-1,0.E0,-1.25E-1)); #1330=AXIS2_PLACEMENT_3D('',#1327,#1328,#1329); #1332=DIRECTION('',(0.E0,-1.E0,0.E0)); #1333=VECTOR('',#1332,1.5E0); #1334=CARTESIAN_POINT('',(7.5E0,1.5E0,2.5E0)); #1335=LINE('',#1334,#1333); #1336=CARTESIAN_POINT('',(7.5E0,0.E0,7.5E0)); #1337=DIRECTION('',(0.E0,1.E0,0.E0)); #1338=DIRECTION('',(0.E0,0.E0,-1.E0)); #1339=AXIS2_PLACEMENT_3D('',#1336,#1337,#1338); #1341=DIRECTION('',(0.E0,-1.E0,0.E0)); #1342=VECTOR('',#1341,1.5E0); #1343=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,8.E0)); #1344=LINE('',#1343,#1342); #1345=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,7.E0)); #1346=DIRECTION('',(0.E0,-1.E0,0.E0)); #1347=DIRECTION('',(0.E0,0.E0,1.E0)); #1348=AXIS2_PLACEMENT_3D('',#1345,#1346,#1347); #1350=DIRECTION('',(0.E0,-1.E0,0.E0)); #1351=VECTOR('',#1350,1.5E0); #1352=CARTESIAN_POINT('',(2.539216291754E0,1.5E0,6.875E0)); #1353=LINE('',#1352,#1351); #1354=CARTESIAN_POINT('',(3.531373033403E0,0.E0,7.E0)); #1355=DIRECTION('',(0.E0,1.E0,0.E0)); #1356=DIRECTION('',(-9.921567416492E-1,0.E0,-1.25E-1)); #1357=AXIS2_PLACEMENT_3D('',#1354,#1355,#1356); #1359=DIRECTION('',(0.E0,-1.E0,0.E0)); #1360=VECTOR('',#1359,1.5E0); #1361=CARTESIAN_POINT('',(0.E0,1.5E0,7.E0)); #1362=LINE('',#1361,#1360); #1363=CARTESIAN_POINT('',(-1.E0,1.5E0,7.E0)); #1364=DIRECTION('',(0.E0,-1.E0,0.E0)); #1365=DIRECTION('',(1.E0,0.E0,0.E0)); #1366=AXIS2_PLACEMENT_3D('',#1363,#1364,#1365); #1368=DIRECTION('',(0.E0,-1.E0,0.E0)); #1369=VECTOR('',#1368,1.5E0); #1370=CARTESIAN_POINT('',(-1.E0,1.5E0,8.E0)); #1371=LINE('',#1370,#1369); #1372=CARTESIAN_POINT('',(-1.E0,0.E0,7.E0)); #1373=DIRECTION('',(0.E0,1.E0,0.E0)); #1374=DIRECTION('',(0.E0,0.E0,1.E0)); #1375=AXIS2_PLACEMENT_3D('',#1372,#1373,#1374); #1377=DIRECTION('',(0.E0,1.E0,0.E0)); #1378=VECTOR('',#1377,1.5E0); #1379=CARTESIAN_POINT('',(0.E0,0.E0,1.325E1)); #1380=LINE('',#1379,#1378); #1381=CARTESIAN_POINT('',(-1.E0,0.E0,1.325E1)); #1382=DIRECTION('',(0.E0,1.E0,0.E0)); #1383=DIRECTION('',(1.E0,0.E0,0.E0)); #1384=AXIS2_PLACEMENT_3D('',#1381,#1382,#1383); #1386=DIRECTION('',(0.E0,1.E0,0.E0)); #1387=VECTOR('',#1386,1.5E0); #1388=CARTESIAN_POINT('',(-1.E0,0.E0,1.225E1)); #1389=LINE('',#1388,#1387); #1390=CARTESIAN_POINT('',(-1.E0,1.5E0,1.325E1)); #1391=DIRECTION('',(0.E0,-1.E0,0.E0)); #1392=DIRECTION('',(0.E0,0.E0,-1.E0)); #1393=AXIS2_PLACEMENT_3D('',#1390,#1391,#1392); #1395=DIRECTION('',(0.E0,-1.E0,0.E0)); #1396=VECTOR('',#1395,1.5E0); #1397=CARTESIAN_POINT('',(2.5E0,1.5E0,1.325E1)); #1398=LINE('',#1397,#1396); #1399=CARTESIAN_POINT('',(3.5E0,1.5E0,1.325E1)); #1400=DIRECTION('',(0.E0,-1.E0,0.E0)); #1401=DIRECTION('',(-1.E0,0.E0,0.E0)); #1402=AXIS2_PLACEMENT_3D('',#1399,#1400,#1401); #1404=DIRECTION('',(0.E0,-1.E0,0.E0)); #1405=VECTOR('',#1404,1.5E0); #1406=CARTESIAN_POINT('',(3.5E0,1.5E0,1.225E1)); #1407=LINE('',#1406,#1405); #1408=CARTESIAN_POINT('',(3.5E0,0.E0,1.325E1)); #1409=DIRECTION('',(0.E0,1.E0,0.E0)); #1410=DIRECTION('',(0.E0,0.E0,-1.E0)); #1411=AXIS2_PLACEMENT_3D('',#1408,#1409,#1410); #1413=DIRECTION('',(0.E0,-1.E0,0.E0)); #1414=VECTOR('',#1413,1.5E0); #1415=CARTESIAN_POINT('',(2.5E0,1.5E0,2.19375E1)); #1416=LINE('',#1415,#1414); #1417=CARTESIAN_POINT('',(5.5E0,1.5E0,2.19375E1)); #1418=DIRECTION('',(0.E0,-1.E0,0.E0)); #1419=DIRECTION('',(-1.E0,0.E0,0.E0)); #1420=AXIS2_PLACEMENT_3D('',#1417,#1418,#1419); #1422=DIRECTION('',(0.E0,-1.E0,0.E0)); #1423=VECTOR('',#1422,1.5E0); #1424=CARTESIAN_POINT('',(5.5E0,1.5E0,1.89375E1)); #1425=LINE('',#1424,#1423); #1426=CARTESIAN_POINT('',(5.5E0,0.E0,2.19375E1)); #1427=DIRECTION('',(0.E0,1.E0,0.E0)); #1428=DIRECTION('',(0.E0,0.E0,-1.E0)); #1429=AXIS2_PLACEMENT_3D('',#1426,#1427,#1428); #1431=DIRECTION('',(0.E0,1.E0,0.E0)); #1432=VECTOR('',#1431,1.5E0); #1433=CARTESIAN_POINT('',(2.15E1,0.E0,2.19375E1)); #1434=LINE('',#1433,#1432); #1435=CARTESIAN_POINT('',(1.85E1,0.E0,2.19375E1)); #1436=DIRECTION('',(0.E0,1.E0,0.E0)); #1437=DIRECTION('',(1.E0,0.E0,0.E0)); #1438=AXIS2_PLACEMENT_3D('',#1435,#1436,#1437); #1440=DIRECTION('',(0.E0,1.E0,0.E0)); #1441=VECTOR('',#1440,1.5E0); #1442=CARTESIAN_POINT('',(1.85E1,0.E0,1.89375E1)); #1443=LINE('',#1442,#1441); #1444=CARTESIAN_POINT('',(1.85E1,1.5E0,2.19375E1)); #1445=DIRECTION('',(0.E0,-1.E0,0.E0)); #1446=DIRECTION('',(0.E0,0.E0,-1.E0)); #1447=AXIS2_PLACEMENT_3D('',#1444,#1445,#1446); #1449=DIRECTION('',(0.E0,-1.E0,0.E0)); #1450=VECTOR('',#1449,1.5E0); #1451=CARTESIAN_POINT('',(2.15E1,1.5E0,2.45E1)); #1452=LINE('',#1451,#1450); #1453=CARTESIAN_POINT('',(1.65E1,1.5E0,2.45E1)); #1454=DIRECTION('',(0.E0,-1.E0,0.E0)); #1455=DIRECTION('',(1.E0,0.E0,0.E0)); #1456=AXIS2_PLACEMENT_3D('',#1453,#1454,#1455); #1458=DIRECTION('',(0.E0,-1.E0,0.E0)); #1459=VECTOR('',#1458,1.5E0); #1460=CARTESIAN_POINT('',(1.65E1,1.5E0,2.95E1)); #1461=LINE('',#1460,#1459); #1462=CARTESIAN_POINT('',(1.65E1,0.E0,2.45E1)); #1463=DIRECTION('',(0.E0,1.E0,0.E0)); #1464=DIRECTION('',(0.E0,0.E0,1.E0)); #1465=AXIS2_PLACEMENT_3D('',#1462,#1463,#1464); #1467=DIRECTION('',(0.E0,-1.E0,0.E0)); #1468=VECTOR('',#1467,1.5E0); #1469=CARTESIAN_POINT('',(7.5E0,1.5E0,2.95E1)); #1470=LINE('',#1469,#1468); #1471=CARTESIAN_POINT('',(7.5E0,1.5E0,2.45E1)); #1472=DIRECTION('',(0.E0,-1.E0,0.E0)); #1473=DIRECTION('',(0.E0,0.E0,1.E0)); #1474=AXIS2_PLACEMENT_3D('',#1471,#1472,#1473); #1476=DIRECTION('',(0.E0,-1.E0,0.E0)); #1477=VECTOR('',#1476,1.5E0); #1478=CARTESIAN_POINT('',(2.5E0,1.5E0,2.45E1)); #1479=LINE('',#1478,#1477); #1480=CARTESIAN_POINT('',(7.5E0,0.E0,2.45E1)); #1481=DIRECTION('',(0.E0,1.E0,0.E0)); #1482=DIRECTION('',(-1.E0,0.E0,0.E0)); #1483=AXIS2_PLACEMENT_3D('',#1480,#1481,#1482); #1485=DIRECTION('',(0.E0,-1.E0,0.E0)); #1486=VECTOR('',#1485,1.5E0); #1487=CARTESIAN_POINT('',(2.15E1,1.5E0,1.40625E1)); #1488=LINE('',#1487,#1486); #1489=CARTESIAN_POINT('',(1.85E1,1.5E0,1.40625E1)); #1490=DIRECTION('',(0.E0,-1.E0,0.E0)); #1491=DIRECTION('',(1.E0,0.E0,0.E0)); #1492=AXIS2_PLACEMENT_3D('',#1489,#1490,#1491); #1494=DIRECTION('',(0.E0,-1.E0,0.E0)); #1495=VECTOR('',#1494,1.5E0); #1496=CARTESIAN_POINT('',(1.85E1,1.5E0,1.70625E1)); #1497=LINE('',#1496,#1495); #1498=CARTESIAN_POINT('',(1.85E1,0.E0,1.40625E1)); #1499=DIRECTION('',(0.E0,1.E0,0.E0)); #1500=DIRECTION('',(0.E0,0.E0,1.E0)); #1501=AXIS2_PLACEMENT_3D('',#1498,#1499,#1500); #1503=DIRECTION('',(0.E0,1.E0,0.E0)); #1504=VECTOR('',#1503,1.5E0); #1505=CARTESIAN_POINT('',(2.5E0,0.E0,1.40625E1)); #1506=LINE('',#1505,#1504); #1507=CARTESIAN_POINT('',(5.5E0,0.E0,1.40625E1)); #1508=DIRECTION('',(0.E0,1.E0,0.E0)); #1509=DIRECTION('',(-1.E0,0.E0,0.E0)); #1510=AXIS2_PLACEMENT_3D('',#1507,#1508,#1509); #1512=DIRECTION('',(0.E0,1.E0,0.E0)); #1513=VECTOR('',#1512,1.5E0); #1514=CARTESIAN_POINT('',(5.5E0,0.E0,1.70625E1)); #1515=LINE('',#1514,#1513); #1516=CARTESIAN_POINT('',(5.5E0,1.5E0,1.40625E1)); #1517=DIRECTION('',(0.E0,-1.E0,0.E0)); #1518=DIRECTION('',(0.E0,0.E0,1.E0)); #1519=AXIS2_PLACEMENT_3D('',#1516,#1517,#1518); #1521=DIRECTION('',(0.E0,1.E0,0.E0)); #1522=VECTOR('',#1521,1.5E0); #1523=CARTESIAN_POINT('',(2.15E1,0.E0,1.325E1)); #1524=LINE('',#1523,#1522); #1525=CARTESIAN_POINT('',(2.05E1,0.E0,1.325E1)); #1526=DIRECTION('',(0.E0,1.E0,0.E0)); #1527=DIRECTION('',(1.E0,0.E0,0.E0)); #1528=AXIS2_PLACEMENT_3D('',#1525,#1526,#1527); #1530=DIRECTION('',(0.E0,1.E0,0.E0)); #1531=VECTOR('',#1530,1.5E0); #1532=CARTESIAN_POINT('',(2.05E1,0.E0,1.225E1)); #1533=LINE('',#1532,#1531); #1534=CARTESIAN_POINT('',(2.05E1,1.5E0,1.325E1)); #1535=DIRECTION('',(0.E0,-1.E0,0.E0)); #1536=DIRECTION('',(0.E0,0.E0,-1.E0)); #1537=AXIS2_PLACEMENT_3D('',#1534,#1535,#1536); #1539=DIRECTION('',(0.E0,-1.E0,0.E0)); #1540=VECTOR('',#1539,1.5E0); #1541=CARTESIAN_POINT('',(2.4E1,1.5E0,1.325E1)); #1542=LINE('',#1541,#1540); #1543=CARTESIAN_POINT('',(2.5E1,1.5E0,1.325E1)); #1544=DIRECTION('',(0.E0,-1.E0,0.E0)); #1545=DIRECTION('',(-1.E0,0.E0,0.E0)); #1546=AXIS2_PLACEMENT_3D('',#1543,#1544,#1545); #1548=DIRECTION('',(0.E0,-1.E0,0.E0)); #1549=VECTOR('',#1548,1.5E0); #1550=CARTESIAN_POINT('',(2.5E1,1.5E0,1.225E1)); #1551=LINE('',#1550,#1549); #1552=CARTESIAN_POINT('',(2.5E1,0.E0,1.325E1)); #1553=DIRECTION('',(0.E0,1.E0,0.E0)); #1554=DIRECTION('',(0.E0,0.E0,-1.E0)); #1555=AXIS2_PLACEMENT_3D('',#1552,#1553,#1554); #1557=DIRECTION('',(0.E0,1.E0,0.E0)); #1558=VECTOR('',#1557,1.5E0); #1559=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1)); #1560=LINE('',#1559,#1558); #1561=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #1562=VECTOR('',#1561,5.656854249492E0); #1563=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1)); #1564=LINE('',#1563,#1562); #1565=DIRECTION('',(0.E0,1.E0,0.E0)); #1566=VECTOR('',#1565,1.5E0); #1567=CARTESIAN_POINT('',(2.E1,0.E0,3.2E1)); #1568=LINE('',#1567,#1566); #1569=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #1570=VECTOR('',#1569,5.656854249492E0); #1571=CARTESIAN_POINT('',(2.4E1,1.5E0,2.8E1)); #1572=LINE('',#1571,#1570); #1573=DIRECTION('',(0.E0,1.E0,0.E0)); #1574=VECTOR('',#1573,1.5E0); #1575=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1)); #1576=LINE('',#1575,#1574); #1577=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #1578=VECTOR('',#1577,5.656854249492E0); #1579=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1)); #1580=LINE('',#1579,#1578); #1581=DIRECTION('',(0.E0,1.E0,0.E0)); #1582=VECTOR('',#1581,1.5E0); #1583=CARTESIAN_POINT('',(0.E0,0.E0,2.8E1)); #1584=LINE('',#1583,#1582); #1585=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #1586=VECTOR('',#1585,5.656854249492E0); #1587=CARTESIAN_POINT('',(4.E0,1.5E0,3.2E1)); #1588=LINE('',#1587,#1586); #1589=DIRECTION('',(0.E0,1.E0,0.E0)); #1590=VECTOR('',#1589,1.5E0); #1591=CARTESIAN_POINT('',(2.4E1,0.E0,7.E0)); #1592=LINE('',#1591,#1590); #1593=CARTESIAN_POINT('',(2.5E1,0.E0,7.E0)); #1594=DIRECTION('',(0.E0,1.E0,0.E0)); #1595=DIRECTION('',(-1.E0,0.E0,0.E0)); #1596=AXIS2_PLACEMENT_3D('',#1593,#1594,#1595); #1598=DIRECTION('',(0.E0,1.E0,0.E0)); #1599=VECTOR('',#1598,1.5E0); #1600=CARTESIAN_POINT('',(2.5E1,0.E0,8.E0)); #1601=LINE('',#1600,#1599); #1602=CARTESIAN_POINT('',(2.5E1,1.5E0,7.E0)); #1603=DIRECTION('',(0.E0,-1.E0,0.E0)); #1604=DIRECTION('',(0.E0,0.E0,1.E0)); #1605=AXIS2_PLACEMENT_3D('',#1602,#1603,#1604); #1607=DIRECTION('',(0.E0,1.E0,0.E0)); #1608=VECTOR('',#1607,1.5E0); #1609=CARTESIAN_POINT('',(2.E1,0.E0,0.E0)); #1610=LINE('',#1609,#1608); #1611=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #1612=VECTOR('',#1611,5.656854249492E0); #1613=CARTESIAN_POINT('',(2.E1,0.E0,0.E0)); #1614=LINE('',#1613,#1612); #1615=DIRECTION('',(0.E0,1.E0,0.E0)); #1616=VECTOR('',#1615,1.5E0); #1617=CARTESIAN_POINT('',(2.4E1,0.E0,4.E0)); #1618=LINE('',#1617,#1616); #1619=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #1620=VECTOR('',#1619,5.656854249492E0); #1621=CARTESIAN_POINT('',(2.E1,1.5E0,0.E0)); #1622=LINE('',#1621,#1620); #1623=DIRECTION('',(0.E0,1.E0,0.E0)); #1624=VECTOR('',#1623,1.5E0); #1625=CARTESIAN_POINT('',(0.E0,0.E0,4.E0)); #1626=LINE('',#1625,#1624); #1627=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #1628=VECTOR('',#1627,5.656854249492E0); #1629=CARTESIAN_POINT('',(0.E0,0.E0,4.E0)); #1630=LINE('',#1629,#1628); #1631=DIRECTION('',(0.E0,1.E0,0.E0)); #1632=VECTOR('',#1631,1.5E0); #1633=CARTESIAN_POINT('',(4.E0,0.E0,0.E0)); #1634=LINE('',#1633,#1632); #1635=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #1636=VECTOR('',#1635,5.656854249492E0); #1637=CARTESIAN_POINT('',(0.E0,1.5E0,4.E0)); #1638=LINE('',#1637,#1636); #1639=DIRECTION('',(0.E0,-1.E0,0.E0)); #1640=VECTOR('',#1639,1.5E0); #1641=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1)); #1642=LINE('',#1641,#1640); #1643=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #1644=VECTOR('',#1643,7.071067811865E-1); #1645=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1)); #1646=LINE('',#1645,#1644); #1647=DIRECTION('',(0.E0,-1.E0,0.E0)); #1648=VECTOR('',#1647,1.5E0); #1649=CARTESIAN_POINT('',(2.6E1,1.5E0,1.175E1)); #1650=LINE('',#1649,#1648); #1651=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #1652=VECTOR('',#1651,7.071067811865E-1); #1653=CARTESIAN_POINT('',(2.55E1,0.E0,1.225E1)); #1654=LINE('',#1653,#1652); #1655=DIRECTION('',(0.E0,-1.E0,0.E0)); #1656=VECTOR('',#1655,2.5E0); #1657=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0)); #1658=LINE('',#1657,#1656); #1659=DIRECTION('',(0.E0,0.E0,1.E0)); #1660=VECTOR('',#1659,2.E0); #1661=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0)); #1662=LINE('',#1661,#1660); #1663=DIRECTION('',(0.E0,0.E0,1.E0)); #1664=VECTOR('',#1663,2.E0); #1665=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0)); #1666=LINE('',#1665,#1664); #1667=DIRECTION('',(0.E0,0.E0,1.E0)); #1668=VECTOR('',#1667,2.E0); #1669=CARTESIAN_POINT('',(1.9E1,1.15E1,8.E0)); #1670=LINE('',#1669,#1668); #1671=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0)); #1672=DIRECTION('',(0.E0,1.E0,0.E0)); #1673=DIRECTION('',(-1.E0,0.E0,0.E0)); #1674=AXIS2_PLACEMENT_3D('',#1671,#1672,#1673); #1676=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0)); #1677=DIRECTION('',(0.E0,1.E0,0.E0)); #1678=DIRECTION('',(1.E0,0.E0,0.E0)); #1679=AXIS2_PLACEMENT_3D('',#1676,#1677,#1678); #1681=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0)); #1682=DIRECTION('',(0.E0,1.E0,0.E0)); #1683=DIRECTION('',(-1.E0,0.E0,0.E0)); #1684=AXIS2_PLACEMENT_3D('',#1681,#1682,#1683); #1686=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0)); #1687=DIRECTION('',(0.E0,1.E0,0.E0)); #1688=DIRECTION('',(1.E0,0.E0,0.E0)); #1689=AXIS2_PLACEMENT_3D('',#1686,#1687,#1688); #1691=DIRECTION('',(0.E0,0.E0,1.E0)); #1692=VECTOR('',#1691,2.E0); #1693=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0)); #1694=LINE('',#1693,#1692); #1695=DIRECTION('',(0.E0,1.E0,0.E0)); #1696=VECTOR('',#1695,1.E1); #1697=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0)); #1698=LINE('',#1697,#1696); #1699=DIRECTION('',(0.E0,1.E0,0.E0)); #1700=VECTOR('',#1699,1.5E0); #1701=CARTESIAN_POINT('',(1.9E1,0.E0,1.1E1)); #1702=LINE('',#1701,#1700); #1703=CARTESIAN_POINT('',(1.8E1,0.E0,1.1E1)); #1704=DIRECTION('',(0.E0,1.E0,0.E0)); #1705=DIRECTION('',(1.E0,0.E0,0.E0)); #1706=AXIS2_PLACEMENT_3D('',#1703,#1704,#1705); #1708=DIRECTION('',(0.E0,1.E0,0.E0)); #1709=VECTOR('',#1708,1.5E0); #1710=CARTESIAN_POINT('',(1.8E1,0.E0,1.E1)); #1711=LINE('',#1710,#1709); #1712=CARTESIAN_POINT('',(1.8E1,1.5E0,1.1E1)); #1713=DIRECTION('',(0.E0,-1.E0,0.E0)); #1714=DIRECTION('',(0.E0,0.E0,-1.E0)); #1715=AXIS2_PLACEMENT_3D('',#1712,#1713,#1714); #1717=DIRECTION('',(1.E0,0.E0,0.E0)); #1718=VECTOR('',#1717,1.2E1); #1719=CARTESIAN_POINT('',(6.E0,1.5E0,1.E1)); #1720=LINE('',#1719,#1718); #1721=DIRECTION('',(0.E0,-1.E0,0.E0)); #1722=VECTOR('',#1721,1.5E0); #1723=CARTESIAN_POINT('',(5.E0,1.5E0,1.1E1)); #1724=LINE('',#1723,#1722); #1725=CARTESIAN_POINT('',(6.E0,1.5E0,1.1E1)); #1726=DIRECTION('',(0.E0,-1.E0,0.E0)); #1727=DIRECTION('',(-1.E0,0.E0,0.E0)); #1728=AXIS2_PLACEMENT_3D('',#1725,#1726,#1727); #1730=DIRECTION('',(0.E0,-1.E0,0.E0)); #1731=VECTOR('',#1730,1.5E0); #1732=CARTESIAN_POINT('',(6.E0,1.5E0,1.E1)); #1733=LINE('',#1732,#1731); #1734=CARTESIAN_POINT('',(6.E0,0.E0,1.1E1)); #1735=DIRECTION('',(0.E0,1.E0,0.E0)); #1736=DIRECTION('',(0.E0,0.E0,-1.E0)); #1737=AXIS2_PLACEMENT_3D('',#1734,#1735,#1736); #1739=DIRECTION('',(0.E0,0.E0,1.E0)); #1740=VECTOR('',#1739,2.E0); #1741=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0)); #1742=LINE('',#1741,#1740); #1743=DIRECTION('',(0.E0,-1.E0,0.E0)); #1744=VECTOR('',#1743,1.E1); #1745=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0)); #1746=LINE('',#1745,#1744); #1747=DIRECTION('',(0.E0,1.E0,0.E0)); #1748=VECTOR('',#1747,1.5E0); #1749=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1)); #1750=LINE('',#1749,#1748); #1751=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #1752=VECTOR('',#1751,7.071067811865E-1); #1753=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1)); #1754=LINE('',#1753,#1752); #1755=DIRECTION('',(0.E0,1.E0,0.E0)); #1756=VECTOR('',#1755,1.5E0); #1757=CARTESIAN_POINT('',(4.5E0,0.E0,1.225E1)); #1758=LINE('',#1757,#1756); #1759=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #1760=VECTOR('',#1759,7.071067811865E-1); #1761=CARTESIAN_POINT('',(5.E0,1.5E0,1.175E1)); #1762=LINE('',#1761,#1760); #1763=CARTESIAN_POINT('',(4.25E0,1.05E1,1.E1)); #1764=DIRECTION('',(0.E0,0.E0,1.E0)); #1765=DIRECTION('',(1.E0,0.E0,0.E0)); #1766=AXIS2_PLACEMENT_3D('',#1763,#1764,#1765); #1768=CARTESIAN_POINT('',(4.25E0,1.05E1,1.E1)); #1769=DIRECTION('',(0.E0,0.E0,1.E0)); #1770=DIRECTION('',(-1.E0,0.E0,0.E0)); #1771=AXIS2_PLACEMENT_3D('',#1768,#1769,#1770); #1773=DIRECTION('',(0.E0,1.E0,0.E0)); #1774=VECTOR('',#1773,5.E0); #1775=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.E1)); #1776=LINE('',#1775,#1774); #1777=DIRECTION('',(0.E0,-1.E0,0.E0)); #1778=VECTOR('',#1777,1.E0); #1779=CARTESIAN_POINT('',(-2.E0,2.5E0,1.E1)); #1780=LINE('',#1779,#1778); #1781=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0)); #1782=VECTOR('',#1781,1.029563014099E1); #1783=CARTESIAN_POINT('',(3.E0,1.15E1,1.E1)); #1784=LINE('',#1783,#1782); #1785=DIRECTION('',(-1.E0,0.E0,0.E0)); #1786=VECTOR('',#1785,2.E0); #1787=CARTESIAN_POINT('',(5.E0,1.15E1,1.E1)); #1788=LINE('',#1787,#1786); #1789=DIRECTION('',(0.E0,1.E0,0.E0)); #1790=VECTOR('',#1789,1.E1); #1791=CARTESIAN_POINT('',(5.E0,1.5E0,1.E1)); #1792=LINE('',#1791,#1790); #1793=DIRECTION('',(0.E0,1.E0,0.E0)); #1794=VECTOR('',#1793,5.E0); #1795=CARTESIAN_POINT('',(2.E0,1.5E0,1.E1)); #1796=LINE('',#1795,#1794); #1797=DIRECTION('',(1.E0,0.E0,0.E0)); #1798=VECTOR('',#1797,1.75E0); #1799=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1)); #1800=LINE('',#1799,#1798); #1801=DIRECTION('',(0.E0,-1.E0,0.E0)); #1802=VECTOR('',#1801,4.3E0); #1803=CARTESIAN_POINT('',(2.5E0,6.65E0,1.E1)); #1804=LINE('',#1803,#1802); #1805=DIRECTION('',(1.E0,0.E0,0.E0)); #1806=VECTOR('',#1805,1.3E0); #1807=CARTESIAN_POINT('',(2.85E0,2.E0,1.E1)); #1808=LINE('',#1807,#1806); #1809=DIRECTION('',(0.E0,1.E0,0.E0)); #1810=VECTOR('',#1809,6.8E0); #1811=CARTESIAN_POINT('',(4.5E0,2.35E0,1.E1)); #1812=LINE('',#1811,#1810); #1813=DIRECTION('',(-1.E0,0.E0,0.E0)); #1814=VECTOR('',#1813,1.197200760546E0); #1815=CARTESIAN_POINT('',(4.15E0,9.5E0,1.E1)); #1816=LINE('',#1815,#1814); #1817=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0)); #1818=VECTOR('',#1817,2.059126028197E0); #1819=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,1.E1)); #1820=LINE('',#1819,#1818); #1821=DIRECTION('',(1.E0,0.E0,0.E0)); #1822=VECTOR('',#1821,1.972007605460E-1); #1823=CARTESIAN_POINT('',(1.952799239454E0,7.E0,1.E1)); #1824=LINE('',#1823,#1822); #1825=DIRECTION('',(0.E0,0.E0,1.E0)); #1826=VECTOR('',#1825,2.E0); #1827=CARTESIAN_POINT('',(4.4125E0,1.05E1,8.E0)); #1828=LINE('',#1827,#1826); #1829=DIRECTION('',(0.E0,0.E0,1.E0)); #1830=VECTOR('',#1829,2.E0); #1831=CARTESIAN_POINT('',(4.0875E0,1.05E1,8.E0)); #1832=LINE('',#1831,#1830); #1833=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1)); #1834=VECTOR('',#1833,5.773502691896E0); #1835=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1)); #1836=LINE('',#1835,#1834); #1837=CARTESIAN_POINT('',(8.675E-1,3.035898384862E0,1.2E1)); #1838=CARTESIAN_POINT('',(8.675E-1,2.930774450068E0,1.206069333205E1)); #1839=CARTESIAN_POINT('',(9.058386382037E-1,2.745461691651E0,1.216768370301E1)); #1840=CARTESIAN_POINT('',(1.029862281194E0,2.608885438662E0,1.224653603944E1)); #1841=CARTESIAN_POINT('',(1.125E0,2.580400233539E0,1.226298198028E1)); #1842=CARTESIAN_POINT('',(1.220137718806E0,2.608885438662E0,1.224653603944E1)); #1843=CARTESIAN_POINT('',(1.344161361796E0,2.745461691651E0,1.216768370301E1)); #1844=CARTESIAN_POINT('',(1.3825E0,2.930774450068E0,1.206069333205E1)); #1845=CARTESIAN_POINT('',(1.3825E0,3.035898384862E0,1.2E1)); #1847=CARTESIAN_POINT('',(1.3825E0,3.035898384862E0,1.2E1)); #1848=CARTESIAN_POINT('',(1.3825E0,3.141022319657E0,1.193930666795E1)); #1849=CARTESIAN_POINT('',(1.344161361796E0,3.326335078073E0,1.183231629699E1)); #1850=CARTESIAN_POINT('',(1.220137718806E0,3.462911331062E0,1.175346396056E1)); #1851=CARTESIAN_POINT('',(1.125E0,3.491396536186E0,1.173701801972E1)); #1852=CARTESIAN_POINT('',(1.029862281194E0,3.462911331062E0,1.175346396056E1)); #1853=CARTESIAN_POINT('',(9.058386382037E-1,3.326335078073E0,1.183231629699E1)); #1854=CARTESIAN_POINT('',(8.675E-1,3.141022319657E0,1.193930666795E1)); #1855=CARTESIAN_POINT('',(8.675E-1,3.035898384862E0,1.2E1)); #1857=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1)); #1858=VECTOR('',#1857,5.773502691896E0); #1859=CARTESIAN_POINT('',(2.E0,6.5E0,1.E1)); #1860=LINE('',#1859,#1858); #1861=DIRECTION('',(0.E0,1.E0,0.E0)); #1862=VECTOR('',#1861,2.035898384862E0); #1863=CARTESIAN_POINT('',(8.675E-1,1.E0,1.2E1)); #1864=LINE('',#1863,#1862); #1865=DIRECTION('',(0.E0,-1.E0,0.E0)); #1866=VECTOR('',#1865,2.035898384862E0); #1867=CARTESIAN_POINT('',(1.3825E0,3.035898384862E0,1.2E1)); #1868=LINE('',#1867,#1866); #1869=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1)); #1870=DIRECTION('',(0.E0,-1.E0,0.E0)); #1871=DIRECTION('',(1.E0,0.E0,0.E0)); #1872=AXIS2_PLACEMENT_3D('',#1869,#1870,#1871); #1874=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1)); #1875=DIRECTION('',(0.E0,-1.E0,0.E0)); #1876=DIRECTION('',(-1.E0,0.E0,0.E0)); #1877=AXIS2_PLACEMENT_3D('',#1874,#1875,#1876); #1879=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1)); #1880=DIRECTION('',(0.E0,-1.E0,0.E0)); #1881=DIRECTION('',(1.E0,0.E0,0.E0)); #1882=AXIS2_PLACEMENT_3D('',#1879,#1880,#1881); #1884=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1)); #1885=DIRECTION('',(0.E0,-1.E0,0.E0)); #1886=DIRECTION('',(-1.E0,0.E0,0.E0)); #1887=AXIS2_PLACEMENT_3D('',#1884,#1885,#1886); #1889=DIRECTION('',(0.E0,-1.E0,0.E0)); #1890=VECTOR('',#1889,1.E0); #1891=CARTESIAN_POINT('',(1.3175E0,1.E0,1.2E1)); #1892=LINE('',#1891,#1890); #1893=DIRECTION('',(0.E0,-1.E0,0.E0)); #1894=VECTOR('',#1893,1.E0); #1895=CARTESIAN_POINT('',(9.325E-1,1.E0,1.2E1)); #1896=LINE('',#1895,#1894); #1897=DIRECTION('',(0.E0,1.E0,0.E0)); #1898=VECTOR('',#1897,2.5E0); #1899=CARTESIAN_POINT('',(-2.E0,0.E0,8.E0)); #1900=LINE('',#1899,#1898); #1901=DIRECTION('',(0.E0,0.E0,1.E0)); #1902=VECTOR('',#1901,2.E0); #1903=CARTESIAN_POINT('',(-2.E0,2.5E0,8.E0)); #1904=LINE('',#1903,#1902); #1905=DIRECTION('',(0.E0,1.E0,0.E0)); #1906=VECTOR('',#1905,1.5E0); #1907=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1)); #1908=LINE('',#1907,#1906); #1909=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #1910=VECTOR('',#1909,7.071067811865E-1); #1911=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1)); #1912=LINE('',#1911,#1910); #1913=DIRECTION('',(0.E0,1.E0,0.E0)); #1914=VECTOR('',#1913,1.5E0); #1915=CARTESIAN_POINT('',(-2.E0,0.E0,1.175E1)); #1916=LINE('',#1915,#1914); #1917=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #1918=VECTOR('',#1917,7.071067811865E-1); #1919=CARTESIAN_POINT('',(-1.5E0,1.5E0,1.225E1)); #1920=LINE('',#1919,#1918); #1921=DIRECTION('',(0.E0,0.E0,1.E0)); #1922=VECTOR('',#1921,2.E0); #1923=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0)); #1924=LINE('',#1923,#1922); #1925=DIRECTION('',(0.E0,0.E0,1.E0)); #1926=VECTOR('',#1925,2.E0); #1927=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0)); #1928=LINE('',#1927,#1926); #1929=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0)); #1930=DIRECTION('',(0.E0,-1.E0,0.E0)); #1931=DIRECTION('',(1.E0,0.E0,0.E0)); #1932=AXIS2_PLACEMENT_3D('',#1929,#1930,#1931); #1934=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0)); #1935=DIRECTION('',(0.E0,-1.E0,0.E0)); #1936=DIRECTION('',(-1.E0,0.E0,0.E0)); #1937=AXIS2_PLACEMENT_3D('',#1934,#1935,#1936); #1939=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0)); #1940=DIRECTION('',(0.E0,-1.E0,0.E0)); #1941=DIRECTION('',(1.E0,0.E0,0.E0)); #1942=AXIS2_PLACEMENT_3D('',#1939,#1940,#1941); #1944=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0)); #1945=DIRECTION('',(0.E0,-1.E0,0.E0)); #1946=DIRECTION('',(-1.E0,0.E0,0.E0)); #1947=AXIS2_PLACEMENT_3D('',#1944,#1945,#1946); #1949=DIRECTION('',(0.E0,-1.E0,0.E0)); #1950=VECTOR('',#1949,3.75E-1); #1951=CARTESIAN_POINT('',(4.095E0,1.15E1,9.E0)); #1952=LINE('',#1951,#1950); #1953=DIRECTION('',(0.E0,-1.E0,0.E0)); #1954=VECTOR('',#1953,3.75E-1); #1955=CARTESIAN_POINT('',(3.905E0,1.15E1,9.E0)); #1956=LINE('',#1955,#1954); #1957=CARTESIAN_POINT('',(4.E0,1.1125E1,9.E0)); #1958=DIRECTION('',(0.E0,-1.E0,0.E0)); #1959=DIRECTION('',(1.E0,0.E0,0.E0)); #1960=AXIS2_PLACEMENT_3D('',#1957,#1958,#1959); #1962=CARTESIAN_POINT('',(4.E0,1.1125E1,9.E0)); #1963=DIRECTION('',(0.E0,-1.E0,0.E0)); #1964=DIRECTION('',(-1.E0,0.E0,0.E0)); #1965=AXIS2_PLACEMENT_3D('',#1962,#1963,#1964); #1967=DIRECTION('',(0.E0,-1.E0,0.E0)); #1968=VECTOR('',#1967,2.5E-1); #1969=CARTESIAN_POINT('',(3.929917478528E0,1.15E1,9.132582521472E0)); #1970=LINE('',#1969,#1968); #1971=DIRECTION('',(0.E0,-1.E0,0.E0)); #1972=VECTOR('',#1971,2.5E-1); #1973=CARTESIAN_POINT('',(3.804917478528E0,1.15E1,9.132582521472E0)); #1974=LINE('',#1973,#1972); #1975=CARTESIAN_POINT('',(3.867417478528E0,1.125E1,9.132582521472E0)); #1976=DIRECTION('',(0.E0,-1.E0,0.E0)); #1977=DIRECTION('',(1.E0,0.E0,0.E0)); #1978=AXIS2_PLACEMENT_3D('',#1975,#1976,#1977); #1980=CARTESIAN_POINT('',(3.867417478528E0,1.125E1,9.132582521472E0)); #1981=DIRECTION('',(0.E0,-1.E0,0.E0)); #1982=DIRECTION('',(-1.E0,0.E0,0.E0)); #1983=AXIS2_PLACEMENT_3D('',#1980,#1981,#1982); #1985=DIRECTION('',(0.E0,0.E0,1.E0)); #1986=VECTOR('',#1985,5.E-1); #1987=CARTESIAN_POINT('',(2.5E0,6.65E0,9.5E0)); #1988=LINE('',#1987,#1986); #1989=CARTESIAN_POINT('',(2.15E0,6.65E0,1.E1)); #1990=DIRECTION('',(0.E0,0.E0,1.E0)); #1991=DIRECTION('',(1.E0,0.E0,0.E0)); #1992=AXIS2_PLACEMENT_3D('',#1989,#1990,#1991); #1994=DIRECTION('',(0.E0,0.E0,1.E0)); #1995=VECTOR('',#1994,5.E-1); #1996=CARTESIAN_POINT('',(2.15E0,7.E0,9.5E0)); #1997=LINE('',#1996,#1995); #1998=CARTESIAN_POINT('',(2.15E0,6.65E0,9.5E0)); #1999=DIRECTION('',(0.E0,0.E0,-1.E0)); #2000=DIRECTION('',(0.E0,1.E0,0.E0)); #2001=AXIS2_PLACEMENT_3D('',#1998,#1999,#2000); #2003=DIRECTION('',(0.E0,-1.E0,0.E0)); #2004=VECTOR('',#2003,4.3E0); #2005=CARTESIAN_POINT('',(2.5E0,6.65E0,9.5E0)); #2006=LINE('',#2005,#2004); #2007=DIRECTION('',(1.E0,0.E0,0.E0)); #2008=VECTOR('',#2007,1.972007605460E-1); #2009=CARTESIAN_POINT('',(1.952799239454E0,7.E0,9.5E0)); #2010=LINE('',#2009,#2008); #2011=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0)); #2012=VECTOR('',#2011,2.059126028197E0); #2013=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,9.5E0)); #2014=LINE('',#2013,#2012); #2015=DIRECTION('',(-1.E0,0.E0,0.E0)); #2016=VECTOR('',#2015,1.197200760546E0); #2017=CARTESIAN_POINT('',(4.15E0,9.5E0,9.5E0)); #2018=LINE('',#2017,#2016); #2019=DIRECTION('',(0.E0,1.E0,0.E0)); #2020=VECTOR('',#2019,6.8E0); #2021=CARTESIAN_POINT('',(4.5E0,2.35E0,9.5E0)); #2022=LINE('',#2021,#2020); #2023=DIRECTION('',(1.E0,0.E0,0.E0)); #2024=VECTOR('',#2023,1.3E0); #2025=CARTESIAN_POINT('',(2.85E0,2.E0,9.5E0)); #2026=LINE('',#2025,#2024); #2027=DIRECTION('',(0.E0,0.E0,-1.E0)); #2028=VECTOR('',#2027,5.E-1); #2029=CARTESIAN_POINT('',(1.952799239454E0,7.E0,1.E1)); #2030=LINE('',#2029,#2028); #2031=CARTESIAN_POINT('',(1.952799239454E0,7.35E0,1.E1)); #2032=DIRECTION('',(0.E0,0.E0,-1.E0)); #2033=DIRECTION('',(0.E0,-1.E0,0.E0)); #2034=AXIS2_PLACEMENT_3D('',#2031,#2032,#2033); #2036=DIRECTION('',(0.E0,0.E0,-1.E0)); #2037=VECTOR('',#2036,5.E-1); #2038=CARTESIAN_POINT('',(1.646844192811E0,7.519975025913E0,1.E1)); #2039=LINE('',#2038,#2037); #2040=CARTESIAN_POINT('',(1.952799239454E0,7.35E0,9.5E0)); #2041=DIRECTION('',(0.E0,0.E0,1.E0)); #2042=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #2043=AXIS2_PLACEMENT_3D('',#2040,#2041,#2042); #2045=DIRECTION('',(0.E0,0.E0,-1.E0)); #2046=VECTOR('',#2045,5.E-1); #2047=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,1.E1)); #2048=LINE('',#2047,#2046); #2049=CARTESIAN_POINT('',(2.952799239454E0,9.15E0,1.E1)); #2050=DIRECTION('',(0.E0,0.E0,-1.E0)); #2051=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #2052=AXIS2_PLACEMENT_3D('',#2049,#2050,#2051); #2054=DIRECTION('',(0.E0,0.E0,-1.E0)); #2055=VECTOR('',#2054,5.E-1); #2056=CARTESIAN_POINT('',(2.952799239454E0,9.5E0,1.E1)); #2057=LINE('',#2056,#2055); #2058=CARTESIAN_POINT('',(2.952799239454E0,9.15E0,9.5E0)); #2059=DIRECTION('',(0.E0,0.E0,1.E0)); #2060=DIRECTION('',(0.E0,1.E0,0.E0)); #2061=AXIS2_PLACEMENT_3D('',#2058,#2059,#2060); #2063=DIRECTION('',(0.E0,0.E0,-1.E0)); #2064=VECTOR('',#2063,5.E-1); #2065=CARTESIAN_POINT('',(4.15E0,9.5E0,1.E1)); #2066=LINE('',#2065,#2064); #2067=CARTESIAN_POINT('',(4.15E0,9.15E0,1.E1)); #2068=DIRECTION('',(0.E0,0.E0,-1.E0)); #2069=DIRECTION('',(0.E0,1.E0,0.E0)); #2070=AXIS2_PLACEMENT_3D('',#2067,#2068,#2069); #2072=DIRECTION('',(0.E0,0.E0,-1.E0)); #2073=VECTOR('',#2072,5.E-1); #2074=CARTESIAN_POINT('',(4.5E0,9.15E0,1.E1)); #2075=LINE('',#2074,#2073); #2076=CARTESIAN_POINT('',(4.15E0,9.15E0,9.5E0)); #2077=DIRECTION('',(0.E0,0.E0,1.E0)); #2078=DIRECTION('',(1.E0,0.E0,0.E0)); #2079=AXIS2_PLACEMENT_3D('',#2076,#2077,#2078); #2081=DIRECTION('',(0.E0,0.E0,-1.E0)); #2082=VECTOR('',#2081,5.E-1); #2083=CARTESIAN_POINT('',(4.5E0,2.35E0,1.E1)); #2084=LINE('',#2083,#2082); #2085=CARTESIAN_POINT('',(4.15E0,2.35E0,1.E1)); #2086=DIRECTION('',(0.E0,0.E0,-1.E0)); #2087=DIRECTION('',(1.E0,0.E0,0.E0)); #2088=AXIS2_PLACEMENT_3D('',#2085,#2086,#2087); #2090=DIRECTION('',(0.E0,0.E0,-1.E0)); #2091=VECTOR('',#2090,5.E-1); #2092=CARTESIAN_POINT('',(4.15E0,2.E0,1.E1)); #2093=LINE('',#2092,#2091); #2094=CARTESIAN_POINT('',(4.15E0,2.35E0,9.5E0)); #2095=DIRECTION('',(0.E0,0.E0,1.E0)); #2096=DIRECTION('',(0.E0,-1.E0,0.E0)); #2097=AXIS2_PLACEMENT_3D('',#2094,#2095,#2096); #2099=DIRECTION('',(0.E0,0.E0,-1.E0)); #2100=VECTOR('',#2099,5.E-1); #2101=CARTESIAN_POINT('',(2.85E0,2.E0,1.E1)); #2102=LINE('',#2101,#2100); #2103=CARTESIAN_POINT('',(2.85E0,2.35E0,1.E1)); #2104=DIRECTION('',(0.E0,0.E0,-1.E0)); #2105=DIRECTION('',(0.E0,-1.E0,0.E0)); #2106=AXIS2_PLACEMENT_3D('',#2103,#2104,#2105); #2108=DIRECTION('',(0.E0,0.E0,-1.E0)); #2109=VECTOR('',#2108,5.E-1); #2110=CARTESIAN_POINT('',(2.5E0,2.35E0,1.E1)); #2111=LINE('',#2110,#2109); #2112=CARTESIAN_POINT('',(2.85E0,2.35E0,9.5E0)); #2113=DIRECTION('',(0.E0,0.E0,1.E0)); #2114=DIRECTION('',(-1.E0,0.E0,0.E0)); #2115=AXIS2_PLACEMENT_3D('',#2112,#2113,#2114); #2117=DIRECTION('',(0.E0,-1.E0,0.E0)); #2118=VECTOR('',#2117,1.5E0); #2119=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1)); #2120=LINE('',#2119,#2118); #2121=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #2122=VECTOR('',#2121,7.071067811865E-1); #2123=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1)); #2124=LINE('',#2123,#2122); #2125=DIRECTION('',(0.E0,-1.E0,0.E0)); #2126=VECTOR('',#2125,1.5E0); #2127=CARTESIAN_POINT('',(1.95E1,1.5E0,1.225E1)); #2128=LINE('',#2127,#2126); #2129=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #2130=VECTOR('',#2129,7.071067811865E-1); #2131=CARTESIAN_POINT('',(1.9E1,0.E0,1.175E1)); #2132=LINE('',#2131,#2130); #2133=DIRECTION('',(0.E0,-1.E0,0.E0)); #2134=VECTOR('',#2133,3.75E-1); #2135=CARTESIAN_POINT('',(1.9905E1,1.15E1,9.E0)); #2136=LINE('',#2135,#2134); #2137=DIRECTION('',(0.E0,-1.E0,0.E0)); #2138=VECTOR('',#2137,3.75E-1); #2139=CARTESIAN_POINT('',(2.0095E1,1.15E1,9.E0)); #2140=LINE('',#2139,#2138); #2141=CARTESIAN_POINT('',(2.E1,1.1125E1,9.E0)); #2142=DIRECTION('',(0.E0,1.E0,0.E0)); #2143=DIRECTION('',(-1.E0,0.E0,0.E0)); #2144=AXIS2_PLACEMENT_3D('',#2141,#2142,#2143); #2146=CARTESIAN_POINT('',(2.E1,1.1125E1,9.E0)); #2147=DIRECTION('',(0.E0,1.E0,0.E0)); #2148=DIRECTION('',(1.E0,0.E0,0.E0)); #2149=AXIS2_PLACEMENT_3D('',#2146,#2147,#2148); #2151=DIRECTION('',(0.E0,-1.E0,0.E0)); #2152=VECTOR('',#2151,2.5E-1); #2153=CARTESIAN_POINT('',(2.007008252147E1,1.15E1,9.132582521472E0)); #2154=LINE('',#2153,#2152); #2155=DIRECTION('',(0.E0,-1.E0,0.E0)); #2156=VECTOR('',#2155,2.5E-1); #2157=CARTESIAN_POINT('',(2.019508252147E1,1.15E1,9.132582521472E0)); #2158=LINE('',#2157,#2156); #2159=CARTESIAN_POINT('',(2.013258252147E1,1.125E1,9.132582521472E0)); #2160=DIRECTION('',(0.E0,1.E0,0.E0)); #2161=DIRECTION('',(-1.E0,0.E0,0.E0)); #2162=AXIS2_PLACEMENT_3D('',#2159,#2160,#2161); #2164=CARTESIAN_POINT('',(2.013258252147E1,1.125E1,9.132582521472E0)); #2165=DIRECTION('',(0.E0,1.E0,0.E0)); #2166=DIRECTION('',(1.E0,0.E0,0.E0)); #2167=AXIS2_PLACEMENT_3D('',#2164,#2165,#2166); #2169=DIRECTION('',(1.421085471520E-14,1.E0,0.E0)); #2170=VECTOR('',#2169,2.5E-1); #2171=CARTESIAN_POINT('',(1.745E1,1.25E0,2.975E1)); #2172=LINE('',#2171,#2170); #2173=DIRECTION('',(-1.421085471520E-14,1.E0,0.E0)); #2174=VECTOR('',#2173,2.5E-1); #2175=CARTESIAN_POINT('',(1.765E1,1.25E0,2.975E1)); #2176=LINE('',#2175,#2174); #2177=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0)); #2178=VECTOR('',#2177,1.154700538379E-1); #2179=CARTESIAN_POINT('',(1.755E1,1.192264973081E0,2.975E1)); #2180=LINE('',#2179,#2178); #2181=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0)); #2182=VECTOR('',#2181,1.154700538379E-1); #2183=CARTESIAN_POINT('',(1.755E1,1.192264973081E0,2.975E1)); #2184=LINE('',#2183,#2182); #2185=CARTESIAN_POINT('',(1.755E1,1.25E0,2.975E1)); #2186=DIRECTION('',(0.E0,-1.E0,0.E0)); #2187=DIRECTION('',(1.E0,0.E0,0.E0)); #2188=AXIS2_PLACEMENT_3D('',#2185,#2186,#2187); #2190=CARTESIAN_POINT('',(1.755E1,1.25E0,2.975E1)); #2191=DIRECTION('',(0.E0,1.E0,0.E0)); #2192=DIRECTION('',(1.E0,0.E0,0.E0)); #2193=AXIS2_PLACEMENT_3D('',#2190,#2191,#2192); #2195=DIRECTION('',(1.421085471520E-14,1.E0,0.E0)); #2196=VECTOR('',#2195,2.5E-1); #2197=CARTESIAN_POINT('',(1.645E1,1.25E0,2.975E1)); #2198=LINE('',#2197,#2196); #2199=DIRECTION('',(-1.421085471520E-14,1.E0,0.E0)); #2200=VECTOR('',#2199,2.5E-1); #2201=CARTESIAN_POINT('',(1.665E1,1.25E0,2.975E1)); #2202=LINE('',#2201,#2200); #2203=DIRECTION('',(-8.660254037844E-1,5.E-1,0.E0)); #2204=VECTOR('',#2203,1.154700538379E-1); #2205=CARTESIAN_POINT('',(1.655E1,1.192264973081E0,2.975E1)); #2206=LINE('',#2205,#2204); #2207=DIRECTION('',(8.660254037844E-1,5.E-1,0.E0)); #2208=VECTOR('',#2207,1.154700538379E-1); #2209=CARTESIAN_POINT('',(1.655E1,1.192264973081E0,2.975E1)); #2210=LINE('',#2209,#2208); #2211=CARTESIAN_POINT('',(1.655E1,1.25E0,2.975E1)); #2212=DIRECTION('',(0.E0,-1.E0,0.E0)); #2213=DIRECTION('',(1.E0,0.E0,0.E0)); #2214=AXIS2_PLACEMENT_3D('',#2211,#2212,#2213); #2216=CARTESIAN_POINT('',(1.655E1,1.25E0,2.975E1)); #2217=DIRECTION('',(0.E0,1.E0,0.E0)); #2218=DIRECTION('',(1.E0,0.E0,0.E0)); #2219=AXIS2_PLACEMENT_3D('',#2216,#2217,#2218); #2221=DIRECTION('',(0.E0,-1.E0,0.E0)); #2222=VECTOR('',#2221,5.E-1); #2223=CARTESIAN_POINT('',(1.3825E0,1.5E0,6.E0)); #2224=LINE('',#2223,#2222); #2225=DIRECTION('',(0.E0,-1.E0,0.E0)); #2226=VECTOR('',#2225,5.E-1); #2227=CARTESIAN_POINT('',(8.675E-1,1.5E0,6.E0)); #2228=LINE('',#2227,#2226); #2229=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0)); #2230=DIRECTION('',(0.E0,-1.E0,0.E0)); #2231=DIRECTION('',(1.E0,0.E0,0.E0)); #2232=AXIS2_PLACEMENT_3D('',#2229,#2230,#2231); #2234=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0)); #2235=DIRECTION('',(0.E0,-1.E0,0.E0)); #2236=DIRECTION('',(-1.E0,0.E0,0.E0)); #2237=AXIS2_PLACEMENT_3D('',#2234,#2235,#2236); #2239=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0)); #2240=DIRECTION('',(0.E0,-1.E0,0.E0)); #2241=DIRECTION('',(1.E0,0.E0,0.E0)); #2242=AXIS2_PLACEMENT_3D('',#2239,#2240,#2241); #2244=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0)); #2245=DIRECTION('',(0.E0,-1.E0,0.E0)); #2246=DIRECTION('',(-1.E0,0.E0,0.E0)); #2247=AXIS2_PLACEMENT_3D('',#2244,#2245,#2246); #2249=DIRECTION('',(0.E0,-1.E0,0.E0)); #2250=VECTOR('',#2249,1.E0); #2251=CARTESIAN_POINT('',(1.3175E0,1.E0,6.E0)); #2252=LINE('',#2251,#2250); #2253=DIRECTION('',(0.E0,-1.E0,0.E0)); #2254=VECTOR('',#2253,1.E0); #2255=CARTESIAN_POINT('',(9.325E-1,1.E0,6.E0)); #2256=LINE('',#2255,#2254); #2257=DIRECTION('',(0.E0,-1.E0,0.E0)); #2258=VECTOR('',#2257,5.E-1); #2259=CARTESIAN_POINT('',(1.3825E0,1.5E0,1.8E1)); #2260=LINE('',#2259,#2258); #2261=DIRECTION('',(0.E0,-1.E0,0.E0)); #2262=VECTOR('',#2261,5.E-1); #2263=CARTESIAN_POINT('',(8.675E-1,1.5E0,1.8E1)); #2264=LINE('',#2263,#2262); #2265=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1)); #2266=DIRECTION('',(0.E0,-1.E0,0.E0)); #2267=DIRECTION('',(1.E0,0.E0,0.E0)); #2268=AXIS2_PLACEMENT_3D('',#2265,#2266,#2267); #2270=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1)); #2271=DIRECTION('',(0.E0,-1.E0,0.E0)); #2272=DIRECTION('',(-1.E0,0.E0,0.E0)); #2273=AXIS2_PLACEMENT_3D('',#2270,#2271,#2272); #2275=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1)); #2276=DIRECTION('',(0.E0,-1.E0,0.E0)); #2277=DIRECTION('',(1.E0,0.E0,0.E0)); #2278=AXIS2_PLACEMENT_3D('',#2275,#2276,#2277); #2280=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1)); #2281=DIRECTION('',(0.E0,-1.E0,0.E0)); #2282=DIRECTION('',(-1.E0,0.E0,0.E0)); #2283=AXIS2_PLACEMENT_3D('',#2280,#2281,#2282); #2285=DIRECTION('',(0.E0,-1.E0,0.E0)); #2286=VECTOR('',#2285,1.E0); #2287=CARTESIAN_POINT('',(1.3175E0,1.E0,1.8E1)); #2288=LINE('',#2287,#2286); #2289=DIRECTION('',(0.E0,-1.E0,0.E0)); #2290=VECTOR('',#2289,1.E0); #2291=CARTESIAN_POINT('',(9.325E-1,1.E0,1.8E1)); #2292=LINE('',#2291,#2290); #2293=DIRECTION('',(0.E0,-1.E0,0.E0)); #2294=VECTOR('',#2293,5.E-1); #2295=CARTESIAN_POINT('',(1.3825E0,1.5E0,2.4E1)); #2296=LINE('',#2295,#2294); #2297=DIRECTION('',(0.E0,-1.E0,0.E0)); #2298=VECTOR('',#2297,5.E-1); #2299=CARTESIAN_POINT('',(8.675E-1,1.5E0,2.4E1)); #2300=LINE('',#2299,#2298); #2301=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1)); #2302=DIRECTION('',(0.E0,-1.E0,0.E0)); #2303=DIRECTION('',(1.E0,0.E0,0.E0)); #2304=AXIS2_PLACEMENT_3D('',#2301,#2302,#2303); #2306=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1)); #2307=DIRECTION('',(0.E0,-1.E0,0.E0)); #2308=DIRECTION('',(-1.E0,0.E0,0.E0)); #2309=AXIS2_PLACEMENT_3D('',#2306,#2307,#2308); #2311=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1)); #2312=DIRECTION('',(0.E0,-1.E0,0.E0)); #2313=DIRECTION('',(1.E0,0.E0,0.E0)); #2314=AXIS2_PLACEMENT_3D('',#2311,#2312,#2313); #2316=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1)); #2317=DIRECTION('',(0.E0,-1.E0,0.E0)); #2318=DIRECTION('',(-1.E0,0.E0,0.E0)); #2319=AXIS2_PLACEMENT_3D('',#2316,#2317,#2318); #2321=DIRECTION('',(0.E0,-1.E0,0.E0)); #2322=VECTOR('',#2321,1.E0); #2323=CARTESIAN_POINT('',(1.3175E0,1.E0,2.4E1)); #2324=LINE('',#2323,#2322); #2325=DIRECTION('',(0.E0,-1.E0,0.E0)); #2326=VECTOR('',#2325,1.E0); #2327=CARTESIAN_POINT('',(9.325E-1,1.E0,2.4E1)); #2328=LINE('',#2327,#2326); #2329=DIRECTION('',(0.E0,-1.E0,0.E0)); #2330=VECTOR('',#2329,5.E-1); #2331=CARTESIAN_POINT('',(2.31325E1,1.5E0,6.E0)); #2332=LINE('',#2331,#2330); #2333=DIRECTION('',(0.E0,-1.E0,0.E0)); #2334=VECTOR('',#2333,5.E-1); #2335=CARTESIAN_POINT('',(2.26175E1,1.5E0,6.E0)); #2336=LINE('',#2335,#2334); #2337=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0)); #2338=DIRECTION('',(0.E0,-1.E0,0.E0)); #2339=DIRECTION('',(1.E0,0.E0,0.E0)); #2340=AXIS2_PLACEMENT_3D('',#2337,#2338,#2339); #2342=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0)); #2343=DIRECTION('',(0.E0,-1.E0,0.E0)); #2344=DIRECTION('',(-1.E0,0.E0,0.E0)); #2345=AXIS2_PLACEMENT_3D('',#2342,#2343,#2344); #2347=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0)); #2348=DIRECTION('',(0.E0,-1.E0,0.E0)); #2349=DIRECTION('',(1.E0,0.E0,0.E0)); #2350=AXIS2_PLACEMENT_3D('',#2347,#2348,#2349); #2352=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0)); #2353=DIRECTION('',(0.E0,-1.E0,0.E0)); #2354=DIRECTION('',(-1.E0,0.E0,0.E0)); #2355=AXIS2_PLACEMENT_3D('',#2352,#2353,#2354); #2357=DIRECTION('',(0.E0,-1.E0,0.E0)); #2358=VECTOR('',#2357,1.E0); #2359=CARTESIAN_POINT('',(2.30675E1,1.E0,6.E0)); #2360=LINE('',#2359,#2358); #2361=DIRECTION('',(0.E0,-1.E0,0.E0)); #2362=VECTOR('',#2361,1.E0); #2363=CARTESIAN_POINT('',(2.26825E1,1.E0,6.E0)); #2364=LINE('',#2363,#2362); #2365=DIRECTION('',(0.E0,-1.E0,0.E0)); #2366=VECTOR('',#2365,5.E-1); #2367=CARTESIAN_POINT('',(2.31325E1,1.5E0,1.8E1)); #2368=LINE('',#2367,#2366); #2369=DIRECTION('',(0.E0,-1.E0,0.E0)); #2370=VECTOR('',#2369,5.E-1); #2371=CARTESIAN_POINT('',(2.26175E1,1.5E0,1.8E1)); #2372=LINE('',#2371,#2370); #2373=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1)); #2374=DIRECTION('',(0.E0,-1.E0,0.E0)); #2375=DIRECTION('',(1.E0,0.E0,0.E0)); #2376=AXIS2_PLACEMENT_3D('',#2373,#2374,#2375); #2378=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1)); #2379=DIRECTION('',(0.E0,-1.E0,0.E0)); #2380=DIRECTION('',(-1.E0,0.E0,0.E0)); #2381=AXIS2_PLACEMENT_3D('',#2378,#2379,#2380); #2383=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1)); #2384=DIRECTION('',(0.E0,-1.E0,0.E0)); #2385=DIRECTION('',(1.E0,0.E0,0.E0)); #2386=AXIS2_PLACEMENT_3D('',#2383,#2384,#2385); #2388=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1)); #2389=DIRECTION('',(0.E0,-1.E0,0.E0)); #2390=DIRECTION('',(-1.E0,0.E0,0.E0)); #2391=AXIS2_PLACEMENT_3D('',#2388,#2389,#2390); #2393=DIRECTION('',(0.E0,-1.E0,0.E0)); #2394=VECTOR('',#2393,1.E0); #2395=CARTESIAN_POINT('',(2.30675E1,1.E0,1.8E1)); #2396=LINE('',#2395,#2394); #2397=DIRECTION('',(0.E0,-1.E0,0.E0)); #2398=VECTOR('',#2397,1.E0); #2399=CARTESIAN_POINT('',(2.26825E1,1.E0,1.8E1)); #2400=LINE('',#2399,#2398); #2401=DIRECTION('',(0.E0,-1.E0,0.E0)); #2402=VECTOR('',#2401,5.E-1); #2403=CARTESIAN_POINT('',(2.31325E1,1.5E0,2.4E1)); #2404=LINE('',#2403,#2402); #2405=DIRECTION('',(0.E0,-1.E0,0.E0)); #2406=VECTOR('',#2405,5.E-1); #2407=CARTESIAN_POINT('',(2.26175E1,1.5E0,2.4E1)); #2408=LINE('',#2407,#2406); #2409=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1)); #2410=DIRECTION('',(0.E0,-1.E0,0.E0)); #2411=DIRECTION('',(1.E0,0.E0,0.E0)); #2412=AXIS2_PLACEMENT_3D('',#2409,#2410,#2411); #2414=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1)); #2415=DIRECTION('',(0.E0,-1.E0,0.E0)); #2416=DIRECTION('',(-1.E0,0.E0,0.E0)); #2417=AXIS2_PLACEMENT_3D('',#2414,#2415,#2416); #2419=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1)); #2420=DIRECTION('',(0.E0,-1.E0,0.E0)); #2421=DIRECTION('',(1.E0,0.E0,0.E0)); #2422=AXIS2_PLACEMENT_3D('',#2419,#2420,#2421); #2424=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1)); #2425=DIRECTION('',(0.E0,-1.E0,0.E0)); #2426=DIRECTION('',(-1.E0,0.E0,0.E0)); #2427=AXIS2_PLACEMENT_3D('',#2424,#2425,#2426); #2429=DIRECTION('',(0.E0,-1.E0,0.E0)); #2430=VECTOR('',#2429,1.E0); #2431=CARTESIAN_POINT('',(2.30675E1,1.E0,2.4E1)); #2432=LINE('',#2431,#2430); #2433=DIRECTION('',(0.E0,-1.E0,0.E0)); #2434=VECTOR('',#2433,1.E0); #2435=CARTESIAN_POINT('',(2.26825E1,1.E0,2.4E1)); #2436=LINE('',#2435,#2434); #2437=DIRECTION('',(0.E0,-1.E0,0.E0)); #2438=VECTOR('',#2437,5.E-1); #2439=CARTESIAN_POINT('',(6.256E0,1.5E0,1.25E0)); #2440=LINE('',#2439,#2438); #2441=DIRECTION('',(0.E0,-1.E0,0.E0)); #2442=VECTOR('',#2441,5.E-1); #2443=CARTESIAN_POINT('',(5.744E0,1.5E0,1.25E0)); #2444=LINE('',#2443,#2442); #2445=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0)); #2446=DIRECTION('',(0.E0,-1.E0,0.E0)); #2447=DIRECTION('',(1.E0,0.E0,0.E0)); #2448=AXIS2_PLACEMENT_3D('',#2445,#2446,#2447); #2450=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0)); #2451=DIRECTION('',(0.E0,-1.E0,0.E0)); #2452=DIRECTION('',(-1.E0,0.E0,0.E0)); #2453=AXIS2_PLACEMENT_3D('',#2450,#2451,#2452); #2455=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0)); #2456=DIRECTION('',(0.E0,-1.E0,0.E0)); #2457=DIRECTION('',(1.E0,0.E0,0.E0)); #2458=AXIS2_PLACEMENT_3D('',#2455,#2456,#2457); #2460=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0)); #2461=DIRECTION('',(0.E0,-1.E0,0.E0)); #2462=DIRECTION('',(-1.E0,0.E0,0.E0)); #2463=AXIS2_PLACEMENT_3D('',#2460,#2461,#2462); #2465=DIRECTION('',(0.E0,-1.E0,0.E0)); #2466=VECTOR('',#2465,1.E0); #2467=CARTESIAN_POINT('',(6.1925E0,1.E0,1.25E0)); #2468=LINE('',#2467,#2466); #2469=DIRECTION('',(0.E0,-1.E0,0.E0)); #2470=VECTOR('',#2469,1.E0); #2471=CARTESIAN_POINT('',(5.8075E0,1.E0,1.25E0)); #2472=LINE('',#2471,#2470); #2473=DIRECTION('',(0.E0,-1.E0,0.E0)); #2474=VECTOR('',#2473,5.E-1); #2475=CARTESIAN_POINT('',(1.2256E1,1.5E0,1.25E0)); #2476=LINE('',#2475,#2474); #2477=DIRECTION('',(0.E0,-1.E0,0.E0)); #2478=VECTOR('',#2477,5.E-1); #2479=CARTESIAN_POINT('',(1.1744E1,1.5E0,1.25E0)); #2480=LINE('',#2479,#2478); #2481=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0)); #2482=DIRECTION('',(0.E0,-1.E0,0.E0)); #2483=DIRECTION('',(1.E0,0.E0,0.E0)); #2484=AXIS2_PLACEMENT_3D('',#2481,#2482,#2483); #2486=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0)); #2487=DIRECTION('',(0.E0,-1.E0,0.E0)); #2488=DIRECTION('',(-1.E0,0.E0,0.E0)); #2489=AXIS2_PLACEMENT_3D('',#2486,#2487,#2488); #2491=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0)); #2492=DIRECTION('',(0.E0,-1.E0,0.E0)); #2493=DIRECTION('',(1.E0,0.E0,0.E0)); #2494=AXIS2_PLACEMENT_3D('',#2491,#2492,#2493); #2496=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0)); #2497=DIRECTION('',(0.E0,-1.E0,0.E0)); #2498=DIRECTION('',(-1.E0,0.E0,0.E0)); #2499=AXIS2_PLACEMENT_3D('',#2496,#2497,#2498); #2501=DIRECTION('',(0.E0,-1.E0,0.E0)); #2502=VECTOR('',#2501,1.E0); #2503=CARTESIAN_POINT('',(1.21925E1,1.E0,1.25E0)); #2504=LINE('',#2503,#2502); #2505=DIRECTION('',(0.E0,-1.E0,0.E0)); #2506=VECTOR('',#2505,1.E0); #2507=CARTESIAN_POINT('',(1.18075E1,1.E0,1.25E0)); #2508=LINE('',#2507,#2506); #2509=DIRECTION('',(0.E0,-1.E0,0.E0)); #2510=VECTOR('',#2509,5.E-1); #2511=CARTESIAN_POINT('',(1.8256E1,1.5E0,1.25E0)); #2512=LINE('',#2511,#2510); #2513=DIRECTION('',(0.E0,-1.E0,0.E0)); #2514=VECTOR('',#2513,5.E-1); #2515=CARTESIAN_POINT('',(1.7744E1,1.5E0,1.25E0)); #2516=LINE('',#2515,#2514); #2517=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0)); #2518=DIRECTION('',(0.E0,-1.E0,0.E0)); #2519=DIRECTION('',(1.E0,0.E0,0.E0)); #2520=AXIS2_PLACEMENT_3D('',#2517,#2518,#2519); #2522=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0)); #2523=DIRECTION('',(0.E0,-1.E0,0.E0)); #2524=DIRECTION('',(-1.E0,0.E0,0.E0)); #2525=AXIS2_PLACEMENT_3D('',#2522,#2523,#2524); #2527=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0)); #2528=DIRECTION('',(0.E0,-1.E0,0.E0)); #2529=DIRECTION('',(1.E0,0.E0,0.E0)); #2530=AXIS2_PLACEMENT_3D('',#2527,#2528,#2529); #2532=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0)); #2533=DIRECTION('',(0.E0,-1.E0,0.E0)); #2534=DIRECTION('',(-1.E0,0.E0,0.E0)); #2535=AXIS2_PLACEMENT_3D('',#2532,#2533,#2534); #2537=DIRECTION('',(0.E0,-1.E0,0.E0)); #2538=VECTOR('',#2537,1.E0); #2539=CARTESIAN_POINT('',(1.81925E1,1.E0,1.25E0)); #2540=LINE('',#2539,#2538); #2541=DIRECTION('',(0.E0,-1.E0,0.E0)); #2542=VECTOR('',#2541,1.E0); #2543=CARTESIAN_POINT('',(1.78075E1,1.E0,1.25E0)); #2544=LINE('',#2543,#2542); #2545=DIRECTION('',(0.E0,-1.E0,0.E0)); #2546=VECTOR('',#2545,5.E-1); #2547=CARTESIAN_POINT('',(6.256E0,1.5E0,3.075E1)); #2548=LINE('',#2547,#2546); #2549=DIRECTION('',(0.E0,-1.E0,0.E0)); #2550=VECTOR('',#2549,5.E-1); #2551=CARTESIAN_POINT('',(5.744E0,1.5E0,3.075E1)); #2552=LINE('',#2551,#2550); #2553=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1)); #2554=DIRECTION('',(0.E0,-1.E0,0.E0)); #2555=DIRECTION('',(1.E0,0.E0,0.E0)); #2556=AXIS2_PLACEMENT_3D('',#2553,#2554,#2555); #2558=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1)); #2559=DIRECTION('',(0.E0,-1.E0,0.E0)); #2560=DIRECTION('',(-1.E0,0.E0,0.E0)); #2561=AXIS2_PLACEMENT_3D('',#2558,#2559,#2560); #2563=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1)); #2564=DIRECTION('',(0.E0,-1.E0,0.E0)); #2565=DIRECTION('',(1.E0,0.E0,0.E0)); #2566=AXIS2_PLACEMENT_3D('',#2563,#2564,#2565); #2568=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1)); #2569=DIRECTION('',(0.E0,-1.E0,0.E0)); #2570=DIRECTION('',(-1.E0,0.E0,0.E0)); #2571=AXIS2_PLACEMENT_3D('',#2568,#2569,#2570); #2573=DIRECTION('',(0.E0,-1.E0,0.E0)); #2574=VECTOR('',#2573,1.E0); #2575=CARTESIAN_POINT('',(6.1925E0,1.E0,3.075E1)); #2576=LINE('',#2575,#2574); #2577=DIRECTION('',(0.E0,-1.E0,0.E0)); #2578=VECTOR('',#2577,1.E0); #2579=CARTESIAN_POINT('',(5.8075E0,1.E0,3.075E1)); #2580=LINE('',#2579,#2578); #2581=DIRECTION('',(0.E0,-1.E0,0.E0)); #2582=VECTOR('',#2581,5.E-1); #2583=CARTESIAN_POINT('',(1.2256E1,1.5E0,3.075E1)); #2584=LINE('',#2583,#2582); #2585=DIRECTION('',(0.E0,-1.E0,0.E0)); #2586=VECTOR('',#2585,5.E-1); #2587=CARTESIAN_POINT('',(1.1744E1,1.5E0,3.075E1)); #2588=LINE('',#2587,#2586); #2589=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1)); #2590=DIRECTION('',(0.E0,-1.E0,0.E0)); #2591=DIRECTION('',(1.E0,0.E0,0.E0)); #2592=AXIS2_PLACEMENT_3D('',#2589,#2590,#2591); #2594=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1)); #2595=DIRECTION('',(0.E0,-1.E0,0.E0)); #2596=DIRECTION('',(-1.E0,0.E0,0.E0)); #2597=AXIS2_PLACEMENT_3D('',#2594,#2595,#2596); #2599=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1)); #2600=DIRECTION('',(0.E0,-1.E0,0.E0)); #2601=DIRECTION('',(1.E0,0.E0,0.E0)); #2602=AXIS2_PLACEMENT_3D('',#2599,#2600,#2601); #2604=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1)); #2605=DIRECTION('',(0.E0,-1.E0,0.E0)); #2606=DIRECTION('',(-1.E0,0.E0,0.E0)); #2607=AXIS2_PLACEMENT_3D('',#2604,#2605,#2606); #2609=DIRECTION('',(0.E0,-1.E0,0.E0)); #2610=VECTOR('',#2609,1.E0); #2611=CARTESIAN_POINT('',(1.21925E1,1.E0,3.075E1)); #2612=LINE('',#2611,#2610); #2613=DIRECTION('',(0.E0,-1.E0,0.E0)); #2614=VECTOR('',#2613,1.E0); #2615=CARTESIAN_POINT('',(1.18075E1,1.E0,3.075E1)); #2616=LINE('',#2615,#2614); #2617=DIRECTION('',(0.E0,-1.E0,0.E0)); #2618=VECTOR('',#2617,5.E-1); #2619=CARTESIAN_POINT('',(1.8256E1,1.5E0,3.075E1)); #2620=LINE('',#2619,#2618); #2621=DIRECTION('',(0.E0,-1.E0,0.E0)); #2622=VECTOR('',#2621,5.E-1); #2623=CARTESIAN_POINT('',(1.7744E1,1.5E0,3.075E1)); #2624=LINE('',#2623,#2622); #2625=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1)); #2626=DIRECTION('',(0.E0,-1.E0,0.E0)); #2627=DIRECTION('',(1.E0,0.E0,0.E0)); #2628=AXIS2_PLACEMENT_3D('',#2625,#2626,#2627); #2630=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1)); #2631=DIRECTION('',(0.E0,-1.E0,0.E0)); #2632=DIRECTION('',(-1.E0,0.E0,0.E0)); #2633=AXIS2_PLACEMENT_3D('',#2630,#2631,#2632); #2635=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1)); #2636=DIRECTION('',(0.E0,-1.E0,0.E0)); #2637=DIRECTION('',(1.E0,0.E0,0.E0)); #2638=AXIS2_PLACEMENT_3D('',#2635,#2636,#2637); #2640=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1)); #2641=DIRECTION('',(0.E0,-1.E0,0.E0)); #2642=DIRECTION('',(-1.E0,0.E0,0.E0)); #2643=AXIS2_PLACEMENT_3D('',#2640,#2641,#2642); #2645=DIRECTION('',(0.E0,-1.E0,0.E0)); #2646=VECTOR('',#2645,1.E0); #2647=CARTESIAN_POINT('',(1.81925E1,1.E0,3.075E1)); #2648=LINE('',#2647,#2646); #2649=DIRECTION('',(0.E0,-1.E0,0.E0)); #2650=VECTOR('',#2649,1.E0); #2651=CARTESIAN_POINT('',(1.78075E1,1.E0,3.075E1)); #2652=LINE('',#2651,#2650); #2653=DIRECTION('',(0.E0,-1.E0,0.E0)); #2654=VECTOR('',#2653,5.E-1); #2655=CARTESIAN_POINT('',(6.2575E0,1.5E0,9.E0)); #2656=LINE('',#2655,#2654); #2657=DIRECTION('',(0.E0,-1.E0,0.E0)); #2658=VECTOR('',#2657,5.E-1); #2659=CARTESIAN_POINT('',(5.7425E0,1.5E0,9.E0)); #2660=LINE('',#2659,#2658); #2661=CARTESIAN_POINT('',(6.E0,1.E0,9.E0)); #2662=DIRECTION('',(0.E0,-1.E0,0.E0)); #2663=DIRECTION('',(1.E0,0.E0,0.E0)); #2664=AXIS2_PLACEMENT_3D('',#2661,#2662,#2663); #2666=CARTESIAN_POINT('',(6.E0,1.E0,9.E0)); #2667=DIRECTION('',(0.E0,-1.E0,0.E0)); #2668=DIRECTION('',(-1.E0,0.E0,0.E0)); #2669=AXIS2_PLACEMENT_3D('',#2666,#2667,#2668); #2671=CARTESIAN_POINT('',(6.E0,1.E0,9.E0)); #2672=DIRECTION('',(0.E0,-1.E0,0.E0)); #2673=DIRECTION('',(1.E0,0.E0,0.E0)); #2674=AXIS2_PLACEMENT_3D('',#2671,#2672,#2673); #2676=CARTESIAN_POINT('',(6.E0,1.E0,9.E0)); #2677=DIRECTION('',(0.E0,-1.E0,0.E0)); #2678=DIRECTION('',(-1.E0,0.E0,0.E0)); #2679=AXIS2_PLACEMENT_3D('',#2676,#2677,#2678); #2681=DIRECTION('',(0.E0,-1.E0,0.E0)); #2682=VECTOR('',#2681,1.E0); #2683=CARTESIAN_POINT('',(6.1925E0,1.E0,9.E0)); #2684=LINE('',#2683,#2682); #2685=DIRECTION('',(0.E0,-1.E0,0.E0)); #2686=VECTOR('',#2685,1.E0); #2687=CARTESIAN_POINT('',(5.8075E0,1.E0,9.E0)); #2688=LINE('',#2687,#2686); #2689=DIRECTION('',(0.E0,-1.E0,0.E0)); #2690=VECTOR('',#2689,5.E-1); #2691=CARTESIAN_POINT('',(1.22575E1,1.5E0,9.E0)); #2692=LINE('',#2691,#2690); #2693=DIRECTION('',(0.E0,-1.E0,0.E0)); #2694=VECTOR('',#2693,5.E-1); #2695=CARTESIAN_POINT('',(1.17425E1,1.5E0,9.E0)); #2696=LINE('',#2695,#2694); #2697=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0)); #2698=DIRECTION('',(0.E0,-1.E0,0.E0)); #2699=DIRECTION('',(1.E0,0.E0,0.E0)); #2700=AXIS2_PLACEMENT_3D('',#2697,#2698,#2699); #2702=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0)); #2703=DIRECTION('',(0.E0,-1.E0,0.E0)); #2704=DIRECTION('',(-1.E0,0.E0,0.E0)); #2705=AXIS2_PLACEMENT_3D('',#2702,#2703,#2704); #2707=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0)); #2708=DIRECTION('',(0.E0,-1.E0,0.E0)); #2709=DIRECTION('',(1.E0,0.E0,0.E0)); #2710=AXIS2_PLACEMENT_3D('',#2707,#2708,#2709); #2712=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0)); #2713=DIRECTION('',(0.E0,-1.E0,0.E0)); #2714=DIRECTION('',(-1.E0,0.E0,0.E0)); #2715=AXIS2_PLACEMENT_3D('',#2712,#2713,#2714); #2717=DIRECTION('',(0.E0,-1.E0,0.E0)); #2718=VECTOR('',#2717,1.E0); #2719=CARTESIAN_POINT('',(1.21925E1,1.E0,9.E0)); #2720=LINE('',#2719,#2718); #2721=DIRECTION('',(0.E0,-1.E0,0.E0)); #2722=VECTOR('',#2721,1.E0); #2723=CARTESIAN_POINT('',(1.18075E1,1.E0,9.E0)); #2724=LINE('',#2723,#2722); #2725=DIRECTION('',(0.E0,-1.E0,0.E0)); #2726=VECTOR('',#2725,5.E-1); #2727=CARTESIAN_POINT('',(1.82575E1,1.5E0,9.E0)); #2728=LINE('',#2727,#2726); #2729=DIRECTION('',(0.E0,-1.E0,0.E0)); #2730=VECTOR('',#2729,5.E-1); #2731=CARTESIAN_POINT('',(1.77425E1,1.5E0,9.E0)); #2732=LINE('',#2731,#2730); #2733=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0)); #2734=DIRECTION('',(0.E0,-1.E0,0.E0)); #2735=DIRECTION('',(1.E0,0.E0,0.E0)); #2736=AXIS2_PLACEMENT_3D('',#2733,#2734,#2735); #2738=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0)); #2739=DIRECTION('',(0.E0,-1.E0,0.E0)); #2740=DIRECTION('',(-1.E0,0.E0,0.E0)); #2741=AXIS2_PLACEMENT_3D('',#2738,#2739,#2740); #2743=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0)); #2744=DIRECTION('',(0.E0,-1.E0,0.E0)); #2745=DIRECTION('',(1.E0,0.E0,0.E0)); #2746=AXIS2_PLACEMENT_3D('',#2743,#2744,#2745); #2748=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0)); #2749=DIRECTION('',(0.E0,-1.E0,0.E0)); #2750=DIRECTION('',(-1.E0,0.E0,0.E0)); #2751=AXIS2_PLACEMENT_3D('',#2748,#2749,#2750); #2753=DIRECTION('',(0.E0,-1.E0,0.E0)); #2754=VECTOR('',#2753,1.E0); #2755=CARTESIAN_POINT('',(1.81925E1,1.E0,9.E0)); #2756=LINE('',#2755,#2754); #2757=DIRECTION('',(0.E0,-1.E0,0.E0)); #2758=VECTOR('',#2757,1.E0); #2759=CARTESIAN_POINT('',(1.78075E1,1.E0,9.E0)); #2760=LINE('',#2759,#2758); #2761=DIRECTION('',(0.E0,-1.E0,0.E0)); #2762=VECTOR('',#2761,5.E-1); #2763=CARTESIAN_POINT('',(6.2575E0,1.5E0,1.8E1)); #2764=LINE('',#2763,#2762); #2765=DIRECTION('',(0.E0,-1.E0,0.E0)); #2766=VECTOR('',#2765,5.E-1); #2767=CARTESIAN_POINT('',(5.7425E0,1.5E0,1.8E1)); #2768=LINE('',#2767,#2766); #2769=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1)); #2770=DIRECTION('',(0.E0,-1.E0,0.E0)); #2771=DIRECTION('',(1.E0,0.E0,0.E0)); #2772=AXIS2_PLACEMENT_3D('',#2769,#2770,#2771); #2774=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1)); #2775=DIRECTION('',(0.E0,-1.E0,0.E0)); #2776=DIRECTION('',(-1.E0,0.E0,0.E0)); #2777=AXIS2_PLACEMENT_3D('',#2774,#2775,#2776); #2779=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1)); #2780=DIRECTION('',(0.E0,-1.E0,0.E0)); #2781=DIRECTION('',(1.E0,0.E0,0.E0)); #2782=AXIS2_PLACEMENT_3D('',#2779,#2780,#2781); #2784=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1)); #2785=DIRECTION('',(0.E0,-1.E0,0.E0)); #2786=DIRECTION('',(-1.E0,0.E0,0.E0)); #2787=AXIS2_PLACEMENT_3D('',#2784,#2785,#2786); #2789=DIRECTION('',(0.E0,-1.E0,0.E0)); #2790=VECTOR('',#2789,1.E0); #2791=CARTESIAN_POINT('',(6.1925E0,1.E0,1.8E1)); #2792=LINE('',#2791,#2790); #2793=DIRECTION('',(0.E0,-1.E0,0.E0)); #2794=VECTOR('',#2793,1.E0); #2795=CARTESIAN_POINT('',(5.8075E0,1.E0,1.8E1)); #2796=LINE('',#2795,#2794); #2797=DIRECTION('',(0.E0,-1.E0,0.E0)); #2798=VECTOR('',#2797,5.E-1); #2799=CARTESIAN_POINT('',(1.22575E1,1.5E0,1.8E1)); #2800=LINE('',#2799,#2798); #2801=DIRECTION('',(0.E0,-1.E0,0.E0)); #2802=VECTOR('',#2801,5.E-1); #2803=CARTESIAN_POINT('',(1.17425E1,1.5E0,1.8E1)); #2804=LINE('',#2803,#2802); #2805=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1)); #2806=DIRECTION('',(0.E0,-1.E0,0.E0)); #2807=DIRECTION('',(1.E0,0.E0,0.E0)); #2808=AXIS2_PLACEMENT_3D('',#2805,#2806,#2807); #2810=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1)); #2811=DIRECTION('',(0.E0,-1.E0,0.E0)); #2812=DIRECTION('',(-1.E0,0.E0,0.E0)); #2813=AXIS2_PLACEMENT_3D('',#2810,#2811,#2812); #2815=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1)); #2816=DIRECTION('',(0.E0,-1.E0,0.E0)); #2817=DIRECTION('',(1.E0,0.E0,0.E0)); #2818=AXIS2_PLACEMENT_3D('',#2815,#2816,#2817); #2820=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1)); #2821=DIRECTION('',(0.E0,-1.E0,0.E0)); #2822=DIRECTION('',(-1.E0,0.E0,0.E0)); #2823=AXIS2_PLACEMENT_3D('',#2820,#2821,#2822); #2825=DIRECTION('',(0.E0,-1.E0,0.E0)); #2826=VECTOR('',#2825,1.E0); #2827=CARTESIAN_POINT('',(1.21925E1,1.E0,1.8E1)); #2828=LINE('',#2827,#2826); #2829=DIRECTION('',(0.E0,-1.E0,0.E0)); #2830=VECTOR('',#2829,1.E0); #2831=CARTESIAN_POINT('',(1.18075E1,1.E0,1.8E1)); #2832=LINE('',#2831,#2830); #2833=DIRECTION('',(0.E0,-1.E0,0.E0)); #2834=VECTOR('',#2833,5.E-1); #2835=CARTESIAN_POINT('',(1.82575E1,1.5E0,1.8E1)); #2836=LINE('',#2835,#2834); #2837=DIRECTION('',(0.E0,-1.E0,0.E0)); #2838=VECTOR('',#2837,5.E-1); #2839=CARTESIAN_POINT('',(1.77425E1,1.5E0,1.8E1)); #2840=LINE('',#2839,#2838); #2841=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1)); #2842=DIRECTION('',(0.E0,-1.E0,0.E0)); #2843=DIRECTION('',(1.E0,0.E0,0.E0)); #2844=AXIS2_PLACEMENT_3D('',#2841,#2842,#2843); #2846=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1)); #2847=DIRECTION('',(0.E0,-1.E0,0.E0)); #2848=DIRECTION('',(-1.E0,0.E0,0.E0)); #2849=AXIS2_PLACEMENT_3D('',#2846,#2847,#2848); #2851=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1)); #2852=DIRECTION('',(0.E0,-1.E0,0.E0)); #2853=DIRECTION('',(1.E0,0.E0,0.E0)); #2854=AXIS2_PLACEMENT_3D('',#2851,#2852,#2853); #2856=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1)); #2857=DIRECTION('',(0.E0,-1.E0,0.E0)); #2858=DIRECTION('',(-1.E0,0.E0,0.E0)); #2859=AXIS2_PLACEMENT_3D('',#2856,#2857,#2858); #2861=DIRECTION('',(0.E0,-1.E0,0.E0)); #2862=VECTOR('',#2861,1.E0); #2863=CARTESIAN_POINT('',(1.81925E1,1.E0,1.8E1)); #2864=LINE('',#2863,#2862); #2865=DIRECTION('',(0.E0,-1.E0,0.E0)); #2866=VECTOR('',#2865,1.E0); #2867=CARTESIAN_POINT('',(1.78075E1,1.E0,1.8E1)); #2868=LINE('',#2867,#2866); #2869=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1)); #2870=VECTOR('',#2869,5.773502691896E0); #2871=CARTESIAN_POINT('',(2.2E1,6.5E0,1.E1)); #2872=LINE('',#2871,#2870); #2873=CARTESIAN_POINT('',(2.31325E1,3.035898384862E0,1.2E1)); #2874=CARTESIAN_POINT('',(2.31325E1,2.930774450068E0,1.206069333205E1)); #2875=CARTESIAN_POINT('',(2.309416136180E1,2.745461691651E0,1.216768370301E1)); #2876=CARTESIAN_POINT('',(2.297013771881E1,2.608885438662E0,1.224653603944E1)); #2877=CARTESIAN_POINT('',(2.2875E1,2.580400233539E0,1.226298198028E1)); #2878=CARTESIAN_POINT('',(2.277986228119E1,2.608885438662E0,1.224653603944E1)); #2879=CARTESIAN_POINT('',(2.265583863820E1,2.745461691651E0,1.216768370301E1)); #2880=CARTESIAN_POINT('',(2.26175E1,2.930774450068E0,1.206069333205E1)); #2881=CARTESIAN_POINT('',(2.26175E1,3.035898384862E0,1.2E1)); #2883=CARTESIAN_POINT('',(2.26175E1,3.035898384862E0,1.2E1)); #2884=CARTESIAN_POINT('',(2.26175E1,3.141022319657E0,1.193930666795E1)); #2885=CARTESIAN_POINT('',(2.265583863820E1,3.326335078073E0,1.183231629699E1)); #2886=CARTESIAN_POINT('',(2.277986228119E1,3.462911331062E0,1.175346396056E1)); #2887=CARTESIAN_POINT('',(2.2875E1,3.491396536186E0,1.173701801972E1)); #2888=CARTESIAN_POINT('',(2.297013771881E1,3.462911331062E0,1.175346396056E1)); #2889=CARTESIAN_POINT('',(2.309416136180E1,3.326335078073E0,1.183231629699E1)); #2890=CARTESIAN_POINT('',(2.31325E1,3.141022319657E0,1.193930666795E1)); #2891=CARTESIAN_POINT('',(2.31325E1,3.035898384862E0,1.2E1)); #2893=DIRECTION('',(0.E0,1.E0,0.E0)); #2894=VECTOR('',#2893,2.035898384862E0); #2895=CARTESIAN_POINT('',(2.26175E1,1.E0,1.2E1)); #2896=LINE('',#2895,#2894); #2897=DIRECTION('',(0.E0,-1.E0,0.E0)); #2898=VECTOR('',#2897,2.035898384862E0); #2899=CARTESIAN_POINT('',(2.31325E1,3.035898384862E0,1.2E1)); #2900=LINE('',#2899,#2898); #2901=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1)); #2902=DIRECTION('',(0.E0,-1.E0,0.E0)); #2903=DIRECTION('',(1.E0,0.E0,0.E0)); #2904=AXIS2_PLACEMENT_3D('',#2901,#2902,#2903); #2906=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1)); #2907=DIRECTION('',(0.E0,-1.E0,0.E0)); #2908=DIRECTION('',(-1.E0,0.E0,0.E0)); #2909=AXIS2_PLACEMENT_3D('',#2906,#2907,#2908); #2911=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1)); #2912=DIRECTION('',(0.E0,-1.E0,0.E0)); #2913=DIRECTION('',(1.E0,0.E0,0.E0)); #2914=AXIS2_PLACEMENT_3D('',#2911,#2912,#2913); #2916=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1)); #2917=DIRECTION('',(0.E0,-1.E0,0.E0)); #2918=DIRECTION('',(-1.E0,0.E0,0.E0)); #2919=AXIS2_PLACEMENT_3D('',#2916,#2917,#2918); #2921=DIRECTION('',(0.E0,-1.E0,0.E0)); #2922=VECTOR('',#2921,1.E0); #2923=CARTESIAN_POINT('',(2.30675E1,1.E0,1.2E1)); #2924=LINE('',#2923,#2922); #2925=DIRECTION('',(0.E0,-1.E0,0.E0)); #2926=VECTOR('',#2925,1.E0); #2927=CARTESIAN_POINT('',(2.26825E1,1.E0,1.2E1)); #2928=LINE('',#2927,#2926); #2929=DIRECTION('',(0.E0,0.E0,-1.E0)); #2930=VECTOR('',#2929,5.E-1); #2931=CARTESIAN_POINT('',(2.15E1,6.65E0,1.E1)); #2932=LINE('',#2931,#2930); #2933=CARTESIAN_POINT('',(2.185E1,6.65E0,9.5E0)); #2934=DIRECTION('',(0.E0,0.E0,-1.E0)); #2935=DIRECTION('',(-1.E0,0.E0,0.E0)); #2936=AXIS2_PLACEMENT_3D('',#2933,#2934,#2935); #2938=DIRECTION('',(0.E0,0.E0,-1.E0)); #2939=VECTOR('',#2938,5.E-1); #2940=CARTESIAN_POINT('',(2.185E1,7.E0,1.E1)); #2941=LINE('',#2940,#2939); #2942=CARTESIAN_POINT('',(2.185E1,6.65E0,1.E1)); #2943=DIRECTION('',(0.E0,0.E0,1.E0)); #2944=DIRECTION('',(1.015061051086E-14,1.E0,0.E0)); #2945=AXIS2_PLACEMENT_3D('',#2942,#2943,#2944); #2947=DIRECTION('',(0.E0,0.E0,1.E0)); #2948=VECTOR('',#2947,5.E-1); #2949=CARTESIAN_POINT('',(2.115E1,2.E0,9.5E0)); #2950=LINE('',#2949,#2948); #2951=CARTESIAN_POINT('',(2.115E1,2.35E0,9.5E0)); #2952=DIRECTION('',(0.E0,0.E0,1.E0)); #2953=DIRECTION('',(0.E0,-1.E0,0.E0)); #2954=AXIS2_PLACEMENT_3D('',#2951,#2952,#2953); #2956=DIRECTION('',(0.E0,0.E0,1.E0)); #2957=VECTOR('',#2956,5.E-1); #2958=CARTESIAN_POINT('',(2.15E1,2.35E0,9.5E0)); #2959=LINE('',#2958,#2957); #2960=CARTESIAN_POINT('',(2.115E1,2.35E0,1.E1)); #2961=DIRECTION('',(0.E0,0.E0,-1.E0)); #2962=DIRECTION('',(1.E0,0.E0,0.E0)); #2963=AXIS2_PLACEMENT_3D('',#2960,#2961,#2962); #2965=DIRECTION('',(0.E0,0.E0,1.E0)); #2966=VECTOR('',#2965,5.E-1); #2967=CARTESIAN_POINT('',(1.95E1,2.35E0,9.5E0)); #2968=LINE('',#2967,#2966); #2969=CARTESIAN_POINT('',(1.985E1,2.35E0,9.5E0)); #2970=DIRECTION('',(0.E0,0.E0,1.E0)); #2971=DIRECTION('',(-1.E0,0.E0,0.E0)); #2972=AXIS2_PLACEMENT_3D('',#2969,#2970,#2971); #2974=DIRECTION('',(0.E0,0.E0,1.E0)); #2975=VECTOR('',#2974,5.E-1); #2976=CARTESIAN_POINT('',(1.985E1,2.E0,9.5E0)); #2977=LINE('',#2976,#2975); #2978=CARTESIAN_POINT('',(1.985E1,2.35E0,1.E1)); #2979=DIRECTION('',(0.E0,0.E0,-1.E0)); #2980=DIRECTION('',(1.015061051086E-14,-1.E0,0.E0)); #2981=AXIS2_PLACEMENT_3D('',#2978,#2979,#2980); #2983=DIRECTION('',(0.E0,0.E0,1.E0)); #2984=VECTOR('',#2983,5.E-1); #2985=CARTESIAN_POINT('',(1.985E1,9.5E0,9.5E0)); #2986=LINE('',#2985,#2984); #2987=CARTESIAN_POINT('',(1.985E1,9.15E0,9.5E0)); #2988=DIRECTION('',(0.E0,0.E0,1.E0)); #2989=DIRECTION('',(1.015061051086E-14,1.E0,0.E0)); #2990=AXIS2_PLACEMENT_3D('',#2987,#2988,#2989); #2992=DIRECTION('',(0.E0,0.E0,1.E0)); #2993=VECTOR('',#2992,5.E-1); #2994=CARTESIAN_POINT('',(1.95E1,9.15E0,9.5E0)); #2995=LINE('',#2994,#2993); #2996=CARTESIAN_POINT('',(1.985E1,9.15E0,1.E1)); #2997=DIRECTION('',(0.E0,0.E0,-1.E0)); #2998=DIRECTION('',(-1.E0,0.E0,0.E0)); #2999=AXIS2_PLACEMENT_3D('',#2996,#2997,#2998); #3001=DIRECTION('',(0.E0,0.E0,1.E0)); #3002=VECTOR('',#3001,5.E-1); #3003=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,9.5E0)); #3004=LINE('',#3003,#3002); #3005=CARTESIAN_POINT('',(2.104720076055E1,9.15E0,9.5E0)); #3006=DIRECTION('',(0.E0,0.E0,1.E0)); #3007=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0)); #3008=AXIS2_PLACEMENT_3D('',#3005,#3006,#3007); #3010=DIRECTION('',(0.E0,0.E0,1.E0)); #3011=VECTOR('',#3010,5.E-1); #3012=CARTESIAN_POINT('',(2.104720076055E1,9.5E0,9.5E0)); #3013=LINE('',#3012,#3011); #3014=CARTESIAN_POINT('',(2.104720076055E1,9.15E0,1.E1)); #3015=DIRECTION('',(0.E0,0.E0,-1.E0)); #3016=DIRECTION('',(0.E0,1.E0,0.E0)); #3017=AXIS2_PLACEMENT_3D('',#3014,#3015,#3016); #3019=DIRECTION('',(0.E0,0.E0,1.E0)); #3020=VECTOR('',#3019,5.E-1); #3021=CARTESIAN_POINT('',(2.204720076055E1,7.E0,9.5E0)); #3022=LINE('',#3021,#3020); #3023=CARTESIAN_POINT('',(2.204720076055E1,7.35E0,9.5E0)); #3024=DIRECTION('',(0.E0,0.E0,1.E0)); #3025=DIRECTION('',(0.E0,-1.E0,0.E0)); #3026=AXIS2_PLACEMENT_3D('',#3023,#3024,#3025); #3028=DIRECTION('',(0.E0,0.E0,1.E0)); #3029=VECTOR('',#3028,5.E-1); #3030=CARTESIAN_POINT('',(2.235315580719E1,7.519975025913E0,9.5E0)); #3031=LINE('',#3030,#3029); #3032=CARTESIAN_POINT('',(2.204720076055E1,7.35E0,1.E1)); #3033=DIRECTION('',(0.E0,0.E0,-1.E0)); #3034=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0)); #3035=AXIS2_PLACEMENT_3D('',#3032,#3033,#3034); #3037=DIRECTION('',(-1.E0,0.E0,0.E0)); #3038=VECTOR('',#3037,1.972007605460E-1); #3039=CARTESIAN_POINT('',(2.204720076055E1,7.E0,9.5E0)); #3040=LINE('',#3039,#3038); #3041=DIRECTION('',(0.E0,-1.E0,0.E0)); #3042=VECTOR('',#3041,4.3E0); #3043=CARTESIAN_POINT('',(2.15E1,6.65E0,9.5E0)); #3044=LINE('',#3043,#3042); #3045=DIRECTION('',(-1.E0,0.E0,0.E0)); #3046=VECTOR('',#3045,1.3E0); #3047=CARTESIAN_POINT('',(2.115E1,2.E0,9.5E0)); #3048=LINE('',#3047,#3046); #3049=DIRECTION('',(0.E0,1.E0,0.E0)); #3050=VECTOR('',#3049,6.8E0); #3051=CARTESIAN_POINT('',(1.95E1,2.35E0,9.5E0)); #3052=LINE('',#3051,#3050); #3053=DIRECTION('',(1.E0,0.E0,0.E0)); #3054=VECTOR('',#3053,1.197200760546E0); #3055=CARTESIAN_POINT('',(1.985E1,9.5E0,9.5E0)); #3056=LINE('',#3055,#3054); #3057=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0)); #3058=VECTOR('',#3057,2.059126028197E0); #3059=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,9.5E0)); #3060=LINE('',#3059,#3058); #3061=DIRECTION('',(0.E0,0.E0,1.E0)); #3062=VECTOR('',#3061,2.5E-1); #3063=CARTESIAN_POINT('',(2.00925E1,1.05E1,8.E0)); #3064=LINE('',#3063,#3062); #3065=DIRECTION('',(0.E0,0.E0,1.E0)); #3066=VECTOR('',#3065,2.5E-1); #3067=CARTESIAN_POINT('',(2.02825E1,1.05E1,8.E0)); #3068=LINE('',#3067,#3066); #3069=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.25E0)); #3070=DIRECTION('',(0.E0,0.E0,-1.E0)); #3071=DIRECTION('',(-1.E0,0.E0,0.E0)); #3072=AXIS2_PLACEMENT_3D('',#3069,#3070,#3071); #3074=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.25E0)); #3075=DIRECTION('',(0.E0,0.E0,-1.E0)); #3076=DIRECTION('',(1.E0,0.E0,0.E0)); #3077=AXIS2_PLACEMENT_3D('',#3074,#3075,#3076); #3079=DIRECTION('',(0.E0,0.E0,1.E0)); #3080=VECTOR('',#3079,2.5E-1); #3081=CARTESIAN_POINT('',(1.9655E1,1.00625E1,8.E0)); #3082=LINE('',#3081,#3080); #3083=DIRECTION('',(0.E0,0.E0,1.E0)); #3084=VECTOR('',#3083,2.5E-1); #3085=CARTESIAN_POINT('',(1.9845E1,1.00625E1,8.E0)); #3086=LINE('',#3085,#3084); #3087=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.25E0)); #3088=DIRECTION('',(0.E0,0.E0,-1.E0)); #3089=DIRECTION('',(-1.E0,0.E0,0.E0)); #3090=AXIS2_PLACEMENT_3D('',#3087,#3088,#3089); #3092=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.25E0)); #3093=DIRECTION('',(0.E0,0.E0,-1.E0)); #3094=DIRECTION('',(1.E0,0.E0,0.E0)); #3095=AXIS2_PLACEMENT_3D('',#3092,#3093,#3094); #3097=DIRECTION('',(0.E0,0.E0,1.E0)); #3098=VECTOR('',#3097,2.5E-1); #3099=CARTESIAN_POINT('',(4.345E0,1.00625E1,8.E0)); #3100=LINE('',#3099,#3098); #3101=DIRECTION('',(0.E0,0.E0,1.E0)); #3102=VECTOR('',#3101,2.5E-1); #3103=CARTESIAN_POINT('',(4.155E0,1.00625E1,8.E0)); #3104=LINE('',#3103,#3102); #3105=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.25E0)); #3106=DIRECTION('',(0.E0,0.E0,1.E0)); #3107=DIRECTION('',(1.E0,0.E0,0.E0)); #3108=AXIS2_PLACEMENT_3D('',#3105,#3106,#3107); #3110=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.25E0)); #3111=DIRECTION('',(0.E0,0.E0,1.E0)); #3112=DIRECTION('',(-1.E0,0.E0,0.E0)); #3113=AXIS2_PLACEMENT_3D('',#3110,#3111,#3112); #3115=DIRECTION('',(0.E0,0.E0,1.E0)); #3116=VECTOR('',#3115,2.5E-1); #3117=CARTESIAN_POINT('',(3.9075E0,1.05E1,8.E0)); #3118=LINE('',#3117,#3116); #3119=DIRECTION('',(0.E0,0.E0,1.E0)); #3120=VECTOR('',#3119,2.5E-1); #3121=CARTESIAN_POINT('',(3.7175E0,1.05E1,8.E0)); #3122=LINE('',#3121,#3120); #3123=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.25E0)); #3124=DIRECTION('',(0.E0,0.E0,1.E0)); #3125=DIRECTION('',(1.E0,0.E0,0.E0)); #3126=AXIS2_PLACEMENT_3D('',#3123,#3124,#3125); #3128=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.25E0)); #3129=DIRECTION('',(0.E0,0.E0,1.E0)); #3130=DIRECTION('',(-1.E0,0.E0,0.E0)); #3131=AXIS2_PLACEMENT_3D('',#3128,#3129,#3130); #3133=DIRECTION('',(0.E0,0.E0,1.E0)); #3134=VECTOR('',#3133,2.5E-1); #3135=CARTESIAN_POINT('',(4.345E0,1.09375E1,8.E0)); #3136=LINE('',#3135,#3134); #3137=DIRECTION('',(0.E0,0.E0,1.E0)); #3138=VECTOR('',#3137,2.5E-1); #3139=CARTESIAN_POINT('',(4.155E0,1.09375E1,8.E0)); #3140=LINE('',#3139,#3138); #3141=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.25E0)); #3142=DIRECTION('',(0.E0,0.E0,1.E0)); #3143=DIRECTION('',(1.E0,0.E0,0.E0)); #3144=AXIS2_PLACEMENT_3D('',#3141,#3142,#3143); #3146=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.25E0)); #3147=DIRECTION('',(0.E0,0.E0,1.E0)); #3148=DIRECTION('',(-1.E0,0.E0,0.E0)); #3149=AXIS2_PLACEMENT_3D('',#3146,#3147,#3148); #3151=DIRECTION('',(0.E0,0.E0,1.E0)); #3152=VECTOR('',#3151,5.E-1); #3153=CARTESIAN_POINT('',(3.75E0,2.E0,8.E0)); #3154=LINE('',#3153,#3152); #3155=CARTESIAN_POINT('',(3.75E0,2.75E0,8.E0)); #3156=DIRECTION('',(0.E0,0.E0,1.E0)); #3157=DIRECTION('',(0.E0,-1.E0,0.E0)); #3158=AXIS2_PLACEMENT_3D('',#3155,#3156,#3157); #3160=DIRECTION('',(0.E0,0.E0,1.E0)); #3161=VECTOR('',#3160,5.E-1); #3162=CARTESIAN_POINT('',(4.5E0,2.75E0,8.E0)); #3163=LINE('',#3162,#3161); #3164=CARTESIAN_POINT('',(3.75E0,2.75E0,8.5E0)); #3165=DIRECTION('',(0.E0,0.E0,-1.E0)); #3166=DIRECTION('',(1.E0,0.E0,0.E0)); #3167=AXIS2_PLACEMENT_3D('',#3164,#3165,#3166); #3169=DIRECTION('',(0.E0,0.E0,1.E0)); #3170=VECTOR('',#3169,5.E-1); #3171=CARTESIAN_POINT('',(4.5E0,8.75E0,8.E0)); #3172=LINE('',#3171,#3170); #3173=CARTESIAN_POINT('',(3.75E0,8.75E0,8.E0)); #3174=DIRECTION('',(0.E0,0.E0,1.E0)); #3175=DIRECTION('',(1.E0,0.E0,0.E0)); #3176=AXIS2_PLACEMENT_3D('',#3173,#3174,#3175); #3178=DIRECTION('',(0.E0,0.E0,1.E0)); #3179=VECTOR('',#3178,5.E-1); #3180=CARTESIAN_POINT('',(3.75E0,9.5E0,8.E0)); #3181=LINE('',#3180,#3179); #3182=CARTESIAN_POINT('',(3.75E0,8.75E0,8.5E0)); #3183=DIRECTION('',(0.E0,0.E0,-1.E0)); #3184=DIRECTION('',(0.E0,1.E0,0.E0)); #3185=AXIS2_PLACEMENT_3D('',#3182,#3183,#3184); #3187=DIRECTION('',(0.E0,0.E0,1.E0)); #3188=VECTOR('',#3187,5.E-1); #3189=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.E0)); #3190=LINE('',#3189,#3188); #3191=CARTESIAN_POINT('',(3.188160579053E0,8.75E0,8.E0)); #3192=DIRECTION('',(0.E0,0.E0,1.E0)); #3193=DIRECTION('',(0.E0,1.E0,0.E0)); #3194=AXIS2_PLACEMENT_3D('',#3191,#3192,#3193); #3196=DIRECTION('',(0.E0,0.E0,1.E0)); #3197=VECTOR('',#3196,5.E-1); #3198=CARTESIAN_POINT('',(2.532542621962E0,9.114232198384E0,8.E0)); #3199=LINE('',#3198,#3197); #3200=CARTESIAN_POINT('',(3.188160579053E0,8.75E0,8.5E0)); #3201=DIRECTION('',(0.E0,0.E0,-1.E0)); #3202=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #3203=AXIS2_PLACEMENT_3D('',#3200,#3201,#3202); #3205=DIRECTION('',(0.E0,0.E0,1.E0)); #3206=VECTOR('',#3205,5.E-1); #3207=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.E0)); #3208=LINE('',#3207,#3206); #3209=CARTESIAN_POINT('',(-1.451727542799E-1,2.75E0,8.E0)); #3210=DIRECTION('',(0.E0,0.E0,1.E0)); #3211=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #3212=AXIS2_PLACEMENT_3D('',#3209,#3210,#3211); #3214=DIRECTION('',(0.E0,0.E0,1.E0)); #3215=VECTOR('',#3214,5.E-1); #3216=CARTESIAN_POINT('',(-1.451727542799E-1,2.E0,8.E0)); #3217=LINE('',#3216,#3215); #3218=CARTESIAN_POINT('',(-1.451727542799E-1,2.75E0,8.5E0)); #3219=DIRECTION('',(0.E0,0.E0,-1.E0)); #3220=DIRECTION('',(0.E0,-1.E0,0.E0)); #3221=AXIS2_PLACEMENT_3D('',#3218,#3219,#3220); #3223=DIRECTION('',(0.E0,-1.E0,0.E0)); #3224=VECTOR('',#3223,6.E0); #3225=CARTESIAN_POINT('',(4.5E0,8.75E0,8.5E0)); #3226=LINE('',#3225,#3224); #3227=DIRECTION('',(1.E0,0.E0,0.E0)); #3228=VECTOR('',#3227,5.618394209466E-1); #3229=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.5E0)); #3230=LINE('',#3229,#3228); #3231=DIRECTION('',(4.856429311786E-1,8.741572761215E-1,0.E0)); #3232=VECTOR('',#3231,6.863753427325E0); #3233=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.5E0)); #3234=LINE('',#3233,#3232); #3235=DIRECTION('',(-1.E0,0.E0,0.E0)); #3236=VECTOR('',#3235,3.895172754280E0); #3237=CARTESIAN_POINT('',(3.75E0,2.E0,8.5E0)); #3238=LINE('',#3237,#3236); #3239=DIRECTION('',(0.E0,0.E0,-1.E0)); #3240=VECTOR('',#3239,5.E-1); #3241=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.5E0)); #3242=LINE('',#3241,#3240); #3243=CARTESIAN_POINT('',(2.414517275428E1,2.75E0,8.5E0)); #3244=DIRECTION('',(0.E0,0.E0,-1.E0)); #3245=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0)); #3246=AXIS2_PLACEMENT_3D('',#3243,#3244,#3245); #3248=DIRECTION('',(0.E0,0.E0,-1.E0)); #3249=VECTOR('',#3248,5.E-1); #3250=CARTESIAN_POINT('',(2.414517275428E1,2.E0,8.5E0)); #3251=LINE('',#3250,#3249); #3252=CARTESIAN_POINT('',(2.414517275428E1,2.75E0,8.E0)); #3253=DIRECTION('',(0.E0,0.E0,1.E0)); #3254=DIRECTION('',(0.E0,-1.E0,0.E0)); #3255=AXIS2_PLACEMENT_3D('',#3252,#3253,#3254); #3257=DIRECTION('',(1.E0,0.E0,0.E0)); #3258=VECTOR('',#3257,3.895172754280E0); #3259=CARTESIAN_POINT('',(2.025E1,2.E0,8.5E0)); #3260=LINE('',#3259,#3258); #3261=DIRECTION('',(-4.856429311786E-1,8.741572761215E-1,0.E0)); #3262=VECTOR('',#3261,6.863753427325E0); #3263=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.5E0)); #3264=LINE('',#3263,#3262); #3265=DIRECTION('',(-1.E0,0.E0,0.E0)); #3266=VECTOR('',#3265,5.618394209466E-1); #3267=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.5E0)); #3268=LINE('',#3267,#3266); #3269=DIRECTION('',(0.E0,-1.E0,0.E0)); #3270=VECTOR('',#3269,6.E0); #3271=CARTESIAN_POINT('',(1.95E1,8.75E0,8.5E0)); #3272=LINE('',#3271,#3270); #3273=DIRECTION('',(0.E0,0.E0,-1.E0)); #3274=VECTOR('',#3273,5.E-1); #3275=CARTESIAN_POINT('',(2.025E1,2.E0,8.5E0)); #3276=LINE('',#3275,#3274); #3277=CARTESIAN_POINT('',(2.025E1,2.75E0,8.5E0)); #3278=DIRECTION('',(0.E0,0.E0,-1.E0)); #3279=DIRECTION('',(0.E0,-1.E0,0.E0)); #3280=AXIS2_PLACEMENT_3D('',#3277,#3278,#3279); #3282=DIRECTION('',(0.E0,0.E0,-1.E0)); #3283=VECTOR('',#3282,5.E-1); #3284=CARTESIAN_POINT('',(1.95E1,2.75E0,8.5E0)); #3285=LINE('',#3284,#3283); #3286=CARTESIAN_POINT('',(2.025E1,2.75E0,8.E0)); #3287=DIRECTION('',(0.E0,0.E0,1.E0)); #3288=DIRECTION('',(-1.E0,0.E0,0.E0)); #3289=AXIS2_PLACEMENT_3D('',#3286,#3287,#3288); #3291=DIRECTION('',(0.E0,0.E0,-1.E0)); #3292=VECTOR('',#3291,5.E-1); #3293=CARTESIAN_POINT('',(1.95E1,8.75E0,8.5E0)); #3294=LINE('',#3293,#3292); #3295=CARTESIAN_POINT('',(2.025E1,8.75E0,8.5E0)); #3296=DIRECTION('',(0.E0,0.E0,-1.E0)); #3297=DIRECTION('',(-1.E0,0.E0,0.E0)); #3298=AXIS2_PLACEMENT_3D('',#3295,#3296,#3297); #3300=DIRECTION('',(0.E0,0.E0,-1.E0)); #3301=VECTOR('',#3300,5.E-1); #3302=CARTESIAN_POINT('',(2.025E1,9.5E0,8.5E0)); #3303=LINE('',#3302,#3301); #3304=CARTESIAN_POINT('',(2.025E1,8.75E0,8.E0)); #3305=DIRECTION('',(0.E0,0.E0,1.E0)); #3306=DIRECTION('',(0.E0,1.E0,0.E0)); #3307=AXIS2_PLACEMENT_3D('',#3304,#3305,#3306); #3309=DIRECTION('',(0.E0,0.E0,-1.E0)); #3310=VECTOR('',#3309,5.E-1); #3311=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.5E0)); #3312=LINE('',#3311,#3310); #3313=CARTESIAN_POINT('',(2.081183942095E1,8.75E0,8.5E0)); #3314=DIRECTION('',(0.E0,0.E0,-1.E0)); #3315=DIRECTION('',(0.E0,1.E0,0.E0)); #3316=AXIS2_PLACEMENT_3D('',#3313,#3314,#3315); #3318=DIRECTION('',(0.E0,0.E0,-1.E0)); #3319=VECTOR('',#3318,5.E-1); #3320=CARTESIAN_POINT('',(2.146745737804E1,9.114232198384E0,8.5E0)); #3321=LINE('',#3320,#3319); #3322=CARTESIAN_POINT('',(2.081183942095E1,8.75E0,8.E0)); #3323=DIRECTION('',(0.E0,0.E0,1.E0)); #3324=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0)); #3325=AXIS2_PLACEMENT_3D('',#3322,#3323,#3324); #3327=DIRECTION('',(0.E0,1.E0,0.E0)); #3328=VECTOR('',#3327,6.875E-1); #3329=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1)); #3330=LINE('',#3329,#3328); #3331=DIRECTION('',(0.E0,1.E0,0.E0)); #3332=VECTOR('',#3331,6.875E-1); #3333=CARTESIAN_POINT('',(7.5E0,0.E0,1.8125E0)); #3334=LINE('',#3333,#3332); #3335=DIRECTION('',(0.E0,1.E0,0.E0)); #3336=VECTOR('',#3335,6.875E-1); #3337=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0)); #3338=LINE('',#3337,#3336); #3339=DIRECTION('',(0.E0,1.E0,0.E0)); #3340=VECTOR('',#3339,6.875E-1); #3341=CARTESIAN_POINT('',(1.05E1,0.E0,6.875E-1)); #3342=LINE('',#3341,#3340); #3343=DIRECTION('',(1.E0,0.E0,0.E0)); #3344=VECTOR('',#3343,3.E0); #3345=CARTESIAN_POINT('',(7.5E0,6.875E-1,6.875E-1)); #3346=LINE('',#3345,#3344); #3347=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.25E0)); #3348=DIRECTION('',(0.E0,-1.E0,0.E0)); #3349=DIRECTION('',(0.E0,0.E0,1.E0)); #3350=AXIS2_PLACEMENT_3D('',#3347,#3348,#3349); #3352=DIRECTION('',(-1.E0,0.E0,0.E0)); #3353=VECTOR('',#3352,3.E0); #3354=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.8125E0)); #3355=LINE('',#3354,#3353); #3356=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.25E0)); #3357=DIRECTION('',(0.E0,-1.E0,0.E0)); #3358=DIRECTION('',(0.E0,0.E0,-1.E0)); #3359=AXIS2_PLACEMENT_3D('',#3356,#3357,#3358); #3361=CARTESIAN_POINT('',(1.61E0,6.875E-1,4.5E0)); #3362=DIRECTION('',(0.E0,-1.E0,0.E0)); #3363=DIRECTION('',(8.910741301059E-1,0.E0,4.538577912254E-1)); #3364=AXIS2_PLACEMENT_3D('',#3361,#3362,#3363); #3366=CARTESIAN_POINT('',(7.5E0,6.875E-1,7.5E0)); #3367=DIRECTION('',(0.E0,1.E0,0.E0)); #3368=DIRECTION('',(-4.496088413988E-1,0.E0,-8.932255536739E-1)); #3369=AXIS2_PLACEMENT_3D('',#3366,#3367,#3368); #3371=CARTESIAN_POINT('',(4.553039342392E0,6.875E-1,1.645354088550E0)); #3372=DIRECTION('',(0.E0,-1.E0,0.E0)); #3373=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #3374=AXIS2_PLACEMENT_3D('',#3371,#3372,#3373); #3376=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #3377=VECTOR('',#3376,4.263248410977E0); #3378=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,4.046865146430E0)); #3379=LINE('',#3378,#3377); #3380=DIRECTION('',(0.E0,1.E0,0.E0)); #3381=VECTOR('',#3380,6.875E-1); #3382=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,4.046865146430E0)); #3383=LINE('',#3382,#3381); #3384=CARTESIAN_POINT('',(1.455736763592E0,0.E0,4.577195232320E0)); #3385=DIRECTION('',(0.E0,1.E0,0.E0)); #3386=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #3387=AXIS2_PLACEMENT_3D('',#3384,#3385,#3386); #3389=DIRECTION('',(0.E0,1.E0,0.E0)); #3390=VECTOR('',#3389,6.875E-1); #3391=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,4.912826677187E0)); #3392=LINE('',#3391,#3390); #3393=CARTESIAN_POINT('',(1.455736763592E0,6.875E-1,4.577195232320E0)); #3394=DIRECTION('',(0.E0,-1.E0,0.E0)); #3395=DIRECTION('',(-8.942796313519E-1,0.E0,4.475085931567E-1)); #3396=AXIS2_PLACEMENT_3D('',#3393,#3394,#3395); #3398=DIRECTION('',(0.E0,1.E0,0.E0)); #3399=VECTOR('',#3398,6.875E-1); #3400=CARTESIAN_POINT('',(3.939978538987E0,0.E0,1.032293285145E0)); #3401=LINE('',#3400,#3399); #3402=DIRECTION('',(0.E0,1.E0,0.E0)); #3403=VECTOR('',#3402,6.875E-1); #3404=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.419779663480E0)); #3405=LINE('',#3404,#3403); #3406=DIRECTION('',(0.E0,1.E0,0.E0)); #3407=VECTOR('',#3406,6.875E-1); #3408=CARTESIAN_POINT('',(2.432015885023E0,0.E0,4.918683812405E0)); #3409=LINE('',#3408,#3407); #3410=DIRECTION('',(0.E0,-1.E0,0.E0)); #3411=VECTOR('',#3410,6.875E-1); #3412=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.815E0)); #3413=LINE('',#3412,#3411); #3414=CARTESIAN_POINT('',(-1.85E-1,0.E0,7.815E0)); #3415=DIRECTION('',(0.E0,-1.E0,0.E0)); #3416=DIRECTION('',(1.E0,0.E0,0.E0)); #3417=AXIS2_PLACEMENT_3D('',#3414,#3415,#3416); #3419=DIRECTION('',(0.E0,-1.E0,0.E0)); #3420=VECTOR('',#3419,6.875E-1); #3421=CARTESIAN_POINT('',(-1.85E-1,6.875E-1,8.69E0)); #3422=LINE('',#3421,#3420); #3423=CARTESIAN_POINT('',(-1.85E-1,6.875E-1,7.815E0)); #3424=DIRECTION('',(0.E0,1.E0,0.E0)); #3425=DIRECTION('',(0.E0,0.E0,1.E0)); #3426=AXIS2_PLACEMENT_3D('',#3423,#3424,#3425); #3428=DIRECTION('',(1.E0,0.E0,0.E0)); #3429=VECTOR('',#3428,7.5E-1); #3430=CARTESIAN_POINT('',(2.6875E0,6.875E-1,8.69E0)); #3431=LINE('',#3430,#3429); #3432=DIRECTION('',(0.E0,0.E0,1.E0)); #3433=VECTOR('',#3432,3.15E-1); #3434=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.5E0)); #3435=LINE('',#3434,#3433); #3436=CARTESIAN_POINT('',(1.25125E0,6.875E-1,7.5E0)); #3437=DIRECTION('',(0.E0,-1.E0,0.E0)); #3438=DIRECTION('',(-1.E0,0.E0,0.E0)); #3439=AXIS2_PLACEMENT_3D('',#3436,#3437,#3438); #3441=DIRECTION('',(0.E0,0.E0,-1.E0)); #3442=VECTOR('',#3441,3.15E-1); #3443=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.815E0)); #3444=LINE('',#3443,#3442); #3445=DIRECTION('',(1.E0,0.E0,0.E0)); #3446=VECTOR('',#3445,2.525E-1); #3447=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,8.69E0)); #3448=LINE('',#3447,#3446); #3449=DIRECTION('',(0.E0,0.E0,-1.E0)); #3450=VECTOR('',#3449,8.1E-1); #3451=CARTESIAN_POINT('',(-1.3125E0,6.875E-1,1.0375E1)); #3452=LINE('',#3451,#3450); #3453=DIRECTION('',(-1.E0,0.E0,0.E0)); #3454=VECTOR('',#3453,3.875E0); #3455=CARTESIAN_POINT('',(3.4375E0,6.875E-1,1.125E1)); #3456=LINE('',#3455,#3454); #3457=DIRECTION('',(0.E0,0.E0,1.E0)); #3458=VECTOR('',#3457,8.1E-1); #3459=CARTESIAN_POINT('',(4.3125E0,6.875E-1,9.565E0)); #3460=LINE('',#3459,#3458); #3461=DIRECTION('',(0.E0,-1.E0,0.E0)); #3462=VECTOR('',#3461,6.875E-1); #3463=CARTESIAN_POINT('',(2.6875E0,6.875E-1,8.69E0)); #3464=LINE('',#3463,#3462); #3465=CARTESIAN_POINT('',(2.6875E0,0.E0,7.815E0)); #3466=DIRECTION('',(0.E0,-1.E0,0.E0)); #3467=DIRECTION('',(0.E0,0.E0,1.E0)); #3468=AXIS2_PLACEMENT_3D('',#3465,#3466,#3467); #3470=DIRECTION('',(0.E0,-1.E0,0.E0)); #3471=VECTOR('',#3470,6.875E-1); #3472=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.815E0)); #3473=LINE('',#3472,#3471); #3474=CARTESIAN_POINT('',(2.6875E0,6.875E-1,7.815E0)); #3475=DIRECTION('',(0.E0,1.E0,0.E0)); #3476=DIRECTION('',(-1.E0,0.E0,0.E0)); #3477=AXIS2_PLACEMENT_3D('',#3474,#3475,#3476); #3479=DIRECTION('',(0.E0,1.E0,0.E0)); #3480=VECTOR('',#3479,6.875E-1); #3481=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0)); #3482=LINE('',#3481,#3480); #3483=DIRECTION('',(0.E0,1.E0,0.E0)); #3484=VECTOR('',#3483,6.875E-1); #3485=CARTESIAN_POINT('',(6.9E-1,0.E0,7.5E0)); #3486=LINE('',#3485,#3484); #3487=DIRECTION('',(0.E0,1.E0,0.E0)); #3488=VECTOR('',#3487,6.875E-1); #3489=CARTESIAN_POINT('',(4.3125E0,0.E0,9.565E0)); #3490=LINE('',#3489,#3488); #3491=CARTESIAN_POINT('',(3.4375E0,0.E0,9.565E0)); #3492=DIRECTION('',(0.E0,1.E0,0.E0)); #3493=DIRECTION('',(1.E0,0.E0,0.E0)); #3494=AXIS2_PLACEMENT_3D('',#3491,#3492,#3493); #3496=DIRECTION('',(0.E0,1.E0,0.E0)); #3497=VECTOR('',#3496,6.875E-1); #3498=CARTESIAN_POINT('',(3.4375E0,0.E0,8.69E0)); #3499=LINE('',#3498,#3497); #3500=CARTESIAN_POINT('',(3.4375E0,6.875E-1,9.565E0)); #3501=DIRECTION('',(0.E0,-1.E0,0.E0)); #3502=DIRECTION('',(0.E0,0.E0,-1.E0)); #3503=AXIS2_PLACEMENT_3D('',#3500,#3501,#3502); #3505=DIRECTION('',(0.E0,1.E0,0.E0)); #3506=VECTOR('',#3505,6.875E-1); #3507=CARTESIAN_POINT('',(3.4375E0,0.E0,1.125E1)); #3508=LINE('',#3507,#3506); #3509=CARTESIAN_POINT('',(3.4375E0,0.E0,1.0375E1)); #3510=DIRECTION('',(0.E0,1.E0,0.E0)); #3511=DIRECTION('',(0.E0,0.E0,1.E0)); #3512=AXIS2_PLACEMENT_3D('',#3509,#3510,#3511); #3514=DIRECTION('',(0.E0,1.E0,0.E0)); #3515=VECTOR('',#3514,6.875E-1); #3516=CARTESIAN_POINT('',(4.3125E0,0.E0,1.0375E1)); #3517=LINE('',#3516,#3515); #3518=CARTESIAN_POINT('',(3.4375E0,6.875E-1,1.0375E1)); #3519=DIRECTION('',(0.E0,-1.E0,0.E0)); #3520=DIRECTION('',(1.E0,0.E0,0.E0)); #3521=AXIS2_PLACEMENT_3D('',#3518,#3519,#3520); #3523=DIRECTION('',(0.E0,1.E0,0.E0)); #3524=VECTOR('',#3523,6.875E-1); #3525=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.0375E1)); #3526=LINE('',#3525,#3524); #3527=CARTESIAN_POINT('',(-4.375E-1,0.E0,1.0375E1)); #3528=DIRECTION('',(0.E0,1.E0,0.E0)); #3529=DIRECTION('',(-1.E0,0.E0,0.E0)); #3530=AXIS2_PLACEMENT_3D('',#3527,#3528,#3529); #3532=DIRECTION('',(0.E0,1.E0,0.E0)); #3533=VECTOR('',#3532,6.875E-1); #3534=CARTESIAN_POINT('',(-4.375E-1,0.E0,1.125E1)); #3535=LINE('',#3534,#3533); #3536=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,1.0375E1)); #3537=DIRECTION('',(0.E0,-1.E0,0.E0)); #3538=DIRECTION('',(0.E0,0.E0,1.E0)); #3539=AXIS2_PLACEMENT_3D('',#3536,#3537,#3538); #3541=DIRECTION('',(0.E0,1.E0,0.E0)); #3542=VECTOR('',#3541,6.875E-1); #3543=CARTESIAN_POINT('',(-4.375E-1,0.E0,8.69E0)); #3544=LINE('',#3543,#3542); #3545=CARTESIAN_POINT('',(-4.375E-1,0.E0,9.565E0)); #3546=DIRECTION('',(0.E0,1.E0,0.E0)); #3547=DIRECTION('',(0.E0,0.E0,-1.E0)); #3548=AXIS2_PLACEMENT_3D('',#3545,#3546,#3547); #3550=DIRECTION('',(0.E0,1.E0,0.E0)); #3551=VECTOR('',#3550,6.875E-1); #3552=CARTESIAN_POINT('',(-1.3125E0,0.E0,9.565E0)); #3553=LINE('',#3552,#3551); #3554=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,9.565E0)); #3555=DIRECTION('',(0.E0,-1.E0,0.E0)); #3556=DIRECTION('',(-1.E0,0.E0,0.E0)); #3557=AXIS2_PLACEMENT_3D('',#3554,#3555,#3556); #3559=DIRECTION('',(0.E0,1.E0,0.E0)); #3560=VECTOR('',#3559,6.875E-1); #3561=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1)); #3562=LINE('',#3561,#3560); #3563=DIRECTION('',(0.E0,1.E0,0.E0)); #3564=VECTOR('',#3563,6.875E-1); #3565=CARTESIAN_POINT('',(1.8125E0,0.E0,1.65E1)); #3566=LINE('',#3565,#3564); #3567=DIRECTION('',(0.E0,1.E0,0.E0)); #3568=VECTOR('',#3567,6.875E-1); #3569=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1)); #3570=LINE('',#3569,#3568); #3571=DIRECTION('',(0.E0,1.E0,0.E0)); #3572=VECTOR('',#3571,6.875E-1); #3573=CARTESIAN_POINT('',(6.875E-1,0.E0,1.35E1)); #3574=LINE('',#3573,#3572); #3575=DIRECTION('',(0.E0,0.E0,-1.E0)); #3576=VECTOR('',#3575,3.E0); #3577=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.65E1)); #3578=LINE('',#3577,#3576); #3579=CARTESIAN_POINT('',(1.25E0,6.875E-1,1.65E1)); #3580=DIRECTION('',(0.E0,-1.E0,0.E0)); #3581=DIRECTION('',(1.E0,0.E0,0.E0)); #3582=AXIS2_PLACEMENT_3D('',#3579,#3580,#3581); #3584=DIRECTION('',(0.E0,0.E0,1.E0)); #3585=VECTOR('',#3584,3.E0); #3586=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.35E1)); #3587=LINE('',#3586,#3585); #3588=CARTESIAN_POINT('',(1.25E0,6.875E-1,1.35E1)); #3589=DIRECTION('',(0.E0,-1.E0,0.E0)); #3590=DIRECTION('',(-1.E0,0.E0,0.E0)); #3591=AXIS2_PLACEMENT_3D('',#3588,#3589,#3590); #3593=DIRECTION('',(0.E0,1.E0,0.E0)); #3594=VECTOR('',#3593,6.875E-1); #3595=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1)); #3596=LINE('',#3595,#3594); #3597=DIRECTION('',(0.E0,1.E0,0.E0)); #3598=VECTOR('',#3597,6.875E-1); #3599=CARTESIAN_POINT('',(1.8125E0,0.E0,2.25E1)); #3600=LINE('',#3599,#3598); #3601=DIRECTION('',(0.E0,1.E0,0.E0)); #3602=VECTOR('',#3601,6.875E-1); #3603=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1)); #3604=LINE('',#3603,#3602); #3605=DIRECTION('',(0.E0,1.E0,0.E0)); #3606=VECTOR('',#3605,6.875E-1); #3607=CARTESIAN_POINT('',(6.875E-1,0.E0,1.95E1)); #3608=LINE('',#3607,#3606); #3609=DIRECTION('',(0.E0,0.E0,-1.E0)); #3610=VECTOR('',#3609,3.E0); #3611=CARTESIAN_POINT('',(6.875E-1,6.875E-1,2.25E1)); #3612=LINE('',#3611,#3610); #3613=CARTESIAN_POINT('',(1.25E0,6.875E-1,2.25E1)); #3614=DIRECTION('',(0.E0,-1.E0,0.E0)); #3615=DIRECTION('',(1.E0,0.E0,0.E0)); #3616=AXIS2_PLACEMENT_3D('',#3613,#3614,#3615); #3618=DIRECTION('',(0.E0,0.E0,1.E0)); #3619=VECTOR('',#3618,3.E0); #3620=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.95E1)); #3621=LINE('',#3620,#3619); #3622=CARTESIAN_POINT('',(1.25E0,6.875E-1,1.95E1)); #3623=DIRECTION('',(0.E0,-1.E0,0.E0)); #3624=DIRECTION('',(-1.E0,0.E0,0.E0)); #3625=AXIS2_PLACEMENT_3D('',#3622,#3623,#3624); #3627=DIRECTION('',(0.E0,1.E0,0.E0)); #3628=VECTOR('',#3627,6.875E-1); #3629=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0)); #3630=LINE('',#3629,#3628); #3631=DIRECTION('',(0.E0,1.E0,0.E0)); #3632=VECTOR('',#3631,6.875E-1); #3633=CARTESIAN_POINT('',(7.5E0,0.E0,9.5E0)); #3634=LINE('',#3633,#3632); #3635=DIRECTION('',(0.E0,1.E0,0.E0)); #3636=VECTOR('',#3635,6.875E-1); #3637=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0)); #3638=LINE('',#3637,#3636); #3639=DIRECTION('',(0.E0,1.E0,0.E0)); #3640=VECTOR('',#3639,6.875E-1); #3641=CARTESIAN_POINT('',(1.05E1,0.E0,8.5E0)); #3642=LINE('',#3641,#3640); #3643=DIRECTION('',(1.E0,0.E0,0.E0)); #3644=VECTOR('',#3643,3.E0); #3645=CARTESIAN_POINT('',(7.5E0,6.875E-1,8.5E0)); #3646=LINE('',#3645,#3644); #3647=CARTESIAN_POINT('',(7.5E0,6.875E-1,9.E0)); #3648=DIRECTION('',(0.E0,-1.E0,0.E0)); #3649=DIRECTION('',(0.E0,0.E0,1.E0)); #3650=AXIS2_PLACEMENT_3D('',#3647,#3648,#3649); #3652=DIRECTION('',(-1.E0,0.E0,0.E0)); #3653=VECTOR('',#3652,3.E0); #3654=CARTESIAN_POINT('',(1.05E1,6.875E-1,9.5E0)); #3655=LINE('',#3654,#3653); #3656=CARTESIAN_POINT('',(1.05E1,6.875E-1,9.E0)); #3657=DIRECTION('',(0.E0,-1.E0,0.E0)); #3658=DIRECTION('',(0.E0,0.E0,-1.E0)); #3659=AXIS2_PLACEMENT_3D('',#3656,#3657,#3658); #3661=DIRECTION('',(0.E0,1.E0,0.E0)); #3662=VECTOR('',#3661,6.875E-1); #3663=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1)); #3664=LINE('',#3663,#3662); #3665=DIRECTION('',(0.E0,1.E0,0.E0)); #3666=VECTOR('',#3665,6.875E-1); #3667=CARTESIAN_POINT('',(7.5E0,0.E0,1.84375E1)); #3668=LINE('',#3667,#3666); #3669=DIRECTION('',(0.E0,1.E0,0.E0)); #3670=VECTOR('',#3669,6.875E-1); #3671=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1)); #3672=LINE('',#3671,#3670); #3673=DIRECTION('',(0.E0,1.E0,0.E0)); #3674=VECTOR('',#3673,6.875E-1); #3675=CARTESIAN_POINT('',(1.05E1,0.E0,1.75625E1)); #3676=LINE('',#3675,#3674); #3677=DIRECTION('',(1.E0,0.E0,0.E0)); #3678=VECTOR('',#3677,3.E0); #3679=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.75625E1)); #3680=LINE('',#3679,#3678); #3681=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.8E1)); #3682=DIRECTION('',(0.E0,-1.E0,0.E0)); #3683=DIRECTION('',(0.E0,0.E0,1.E0)); #3684=AXIS2_PLACEMENT_3D('',#3681,#3682,#3683); #3686=DIRECTION('',(-1.E0,0.E0,0.E0)); #3687=VECTOR('',#3686,3.E0); #3688=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.84375E1)); #3689=LINE('',#3688,#3687); #3690=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.8E1)); #3691=DIRECTION('',(0.E0,-1.E0,0.E0)); #3692=DIRECTION('',(0.E0,0.E0,-1.E0)); #3693=AXIS2_PLACEMENT_3D('',#3690,#3691,#3692); #3695=DIRECTION('',(0.E0,1.E0,0.E0)); #3696=VECTOR('',#3695,6.875E-1); #3697=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1)); #3698=LINE('',#3697,#3696); #3699=DIRECTION('',(0.E0,1.E0,0.E0)); #3700=VECTOR('',#3699,6.875E-1); #3701=CARTESIAN_POINT('',(1.05E1,0.E0,3.13125E1)); #3702=LINE('',#3701,#3700); #3703=DIRECTION('',(0.E0,1.E0,0.E0)); #3704=VECTOR('',#3703,6.875E-1); #3705=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1)); #3706=LINE('',#3705,#3704); #3707=DIRECTION('',(0.E0,1.E0,0.E0)); #3708=VECTOR('',#3707,6.875E-1); #3709=CARTESIAN_POINT('',(7.5E0,0.E0,3.01875E1)); #3710=LINE('',#3709,#3708); #3711=DIRECTION('',(1.E0,0.E0,0.E0)); #3712=VECTOR('',#3711,3.E0); #3713=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.13125E1)); #3714=LINE('',#3713,#3712); #3715=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.075E1)); #3716=DIRECTION('',(0.E0,1.E0,0.E0)); #3717=DIRECTION('',(0.E0,0.E0,1.E0)); #3718=AXIS2_PLACEMENT_3D('',#3715,#3716,#3717); #3720=DIRECTION('',(-1.E0,0.E0,0.E0)); #3721=VECTOR('',#3720,3.E0); #3722=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.01875E1)); #3723=LINE('',#3722,#3721); #3724=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.075E1)); #3725=DIRECTION('',(0.E0,1.E0,0.E0)); #3726=DIRECTION('',(0.E0,0.E0,-1.E0)); #3727=AXIS2_PLACEMENT_3D('',#3724,#3725,#3726); #3729=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #3730=VECTOR('',#3729,4.263248410977E0); #3731=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,2.795313485357E1)); #3732=LINE('',#3731,#3730); #3733=CARTESIAN_POINT('',(4.553039342392E0,6.875E-1,3.035464591145E1)); #3734=DIRECTION('',(0.E0,1.E0,0.E0)); #3735=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #3736=AXIS2_PLACEMENT_3D('',#3733,#3734,#3735); #3738=CARTESIAN_POINT('',(7.5E0,6.875E-1,2.45E1)); #3739=DIRECTION('',(0.E0,-1.E0,0.E0)); #3740=DIRECTION('',(-4.496088413988E-1,0.E0,8.932255536739E-1)); #3741=AXIS2_PLACEMENT_3D('',#3738,#3739,#3740); #3743=CARTESIAN_POINT('',(1.61E0,6.875E-1,2.75E1)); #3744=DIRECTION('',(0.E0,1.E0,0.E0)); #3745=DIRECTION('',(8.910741301059E-1,0.E0,-4.538577912254E-1)); #3746=AXIS2_PLACEMENT_3D('',#3743,#3744,#3745); #3748=DIRECTION('',(0.E0,1.E0,-1.033516706560E-14)); #3749=VECTOR('',#3748,6.875E-1); #3750=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,2.708717332281E1)); #3751=LINE('',#3750,#3749); #3752=CARTESIAN_POINT('',(1.455736763592E0,0.E0,2.742280476768E1)); #3753=DIRECTION('',(0.E0,1.E0,0.E0)); #3754=DIRECTION('',(-8.942796313519E-1,0.E0,-4.475085931567E-1)); #3755=AXIS2_PLACEMENT_3D('',#3752,#3753,#3754); #3757=DIRECTION('',(0.E0,1.E0,1.033516706560E-14)); #3758=VECTOR('',#3757,6.875E-1); #3759=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,2.795313485357E1)); #3760=LINE('',#3759,#3758); #3761=CARTESIAN_POINT('',(1.455736763592E0,6.875E-1,2.742280476768E1)); #3762=DIRECTION('',(0.E0,-1.E0,0.E0)); #3763=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811866E-1)); #3764=AXIS2_PLACEMENT_3D('',#3761,#3762,#3763); #3766=DIRECTION('',(0.E0,1.E0,1.033516706560E-14)); #3767=VECTOR('',#3766,6.875E-1); #3768=CARTESIAN_POINT('',(2.432015885023E0,0.E0,2.708131618759E1)); #3769=LINE('',#3768,#3767); #3770=DIRECTION('',(0.E0,1.E0,0.E0)); #3771=VECTOR('',#3770,6.875E-1); #3772=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.958022033652E1)); #3773=LINE('',#3772,#3771); #3774=DIRECTION('',(0.E0,1.E0,0.E0)); #3775=VECTOR('',#3774,6.875E-1); #3776=CARTESIAN_POINT('',(3.939978538987E0,0.E0,3.096770671486E1)); #3777=LINE('',#3776,#3775); #3778=DIRECTION('',(0.E0,1.E0,0.E0)); #3779=VECTOR('',#3778,6.875E-1); #3780=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1)); #3781=LINE('',#3780,#3779); #3782=DIRECTION('',(0.E0,1.E0,0.E0)); #3783=VECTOR('',#3782,6.875E-1); #3784=CARTESIAN_POINT('',(1.35E1,0.E0,6.875E-1)); #3785=LINE('',#3784,#3783); #3786=DIRECTION('',(0.E0,1.E0,0.E0)); #3787=VECTOR('',#3786,6.875E-1); #3788=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0)); #3789=LINE('',#3788,#3787); #3790=DIRECTION('',(0.E0,1.E0,0.E0)); #3791=VECTOR('',#3790,6.875E-1); #3792=CARTESIAN_POINT('',(1.65E1,0.E0,1.8125E0)); #3793=LINE('',#3792,#3791); #3794=DIRECTION('',(-1.E0,0.E0,0.E0)); #3795=VECTOR('',#3794,3.E0); #3796=CARTESIAN_POINT('',(1.65E1,6.875E-1,6.875E-1)); #3797=LINE('',#3796,#3795); #3798=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.25E0)); #3799=DIRECTION('',(0.E0,1.E0,0.E0)); #3800=DIRECTION('',(0.E0,0.E0,-1.E0)); #3801=AXIS2_PLACEMENT_3D('',#3798,#3799,#3800); #3803=DIRECTION('',(1.E0,0.E0,0.E0)); #3804=VECTOR('',#3803,3.E0); #3805=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.8125E0)); #3806=LINE('',#3805,#3804); #3807=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.25E0)); #3808=DIRECTION('',(0.E0,1.E0,0.E0)); #3809=DIRECTION('',(0.E0,0.E0,1.E0)); #3810=AXIS2_PLACEMENT_3D('',#3807,#3808,#3809); #3812=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #3813=VECTOR('',#3812,4.263248410977E0); #3814=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,4.046865146430E0)); #3815=LINE('',#3814,#3813); #3816=CARTESIAN_POINT('',(1.944696065761E1,6.875E-1,1.645354088550E0)); #3817=DIRECTION('',(0.E0,1.E0,0.E0)); #3818=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #3819=AXIS2_PLACEMENT_3D('',#3816,#3817,#3818); #3821=CARTESIAN_POINT('',(1.65E1,6.875E-1,7.5E0)); #3822=DIRECTION('',(0.E0,-1.E0,0.E0)); #3823=DIRECTION('',(4.496088413988E-1,0.E0,-8.932255536739E-1)); #3824=AXIS2_PLACEMENT_3D('',#3821,#3822,#3823); #3826=CARTESIAN_POINT('',(2.239E1,6.875E-1,4.5E0)); #3827=DIRECTION('',(0.E0,1.E0,0.E0)); #3828=DIRECTION('',(-8.910741301059E-1,0.E0,4.538577912254E-1)); #3829=AXIS2_PLACEMENT_3D('',#3826,#3827,#3828); #3831=DIRECTION('',(-1.033516706560E-14,1.E0,2.583791766400E-14)); #3832=VECTOR('',#3831,6.875E-1); #3833=CARTESIAN_POINT('',(2.321497295992E1,0.E0,4.912826677187E0)); #3834=LINE('',#3833,#3832); #3835=CARTESIAN_POINT('',(2.254426323641E1,0.E0,4.577195232320E0)); #3836=DIRECTION('',(0.E0,1.E0,0.E0)); #3837=DIRECTION('',(8.942796313519E-1,0.E0,4.475085931567E-1)); #3838=AXIS2_PLACEMENT_3D('',#3835,#3836,#3837); #3840=DIRECTION('',(0.E0,1.E0,0.E0)); #3841=VECTOR('',#3840,6.875E-1); #3842=CARTESIAN_POINT('',(2.307459332230E1,0.E0,4.046865146430E0)); #3843=LINE('',#3842,#3841); #3844=CARTESIAN_POINT('',(2.254426323641E1,6.875E-1,4.577195232320E0)); #3845=DIRECTION('',(0.E0,-1.E0,0.E0)); #3846=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #3847=AXIS2_PLACEMENT_3D('',#3844,#3845,#3846); #3849=DIRECTION('',(-1.550275059840E-14,1.E0,-2.067033413120E-14)); #3850=VECTOR('',#3849,6.875E-1); #3851=CARTESIAN_POINT('',(2.156798411498E1,0.E0,4.918683812405E0)); #3852=LINE('',#3851,#3850); #3853=DIRECTION('',(1.550275059840E-14,1.E0,0.E0)); #3854=VECTOR('',#3853,6.875E-1); #3855=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.419779663480E0)); #3856=LINE('',#3855,#3854); #3857=DIRECTION('',(0.E0,1.E0,0.E0)); #3858=VECTOR('',#3857,6.875E-1); #3859=CARTESIAN_POINT('',(2.006002146101E1,0.E0,1.032293285145E0)); #3860=LINE('',#3859,#3858); #3861=DIRECTION('',(0.E0,1.E0,0.E0)); #3862=VECTOR('',#3861,6.875E-1); #3863=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1)); #3864=LINE('',#3863,#3862); #3865=DIRECTION('',(0.E0,1.E0,0.E0)); #3866=VECTOR('',#3865,6.875E-1); #3867=CARTESIAN_POINT('',(2.33125E1,0.E0,1.35E1)); #3868=LINE('',#3867,#3866); #3869=DIRECTION('',(0.E0,1.E0,0.E0)); #3870=VECTOR('',#3869,6.875E-1); #3871=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1)); #3872=LINE('',#3871,#3870); #3873=DIRECTION('',(0.E0,1.E0,0.E0)); #3874=VECTOR('',#3873,6.875E-1); #3875=CARTESIAN_POINT('',(2.21875E1,0.E0,1.65E1)); #3876=LINE('',#3875,#3874); #3877=DIRECTION('',(0.E0,0.E0,-1.E0)); #3878=VECTOR('',#3877,3.E0); #3879=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.65E1)); #3880=LINE('',#3879,#3878); #3881=CARTESIAN_POINT('',(2.275E1,6.875E-1,1.35E1)); #3882=DIRECTION('',(0.E0,1.E0,0.E0)); #3883=DIRECTION('',(1.E0,0.E0,0.E0)); #3884=AXIS2_PLACEMENT_3D('',#3881,#3882,#3883); #3886=DIRECTION('',(0.E0,0.E0,1.E0)); #3887=VECTOR('',#3886,3.E0); #3888=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.35E1)); #3889=LINE('',#3888,#3887); #3890=CARTESIAN_POINT('',(2.275E1,6.875E-1,1.65E1)); #3891=DIRECTION('',(0.E0,1.E0,0.E0)); #3892=DIRECTION('',(-1.E0,0.E0,0.E0)); #3893=AXIS2_PLACEMENT_3D('',#3890,#3891,#3892); #3895=DIRECTION('',(0.E0,1.E0,0.E0)); #3896=VECTOR('',#3895,6.875E-1); #3897=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1)); #3898=LINE('',#3897,#3896); #3899=DIRECTION('',(0.E0,1.E0,0.E0)); #3900=VECTOR('',#3899,6.875E-1); #3901=CARTESIAN_POINT('',(2.33125E1,0.E0,1.95E1)); #3902=LINE('',#3901,#3900); #3903=DIRECTION('',(0.E0,1.E0,0.E0)); #3904=VECTOR('',#3903,6.875E-1); #3905=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1)); #3906=LINE('',#3905,#3904); #3907=DIRECTION('',(0.E0,1.E0,0.E0)); #3908=VECTOR('',#3907,6.875E-1); #3909=CARTESIAN_POINT('',(2.21875E1,0.E0,2.25E1)); #3910=LINE('',#3909,#3908); #3911=DIRECTION('',(0.E0,0.E0,-1.E0)); #3912=VECTOR('',#3911,3.E0); #3913=CARTESIAN_POINT('',(2.33125E1,6.875E-1,2.25E1)); #3914=LINE('',#3913,#3912); #3915=CARTESIAN_POINT('',(2.275E1,6.875E-1,1.95E1)); #3916=DIRECTION('',(0.E0,1.E0,0.E0)); #3917=DIRECTION('',(1.E0,0.E0,0.E0)); #3918=AXIS2_PLACEMENT_3D('',#3915,#3916,#3917); #3920=DIRECTION('',(0.E0,0.E0,1.E0)); #3921=VECTOR('',#3920,3.E0); #3922=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.95E1)); #3923=LINE('',#3922,#3921); #3924=CARTESIAN_POINT('',(2.275E1,6.875E-1,2.25E1)); #3925=DIRECTION('',(0.E0,1.E0,0.E0)); #3926=DIRECTION('',(-1.E0,0.E0,0.E0)); #3927=AXIS2_PLACEMENT_3D('',#3924,#3925,#3926); #3929=DIRECTION('',(0.E0,1.E0,0.E0)); #3930=VECTOR('',#3929,6.875E-1); #3931=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0)); #3932=LINE('',#3931,#3930); #3933=DIRECTION('',(0.E0,1.E0,0.E0)); #3934=VECTOR('',#3933,6.875E-1); #3935=CARTESIAN_POINT('',(1.35E1,0.E0,8.5E0)); #3936=LINE('',#3935,#3934); #3937=DIRECTION('',(0.E0,1.E0,0.E0)); #3938=VECTOR('',#3937,6.875E-1); #3939=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0)); #3940=LINE('',#3939,#3938); #3941=DIRECTION('',(0.E0,1.E0,0.E0)); #3942=VECTOR('',#3941,6.875E-1); #3943=CARTESIAN_POINT('',(1.65E1,0.E0,9.5E0)); #3944=LINE('',#3943,#3942); #3945=DIRECTION('',(-1.E0,0.E0,0.E0)); #3946=VECTOR('',#3945,3.E0); #3947=CARTESIAN_POINT('',(1.65E1,6.875E-1,8.5E0)); #3948=LINE('',#3947,#3946); #3949=CARTESIAN_POINT('',(1.35E1,6.875E-1,9.E0)); #3950=DIRECTION('',(0.E0,1.E0,0.E0)); #3951=DIRECTION('',(0.E0,0.E0,-1.E0)); #3952=AXIS2_PLACEMENT_3D('',#3949,#3950,#3951); #3954=DIRECTION('',(1.E0,0.E0,0.E0)); #3955=VECTOR('',#3954,3.E0); #3956=CARTESIAN_POINT('',(1.35E1,6.875E-1,9.5E0)); #3957=LINE('',#3956,#3955); #3958=CARTESIAN_POINT('',(1.65E1,6.875E-1,9.E0)); #3959=DIRECTION('',(0.E0,1.E0,0.E0)); #3960=DIRECTION('',(0.E0,0.E0,1.E0)); #3961=AXIS2_PLACEMENT_3D('',#3958,#3959,#3960); #3963=DIRECTION('',(0.E0,1.E0,0.E0)); #3964=VECTOR('',#3963,6.875E-1); #3965=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1)); #3966=LINE('',#3965,#3964); #3967=DIRECTION('',(0.E0,1.E0,0.E0)); #3968=VECTOR('',#3967,6.875E-1); #3969=CARTESIAN_POINT('',(1.35E1,0.E0,1.75625E1)); #3970=LINE('',#3969,#3968); #3971=DIRECTION('',(0.E0,1.E0,0.E0)); #3972=VECTOR('',#3971,6.875E-1); #3973=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1)); #3974=LINE('',#3973,#3972); #3975=DIRECTION('',(0.E0,1.E0,0.E0)); #3976=VECTOR('',#3975,6.875E-1); #3977=CARTESIAN_POINT('',(1.65E1,0.E0,1.84375E1)); #3978=LINE('',#3977,#3976); #3979=DIRECTION('',(-1.E0,0.E0,0.E0)); #3980=VECTOR('',#3979,3.E0); #3981=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.75625E1)); #3982=LINE('',#3981,#3980); #3983=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.8E1)); #3984=DIRECTION('',(0.E0,1.E0,0.E0)); #3985=DIRECTION('',(0.E0,0.E0,-1.E0)); #3986=AXIS2_PLACEMENT_3D('',#3983,#3984,#3985); #3988=DIRECTION('',(1.E0,0.E0,0.E0)); #3989=VECTOR('',#3988,3.E0); #3990=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.84375E1)); #3991=LINE('',#3990,#3989); #3992=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.8E1)); #3993=DIRECTION('',(0.E0,1.E0,0.E0)); #3994=DIRECTION('',(0.E0,0.E0,1.E0)); #3995=AXIS2_PLACEMENT_3D('',#3992,#3993,#3994); #3997=DIRECTION('',(0.E0,1.E0,0.E0)); #3998=VECTOR('',#3997,6.875E-1); #3999=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1)); #4000=LINE('',#3999,#3998); #4001=DIRECTION('',(0.E0,1.E0,0.E0)); #4002=VECTOR('',#4001,6.875E-1); #4003=CARTESIAN_POINT('',(1.65E1,0.E0,3.01875E1)); #4004=LINE('',#4003,#4002); #4005=DIRECTION('',(0.E0,1.E0,0.E0)); #4006=VECTOR('',#4005,6.875E-1); #4007=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1)); #4008=LINE('',#4007,#4006); #4009=DIRECTION('',(0.E0,1.E0,0.E0)); #4010=VECTOR('',#4009,6.875E-1); #4011=CARTESIAN_POINT('',(1.35E1,0.E0,3.13125E1)); #4012=LINE('',#4011,#4010); #4013=DIRECTION('',(-1.E0,0.E0,0.E0)); #4014=VECTOR('',#4013,3.E0); #4015=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.13125E1)); #4016=LINE('',#4015,#4014); #4017=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.075E1)); #4018=DIRECTION('',(0.E0,-1.E0,0.E0)); #4019=DIRECTION('',(0.E0,0.E0,-1.E0)); #4020=AXIS2_PLACEMENT_3D('',#4017,#4018,#4019); #4022=DIRECTION('',(1.E0,0.E0,0.E0)); #4023=VECTOR('',#4022,3.E0); #4024=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.01875E1)); #4025=LINE('',#4024,#4023); #4026=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.075E1)); #4027=DIRECTION('',(0.E0,-1.E0,0.E0)); #4028=DIRECTION('',(0.E0,0.E0,1.E0)); #4029=AXIS2_PLACEMENT_3D('',#4026,#4027,#4028); #4031=CARTESIAN_POINT('',(2.239E1,6.875E-1,2.75E1)); #4032=DIRECTION('',(0.E0,-1.E0,0.E0)); #4033=DIRECTION('',(-8.910741301059E-1,0.E0,-4.538577912254E-1)); #4034=AXIS2_PLACEMENT_3D('',#4031,#4032,#4033); #4036=CARTESIAN_POINT('',(1.65E1,6.875E-1,2.45E1)); #4037=DIRECTION('',(0.E0,1.E0,0.E0)); #4038=DIRECTION('',(4.496088413988E-1,0.E0,8.932255536739E-1)); #4039=AXIS2_PLACEMENT_3D('',#4036,#4037,#4038); #4041=CARTESIAN_POINT('',(1.944696065761E1,6.875E-1,3.035464591145E1)); #4042=DIRECTION('',(0.E0,-1.E0,0.E0)); #4043=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #4044=AXIS2_PLACEMENT_3D('',#4041,#4042,#4043); #4046=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #4047=VECTOR('',#4046,4.263248410977E0); #4048=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,2.795313485357E1)); #4049=LINE('',#4048,#4047); #4050=DIRECTION('',(0.E0,1.E0,0.E0)); #4051=VECTOR('',#4050,6.875E-1); #4052=CARTESIAN_POINT('',(2.307459332230E1,0.E0,2.795313485357E1)); #4053=LINE('',#4052,#4051); #4054=CARTESIAN_POINT('',(2.254426323641E1,0.E0,2.742280476768E1)); #4055=DIRECTION('',(0.E0,1.E0,0.E0)); #4056=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #4057=AXIS2_PLACEMENT_3D('',#4054,#4055,#4056); #4059=DIRECTION('',(0.E0,1.E0,2.067033413120E-14)); #4060=VECTOR('',#4059,6.875E-1); #4061=CARTESIAN_POINT('',(2.321497295992E1,0.E0,2.708717332281E1)); #4062=LINE('',#4061,#4060); #4063=CARTESIAN_POINT('',(2.254426323641E1,6.875E-1,2.742280476768E1)); #4064=DIRECTION('',(0.E0,-1.E0,0.E0)); #4065=DIRECTION('',(8.942796313519E-1,0.E0,-4.475085931567E-1)); #4066=AXIS2_PLACEMENT_3D('',#4063,#4064,#4065); #4068=DIRECTION('',(0.E0,1.E0,0.E0)); #4069=VECTOR('',#4068,6.875E-1); #4070=CARTESIAN_POINT('',(2.006002146101E1,0.E0,3.096770671486E1)); #4071=LINE('',#4070,#4069); #4072=DIRECTION('',(1.033516706560E-14,1.E0,0.E0)); #4073=VECTOR('',#4072,6.875E-1); #4074=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.958022033652E1)); #4075=LINE('',#4074,#4073); #4076=DIRECTION('',(-2.067033413120E-14,1.E0,3.100550119680E-14)); #4077=VECTOR('',#4076,6.875E-1); #4078=CARTESIAN_POINT('',(2.156798411498E1,0.E0,2.708131618759E1)); #4079=LINE('',#4078,#4077); #4080=DIRECTION('',(0.E0,1.E0,0.E0)); #4081=VECTOR('',#4080,6.875E-1); #4082=CARTESIAN_POINT('',(2.13075E1,0.E0,8.69E0)); #4083=LINE('',#4082,#4081); #4084=CARTESIAN_POINT('',(2.13075E1,6.875E-1,7.81E0)); #4085=DIRECTION('',(0.E0,1.E0,0.E0)); #4086=DIRECTION('',(0.E0,0.E0,1.E0)); #4087=AXIS2_PLACEMENT_3D('',#4084,#4085,#4086); #4089=DIRECTION('',(0.E0,1.E0,0.E0)); #4090=VECTOR('',#4089,6.875E-1); #4091=CARTESIAN_POINT('',(2.21875E1,0.E0,7.81E0)); #4092=LINE('',#4091,#4090); #4093=CARTESIAN_POINT('',(2.13075E1,0.E0,7.81E0)); #4094=DIRECTION('',(0.E0,-1.E0,0.E0)); #4095=DIRECTION('',(1.E0,0.E0,0.E0)); #4096=AXIS2_PLACEMENT_3D('',#4093,#4094,#4095); #4098=DIRECTION('',(0.E0,-1.E0,0.E0)); #4099=VECTOR('',#4098,6.875E-1); #4100=CARTESIAN_POINT('',(1.96875E1,6.875E-1,9.57E0)); #4101=LINE('',#4100,#4099); #4102=CARTESIAN_POINT('',(2.05675E1,6.875E-1,9.57E0)); #4103=DIRECTION('',(0.E0,-1.E0,0.E0)); #4104=DIRECTION('',(-1.E0,0.E0,0.E0)); #4105=AXIS2_PLACEMENT_3D('',#4102,#4103,#4104); #4107=DIRECTION('',(0.E0,-1.E0,0.E0)); #4108=VECTOR('',#4107,6.875E-1); #4109=CARTESIAN_POINT('',(2.05675E1,6.875E-1,8.69E0)); #4110=LINE('',#4109,#4108); #4111=CARTESIAN_POINT('',(2.05675E1,0.E0,9.57E0)); #4112=DIRECTION('',(0.E0,1.E0,0.E0)); #4113=DIRECTION('',(0.E0,0.E0,-1.E0)); #4114=AXIS2_PLACEMENT_3D('',#4111,#4112,#4113); #4116=DIRECTION('',(0.E0,-1.E0,0.E0)); #4117=VECTOR('',#4116,6.875E-1); #4118=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.125E1)); #4119=LINE('',#4118,#4117); #4120=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.037E1)); #4121=DIRECTION('',(0.E0,-1.E0,0.E0)); #4122=DIRECTION('',(0.E0,0.E0,1.E0)); #4123=AXIS2_PLACEMENT_3D('',#4120,#4121,#4122); #4125=DIRECTION('',(0.E0,-1.E0,0.E0)); #4126=VECTOR('',#4125,6.875E-1); #4127=CARTESIAN_POINT('',(1.96875E1,6.875E-1,1.037E1)); #4128=LINE('',#4127,#4126); #4129=CARTESIAN_POINT('',(2.05675E1,0.E0,1.037E1)); #4130=DIRECTION('',(0.E0,1.E0,0.E0)); #4131=DIRECTION('',(-1.E0,0.E0,0.E0)); #4132=AXIS2_PLACEMENT_3D('',#4129,#4130,#4131); #4134=DIRECTION('',(0.E0,-1.E0,0.E0)); #4135=VECTOR('',#4134,6.875E-1); #4136=CARTESIAN_POINT('',(2.53125E1,6.875E-1,1.037E1)); #4137=LINE('',#4136,#4135); #4138=CARTESIAN_POINT('',(2.44325E1,6.875E-1,1.037E1)); #4139=DIRECTION('',(0.E0,-1.E0,0.E0)); #4140=DIRECTION('',(1.E0,0.E0,0.E0)); #4141=AXIS2_PLACEMENT_3D('',#4138,#4139,#4140); #4143=DIRECTION('',(0.E0,-1.E0,0.E0)); #4144=VECTOR('',#4143,6.875E-1); #4145=CARTESIAN_POINT('',(2.44325E1,6.875E-1,1.125E1)); #4146=LINE('',#4145,#4144); #4147=CARTESIAN_POINT('',(2.44325E1,0.E0,1.037E1)); #4148=DIRECTION('',(0.E0,1.E0,0.E0)); #4149=DIRECTION('',(0.E0,0.E0,1.E0)); #4150=AXIS2_PLACEMENT_3D('',#4147,#4148,#4149); #4152=DIRECTION('',(0.E0,-1.E0,0.E0)); #4153=VECTOR('',#4152,6.875E-1); #4154=CARTESIAN_POINT('',(2.44325E1,6.875E-1,8.69E0)); #4155=LINE('',#4154,#4153); #4156=CARTESIAN_POINT('',(2.44325E1,6.875E-1,9.57E0)); #4157=DIRECTION('',(0.E0,-1.E0,0.E0)); #4158=DIRECTION('',(0.E0,0.E0,-1.E0)); #4159=AXIS2_PLACEMENT_3D('',#4156,#4157,#4158); #4161=DIRECTION('',(0.E0,-1.E0,0.E0)); #4162=VECTOR('',#4161,6.875E-1); #4163=CARTESIAN_POINT('',(2.53125E1,6.875E-1,9.57E0)); #4164=LINE('',#4163,#4162); #4165=CARTESIAN_POINT('',(2.44325E1,0.E0,9.57E0)); #4166=DIRECTION('',(0.E0,1.E0,0.E0)); #4167=DIRECTION('',(1.E0,0.E0,0.E0)); #4168=AXIS2_PLACEMENT_3D('',#4165,#4166,#4167); #4170=DIRECTION('',(0.E0,1.E0,0.E0)); #4171=VECTOR('',#4170,6.875E-1); #4172=CARTESIAN_POINT('',(2.331E1,0.E0,7.81E0)); #4173=LINE('',#4172,#4171); #4174=CARTESIAN_POINT('',(2.419E1,6.875E-1,7.81E0)); #4175=DIRECTION('',(0.E0,1.E0,0.E0)); #4176=DIRECTION('',(-1.E0,0.E0,0.E0)); #4177=AXIS2_PLACEMENT_3D('',#4174,#4175,#4176); #4179=DIRECTION('',(0.E0,1.E0,0.E0)); #4180=VECTOR('',#4179,6.875E-1); #4181=CARTESIAN_POINT('',(2.419E1,0.E0,8.69E0)); #4182=LINE('',#4181,#4180); #4183=CARTESIAN_POINT('',(2.419E1,0.E0,7.81E0)); #4184=DIRECTION('',(0.E0,-1.E0,0.E0)); #4185=DIRECTION('',(0.E0,0.E0,1.E0)); #4186=AXIS2_PLACEMENT_3D('',#4183,#4184,#4185); #4188=DIRECTION('',(0.E0,1.E0,1.033516706560E-14)); #4189=VECTOR('',#4188,6.875E-1); #4190=CARTESIAN_POINT('',(2.331E1,0.E0,7.5E0)); #4191=LINE('',#4190,#4189); #4192=DIRECTION('',(0.E0,1.E0,0.E0)); #4193=VECTOR('',#4192,6.875E-1); #4194=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0)); #4195=LINE('',#4194,#4193); #4196=DIRECTION('',(-1.E0,0.E0,0.E0)); #4197=VECTOR('',#4196,2.425E-1); #4198=CARTESIAN_POINT('',(2.44325E1,6.875E-1,8.69E0)); #4199=LINE('',#4198,#4197); #4200=DIRECTION('',(0.E0,0.E0,-1.E0)); #4201=VECTOR('',#4200,3.1E-1); #4202=CARTESIAN_POINT('',(2.331E1,6.875E-1,7.81E0)); #4203=LINE('',#4202,#4201); #4204=CARTESIAN_POINT('',(2.274875E1,6.875E-1,7.5E0)); #4205=DIRECTION('',(0.E0,1.E0,0.E0)); #4206=DIRECTION('',(1.E0,0.E0,0.E0)); #4207=AXIS2_PLACEMENT_3D('',#4204,#4205,#4206); #4209=DIRECTION('',(0.E0,0.E0,1.E0)); #4210=VECTOR('',#4209,3.1E-1); #4211=CARTESIAN_POINT('',(2.21875E1,6.875E-1,7.5E0)); #4212=LINE('',#4211,#4210); #4213=DIRECTION('',(-1.E0,0.E0,0.E0)); #4214=VECTOR('',#4213,7.4E-1); #4215=CARTESIAN_POINT('',(2.13075E1,6.875E-1,8.69E0)); #4216=LINE('',#4215,#4214); #4217=DIRECTION('',(0.E0,0.E0,1.E0)); #4218=VECTOR('',#4217,8.E-1); #4219=CARTESIAN_POINT('',(1.96875E1,6.875E-1,9.57E0)); #4220=LINE('',#4219,#4218); #4221=DIRECTION('',(1.E0,0.E0,0.E0)); #4222=VECTOR('',#4221,3.865E0); #4223=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.125E1)); #4224=LINE('',#4223,#4222); #4225=DIRECTION('',(0.E0,0.E0,-1.E0)); #4226=VECTOR('',#4225,8.E-1); #4227=CARTESIAN_POINT('',(2.53125E1,6.875E-1,1.037E1)); #4228=LINE('',#4227,#4226); #4229=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1)); #4230=CARTESIAN_POINT('',(2.4E1,1.5E0,2.8E1)); #4231=VERTEX_POINT('',#4229); #4232=VERTEX_POINT('',#4230); #4233=CARTESIAN_POINT('',(2.E1,0.E0,3.2E1)); #4234=CARTESIAN_POINT('',(2.E1,1.5E0,3.2E1)); #4235=VERTEX_POINT('',#4233); #4236=VERTEX_POINT('',#4234); #4237=CARTESIAN_POINT('',(2.E1,0.E0,0.E0)); #4238=CARTESIAN_POINT('',(2.E1,1.5E0,0.E0)); #4239=VERTEX_POINT('',#4237); #4240=VERTEX_POINT('',#4238); #4241=CARTESIAN_POINT('',(2.4E1,0.E0,4.E0)); #4242=CARTESIAN_POINT('',(2.4E1,1.5E0,4.E0)); #4243=VERTEX_POINT('',#4241); #4244=VERTEX_POINT('',#4242); #4245=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1)); #4246=CARTESIAN_POINT('',(4.E0,1.5E0,3.2E1)); #4247=VERTEX_POINT('',#4245); #4248=VERTEX_POINT('',#4246); #4249=CARTESIAN_POINT('',(0.E0,0.E0,2.8E1)); #4250=CARTESIAN_POINT('',(0.E0,1.5E0,2.8E1)); #4251=VERTEX_POINT('',#4249); #4252=VERTEX_POINT('',#4250); #4253=CARTESIAN_POINT('',(0.E0,0.E0,4.E0)); #4254=CARTESIAN_POINT('',(0.E0,1.5E0,4.E0)); #4255=VERTEX_POINT('',#4253); #4256=VERTEX_POINT('',#4254); #4257=CARTESIAN_POINT('',(4.E0,0.E0,0.E0)); #4258=CARTESIAN_POINT('',(4.E0,1.5E0,0.E0)); #4259=VERTEX_POINT('',#4257); #4260=VERTEX_POINT('',#4258); #4261=CARTESIAN_POINT('',(7.5E0,1.5E0,2.5E0)); #4262=CARTESIAN_POINT('',(7.5E0,0.E0,2.5E0)); #4263=VERTEX_POINT('',#4261); #4264=VERTEX_POINT('',#4262); #4265=CARTESIAN_POINT('',(1.65E1,1.5E0,2.5E0)); #4266=CARTESIAN_POINT('',(1.65E1,0.E0,2.5E0)); #4267=VERTEX_POINT('',#4265); #4268=VERTEX_POINT('',#4266); #4269=CARTESIAN_POINT('',(7.5E0,1.5E0,2.95E1)); #4270=CARTESIAN_POINT('',(7.5E0,0.E0,2.95E1)); #4271=VERTEX_POINT('',#4269); #4272=VERTEX_POINT('',#4270); #4273=CARTESIAN_POINT('',(2.5E0,1.5E0,2.45E1)); #4274=CARTESIAN_POINT('',(2.5E0,0.E0,2.45E1)); #4275=VERTEX_POINT('',#4273); #4276=VERTEX_POINT('',#4274); #4277=CARTESIAN_POINT('',(2.15E1,1.5E0,2.45E1)); #4278=CARTESIAN_POINT('',(2.15E1,0.E0,2.45E1)); #4279=VERTEX_POINT('',#4277); #4280=VERTEX_POINT('',#4278); #4281=CARTESIAN_POINT('',(1.65E1,1.5E0,2.95E1)); #4282=CARTESIAN_POINT('',(1.65E1,0.E0,2.95E1)); #4283=VERTEX_POINT('',#4281); #4284=VERTEX_POINT('',#4282); #4285=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0)); #4286=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0)); #4287=VERTEX_POINT('',#4285); #4288=VERTEX_POINT('',#4286); #4289=CARTESIAN_POINT('',(-2.E0,2.5E0,8.E0)); #4290=VERTEX_POINT('',#4289); #4291=CARTESIAN_POINT('',(5.E0,1.15E1,1.E1)); #4292=CARTESIAN_POINT('',(3.E0,1.15E1,1.E1)); #4293=VERTEX_POINT('',#4291); #4294=VERTEX_POINT('',#4292); #4295=CARTESIAN_POINT('',(-2.E0,2.5E0,1.E1)); #4296=VERTEX_POINT('',#4295); #4297=CARTESIAN_POINT('',(-2.E0,1.5E0,1.E1)); #4298=VERTEX_POINT('',#4297); #4299=CARTESIAN_POINT('',(-2.E0,0.E0,8.E0)); #4300=VERTEX_POINT('',#4299); #4301=CARTESIAN_POINT('',(2.5E0,1.5E0,1.325E1)); #4302=CARTESIAN_POINT('',(2.5E0,0.E0,1.325E1)); #4303=VERTEX_POINT('',#4301); #4304=VERTEX_POINT('',#4302); #4305=CARTESIAN_POINT('',(3.5E0,1.5E0,1.225E1)); #4306=CARTESIAN_POINT('',(3.5E0,0.E0,1.225E1)); #4307=VERTEX_POINT('',#4305); #4308=VERTEX_POINT('',#4306); #4309=CARTESIAN_POINT('',(0.E0,0.E0,1.325E1)); #4310=CARTESIAN_POINT('',(0.E0,1.5E0,1.325E1)); #4311=VERTEX_POINT('',#4309); #4312=VERTEX_POINT('',#4310); #4313=CARTESIAN_POINT('',(-1.E0,0.E0,1.225E1)); #4314=CARTESIAN_POINT('',(-1.E0,1.5E0,1.225E1)); #4315=VERTEX_POINT('',#4313); #4316=VERTEX_POINT('',#4314); #4317=CARTESIAN_POINT('',(0.E0,1.5E0,7.E0)); #4318=CARTESIAN_POINT('',(0.E0,0.E0,7.E0)); #4319=VERTEX_POINT('',#4317); #4320=VERTEX_POINT('',#4318); #4321=CARTESIAN_POINT('',(-1.E0,1.5E0,8.E0)); #4322=CARTESIAN_POINT('',(-1.E0,0.E0,8.E0)); #4323=VERTEX_POINT('',#4321); #4324=VERTEX_POINT('',#4322); #4325=CARTESIAN_POINT('',(3.531373033403E0,1.5E0,8.E0)); #4326=CARTESIAN_POINT('',(3.531373033403E0,0.E0,8.E0)); #4327=VERTEX_POINT('',#4325); #4328=VERTEX_POINT('',#4326); #4329=CARTESIAN_POINT('',(2.539216291754E0,1.5E0,6.875E0)); #4330=CARTESIAN_POINT('',(2.539216291754E0,0.E0,6.875E0)); #4331=VERTEX_POINT('',#4329); #4332=VERTEX_POINT('',#4330); #4333=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1)); #4334=CARTESIAN_POINT('',(5.E0,1.5E0,1.175E1)); #4335=VERTEX_POINT('',#4333); #4336=VERTEX_POINT('',#4334); #4337=CARTESIAN_POINT('',(4.5E0,0.E0,1.225E1)); #4338=CARTESIAN_POINT('',(4.5E0,1.5E0,1.225E1)); #4339=VERTEX_POINT('',#4337); #4340=VERTEX_POINT('',#4338); #4341=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1)); #4342=CARTESIAN_POINT('',(-1.5E0,1.5E0,1.225E1)); #4343=VERTEX_POINT('',#4341); #4344=VERTEX_POINT('',#4342); #4345=CARTESIAN_POINT('',(-2.E0,0.E0,1.175E1)); #4346=CARTESIAN_POINT('',(-2.E0,1.5E0,1.175E1)); #4347=VERTEX_POINT('',#4345); #4348=VERTEX_POINT('',#4346); #4349=CARTESIAN_POINT('',(4.095E0,1.1125E1,9.E0)); #4350=CARTESIAN_POINT('',(3.905E0,1.1125E1,9.E0)); #4351=VERTEX_POINT('',#4349); #4352=VERTEX_POINT('',#4350); #4353=CARTESIAN_POINT('',(4.095E0,1.15E1,9.E0)); #4354=CARTESIAN_POINT('',(3.905E0,1.15E1,9.E0)); #4355=VERTEX_POINT('',#4353); #4356=VERTEX_POINT('',#4354); #4357=CARTESIAN_POINT('',(3.929917478528E0,1.125E1,9.132582521472E0)); #4358=CARTESIAN_POINT('',(3.804917478528E0,1.125E1,9.132582521472E0)); #4359=VERTEX_POINT('',#4357); #4360=VERTEX_POINT('',#4358); #4361=CARTESIAN_POINT('',(3.929917478528E0,1.15E1,9.132582521472E0)); #4362=CARTESIAN_POINT('',(3.804917478528E0,1.15E1,9.132582521472E0)); #4363=VERTEX_POINT('',#4361); #4364=VERTEX_POINT('',#4362); #4365=CARTESIAN_POINT('',(6.45E0,1.192264973081E0,2.975E1)); #4366=CARTESIAN_POINT('',(6.55E0,1.25E0,2.975E1)); #4367=VERTEX_POINT('',#4365); #4368=VERTEX_POINT('',#4366); #4369=CARTESIAN_POINT('',(6.35E0,1.25E0,2.975E1)); #4370=VERTEX_POINT('',#4369); #4371=CARTESIAN_POINT('',(6.35E0,1.5E0,2.975E1)); #4372=CARTESIAN_POINT('',(6.55E0,1.5E0,2.975E1)); #4373=VERTEX_POINT('',#4371); #4374=VERTEX_POINT('',#4372); #4375=CARTESIAN_POINT('',(7.45E0,1.192264973081E0,2.975E1)); #4376=CARTESIAN_POINT('',(7.55E0,1.25E0,2.975E1)); #4377=VERTEX_POINT('',#4375); #4378=VERTEX_POINT('',#4376); #4379=CARTESIAN_POINT('',(7.35E0,1.25E0,2.975E1)); #4380=VERTEX_POINT('',#4379); #4381=CARTESIAN_POINT('',(7.35E0,1.5E0,2.975E1)); #4382=CARTESIAN_POINT('',(7.55E0,1.5E0,2.975E1)); #4383=VERTEX_POINT('',#4381); #4384=VERTEX_POINT('',#4382); #4385=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0)); #4386=CARTESIAN_POINT('',(1.9E1,1.15E1,8.E0)); #4387=VERTEX_POINT('',#4385); #4388=VERTEX_POINT('',#4386); #4389=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0)); #4390=VERTEX_POINT('',#4389); #4391=CARTESIAN_POINT('',(1.9E1,1.15E1,1.E1)); #4392=CARTESIAN_POINT('',(2.1E1,1.15E1,1.E1)); #4393=VERTEX_POINT('',#4391); #4394=VERTEX_POINT('',#4392); #4395=CARTESIAN_POINT('',(2.6E1,2.5E0,1.E1)); #4396=VERTEX_POINT('',#4395); #4397=CARTESIAN_POINT('',(2.6E1,1.5E0,1.E1)); #4398=VERTEX_POINT('',#4397); #4399=CARTESIAN_POINT('',(2.6E1,0.E0,8.E0)); #4400=VERTEX_POINT('',#4399); #4401=CARTESIAN_POINT('',(2.4E1,1.5E0,1.325E1)); #4402=CARTESIAN_POINT('',(2.4E1,0.E0,1.325E1)); #4403=VERTEX_POINT('',#4401); #4404=VERTEX_POINT('',#4402); #4405=CARTESIAN_POINT('',(2.5E1,1.5E0,1.225E1)); #4406=CARTESIAN_POINT('',(2.5E1,0.E0,1.225E1)); #4407=VERTEX_POINT('',#4405); #4408=VERTEX_POINT('',#4406); #4409=CARTESIAN_POINT('',(2.15E1,0.E0,1.325E1)); #4410=CARTESIAN_POINT('',(2.15E1,1.5E0,1.325E1)); #4411=VERTEX_POINT('',#4409); #4412=VERTEX_POINT('',#4410); #4413=CARTESIAN_POINT('',(2.05E1,0.E0,1.225E1)); #4414=CARTESIAN_POINT('',(2.05E1,1.5E0,1.225E1)); #4415=VERTEX_POINT('',#4413); #4416=VERTEX_POINT('',#4414); #4417=CARTESIAN_POINT('',(2.4E1,0.E0,7.E0)); #4418=CARTESIAN_POINT('',(2.4E1,1.5E0,7.E0)); #4419=VERTEX_POINT('',#4417); #4420=VERTEX_POINT('',#4418); #4421=CARTESIAN_POINT('',(2.5E1,0.E0,8.E0)); #4422=CARTESIAN_POINT('',(2.5E1,1.5E0,8.E0)); #4423=VERTEX_POINT('',#4421); #4424=VERTEX_POINT('',#4422); #4425=CARTESIAN_POINT('',(2.046862696660E1,0.E0,8.E0)); #4426=CARTESIAN_POINT('',(2.046862696660E1,1.5E0,8.E0)); #4427=VERTEX_POINT('',#4425); #4428=VERTEX_POINT('',#4426); #4429=CARTESIAN_POINT('',(2.146078370825E1,0.E0,6.875E0)); #4430=CARTESIAN_POINT('',(2.146078370825E1,1.5E0,6.875E0)); #4431=VERTEX_POINT('',#4429); #4432=VERTEX_POINT('',#4430); #4433=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1)); #4434=CARTESIAN_POINT('',(1.9E1,0.E0,1.175E1)); #4435=VERTEX_POINT('',#4433); #4436=VERTEX_POINT('',#4434); #4437=CARTESIAN_POINT('',(1.95E1,1.5E0,1.225E1)); #4438=CARTESIAN_POINT('',(1.95E1,0.E0,1.225E1)); #4439=VERTEX_POINT('',#4437); #4440=VERTEX_POINT('',#4438); #4441=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1)); #4442=CARTESIAN_POINT('',(2.55E1,0.E0,1.225E1)); #4443=VERTEX_POINT('',#4441); #4444=VERTEX_POINT('',#4442); #4445=CARTESIAN_POINT('',(2.6E1,1.5E0,1.175E1)); #4446=CARTESIAN_POINT('',(2.6E1,0.E0,1.175E1)); #4447=VERTEX_POINT('',#4445); #4448=VERTEX_POINT('',#4446); #4449=CARTESIAN_POINT('',(1.9905E1,1.1125E1,9.E0)); #4450=CARTESIAN_POINT('',(2.0095E1,1.1125E1,9.E0)); #4451=VERTEX_POINT('',#4449); #4452=VERTEX_POINT('',#4450); #4453=CARTESIAN_POINT('',(1.9905E1,1.15E1,9.E0)); #4454=CARTESIAN_POINT('',(2.0095E1,1.15E1,9.E0)); #4455=VERTEX_POINT('',#4453); #4456=VERTEX_POINT('',#4454); #4457=CARTESIAN_POINT('',(2.007008252147E1,1.125E1,9.132582521472E0)); #4458=CARTESIAN_POINT('',(2.019508252147E1,1.125E1,9.132582521472E0)); #4459=VERTEX_POINT('',#4457); #4460=VERTEX_POINT('',#4458); #4461=CARTESIAN_POINT('',(2.007008252147E1,1.15E1,9.132582521472E0)); #4462=CARTESIAN_POINT('',(2.019508252147E1,1.15E1,9.132582521472E0)); #4463=VERTEX_POINT('',#4461); #4464=VERTEX_POINT('',#4462); #4465=CARTESIAN_POINT('',(1.755E1,1.192264973081E0,2.975E1)); #4466=CARTESIAN_POINT('',(1.745E1,1.25E0,2.975E1)); #4467=VERTEX_POINT('',#4465); #4468=VERTEX_POINT('',#4466); #4469=CARTESIAN_POINT('',(1.765E1,1.25E0,2.975E1)); #4470=VERTEX_POINT('',#4469); #4471=CARTESIAN_POINT('',(1.765E1,1.5E0,2.975E1)); #4472=CARTESIAN_POINT('',(1.745E1,1.5E0,2.975E1)); #4473=VERTEX_POINT('',#4471); #4474=VERTEX_POINT('',#4472); #4475=CARTESIAN_POINT('',(1.655E1,1.192264973081E0,2.975E1)); #4476=CARTESIAN_POINT('',(1.645E1,1.25E0,2.975E1)); #4477=VERTEX_POINT('',#4475); #4478=VERTEX_POINT('',#4476); #4479=CARTESIAN_POINT('',(1.665E1,1.25E0,2.975E1)); #4480=VERTEX_POINT('',#4479); #4481=CARTESIAN_POINT('',(1.665E1,1.5E0,2.975E1)); #4482=CARTESIAN_POINT('',(1.645E1,1.5E0,2.975E1)); #4483=VERTEX_POINT('',#4481); #4484=VERTEX_POINT('',#4482); #4485=CARTESIAN_POINT('',(1.3175E0,0.E0,6.E0)); #4486=CARTESIAN_POINT('',(9.325E-1,0.E0,6.E0)); #4487=VERTEX_POINT('',#4485); #4488=VERTEX_POINT('',#4486); #4489=CARTESIAN_POINT('',(1.3825E0,1.E0,6.E0)); #4490=CARTESIAN_POINT('',(8.675E-1,1.E0,6.E0)); #4491=VERTEX_POINT('',#4489); #4492=VERTEX_POINT('',#4490); #4493=CARTESIAN_POINT('',(1.3825E0,1.5E0,6.E0)); #4494=CARTESIAN_POINT('',(8.675E-1,1.5E0,6.E0)); #4495=VERTEX_POINT('',#4493); #4496=VERTEX_POINT('',#4494); #4497=CARTESIAN_POINT('',(1.3175E0,1.E0,6.E0)); #4498=CARTESIAN_POINT('',(9.325E-1,1.E0,6.E0)); #4499=VERTEX_POINT('',#4497); #4500=VERTEX_POINT('',#4498); #4501=CARTESIAN_POINT('',(1.3175E0,0.E0,1.2E1)); #4502=CARTESIAN_POINT('',(9.325E-1,0.E0,1.2E1)); #4503=VERTEX_POINT('',#4501); #4504=VERTEX_POINT('',#4502); #4505=CARTESIAN_POINT('',(1.3175E0,0.E0,1.8E1)); #4506=CARTESIAN_POINT('',(9.325E-1,0.E0,1.8E1)); #4507=VERTEX_POINT('',#4505); #4508=VERTEX_POINT('',#4506); #4509=CARTESIAN_POINT('',(1.3175E0,0.E0,2.4E1)); #4510=CARTESIAN_POINT('',(9.325E-1,0.E0,2.4E1)); #4511=VERTEX_POINT('',#4509); #4512=VERTEX_POINT('',#4510); #4513=CARTESIAN_POINT('',(2.30675E1,0.E0,6.E0)); #4514=CARTESIAN_POINT('',(2.26825E1,0.E0,6.E0)); #4515=VERTEX_POINT('',#4513); #4516=VERTEX_POINT('',#4514); #4517=CARTESIAN_POINT('',(2.30675E1,0.E0,1.2E1)); #4518=CARTESIAN_POINT('',(2.26825E1,0.E0,1.2E1)); #4519=VERTEX_POINT('',#4517); #4520=VERTEX_POINT('',#4518); #4521=CARTESIAN_POINT('',(2.30675E1,0.E0,1.8E1)); #4522=CARTESIAN_POINT('',(2.26825E1,0.E0,1.8E1)); #4523=VERTEX_POINT('',#4521); #4524=VERTEX_POINT('',#4522); #4525=CARTESIAN_POINT('',(2.30675E1,0.E0,2.4E1)); #4526=CARTESIAN_POINT('',(2.26825E1,0.E0,2.4E1)); #4527=VERTEX_POINT('',#4525); #4528=VERTEX_POINT('',#4526); #4529=CARTESIAN_POINT('',(1.3825E0,1.E0,1.2E1)); #4530=CARTESIAN_POINT('',(8.675E-1,1.E0,1.2E1)); #4531=VERTEX_POINT('',#4529); #4532=VERTEX_POINT('',#4530); #4533=CARTESIAN_POINT('',(1.3175E0,1.E0,1.2E1)); #4534=CARTESIAN_POINT('',(9.325E-1,1.E0,1.2E1)); #4535=VERTEX_POINT('',#4533); #4536=VERTEX_POINT('',#4534); #4537=CARTESIAN_POINT('',(1.3825E0,1.E0,1.8E1)); #4538=CARTESIAN_POINT('',(8.675E-1,1.E0,1.8E1)); #4539=VERTEX_POINT('',#4537); #4540=VERTEX_POINT('',#4538); #4541=CARTESIAN_POINT('',(1.3825E0,1.5E0,1.8E1)); #4542=CARTESIAN_POINT('',(8.675E-1,1.5E0,1.8E1)); #4543=VERTEX_POINT('',#4541); #4544=VERTEX_POINT('',#4542); #4545=CARTESIAN_POINT('',(1.3175E0,1.E0,1.8E1)); #4546=CARTESIAN_POINT('',(9.325E-1,1.E0,1.8E1)); #4547=VERTEX_POINT('',#4545); #4548=VERTEX_POINT('',#4546); #4549=CARTESIAN_POINT('',(1.3825E0,1.E0,2.4E1)); #4550=CARTESIAN_POINT('',(8.675E-1,1.E0,2.4E1)); #4551=VERTEX_POINT('',#4549); #4552=VERTEX_POINT('',#4550); #4553=CARTESIAN_POINT('',(1.3825E0,1.5E0,2.4E1)); #4554=CARTESIAN_POINT('',(8.675E-1,1.5E0,2.4E1)); #4555=VERTEX_POINT('',#4553); #4556=VERTEX_POINT('',#4554); #4557=CARTESIAN_POINT('',(1.3175E0,1.E0,2.4E1)); #4558=CARTESIAN_POINT('',(9.325E-1,1.E0,2.4E1)); #4559=VERTEX_POINT('',#4557); #4560=VERTEX_POINT('',#4558); #4561=CARTESIAN_POINT('',(2.31325E1,1.E0,6.E0)); #4562=CARTESIAN_POINT('',(2.26175E1,1.E0,6.E0)); #4563=VERTEX_POINT('',#4561); #4564=VERTEX_POINT('',#4562); #4565=CARTESIAN_POINT('',(2.31325E1,1.5E0,6.E0)); #4566=CARTESIAN_POINT('',(2.26175E1,1.5E0,6.E0)); #4567=VERTEX_POINT('',#4565); #4568=VERTEX_POINT('',#4566); #4569=CARTESIAN_POINT('',(2.30675E1,1.E0,6.E0)); #4570=CARTESIAN_POINT('',(2.26825E1,1.E0,6.E0)); #4571=VERTEX_POINT('',#4569); #4572=VERTEX_POINT('',#4570); #4573=CARTESIAN_POINT('',(2.31325E1,1.E0,1.2E1)); #4574=CARTESIAN_POINT('',(2.26175E1,1.E0,1.2E1)); #4575=VERTEX_POINT('',#4573); #4576=VERTEX_POINT('',#4574); #4577=CARTESIAN_POINT('',(2.30675E1,1.E0,1.2E1)); #4578=CARTESIAN_POINT('',(2.26825E1,1.E0,1.2E1)); #4579=VERTEX_POINT('',#4577); #4580=VERTEX_POINT('',#4578); #4581=CARTESIAN_POINT('',(2.31325E1,1.E0,1.8E1)); #4582=CARTESIAN_POINT('',(2.26175E1,1.E0,1.8E1)); #4583=VERTEX_POINT('',#4581); #4584=VERTEX_POINT('',#4582); #4585=CARTESIAN_POINT('',(2.31325E1,1.5E0,1.8E1)); #4586=CARTESIAN_POINT('',(2.26175E1,1.5E0,1.8E1)); #4587=VERTEX_POINT('',#4585); #4588=VERTEX_POINT('',#4586); #4589=CARTESIAN_POINT('',(2.30675E1,1.E0,1.8E1)); #4590=CARTESIAN_POINT('',(2.26825E1,1.E0,1.8E1)); #4591=VERTEX_POINT('',#4589); #4592=VERTEX_POINT('',#4590); #4593=CARTESIAN_POINT('',(2.31325E1,1.E0,2.4E1)); #4594=CARTESIAN_POINT('',(2.26175E1,1.E0,2.4E1)); #4595=VERTEX_POINT('',#4593); #4596=VERTEX_POINT('',#4594); #4597=CARTESIAN_POINT('',(2.31325E1,1.5E0,2.4E1)); #4598=CARTESIAN_POINT('',(2.26175E1,1.5E0,2.4E1)); #4599=VERTEX_POINT('',#4597); #4600=VERTEX_POINT('',#4598); #4601=CARTESIAN_POINT('',(2.30675E1,1.E0,2.4E1)); #4602=CARTESIAN_POINT('',(2.26825E1,1.E0,2.4E1)); #4603=VERTEX_POINT('',#4601); #4604=VERTEX_POINT('',#4602); #4605=CARTESIAN_POINT('',(6.1925E0,0.E0,1.25E0)); #4606=CARTESIAN_POINT('',(5.8075E0,0.E0,1.25E0)); #4607=VERTEX_POINT('',#4605); #4608=VERTEX_POINT('',#4606); #4609=CARTESIAN_POINT('',(6.256E0,1.E0,1.25E0)); #4610=CARTESIAN_POINT('',(5.744E0,1.E0,1.25E0)); #4611=VERTEX_POINT('',#4609); #4612=VERTEX_POINT('',#4610); #4613=CARTESIAN_POINT('',(6.256E0,1.5E0,1.25E0)); #4614=CARTESIAN_POINT('',(5.744E0,1.5E0,1.25E0)); #4615=VERTEX_POINT('',#4613); #4616=VERTEX_POINT('',#4614); #4617=CARTESIAN_POINT('',(6.1925E0,1.E0,1.25E0)); #4618=CARTESIAN_POINT('',(5.8075E0,1.E0,1.25E0)); #4619=VERTEX_POINT('',#4617); #4620=VERTEX_POINT('',#4618); #4621=CARTESIAN_POINT('',(1.21925E1,0.E0,1.25E0)); #4622=CARTESIAN_POINT('',(1.18075E1,0.E0,1.25E0)); #4623=VERTEX_POINT('',#4621); #4624=VERTEX_POINT('',#4622); #4625=CARTESIAN_POINT('',(6.1925E0,0.E0,3.075E1)); #4626=CARTESIAN_POINT('',(5.8075E0,0.E0,3.075E1)); #4627=VERTEX_POINT('',#4625); #4628=VERTEX_POINT('',#4626); #4629=CARTESIAN_POINT('',(1.21925E1,0.E0,3.075E1)); #4630=CARTESIAN_POINT('',(1.18075E1,0.E0,3.075E1)); #4631=VERTEX_POINT('',#4629); #4632=VERTEX_POINT('',#4630); #4633=CARTESIAN_POINT('',(1.81925E1,0.E0,1.25E0)); #4634=CARTESIAN_POINT('',(1.78075E1,0.E0,1.25E0)); #4635=VERTEX_POINT('',#4633); #4636=VERTEX_POINT('',#4634); #4637=CARTESIAN_POINT('',(1.81925E1,0.E0,3.075E1)); #4638=CARTESIAN_POINT('',(1.78075E1,0.E0,3.075E1)); #4639=VERTEX_POINT('',#4637); #4640=VERTEX_POINT('',#4638); #4641=CARTESIAN_POINT('',(1.2256E1,1.E0,1.25E0)); #4642=CARTESIAN_POINT('',(1.1744E1,1.E0,1.25E0)); #4643=VERTEX_POINT('',#4641); #4644=VERTEX_POINT('',#4642); #4645=CARTESIAN_POINT('',(1.2256E1,1.5E0,1.25E0)); #4646=CARTESIAN_POINT('',(1.1744E1,1.5E0,1.25E0)); #4647=VERTEX_POINT('',#4645); #4648=VERTEX_POINT('',#4646); #4649=CARTESIAN_POINT('',(1.21925E1,1.E0,1.25E0)); #4650=CARTESIAN_POINT('',(1.18075E1,1.E0,1.25E0)); #4651=VERTEX_POINT('',#4649); #4652=VERTEX_POINT('',#4650); #4653=CARTESIAN_POINT('',(1.8256E1,1.E0,1.25E0)); #4654=CARTESIAN_POINT('',(1.7744E1,1.E0,1.25E0)); #4655=VERTEX_POINT('',#4653); #4656=VERTEX_POINT('',#4654); #4657=CARTESIAN_POINT('',(1.8256E1,1.5E0,1.25E0)); #4658=CARTESIAN_POINT('',(1.7744E1,1.5E0,1.25E0)); #4659=VERTEX_POINT('',#4657); #4660=VERTEX_POINT('',#4658); #4661=CARTESIAN_POINT('',(1.81925E1,1.E0,1.25E0)); #4662=CARTESIAN_POINT('',(1.78075E1,1.E0,1.25E0)); #4663=VERTEX_POINT('',#4661); #4664=VERTEX_POINT('',#4662); #4665=CARTESIAN_POINT('',(6.256E0,1.E0,3.075E1)); #4666=CARTESIAN_POINT('',(5.744E0,1.E0,3.075E1)); #4667=VERTEX_POINT('',#4665); #4668=VERTEX_POINT('',#4666); #4669=CARTESIAN_POINT('',(6.256E0,1.5E0,3.075E1)); #4670=CARTESIAN_POINT('',(5.744E0,1.5E0,3.075E1)); #4671=VERTEX_POINT('',#4669); #4672=VERTEX_POINT('',#4670); #4673=CARTESIAN_POINT('',(6.1925E0,1.E0,3.075E1)); #4674=CARTESIAN_POINT('',(5.8075E0,1.E0,3.075E1)); #4675=VERTEX_POINT('',#4673); #4676=VERTEX_POINT('',#4674); #4677=CARTESIAN_POINT('',(1.2256E1,1.E0,3.075E1)); #4678=CARTESIAN_POINT('',(1.1744E1,1.E0,3.075E1)); #4679=VERTEX_POINT('',#4677); #4680=VERTEX_POINT('',#4678); #4681=CARTESIAN_POINT('',(1.2256E1,1.5E0,3.075E1)); #4682=CARTESIAN_POINT('',(1.1744E1,1.5E0,3.075E1)); #4683=VERTEX_POINT('',#4681); #4684=VERTEX_POINT('',#4682); #4685=CARTESIAN_POINT('',(1.21925E1,1.E0,3.075E1)); #4686=CARTESIAN_POINT('',(1.18075E1,1.E0,3.075E1)); #4687=VERTEX_POINT('',#4685); #4688=VERTEX_POINT('',#4686); #4689=CARTESIAN_POINT('',(1.8256E1,1.E0,3.075E1)); #4690=CARTESIAN_POINT('',(1.7744E1,1.E0,3.075E1)); #4691=VERTEX_POINT('',#4689); #4692=VERTEX_POINT('',#4690); #4693=CARTESIAN_POINT('',(1.8256E1,1.5E0,3.075E1)); #4694=CARTESIAN_POINT('',(1.7744E1,1.5E0,3.075E1)); #4695=VERTEX_POINT('',#4693); #4696=VERTEX_POINT('',#4694); #4697=CARTESIAN_POINT('',(1.81925E1,1.E0,3.075E1)); #4698=CARTESIAN_POINT('',(1.78075E1,1.E0,3.075E1)); #4699=VERTEX_POINT('',#4697); #4700=VERTEX_POINT('',#4698); #4701=CARTESIAN_POINT('',(4.4125E0,1.05E1,8.E0)); #4702=CARTESIAN_POINT('',(4.0875E0,1.05E1,8.E0)); #4703=VERTEX_POINT('',#4701); #4704=VERTEX_POINT('',#4702); #4705=CARTESIAN_POINT('',(4.4125E0,1.05E1,1.E1)); #4706=CARTESIAN_POINT('',(4.0875E0,1.05E1,1.E1)); #4707=VERTEX_POINT('',#4705); #4708=VERTEX_POINT('',#4706); #4709=CARTESIAN_POINT('',(4.345E0,1.09375E1,8.25E0)); #4710=CARTESIAN_POINT('',(4.155E0,1.09375E1,8.25E0)); #4711=VERTEX_POINT('',#4709); #4712=VERTEX_POINT('',#4710); #4713=CARTESIAN_POINT('',(4.345E0,1.09375E1,8.E0)); #4714=CARTESIAN_POINT('',(4.155E0,1.09375E1,8.E0)); #4715=VERTEX_POINT('',#4713); #4716=VERTEX_POINT('',#4714); #4717=CARTESIAN_POINT('',(3.9075E0,1.05E1,8.25E0)); #4718=CARTESIAN_POINT('',(3.7175E0,1.05E1,8.25E0)); #4719=VERTEX_POINT('',#4717); #4720=VERTEX_POINT('',#4718); #4721=CARTESIAN_POINT('',(3.9075E0,1.05E1,8.E0)); #4722=CARTESIAN_POINT('',(3.7175E0,1.05E1,8.E0)); #4723=VERTEX_POINT('',#4721); #4724=VERTEX_POINT('',#4722); #4725=CARTESIAN_POINT('',(4.345E0,1.00625E1,8.25E0)); #4726=CARTESIAN_POINT('',(4.155E0,1.00625E1,8.25E0)); #4727=VERTEX_POINT('',#4725); #4728=VERTEX_POINT('',#4726); #4729=CARTESIAN_POINT('',(4.345E0,1.00625E1,8.E0)); #4730=CARTESIAN_POINT('',(4.155E0,1.00625E1,8.E0)); #4731=VERTEX_POINT('',#4729); #4732=VERTEX_POINT('',#4730); #4733=CARTESIAN_POINT('',(1.95875E1,1.05E1,8.E0)); #4734=CARTESIAN_POINT('',(1.99125E1,1.05E1,8.E0)); #4735=VERTEX_POINT('',#4733); #4736=VERTEX_POINT('',#4734); #4737=CARTESIAN_POINT('',(1.95875E1,1.05E1,1.E1)); #4738=CARTESIAN_POINT('',(1.99125E1,1.05E1,1.E1)); #4739=VERTEX_POINT('',#4737); #4740=VERTEX_POINT('',#4738); #4741=CARTESIAN_POINT('',(1.9655E1,1.09375E1,8.25E0)); #4742=CARTESIAN_POINT('',(1.9845E1,1.09375E1,8.25E0)); #4743=VERTEX_POINT('',#4741); #4744=VERTEX_POINT('',#4742); #4745=CARTESIAN_POINT('',(1.9655E1,1.09375E1,8.E0)); #4746=CARTESIAN_POINT('',(1.9845E1,1.09375E1,8.E0)); #4747=VERTEX_POINT('',#4745); #4748=VERTEX_POINT('',#4746); #4749=CARTESIAN_POINT('',(2.00925E1,1.05E1,8.25E0)); #4750=CARTESIAN_POINT('',(2.02825E1,1.05E1,8.25E0)); #4751=VERTEX_POINT('',#4749); #4752=VERTEX_POINT('',#4750); #4753=CARTESIAN_POINT('',(2.00925E1,1.05E1,8.E0)); #4754=CARTESIAN_POINT('',(2.02825E1,1.05E1,8.E0)); #4755=VERTEX_POINT('',#4753); #4756=VERTEX_POINT('',#4754); #4757=CARTESIAN_POINT('',(1.9655E1,1.00625E1,8.25E0)); #4758=CARTESIAN_POINT('',(1.9845E1,1.00625E1,8.25E0)); #4759=VERTEX_POINT('',#4757); #4760=VERTEX_POINT('',#4758); #4761=CARTESIAN_POINT('',(1.9655E1,1.00625E1,8.E0)); #4762=CARTESIAN_POINT('',(1.9845E1,1.00625E1,8.E0)); #4763=VERTEX_POINT('',#4761); #4764=VERTEX_POINT('',#4762); #4765=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0)); #4766=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0)); #4767=VERTEX_POINT('',#4765); #4768=VERTEX_POINT('',#4766); #4769=CARTESIAN_POINT('',(5.E0,1.5E0,1.1E1)); #4770=CARTESIAN_POINT('',(5.E0,0.E0,1.1E1)); #4771=VERTEX_POINT('',#4769); #4772=VERTEX_POINT('',#4770); #4773=CARTESIAN_POINT('',(6.E0,1.5E0,1.E1)); #4774=CARTESIAN_POINT('',(6.E0,0.E0,1.E1)); #4775=VERTEX_POINT('',#4773); #4776=VERTEX_POINT('',#4774); #4777=CARTESIAN_POINT('',(1.9E1,0.E0,1.1E1)); #4778=CARTESIAN_POINT('',(1.9E1,1.5E0,1.1E1)); #4779=VERTEX_POINT('',#4777); #4780=VERTEX_POINT('',#4778); #4781=CARTESIAN_POINT('',(1.8E1,0.E0,1.E1)); #4782=CARTESIAN_POINT('',(1.8E1,1.5E0,1.E1)); #4783=VERTEX_POINT('',#4781); #4784=VERTEX_POINT('',#4782); #4785=CARTESIAN_POINT('',(5.E0,1.5E0,1.E1)); #4786=VERTEX_POINT('',#4785); #4787=CARTESIAN_POINT('',(1.9E1,1.5E0,1.E1)); #4788=VERTEX_POINT('',#4787); #4789=CARTESIAN_POINT('',(2.5E0,1.5E0,2.19375E1)); #4790=CARTESIAN_POINT('',(2.5E0,0.E0,2.19375E1)); #4791=VERTEX_POINT('',#4789); #4792=VERTEX_POINT('',#4790); #4793=CARTESIAN_POINT('',(5.5E0,1.5E0,1.89375E1)); #4794=CARTESIAN_POINT('',(5.5E0,0.E0,1.89375E1)); #4795=VERTEX_POINT('',#4793); #4796=VERTEX_POINT('',#4794); #4797=CARTESIAN_POINT('',(2.15E1,0.E0,2.19375E1)); #4798=CARTESIAN_POINT('',(2.15E1,1.5E0,2.19375E1)); #4799=VERTEX_POINT('',#4797); #4800=VERTEX_POINT('',#4798); #4801=CARTESIAN_POINT('',(1.85E1,0.E0,1.89375E1)); #4802=CARTESIAN_POINT('',(1.85E1,1.5E0,1.89375E1)); #4803=VERTEX_POINT('',#4801); #4804=VERTEX_POINT('',#4802); #4805=CARTESIAN_POINT('',(2.15E1,1.5E0,1.40625E1)); #4806=CARTESIAN_POINT('',(2.15E1,0.E0,1.40625E1)); #4807=VERTEX_POINT('',#4805); #4808=VERTEX_POINT('',#4806); #4809=CARTESIAN_POINT('',(1.85E1,1.5E0,1.70625E1)); #4810=CARTESIAN_POINT('',(1.85E1,0.E0,1.70625E1)); #4811=VERTEX_POINT('',#4809); #4812=VERTEX_POINT('',#4810); #4813=CARTESIAN_POINT('',(2.5E0,0.E0,1.40625E1)); #4814=CARTESIAN_POINT('',(2.5E0,1.5E0,1.40625E1)); #4815=VERTEX_POINT('',#4813); #4816=VERTEX_POINT('',#4814); #4817=CARTESIAN_POINT('',(5.5E0,0.E0,1.70625E1)); #4818=CARTESIAN_POINT('',(5.5E0,1.5E0,1.70625E1)); #4819=VERTEX_POINT('',#4817); #4820=VERTEX_POINT('',#4818); #4821=CARTESIAN_POINT('',(6.1925E0,0.E0,9.E0)); #4822=CARTESIAN_POINT('',(5.8075E0,0.E0,9.E0)); #4823=VERTEX_POINT('',#4821); #4824=VERTEX_POINT('',#4822); #4825=CARTESIAN_POINT('',(6.2575E0,1.E0,9.E0)); #4826=CARTESIAN_POINT('',(5.7425E0,1.E0,9.E0)); #4827=VERTEX_POINT('',#4825); #4828=VERTEX_POINT('',#4826); #4829=CARTESIAN_POINT('',(6.2575E0,1.5E0,9.E0)); #4830=CARTESIAN_POINT('',(5.7425E0,1.5E0,9.E0)); #4831=VERTEX_POINT('',#4829); #4832=VERTEX_POINT('',#4830); #4833=CARTESIAN_POINT('',(6.1925E0,1.E0,9.E0)); #4834=CARTESIAN_POINT('',(5.8075E0,1.E0,9.E0)); #4835=VERTEX_POINT('',#4833); #4836=VERTEX_POINT('',#4834); #4837=CARTESIAN_POINT('',(1.21925E1,0.E0,9.E0)); #4838=CARTESIAN_POINT('',(1.18075E1,0.E0,9.E0)); #4839=VERTEX_POINT('',#4837); #4840=VERTEX_POINT('',#4838); #4841=CARTESIAN_POINT('',(1.81925E1,0.E0,9.E0)); #4842=CARTESIAN_POINT('',(1.78075E1,0.E0,9.E0)); #4843=VERTEX_POINT('',#4841); #4844=VERTEX_POINT('',#4842); #4845=CARTESIAN_POINT('',(6.1925E0,0.E0,1.8E1)); #4846=CARTESIAN_POINT('',(5.8075E0,0.E0,1.8E1)); #4847=VERTEX_POINT('',#4845); #4848=VERTEX_POINT('',#4846); #4849=CARTESIAN_POINT('',(1.21925E1,0.E0,1.8E1)); #4850=CARTESIAN_POINT('',(1.18075E1,0.E0,1.8E1)); #4851=VERTEX_POINT('',#4849); #4852=VERTEX_POINT('',#4850); #4853=CARTESIAN_POINT('',(1.81925E1,0.E0,1.8E1)); #4854=CARTESIAN_POINT('',(1.78075E1,0.E0,1.8E1)); #4855=VERTEX_POINT('',#4853); #4856=VERTEX_POINT('',#4854); #4857=CARTESIAN_POINT('',(1.22575E1,1.E0,9.E0)); #4858=CARTESIAN_POINT('',(1.17425E1,1.E0,9.E0)); #4859=VERTEX_POINT('',#4857); #4860=VERTEX_POINT('',#4858); #4861=CARTESIAN_POINT('',(1.22575E1,1.5E0,9.E0)); #4862=CARTESIAN_POINT('',(1.17425E1,1.5E0,9.E0)); #4863=VERTEX_POINT('',#4861); #4864=VERTEX_POINT('',#4862); #4865=CARTESIAN_POINT('',(1.21925E1,1.E0,9.E0)); #4866=CARTESIAN_POINT('',(1.18075E1,1.E0,9.E0)); #4867=VERTEX_POINT('',#4865); #4868=VERTEX_POINT('',#4866); #4869=CARTESIAN_POINT('',(1.82575E1,1.E0,9.E0)); #4870=CARTESIAN_POINT('',(1.77425E1,1.E0,9.E0)); #4871=VERTEX_POINT('',#4869); #4872=VERTEX_POINT('',#4870); #4873=CARTESIAN_POINT('',(1.82575E1,1.5E0,9.E0)); #4874=CARTESIAN_POINT('',(1.77425E1,1.5E0,9.E0)); #4875=VERTEX_POINT('',#4873); #4876=VERTEX_POINT('',#4874); #4877=CARTESIAN_POINT('',(1.81925E1,1.E0,9.E0)); #4878=CARTESIAN_POINT('',(1.78075E1,1.E0,9.E0)); #4879=VERTEX_POINT('',#4877); #4880=VERTEX_POINT('',#4878); #4881=CARTESIAN_POINT('',(6.2575E0,1.E0,1.8E1)); #4882=CARTESIAN_POINT('',(5.7425E0,1.E0,1.8E1)); #4883=VERTEX_POINT('',#4881); #4884=VERTEX_POINT('',#4882); #4885=CARTESIAN_POINT('',(6.2575E0,1.5E0,1.8E1)); #4886=CARTESIAN_POINT('',(5.7425E0,1.5E0,1.8E1)); #4887=VERTEX_POINT('',#4885); #4888=VERTEX_POINT('',#4886); #4889=CARTESIAN_POINT('',(6.1925E0,1.E0,1.8E1)); #4890=CARTESIAN_POINT('',(5.8075E0,1.E0,1.8E1)); #4891=VERTEX_POINT('',#4889); #4892=VERTEX_POINT('',#4890); #4893=CARTESIAN_POINT('',(1.22575E1,1.E0,1.8E1)); #4894=CARTESIAN_POINT('',(1.17425E1,1.E0,1.8E1)); #4895=VERTEX_POINT('',#4893); #4896=VERTEX_POINT('',#4894); #4897=CARTESIAN_POINT('',(1.22575E1,1.5E0,1.8E1)); #4898=CARTESIAN_POINT('',(1.17425E1,1.5E0,1.8E1)); #4899=VERTEX_POINT('',#4897); #4900=VERTEX_POINT('',#4898); #4901=CARTESIAN_POINT('',(1.21925E1,1.E0,1.8E1)); #4902=CARTESIAN_POINT('',(1.18075E1,1.E0,1.8E1)); #4903=VERTEX_POINT('',#4901); #4904=VERTEX_POINT('',#4902); #4905=CARTESIAN_POINT('',(1.82575E1,1.E0,1.8E1)); #4906=CARTESIAN_POINT('',(1.77425E1,1.E0,1.8E1)); #4907=VERTEX_POINT('',#4905); #4908=VERTEX_POINT('',#4906); #4909=CARTESIAN_POINT('',(1.82575E1,1.5E0,1.8E1)); #4910=CARTESIAN_POINT('',(1.77425E1,1.5E0,1.8E1)); #4911=VERTEX_POINT('',#4909); #4912=VERTEX_POINT('',#4910); #4913=CARTESIAN_POINT('',(1.81925E1,1.E0,1.8E1)); #4914=CARTESIAN_POINT('',(1.78075E1,1.E0,1.8E1)); #4915=VERTEX_POINT('',#4913); #4916=VERTEX_POINT('',#4914); #4917=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.288675134595E1)); #4918=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.E1)); #4919=VERTEX_POINT('',#4917); #4920=VERTEX_POINT('',#4918); #4921=CARTESIAN_POINT('',(2.E0,1.5E0,1.288675134595E1)); #4922=CARTESIAN_POINT('',(2.E0,1.5E0,1.E1)); #4923=VERTEX_POINT('',#4921); #4924=VERTEX_POINT('',#4922); #4925=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1)); #4926=VERTEX_POINT('',#4925); #4927=CARTESIAN_POINT('',(2.E0,6.5E0,1.E1)); #4928=VERTEX_POINT('',#4927); #4929=VERTEX_POINT('',#1837); #4930=VERTEX_POINT('',#1845); #4931=CARTESIAN_POINT('',(2.375E1,1.5E0,1.288675134595E1)); #4932=CARTESIAN_POINT('',(2.375E1,1.5E0,1.E1)); #4933=VERTEX_POINT('',#4931); #4934=VERTEX_POINT('',#4932); #4935=CARTESIAN_POINT('',(2.2E1,1.5E0,1.288675134595E1)); #4936=CARTESIAN_POINT('',(2.2E1,1.5E0,1.E1)); #4937=VERTEX_POINT('',#4935); #4938=VERTEX_POINT('',#4936); #4939=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1)); #4940=VERTEX_POINT('',#4939); #4941=CARTESIAN_POINT('',(2.2E1,6.5E0,1.E1)); #4942=VERTEX_POINT('',#4941); #4943=VERTEX_POINT('',#2873); #4944=VERTEX_POINT('',#2881); #4945=CARTESIAN_POINT('',(3.75E0,2.E0,8.E0)); #4946=CARTESIAN_POINT('',(3.75E0,2.E0,8.5E0)); #4947=VERTEX_POINT('',#4945); #4948=VERTEX_POINT('',#4946); #4949=CARTESIAN_POINT('',(4.5E0,2.75E0,8.E0)); #4950=CARTESIAN_POINT('',(4.5E0,2.75E0,8.5E0)); #4951=VERTEX_POINT('',#4949); #4952=VERTEX_POINT('',#4950); #4953=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.E0)); #4954=CARTESIAN_POINT('',(-8.007907113711E-1,3.114232198384E0,8.5E0)); #4955=VERTEX_POINT('',#4953); #4956=VERTEX_POINT('',#4954); #4957=CARTESIAN_POINT('',(-1.451727542799E-1,2.E0,8.E0)); #4958=CARTESIAN_POINT('',(-1.451727542799E-1,2.E0,8.5E0)); #4959=VERTEX_POINT('',#4957); #4960=VERTEX_POINT('',#4958); #4961=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.E0)); #4962=CARTESIAN_POINT('',(3.188160579053E0,9.5E0,8.5E0)); #4963=VERTEX_POINT('',#4961); #4964=VERTEX_POINT('',#4962); #4965=CARTESIAN_POINT('',(2.532542621962E0,9.114232198384E0,8.E0)); #4966=CARTESIAN_POINT('',(2.532542621962E0,9.114232198384E0,8.5E0)); #4967=VERTEX_POINT('',#4965); #4968=VERTEX_POINT('',#4966); #4969=CARTESIAN_POINT('',(4.5E0,8.75E0,8.E0)); #4970=CARTESIAN_POINT('',(4.5E0,8.75E0,8.5E0)); #4971=VERTEX_POINT('',#4969); #4972=VERTEX_POINT('',#4970); #4973=CARTESIAN_POINT('',(3.75E0,9.5E0,8.E0)); #4974=CARTESIAN_POINT('',(3.75E0,9.5E0,8.5E0)); #4975=VERTEX_POINT('',#4973); #4976=VERTEX_POINT('',#4974); #4977=CARTESIAN_POINT('',(2.85E0,2.E0,1.E1)); #4978=CARTESIAN_POINT('',(2.85E0,2.E0,9.5E0)); #4979=VERTEX_POINT('',#4977); #4980=VERTEX_POINT('',#4978); #4981=CARTESIAN_POINT('',(2.5E0,2.35E0,1.E1)); #4982=CARTESIAN_POINT('',(2.5E0,2.35E0,9.5E0)); #4983=VERTEX_POINT('',#4981); #4984=VERTEX_POINT('',#4982); #4985=CARTESIAN_POINT('',(4.5E0,2.35E0,1.E1)); #4986=CARTESIAN_POINT('',(4.5E0,2.35E0,9.5E0)); #4987=VERTEX_POINT('',#4985); #4988=VERTEX_POINT('',#4986); #4989=CARTESIAN_POINT('',(4.15E0,2.E0,1.E1)); #4990=CARTESIAN_POINT('',(4.15E0,2.E0,9.5E0)); #4991=VERTEX_POINT('',#4989); #4992=VERTEX_POINT('',#4990); #4993=CARTESIAN_POINT('',(1.952799239454E0,7.E0,1.E1)); #4994=CARTESIAN_POINT('',(1.952799239454E0,7.E0,9.5E0)); #4995=VERTEX_POINT('',#4993); #4996=VERTEX_POINT('',#4994); #4997=CARTESIAN_POINT('',(1.646844192811E0,7.519975025913E0,1.E1)); #4998=CARTESIAN_POINT('',(1.646844192811E0,7.519975025913E0,9.5E0)); #4999=VERTEX_POINT('',#4997); #5000=VERTEX_POINT('',#4998); #5001=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,1.E1)); #5002=CARTESIAN_POINT('',(2.646844192811E0,9.319975025913E0,9.5E0)); #5003=VERTEX_POINT('',#5001); #5004=VERTEX_POINT('',#5002); #5005=CARTESIAN_POINT('',(2.952799239454E0,9.5E0,1.E1)); #5006=CARTESIAN_POINT('',(2.952799239454E0,9.5E0,9.5E0)); #5007=VERTEX_POINT('',#5005); #5008=VERTEX_POINT('',#5006); #5009=CARTESIAN_POINT('',(4.15E0,9.5E0,1.E1)); #5010=CARTESIAN_POINT('',(4.15E0,9.5E0,9.5E0)); #5011=VERTEX_POINT('',#5009); #5012=VERTEX_POINT('',#5010); #5013=CARTESIAN_POINT('',(4.5E0,9.15E0,1.E1)); #5014=CARTESIAN_POINT('',(4.5E0,9.15E0,9.5E0)); #5015=VERTEX_POINT('',#5013); #5016=VERTEX_POINT('',#5014); #5017=CARTESIAN_POINT('',(2.5E0,6.65E0,9.5E0)); #5018=CARTESIAN_POINT('',(2.5E0,6.65E0,1.E1)); #5019=VERTEX_POINT('',#5017); #5020=VERTEX_POINT('',#5018); #5021=CARTESIAN_POINT('',(2.15E0,7.E0,1.E1)); #5022=VERTEX_POINT('',#5021); #5023=CARTESIAN_POINT('',(2.15E0,7.E0,9.5E0)); #5024=VERTEX_POINT('',#5023); #5025=CARTESIAN_POINT('',(2.025E1,2.E0,8.5E0)); #5026=CARTESIAN_POINT('',(2.025E1,2.E0,8.E0)); #5027=VERTEX_POINT('',#5025); #5028=VERTEX_POINT('',#5026); #5029=CARTESIAN_POINT('',(1.95E1,2.75E0,8.5E0)); #5030=VERTEX_POINT('',#5029); #5031=CARTESIAN_POINT('',(1.95E1,2.75E0,8.E0)); #5032=VERTEX_POINT('',#5031); #5033=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.5E0)); #5034=CARTESIAN_POINT('',(2.480079071137E1,3.114232198384E0,8.E0)); #5035=VERTEX_POINT('',#5033); #5036=VERTEX_POINT('',#5034); #5037=CARTESIAN_POINT('',(2.414517275428E1,2.E0,8.5E0)); #5038=VERTEX_POINT('',#5037); #5039=CARTESIAN_POINT('',(2.414517275428E1,2.E0,8.E0)); #5040=VERTEX_POINT('',#5039); #5041=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.5E0)); #5042=CARTESIAN_POINT('',(2.081183942095E1,9.5E0,8.E0)); #5043=VERTEX_POINT('',#5041); #5044=VERTEX_POINT('',#5042); #5045=CARTESIAN_POINT('',(2.146745737804E1,9.114232198384E0,8.5E0)); #5046=VERTEX_POINT('',#5045); #5047=CARTESIAN_POINT('',(2.146745737804E1,9.114232198384E0,8.E0)); #5048=VERTEX_POINT('',#5047); #5049=CARTESIAN_POINT('',(1.95E1,8.75E0,8.5E0)); #5050=CARTESIAN_POINT('',(1.95E1,8.75E0,8.E0)); #5051=VERTEX_POINT('',#5049); #5052=VERTEX_POINT('',#5050); #5053=CARTESIAN_POINT('',(2.025E1,9.5E0,8.5E0)); #5054=VERTEX_POINT('',#5053); #5055=CARTESIAN_POINT('',(2.025E1,9.5E0,8.E0)); #5056=VERTEX_POINT('',#5055); #5057=CARTESIAN_POINT('',(2.115E1,2.E0,9.5E0)); #5058=CARTESIAN_POINT('',(2.115E1,2.E0,1.E1)); #5059=VERTEX_POINT('',#5057); #5060=VERTEX_POINT('',#5058); #5061=CARTESIAN_POINT('',(2.15E1,2.35E0,9.5E0)); #5062=VERTEX_POINT('',#5061); #5063=CARTESIAN_POINT('',(2.15E1,2.35E0,1.E1)); #5064=VERTEX_POINT('',#5063); #5065=CARTESIAN_POINT('',(1.95E1,2.35E0,9.5E0)); #5066=CARTESIAN_POINT('',(1.95E1,2.35E0,1.E1)); #5067=VERTEX_POINT('',#5065); #5068=VERTEX_POINT('',#5066); #5069=CARTESIAN_POINT('',(1.985E1,2.E0,9.5E0)); #5070=VERTEX_POINT('',#5069); #5071=CARTESIAN_POINT('',(1.985E1,2.E0,1.E1)); #5072=VERTEX_POINT('',#5071); #5073=CARTESIAN_POINT('',(2.204720076055E1,7.E0,9.5E0)); #5074=CARTESIAN_POINT('',(2.204720076055E1,7.E0,1.E1)); #5075=VERTEX_POINT('',#5073); #5076=VERTEX_POINT('',#5074); #5077=CARTESIAN_POINT('',(2.235315580719E1,7.519975025913E0,9.5E0)); #5078=VERTEX_POINT('',#5077); #5079=CARTESIAN_POINT('',(2.235315580719E1,7.519975025913E0,1.E1)); #5080=VERTEX_POINT('',#5079); #5081=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,9.5E0)); #5082=CARTESIAN_POINT('',(2.135315580719E1,9.319975025913E0,1.E1)); #5083=VERTEX_POINT('',#5081); #5084=VERTEX_POINT('',#5082); #5085=CARTESIAN_POINT('',(2.104720076055E1,9.5E0,9.5E0)); #5086=VERTEX_POINT('',#5085); #5087=CARTESIAN_POINT('',(2.104720076055E1,9.5E0,1.E1)); #5088=VERTEX_POINT('',#5087); #5089=CARTESIAN_POINT('',(1.985E1,9.5E0,9.5E0)); #5090=CARTESIAN_POINT('',(1.985E1,9.5E0,1.E1)); #5091=VERTEX_POINT('',#5089); #5092=VERTEX_POINT('',#5090); #5093=CARTESIAN_POINT('',(1.95E1,9.15E0,9.5E0)); #5094=VERTEX_POINT('',#5093); #5095=CARTESIAN_POINT('',(1.95E1,9.15E0,1.E1)); #5096=VERTEX_POINT('',#5095); #5097=CARTESIAN_POINT('',(2.15E1,6.65E0,1.E1)); #5098=CARTESIAN_POINT('',(2.15E1,6.65E0,9.5E0)); #5099=VERTEX_POINT('',#5097); #5100=VERTEX_POINT('',#5098); #5101=CARTESIAN_POINT('',(2.185E1,7.E0,1.E1)); #5102=CARTESIAN_POINT('',(2.185E1,7.E0,9.5E0)); #5103=VERTEX_POINT('',#5101); #5104=VERTEX_POINT('',#5102); #5105=CARTESIAN_POINT('',(7.5E0,6.875E-1,6.875E-1)); #5106=CARTESIAN_POINT('',(1.05E1,6.875E-1,6.875E-1)); #5107=VERTEX_POINT('',#5105); #5108=VERTEX_POINT('',#5106); #5109=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.8125E0)); #5110=VERTEX_POINT('',#5109); #5111=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.8125E0)); #5112=VERTEX_POINT('',#5111); #5113=CARTESIAN_POINT('',(3.939978538987E0,6.875E-1,1.032293285145E0)); #5114=CARTESIAN_POINT('',(4.942849714544E0,6.875E-1,2.419779663480E0)); #5115=VERTEX_POINT('',#5113); #5116=VERTEX_POINT('',#5114); #5117=CARTESIAN_POINT('',(2.432015885023E0,6.875E-1,4.918683812405E0)); #5118=VERTEX_POINT('',#5117); #5119=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1)); #5120=CARTESIAN_POINT('',(1.05E1,0.E0,6.875E-1)); #5121=VERTEX_POINT('',#5119); #5122=VERTEX_POINT('',#5120); #5123=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0)); #5124=VERTEX_POINT('',#5123); #5125=CARTESIAN_POINT('',(7.5E0,0.E0,1.8125E0)); #5126=VERTEX_POINT('',#5125); #5127=CARTESIAN_POINT('',(3.939978538987E0,0.E0,1.032293285145E0)); #5128=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.419779663480E0)); #5129=VERTEX_POINT('',#5127); #5130=VERTEX_POINT('',#5128); #5131=CARTESIAN_POINT('',(2.432015885023E0,0.E0,4.918683812405E0)); #5132=VERTEX_POINT('',#5131); #5133=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,4.046865146430E0)); #5134=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,4.046865146430E0)); #5135=VERTEX_POINT('',#5133); #5136=VERTEX_POINT('',#5134); #5137=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,4.912826677187E0)); #5138=CARTESIAN_POINT('',(7.850270400779E-1,6.875E-1,4.912826677187E0)); #5139=VERTEX_POINT('',#5137); #5140=VERTEX_POINT('',#5138); #5141=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.5E0)); #5142=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.5E0)); #5143=VERTEX_POINT('',#5141); #5144=VERTEX_POINT('',#5142); #5145=CARTESIAN_POINT('',(6.9E-1,0.E0,7.5E0)); #5146=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0)); #5147=VERTEX_POINT('',#5145); #5148=VERTEX_POINT('',#5146); #5149=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.0375E1)); #5150=CARTESIAN_POINT('',(-1.3125E0,6.875E-1,1.0375E1)); #5151=VERTEX_POINT('',#5149); #5152=VERTEX_POINT('',#5150); #5153=CARTESIAN_POINT('',(-4.375E-1,0.E0,1.125E1)); #5154=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,1.125E1)); #5155=VERTEX_POINT('',#5153); #5156=VERTEX_POINT('',#5154); #5157=CARTESIAN_POINT('',(-4.375E-1,0.E0,8.69E0)); #5158=CARTESIAN_POINT('',(-4.375E-1,6.875E-1,8.69E0)); #5159=VERTEX_POINT('',#5157); #5160=VERTEX_POINT('',#5158); #5161=CARTESIAN_POINT('',(-1.3125E0,0.E0,9.565E0)); #5162=CARTESIAN_POINT('',(-1.3125E0,6.875E-1,9.565E0)); #5163=VERTEX_POINT('',#5161); #5164=VERTEX_POINT('',#5162); #5165=CARTESIAN_POINT('',(4.3125E0,0.E0,9.565E0)); #5166=CARTESIAN_POINT('',(4.3125E0,6.875E-1,9.565E0)); #5167=VERTEX_POINT('',#5165); #5168=VERTEX_POINT('',#5166); #5169=CARTESIAN_POINT('',(3.4375E0,0.E0,8.69E0)); #5170=CARTESIAN_POINT('',(3.4375E0,6.875E-1,8.69E0)); #5171=VERTEX_POINT('',#5169); #5172=VERTEX_POINT('',#5170); #5173=CARTESIAN_POINT('',(3.4375E0,0.E0,1.125E1)); #5174=CARTESIAN_POINT('',(3.4375E0,6.875E-1,1.125E1)); #5175=VERTEX_POINT('',#5173); #5176=VERTEX_POINT('',#5174); #5177=CARTESIAN_POINT('',(4.3125E0,0.E0,1.0375E1)); #5178=CARTESIAN_POINT('',(4.3125E0,6.875E-1,1.0375E1)); #5179=VERTEX_POINT('',#5177); #5180=VERTEX_POINT('',#5178); #5181=CARTESIAN_POINT('',(6.9E-1,6.875E-1,7.815E0)); #5182=CARTESIAN_POINT('',(6.9E-1,0.E0,7.815E0)); #5183=VERTEX_POINT('',#5181); #5184=VERTEX_POINT('',#5182); #5185=CARTESIAN_POINT('',(-1.85E-1,0.E0,8.69E0)); #5186=VERTEX_POINT('',#5185); #5187=CARTESIAN_POINT('',(-1.85E-1,6.875E-1,8.69E0)); #5188=VERTEX_POINT('',#5187); #5189=CARTESIAN_POINT('',(2.6875E0,6.875E-1,8.69E0)); #5190=CARTESIAN_POINT('',(2.6875E0,0.E0,8.69E0)); #5191=VERTEX_POINT('',#5189); #5192=VERTEX_POINT('',#5190); #5193=CARTESIAN_POINT('',(1.8125E0,0.E0,7.815E0)); #5194=VERTEX_POINT('',#5193); #5195=CARTESIAN_POINT('',(1.8125E0,6.875E-1,7.815E0)); #5196=VERTEX_POINT('',#5195); #5197=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.65E1)); #5198=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.35E1)); #5199=VERTEX_POINT('',#5197); #5200=VERTEX_POINT('',#5198); #5201=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.35E1)); #5202=VERTEX_POINT('',#5201); #5203=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.65E1)); #5204=VERTEX_POINT('',#5203); #5205=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1)); #5206=CARTESIAN_POINT('',(6.875E-1,0.E0,1.35E1)); #5207=VERTEX_POINT('',#5205); #5208=VERTEX_POINT('',#5206); #5209=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1)); #5210=VERTEX_POINT('',#5209); #5211=CARTESIAN_POINT('',(1.8125E0,0.E0,1.65E1)); #5212=VERTEX_POINT('',#5211); #5213=CARTESIAN_POINT('',(6.875E-1,6.875E-1,2.25E1)); #5214=CARTESIAN_POINT('',(6.875E-1,6.875E-1,1.95E1)); #5215=VERTEX_POINT('',#5213); #5216=VERTEX_POINT('',#5214); #5217=CARTESIAN_POINT('',(1.8125E0,6.875E-1,1.95E1)); #5218=VERTEX_POINT('',#5217); #5219=CARTESIAN_POINT('',(1.8125E0,6.875E-1,2.25E1)); #5220=VERTEX_POINT('',#5219); #5221=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1)); #5222=CARTESIAN_POINT('',(6.875E-1,0.E0,1.95E1)); #5223=VERTEX_POINT('',#5221); #5224=VERTEX_POINT('',#5222); #5225=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1)); #5226=VERTEX_POINT('',#5225); #5227=CARTESIAN_POINT('',(1.8125E0,0.E0,2.25E1)); #5228=VERTEX_POINT('',#5227); #5229=CARTESIAN_POINT('',(7.5E0,6.875E-1,8.5E0)); #5230=CARTESIAN_POINT('',(1.05E1,6.875E-1,8.5E0)); #5231=VERTEX_POINT('',#5229); #5232=VERTEX_POINT('',#5230); #5233=CARTESIAN_POINT('',(1.05E1,6.875E-1,9.5E0)); #5234=VERTEX_POINT('',#5233); #5235=CARTESIAN_POINT('',(7.5E0,6.875E-1,9.5E0)); #5236=VERTEX_POINT('',#5235); #5237=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0)); #5238=CARTESIAN_POINT('',(1.05E1,0.E0,8.5E0)); #5239=VERTEX_POINT('',#5237); #5240=VERTEX_POINT('',#5238); #5241=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0)); #5242=VERTEX_POINT('',#5241); #5243=CARTESIAN_POINT('',(7.5E0,0.E0,9.5E0)); #5244=VERTEX_POINT('',#5243); #5245=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.75625E1)); #5246=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.75625E1)); #5247=VERTEX_POINT('',#5245); #5248=VERTEX_POINT('',#5246); #5249=CARTESIAN_POINT('',(1.05E1,6.875E-1,1.84375E1)); #5250=VERTEX_POINT('',#5249); #5251=CARTESIAN_POINT('',(7.5E0,6.875E-1,1.84375E1)); #5252=VERTEX_POINT('',#5251); #5253=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1)); #5254=CARTESIAN_POINT('',(1.05E1,0.E0,1.75625E1)); #5255=VERTEX_POINT('',#5253); #5256=VERTEX_POINT('',#5254); #5257=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1)); #5258=VERTEX_POINT('',#5257); #5259=CARTESIAN_POINT('',(7.5E0,0.E0,1.84375E1)); #5260=VERTEX_POINT('',#5259); #5261=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.13125E1)); #5262=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.13125E1)); #5263=VERTEX_POINT('',#5261); #5264=VERTEX_POINT('',#5262); #5265=CARTESIAN_POINT('',(1.05E1,6.875E-1,3.01875E1)); #5266=VERTEX_POINT('',#5265); #5267=CARTESIAN_POINT('',(7.5E0,6.875E-1,3.01875E1)); #5268=VERTEX_POINT('',#5267); #5269=CARTESIAN_POINT('',(3.939978538987E0,6.875E-1,3.096770671486E1)); #5270=CARTESIAN_POINT('',(4.942849714544E0,6.875E-1,2.958022033652E1)); #5271=VERTEX_POINT('',#5269); #5272=VERTEX_POINT('',#5270); #5273=CARTESIAN_POINT('',(2.432015885023E0,6.875E-1,2.708131618759E1)); #5274=VERTEX_POINT('',#5273); #5275=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1)); #5276=CARTESIAN_POINT('',(1.05E1,0.E0,3.13125E1)); #5277=VERTEX_POINT('',#5275); #5278=VERTEX_POINT('',#5276); #5279=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1)); #5280=VERTEX_POINT('',#5279); #5281=CARTESIAN_POINT('',(7.5E0,0.E0,3.01875E1)); #5282=VERTEX_POINT('',#5281); #5283=CARTESIAN_POINT('',(3.939978538987E0,0.E0,3.096770671486E1)); #5284=CARTESIAN_POINT('',(4.942849714544E0,0.E0,2.958022033652E1)); #5285=VERTEX_POINT('',#5283); #5286=VERTEX_POINT('',#5284); #5287=CARTESIAN_POINT('',(2.432015885023E0,0.E0,2.708131618759E1)); #5288=VERTEX_POINT('',#5287); #5289=CARTESIAN_POINT('',(1.65E1,6.875E-1,6.875E-1)); #5290=CARTESIAN_POINT('',(1.35E1,6.875E-1,6.875E-1)); #5291=VERTEX_POINT('',#5289); #5292=VERTEX_POINT('',#5290); #5293=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.8125E0)); #5294=VERTEX_POINT('',#5293); #5295=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.8125E0)); #5296=VERTEX_POINT('',#5295); #5297=CARTESIAN_POINT('',(2.006002146101E1,6.875E-1,1.032293285145E0)); #5298=CARTESIAN_POINT('',(1.905715028546E1,6.875E-1,2.419779663480E0)); #5299=VERTEX_POINT('',#5297); #5300=VERTEX_POINT('',#5298); #5301=CARTESIAN_POINT('',(2.156798411498E1,6.875E-1,4.918683812405E0)); #5302=VERTEX_POINT('',#5301); #5303=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1)); #5304=CARTESIAN_POINT('',(1.35E1,0.E0,6.875E-1)); #5305=VERTEX_POINT('',#5303); #5306=VERTEX_POINT('',#5304); #5307=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0)); #5308=VERTEX_POINT('',#5307); #5309=CARTESIAN_POINT('',(1.65E1,0.E0,1.8125E0)); #5310=VERTEX_POINT('',#5309); #5311=CARTESIAN_POINT('',(2.006002146101E1,0.E0,1.032293285145E0)); #5312=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.419779663480E0)); #5313=VERTEX_POINT('',#5311); #5314=VERTEX_POINT('',#5312); #5315=CARTESIAN_POINT('',(2.156798411498E1,0.E0,4.918683812405E0)); #5316=VERTEX_POINT('',#5315); #5317=CARTESIAN_POINT('',(2.331E1,6.875E-1,7.5E0)); #5318=CARTESIAN_POINT('',(2.21875E1,6.875E-1,7.5E0)); #5319=VERTEX_POINT('',#5317); #5320=VERTEX_POINT('',#5318); #5321=CARTESIAN_POINT('',(2.331E1,0.E0,7.5E0)); #5322=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0)); #5323=VERTEX_POINT('',#5321); #5324=VERTEX_POINT('',#5322); #5325=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.65E1)); #5326=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.35E1)); #5327=VERTEX_POINT('',#5325); #5328=VERTEX_POINT('',#5326); #5329=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.35E1)); #5330=VERTEX_POINT('',#5329); #5331=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.65E1)); #5332=VERTEX_POINT('',#5331); #5333=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1)); #5334=CARTESIAN_POINT('',(2.33125E1,0.E0,1.35E1)); #5335=VERTEX_POINT('',#5333); #5336=VERTEX_POINT('',#5334); #5337=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1)); #5338=VERTEX_POINT('',#5337); #5339=CARTESIAN_POINT('',(2.21875E1,0.E0,1.65E1)); #5340=VERTEX_POINT('',#5339); #5341=CARTESIAN_POINT('',(2.33125E1,6.875E-1,2.25E1)); #5342=CARTESIAN_POINT('',(2.33125E1,6.875E-1,1.95E1)); #5343=VERTEX_POINT('',#5341); #5344=VERTEX_POINT('',#5342); #5345=CARTESIAN_POINT('',(2.21875E1,6.875E-1,1.95E1)); #5346=VERTEX_POINT('',#5345); #5347=CARTESIAN_POINT('',(2.21875E1,6.875E-1,2.25E1)); #5348=VERTEX_POINT('',#5347); #5349=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1)); #5350=CARTESIAN_POINT('',(2.33125E1,0.E0,1.95E1)); #5351=VERTEX_POINT('',#5349); #5352=VERTEX_POINT('',#5350); #5353=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1)); #5354=VERTEX_POINT('',#5353); #5355=CARTESIAN_POINT('',(2.21875E1,0.E0,2.25E1)); #5356=VERTEX_POINT('',#5355); #5357=CARTESIAN_POINT('',(1.65E1,6.875E-1,8.5E0)); #5358=CARTESIAN_POINT('',(1.35E1,6.875E-1,8.5E0)); #5359=VERTEX_POINT('',#5357); #5360=VERTEX_POINT('',#5358); #5361=CARTESIAN_POINT('',(1.35E1,6.875E-1,9.5E0)); #5362=VERTEX_POINT('',#5361); #5363=CARTESIAN_POINT('',(1.65E1,6.875E-1,9.5E0)); #5364=VERTEX_POINT('',#5363); #5365=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0)); #5366=CARTESIAN_POINT('',(1.35E1,0.E0,8.5E0)); #5367=VERTEX_POINT('',#5365); #5368=VERTEX_POINT('',#5366); #5369=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0)); #5370=VERTEX_POINT('',#5369); #5371=CARTESIAN_POINT('',(1.65E1,0.E0,9.5E0)); #5372=VERTEX_POINT('',#5371); #5373=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.75625E1)); #5374=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.75625E1)); #5375=VERTEX_POINT('',#5373); #5376=VERTEX_POINT('',#5374); #5377=CARTESIAN_POINT('',(1.35E1,6.875E-1,1.84375E1)); #5378=VERTEX_POINT('',#5377); #5379=CARTESIAN_POINT('',(1.65E1,6.875E-1,1.84375E1)); #5380=VERTEX_POINT('',#5379); #5381=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1)); #5382=CARTESIAN_POINT('',(1.35E1,0.E0,1.75625E1)); #5383=VERTEX_POINT('',#5381); #5384=VERTEX_POINT('',#5382); #5385=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1)); #5386=VERTEX_POINT('',#5385); #5387=CARTESIAN_POINT('',(1.65E1,0.E0,1.84375E1)); #5388=VERTEX_POINT('',#5387); #5389=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.13125E1)); #5390=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.13125E1)); #5391=VERTEX_POINT('',#5389); #5392=VERTEX_POINT('',#5390); #5393=CARTESIAN_POINT('',(1.35E1,6.875E-1,3.01875E1)); #5394=VERTEX_POINT('',#5393); #5395=CARTESIAN_POINT('',(1.65E1,6.875E-1,3.01875E1)); #5396=VERTEX_POINT('',#5395); #5397=CARTESIAN_POINT('',(2.006002146101E1,6.875E-1,3.096770671486E1)); #5398=CARTESIAN_POINT('',(1.905715028546E1,6.875E-1,2.958022033652E1)); #5399=VERTEX_POINT('',#5397); #5400=VERTEX_POINT('',#5398); #5401=CARTESIAN_POINT('',(2.156798411498E1,6.875E-1,2.708131618759E1)); #5402=VERTEX_POINT('',#5401); #5403=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1)); #5404=CARTESIAN_POINT('',(1.35E1,0.E0,3.13125E1)); #5405=VERTEX_POINT('',#5403); #5406=VERTEX_POINT('',#5404); #5407=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1)); #5408=VERTEX_POINT('',#5407); #5409=CARTESIAN_POINT('',(1.65E1,0.E0,3.01875E1)); #5410=VERTEX_POINT('',#5409); #5411=CARTESIAN_POINT('',(2.006002146101E1,0.E0,3.096770671486E1)); #5412=CARTESIAN_POINT('',(1.905715028546E1,0.E0,2.958022033652E1)); #5413=VERTEX_POINT('',#5411); #5414=VERTEX_POINT('',#5412); #5415=CARTESIAN_POINT('',(2.156798411498E1,0.E0,2.708131618759E1)); #5416=VERTEX_POINT('',#5415); #5417=CARTESIAN_POINT('',(1.96875E1,6.875E-1,9.57E0)); #5418=CARTESIAN_POINT('',(1.96875E1,0.E0,9.57E0)); #5419=VERTEX_POINT('',#5417); #5420=VERTEX_POINT('',#5418); #5421=CARTESIAN_POINT('',(2.05675E1,6.875E-1,8.69E0)); #5422=VERTEX_POINT('',#5421); #5423=CARTESIAN_POINT('',(2.05675E1,0.E0,8.69E0)); #5424=VERTEX_POINT('',#5423); #5425=CARTESIAN_POINT('',(2.05675E1,6.875E-1,1.125E1)); #5426=CARTESIAN_POINT('',(2.05675E1,0.E0,1.125E1)); #5427=VERTEX_POINT('',#5425); #5428=VERTEX_POINT('',#5426); #5429=CARTESIAN_POINT('',(1.96875E1,6.875E-1,1.037E1)); #5430=VERTEX_POINT('',#5429); #5431=CARTESIAN_POINT('',(1.96875E1,0.E0,1.037E1)); #5432=VERTEX_POINT('',#5431); #5433=CARTESIAN_POINT('',(2.44325E1,6.875E-1,8.69E0)); #5434=CARTESIAN_POINT('',(2.44325E1,0.E0,8.69E0)); #5435=VERTEX_POINT('',#5433); #5436=VERTEX_POINT('',#5434); #5437=CARTESIAN_POINT('',(2.53125E1,6.875E-1,9.57E0)); #5438=VERTEX_POINT('',#5437); #5439=CARTESIAN_POINT('',(2.53125E1,0.E0,9.57E0)); #5440=VERTEX_POINT('',#5439); #5441=CARTESIAN_POINT('',(2.53125E1,6.875E-1,1.037E1)); #5442=CARTESIAN_POINT('',(2.53125E1,0.E0,1.037E1)); #5443=VERTEX_POINT('',#5441); #5444=VERTEX_POINT('',#5442); #5445=CARTESIAN_POINT('',(2.44325E1,6.875E-1,1.125E1)); #5446=VERTEX_POINT('',#5445); #5447=CARTESIAN_POINT('',(2.44325E1,0.E0,1.125E1)); #5448=VERTEX_POINT('',#5447); #5449=CARTESIAN_POINT('',(2.13075E1,0.E0,8.69E0)); #5450=CARTESIAN_POINT('',(2.13075E1,6.875E-1,8.69E0)); #5451=VERTEX_POINT('',#5449); #5452=VERTEX_POINT('',#5450); #5453=CARTESIAN_POINT('',(2.21875E1,0.E0,7.81E0)); #5454=CARTESIAN_POINT('',(2.21875E1,6.875E-1,7.81E0)); #5455=VERTEX_POINT('',#5453); #5456=VERTEX_POINT('',#5454); #5457=CARTESIAN_POINT('',(2.331E1,0.E0,7.81E0)); #5458=CARTESIAN_POINT('',(2.331E1,6.875E-1,7.81E0)); #5459=VERTEX_POINT('',#5457); #5460=VERTEX_POINT('',#5458); #5461=CARTESIAN_POINT('',(2.419E1,0.E0,8.69E0)); #5462=CARTESIAN_POINT('',(2.419E1,6.875E-1,8.69E0)); #5463=VERTEX_POINT('',#5461); #5464=VERTEX_POINT('',#5462); #5465=CARTESIAN_POINT('',(2.321497295992E1,0.E0,4.912826677187E0)); #5466=CARTESIAN_POINT('',(2.321497295992E1,6.875E-1,4.912826677187E0)); #5467=VERTEX_POINT('',#5465); #5468=VERTEX_POINT('',#5466); #5469=CARTESIAN_POINT('',(2.307459332230E1,0.E0,4.046865146430E0)); #5470=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,4.046865146430E0)); #5471=VERTEX_POINT('',#5469); #5472=VERTEX_POINT('',#5470); #5473=CARTESIAN_POINT('',(7.850270400779E-1,0.E0,2.708717332281E1)); #5474=CARTESIAN_POINT('',(7.850270400779E-1,6.875E-1,2.708717332281E1)); #5475=VERTEX_POINT('',#5473); #5476=VERTEX_POINT('',#5474); #5477=CARTESIAN_POINT('',(9.254066777019E-1,0.E0,2.795313485357E1)); #5478=CARTESIAN_POINT('',(9.254066777019E-1,6.875E-1,2.795313485357E1)); #5479=VERTEX_POINT('',#5477); #5480=VERTEX_POINT('',#5478); #5481=CARTESIAN_POINT('',(2.307459332230E1,0.E0,2.795313485357E1)); #5482=CARTESIAN_POINT('',(2.307459332230E1,6.875E-1,2.795313485357E1)); #5483=VERTEX_POINT('',#5481); #5484=VERTEX_POINT('',#5482); #5485=CARTESIAN_POINT('',(2.321497295992E1,0.E0,2.708717332281E1)); #5486=CARTESIAN_POINT('',(2.321497295992E1,6.875E-1,2.708717332281E1)); #5487=VERTEX_POINT('',#5485); #5488=VERTEX_POINT('',#5486); #5489=CARTESIAN_POINT('',(0.E0,0.E0,0.E0)); #5490=DIRECTION('',(0.E0,1.E0,0.E0)); #5491=DIRECTION('',(1.E0,0.E0,0.E0)); #5492=AXIS2_PLACEMENT_3D('',#5489,#5490,#5491); #5493=PLANE('',#5492); #5495=ORIENTED_EDGE('',*,*,#5494,.F.); #5497=ORIENTED_EDGE('',*,*,#5496,.F.); #5499=ORIENTED_EDGE('',*,*,#5498,.T.); #5501=ORIENTED_EDGE('',*,*,#5500,.F.); #5503=ORIENTED_EDGE('',*,*,#5502,.T.); #5505=ORIENTED_EDGE('',*,*,#5504,.F.); #5507=ORIENTED_EDGE('',*,*,#5506,.T.); #5509=ORIENTED_EDGE('',*,*,#5508,.F.); #5511=ORIENTED_EDGE('',*,*,#5510,.T.); #5513=ORIENTED_EDGE('',*,*,#5512,.T.); #5515=ORIENTED_EDGE('',*,*,#5514,.F.); #5517=ORIENTED_EDGE('',*,*,#5516,.T.); #5519=ORIENTED_EDGE('',*,*,#5518,.F.); #5521=ORIENTED_EDGE('',*,*,#5520,.T.); #5523=ORIENTED_EDGE('',*,*,#5522,.F.); #5525=ORIENTED_EDGE('',*,*,#5524,.T.); #5527=ORIENTED_EDGE('',*,*,#5526,.F.); #5529=ORIENTED_EDGE('',*,*,#5528,.T.); #5531=ORIENTED_EDGE('',*,*,#5530,.F.); #5533=ORIENTED_EDGE('',*,*,#5532,.F.); #5535=ORIENTED_EDGE('',*,*,#5534,.T.); #5537=ORIENTED_EDGE('',*,*,#5536,.F.); #5538=EDGE_LOOP('',(#5495,#5497,#5499,#5501,#5503,#5505,#5507,#5509,#5511,#5513, #5515,#5517,#5519,#5521,#5523,#5525,#5527,#5529,#5531,#5533,#5535,#5537)); #5539=FACE_OUTER_BOUND('',#5538,.F.); #5541=ORIENTED_EDGE('',*,*,#5540,.T.); #5543=ORIENTED_EDGE('',*,*,#5542,.F.); #5545=ORIENTED_EDGE('',*,*,#5544,.F.); #5547=ORIENTED_EDGE('',*,*,#5546,.F.); #5549=ORIENTED_EDGE('',*,*,#5548,.F.); #5551=ORIENTED_EDGE('',*,*,#5550,.F.); #5552=EDGE_LOOP('',(#5541,#5543,#5545,#5547,#5549,#5551)); #5553=FACE_BOUND('',#5552,.F.); #5555=ORIENTED_EDGE('',*,*,#5554,.T.); #5557=ORIENTED_EDGE('',*,*,#5556,.T.); #5558=EDGE_LOOP('',(#5555,#5557)); #5559=FACE_BOUND('',#5558,.F.); #5561=ORIENTED_EDGE('',*,*,#5560,.T.); #5563=ORIENTED_EDGE('',*,*,#5562,.T.); #5564=EDGE_LOOP('',(#5561,#5563)); #5565=FACE_BOUND('',#5564,.F.); #5567=ORIENTED_EDGE('',*,*,#5566,.T.); #5569=ORIENTED_EDGE('',*,*,#5568,.T.); #5570=EDGE_LOOP('',(#5567,#5569)); #5571=FACE_BOUND('',#5570,.F.); #5573=ORIENTED_EDGE('',*,*,#5572,.T.); #5575=ORIENTED_EDGE('',*,*,#5574,.T.); #5576=EDGE_LOOP('',(#5573,#5575)); #5577=FACE_BOUND('',#5576,.F.); #5579=ORIENTED_EDGE('',*,*,#5578,.T.); #5581=ORIENTED_EDGE('',*,*,#5580,.T.); #5582=EDGE_LOOP('',(#5579,#5581)); #5583=FACE_BOUND('',#5582,.F.); #5585=ORIENTED_EDGE('',*,*,#5584,.T.); #5587=ORIENTED_EDGE('',*,*,#5586,.T.); #5588=EDGE_LOOP('',(#5585,#5587)); #5589=FACE_BOUND('',#5588,.F.); #5591=ORIENTED_EDGE('',*,*,#5590,.T.); #5593=ORIENTED_EDGE('',*,*,#5592,.T.); #5594=EDGE_LOOP('',(#5591,#5593)); #5595=FACE_BOUND('',#5594,.F.); #5597=ORIENTED_EDGE('',*,*,#5596,.T.); #5599=ORIENTED_EDGE('',*,*,#5598,.T.); #5600=EDGE_LOOP('',(#5597,#5599)); #5601=FACE_BOUND('',#5600,.F.); #5603=ORIENTED_EDGE('',*,*,#5602,.T.); #5605=ORIENTED_EDGE('',*,*,#5604,.T.); #5606=EDGE_LOOP('',(#5603,#5605)); #5607=FACE_BOUND('',#5606,.F.); #5609=ORIENTED_EDGE('',*,*,#5608,.T.); #5611=ORIENTED_EDGE('',*,*,#5610,.T.); #5612=EDGE_LOOP('',(#5609,#5611)); #5613=FACE_BOUND('',#5612,.F.); #5615=ORIENTED_EDGE('',*,*,#5614,.T.); #5617=ORIENTED_EDGE('',*,*,#5616,.T.); #5618=EDGE_LOOP('',(#5615,#5617)); #5619=FACE_BOUND('',#5618,.F.); #5621=ORIENTED_EDGE('',*,*,#5620,.T.); #5623=ORIENTED_EDGE('',*,*,#5622,.T.); #5624=EDGE_LOOP('',(#5621,#5623)); #5625=FACE_BOUND('',#5624,.F.); #5627=ORIENTED_EDGE('',*,*,#5626,.T.); #5629=ORIENTED_EDGE('',*,*,#5628,.T.); #5630=EDGE_LOOP('',(#5627,#5629)); #5631=FACE_BOUND('',#5630,.F.); #5633=ORIENTED_EDGE('',*,*,#5632,.T.); #5635=ORIENTED_EDGE('',*,*,#5634,.T.); #5636=EDGE_LOOP('',(#5633,#5635)); #5637=FACE_BOUND('',#5636,.F.); #5639=ORIENTED_EDGE('',*,*,#5638,.T.); #5641=ORIENTED_EDGE('',*,*,#5640,.F.); #5643=ORIENTED_EDGE('',*,*,#5642,.F.); #5645=ORIENTED_EDGE('',*,*,#5644,.F.); #5647=ORIENTED_EDGE('',*,*,#5646,.F.); #5649=ORIENTED_EDGE('',*,*,#5648,.F.); #5651=ORIENTED_EDGE('',*,*,#5650,.F.); #5653=ORIENTED_EDGE('',*,*,#5652,.F.); #5654=EDGE_LOOP('',(#5639,#5641,#5643,#5645,#5647,#5649,#5651,#5653)); #5655=FACE_BOUND('',#5654,.F.); #5657=ORIENTED_EDGE('',*,*,#5656,.F.); #5659=ORIENTED_EDGE('',*,*,#5658,.F.); #5661=ORIENTED_EDGE('',*,*,#5660,.T.); #5663=ORIENTED_EDGE('',*,*,#5662,.F.); #5665=ORIENTED_EDGE('',*,*,#5664,.F.); #5667=ORIENTED_EDGE('',*,*,#5666,.F.); #5669=ORIENTED_EDGE('',*,*,#5668,.T.); #5671=ORIENTED_EDGE('',*,*,#5670,.F.); #5673=ORIENTED_EDGE('',*,*,#5672,.T.); #5675=ORIENTED_EDGE('',*,*,#5674,.F.); #5677=ORIENTED_EDGE('',*,*,#5676,.T.); #5679=ORIENTED_EDGE('',*,*,#5678,.F.); #5681=ORIENTED_EDGE('',*,*,#5680,.F.); #5683=ORIENTED_EDGE('',*,*,#5682,.T.); #5685=ORIENTED_EDGE('',*,*,#5684,.F.); #5687=ORIENTED_EDGE('',*,*,#5686,.F.); #5688=EDGE_LOOP('',(#5657,#5659,#5661,#5663,#5665,#5667,#5669,#5671,#5673,#5675, #5677,#5679,#5681,#5683,#5685,#5687)); #5689=FACE_BOUND('',#5688,.F.); #5691=ORIENTED_EDGE('',*,*,#5690,.T.); #5693=ORIENTED_EDGE('',*,*,#5692,.T.); #5694=EDGE_LOOP('',(#5691,#5693)); #5695=FACE_BOUND('',#5694,.F.); #5697=ORIENTED_EDGE('',*,*,#5696,.T.); #5699=ORIENTED_EDGE('',*,*,#5698,.T.); #5700=EDGE_LOOP('',(#5697,#5699)); #5701=FACE_BOUND('',#5700,.F.); #5703=ORIENTED_EDGE('',*,*,#5702,.T.); #5705=ORIENTED_EDGE('',*,*,#5704,.T.); #5706=EDGE_LOOP('',(#5703,#5705)); #5707=FACE_BOUND('',#5706,.F.); #5709=ORIENTED_EDGE('',*,*,#5708,.T.); #5711=ORIENTED_EDGE('',*,*,#5710,.T.); #5712=EDGE_LOOP('',(#5709,#5711)); #5713=FACE_BOUND('',#5712,.F.); #5715=ORIENTED_EDGE('',*,*,#5714,.T.); #5717=ORIENTED_EDGE('',*,*,#5716,.T.); #5718=EDGE_LOOP('',(#5715,#5717)); #5719=FACE_BOUND('',#5718,.F.); #5721=ORIENTED_EDGE('',*,*,#5720,.T.); #5723=ORIENTED_EDGE('',*,*,#5722,.T.); #5724=EDGE_LOOP('',(#5721,#5723)); #5725=FACE_BOUND('',#5724,.F.); #5727=ORIENTED_EDGE('',*,*,#5726,.T.); #5729=ORIENTED_EDGE('',*,*,#5728,.T.); #5731=ORIENTED_EDGE('',*,*,#5730,.T.); #5733=ORIENTED_EDGE('',*,*,#5732,.T.); #5734=EDGE_LOOP('',(#5727,#5729,#5731,#5733)); #5735=FACE_BOUND('',#5734,.F.); #5737=ORIENTED_EDGE('',*,*,#5736,.T.); #5739=ORIENTED_EDGE('',*,*,#5738,.F.); #5741=ORIENTED_EDGE('',*,*,#5740,.T.); #5743=ORIENTED_EDGE('',*,*,#5742,.T.); #5745=ORIENTED_EDGE('',*,*,#5744,.F.); #5746=EDGE_LOOP('',(#5737,#5739,#5741,#5743,#5745)); #5747=FACE_BOUND('',#5746,.F.); #5749=ORIENTED_EDGE('',*,*,#5748,.F.); #5751=ORIENTED_EDGE('',*,*,#5750,.T.); #5753=ORIENTED_EDGE('',*,*,#5752,.T.); #5755=ORIENTED_EDGE('',*,*,#5754,.T.); #5757=ORIENTED_EDGE('',*,*,#5756,.F.); #5759=ORIENTED_EDGE('',*,*,#5758,.T.); #5761=ORIENTED_EDGE('',*,*,#5760,.F.); #5763=ORIENTED_EDGE('',*,*,#5762,.T.); #5765=ORIENTED_EDGE('',*,*,#5764,.F.); #5767=ORIENTED_EDGE('',*,*,#5766,.T.); #5769=ORIENTED_EDGE('',*,*,#5768,.F.); #5771=ORIENTED_EDGE('',*,*,#5770,.T.); #5773=ORIENTED_EDGE('',*,*,#5772,.F.); #5775=ORIENTED_EDGE('',*,*,#5774,.T.); #5776=EDGE_LOOP('',(#5749,#5751,#5753,#5755,#5757,#5759,#5761,#5763,#5765,#5767, #5769,#5771,#5773,#5775)); #5777=FACE_BOUND('',#5776,.F.); #5779=ORIENTED_EDGE('',*,*,#5778,.T.); #5781=ORIENTED_EDGE('',*,*,#5780,.T.); #5783=ORIENTED_EDGE('',*,*,#5782,.T.); #5785=ORIENTED_EDGE('',*,*,#5784,.T.); #5786=EDGE_LOOP('',(#5779,#5781,#5783,#5785)); #5787=FACE_BOUND('',#5786,.F.); #5789=ORIENTED_EDGE('',*,*,#5788,.T.); #5791=ORIENTED_EDGE('',*,*,#5790,.T.); #5793=ORIENTED_EDGE('',*,*,#5792,.T.); #5795=ORIENTED_EDGE('',*,*,#5794,.T.); #5796=EDGE_LOOP('',(#5789,#5791,#5793,#5795)); #5797=FACE_BOUND('',#5796,.F.); #5799=ORIENTED_EDGE('',*,*,#5798,.T.); #5801=ORIENTED_EDGE('',*,*,#5800,.T.); #5803=ORIENTED_EDGE('',*,*,#5802,.T.); #5805=ORIENTED_EDGE('',*,*,#5804,.T.); #5806=EDGE_LOOP('',(#5799,#5801,#5803,#5805)); #5807=FACE_BOUND('',#5806,.F.); #5809=ORIENTED_EDGE('',*,*,#5808,.T.); #5811=ORIENTED_EDGE('',*,*,#5810,.T.); #5813=ORIENTED_EDGE('',*,*,#5812,.T.); #5815=ORIENTED_EDGE('',*,*,#5814,.T.); #5816=EDGE_LOOP('',(#5809,#5811,#5813,#5815)); #5817=FACE_BOUND('',#5816,.F.); #5819=ORIENTED_EDGE('',*,*,#5818,.F.); #5821=ORIENTED_EDGE('',*,*,#5820,.F.); #5823=ORIENTED_EDGE('',*,*,#5822,.F.); #5825=ORIENTED_EDGE('',*,*,#5824,.F.); #5826=EDGE_LOOP('',(#5819,#5821,#5823,#5825)); #5827=FACE_BOUND('',#5826,.F.); #5829=ORIENTED_EDGE('',*,*,#5828,.F.); #5831=ORIENTED_EDGE('',*,*,#5830,.F.); #5833=ORIENTED_EDGE('',*,*,#5832,.F.); #5835=ORIENTED_EDGE('',*,*,#5834,.F.); #5836=EDGE_LOOP('',(#5829,#5831,#5833,#5835)); #5837=FACE_BOUND('',#5836,.F.); #5839=ORIENTED_EDGE('',*,*,#5838,.F.); #5841=ORIENTED_EDGE('',*,*,#5840,.F.); #5843=ORIENTED_EDGE('',*,*,#5842,.F.); #5845=ORIENTED_EDGE('',*,*,#5844,.F.); #5846=EDGE_LOOP('',(#5839,#5841,#5843,#5845)); #5847=FACE_BOUND('',#5846,.F.); #5849=ORIENTED_EDGE('',*,*,#5848,.F.); #5851=ORIENTED_EDGE('',*,*,#5850,.F.); #5853=ORIENTED_EDGE('',*,*,#5852,.F.); #5855=ORIENTED_EDGE('',*,*,#5854,.F.); #5856=EDGE_LOOP('',(#5849,#5851,#5853,#5855)); #5857=FACE_BOUND('',#5856,.F.); #5859=ORIENTED_EDGE('',*,*,#5858,.F.); #5861=ORIENTED_EDGE('',*,*,#5860,.F.); #5863=ORIENTED_EDGE('',*,*,#5862,.F.); #5865=ORIENTED_EDGE('',*,*,#5864,.F.); #5866=EDGE_LOOP('',(#5859,#5861,#5863,#5865)); #5867=FACE_BOUND('',#5866,.F.); #5869=ORIENTED_EDGE('',*,*,#5868,.F.); #5871=ORIENTED_EDGE('',*,*,#5870,.F.); #5873=ORIENTED_EDGE('',*,*,#5872,.F.); #5875=ORIENTED_EDGE('',*,*,#5874,.F.); #5876=EDGE_LOOP('',(#5869,#5871,#5873,#5875)); #5877=FACE_BOUND('',#5876,.F.); #5879=ORIENTED_EDGE('',*,*,#5878,.T.); #5881=ORIENTED_EDGE('',*,*,#5880,.T.); #5883=ORIENTED_EDGE('',*,*,#5882,.T.); #5885=ORIENTED_EDGE('',*,*,#5884,.T.); #5886=EDGE_LOOP('',(#5879,#5881,#5883,#5885)); #5887=FACE_BOUND('',#5886,.F.); #5889=ORIENTED_EDGE('',*,*,#5888,.F.); #5891=ORIENTED_EDGE('',*,*,#5890,.F.); #5893=ORIENTED_EDGE('',*,*,#5892,.F.); #5895=ORIENTED_EDGE('',*,*,#5894,.F.); #5897=ORIENTED_EDGE('',*,*,#5896,.F.); #5899=ORIENTED_EDGE('',*,*,#5898,.F.); #5901=ORIENTED_EDGE('',*,*,#5900,.F.); #5903=ORIENTED_EDGE('',*,*,#5902,.F.); #5905=ORIENTED_EDGE('',*,*,#5904,.F.); #5907=ORIENTED_EDGE('',*,*,#5906,.F.); #5909=ORIENTED_EDGE('',*,*,#5908,.F.); #5911=ORIENTED_EDGE('',*,*,#5910,.F.); #5913=ORIENTED_EDGE('',*,*,#5912,.F.); #5915=ORIENTED_EDGE('',*,*,#5914,.F.); #5916=EDGE_LOOP('',(#5889,#5891,#5893,#5895,#5897,#5899,#5901,#5903,#5905,#5907, #5909,#5911,#5913,#5915)); #5917=FACE_BOUND('',#5916,.F.); #5919=ORIENTED_EDGE('',*,*,#5918,.F.); #5921=ORIENTED_EDGE('',*,*,#5920,.F.); #5923=ORIENTED_EDGE('',*,*,#5922,.F.); #5925=ORIENTED_EDGE('',*,*,#5924,.T.); #5927=ORIENTED_EDGE('',*,*,#5926,.F.); #5928=EDGE_LOOP('',(#5919,#5921,#5923,#5925,#5927)); #5929=FACE_BOUND('',#5928,.F.); #5931=ORIENTED_EDGE('',*,*,#5930,.F.); #5933=ORIENTED_EDGE('',*,*,#5932,.F.); #5935=ORIENTED_EDGE('',*,*,#5934,.F.); #5937=ORIENTED_EDGE('',*,*,#5936,.T.); #5939=ORIENTED_EDGE('',*,*,#5938,.F.); #5940=EDGE_LOOP('',(#5931,#5933,#5935,#5937,#5939)); #5941=FACE_BOUND('',#5940,.F.); #5943=ORIENTED_EDGE('',*,*,#5942,.T.); #5945=ORIENTED_EDGE('',*,*,#5944,.F.); #5947=ORIENTED_EDGE('',*,*,#5946,.T.); #5949=ORIENTED_EDGE('',*,*,#5948,.T.); #5951=ORIENTED_EDGE('',*,*,#5950,.F.); #5952=EDGE_LOOP('',(#5943,#5945,#5947,#5949,#5951)); #5953=FACE_BOUND('',#5952,.F.); #5954=ADVANCED_FACE('',(#5539,#5553,#5559,#5565,#5571,#5577,#5583,#5589,#5595, #5601,#5607,#5613,#5619,#5625,#5631,#5637,#5655,#5689,#5695,#5701,#5707,#5713, #5719,#5725,#5735,#5747,#5777,#5787,#5797,#5807,#5817,#5827,#5837,#5847,#5857, #5867,#5877,#5887,#5917,#5929,#5941,#5953),#5493,.F.); #5955=CARTESIAN_POINT('',(0.E0,0.E0,8.E0)); #5956=DIRECTION('',(0.E0,0.E0,1.E0)); #5957=DIRECTION('',(1.E0,0.E0,0.E0)); #5958=AXIS2_PLACEMENT_3D('',#5955,#5956,#5957); #5959=PLANE('',#5958); #5960=ORIENTED_EDGE('',*,*,#5540,.F.); #5962=ORIENTED_EDGE('',*,*,#5961,.T.); #5964=ORIENTED_EDGE('',*,*,#5963,.F.); #5966=ORIENTED_EDGE('',*,*,#5965,.F.); #5967=ORIENTED_EDGE('',*,*,#5494,.T.); #5969=ORIENTED_EDGE('',*,*,#5968,.F.); #5971=ORIENTED_EDGE('',*,*,#5970,.F.); #5973=ORIENTED_EDGE('',*,*,#5972,.T.); #5975=ORIENTED_EDGE('',*,*,#5974,.F.); #5977=ORIENTED_EDGE('',*,*,#5976,.F.); #5979=ORIENTED_EDGE('',*,*,#5978,.F.); #5981=ORIENTED_EDGE('',*,*,#5980,.T.); #5983=ORIENTED_EDGE('',*,*,#5982,.T.); #5985=ORIENTED_EDGE('',*,*,#5984,.F.); #5986=ORIENTED_EDGE('',*,*,#5510,.F.); #5988=ORIENTED_EDGE('',*,*,#5987,.F.); #5990=ORIENTED_EDGE('',*,*,#5989,.F.); #5992=ORIENTED_EDGE('',*,*,#5991,.T.); #5993=EDGE_LOOP('',(#5960,#5962,#5964,#5966,#5967,#5969,#5971,#5973,#5975,#5977, #5979,#5981,#5983,#5985,#5986,#5988,#5990,#5992)); #5994=FACE_OUTER_BOUND('',#5993,.F.); #5996=ORIENTED_EDGE('',*,*,#5995,.T.); #5998=ORIENTED_EDGE('',*,*,#5997,.T.); #5999=EDGE_LOOP('',(#5996,#5998)); #6000=FACE_BOUND('',#5999,.F.); #6002=ORIENTED_EDGE('',*,*,#6001,.T.); #6004=ORIENTED_EDGE('',*,*,#6003,.T.); #6005=EDGE_LOOP('',(#6002,#6004)); #6006=FACE_BOUND('',#6005,.F.); #6008=ORIENTED_EDGE('',*,*,#6007,.T.); #6010=ORIENTED_EDGE('',*,*,#6009,.T.); #6011=EDGE_LOOP('',(#6008,#6010)); #6012=FACE_BOUND('',#6011,.F.); #6014=ORIENTED_EDGE('',*,*,#6013,.T.); #6016=ORIENTED_EDGE('',*,*,#6015,.T.); #6017=EDGE_LOOP('',(#6014,#6016)); #6018=FACE_BOUND('',#6017,.F.); #6020=ORIENTED_EDGE('',*,*,#6019,.F.); #6022=ORIENTED_EDGE('',*,*,#6021,.F.); #6023=EDGE_LOOP('',(#6020,#6022)); #6024=FACE_BOUND('',#6023,.F.); #6026=ORIENTED_EDGE('',*,*,#6025,.F.); #6028=ORIENTED_EDGE('',*,*,#6027,.F.); #6029=EDGE_LOOP('',(#6026,#6028)); #6030=FACE_BOUND('',#6029,.F.); #6032=ORIENTED_EDGE('',*,*,#6031,.F.); #6034=ORIENTED_EDGE('',*,*,#6033,.F.); #6035=EDGE_LOOP('',(#6032,#6034)); #6036=FACE_BOUND('',#6035,.F.); #6038=ORIENTED_EDGE('',*,*,#6037,.F.); #6040=ORIENTED_EDGE('',*,*,#6039,.F.); #6041=EDGE_LOOP('',(#6038,#6040)); #6042=FACE_BOUND('',#6041,.F.); #6044=ORIENTED_EDGE('',*,*,#6043,.T.); #6046=ORIENTED_EDGE('',*,*,#6045,.F.); #6048=ORIENTED_EDGE('',*,*,#6047,.T.); #6050=ORIENTED_EDGE('',*,*,#6049,.F.); #6052=ORIENTED_EDGE('',*,*,#6051,.T.); #6054=ORIENTED_EDGE('',*,*,#6053,.F.); #6056=ORIENTED_EDGE('',*,*,#6055,.T.); #6058=ORIENTED_EDGE('',*,*,#6057,.F.); #6059=EDGE_LOOP('',(#6044,#6046,#6048,#6050,#6052,#6054,#6056,#6058)); #6060=FACE_BOUND('',#6059,.F.); #6062=ORIENTED_EDGE('',*,*,#6061,.F.); #6064=ORIENTED_EDGE('',*,*,#6063,.F.); #6066=ORIENTED_EDGE('',*,*,#6065,.F.); #6068=ORIENTED_EDGE('',*,*,#6067,.F.); #6070=ORIENTED_EDGE('',*,*,#6069,.F.); #6072=ORIENTED_EDGE('',*,*,#6071,.F.); #6074=ORIENTED_EDGE('',*,*,#6073,.F.); #6076=ORIENTED_EDGE('',*,*,#6075,.F.); #6077=EDGE_LOOP('',(#6062,#6064,#6066,#6068,#6070,#6072,#6074,#6076)); #6078=FACE_BOUND('',#6077,.F.); #6079=ADVANCED_FACE('',(#5994,#6000,#6006,#6012,#6018,#6024,#6030,#6036,#6042, #6060,#6078),#5959,.F.); #6080=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0)); #6081=DIRECTION('',(0.E0,0.E0,-1.E0)); #6082=DIRECTION('',(-1.E0,0.E0,0.E0)); #6083=AXIS2_PLACEMENT_3D('',#6080,#6081,#6082); #6084=CYLINDRICAL_SURFACE('',#6083,9.5E-2); #6085=ORIENTED_EDGE('',*,*,#5995,.F.); #6087=ORIENTED_EDGE('',*,*,#6086,.T.); #6089=ORIENTED_EDGE('',*,*,#6088,.T.); #6091=ORIENTED_EDGE('',*,*,#6090,.F.); #6092=EDGE_LOOP('',(#6085,#6087,#6089,#6091)); #6093=FACE_OUTER_BOUND('',#6092,.F.); #6094=ADVANCED_FACE('',(#6093),#6084,.F.); #6095=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.E0)); #6096=DIRECTION('',(0.E0,0.E0,-1.E0)); #6097=DIRECTION('',(-1.E0,0.E0,0.E0)); #6098=AXIS2_PLACEMENT_3D('',#6095,#6096,#6097); #6099=CYLINDRICAL_SURFACE('',#6098,9.5E-2); #6100=ORIENTED_EDGE('',*,*,#5997,.F.); #6101=ORIENTED_EDGE('',*,*,#6090,.T.); #6103=ORIENTED_EDGE('',*,*,#6102,.T.); #6104=ORIENTED_EDGE('',*,*,#6086,.F.); #6105=EDGE_LOOP('',(#6100,#6101,#6103,#6104)); #6106=FACE_OUTER_BOUND('',#6105,.F.); #6107=ADVANCED_FACE('',(#6106),#6099,.F.); #6108=CARTESIAN_POINT('',(1.975E1,1.09375E1,8.25E0)); #6109=DIRECTION('',(0.E0,0.E0,-1.E0)); #6110=DIRECTION('',(-1.E0,0.E0,0.E0)); #6111=AXIS2_PLACEMENT_3D('',#6108,#6109,#6110); #6112=PLANE('',#6111); #6113=ORIENTED_EDGE('',*,*,#6088,.F.); #6114=ORIENTED_EDGE('',*,*,#6102,.F.); #6115=EDGE_LOOP('',(#6113,#6114)); #6116=FACE_OUTER_BOUND('',#6115,.F.); #6117=ADVANCED_FACE('',(#6116),#6112,.T.); #6118=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0)); #6119=DIRECTION('',(0.E0,0.E0,-1.E0)); #6120=DIRECTION('',(-1.E0,0.E0,0.E0)); #6121=AXIS2_PLACEMENT_3D('',#6118,#6119,#6120); #6122=CYLINDRICAL_SURFACE('',#6121,1.625E-1); #6123=ORIENTED_EDGE('',*,*,#6001,.F.); #6125=ORIENTED_EDGE('',*,*,#6124,.T.); #6127=ORIENTED_EDGE('',*,*,#6126,.T.); #6129=ORIENTED_EDGE('',*,*,#6128,.F.); #6130=EDGE_LOOP('',(#6123,#6125,#6127,#6129)); #6131=FACE_OUTER_BOUND('',#6130,.F.); #6132=ADVANCED_FACE('',(#6131),#6122,.F.); #6133=CARTESIAN_POINT('',(1.975E1,1.05E1,8.E0)); #6134=DIRECTION('',(0.E0,0.E0,-1.E0)); #6135=DIRECTION('',(-1.E0,0.E0,0.E0)); #6136=AXIS2_PLACEMENT_3D('',#6133,#6134,#6135); #6137=CYLINDRICAL_SURFACE('',#6136,1.625E-1); #6138=ORIENTED_EDGE('',*,*,#6003,.F.); #6139=ORIENTED_EDGE('',*,*,#6128,.T.); #6141=ORIENTED_EDGE('',*,*,#6140,.T.); #6142=ORIENTED_EDGE('',*,*,#6124,.F.); #6143=EDGE_LOOP('',(#6138,#6139,#6141,#6142)); #6144=FACE_OUTER_BOUND('',#6143,.F.); #6145=ADVANCED_FACE('',(#6144),#6137,.F.); #6146=CARTESIAN_POINT('',(2.4E1,0.E0,1.E1)); #6147=DIRECTION('',(0.E0,0.E0,-1.E0)); #6148=DIRECTION('',(-1.E0,0.E0,0.E0)); #6149=AXIS2_PLACEMENT_3D('',#6146,#6147,#6148); #6150=PLANE('',#6149); #6152=ORIENTED_EDGE('',*,*,#6151,.T.); #6154=ORIENTED_EDGE('',*,*,#6153,.T.); #6156=ORIENTED_EDGE('',*,*,#6155,.F.); #6158=ORIENTED_EDGE('',*,*,#6157,.F.); #6160=ORIENTED_EDGE('',*,*,#6159,.T.); #6162=ORIENTED_EDGE('',*,*,#6161,.T.); #6164=ORIENTED_EDGE('',*,*,#6163,.T.); #6166=ORIENTED_EDGE('',*,*,#6165,.T.); #6168=ORIENTED_EDGE('',*,*,#6167,.F.); #6169=EDGE_LOOP('',(#6152,#6154,#6156,#6158,#6160,#6162,#6164,#6166,#6168)); #6170=FACE_OUTER_BOUND('',#6169,.F.); #6171=ORIENTED_EDGE('',*,*,#6126,.F.); #6172=ORIENTED_EDGE('',*,*,#6140,.F.); #6173=EDGE_LOOP('',(#6171,#6172)); #6174=FACE_BOUND('',#6173,.F.); #6176=ORIENTED_EDGE('',*,*,#6175,.F.); #6178=ORIENTED_EDGE('',*,*,#6177,.F.); #6180=ORIENTED_EDGE('',*,*,#6179,.F.); #6182=ORIENTED_EDGE('',*,*,#6181,.F.); #6184=ORIENTED_EDGE('',*,*,#6183,.F.); #6186=ORIENTED_EDGE('',*,*,#6185,.F.); #6188=ORIENTED_EDGE('',*,*,#6187,.F.); #6190=ORIENTED_EDGE('',*,*,#6189,.F.); #6192=ORIENTED_EDGE('',*,*,#6191,.F.); #6194=ORIENTED_EDGE('',*,*,#6193,.F.); #6196=ORIENTED_EDGE('',*,*,#6195,.F.); #6198=ORIENTED_EDGE('',*,*,#6197,.F.); #6199=EDGE_LOOP('',(#6176,#6178,#6180,#6182,#6184,#6186,#6188,#6190,#6192,#6194, #6196,#6198)); #6200=FACE_BOUND('',#6199,.F.); #6201=ADVANCED_FACE('',(#6170,#6174,#6200),#6150,.F.); #6202=CARTESIAN_POINT('',(2.375E1,1.5E0,1.2E1)); #6203=DIRECTION('',(1.E0,0.E0,0.E0)); #6204=DIRECTION('',(0.E0,-1.E0,0.E0)); #6205=AXIS2_PLACEMENT_3D('',#6202,#6203,#6204); #6206=PLANE('',#6205); #6208=ORIENTED_EDGE('',*,*,#6207,.F.); #6210=ORIENTED_EDGE('',*,*,#6209,.F.); #6211=ORIENTED_EDGE('',*,*,#6151,.F.); #6212=EDGE_LOOP('',(#6208,#6210,#6211)); #6213=FACE_OUTER_BOUND('',#6212,.F.); #6214=ADVANCED_FACE('',(#6213),#6206,.T.); #6215=CARTESIAN_POINT('',(0.E0,1.5E0,0.E0)); #6216=DIRECTION('',(0.E0,1.E0,0.E0)); #6217=DIRECTION('',(1.E0,0.E0,0.E0)); #6218=AXIS2_PLACEMENT_3D('',#6215,#6216,#6217); #6219=PLANE('',#6218); #6220=ORIENTED_EDGE('',*,*,#5963,.T.); #6222=ORIENTED_EDGE('',*,*,#6221,.F.); #6224=ORIENTED_EDGE('',*,*,#6223,.F.); #6226=ORIENTED_EDGE('',*,*,#6225,.T.); #6228=ORIENTED_EDGE('',*,*,#6227,.F.); #6230=ORIENTED_EDGE('',*,*,#6229,.F.); #6231=ORIENTED_EDGE('',*,*,#5989,.T.); #6233=ORIENTED_EDGE('',*,*,#6232,.F.); #6235=ORIENTED_EDGE('',*,*,#6234,.F.); #6237=ORIENTED_EDGE('',*,*,#6236,.T.); #6239=ORIENTED_EDGE('',*,*,#6238,.F.); #6241=ORIENTED_EDGE('',*,*,#6240,.T.); #6243=ORIENTED_EDGE('',*,*,#6242,.F.); #6245=ORIENTED_EDGE('',*,*,#6244,.F.); #6246=EDGE_LOOP('',(#6220,#6222,#6224,#6226,#6228,#6230,#6231,#6233,#6235,#6237, #6239,#6241,#6243,#6245)); #6247=FACE_OUTER_BOUND('',#6246,.F.); #6249=ORIENTED_EDGE('',*,*,#6248,.F.); #6251=ORIENTED_EDGE('',*,*,#6250,.F.); #6252=EDGE_LOOP('',(#6249,#6251)); #6253=FACE_BOUND('',#6252,.F.); #6255=ORIENTED_EDGE('',*,*,#6254,.F.); #6257=ORIENTED_EDGE('',*,*,#6256,.F.); #6258=EDGE_LOOP('',(#6255,#6257)); #6259=FACE_BOUND('',#6258,.F.); #6261=ORIENTED_EDGE('',*,*,#6260,.F.); #6263=ORIENTED_EDGE('',*,*,#6262,.F.); #6264=EDGE_LOOP('',(#6261,#6263)); #6265=FACE_BOUND('',#6264,.F.); #6267=ORIENTED_EDGE('',*,*,#6266,.F.); #6269=ORIENTED_EDGE('',*,*,#6268,.F.); #6270=EDGE_LOOP('',(#6267,#6269)); #6271=FACE_BOUND('',#6270,.F.); #6273=ORIENTED_EDGE('',*,*,#6272,.F.); #6275=ORIENTED_EDGE('',*,*,#6274,.F.); #6276=EDGE_LOOP('',(#6273,#6275)); #6277=FACE_BOUND('',#6276,.F.); #6278=ADVANCED_FACE('',(#6247,#6253,#6259,#6265,#6271,#6277),#6219,.T.); #6279=CARTESIAN_POINT('',(0.E0,1.5E0,0.E0)); #6280=DIRECTION('',(0.E0,1.E0,0.E0)); #6281=DIRECTION('',(1.E0,0.E0,0.E0)); #6282=AXIS2_PLACEMENT_3D('',#6279,#6280,#6281); #6283=PLANE('',#6282); #6284=ORIENTED_EDGE('',*,*,#6207,.T.); #6285=ORIENTED_EDGE('',*,*,#6167,.T.); #6287=ORIENTED_EDGE('',*,*,#6286,.T.); #6289=ORIENTED_EDGE('',*,*,#6288,.F.); #6291=ORIENTED_EDGE('',*,*,#6290,.T.); #6293=ORIENTED_EDGE('',*,*,#6292,.F.); #6295=ORIENTED_EDGE('',*,*,#6294,.F.); #6297=ORIENTED_EDGE('',*,*,#6296,.T.); #6299=ORIENTED_EDGE('',*,*,#6298,.F.); #6301=ORIENTED_EDGE('',*,*,#6300,.T.); #6303=ORIENTED_EDGE('',*,*,#6302,.F.); #6305=ORIENTED_EDGE('',*,*,#6304,.F.); #6307=ORIENTED_EDGE('',*,*,#6306,.F.); #6309=ORIENTED_EDGE('',*,*,#6308,.T.); #6311=ORIENTED_EDGE('',*,*,#6310,.F.); #6313=ORIENTED_EDGE('',*,*,#6312,.T.); #6315=ORIENTED_EDGE('',*,*,#6314,.F.); #6317=ORIENTED_EDGE('',*,*,#6316,.T.); #6319=ORIENTED_EDGE('',*,*,#6318,.T.); #6321=ORIENTED_EDGE('',*,*,#6320,.T.); #6323=ORIENTED_EDGE('',*,*,#6322,.F.); #6324=ORIENTED_EDGE('',*,*,#5976,.T.); #6326=ORIENTED_EDGE('',*,*,#6325,.T.); #6327=ORIENTED_EDGE('',*,*,#6157,.T.); #6329=ORIENTED_EDGE('',*,*,#6328,.F.); #6331=ORIENTED_EDGE('',*,*,#6330,.F.); #6332=EDGE_LOOP('',(#6284,#6285,#6287,#6289,#6291,#6293,#6295,#6297,#6299,#6301, #6303,#6305,#6307,#6309,#6311,#6313,#6315,#6317,#6319,#6321,#6323,#6324,#6326, #6327,#6329,#6331)); #6333=FACE_OUTER_BOUND('',#6332,.F.); #6335=ORIENTED_EDGE('',*,*,#6334,.F.); #6337=ORIENTED_EDGE('',*,*,#6336,.F.); #6338=EDGE_LOOP('',(#6335,#6337)); #6339=FACE_BOUND('',#6338,.F.); #6341=ORIENTED_EDGE('',*,*,#6340,.F.); #6343=ORIENTED_EDGE('',*,*,#6342,.F.); #6344=EDGE_LOOP('',(#6341,#6343)); #6345=FACE_BOUND('',#6344,.F.); #6347=ORIENTED_EDGE('',*,*,#6346,.T.); #6349=ORIENTED_EDGE('',*,*,#6348,.T.); #6350=EDGE_LOOP('',(#6347,#6349)); #6351=FACE_BOUND('',#6350,.F.); #6353=ORIENTED_EDGE('',*,*,#6352,.T.); #6355=ORIENTED_EDGE('',*,*,#6354,.T.); #6356=EDGE_LOOP('',(#6353,#6355)); #6357=FACE_BOUND('',#6356,.F.); #6359=ORIENTED_EDGE('',*,*,#6358,.F.); #6361=ORIENTED_EDGE('',*,*,#6360,.F.); #6362=EDGE_LOOP('',(#6359,#6361)); #6363=FACE_BOUND('',#6362,.F.); #6365=ORIENTED_EDGE('',*,*,#6364,.F.); #6367=ORIENTED_EDGE('',*,*,#6366,.F.); #6368=EDGE_LOOP('',(#6365,#6367)); #6369=FACE_BOUND('',#6368,.F.); #6371=ORIENTED_EDGE('',*,*,#6370,.F.); #6373=ORIENTED_EDGE('',*,*,#6372,.F.); #6374=EDGE_LOOP('',(#6371,#6373)); #6375=FACE_BOUND('',#6374,.F.); #6377=ORIENTED_EDGE('',*,*,#6376,.F.); #6379=ORIENTED_EDGE('',*,*,#6378,.F.); #6380=EDGE_LOOP('',(#6377,#6379)); #6381=FACE_BOUND('',#6380,.F.); #6383=ORIENTED_EDGE('',*,*,#6382,.F.); #6385=ORIENTED_EDGE('',*,*,#6384,.F.); #6386=EDGE_LOOP('',(#6383,#6385)); #6387=FACE_BOUND('',#6386,.F.); #6389=ORIENTED_EDGE('',*,*,#6388,.F.); #6391=ORIENTED_EDGE('',*,*,#6390,.F.); #6392=EDGE_LOOP('',(#6389,#6391)); #6393=FACE_BOUND('',#6392,.F.); #6395=ORIENTED_EDGE('',*,*,#6394,.F.); #6397=ORIENTED_EDGE('',*,*,#6396,.F.); #6398=EDGE_LOOP('',(#6395,#6397)); #6399=FACE_BOUND('',#6398,.F.); #6401=ORIENTED_EDGE('',*,*,#6400,.T.); #6403=ORIENTED_EDGE('',*,*,#6402,.F.); #6405=ORIENTED_EDGE('',*,*,#6404,.F.); #6407=ORIENTED_EDGE('',*,*,#6406,.F.); #6409=ORIENTED_EDGE('',*,*,#6408,.T.); #6411=ORIENTED_EDGE('',*,*,#6410,.F.); #6413=ORIENTED_EDGE('',*,*,#6412,.T.); #6415=ORIENTED_EDGE('',*,*,#6414,.F.); #6416=EDGE_LOOP('',(#6401,#6403,#6405,#6407,#6409,#6411,#6413,#6415)); #6417=FACE_BOUND('',#6416,.F.); #6419=ORIENTED_EDGE('',*,*,#6418,.F.); #6421=ORIENTED_EDGE('',*,*,#6420,.F.); #6423=ORIENTED_EDGE('',*,*,#6422,.T.); #6425=ORIENTED_EDGE('',*,*,#6424,.F.); #6427=ORIENTED_EDGE('',*,*,#6426,.T.); #6429=ORIENTED_EDGE('',*,*,#6428,.F.); #6431=ORIENTED_EDGE('',*,*,#6430,.T.); #6433=ORIENTED_EDGE('',*,*,#6432,.F.); #6435=ORIENTED_EDGE('',*,*,#6434,.F.); #6437=ORIENTED_EDGE('',*,*,#6436,.F.); #6439=ORIENTED_EDGE('',*,*,#6438,.F.); #6441=ORIENTED_EDGE('',*,*,#6440,.T.); #6443=ORIENTED_EDGE('',*,*,#6442,.F.); #6445=ORIENTED_EDGE('',*,*,#6444,.F.); #6447=ORIENTED_EDGE('',*,*,#6446,.T.); #6449=ORIENTED_EDGE('',*,*,#6448,.F.); #6450=EDGE_LOOP('',(#6419,#6421,#6423,#6425,#6427,#6429,#6431,#6433,#6435,#6437, #6439,#6441,#6443,#6445,#6447,#6449)); #6451=FACE_BOUND('',#6450,.F.); #6453=ORIENTED_EDGE('',*,*,#6452,.F.); #6455=ORIENTED_EDGE('',*,*,#6454,.F.); #6456=EDGE_LOOP('',(#6453,#6455)); #6457=FACE_BOUND('',#6456,.F.); #6459=ORIENTED_EDGE('',*,*,#6458,.F.); #6461=ORIENTED_EDGE('',*,*,#6460,.F.); #6462=EDGE_LOOP('',(#6459,#6461)); #6463=FACE_BOUND('',#6462,.F.); #6465=ORIENTED_EDGE('',*,*,#6464,.F.); #6467=ORIENTED_EDGE('',*,*,#6466,.F.); #6468=EDGE_LOOP('',(#6465,#6467)); #6469=FACE_BOUND('',#6468,.F.); #6471=ORIENTED_EDGE('',*,*,#6470,.F.); #6473=ORIENTED_EDGE('',*,*,#6472,.F.); #6474=EDGE_LOOP('',(#6471,#6473)); #6475=FACE_BOUND('',#6474,.F.); #6477=ORIENTED_EDGE('',*,*,#6476,.F.); #6479=ORIENTED_EDGE('',*,*,#6478,.F.); #6480=EDGE_LOOP('',(#6477,#6479)); #6481=FACE_BOUND('',#6480,.F.); #6483=ORIENTED_EDGE('',*,*,#6482,.F.); #6485=ORIENTED_EDGE('',*,*,#6484,.F.); #6486=EDGE_LOOP('',(#6483,#6485)); #6487=FACE_BOUND('',#6486,.F.); #6488=ADVANCED_FACE('',(#6333,#6339,#6345,#6351,#6357,#6363,#6369,#6375,#6381, #6387,#6393,#6399,#6417,#6451,#6457,#6463,#6469,#6475,#6481,#6487),#6283,.T.); #6489=CARTESIAN_POINT('',(6.45E0,1.176878221735E0,2.975E1)); #6490=DIRECTION('',(0.E0,1.E0,0.E0)); #6491=DIRECTION('',(-1.E0,0.E0,0.E0)); #6492=AXIS2_PLACEMENT_3D('',#6489,#6490,#6491); #6493=CYLINDRICAL_SURFACE('',#6492,1.E-1); #6494=ORIENTED_EDGE('',*,*,#6334,.T.); #6496=ORIENTED_EDGE('',*,*,#6495,.F.); #6498=ORIENTED_EDGE('',*,*,#6497,.F.); #6500=ORIENTED_EDGE('',*,*,#6499,.T.); #6501=EDGE_LOOP('',(#6494,#6496,#6498,#6500)); #6502=FACE_OUTER_BOUND('',#6501,.F.); #6503=ADVANCED_FACE('',(#6502),#6493,.F.); #6504=CARTESIAN_POINT('',(6.45E0,1.176878221735E0,2.975E1)); #6505=DIRECTION('',(0.E0,1.E0,0.E0)); #6506=DIRECTION('',(-1.E0,0.E0,0.E0)); #6507=AXIS2_PLACEMENT_3D('',#6504,#6505,#6506); #6508=CYLINDRICAL_SURFACE('',#6507,1.E-1); #6509=ORIENTED_EDGE('',*,*,#6336,.T.); #6510=ORIENTED_EDGE('',*,*,#6499,.F.); #6512=ORIENTED_EDGE('',*,*,#6511,.T.); #6513=ORIENTED_EDGE('',*,*,#6495,.T.); #6514=EDGE_LOOP('',(#6509,#6510,#6512,#6513)); #6515=FACE_OUTER_BOUND('',#6514,.F.); #6516=ADVANCED_FACE('',(#6515),#6508,.F.); #6517=CARTESIAN_POINT('',(6.45E0,1.234346967234E0,2.975E1)); #6518=DIRECTION('',(0.E0,1.E0,0.E0)); #6519=DIRECTION('',(-1.E0,0.E0,0.E0)); #6520=AXIS2_PLACEMENT_3D('',#6517,#6518,#6519); #6521=CONICAL_SURFACE('',#6520,7.288815195685E-2,6.E1); #6523=ORIENTED_EDGE('',*,*,#6522,.T.); #6524=ORIENTED_EDGE('',*,*,#6511,.F.); #6526=ORIENTED_EDGE('',*,*,#6525,.F.); #6527=EDGE_LOOP('',(#6523,#6524,#6526)); #6528=FACE_OUTER_BOUND('',#6527,.F.); #6529=ADVANCED_FACE('',(#6528),#6521,.F.); #6530=CARTESIAN_POINT('',(6.45E0,1.234346967234E0,2.975E1)); #6531=DIRECTION('',(0.E0,1.E0,0.E0)); #6532=DIRECTION('',(-1.E0,0.E0,0.E0)); #6533=AXIS2_PLACEMENT_3D('',#6530,#6531,#6532); #6534=CONICAL_SURFACE('',#6533,7.288815195685E-2,6.E1); #6535=ORIENTED_EDGE('',*,*,#6522,.F.); #6536=ORIENTED_EDGE('',*,*,#6525,.T.); #6537=ORIENTED_EDGE('',*,*,#6497,.T.); #6538=EDGE_LOOP('',(#6535,#6536,#6537)); #6539=FACE_OUTER_BOUND('',#6538,.F.); #6540=ADVANCED_FACE('',(#6539),#6534,.F.); #6541=CARTESIAN_POINT('',(7.45E0,1.176878221735E0,2.975E1)); #6542=DIRECTION('',(0.E0,1.E0,0.E0)); #6543=DIRECTION('',(-1.E0,0.E0,0.E0)); #6544=AXIS2_PLACEMENT_3D('',#6541,#6542,#6543); #6545=CYLINDRICAL_SURFACE('',#6544,1.E-1); #6546=ORIENTED_EDGE('',*,*,#6340,.T.); #6548=ORIENTED_EDGE('',*,*,#6547,.F.); #6550=ORIENTED_EDGE('',*,*,#6549,.F.); #6552=ORIENTED_EDGE('',*,*,#6551,.T.); #6553=EDGE_LOOP('',(#6546,#6548,#6550,#6552)); #6554=FACE_OUTER_BOUND('',#6553,.F.); #6555=ADVANCED_FACE('',(#6554),#6545,.F.); #6556=CARTESIAN_POINT('',(7.45E0,1.176878221735E0,2.975E1)); #6557=DIRECTION('',(0.E0,1.E0,0.E0)); #6558=DIRECTION('',(-1.E0,0.E0,0.E0)); #6559=AXIS2_PLACEMENT_3D('',#6556,#6557,#6558); #6560=CYLINDRICAL_SURFACE('',#6559,1.E-1); #6561=ORIENTED_EDGE('',*,*,#6342,.T.); #6562=ORIENTED_EDGE('',*,*,#6551,.F.); #6564=ORIENTED_EDGE('',*,*,#6563,.T.); #6565=ORIENTED_EDGE('',*,*,#6547,.T.); #6566=EDGE_LOOP('',(#6561,#6562,#6564,#6565)); #6567=FACE_OUTER_BOUND('',#6566,.F.); #6568=ADVANCED_FACE('',(#6567),#6560,.F.); #6569=CARTESIAN_POINT('',(7.45E0,1.234346967234E0,2.975E1)); #6570=DIRECTION('',(0.E0,1.E0,0.E0)); #6571=DIRECTION('',(-1.E0,0.E0,0.E0)); #6572=AXIS2_PLACEMENT_3D('',#6569,#6570,#6571); #6573=CONICAL_SURFACE('',#6572,7.288815195685E-2,6.E1); #6575=ORIENTED_EDGE('',*,*,#6574,.T.); #6576=ORIENTED_EDGE('',*,*,#6563,.F.); #6578=ORIENTED_EDGE('',*,*,#6577,.F.); #6579=EDGE_LOOP('',(#6575,#6576,#6578)); #6580=FACE_OUTER_BOUND('',#6579,.F.); #6581=ADVANCED_FACE('',(#6580),#6573,.F.); #6582=CARTESIAN_POINT('',(7.45E0,1.234346967234E0,2.975E1)); #6583=DIRECTION('',(0.E0,1.E0,0.E0)); #6584=DIRECTION('',(-1.E0,0.E0,0.E0)); #6585=AXIS2_PLACEMENT_3D('',#6582,#6583,#6584); #6586=CONICAL_SURFACE('',#6585,7.288815195685E-2,6.E1); #6587=ORIENTED_EDGE('',*,*,#6574,.F.); #6588=ORIENTED_EDGE('',*,*,#6577,.T.); #6589=ORIENTED_EDGE('',*,*,#6549,.T.); #6590=EDGE_LOOP('',(#6587,#6588,#6589)); #6591=FACE_OUTER_BOUND('',#6590,.F.); #6592=ADVANCED_FACE('',(#6591),#6586,.F.); #6593=CARTESIAN_POINT('',(2.046862696660E1,-7.805924235695E-2,7.E0)); #6594=DIRECTION('',(0.E0,1.E0,0.E0)); #6595=DIRECTION('',(0.E0,0.E0,1.E0)); #6596=AXIS2_PLACEMENT_3D('',#6593,#6594,#6595); #6597=CYLINDRICAL_SURFACE('',#6596,1.E0); #6598=ORIENTED_EDGE('',*,*,#5961,.F.); #6599=ORIENTED_EDGE('',*,*,#5550,.T.); #6601=ORIENTED_EDGE('',*,*,#6600,.T.); #6602=ORIENTED_EDGE('',*,*,#6221,.T.); #6603=EDGE_LOOP('',(#6598,#6599,#6601,#6602)); #6604=FACE_OUTER_BOUND('',#6603,.F.); #6605=ADVANCED_FACE('',(#6604),#6597,.F.); #6606=CARTESIAN_POINT('',(1.65E1,1.562633489099E0,7.5E0)); #6607=DIRECTION('',(0.E0,-1.E0,0.E0)); #6608=DIRECTION('',(0.E0,0.E0,-1.E0)); #6609=AXIS2_PLACEMENT_3D('',#6606,#6607,#6608); #6610=CYLINDRICAL_SURFACE('',#6609,5.E0); #6611=ORIENTED_EDGE('',*,*,#6600,.F.); #6612=ORIENTED_EDGE('',*,*,#5548,.T.); #6614=ORIENTED_EDGE('',*,*,#6613,.F.); #6615=ORIENTED_EDGE('',*,*,#6223,.T.); #6616=EDGE_LOOP('',(#6611,#6612,#6614,#6615)); #6617=FACE_OUTER_BOUND('',#6616,.F.); #6618=ADVANCED_FACE('',(#6617),#6610,.F.); #6619=CARTESIAN_POINT('',(2.15E1,1.5E0,2.5E0)); #6620=DIRECTION('',(0.E0,0.E0,-1.E0)); #6621=DIRECTION('',(-1.E0,0.E0,0.E0)); #6622=AXIS2_PLACEMENT_3D('',#6619,#6620,#6621); #6623=PLANE('',#6622); #6625=ORIENTED_EDGE('',*,*,#6624,.F.); #6626=ORIENTED_EDGE('',*,*,#6225,.F.); #6627=ORIENTED_EDGE('',*,*,#6613,.T.); #6628=ORIENTED_EDGE('',*,*,#5546,.T.); #6629=EDGE_LOOP('',(#6625,#6626,#6627,#6628)); #6630=FACE_OUTER_BOUND('',#6629,.F.); #6631=ADVANCED_FACE('',(#6630),#6623,.F.); #6632=CARTESIAN_POINT('',(7.5E0,1.562633489099E0,7.5E0)); #6633=DIRECTION('',(0.E0,-1.E0,0.E0)); #6634=DIRECTION('',(-1.E0,0.E0,0.E0)); #6635=AXIS2_PLACEMENT_3D('',#6632,#6633,#6634); #6636=CYLINDRICAL_SURFACE('',#6635,5.E0); #6638=ORIENTED_EDGE('',*,*,#6637,.F.); #6639=ORIENTED_EDGE('',*,*,#6227,.T.); #6640=ORIENTED_EDGE('',*,*,#6624,.T.); #6641=ORIENTED_EDGE('',*,*,#5544,.T.); #6642=EDGE_LOOP('',(#6638,#6639,#6640,#6641)); #6643=FACE_OUTER_BOUND('',#6642,.F.); #6644=ADVANCED_FACE('',(#6643),#6636,.F.); #6645=CARTESIAN_POINT('',(3.531373033403E0,1.157860978230E1,7.E0)); #6646=DIRECTION('',(0.E0,-1.E0,0.E0)); #6647=DIRECTION('',(0.E0,0.E0,1.E0)); #6648=AXIS2_PLACEMENT_3D('',#6645,#6646,#6647); #6649=CYLINDRICAL_SURFACE('',#6648,1.E0); #6650=ORIENTED_EDGE('',*,*,#5991,.F.); #6651=ORIENTED_EDGE('',*,*,#6229,.T.); #6652=ORIENTED_EDGE('',*,*,#6637,.T.); #6653=ORIENTED_EDGE('',*,*,#5542,.T.); #6654=EDGE_LOOP('',(#6650,#6651,#6652,#6653)); #6655=FACE_OUTER_BOUND('',#6654,.F.); #6656=ADVANCED_FACE('',(#6655),#6649,.F.); #6657=CARTESIAN_POINT('',(-1.E0,1.161044894892E1,7.E0)); #6658=DIRECTION('',(0.E0,-1.E0,0.E0)); #6659=DIRECTION('',(1.E0,0.E0,0.E0)); #6660=AXIS2_PLACEMENT_3D('',#6657,#6658,#6659); #6661=CYLINDRICAL_SURFACE('',#6660,1.E0); #6663=ORIENTED_EDGE('',*,*,#6662,.F.); #6664=ORIENTED_EDGE('',*,*,#6232,.T.); #6665=ORIENTED_EDGE('',*,*,#5987,.T.); #6666=ORIENTED_EDGE('',*,*,#5508,.T.); #6667=EDGE_LOOP('',(#6663,#6664,#6665,#6666)); #6668=FACE_OUTER_BOUND('',#6667,.F.); #6669=ADVANCED_FACE('',(#6668),#6661,.F.); #6670=CARTESIAN_POINT('',(0.E0,0.E0,0.E0)); #6671=DIRECTION('',(-1.E0,0.E0,0.E0)); #6672=DIRECTION('',(0.E0,0.E0,1.E0)); #6673=AXIS2_PLACEMENT_3D('',#6670,#6671,#6672); #6674=PLANE('',#6673); #6676=ORIENTED_EDGE('',*,*,#6675,.T.); #6677=ORIENTED_EDGE('',*,*,#6302,.T.); #6679=ORIENTED_EDGE('',*,*,#6678,.F.); #6680=ORIENTED_EDGE('',*,*,#5520,.F.); #6681=EDGE_LOOP('',(#6676,#6677,#6679,#6680)); #6682=FACE_OUTER_BOUND('',#6681,.F.); #6683=ADVANCED_FACE('',(#6682),#6674,.T.); #6684=CARTESIAN_POINT('',(0.E0,0.E0,0.E0)); #6685=DIRECTION('',(-1.E0,0.E0,0.E0)); #6686=DIRECTION('',(0.E0,0.E0,1.E0)); #6687=AXIS2_PLACEMENT_3D('',#6684,#6685,#6686); #6688=PLANE('',#6687); #6689=ORIENTED_EDGE('',*,*,#6662,.T.); #6690=ORIENTED_EDGE('',*,*,#5506,.F.); #6692=ORIENTED_EDGE('',*,*,#6691,.T.); #6693=ORIENTED_EDGE('',*,*,#6234,.T.); #6694=EDGE_LOOP('',(#6689,#6690,#6692,#6693)); #6695=FACE_OUTER_BOUND('',#6694,.F.); #6696=ADVANCED_FACE('',(#6695),#6688,.T.); #6697=CARTESIAN_POINT('',(-1.E0,-5.722942641981E-2,1.325E1)); #6698=DIRECTION('',(0.E0,1.E0,0.E0)); #6699=DIRECTION('',(1.E0,0.E0,0.E0)); #6700=AXIS2_PLACEMENT_3D('',#6697,#6698,#6699); #6701=CYLINDRICAL_SURFACE('',#6700,1.E0); #6702=ORIENTED_EDGE('',*,*,#6675,.F.); #6703=ORIENTED_EDGE('',*,*,#5518,.T.); #6705=ORIENTED_EDGE('',*,*,#6704,.T.); #6706=ORIENTED_EDGE('',*,*,#6304,.T.); #6707=EDGE_LOOP('',(#6702,#6703,#6705,#6706)); #6708=FACE_OUTER_BOUND('',#6707,.F.); #6709=ADVANCED_FACE('',(#6708),#6701,.F.); #6710=CARTESIAN_POINT('',(-2.E0,0.E0,1.225E1)); #6711=DIRECTION('',(0.E0,0.E0,1.E0)); #6712=DIRECTION('',(1.E0,0.E0,0.E0)); #6713=AXIS2_PLACEMENT_3D('',#6710,#6711,#6712); #6714=PLANE('',#6713); #6716=ORIENTED_EDGE('',*,*,#6715,.F.); #6717=ORIENTED_EDGE('',*,*,#6442,.T.); #6719=ORIENTED_EDGE('',*,*,#6718,.F.); #6720=ORIENTED_EDGE('',*,*,#5668,.F.); #6721=EDGE_LOOP('',(#6716,#6717,#6719,#6720)); #6722=FACE_OUTER_BOUND('',#6721,.F.); #6723=ADVANCED_FACE('',(#6722),#6714,.T.); #6724=CARTESIAN_POINT('',(-2.E0,0.E0,1.225E1)); #6725=DIRECTION('',(0.E0,0.E0,1.E0)); #6726=DIRECTION('',(1.E0,0.E0,0.E0)); #6727=AXIS2_PLACEMENT_3D('',#6724,#6725,#6726); #6728=PLANE('',#6727); #6729=ORIENTED_EDGE('',*,*,#6704,.F.); #6730=ORIENTED_EDGE('',*,*,#5516,.F.); #6732=ORIENTED_EDGE('',*,*,#6731,.T.); #6733=ORIENTED_EDGE('',*,*,#6306,.T.); #6734=EDGE_LOOP('',(#6729,#6730,#6732,#6733)); #6735=FACE_OUTER_BOUND('',#6734,.F.); #6736=ADVANCED_FACE('',(#6735),#6728,.T.); #6737=CARTESIAN_POINT('',(3.5E0,1.566978255297E0,1.325E1)); #6738=DIRECTION('',(0.E0,-1.E0,0.E0)); #6739=DIRECTION('',(-1.E0,0.E0,0.E0)); #6740=AXIS2_PLACEMENT_3D('',#6737,#6738,#6739); #6741=CYLINDRICAL_SURFACE('',#6740,1.E0); #6743=ORIENTED_EDGE('',*,*,#6742,.F.); #6744=ORIENTED_EDGE('',*,*,#6444,.T.); #6745=ORIENTED_EDGE('',*,*,#6715,.T.); #6746=ORIENTED_EDGE('',*,*,#5666,.T.); #6747=EDGE_LOOP('',(#6743,#6744,#6745,#6746)); #6748=FACE_OUTER_BOUND('',#6747,.F.); #6749=ADVANCED_FACE('',(#6748),#6741,.F.); #6750=CARTESIAN_POINT('',(2.5E0,1.5E0,2.5E0)); #6751=DIRECTION('',(-1.E0,0.E0,0.E0)); #6752=DIRECTION('',(0.E0,0.E0,1.E0)); #6753=AXIS2_PLACEMENT_3D('',#6750,#6751,#6752); #6754=PLANE('',#6753); #6756=ORIENTED_EDGE('',*,*,#6755,.T.); #6757=ORIENTED_EDGE('',*,*,#5650,.T.); #6759=ORIENTED_EDGE('',*,*,#6758,.F.); #6760=ORIENTED_EDGE('',*,*,#6408,.F.); #6761=EDGE_LOOP('',(#6756,#6757,#6759,#6760)); #6762=FACE_OUTER_BOUND('',#6761,.F.); #6763=ADVANCED_FACE('',(#6762),#6754,.F.); #6764=CARTESIAN_POINT('',(2.5E0,1.5E0,2.5E0)); #6765=DIRECTION('',(-1.E0,0.E0,0.E0)); #6766=DIRECTION('',(0.E0,0.E0,1.E0)); #6767=AXIS2_PLACEMENT_3D('',#6764,#6765,#6766); #6768=PLANE('',#6767); #6770=ORIENTED_EDGE('',*,*,#6769,.T.); #6771=ORIENTED_EDGE('',*,*,#6446,.F.); #6772=ORIENTED_EDGE('',*,*,#6742,.T.); #6773=ORIENTED_EDGE('',*,*,#5664,.T.); #6774=EDGE_LOOP('',(#6770,#6771,#6772,#6773)); #6775=FACE_OUTER_BOUND('',#6774,.F.); #6776=ADVANCED_FACE('',(#6775),#6768,.F.); #6777=CARTESIAN_POINT('',(5.5E0,1.568923974228E0,2.19375E1)); #6778=DIRECTION('',(0.E0,-1.E0,0.E0)); #6779=DIRECTION('',(-1.E0,0.E0,0.E0)); #6780=AXIS2_PLACEMENT_3D('',#6777,#6778,#6779); #6781=CYLINDRICAL_SURFACE('',#6780,3.E0); #6782=ORIENTED_EDGE('',*,*,#6755,.F.); #6783=ORIENTED_EDGE('',*,*,#6406,.T.); #6785=ORIENTED_EDGE('',*,*,#6784,.T.); #6786=ORIENTED_EDGE('',*,*,#5652,.T.); #6787=EDGE_LOOP('',(#6782,#6783,#6785,#6786)); #6788=FACE_OUTER_BOUND('',#6787,.F.); #6789=ADVANCED_FACE('',(#6788),#6781,.F.); #6790=CARTESIAN_POINT('',(2.5E0,0.E0,1.89375E1)); #6791=DIRECTION('',(0.E0,0.E0,1.E0)); #6792=DIRECTION('',(1.E0,0.E0,0.E0)); #6793=AXIS2_PLACEMENT_3D('',#6790,#6791,#6792); #6794=PLANE('',#6793); #6795=ORIENTED_EDGE('',*,*,#6784,.F.); #6796=ORIENTED_EDGE('',*,*,#6404,.T.); #6798=ORIENTED_EDGE('',*,*,#6797,.F.); #6799=ORIENTED_EDGE('',*,*,#5638,.F.); #6800=EDGE_LOOP('',(#6795,#6796,#6798,#6799)); #6801=FACE_OUTER_BOUND('',#6800,.F.); #6802=ADVANCED_FACE('',(#6801),#6794,.T.); #6803=CARTESIAN_POINT('',(1.85E1,-5.889194178308E-2,2.19375E1)); #6804=DIRECTION('',(0.E0,1.E0,0.E0)); #6805=DIRECTION('',(1.E0,0.E0,0.E0)); #6806=AXIS2_PLACEMENT_3D('',#6803,#6804,#6805); #6807=CYLINDRICAL_SURFACE('',#6806,3.E0); #6809=ORIENTED_EDGE('',*,*,#6808,.F.); #6810=ORIENTED_EDGE('',*,*,#5640,.T.); #6811=ORIENTED_EDGE('',*,*,#6797,.T.); #6812=ORIENTED_EDGE('',*,*,#6402,.T.); #6813=EDGE_LOOP('',(#6809,#6810,#6811,#6812)); #6814=FACE_OUTER_BOUND('',#6813,.F.); #6815=ADVANCED_FACE('',(#6814),#6807,.F.); #6816=CARTESIAN_POINT('',(2.15E1,1.5E0,2.95E1)); #6817=DIRECTION('',(1.E0,0.E0,0.E0)); #6818=DIRECTION('',(0.E0,0.E0,-1.E0)); #6819=AXIS2_PLACEMENT_3D('',#6816,#6817,#6818); #6820=PLANE('',#6819); #6821=ORIENTED_EDGE('',*,*,#6808,.T.); #6822=ORIENTED_EDGE('',*,*,#6400,.F.); #6824=ORIENTED_EDGE('',*,*,#6823,.T.); #6825=ORIENTED_EDGE('',*,*,#5642,.T.); #6826=EDGE_LOOP('',(#6821,#6822,#6824,#6825)); #6827=FACE_OUTER_BOUND('',#6826,.F.); #6828=ADVANCED_FACE('',(#6827),#6820,.F.); #6829=CARTESIAN_POINT('',(2.15E1,1.5E0,2.95E1)); #6830=DIRECTION('',(1.E0,0.E0,0.E0)); #6831=DIRECTION('',(0.E0,0.E0,-1.E0)); #6832=AXIS2_PLACEMENT_3D('',#6829,#6830,#6831); #6833=PLANE('',#6832); #6835=ORIENTED_EDGE('',*,*,#6834,.T.); #6836=ORIENTED_EDGE('',*,*,#5656,.T.); #6838=ORIENTED_EDGE('',*,*,#6837,.T.); #6839=ORIENTED_EDGE('',*,*,#6422,.F.); #6840=EDGE_LOOP('',(#6835,#6836,#6838,#6839)); #6841=FACE_OUTER_BOUND('',#6840,.F.); #6842=ADVANCED_FACE('',(#6841),#6833,.F.); #6843=CARTESIAN_POINT('',(1.65E1,1.562633489099E0,2.45E1)); #6844=DIRECTION('',(0.E0,-1.E0,0.E0)); #6845=DIRECTION('',(1.E0,0.E0,0.E0)); #6846=AXIS2_PLACEMENT_3D('',#6843,#6844,#6845); #6847=CYLINDRICAL_SURFACE('',#6846,5.E0); #6848=ORIENTED_EDGE('',*,*,#6823,.F.); #6849=ORIENTED_EDGE('',*,*,#6414,.T.); #6851=ORIENTED_EDGE('',*,*,#6850,.T.); #6852=ORIENTED_EDGE('',*,*,#5644,.T.); #6853=EDGE_LOOP('',(#6848,#6849,#6851,#6852)); #6854=FACE_OUTER_BOUND('',#6853,.F.); #6855=ADVANCED_FACE('',(#6854),#6847,.F.); #6856=CARTESIAN_POINT('',(2.5E0,1.5E0,2.95E1)); #6857=DIRECTION('',(0.E0,0.E0,1.E0)); #6858=DIRECTION('',(1.E0,0.E0,0.E0)); #6859=AXIS2_PLACEMENT_3D('',#6856,#6857,#6858); #6860=PLANE('',#6859); #6862=ORIENTED_EDGE('',*,*,#6861,.T.); #6863=ORIENTED_EDGE('',*,*,#5646,.T.); #6864=ORIENTED_EDGE('',*,*,#6850,.F.); #6865=ORIENTED_EDGE('',*,*,#6412,.F.); #6866=EDGE_LOOP('',(#6862,#6863,#6864,#6865)); #6867=FACE_OUTER_BOUND('',#6866,.F.); #6868=ADVANCED_FACE('',(#6867),#6860,.F.); #6869=CARTESIAN_POINT('',(7.5E0,1.562633489099E0,2.45E1)); #6870=DIRECTION('',(0.E0,-1.E0,0.E0)); #6871=DIRECTION('',(0.E0,0.E0,1.E0)); #6872=AXIS2_PLACEMENT_3D('',#6869,#6870,#6871); #6873=CYLINDRICAL_SURFACE('',#6872,5.E0); #6874=ORIENTED_EDGE('',*,*,#6861,.F.); #6875=ORIENTED_EDGE('',*,*,#6410,.T.); #6876=ORIENTED_EDGE('',*,*,#6758,.T.); #6877=ORIENTED_EDGE('',*,*,#5648,.T.); #6878=EDGE_LOOP('',(#6874,#6875,#6876,#6877)); #6879=FACE_OUTER_BOUND('',#6878,.F.); #6880=ADVANCED_FACE('',(#6879),#6873,.F.); #6881=CARTESIAN_POINT('',(1.85E1,1.568923974228E0,1.40625E1)); #6882=DIRECTION('',(0.E0,-1.E0,0.E0)); #6883=DIRECTION('',(1.E0,0.E0,0.E0)); #6884=AXIS2_PLACEMENT_3D('',#6881,#6882,#6883); #6885=CYLINDRICAL_SURFACE('',#6884,3.E0); #6886=ORIENTED_EDGE('',*,*,#6834,.F.); #6887=ORIENTED_EDGE('',*,*,#6420,.T.); #6889=ORIENTED_EDGE('',*,*,#6888,.T.); #6890=ORIENTED_EDGE('',*,*,#5658,.T.); #6891=EDGE_LOOP('',(#6886,#6887,#6889,#6890)); #6892=FACE_OUTER_BOUND('',#6891,.F.); #6893=ADVANCED_FACE('',(#6892),#6885,.F.); #6894=CARTESIAN_POINT('',(2.15E1,0.E0,1.70625E1)); #6895=DIRECTION('',(0.E0,0.E0,-1.E0)); #6896=DIRECTION('',(-1.E0,0.E0,0.E0)); #6897=AXIS2_PLACEMENT_3D('',#6894,#6895,#6896); #6898=PLANE('',#6897); #6899=ORIENTED_EDGE('',*,*,#6888,.F.); #6900=ORIENTED_EDGE('',*,*,#6418,.T.); #6902=ORIENTED_EDGE('',*,*,#6901,.F.); #6903=ORIENTED_EDGE('',*,*,#5660,.F.); #6904=EDGE_LOOP('',(#6899,#6900,#6902,#6903)); #6905=FACE_OUTER_BOUND('',#6904,.F.); #6906=ADVANCED_FACE('',(#6905),#6898,.T.); #6907=CARTESIAN_POINT('',(5.5E0,-5.889194178308E-2,1.40625E1)); #6908=DIRECTION('',(0.E0,1.E0,0.E0)); #6909=DIRECTION('',(-1.E0,0.E0,0.E0)); #6910=AXIS2_PLACEMENT_3D('',#6907,#6908,#6909); #6911=CYLINDRICAL_SURFACE('',#6910,3.E0); #6912=ORIENTED_EDGE('',*,*,#6769,.F.); #6913=ORIENTED_EDGE('',*,*,#5662,.T.); #6914=ORIENTED_EDGE('',*,*,#6901,.T.); #6915=ORIENTED_EDGE('',*,*,#6448,.T.); #6916=EDGE_LOOP('',(#6912,#6913,#6914,#6915)); #6917=FACE_OUTER_BOUND('',#6916,.F.); #6918=ADVANCED_FACE('',(#6917),#6911,.F.); #6919=CARTESIAN_POINT('',(2.05E1,-5.889194178308E-2,1.325E1)); #6920=DIRECTION('',(0.E0,1.E0,0.E0)); #6921=DIRECTION('',(1.E0,0.E0,0.E0)); #6922=AXIS2_PLACEMENT_3D('',#6919,#6920,#6921); #6923=CYLINDRICAL_SURFACE('',#6922,1.E0); #6924=ORIENTED_EDGE('',*,*,#6837,.F.); #6925=ORIENTED_EDGE('',*,*,#5686,.T.); #6927=ORIENTED_EDGE('',*,*,#6926,.T.); #6928=ORIENTED_EDGE('',*,*,#6424,.T.); #6929=EDGE_LOOP('',(#6924,#6925,#6927,#6928)); #6930=FACE_OUTER_BOUND('',#6929,.F.); #6931=ADVANCED_FACE('',(#6930),#6923,.F.); #6932=CARTESIAN_POINT('',(2.6E1,0.E0,1.225E1)); #6933=DIRECTION('',(0.E0,0.E0,-1.E0)); #6934=DIRECTION('',(-1.E0,0.E0,0.E0)); #6935=AXIS2_PLACEMENT_3D('',#6932,#6933,#6934); #6936=PLANE('',#6935); #6938=ORIENTED_EDGE('',*,*,#6937,.F.); #6939=ORIENTED_EDGE('',*,*,#6290,.F.); #6941=ORIENTED_EDGE('',*,*,#6940,.T.); #6942=ORIENTED_EDGE('',*,*,#5532,.T.); #6943=EDGE_LOOP('',(#6938,#6939,#6941,#6942)); #6944=FACE_OUTER_BOUND('',#6943,.F.); #6945=ADVANCED_FACE('',(#6944),#6936,.F.); #6946=CARTESIAN_POINT('',(2.6E1,0.E0,1.225E1)); #6947=DIRECTION('',(0.E0,0.E0,-1.E0)); #6948=DIRECTION('',(-1.E0,0.E0,0.E0)); #6949=AXIS2_PLACEMENT_3D('',#6946,#6947,#6948); #6950=PLANE('',#6949); #6951=ORIENTED_EDGE('',*,*,#6926,.F.); #6952=ORIENTED_EDGE('',*,*,#5684,.T.); #6954=ORIENTED_EDGE('',*,*,#6953,.F.); #6955=ORIENTED_EDGE('',*,*,#6426,.F.); #6956=EDGE_LOOP('',(#6951,#6952,#6954,#6955)); #6957=FACE_OUTER_BOUND('',#6956,.F.); #6958=ADVANCED_FACE('',(#6957),#6950,.F.); #6959=CARTESIAN_POINT('',(2.5E1,1.568923974228E0,1.325E1)); #6960=DIRECTION('',(0.E0,-1.E0,0.E0)); #6961=DIRECTION('',(-1.E0,0.E0,0.E0)); #6962=AXIS2_PLACEMENT_3D('',#6959,#6960,#6961); #6963=CYLINDRICAL_SURFACE('',#6962,1.E0); #6965=ORIENTED_EDGE('',*,*,#6964,.F.); #6966=ORIENTED_EDGE('',*,*,#6292,.T.); #6967=ORIENTED_EDGE('',*,*,#6937,.T.); #6968=ORIENTED_EDGE('',*,*,#5530,.T.); #6969=EDGE_LOOP('',(#6965,#6966,#6967,#6968)); #6970=FACE_OUTER_BOUND('',#6969,.F.); #6971=ADVANCED_FACE('',(#6970),#6963,.F.); #6972=CARTESIAN_POINT('',(2.4E1,0.E0,3.2E1)); #6973=DIRECTION('',(1.E0,0.E0,0.E0)); #6974=DIRECTION('',(0.E0,0.E0,-1.E0)); #6975=AXIS2_PLACEMENT_3D('',#6972,#6973,#6974); #6976=PLANE('',#6975); #6977=ORIENTED_EDGE('',*,*,#6964,.T.); #6978=ORIENTED_EDGE('',*,*,#5528,.F.); #6980=ORIENTED_EDGE('',*,*,#6979,.T.); #6981=ORIENTED_EDGE('',*,*,#6294,.T.); #6982=EDGE_LOOP('',(#6977,#6978,#6980,#6981)); #6983=FACE_OUTER_BOUND('',#6982,.F.); #6984=ADVANCED_FACE('',(#6983),#6976,.T.); #6985=CARTESIAN_POINT('',(2.4E1,0.E0,3.2E1)); #6986=DIRECTION('',(1.E0,0.E0,0.E0)); #6987=DIRECTION('',(0.E0,0.E0,-1.E0)); #6988=AXIS2_PLACEMENT_3D('',#6985,#6986,#6987); #6989=PLANE('',#6988); #6991=ORIENTED_EDGE('',*,*,#6990,.T.); #6992=ORIENTED_EDGE('',*,*,#6242,.T.); #6994=ORIENTED_EDGE('',*,*,#6993,.F.); #6995=ORIENTED_EDGE('',*,*,#5498,.F.); #6996=EDGE_LOOP('',(#6991,#6992,#6994,#6995)); #6997=FACE_OUTER_BOUND('',#6996,.F.); #6998=ADVANCED_FACE('',(#6997),#6989,.T.); #6999=CARTESIAN_POINT('',(2.4E1,0.E0,2.8E1)); #7000=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #7001=DIRECTION('',(0.E0,1.E0,0.E0)); #7002=AXIS2_PLACEMENT_3D('',#6999,#7000,#7001); #7003=PLANE('',#7002); #7004=ORIENTED_EDGE('',*,*,#6979,.F.); #7005=ORIENTED_EDGE('',*,*,#5526,.T.); #7007=ORIENTED_EDGE('',*,*,#7006,.T.); #7008=ORIENTED_EDGE('',*,*,#6296,.F.); #7009=EDGE_LOOP('',(#7004,#7005,#7007,#7008)); #7010=FACE_OUTER_BOUND('',#7009,.F.); #7011=ADVANCED_FACE('',(#7010),#7003,.T.); #7012=CARTESIAN_POINT('',(0.E0,0.E0,3.2E1)); #7013=DIRECTION('',(0.E0,0.E0,1.E0)); #7014=DIRECTION('',(1.E0,0.E0,0.E0)); #7015=AXIS2_PLACEMENT_3D('',#7012,#7013,#7014); #7016=PLANE('',#7015); #7017=ORIENTED_EDGE('',*,*,#5524,.F.); #7019=ORIENTED_EDGE('',*,*,#7018,.T.); #7020=ORIENTED_EDGE('',*,*,#6298,.T.); #7021=ORIENTED_EDGE('',*,*,#7006,.F.); #7022=EDGE_LOOP('',(#7017,#7019,#7020,#7021)); #7023=FACE_OUTER_BOUND('',#7022,.F.); #7024=ADVANCED_FACE('',(#7023),#7016,.T.); #7025=CARTESIAN_POINT('',(4.E0,0.E0,3.2E1)); #7026=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #7027=DIRECTION('',(0.E0,1.E0,0.E0)); #7028=AXIS2_PLACEMENT_3D('',#7025,#7026,#7027); #7029=PLANE('',#7028); #7030=ORIENTED_EDGE('',*,*,#7018,.F.); #7031=ORIENTED_EDGE('',*,*,#5522,.T.); #7032=ORIENTED_EDGE('',*,*,#6678,.T.); #7033=ORIENTED_EDGE('',*,*,#6300,.F.); #7034=EDGE_LOOP('',(#7030,#7031,#7032,#7033)); #7035=FACE_OUTER_BOUND('',#7034,.F.); #7036=ADVANCED_FACE('',(#7035),#7029,.T.); #7037=CARTESIAN_POINT('',(2.5E1,-7.055249658685E-2,7.E0)); #7038=DIRECTION('',(0.E0,1.E0,0.E0)); #7039=DIRECTION('',(-1.E0,0.E0,0.E0)); #7040=AXIS2_PLACEMENT_3D('',#7037,#7038,#7039); #7041=CYLINDRICAL_SURFACE('',#7040,1.E0); #7042=ORIENTED_EDGE('',*,*,#6990,.F.); #7043=ORIENTED_EDGE('',*,*,#5496,.T.); #7044=ORIENTED_EDGE('',*,*,#5965,.T.); #7045=ORIENTED_EDGE('',*,*,#6244,.T.); #7046=EDGE_LOOP('',(#7042,#7043,#7044,#7045)); #7047=FACE_OUTER_BOUND('',#7046,.F.); #7048=ADVANCED_FACE('',(#7047),#7041,.F.); #7049=CARTESIAN_POINT('',(2.E1,0.E0,0.E0)); #7050=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #7051=DIRECTION('',(0.E0,1.E0,0.E0)); #7052=AXIS2_PLACEMENT_3D('',#7049,#7050,#7051); #7053=PLANE('',#7052); #7055=ORIENTED_EDGE('',*,*,#7054,.F.); #7056=ORIENTED_EDGE('',*,*,#5500,.T.); #7057=ORIENTED_EDGE('',*,*,#6993,.T.); #7058=ORIENTED_EDGE('',*,*,#6240,.F.); #7059=EDGE_LOOP('',(#7055,#7056,#7057,#7058)); #7060=FACE_OUTER_BOUND('',#7059,.F.); #7061=ADVANCED_FACE('',(#7060),#7053,.T.); #7062=CARTESIAN_POINT('',(2.4E1,0.E0,0.E0)); #7063=DIRECTION('',(0.E0,0.E0,-1.E0)); #7064=DIRECTION('',(-1.E0,0.E0,0.E0)); #7065=AXIS2_PLACEMENT_3D('',#7062,#7063,#7064); #7066=PLANE('',#7065); #7067=ORIENTED_EDGE('',*,*,#5502,.F.); #7068=ORIENTED_EDGE('',*,*,#7054,.T.); #7069=ORIENTED_EDGE('',*,*,#6238,.T.); #7071=ORIENTED_EDGE('',*,*,#7070,.F.); #7072=EDGE_LOOP('',(#7067,#7068,#7069,#7071)); #7073=FACE_OUTER_BOUND('',#7072,.F.); #7074=ADVANCED_FACE('',(#7073),#7066,.T.); #7075=CARTESIAN_POINT('',(0.E0,0.E0,4.E0)); #7076=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #7077=DIRECTION('',(0.E0,1.E0,0.E0)); #7078=AXIS2_PLACEMENT_3D('',#7075,#7076,#7077); #7079=PLANE('',#7078); #7080=ORIENTED_EDGE('',*,*,#6691,.F.); #7081=ORIENTED_EDGE('',*,*,#5504,.T.); #7082=ORIENTED_EDGE('',*,*,#7070,.T.); #7083=ORIENTED_EDGE('',*,*,#6236,.F.); #7084=EDGE_LOOP('',(#7080,#7081,#7082,#7083)); #7085=FACE_OUTER_BOUND('',#7084,.F.); #7086=ADVANCED_FACE('',(#7085),#7079,.T.); #7087=CARTESIAN_POINT('',(2.55E1,1.5E0,1.225E1)); #7088=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #7089=DIRECTION('',(0.E0,-1.E0,0.E0)); #7090=AXIS2_PLACEMENT_3D('',#7087,#7088,#7089); #7091=PLANE('',#7090); #7092=ORIENTED_EDGE('',*,*,#6940,.F.); #7093=ORIENTED_EDGE('',*,*,#6288,.T.); #7095=ORIENTED_EDGE('',*,*,#7094,.T.); #7096=ORIENTED_EDGE('',*,*,#5534,.F.); #7097=EDGE_LOOP('',(#7092,#7093,#7095,#7096)); #7098=FACE_OUTER_BOUND('',#7097,.F.); #7099=ADVANCED_FACE('',(#7098),#7091,.T.); #7100=CARTESIAN_POINT('',(2.6E1,2.5E0,8.E0)); #7101=DIRECTION('',(-1.E0,0.E0,0.E0)); #7102=DIRECTION('',(0.E0,-1.E0,0.E0)); #7103=AXIS2_PLACEMENT_3D('',#7100,#7101,#7102); #7104=PLANE('',#7103); #7105=ORIENTED_EDGE('',*,*,#5968,.T.); #7106=ORIENTED_EDGE('',*,*,#5536,.T.); #7107=ORIENTED_EDGE('',*,*,#7094,.F.); #7108=ORIENTED_EDGE('',*,*,#6286,.F.); #7109=ORIENTED_EDGE('',*,*,#6165,.F.); #7111=ORIENTED_EDGE('',*,*,#7110,.F.); #7112=EDGE_LOOP('',(#7105,#7106,#7107,#7108,#7109,#7111)); #7113=FACE_OUTER_BOUND('',#7112,.F.); #7114=ADVANCED_FACE('',(#7113),#7104,.F.); #7115=CARTESIAN_POINT('',(2.1E1,1.15E1,8.E0)); #7116=DIRECTION('',(-8.741572761215E-1,-4.856429311786E-1,0.E0)); #7117=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0)); #7118=AXIS2_PLACEMENT_3D('',#7115,#7116,#7117); #7119=PLANE('',#7118); #7120=ORIENTED_EDGE('',*,*,#5970,.T.); #7121=ORIENTED_EDGE('',*,*,#7110,.T.); #7122=ORIENTED_EDGE('',*,*,#6163,.F.); #7124=ORIENTED_EDGE('',*,*,#7123,.F.); #7125=EDGE_LOOP('',(#7120,#7121,#7122,#7124)); #7126=FACE_OUTER_BOUND('',#7125,.F.); #7127=ADVANCED_FACE('',(#7126),#7119,.F.); #7128=CARTESIAN_POINT('',(1.9E1,1.15E1,8.E0)); #7129=DIRECTION('',(0.E0,-1.E0,0.E0)); #7130=DIRECTION('',(1.E0,0.E0,0.E0)); #7131=AXIS2_PLACEMENT_3D('',#7128,#7129,#7130); #7132=PLANE('',#7131); #7133=ORIENTED_EDGE('',*,*,#5972,.F.); #7134=ORIENTED_EDGE('',*,*,#7123,.T.); #7135=ORIENTED_EDGE('',*,*,#6161,.F.); #7137=ORIENTED_EDGE('',*,*,#7136,.F.); #7138=EDGE_LOOP('',(#7133,#7134,#7135,#7137)); #7139=FACE_OUTER_BOUND('',#7138,.F.); #7141=ORIENTED_EDGE('',*,*,#7140,.T.); #7143=ORIENTED_EDGE('',*,*,#7142,.T.); #7144=EDGE_LOOP('',(#7141,#7143)); #7145=FACE_BOUND('',#7144,.F.); #7147=ORIENTED_EDGE('',*,*,#7146,.T.); #7149=ORIENTED_EDGE('',*,*,#7148,.T.); #7150=EDGE_LOOP('',(#7147,#7149)); #7151=FACE_BOUND('',#7150,.F.); #7152=ADVANCED_FACE('',(#7139,#7145,#7151),#7132,.F.); #7153=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0)); #7154=DIRECTION('',(1.E0,0.E0,0.E0)); #7155=DIRECTION('',(0.E0,1.E0,0.E0)); #7156=AXIS2_PLACEMENT_3D('',#7153,#7154,#7155); #7157=PLANE('',#7156); #7159=ORIENTED_EDGE('',*,*,#7158,.T.); #7160=ORIENTED_EDGE('',*,*,#6430,.F.); #7162=ORIENTED_EDGE('',*,*,#7161,.T.); #7163=ORIENTED_EDGE('',*,*,#5680,.T.); #7164=EDGE_LOOP('',(#7159,#7160,#7162,#7163)); #7165=FACE_OUTER_BOUND('',#7164,.F.); #7166=ADVANCED_FACE('',(#7165),#7157,.F.); #7167=CARTESIAN_POINT('',(1.9E1,1.5E0,8.E0)); #7168=DIRECTION('',(1.E0,0.E0,0.E0)); #7169=DIRECTION('',(0.E0,1.E0,0.E0)); #7170=AXIS2_PLACEMENT_3D('',#7167,#7168,#7169); #7171=PLANE('',#7170); #7172=ORIENTED_EDGE('',*,*,#6325,.F.); #7173=ORIENTED_EDGE('',*,*,#5974,.T.); #7174=ORIENTED_EDGE('',*,*,#7136,.T.); #7175=ORIENTED_EDGE('',*,*,#6159,.F.); #7176=EDGE_LOOP('',(#7172,#7173,#7174,#7175)); #7177=FACE_OUTER_BOUND('',#7176,.F.); #7178=ADVANCED_FACE('',(#7177),#7171,.F.); #7179=CARTESIAN_POINT('',(1.8E1,-7.099592191979E-2,1.1E1)); #7180=DIRECTION('',(0.E0,1.E0,0.E0)); #7181=DIRECTION('',(1.E0,0.E0,0.E0)); #7182=AXIS2_PLACEMENT_3D('',#7179,#7180,#7181); #7183=CYLINDRICAL_SURFACE('',#7182,1.E0); #7184=ORIENTED_EDGE('',*,*,#7158,.F.); #7185=ORIENTED_EDGE('',*,*,#5678,.T.); #7187=ORIENTED_EDGE('',*,*,#7186,.T.); #7188=ORIENTED_EDGE('',*,*,#6432,.T.); #7189=EDGE_LOOP('',(#7184,#7185,#7187,#7188)); #7190=FACE_OUTER_BOUND('',#7189,.F.); #7191=ADVANCED_FACE('',(#7190),#7183,.F.); #7192=CARTESIAN_POINT('',(5.E0,1.5E0,1.E1)); #7193=DIRECTION('',(0.E0,0.E0,1.E0)); #7194=DIRECTION('',(0.E0,-1.E0,0.E0)); #7195=AXIS2_PLACEMENT_3D('',#7192,#7193,#7194); #7196=PLANE('',#7195); #7198=ORIENTED_EDGE('',*,*,#7197,.F.); #7199=ORIENTED_EDGE('',*,*,#6434,.T.); #7200=ORIENTED_EDGE('',*,*,#7186,.F.); #7201=ORIENTED_EDGE('',*,*,#5676,.F.); #7202=EDGE_LOOP('',(#7198,#7199,#7200,#7201)); #7203=FACE_OUTER_BOUND('',#7202,.F.); #7204=ADVANCED_FACE('',(#7203),#7196,.T.); #7205=CARTESIAN_POINT('',(6.E0,1.567729432957E0,1.1E1)); #7206=DIRECTION('',(0.E0,-1.E0,0.E0)); #7207=DIRECTION('',(-1.E0,0.E0,0.E0)); #7208=AXIS2_PLACEMENT_3D('',#7205,#7206,#7207); #7209=CYLINDRICAL_SURFACE('',#7208,1.E0); #7211=ORIENTED_EDGE('',*,*,#7210,.F.); #7212=ORIENTED_EDGE('',*,*,#6436,.T.); #7213=ORIENTED_EDGE('',*,*,#7197,.T.); #7214=ORIENTED_EDGE('',*,*,#5674,.T.); #7215=EDGE_LOOP('',(#7211,#7212,#7213,#7214)); #7216=FACE_OUTER_BOUND('',#7215,.F.); #7217=ADVANCED_FACE('',(#7216),#7209,.F.); #7218=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0)); #7219=DIRECTION('',(1.E0,0.E0,0.E0)); #7220=DIRECTION('',(0.E0,1.E0,0.E0)); #7221=AXIS2_PLACEMENT_3D('',#7218,#7219,#7220); #7222=PLANE('',#7221); #7223=ORIENTED_EDGE('',*,*,#7210,.T.); #7224=ORIENTED_EDGE('',*,*,#5672,.F.); #7226=ORIENTED_EDGE('',*,*,#7225,.T.); #7227=ORIENTED_EDGE('',*,*,#6438,.T.); #7228=EDGE_LOOP('',(#7223,#7224,#7226,#7227)); #7229=FACE_OUTER_BOUND('',#7228,.F.); #7230=ADVANCED_FACE('',(#7229),#7222,.T.); #7231=CARTESIAN_POINT('',(5.E0,1.5E0,8.E0)); #7232=DIRECTION('',(1.E0,0.E0,0.E0)); #7233=DIRECTION('',(0.E0,1.E0,0.E0)); #7234=AXIS2_PLACEMENT_3D('',#7231,#7232,#7233); #7235=PLANE('',#7234); #7236=ORIENTED_EDGE('',*,*,#6322,.T.); #7238=ORIENTED_EDGE('',*,*,#7237,.T.); #7240=ORIENTED_EDGE('',*,*,#7239,.F.); #7241=ORIENTED_EDGE('',*,*,#5978,.T.); #7242=EDGE_LOOP('',(#7236,#7238,#7240,#7241)); #7243=FACE_OUTER_BOUND('',#7242,.F.); #7244=ADVANCED_FACE('',(#7243),#7235,.T.); #7245=CARTESIAN_POINT('',(5.E0,0.E0,1.175E1)); #7246=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #7247=DIRECTION('',(0.E0,1.E0,0.E0)); #7248=AXIS2_PLACEMENT_3D('',#7245,#7246,#7247); #7249=PLANE('',#7248); #7250=ORIENTED_EDGE('',*,*,#7225,.F.); #7251=ORIENTED_EDGE('',*,*,#5670,.T.); #7252=ORIENTED_EDGE('',*,*,#6718,.T.); #7253=ORIENTED_EDGE('',*,*,#6440,.F.); #7254=EDGE_LOOP('',(#7250,#7251,#7252,#7253)); #7255=FACE_OUTER_BOUND('',#7254,.F.); #7256=ADVANCED_FACE('',(#7255),#7249,.T.); #7257=CARTESIAN_POINT('',(0.E0,0.E0,1.E1)); #7258=DIRECTION('',(0.E0,0.E0,1.E0)); #7259=DIRECTION('',(1.E0,0.E0,0.E0)); #7260=AXIS2_PLACEMENT_3D('',#7257,#7258,#7259); #7261=PLANE('',#7260); #7263=ORIENTED_EDGE('',*,*,#7262,.F.); #7264=ORIENTED_EDGE('',*,*,#6312,.F.); #7266=ORIENTED_EDGE('',*,*,#7265,.F.); #7268=ORIENTED_EDGE('',*,*,#7267,.F.); #7270=ORIENTED_EDGE('',*,*,#7269,.F.); #7271=ORIENTED_EDGE('',*,*,#7237,.F.); #7272=ORIENTED_EDGE('',*,*,#6320,.F.); #7274=ORIENTED_EDGE('',*,*,#7273,.T.); #7276=ORIENTED_EDGE('',*,*,#7275,.F.); #7277=EDGE_LOOP('',(#7263,#7264,#7266,#7268,#7270,#7271,#7272,#7274,#7276)); #7278=FACE_OUTER_BOUND('',#7277,.F.); #7280=ORIENTED_EDGE('',*,*,#7279,.T.); #7282=ORIENTED_EDGE('',*,*,#7281,.T.); #7283=EDGE_LOOP('',(#7280,#7282)); #7284=FACE_BOUND('',#7283,.F.); #7286=ORIENTED_EDGE('',*,*,#7285,.F.); #7288=ORIENTED_EDGE('',*,*,#7287,.T.); #7290=ORIENTED_EDGE('',*,*,#7289,.F.); #7292=ORIENTED_EDGE('',*,*,#7291,.T.); #7294=ORIENTED_EDGE('',*,*,#7293,.F.); #7296=ORIENTED_EDGE('',*,*,#7295,.T.); #7298=ORIENTED_EDGE('',*,*,#7297,.F.); #7300=ORIENTED_EDGE('',*,*,#7299,.T.); #7302=ORIENTED_EDGE('',*,*,#7301,.F.); #7304=ORIENTED_EDGE('',*,*,#7303,.T.); #7306=ORIENTED_EDGE('',*,*,#7305,.F.); #7308=ORIENTED_EDGE('',*,*,#7307,.T.); #7309=EDGE_LOOP('',(#7286,#7288,#7290,#7292,#7294,#7296,#7298,#7300,#7302,#7304, #7306,#7308)); #7310=FACE_BOUND('',#7309,.F.); #7311=ADVANCED_FACE('',(#7278,#7284,#7310),#7261,.T.); #7312=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0)); #7313=DIRECTION('',(0.E0,0.E0,1.E0)); #7314=DIRECTION('',(1.E0,0.E0,0.E0)); #7315=AXIS2_PLACEMENT_3D('',#7312,#7313,#7314); #7316=CYLINDRICAL_SURFACE('',#7315,1.625E-1); #7317=ORIENTED_EDGE('',*,*,#6031,.T.); #7319=ORIENTED_EDGE('',*,*,#7318,.T.); #7320=ORIENTED_EDGE('',*,*,#7279,.F.); #7322=ORIENTED_EDGE('',*,*,#7321,.F.); #7323=EDGE_LOOP('',(#7317,#7319,#7320,#7322)); #7324=FACE_OUTER_BOUND('',#7323,.F.); #7325=ADVANCED_FACE('',(#7324),#7316,.F.); #7326=CARTESIAN_POINT('',(4.25E0,1.05E1,8.E0)); #7327=DIRECTION('',(0.E0,0.E0,1.E0)); #7328=DIRECTION('',(1.E0,0.E0,0.E0)); #7329=AXIS2_PLACEMENT_3D('',#7326,#7327,#7328); #7330=CYLINDRICAL_SURFACE('',#7329,1.625E-1); #7331=ORIENTED_EDGE('',*,*,#6033,.T.); #7332=ORIENTED_EDGE('',*,*,#7321,.T.); #7333=ORIENTED_EDGE('',*,*,#7281,.F.); #7334=ORIENTED_EDGE('',*,*,#7318,.F.); #7335=EDGE_LOOP('',(#7331,#7332,#7333,#7334)); #7336=FACE_OUTER_BOUND('',#7335,.F.); #7337=ADVANCED_FACE('',(#7336),#7330,.F.); #7338=CARTESIAN_POINT('',(2.5E-1,1.5E0,1.2E1)); #7339=DIRECTION('',(1.E0,0.E0,0.E0)); #7340=DIRECTION('',(0.E0,-1.E0,0.E0)); #7341=AXIS2_PLACEMENT_3D('',#7338,#7339,#7340); #7342=PLANE('',#7341); #7343=ORIENTED_EDGE('',*,*,#6314,.T.); #7344=ORIENTED_EDGE('',*,*,#7262,.T.); #7346=ORIENTED_EDGE('',*,*,#7345,.T.); #7347=EDGE_LOOP('',(#7343,#7344,#7346)); #7348=FACE_OUTER_BOUND('',#7347,.F.); #7349=ADVANCED_FACE('',(#7348),#7342,.F.); #7350=CARTESIAN_POINT('',(2.5E-1,6.5E0,1.E1)); #7351=DIRECTION('',(0.E0,5.E-1,8.660254037844E-1)); #7352=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1)); #7353=AXIS2_PLACEMENT_3D('',#7350,#7351,#7352); #7354=PLANE('',#7353); #7355=ORIENTED_EDGE('',*,*,#6316,.F.); #7356=ORIENTED_EDGE('',*,*,#7345,.F.); #7357=ORIENTED_EDGE('',*,*,#7275,.T.); #7359=ORIENTED_EDGE('',*,*,#7358,.T.); #7360=EDGE_LOOP('',(#7355,#7356,#7357,#7359)); #7361=FACE_OUTER_BOUND('',#7360,.F.); #7363=ORIENTED_EDGE('',*,*,#7362,.T.); #7365=ORIENTED_EDGE('',*,*,#7364,.T.); #7366=EDGE_LOOP('',(#7363,#7365)); #7367=FACE_BOUND('',#7366,.F.); #7368=ADVANCED_FACE('',(#7361,#7367),#7354,.T.); #7369=CARTESIAN_POINT('',(2.E0,1.5E0,1.2E1)); #7370=DIRECTION('',(1.E0,0.E0,0.E0)); #7371=DIRECTION('',(0.E0,-1.E0,0.E0)); #7372=AXIS2_PLACEMENT_3D('',#7369,#7370,#7371); #7373=PLANE('',#7372); #7374=ORIENTED_EDGE('',*,*,#6318,.F.); #7375=ORIENTED_EDGE('',*,*,#7358,.F.); #7376=ORIENTED_EDGE('',*,*,#7273,.F.); #7377=EDGE_LOOP('',(#7374,#7375,#7376)); #7378=FACE_OUTER_BOUND('',#7377,.F.); #7379=ADVANCED_FACE('',(#7378),#7373,.T.); #7380=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1)); #7381=DIRECTION('',(0.E0,-1.E0,0.E0)); #7382=DIRECTION('',(1.E0,0.E0,0.E0)); #7383=AXIS2_PLACEMENT_3D('',#7380,#7381,#7382); #7384=CYLINDRICAL_SURFACE('',#7383,2.575E-1); #7386=ORIENTED_EDGE('',*,*,#7385,.F.); #7387=ORIENTED_EDGE('',*,*,#7362,.F.); #7389=ORIENTED_EDGE('',*,*,#7388,.F.); #7391=ORIENTED_EDGE('',*,*,#7390,.F.); #7392=EDGE_LOOP('',(#7386,#7387,#7389,#7391)); #7393=FACE_OUTER_BOUND('',#7392,.F.); #7394=ADVANCED_FACE('',(#7393),#7384,.F.); #7395=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1)); #7396=DIRECTION('',(0.E0,-1.E0,0.E0)); #7397=DIRECTION('',(1.E0,0.E0,0.E0)); #7398=AXIS2_PLACEMENT_3D('',#7395,#7396,#7397); #7399=CYLINDRICAL_SURFACE('',#7398,2.575E-1); #7400=ORIENTED_EDGE('',*,*,#7388,.T.); #7401=ORIENTED_EDGE('',*,*,#7364,.F.); #7402=ORIENTED_EDGE('',*,*,#7385,.T.); #7404=ORIENTED_EDGE('',*,*,#7403,.F.); #7405=EDGE_LOOP('',(#7400,#7401,#7402,#7404)); #7406=FACE_OUTER_BOUND('',#7405,.F.); #7407=ADVANCED_FACE('',(#7406),#7399,.F.); #7408=CARTESIAN_POINT('',(1.125E0,1.E0,1.2E1)); #7409=DIRECTION('',(0.E0,-1.E0,0.E0)); #7410=DIRECTION('',(1.E0,0.E0,0.E0)); #7411=AXIS2_PLACEMENT_3D('',#7408,#7409,#7410); #7412=PLANE('',#7411); #7413=ORIENTED_EDGE('',*,*,#7390,.T.); #7414=ORIENTED_EDGE('',*,*,#7403,.T.); #7415=EDGE_LOOP('',(#7413,#7414)); #7416=FACE_OUTER_BOUND('',#7415,.F.); #7418=ORIENTED_EDGE('',*,*,#7417,.F.); #7420=ORIENTED_EDGE('',*,*,#7419,.F.); #7421=EDGE_LOOP('',(#7418,#7420)); #7422=FACE_BOUND('',#7421,.F.); #7423=ADVANCED_FACE('',(#7416,#7422),#7412,.F.); #7424=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1)); #7425=DIRECTION('',(0.E0,-1.E0,0.E0)); #7426=DIRECTION('',(1.E0,0.E0,0.E0)); #7427=AXIS2_PLACEMENT_3D('',#7424,#7425,#7426); #7428=CYLINDRICAL_SURFACE('',#7427,1.925E-1); #7429=ORIENTED_EDGE('',*,*,#7417,.T.); #7431=ORIENTED_EDGE('',*,*,#7430,.T.); #7432=ORIENTED_EDGE('',*,*,#5620,.F.); #7434=ORIENTED_EDGE('',*,*,#7433,.F.); #7435=EDGE_LOOP('',(#7429,#7431,#7432,#7434)); #7436=FACE_OUTER_BOUND('',#7435,.F.); #7437=ADVANCED_FACE('',(#7436),#7428,.F.); #7438=CARTESIAN_POINT('',(1.125E0,1.5E0,1.2E1)); #7439=DIRECTION('',(0.E0,-1.E0,0.E0)); #7440=DIRECTION('',(1.E0,0.E0,0.E0)); #7441=AXIS2_PLACEMENT_3D('',#7438,#7439,#7440); #7442=CYLINDRICAL_SURFACE('',#7441,1.925E-1); #7443=ORIENTED_EDGE('',*,*,#7419,.T.); #7444=ORIENTED_EDGE('',*,*,#7433,.T.); #7445=ORIENTED_EDGE('',*,*,#5622,.F.); #7446=ORIENTED_EDGE('',*,*,#7430,.F.); #7447=EDGE_LOOP('',(#7443,#7444,#7445,#7446)); #7448=FACE_OUTER_BOUND('',#7447,.F.); #7449=ADVANCED_FACE('',(#7448),#7442,.F.); #7450=CARTESIAN_POINT('',(-2.E0,2.5E0,8.E0)); #7451=DIRECTION('',(-1.E0,0.E0,0.E0)); #7452=DIRECTION('',(0.E0,-1.E0,0.E0)); #7453=AXIS2_PLACEMENT_3D('',#7450,#7451,#7452); #7454=PLANE('',#7453); #7455=ORIENTED_EDGE('',*,*,#7265,.T.); #7456=ORIENTED_EDGE('',*,*,#6310,.T.); #7458=ORIENTED_EDGE('',*,*,#7457,.F.); #7459=ORIENTED_EDGE('',*,*,#5512,.F.); #7460=ORIENTED_EDGE('',*,*,#5984,.T.); #7462=ORIENTED_EDGE('',*,*,#7461,.T.); #7463=EDGE_LOOP('',(#7455,#7456,#7458,#7459,#7460,#7462)); #7464=FACE_OUTER_BOUND('',#7463,.F.); #7465=ADVANCED_FACE('',(#7464),#7454,.T.); #7466=CARTESIAN_POINT('',(-1.5E0,0.E0,1.225E1)); #7467=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #7468=DIRECTION('',(0.E0,1.E0,0.E0)); #7469=AXIS2_PLACEMENT_3D('',#7466,#7467,#7468); #7470=PLANE('',#7469); #7471=ORIENTED_EDGE('',*,*,#6731,.F.); #7472=ORIENTED_EDGE('',*,*,#5514,.T.); #7473=ORIENTED_EDGE('',*,*,#7457,.T.); #7474=ORIENTED_EDGE('',*,*,#6308,.F.); #7475=EDGE_LOOP('',(#7471,#7472,#7473,#7474)); #7476=FACE_OUTER_BOUND('',#7475,.F.); #7477=ADVANCED_FACE('',(#7476),#7470,.T.); #7478=CARTESIAN_POINT('',(3.E0,1.15E1,8.E0)); #7479=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #7480=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0)); #7481=AXIS2_PLACEMENT_3D('',#7478,#7479,#7480); #7482=PLANE('',#7481); #7483=ORIENTED_EDGE('',*,*,#5982,.F.); #7485=ORIENTED_EDGE('',*,*,#7484,.T.); #7486=ORIENTED_EDGE('',*,*,#7267,.T.); #7487=ORIENTED_EDGE('',*,*,#7461,.F.); #7488=EDGE_LOOP('',(#7483,#7485,#7486,#7487)); #7489=FACE_OUTER_BOUND('',#7488,.F.); #7490=ADVANCED_FACE('',(#7489),#7482,.T.); #7491=CARTESIAN_POINT('',(5.E0,1.15E1,8.E0)); #7492=DIRECTION('',(0.E0,1.E0,0.E0)); #7493=DIRECTION('',(-1.E0,0.E0,0.E0)); #7494=AXIS2_PLACEMENT_3D('',#7491,#7492,#7493); #7495=PLANE('',#7494); #7496=ORIENTED_EDGE('',*,*,#5980,.F.); #7497=ORIENTED_EDGE('',*,*,#7239,.T.); #7498=ORIENTED_EDGE('',*,*,#7269,.T.); #7499=ORIENTED_EDGE('',*,*,#7484,.F.); #7500=EDGE_LOOP('',(#7496,#7497,#7498,#7499)); #7501=FACE_OUTER_BOUND('',#7500,.F.); #7503=ORIENTED_EDGE('',*,*,#7502,.F.); #7505=ORIENTED_EDGE('',*,*,#7504,.F.); #7506=EDGE_LOOP('',(#7503,#7505)); #7507=FACE_BOUND('',#7506,.F.); #7509=ORIENTED_EDGE('',*,*,#7508,.F.); #7511=ORIENTED_EDGE('',*,*,#7510,.F.); #7512=EDGE_LOOP('',(#7509,#7511)); #7513=FACE_BOUND('',#7512,.F.); #7514=ADVANCED_FACE('',(#7501,#7507,#7513),#7495,.T.); #7515=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0)); #7516=DIRECTION('',(0.E0,-1.E0,0.E0)); #7517=DIRECTION('',(1.E0,0.E0,0.E0)); #7518=AXIS2_PLACEMENT_3D('',#7515,#7516,#7517); #7519=CYLINDRICAL_SURFACE('',#7518,9.5E-2); #7520=ORIENTED_EDGE('',*,*,#7502,.T.); #7522=ORIENTED_EDGE('',*,*,#7521,.T.); #7524=ORIENTED_EDGE('',*,*,#7523,.F.); #7526=ORIENTED_EDGE('',*,*,#7525,.F.); #7527=EDGE_LOOP('',(#7520,#7522,#7524,#7526)); #7528=FACE_OUTER_BOUND('',#7527,.F.); #7529=ADVANCED_FACE('',(#7528),#7519,.F.); #7530=CARTESIAN_POINT('',(4.E0,1.15E1,9.E0)); #7531=DIRECTION('',(0.E0,-1.E0,0.E0)); #7532=DIRECTION('',(1.E0,0.E0,0.E0)); #7533=AXIS2_PLACEMENT_3D('',#7530,#7531,#7532); #7534=CYLINDRICAL_SURFACE('',#7533,9.5E-2); #7535=ORIENTED_EDGE('',*,*,#7504,.T.); #7536=ORIENTED_EDGE('',*,*,#7525,.T.); #7538=ORIENTED_EDGE('',*,*,#7537,.F.); #7539=ORIENTED_EDGE('',*,*,#7521,.F.); #7540=EDGE_LOOP('',(#7535,#7536,#7538,#7539)); #7541=FACE_OUTER_BOUND('',#7540,.F.); #7542=ADVANCED_FACE('',(#7541),#7534,.F.); #7543=CARTESIAN_POINT('',(4.E0,1.1125E1,9.E0)); #7544=DIRECTION('',(0.E0,-1.E0,0.E0)); #7545=DIRECTION('',(1.E0,0.E0,0.E0)); #7546=AXIS2_PLACEMENT_3D('',#7543,#7544,#7545); #7547=PLANE('',#7546); #7548=ORIENTED_EDGE('',*,*,#7523,.T.); #7549=ORIENTED_EDGE('',*,*,#7537,.T.); #7550=EDGE_LOOP('',(#7548,#7549)); #7551=FACE_OUTER_BOUND('',#7550,.F.); #7552=ADVANCED_FACE('',(#7551),#7547,.F.); #7553=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0)); #7554=DIRECTION('',(0.E0,-1.E0,0.E0)); #7555=DIRECTION('',(1.E0,0.E0,0.E0)); #7556=AXIS2_PLACEMENT_3D('',#7553,#7554,#7555); #7557=CYLINDRICAL_SURFACE('',#7556,6.25E-2); #7558=ORIENTED_EDGE('',*,*,#7508,.T.); #7560=ORIENTED_EDGE('',*,*,#7559,.T.); #7562=ORIENTED_EDGE('',*,*,#7561,.F.); #7564=ORIENTED_EDGE('',*,*,#7563,.F.); #7565=EDGE_LOOP('',(#7558,#7560,#7562,#7564)); #7566=FACE_OUTER_BOUND('',#7565,.F.); #7567=ADVANCED_FACE('',(#7566),#7557,.F.); #7568=CARTESIAN_POINT('',(3.867417478528E0,1.15E1,9.132582521472E0)); #7569=DIRECTION('',(0.E0,-1.E0,0.E0)); #7570=DIRECTION('',(1.E0,0.E0,0.E0)); #7571=AXIS2_PLACEMENT_3D('',#7568,#7569,#7570); #7572=CYLINDRICAL_SURFACE('',#7571,6.25E-2); #7573=ORIENTED_EDGE('',*,*,#7510,.T.); #7574=ORIENTED_EDGE('',*,*,#7563,.T.); #7576=ORIENTED_EDGE('',*,*,#7575,.F.); #7577=ORIENTED_EDGE('',*,*,#7559,.F.); #7578=EDGE_LOOP('',(#7573,#7574,#7576,#7577)); #7579=FACE_OUTER_BOUND('',#7578,.F.); #7580=ADVANCED_FACE('',(#7579),#7572,.F.); #7581=CARTESIAN_POINT('',(3.867417478528E0,1.125E1,9.132582521472E0)); #7582=DIRECTION('',(0.E0,-1.E0,0.E0)); #7583=DIRECTION('',(1.E0,0.E0,0.E0)); #7584=AXIS2_PLACEMENT_3D('',#7581,#7582,#7583); #7585=PLANE('',#7584); #7586=ORIENTED_EDGE('',*,*,#7561,.T.); #7587=ORIENTED_EDGE('',*,*,#7575,.T.); #7588=EDGE_LOOP('',(#7586,#7587)); #7589=FACE_OUTER_BOUND('',#7588,.F.); #7590=ADVANCED_FACE('',(#7589),#7585,.F.); #7591=CARTESIAN_POINT('',(2.15E0,6.65E0,9.441108058217E0)); #7592=DIRECTION('',(0.E0,0.E0,1.E0)); #7593=DIRECTION('',(1.E0,0.E0,0.E0)); #7594=AXIS2_PLACEMENT_3D('',#7591,#7592,#7593); #7595=CYLINDRICAL_SURFACE('',#7594,3.5E-1); #7597=ORIENTED_EDGE('',*,*,#7596,.T.); #7598=ORIENTED_EDGE('',*,*,#7285,.T.); #7600=ORIENTED_EDGE('',*,*,#7599,.F.); #7602=ORIENTED_EDGE('',*,*,#7601,.T.); #7603=EDGE_LOOP('',(#7597,#7598,#7600,#7602)); #7604=FACE_OUTER_BOUND('',#7603,.F.); #7605=ADVANCED_FACE('',(#7604),#7595,.T.); #7606=CARTESIAN_POINT('',(2.5E0,7.E0,1.E1)); #7607=DIRECTION('',(-1.E0,0.E0,0.E0)); #7608=DIRECTION('',(0.E0,-1.E0,0.E0)); #7609=AXIS2_PLACEMENT_3D('',#7606,#7607,#7608); #7610=PLANE('',#7609); #7611=ORIENTED_EDGE('',*,*,#7596,.F.); #7613=ORIENTED_EDGE('',*,*,#7612,.T.); #7615=ORIENTED_EDGE('',*,*,#7614,.F.); #7616=ORIENTED_EDGE('',*,*,#7287,.F.); #7617=EDGE_LOOP('',(#7611,#7613,#7615,#7616)); #7618=FACE_OUTER_BOUND('',#7617,.F.); #7619=ADVANCED_FACE('',(#7618),#7610,.F.); #7620=CARTESIAN_POINT('',(0.E0,0.E0,9.5E0)); #7621=DIRECTION('',(0.E0,0.E0,1.E0)); #7622=DIRECTION('',(1.E0,0.E0,0.E0)); #7623=AXIS2_PLACEMENT_3D('',#7620,#7621,#7622); #7624=PLANE('',#7623); #7625=ORIENTED_EDGE('',*,*,#7612,.F.); #7626=ORIENTED_EDGE('',*,*,#7601,.F.); #7628=ORIENTED_EDGE('',*,*,#7627,.F.); #7630=ORIENTED_EDGE('',*,*,#7629,.F.); #7632=ORIENTED_EDGE('',*,*,#7631,.F.); #7634=ORIENTED_EDGE('',*,*,#7633,.F.); #7636=ORIENTED_EDGE('',*,*,#7635,.F.); #7638=ORIENTED_EDGE('',*,*,#7637,.F.); #7640=ORIENTED_EDGE('',*,*,#7639,.F.); #7642=ORIENTED_EDGE('',*,*,#7641,.F.); #7644=ORIENTED_EDGE('',*,*,#7643,.F.); #7646=ORIENTED_EDGE('',*,*,#7645,.F.); #7647=EDGE_LOOP('',(#7625,#7626,#7628,#7630,#7632,#7634,#7636,#7638,#7640,#7642, #7644,#7646)); #7648=FACE_OUTER_BOUND('',#7647,.F.); #7649=ADVANCED_FACE('',(#7648),#7624,.T.); #7650=CARTESIAN_POINT('',(1.357969178416E0,7.E0,1.E1)); #7651=DIRECTION('',(0.E0,-1.E0,0.E0)); #7652=DIRECTION('',(1.E0,0.E0,0.E0)); #7653=AXIS2_PLACEMENT_3D('',#7650,#7651,#7652); #7654=PLANE('',#7653); #7655=ORIENTED_EDGE('',*,*,#7599,.T.); #7656=ORIENTED_EDGE('',*,*,#7307,.F.); #7658=ORIENTED_EDGE('',*,*,#7657,.T.); #7659=ORIENTED_EDGE('',*,*,#7627,.T.); #7660=EDGE_LOOP('',(#7655,#7656,#7658,#7659)); #7661=FACE_OUTER_BOUND('',#7660,.F.); #7662=ADVANCED_FACE('',(#7661),#7654,.F.); #7663=CARTESIAN_POINT('',(1.952799239454E0,7.35E0,1.006892397423E1)); #7664=DIRECTION('',(0.E0,0.E0,-1.E0)); #7665=DIRECTION('',(0.E0,-1.E0,0.E0)); #7666=AXIS2_PLACEMENT_3D('',#7663,#7664,#7665); #7667=CYLINDRICAL_SURFACE('',#7666,3.5E-1); #7668=ORIENTED_EDGE('',*,*,#7657,.F.); #7669=ORIENTED_EDGE('',*,*,#7305,.T.); #7671=ORIENTED_EDGE('',*,*,#7670,.T.); #7672=ORIENTED_EDGE('',*,*,#7629,.T.); #7673=EDGE_LOOP('',(#7668,#7669,#7671,#7672)); #7674=FACE_OUTER_BOUND('',#7673,.F.); #7675=ADVANCED_FACE('',(#7674),#7667,.F.); #7676=CARTESIAN_POINT('',(2.746858067304E0,9.5E0,1.E1)); #7677=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #7678=DIRECTION('',(-4.856429311786E-1,-8.741572761215E-1,0.E0)); #7679=AXIS2_PLACEMENT_3D('',#7676,#7677,#7678); #7680=PLANE('',#7679); #7681=ORIENTED_EDGE('',*,*,#7670,.F.); #7682=ORIENTED_EDGE('',*,*,#7303,.F.); #7684=ORIENTED_EDGE('',*,*,#7683,.T.); #7685=ORIENTED_EDGE('',*,*,#7631,.T.); #7686=EDGE_LOOP('',(#7681,#7682,#7684,#7685)); #7687=FACE_OUTER_BOUND('',#7686,.F.); #7688=ADVANCED_FACE('',(#7687),#7680,.F.); #7689=CARTESIAN_POINT('',(2.952799239454E0,9.15E0,1.006892397423E1)); #7690=DIRECTION('',(0.E0,0.E0,-1.E0)); #7691=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #7692=AXIS2_PLACEMENT_3D('',#7689,#7690,#7691); #7693=CYLINDRICAL_SURFACE('',#7692,3.5E-1); #7694=ORIENTED_EDGE('',*,*,#7683,.F.); #7695=ORIENTED_EDGE('',*,*,#7301,.T.); #7697=ORIENTED_EDGE('',*,*,#7696,.T.); #7698=ORIENTED_EDGE('',*,*,#7633,.T.); #7699=EDGE_LOOP('',(#7694,#7695,#7697,#7698)); #7700=FACE_OUTER_BOUND('',#7699,.F.); #7701=ADVANCED_FACE('',(#7700),#7693,.F.); #7702=CARTESIAN_POINT('',(4.5E0,9.5E0,1.E1)); #7703=DIRECTION('',(0.E0,1.E0,0.E0)); #7704=DIRECTION('',(-1.E0,0.E0,0.E0)); #7705=AXIS2_PLACEMENT_3D('',#7702,#7703,#7704); #7706=PLANE('',#7705); #7707=ORIENTED_EDGE('',*,*,#7696,.F.); #7708=ORIENTED_EDGE('',*,*,#7299,.F.); #7710=ORIENTED_EDGE('',*,*,#7709,.T.); #7711=ORIENTED_EDGE('',*,*,#7635,.T.); #7712=EDGE_LOOP('',(#7707,#7708,#7710,#7711)); #7713=FACE_OUTER_BOUND('',#7712,.F.); #7714=ADVANCED_FACE('',(#7713),#7706,.F.); #7715=CARTESIAN_POINT('',(4.15E0,9.15E0,1.006892397423E1)); #7716=DIRECTION('',(0.E0,0.E0,-1.E0)); #7717=DIRECTION('',(0.E0,1.E0,0.E0)); #7718=AXIS2_PLACEMENT_3D('',#7715,#7716,#7717); #7719=CYLINDRICAL_SURFACE('',#7718,3.5E-1); #7720=ORIENTED_EDGE('',*,*,#7709,.F.); #7721=ORIENTED_EDGE('',*,*,#7297,.T.); #7723=ORIENTED_EDGE('',*,*,#7722,.T.); #7724=ORIENTED_EDGE('',*,*,#7637,.T.); #7725=EDGE_LOOP('',(#7720,#7721,#7723,#7724)); #7726=FACE_OUTER_BOUND('',#7725,.F.); #7727=ADVANCED_FACE('',(#7726),#7719,.F.); #7728=CARTESIAN_POINT('',(4.5E0,2.E0,1.E1)); #7729=DIRECTION('',(1.E0,0.E0,0.E0)); #7730=DIRECTION('',(0.E0,1.E0,0.E0)); #7731=AXIS2_PLACEMENT_3D('',#7728,#7729,#7730); #7732=PLANE('',#7731); #7734=ORIENTED_EDGE('',*,*,#7733,.T.); #7735=ORIENTED_EDGE('',*,*,#7639,.T.); #7736=ORIENTED_EDGE('',*,*,#7722,.F.); #7737=ORIENTED_EDGE('',*,*,#7295,.F.); #7738=EDGE_LOOP('',(#7734,#7735,#7736,#7737)); #7739=FACE_OUTER_BOUND('',#7738,.F.); #7740=ADVANCED_FACE('',(#7739),#7732,.F.); #7741=CARTESIAN_POINT('',(4.15E0,2.35E0,1.006892397423E1)); #7742=DIRECTION('',(0.E0,0.E0,-1.E0)); #7743=DIRECTION('',(1.E0,0.E0,0.E0)); #7744=AXIS2_PLACEMENT_3D('',#7741,#7742,#7743); #7745=CYLINDRICAL_SURFACE('',#7744,3.5E-1); #7746=ORIENTED_EDGE('',*,*,#7733,.F.); #7747=ORIENTED_EDGE('',*,*,#7293,.T.); #7749=ORIENTED_EDGE('',*,*,#7748,.T.); #7750=ORIENTED_EDGE('',*,*,#7641,.T.); #7751=EDGE_LOOP('',(#7746,#7747,#7749,#7750)); #7752=FACE_OUTER_BOUND('',#7751,.F.); #7753=ADVANCED_FACE('',(#7752),#7745,.F.); #7754=CARTESIAN_POINT('',(2.5E0,2.E0,1.E1)); #7755=DIRECTION('',(0.E0,-1.E0,0.E0)); #7756=DIRECTION('',(1.E0,0.E0,0.E0)); #7757=AXIS2_PLACEMENT_3D('',#7754,#7755,#7756); #7758=PLANE('',#7757); #7760=ORIENTED_EDGE('',*,*,#7759,.T.); #7761=ORIENTED_EDGE('',*,*,#7643,.T.); #7762=ORIENTED_EDGE('',*,*,#7748,.F.); #7763=ORIENTED_EDGE('',*,*,#7291,.F.); #7764=EDGE_LOOP('',(#7760,#7761,#7762,#7763)); #7765=FACE_OUTER_BOUND('',#7764,.F.); #7766=ADVANCED_FACE('',(#7765),#7758,.F.); #7767=CARTESIAN_POINT('',(2.85E0,2.35E0,1.006892397423E1)); #7768=DIRECTION('',(0.E0,0.E0,-1.E0)); #7769=DIRECTION('',(0.E0,-1.E0,0.E0)); #7770=AXIS2_PLACEMENT_3D('',#7767,#7768,#7769); #7771=CYLINDRICAL_SURFACE('',#7770,3.5E-1); #7772=ORIENTED_EDGE('',*,*,#7759,.F.); #7773=ORIENTED_EDGE('',*,*,#7289,.T.); #7774=ORIENTED_EDGE('',*,*,#7614,.T.); #7775=ORIENTED_EDGE('',*,*,#7645,.T.); #7776=EDGE_LOOP('',(#7772,#7773,#7774,#7775)); #7777=FACE_OUTER_BOUND('',#7776,.F.); #7778=ADVANCED_FACE('',(#7777),#7771,.F.); #7779=CARTESIAN_POINT('',(1.9E1,1.5E0,1.175E1)); #7780=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #7781=DIRECTION('',(0.E0,-1.E0,0.E0)); #7782=AXIS2_PLACEMENT_3D('',#7779,#7780,#7781); #7783=PLANE('',#7782); #7784=ORIENTED_EDGE('',*,*,#7161,.F.); #7785=ORIENTED_EDGE('',*,*,#6428,.T.); #7786=ORIENTED_EDGE('',*,*,#6953,.T.); #7787=ORIENTED_EDGE('',*,*,#5682,.F.); #7788=EDGE_LOOP('',(#7784,#7785,#7786,#7787)); #7789=FACE_OUTER_BOUND('',#7788,.F.); #7790=ADVANCED_FACE('',(#7789),#7783,.T.); #7791=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0)); #7792=DIRECTION('',(0.E0,1.E0,0.E0)); #7793=DIRECTION('',(-1.E0,0.E0,0.E0)); #7794=AXIS2_PLACEMENT_3D('',#7791,#7792,#7793); #7795=CYLINDRICAL_SURFACE('',#7794,9.5E-2); #7796=ORIENTED_EDGE('',*,*,#7140,.F.); #7798=ORIENTED_EDGE('',*,*,#7797,.T.); #7800=ORIENTED_EDGE('',*,*,#7799,.T.); #7802=ORIENTED_EDGE('',*,*,#7801,.F.); #7803=EDGE_LOOP('',(#7796,#7798,#7800,#7802)); #7804=FACE_OUTER_BOUND('',#7803,.F.); #7805=ADVANCED_FACE('',(#7804),#7795,.F.); #7806=CARTESIAN_POINT('',(2.E1,1.15E1,9.E0)); #7807=DIRECTION('',(0.E0,1.E0,0.E0)); #7808=DIRECTION('',(-1.E0,0.E0,0.E0)); #7809=AXIS2_PLACEMENT_3D('',#7806,#7807,#7808); #7810=CYLINDRICAL_SURFACE('',#7809,9.5E-2); #7811=ORIENTED_EDGE('',*,*,#7142,.F.); #7812=ORIENTED_EDGE('',*,*,#7801,.T.); #7814=ORIENTED_EDGE('',*,*,#7813,.T.); #7815=ORIENTED_EDGE('',*,*,#7797,.F.); #7816=EDGE_LOOP('',(#7811,#7812,#7814,#7815)); #7817=FACE_OUTER_BOUND('',#7816,.F.); #7818=ADVANCED_FACE('',(#7817),#7810,.F.); #7819=CARTESIAN_POINT('',(2.E1,1.1125E1,9.E0)); #7820=DIRECTION('',(0.E0,1.E0,0.E0)); #7821=DIRECTION('',(-1.E0,0.E0,0.E0)); #7822=AXIS2_PLACEMENT_3D('',#7819,#7820,#7821); #7823=PLANE('',#7822); #7824=ORIENTED_EDGE('',*,*,#7799,.F.); #7825=ORIENTED_EDGE('',*,*,#7813,.F.); #7826=EDGE_LOOP('',(#7824,#7825)); #7827=FACE_OUTER_BOUND('',#7826,.F.); #7828=ADVANCED_FACE('',(#7827),#7823,.T.); #7829=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0)); #7830=DIRECTION('',(0.E0,1.E0,0.E0)); #7831=DIRECTION('',(-1.E0,0.E0,0.E0)); #7832=AXIS2_PLACEMENT_3D('',#7829,#7830,#7831); #7833=CYLINDRICAL_SURFACE('',#7832,6.25E-2); #7834=ORIENTED_EDGE('',*,*,#7146,.F.); #7836=ORIENTED_EDGE('',*,*,#7835,.T.); #7838=ORIENTED_EDGE('',*,*,#7837,.T.); #7840=ORIENTED_EDGE('',*,*,#7839,.F.); #7841=EDGE_LOOP('',(#7834,#7836,#7838,#7840)); #7842=FACE_OUTER_BOUND('',#7841,.F.); #7843=ADVANCED_FACE('',(#7842),#7833,.F.); #7844=CARTESIAN_POINT('',(2.013258252147E1,1.15E1,9.132582521472E0)); #7845=DIRECTION('',(0.E0,1.E0,0.E0)); #7846=DIRECTION('',(-1.E0,0.E0,0.E0)); #7847=AXIS2_PLACEMENT_3D('',#7844,#7845,#7846); #7848=CYLINDRICAL_SURFACE('',#7847,6.25E-2); #7849=ORIENTED_EDGE('',*,*,#7148,.F.); #7850=ORIENTED_EDGE('',*,*,#7839,.T.); #7852=ORIENTED_EDGE('',*,*,#7851,.T.); #7853=ORIENTED_EDGE('',*,*,#7835,.F.); #7854=EDGE_LOOP('',(#7849,#7850,#7852,#7853)); #7855=FACE_OUTER_BOUND('',#7854,.F.); #7856=ADVANCED_FACE('',(#7855),#7848,.F.); #7857=CARTESIAN_POINT('',(2.013258252147E1,1.125E1,9.132582521472E0)); #7858=DIRECTION('',(0.E0,1.E0,0.E0)); #7859=DIRECTION('',(-1.E0,0.E0,0.E0)); #7860=AXIS2_PLACEMENT_3D('',#7857,#7858,#7859); #7861=PLANE('',#7860); #7862=ORIENTED_EDGE('',*,*,#7837,.F.); #7863=ORIENTED_EDGE('',*,*,#7851,.F.); #7864=EDGE_LOOP('',(#7862,#7863)); #7865=FACE_OUTER_BOUND('',#7864,.F.); #7866=ADVANCED_FACE('',(#7865),#7861,.T.); #7867=CARTESIAN_POINT('',(1.755E1,1.176878221735E0,2.975E1)); #7868=DIRECTION('',(0.E0,-1.E0,0.E0)); #7869=DIRECTION('',(1.E0,0.E0,0.E0)); #7870=AXIS2_PLACEMENT_3D('',#7867,#7868,#7869); #7871=CYLINDRICAL_SURFACE('',#7870,1.E-1); #7872=ORIENTED_EDGE('',*,*,#6346,.F.); #7874=ORIENTED_EDGE('',*,*,#7873,.F.); #7876=ORIENTED_EDGE('',*,*,#7875,.T.); #7878=ORIENTED_EDGE('',*,*,#7877,.T.); #7879=EDGE_LOOP('',(#7872,#7874,#7876,#7878)); #7880=FACE_OUTER_BOUND('',#7879,.F.); #7881=ADVANCED_FACE('',(#7880),#7871,.F.); #7882=CARTESIAN_POINT('',(1.755E1,1.176878221735E0,2.975E1)); #7883=DIRECTION('',(0.E0,-1.E0,0.E0)); #7884=DIRECTION('',(1.E0,0.E0,0.E0)); #7885=AXIS2_PLACEMENT_3D('',#7882,#7883,#7884); #7886=CYLINDRICAL_SURFACE('',#7885,1.E-1); #7887=ORIENTED_EDGE('',*,*,#6348,.F.); #7888=ORIENTED_EDGE('',*,*,#7877,.F.); #7890=ORIENTED_EDGE('',*,*,#7889,.F.); #7891=ORIENTED_EDGE('',*,*,#7873,.T.); #7892=EDGE_LOOP('',(#7887,#7888,#7890,#7891)); #7893=FACE_OUTER_BOUND('',#7892,.F.); #7894=ADVANCED_FACE('',(#7893),#7886,.F.); #7895=CARTESIAN_POINT('',(1.755E1,1.234346967234E0,2.975E1)); #7896=DIRECTION('',(0.E0,1.E0,0.E0)); #7897=DIRECTION('',(-1.E0,0.E0,0.E0)); #7898=AXIS2_PLACEMENT_3D('',#7895,#7896,#7897); #7899=CONICAL_SURFACE('',#7898,7.288815195685E-2,6.E1); #7901=ORIENTED_EDGE('',*,*,#7900,.F.); #7903=ORIENTED_EDGE('',*,*,#7902,.T.); #7904=ORIENTED_EDGE('',*,*,#7889,.T.); #7905=EDGE_LOOP('',(#7901,#7903,#7904)); #7906=FACE_OUTER_BOUND('',#7905,.F.); #7907=ADVANCED_FACE('',(#7906),#7899,.F.); #7908=CARTESIAN_POINT('',(1.755E1,1.234346967234E0,2.975E1)); #7909=DIRECTION('',(0.E0,1.E0,0.E0)); #7910=DIRECTION('',(-1.E0,0.E0,0.E0)); #7911=AXIS2_PLACEMENT_3D('',#7908,#7909,#7910); #7912=CONICAL_SURFACE('',#7911,7.288815195685E-2,6.E1); #7913=ORIENTED_EDGE('',*,*,#7900,.T.); #7914=ORIENTED_EDGE('',*,*,#7875,.F.); #7915=ORIENTED_EDGE('',*,*,#7902,.F.); #7916=EDGE_LOOP('',(#7913,#7914,#7915)); #7917=FACE_OUTER_BOUND('',#7916,.F.); #7918=ADVANCED_FACE('',(#7917),#7912,.F.); #7919=CARTESIAN_POINT('',(1.655E1,1.176878221735E0,2.975E1)); #7920=DIRECTION('',(0.E0,-1.E0,0.E0)); #7921=DIRECTION('',(1.E0,0.E0,0.E0)); #7922=AXIS2_PLACEMENT_3D('',#7919,#7920,#7921); #7923=CYLINDRICAL_SURFACE('',#7922,1.E-1); #7924=ORIENTED_EDGE('',*,*,#6352,.F.); #7926=ORIENTED_EDGE('',*,*,#7925,.F.); #7928=ORIENTED_EDGE('',*,*,#7927,.T.); #7930=ORIENTED_EDGE('',*,*,#7929,.T.); #7931=EDGE_LOOP('',(#7924,#7926,#7928,#7930)); #7932=FACE_OUTER_BOUND('',#7931,.F.); #7933=ADVANCED_FACE('',(#7932),#7923,.F.); #7934=CARTESIAN_POINT('',(1.655E1,1.176878221735E0,2.975E1)); #7935=DIRECTION('',(0.E0,-1.E0,0.E0)); #7936=DIRECTION('',(1.E0,0.E0,0.E0)); #7937=AXIS2_PLACEMENT_3D('',#7934,#7935,#7936); #7938=CYLINDRICAL_SURFACE('',#7937,1.E-1); #7939=ORIENTED_EDGE('',*,*,#6354,.F.); #7940=ORIENTED_EDGE('',*,*,#7929,.F.); #7942=ORIENTED_EDGE('',*,*,#7941,.F.); #7943=ORIENTED_EDGE('',*,*,#7925,.T.); #7944=EDGE_LOOP('',(#7939,#7940,#7942,#7943)); #7945=FACE_OUTER_BOUND('',#7944,.F.); #7946=ADVANCED_FACE('',(#7945),#7938,.F.); #7947=CARTESIAN_POINT('',(1.655E1,1.234346967234E0,2.975E1)); #7948=DIRECTION('',(0.E0,1.E0,0.E0)); #7949=DIRECTION('',(-1.E0,0.E0,0.E0)); #7950=AXIS2_PLACEMENT_3D('',#7947,#7948,#7949); #7951=CONICAL_SURFACE('',#7950,7.288815195685E-2,6.E1); #7953=ORIENTED_EDGE('',*,*,#7952,.F.); #7955=ORIENTED_EDGE('',*,*,#7954,.T.); #7956=ORIENTED_EDGE('',*,*,#7941,.T.); #7957=EDGE_LOOP('',(#7953,#7955,#7956)); #7958=FACE_OUTER_BOUND('',#7957,.F.); #7959=ADVANCED_FACE('',(#7958),#7951,.F.); #7960=CARTESIAN_POINT('',(1.655E1,1.234346967234E0,2.975E1)); #7961=DIRECTION('',(0.E0,1.E0,0.E0)); #7962=DIRECTION('',(-1.E0,0.E0,0.E0)); #7963=AXIS2_PLACEMENT_3D('',#7960,#7961,#7962); #7964=CONICAL_SURFACE('',#7963,7.288815195685E-2,6.E1); #7965=ORIENTED_EDGE('',*,*,#7952,.T.); #7966=ORIENTED_EDGE('',*,*,#7927,.F.); #7967=ORIENTED_EDGE('',*,*,#7954,.F.); #7968=EDGE_LOOP('',(#7965,#7966,#7967)); #7969=FACE_OUTER_BOUND('',#7968,.F.); #7970=ADVANCED_FACE('',(#7969),#7964,.F.); #7971=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0)); #7972=DIRECTION('',(0.E0,-1.E0,0.E0)); #7973=DIRECTION('',(1.E0,0.E0,0.E0)); #7974=AXIS2_PLACEMENT_3D('',#7971,#7972,#7973); #7975=CYLINDRICAL_SURFACE('',#7974,2.575E-1); #7976=ORIENTED_EDGE('',*,*,#6248,.T.); #7978=ORIENTED_EDGE('',*,*,#7977,.T.); #7980=ORIENTED_EDGE('',*,*,#7979,.F.); #7982=ORIENTED_EDGE('',*,*,#7981,.F.); #7983=EDGE_LOOP('',(#7976,#7978,#7980,#7982)); #7984=FACE_OUTER_BOUND('',#7983,.F.); #7985=ADVANCED_FACE('',(#7984),#7975,.F.); #7986=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0)); #7987=DIRECTION('',(0.E0,-1.E0,0.E0)); #7988=DIRECTION('',(1.E0,0.E0,0.E0)); #7989=AXIS2_PLACEMENT_3D('',#7986,#7987,#7988); #7990=CYLINDRICAL_SURFACE('',#7989,2.575E-1); #7991=ORIENTED_EDGE('',*,*,#6250,.T.); #7992=ORIENTED_EDGE('',*,*,#7981,.T.); #7994=ORIENTED_EDGE('',*,*,#7993,.F.); #7995=ORIENTED_EDGE('',*,*,#7977,.F.); #7996=EDGE_LOOP('',(#7991,#7992,#7994,#7995)); #7997=FACE_OUTER_BOUND('',#7996,.F.); #7998=ADVANCED_FACE('',(#7997),#7990,.F.); #7999=CARTESIAN_POINT('',(1.125E0,1.E0,6.E0)); #8000=DIRECTION('',(0.E0,-1.E0,0.E0)); #8001=DIRECTION('',(1.E0,0.E0,0.E0)); #8002=AXIS2_PLACEMENT_3D('',#7999,#8000,#8001); #8003=PLANE('',#8002); #8004=ORIENTED_EDGE('',*,*,#7979,.T.); #8005=ORIENTED_EDGE('',*,*,#7993,.T.); #8006=EDGE_LOOP('',(#8004,#8005)); #8007=FACE_OUTER_BOUND('',#8006,.F.); #8009=ORIENTED_EDGE('',*,*,#8008,.F.); #8011=ORIENTED_EDGE('',*,*,#8010,.F.); #8012=EDGE_LOOP('',(#8009,#8011)); #8013=FACE_BOUND('',#8012,.F.); #8014=ADVANCED_FACE('',(#8007,#8013),#8003,.F.); #8015=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0)); #8016=DIRECTION('',(0.E0,-1.E0,0.E0)); #8017=DIRECTION('',(1.E0,0.E0,0.E0)); #8018=AXIS2_PLACEMENT_3D('',#8015,#8016,#8017); #8019=CYLINDRICAL_SURFACE('',#8018,1.925E-1); #8020=ORIENTED_EDGE('',*,*,#8008,.T.); #8022=ORIENTED_EDGE('',*,*,#8021,.T.); #8023=ORIENTED_EDGE('',*,*,#5626,.F.); #8025=ORIENTED_EDGE('',*,*,#8024,.F.); #8026=EDGE_LOOP('',(#8020,#8022,#8023,#8025)); #8027=FACE_OUTER_BOUND('',#8026,.F.); #8028=ADVANCED_FACE('',(#8027),#8019,.F.); #8029=CARTESIAN_POINT('',(1.125E0,1.5E0,6.E0)); #8030=DIRECTION('',(0.E0,-1.E0,0.E0)); #8031=DIRECTION('',(1.E0,0.E0,0.E0)); #8032=AXIS2_PLACEMENT_3D('',#8029,#8030,#8031); #8033=CYLINDRICAL_SURFACE('',#8032,1.925E-1); #8034=ORIENTED_EDGE('',*,*,#8010,.T.); #8035=ORIENTED_EDGE('',*,*,#8024,.T.); #8036=ORIENTED_EDGE('',*,*,#5628,.F.); #8037=ORIENTED_EDGE('',*,*,#8021,.F.); #8038=EDGE_LOOP('',(#8034,#8035,#8036,#8037)); #8039=FACE_OUTER_BOUND('',#8038,.F.); #8040=ADVANCED_FACE('',(#8039),#8033,.F.); #8041=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1)); #8042=DIRECTION('',(0.E0,-1.E0,0.E0)); #8043=DIRECTION('',(1.E0,0.E0,0.E0)); #8044=AXIS2_PLACEMENT_3D('',#8041,#8042,#8043); #8045=CYLINDRICAL_SURFACE('',#8044,2.575E-1); #8046=ORIENTED_EDGE('',*,*,#6358,.T.); #8048=ORIENTED_EDGE('',*,*,#8047,.T.); #8050=ORIENTED_EDGE('',*,*,#8049,.F.); #8052=ORIENTED_EDGE('',*,*,#8051,.F.); #8053=EDGE_LOOP('',(#8046,#8048,#8050,#8052)); #8054=FACE_OUTER_BOUND('',#8053,.F.); #8055=ADVANCED_FACE('',(#8054),#8045,.F.); #8056=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1)); #8057=DIRECTION('',(0.E0,-1.E0,0.E0)); #8058=DIRECTION('',(1.E0,0.E0,0.E0)); #8059=AXIS2_PLACEMENT_3D('',#8056,#8057,#8058); #8060=CYLINDRICAL_SURFACE('',#8059,2.575E-1); #8061=ORIENTED_EDGE('',*,*,#6360,.T.); #8062=ORIENTED_EDGE('',*,*,#8051,.T.); #8064=ORIENTED_EDGE('',*,*,#8063,.F.); #8065=ORIENTED_EDGE('',*,*,#8047,.F.); #8066=EDGE_LOOP('',(#8061,#8062,#8064,#8065)); #8067=FACE_OUTER_BOUND('',#8066,.F.); #8068=ADVANCED_FACE('',(#8067),#8060,.F.); #8069=CARTESIAN_POINT('',(1.125E0,1.E0,1.8E1)); #8070=DIRECTION('',(0.E0,-1.E0,0.E0)); #8071=DIRECTION('',(1.E0,0.E0,0.E0)); #8072=AXIS2_PLACEMENT_3D('',#8069,#8070,#8071); #8073=PLANE('',#8072); #8074=ORIENTED_EDGE('',*,*,#8049,.T.); #8075=ORIENTED_EDGE('',*,*,#8063,.T.); #8076=EDGE_LOOP('',(#8074,#8075)); #8077=FACE_OUTER_BOUND('',#8076,.F.); #8079=ORIENTED_EDGE('',*,*,#8078,.F.); #8081=ORIENTED_EDGE('',*,*,#8080,.F.); #8082=EDGE_LOOP('',(#8079,#8081)); #8083=FACE_BOUND('',#8082,.F.); #8084=ADVANCED_FACE('',(#8077,#8083),#8073,.F.); #8085=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1)); #8086=DIRECTION('',(0.E0,-1.E0,0.E0)); #8087=DIRECTION('',(1.E0,0.E0,0.E0)); #8088=AXIS2_PLACEMENT_3D('',#8085,#8086,#8087); #8089=CYLINDRICAL_SURFACE('',#8088,1.925E-1); #8090=ORIENTED_EDGE('',*,*,#8078,.T.); #8092=ORIENTED_EDGE('',*,*,#8091,.T.); #8093=ORIENTED_EDGE('',*,*,#5614,.F.); #8095=ORIENTED_EDGE('',*,*,#8094,.F.); #8096=EDGE_LOOP('',(#8090,#8092,#8093,#8095)); #8097=FACE_OUTER_BOUND('',#8096,.F.); #8098=ADVANCED_FACE('',(#8097),#8089,.F.); #8099=CARTESIAN_POINT('',(1.125E0,1.5E0,1.8E1)); #8100=DIRECTION('',(0.E0,-1.E0,0.E0)); #8101=DIRECTION('',(1.E0,0.E0,0.E0)); #8102=AXIS2_PLACEMENT_3D('',#8099,#8100,#8101); #8103=CYLINDRICAL_SURFACE('',#8102,1.925E-1); #8104=ORIENTED_EDGE('',*,*,#8080,.T.); #8105=ORIENTED_EDGE('',*,*,#8094,.T.); #8106=ORIENTED_EDGE('',*,*,#5616,.F.); #8107=ORIENTED_EDGE('',*,*,#8091,.F.); #8108=EDGE_LOOP('',(#8104,#8105,#8106,#8107)); #8109=FACE_OUTER_BOUND('',#8108,.F.); #8110=ADVANCED_FACE('',(#8109),#8103,.F.); #8111=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1)); #8112=DIRECTION('',(0.E0,-1.E0,0.E0)); #8113=DIRECTION('',(1.E0,0.E0,0.E0)); #8114=AXIS2_PLACEMENT_3D('',#8111,#8112,#8113); #8115=CYLINDRICAL_SURFACE('',#8114,2.575E-1); #8116=ORIENTED_EDGE('',*,*,#6364,.T.); #8118=ORIENTED_EDGE('',*,*,#8117,.T.); #8120=ORIENTED_EDGE('',*,*,#8119,.F.); #8122=ORIENTED_EDGE('',*,*,#8121,.F.); #8123=EDGE_LOOP('',(#8116,#8118,#8120,#8122)); #8124=FACE_OUTER_BOUND('',#8123,.F.); #8125=ADVANCED_FACE('',(#8124),#8115,.F.); #8126=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1)); #8127=DIRECTION('',(0.E0,-1.E0,0.E0)); #8128=DIRECTION('',(1.E0,0.E0,0.E0)); #8129=AXIS2_PLACEMENT_3D('',#8126,#8127,#8128); #8130=CYLINDRICAL_SURFACE('',#8129,2.575E-1); #8131=ORIENTED_EDGE('',*,*,#6366,.T.); #8132=ORIENTED_EDGE('',*,*,#8121,.T.); #8134=ORIENTED_EDGE('',*,*,#8133,.F.); #8135=ORIENTED_EDGE('',*,*,#8117,.F.); #8136=EDGE_LOOP('',(#8131,#8132,#8134,#8135)); #8137=FACE_OUTER_BOUND('',#8136,.F.); #8138=ADVANCED_FACE('',(#8137),#8130,.F.); #8139=CARTESIAN_POINT('',(1.125E0,1.E0,2.4E1)); #8140=DIRECTION('',(0.E0,-1.E0,0.E0)); #8141=DIRECTION('',(1.E0,0.E0,0.E0)); #8142=AXIS2_PLACEMENT_3D('',#8139,#8140,#8141); #8143=PLANE('',#8142); #8144=ORIENTED_EDGE('',*,*,#8119,.T.); #8145=ORIENTED_EDGE('',*,*,#8133,.T.); #8146=EDGE_LOOP('',(#8144,#8145)); #8147=FACE_OUTER_BOUND('',#8146,.F.); #8149=ORIENTED_EDGE('',*,*,#8148,.F.); #8151=ORIENTED_EDGE('',*,*,#8150,.F.); #8152=EDGE_LOOP('',(#8149,#8151)); #8153=FACE_BOUND('',#8152,.F.); #8154=ADVANCED_FACE('',(#8147,#8153),#8143,.F.); #8155=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1)); #8156=DIRECTION('',(0.E0,-1.E0,0.E0)); #8157=DIRECTION('',(1.E0,0.E0,0.E0)); #8158=AXIS2_PLACEMENT_3D('',#8155,#8156,#8157); #8159=CYLINDRICAL_SURFACE('',#8158,1.925E-1); #8160=ORIENTED_EDGE('',*,*,#8148,.T.); #8162=ORIENTED_EDGE('',*,*,#8161,.T.); #8163=ORIENTED_EDGE('',*,*,#5608,.F.); #8165=ORIENTED_EDGE('',*,*,#8164,.F.); #8166=EDGE_LOOP('',(#8160,#8162,#8163,#8165)); #8167=FACE_OUTER_BOUND('',#8166,.F.); #8168=ADVANCED_FACE('',(#8167),#8159,.F.); #8169=CARTESIAN_POINT('',(1.125E0,1.5E0,2.4E1)); #8170=DIRECTION('',(0.E0,-1.E0,0.E0)); #8171=DIRECTION('',(1.E0,0.E0,0.E0)); #8172=AXIS2_PLACEMENT_3D('',#8169,#8170,#8171); #8173=CYLINDRICAL_SURFACE('',#8172,1.925E-1); #8174=ORIENTED_EDGE('',*,*,#8150,.T.); #8175=ORIENTED_EDGE('',*,*,#8164,.T.); #8176=ORIENTED_EDGE('',*,*,#5610,.F.); #8177=ORIENTED_EDGE('',*,*,#8161,.F.); #8178=EDGE_LOOP('',(#8174,#8175,#8176,#8177)); #8179=FACE_OUTER_BOUND('',#8178,.F.); #8180=ADVANCED_FACE('',(#8179),#8173,.F.); #8181=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0)); #8182=DIRECTION('',(0.E0,-1.E0,0.E0)); #8183=DIRECTION('',(1.E0,0.E0,0.E0)); #8184=AXIS2_PLACEMENT_3D('',#8181,#8182,#8183); #8185=CYLINDRICAL_SURFACE('',#8184,2.575E-1); #8186=ORIENTED_EDGE('',*,*,#6254,.T.); #8188=ORIENTED_EDGE('',*,*,#8187,.T.); #8190=ORIENTED_EDGE('',*,*,#8189,.F.); #8192=ORIENTED_EDGE('',*,*,#8191,.F.); #8193=EDGE_LOOP('',(#8186,#8188,#8190,#8192)); #8194=FACE_OUTER_BOUND('',#8193,.F.); #8195=ADVANCED_FACE('',(#8194),#8185,.F.); #8196=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0)); #8197=DIRECTION('',(0.E0,-1.E0,0.E0)); #8198=DIRECTION('',(1.E0,0.E0,0.E0)); #8199=AXIS2_PLACEMENT_3D('',#8196,#8197,#8198); #8200=CYLINDRICAL_SURFACE('',#8199,2.575E-1); #8201=ORIENTED_EDGE('',*,*,#6256,.T.); #8202=ORIENTED_EDGE('',*,*,#8191,.T.); #8204=ORIENTED_EDGE('',*,*,#8203,.F.); #8205=ORIENTED_EDGE('',*,*,#8187,.F.); #8206=EDGE_LOOP('',(#8201,#8202,#8204,#8205)); #8207=FACE_OUTER_BOUND('',#8206,.F.); #8208=ADVANCED_FACE('',(#8207),#8200,.F.); #8209=CARTESIAN_POINT('',(2.2875E1,1.E0,6.E0)); #8210=DIRECTION('',(0.E0,-1.E0,0.E0)); #8211=DIRECTION('',(1.E0,0.E0,0.E0)); #8212=AXIS2_PLACEMENT_3D('',#8209,#8210,#8211); #8213=PLANE('',#8212); #8214=ORIENTED_EDGE('',*,*,#8189,.T.); #8215=ORIENTED_EDGE('',*,*,#8203,.T.); #8216=EDGE_LOOP('',(#8214,#8215)); #8217=FACE_OUTER_BOUND('',#8216,.F.); #8219=ORIENTED_EDGE('',*,*,#8218,.F.); #8221=ORIENTED_EDGE('',*,*,#8220,.F.); #8222=EDGE_LOOP('',(#8219,#8221)); #8223=FACE_BOUND('',#8222,.F.); #8224=ADVANCED_FACE('',(#8217,#8223),#8213,.F.); #8225=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0)); #8226=DIRECTION('',(0.E0,-1.E0,0.E0)); #8227=DIRECTION('',(1.E0,0.E0,0.E0)); #8228=AXIS2_PLACEMENT_3D('',#8225,#8226,#8227); #8229=CYLINDRICAL_SURFACE('',#8228,1.925E-1); #8230=ORIENTED_EDGE('',*,*,#8218,.T.); #8232=ORIENTED_EDGE('',*,*,#8231,.T.); #8233=ORIENTED_EDGE('',*,*,#5602,.F.); #8235=ORIENTED_EDGE('',*,*,#8234,.F.); #8236=EDGE_LOOP('',(#8230,#8232,#8233,#8235)); #8237=FACE_OUTER_BOUND('',#8236,.F.); #8238=ADVANCED_FACE('',(#8237),#8229,.F.); #8239=CARTESIAN_POINT('',(2.2875E1,1.5E0,6.E0)); #8240=DIRECTION('',(0.E0,-1.E0,0.E0)); #8241=DIRECTION('',(1.E0,0.E0,0.E0)); #8242=AXIS2_PLACEMENT_3D('',#8239,#8240,#8241); #8243=CYLINDRICAL_SURFACE('',#8242,1.925E-1); #8244=ORIENTED_EDGE('',*,*,#8220,.T.); #8245=ORIENTED_EDGE('',*,*,#8234,.T.); #8246=ORIENTED_EDGE('',*,*,#5604,.F.); #8247=ORIENTED_EDGE('',*,*,#8231,.F.); #8248=EDGE_LOOP('',(#8244,#8245,#8246,#8247)); #8249=FACE_OUTER_BOUND('',#8248,.F.); #8250=ADVANCED_FACE('',(#8249),#8243,.F.); #8251=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1)); #8252=DIRECTION('',(0.E0,-1.E0,0.E0)); #8253=DIRECTION('',(1.E0,0.E0,0.E0)); #8254=AXIS2_PLACEMENT_3D('',#8251,#8252,#8253); #8255=CYLINDRICAL_SURFACE('',#8254,2.575E-1); #8256=ORIENTED_EDGE('',*,*,#6370,.T.); #8258=ORIENTED_EDGE('',*,*,#8257,.T.); #8260=ORIENTED_EDGE('',*,*,#8259,.F.); #8262=ORIENTED_EDGE('',*,*,#8261,.F.); #8263=EDGE_LOOP('',(#8256,#8258,#8260,#8262)); #8264=FACE_OUTER_BOUND('',#8263,.F.); #8265=ADVANCED_FACE('',(#8264),#8255,.F.); #8266=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1)); #8267=DIRECTION('',(0.E0,-1.E0,0.E0)); #8268=DIRECTION('',(1.E0,0.E0,0.E0)); #8269=AXIS2_PLACEMENT_3D('',#8266,#8267,#8268); #8270=CYLINDRICAL_SURFACE('',#8269,2.575E-1); #8271=ORIENTED_EDGE('',*,*,#6372,.T.); #8272=ORIENTED_EDGE('',*,*,#8261,.T.); #8274=ORIENTED_EDGE('',*,*,#8273,.F.); #8275=ORIENTED_EDGE('',*,*,#8257,.F.); #8276=EDGE_LOOP('',(#8271,#8272,#8274,#8275)); #8277=FACE_OUTER_BOUND('',#8276,.F.); #8278=ADVANCED_FACE('',(#8277),#8270,.F.); #8279=CARTESIAN_POINT('',(2.2875E1,1.E0,1.8E1)); #8280=DIRECTION('',(0.E0,-1.E0,0.E0)); #8281=DIRECTION('',(1.E0,0.E0,0.E0)); #8282=AXIS2_PLACEMENT_3D('',#8279,#8280,#8281); #8283=PLANE('',#8282); #8284=ORIENTED_EDGE('',*,*,#8259,.T.); #8285=ORIENTED_EDGE('',*,*,#8273,.T.); #8286=EDGE_LOOP('',(#8284,#8285)); #8287=FACE_OUTER_BOUND('',#8286,.F.); #8289=ORIENTED_EDGE('',*,*,#8288,.F.); #8291=ORIENTED_EDGE('',*,*,#8290,.F.); #8292=EDGE_LOOP('',(#8289,#8291)); #8293=FACE_BOUND('',#8292,.F.); #8294=ADVANCED_FACE('',(#8287,#8293),#8283,.F.); #8295=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1)); #8296=DIRECTION('',(0.E0,-1.E0,0.E0)); #8297=DIRECTION('',(1.E0,0.E0,0.E0)); #8298=AXIS2_PLACEMENT_3D('',#8295,#8296,#8297); #8299=CYLINDRICAL_SURFACE('',#8298,1.925E-1); #8300=ORIENTED_EDGE('',*,*,#8288,.T.); #8302=ORIENTED_EDGE('',*,*,#8301,.T.); #8303=ORIENTED_EDGE('',*,*,#5590,.F.); #8305=ORIENTED_EDGE('',*,*,#8304,.F.); #8306=EDGE_LOOP('',(#8300,#8302,#8303,#8305)); #8307=FACE_OUTER_BOUND('',#8306,.F.); #8308=ADVANCED_FACE('',(#8307),#8299,.F.); #8309=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.8E1)); #8310=DIRECTION('',(0.E0,-1.E0,0.E0)); #8311=DIRECTION('',(1.E0,0.E0,0.E0)); #8312=AXIS2_PLACEMENT_3D('',#8309,#8310,#8311); #8313=CYLINDRICAL_SURFACE('',#8312,1.925E-1); #8314=ORIENTED_EDGE('',*,*,#8290,.T.); #8315=ORIENTED_EDGE('',*,*,#8304,.T.); #8316=ORIENTED_EDGE('',*,*,#5592,.F.); #8317=ORIENTED_EDGE('',*,*,#8301,.F.); #8318=EDGE_LOOP('',(#8314,#8315,#8316,#8317)); #8319=FACE_OUTER_BOUND('',#8318,.F.); #8320=ADVANCED_FACE('',(#8319),#8313,.F.); #8321=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1)); #8322=DIRECTION('',(0.E0,-1.E0,0.E0)); #8323=DIRECTION('',(1.E0,0.E0,0.E0)); #8324=AXIS2_PLACEMENT_3D('',#8321,#8322,#8323); #8325=CYLINDRICAL_SURFACE('',#8324,2.575E-1); #8326=ORIENTED_EDGE('',*,*,#6376,.T.); #8328=ORIENTED_EDGE('',*,*,#8327,.T.); #8330=ORIENTED_EDGE('',*,*,#8329,.F.); #8332=ORIENTED_EDGE('',*,*,#8331,.F.); #8333=EDGE_LOOP('',(#8326,#8328,#8330,#8332)); #8334=FACE_OUTER_BOUND('',#8333,.F.); #8335=ADVANCED_FACE('',(#8334),#8325,.F.); #8336=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1)); #8337=DIRECTION('',(0.E0,-1.E0,0.E0)); #8338=DIRECTION('',(1.E0,0.E0,0.E0)); #8339=AXIS2_PLACEMENT_3D('',#8336,#8337,#8338); #8340=CYLINDRICAL_SURFACE('',#8339,2.575E-1); #8341=ORIENTED_EDGE('',*,*,#6378,.T.); #8342=ORIENTED_EDGE('',*,*,#8331,.T.); #8344=ORIENTED_EDGE('',*,*,#8343,.F.); #8345=ORIENTED_EDGE('',*,*,#8327,.F.); #8346=EDGE_LOOP('',(#8341,#8342,#8344,#8345)); #8347=FACE_OUTER_BOUND('',#8346,.F.); #8348=ADVANCED_FACE('',(#8347),#8340,.F.); #8349=CARTESIAN_POINT('',(2.2875E1,1.E0,2.4E1)); #8350=DIRECTION('',(0.E0,-1.E0,0.E0)); #8351=DIRECTION('',(1.E0,0.E0,0.E0)); #8352=AXIS2_PLACEMENT_3D('',#8349,#8350,#8351); #8353=PLANE('',#8352); #8354=ORIENTED_EDGE('',*,*,#8329,.T.); #8355=ORIENTED_EDGE('',*,*,#8343,.T.); #8356=EDGE_LOOP('',(#8354,#8355)); #8357=FACE_OUTER_BOUND('',#8356,.F.); #8359=ORIENTED_EDGE('',*,*,#8358,.F.); #8361=ORIENTED_EDGE('',*,*,#8360,.F.); #8362=EDGE_LOOP('',(#8359,#8361)); #8363=FACE_BOUND('',#8362,.F.); #8364=ADVANCED_FACE('',(#8357,#8363),#8353,.F.); #8365=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1)); #8366=DIRECTION('',(0.E0,-1.E0,0.E0)); #8367=DIRECTION('',(1.E0,0.E0,0.E0)); #8368=AXIS2_PLACEMENT_3D('',#8365,#8366,#8367); #8369=CYLINDRICAL_SURFACE('',#8368,1.925E-1); #8370=ORIENTED_EDGE('',*,*,#8358,.T.); #8372=ORIENTED_EDGE('',*,*,#8371,.T.); #8373=ORIENTED_EDGE('',*,*,#5584,.F.); #8375=ORIENTED_EDGE('',*,*,#8374,.F.); #8376=EDGE_LOOP('',(#8370,#8372,#8373,#8375)); #8377=FACE_OUTER_BOUND('',#8376,.F.); #8378=ADVANCED_FACE('',(#8377),#8369,.F.); #8379=CARTESIAN_POINT('',(2.2875E1,1.5E0,2.4E1)); #8380=DIRECTION('',(0.E0,-1.E0,0.E0)); #8381=DIRECTION('',(1.E0,0.E0,0.E0)); #8382=AXIS2_PLACEMENT_3D('',#8379,#8380,#8381); #8383=CYLINDRICAL_SURFACE('',#8382,1.925E-1); #8384=ORIENTED_EDGE('',*,*,#8360,.T.); #8385=ORIENTED_EDGE('',*,*,#8374,.T.); #8386=ORIENTED_EDGE('',*,*,#5586,.F.); #8387=ORIENTED_EDGE('',*,*,#8371,.F.); #8388=EDGE_LOOP('',(#8384,#8385,#8386,#8387)); #8389=FACE_OUTER_BOUND('',#8388,.F.); #8390=ADVANCED_FACE('',(#8389),#8383,.F.); #8391=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0)); #8392=DIRECTION('',(0.E0,-1.E0,0.E0)); #8393=DIRECTION('',(1.E0,0.E0,0.E0)); #8394=AXIS2_PLACEMENT_3D('',#8391,#8392,#8393); #8395=CYLINDRICAL_SURFACE('',#8394,2.56E-1); #8396=ORIENTED_EDGE('',*,*,#6260,.T.); #8398=ORIENTED_EDGE('',*,*,#8397,.T.); #8400=ORIENTED_EDGE('',*,*,#8399,.F.); #8402=ORIENTED_EDGE('',*,*,#8401,.F.); #8403=EDGE_LOOP('',(#8396,#8398,#8400,#8402)); #8404=FACE_OUTER_BOUND('',#8403,.F.); #8405=ADVANCED_FACE('',(#8404),#8395,.F.); #8406=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0)); #8407=DIRECTION('',(0.E0,-1.E0,0.E0)); #8408=DIRECTION('',(1.E0,0.E0,0.E0)); #8409=AXIS2_PLACEMENT_3D('',#8406,#8407,#8408); #8410=CYLINDRICAL_SURFACE('',#8409,2.56E-1); #8411=ORIENTED_EDGE('',*,*,#6262,.T.); #8412=ORIENTED_EDGE('',*,*,#8401,.T.); #8414=ORIENTED_EDGE('',*,*,#8413,.F.); #8415=ORIENTED_EDGE('',*,*,#8397,.F.); #8416=EDGE_LOOP('',(#8411,#8412,#8414,#8415)); #8417=FACE_OUTER_BOUND('',#8416,.F.); #8418=ADVANCED_FACE('',(#8417),#8410,.F.); #8419=CARTESIAN_POINT('',(6.E0,1.E0,1.25E0)); #8420=DIRECTION('',(0.E0,-1.E0,0.E0)); #8421=DIRECTION('',(1.E0,0.E0,0.E0)); #8422=AXIS2_PLACEMENT_3D('',#8419,#8420,#8421); #8423=PLANE('',#8422); #8424=ORIENTED_EDGE('',*,*,#8399,.T.); #8425=ORIENTED_EDGE('',*,*,#8413,.T.); #8426=EDGE_LOOP('',(#8424,#8425)); #8427=FACE_OUTER_BOUND('',#8426,.F.); #8429=ORIENTED_EDGE('',*,*,#8428,.F.); #8431=ORIENTED_EDGE('',*,*,#8430,.F.); #8432=EDGE_LOOP('',(#8429,#8431)); #8433=FACE_BOUND('',#8432,.F.); #8434=ADVANCED_FACE('',(#8427,#8433),#8423,.F.); #8435=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0)); #8436=DIRECTION('',(0.E0,-1.E0,0.E0)); #8437=DIRECTION('',(1.E0,0.E0,0.E0)); #8438=AXIS2_PLACEMENT_3D('',#8435,#8436,#8437); #8439=CYLINDRICAL_SURFACE('',#8438,1.925E-1); #8440=ORIENTED_EDGE('',*,*,#8428,.T.); #8442=ORIENTED_EDGE('',*,*,#8441,.T.); #8443=ORIENTED_EDGE('',*,*,#5632,.F.); #8445=ORIENTED_EDGE('',*,*,#8444,.F.); #8446=EDGE_LOOP('',(#8440,#8442,#8443,#8445)); #8447=FACE_OUTER_BOUND('',#8446,.F.); #8448=ADVANCED_FACE('',(#8447),#8439,.F.); #8449=CARTESIAN_POINT('',(6.E0,1.5E0,1.25E0)); #8450=DIRECTION('',(0.E0,-1.E0,0.E0)); #8451=DIRECTION('',(1.E0,0.E0,0.E0)); #8452=AXIS2_PLACEMENT_3D('',#8449,#8450,#8451); #8453=CYLINDRICAL_SURFACE('',#8452,1.925E-1); #8454=ORIENTED_EDGE('',*,*,#8430,.T.); #8455=ORIENTED_EDGE('',*,*,#8444,.T.); #8456=ORIENTED_EDGE('',*,*,#5634,.F.); #8457=ORIENTED_EDGE('',*,*,#8441,.F.); #8458=EDGE_LOOP('',(#8454,#8455,#8456,#8457)); #8459=FACE_OUTER_BOUND('',#8458,.F.); #8460=ADVANCED_FACE('',(#8459),#8453,.F.); #8461=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0)); #8462=DIRECTION('',(0.E0,-1.E0,0.E0)); #8463=DIRECTION('',(1.E0,0.E0,0.E0)); #8464=AXIS2_PLACEMENT_3D('',#8461,#8462,#8463); #8465=CYLINDRICAL_SURFACE('',#8464,2.56E-1); #8466=ORIENTED_EDGE('',*,*,#6266,.T.); #8468=ORIENTED_EDGE('',*,*,#8467,.T.); #8470=ORIENTED_EDGE('',*,*,#8469,.F.); #8472=ORIENTED_EDGE('',*,*,#8471,.F.); #8473=EDGE_LOOP('',(#8466,#8468,#8470,#8472)); #8474=FACE_OUTER_BOUND('',#8473,.F.); #8475=ADVANCED_FACE('',(#8474),#8465,.F.); #8476=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0)); #8477=DIRECTION('',(0.E0,-1.E0,0.E0)); #8478=DIRECTION('',(1.E0,0.E0,0.E0)); #8479=AXIS2_PLACEMENT_3D('',#8476,#8477,#8478); #8480=CYLINDRICAL_SURFACE('',#8479,2.56E-1); #8481=ORIENTED_EDGE('',*,*,#6268,.T.); #8482=ORIENTED_EDGE('',*,*,#8471,.T.); #8484=ORIENTED_EDGE('',*,*,#8483,.F.); #8485=ORIENTED_EDGE('',*,*,#8467,.F.); #8486=EDGE_LOOP('',(#8481,#8482,#8484,#8485)); #8487=FACE_OUTER_BOUND('',#8486,.F.); #8488=ADVANCED_FACE('',(#8487),#8480,.F.); #8489=CARTESIAN_POINT('',(1.2E1,1.E0,1.25E0)); #8490=DIRECTION('',(0.E0,-1.E0,0.E0)); #8491=DIRECTION('',(1.E0,0.E0,0.E0)); #8492=AXIS2_PLACEMENT_3D('',#8489,#8490,#8491); #8493=PLANE('',#8492); #8494=ORIENTED_EDGE('',*,*,#8469,.T.); #8495=ORIENTED_EDGE('',*,*,#8483,.T.); #8496=EDGE_LOOP('',(#8494,#8495)); #8497=FACE_OUTER_BOUND('',#8496,.F.); #8499=ORIENTED_EDGE('',*,*,#8498,.F.); #8501=ORIENTED_EDGE('',*,*,#8500,.F.); #8502=EDGE_LOOP('',(#8499,#8501)); #8503=FACE_BOUND('',#8502,.F.); #8504=ADVANCED_FACE('',(#8497,#8503),#8493,.F.); #8505=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0)); #8506=DIRECTION('',(0.E0,-1.E0,0.E0)); #8507=DIRECTION('',(1.E0,0.E0,0.E0)); #8508=AXIS2_PLACEMENT_3D('',#8505,#8506,#8507); #8509=CYLINDRICAL_SURFACE('',#8508,1.925E-1); #8510=ORIENTED_EDGE('',*,*,#8498,.T.); #8512=ORIENTED_EDGE('',*,*,#8511,.T.); #8513=ORIENTED_EDGE('',*,*,#5578,.F.); #8515=ORIENTED_EDGE('',*,*,#8514,.F.); #8516=EDGE_LOOP('',(#8510,#8512,#8513,#8515)); #8517=FACE_OUTER_BOUND('',#8516,.F.); #8518=ADVANCED_FACE('',(#8517),#8509,.F.); #8519=CARTESIAN_POINT('',(1.2E1,1.5E0,1.25E0)); #8520=DIRECTION('',(0.E0,-1.E0,0.E0)); #8521=DIRECTION('',(1.E0,0.E0,0.E0)); #8522=AXIS2_PLACEMENT_3D('',#8519,#8520,#8521); #8523=CYLINDRICAL_SURFACE('',#8522,1.925E-1); #8524=ORIENTED_EDGE('',*,*,#8500,.T.); #8525=ORIENTED_EDGE('',*,*,#8514,.T.); #8526=ORIENTED_EDGE('',*,*,#5580,.F.); #8527=ORIENTED_EDGE('',*,*,#8511,.F.); #8528=EDGE_LOOP('',(#8524,#8525,#8526,#8527)); #8529=FACE_OUTER_BOUND('',#8528,.F.); #8530=ADVANCED_FACE('',(#8529),#8523,.F.); #8531=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0)); #8532=DIRECTION('',(0.E0,-1.E0,0.E0)); #8533=DIRECTION('',(1.E0,0.E0,0.E0)); #8534=AXIS2_PLACEMENT_3D('',#8531,#8532,#8533); #8535=CYLINDRICAL_SURFACE('',#8534,2.56E-1); #8536=ORIENTED_EDGE('',*,*,#6272,.T.); #8538=ORIENTED_EDGE('',*,*,#8537,.T.); #8540=ORIENTED_EDGE('',*,*,#8539,.F.); #8542=ORIENTED_EDGE('',*,*,#8541,.F.); #8543=EDGE_LOOP('',(#8536,#8538,#8540,#8542)); #8544=FACE_OUTER_BOUND('',#8543,.F.); #8545=ADVANCED_FACE('',(#8544),#8535,.F.); #8546=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0)); #8547=DIRECTION('',(0.E0,-1.E0,0.E0)); #8548=DIRECTION('',(1.E0,0.E0,0.E0)); #8549=AXIS2_PLACEMENT_3D('',#8546,#8547,#8548); #8550=CYLINDRICAL_SURFACE('',#8549,2.56E-1); #8551=ORIENTED_EDGE('',*,*,#6274,.T.); #8552=ORIENTED_EDGE('',*,*,#8541,.T.); #8554=ORIENTED_EDGE('',*,*,#8553,.F.); #8555=ORIENTED_EDGE('',*,*,#8537,.F.); #8556=EDGE_LOOP('',(#8551,#8552,#8554,#8555)); #8557=FACE_OUTER_BOUND('',#8556,.F.); #8558=ADVANCED_FACE('',(#8557),#8550,.F.); #8559=CARTESIAN_POINT('',(1.8E1,1.E0,1.25E0)); #8560=DIRECTION('',(0.E0,-1.E0,0.E0)); #8561=DIRECTION('',(1.E0,0.E0,0.E0)); #8562=AXIS2_PLACEMENT_3D('',#8559,#8560,#8561); #8563=PLANE('',#8562); #8564=ORIENTED_EDGE('',*,*,#8539,.T.); #8565=ORIENTED_EDGE('',*,*,#8553,.T.); #8566=EDGE_LOOP('',(#8564,#8565)); #8567=FACE_OUTER_BOUND('',#8566,.F.); #8569=ORIENTED_EDGE('',*,*,#8568,.F.); #8571=ORIENTED_EDGE('',*,*,#8570,.F.); #8572=EDGE_LOOP('',(#8569,#8571)); #8573=FACE_BOUND('',#8572,.F.); #8574=ADVANCED_FACE('',(#8567,#8573),#8563,.F.); #8575=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0)); #8576=DIRECTION('',(0.E0,-1.E0,0.E0)); #8577=DIRECTION('',(1.E0,0.E0,0.E0)); #8578=AXIS2_PLACEMENT_3D('',#8575,#8576,#8577); #8579=CYLINDRICAL_SURFACE('',#8578,1.925E-1); #8580=ORIENTED_EDGE('',*,*,#8568,.T.); #8582=ORIENTED_EDGE('',*,*,#8581,.T.); #8583=ORIENTED_EDGE('',*,*,#5560,.F.); #8585=ORIENTED_EDGE('',*,*,#8584,.F.); #8586=EDGE_LOOP('',(#8580,#8582,#8583,#8585)); #8587=FACE_OUTER_BOUND('',#8586,.F.); #8588=ADVANCED_FACE('',(#8587),#8579,.F.); #8589=CARTESIAN_POINT('',(1.8E1,1.5E0,1.25E0)); #8590=DIRECTION('',(0.E0,-1.E0,0.E0)); #8591=DIRECTION('',(1.E0,0.E0,0.E0)); #8592=AXIS2_PLACEMENT_3D('',#8589,#8590,#8591); #8593=CYLINDRICAL_SURFACE('',#8592,1.925E-1); #8594=ORIENTED_EDGE('',*,*,#8570,.T.); #8595=ORIENTED_EDGE('',*,*,#8584,.T.); #8596=ORIENTED_EDGE('',*,*,#5562,.F.); #8597=ORIENTED_EDGE('',*,*,#8581,.F.); #8598=EDGE_LOOP('',(#8594,#8595,#8596,#8597)); #8599=FACE_OUTER_BOUND('',#8598,.F.); #8600=ADVANCED_FACE('',(#8599),#8593,.F.); #8601=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1)); #8602=DIRECTION('',(0.E0,-1.E0,0.E0)); #8603=DIRECTION('',(1.E0,0.E0,0.E0)); #8604=AXIS2_PLACEMENT_3D('',#8601,#8602,#8603); #8605=CYLINDRICAL_SURFACE('',#8604,2.56E-1); #8606=ORIENTED_EDGE('',*,*,#6382,.T.); #8608=ORIENTED_EDGE('',*,*,#8607,.T.); #8610=ORIENTED_EDGE('',*,*,#8609,.F.); #8612=ORIENTED_EDGE('',*,*,#8611,.F.); #8613=EDGE_LOOP('',(#8606,#8608,#8610,#8612)); #8614=FACE_OUTER_BOUND('',#8613,.F.); #8615=ADVANCED_FACE('',(#8614),#8605,.F.); #8616=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1)); #8617=DIRECTION('',(0.E0,-1.E0,0.E0)); #8618=DIRECTION('',(1.E0,0.E0,0.E0)); #8619=AXIS2_PLACEMENT_3D('',#8616,#8617,#8618); #8620=CYLINDRICAL_SURFACE('',#8619,2.56E-1); #8621=ORIENTED_EDGE('',*,*,#6384,.T.); #8622=ORIENTED_EDGE('',*,*,#8611,.T.); #8624=ORIENTED_EDGE('',*,*,#8623,.F.); #8625=ORIENTED_EDGE('',*,*,#8607,.F.); #8626=EDGE_LOOP('',(#8621,#8622,#8624,#8625)); #8627=FACE_OUTER_BOUND('',#8626,.F.); #8628=ADVANCED_FACE('',(#8627),#8620,.F.); #8629=CARTESIAN_POINT('',(6.E0,1.E0,3.075E1)); #8630=DIRECTION('',(0.E0,-1.E0,0.E0)); #8631=DIRECTION('',(1.E0,0.E0,0.E0)); #8632=AXIS2_PLACEMENT_3D('',#8629,#8630,#8631); #8633=PLANE('',#8632); #8634=ORIENTED_EDGE('',*,*,#8609,.T.); #8635=ORIENTED_EDGE('',*,*,#8623,.T.); #8636=EDGE_LOOP('',(#8634,#8635)); #8637=FACE_OUTER_BOUND('',#8636,.F.); #8639=ORIENTED_EDGE('',*,*,#8638,.F.); #8641=ORIENTED_EDGE('',*,*,#8640,.F.); #8642=EDGE_LOOP('',(#8639,#8641)); #8643=FACE_BOUND('',#8642,.F.); #8644=ADVANCED_FACE('',(#8637,#8643),#8633,.F.); #8645=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1)); #8646=DIRECTION('',(0.E0,-1.E0,0.E0)); #8647=DIRECTION('',(1.E0,0.E0,0.E0)); #8648=AXIS2_PLACEMENT_3D('',#8645,#8646,#8647); #8649=CYLINDRICAL_SURFACE('',#8648,1.925E-1); #8650=ORIENTED_EDGE('',*,*,#8638,.T.); #8652=ORIENTED_EDGE('',*,*,#8651,.T.); #8653=ORIENTED_EDGE('',*,*,#5572,.F.); #8655=ORIENTED_EDGE('',*,*,#8654,.F.); #8656=EDGE_LOOP('',(#8650,#8652,#8653,#8655)); #8657=FACE_OUTER_BOUND('',#8656,.F.); #8658=ADVANCED_FACE('',(#8657),#8649,.F.); #8659=CARTESIAN_POINT('',(6.E0,1.5E0,3.075E1)); #8660=DIRECTION('',(0.E0,-1.E0,0.E0)); #8661=DIRECTION('',(1.E0,0.E0,0.E0)); #8662=AXIS2_PLACEMENT_3D('',#8659,#8660,#8661); #8663=CYLINDRICAL_SURFACE('',#8662,1.925E-1); #8664=ORIENTED_EDGE('',*,*,#8640,.T.); #8665=ORIENTED_EDGE('',*,*,#8654,.T.); #8666=ORIENTED_EDGE('',*,*,#5574,.F.); #8667=ORIENTED_EDGE('',*,*,#8651,.F.); #8668=EDGE_LOOP('',(#8664,#8665,#8666,#8667)); #8669=FACE_OUTER_BOUND('',#8668,.F.); #8670=ADVANCED_FACE('',(#8669),#8663,.F.); #8671=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1)); #8672=DIRECTION('',(0.E0,-1.E0,0.E0)); #8673=DIRECTION('',(1.E0,0.E0,0.E0)); #8674=AXIS2_PLACEMENT_3D('',#8671,#8672,#8673); #8675=CYLINDRICAL_SURFACE('',#8674,2.56E-1); #8676=ORIENTED_EDGE('',*,*,#6388,.T.); #8678=ORIENTED_EDGE('',*,*,#8677,.T.); #8680=ORIENTED_EDGE('',*,*,#8679,.F.); #8682=ORIENTED_EDGE('',*,*,#8681,.F.); #8683=EDGE_LOOP('',(#8676,#8678,#8680,#8682)); #8684=FACE_OUTER_BOUND('',#8683,.F.); #8685=ADVANCED_FACE('',(#8684),#8675,.F.); #8686=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1)); #8687=DIRECTION('',(0.E0,-1.E0,0.E0)); #8688=DIRECTION('',(1.E0,0.E0,0.E0)); #8689=AXIS2_PLACEMENT_3D('',#8686,#8687,#8688); #8690=CYLINDRICAL_SURFACE('',#8689,2.56E-1); #8691=ORIENTED_EDGE('',*,*,#6390,.T.); #8692=ORIENTED_EDGE('',*,*,#8681,.T.); #8694=ORIENTED_EDGE('',*,*,#8693,.F.); #8695=ORIENTED_EDGE('',*,*,#8677,.F.); #8696=EDGE_LOOP('',(#8691,#8692,#8694,#8695)); #8697=FACE_OUTER_BOUND('',#8696,.F.); #8698=ADVANCED_FACE('',(#8697),#8690,.F.); #8699=CARTESIAN_POINT('',(1.2E1,1.E0,3.075E1)); #8700=DIRECTION('',(0.E0,-1.E0,0.E0)); #8701=DIRECTION('',(1.E0,0.E0,0.E0)); #8702=AXIS2_PLACEMENT_3D('',#8699,#8700,#8701); #8703=PLANE('',#8702); #8704=ORIENTED_EDGE('',*,*,#8679,.T.); #8705=ORIENTED_EDGE('',*,*,#8693,.T.); #8706=EDGE_LOOP('',(#8704,#8705)); #8707=FACE_OUTER_BOUND('',#8706,.F.); #8709=ORIENTED_EDGE('',*,*,#8708,.F.); #8711=ORIENTED_EDGE('',*,*,#8710,.F.); #8712=EDGE_LOOP('',(#8709,#8711)); #8713=FACE_BOUND('',#8712,.F.); #8714=ADVANCED_FACE('',(#8707,#8713),#8703,.F.); #8715=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1)); #8716=DIRECTION('',(0.E0,-1.E0,0.E0)); #8717=DIRECTION('',(1.E0,0.E0,0.E0)); #8718=AXIS2_PLACEMENT_3D('',#8715,#8716,#8717); #8719=CYLINDRICAL_SURFACE('',#8718,1.925E-1); #8720=ORIENTED_EDGE('',*,*,#8708,.T.); #8722=ORIENTED_EDGE('',*,*,#8721,.T.); #8723=ORIENTED_EDGE('',*,*,#5566,.F.); #8725=ORIENTED_EDGE('',*,*,#8724,.F.); #8726=EDGE_LOOP('',(#8720,#8722,#8723,#8725)); #8727=FACE_OUTER_BOUND('',#8726,.F.); #8728=ADVANCED_FACE('',(#8727),#8719,.F.); #8729=CARTESIAN_POINT('',(1.2E1,1.5E0,3.075E1)); #8730=DIRECTION('',(0.E0,-1.E0,0.E0)); #8731=DIRECTION('',(1.E0,0.E0,0.E0)); #8732=AXIS2_PLACEMENT_3D('',#8729,#8730,#8731); #8733=CYLINDRICAL_SURFACE('',#8732,1.925E-1); #8734=ORIENTED_EDGE('',*,*,#8710,.T.); #8735=ORIENTED_EDGE('',*,*,#8724,.T.); #8736=ORIENTED_EDGE('',*,*,#5568,.F.); #8737=ORIENTED_EDGE('',*,*,#8721,.F.); #8738=EDGE_LOOP('',(#8734,#8735,#8736,#8737)); #8739=FACE_OUTER_BOUND('',#8738,.F.); #8740=ADVANCED_FACE('',(#8739),#8733,.F.); #8741=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1)); #8742=DIRECTION('',(0.E0,-1.E0,0.E0)); #8743=DIRECTION('',(1.E0,0.E0,0.E0)); #8744=AXIS2_PLACEMENT_3D('',#8741,#8742,#8743); #8745=CYLINDRICAL_SURFACE('',#8744,2.56E-1); #8746=ORIENTED_EDGE('',*,*,#6394,.T.); #8748=ORIENTED_EDGE('',*,*,#8747,.T.); #8750=ORIENTED_EDGE('',*,*,#8749,.F.); #8752=ORIENTED_EDGE('',*,*,#8751,.F.); #8753=EDGE_LOOP('',(#8746,#8748,#8750,#8752)); #8754=FACE_OUTER_BOUND('',#8753,.F.); #8755=ADVANCED_FACE('',(#8754),#8745,.F.); #8756=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1)); #8757=DIRECTION('',(0.E0,-1.E0,0.E0)); #8758=DIRECTION('',(1.E0,0.E0,0.E0)); #8759=AXIS2_PLACEMENT_3D('',#8756,#8757,#8758); #8760=CYLINDRICAL_SURFACE('',#8759,2.56E-1); #8761=ORIENTED_EDGE('',*,*,#6396,.T.); #8762=ORIENTED_EDGE('',*,*,#8751,.T.); #8764=ORIENTED_EDGE('',*,*,#8763,.F.); #8765=ORIENTED_EDGE('',*,*,#8747,.F.); #8766=EDGE_LOOP('',(#8761,#8762,#8764,#8765)); #8767=FACE_OUTER_BOUND('',#8766,.F.); #8768=ADVANCED_FACE('',(#8767),#8760,.F.); #8769=CARTESIAN_POINT('',(1.8E1,1.E0,3.075E1)); #8770=DIRECTION('',(0.E0,-1.E0,0.E0)); #8771=DIRECTION('',(1.E0,0.E0,0.E0)); #8772=AXIS2_PLACEMENT_3D('',#8769,#8770,#8771); #8773=PLANE('',#8772); #8774=ORIENTED_EDGE('',*,*,#8749,.T.); #8775=ORIENTED_EDGE('',*,*,#8763,.T.); #8776=EDGE_LOOP('',(#8774,#8775)); #8777=FACE_OUTER_BOUND('',#8776,.F.); #8779=ORIENTED_EDGE('',*,*,#8778,.F.); #8781=ORIENTED_EDGE('',*,*,#8780,.F.); #8782=EDGE_LOOP('',(#8779,#8781)); #8783=FACE_BOUND('',#8782,.F.); #8784=ADVANCED_FACE('',(#8777,#8783),#8773,.F.); #8785=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1)); #8786=DIRECTION('',(0.E0,-1.E0,0.E0)); #8787=DIRECTION('',(1.E0,0.E0,0.E0)); #8788=AXIS2_PLACEMENT_3D('',#8785,#8786,#8787); #8789=CYLINDRICAL_SURFACE('',#8788,1.925E-1); #8790=ORIENTED_EDGE('',*,*,#8778,.T.); #8792=ORIENTED_EDGE('',*,*,#8791,.T.); #8793=ORIENTED_EDGE('',*,*,#5554,.F.); #8795=ORIENTED_EDGE('',*,*,#8794,.F.); #8796=EDGE_LOOP('',(#8790,#8792,#8793,#8795)); #8797=FACE_OUTER_BOUND('',#8796,.F.); #8798=ADVANCED_FACE('',(#8797),#8789,.F.); #8799=CARTESIAN_POINT('',(1.8E1,1.5E0,3.075E1)); #8800=DIRECTION('',(0.E0,-1.E0,0.E0)); #8801=DIRECTION('',(1.E0,0.E0,0.E0)); #8802=AXIS2_PLACEMENT_3D('',#8799,#8800,#8801); #8803=CYLINDRICAL_SURFACE('',#8802,1.925E-1); #8804=ORIENTED_EDGE('',*,*,#8780,.T.); #8805=ORIENTED_EDGE('',*,*,#8794,.T.); #8806=ORIENTED_EDGE('',*,*,#5556,.F.); #8807=ORIENTED_EDGE('',*,*,#8791,.F.); #8808=EDGE_LOOP('',(#8804,#8805,#8806,#8807)); #8809=FACE_OUTER_BOUND('',#8808,.F.); #8810=ADVANCED_FACE('',(#8809),#8803,.F.); #8811=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0)); #8812=DIRECTION('',(0.E0,-1.E0,0.E0)); #8813=DIRECTION('',(1.E0,0.E0,0.E0)); #8814=AXIS2_PLACEMENT_3D('',#8811,#8812,#8813); #8815=CYLINDRICAL_SURFACE('',#8814,2.575E-1); #8816=ORIENTED_EDGE('',*,*,#6452,.T.); #8818=ORIENTED_EDGE('',*,*,#8817,.T.); #8820=ORIENTED_EDGE('',*,*,#8819,.F.); #8822=ORIENTED_EDGE('',*,*,#8821,.F.); #8823=EDGE_LOOP('',(#8816,#8818,#8820,#8822)); #8824=FACE_OUTER_BOUND('',#8823,.F.); #8825=ADVANCED_FACE('',(#8824),#8815,.F.); #8826=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0)); #8827=DIRECTION('',(0.E0,-1.E0,0.E0)); #8828=DIRECTION('',(1.E0,0.E0,0.E0)); #8829=AXIS2_PLACEMENT_3D('',#8826,#8827,#8828); #8830=CYLINDRICAL_SURFACE('',#8829,2.575E-1); #8831=ORIENTED_EDGE('',*,*,#6454,.T.); #8832=ORIENTED_EDGE('',*,*,#8821,.T.); #8834=ORIENTED_EDGE('',*,*,#8833,.F.); #8835=ORIENTED_EDGE('',*,*,#8817,.F.); #8836=EDGE_LOOP('',(#8831,#8832,#8834,#8835)); #8837=FACE_OUTER_BOUND('',#8836,.F.); #8838=ADVANCED_FACE('',(#8837),#8830,.F.); #8839=CARTESIAN_POINT('',(6.E0,1.E0,9.E0)); #8840=DIRECTION('',(0.E0,-1.E0,0.E0)); #8841=DIRECTION('',(1.E0,0.E0,0.E0)); #8842=AXIS2_PLACEMENT_3D('',#8839,#8840,#8841); #8843=PLANE('',#8842); #8844=ORIENTED_EDGE('',*,*,#8819,.T.); #8845=ORIENTED_EDGE('',*,*,#8833,.T.); #8846=EDGE_LOOP('',(#8844,#8845)); #8847=FACE_OUTER_BOUND('',#8846,.F.); #8849=ORIENTED_EDGE('',*,*,#8848,.F.); #8851=ORIENTED_EDGE('',*,*,#8850,.F.); #8852=EDGE_LOOP('',(#8849,#8851)); #8853=FACE_BOUND('',#8852,.F.); #8854=ADVANCED_FACE('',(#8847,#8853),#8843,.F.); #8855=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0)); #8856=DIRECTION('',(0.E0,-1.E0,0.E0)); #8857=DIRECTION('',(1.E0,0.E0,0.E0)); #8858=AXIS2_PLACEMENT_3D('',#8855,#8856,#8857); #8859=CYLINDRICAL_SURFACE('',#8858,1.925E-1); #8860=ORIENTED_EDGE('',*,*,#8848,.T.); #8862=ORIENTED_EDGE('',*,*,#8861,.T.); #8863=ORIENTED_EDGE('',*,*,#5690,.F.); #8865=ORIENTED_EDGE('',*,*,#8864,.F.); #8866=EDGE_LOOP('',(#8860,#8862,#8863,#8865)); #8867=FACE_OUTER_BOUND('',#8866,.F.); #8868=ADVANCED_FACE('',(#8867),#8859,.F.); #8869=CARTESIAN_POINT('',(6.E0,1.5E0,9.E0)); #8870=DIRECTION('',(0.E0,-1.E0,0.E0)); #8871=DIRECTION('',(1.E0,0.E0,0.E0)); #8872=AXIS2_PLACEMENT_3D('',#8869,#8870,#8871); #8873=CYLINDRICAL_SURFACE('',#8872,1.925E-1); #8874=ORIENTED_EDGE('',*,*,#8850,.T.); #8875=ORIENTED_EDGE('',*,*,#8864,.T.); #8876=ORIENTED_EDGE('',*,*,#5692,.F.); #8877=ORIENTED_EDGE('',*,*,#8861,.F.); #8878=EDGE_LOOP('',(#8874,#8875,#8876,#8877)); #8879=FACE_OUTER_BOUND('',#8878,.F.); #8880=ADVANCED_FACE('',(#8879),#8873,.F.); #8881=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0)); #8882=DIRECTION('',(0.E0,-1.E0,0.E0)); #8883=DIRECTION('',(1.E0,0.E0,0.E0)); #8884=AXIS2_PLACEMENT_3D('',#8881,#8882,#8883); #8885=CYLINDRICAL_SURFACE('',#8884,2.575E-1); #8886=ORIENTED_EDGE('',*,*,#6458,.T.); #8888=ORIENTED_EDGE('',*,*,#8887,.T.); #8890=ORIENTED_EDGE('',*,*,#8889,.F.); #8892=ORIENTED_EDGE('',*,*,#8891,.F.); #8893=EDGE_LOOP('',(#8886,#8888,#8890,#8892)); #8894=FACE_OUTER_BOUND('',#8893,.F.); #8895=ADVANCED_FACE('',(#8894),#8885,.F.); #8896=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0)); #8897=DIRECTION('',(0.E0,-1.E0,0.E0)); #8898=DIRECTION('',(1.E0,0.E0,0.E0)); #8899=AXIS2_PLACEMENT_3D('',#8896,#8897,#8898); #8900=CYLINDRICAL_SURFACE('',#8899,2.575E-1); #8901=ORIENTED_EDGE('',*,*,#6460,.T.); #8902=ORIENTED_EDGE('',*,*,#8891,.T.); #8904=ORIENTED_EDGE('',*,*,#8903,.F.); #8905=ORIENTED_EDGE('',*,*,#8887,.F.); #8906=EDGE_LOOP('',(#8901,#8902,#8904,#8905)); #8907=FACE_OUTER_BOUND('',#8906,.F.); #8908=ADVANCED_FACE('',(#8907),#8900,.F.); #8909=CARTESIAN_POINT('',(1.2E1,1.E0,9.E0)); #8910=DIRECTION('',(0.E0,-1.E0,0.E0)); #8911=DIRECTION('',(1.E0,0.E0,0.E0)); #8912=AXIS2_PLACEMENT_3D('',#8909,#8910,#8911); #8913=PLANE('',#8912); #8914=ORIENTED_EDGE('',*,*,#8889,.T.); #8915=ORIENTED_EDGE('',*,*,#8903,.T.); #8916=EDGE_LOOP('',(#8914,#8915)); #8917=FACE_OUTER_BOUND('',#8916,.F.); #8919=ORIENTED_EDGE('',*,*,#8918,.F.); #8921=ORIENTED_EDGE('',*,*,#8920,.F.); #8922=EDGE_LOOP('',(#8919,#8921)); #8923=FACE_BOUND('',#8922,.F.); #8924=ADVANCED_FACE('',(#8917,#8923),#8913,.F.); #8925=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0)); #8926=DIRECTION('',(0.E0,-1.E0,0.E0)); #8927=DIRECTION('',(1.E0,0.E0,0.E0)); #8928=AXIS2_PLACEMENT_3D('',#8925,#8926,#8927); #8929=CYLINDRICAL_SURFACE('',#8928,1.925E-1); #8930=ORIENTED_EDGE('',*,*,#8918,.T.); #8932=ORIENTED_EDGE('',*,*,#8931,.T.); #8933=ORIENTED_EDGE('',*,*,#5696,.F.); #8935=ORIENTED_EDGE('',*,*,#8934,.F.); #8936=EDGE_LOOP('',(#8930,#8932,#8933,#8935)); #8937=FACE_OUTER_BOUND('',#8936,.F.); #8938=ADVANCED_FACE('',(#8937),#8929,.F.); #8939=CARTESIAN_POINT('',(1.2E1,1.5E0,9.E0)); #8940=DIRECTION('',(0.E0,-1.E0,0.E0)); #8941=DIRECTION('',(1.E0,0.E0,0.E0)); #8942=AXIS2_PLACEMENT_3D('',#8939,#8940,#8941); #8943=CYLINDRICAL_SURFACE('',#8942,1.925E-1); #8944=ORIENTED_EDGE('',*,*,#8920,.T.); #8945=ORIENTED_EDGE('',*,*,#8934,.T.); #8946=ORIENTED_EDGE('',*,*,#5698,.F.); #8947=ORIENTED_EDGE('',*,*,#8931,.F.); #8948=EDGE_LOOP('',(#8944,#8945,#8946,#8947)); #8949=FACE_OUTER_BOUND('',#8948,.F.); #8950=ADVANCED_FACE('',(#8949),#8943,.F.); #8951=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0)); #8952=DIRECTION('',(0.E0,-1.E0,0.E0)); #8953=DIRECTION('',(1.E0,0.E0,0.E0)); #8954=AXIS2_PLACEMENT_3D('',#8951,#8952,#8953); #8955=CYLINDRICAL_SURFACE('',#8954,2.575E-1); #8956=ORIENTED_EDGE('',*,*,#6464,.T.); #8958=ORIENTED_EDGE('',*,*,#8957,.T.); #8960=ORIENTED_EDGE('',*,*,#8959,.F.); #8962=ORIENTED_EDGE('',*,*,#8961,.F.); #8963=EDGE_LOOP('',(#8956,#8958,#8960,#8962)); #8964=FACE_OUTER_BOUND('',#8963,.F.); #8965=ADVANCED_FACE('',(#8964),#8955,.F.); #8966=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0)); #8967=DIRECTION('',(0.E0,-1.E0,0.E0)); #8968=DIRECTION('',(1.E0,0.E0,0.E0)); #8969=AXIS2_PLACEMENT_3D('',#8966,#8967,#8968); #8970=CYLINDRICAL_SURFACE('',#8969,2.575E-1); #8971=ORIENTED_EDGE('',*,*,#6466,.T.); #8972=ORIENTED_EDGE('',*,*,#8961,.T.); #8974=ORIENTED_EDGE('',*,*,#8973,.F.); #8975=ORIENTED_EDGE('',*,*,#8957,.F.); #8976=EDGE_LOOP('',(#8971,#8972,#8974,#8975)); #8977=FACE_OUTER_BOUND('',#8976,.F.); #8978=ADVANCED_FACE('',(#8977),#8970,.F.); #8979=CARTESIAN_POINT('',(1.8E1,1.E0,9.E0)); #8980=DIRECTION('',(0.E0,-1.E0,0.E0)); #8981=DIRECTION('',(1.E0,0.E0,0.E0)); #8982=AXIS2_PLACEMENT_3D('',#8979,#8980,#8981); #8983=PLANE('',#8982); #8984=ORIENTED_EDGE('',*,*,#8959,.T.); #8985=ORIENTED_EDGE('',*,*,#8973,.T.); #8986=EDGE_LOOP('',(#8984,#8985)); #8987=FACE_OUTER_BOUND('',#8986,.F.); #8989=ORIENTED_EDGE('',*,*,#8988,.F.); #8991=ORIENTED_EDGE('',*,*,#8990,.F.); #8992=EDGE_LOOP('',(#8989,#8991)); #8993=FACE_BOUND('',#8992,.F.); #8994=ADVANCED_FACE('',(#8987,#8993),#8983,.F.); #8995=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0)); #8996=DIRECTION('',(0.E0,-1.E0,0.E0)); #8997=DIRECTION('',(1.E0,0.E0,0.E0)); #8998=AXIS2_PLACEMENT_3D('',#8995,#8996,#8997); #8999=CYLINDRICAL_SURFACE('',#8998,1.925E-1); #9000=ORIENTED_EDGE('',*,*,#8988,.T.); #9002=ORIENTED_EDGE('',*,*,#9001,.T.); #9003=ORIENTED_EDGE('',*,*,#5702,.F.); #9005=ORIENTED_EDGE('',*,*,#9004,.F.); #9006=EDGE_LOOP('',(#9000,#9002,#9003,#9005)); #9007=FACE_OUTER_BOUND('',#9006,.F.); #9008=ADVANCED_FACE('',(#9007),#8999,.F.); #9009=CARTESIAN_POINT('',(1.8E1,1.5E0,9.E0)); #9010=DIRECTION('',(0.E0,-1.E0,0.E0)); #9011=DIRECTION('',(1.E0,0.E0,0.E0)); #9012=AXIS2_PLACEMENT_3D('',#9009,#9010,#9011); #9013=CYLINDRICAL_SURFACE('',#9012,1.925E-1); #9014=ORIENTED_EDGE('',*,*,#8990,.T.); #9015=ORIENTED_EDGE('',*,*,#9004,.T.); #9016=ORIENTED_EDGE('',*,*,#5704,.F.); #9017=ORIENTED_EDGE('',*,*,#9001,.F.); #9018=EDGE_LOOP('',(#9014,#9015,#9016,#9017)); #9019=FACE_OUTER_BOUND('',#9018,.F.); #9020=ADVANCED_FACE('',(#9019),#9013,.F.); #9021=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1)); #9022=DIRECTION('',(0.E0,-1.E0,0.E0)); #9023=DIRECTION('',(1.E0,0.E0,0.E0)); #9024=AXIS2_PLACEMENT_3D('',#9021,#9022,#9023); #9025=CYLINDRICAL_SURFACE('',#9024,2.575E-1); #9026=ORIENTED_EDGE('',*,*,#6470,.T.); #9028=ORIENTED_EDGE('',*,*,#9027,.T.); #9030=ORIENTED_EDGE('',*,*,#9029,.F.); #9032=ORIENTED_EDGE('',*,*,#9031,.F.); #9033=EDGE_LOOP('',(#9026,#9028,#9030,#9032)); #9034=FACE_OUTER_BOUND('',#9033,.F.); #9035=ADVANCED_FACE('',(#9034),#9025,.F.); #9036=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1)); #9037=DIRECTION('',(0.E0,-1.E0,0.E0)); #9038=DIRECTION('',(1.E0,0.E0,0.E0)); #9039=AXIS2_PLACEMENT_3D('',#9036,#9037,#9038); #9040=CYLINDRICAL_SURFACE('',#9039,2.575E-1); #9041=ORIENTED_EDGE('',*,*,#6472,.T.); #9042=ORIENTED_EDGE('',*,*,#9031,.T.); #9044=ORIENTED_EDGE('',*,*,#9043,.F.); #9045=ORIENTED_EDGE('',*,*,#9027,.F.); #9046=EDGE_LOOP('',(#9041,#9042,#9044,#9045)); #9047=FACE_OUTER_BOUND('',#9046,.F.); #9048=ADVANCED_FACE('',(#9047),#9040,.F.); #9049=CARTESIAN_POINT('',(6.E0,1.E0,1.8E1)); #9050=DIRECTION('',(0.E0,-1.E0,0.E0)); #9051=DIRECTION('',(1.E0,0.E0,0.E0)); #9052=AXIS2_PLACEMENT_3D('',#9049,#9050,#9051); #9053=PLANE('',#9052); #9054=ORIENTED_EDGE('',*,*,#9029,.T.); #9055=ORIENTED_EDGE('',*,*,#9043,.T.); #9056=EDGE_LOOP('',(#9054,#9055)); #9057=FACE_OUTER_BOUND('',#9056,.F.); #9059=ORIENTED_EDGE('',*,*,#9058,.F.); #9061=ORIENTED_EDGE('',*,*,#9060,.F.); #9062=EDGE_LOOP('',(#9059,#9061)); #9063=FACE_BOUND('',#9062,.F.); #9064=ADVANCED_FACE('',(#9057,#9063),#9053,.F.); #9065=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1)); #9066=DIRECTION('',(0.E0,-1.E0,0.E0)); #9067=DIRECTION('',(1.E0,0.E0,0.E0)); #9068=AXIS2_PLACEMENT_3D('',#9065,#9066,#9067); #9069=CYLINDRICAL_SURFACE('',#9068,1.925E-1); #9070=ORIENTED_EDGE('',*,*,#9058,.T.); #9072=ORIENTED_EDGE('',*,*,#9071,.T.); #9073=ORIENTED_EDGE('',*,*,#5708,.F.); #9075=ORIENTED_EDGE('',*,*,#9074,.F.); #9076=EDGE_LOOP('',(#9070,#9072,#9073,#9075)); #9077=FACE_OUTER_BOUND('',#9076,.F.); #9078=ADVANCED_FACE('',(#9077),#9069,.F.); #9079=CARTESIAN_POINT('',(6.E0,1.5E0,1.8E1)); #9080=DIRECTION('',(0.E0,-1.E0,0.E0)); #9081=DIRECTION('',(1.E0,0.E0,0.E0)); #9082=AXIS2_PLACEMENT_3D('',#9079,#9080,#9081); #9083=CYLINDRICAL_SURFACE('',#9082,1.925E-1); #9084=ORIENTED_EDGE('',*,*,#9060,.T.); #9085=ORIENTED_EDGE('',*,*,#9074,.T.); #9086=ORIENTED_EDGE('',*,*,#5710,.F.); #9087=ORIENTED_EDGE('',*,*,#9071,.F.); #9088=EDGE_LOOP('',(#9084,#9085,#9086,#9087)); #9089=FACE_OUTER_BOUND('',#9088,.F.); #9090=ADVANCED_FACE('',(#9089),#9083,.F.); #9091=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1)); #9092=DIRECTION('',(0.E0,-1.E0,0.E0)); #9093=DIRECTION('',(1.E0,0.E0,0.E0)); #9094=AXIS2_PLACEMENT_3D('',#9091,#9092,#9093); #9095=CYLINDRICAL_SURFACE('',#9094,2.575E-1); #9096=ORIENTED_EDGE('',*,*,#6476,.T.); #9098=ORIENTED_EDGE('',*,*,#9097,.T.); #9100=ORIENTED_EDGE('',*,*,#9099,.F.); #9102=ORIENTED_EDGE('',*,*,#9101,.F.); #9103=EDGE_LOOP('',(#9096,#9098,#9100,#9102)); #9104=FACE_OUTER_BOUND('',#9103,.F.); #9105=ADVANCED_FACE('',(#9104),#9095,.F.); #9106=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1)); #9107=DIRECTION('',(0.E0,-1.E0,0.E0)); #9108=DIRECTION('',(1.E0,0.E0,0.E0)); #9109=AXIS2_PLACEMENT_3D('',#9106,#9107,#9108); #9110=CYLINDRICAL_SURFACE('',#9109,2.575E-1); #9111=ORIENTED_EDGE('',*,*,#6478,.T.); #9112=ORIENTED_EDGE('',*,*,#9101,.T.); #9114=ORIENTED_EDGE('',*,*,#9113,.F.); #9115=ORIENTED_EDGE('',*,*,#9097,.F.); #9116=EDGE_LOOP('',(#9111,#9112,#9114,#9115)); #9117=FACE_OUTER_BOUND('',#9116,.F.); #9118=ADVANCED_FACE('',(#9117),#9110,.F.); #9119=CARTESIAN_POINT('',(1.2E1,1.E0,1.8E1)); #9120=DIRECTION('',(0.E0,-1.E0,0.E0)); #9121=DIRECTION('',(1.E0,0.E0,0.E0)); #9122=AXIS2_PLACEMENT_3D('',#9119,#9120,#9121); #9123=PLANE('',#9122); #9124=ORIENTED_EDGE('',*,*,#9099,.T.); #9125=ORIENTED_EDGE('',*,*,#9113,.T.); #9126=EDGE_LOOP('',(#9124,#9125)); #9127=FACE_OUTER_BOUND('',#9126,.F.); #9129=ORIENTED_EDGE('',*,*,#9128,.F.); #9131=ORIENTED_EDGE('',*,*,#9130,.F.); #9132=EDGE_LOOP('',(#9129,#9131)); #9133=FACE_BOUND('',#9132,.F.); #9134=ADVANCED_FACE('',(#9127,#9133),#9123,.F.); #9135=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1)); #9136=DIRECTION('',(0.E0,-1.E0,0.E0)); #9137=DIRECTION('',(1.E0,0.E0,0.E0)); #9138=AXIS2_PLACEMENT_3D('',#9135,#9136,#9137); #9139=CYLINDRICAL_SURFACE('',#9138,1.925E-1); #9140=ORIENTED_EDGE('',*,*,#9128,.T.); #9142=ORIENTED_EDGE('',*,*,#9141,.T.); #9143=ORIENTED_EDGE('',*,*,#5714,.F.); #9145=ORIENTED_EDGE('',*,*,#9144,.F.); #9146=EDGE_LOOP('',(#9140,#9142,#9143,#9145)); #9147=FACE_OUTER_BOUND('',#9146,.F.); #9148=ADVANCED_FACE('',(#9147),#9139,.F.); #9149=CARTESIAN_POINT('',(1.2E1,1.5E0,1.8E1)); #9150=DIRECTION('',(0.E0,-1.E0,0.E0)); #9151=DIRECTION('',(1.E0,0.E0,0.E0)); #9152=AXIS2_PLACEMENT_3D('',#9149,#9150,#9151); #9153=CYLINDRICAL_SURFACE('',#9152,1.925E-1); #9154=ORIENTED_EDGE('',*,*,#9130,.T.); #9155=ORIENTED_EDGE('',*,*,#9144,.T.); #9156=ORIENTED_EDGE('',*,*,#5716,.F.); #9157=ORIENTED_EDGE('',*,*,#9141,.F.); #9158=EDGE_LOOP('',(#9154,#9155,#9156,#9157)); #9159=FACE_OUTER_BOUND('',#9158,.F.); #9160=ADVANCED_FACE('',(#9159),#9153,.F.); #9161=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1)); #9162=DIRECTION('',(0.E0,-1.E0,0.E0)); #9163=DIRECTION('',(1.E0,0.E0,0.E0)); #9164=AXIS2_PLACEMENT_3D('',#9161,#9162,#9163); #9165=CYLINDRICAL_SURFACE('',#9164,2.575E-1); #9166=ORIENTED_EDGE('',*,*,#6482,.T.); #9168=ORIENTED_EDGE('',*,*,#9167,.T.); #9170=ORIENTED_EDGE('',*,*,#9169,.F.); #9172=ORIENTED_EDGE('',*,*,#9171,.F.); #9173=EDGE_LOOP('',(#9166,#9168,#9170,#9172)); #9174=FACE_OUTER_BOUND('',#9173,.F.); #9175=ADVANCED_FACE('',(#9174),#9165,.F.); #9176=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1)); #9177=DIRECTION('',(0.E0,-1.E0,0.E0)); #9178=DIRECTION('',(1.E0,0.E0,0.E0)); #9179=AXIS2_PLACEMENT_3D('',#9176,#9177,#9178); #9180=CYLINDRICAL_SURFACE('',#9179,2.575E-1); #9181=ORIENTED_EDGE('',*,*,#6484,.T.); #9182=ORIENTED_EDGE('',*,*,#9171,.T.); #9184=ORIENTED_EDGE('',*,*,#9183,.F.); #9185=ORIENTED_EDGE('',*,*,#9167,.F.); #9186=EDGE_LOOP('',(#9181,#9182,#9184,#9185)); #9187=FACE_OUTER_BOUND('',#9186,.F.); #9188=ADVANCED_FACE('',(#9187),#9180,.F.); #9189=CARTESIAN_POINT('',(1.8E1,1.E0,1.8E1)); #9190=DIRECTION('',(0.E0,-1.E0,0.E0)); #9191=DIRECTION('',(1.E0,0.E0,0.E0)); #9192=AXIS2_PLACEMENT_3D('',#9189,#9190,#9191); #9193=PLANE('',#9192); #9194=ORIENTED_EDGE('',*,*,#9169,.T.); #9195=ORIENTED_EDGE('',*,*,#9183,.T.); #9196=EDGE_LOOP('',(#9194,#9195)); #9197=FACE_OUTER_BOUND('',#9196,.F.); #9199=ORIENTED_EDGE('',*,*,#9198,.F.); #9201=ORIENTED_EDGE('',*,*,#9200,.F.); #9202=EDGE_LOOP('',(#9199,#9201)); #9203=FACE_BOUND('',#9202,.F.); #9204=ADVANCED_FACE('',(#9197,#9203),#9193,.F.); #9205=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1)); #9206=DIRECTION('',(0.E0,-1.E0,0.E0)); #9207=DIRECTION('',(1.E0,0.E0,0.E0)); #9208=AXIS2_PLACEMENT_3D('',#9205,#9206,#9207); #9209=CYLINDRICAL_SURFACE('',#9208,1.925E-1); #9210=ORIENTED_EDGE('',*,*,#9198,.T.); #9212=ORIENTED_EDGE('',*,*,#9211,.T.); #9213=ORIENTED_EDGE('',*,*,#5720,.F.); #9215=ORIENTED_EDGE('',*,*,#9214,.F.); #9216=EDGE_LOOP('',(#9210,#9212,#9213,#9215)); #9217=FACE_OUTER_BOUND('',#9216,.F.); #9218=ADVANCED_FACE('',(#9217),#9209,.F.); #9219=CARTESIAN_POINT('',(1.8E1,1.5E0,1.8E1)); #9220=DIRECTION('',(0.E0,-1.E0,0.E0)); #9221=DIRECTION('',(1.E0,0.E0,0.E0)); #9222=AXIS2_PLACEMENT_3D('',#9219,#9220,#9221); #9223=CYLINDRICAL_SURFACE('',#9222,1.925E-1); #9224=ORIENTED_EDGE('',*,*,#9200,.T.); #9225=ORIENTED_EDGE('',*,*,#9214,.T.); #9226=ORIENTED_EDGE('',*,*,#5722,.F.); #9227=ORIENTED_EDGE('',*,*,#9211,.F.); #9228=EDGE_LOOP('',(#9224,#9225,#9226,#9227)); #9229=FACE_OUTER_BOUND('',#9228,.F.); #9230=ADVANCED_FACE('',(#9229),#9223,.F.); #9231=CARTESIAN_POINT('',(2.2E1,1.5E0,1.2E1)); #9232=DIRECTION('',(1.E0,0.E0,0.E0)); #9233=DIRECTION('',(0.E0,-1.E0,0.E0)); #9234=AXIS2_PLACEMENT_3D('',#9231,#9232,#9233); #9235=PLANE('',#9234); #9236=ORIENTED_EDGE('',*,*,#6328,.T.); #9237=ORIENTED_EDGE('',*,*,#6155,.T.); #9239=ORIENTED_EDGE('',*,*,#9238,.T.); #9240=EDGE_LOOP('',(#9236,#9237,#9239)); #9241=FACE_OUTER_BOUND('',#9240,.F.); #9242=ADVANCED_FACE('',(#9241),#9235,.F.); #9243=CARTESIAN_POINT('',(2.375E1,6.5E0,1.E1)); #9244=DIRECTION('',(0.E0,-5.E-1,-8.660254037844E-1)); #9245=DIRECTION('',(0.E0,-8.660254037844E-1,5.E-1)); #9246=AXIS2_PLACEMENT_3D('',#9243,#9244,#9245); #9247=PLANE('',#9246); #9248=ORIENTED_EDGE('',*,*,#6330,.T.); #9249=ORIENTED_EDGE('',*,*,#9238,.F.); #9250=ORIENTED_EDGE('',*,*,#6153,.F.); #9251=ORIENTED_EDGE('',*,*,#6209,.T.); #9252=EDGE_LOOP('',(#9248,#9249,#9250,#9251)); #9253=FACE_OUTER_BOUND('',#9252,.F.); #9255=ORIENTED_EDGE('',*,*,#9254,.F.); #9257=ORIENTED_EDGE('',*,*,#9256,.F.); #9258=EDGE_LOOP('',(#9255,#9257)); #9259=FACE_BOUND('',#9258,.F.); #9260=ADVANCED_FACE('',(#9253,#9259),#9247,.F.); #9261=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1)); #9262=DIRECTION('',(0.E0,-1.E0,0.E0)); #9263=DIRECTION('',(1.E0,0.E0,0.E0)); #9264=AXIS2_PLACEMENT_3D('',#9261,#9262,#9263); #9265=CYLINDRICAL_SURFACE('',#9264,2.575E-1); #9267=ORIENTED_EDGE('',*,*,#9266,.F.); #9268=ORIENTED_EDGE('',*,*,#9254,.T.); #9270=ORIENTED_EDGE('',*,*,#9269,.F.); #9272=ORIENTED_EDGE('',*,*,#9271,.F.); #9273=EDGE_LOOP('',(#9267,#9268,#9270,#9272)); #9274=FACE_OUTER_BOUND('',#9273,.F.); #9275=ADVANCED_FACE('',(#9274),#9265,.F.); #9276=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1)); #9277=DIRECTION('',(0.E0,-1.E0,0.E0)); #9278=DIRECTION('',(1.E0,0.E0,0.E0)); #9279=AXIS2_PLACEMENT_3D('',#9276,#9277,#9278); #9280=CYLINDRICAL_SURFACE('',#9279,2.575E-1); #9281=ORIENTED_EDGE('',*,*,#9269,.T.); #9282=ORIENTED_EDGE('',*,*,#9256,.T.); #9283=ORIENTED_EDGE('',*,*,#9266,.T.); #9285=ORIENTED_EDGE('',*,*,#9284,.F.); #9286=EDGE_LOOP('',(#9281,#9282,#9283,#9285)); #9287=FACE_OUTER_BOUND('',#9286,.F.); #9288=ADVANCED_FACE('',(#9287),#9280,.F.); #9289=CARTESIAN_POINT('',(2.2875E1,1.E0,1.2E1)); #9290=DIRECTION('',(0.E0,-1.E0,0.E0)); #9291=DIRECTION('',(1.E0,0.E0,0.E0)); #9292=AXIS2_PLACEMENT_3D('',#9289,#9290,#9291); #9293=PLANE('',#9292); #9294=ORIENTED_EDGE('',*,*,#9271,.T.); #9295=ORIENTED_EDGE('',*,*,#9284,.T.); #9296=EDGE_LOOP('',(#9294,#9295)); #9297=FACE_OUTER_BOUND('',#9296,.F.); #9299=ORIENTED_EDGE('',*,*,#9298,.F.); #9301=ORIENTED_EDGE('',*,*,#9300,.F.); #9302=EDGE_LOOP('',(#9299,#9301)); #9303=FACE_BOUND('',#9302,.F.); #9304=ADVANCED_FACE('',(#9297,#9303),#9293,.F.); #9305=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1)); #9306=DIRECTION('',(0.E0,-1.E0,0.E0)); #9307=DIRECTION('',(1.E0,0.E0,0.E0)); #9308=AXIS2_PLACEMENT_3D('',#9305,#9306,#9307); #9309=CYLINDRICAL_SURFACE('',#9308,1.925E-1); #9310=ORIENTED_EDGE('',*,*,#9298,.T.); #9312=ORIENTED_EDGE('',*,*,#9311,.T.); #9313=ORIENTED_EDGE('',*,*,#5596,.F.); #9315=ORIENTED_EDGE('',*,*,#9314,.F.); #9316=EDGE_LOOP('',(#9310,#9312,#9313,#9315)); #9317=FACE_OUTER_BOUND('',#9316,.F.); #9318=ADVANCED_FACE('',(#9317),#9309,.F.); #9319=CARTESIAN_POINT('',(2.2875E1,1.5E0,1.2E1)); #9320=DIRECTION('',(0.E0,-1.E0,0.E0)); #9321=DIRECTION('',(1.E0,0.E0,0.E0)); #9322=AXIS2_PLACEMENT_3D('',#9319,#9320,#9321); #9323=CYLINDRICAL_SURFACE('',#9322,1.925E-1); #9324=ORIENTED_EDGE('',*,*,#9300,.T.); #9325=ORIENTED_EDGE('',*,*,#9314,.T.); #9326=ORIENTED_EDGE('',*,*,#5598,.F.); #9327=ORIENTED_EDGE('',*,*,#9311,.F.); #9328=EDGE_LOOP('',(#9324,#9325,#9326,#9327)); #9329=FACE_OUTER_BOUND('',#9328,.F.); #9330=ADVANCED_FACE('',(#9329),#9323,.F.); #9331=CARTESIAN_POINT('',(2.185E1,6.65E0,1.006892397423E1)); #9332=DIRECTION('',(0.E0,0.E0,-1.E0)); #9333=DIRECTION('',(-1.E0,0.E0,0.E0)); #9334=AXIS2_PLACEMENT_3D('',#9331,#9332,#9333); #9335=CYLINDRICAL_SURFACE('',#9334,3.5E-1); #9337=ORIENTED_EDGE('',*,*,#9336,.T.); #9339=ORIENTED_EDGE('',*,*,#9338,.T.); #9341=ORIENTED_EDGE('',*,*,#9340,.F.); #9342=ORIENTED_EDGE('',*,*,#6175,.T.); #9343=EDGE_LOOP('',(#9337,#9339,#9341,#9342)); #9344=FACE_OUTER_BOUND('',#9343,.F.); #9345=ADVANCED_FACE('',(#9344),#9335,.T.); #9346=CARTESIAN_POINT('',(2.15E1,7.E0,1.E1)); #9347=DIRECTION('',(-1.E0,0.E0,0.E0)); #9348=DIRECTION('',(0.E0,-1.E0,0.E0)); #9349=AXIS2_PLACEMENT_3D('',#9346,#9347,#9348); #9350=PLANE('',#9349); #9351=ORIENTED_EDGE('',*,*,#9336,.F.); #9352=ORIENTED_EDGE('',*,*,#6197,.T.); #9354=ORIENTED_EDGE('',*,*,#9353,.F.); #9356=ORIENTED_EDGE('',*,*,#9355,.F.); #9357=EDGE_LOOP('',(#9351,#9352,#9354,#9356)); #9358=FACE_OUTER_BOUND('',#9357,.F.); #9359=ADVANCED_FACE('',(#9358),#9350,.T.); #9360=CARTESIAN_POINT('',(2.115E1,2.35E0,9.441108058217E0)); #9361=DIRECTION('',(0.E0,0.E0,1.E0)); #9362=DIRECTION('',(1.015061051086E-14,-1.E0,0.E0)); #9363=AXIS2_PLACEMENT_3D('',#9360,#9361,#9362); #9364=CYLINDRICAL_SURFACE('',#9363,3.5E-1); #9366=ORIENTED_EDGE('',*,*,#9365,.F.); #9368=ORIENTED_EDGE('',*,*,#9367,.T.); #9369=ORIENTED_EDGE('',*,*,#9353,.T.); #9370=ORIENTED_EDGE('',*,*,#6195,.T.); #9371=EDGE_LOOP('',(#9366,#9368,#9369,#9370)); #9372=FACE_OUTER_BOUND('',#9371,.F.); #9373=ADVANCED_FACE('',(#9372),#9364,.F.); #9374=CARTESIAN_POINT('',(2.15E1,2.E0,1.E1)); #9375=DIRECTION('',(0.E0,1.E0,0.E0)); #9376=DIRECTION('',(-1.E0,0.E0,0.E0)); #9377=AXIS2_PLACEMENT_3D('',#9374,#9375,#9376); #9378=PLANE('',#9377); #9379=ORIENTED_EDGE('',*,*,#9365,.T.); #9380=ORIENTED_EDGE('',*,*,#6193,.T.); #9382=ORIENTED_EDGE('',*,*,#9381,.F.); #9384=ORIENTED_EDGE('',*,*,#9383,.F.); #9385=EDGE_LOOP('',(#9379,#9380,#9382,#9384)); #9386=FACE_OUTER_BOUND('',#9385,.F.); #9387=ADVANCED_FACE('',(#9386),#9378,.T.); #9388=CARTESIAN_POINT('',(1.985E1,2.35E0,9.441108058217E0)); #9389=DIRECTION('',(0.E0,0.E0,1.E0)); #9390=DIRECTION('',(-1.E0,0.E0,0.E0)); #9391=AXIS2_PLACEMENT_3D('',#9388,#9389,#9390); #9392=CYLINDRICAL_SURFACE('',#9391,3.5E-1); #9394=ORIENTED_EDGE('',*,*,#9393,.F.); #9396=ORIENTED_EDGE('',*,*,#9395,.T.); #9397=ORIENTED_EDGE('',*,*,#9381,.T.); #9398=ORIENTED_EDGE('',*,*,#6191,.T.); #9399=EDGE_LOOP('',(#9394,#9396,#9397,#9398)); #9400=FACE_OUTER_BOUND('',#9399,.F.); #9401=ADVANCED_FACE('',(#9400),#9392,.F.); #9402=CARTESIAN_POINT('',(1.95E1,2.E0,1.E1)); #9403=DIRECTION('',(1.E0,0.E0,0.E0)); #9404=DIRECTION('',(0.E0,1.E0,0.E0)); #9405=AXIS2_PLACEMENT_3D('',#9402,#9403,#9404); #9406=PLANE('',#9405); #9407=ORIENTED_EDGE('',*,*,#9393,.T.); #9408=ORIENTED_EDGE('',*,*,#6189,.T.); #9410=ORIENTED_EDGE('',*,*,#9409,.F.); #9412=ORIENTED_EDGE('',*,*,#9411,.F.); #9413=EDGE_LOOP('',(#9407,#9408,#9410,#9412)); #9414=FACE_OUTER_BOUND('',#9413,.F.); #9415=ADVANCED_FACE('',(#9414),#9406,.T.); #9416=CARTESIAN_POINT('',(1.985E1,9.15E0,9.441108058217E0)); #9417=DIRECTION('',(0.E0,0.E0,1.E0)); #9418=DIRECTION('',(-1.015061051086E-14,1.E0,0.E0)); #9419=AXIS2_PLACEMENT_3D('',#9416,#9417,#9418); #9420=CYLINDRICAL_SURFACE('',#9419,3.5E-1); #9422=ORIENTED_EDGE('',*,*,#9421,.F.); #9424=ORIENTED_EDGE('',*,*,#9423,.T.); #9425=ORIENTED_EDGE('',*,*,#9409,.T.); #9426=ORIENTED_EDGE('',*,*,#6187,.T.); #9427=EDGE_LOOP('',(#9422,#9424,#9425,#9426)); #9428=FACE_OUTER_BOUND('',#9427,.F.); #9429=ADVANCED_FACE('',(#9428),#9420,.F.); #9430=CARTESIAN_POINT('',(1.95E1,9.5E0,1.E1)); #9431=DIRECTION('',(0.E0,-1.E0,0.E0)); #9432=DIRECTION('',(1.E0,0.E0,0.E0)); #9433=AXIS2_PLACEMENT_3D('',#9430,#9431,#9432); #9434=PLANE('',#9433); #9436=ORIENTED_EDGE('',*,*,#9435,.F.); #9438=ORIENTED_EDGE('',*,*,#9437,.F.); #9439=ORIENTED_EDGE('',*,*,#9421,.T.); #9440=ORIENTED_EDGE('',*,*,#6185,.T.); #9441=EDGE_LOOP('',(#9436,#9438,#9439,#9440)); #9442=FACE_OUTER_BOUND('',#9441,.F.); #9443=ADVANCED_FACE('',(#9442),#9434,.T.); #9444=CARTESIAN_POINT('',(2.104720076055E1,9.15E0,9.441108058217E0)); #9445=DIRECTION('',(0.E0,0.E0,1.E0)); #9446=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0)); #9447=AXIS2_PLACEMENT_3D('',#9444,#9445,#9446); #9448=CYLINDRICAL_SURFACE('',#9447,3.5E-1); #9450=ORIENTED_EDGE('',*,*,#9449,.F.); #9452=ORIENTED_EDGE('',*,*,#9451,.T.); #9453=ORIENTED_EDGE('',*,*,#9435,.T.); #9454=ORIENTED_EDGE('',*,*,#6183,.T.); #9455=EDGE_LOOP('',(#9450,#9452,#9453,#9454)); #9456=FACE_OUTER_BOUND('',#9455,.F.); #9457=ADVANCED_FACE('',(#9456),#9448,.F.); #9458=CARTESIAN_POINT('',(2.125314193270E1,9.5E0,1.E1)); #9459=DIRECTION('',(-8.741572761215E-1,-4.856429311786E-1,0.E0)); #9460=DIRECTION('',(4.856429311786E-1,-8.741572761215E-1,0.E0)); #9461=AXIS2_PLACEMENT_3D('',#9458,#9459,#9460); #9462=PLANE('',#9461); #9464=ORIENTED_EDGE('',*,*,#9463,.F.); #9466=ORIENTED_EDGE('',*,*,#9465,.F.); #9467=ORIENTED_EDGE('',*,*,#9449,.T.); #9468=ORIENTED_EDGE('',*,*,#6181,.T.); #9469=EDGE_LOOP('',(#9464,#9466,#9467,#9468)); #9470=FACE_OUTER_BOUND('',#9469,.F.); #9471=ADVANCED_FACE('',(#9470),#9462,.T.); #9472=CARTESIAN_POINT('',(2.204720076055E1,7.35E0,9.441108058217E0)); #9473=DIRECTION('',(0.E0,0.E0,1.E0)); #9474=DIRECTION('',(0.E0,-1.E0,0.E0)); #9475=AXIS2_PLACEMENT_3D('',#9472,#9473,#9474); #9476=CYLINDRICAL_SURFACE('',#9475,3.5E-1); #9478=ORIENTED_EDGE('',*,*,#9477,.F.); #9480=ORIENTED_EDGE('',*,*,#9479,.T.); #9481=ORIENTED_EDGE('',*,*,#9463,.T.); #9482=ORIENTED_EDGE('',*,*,#6179,.T.); #9483=EDGE_LOOP('',(#9478,#9480,#9481,#9482)); #9484=FACE_OUTER_BOUND('',#9483,.F.); #9485=ADVANCED_FACE('',(#9484),#9476,.F.); #9486=CARTESIAN_POINT('',(2.264203082158E1,7.E0,1.E1)); #9487=DIRECTION('',(0.E0,1.E0,0.E0)); #9488=DIRECTION('',(-1.E0,0.E0,0.E0)); #9489=AXIS2_PLACEMENT_3D('',#9486,#9487,#9488); #9490=PLANE('',#9489); #9491=ORIENTED_EDGE('',*,*,#9340,.T.); #9493=ORIENTED_EDGE('',*,*,#9492,.F.); #9494=ORIENTED_EDGE('',*,*,#9477,.T.); #9495=ORIENTED_EDGE('',*,*,#6177,.T.); #9496=EDGE_LOOP('',(#9491,#9493,#9494,#9495)); #9497=FACE_OUTER_BOUND('',#9496,.F.); #9498=ADVANCED_FACE('',(#9497),#9490,.T.); #9499=CARTESIAN_POINT('',(2.4E1,0.E0,9.5E0)); #9500=DIRECTION('',(0.E0,0.E0,-1.E0)); #9501=DIRECTION('',(-1.E0,0.E0,0.E0)); #9502=AXIS2_PLACEMENT_3D('',#9499,#9500,#9501); #9503=PLANE('',#9502); #9504=ORIENTED_EDGE('',*,*,#9492,.T.); #9505=ORIENTED_EDGE('',*,*,#9338,.F.); #9506=ORIENTED_EDGE('',*,*,#9355,.T.); #9507=ORIENTED_EDGE('',*,*,#9367,.F.); #9508=ORIENTED_EDGE('',*,*,#9383,.T.); #9509=ORIENTED_EDGE('',*,*,#9395,.F.); #9510=ORIENTED_EDGE('',*,*,#9411,.T.); #9511=ORIENTED_EDGE('',*,*,#9423,.F.); #9512=ORIENTED_EDGE('',*,*,#9437,.T.); #9513=ORIENTED_EDGE('',*,*,#9451,.F.); #9514=ORIENTED_EDGE('',*,*,#9465,.T.); #9515=ORIENTED_EDGE('',*,*,#9479,.F.); #9516=EDGE_LOOP('',(#9504,#9505,#9506,#9507,#9508,#9509,#9510,#9511,#9512,#9513, #9514,#9515)); #9517=FACE_OUTER_BOUND('',#9516,.F.); #9518=ADVANCED_FACE('',(#9517),#9503,.F.); #9519=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0)); #9520=DIRECTION('',(0.E0,0.E0,-1.E0)); #9521=DIRECTION('',(-1.E0,0.E0,0.E0)); #9522=AXIS2_PLACEMENT_3D('',#9519,#9520,#9521); #9523=CYLINDRICAL_SURFACE('',#9522,9.5E-2); #9524=ORIENTED_EDGE('',*,*,#6007,.F.); #9526=ORIENTED_EDGE('',*,*,#9525,.T.); #9528=ORIENTED_EDGE('',*,*,#9527,.T.); #9530=ORIENTED_EDGE('',*,*,#9529,.F.); #9531=EDGE_LOOP('',(#9524,#9526,#9528,#9530)); #9532=FACE_OUTER_BOUND('',#9531,.F.); #9533=ADVANCED_FACE('',(#9532),#9523,.F.); #9534=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.E0)); #9535=DIRECTION('',(0.E0,0.E0,-1.E0)); #9536=DIRECTION('',(-1.E0,0.E0,0.E0)); #9537=AXIS2_PLACEMENT_3D('',#9534,#9535,#9536); #9538=CYLINDRICAL_SURFACE('',#9537,9.5E-2); #9539=ORIENTED_EDGE('',*,*,#6009,.F.); #9540=ORIENTED_EDGE('',*,*,#9529,.T.); #9542=ORIENTED_EDGE('',*,*,#9541,.T.); #9543=ORIENTED_EDGE('',*,*,#9525,.F.); #9544=EDGE_LOOP('',(#9539,#9540,#9542,#9543)); #9545=FACE_OUTER_BOUND('',#9544,.F.); #9546=ADVANCED_FACE('',(#9545),#9538,.F.); #9547=CARTESIAN_POINT('',(2.01875E1,1.05E1,8.25E0)); #9548=DIRECTION('',(0.E0,0.E0,-1.E0)); #9549=DIRECTION('',(-1.E0,0.E0,0.E0)); #9550=AXIS2_PLACEMENT_3D('',#9547,#9548,#9549); #9551=PLANE('',#9550); #9552=ORIENTED_EDGE('',*,*,#9527,.F.); #9553=ORIENTED_EDGE('',*,*,#9541,.F.); #9554=EDGE_LOOP('',(#9552,#9553)); #9555=FACE_OUTER_BOUND('',#9554,.F.); #9556=ADVANCED_FACE('',(#9555),#9551,.T.); #9557=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0)); #9558=DIRECTION('',(0.E0,0.E0,-1.E0)); #9559=DIRECTION('',(-1.E0,0.E0,0.E0)); #9560=AXIS2_PLACEMENT_3D('',#9557,#9558,#9559); #9561=CYLINDRICAL_SURFACE('',#9560,9.5E-2); #9562=ORIENTED_EDGE('',*,*,#6013,.F.); #9564=ORIENTED_EDGE('',*,*,#9563,.T.); #9566=ORIENTED_EDGE('',*,*,#9565,.T.); #9568=ORIENTED_EDGE('',*,*,#9567,.F.); #9569=EDGE_LOOP('',(#9562,#9564,#9566,#9568)); #9570=FACE_OUTER_BOUND('',#9569,.F.); #9571=ADVANCED_FACE('',(#9570),#9561,.F.); #9572=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.E0)); #9573=DIRECTION('',(0.E0,0.E0,-1.E0)); #9574=DIRECTION('',(-1.E0,0.E0,0.E0)); #9575=AXIS2_PLACEMENT_3D('',#9572,#9573,#9574); #9576=CYLINDRICAL_SURFACE('',#9575,9.5E-2); #9577=ORIENTED_EDGE('',*,*,#6015,.F.); #9578=ORIENTED_EDGE('',*,*,#9567,.T.); #9580=ORIENTED_EDGE('',*,*,#9579,.T.); #9581=ORIENTED_EDGE('',*,*,#9563,.F.); #9582=EDGE_LOOP('',(#9577,#9578,#9580,#9581)); #9583=FACE_OUTER_BOUND('',#9582,.F.); #9584=ADVANCED_FACE('',(#9583),#9576,.F.); #9585=CARTESIAN_POINT('',(1.975E1,1.00625E1,8.25E0)); #9586=DIRECTION('',(0.E0,0.E0,-1.E0)); #9587=DIRECTION('',(-1.E0,0.E0,0.E0)); #9588=AXIS2_PLACEMENT_3D('',#9585,#9586,#9587); #9589=PLANE('',#9588); #9590=ORIENTED_EDGE('',*,*,#9565,.F.); #9591=ORIENTED_EDGE('',*,*,#9579,.F.); #9592=EDGE_LOOP('',(#9590,#9591)); #9593=FACE_OUTER_BOUND('',#9592,.F.); #9594=ADVANCED_FACE('',(#9593),#9589,.T.); #9595=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0)); #9596=DIRECTION('',(0.E0,0.E0,1.E0)); #9597=DIRECTION('',(1.E0,0.E0,0.E0)); #9598=AXIS2_PLACEMENT_3D('',#9595,#9596,#9597); #9599=CYLINDRICAL_SURFACE('',#9598,9.5E-2); #9600=ORIENTED_EDGE('',*,*,#6019,.T.); #9602=ORIENTED_EDGE('',*,*,#9601,.T.); #9604=ORIENTED_EDGE('',*,*,#9603,.F.); #9606=ORIENTED_EDGE('',*,*,#9605,.F.); #9607=EDGE_LOOP('',(#9600,#9602,#9604,#9606)); #9608=FACE_OUTER_BOUND('',#9607,.F.); #9609=ADVANCED_FACE('',(#9608),#9599,.F.); #9610=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.E0)); #9611=DIRECTION('',(0.E0,0.E0,1.E0)); #9612=DIRECTION('',(1.E0,0.E0,0.E0)); #9613=AXIS2_PLACEMENT_3D('',#9610,#9611,#9612); #9614=CYLINDRICAL_SURFACE('',#9613,9.5E-2); #9615=ORIENTED_EDGE('',*,*,#6021,.T.); #9616=ORIENTED_EDGE('',*,*,#9605,.T.); #9618=ORIENTED_EDGE('',*,*,#9617,.F.); #9619=ORIENTED_EDGE('',*,*,#9601,.F.); #9620=EDGE_LOOP('',(#9615,#9616,#9618,#9619)); #9621=FACE_OUTER_BOUND('',#9620,.F.); #9622=ADVANCED_FACE('',(#9621),#9614,.F.); #9623=CARTESIAN_POINT('',(4.25E0,1.00625E1,8.25E0)); #9624=DIRECTION('',(0.E0,0.E0,1.E0)); #9625=DIRECTION('',(1.E0,0.E0,0.E0)); #9626=AXIS2_PLACEMENT_3D('',#9623,#9624,#9625); #9627=PLANE('',#9626); #9628=ORIENTED_EDGE('',*,*,#9603,.T.); #9629=ORIENTED_EDGE('',*,*,#9617,.T.); #9630=EDGE_LOOP('',(#9628,#9629)); #9631=FACE_OUTER_BOUND('',#9630,.F.); #9632=ADVANCED_FACE('',(#9631),#9627,.F.); #9633=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0)); #9634=DIRECTION('',(0.E0,0.E0,1.E0)); #9635=DIRECTION('',(1.E0,0.E0,0.E0)); #9636=AXIS2_PLACEMENT_3D('',#9633,#9634,#9635); #9637=CYLINDRICAL_SURFACE('',#9636,9.5E-2); #9638=ORIENTED_EDGE('',*,*,#6025,.T.); #9640=ORIENTED_EDGE('',*,*,#9639,.T.); #9642=ORIENTED_EDGE('',*,*,#9641,.F.); #9644=ORIENTED_EDGE('',*,*,#9643,.F.); #9645=EDGE_LOOP('',(#9638,#9640,#9642,#9644)); #9646=FACE_OUTER_BOUND('',#9645,.F.); #9647=ADVANCED_FACE('',(#9646),#9637,.F.); #9648=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.E0)); #9649=DIRECTION('',(0.E0,0.E0,1.E0)); #9650=DIRECTION('',(1.E0,0.E0,0.E0)); #9651=AXIS2_PLACEMENT_3D('',#9648,#9649,#9650); #9652=CYLINDRICAL_SURFACE('',#9651,9.5E-2); #9653=ORIENTED_EDGE('',*,*,#6027,.T.); #9654=ORIENTED_EDGE('',*,*,#9643,.T.); #9656=ORIENTED_EDGE('',*,*,#9655,.F.); #9657=ORIENTED_EDGE('',*,*,#9639,.F.); #9658=EDGE_LOOP('',(#9653,#9654,#9656,#9657)); #9659=FACE_OUTER_BOUND('',#9658,.F.); #9660=ADVANCED_FACE('',(#9659),#9652,.F.); #9661=CARTESIAN_POINT('',(3.8125E0,1.05E1,8.25E0)); #9662=DIRECTION('',(0.E0,0.E0,1.E0)); #9663=DIRECTION('',(1.E0,0.E0,0.E0)); #9664=AXIS2_PLACEMENT_3D('',#9661,#9662,#9663); #9665=PLANE('',#9664); #9666=ORIENTED_EDGE('',*,*,#9641,.T.); #9667=ORIENTED_EDGE('',*,*,#9655,.T.); #9668=EDGE_LOOP('',(#9666,#9667)); #9669=FACE_OUTER_BOUND('',#9668,.F.); #9670=ADVANCED_FACE('',(#9669),#9665,.F.); #9671=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0)); #9672=DIRECTION('',(0.E0,0.E0,1.E0)); #9673=DIRECTION('',(1.E0,0.E0,0.E0)); #9674=AXIS2_PLACEMENT_3D('',#9671,#9672,#9673); #9675=CYLINDRICAL_SURFACE('',#9674,9.5E-2); #9676=ORIENTED_EDGE('',*,*,#6037,.T.); #9678=ORIENTED_EDGE('',*,*,#9677,.T.); #9680=ORIENTED_EDGE('',*,*,#9679,.F.); #9682=ORIENTED_EDGE('',*,*,#9681,.F.); #9683=EDGE_LOOP('',(#9676,#9678,#9680,#9682)); #9684=FACE_OUTER_BOUND('',#9683,.F.); #9685=ADVANCED_FACE('',(#9684),#9675,.F.); #9686=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.E0)); #9687=DIRECTION('',(0.E0,0.E0,1.E0)); #9688=DIRECTION('',(1.E0,0.E0,0.E0)); #9689=AXIS2_PLACEMENT_3D('',#9686,#9687,#9688); #9690=CYLINDRICAL_SURFACE('',#9689,9.5E-2); #9691=ORIENTED_EDGE('',*,*,#6039,.T.); #9692=ORIENTED_EDGE('',*,*,#9681,.T.); #9694=ORIENTED_EDGE('',*,*,#9693,.F.); #9695=ORIENTED_EDGE('',*,*,#9677,.F.); #9696=EDGE_LOOP('',(#9691,#9692,#9694,#9695)); #9697=FACE_OUTER_BOUND('',#9696,.F.); #9698=ADVANCED_FACE('',(#9697),#9690,.F.); #9699=CARTESIAN_POINT('',(4.25E0,1.09375E1,8.25E0)); #9700=DIRECTION('',(0.E0,0.E0,1.E0)); #9701=DIRECTION('',(1.E0,0.E0,0.E0)); #9702=AXIS2_PLACEMENT_3D('',#9699,#9700,#9701); #9703=PLANE('',#9702); #9704=ORIENTED_EDGE('',*,*,#9679,.T.); #9705=ORIENTED_EDGE('',*,*,#9693,.T.); #9706=EDGE_LOOP('',(#9704,#9705)); #9707=FACE_OUTER_BOUND('',#9706,.F.); #9708=ADVANCED_FACE('',(#9707),#9703,.F.); #9709=CARTESIAN_POINT('',(4.5E0,2.E0,8.E0)); #9710=DIRECTION('',(0.E0,-1.E0,0.E0)); #9711=DIRECTION('',(-1.E0,0.E0,0.E0)); #9712=AXIS2_PLACEMENT_3D('',#9709,#9710,#9711); #9713=PLANE('',#9712); #9715=ORIENTED_EDGE('',*,*,#9714,.T.); #9717=ORIENTED_EDGE('',*,*,#9716,.T.); #9719=ORIENTED_EDGE('',*,*,#9718,.F.); #9720=ORIENTED_EDGE('',*,*,#6043,.F.); #9721=EDGE_LOOP('',(#9715,#9717,#9719,#9720)); #9722=FACE_OUTER_BOUND('',#9721,.F.); #9723=ADVANCED_FACE('',(#9722),#9713,.F.); #9724=CARTESIAN_POINT('',(3.75E0,2.75E0,7.931076025772E0)); #9725=DIRECTION('',(0.E0,0.E0,1.E0)); #9726=DIRECTION('',(0.E0,-1.E0,0.E0)); #9727=AXIS2_PLACEMENT_3D('',#9724,#9725,#9726); #9728=CYLINDRICAL_SURFACE('',#9727,7.5E-1); #9729=ORIENTED_EDGE('',*,*,#9714,.F.); #9730=ORIENTED_EDGE('',*,*,#6057,.T.); #9732=ORIENTED_EDGE('',*,*,#9731,.T.); #9734=ORIENTED_EDGE('',*,*,#9733,.T.); #9735=EDGE_LOOP('',(#9729,#9730,#9732,#9734)); #9736=FACE_OUTER_BOUND('',#9735,.F.); #9737=ADVANCED_FACE('',(#9736),#9728,.F.); #9738=CARTESIAN_POINT('',(4.5E0,9.5E0,8.E0)); #9739=DIRECTION('',(1.E0,0.E0,0.E0)); #9740=DIRECTION('',(0.E0,-1.E0,0.E0)); #9741=AXIS2_PLACEMENT_3D('',#9738,#9739,#9740); #9742=PLANE('',#9741); #9743=ORIENTED_EDGE('',*,*,#9731,.F.); #9744=ORIENTED_EDGE('',*,*,#6055,.F.); #9746=ORIENTED_EDGE('',*,*,#9745,.T.); #9748=ORIENTED_EDGE('',*,*,#9747,.T.); #9749=EDGE_LOOP('',(#9743,#9744,#9746,#9748)); #9750=FACE_OUTER_BOUND('',#9749,.F.); #9751=ADVANCED_FACE('',(#9750),#9742,.F.); #9752=CARTESIAN_POINT('',(3.75E0,8.75E0,7.931076025772E0)); #9753=DIRECTION('',(0.E0,0.E0,1.E0)); #9754=DIRECTION('',(1.E0,0.E0,0.E0)); #9755=AXIS2_PLACEMENT_3D('',#9752,#9753,#9754); #9756=CYLINDRICAL_SURFACE('',#9755,7.5E-1); #9757=ORIENTED_EDGE('',*,*,#9745,.F.); #9758=ORIENTED_EDGE('',*,*,#6053,.T.); #9760=ORIENTED_EDGE('',*,*,#9759,.T.); #9762=ORIENTED_EDGE('',*,*,#9761,.T.); #9763=EDGE_LOOP('',(#9757,#9758,#9760,#9762)); #9764=FACE_OUTER_BOUND('',#9763,.F.); #9765=ADVANCED_FACE('',(#9764),#9756,.F.); #9766=CARTESIAN_POINT('',(2.746858067304E0,9.5E0,8.E0)); #9767=DIRECTION('',(0.E0,1.E0,0.E0)); #9768=DIRECTION('',(1.E0,0.E0,0.E0)); #9769=AXIS2_PLACEMENT_3D('',#9766,#9767,#9768); #9770=PLANE('',#9769); #9772=ORIENTED_EDGE('',*,*,#9771,.T.); #9774=ORIENTED_EDGE('',*,*,#9773,.T.); #9775=ORIENTED_EDGE('',*,*,#9759,.F.); #9776=ORIENTED_EDGE('',*,*,#6051,.F.); #9777=EDGE_LOOP('',(#9772,#9774,#9775,#9776)); #9778=FACE_OUTER_BOUND('',#9777,.F.); #9779=ADVANCED_FACE('',(#9778),#9770,.F.); #9780=CARTESIAN_POINT('',(3.188160579053E0,8.75E0,7.931076025772E0)); #9781=DIRECTION('',(0.E0,0.E0,1.E0)); #9782=DIRECTION('',(0.E0,1.E0,0.E0)); #9783=AXIS2_PLACEMENT_3D('',#9780,#9781,#9782); #9784=CYLINDRICAL_SURFACE('',#9783,7.5E-1); #9785=ORIENTED_EDGE('',*,*,#9771,.F.); #9786=ORIENTED_EDGE('',*,*,#6049,.T.); #9788=ORIENTED_EDGE('',*,*,#9787,.T.); #9790=ORIENTED_EDGE('',*,*,#9789,.T.); #9791=EDGE_LOOP('',(#9785,#9786,#9788,#9790)); #9792=FACE_OUTER_BOUND('',#9791,.F.); #9793=ADVANCED_FACE('',(#9792),#9784,.F.); #9794=CARTESIAN_POINT('',(-1.419808599362E0,2.E0,8.E0)); #9795=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #9796=DIRECTION('',(4.856429311786E-1,8.741572761215E-1,0.E0)); #9797=AXIS2_PLACEMENT_3D('',#9794,#9795,#9796); #9798=PLANE('',#9797); #9800=ORIENTED_EDGE('',*,*,#9799,.T.); #9802=ORIENTED_EDGE('',*,*,#9801,.T.); #9803=ORIENTED_EDGE('',*,*,#9787,.F.); #9804=ORIENTED_EDGE('',*,*,#6047,.F.); #9805=EDGE_LOOP('',(#9800,#9802,#9803,#9804)); #9806=FACE_OUTER_BOUND('',#9805,.F.); #9807=ADVANCED_FACE('',(#9806),#9798,.F.); #9808=CARTESIAN_POINT('',(-1.451727542799E-1,2.75E0,7.931076025772E0)); #9809=DIRECTION('',(0.E0,0.E0,1.E0)); #9810=DIRECTION('',(-8.741572761215E-1,4.856429311786E-1,0.E0)); #9811=AXIS2_PLACEMENT_3D('',#9808,#9809,#9810); #9812=CYLINDRICAL_SURFACE('',#9811,7.5E-1); #9813=ORIENTED_EDGE('',*,*,#9799,.F.); #9814=ORIENTED_EDGE('',*,*,#6045,.T.); #9815=ORIENTED_EDGE('',*,*,#9718,.T.); #9817=ORIENTED_EDGE('',*,*,#9816,.T.); #9818=EDGE_LOOP('',(#9813,#9814,#9815,#9817)); #9819=FACE_OUTER_BOUND('',#9818,.F.); #9820=ADVANCED_FACE('',(#9819),#9812,.F.); #9821=CARTESIAN_POINT('',(0.E0,0.E0,8.5E0)); #9822=DIRECTION('',(0.E0,0.E0,-1.E0)); #9823=DIRECTION('',(0.E0,-1.E0,0.E0)); #9824=AXIS2_PLACEMENT_3D('',#9821,#9822,#9823); #9825=PLANE('',#9824); #9826=ORIENTED_EDGE('',*,*,#9733,.F.); #9827=ORIENTED_EDGE('',*,*,#9747,.F.); #9828=ORIENTED_EDGE('',*,*,#9761,.F.); #9829=ORIENTED_EDGE('',*,*,#9773,.F.); #9830=ORIENTED_EDGE('',*,*,#9789,.F.); #9831=ORIENTED_EDGE('',*,*,#9801,.F.); #9832=ORIENTED_EDGE('',*,*,#9816,.F.); #9833=ORIENTED_EDGE('',*,*,#9716,.F.); #9834=EDGE_LOOP('',(#9826,#9827,#9828,#9829,#9830,#9831,#9832,#9833)); #9835=FACE_OUTER_BOUND('',#9834,.F.); #9836=ADVANCED_FACE('',(#9835),#9825,.T.); #9837=CARTESIAN_POINT('',(2.541980859936E1,2.E0,8.E0)); #9838=DIRECTION('',(-8.741572761215E-1,-4.856429311786E-1,0.E0)); #9839=DIRECTION('',(-4.856429311786E-1,8.741572761215E-1,0.E0)); #9840=AXIS2_PLACEMENT_3D('',#9837,#9838,#9839); #9841=PLANE('',#9840); #9843=ORIENTED_EDGE('',*,*,#9842,.T.); #9844=ORIENTED_EDGE('',*,*,#6061,.T.); #9846=ORIENTED_EDGE('',*,*,#9845,.F.); #9848=ORIENTED_EDGE('',*,*,#9847,.F.); #9849=EDGE_LOOP('',(#9843,#9844,#9846,#9848)); #9850=FACE_OUTER_BOUND('',#9849,.F.); #9851=ADVANCED_FACE('',(#9850),#9841,.T.); #9852=CARTESIAN_POINT('',(2.414517275428E1,2.75E0,8.558891941783E0)); #9853=DIRECTION('',(0.E0,0.E0,-1.E0)); #9854=DIRECTION('',(8.741572761215E-1,4.856429311786E-1,0.E0)); #9855=AXIS2_PLACEMENT_3D('',#9852,#9853,#9854); #9856=CYLINDRICAL_SURFACE('',#9855,7.5E-1); #9857=ORIENTED_EDGE('',*,*,#9842,.F.); #9859=ORIENTED_EDGE('',*,*,#9858,.T.); #9861=ORIENTED_EDGE('',*,*,#9860,.T.); #9862=ORIENTED_EDGE('',*,*,#6063,.T.); #9863=EDGE_LOOP('',(#9857,#9859,#9861,#9862)); #9864=FACE_OUTER_BOUND('',#9863,.F.); #9865=ADVANCED_FACE('',(#9864),#9856,.F.); #9866=CARTESIAN_POINT('',(2.4E1,0.E0,8.5E0)); #9867=DIRECTION('',(0.E0,0.E0,1.E0)); #9868=DIRECTION('',(0.E0,-1.E0,0.E0)); #9869=AXIS2_PLACEMENT_3D('',#9866,#9867,#9868); #9870=PLANE('',#9869); #9872=ORIENTED_EDGE('',*,*,#9871,.F.); #9874=ORIENTED_EDGE('',*,*,#9873,.T.); #9875=ORIENTED_EDGE('',*,*,#9858,.F.); #9876=ORIENTED_EDGE('',*,*,#9847,.T.); #9878=ORIENTED_EDGE('',*,*,#9877,.F.); #9880=ORIENTED_EDGE('',*,*,#9879,.T.); #9882=ORIENTED_EDGE('',*,*,#9881,.F.); #9884=ORIENTED_EDGE('',*,*,#9883,.T.); #9885=EDGE_LOOP('',(#9872,#9874,#9875,#9876,#9878,#9880,#9882,#9884)); #9886=FACE_OUTER_BOUND('',#9885,.F.); #9887=ADVANCED_FACE('',(#9886),#9870,.F.); #9888=CARTESIAN_POINT('',(2.025E1,2.75E0,8.558891941783E0)); #9889=DIRECTION('',(0.E0,0.E0,-1.E0)); #9890=DIRECTION('',(0.E0,-1.E0,0.E0)); #9891=AXIS2_PLACEMENT_3D('',#9888,#9889,#9890); #9892=CYLINDRICAL_SURFACE('',#9891,7.5E-1); #9894=ORIENTED_EDGE('',*,*,#9893,.F.); #9895=ORIENTED_EDGE('',*,*,#9871,.T.); #9897=ORIENTED_EDGE('',*,*,#9896,.T.); #9898=ORIENTED_EDGE('',*,*,#6067,.T.); #9899=EDGE_LOOP('',(#9894,#9895,#9897,#9898)); #9900=FACE_OUTER_BOUND('',#9899,.F.); #9901=ADVANCED_FACE('',(#9900),#9892,.F.); #9902=CARTESIAN_POINT('',(1.95E1,2.E0,8.E0)); #9903=DIRECTION('',(0.E0,1.E0,0.E0)); #9904=DIRECTION('',(1.E0,0.E0,0.E0)); #9905=AXIS2_PLACEMENT_3D('',#9902,#9903,#9904); #9906=PLANE('',#9905); #9907=ORIENTED_EDGE('',*,*,#9893,.T.); #9908=ORIENTED_EDGE('',*,*,#6065,.T.); #9909=ORIENTED_EDGE('',*,*,#9860,.F.); #9910=ORIENTED_EDGE('',*,*,#9873,.F.); #9911=EDGE_LOOP('',(#9907,#9908,#9909,#9910)); #9912=FACE_OUTER_BOUND('',#9911,.F.); #9913=ADVANCED_FACE('',(#9912),#9906,.T.); #9914=CARTESIAN_POINT('',(1.95E1,9.5E0,8.E0)); #9915=DIRECTION('',(1.E0,0.E0,0.E0)); #9916=DIRECTION('',(0.E0,-1.E0,0.E0)); #9917=AXIS2_PLACEMENT_3D('',#9914,#9915,#9916); #9918=PLANE('',#9917); #9919=ORIENTED_EDGE('',*,*,#9896,.F.); #9920=ORIENTED_EDGE('',*,*,#9883,.F.); #9922=ORIENTED_EDGE('',*,*,#9921,.T.); #9923=ORIENTED_EDGE('',*,*,#6069,.T.); #9924=EDGE_LOOP('',(#9919,#9920,#9922,#9923)); #9925=FACE_OUTER_BOUND('',#9924,.F.); #9926=ADVANCED_FACE('',(#9925),#9918,.T.); #9927=CARTESIAN_POINT('',(2.025E1,8.75E0,8.558891941783E0)); #9928=DIRECTION('',(0.E0,0.E0,-1.E0)); #9929=DIRECTION('',(-1.E0,0.E0,0.E0)); #9930=AXIS2_PLACEMENT_3D('',#9927,#9928,#9929); #9931=CYLINDRICAL_SURFACE('',#9930,7.5E-1); #9932=ORIENTED_EDGE('',*,*,#9921,.F.); #9933=ORIENTED_EDGE('',*,*,#9881,.T.); #9935=ORIENTED_EDGE('',*,*,#9934,.T.); #9936=ORIENTED_EDGE('',*,*,#6071,.T.); #9937=EDGE_LOOP('',(#9932,#9933,#9935,#9936)); #9938=FACE_OUTER_BOUND('',#9937,.F.); #9939=ADVANCED_FACE('',(#9938),#9931,.F.); #9940=CARTESIAN_POINT('',(2.125314193270E1,9.5E0,8.E0)); #9941=DIRECTION('',(0.E0,-1.E0,0.E0)); #9942=DIRECTION('',(-1.E0,0.E0,0.E0)); #9943=AXIS2_PLACEMENT_3D('',#9940,#9941,#9942); #9944=PLANE('',#9943); #9946=ORIENTED_EDGE('',*,*,#9945,.T.); #9947=ORIENTED_EDGE('',*,*,#6073,.T.); #9948=ORIENTED_EDGE('',*,*,#9934,.F.); #9949=ORIENTED_EDGE('',*,*,#9879,.F.); #9950=EDGE_LOOP('',(#9946,#9947,#9948,#9949)); #9951=FACE_OUTER_BOUND('',#9950,.F.); #9952=ADVANCED_FACE('',(#9951),#9944,.T.); #9953=CARTESIAN_POINT('',(2.081183942095E1,8.75E0,8.558891941783E0)); #9954=DIRECTION('',(0.E0,0.E0,-1.E0)); #9955=DIRECTION('',(0.E0,1.E0,0.E0)); #9956=AXIS2_PLACEMENT_3D('',#9953,#9954,#9955); #9957=CYLINDRICAL_SURFACE('',#9956,7.5E-1); #9958=ORIENTED_EDGE('',*,*,#9945,.F.); #9959=ORIENTED_EDGE('',*,*,#9877,.T.); #9960=ORIENTED_EDGE('',*,*,#9845,.T.); #9961=ORIENTED_EDGE('',*,*,#6075,.T.); #9962=EDGE_LOOP('',(#9958,#9959,#9960,#9961)); #9963=FACE_OUTER_BOUND('',#9962,.F.); #9964=ADVANCED_FACE('',(#9963),#9957,.F.); #9965=CARTESIAN_POINT('',(7.5E0,0.E0,6.875E-1)); #9966=DIRECTION('',(0.E0,0.E0,-1.E0)); #9967=DIRECTION('',(1.E0,0.E0,0.E0)); #9968=AXIS2_PLACEMENT_3D('',#9965,#9966,#9967); #9969=PLANE('',#9968); #9970=ORIENTED_EDGE('',*,*,#5726,.F.); #9972=ORIENTED_EDGE('',*,*,#9971,.T.); #9974=ORIENTED_EDGE('',*,*,#9973,.T.); #9976=ORIENTED_EDGE('',*,*,#9975,.F.); #9977=EDGE_LOOP('',(#9970,#9972,#9974,#9976)); #9978=FACE_OUTER_BOUND('',#9977,.F.); #9979=ADVANCED_FACE('',(#9978),#9969,.F.); #9980=CARTESIAN_POINT('',(7.5E0,0.E0,1.25E0)); #9981=DIRECTION('',(0.E0,-1.E0,0.E0)); #9982=DIRECTION('',(1.E0,0.E0,0.E0)); #9983=AXIS2_PLACEMENT_3D('',#9980,#9981,#9982); #9984=CYLINDRICAL_SURFACE('',#9983,5.625E-1); #9985=ORIENTED_EDGE('',*,*,#5732,.F.); #9987=ORIENTED_EDGE('',*,*,#9986,.T.); #9989=ORIENTED_EDGE('',*,*,#9988,.T.); #9990=ORIENTED_EDGE('',*,*,#9971,.F.); #9991=EDGE_LOOP('',(#9985,#9987,#9989,#9990)); #9992=FACE_OUTER_BOUND('',#9991,.F.); #9993=ADVANCED_FACE('',(#9992),#9984,.F.); #9994=CARTESIAN_POINT('',(1.05E1,0.E0,1.8125E0)); #9995=DIRECTION('',(0.E0,0.E0,1.E0)); #9996=DIRECTION('',(-1.E0,0.E0,0.E0)); #9997=AXIS2_PLACEMENT_3D('',#9994,#9995,#9996); #9998=PLANE('',#9997); #9999=ORIENTED_EDGE('',*,*,#5730,.F.); #10001=ORIENTED_EDGE('',*,*,#10000,.T.); #10003=ORIENTED_EDGE('',*,*,#10002,.T.); #10004=ORIENTED_EDGE('',*,*,#9986,.F.); #10005=EDGE_LOOP('',(#9999,#10001,#10003,#10004)); #10006=FACE_OUTER_BOUND('',#10005,.F.); #10007=ADVANCED_FACE('',(#10006),#9998,.F.); #10008=CARTESIAN_POINT('',(1.05E1,0.E0,1.25E0)); #10009=DIRECTION('',(0.E0,-1.E0,0.E0)); #10010=DIRECTION('',(1.E0,0.E0,0.E0)); #10011=AXIS2_PLACEMENT_3D('',#10008,#10009,#10010); #10012=CYLINDRICAL_SURFACE('',#10011,5.625E-1); #10013=ORIENTED_EDGE('',*,*,#5728,.F.); #10014=ORIENTED_EDGE('',*,*,#9975,.T.); #10016=ORIENTED_EDGE('',*,*,#10015,.T.); #10017=ORIENTED_EDGE('',*,*,#10000,.F.); #10018=EDGE_LOOP('',(#10013,#10014,#10016,#10017)); #10019=FACE_OUTER_BOUND('',#10018,.F.); #10020=ADVANCED_FACE('',(#10019),#10012,.F.); #10021=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0)); #10022=DIRECTION('',(0.E0,-1.E0,0.E0)); #10023=DIRECTION('',(1.E0,0.E0,0.E0)); #10024=AXIS2_PLACEMENT_3D('',#10021,#10022,#10023); #10025=PLANE('',#10024); #10026=ORIENTED_EDGE('',*,*,#9973,.F.); #10027=ORIENTED_EDGE('',*,*,#9988,.F.); #10028=ORIENTED_EDGE('',*,*,#10002,.F.); #10029=ORIENTED_EDGE('',*,*,#10015,.F.); #10030=EDGE_LOOP('',(#10026,#10027,#10028,#10029)); #10031=FACE_OUTER_BOUND('',#10030,.F.); #10032=ADVANCED_FACE('',(#10031),#10025,.T.); #10033=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0)); #10034=DIRECTION('',(0.E0,-1.E0,0.E0)); #10035=DIRECTION('',(1.E0,0.E0,0.E0)); #10036=AXIS2_PLACEMENT_3D('',#10033,#10034,#10035); #10037=PLANE('',#10036); #10039=ORIENTED_EDGE('',*,*,#10038,.F.); #10041=ORIENTED_EDGE('',*,*,#10040,.F.); #10043=ORIENTED_EDGE('',*,*,#10042,.F.); #10045=ORIENTED_EDGE('',*,*,#10044,.F.); #10047=ORIENTED_EDGE('',*,*,#10046,.F.); #10048=EDGE_LOOP('',(#10039,#10041,#10043,#10045,#10047)); #10049=FACE_OUTER_BOUND('',#10048,.F.); #10050=ADVANCED_FACE('',(#10049),#10037,.T.); #10051=CARTESIAN_POINT('',(1.455736763592E0,-6.892397422826E-2, 4.577195232320E0)); #10052=DIRECTION('',(0.E0,1.E0,0.E0)); #10053=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #10054=AXIS2_PLACEMENT_3D('',#10051,#10052,#10053); #10055=CYLINDRICAL_SURFACE('',#10054,7.5E-1); #10057=ORIENTED_EDGE('',*,*,#10056,.F.); #10058=ORIENTED_EDGE('',*,*,#5738,.T.); #10060=ORIENTED_EDGE('',*,*,#10059,.T.); #10061=ORIENTED_EDGE('',*,*,#10038,.T.); #10062=EDGE_LOOP('',(#10057,#10058,#10060,#10061)); #10063=FACE_OUTER_BOUND('',#10062,.F.); #10064=ADVANCED_FACE('',(#10063),#10055,.F.); #10065=CARTESIAN_POINT('',(6.875E-1,0.E0,4.284771824132E0)); #10066=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #10067=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #10068=AXIS2_PLACEMENT_3D('',#10065,#10066,#10067); #10069=PLANE('',#10068); #10070=ORIENTED_EDGE('',*,*,#10056,.T.); #10071=ORIENTED_EDGE('',*,*,#10046,.T.); #10073=ORIENTED_EDGE('',*,*,#10072,.F.); #10074=ORIENTED_EDGE('',*,*,#5740,.F.); #10075=EDGE_LOOP('',(#10070,#10071,#10073,#10074)); #10076=FACE_OUTER_BOUND('',#10075,.F.); #10077=ADVANCED_FACE('',(#10076),#10069,.F.); #10078=CARTESIAN_POINT('',(4.553039342392E0,0.E0,1.645354088550E0)); #10079=DIRECTION('',(0.E0,-1.E0,0.E0)); #10080=DIRECTION('',(1.E0,0.E0,0.E0)); #10081=AXIS2_PLACEMENT_3D('',#10078,#10079,#10080); #10082=CYLINDRICAL_SURFACE('',#10081,8.669989027347E-1); #10083=ORIENTED_EDGE('',*,*,#5742,.F.); #10084=ORIENTED_EDGE('',*,*,#10072,.T.); #10085=ORIENTED_EDGE('',*,*,#10044,.T.); #10087=ORIENTED_EDGE('',*,*,#10086,.F.); #10088=EDGE_LOOP('',(#10083,#10084,#10085,#10087)); #10089=FACE_OUTER_BOUND('',#10088,.F.); #10090=ADVANCED_FACE('',(#10089),#10082,.F.); #10091=CARTESIAN_POINT('',(7.5E0,0.E0,7.5E0)); #10092=DIRECTION('',(0.E0,-1.E0,0.E0)); #10093=DIRECTION('',(1.E0,0.E0,0.E0)); #10094=AXIS2_PLACEMENT_3D('',#10091,#10092,#10093); #10095=CYLINDRICAL_SURFACE('',#10094,5.6875E0); #10096=ORIENTED_EDGE('',*,*,#5744,.T.); #10097=ORIENTED_EDGE('',*,*,#10086,.T.); #10098=ORIENTED_EDGE('',*,*,#10042,.T.); #10100=ORIENTED_EDGE('',*,*,#10099,.F.); #10101=EDGE_LOOP('',(#10096,#10097,#10098,#10100)); #10102=FACE_OUTER_BOUND('',#10101,.F.); #10103=ADVANCED_FACE('',(#10102),#10095,.T.); #10104=CARTESIAN_POINT('',(1.61E0,0.E0,4.5E0)); #10105=DIRECTION('',(0.E0,-1.E0,0.E0)); #10106=DIRECTION('',(1.E0,0.E0,0.E0)); #10107=AXIS2_PLACEMENT_3D('',#10104,#10105,#10106); #10108=CYLINDRICAL_SURFACE('',#10107,9.225E-1); #10109=ORIENTED_EDGE('',*,*,#10059,.F.); #10110=ORIENTED_EDGE('',*,*,#5736,.F.); #10111=ORIENTED_EDGE('',*,*,#10099,.T.); #10112=ORIENTED_EDGE('',*,*,#10040,.T.); #10113=EDGE_LOOP('',(#10109,#10110,#10111,#10112)); #10114=FACE_OUTER_BOUND('',#10113,.F.); #10115=ADVANCED_FACE('',(#10114),#10108,.F.); #10116=CARTESIAN_POINT('',(-1.85E-1,7.463919417831E-1,7.815E0)); #10117=DIRECTION('',(0.E0,-1.E0,0.E0)); #10118=DIRECTION('',(1.E0,0.E0,0.E0)); #10119=AXIS2_PLACEMENT_3D('',#10116,#10117,#10118); #10120=CYLINDRICAL_SURFACE('',#10119,8.75E-1); #10122=ORIENTED_EDGE('',*,*,#10121,.T.); #10123=ORIENTED_EDGE('',*,*,#5748,.T.); #10125=ORIENTED_EDGE('',*,*,#10124,.F.); #10127=ORIENTED_EDGE('',*,*,#10126,.T.); #10128=EDGE_LOOP('',(#10122,#10123,#10125,#10127)); #10129=FACE_OUTER_BOUND('',#10128,.F.); #10130=ADVANCED_FACE('',(#10129),#10120,.T.); #10131=CARTESIAN_POINT('',(6.9E-1,0.E0,8.69E0)); #10132=DIRECTION('',(-1.E0,0.E0,0.E0)); #10133=DIRECTION('',(0.E0,0.E0,-1.E0)); #10134=AXIS2_PLACEMENT_3D('',#10131,#10132,#10133); #10135=PLANE('',#10134); #10136=ORIENTED_EDGE('',*,*,#10121,.F.); #10138=ORIENTED_EDGE('',*,*,#10137,.T.); #10140=ORIENTED_EDGE('',*,*,#10139,.F.); #10141=ORIENTED_EDGE('',*,*,#5750,.F.); #10142=EDGE_LOOP('',(#10136,#10138,#10140,#10141)); #10143=FACE_OUTER_BOUND('',#10142,.F.); #10144=ADVANCED_FACE('',(#10143),#10135,.F.); #10145=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0)); #10146=DIRECTION('',(0.E0,-1.E0,0.E0)); #10147=DIRECTION('',(1.E0,0.E0,0.E0)); #10148=AXIS2_PLACEMENT_3D('',#10145,#10146,#10147); #10149=PLANE('',#10148); #10151=ORIENTED_EDGE('',*,*,#10150,.F.); #10153=ORIENTED_EDGE('',*,*,#10152,.F.); #10155=ORIENTED_EDGE('',*,*,#10154,.F.); #10157=ORIENTED_EDGE('',*,*,#10156,.F.); #10158=ORIENTED_EDGE('',*,*,#10137,.F.); #10159=ORIENTED_EDGE('',*,*,#10126,.F.); #10161=ORIENTED_EDGE('',*,*,#10160,.F.); #10163=ORIENTED_EDGE('',*,*,#10162,.F.); #10165=ORIENTED_EDGE('',*,*,#10164,.F.); #10167=ORIENTED_EDGE('',*,*,#10166,.F.); #10169=ORIENTED_EDGE('',*,*,#10168,.F.); #10171=ORIENTED_EDGE('',*,*,#10170,.F.); #10173=ORIENTED_EDGE('',*,*,#10172,.F.); #10175=ORIENTED_EDGE('',*,*,#10174,.F.); #10176=EDGE_LOOP('',(#10151,#10153,#10155,#10157,#10158,#10159,#10161,#10163, #10165,#10167,#10169,#10171,#10173,#10175)); #10177=FACE_OUTER_BOUND('',#10176,.F.); #10178=ADVANCED_FACE('',(#10177),#10149,.T.); #10179=CARTESIAN_POINT('',(1.8125E0,0.E0,8.69E0)); #10180=DIRECTION('',(0.E0,0.E0,-1.E0)); #10181=DIRECTION('',(1.E0,0.E0,0.E0)); #10182=AXIS2_PLACEMENT_3D('',#10179,#10180,#10181); #10183=PLANE('',#10182); #10185=ORIENTED_EDGE('',*,*,#10184,.F.); #10186=ORIENTED_EDGE('',*,*,#10150,.T.); #10188=ORIENTED_EDGE('',*,*,#10187,.F.); #10189=ORIENTED_EDGE('',*,*,#5758,.F.); #10190=EDGE_LOOP('',(#10185,#10186,#10188,#10189)); #10191=FACE_OUTER_BOUND('',#10190,.F.); #10192=ADVANCED_FACE('',(#10191),#10183,.F.); #10193=CARTESIAN_POINT('',(2.6875E0,7.463919417831E-1,7.815E0)); #10194=DIRECTION('',(0.E0,-1.E0,0.E0)); #10195=DIRECTION('',(0.E0,0.E0,1.E0)); #10196=AXIS2_PLACEMENT_3D('',#10193,#10194,#10195); #10197=CYLINDRICAL_SURFACE('',#10196,8.75E-1); #10198=ORIENTED_EDGE('',*,*,#10184,.T.); #10199=ORIENTED_EDGE('',*,*,#5756,.T.); #10201=ORIENTED_EDGE('',*,*,#10200,.F.); #10202=ORIENTED_EDGE('',*,*,#10152,.T.); #10203=EDGE_LOOP('',(#10198,#10199,#10201,#10202)); #10204=FACE_OUTER_BOUND('',#10203,.F.); #10205=ADVANCED_FACE('',(#10204),#10197,.T.); #10206=CARTESIAN_POINT('',(1.8125E0,0.E0,7.5E0)); #10207=DIRECTION('',(1.E0,0.E0,0.E0)); #10208=DIRECTION('',(0.E0,0.E0,1.E0)); #10209=AXIS2_PLACEMENT_3D('',#10206,#10207,#10208); #10210=PLANE('',#10209); #10211=ORIENTED_EDGE('',*,*,#10200,.T.); #10212=ORIENTED_EDGE('',*,*,#5754,.F.); #10214=ORIENTED_EDGE('',*,*,#10213,.T.); #10215=ORIENTED_EDGE('',*,*,#10154,.T.); #10216=EDGE_LOOP('',(#10211,#10212,#10214,#10215)); #10217=FACE_OUTER_BOUND('',#10216,.F.); #10218=ADVANCED_FACE('',(#10217),#10210,.F.); #10219=CARTESIAN_POINT('',(1.25125E0,0.E0,7.5E0)); #10220=DIRECTION('',(0.E0,-1.E0,0.E0)); #10221=DIRECTION('',(1.E0,0.E0,0.E0)); #10222=AXIS2_PLACEMENT_3D('',#10219,#10220,#10221); #10223=CYLINDRICAL_SURFACE('',#10222,5.6125E-1); #10224=ORIENTED_EDGE('',*,*,#5752,.F.); #10225=ORIENTED_EDGE('',*,*,#10139,.T.); #10226=ORIENTED_EDGE('',*,*,#10156,.T.); #10227=ORIENTED_EDGE('',*,*,#10213,.F.); #10228=EDGE_LOOP('',(#10224,#10225,#10226,#10227)); #10229=FACE_OUTER_BOUND('',#10228,.F.); #10230=ADVANCED_FACE('',(#10229),#10223,.F.); #10231=CARTESIAN_POINT('',(3.4375E0,-6.892397422826E-2,9.565E0)); #10232=DIRECTION('',(0.E0,1.E0,0.E0)); #10233=DIRECTION('',(1.E0,0.E0,0.E0)); #10234=AXIS2_PLACEMENT_3D('',#10231,#10232,#10233); #10235=CYLINDRICAL_SURFACE('',#10234,8.75E-1); #10237=ORIENTED_EDGE('',*,*,#10236,.F.); #10238=ORIENTED_EDGE('',*,*,#5760,.T.); #10239=ORIENTED_EDGE('',*,*,#10187,.T.); #10240=ORIENTED_EDGE('',*,*,#10174,.T.); #10241=EDGE_LOOP('',(#10237,#10238,#10239,#10240)); #10242=FACE_OUTER_BOUND('',#10241,.F.); #10243=ADVANCED_FACE('',(#10242),#10235,.F.); #10244=CARTESIAN_POINT('',(4.3125E0,0.E0,8.69E0)); #10245=DIRECTION('',(1.E0,0.E0,0.E0)); #10246=DIRECTION('',(0.E0,0.E0,1.E0)); #10247=AXIS2_PLACEMENT_3D('',#10244,#10245,#10246); #10248=PLANE('',#10247); #10249=ORIENTED_EDGE('',*,*,#10236,.T.); #10250=ORIENTED_EDGE('',*,*,#10172,.T.); #10252=ORIENTED_EDGE('',*,*,#10251,.F.); #10253=ORIENTED_EDGE('',*,*,#5762,.F.); #10254=EDGE_LOOP('',(#10249,#10250,#10252,#10253)); #10255=FACE_OUTER_BOUND('',#10254,.F.); #10256=ADVANCED_FACE('',(#10255),#10248,.F.); #10257=CARTESIAN_POINT('',(3.4375E0,-6.892397422826E-2,1.0375E1)); #10258=DIRECTION('',(0.E0,1.E0,0.E0)); #10259=DIRECTION('',(0.E0,0.E0,1.E0)); #10260=AXIS2_PLACEMENT_3D('',#10257,#10258,#10259); #10261=CYLINDRICAL_SURFACE('',#10260,8.75E-1); #10263=ORIENTED_EDGE('',*,*,#10262,.F.); #10264=ORIENTED_EDGE('',*,*,#5764,.T.); #10265=ORIENTED_EDGE('',*,*,#10251,.T.); #10266=ORIENTED_EDGE('',*,*,#10170,.T.); #10267=EDGE_LOOP('',(#10263,#10264,#10265,#10266)); #10268=FACE_OUTER_BOUND('',#10267,.F.); #10269=ADVANCED_FACE('',(#10268),#10261,.F.); #10270=CARTESIAN_POINT('',(4.3125E0,0.E0,1.125E1)); #10271=DIRECTION('',(0.E0,0.E0,1.E0)); #10272=DIRECTION('',(-1.E0,0.E0,0.E0)); #10273=AXIS2_PLACEMENT_3D('',#10270,#10271,#10272); #10274=PLANE('',#10273); #10276=ORIENTED_EDGE('',*,*,#10275,.F.); #10277=ORIENTED_EDGE('',*,*,#5766,.F.); #10278=ORIENTED_EDGE('',*,*,#10262,.T.); #10279=ORIENTED_EDGE('',*,*,#10168,.T.); #10280=EDGE_LOOP('',(#10276,#10277,#10278,#10279)); #10281=FACE_OUTER_BOUND('',#10280,.F.); #10282=ADVANCED_FACE('',(#10281),#10274,.F.); #10283=CARTESIAN_POINT('',(-4.375E-1,-6.892397422826E-2,1.0375E1)); #10284=DIRECTION('',(0.E0,1.E0,0.E0)); #10285=DIRECTION('',(-1.E0,0.E0,0.E0)); #10286=AXIS2_PLACEMENT_3D('',#10283,#10284,#10285); #10287=CYLINDRICAL_SURFACE('',#10286,8.75E-1); #10289=ORIENTED_EDGE('',*,*,#10288,.F.); #10290=ORIENTED_EDGE('',*,*,#5768,.T.); #10291=ORIENTED_EDGE('',*,*,#10275,.T.); #10292=ORIENTED_EDGE('',*,*,#10166,.T.); #10293=EDGE_LOOP('',(#10289,#10290,#10291,#10292)); #10294=FACE_OUTER_BOUND('',#10293,.F.); #10295=ADVANCED_FACE('',(#10294),#10287,.F.); #10296=CARTESIAN_POINT('',(-1.3125E0,0.E0,1.125E1)); #10297=DIRECTION('',(-1.E0,0.E0,0.E0)); #10298=DIRECTION('',(0.E0,0.E0,-1.E0)); #10299=AXIS2_PLACEMENT_3D('',#10296,#10297,#10298); #10300=PLANE('',#10299); #10301=ORIENTED_EDGE('',*,*,#10288,.T.); #10302=ORIENTED_EDGE('',*,*,#10164,.T.); #10304=ORIENTED_EDGE('',*,*,#10303,.F.); #10305=ORIENTED_EDGE('',*,*,#5770,.F.); #10306=EDGE_LOOP('',(#10301,#10302,#10304,#10305)); #10307=FACE_OUTER_BOUND('',#10306,.F.); #10308=ADVANCED_FACE('',(#10307),#10300,.F.); #10309=CARTESIAN_POINT('',(-4.375E-1,-6.892397422826E-2,9.565E0)); #10310=DIRECTION('',(0.E0,1.E0,0.E0)); #10311=DIRECTION('',(0.E0,0.E0,-1.E0)); #10312=AXIS2_PLACEMENT_3D('',#10309,#10310,#10311); #10313=CYLINDRICAL_SURFACE('',#10312,8.75E-1); #10315=ORIENTED_EDGE('',*,*,#10314,.F.); #10316=ORIENTED_EDGE('',*,*,#5772,.T.); #10317=ORIENTED_EDGE('',*,*,#10303,.T.); #10318=ORIENTED_EDGE('',*,*,#10162,.T.); #10319=EDGE_LOOP('',(#10315,#10316,#10317,#10318)); #10320=FACE_OUTER_BOUND('',#10319,.F.); #10321=ADVANCED_FACE('',(#10320),#10313,.F.); #10322=CARTESIAN_POINT('',(-1.3125E0,0.E0,8.69E0)); #10323=DIRECTION('',(0.E0,0.E0,-1.E0)); #10324=DIRECTION('',(1.E0,0.E0,0.E0)); #10325=AXIS2_PLACEMENT_3D('',#10322,#10323,#10324); #10326=PLANE('',#10325); #10327=ORIENTED_EDGE('',*,*,#10124,.T.); #10328=ORIENTED_EDGE('',*,*,#5774,.F.); #10329=ORIENTED_EDGE('',*,*,#10314,.T.); #10330=ORIENTED_EDGE('',*,*,#10160,.T.); #10331=EDGE_LOOP('',(#10327,#10328,#10329,#10330)); #10332=FACE_OUTER_BOUND('',#10331,.F.); #10333=ADVANCED_FACE('',(#10332),#10326,.F.); #10334=CARTESIAN_POINT('',(6.875E-1,0.E0,1.65E1)); #10335=DIRECTION('',(-1.E0,0.E0,0.E0)); #10336=DIRECTION('',(0.E0,0.E0,-1.E0)); #10337=AXIS2_PLACEMENT_3D('',#10334,#10335,#10336); #10338=PLANE('',#10337); #10339=ORIENTED_EDGE('',*,*,#5778,.F.); #10341=ORIENTED_EDGE('',*,*,#10340,.T.); #10343=ORIENTED_EDGE('',*,*,#10342,.T.); #10345=ORIENTED_EDGE('',*,*,#10344,.F.); #10346=EDGE_LOOP('',(#10339,#10341,#10343,#10345)); #10347=FACE_OUTER_BOUND('',#10346,.F.); #10348=ADVANCED_FACE('',(#10347),#10338,.F.); #10349=CARTESIAN_POINT('',(1.25E0,0.E0,1.65E1)); #10350=DIRECTION('',(0.E0,-1.E0,0.E0)); #10351=DIRECTION('',(1.E0,0.E0,0.E0)); #10352=AXIS2_PLACEMENT_3D('',#10349,#10350,#10351); #10353=CYLINDRICAL_SURFACE('',#10352,5.625E-1); #10354=ORIENTED_EDGE('',*,*,#5784,.F.); #10356=ORIENTED_EDGE('',*,*,#10355,.T.); #10358=ORIENTED_EDGE('',*,*,#10357,.T.); #10359=ORIENTED_EDGE('',*,*,#10340,.F.); #10360=EDGE_LOOP('',(#10354,#10356,#10358,#10359)); #10361=FACE_OUTER_BOUND('',#10360,.F.); #10362=ADVANCED_FACE('',(#10361),#10353,.F.); #10363=CARTESIAN_POINT('',(1.8125E0,0.E0,1.35E1)); #10364=DIRECTION('',(1.E0,0.E0,0.E0)); #10365=DIRECTION('',(0.E0,0.E0,1.E0)); #10366=AXIS2_PLACEMENT_3D('',#10363,#10364,#10365); #10367=PLANE('',#10366); #10368=ORIENTED_EDGE('',*,*,#5782,.F.); #10370=ORIENTED_EDGE('',*,*,#10369,.T.); #10372=ORIENTED_EDGE('',*,*,#10371,.T.); #10373=ORIENTED_EDGE('',*,*,#10355,.F.); #10374=EDGE_LOOP('',(#10368,#10370,#10372,#10373)); #10375=FACE_OUTER_BOUND('',#10374,.F.); #10376=ADVANCED_FACE('',(#10375),#10367,.F.); #10377=CARTESIAN_POINT('',(1.25E0,0.E0,1.35E1)); #10378=DIRECTION('',(0.E0,-1.E0,0.E0)); #10379=DIRECTION('',(1.E0,0.E0,0.E0)); #10380=AXIS2_PLACEMENT_3D('',#10377,#10378,#10379); #10381=CYLINDRICAL_SURFACE('',#10380,5.625E-1); #10382=ORIENTED_EDGE('',*,*,#5780,.F.); #10383=ORIENTED_EDGE('',*,*,#10344,.T.); #10385=ORIENTED_EDGE('',*,*,#10384,.T.); #10386=ORIENTED_EDGE('',*,*,#10369,.F.); #10387=EDGE_LOOP('',(#10382,#10383,#10385,#10386)); #10388=FACE_OUTER_BOUND('',#10387,.F.); #10389=ADVANCED_FACE('',(#10388),#10381,.F.); #10390=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0)); #10391=DIRECTION('',(0.E0,-1.E0,0.E0)); #10392=DIRECTION('',(1.E0,0.E0,0.E0)); #10393=AXIS2_PLACEMENT_3D('',#10390,#10391,#10392); #10394=PLANE('',#10393); #10395=ORIENTED_EDGE('',*,*,#10342,.F.); #10396=ORIENTED_EDGE('',*,*,#10357,.F.); #10397=ORIENTED_EDGE('',*,*,#10371,.F.); #10398=ORIENTED_EDGE('',*,*,#10384,.F.); #10399=EDGE_LOOP('',(#10395,#10396,#10397,#10398)); #10400=FACE_OUTER_BOUND('',#10399,.F.); #10401=ADVANCED_FACE('',(#10400),#10394,.T.); #10402=CARTESIAN_POINT('',(6.875E-1,0.E0,2.25E1)); #10403=DIRECTION('',(-1.E0,0.E0,0.E0)); #10404=DIRECTION('',(0.E0,0.E0,-1.E0)); #10405=AXIS2_PLACEMENT_3D('',#10402,#10403,#10404); #10406=PLANE('',#10405); #10407=ORIENTED_EDGE('',*,*,#5788,.F.); #10409=ORIENTED_EDGE('',*,*,#10408,.T.); #10411=ORIENTED_EDGE('',*,*,#10410,.T.); #10413=ORIENTED_EDGE('',*,*,#10412,.F.); #10414=EDGE_LOOP('',(#10407,#10409,#10411,#10413)); #10415=FACE_OUTER_BOUND('',#10414,.F.); #10416=ADVANCED_FACE('',(#10415),#10406,.F.); #10417=CARTESIAN_POINT('',(1.25E0,0.E0,2.25E1)); #10418=DIRECTION('',(0.E0,-1.E0,0.E0)); #10419=DIRECTION('',(1.E0,0.E0,0.E0)); #10420=AXIS2_PLACEMENT_3D('',#10417,#10418,#10419); #10421=CYLINDRICAL_SURFACE('',#10420,5.625E-1); #10422=ORIENTED_EDGE('',*,*,#5794,.F.); #10424=ORIENTED_EDGE('',*,*,#10423,.T.); #10426=ORIENTED_EDGE('',*,*,#10425,.T.); #10427=ORIENTED_EDGE('',*,*,#10408,.F.); #10428=EDGE_LOOP('',(#10422,#10424,#10426,#10427)); #10429=FACE_OUTER_BOUND('',#10428,.F.); #10430=ADVANCED_FACE('',(#10429),#10421,.F.); #10431=CARTESIAN_POINT('',(1.8125E0,0.E0,1.95E1)); #10432=DIRECTION('',(1.E0,0.E0,0.E0)); #10433=DIRECTION('',(0.E0,0.E0,1.E0)); #10434=AXIS2_PLACEMENT_3D('',#10431,#10432,#10433); #10435=PLANE('',#10434); #10436=ORIENTED_EDGE('',*,*,#5792,.F.); #10438=ORIENTED_EDGE('',*,*,#10437,.T.); #10440=ORIENTED_EDGE('',*,*,#10439,.T.); #10441=ORIENTED_EDGE('',*,*,#10423,.F.); #10442=EDGE_LOOP('',(#10436,#10438,#10440,#10441)); #10443=FACE_OUTER_BOUND('',#10442,.F.); #10444=ADVANCED_FACE('',(#10443),#10435,.F.); #10445=CARTESIAN_POINT('',(1.25E0,0.E0,1.95E1)); #10446=DIRECTION('',(0.E0,-1.E0,0.E0)); #10447=DIRECTION('',(1.E0,0.E0,0.E0)); #10448=AXIS2_PLACEMENT_3D('',#10445,#10446,#10447); #10449=CYLINDRICAL_SURFACE('',#10448,5.625E-1); #10450=ORIENTED_EDGE('',*,*,#5790,.F.); #10451=ORIENTED_EDGE('',*,*,#10412,.T.); #10453=ORIENTED_EDGE('',*,*,#10452,.T.); #10454=ORIENTED_EDGE('',*,*,#10437,.F.); #10455=EDGE_LOOP('',(#10450,#10451,#10453,#10454)); #10456=FACE_OUTER_BOUND('',#10455,.F.); #10457=ADVANCED_FACE('',(#10456),#10449,.F.); #10458=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0)); #10459=DIRECTION('',(0.E0,-1.E0,0.E0)); #10460=DIRECTION('',(1.E0,0.E0,0.E0)); #10461=AXIS2_PLACEMENT_3D('',#10458,#10459,#10460); #10462=PLANE('',#10461); #10463=ORIENTED_EDGE('',*,*,#10410,.F.); #10464=ORIENTED_EDGE('',*,*,#10425,.F.); #10465=ORIENTED_EDGE('',*,*,#10439,.F.); #10466=ORIENTED_EDGE('',*,*,#10452,.F.); #10467=EDGE_LOOP('',(#10463,#10464,#10465,#10466)); #10468=FACE_OUTER_BOUND('',#10467,.F.); #10469=ADVANCED_FACE('',(#10468),#10462,.T.); #10470=CARTESIAN_POINT('',(7.5E0,0.E0,8.5E0)); #10471=DIRECTION('',(0.E0,0.E0,-1.E0)); #10472=DIRECTION('',(1.E0,0.E0,0.E0)); #10473=AXIS2_PLACEMENT_3D('',#10470,#10471,#10472); #10474=PLANE('',#10473); #10475=ORIENTED_EDGE('',*,*,#5798,.F.); #10477=ORIENTED_EDGE('',*,*,#10476,.T.); #10479=ORIENTED_EDGE('',*,*,#10478,.T.); #10481=ORIENTED_EDGE('',*,*,#10480,.F.); #10482=EDGE_LOOP('',(#10475,#10477,#10479,#10481)); #10483=FACE_OUTER_BOUND('',#10482,.F.); #10484=ADVANCED_FACE('',(#10483),#10474,.F.); #10485=CARTESIAN_POINT('',(7.5E0,0.E0,9.E0)); #10486=DIRECTION('',(0.E0,-1.E0,0.E0)); #10487=DIRECTION('',(1.E0,0.E0,0.E0)); #10488=AXIS2_PLACEMENT_3D('',#10485,#10486,#10487); #10489=CYLINDRICAL_SURFACE('',#10488,5.E-1); #10490=ORIENTED_EDGE('',*,*,#5804,.F.); #10492=ORIENTED_EDGE('',*,*,#10491,.T.); #10494=ORIENTED_EDGE('',*,*,#10493,.T.); #10495=ORIENTED_EDGE('',*,*,#10476,.F.); #10496=EDGE_LOOP('',(#10490,#10492,#10494,#10495)); #10497=FACE_OUTER_BOUND('',#10496,.F.); #10498=ADVANCED_FACE('',(#10497),#10489,.F.); #10499=CARTESIAN_POINT('',(1.05E1,0.E0,9.5E0)); #10500=DIRECTION('',(0.E0,0.E0,1.E0)); #10501=DIRECTION('',(-1.E0,0.E0,0.E0)); #10502=AXIS2_PLACEMENT_3D('',#10499,#10500,#10501); #10503=PLANE('',#10502); #10504=ORIENTED_EDGE('',*,*,#5802,.F.); #10506=ORIENTED_EDGE('',*,*,#10505,.T.); #10508=ORIENTED_EDGE('',*,*,#10507,.T.); #10509=ORIENTED_EDGE('',*,*,#10491,.F.); #10510=EDGE_LOOP('',(#10504,#10506,#10508,#10509)); #10511=FACE_OUTER_BOUND('',#10510,.F.); #10512=ADVANCED_FACE('',(#10511),#10503,.F.); #10513=CARTESIAN_POINT('',(1.05E1,0.E0,9.E0)); #10514=DIRECTION('',(0.E0,-1.E0,0.E0)); #10515=DIRECTION('',(1.E0,0.E0,0.E0)); #10516=AXIS2_PLACEMENT_3D('',#10513,#10514,#10515); #10517=CYLINDRICAL_SURFACE('',#10516,5.E-1); #10518=ORIENTED_EDGE('',*,*,#5800,.F.); #10519=ORIENTED_EDGE('',*,*,#10480,.T.); #10521=ORIENTED_EDGE('',*,*,#10520,.T.); #10522=ORIENTED_EDGE('',*,*,#10505,.F.); #10523=EDGE_LOOP('',(#10518,#10519,#10521,#10522)); #10524=FACE_OUTER_BOUND('',#10523,.F.); #10525=ADVANCED_FACE('',(#10524),#10517,.F.); #10526=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0)); #10527=DIRECTION('',(0.E0,-1.E0,0.E0)); #10528=DIRECTION('',(1.E0,0.E0,0.E0)); #10529=AXIS2_PLACEMENT_3D('',#10526,#10527,#10528); #10530=PLANE('',#10529); #10531=ORIENTED_EDGE('',*,*,#10478,.F.); #10532=ORIENTED_EDGE('',*,*,#10493,.F.); #10533=ORIENTED_EDGE('',*,*,#10507,.F.); #10534=ORIENTED_EDGE('',*,*,#10520,.F.); #10535=EDGE_LOOP('',(#10531,#10532,#10533,#10534)); #10536=FACE_OUTER_BOUND('',#10535,.F.); #10537=ADVANCED_FACE('',(#10536),#10530,.T.); #10538=CARTESIAN_POINT('',(7.5E0,0.E0,1.75625E1)); #10539=DIRECTION('',(0.E0,0.E0,-1.E0)); #10540=DIRECTION('',(1.E0,0.E0,0.E0)); #10541=AXIS2_PLACEMENT_3D('',#10538,#10539,#10540); #10542=PLANE('',#10541); #10543=ORIENTED_EDGE('',*,*,#5808,.F.); #10545=ORIENTED_EDGE('',*,*,#10544,.T.); #10547=ORIENTED_EDGE('',*,*,#10546,.T.); #10549=ORIENTED_EDGE('',*,*,#10548,.F.); #10550=EDGE_LOOP('',(#10543,#10545,#10547,#10549)); #10551=FACE_OUTER_BOUND('',#10550,.F.); #10552=ADVANCED_FACE('',(#10551),#10542,.F.); #10553=CARTESIAN_POINT('',(7.5E0,0.E0,1.8E1)); #10554=DIRECTION('',(0.E0,-1.E0,0.E0)); #10555=DIRECTION('',(1.E0,0.E0,0.E0)); #10556=AXIS2_PLACEMENT_3D('',#10553,#10554,#10555); #10557=CYLINDRICAL_SURFACE('',#10556,4.375E-1); #10558=ORIENTED_EDGE('',*,*,#5814,.F.); #10560=ORIENTED_EDGE('',*,*,#10559,.T.); #10562=ORIENTED_EDGE('',*,*,#10561,.T.); #10563=ORIENTED_EDGE('',*,*,#10544,.F.); #10564=EDGE_LOOP('',(#10558,#10560,#10562,#10563)); #10565=FACE_OUTER_BOUND('',#10564,.F.); #10566=ADVANCED_FACE('',(#10565),#10557,.F.); #10567=CARTESIAN_POINT('',(1.05E1,0.E0,1.84375E1)); #10568=DIRECTION('',(0.E0,0.E0,1.E0)); #10569=DIRECTION('',(-1.E0,0.E0,0.E0)); #10570=AXIS2_PLACEMENT_3D('',#10567,#10568,#10569); #10571=PLANE('',#10570); #10572=ORIENTED_EDGE('',*,*,#5812,.F.); #10574=ORIENTED_EDGE('',*,*,#10573,.T.); #10576=ORIENTED_EDGE('',*,*,#10575,.T.); #10577=ORIENTED_EDGE('',*,*,#10559,.F.); #10578=EDGE_LOOP('',(#10572,#10574,#10576,#10577)); #10579=FACE_OUTER_BOUND('',#10578,.F.); #10580=ADVANCED_FACE('',(#10579),#10571,.F.); #10581=CARTESIAN_POINT('',(1.05E1,0.E0,1.8E1)); #10582=DIRECTION('',(0.E0,-1.E0,0.E0)); #10583=DIRECTION('',(1.E0,0.E0,0.E0)); #10584=AXIS2_PLACEMENT_3D('',#10581,#10582,#10583); #10585=CYLINDRICAL_SURFACE('',#10584,4.375E-1); #10586=ORIENTED_EDGE('',*,*,#5810,.F.); #10587=ORIENTED_EDGE('',*,*,#10548,.T.); #10589=ORIENTED_EDGE('',*,*,#10588,.T.); #10590=ORIENTED_EDGE('',*,*,#10573,.F.); #10591=EDGE_LOOP('',(#10586,#10587,#10589,#10590)); #10592=FACE_OUTER_BOUND('',#10591,.F.); #10593=ADVANCED_FACE('',(#10592),#10585,.F.); #10594=CARTESIAN_POINT('',(0.E0,6.875E-1,0.E0)); #10595=DIRECTION('',(0.E0,-1.E0,0.E0)); #10596=DIRECTION('',(1.E0,0.E0,0.E0)); #10597=AXIS2_PLACEMENT_3D('',#10594,#10595,#10596); #10598=PLANE('',#10597); #10599=ORIENTED_EDGE('',*,*,#10546,.F.); #10600=ORIENTED_EDGE('',*,*,#10561,.F.); #10601=ORIENTED_EDGE('',*,*,#10575,.F.); #10602=ORIENTED_EDGE('',*,*,#10588,.F.); #10603=EDGE_LOOP('',(#10599,#10600,#10601,#10602)); #10604=FACE_OUTER_BOUND('',#10603,.F.); #10605=ADVANCED_FACE('',(#10604),#10598,.T.); #10606=CARTESIAN_POINT('',(7.5E0,0.E0,3.13125E1)); #10607=DIRECTION('',(0.E0,0.E0,-1.E0)); #10608=DIRECTION('',(1.E0,0.E0,0.E0)); #10609=AXIS2_PLACEMENT_3D('',#10606,#10607,#10608); #10610=PLANE('',#10609); #10611=ORIENTED_EDGE('',*,*,#5818,.T.); #10613=ORIENTED_EDGE('',*,*,#10612,.T.); #10615=ORIENTED_EDGE('',*,*,#10614,.F.); #10617=ORIENTED_EDGE('',*,*,#10616,.F.); #10618=EDGE_LOOP('',(#10611,#10613,#10615,#10617)); #10619=FACE_OUTER_BOUND('',#10618,.F.); #10620=ADVANCED_FACE('',(#10619),#10610,.T.); #10621=CARTESIAN_POINT('',(1.05E1,0.E0,3.075E1)); #10622=DIRECTION('',(0.E0,1.E0,0.E0)); #10623=DIRECTION('',(1.E0,0.E0,0.E0)); #10624=AXIS2_PLACEMENT_3D('',#10621,#10622,#10623); #10625=CYLINDRICAL_SURFACE('',#10624,5.625E-1); #10626=ORIENTED_EDGE('',*,*,#5824,.T.); #10628=ORIENTED_EDGE('',*,*,#10627,.T.); #10630=ORIENTED_EDGE('',*,*,#10629,.F.); #10631=ORIENTED_EDGE('',*,*,#10612,.F.); #10632=EDGE_LOOP('',(#10626,#10628,#10630,#10631)); #10633=FACE_OUTER_BOUND('',#10632,.F.); #10634=ADVANCED_FACE('',(#10633),#10625,.F.); #10635=CARTESIAN_POINT('',(1.05E1,0.E0,3.01875E1)); #10636=DIRECTION('',(0.E0,0.E0,1.E0)); #10637=DIRECTION('',(-1.E0,0.E0,0.E0)); #10638=AXIS2_PLACEMENT_3D('',#10635,#10636,#10637); #10639=PLANE('',#10638); #10640=ORIENTED_EDGE('',*,*,#5822,.T.); #10642=ORIENTED_EDGE('',*,*,#10641,.T.); #10644=ORIENTED_EDGE('',*,*,#10643,.F.); #10645=ORIENTED_EDGE('',*,*,#10627,.F.); #10646=EDGE_LOOP('',(#10640,#10642,#10644,#10645)); #10647=FACE_OUTER_BOUND('',#10646,.F.); #10648=ADVANCED_FACE('',(#10647),#10639,.T.); #10649=CARTESIAN_POINT('',(7.5E0,0.E0,3.075E1)); #10650=DIRECTION('',(0.E0,1.E0,0.E0)); #10651=DIRECTION('',(1.E0,0.E0,0.E0)); #10652=AXIS2_PLACEMENT_3D('',#10649,#10650,#10651); #10653=CYLINDRICAL_SURFACE('',#10652,5.625E-1); #10654=ORIENTED_EDGE('',*,*,#5820,.T.); #10655=ORIENTED_EDGE('',*,*,#10616,.T.); #10657=ORIENTED_EDGE('',*,*,#10656,.F.); #10658=ORIENTED_EDGE('',*,*,#10641,.F.); #10659=EDGE_LOOP('',(#10654,#10655,#10657,#10658)); #10660=FACE_OUTER_BOUND('',#10659,.F.); #10661=ADVANCED_FACE('',(#10660),#10653,.F.); #10662=CARTESIAN_POINT('',(0.E0,6.875E-1,3.2E1)); #10663=DIRECTION('',(0.E0,1.E0,0.E0)); #10664=DIRECTION('',(1.E0,0.E0,0.E0)); #10665=AXIS2_PLACEMENT_3D('',#10662,#10663,#10664); #10666=PLANE('',#10665); #10667=ORIENTED_EDGE('',*,*,#10614,.T.); #10668=ORIENTED_EDGE('',*,*,#10629,.T.); #10669=ORIENTED_EDGE('',*,*,#10643,.T.); #10670=ORIENTED_EDGE('',*,*,#10656,.T.); #10671=EDGE_LOOP('',(#10667,#10668,#10669,#10670)); #10672=FACE_OUTER_BOUND('',#10671,.F.); #10673=ADVANCED_FACE('',(#10672),#10666,.F.); #10674=CARTESIAN_POINT('',(0.E0,6.875E-1,3.2E1)); #10675=DIRECTION('',(0.E0,1.E0,0.E0)); #10676=DIRECTION('',(1.E0,0.E0,0.E0)); #10677=AXIS2_PLACEMENT_3D('',#10674,#10675,#10676); #10678=PLANE('',#10677); #10680=ORIENTED_EDGE('',*,*,#10679,.F.); #10682=ORIENTED_EDGE('',*,*,#10681,.T.); #10684=ORIENTED_EDGE('',*,*,#10683,.T.); #10686=ORIENTED_EDGE('',*,*,#10685,.T.); #10688=ORIENTED_EDGE('',*,*,#10687,.T.); #10689=EDGE_LOOP('',(#10680,#10682,#10684,#10686,#10688)); #10690=FACE_OUTER_BOUND('',#10689,.F.); #10691=ADVANCED_FACE('',(#10690),#10678,.F.); #10692=CARTESIAN_POINT('',(1.455736763592E0,-6.642389448824E-2, 2.742280476768E1)); #10693=DIRECTION('',(0.E0,1.E0,0.E0)); #10694=DIRECTION('',(-8.942796313519E-1,0.E0,-4.475085931567E-1)); #10695=AXIS2_PLACEMENT_3D('',#10692,#10693,#10694); #10696=CYLINDRICAL_SURFACE('',#10695,7.5E-1); #10698=ORIENTED_EDGE('',*,*,#10697,.F.); #10699=ORIENTED_EDGE('',*,*,#5932,.T.); #10701=ORIENTED_EDGE('',*,*,#10700,.T.); #10702=ORIENTED_EDGE('',*,*,#10679,.T.); #10703=EDGE_LOOP('',(#10698,#10699,#10701,#10702)); #10704=FACE_OUTER_BOUND('',#10703,.F.); #10705=ADVANCED_FACE('',(#10704),#10696,.F.); #10706=CARTESIAN_POINT('',(1.61E0,0.E0,2.75E1)); #10707=DIRECTION('',(0.E0,1.E0,0.E0)); #10708=DIRECTION('',(1.E0,0.E0,0.E0)); #10709=AXIS2_PLACEMENT_3D('',#10706,#10707,#10708); #10710=CYLINDRICAL_SURFACE('',#10709,9.225E-1); #10711=ORIENTED_EDGE('',*,*,#10697,.T.); #10712=ORIENTED_EDGE('',*,*,#10687,.F.); #10714=ORIENTED_EDGE('',*,*,#10713,.F.); #10715=ORIENTED_EDGE('',*,*,#5934,.T.); #10716=EDGE_LOOP('',(#10711,#10712,#10714,#10715)); #10717=FACE_OUTER_BOUND('',#10716,.F.); #10718=ADVANCED_FACE('',(#10717),#10710,.F.); #10719=CARTESIAN_POINT('',(7.5E0,0.E0,2.45E1)); #10720=DIRECTION('',(0.E0,1.E0,0.E0)); #10721=DIRECTION('',(1.E0,0.E0,0.E0)); #10722=AXIS2_PLACEMENT_3D('',#10719,#10720,#10721); #10723=CYLINDRICAL_SURFACE('',#10722,5.6875E0); #10724=ORIENTED_EDGE('',*,*,#5936,.F.); #10725=ORIENTED_EDGE('',*,*,#10713,.T.); #10726=ORIENTED_EDGE('',*,*,#10685,.F.); #10728=ORIENTED_EDGE('',*,*,#10727,.F.); #10729=EDGE_LOOP('',(#10724,#10725,#10726,#10728)); #10730=FACE_OUTER_BOUND('',#10729,.F.); #10731=ADVANCED_FACE('',(#10730),#10723,.T.); #10732=CARTESIAN_POINT('',(4.553039342392E0,0.E0,3.035464591145E1)); #10733=DIRECTION('',(0.E0,1.E0,0.E0)); #10734=DIRECTION('',(1.E0,0.E0,0.E0)); #10735=AXIS2_PLACEMENT_3D('',#10732,#10733,#10734); #10736=CYLINDRICAL_SURFACE('',#10735,8.669989027347E-1); #10737=ORIENTED_EDGE('',*,*,#5938,.T.); #10738=ORIENTED_EDGE('',*,*,#10727,.T.); #10739=ORIENTED_EDGE('',*,*,#10683,.F.); #10741=ORIENTED_EDGE('',*,*,#10740,.F.); #10742=EDGE_LOOP('',(#10737,#10738,#10739,#10741)); #10743=FACE_OUTER_BOUND('',#10742,.F.); #10744=ADVANCED_FACE('',(#10743),#10736,.F.); #10745=CARTESIAN_POINT('',(6.875E-1,0.E0,2.771522817587E1)); #10746=DIRECTION('',(7.071067811865E-1,0.E0,-7.071067811865E-1)); #10747=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #10748=AXIS2_PLACEMENT_3D('',#10745,#10746,#10747); #10749=PLANE('',#10748); #10750=ORIENTED_EDGE('',*,*,#10700,.F.); #10751=ORIENTED_EDGE('',*,*,#5930,.T.); #10752=ORIENTED_EDGE('',*,*,#10740,.T.); #10753=ORIENTED_EDGE('',*,*,#10681,.F.); #10754=EDGE_LOOP('',(#10750,#10751,#10752,#10753)); #10755=FACE_OUTER_BOUND('',#10754,.F.); #10756=ADVANCED_FACE('',(#10755),#10749,.T.); #10757=CARTESIAN_POINT('',(1.65E1,0.E0,6.875E-1)); #10758=DIRECTION('',(0.E0,0.E0,1.E0)); #10759=DIRECTION('',(-1.E0,0.E0,0.E0)); #10760=AXIS2_PLACEMENT_3D('',#10757,#10758,#10759); #10761=PLANE('',#10760); #10762=ORIENTED_EDGE('',*,*,#5828,.T.); #10764=ORIENTED_EDGE('',*,*,#10763,.T.); #10766=ORIENTED_EDGE('',*,*,#10765,.F.); #10768=ORIENTED_EDGE('',*,*,#10767,.F.); #10769=EDGE_LOOP('',(#10762,#10764,#10766,#10768)); #10770=FACE_OUTER_BOUND('',#10769,.F.); #10771=ADVANCED_FACE('',(#10770),#10761,.T.); #10772=CARTESIAN_POINT('',(1.35E1,0.E0,1.25E0)); #10773=DIRECTION('',(0.E0,1.E0,0.E0)); #10774=DIRECTION('',(-1.E0,0.E0,0.E0)); #10775=AXIS2_PLACEMENT_3D('',#10772,#10773,#10774); #10776=CYLINDRICAL_SURFACE('',#10775,5.625E-1); #10777=ORIENTED_EDGE('',*,*,#5834,.T.); #10779=ORIENTED_EDGE('',*,*,#10778,.T.); #10781=ORIENTED_EDGE('',*,*,#10780,.F.); #10782=ORIENTED_EDGE('',*,*,#10763,.F.); #10783=EDGE_LOOP('',(#10777,#10779,#10781,#10782)); #10784=FACE_OUTER_BOUND('',#10783,.F.); #10785=ADVANCED_FACE('',(#10784),#10776,.F.); #10786=CARTESIAN_POINT('',(1.35E1,0.E0,1.8125E0)); #10787=DIRECTION('',(0.E0,0.E0,-1.E0)); #10788=DIRECTION('',(1.E0,0.E0,0.E0)); #10789=AXIS2_PLACEMENT_3D('',#10786,#10787,#10788); #10790=PLANE('',#10789); #10791=ORIENTED_EDGE('',*,*,#5832,.T.); #10793=ORIENTED_EDGE('',*,*,#10792,.T.); #10795=ORIENTED_EDGE('',*,*,#10794,.F.); #10796=ORIENTED_EDGE('',*,*,#10778,.F.); #10797=EDGE_LOOP('',(#10791,#10793,#10795,#10796)); #10798=FACE_OUTER_BOUND('',#10797,.F.); #10799=ADVANCED_FACE('',(#10798),#10790,.T.); #10800=CARTESIAN_POINT('',(1.65E1,0.E0,1.25E0)); #10801=DIRECTION('',(0.E0,1.E0,0.E0)); #10802=DIRECTION('',(-1.E0,0.E0,0.E0)); #10803=AXIS2_PLACEMENT_3D('',#10800,#10801,#10802); #10804=CYLINDRICAL_SURFACE('',#10803,5.625E-1); #10805=ORIENTED_EDGE('',*,*,#5830,.T.); #10806=ORIENTED_EDGE('',*,*,#10767,.T.); #10808=ORIENTED_EDGE('',*,*,#10807,.F.); #10809=ORIENTED_EDGE('',*,*,#10792,.F.); #10810=EDGE_LOOP('',(#10805,#10806,#10808,#10809)); #10811=FACE_OUTER_BOUND('',#10810,.F.); #10812=ADVANCED_FACE('',(#10811),#10804,.F.); #10813=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0)); #10814=DIRECTION('',(0.E0,1.E0,0.E0)); #10815=DIRECTION('',(-1.E0,0.E0,0.E0)); #10816=AXIS2_PLACEMENT_3D('',#10813,#10814,#10815); #10817=PLANE('',#10816); #10818=ORIENTED_EDGE('',*,*,#10765,.T.); #10819=ORIENTED_EDGE('',*,*,#10780,.T.); #10820=ORIENTED_EDGE('',*,*,#10794,.T.); #10821=ORIENTED_EDGE('',*,*,#10807,.T.); #10822=EDGE_LOOP('',(#10818,#10819,#10820,#10821)); #10823=FACE_OUTER_BOUND('',#10822,.F.); #10824=ADVANCED_FACE('',(#10823),#10817,.F.); #10825=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0)); #10826=DIRECTION('',(0.E0,1.E0,0.E0)); #10827=DIRECTION('',(-1.E0,0.E0,0.E0)); #10828=AXIS2_PLACEMENT_3D('',#10825,#10826,#10827); #10829=PLANE('',#10828); #10831=ORIENTED_EDGE('',*,*,#10830,.F.); #10833=ORIENTED_EDGE('',*,*,#10832,.T.); #10835=ORIENTED_EDGE('',*,*,#10834,.T.); #10837=ORIENTED_EDGE('',*,*,#10836,.T.); #10839=ORIENTED_EDGE('',*,*,#10838,.T.); #10840=EDGE_LOOP('',(#10831,#10833,#10835,#10837,#10839)); #10841=FACE_OUTER_BOUND('',#10840,.F.); #10842=ADVANCED_FACE('',(#10841),#10829,.F.); #10843=CARTESIAN_POINT('',(2.254426323641E1,-6.642389448824E-2, 4.577195232320E0)); #10844=DIRECTION('',(0.E0,1.E0,0.E0)); #10845=DIRECTION('',(8.942796313519E-1,0.E0,4.475085931567E-1)); #10846=AXIS2_PLACEMENT_3D('',#10843,#10844,#10845); #10847=CYLINDRICAL_SURFACE('',#10846,7.5E-1); #10849=ORIENTED_EDGE('',*,*,#10848,.F.); #10850=ORIENTED_EDGE('',*,*,#5920,.T.); #10852=ORIENTED_EDGE('',*,*,#10851,.T.); #10853=ORIENTED_EDGE('',*,*,#10830,.T.); #10854=EDGE_LOOP('',(#10849,#10850,#10852,#10853)); #10855=FACE_OUTER_BOUND('',#10854,.F.); #10856=ADVANCED_FACE('',(#10855),#10847,.F.); #10857=CARTESIAN_POINT('',(2.239E1,0.E0,4.5E0)); #10858=DIRECTION('',(0.E0,1.E0,0.E0)); #10859=DIRECTION('',(-1.E0,0.E0,0.E0)); #10860=AXIS2_PLACEMENT_3D('',#10857,#10858,#10859); #10861=CYLINDRICAL_SURFACE('',#10860,9.225E-1); #10862=ORIENTED_EDGE('',*,*,#10848,.T.); #10863=ORIENTED_EDGE('',*,*,#10838,.F.); #10865=ORIENTED_EDGE('',*,*,#10864,.F.); #10866=ORIENTED_EDGE('',*,*,#5922,.T.); #10867=EDGE_LOOP('',(#10862,#10863,#10865,#10866)); #10868=FACE_OUTER_BOUND('',#10867,.F.); #10869=ADVANCED_FACE('',(#10868),#10861,.F.); #10870=CARTESIAN_POINT('',(1.65E1,0.E0,7.5E0)); #10871=DIRECTION('',(0.E0,1.E0,0.E0)); #10872=DIRECTION('',(-1.E0,0.E0,0.E0)); #10873=AXIS2_PLACEMENT_3D('',#10870,#10871,#10872); #10874=CYLINDRICAL_SURFACE('',#10873,5.6875E0); #10875=ORIENTED_EDGE('',*,*,#5924,.F.); #10876=ORIENTED_EDGE('',*,*,#10864,.T.); #10877=ORIENTED_EDGE('',*,*,#10836,.F.); #10879=ORIENTED_EDGE('',*,*,#10878,.F.); #10880=EDGE_LOOP('',(#10875,#10876,#10877,#10879)); #10881=FACE_OUTER_BOUND('',#10880,.F.); #10882=ADVANCED_FACE('',(#10881),#10874,.T.); #10883=CARTESIAN_POINT('',(1.944696065761E1,0.E0,1.645354088550E0)); #10884=DIRECTION('',(0.E0,1.E0,0.E0)); #10885=DIRECTION('',(-1.E0,0.E0,0.E0)); #10886=AXIS2_PLACEMENT_3D('',#10883,#10884,#10885); #10887=CYLINDRICAL_SURFACE('',#10886,8.669989027347E-1); #10888=ORIENTED_EDGE('',*,*,#5926,.T.); #10889=ORIENTED_EDGE('',*,*,#10878,.T.); #10890=ORIENTED_EDGE('',*,*,#10834,.F.); #10892=ORIENTED_EDGE('',*,*,#10891,.F.); #10893=EDGE_LOOP('',(#10888,#10889,#10890,#10892)); #10894=FACE_OUTER_BOUND('',#10893,.F.); #10895=ADVANCED_FACE('',(#10894),#10887,.F.); #10896=CARTESIAN_POINT('',(2.33125E1,0.E0,4.284771824132E0)); #10897=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #10898=DIRECTION('',(-7.071067811865E-1,0.E0,-7.071067811865E-1)); #10899=AXIS2_PLACEMENT_3D('',#10896,#10897,#10898); #10900=PLANE('',#10899); #10901=ORIENTED_EDGE('',*,*,#10851,.F.); #10902=ORIENTED_EDGE('',*,*,#5918,.T.); #10903=ORIENTED_EDGE('',*,*,#10891,.T.); #10904=ORIENTED_EDGE('',*,*,#10832,.F.); #10905=EDGE_LOOP('',(#10901,#10902,#10903,#10904)); #10906=FACE_OUTER_BOUND('',#10905,.F.); #10907=ADVANCED_FACE('',(#10906),#10900,.T.); #10908=CARTESIAN_POINT('',(2.33125E1,0.E0,1.65E1)); #10909=DIRECTION('',(-1.E0,0.E0,0.E0)); #10910=DIRECTION('',(0.E0,0.E0,-1.E0)); #10911=AXIS2_PLACEMENT_3D('',#10908,#10909,#10910); #10912=PLANE('',#10911); #10913=ORIENTED_EDGE('',*,*,#5838,.T.); #10915=ORIENTED_EDGE('',*,*,#10914,.T.); #10917=ORIENTED_EDGE('',*,*,#10916,.F.); #10919=ORIENTED_EDGE('',*,*,#10918,.F.); #10920=EDGE_LOOP('',(#10913,#10915,#10917,#10919)); #10921=FACE_OUTER_BOUND('',#10920,.F.); #10922=ADVANCED_FACE('',(#10921),#10912,.T.); #10923=CARTESIAN_POINT('',(2.275E1,0.E0,1.35E1)); #10924=DIRECTION('',(0.E0,1.E0,0.E0)); #10925=DIRECTION('',(-1.E0,0.E0,0.E0)); #10926=AXIS2_PLACEMENT_3D('',#10923,#10924,#10925); #10927=CYLINDRICAL_SURFACE('',#10926,5.625E-1); #10928=ORIENTED_EDGE('',*,*,#5844,.T.); #10930=ORIENTED_EDGE('',*,*,#10929,.T.); #10932=ORIENTED_EDGE('',*,*,#10931,.F.); #10933=ORIENTED_EDGE('',*,*,#10914,.F.); #10934=EDGE_LOOP('',(#10928,#10930,#10932,#10933)); #10935=FACE_OUTER_BOUND('',#10934,.F.); #10936=ADVANCED_FACE('',(#10935),#10927,.F.); #10937=CARTESIAN_POINT('',(2.21875E1,0.E0,1.35E1)); #10938=DIRECTION('',(1.E0,0.E0,0.E0)); #10939=DIRECTION('',(0.E0,0.E0,1.E0)); #10940=AXIS2_PLACEMENT_3D('',#10937,#10938,#10939); #10941=PLANE('',#10940); #10942=ORIENTED_EDGE('',*,*,#5842,.T.); #10944=ORIENTED_EDGE('',*,*,#10943,.T.); #10946=ORIENTED_EDGE('',*,*,#10945,.F.); #10947=ORIENTED_EDGE('',*,*,#10929,.F.); #10948=EDGE_LOOP('',(#10942,#10944,#10946,#10947)); #10949=FACE_OUTER_BOUND('',#10948,.F.); #10950=ADVANCED_FACE('',(#10949),#10941,.T.); #10951=CARTESIAN_POINT('',(2.275E1,0.E0,1.65E1)); #10952=DIRECTION('',(0.E0,1.E0,0.E0)); #10953=DIRECTION('',(-1.E0,0.E0,0.E0)); #10954=AXIS2_PLACEMENT_3D('',#10951,#10952,#10953); #10955=CYLINDRICAL_SURFACE('',#10954,5.625E-1); #10956=ORIENTED_EDGE('',*,*,#5840,.T.); #10957=ORIENTED_EDGE('',*,*,#10918,.T.); #10959=ORIENTED_EDGE('',*,*,#10958,.F.); #10960=ORIENTED_EDGE('',*,*,#10943,.F.); #10961=EDGE_LOOP('',(#10956,#10957,#10959,#10960)); #10962=FACE_OUTER_BOUND('',#10961,.F.); #10963=ADVANCED_FACE('',(#10962),#10955,.F.); #10964=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0)); #10965=DIRECTION('',(0.E0,1.E0,0.E0)); #10966=DIRECTION('',(-1.E0,0.E0,0.E0)); #10967=AXIS2_PLACEMENT_3D('',#10964,#10965,#10966); #10968=PLANE('',#10967); #10969=ORIENTED_EDGE('',*,*,#10916,.T.); #10970=ORIENTED_EDGE('',*,*,#10931,.T.); #10971=ORIENTED_EDGE('',*,*,#10945,.T.); #10972=ORIENTED_EDGE('',*,*,#10958,.T.); #10973=EDGE_LOOP('',(#10969,#10970,#10971,#10972)); #10974=FACE_OUTER_BOUND('',#10973,.F.); #10975=ADVANCED_FACE('',(#10974),#10968,.F.); #10976=CARTESIAN_POINT('',(2.33125E1,0.E0,2.25E1)); #10977=DIRECTION('',(-1.E0,0.E0,0.E0)); #10978=DIRECTION('',(0.E0,0.E0,-1.E0)); #10979=AXIS2_PLACEMENT_3D('',#10976,#10977,#10978); #10980=PLANE('',#10979); #10981=ORIENTED_EDGE('',*,*,#5848,.T.); #10983=ORIENTED_EDGE('',*,*,#10982,.T.); #10985=ORIENTED_EDGE('',*,*,#10984,.F.); #10987=ORIENTED_EDGE('',*,*,#10986,.F.); #10988=EDGE_LOOP('',(#10981,#10983,#10985,#10987)); #10989=FACE_OUTER_BOUND('',#10988,.F.); #10990=ADVANCED_FACE('',(#10989),#10980,.T.); #10991=CARTESIAN_POINT('',(2.275E1,0.E0,1.95E1)); #10992=DIRECTION('',(0.E0,1.E0,0.E0)); #10993=DIRECTION('',(-1.E0,0.E0,0.E0)); #10994=AXIS2_PLACEMENT_3D('',#10991,#10992,#10993); #10995=CYLINDRICAL_SURFACE('',#10994,5.625E-1); #10996=ORIENTED_EDGE('',*,*,#5854,.T.); #10998=ORIENTED_EDGE('',*,*,#10997,.T.); #11000=ORIENTED_EDGE('',*,*,#10999,.F.); #11001=ORIENTED_EDGE('',*,*,#10982,.F.); #11002=EDGE_LOOP('',(#10996,#10998,#11000,#11001)); #11003=FACE_OUTER_BOUND('',#11002,.F.); #11004=ADVANCED_FACE('',(#11003),#10995,.F.); #11005=CARTESIAN_POINT('',(2.21875E1,0.E0,1.95E1)); #11006=DIRECTION('',(1.E0,0.E0,0.E0)); #11007=DIRECTION('',(0.E0,0.E0,1.E0)); #11008=AXIS2_PLACEMENT_3D('',#11005,#11006,#11007); #11009=PLANE('',#11008); #11010=ORIENTED_EDGE('',*,*,#5852,.T.); #11012=ORIENTED_EDGE('',*,*,#11011,.T.); #11014=ORIENTED_EDGE('',*,*,#11013,.F.); #11015=ORIENTED_EDGE('',*,*,#10997,.F.); #11016=EDGE_LOOP('',(#11010,#11012,#11014,#11015)); #11017=FACE_OUTER_BOUND('',#11016,.F.); #11018=ADVANCED_FACE('',(#11017),#11009,.T.); #11019=CARTESIAN_POINT('',(2.275E1,0.E0,2.25E1)); #11020=DIRECTION('',(0.E0,1.E0,0.E0)); #11021=DIRECTION('',(-1.E0,0.E0,0.E0)); #11022=AXIS2_PLACEMENT_3D('',#11019,#11020,#11021); #11023=CYLINDRICAL_SURFACE('',#11022,5.625E-1); #11024=ORIENTED_EDGE('',*,*,#5850,.T.); #11025=ORIENTED_EDGE('',*,*,#10986,.T.); #11027=ORIENTED_EDGE('',*,*,#11026,.F.); #11028=ORIENTED_EDGE('',*,*,#11011,.F.); #11029=EDGE_LOOP('',(#11024,#11025,#11027,#11028)); #11030=FACE_OUTER_BOUND('',#11029,.F.); #11031=ADVANCED_FACE('',(#11030),#11023,.F.); #11032=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0)); #11033=DIRECTION('',(0.E0,1.E0,0.E0)); #11034=DIRECTION('',(-1.E0,0.E0,0.E0)); #11035=AXIS2_PLACEMENT_3D('',#11032,#11033,#11034); #11036=PLANE('',#11035); #11037=ORIENTED_EDGE('',*,*,#10984,.T.); #11038=ORIENTED_EDGE('',*,*,#10999,.T.); #11039=ORIENTED_EDGE('',*,*,#11013,.T.); #11040=ORIENTED_EDGE('',*,*,#11026,.T.); #11041=EDGE_LOOP('',(#11037,#11038,#11039,#11040)); #11042=FACE_OUTER_BOUND('',#11041,.F.); #11043=ADVANCED_FACE('',(#11042),#11036,.F.); #11044=CARTESIAN_POINT('',(1.65E1,0.E0,8.5E0)); #11045=DIRECTION('',(0.E0,0.E0,1.E0)); #11046=DIRECTION('',(-1.E0,0.E0,0.E0)); #11047=AXIS2_PLACEMENT_3D('',#11044,#11045,#11046); #11048=PLANE('',#11047); #11049=ORIENTED_EDGE('',*,*,#5858,.T.); #11051=ORIENTED_EDGE('',*,*,#11050,.T.); #11053=ORIENTED_EDGE('',*,*,#11052,.F.); #11055=ORIENTED_EDGE('',*,*,#11054,.F.); #11056=EDGE_LOOP('',(#11049,#11051,#11053,#11055)); #11057=FACE_OUTER_BOUND('',#11056,.F.); #11058=ADVANCED_FACE('',(#11057),#11048,.T.); #11059=CARTESIAN_POINT('',(1.35E1,0.E0,9.E0)); #11060=DIRECTION('',(0.E0,1.E0,0.E0)); #11061=DIRECTION('',(-1.E0,0.E0,0.E0)); #11062=AXIS2_PLACEMENT_3D('',#11059,#11060,#11061); #11063=CYLINDRICAL_SURFACE('',#11062,5.E-1); #11064=ORIENTED_EDGE('',*,*,#5864,.T.); #11066=ORIENTED_EDGE('',*,*,#11065,.T.); #11068=ORIENTED_EDGE('',*,*,#11067,.F.); #11069=ORIENTED_EDGE('',*,*,#11050,.F.); #11070=EDGE_LOOP('',(#11064,#11066,#11068,#11069)); #11071=FACE_OUTER_BOUND('',#11070,.F.); #11072=ADVANCED_FACE('',(#11071),#11063,.F.); #11073=CARTESIAN_POINT('',(1.35E1,0.E0,9.5E0)); #11074=DIRECTION('',(0.E0,0.E0,-1.E0)); #11075=DIRECTION('',(1.E0,0.E0,0.E0)); #11076=AXIS2_PLACEMENT_3D('',#11073,#11074,#11075); #11077=PLANE('',#11076); #11078=ORIENTED_EDGE('',*,*,#5862,.T.); #11080=ORIENTED_EDGE('',*,*,#11079,.T.); #11082=ORIENTED_EDGE('',*,*,#11081,.F.); #11083=ORIENTED_EDGE('',*,*,#11065,.F.); #11084=EDGE_LOOP('',(#11078,#11080,#11082,#11083)); #11085=FACE_OUTER_BOUND('',#11084,.F.); #11086=ADVANCED_FACE('',(#11085),#11077,.T.); #11087=CARTESIAN_POINT('',(1.65E1,0.E0,9.E0)); #11088=DIRECTION('',(0.E0,1.E0,0.E0)); #11089=DIRECTION('',(-1.E0,0.E0,0.E0)); #11090=AXIS2_PLACEMENT_3D('',#11087,#11088,#11089); #11091=CYLINDRICAL_SURFACE('',#11090,5.E-1); #11092=ORIENTED_EDGE('',*,*,#5860,.T.); #11093=ORIENTED_EDGE('',*,*,#11054,.T.); #11095=ORIENTED_EDGE('',*,*,#11094,.F.); #11096=ORIENTED_EDGE('',*,*,#11079,.F.); #11097=EDGE_LOOP('',(#11092,#11093,#11095,#11096)); #11098=FACE_OUTER_BOUND('',#11097,.F.); #11099=ADVANCED_FACE('',(#11098),#11091,.F.); #11100=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0)); #11101=DIRECTION('',(0.E0,1.E0,0.E0)); #11102=DIRECTION('',(-1.E0,0.E0,0.E0)); #11103=AXIS2_PLACEMENT_3D('',#11100,#11101,#11102); #11104=PLANE('',#11103); #11105=ORIENTED_EDGE('',*,*,#11052,.T.); #11106=ORIENTED_EDGE('',*,*,#11067,.T.); #11107=ORIENTED_EDGE('',*,*,#11081,.T.); #11108=ORIENTED_EDGE('',*,*,#11094,.T.); #11109=EDGE_LOOP('',(#11105,#11106,#11107,#11108)); #11110=FACE_OUTER_BOUND('',#11109,.F.); #11111=ADVANCED_FACE('',(#11110),#11104,.F.); #11112=CARTESIAN_POINT('',(1.65E1,0.E0,1.75625E1)); #11113=DIRECTION('',(0.E0,0.E0,1.E0)); #11114=DIRECTION('',(-1.E0,0.E0,0.E0)); #11115=AXIS2_PLACEMENT_3D('',#11112,#11113,#11114); #11116=PLANE('',#11115); #11117=ORIENTED_EDGE('',*,*,#5868,.T.); #11119=ORIENTED_EDGE('',*,*,#11118,.T.); #11121=ORIENTED_EDGE('',*,*,#11120,.F.); #11123=ORIENTED_EDGE('',*,*,#11122,.F.); #11124=EDGE_LOOP('',(#11117,#11119,#11121,#11123)); #11125=FACE_OUTER_BOUND('',#11124,.F.); #11126=ADVANCED_FACE('',(#11125),#11116,.T.); #11127=CARTESIAN_POINT('',(1.35E1,0.E0,1.8E1)); #11128=DIRECTION('',(0.E0,1.E0,0.E0)); #11129=DIRECTION('',(-1.E0,0.E0,0.E0)); #11130=AXIS2_PLACEMENT_3D('',#11127,#11128,#11129); #11131=CYLINDRICAL_SURFACE('',#11130,4.375E-1); #11132=ORIENTED_EDGE('',*,*,#5874,.T.); #11134=ORIENTED_EDGE('',*,*,#11133,.T.); #11136=ORIENTED_EDGE('',*,*,#11135,.F.); #11137=ORIENTED_EDGE('',*,*,#11118,.F.); #11138=EDGE_LOOP('',(#11132,#11134,#11136,#11137)); #11139=FACE_OUTER_BOUND('',#11138,.F.); #11140=ADVANCED_FACE('',(#11139),#11131,.F.); #11141=CARTESIAN_POINT('',(1.35E1,0.E0,1.84375E1)); #11142=DIRECTION('',(0.E0,0.E0,-1.E0)); #11143=DIRECTION('',(1.E0,0.E0,0.E0)); #11144=AXIS2_PLACEMENT_3D('',#11141,#11142,#11143); #11145=PLANE('',#11144); #11146=ORIENTED_EDGE('',*,*,#5872,.T.); #11148=ORIENTED_EDGE('',*,*,#11147,.T.); #11150=ORIENTED_EDGE('',*,*,#11149,.F.); #11151=ORIENTED_EDGE('',*,*,#11133,.F.); #11152=EDGE_LOOP('',(#11146,#11148,#11150,#11151)); #11153=FACE_OUTER_BOUND('',#11152,.F.); #11154=ADVANCED_FACE('',(#11153),#11145,.T.); #11155=CARTESIAN_POINT('',(1.65E1,0.E0,1.8E1)); #11156=DIRECTION('',(0.E0,1.E0,0.E0)); #11157=DIRECTION('',(-1.E0,0.E0,0.E0)); #11158=AXIS2_PLACEMENT_3D('',#11155,#11156,#11157); #11159=CYLINDRICAL_SURFACE('',#11158,4.375E-1); #11160=ORIENTED_EDGE('',*,*,#5870,.T.); #11161=ORIENTED_EDGE('',*,*,#11122,.T.); #11163=ORIENTED_EDGE('',*,*,#11162,.F.); #11164=ORIENTED_EDGE('',*,*,#11147,.F.); #11165=EDGE_LOOP('',(#11160,#11161,#11163,#11164)); #11166=FACE_OUTER_BOUND('',#11165,.F.); #11167=ADVANCED_FACE('',(#11166),#11159,.F.); #11168=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0)); #11169=DIRECTION('',(0.E0,1.E0,0.E0)); #11170=DIRECTION('',(-1.E0,0.E0,0.E0)); #11171=AXIS2_PLACEMENT_3D('',#11168,#11169,#11170); #11172=PLANE('',#11171); #11173=ORIENTED_EDGE('',*,*,#11120,.T.); #11174=ORIENTED_EDGE('',*,*,#11135,.T.); #11175=ORIENTED_EDGE('',*,*,#11149,.T.); #11176=ORIENTED_EDGE('',*,*,#11162,.T.); #11177=EDGE_LOOP('',(#11173,#11174,#11175,#11176)); #11178=FACE_OUTER_BOUND('',#11177,.F.); #11179=ADVANCED_FACE('',(#11178),#11172,.F.); #11180=CARTESIAN_POINT('',(1.65E1,0.E0,3.13125E1)); #11181=DIRECTION('',(0.E0,0.E0,1.E0)); #11182=DIRECTION('',(-1.E0,0.E0,0.E0)); #11183=AXIS2_PLACEMENT_3D('',#11180,#11181,#11182); #11184=PLANE('',#11183); #11185=ORIENTED_EDGE('',*,*,#5878,.F.); #11187=ORIENTED_EDGE('',*,*,#11186,.T.); #11189=ORIENTED_EDGE('',*,*,#11188,.T.); #11191=ORIENTED_EDGE('',*,*,#11190,.F.); #11192=EDGE_LOOP('',(#11185,#11187,#11189,#11191)); #11193=FACE_OUTER_BOUND('',#11192,.F.); #11194=ADVANCED_FACE('',(#11193),#11184,.F.); #11195=CARTESIAN_POINT('',(1.65E1,0.E0,3.075E1)); #11196=DIRECTION('',(0.E0,-1.E0,0.E0)); #11197=DIRECTION('',(-1.E0,0.E0,0.E0)); #11198=AXIS2_PLACEMENT_3D('',#11195,#11196,#11197); #11199=CYLINDRICAL_SURFACE('',#11198,5.625E-1); #11200=ORIENTED_EDGE('',*,*,#5884,.F.); #11202=ORIENTED_EDGE('',*,*,#11201,.T.); #11204=ORIENTED_EDGE('',*,*,#11203,.T.); #11205=ORIENTED_EDGE('',*,*,#11186,.F.); #11206=EDGE_LOOP('',(#11200,#11202,#11204,#11205)); #11207=FACE_OUTER_BOUND('',#11206,.F.); #11208=ADVANCED_FACE('',(#11207),#11199,.F.); #11209=CARTESIAN_POINT('',(1.35E1,0.E0,3.01875E1)); #11210=DIRECTION('',(0.E0,0.E0,-1.E0)); #11211=DIRECTION('',(1.E0,0.E0,0.E0)); #11212=AXIS2_PLACEMENT_3D('',#11209,#11210,#11211); #11213=PLANE('',#11212); #11214=ORIENTED_EDGE('',*,*,#5882,.F.); #11216=ORIENTED_EDGE('',*,*,#11215,.T.); #11218=ORIENTED_EDGE('',*,*,#11217,.T.); #11219=ORIENTED_EDGE('',*,*,#11201,.F.); #11220=EDGE_LOOP('',(#11214,#11216,#11218,#11219)); #11221=FACE_OUTER_BOUND('',#11220,.F.); #11222=ADVANCED_FACE('',(#11221),#11213,.F.); #11223=CARTESIAN_POINT('',(1.35E1,0.E0,3.075E1)); #11224=DIRECTION('',(0.E0,-1.E0,0.E0)); #11225=DIRECTION('',(-1.E0,0.E0,0.E0)); #11226=AXIS2_PLACEMENT_3D('',#11223,#11224,#11225); #11227=CYLINDRICAL_SURFACE('',#11226,5.625E-1); #11228=ORIENTED_EDGE('',*,*,#5880,.F.); #11229=ORIENTED_EDGE('',*,*,#11190,.T.); #11231=ORIENTED_EDGE('',*,*,#11230,.T.); #11232=ORIENTED_EDGE('',*,*,#11215,.F.); #11233=EDGE_LOOP('',(#11228,#11229,#11231,#11232)); #11234=FACE_OUTER_BOUND('',#11233,.F.); #11235=ADVANCED_FACE('',(#11234),#11227,.F.); #11236=CARTESIAN_POINT('',(2.4E1,6.875E-1,3.2E1)); #11237=DIRECTION('',(0.E0,-1.E0,0.E0)); #11238=DIRECTION('',(-1.E0,0.E0,0.E0)); #11239=AXIS2_PLACEMENT_3D('',#11236,#11237,#11238); #11240=PLANE('',#11239); #11241=ORIENTED_EDGE('',*,*,#11188,.F.); #11242=ORIENTED_EDGE('',*,*,#11203,.F.); #11243=ORIENTED_EDGE('',*,*,#11217,.F.); #11244=ORIENTED_EDGE('',*,*,#11230,.F.); #11245=EDGE_LOOP('',(#11241,#11242,#11243,#11244)); #11246=FACE_OUTER_BOUND('',#11245,.F.); #11247=ADVANCED_FACE('',(#11246),#11240,.T.); #11248=CARTESIAN_POINT('',(2.4E1,6.875E-1,3.2E1)); #11249=DIRECTION('',(0.E0,-1.E0,0.E0)); #11250=DIRECTION('',(-1.E0,0.E0,0.E0)); #11251=AXIS2_PLACEMENT_3D('',#11248,#11249,#11250); #11252=PLANE('',#11251); #11254=ORIENTED_EDGE('',*,*,#11253,.F.); #11256=ORIENTED_EDGE('',*,*,#11255,.F.); #11258=ORIENTED_EDGE('',*,*,#11257,.F.); #11260=ORIENTED_EDGE('',*,*,#11259,.F.); #11262=ORIENTED_EDGE('',*,*,#11261,.F.); #11263=EDGE_LOOP('',(#11254,#11256,#11258,#11260,#11262)); #11264=FACE_OUTER_BOUND('',#11263,.F.); #11265=ADVANCED_FACE('',(#11264),#11252,.T.); #11266=CARTESIAN_POINT('',(2.254426323641E1,-6.892397422826E-2, 2.742280476768E1)); #11267=DIRECTION('',(0.E0,1.E0,0.E0)); #11268=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #11269=AXIS2_PLACEMENT_3D('',#11266,#11267,#11268); #11270=CYLINDRICAL_SURFACE('',#11269,7.5E-1); #11272=ORIENTED_EDGE('',*,*,#11271,.F.); #11273=ORIENTED_EDGE('',*,*,#5944,.T.); #11275=ORIENTED_EDGE('',*,*,#11274,.T.); #11276=ORIENTED_EDGE('',*,*,#11253,.T.); #11277=EDGE_LOOP('',(#11272,#11273,#11275,#11276)); #11278=FACE_OUTER_BOUND('',#11277,.F.); #11279=ADVANCED_FACE('',(#11278),#11270,.F.); #11280=CARTESIAN_POINT('',(2.33125E1,0.E0,2.771522817587E1)); #11281=DIRECTION('',(7.071067811865E-1,0.E0,7.071067811865E-1)); #11282=DIRECTION('',(-7.071067811865E-1,0.E0,7.071067811865E-1)); #11283=AXIS2_PLACEMENT_3D('',#11280,#11281,#11282); #11284=PLANE('',#11283); #11285=ORIENTED_EDGE('',*,*,#11271,.T.); #11286=ORIENTED_EDGE('',*,*,#11261,.T.); #11288=ORIENTED_EDGE('',*,*,#11287,.F.); #11289=ORIENTED_EDGE('',*,*,#5946,.F.); #11290=EDGE_LOOP('',(#11285,#11286,#11288,#11289)); #11291=FACE_OUTER_BOUND('',#11290,.F.); #11292=ADVANCED_FACE('',(#11291),#11284,.F.); #11293=CARTESIAN_POINT('',(1.944696065761E1,0.E0,3.035464591145E1)); #11294=DIRECTION('',(0.E0,-1.E0,0.E0)); #11295=DIRECTION('',(-1.E0,0.E0,0.E0)); #11296=AXIS2_PLACEMENT_3D('',#11293,#11294,#11295); #11297=CYLINDRICAL_SURFACE('',#11296,8.669989027347E-1); #11298=ORIENTED_EDGE('',*,*,#5948,.F.); #11299=ORIENTED_EDGE('',*,*,#11287,.T.); #11300=ORIENTED_EDGE('',*,*,#11259,.T.); #11302=ORIENTED_EDGE('',*,*,#11301,.F.); #11303=EDGE_LOOP('',(#11298,#11299,#11300,#11302)); #11304=FACE_OUTER_BOUND('',#11303,.F.); #11305=ADVANCED_FACE('',(#11304),#11297,.F.); #11306=CARTESIAN_POINT('',(1.65E1,0.E0,2.45E1)); #11307=DIRECTION('',(0.E0,-1.E0,0.E0)); #11308=DIRECTION('',(-1.E0,0.E0,0.E0)); #11309=AXIS2_PLACEMENT_3D('',#11306,#11307,#11308); #11310=CYLINDRICAL_SURFACE('',#11309,5.6875E0); #11311=ORIENTED_EDGE('',*,*,#5950,.T.); #11312=ORIENTED_EDGE('',*,*,#11301,.T.); #11313=ORIENTED_EDGE('',*,*,#11257,.T.); #11315=ORIENTED_EDGE('',*,*,#11314,.F.); #11316=EDGE_LOOP('',(#11311,#11312,#11313,#11315)); #11317=FACE_OUTER_BOUND('',#11316,.F.); #11318=ADVANCED_FACE('',(#11317),#11310,.T.); #11319=CARTESIAN_POINT('',(2.239E1,0.E0,2.75E1)); #11320=DIRECTION('',(0.E0,-1.E0,0.E0)); #11321=DIRECTION('',(-1.E0,0.E0,0.E0)); #11322=AXIS2_PLACEMENT_3D('',#11319,#11320,#11321); #11323=CYLINDRICAL_SURFACE('',#11322,9.225E-1); #11324=ORIENTED_EDGE('',*,*,#11274,.F.); #11325=ORIENTED_EDGE('',*,*,#5942,.F.); #11326=ORIENTED_EDGE('',*,*,#11314,.T.); #11327=ORIENTED_EDGE('',*,*,#11255,.T.); #11328=EDGE_LOOP('',(#11324,#11325,#11326,#11327)); #11329=FACE_OUTER_BOUND('',#11328,.F.); #11330=ADVANCED_FACE('',(#11329),#11323,.F.); #11331=CARTESIAN_POINT('',(2.13075E1,-6.892397422826E-2,7.81E0)); #11332=DIRECTION('',(0.E0,1.E0,0.E0)); #11333=DIRECTION('',(0.E0,0.E0,1.E0)); #11334=AXIS2_PLACEMENT_3D('',#11331,#11332,#11333); #11335=CYLINDRICAL_SURFACE('',#11334,8.8E-1); #11337=ORIENTED_EDGE('',*,*,#11336,.T.); #11339=ORIENTED_EDGE('',*,*,#11338,.T.); #11341=ORIENTED_EDGE('',*,*,#11340,.F.); #11342=ORIENTED_EDGE('',*,*,#5888,.T.); #11343=EDGE_LOOP('',(#11337,#11339,#11341,#11342)); #11344=FACE_OUTER_BOUND('',#11343,.F.); #11345=ADVANCED_FACE('',(#11344),#11335,.T.); #11346=CARTESIAN_POINT('',(2.21875E1,0.E0,8.69E0)); #11347=DIRECTION('',(0.E0,0.E0,1.E0)); #11348=DIRECTION('',(-1.E0,0.E0,0.E0)); #11349=AXIS2_PLACEMENT_3D('',#11346,#11347,#11348); #11350=PLANE('',#11349); #11351=ORIENTED_EDGE('',*,*,#11336,.F.); #11352=ORIENTED_EDGE('',*,*,#5914,.T.); #11354=ORIENTED_EDGE('',*,*,#11353,.F.); #11356=ORIENTED_EDGE('',*,*,#11355,.F.); #11357=EDGE_LOOP('',(#11351,#11352,#11354,#11356)); #11358=FACE_OUTER_BOUND('',#11357,.F.); #11359=ADVANCED_FACE('',(#11358),#11350,.T.); #11360=CARTESIAN_POINT('',(2.05675E1,7.463919417831E-1,9.57E0)); #11361=DIRECTION('',(0.E0,-1.E0,0.E0)); #11362=DIRECTION('',(-1.E0,0.E0,0.E0)); #11363=AXIS2_PLACEMENT_3D('',#11360,#11361,#11362); #11364=CYLINDRICAL_SURFACE('',#11363,8.8E-1); #11366=ORIENTED_EDGE('',*,*,#11365,.F.); #11368=ORIENTED_EDGE('',*,*,#11367,.T.); #11369=ORIENTED_EDGE('',*,*,#11353,.T.); #11370=ORIENTED_EDGE('',*,*,#5912,.T.); #11371=EDGE_LOOP('',(#11366,#11368,#11369,#11370)); #11372=FACE_OUTER_BOUND('',#11371,.F.); #11373=ADVANCED_FACE('',(#11372),#11364,.F.); #11374=CARTESIAN_POINT('',(1.96875E1,0.E0,8.69E0)); #11375=DIRECTION('',(1.E0,0.E0,0.E0)); #11376=DIRECTION('',(0.E0,0.E0,1.E0)); #11377=AXIS2_PLACEMENT_3D('',#11374,#11375,#11376); #11378=PLANE('',#11377); #11379=ORIENTED_EDGE('',*,*,#11365,.T.); #11380=ORIENTED_EDGE('',*,*,#5910,.T.); #11382=ORIENTED_EDGE('',*,*,#11381,.F.); #11384=ORIENTED_EDGE('',*,*,#11383,.F.); #11385=EDGE_LOOP('',(#11379,#11380,#11382,#11384)); #11386=FACE_OUTER_BOUND('',#11385,.F.); #11387=ADVANCED_FACE('',(#11386),#11378,.T.); #11388=CARTESIAN_POINT('',(2.05675E1,7.463919417831E-1,1.037E1)); #11389=DIRECTION('',(0.E0,-1.E0,0.E0)); #11390=DIRECTION('',(0.E0,0.E0,1.E0)); #11391=AXIS2_PLACEMENT_3D('',#11388,#11389,#11390); #11392=CYLINDRICAL_SURFACE('',#11391,8.8E-1); #11394=ORIENTED_EDGE('',*,*,#11393,.F.); #11396=ORIENTED_EDGE('',*,*,#11395,.T.); #11397=ORIENTED_EDGE('',*,*,#11381,.T.); #11398=ORIENTED_EDGE('',*,*,#5908,.T.); #11399=EDGE_LOOP('',(#11394,#11396,#11397,#11398)); #11400=FACE_OUTER_BOUND('',#11399,.F.); #11401=ADVANCED_FACE('',(#11400),#11392,.F.); #11402=CARTESIAN_POINT('',(1.96875E1,0.E0,1.125E1)); #11403=DIRECTION('',(0.E0,0.E0,-1.E0)); #11404=DIRECTION('',(1.E0,0.E0,0.E0)); #11405=AXIS2_PLACEMENT_3D('',#11402,#11403,#11404); #11406=PLANE('',#11405); #11407=ORIENTED_EDGE('',*,*,#11393,.T.); #11408=ORIENTED_EDGE('',*,*,#5906,.T.); #11410=ORIENTED_EDGE('',*,*,#11409,.F.); #11412=ORIENTED_EDGE('',*,*,#11411,.F.); #11413=EDGE_LOOP('',(#11407,#11408,#11410,#11412)); #11414=FACE_OUTER_BOUND('',#11413,.F.); #11415=ADVANCED_FACE('',(#11414),#11406,.T.); #11416=CARTESIAN_POINT('',(2.44325E1,7.463919417831E-1,1.037E1)); #11417=DIRECTION('',(0.E0,-1.E0,0.E0)); #11418=DIRECTION('',(1.E0,0.E0,0.E0)); #11419=AXIS2_PLACEMENT_3D('',#11416,#11417,#11418); #11420=CYLINDRICAL_SURFACE('',#11419,8.8E-1); #11422=ORIENTED_EDGE('',*,*,#11421,.F.); #11424=ORIENTED_EDGE('',*,*,#11423,.T.); #11425=ORIENTED_EDGE('',*,*,#11409,.T.); #11426=ORIENTED_EDGE('',*,*,#5904,.T.); #11427=EDGE_LOOP('',(#11422,#11424,#11425,#11426)); #11428=FACE_OUTER_BOUND('',#11427,.F.); #11429=ADVANCED_FACE('',(#11428),#11420,.F.); #11430=CARTESIAN_POINT('',(2.53125E1,0.E0,1.125E1)); #11431=DIRECTION('',(-1.E0,0.E0,0.E0)); #11432=DIRECTION('',(0.E0,0.E0,-1.E0)); #11433=AXIS2_PLACEMENT_3D('',#11430,#11431,#11432); #11434=PLANE('',#11433); #11436=ORIENTED_EDGE('',*,*,#11435,.F.); #11438=ORIENTED_EDGE('',*,*,#11437,.F.); #11439=ORIENTED_EDGE('',*,*,#11421,.T.); #11440=ORIENTED_EDGE('',*,*,#5902,.T.); #11441=EDGE_LOOP('',(#11436,#11438,#11439,#11440)); #11442=FACE_OUTER_BOUND('',#11441,.F.); #11443=ADVANCED_FACE('',(#11442),#11434,.T.); #11444=CARTESIAN_POINT('',(2.44325E1,7.463919417831E-1,9.57E0)); #11445=DIRECTION('',(0.E0,-1.E0,0.E0)); #11446=DIRECTION('',(0.E0,0.E0,-1.E0)); #11447=AXIS2_PLACEMENT_3D('',#11444,#11445,#11446); #11448=CYLINDRICAL_SURFACE('',#11447,8.8E-1); #11450=ORIENTED_EDGE('',*,*,#11449,.F.); #11452=ORIENTED_EDGE('',*,*,#11451,.T.); #11453=ORIENTED_EDGE('',*,*,#11435,.T.); #11454=ORIENTED_EDGE('',*,*,#5900,.T.); #11455=EDGE_LOOP('',(#11450,#11452,#11453,#11454)); #11456=FACE_OUTER_BOUND('',#11455,.F.); #11457=ADVANCED_FACE('',(#11456),#11448,.F.); #11458=CARTESIAN_POINT('',(2.53125E1,0.E0,8.69E0)); #11459=DIRECTION('',(0.E0,0.E0,1.E0)); #11460=DIRECTION('',(-1.E0,0.E0,0.E0)); #11461=AXIS2_PLACEMENT_3D('',#11458,#11459,#11460); #11462=PLANE('',#11461); #11464=ORIENTED_EDGE('',*,*,#11463,.T.); #11466=ORIENTED_EDGE('',*,*,#11465,.F.); #11467=ORIENTED_EDGE('',*,*,#11449,.T.); #11468=ORIENTED_EDGE('',*,*,#5898,.T.); #11469=EDGE_LOOP('',(#11464,#11466,#11467,#11468)); #11470=FACE_OUTER_BOUND('',#11469,.F.); #11471=ADVANCED_FACE('',(#11470),#11462,.T.); #11472=CARTESIAN_POINT('',(2.419E1,-6.892397422826E-2,7.81E0)); #11473=DIRECTION('',(0.E0,1.E0,0.E0)); #11474=DIRECTION('',(-1.E0,0.E0,0.E0)); #11475=AXIS2_PLACEMENT_3D('',#11472,#11473,#11474); #11476=CYLINDRICAL_SURFACE('',#11475,8.8E-1); #11478=ORIENTED_EDGE('',*,*,#11477,.T.); #11480=ORIENTED_EDGE('',*,*,#11479,.T.); #11481=ORIENTED_EDGE('',*,*,#11463,.F.); #11482=ORIENTED_EDGE('',*,*,#5896,.T.); #11483=EDGE_LOOP('',(#11478,#11480,#11481,#11482)); #11484=FACE_OUTER_BOUND('',#11483,.F.); #11485=ADVANCED_FACE('',(#11484),#11476,.T.); #11486=CARTESIAN_POINT('',(2.331E1,0.E0,8.69E0)); #11487=DIRECTION('',(-1.E0,0.E0,0.E0)); #11488=DIRECTION('',(0.E0,0.E0,-1.E0)); #11489=AXIS2_PLACEMENT_3D('',#11486,#11487,#11488); #11490=PLANE('',#11489); #11491=ORIENTED_EDGE('',*,*,#11477,.F.); #11492=ORIENTED_EDGE('',*,*,#5894,.T.); #11494=ORIENTED_EDGE('',*,*,#11493,.T.); #11496=ORIENTED_EDGE('',*,*,#11495,.F.); #11497=EDGE_LOOP('',(#11491,#11492,#11494,#11496)); #11498=FACE_OUTER_BOUND('',#11497,.F.); #11499=ADVANCED_FACE('',(#11498),#11490,.T.); #11500=CARTESIAN_POINT('',(2.274875E1,0.E0,7.5E0)); #11501=DIRECTION('',(0.E0,1.E0,0.E0)); #11502=DIRECTION('',(-1.E0,0.E0,0.E0)); #11503=AXIS2_PLACEMENT_3D('',#11500,#11501,#11502); #11504=CYLINDRICAL_SURFACE('',#11503,5.6125E-1); #11505=ORIENTED_EDGE('',*,*,#5892,.T.); #11507=ORIENTED_EDGE('',*,*,#11506,.T.); #11509=ORIENTED_EDGE('',*,*,#11508,.F.); #11510=ORIENTED_EDGE('',*,*,#11493,.F.); #11511=EDGE_LOOP('',(#11505,#11507,#11509,#11510)); #11512=FACE_OUTER_BOUND('',#11511,.F.); #11513=ADVANCED_FACE('',(#11512),#11504,.F.); #11514=CARTESIAN_POINT('',(2.21875E1,0.E0,7.5E0)); #11515=DIRECTION('',(1.E0,0.E0,0.E0)); #11516=DIRECTION('',(0.E0,0.E0,1.E0)); #11517=AXIS2_PLACEMENT_3D('',#11514,#11515,#11516); #11518=PLANE('',#11517); #11519=ORIENTED_EDGE('',*,*,#11340,.T.); #11521=ORIENTED_EDGE('',*,*,#11520,.F.); #11522=ORIENTED_EDGE('',*,*,#11506,.F.); #11523=ORIENTED_EDGE('',*,*,#5890,.T.); #11524=EDGE_LOOP('',(#11519,#11521,#11522,#11523)); #11525=FACE_OUTER_BOUND('',#11524,.F.); #11526=ADVANCED_FACE('',(#11525),#11518,.T.); #11527=CARTESIAN_POINT('',(2.4E1,6.875E-1,0.E0)); #11528=DIRECTION('',(0.E0,1.E0,0.E0)); #11529=DIRECTION('',(-1.E0,0.E0,0.E0)); #11530=AXIS2_PLACEMENT_3D('',#11527,#11528,#11529); #11531=PLANE('',#11530); #11532=ORIENTED_EDGE('',*,*,#11465,.T.); #11533=ORIENTED_EDGE('',*,*,#11479,.F.); #11534=ORIENTED_EDGE('',*,*,#11495,.T.); #11535=ORIENTED_EDGE('',*,*,#11508,.T.); #11536=ORIENTED_EDGE('',*,*,#11520,.T.); #11537=ORIENTED_EDGE('',*,*,#11338,.F.); #11538=ORIENTED_EDGE('',*,*,#11355,.T.); #11539=ORIENTED_EDGE('',*,*,#11367,.F.); #11540=ORIENTED_EDGE('',*,*,#11383,.T.); #11541=ORIENTED_EDGE('',*,*,#11395,.F.); #11542=ORIENTED_EDGE('',*,*,#11411,.T.); #11543=ORIENTED_EDGE('',*,*,#11423,.F.); #11544=ORIENTED_EDGE('',*,*,#11437,.T.); #11545=ORIENTED_EDGE('',*,*,#11451,.F.); #11546=EDGE_LOOP('',(#11532,#11533,#11534,#11535,#11536,#11537,#11538,#11539, #11540,#11541,#11542,#11543,#11544,#11545)); #11547=FACE_OUTER_BOUND('',#11546,.F.); #11548=ADVANCED_FACE('',(#11547),#11531,.F.); #11549=CLOSED_SHELL('',(#5954,#6079,#6094,#6107,#6117,#6132,#6145,#6201,#6214, #6278,#6488,#6503,#6516,#6529,#6540,#6555,#6568,#6581,#6592,#6605,#6618,#6631, #6644,#6656,#6669,#6683,#6696,#6709,#6723,#6736,#6749,#6763,#6776,#6789,#6802, #6815,#6828,#6842,#6855,#6868,#6880,#6893,#6906,#6918,#6931,#6945,#6958,#6971, #6984,#6998,#7011,#7024,#7036,#7048,#7061,#7074,#7086,#7099,#7114,#7127,#7152, #7166,#7178,#7191,#7204,#7217,#7230,#7244,#7256,#7311,#7325,#7337,#7349,#7368, #7379,#7394,#7407,#7423,#7437,#7449,#7465,#7477,#7490,#7514,#7529,#7542,#7552, #7567,#7580,#7590,#7605,#7619,#7649,#7662,#7675,#7688,#7701,#7714,#7727,#7740, #7753,#7766,#7778,#7790,#7805,#7818,#7828,#7843,#7856,#7866,#7881,#7894,#7907, #7918,#7933,#7946,#7959,#7970,#7985,#7998,#8014,#8028,#8040,#8055,#8068,#8084, #8098,#8110,#8125,#8138,#8154,#8168,#8180,#8195,#8208,#8224,#8238,#8250,#8265, #8278,#8294,#8308,#8320,#8335,#8348,#8364,#8378,#8390,#8405,#8418,#8434,#8448, #8460,#8475,#8488,#8504,#8518,#8530,#8545,#8558,#8574,#8588,#8600,#8615,#8628, #8644,#8658,#8670,#8685,#8698,#8714,#8728,#8740,#8755,#8768,#8784,#8798,#8810, #8825,#8838,#8854,#8868,#8880,#8895,#8908,#8924,#8938,#8950,#8965,#8978,#8994, #9008,#9020,#9035,#9048,#9064,#9078,#9090,#9105,#9118,#9134,#9148,#9160,#9175, #9188,#9204,#9218,#9230,#9242,#9260,#9275,#9288,#9304,#9318,#9330,#9345,#9359, #9373,#9387,#9401,#9415,#9429,#9443,#9457,#9471,#9485,#9498,#9518,#9533,#9546, #9556,#9571,#9584,#9594,#9609,#9622,#9632,#9647,#9660,#9670,#9685,#9698,#9708, #9723,#9737,#9751,#9765,#9779,#9793,#9807,#9820,#9836,#9851,#9865,#9887,#9901, #9913,#9926,#9939,#9952,#9964,#9979,#9993,#10007,#10020,#10032,#10050,#10064, #10077,#10090,#10103,#10115,#10130,#10144,#10178,#10192,#10205,#10218,#10230, #10243,#10256,#10269,#10282,#10295,#10308,#10321,#10333,#10348,#10362,#10376, #10389,#10401,#10416,#10430,#10444,#10457,#10469,#10484,#10498,#10512,#10525, #10537,#10552,#10566,#10580,#10593,#10605,#10620,#10634,#10648,#10661,#10673, #10691,#10705,#10718,#10731,#10744,#10756,#10771,#10785,#10799,#10812,#10824, #10842,#10856,#10869,#10882,#10895,#10907,#10922,#10936,#10950,#10963,#10975, #10990,#11004,#11018,#11031,#11043,#11058,#11072,#11086,#11099,#11111,#11126, #11140,#11154,#11167,#11179,#11194,#11208,#11222,#11235,#11247,#11265,#11279, #11292,#11305,#11318,#11330,#11345,#11359,#11373,#11387,#11401,#11415,#11429, #11443,#11457,#11471,#11485,#11499,#11513,#11526,#11548)); #11550=MANIFOLD_SOLID_BREP('',#11549); #11551=DIMENSIONAL_EXPONENTS(1.E0,0.E0,0.E0,0.E0,0.E0,0.E0,0.E0); #11552=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.)); #11553=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(2.54E1),#11552); #11554=(CONVERSION_BASED_UNIT('INCH',#11553)LENGTH_UNIT()NAMED_UNIT(#11551)); #11555=DIMENSIONAL_EXPONENTS(0.E0,0.E0,0.E0,0.E0,0.E0,0.E0,0.E0); #11556=(NAMED_UNIT(*)PLANE_ANGLE_UNIT()SI_UNIT($,.RADIAN.)); #11557=PLANE_ANGLE_MEASURE_WITH_UNIT(PLANE_ANGLE_MEASURE(1.745329251994E-2), #11556); #11558=(CONVERSION_BASED_UNIT('DEGREE',#11557)NAMED_UNIT(#11555)PLANE_ANGLE_UNIT()); #11559=(NAMED_UNIT(*)SI_UNIT($,.STERADIAN.)SOLID_ANGLE_UNIT()); #11560=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(4.404650704771E-3),#11554, 'closure', 'Maximum model space distance between geometric entities at asserted connectivities'); #11561=(GEOMETRIC_REPRESENTATION_CONTEXT(3)GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT(( #11560))GLOBAL_UNIT_ASSIGNED_CONTEXT((#11554,#11558,#11559))REPRESENTATION_CONTEXT('ID1','3')); #11563=APPLICATION_CONTEXT( 'CONFIGURATION CONTROLLED 3D DESIGNS OF MECHANICAL PARTS AND ASSEMBLIES'); #11564=APPLICATION_PROTOCOL_DEFINITION('international standard', 'config_control_design',1994,#11563); #11565=DESIGN_CONTEXT('',#11563,'design'); #11566=MECHANICAL_CONTEXT('',#11563,'mechanical'); #11567=PRODUCT('PROESOURCE','PROESOURCE','NOT SPECIFIED',(#11566)); #11568=PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE('1','LAST_VERSION', #11567,.MADE.); #11572=PRODUCT_CATEGORY('part',''); #11573=PRODUCT_RELATED_PRODUCT_CATEGORY('detail','',(#11567)); #11574=PRODUCT_CATEGORY_RELATIONSHIP('','',#11572,#11573); #11575=SECURITY_CLASSIFICATION_LEVEL('unclassified'); #11576=SECURITY_CLASSIFICATION('','',#11575); #11577=CC_DESIGN_SECURITY_CLASSIFICATION(#11576,(#11568)); #11578=APPROVAL_STATUS('approved'); #11579=APPROVAL(#11578,''); #11580=CC_DESIGN_APPROVAL(#11579,(#11576,#11568,#11569)); #11581=CALENDAR_DATE(102,4,11); #11582=COORDINATED_UNIVERSAL_TIME_OFFSET(5,0,.BEHIND.); #11583=LOCAL_TIME(14,0,4.8E1,#11582); #11584=DATE_AND_TIME(#11581,#11583); #11585=APPROVAL_DATE_TIME(#11584,#11579); #11586=DATE_TIME_ROLE('creation_date'); #11587=CC_DESIGN_DATE_AND_TIME_ASSIGNMENT(#11584,#11586,(#11569)); #11588=DATE_TIME_ROLE('classification_date'); #11589=CC_DESIGN_DATE_AND_TIME_ASSIGNMENT(#11584,#11588,(#11576)); #11590=PERSON('UNSPECIFIED','UNSPECIFIED',$,$,$,$); #11591=ORGANIZATION('UNSPECIFIED','UNSPECIFIED','UNSPECIFIED'); #11592=PERSON_AND_ORGANIZATION(#11590,#11591); #11593=APPROVAL_ROLE('approver'); #11594=APPROVAL_PERSON_ORGANIZATION(#11592,#11579,#11593); #11595=PERSON_AND_ORGANIZATION_ROLE('creator'); #11596=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11595,(#11568, #11569)); #11597=PERSON_AND_ORGANIZATION_ROLE('design_supplier'); #11598=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11597,(#11568)); #11599=PERSON_AND_ORGANIZATION_ROLE('classification_officer'); #11600=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11599,(#11576)); #11601=PERSON_AND_ORGANIZATION_ROLE('design_owner'); #11602=CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT(#11592,#11601,(#11567)); #13=CIRCLE('',#12,1.925E-1); #18=CIRCLE('',#17,1.925E-1); #23=CIRCLE('',#22,1.925E-1); #28=CIRCLE('',#27,1.925E-1); #33=CIRCLE('',#32,1.925E-1); #38=CIRCLE('',#37,1.925E-1); #43=CIRCLE('',#42,1.925E-1); #48=CIRCLE('',#47,1.925E-1); #53=CIRCLE('',#52,1.925E-1); #58=CIRCLE('',#57,1.925E-1); #63=CIRCLE('',#62,1.925E-1); #68=CIRCLE('',#67,1.925E-1); #73=CIRCLE('',#72,1.925E-1); #78=CIRCLE('',#77,1.925E-1); #83=CIRCLE('',#82,1.925E-1); #88=CIRCLE('',#87,1.925E-1); #93=CIRCLE('',#92,1.925E-1); #98=CIRCLE('',#97,1.925E-1); #103=CIRCLE('',#102,1.925E-1); #108=CIRCLE('',#107,1.925E-1); #113=CIRCLE('',#112,1.925E-1); #118=CIRCLE('',#117,1.925E-1); #123=CIRCLE('',#122,1.925E-1); #128=CIRCLE('',#127,1.925E-1); #181=CIRCLE('',#180,1.925E-1); #186=CIRCLE('',#185,1.925E-1); #191=CIRCLE('',#190,1.925E-1); #196=CIRCLE('',#195,1.925E-1); #249=CIRCLE('',#248,1.925E-1); #254=CIRCLE('',#253,1.925E-1); #259=CIRCLE('',#258,1.925E-1); #264=CIRCLE('',#263,1.925E-1); #269=CIRCLE('',#268,1.925E-1); #274=CIRCLE('',#273,1.925E-1); #279=CIRCLE('',#278,1.925E-1); #284=CIRCLE('',#283,1.925E-1); #289=CIRCLE('',#288,1.925E-1); #294=CIRCLE('',#293,1.925E-1); #299=CIRCLE('',#298,1.925E-1); #304=CIRCLE('',#303,1.925E-1); #313=CIRCLE('',#312,5.625E-1); #322=CIRCLE('',#321,5.625E-1); #327=CIRCLE('',#326,9.225E-1); #336=CIRCLE('',#335,8.669989027347E-1); #341=CIRCLE('',#340,5.6875E0); #350=CIRCLE('',#349,5.6125E-1); #383=CIRCLE('',#382,5.625E-1); #392=CIRCLE('',#391,5.625E-1); #401=CIRCLE('',#400,5.625E-1); #410=CIRCLE('',#409,5.625E-1); #419=CIRCLE('',#418,5.E-1); #428=CIRCLE('',#427,5.E-1); #437=CIRCLE('',#436,4.375E-1); #446=CIRCLE('',#445,4.375E-1); #455=CIRCLE('',#454,5.625E-1); #464=CIRCLE('',#463,5.625E-1); #473=CIRCLE('',#472,5.625E-1); #482=CIRCLE('',#481,5.625E-1); #491=CIRCLE('',#490,5.625E-1); #500=CIRCLE('',#499,5.625E-1); #509=CIRCLE('',#508,5.625E-1); #518=CIRCLE('',#517,5.625E-1); #527=CIRCLE('',#526,5.E-1); #536=CIRCLE('',#535,5.E-1); #545=CIRCLE('',#544,4.375E-1); #554=CIRCLE('',#553,4.375E-1); #563=CIRCLE('',#562,5.625E-1); #572=CIRCLE('',#571,5.625E-1); #581=CIRCLE('',#580,5.6125E-1); #614=CIRCLE('',#613,9.225E-1); #619=CIRCLE('',#618,5.6875E0); #624=CIRCLE('',#623,8.669989027347E-1); #633=CIRCLE('',#632,9.225E-1); #638=CIRCLE('',#637,5.6875E0); #643=CIRCLE('',#642,8.669989027347E-1); #648=CIRCLE('',#647,9.225E-1); #657=CIRCLE('',#656,8.669989027347E-1); #662=CIRCLE('',#661,5.6875E0); #667=CIRCLE('',#666,9.5E-2); #672=CIRCLE('',#671,9.5E-2); #677=CIRCLE('',#676,1.625E-1); #682=CIRCLE('',#681,1.625E-1); #687=CIRCLE('',#686,9.5E-2); #692=CIRCLE('',#691,9.5E-2); #697=CIRCLE('',#696,9.5E-2); #702=CIRCLE('',#701,9.5E-2); #707=CIRCLE('',#706,9.5E-2); #712=CIRCLE('',#711,9.5E-2); #717=CIRCLE('',#716,9.5E-2); #722=CIRCLE('',#721,9.5E-2); #727=CIRCLE('',#726,1.625E-1); #732=CIRCLE('',#731,1.625E-1); #737=CIRCLE('',#736,9.5E-2); #742=CIRCLE('',#741,9.5E-2); #803=CIRCLE('',#802,9.5E-2); #808=CIRCLE('',#807,9.5E-2); #821=CIRCLE('',#820,1.625E-1); #826=CIRCLE('',#825,1.625E-1); #887=CIRCLE('',#886,1.E-1); #892=CIRCLE('',#891,1.E-1); #897=CIRCLE('',#896,1.E-1); #902=CIRCLE('',#901,1.E-1); #931=CIRCLE('',#930,1.E-1); #936=CIRCLE('',#935,1.E-1); #941=CIRCLE('',#940,1.E-1); #946=CIRCLE('',#945,1.E-1); #951=CIRCLE('',#950,2.575E-1); #956=CIRCLE('',#955,2.575E-1); #961=CIRCLE('',#960,2.575E-1); #966=CIRCLE('',#965,2.575E-1); #971=CIRCLE('',#970,2.575E-1); #976=CIRCLE('',#975,2.575E-1); #981=CIRCLE('',#980,2.575E-1); #986=CIRCLE('',#985,2.575E-1); #991=CIRCLE('',#990,2.575E-1); #996=CIRCLE('',#995,2.575E-1); #1001=CIRCLE('',#1000,2.575E-1); #1006=CIRCLE('',#1005,2.575E-1); #1011=CIRCLE('',#1010,2.56E-1); #1016=CIRCLE('',#1015,2.56E-1); #1021=CIRCLE('',#1020,2.56E-1); #1026=CIRCLE('',#1025,2.56E-1); #1031=CIRCLE('',#1030,2.56E-1); #1036=CIRCLE('',#1035,2.56E-1); #1041=CIRCLE('',#1040,2.56E-1); #1046=CIRCLE('',#1045,2.56E-1); #1051=CIRCLE('',#1050,2.56E-1); #1056=CIRCLE('',#1055,2.56E-1); #1061=CIRCLE('',#1060,2.56E-1); #1066=CIRCLE('',#1065,2.56E-1); #1115=CIRCLE('',#1114,2.575E-1); #1120=CIRCLE('',#1119,2.575E-1); #1125=CIRCLE('',#1124,2.575E-1); #1130=CIRCLE('',#1129,2.575E-1); #1135=CIRCLE('',#1134,2.575E-1); #1140=CIRCLE('',#1139,2.575E-1); #1145=CIRCLE('',#1144,2.575E-1); #1150=CIRCLE('',#1149,2.575E-1); #1155=CIRCLE('',#1154,2.575E-1); #1160=CIRCLE('',#1159,2.575E-1); #1165=CIRCLE('',#1164,2.575E-1); #1170=CIRCLE('',#1169,2.575E-1); #1259=CIRCLE('',#1258,1.E-1); #1268=CIRCLE('',#1267,1.E-1); #1285=CIRCLE('',#1284,1.E-1); #1294=CIRCLE('',#1293,1.E-1); #1303=CIRCLE('',#1302,1.E0); #1312=CIRCLE('',#1311,1.E0); #1317=CIRCLE('',#1316,5.E0); #1326=CIRCLE('',#1325,5.E0); #1331=CIRCLE('',#1330,5.E0); #1340=CIRCLE('',#1339,5.E0); #1349=CIRCLE('',#1348,1.E0); #1358=CIRCLE('',#1357,1.E0); #1367=CIRCLE('',#1366,1.E0); #1376=CIRCLE('',#1375,1.E0); #1385=CIRCLE('',#1384,1.E0); #1394=CIRCLE('',#1393,1.E0); #1403=CIRCLE('',#1402,1.E0); #1412=CIRCLE('',#1411,1.E0); #1421=CIRCLE('',#1420,3.E0); #1430=CIRCLE('',#1429,3.E0); #1439=CIRCLE('',#1438,3.E0); #1448=CIRCLE('',#1447,3.E0); #1457=CIRCLE('',#1456,5.E0); #1466=CIRCLE('',#1465,5.E0); #1475=CIRCLE('',#1474,5.E0); #1484=CIRCLE('',#1483,5.E0); #1493=CIRCLE('',#1492,3.E0); #1502=CIRCLE('',#1501,3.E0); #1511=CIRCLE('',#1510,3.E0); #1520=CIRCLE('',#1519,3.E0); #1529=CIRCLE('',#1528,1.E0); #1538=CIRCLE('',#1537,1.E0); #1547=CIRCLE('',#1546,1.E0); #1556=CIRCLE('',#1555,1.E0); #1597=CIRCLE('',#1596,1.E0); #1606=CIRCLE('',#1605,1.E0); #1675=CIRCLE('',#1674,9.5E-2); #1680=CIRCLE('',#1679,9.5E-2); #1685=CIRCLE('',#1684,6.25E-2); #1690=CIRCLE('',#1689,6.25E-2); #1707=CIRCLE('',#1706,1.E0); #1716=CIRCLE('',#1715,1.E0); #1729=CIRCLE('',#1728,1.E0); #1738=CIRCLE('',#1737,1.E0); #1767=CIRCLE('',#1766,1.625E-1); #1772=CIRCLE('',#1771,1.625E-1); #1846=B_SPLINE_CURVE_WITH_KNOTS('',3,(#1837,#1838,#1839,#1840,#1841,#1842,#1843, #1844,#1845),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1, 6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.); #1856=B_SPLINE_CURVE_WITH_KNOTS('',3,(#1847,#1848,#1849,#1850,#1851,#1852,#1853, #1854,#1855),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1, 6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.); #1873=CIRCLE('',#1872,2.575E-1); #1878=CIRCLE('',#1877,2.575E-1); #1883=CIRCLE('',#1882,1.925E-1); #1888=CIRCLE('',#1887,1.925E-1); #1933=CIRCLE('',#1932,9.5E-2); #1938=CIRCLE('',#1937,9.5E-2); #1943=CIRCLE('',#1942,6.25E-2); #1948=CIRCLE('',#1947,6.25E-2); #1961=CIRCLE('',#1960,9.5E-2); #1966=CIRCLE('',#1965,9.5E-2); #1979=CIRCLE('',#1978,6.25E-2); #1984=CIRCLE('',#1983,6.25E-2); #1993=CIRCLE('',#1992,3.5E-1); #2002=CIRCLE('',#2001,3.5E-1); #2035=CIRCLE('',#2034,3.5E-1); #2044=CIRCLE('',#2043,3.5E-1); #2053=CIRCLE('',#2052,3.5E-1); #2062=CIRCLE('',#2061,3.5E-1); #2071=CIRCLE('',#2070,3.5E-1); #2080=CIRCLE('',#2079,3.5E-1); #2089=CIRCLE('',#2088,3.5E-1); #2098=CIRCLE('',#2097,3.5E-1); #2107=CIRCLE('',#2106,3.5E-1); #2116=CIRCLE('',#2115,3.5E-1); #2145=CIRCLE('',#2144,9.5E-2); #2150=CIRCLE('',#2149,9.5E-2); #2163=CIRCLE('',#2162,6.25E-2); #2168=CIRCLE('',#2167,6.25E-2); #2189=CIRCLE('',#2188,1.E-1); #2194=CIRCLE('',#2193,1.E-1); #2215=CIRCLE('',#2214,1.E-1); #2220=CIRCLE('',#2219,1.E-1); #2233=CIRCLE('',#2232,2.575E-1); #2238=CIRCLE('',#2237,2.575E-1); #2243=CIRCLE('',#2242,1.925E-1); #2248=CIRCLE('',#2247,1.925E-1); #2269=CIRCLE('',#2268,2.575E-1); #2274=CIRCLE('',#2273,2.575E-1); #2279=CIRCLE('',#2278,1.925E-1); #2284=CIRCLE('',#2283,1.925E-1); #2305=CIRCLE('',#2304,2.575E-1); #2310=CIRCLE('',#2309,2.575E-1); #2315=CIRCLE('',#2314,1.925E-1); #2320=CIRCLE('',#2319,1.925E-1); #2341=CIRCLE('',#2340,2.575E-1); #2346=CIRCLE('',#2345,2.575E-1); #2351=CIRCLE('',#2350,1.925E-1); #2356=CIRCLE('',#2355,1.925E-1); #2377=CIRCLE('',#2376,2.575E-1); #2382=CIRCLE('',#2381,2.575E-1); #2387=CIRCLE('',#2386,1.925E-1); #2392=CIRCLE('',#2391,1.925E-1); #2413=CIRCLE('',#2412,2.575E-1); #2418=CIRCLE('',#2417,2.575E-1); #2423=CIRCLE('',#2422,1.925E-1); #2428=CIRCLE('',#2427,1.925E-1); #2449=CIRCLE('',#2448,2.56E-1); #2454=CIRCLE('',#2453,2.56E-1); #2459=CIRCLE('',#2458,1.925E-1); #2464=CIRCLE('',#2463,1.925E-1); #2485=CIRCLE('',#2484,2.56E-1); #2490=CIRCLE('',#2489,2.56E-1); #2495=CIRCLE('',#2494,1.925E-1); #2500=CIRCLE('',#2499,1.925E-1); #2521=CIRCLE('',#2520,2.56E-1); #2526=CIRCLE('',#2525,2.56E-1); #2531=CIRCLE('',#2530,1.925E-1); #2536=CIRCLE('',#2535,1.925E-1); #2557=CIRCLE('',#2556,2.56E-1); #2562=CIRCLE('',#2561,2.56E-1); #2567=CIRCLE('',#2566,1.925E-1); #2572=CIRCLE('',#2571,1.925E-1); #2593=CIRCLE('',#2592,2.56E-1); #2598=CIRCLE('',#2597,2.56E-1); #2603=CIRCLE('',#2602,1.925E-1); #2608=CIRCLE('',#2607,1.925E-1); #2629=CIRCLE('',#2628,2.56E-1); #2634=CIRCLE('',#2633,2.56E-1); #2639=CIRCLE('',#2638,1.925E-1); #2644=CIRCLE('',#2643,1.925E-1); #2665=CIRCLE('',#2664,2.575E-1); #2670=CIRCLE('',#2669,2.575E-1); #2675=CIRCLE('',#2674,1.925E-1); #2680=CIRCLE('',#2679,1.925E-1); #2701=CIRCLE('',#2700,2.575E-1); #2706=CIRCLE('',#2705,2.575E-1); #2711=CIRCLE('',#2710,1.925E-1); #2716=CIRCLE('',#2715,1.925E-1); #2737=CIRCLE('',#2736,2.575E-1); #2742=CIRCLE('',#2741,2.575E-1); #2747=CIRCLE('',#2746,1.925E-1); #2752=CIRCLE('',#2751,1.925E-1); #2773=CIRCLE('',#2772,2.575E-1); #2778=CIRCLE('',#2777,2.575E-1); #2783=CIRCLE('',#2782,1.925E-1); #2788=CIRCLE('',#2787,1.925E-1); #2809=CIRCLE('',#2808,2.575E-1); #2814=CIRCLE('',#2813,2.575E-1); #2819=CIRCLE('',#2818,1.925E-1); #2824=CIRCLE('',#2823,1.925E-1); #2845=CIRCLE('',#2844,2.575E-1); #2850=CIRCLE('',#2849,2.575E-1); #2855=CIRCLE('',#2854,1.925E-1); #2860=CIRCLE('',#2859,1.925E-1); #2882=B_SPLINE_CURVE_WITH_KNOTS('',3,(#2873,#2874,#2875,#2876,#2877,#2878,#2879, #2880,#2881),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1, 6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.); #2892=B_SPLINE_CURVE_WITH_KNOTS('',3,(#2883,#2884,#2885,#2886,#2887,#2888,#2889, #2890,#2891),.UNSPECIFIED.,.F.,.F.,(4,1,1,1,1,1,4),(0.E0,2.5E-1,3.75E-1,5.E-1, 6.25E-1,7.5E-1,1.E0),.UNSPECIFIED.); #2905=CIRCLE('',#2904,2.575E-1); #2910=CIRCLE('',#2909,2.575E-1); #2915=CIRCLE('',#2914,1.925E-1); #2920=CIRCLE('',#2919,1.925E-1); #2937=CIRCLE('',#2936,3.5E-1); #2946=CIRCLE('',#2945,3.5E-1); #2955=CIRCLE('',#2954,3.5E-1); #2964=CIRCLE('',#2963,3.5E-1); #2973=CIRCLE('',#2972,3.5E-1); #2982=CIRCLE('',#2981,3.5E-1); #2991=CIRCLE('',#2990,3.5E-1); #3000=CIRCLE('',#2999,3.5E-1); #3009=CIRCLE('',#3008,3.5E-1); #3018=CIRCLE('',#3017,3.5E-1); #3027=CIRCLE('',#3026,3.5E-1); #3036=CIRCLE('',#3035,3.5E-1); #3073=CIRCLE('',#3072,9.5E-2); #3078=CIRCLE('',#3077,9.5E-2); #3091=CIRCLE('',#3090,9.5E-2); #3096=CIRCLE('',#3095,9.5E-2); #3109=CIRCLE('',#3108,9.5E-2); #3114=CIRCLE('',#3113,9.5E-2); #3127=CIRCLE('',#3126,9.5E-2); #3132=CIRCLE('',#3131,9.5E-2); #3145=CIRCLE('',#3144,9.5E-2); #3150=CIRCLE('',#3149,9.5E-2); #3159=CIRCLE('',#3158,7.5E-1); #3168=CIRCLE('',#3167,7.5E-1); #3177=CIRCLE('',#3176,7.5E-1); #3186=CIRCLE('',#3185,7.5E-1); #3195=CIRCLE('',#3194,7.5E-1); #3204=CIRCLE('',#3203,7.5E-1); #3213=CIRCLE('',#3212,7.5E-1); #3222=CIRCLE('',#3221,7.5E-1); #3247=CIRCLE('',#3246,7.5E-1); #3256=CIRCLE('',#3255,7.5E-1); #3281=CIRCLE('',#3280,7.5E-1); #3290=CIRCLE('',#3289,7.5E-1); #3299=CIRCLE('',#3298,7.5E-1); #3308=CIRCLE('',#3307,7.5E-1); #3317=CIRCLE('',#3316,7.5E-1); #3326=CIRCLE('',#3325,7.5E-1); #3351=CIRCLE('',#3350,5.625E-1); #3360=CIRCLE('',#3359,5.625E-1); #3365=CIRCLE('',#3364,9.225E-1); #3370=CIRCLE('',#3369,5.6875E0); #3375=CIRCLE('',#3374,8.669989027347E-1); #3388=CIRCLE('',#3387,7.5E-1); #3397=CIRCLE('',#3396,7.5E-1); #3418=CIRCLE('',#3417,8.75E-1); #3427=CIRCLE('',#3426,8.75E-1); #3440=CIRCLE('',#3439,5.6125E-1); #3469=CIRCLE('',#3468,8.75E-1); #3478=CIRCLE('',#3477,8.75E-1); #3495=CIRCLE('',#3494,8.75E-1); #3504=CIRCLE('',#3503,8.75E-1); #3513=CIRCLE('',#3512,8.75E-1); #3522=CIRCLE('',#3521,8.75E-1); #3531=CIRCLE('',#3530,8.75E-1); #3540=CIRCLE('',#3539,8.75E-1); #3549=CIRCLE('',#3548,8.75E-1); #3558=CIRCLE('',#3557,8.75E-1); #3583=CIRCLE('',#3582,5.625E-1); #3592=CIRCLE('',#3591,5.625E-1); #3617=CIRCLE('',#3616,5.625E-1); #3626=CIRCLE('',#3625,5.625E-1); #3651=CIRCLE('',#3650,5.E-1); #3660=CIRCLE('',#3659,5.E-1); #3685=CIRCLE('',#3684,4.375E-1); #3694=CIRCLE('',#3693,4.375E-1); #3719=CIRCLE('',#3718,5.625E-1); #3728=CIRCLE('',#3727,5.625E-1); #3737=CIRCLE('',#3736,8.669989027347E-1); #3742=CIRCLE('',#3741,5.6875E0); #3747=CIRCLE('',#3746,9.225E-1); #3756=CIRCLE('',#3755,7.5E-1); #3765=CIRCLE('',#3764,7.5E-1); #3802=CIRCLE('',#3801,5.625E-1); #3811=CIRCLE('',#3810,5.625E-1); #3820=CIRCLE('',#3819,8.669989027347E-1); #3825=CIRCLE('',#3824,5.6875E0); #3830=CIRCLE('',#3829,9.225E-1); #3839=CIRCLE('',#3838,7.5E-1); #3848=CIRCLE('',#3847,7.5E-1); #3885=CIRCLE('',#3884,5.625E-1); #3894=CIRCLE('',#3893,5.625E-1); #3919=CIRCLE('',#3918,5.625E-1); #3928=CIRCLE('',#3927,5.625E-1); #3953=CIRCLE('',#3952,5.E-1); #3962=CIRCLE('',#3961,5.E-1); #3987=CIRCLE('',#3986,4.375E-1); #3996=CIRCLE('',#3995,4.375E-1); #4021=CIRCLE('',#4020,5.625E-1); #4030=CIRCLE('',#4029,5.625E-1); #4035=CIRCLE('',#4034,9.225E-1); #4040=CIRCLE('',#4039,5.6875E0); #4045=CIRCLE('',#4044,8.669989027347E-1); #4058=CIRCLE('',#4057,7.5E-1); #4067=CIRCLE('',#4066,7.5E-1); #4088=CIRCLE('',#4087,8.8E-1); #4097=CIRCLE('',#4096,8.8E-1); #4106=CIRCLE('',#4105,8.8E-1); #4115=CIRCLE('',#4114,8.8E-1); #4124=CIRCLE('',#4123,8.8E-1); #4133=CIRCLE('',#4132,8.8E-1); #4142=CIRCLE('',#4141,8.8E-1); #4151=CIRCLE('',#4150,8.8E-1); #4160=CIRCLE('',#4159,8.8E-1); #4169=CIRCLE('',#4168,8.8E-1); #4178=CIRCLE('',#4177,8.8E-1); #4187=CIRCLE('',#4186,8.8E-1); #4208=CIRCLE('',#4207,5.6125E-1); #5494=EDGE_CURVE('',#4423,#4400,#132,.T.); #5496=EDGE_CURVE('',#4419,#4423,#1597,.T.); #5498=EDGE_CURVE('',#4419,#4243,#136,.T.); #5500=EDGE_CURVE('',#4239,#4243,#1614,.T.); #5502=EDGE_CURVE('',#4239,#4259,#140,.T.); #5504=EDGE_CURVE('',#4255,#4259,#1630,.T.); #5506=EDGE_CURVE('',#4255,#4320,#144,.T.); #5508=EDGE_CURVE('',#4324,#4320,#1376,.T.); #5510=EDGE_CURVE('',#4324,#4300,#148,.T.); #5512=EDGE_CURVE('',#4300,#4347,#152,.T.); #5514=EDGE_CURVE('',#4343,#4347,#1912,.T.); #5516=EDGE_CURVE('',#4343,#4315,#156,.T.); #5518=EDGE_CURVE('',#4311,#4315,#1385,.T.); #5520=EDGE_CURVE('',#4311,#4251,#160,.T.); #5522=EDGE_CURVE('',#4247,#4251,#1580,.T.); #5524=EDGE_CURVE('',#4247,#4235,#164,.T.); #5526=EDGE_CURVE('',#4231,#4235,#1564,.T.); #5528=EDGE_CURVE('',#4231,#4404,#168,.T.); #5530=EDGE_CURVE('',#4408,#4404,#1556,.T.); #5532=EDGE_CURVE('',#4444,#4408,#172,.T.); #5534=EDGE_CURVE('',#4444,#4448,#1654,.T.); #5536=EDGE_CURVE('',#4400,#4448,#176,.T.); #5540=EDGE_CURVE('',#4427,#4328,#4,.T.); #5542=EDGE_CURVE('',#4332,#4328,#1358,.T.); #5544=EDGE_CURVE('',#4264,#4332,#1340,.T.); #5546=EDGE_CURVE('',#4268,#4264,#8,.T.); #5548=EDGE_CURVE('',#4431,#4268,#1317,.T.); #5550=EDGE_CURVE('',#4427,#4431,#1303,.T.); #5554=EDGE_CURVE('',#4639,#4640,#13,.T.); #5556=EDGE_CURVE('',#4640,#4639,#18,.T.); #5560=EDGE_CURVE('',#4635,#4636,#23,.T.); #5562=EDGE_CURVE('',#4636,#4635,#28,.T.); #5566=EDGE_CURVE('',#4631,#4632,#33,.T.); #5568=EDGE_CURVE('',#4632,#4631,#38,.T.); #5572=EDGE_CURVE('',#4627,#4628,#43,.T.); #5574=EDGE_CURVE('',#4628,#4627,#48,.T.); #5578=EDGE_CURVE('',#4623,#4624,#53,.T.); #5580=EDGE_CURVE('',#4624,#4623,#58,.T.); #5584=EDGE_CURVE('',#4527,#4528,#63,.T.); #5586=EDGE_CURVE('',#4528,#4527,#68,.T.); #5590=EDGE_CURVE('',#4523,#4524,#73,.T.); #5592=EDGE_CURVE('',#4524,#4523,#78,.T.); #5596=EDGE_CURVE('',#4519,#4520,#83,.T.); #5598=EDGE_CURVE('',#4520,#4519,#88,.T.); #5602=EDGE_CURVE('',#4515,#4516,#93,.T.); #5604=EDGE_CURVE('',#4516,#4515,#98,.T.); #5608=EDGE_CURVE('',#4511,#4512,#103,.T.); #5610=EDGE_CURVE('',#4512,#4511,#108,.T.); #5614=EDGE_CURVE('',#4507,#4508,#113,.T.); #5616=EDGE_CURVE('',#4508,#4507,#118,.T.); #5620=EDGE_CURVE('',#4503,#4504,#123,.T.); #5622=EDGE_CURVE('',#4504,#4503,#128,.T.); #5626=EDGE_CURVE('',#4487,#4488,#181,.T.); #5628=EDGE_CURVE('',#4488,#4487,#186,.T.); #5632=EDGE_CURVE('',#4607,#4608,#191,.T.); #5634=EDGE_CURVE('',#4608,#4607,#196,.T.); #5638=EDGE_CURVE('',#4796,#4803,#200,.T.); #5640=EDGE_CURVE('',#4799,#4803,#1439,.T.); #5642=EDGE_CURVE('',#4280,#4799,#204,.T.); #5644=EDGE_CURVE('',#4284,#4280,#1466,.T.); #5646=EDGE_CURVE('',#4272,#4284,#208,.T.); #5648=EDGE_CURVE('',#4276,#4272,#1484,.T.); #5650=EDGE_CURVE('',#4792,#4276,#212,.T.); #5652=EDGE_CURVE('',#4796,#4792,#1430,.T.); #5656=EDGE_CURVE('',#4808,#4411,#216,.T.); #5658=EDGE_CURVE('',#4812,#4808,#1502,.T.); #5660=EDGE_CURVE('',#4812,#4819,#220,.T.); #5662=EDGE_CURVE('',#4815,#4819,#1511,.T.); #5664=EDGE_CURVE('',#4304,#4815,#224,.T.); #5666=EDGE_CURVE('',#4308,#4304,#1412,.T.); #5668=EDGE_CURVE('',#4308,#4339,#228,.T.); #5670=EDGE_CURVE('',#4335,#4339,#1754,.T.); #5672=EDGE_CURVE('',#4335,#4772,#232,.T.); #5674=EDGE_CURVE('',#4776,#4772,#1738,.T.); #5676=EDGE_CURVE('',#4776,#4783,#236,.T.); #5678=EDGE_CURVE('',#4779,#4783,#1707,.T.); #5680=EDGE_CURVE('',#4436,#4779,#240,.T.); #5682=EDGE_CURVE('',#4436,#4440,#2132,.T.); #5684=EDGE_CURVE('',#4415,#4440,#244,.T.); #5686=EDGE_CURVE('',#4411,#4415,#1529,.T.); #5690=EDGE_CURVE('',#4823,#4824,#249,.T.); #5692=EDGE_CURVE('',#4824,#4823,#254,.T.); #5696=EDGE_CURVE('',#4839,#4840,#259,.T.); #5698=EDGE_CURVE('',#4840,#4839,#264,.T.); #5702=EDGE_CURVE('',#4843,#4844,#269,.T.); #5704=EDGE_CURVE('',#4844,#4843,#274,.T.); #5708=EDGE_CURVE('',#4847,#4848,#279,.T.); #5710=EDGE_CURVE('',#4848,#4847,#284,.T.); #5714=EDGE_CURVE('',#4851,#4852,#289,.T.); #5716=EDGE_CURVE('',#4852,#4851,#294,.T.); #5720=EDGE_CURVE('',#4855,#4856,#299,.T.); #5722=EDGE_CURVE('',#4856,#4855,#304,.T.); #5726=EDGE_CURVE('',#5121,#5122,#308,.T.); #5728=EDGE_CURVE('',#5122,#5124,#313,.T.); #5730=EDGE_CURVE('',#5124,#5126,#317,.T.); #5732=EDGE_CURVE('',#5126,#5121,#322,.T.); #5736=EDGE_CURVE('',#5132,#5139,#327,.T.); #5738=EDGE_CURVE('',#5135,#5139,#3388,.T.); #5740=EDGE_CURVE('',#5135,#5129,#331,.T.); #5742=EDGE_CURVE('',#5129,#5130,#336,.T.); #5744=EDGE_CURVE('',#5132,#5130,#341,.T.); #5748=EDGE_CURVE('',#5184,#5186,#3418,.T.); #5750=EDGE_CURVE('',#5184,#5147,#345,.T.); #5752=EDGE_CURVE('',#5147,#5148,#350,.T.); #5754=EDGE_CURVE('',#5148,#5194,#354,.T.); #5756=EDGE_CURVE('',#5192,#5194,#3469,.T.); #5758=EDGE_CURVE('',#5192,#5171,#358,.T.); #5760=EDGE_CURVE('',#5167,#5171,#3495,.T.); #5762=EDGE_CURVE('',#5167,#5179,#362,.T.); #5764=EDGE_CURVE('',#5175,#5179,#3513,.T.); #5766=EDGE_CURVE('',#5175,#5155,#366,.T.); #5768=EDGE_CURVE('',#5151,#5155,#3531,.T.); #5770=EDGE_CURVE('',#5151,#5163,#370,.T.); #5772=EDGE_CURVE('',#5159,#5163,#3549,.T.); #5774=EDGE_CURVE('',#5159,#5186,#374,.T.); #5778=EDGE_CURVE('',#5207,#5208,#378,.T.); #5780=EDGE_CURVE('',#5208,#5210,#383,.T.); #5782=EDGE_CURVE('',#5210,#5212,#387,.T.); #5784=EDGE_CURVE('',#5212,#5207,#392,.T.); #5788=EDGE_CURVE('',#5223,#5224,#396,.T.); #5790=EDGE_CURVE('',#5224,#5226,#401,.T.); #5792=EDGE_CURVE('',#5226,#5228,#405,.T.); #5794=EDGE_CURVE('',#5228,#5223,#410,.T.); #5798=EDGE_CURVE('',#5239,#5240,#414,.T.); #5800=EDGE_CURVE('',#5240,#5242,#419,.T.); #5802=EDGE_CURVE('',#5242,#5244,#423,.T.); #5804=EDGE_CURVE('',#5244,#5239,#428,.T.); #5808=EDGE_CURVE('',#5255,#5256,#432,.T.); #5810=EDGE_CURVE('',#5256,#5258,#437,.T.); #5812=EDGE_CURVE('',#5258,#5260,#441,.T.); #5814=EDGE_CURVE('',#5260,#5255,#446,.T.); #5818=EDGE_CURVE('',#5277,#5278,#450,.T.); #5820=EDGE_CURVE('',#5282,#5277,#455,.T.); #5822=EDGE_CURVE('',#5280,#5282,#459,.T.); #5824=EDGE_CURVE('',#5278,#5280,#464,.T.); #5828=EDGE_CURVE('',#5305,#5306,#468,.T.); #5830=EDGE_CURVE('',#5310,#5305,#473,.T.); #5832=EDGE_CURVE('',#5308,#5310,#477,.T.); #5834=EDGE_CURVE('',#5306,#5308,#482,.T.); #5838=EDGE_CURVE('',#5335,#5336,#486,.T.); #5840=EDGE_CURVE('',#5340,#5335,#491,.T.); #5842=EDGE_CURVE('',#5338,#5340,#495,.T.); #5844=EDGE_CURVE('',#5336,#5338,#500,.T.); #5848=EDGE_CURVE('',#5351,#5352,#504,.T.); #5850=EDGE_CURVE('',#5356,#5351,#509,.T.); #5852=EDGE_CURVE('',#5354,#5356,#513,.T.); #5854=EDGE_CURVE('',#5352,#5354,#518,.T.); #5858=EDGE_CURVE('',#5367,#5368,#522,.T.); #5860=EDGE_CURVE('',#5372,#5367,#527,.T.); #5862=EDGE_CURVE('',#5370,#5372,#531,.T.); #5864=EDGE_CURVE('',#5368,#5370,#536,.T.); #5868=EDGE_CURVE('',#5383,#5384,#540,.T.); #5870=EDGE_CURVE('',#5388,#5383,#545,.T.); #5872=EDGE_CURVE('',#5386,#5388,#549,.T.); #5874=EDGE_CURVE('',#5384,#5386,#554,.T.); #5878=EDGE_CURVE('',#5405,#5406,#558,.T.); #5880=EDGE_CURVE('',#5406,#5408,#563,.T.); #5882=EDGE_CURVE('',#5408,#5410,#567,.T.); #5884=EDGE_CURVE('',#5410,#5405,#572,.T.); #5888=EDGE_CURVE('',#5455,#5451,#4097,.T.); #5890=EDGE_CURVE('',#5324,#5455,#576,.T.); #5892=EDGE_CURVE('',#5323,#5324,#581,.T.); #5894=EDGE_CURVE('',#5459,#5323,#585,.T.); #5896=EDGE_CURVE('',#5463,#5459,#4187,.T.); #5898=EDGE_CURVE('',#5436,#5463,#589,.T.); #5900=EDGE_CURVE('',#5440,#5436,#4169,.T.); #5902=EDGE_CURVE('',#5444,#5440,#593,.T.); #5904=EDGE_CURVE('',#5448,#5444,#4151,.T.); #5906=EDGE_CURVE('',#5428,#5448,#597,.T.); #5908=EDGE_CURVE('',#5432,#5428,#4133,.T.); #5910=EDGE_CURVE('',#5420,#5432,#601,.T.); #5912=EDGE_CURVE('',#5424,#5420,#4115,.T.); #5914=EDGE_CURVE('',#5451,#5424,#605,.T.); #5918=EDGE_CURVE('',#5471,#5313,#609,.T.); #5920=EDGE_CURVE('',#5467,#5471,#3839,.T.); #5922=EDGE_CURVE('',#5316,#5467,#614,.T.); #5924=EDGE_CURVE('',#5316,#5314,#619,.T.); #5926=EDGE_CURVE('',#5313,#5314,#624,.T.); #5930=EDGE_CURVE('',#5479,#5285,#628,.T.); #5932=EDGE_CURVE('',#5475,#5479,#3756,.T.); #5934=EDGE_CURVE('',#5288,#5475,#633,.T.); #5936=EDGE_CURVE('',#5288,#5286,#638,.T.); #5938=EDGE_CURVE('',#5285,#5286,#643,.T.); #5942=EDGE_CURVE('',#5416,#5487,#648,.T.); #5944=EDGE_CURVE('',#5483,#5487,#4058,.T.); #5946=EDGE_CURVE('',#5483,#5413,#652,.T.); #5948=EDGE_CURVE('',#5413,#5414,#657,.T.); #5950=EDGE_CURVE('',#5416,#5414,#662,.T.); #5961=EDGE_CURVE('',#4427,#4428,#1298,.T.); #5963=EDGE_CURVE('',#4424,#4428,#906,.T.); #5965=EDGE_CURVE('',#4423,#4424,#1601,.T.); #5968=EDGE_CURVE('',#4390,#4400,#1658,.T.); #5970=EDGE_CURVE('',#4387,#4390,#746,.T.); #5972=EDGE_CURVE('',#4387,#4388,#750,.T.); #5974=EDGE_CURVE('',#4768,#4388,#1698,.T.); #5976=EDGE_CURVE('',#4767,#4768,#1230,.T.); #5978=EDGE_CURVE('',#4287,#4767,#1746,.T.); #5980=EDGE_CURVE('',#4287,#4288,#754,.T.); #5982=EDGE_CURVE('',#4288,#4290,#758,.T.); #5984=EDGE_CURVE('',#4300,#4290,#1900,.T.); #5987=EDGE_CURVE('',#4323,#4324,#1371,.T.); #5989=EDGE_CURVE('',#4327,#4323,#914,.T.); #5991=EDGE_CURVE('',#4327,#4328,#1344,.T.); #5995=EDGE_CURVE('',#4747,#4748,#667,.T.); #5997=EDGE_CURVE('',#4748,#4747,#672,.T.); #6001=EDGE_CURVE('',#4735,#4736,#677,.T.); #6003=EDGE_CURVE('',#4736,#4735,#682,.T.); #6007=EDGE_CURVE('',#4755,#4756,#687,.T.); #6009=EDGE_CURVE('',#4756,#4755,#692,.T.); #6013=EDGE_CURVE('',#4763,#4764,#697,.T.); #6015=EDGE_CURVE('',#4764,#4763,#702,.T.); #6019=EDGE_CURVE('',#4731,#4732,#707,.T.); #6021=EDGE_CURVE('',#4732,#4731,#712,.T.); #6025=EDGE_CURVE('',#4723,#4724,#717,.T.); #6027=EDGE_CURVE('',#4724,#4723,#722,.T.); #6031=EDGE_CURVE('',#4703,#4704,#727,.T.); #6033=EDGE_CURVE('',#4704,#4703,#732,.T.); #6037=EDGE_CURVE('',#4715,#4716,#737,.T.); #6039=EDGE_CURVE('',#4716,#4715,#742,.T.); #6043=EDGE_CURVE('',#4947,#4959,#762,.T.); #6045=EDGE_CURVE('',#4955,#4959,#3213,.T.); #6047=EDGE_CURVE('',#4955,#4967,#766,.T.); #6049=EDGE_CURVE('',#4963,#4967,#3195,.T.); #6051=EDGE_CURVE('',#4963,#4975,#770,.T.); #6053=EDGE_CURVE('',#4971,#4975,#3177,.T.); #6055=EDGE_CURVE('',#4971,#4951,#774,.T.); #6057=EDGE_CURVE('',#4947,#4951,#3159,.T.); #6061=EDGE_CURVE('',#5036,#5048,#778,.T.); #6063=EDGE_CURVE('',#5040,#5036,#3256,.T.); #6065=EDGE_CURVE('',#5028,#5040,#782,.T.); #6067=EDGE_CURVE('',#5032,#5028,#3290,.T.); #6069=EDGE_CURVE('',#5052,#5032,#786,.T.); #6071=EDGE_CURVE('',#5056,#5052,#3308,.T.); #6073=EDGE_CURVE('',#5044,#5056,#790,.T.); #6075=EDGE_CURVE('',#5048,#5044,#3326,.T.); #6086=EDGE_CURVE('',#4747,#4743,#794,.T.); #6088=EDGE_CURVE('',#4743,#4744,#803,.T.); #6090=EDGE_CURVE('',#4748,#4744,#798,.T.); #6102=EDGE_CURVE('',#4744,#4743,#808,.T.); #6124=EDGE_CURVE('',#4735,#4739,#812,.T.); #6126=EDGE_CURVE('',#4739,#4740,#821,.T.); #6128=EDGE_CURVE('',#4736,#4740,#816,.T.); #6140=EDGE_CURVE('',#4740,#4739,#826,.T.); #6151=EDGE_CURVE('',#4934,#4940,#830,.T.); #6153=EDGE_CURVE('',#4940,#4942,#834,.T.); #6155=EDGE_CURVE('',#4938,#4942,#838,.T.); #6157=EDGE_CURVE('',#4788,#4938,#1234,.T.); #6159=EDGE_CURVE('',#4788,#4393,#842,.T.); #6161=EDGE_CURVE('',#4393,#4394,#846,.T.); #6163=EDGE_CURVE('',#4394,#4396,#850,.T.); #6165=EDGE_CURVE('',#4396,#4398,#854,.T.); #6167=EDGE_CURVE('',#4934,#4398,#1178,.T.); #6175=EDGE_CURVE('',#5103,#5099,#2946,.T.); #6177=EDGE_CURVE('',#5076,#5103,#858,.T.); #6179=EDGE_CURVE('',#5080,#5076,#3036,.T.); #6181=EDGE_CURVE('',#5084,#5080,#862,.T.); #6183=EDGE_CURVE('',#5088,#5084,#3018,.T.); #6185=EDGE_CURVE('',#5092,#5088,#866,.T.); #6187=EDGE_CURVE('',#5096,#5092,#3000,.T.); #6189=EDGE_CURVE('',#5068,#5096,#870,.T.); #6191=EDGE_CURVE('',#5072,#5068,#2982,.T.); #6193=EDGE_CURVE('',#5060,#5072,#874,.T.); #6195=EDGE_CURVE('',#5064,#5060,#2964,.T.); #6197=EDGE_CURVE('',#5099,#5064,#878,.T.); #6207=EDGE_CURVE('',#4933,#4934,#1174,.T.); #6209=EDGE_CURVE('',#4940,#4933,#882,.T.); #6221=EDGE_CURVE('',#4432,#4428,#1312,.T.); #6223=EDGE_CURVE('',#4267,#4432,#1326,.T.); #6225=EDGE_CURVE('',#4267,#4263,#910,.T.); #6227=EDGE_CURVE('',#4331,#4263,#1331,.T.); #6229=EDGE_CURVE('',#4327,#4331,#1349,.T.); #6232=EDGE_CURVE('',#4319,#4323,#1367,.T.); #6234=EDGE_CURVE('',#4256,#4319,#918,.T.); #6236=EDGE_CURVE('',#4256,#4260,#1638,.T.); #6238=EDGE_CURVE('',#4240,#4260,#922,.T.); #6240=EDGE_CURVE('',#4240,#4244,#1622,.T.); #6242=EDGE_CURVE('',#4420,#4244,#926,.T.); #6244=EDGE_CURVE('',#4424,#4420,#1606,.T.); #6248=EDGE_CURVE('',#4495,#4496,#951,.T.); #6250=EDGE_CURVE('',#4496,#4495,#956,.T.); #6254=EDGE_CURVE('',#4567,#4568,#981,.T.); #6256=EDGE_CURVE('',#4568,#4567,#986,.T.); #6260=EDGE_CURVE('',#4615,#4616,#1011,.T.); #6262=EDGE_CURVE('',#4616,#4615,#1016,.T.); #6266=EDGE_CURVE('',#4647,#4648,#1021,.T.); #6268=EDGE_CURVE('',#4648,#4647,#1026,.T.); #6272=EDGE_CURVE('',#4659,#4660,#1031,.T.); #6274=EDGE_CURVE('',#4660,#4659,#1036,.T.); #6286=EDGE_CURVE('',#4398,#4447,#1182,.T.); #6288=EDGE_CURVE('',#4443,#4447,#1646,.T.); #6290=EDGE_CURVE('',#4443,#4407,#1186,.T.); #6292=EDGE_CURVE('',#4403,#4407,#1547,.T.); #6294=EDGE_CURVE('',#4232,#4403,#1190,.T.); #6296=EDGE_CURVE('',#4232,#4236,#1572,.T.); #6298=EDGE_CURVE('',#4248,#4236,#1194,.T.); #6300=EDGE_CURVE('',#4248,#4252,#1588,.T.); #6302=EDGE_CURVE('',#4312,#4252,#1198,.T.); #6304=EDGE_CURVE('',#4316,#4312,#1394,.T.); #6306=EDGE_CURVE('',#4344,#4316,#1202,.T.); #6308=EDGE_CURVE('',#4344,#4348,#1920,.T.); #6310=EDGE_CURVE('',#4298,#4348,#1206,.T.); #6312=EDGE_CURVE('',#4298,#4920,#1210,.T.); #6314=EDGE_CURVE('',#4919,#4920,#1214,.T.); #6316=EDGE_CURVE('',#4919,#4923,#1218,.T.); #6318=EDGE_CURVE('',#4923,#4924,#1222,.T.); #6320=EDGE_CURVE('',#4924,#4786,#1226,.T.); #6322=EDGE_CURVE('',#4767,#4786,#1742,.T.); #6325=EDGE_CURVE('',#4768,#4788,#1694,.T.); #6328=EDGE_CURVE('',#4937,#4938,#1238,.T.); #6330=EDGE_CURVE('',#4933,#4937,#1242,.T.); #6334=EDGE_CURVE('',#4373,#4374,#887,.T.); #6336=EDGE_CURVE('',#4374,#4373,#892,.T.); #6340=EDGE_CURVE('',#4383,#4384,#897,.T.); #6342=EDGE_CURVE('',#4384,#4383,#902,.T.); #6346=EDGE_CURVE('',#4473,#4474,#931,.T.); #6348=EDGE_CURVE('',#4474,#4473,#936,.T.); #6352=EDGE_CURVE('',#4483,#4484,#941,.T.); #6354=EDGE_CURVE('',#4484,#4483,#946,.T.); #6358=EDGE_CURVE('',#4543,#4544,#961,.T.); #6360=EDGE_CURVE('',#4544,#4543,#966,.T.); #6364=EDGE_CURVE('',#4555,#4556,#971,.T.); #6366=EDGE_CURVE('',#4556,#4555,#976,.T.); #6370=EDGE_CURVE('',#4587,#4588,#991,.T.); #6372=EDGE_CURVE('',#4588,#4587,#996,.T.); #6376=EDGE_CURVE('',#4599,#4600,#1001,.T.); #6378=EDGE_CURVE('',#4600,#4599,#1006,.T.); #6382=EDGE_CURVE('',#4671,#4672,#1041,.T.); #6384=EDGE_CURVE('',#4672,#4671,#1046,.T.); #6388=EDGE_CURVE('',#4683,#4684,#1051,.T.); #6390=EDGE_CURVE('',#4684,#4683,#1056,.T.); #6394=EDGE_CURVE('',#4695,#4696,#1061,.T.); #6396=EDGE_CURVE('',#4696,#4695,#1066,.T.); #6400=EDGE_CURVE('',#4279,#4800,#1070,.T.); #6402=EDGE_CURVE('',#4804,#4800,#1448,.T.); #6404=EDGE_CURVE('',#4795,#4804,#1074,.T.); #6406=EDGE_CURVE('',#4791,#4795,#1421,.T.); #6408=EDGE_CURVE('',#4791,#4275,#1078,.T.); #6410=EDGE_CURVE('',#4271,#4275,#1475,.T.); #6412=EDGE_CURVE('',#4271,#4283,#1082,.T.); #6414=EDGE_CURVE('',#4279,#4283,#1457,.T.); #6418=EDGE_CURVE('',#4811,#4820,#1086,.T.); #6420=EDGE_CURVE('',#4807,#4811,#1493,.T.); #6422=EDGE_CURVE('',#4807,#4412,#1090,.T.); #6424=EDGE_CURVE('',#4416,#4412,#1538,.T.); #6426=EDGE_CURVE('',#4416,#4439,#1094,.T.); #6428=EDGE_CURVE('',#4435,#4439,#2124,.T.); #6430=EDGE_CURVE('',#4435,#4780,#1098,.T.); #6432=EDGE_CURVE('',#4784,#4780,#1716,.T.); #6434=EDGE_CURVE('',#4775,#4784,#1720,.T.); #6436=EDGE_CURVE('',#4771,#4775,#1729,.T.); #6438=EDGE_CURVE('',#4336,#4771,#1102,.T.); #6440=EDGE_CURVE('',#4336,#4340,#1762,.T.); #6442=EDGE_CURVE('',#4307,#4340,#1106,.T.); #6444=EDGE_CURVE('',#4303,#4307,#1403,.T.); #6446=EDGE_CURVE('',#4303,#4816,#1110,.T.); #6448=EDGE_CURVE('',#4820,#4816,#1520,.T.); #6452=EDGE_CURVE('',#4831,#4832,#1115,.T.); #6454=EDGE_CURVE('',#4832,#4831,#1120,.T.); #6458=EDGE_CURVE('',#4863,#4864,#1125,.T.); #6460=EDGE_CURVE('',#4864,#4863,#1130,.T.); #6464=EDGE_CURVE('',#4875,#4876,#1135,.T.); #6466=EDGE_CURVE('',#4876,#4875,#1140,.T.); #6470=EDGE_CURVE('',#4887,#4888,#1145,.T.); #6472=EDGE_CURVE('',#4888,#4887,#1150,.T.); #6476=EDGE_CURVE('',#4899,#4900,#1155,.T.); #6478=EDGE_CURVE('',#4900,#4899,#1160,.T.); #6482=EDGE_CURVE('',#4911,#4912,#1165,.T.); #6484=EDGE_CURVE('',#4912,#4911,#1170,.T.); #6495=EDGE_CURVE('',#4368,#4374,#1250,.T.); #6497=EDGE_CURVE('',#4370,#4368,#1268,.T.); #6499=EDGE_CURVE('',#4370,#4373,#1246,.T.); #6511=EDGE_CURVE('',#4370,#4368,#1259,.T.); #6522=EDGE_CURVE('',#4367,#4368,#1254,.T.); #6525=EDGE_CURVE('',#4367,#4370,#1263,.T.); #6547=EDGE_CURVE('',#4378,#4384,#1276,.T.); #6549=EDGE_CURVE('',#4380,#4378,#1294,.T.); #6551=EDGE_CURVE('',#4380,#4383,#1272,.T.); #6563=EDGE_CURVE('',#4380,#4378,#1285,.T.); #6574=EDGE_CURVE('',#4377,#4378,#1280,.T.); #6577=EDGE_CURVE('',#4377,#4380,#1289,.T.); #6600=EDGE_CURVE('',#4431,#4432,#1307,.T.); #6613=EDGE_CURVE('',#4267,#4268,#1321,.T.); #6624=EDGE_CURVE('',#4263,#4264,#1335,.T.); #6637=EDGE_CURVE('',#4331,#4332,#1353,.T.); #6662=EDGE_CURVE('',#4319,#4320,#1362,.T.); #6675=EDGE_CURVE('',#4311,#4312,#1380,.T.); #6678=EDGE_CURVE('',#4251,#4252,#1584,.T.); #6691=EDGE_CURVE('',#4255,#4256,#1626,.T.); #6704=EDGE_CURVE('',#4315,#4316,#1389,.T.); #6715=EDGE_CURVE('',#4307,#4308,#1407,.T.); #6718=EDGE_CURVE('',#4339,#4340,#1758,.T.); #6731=EDGE_CURVE('',#4343,#4344,#1908,.T.); #6742=EDGE_CURVE('',#4303,#4304,#1398,.T.); #6755=EDGE_CURVE('',#4791,#4792,#1416,.T.); #6758=EDGE_CURVE('',#4275,#4276,#1479,.T.); #6769=EDGE_CURVE('',#4815,#4816,#1506,.T.); #6784=EDGE_CURVE('',#4795,#4796,#1425,.T.); #6797=EDGE_CURVE('',#4803,#4804,#1443,.T.); #6808=EDGE_CURVE('',#4799,#4800,#1434,.T.); #6823=EDGE_CURVE('',#4279,#4280,#1452,.T.); #6834=EDGE_CURVE('',#4807,#4808,#1488,.T.); #6837=EDGE_CURVE('',#4411,#4412,#1524,.T.); #6850=EDGE_CURVE('',#4283,#4284,#1461,.T.); #6861=EDGE_CURVE('',#4271,#4272,#1470,.T.); #6888=EDGE_CURVE('',#4811,#4812,#1497,.T.); #6901=EDGE_CURVE('',#4819,#4820,#1515,.T.); #6926=EDGE_CURVE('',#4415,#4416,#1533,.T.); #6937=EDGE_CURVE('',#4407,#4408,#1551,.T.); #6940=EDGE_CURVE('',#4443,#4444,#1642,.T.); #6953=EDGE_CURVE('',#4439,#4440,#2128,.T.); #6964=EDGE_CURVE('',#4403,#4404,#1542,.T.); #6979=EDGE_CURVE('',#4231,#4232,#1560,.T.); #6990=EDGE_CURVE('',#4419,#4420,#1592,.T.); #6993=EDGE_CURVE('',#4243,#4244,#1618,.T.); #7006=EDGE_CURVE('',#4235,#4236,#1568,.T.); #7018=EDGE_CURVE('',#4247,#4248,#1576,.T.); #7054=EDGE_CURVE('',#4239,#4240,#1610,.T.); #7070=EDGE_CURVE('',#4259,#4260,#1634,.T.); #7094=EDGE_CURVE('',#4447,#4448,#1650,.T.); #7110=EDGE_CURVE('',#4390,#4396,#1662,.T.); #7123=EDGE_CURVE('',#4387,#4394,#1666,.T.); #7136=EDGE_CURVE('',#4388,#4393,#1670,.T.); #7140=EDGE_CURVE('',#4455,#4456,#1675,.T.); #7142=EDGE_CURVE('',#4456,#4455,#1680,.T.); #7146=EDGE_CURVE('',#4463,#4464,#1685,.T.); #7148=EDGE_CURVE('',#4464,#4463,#1690,.T.); #7158=EDGE_CURVE('',#4779,#4780,#1702,.T.); #7161=EDGE_CURVE('',#4435,#4436,#2120,.T.); #7186=EDGE_CURVE('',#4783,#4784,#1711,.T.); #7197=EDGE_CURVE('',#4775,#4776,#1733,.T.); #7210=EDGE_CURVE('',#4771,#4772,#1724,.T.); #7225=EDGE_CURVE('',#4335,#4336,#1750,.T.); #7237=EDGE_CURVE('',#4786,#4293,#1792,.T.); #7239=EDGE_CURVE('',#4287,#4293,#1928,.T.); #7262=EDGE_CURVE('',#4920,#4926,#1776,.T.); #7265=EDGE_CURVE('',#4296,#4298,#1780,.T.); #7267=EDGE_CURVE('',#4294,#4296,#1784,.T.); #7269=EDGE_CURVE('',#4293,#4294,#1788,.T.); #7273=EDGE_CURVE('',#4924,#4928,#1796,.T.); #7275=EDGE_CURVE('',#4926,#4928,#1800,.T.); #7279=EDGE_CURVE('',#4707,#4708,#1767,.T.); #7281=EDGE_CURVE('',#4708,#4707,#1772,.T.); #7285=EDGE_CURVE('',#5020,#5022,#1993,.T.); #7287=EDGE_CURVE('',#5020,#4983,#1804,.T.); #7289=EDGE_CURVE('',#4979,#4983,#2107,.T.); #7291=EDGE_CURVE('',#4979,#4991,#1808,.T.); #7293=EDGE_CURVE('',#4987,#4991,#2089,.T.); #7295=EDGE_CURVE('',#4987,#5015,#1812,.T.); #7297=EDGE_CURVE('',#5011,#5015,#2071,.T.); #7299=EDGE_CURVE('',#5011,#5007,#1816,.T.); #7301=EDGE_CURVE('',#5003,#5007,#2053,.T.); #7303=EDGE_CURVE('',#5003,#4999,#1820,.T.); #7305=EDGE_CURVE('',#4995,#4999,#2035,.T.); #7307=EDGE_CURVE('',#4995,#5022,#1824,.T.); #7318=EDGE_CURVE('',#4704,#4708,#1832,.T.); #7321=EDGE_CURVE('',#4703,#4707,#1828,.T.); #7345=EDGE_CURVE('',#4926,#4919,#1836,.T.); #7358=EDGE_CURVE('',#4928,#4923,#1860,.T.); #7362=EDGE_CURVE('',#4929,#4930,#1846,.T.); #7364=EDGE_CURVE('',#4930,#4929,#1856,.T.); #7385=EDGE_CURVE('',#4930,#4531,#1868,.T.); #7388=EDGE_CURVE('',#4532,#4929,#1864,.T.); #7390=EDGE_CURVE('',#4531,#4532,#1873,.T.); #7403=EDGE_CURVE('',#4532,#4531,#1878,.T.); #7417=EDGE_CURVE('',#4535,#4536,#1883,.T.); #7419=EDGE_CURVE('',#4536,#4535,#1888,.T.); #7430=EDGE_CURVE('',#4536,#4504,#1896,.T.); #7433=EDGE_CURVE('',#4535,#4503,#1892,.T.); #7457=EDGE_CURVE('',#4347,#4348,#1916,.T.); #7461=EDGE_CURVE('',#4290,#4296,#1904,.T.); #7484=EDGE_CURVE('',#4288,#4294,#1924,.T.); #7502=EDGE_CURVE('',#4355,#4356,#1933,.T.); #7504=EDGE_CURVE('',#4356,#4355,#1938,.T.); #7508=EDGE_CURVE('',#4363,#4364,#1943,.T.); #7510=EDGE_CURVE('',#4364,#4363,#1948,.T.); #7521=EDGE_CURVE('',#4356,#4352,#1956,.T.); #7523=EDGE_CURVE('',#4351,#4352,#1961,.T.); #7525=EDGE_CURVE('',#4355,#4351,#1952,.T.); #7537=EDGE_CURVE('',#4352,#4351,#1966,.T.); #7559=EDGE_CURVE('',#4364,#4360,#1974,.T.); #7561=EDGE_CURVE('',#4359,#4360,#1979,.T.); #7563=EDGE_CURVE('',#4363,#4359,#1970,.T.); #7575=EDGE_CURVE('',#4360,#4359,#1984,.T.); #7596=EDGE_CURVE('',#5019,#5020,#1988,.T.); #7599=EDGE_CURVE('',#5024,#5022,#1997,.T.); #7601=EDGE_CURVE('',#5024,#5019,#2002,.T.); #7612=EDGE_CURVE('',#5019,#4984,#2006,.T.); #7614=EDGE_CURVE('',#4983,#4984,#2111,.T.); #7627=EDGE_CURVE('',#4996,#5024,#2010,.T.); #7629=EDGE_CURVE('',#5000,#4996,#2044,.T.); #7631=EDGE_CURVE('',#5004,#5000,#2014,.T.); #7633=EDGE_CURVE('',#5008,#5004,#2062,.T.); #7635=EDGE_CURVE('',#5012,#5008,#2018,.T.); #7637=EDGE_CURVE('',#5016,#5012,#2080,.T.); #7639=EDGE_CURVE('',#4988,#5016,#2022,.T.); #7641=EDGE_CURVE('',#4992,#4988,#2098,.T.); #7643=EDGE_CURVE('',#4980,#4992,#2026,.T.); #7645=EDGE_CURVE('',#4984,#4980,#2116,.T.); #7657=EDGE_CURVE('',#4995,#4996,#2030,.T.); #7670=EDGE_CURVE('',#4999,#5000,#2039,.T.); #7683=EDGE_CURVE('',#5003,#5004,#2048,.T.); #7696=EDGE_CURVE('',#5007,#5008,#2057,.T.); #7709=EDGE_CURVE('',#5011,#5012,#2066,.T.); #7722=EDGE_CURVE('',#5015,#5016,#2075,.T.); #7733=EDGE_CURVE('',#4987,#4988,#2084,.T.); #7748=EDGE_CURVE('',#4991,#4992,#2093,.T.); #7759=EDGE_CURVE('',#4979,#4980,#2102,.T.); #7797=EDGE_CURVE('',#4455,#4451,#2136,.T.); #7799=EDGE_CURVE('',#4451,#4452,#2145,.T.); #7801=EDGE_CURVE('',#4456,#4452,#2140,.T.); #7813=EDGE_CURVE('',#4452,#4451,#2150,.T.); #7835=EDGE_CURVE('',#4463,#4459,#2154,.T.); #7837=EDGE_CURVE('',#4459,#4460,#2163,.T.); #7839=EDGE_CURVE('',#4464,#4460,#2158,.T.); #7851=EDGE_CURVE('',#4460,#4459,#2168,.T.); #7873=EDGE_CURVE('',#4470,#4473,#2176,.T.); #7875=EDGE_CURVE('',#4470,#4468,#2194,.T.); #7877=EDGE_CURVE('',#4468,#4474,#2172,.T.); #7889=EDGE_CURVE('',#4470,#4468,#2189,.T.); #7900=EDGE_CURVE('',#4467,#4468,#2180,.T.); #7902=EDGE_CURVE('',#4467,#4470,#2184,.T.); #7925=EDGE_CURVE('',#4480,#4483,#2202,.T.); #7927=EDGE_CURVE('',#4480,#4478,#2220,.T.); #7929=EDGE_CURVE('',#4478,#4484,#2198,.T.); #7941=EDGE_CURVE('',#4480,#4478,#2215,.T.); #7952=EDGE_CURVE('',#4477,#4478,#2206,.T.); #7954=EDGE_CURVE('',#4477,#4480,#2210,.T.); #7977=EDGE_CURVE('',#4496,#4492,#2228,.T.); #7979=EDGE_CURVE('',#4491,#4492,#2233,.T.); #7981=EDGE_CURVE('',#4495,#4491,#2224,.T.); #7993=EDGE_CURVE('',#4492,#4491,#2238,.T.); #8008=EDGE_CURVE('',#4499,#4500,#2243,.T.); #8010=EDGE_CURVE('',#4500,#4499,#2248,.T.); #8021=EDGE_CURVE('',#4500,#4488,#2256,.T.); #8024=EDGE_CURVE('',#4499,#4487,#2252,.T.); #8047=EDGE_CURVE('',#4544,#4540,#2264,.T.); #8049=EDGE_CURVE('',#4539,#4540,#2269,.T.); #8051=EDGE_CURVE('',#4543,#4539,#2260,.T.); #8063=EDGE_CURVE('',#4540,#4539,#2274,.T.); #8078=EDGE_CURVE('',#4547,#4548,#2279,.T.); #8080=EDGE_CURVE('',#4548,#4547,#2284,.T.); #8091=EDGE_CURVE('',#4548,#4508,#2292,.T.); #8094=EDGE_CURVE('',#4547,#4507,#2288,.T.); #8117=EDGE_CURVE('',#4556,#4552,#2300,.T.); #8119=EDGE_CURVE('',#4551,#4552,#2305,.T.); #8121=EDGE_CURVE('',#4555,#4551,#2296,.T.); #8133=EDGE_CURVE('',#4552,#4551,#2310,.T.); #8148=EDGE_CURVE('',#4559,#4560,#2315,.T.); #8150=EDGE_CURVE('',#4560,#4559,#2320,.T.); #8161=EDGE_CURVE('',#4560,#4512,#2328,.T.); #8164=EDGE_CURVE('',#4559,#4511,#2324,.T.); #8187=EDGE_CURVE('',#4568,#4564,#2336,.T.); #8189=EDGE_CURVE('',#4563,#4564,#2341,.T.); #8191=EDGE_CURVE('',#4567,#4563,#2332,.T.); #8203=EDGE_CURVE('',#4564,#4563,#2346,.T.); #8218=EDGE_CURVE('',#4571,#4572,#2351,.T.); #8220=EDGE_CURVE('',#4572,#4571,#2356,.T.); #8231=EDGE_CURVE('',#4572,#4516,#2364,.T.); #8234=EDGE_CURVE('',#4571,#4515,#2360,.T.); #8257=EDGE_CURVE('',#4588,#4584,#2372,.T.); #8259=EDGE_CURVE('',#4583,#4584,#2377,.T.); #8261=EDGE_CURVE('',#4587,#4583,#2368,.T.); #8273=EDGE_CURVE('',#4584,#4583,#2382,.T.); #8288=EDGE_CURVE('',#4591,#4592,#2387,.T.); #8290=EDGE_CURVE('',#4592,#4591,#2392,.T.); #8301=EDGE_CURVE('',#4592,#4524,#2400,.T.); #8304=EDGE_CURVE('',#4591,#4523,#2396,.T.); #8327=EDGE_CURVE('',#4600,#4596,#2408,.T.); #8329=EDGE_CURVE('',#4595,#4596,#2413,.T.); #8331=EDGE_CURVE('',#4599,#4595,#2404,.T.); #8343=EDGE_CURVE('',#4596,#4595,#2418,.T.); #8358=EDGE_CURVE('',#4603,#4604,#2423,.T.); #8360=EDGE_CURVE('',#4604,#4603,#2428,.T.); #8371=EDGE_CURVE('',#4604,#4528,#2436,.T.); #8374=EDGE_CURVE('',#4603,#4527,#2432,.T.); #8397=EDGE_CURVE('',#4616,#4612,#2444,.T.); #8399=EDGE_CURVE('',#4611,#4612,#2449,.T.); #8401=EDGE_CURVE('',#4615,#4611,#2440,.T.); #8413=EDGE_CURVE('',#4612,#4611,#2454,.T.); #8428=EDGE_CURVE('',#4619,#4620,#2459,.T.); #8430=EDGE_CURVE('',#4620,#4619,#2464,.T.); #8441=EDGE_CURVE('',#4620,#4608,#2472,.T.); #8444=EDGE_CURVE('',#4619,#4607,#2468,.T.); #8467=EDGE_CURVE('',#4648,#4644,#2480,.T.); #8469=EDGE_CURVE('',#4643,#4644,#2485,.T.); #8471=EDGE_CURVE('',#4647,#4643,#2476,.T.); #8483=EDGE_CURVE('',#4644,#4643,#2490,.T.); #8498=EDGE_CURVE('',#4651,#4652,#2495,.T.); #8500=EDGE_CURVE('',#4652,#4651,#2500,.T.); #8511=EDGE_CURVE('',#4652,#4624,#2508,.T.); #8514=EDGE_CURVE('',#4651,#4623,#2504,.T.); #8537=EDGE_CURVE('',#4660,#4656,#2516,.T.); #8539=EDGE_CURVE('',#4655,#4656,#2521,.T.); #8541=EDGE_CURVE('',#4659,#4655,#2512,.T.); #8553=EDGE_CURVE('',#4656,#4655,#2526,.T.); #8568=EDGE_CURVE('',#4663,#4664,#2531,.T.); #8570=EDGE_CURVE('',#4664,#4663,#2536,.T.); #8581=EDGE_CURVE('',#4664,#4636,#2544,.T.); #8584=EDGE_CURVE('',#4663,#4635,#2540,.T.); #8607=EDGE_CURVE('',#4672,#4668,#2552,.T.); #8609=EDGE_CURVE('',#4667,#4668,#2557,.T.); #8611=EDGE_CURVE('',#4671,#4667,#2548,.T.); #8623=EDGE_CURVE('',#4668,#4667,#2562,.T.); #8638=EDGE_CURVE('',#4675,#4676,#2567,.T.); #8640=EDGE_CURVE('',#4676,#4675,#2572,.T.); #8651=EDGE_CURVE('',#4676,#4628,#2580,.T.); #8654=EDGE_CURVE('',#4675,#4627,#2576,.T.); #8677=EDGE_CURVE('',#4684,#4680,#2588,.T.); #8679=EDGE_CURVE('',#4679,#4680,#2593,.T.); #8681=EDGE_CURVE('',#4683,#4679,#2584,.T.); #8693=EDGE_CURVE('',#4680,#4679,#2598,.T.); #8708=EDGE_CURVE('',#4687,#4688,#2603,.T.); #8710=EDGE_CURVE('',#4688,#4687,#2608,.T.); #8721=EDGE_CURVE('',#4688,#4632,#2616,.T.); #8724=EDGE_CURVE('',#4687,#4631,#2612,.T.); #8747=EDGE_CURVE('',#4696,#4692,#2624,.T.); #8749=EDGE_CURVE('',#4691,#4692,#2629,.T.); #8751=EDGE_CURVE('',#4695,#4691,#2620,.T.); #8763=EDGE_CURVE('',#4692,#4691,#2634,.T.); #8778=EDGE_CURVE('',#4699,#4700,#2639,.T.); #8780=EDGE_CURVE('',#4700,#4699,#2644,.T.); #8791=EDGE_CURVE('',#4700,#4640,#2652,.T.); #8794=EDGE_CURVE('',#4699,#4639,#2648,.T.); #8817=EDGE_CURVE('',#4832,#4828,#2660,.T.); #8819=EDGE_CURVE('',#4827,#4828,#2665,.T.); #8821=EDGE_CURVE('',#4831,#4827,#2656,.T.); #8833=EDGE_CURVE('',#4828,#4827,#2670,.T.); #8848=EDGE_CURVE('',#4835,#4836,#2675,.T.); #8850=EDGE_CURVE('',#4836,#4835,#2680,.T.); #8861=EDGE_CURVE('',#4836,#4824,#2688,.T.); #8864=EDGE_CURVE('',#4835,#4823,#2684,.T.); #8887=EDGE_CURVE('',#4864,#4860,#2696,.T.); #8889=EDGE_CURVE('',#4859,#4860,#2701,.T.); #8891=EDGE_CURVE('',#4863,#4859,#2692,.T.); #8903=EDGE_CURVE('',#4860,#4859,#2706,.T.); #8918=EDGE_CURVE('',#4867,#4868,#2711,.T.); #8920=EDGE_CURVE('',#4868,#4867,#2716,.T.); #8931=EDGE_CURVE('',#4868,#4840,#2724,.T.); #8934=EDGE_CURVE('',#4867,#4839,#2720,.T.); #8957=EDGE_CURVE('',#4876,#4872,#2732,.T.); #8959=EDGE_CURVE('',#4871,#4872,#2737,.T.); #8961=EDGE_CURVE('',#4875,#4871,#2728,.T.); #8973=EDGE_CURVE('',#4872,#4871,#2742,.T.); #8988=EDGE_CURVE('',#4879,#4880,#2747,.T.); #8990=EDGE_CURVE('',#4880,#4879,#2752,.T.); #9001=EDGE_CURVE('',#4880,#4844,#2760,.T.); #9004=EDGE_CURVE('',#4879,#4843,#2756,.T.); #9027=EDGE_CURVE('',#4888,#4884,#2768,.T.); #9029=EDGE_CURVE('',#4883,#4884,#2773,.T.); #9031=EDGE_CURVE('',#4887,#4883,#2764,.T.); #9043=EDGE_CURVE('',#4884,#4883,#2778,.T.); #9058=EDGE_CURVE('',#4891,#4892,#2783,.T.); #9060=EDGE_CURVE('',#4892,#4891,#2788,.T.); #9071=EDGE_CURVE('',#4892,#4848,#2796,.T.); #9074=EDGE_CURVE('',#4891,#4847,#2792,.T.); #9097=EDGE_CURVE('',#4900,#4896,#2804,.T.); #9099=EDGE_CURVE('',#4895,#4896,#2809,.T.); #9101=EDGE_CURVE('',#4899,#4895,#2800,.T.); #9113=EDGE_CURVE('',#4896,#4895,#2814,.T.); #9128=EDGE_CURVE('',#4903,#4904,#2819,.T.); #9130=EDGE_CURVE('',#4904,#4903,#2824,.T.); #9141=EDGE_CURVE('',#4904,#4852,#2832,.T.); #9144=EDGE_CURVE('',#4903,#4851,#2828,.T.); #9167=EDGE_CURVE('',#4912,#4908,#2840,.T.); #9169=EDGE_CURVE('',#4907,#4908,#2845,.T.); #9171=EDGE_CURVE('',#4911,#4907,#2836,.T.); #9183=EDGE_CURVE('',#4908,#4907,#2850,.T.); #9198=EDGE_CURVE('',#4915,#4916,#2855,.T.); #9200=EDGE_CURVE('',#4916,#4915,#2860,.T.); #9211=EDGE_CURVE('',#4916,#4856,#2868,.T.); #9214=EDGE_CURVE('',#4915,#4855,#2864,.T.); #9238=EDGE_CURVE('',#4942,#4937,#2872,.T.); #9254=EDGE_CURVE('',#4943,#4944,#2882,.T.); #9256=EDGE_CURVE('',#4944,#4943,#2892,.T.); #9266=EDGE_CURVE('',#4943,#4575,#2900,.T.); #9269=EDGE_CURVE('',#4576,#4944,#2896,.T.); #9271=EDGE_CURVE('',#4575,#4576,#2905,.T.); #9284=EDGE_CURVE('',#4576,#4575,#2910,.T.); #9298=EDGE_CURVE('',#4579,#4580,#2915,.T.); #9300=EDGE_CURVE('',#4580,#4579,#2920,.T.); #9311=EDGE_CURVE('',#4580,#4520,#2928,.T.); #9314=EDGE_CURVE('',#4579,#4519,#2924,.T.); #9336=EDGE_CURVE('',#5099,#5100,#2932,.T.); #9338=EDGE_CURVE('',#5100,#5104,#2937,.T.); #9340=EDGE_CURVE('',#5103,#5104,#2941,.T.); #9353=EDGE_CURVE('',#5062,#5064,#2959,.T.); #9355=EDGE_CURVE('',#5100,#5062,#3044,.T.); #9365=EDGE_CURVE('',#5059,#5060,#2950,.T.); #9367=EDGE_CURVE('',#5059,#5062,#2955,.T.); #9381=EDGE_CURVE('',#5070,#5072,#2977,.T.); #9383=EDGE_CURVE('',#5059,#5070,#3048,.T.); #9393=EDGE_CURVE('',#5067,#5068,#2968,.T.); #9395=EDGE_CURVE('',#5067,#5070,#2973,.T.); #9409=EDGE_CURVE('',#5094,#5096,#2995,.T.); #9411=EDGE_CURVE('',#5067,#5094,#3052,.T.); #9421=EDGE_CURVE('',#5091,#5092,#2986,.T.); #9423=EDGE_CURVE('',#5091,#5094,#2991,.T.); #9435=EDGE_CURVE('',#5086,#5088,#3013,.T.); #9437=EDGE_CURVE('',#5091,#5086,#3056,.T.); #9449=EDGE_CURVE('',#5083,#5084,#3004,.T.); #9451=EDGE_CURVE('',#5083,#5086,#3009,.T.); #9463=EDGE_CURVE('',#5078,#5080,#3031,.T.); #9465=EDGE_CURVE('',#5083,#5078,#3060,.T.); #9477=EDGE_CURVE('',#5075,#5076,#3022,.T.); #9479=EDGE_CURVE('',#5075,#5078,#3027,.T.); #9492=EDGE_CURVE('',#5075,#5104,#3040,.T.); #9525=EDGE_CURVE('',#4755,#4751,#3064,.T.); #9527=EDGE_CURVE('',#4751,#4752,#3073,.T.); #9529=EDGE_CURVE('',#4756,#4752,#3068,.T.); #9541=EDGE_CURVE('',#4752,#4751,#3078,.T.); #9563=EDGE_CURVE('',#4763,#4759,#3082,.T.); #9565=EDGE_CURVE('',#4759,#4760,#3091,.T.); #9567=EDGE_CURVE('',#4764,#4760,#3086,.T.); #9579=EDGE_CURVE('',#4760,#4759,#3096,.T.); #9601=EDGE_CURVE('',#4732,#4728,#3104,.T.); #9603=EDGE_CURVE('',#4727,#4728,#3109,.T.); #9605=EDGE_CURVE('',#4731,#4727,#3100,.T.); #9617=EDGE_CURVE('',#4728,#4727,#3114,.T.); #9639=EDGE_CURVE('',#4724,#4720,#3122,.T.); #9641=EDGE_CURVE('',#4719,#4720,#3127,.T.); #9643=EDGE_CURVE('',#4723,#4719,#3118,.T.); #9655=EDGE_CURVE('',#4720,#4719,#3132,.T.); #9677=EDGE_CURVE('',#4716,#4712,#3140,.T.); #9679=EDGE_CURVE('',#4711,#4712,#3145,.T.); #9681=EDGE_CURVE('',#4715,#4711,#3136,.T.); #9693=EDGE_CURVE('',#4712,#4711,#3150,.T.); #9714=EDGE_CURVE('',#4947,#4948,#3154,.T.); #9716=EDGE_CURVE('',#4948,#4960,#3238,.T.); #9718=EDGE_CURVE('',#4959,#4960,#3217,.T.); #9731=EDGE_CURVE('',#4951,#4952,#3163,.T.); #9733=EDGE_CURVE('',#4952,#4948,#3168,.T.); #9745=EDGE_CURVE('',#4971,#4972,#3172,.T.); #9747=EDGE_CURVE('',#4972,#4952,#3226,.T.); #9759=EDGE_CURVE('',#4975,#4976,#3181,.T.); #9761=EDGE_CURVE('',#4976,#4972,#3186,.T.); #9771=EDGE_CURVE('',#4963,#4964,#3190,.T.); #9773=EDGE_CURVE('',#4964,#4976,#3230,.T.); #9787=EDGE_CURVE('',#4967,#4968,#3199,.T.); #9789=EDGE_CURVE('',#4968,#4964,#3204,.T.); #9799=EDGE_CURVE('',#4955,#4956,#3208,.T.); #9801=EDGE_CURVE('',#4956,#4968,#3234,.T.); #9816=EDGE_CURVE('',#4960,#4956,#3222,.T.); #9842=EDGE_CURVE('',#5035,#5036,#3242,.T.); #9845=EDGE_CURVE('',#5046,#5048,#3321,.T.); #9847=EDGE_CURVE('',#5035,#5046,#3264,.T.); #9858=EDGE_CURVE('',#5035,#5038,#3247,.T.); #9860=EDGE_CURVE('',#5038,#5040,#3251,.T.); #9871=EDGE_CURVE('',#5027,#5030,#3281,.T.); #9873=EDGE_CURVE('',#5027,#5038,#3260,.T.); #9877=EDGE_CURVE('',#5043,#5046,#3317,.T.); #9879=EDGE_CURVE('',#5043,#5054,#3268,.T.); #9881=EDGE_CURVE('',#5051,#5054,#3299,.T.); #9883=EDGE_CURVE('',#5051,#5030,#3272,.T.); #9893=EDGE_CURVE('',#5027,#5028,#3276,.T.); #9896=EDGE_CURVE('',#5030,#5032,#3285,.T.); #9921=EDGE_CURVE('',#5051,#5052,#3294,.T.); #9934=EDGE_CURVE('',#5054,#5056,#3303,.T.); #9945=EDGE_CURVE('',#5043,#5044,#3312,.T.); #9971=EDGE_CURVE('',#5121,#5107,#3330,.T.); #9973=EDGE_CURVE('',#5107,#5108,#3346,.T.); #9975=EDGE_CURVE('',#5122,#5108,#3342,.T.); #9986=EDGE_CURVE('',#5126,#5112,#3334,.T.); #9988=EDGE_CURVE('',#5112,#5107,#3351,.T.); #10000=EDGE_CURVE('',#5124,#5110,#3338,.T.); #10002=EDGE_CURVE('',#5110,#5112,#3355,.T.); #10015=EDGE_CURVE('',#5108,#5110,#3360,.T.); #10038=EDGE_CURVE('',#5140,#5136,#3397,.T.); #10040=EDGE_CURVE('',#5118,#5140,#3365,.T.); #10042=EDGE_CURVE('',#5116,#5118,#3370,.T.); #10044=EDGE_CURVE('',#5115,#5116,#3375,.T.); #10046=EDGE_CURVE('',#5136,#5115,#3379,.T.); #10056=EDGE_CURVE('',#5135,#5136,#3383,.T.); #10059=EDGE_CURVE('',#5139,#5140,#3392,.T.); #10072=EDGE_CURVE('',#5129,#5115,#3401,.T.); #10086=EDGE_CURVE('',#5130,#5116,#3405,.T.); #10099=EDGE_CURVE('',#5132,#5118,#3409,.T.); #10121=EDGE_CURVE('',#5183,#5184,#3413,.T.); #10124=EDGE_CURVE('',#5188,#5186,#3422,.T.); #10126=EDGE_CURVE('',#5188,#5183,#3427,.T.); #10137=EDGE_CURVE('',#5183,#5143,#3444,.T.); #10139=EDGE_CURVE('',#5147,#5143,#3486,.T.); #10150=EDGE_CURVE('',#5191,#5172,#3431,.T.); #10152=EDGE_CURVE('',#5196,#5191,#3478,.T.); #10154=EDGE_CURVE('',#5144,#5196,#3435,.T.); #10156=EDGE_CURVE('',#5143,#5144,#3440,.T.); #10160=EDGE_CURVE('',#5160,#5188,#3448,.T.); #10162=EDGE_CURVE('',#5164,#5160,#3558,.T.); #10164=EDGE_CURVE('',#5152,#5164,#3452,.T.); #10166=EDGE_CURVE('',#5156,#5152,#3540,.T.); #10168=EDGE_CURVE('',#5176,#5156,#3456,.T.); #10170=EDGE_CURVE('',#5180,#5176,#3522,.T.); #10172=EDGE_CURVE('',#5168,#5180,#3460,.T.); #10174=EDGE_CURVE('',#5172,#5168,#3504,.T.); #10184=EDGE_CURVE('',#5191,#5192,#3464,.T.); #10187=EDGE_CURVE('',#5171,#5172,#3499,.T.); #10200=EDGE_CURVE('',#5196,#5194,#3473,.T.); #10213=EDGE_CURVE('',#5148,#5144,#3482,.T.); #10236=EDGE_CURVE('',#5167,#5168,#3490,.T.); #10251=EDGE_CURVE('',#5179,#5180,#3517,.T.); #10262=EDGE_CURVE('',#5175,#5176,#3508,.T.); #10275=EDGE_CURVE('',#5155,#5156,#3535,.T.); #10288=EDGE_CURVE('',#5151,#5152,#3526,.T.); #10303=EDGE_CURVE('',#5163,#5164,#3553,.T.); #10314=EDGE_CURVE('',#5159,#5160,#3544,.T.); #10340=EDGE_CURVE('',#5207,#5199,#3562,.T.); #10342=EDGE_CURVE('',#5199,#5200,#3578,.T.); #10344=EDGE_CURVE('',#5208,#5200,#3574,.T.); #10355=EDGE_CURVE('',#5212,#5204,#3566,.T.); #10357=EDGE_CURVE('',#5204,#5199,#3583,.T.); #10369=EDGE_CURVE('',#5210,#5202,#3570,.T.); #10371=EDGE_CURVE('',#5202,#5204,#3587,.T.); #10384=EDGE_CURVE('',#5200,#5202,#3592,.T.); #10408=EDGE_CURVE('',#5223,#5215,#3596,.T.); #10410=EDGE_CURVE('',#5215,#5216,#3612,.T.); #10412=EDGE_CURVE('',#5224,#5216,#3608,.T.); #10423=EDGE_CURVE('',#5228,#5220,#3600,.T.); #10425=EDGE_CURVE('',#5220,#5215,#3617,.T.); #10437=EDGE_CURVE('',#5226,#5218,#3604,.T.); #10439=EDGE_CURVE('',#5218,#5220,#3621,.T.); #10452=EDGE_CURVE('',#5216,#5218,#3626,.T.); #10476=EDGE_CURVE('',#5239,#5231,#3630,.T.); #10478=EDGE_CURVE('',#5231,#5232,#3646,.T.); #10480=EDGE_CURVE('',#5240,#5232,#3642,.T.); #10491=EDGE_CURVE('',#5244,#5236,#3634,.T.); #10493=EDGE_CURVE('',#5236,#5231,#3651,.T.); #10505=EDGE_CURVE('',#5242,#5234,#3638,.T.); #10507=EDGE_CURVE('',#5234,#5236,#3655,.T.); #10520=EDGE_CURVE('',#5232,#5234,#3660,.T.); #10544=EDGE_CURVE('',#5255,#5247,#3664,.T.); #10546=EDGE_CURVE('',#5247,#5248,#3680,.T.); #10548=EDGE_CURVE('',#5256,#5248,#3676,.T.); #10559=EDGE_CURVE('',#5260,#5252,#3668,.T.); #10561=EDGE_CURVE('',#5252,#5247,#3685,.T.); #10573=EDGE_CURVE('',#5258,#5250,#3672,.T.); #10575=EDGE_CURVE('',#5250,#5252,#3689,.T.); #10588=EDGE_CURVE('',#5248,#5250,#3694,.T.); #10612=EDGE_CURVE('',#5278,#5264,#3702,.T.); #10614=EDGE_CURVE('',#5263,#5264,#3714,.T.); #10616=EDGE_CURVE('',#5277,#5263,#3698,.T.); #10627=EDGE_CURVE('',#5280,#5266,#3706,.T.); #10629=EDGE_CURVE('',#5264,#5266,#3719,.T.); #10641=EDGE_CURVE('',#5282,#5268,#3710,.T.); #10643=EDGE_CURVE('',#5266,#5268,#3723,.T.); #10656=EDGE_CURVE('',#5268,#5263,#3728,.T.); #10679=EDGE_CURVE('',#5480,#5476,#3765,.T.); #10681=EDGE_CURVE('',#5480,#5271,#3732,.T.); #10683=EDGE_CURVE('',#5271,#5272,#3737,.T.); #10685=EDGE_CURVE('',#5272,#5274,#3742,.T.); #10687=EDGE_CURVE('',#5274,#5476,#3747,.T.); #10697=EDGE_CURVE('',#5475,#5476,#3751,.T.); #10700=EDGE_CURVE('',#5479,#5480,#3760,.T.); #10713=EDGE_CURVE('',#5288,#5274,#3769,.T.); #10727=EDGE_CURVE('',#5286,#5272,#3773,.T.); #10740=EDGE_CURVE('',#5285,#5271,#3777,.T.); #10763=EDGE_CURVE('',#5306,#5292,#3785,.T.); #10765=EDGE_CURVE('',#5291,#5292,#3797,.T.); #10767=EDGE_CURVE('',#5305,#5291,#3781,.T.); #10778=EDGE_CURVE('',#5308,#5294,#3789,.T.); #10780=EDGE_CURVE('',#5292,#5294,#3802,.T.); #10792=EDGE_CURVE('',#5310,#5296,#3793,.T.); #10794=EDGE_CURVE('',#5294,#5296,#3806,.T.); #10807=EDGE_CURVE('',#5296,#5291,#3811,.T.); #10830=EDGE_CURVE('',#5472,#5468,#3848,.T.); #10832=EDGE_CURVE('',#5472,#5299,#3815,.T.); #10834=EDGE_CURVE('',#5299,#5300,#3820,.T.); #10836=EDGE_CURVE('',#5300,#5302,#3825,.T.); #10838=EDGE_CURVE('',#5302,#5468,#3830,.T.); #10848=EDGE_CURVE('',#5467,#5468,#3834,.T.); #10851=EDGE_CURVE('',#5471,#5472,#3843,.T.); #10864=EDGE_CURVE('',#5316,#5302,#3852,.T.); #10878=EDGE_CURVE('',#5314,#5300,#3856,.T.); #10891=EDGE_CURVE('',#5313,#5299,#3860,.T.); #10914=EDGE_CURVE('',#5336,#5328,#3868,.T.); #10916=EDGE_CURVE('',#5327,#5328,#3880,.T.); #10918=EDGE_CURVE('',#5335,#5327,#3864,.T.); #10929=EDGE_CURVE('',#5338,#5330,#3872,.T.); #10931=EDGE_CURVE('',#5328,#5330,#3885,.T.); #10943=EDGE_CURVE('',#5340,#5332,#3876,.T.); #10945=EDGE_CURVE('',#5330,#5332,#3889,.T.); #10958=EDGE_CURVE('',#5332,#5327,#3894,.T.); #10982=EDGE_CURVE('',#5352,#5344,#3902,.T.); #10984=EDGE_CURVE('',#5343,#5344,#3914,.T.); #10986=EDGE_CURVE('',#5351,#5343,#3898,.T.); #10997=EDGE_CURVE('',#5354,#5346,#3906,.T.); #10999=EDGE_CURVE('',#5344,#5346,#3919,.T.); #11011=EDGE_CURVE('',#5356,#5348,#3910,.T.); #11013=EDGE_CURVE('',#5346,#5348,#3923,.T.); #11026=EDGE_CURVE('',#5348,#5343,#3928,.T.); #11050=EDGE_CURVE('',#5368,#5360,#3936,.T.); #11052=EDGE_CURVE('',#5359,#5360,#3948,.T.); #11054=EDGE_CURVE('',#5367,#5359,#3932,.T.); #11065=EDGE_CURVE('',#5370,#5362,#3940,.T.); #11067=EDGE_CURVE('',#5360,#5362,#3953,.T.); #11079=EDGE_CURVE('',#5372,#5364,#3944,.T.); #11081=EDGE_CURVE('',#5362,#5364,#3957,.T.); #11094=EDGE_CURVE('',#5364,#5359,#3962,.T.); #11118=EDGE_CURVE('',#5384,#5376,#3970,.T.); #11120=EDGE_CURVE('',#5375,#5376,#3982,.T.); #11122=EDGE_CURVE('',#5383,#5375,#3966,.T.); #11133=EDGE_CURVE('',#5386,#5378,#3974,.T.); #11135=EDGE_CURVE('',#5376,#5378,#3987,.T.); #11147=EDGE_CURVE('',#5388,#5380,#3978,.T.); #11149=EDGE_CURVE('',#5378,#5380,#3991,.T.); #11162=EDGE_CURVE('',#5380,#5375,#3996,.T.); #11186=EDGE_CURVE('',#5405,#5391,#4000,.T.); #11188=EDGE_CURVE('',#5391,#5392,#4016,.T.); #11190=EDGE_CURVE('',#5406,#5392,#4012,.T.); #11201=EDGE_CURVE('',#5410,#5396,#4004,.T.); #11203=EDGE_CURVE('',#5396,#5391,#4021,.T.); #11215=EDGE_CURVE('',#5408,#5394,#4008,.T.); #11217=EDGE_CURVE('',#5394,#5396,#4025,.T.); #11230=EDGE_CURVE('',#5392,#5394,#4030,.T.); #11253=EDGE_CURVE('',#5488,#5484,#4067,.T.); #11255=EDGE_CURVE('',#5402,#5488,#4035,.T.); #11257=EDGE_CURVE('',#5400,#5402,#4040,.T.); #11259=EDGE_CURVE('',#5399,#5400,#4045,.T.); #11261=EDGE_CURVE('',#5484,#5399,#4049,.T.); #11271=EDGE_CURVE('',#5483,#5484,#4053,.T.); #11274=EDGE_CURVE('',#5487,#5488,#4062,.T.); #11287=EDGE_CURVE('',#5413,#5399,#4071,.T.); #11301=EDGE_CURVE('',#5414,#5400,#4075,.T.); #11314=EDGE_CURVE('',#5416,#5402,#4079,.T.); #11336=EDGE_CURVE('',#5451,#5452,#4083,.T.); #11338=EDGE_CURVE('',#5452,#5456,#4088,.T.); #11340=EDGE_CURVE('',#5455,#5456,#4092,.T.); #11353=EDGE_CURVE('',#5422,#5424,#4110,.T.); #11355=EDGE_CURVE('',#5452,#5422,#4216,.T.); #11365=EDGE_CURVE('',#5419,#5420,#4101,.T.); #11367=EDGE_CURVE('',#5419,#5422,#4106,.T.); #11381=EDGE_CURVE('',#5430,#5432,#4128,.T.); #11383=EDGE_CURVE('',#5419,#5430,#4220,.T.); #11393=EDGE_CURVE('',#5427,#5428,#4119,.T.); #11395=EDGE_CURVE('',#5427,#5430,#4124,.T.); #11409=EDGE_CURVE('',#5446,#5448,#4146,.T.); #11411=EDGE_CURVE('',#5427,#5446,#4224,.T.); #11421=EDGE_CURVE('',#5443,#5444,#4137,.T.); #11423=EDGE_CURVE('',#5443,#5446,#4142,.T.); #11435=EDGE_CURVE('',#5438,#5440,#4164,.T.); #11437=EDGE_CURVE('',#5443,#5438,#4228,.T.); #11449=EDGE_CURVE('',#5435,#5436,#4155,.T.); #11451=EDGE_CURVE('',#5435,#5438,#4160,.T.); #11463=EDGE_CURVE('',#5463,#5464,#4182,.T.); #11465=EDGE_CURVE('',#5435,#5464,#4199,.T.); #11477=EDGE_CURVE('',#5459,#5460,#4173,.T.); #11479=EDGE_CURVE('',#5460,#5464,#4178,.T.); #11493=EDGE_CURVE('',#5323,#5319,#4191,.T.); #11495=EDGE_CURVE('',#5460,#5319,#4203,.T.); #11506=EDGE_CURVE('',#5324,#5320,#4195,.T.); #11508=EDGE_CURVE('',#5319,#5320,#4208,.T.); #11520=EDGE_CURVE('',#5320,#5456,#4212,.T.); #11562=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#11550),#11561); #11569=PRODUCT_DEFINITION('design','',#11568,#11565); #11570=PRODUCT_DEFINITION_SHAPE('','SHAPE FOR PROESOURCE.',#11569); #11571=SHAPE_DEFINITION_REPRESENTATION(#11570,#11562); ENDSEC; END-ISO-10303-21; netgen-6.2.1905/tutorials/sculpture.geo0000644000175000017500000000062413504650527016553 0ustar kurtkurtalgebraic3d # # intersection of sphere and cylinders # motivated by a sculpture found in St. Gallen # solid cyls = cylinder ( -100, 0, 0; 200, 0, 0; 40 ) or cylinder ( 100, -100, 100; 100, 200, 100; 40) or cylinder ( 0, 100, -100; 0, 100, 200; 40); solid sculpture = sphere (50, 50, 50; 80) and not cyls and not sphere (50, 50, 50; 50); tlo sculpture -col=[0.5, 0.5, 0.5]; netgen-6.2.1905/tutorials/cylinder.geo0000644000175000017500000000027013504650527016333 0ustar kurtkurt# ## a cylinder # algebraic3d # cut cylinder by planes: solid fincyl = cylinder ( 3, 0, 0; -1, 0, 0; 0.5 ) and plane (0, 0, 0; -1, 0, 0) and plane (2, 0, 0; 1, 0, 0); tlo fincyl; netgen-6.2.1905/tutorials/cylsphere.geo0000644000175000017500000000033213504650527016517 0ustar kurtkurt# ## Cylinder and Spehre # algebraic3d solid cyl = cylinder ( 3, 0, 0; -3, 0, 0; 0.5 ) and plane (-2, 0, 0; -1, 0, 0) and plane (2, 0, 0; 1, 0, 0); solid sp = sphere (0, 0, 0; 1); solid main = sp or cyl; tlo main; netgen-6.2.1905/tutorials/ellipticcyl.geo0000644000175000017500000000026513504650527017043 0ustar kurtkurt# ## An elliptic cylinder # algebraic3d solid cutcone = ellipticcylinder ( 0, 0, 0; 1, 0, 0; 0, 0.5, 0) and plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 1; 0, 0, 1); tlo cutcone; netgen-6.2.1905/tutorials/hinge.stl0000644000175000017500000115516113504650527015657 0ustar kurtkurtsolid facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 3.853128e+001 1.825847e+001 5.000000e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.878911e+001 1.881140e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 3.957044e+001 1.974256e+001 5.000000e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.007020e+001 2.009249e+001 5.000000e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.121243e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.242797e+001 2.050823e+001 5.000000e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.406996e+001 1.974256e+001 5.000000e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 3.947097e+001 1.620635e+001 4.399139e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 3.965514e+001 1.581140e+001 4.399139e+000 vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 3.990509e+001 1.545443e+001 4.399139e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 4.021323e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.514629e+001 4.399139e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.057020e+001 1.489634e+001 4.399139e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.096515e+001 1.471217e+001 4.399139e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.096515e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.096515e+001 1.471217e+001 4.399139e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.138608e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.138608e+001 1.459938e+001 4.399139e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.182020e+001 1.456140e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.456140e+001 4.399139e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 vertex 4.242797e+001 1.361457e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.242797e+001 1.361457e+001 5.000000e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.307020e+001 1.489634e+001 4.399139e+000 vertex 4.267525e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 vertex 4.307020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.307020e+001 1.489634e+001 4.399139e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 vertex 4.342717e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 4.342717e+001 1.514629e+001 4.399139e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 4.373531e+001 1.545443e+001 4.399139e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.485129e+001 1.531140e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.485129e+001 1.531140e+001 5.000000e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.620635e+001 4.399139e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.620635e+001 4.399139e+000 vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 4.510912e+001 1.586433e+001 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 4.428222e+001 1.662728e+001 4.399139e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.432020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 vertex 4.526703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.526703e+001 1.766917e+001 5.000000e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.398526e+001 1.831140e+001 4.399139e+000 vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.406996e+001 1.974256e+001 5.000000e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 4.406996e+001 1.974256e+001 5.000000e+000 vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.526703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.373531e+001 1.545443e+001 4.399139e+000 vertex 4.485129e+001 1.531140e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 4.342717e+001 1.514629e+001 4.399139e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.373531e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.242797e+001 1.361457e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.182020e+001 1.456140e+001 4.399139e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.432020e+001 1.706140e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.432020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -9.048915e-016 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 outer loop vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -1.030095e-015 outer loop vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.416943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 1.440206e-016 outer loop vertex 4.398526e+001 1.831140e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -1.586601e-015 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 4.399139e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 outer loop vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.373531e+001 1.866837e+001 4.399139e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -1.324456e-015 outer loop vertex 4.307020e+001 1.922646e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 4.399139e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -1.217252e-015 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 4.399139e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 outer loop vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.267525e+001 1.941063e+001 4.399139e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 outer loop vertex 4.182020e+001 1.956140e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.182020e+001 1.956140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -2.500203e-016 outer loop vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.138608e+001 1.952342e+001 4.399139e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -9.292106e-016 outer loop vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 4.399139e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -9.250596e-016 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.021323e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -1.142109e-015 outer loop vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -1.059565e-015 outer loop vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 4.399139e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -4.853241e-016 outer loop vertex 3.947097e+001 1.791645e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 4.399139e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 outer loop vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.935818e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.038636e-017 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 4.399139e+000 vertex 3.935818e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.947097e+001 1.620635e+001 4.399139e+000 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 2.316081e-016 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 4.399139e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 2.855272e-016 outer loop vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 3.990509e+001 1.545443e+001 4.399139e+000 vertex 4.021323e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 3.307707e-016 outer loop vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 4.021323e+001 1.514629e+001 4.399139e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -6.826070e-016 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 4.399139e+000 vertex 4.096515e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -4.180408e-016 outer loop vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 4.096515e+001 1.471217e+001 4.399139e+000 vertex 4.138608e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.138608e+001 1.459938e+001 4.399139e+000 vertex 4.182020e+001 1.456140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.182020e+001 1.456140e+001 4.399139e+000 vertex 4.225432e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 2.800343e-017 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.267525e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -3.659639e-016 outer loop vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.307020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 5.956618e-016 outer loop vertex 4.342717e+001 1.514629e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 4.399139e+000 vertex 4.342717e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 4.399139e+000 vertex 4.373531e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.373531e+001 1.545443e+001 4.399139e+000 vertex 4.398526e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.416943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 4.428222e+001 1.662728e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 4.399139e+000 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 4.428222e+001 1.662728e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.373531e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 8.614567e-016 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -3.257609e-016 outer loop vertex 4.342717e+001 1.514629e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 3.166431e-016 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 endloop endfacet facet normal -2.588190e-001 9.659258e-001 0.000000e+000 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.182020e+001 1.456140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -1.411631e-016 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 4.138608e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -4.198697e-016 outer loop vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 4.096515e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 3.691957e-016 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 3.330001e-016 outer loop vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 4.021323e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 2.855272e-016 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 3.990509e+001 1.545443e+001 4.399139e+000 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal 8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 2.090204e-016 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.947097e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.040056e-016 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 3.935818e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 1.030095e-015 outer loop vertex 3.947097e+001 1.791645e+001 -8.881784e-016 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.935818e+001 1.749552e+001 -8.881784e-016 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 1.954566e-016 outer loop vertex 3.947097e+001 1.791645e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 2.606088e-016 outer loop vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 5.710544e-016 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 3.981523e-016 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 1.216174e-015 outer loop vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 5.284567e-016 outer loop vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 outer loop vertex 4.182020e+001 1.956140e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 2.497501e-016 outer loop vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 2.461305e-016 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 outer loop vertex 4.307020e+001 1.922646e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 0.000000e+000 outer loop vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 1.520218e-015 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 4.850219e-016 outer loop vertex 4.398526e+001 1.831140e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.235818e+001 1.262728e+001 4.399139e+000 vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.247097e+001 1.220635e+001 4.399139e+000 vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 vertex 2.213904e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 vertex 2.362313e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.362313e+001 9.772476e+000 5.000000e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.438608e+001 1.059938e+001 4.399139e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.438608e+001 1.059938e+001 4.399139e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.421243e+001 9.614573e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.056140e+001 4.399139e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 vertex 2.601727e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.601727e+001 9.772476e+000 5.000000e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.607020e+001 1.089634e+001 4.399139e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.607020e+001 1.089634e+001 4.399139e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.657020e+001 1.003031e+001 5.000000e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.642717e+001 1.114629e+001 4.399139e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 2.785129e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.728222e+001 1.262728e+001 4.399139e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.716943e+001 1.391645e+001 4.399139e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.673531e+001 1.466837e+001 4.399139e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.642717e+001 1.497651e+001 4.399139e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.607020e+001 1.522646e+001 4.399139e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.556140e+001 4.399139e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.438608e+001 1.552342e+001 4.399139e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.321323e+001 1.497651e+001 4.399139e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 2.257044e+001 1.574256e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 vertex 2.257044e+001 1.574256e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.290509e+001 1.466837e+001 4.399139e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.265514e+001 1.431140e+001 4.399139e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 vertex 2.137337e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.232020e+001 1.306140e+001 4.399139e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.137337e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.728222e+001 1.262728e+001 4.399139e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.785129e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.601727e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.362313e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.213904e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 -3.438588e-017 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 2.732020e+001 1.306140e+001 0.000000e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -6.515219e-017 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.728222e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 1.414640e-015 outer loop vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.716943e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -3.545305e-016 outer loop vertex 2.716943e+001 1.391645e+001 0.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 -7.585588e-016 outer loop vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -2.635182e-016 outer loop vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -5.710544e-016 outer loop vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -8.612394e-016 outer loop vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -4.853241e-016 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -5.300545e-016 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 outer loop vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -5.029161e-016 outer loop vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -6.400577e-016 outer loop vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -5.879071e-016 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.357020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -5.942889e-016 outer loop vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -5.710544e-016 outer loop vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -8.612394e-016 outer loop vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -3.146724e-016 outer loop vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 outer loop vertex 2.235818e+001 1.349552e+001 0.000000e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 outer loop vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 3.519318e-017 outer loop vertex 2.235818e+001 1.262728e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 -5.710544e-016 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 1.706518e-016 outer loop vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 2.316081e-016 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 -2.855272e-016 outer loop vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 0.000000e+000 outer loop vertex 2.357020e+001 1.089634e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -3.413035e-016 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -2.090204e-016 outer loop vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.438608e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -7.038636e-017 outer loop vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 4.399139e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 -3.318735e-016 outer loop vertex 2.525432e+001 1.059938e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 2.090204e-016 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 0.000000e+000 outer loop vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.607020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 1.324456e-016 outer loop vertex 2.642717e+001 1.114629e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 4.399139e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 5.710544e-016 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 -3.413035e-016 outer loop vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 -1.045102e-016 outer loop vertex 2.728222e+001 1.262728e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 -2.063153e-016 outer loop vertex 2.728222e+001 1.262728e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 6.587610e-016 outer loop vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 2.895653e-016 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 0.000000e+000 outer loop vertex 2.642717e+001 1.114629e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 3.402392e-016 outer loop vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 -1.845979e-016 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 7.058154e-017 outer loop vertex 2.525432e+001 1.059938e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -7.058154e-017 outer loop vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -2.099348e-016 outer loop vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 0.000000e+000 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 -1.303044e-016 outer loop vertex 2.357020e+001 1.089634e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 2.895653e-016 outer loop vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 2.316522e-016 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -3.909131e-016 outer loop vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 1.049674e-016 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.040056e-016 outer loop vertex 2.235818e+001 1.262728e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 outer loop vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 1.134605e-015 outer loop vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.235818e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 5.863697e-016 outer loop vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 9.266089e-016 outer loop vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 8.542176e-016 outer loop vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 8.612394e-016 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.321323e+001 1.497651e+001 0.000000e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 8.542176e-016 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 9.193698e-016 outer loop vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 outer loop vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 9.051759e-016 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 1.031576e-015 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 5.863697e-016 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 9.266089e-016 outer loop vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 1.143783e-015 outer loop vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 6.298045e-016 outer loop vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 1.049674e-015 outer loop vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 4.320200e+000 1.706140e+001 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 4.373373e+000 1.766917e+001 5.000000e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex 4.373373e+000 1.766917e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.789111e+000 1.881140e+001 5.000000e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 6.070200e+000 2.009249e+001 5.000000e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 6.623129e+000 2.035032e+001 5.000000e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 6.623129e+000 2.035032e+001 5.000000e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 7.212431e+000 2.050823e+001 5.000000e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 7.386080e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 7.820200e+000 2.056140e+001 5.000000e+000 vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 vertex 9.070200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 9.070200e+000 1.922646e+001 4.399139e+000 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 1.050136e+001 1.931116e+001 5.000000e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 1.085129e+001 1.881140e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 1.126703e+001 1.766917e+001 5.000000e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 1.126703e+001 1.766917e+001 5.000000e+000 vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 5.655136e+000 1.581140e+001 4.399139e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 vertex 5.655136e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 5.655136e+000 1.581140e+001 4.399139e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 5.905089e+000 1.545443e+001 4.399139e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex 5.570443e+000 1.438024e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 5.570443e+000 1.438024e+001 5.000000e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 6.965150e+000 1.471217e+001 4.399139e+000 vertex 6.570200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 6.965150e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 9.070200e+000 1.489634e+001 4.399139e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.545443e+001 4.399139e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.545443e+001 4.399139e+000 vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 1.050136e+001 1.481164e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 9.985264e+000 1.581140e+001 4.399139e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 1.016943e+001 1.620635e+001 4.399139e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.028222e+001 1.662728e+001 4.399139e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 1.028222e+001 1.662728e+001 4.399139e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.032020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 9.070200e+000 1.922646e+001 4.399139e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 9.570200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 vertex 9.570200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 9.070200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 9.070200e+000 1.489634e+001 4.399139e+000 vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 5.570443e+000 1.438024e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 5.358181e+000 1.662728e+001 4.399139e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 5.358181e+000 1.662728e+001 4.399139e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 -8.881784e-016 vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -9.067013e-016 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 outer loop vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -6.400577e-016 outer loop vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 -5.879071e-016 outer loop vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 4.399139e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -5.942889e-016 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 9.735311e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -6.296313e-016 outer loop vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 4.399139e+000 vertex 9.070200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -1.046600e-015 outer loop vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 4.399139e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 4.399139e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 outer loop vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 8.254320e+000 1.952342e+001 4.399139e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 outer loop vertex 7.386080e+000 1.952342e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 4.399139e+000 vertex 7.386080e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -3.545305e-016 outer loop vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -7.585588e-016 outer loop vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 6.570200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -1.040864e-015 outer loop vertex 6.213231e+000 1.897651e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -8.565816e-016 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 4.399139e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -3.980232e-016 outer loop vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -8.512880e-016 outer loop vertex 5.470968e+000 1.791645e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 4.399139e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -7.250733e-016 outer loop vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 5.358181e+000 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 outer loop vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.038636e-017 outer loop vertex 5.358181e+000 1.662728e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 4.399139e+000 vertex 5.358181e+000 1.662728e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 -3.900374e-016 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 4.399139e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -1.829819e-016 outer loop vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.470968e+000 1.620635e+001 4.399139e+000 vertex 5.655136e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 6.622278e-017 outer loop vertex 5.905089e+000 1.545443e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 4.399139e+000 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 -6.583952e-030 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 4.399139e+000 vertex 6.213231e+000 1.514629e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 2.149666e-016 outer loop vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 6.570200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -2.559776e-016 outer loop vertex 6.965150e+000 1.471217e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 6.965150e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -1.567653e-016 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 4.399139e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -1.759659e-017 outer loop vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 7.820200e+000 1.456140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 7.038636e-017 outer loop vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 8.254320e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 -2.855272e-016 outer loop vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 8.675250e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -1.953121e-016 outer loop vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 9.070200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -9.916256e-017 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 4.399139e+000 vertex 9.427169e+000 1.514629e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 9.735311e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 4.399139e+000 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 3.659639e-016 outer loop vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 9.985264e+000 1.581140e+001 4.399139e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 4.399139e+000 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 3.909131e-016 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.427169e+000 1.514629e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -9.410872e-017 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -1.954566e-016 outer loop vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 8.675250e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 2.099348e-016 outer loop vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 1.809783e-017 outer loop vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -5.429349e-017 outer loop vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 7.386080e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -1.592609e-016 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 2.750870e-016 outer loop vertex 6.965150e+000 1.471217e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 9.916256e-017 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 endloop endfacet facet normal 7.071068e-001 7.071068e-001 1.447826e-016 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 -1.592609e-016 outer loop vertex 5.905089e+000 1.545443e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -3.691957e-016 outer loop vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 2.099348e-016 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.040056e-016 outer loop vertex 5.358181e+000 1.662728e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 7.040056e-016 outer loop vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex 5.358181e+000 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 6.400577e-016 outer loop vertex 5.470968e+000 1.791645e+001 -8.881784e-016 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 5.358181e+000 1.749552e+001 -8.881784e-016 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 9.338481e-016 outer loop vertex 5.470968e+000 1.791645e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 5.942889e-016 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 4.271088e-016 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 6.298045e-016 outer loop vertex 6.213231e+000 1.897651e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 1.049674e-015 outer loop vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex 6.965150e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 5.300545e-016 outer loop vertex 7.386080e+000 1.952342e+001 -8.881784e-016 vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 6.965150e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 outer loop vertex 7.386080e+000 1.952342e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 outer loop vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 3.547175e-016 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 7.601089e-016 outer loop vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 outer loop vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 8.542176e-016 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.735311e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 8.614567e-016 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 9.985264e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 8.542176e-016 outer loop vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 outer loop vertex 1.482020e+001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 2.425509e-016 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -4.635355e-016 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 -2.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 5.101317e-016 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -5.234721e-016 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -4.809511e-016 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -5.134128e-016 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -5.024296e-016 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -4.870609e-016 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal -4.973720e-016 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal -4.930284e-016 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -4.799411e-016 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 2.000000e+000 vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 1.561400e+000 2.401924e+000 vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 -1.438600e+000 7.598076e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex -1.798000e-001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 2.880478e+000 3.973940e+000 vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex -1.798000e-001 1.561400e+000 2.401924e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 1.561400e+000 2.401924e+000 vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex -1.798000e-001 6.140000e-002 2.000000e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 4.891892e-016 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 2.000000e+000 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal 4.741508e-016 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal 4.759201e-016 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 4.706124e-016 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 4.599971e-016 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 4.812277e-016 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 4.546894e-016 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 outer loop vertex 3.482020e+001 -2.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 outer loop vertex 4.982020e+001 -2.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 2.425509e-016 9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -2.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -4.635355e-016 9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -2.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 5.101317e-016 9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -5.234721e-016 9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -4.809511e-016 9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -5.134128e-016 8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -5.024296e-016 7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -4.870609e-016 5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal -4.973720e-016 4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal -4.930284e-016 2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -4.799411e-016 8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 4.982020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 4.982020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 outer loop vertex 3.482020e+001 3.061400e+000 5.000000e+000 vertex 4.982020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 -1.866963e+000 7.298133e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 3.061400e+000 5.000000e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 outer loop vertex 3.482020e+001 3.061400e+000 5.000000e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 1.561400e+000 2.401924e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 3.482020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 4.891892e-016 8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 2.000000e+000 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal 4.741508e-016 2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal 4.759201e-016 4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 4.706124e-016 5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 4.599971e-016 7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 4.812277e-016 8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 4.546894e-016 9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 3.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 3.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 4.150665e+000 6.093379e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 4.813319e+000 1.336768e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 3.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 3.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 3.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 3.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 3.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 3.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 3.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.966323e-001 8.200039e-002 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal -4.306895e-017 -9.698266e-001 2.437957e-001 outer loop vertex 3.482020e+001 5.980711e+000 4.019309e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 vertex 3.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal -4.425936e-017 -9.966323e-001 8.200039e-002 outer loop vertex 3.482020e+001 5.980711e+000 4.019309e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal 1.692405e-017 -9.698266e-001 2.437957e-001 outer loop vertex 1.482020e+001 5.980711e+000 4.019309e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal -3.581497e-018 -9.169362e-001 3.990338e-001 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 0.000000e+000 -9.169362e-001 3.990338e-001 outer loop vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 1.313813e-017 -8.393837e-001 5.435393e-001 outer loop vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 4.813319e+000 1.336768e+000 endloop endfacet facet normal 0.000000e+000 -7.392549e-001 6.734257e-001 outer loop vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 4.150665e+000 6.093379e-001 endloop endfacet facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 4.150665e+000 6.093379e-001 endloop endfacet facet normal 2.820675e-018 -7.392549e-001 6.734257e-001 outer loop vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 4.813319e+000 1.336768e+000 endloop endfacet facet normal 0.000000e+000 -8.393837e-001 5.435393e-001 outer loop vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.268727e+000 2.500000e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex 1.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.980711e+000 4.019309e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.007020e+001 1.403031e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.062313e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.182020e+001 1.356140e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.242797e+001 1.361457e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.242797e+001 1.361457e+001 5.000000e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.657020e+001 1.609249e+001 5.000000e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.542797e+001 1.650823e+001 5.000000e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 vertex 9.017271e+000 2.035032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 2.482020e+001 1.656140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.126703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 1.126703e+001 1.766917e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.257044e+001 1.574256e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.126703e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.153128e+001 1.425847e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.132020e+001 1.306140e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.007020e+001 2.009249e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 9.017271e+000 2.035032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.406996e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.406996e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.526703e+001 1.766917e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.526703e+001 1.766917e+001 5.000000e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.485129e+001 1.531140e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.485129e+001 1.531140e+001 5.000000e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 vertex 3.913904e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.257044e+001 1.574256e+001 5.000000e+000 vertex 1.126703e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.257044e+001 1.574256e+001 5.000000e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 1.126703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.601727e+001 9.772476e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.601727e+001 9.772476e+000 5.000000e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.362313e+001 9.772476e+000 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.362313e+001 9.772476e+000 5.000000e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.132020e+001 1.306140e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 vertex 2.137337e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.373373e+000 1.766917e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.373373e+000 1.766917e+001 5.000000e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.623129e+000 2.035032e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.623129e+000 2.035032e+001 5.000000e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.570443e+000 1.438024e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.570443e+000 1.438024e+001 5.000000e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 outer loop vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 outer loop vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 outer loop vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 outer loop vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 -9.961947e-001 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal -5.124559e-017 -8.715574e-002 -9.961947e-001 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 outer loop vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 outer loop vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 outer loop vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 0.000000e+000 2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 1.432567e-016 1.253334e-017 -1.000000e+000 outer loop vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.432020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal 1.174024e-016 3.145787e-017 -1.000000e+000 outer loop vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 9.887861e-017 4.610785e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 8.409715e-017 5.888546e-017 -1.000000e+000 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.398526e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.118001e-017 7.118001e-017 -1.000000e+000 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 5.888546e-017 8.409715e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 -8.881784e-016 endloop endfacet facet normal 4.610785e-017 9.887861e-017 -1.000000e+000 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.307020e+001 1.922646e+001 -8.881784e-016 endloop endfacet facet normal 3.145787e-017 1.174024e-016 -1.000000e+000 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 1.253334e-017 1.432567e-016 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 -8.881784e-016 endloop endfacet facet normal -1.618835e-017 1.850337e-016 -1.000000e+000 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.182020e+001 1.956140e+001 -8.881784e-016 endloop endfacet facet normal -7.259975e-017 2.709460e-016 -1.000000e+000 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 1.571783e-016 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.383491e-031 1.571783e-016 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 7.259975e-017 2.709460e-016 -1.000000e+000 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 1.618835e-017 1.850337e-016 -1.000000e+000 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.253334e-017 1.432567e-016 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 7.386080e+000 1.952342e+001 -8.881784e-016 endloop endfacet facet normal -3.145787e-017 1.174024e-016 -1.000000e+000 outer loop vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 7.386080e+000 1.952342e+001 -8.881784e-016 endloop endfacet facet normal -4.610785e-017 9.887861e-017 -1.000000e+000 outer loop vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -5.888546e-017 8.409715e-017 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 -8.881784e-016 endloop endfacet facet normal -7.118001e-017 7.118001e-017 -1.000000e+000 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 6.213231e+000 1.897651e+001 -8.881784e-016 endloop endfacet facet normal -8.409715e-017 5.888546e-017 -1.000000e+000 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -9.887861e-017 4.610785e-017 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex 5.470968e+000 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -1.174024e-016 3.145787e-017 -1.000000e+000 outer loop vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.470968e+000 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -1.432567e-016 1.253334e-017 -1.000000e+000 outer loop vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.850337e-016 -1.618835e-017 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -2.709460e-016 -7.259975e-017 -1.000000e+000 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.358181e+000 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -1.015055e-016 3.552714e-017 -1.000000e+000 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 -8.881784e-016 endloop endfacet facet normal 6.691135e-017 -3.482212e-017 -1.000000e+000 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -7.350854e-018 -8.402064e-017 -1.000000e+000 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 6.587563e-018 -7.529618e-017 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 2.265514e+001 1.181140e+001 0.000000e+000 endloop endfacet facet normal 4.990041e-017 -4.995282e-017 -1.000000e+000 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.357020e+001 1.089634e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.525432e+001 1.059938e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.642717e+001 1.114629e+001 0.000000e+000 endloop endfacet facet normal -4.990041e-017 -4.995282e-017 -1.000000e+000 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 endloop endfacet facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 4.096515e+001 1.471217e+001 -8.881784e-016 endloop endfacet facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 0.000000e+000 endloop endfacet facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 2.728222e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 endloop endfacet facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 3.990509e+001 1.545443e+001 -8.881784e-016 endloop endfacet facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 2.716943e+001 1.391645e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 0.000000e+000 endloop endfacet facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 0.000000e+000 endloop endfacet facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 3.947097e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 2.607020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 -8.881784e-016 endloop endfacet facet normal 3.279817e-031 -2.423364e-016 -1.000000e+000 outer loop vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal 1.631843e-017 -1.865205e-016 -1.000000e+000 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 0.000000e+000 endloop endfacet facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 9.985264e+000 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.719385e-017 7.719385e-017 -1.000000e+000 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 2.438608e+001 1.552342e+001 0.000000e+000 endloop endfacet facet normal -8.446175e-017 1.206239e-016 -1.000000e+000 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 endloop endfacet facet normal -1.631843e-017 -1.865205e-016 -1.000000e+000 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal -7.719385e-017 7.719385e-017 -1.000000e+000 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 2.525432e+001 1.552342e+001 0.000000e+000 endloop endfacet facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.947097e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 3.947097e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 2.642717e+001 1.497651e+001 0.000000e+000 endloop endfacet facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 3.935818e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 2.698526e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 2.716943e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 endloop endfacet facet normal -6.587563e-018 -7.529618e-017 -1.000000e+000 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 7.350854e-018 -8.402064e-017 -1.000000e+000 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -6.691135e-017 -3.482212e-017 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -5.921189e-017 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 2.709460e-016 -7.259975e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal 1.850337e-016 -1.618835e-017 -1.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.428222e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 9.985264e+000 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.357020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 2.357020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 -8.881784e-016 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 1.028222e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 0.000000e+000 endloop endfacet facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.247097e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 2.235818e+001 1.349552e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 0.000000e+000 endloop endfacet facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 2.235818e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 endloop endfacet facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 8.675250e+000 1.471217e+001 -8.881784e-016 endloop endfacet facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 8.446175e-017 1.206239e-016 -1.000000e+000 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 endloop endfacet facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 2.235818e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 9.735311e+000 1.545443e+001 -8.881784e-016 endloop endfacet facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 2.265514e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 1.016943e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 5.921189e-017 0.000000e+000 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.015055e-016 3.552714e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 1.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 1.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 vertex -1.798000e-001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.268727e+000 2.500000e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex -1.798000e-001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex -1.798000e-001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.000000e+000 -2.095500e-016 -1.548743e-015 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 1.776357e-016 0.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 -2.628500e-015 1.840496e-015 outer loop vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 -2.086809e-015 9.730950e-016 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex -1.798000e-001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 -1.863973e-015 4.994500e-016 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 -1.776357e-015 1.554111e-016 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 -1.776357e-015 -1.554111e-016 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex -1.798000e-001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 2.561400e+000 9.330127e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 1.771501e+000 9.698463e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex -1.798000e-001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex -1.798000e-001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex -1.798000e-001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex -1.798000e-001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex -1.798000e-001 4.391527e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 -7.105427e-016 4.029688e-015 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -1.061532e-017 -8.715574e-002 -9.961947e-001 outer loop vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 5.124559e-017 -8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 2.547676e-017 -2.588190e-001 -9.659258e-001 outer loop vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal -3.065033e-017 -2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 4.246127e-018 -4.226183e-001 -9.063078e-001 outer loop vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 3.616145e-018 -4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 8.492254e-018 -5.735764e-001 -8.191520e-001 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal -2.427694e-017 -5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex -1.798000e-001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 outer loop vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal -4.186913e-017 -7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 2.123063e-017 -8.191520e-001 -5.735764e-001 outer loop vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -4.268727e+000 2.500000e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal -2.908199e-017 -8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal -3.616145e-018 -9.063078e-001 -4.226183e-001 outer loop vertex 1.482020e+001 -4.268727e+000 2.500000e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 -4.268727e+000 2.500000e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 6.130066e-017 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -2.802264e-017 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 3.318329e-017 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 7.232290e-018 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -2.172279e-030 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 3.884310e-017 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal 8.428841e-017 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal -2.322295e-017 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 4.159406e-017 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal 5.816399e-017 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 3.884310e-017 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 7.145594e-017 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 1.910757e-017 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal -8.492254e-018 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal -4.344559e-030 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.153573e-017 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -6.793803e-017 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 2.866136e-017 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal -8.492254e-018 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal -5.944578e-017 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -3.821514e-017 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal -1.910757e-017 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal -9.023020e-017 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 2.016910e-017 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 4.982020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 4.982020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 4.982020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -1.648701e+000 3.015369e-001 endloop endfacet endsolid netgen-6.2.1905/tutorials/cubeandspheres.geo0000644000175000017500000000072713504650527017524 0ustar kurtkurt# ## Cube and Spheres # algebraic3d # a cube solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); # two shperes solid sph1 = sphere (0.5, 0.5, 0.5; 0.58); solid sph2 = sphere (0.5, 0.5, 0.5; 0.75); # cut cube with inner and outer sphere solid main = cube and sph2 and not sph1; tlo main; netgen-6.2.1905/tutorials/manyholes.geo0000644000175000017500000000070013504650527016517 0ustar kurtkurtalgebraic3d # ## CSG feature copy # # define a axis parallel brick: solid br = orthobrick (0, 0, 0; 10, 10, 1); # define reference cylinder: solid cyl1 = cylinder (0.5, 0.5, -1; 0.5, 0.5, 3; 0.2); # make copies: solid cylx = multitranslate (1, 0, 0; 9; cyl1); solid cyls = multitranslate (0, 1, 0; 9; cylx); solid main = br and not cyls; tlo main; # provide bounding-box for fastening bisection alg: boundingbox (-1, -1, -1; 11, 11, 2); netgen-6.2.1905/tutorials/circle_on_cube.geo0000644000175000017500000000077213504650527017464 0ustar kurtkurt# ## A cube # algebraic3d # cube consisting of 6 planes: solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid top = plane (1,1,1; 0, 0, 1); solid cyl = top and plane (0,0,0; 0, 0, -1) and cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.2); tlo cube; # take just surface 'top' of solid 'cyl' tlo cyl top -col=[1,0,0]; netgen-6.2.1905/tutorials/cubemsphere.geo0000644000175000017500000000057413504650527017033 0ustar kurtkurt# ## Cube minus Cylinder # algebraic3d solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid sp = sphere (0.5, 0.5, 0; 0.001); # cut off small sphere: solid main = cube and not sp; tlo main; netgen-6.2.1905/tutorials/boxcyl.geo0000644000175000017500000000105613504650527016025 0ustar kurtkurt# ## Two cylinders on a box # algebraic3d #define box: solid box = plane (0, 0, 0.5; -1, 0, 0) and plane (0, 0, 0.5; 0, -1, 0) and plane (0, 0, 0.5; 0, 0, -1) and plane (2, 1.5, 1; 1, 0, 0) and plane (2, 1.5, 1; 0, 1, 0) and plane (2, 1.5, 1; 0, 0, 1); #define cylinders: solid cyls = (cylinder (0.5, 0.75, 0; 0.5, 0.75, 2; 0.3) or cylinder (1.5, 0.75, 0; 1.5, 0.75, 2; 0.3) ) and plane (0, 0, 0.7; 0, 0, -1) and plane (0, 0, 1.5; 0, 0, 1); #combine both: solid main = box or cyls; #define sub-domains: tlo main; singular edge box cyls; netgen-6.2.1905/tutorials/cubeandring.geo0000644000175000017500000000121013504650527016776 0ustar kurtkurtalgebraic3d curve2d testcurve=(8; -0.5,1; -0.55,1.5; # -0.275,1.775; -0.5,2; 0,2.05; 0.5,2; 0.55,1.5; 0.5,1; 0,0.95; 4; 3,8,1,2; 3,2,3,4; 3,4,5,6; 3,6,7,8); #curve2d testcurve=(8; # -0.5,1; # -0.55,1.5; # -0.5,2; # 0,2.05; # 0.5,2; # 0.55,1.5; # 0.5,1; # 0,0.95; # 4; # 3,8,1,2; # 3,2,3,4; # 3,4,5,6; # 3,6,7,8); curve2d testcurve1=(4; -0.55,1.5; 0,2.05; 0.55,1.5; 0,0.95; 4; 2,1,2; 2,2,3; 2,3,4; 2,4,1); solid mytorus = revolution(0,0,0.5;1,0,0.5;testcurve); #solid mytorus = revolution(0,0,0.5;1,0,0.5;testcurve1); solid bbb = orthobrick(-4,-4,-4;4,4,0.1); solid brickandring = mytorus or bbb; tlo brickandring; netgen-6.2.1905/tutorials/shaft.geo0000644000175000017500000000435713504650527015641 0ustar kurtkurt# ## Crankshaft # algebraic3d solid p1 = plane (0, 0, 0; -1, 0, 0) and plane (10, 0, 0; 1, 0, 0) and ( plane (35, 0, 28; 0, -1, 3) and plane (35, 0, -28; 0, -1, -3) and plane (35, 0, 0; 0, 1, 0) and plane (35, -30, 0; 0, -1, 0) or cylinder (-10, 0, 0; 20, 0, 0; 30) or cylinder (-10, -30, 0; 20, -30, 0; 20) ); solid p2 = plane (35, 0, 0; -1, 0, 0) and plane (45, 0, 0; 1, 0, 0) and ( plane (35, 0, 28; 0, -1, 3) and plane (35, 0, -28; 0, -1, -3) and plane (35, 0, 0; 0, 1, 0) and plane (35, -30, 0; 0, -1, 0) or cylinder (30, 0, 0; 50, 0, 0; 30) or cylinder (30, -30, 0; 50, -30, 0; 20) ); solid p3 = plane (80, 0, 0; -1, 0, 0) and plane (90, 0, 0; 1, 0, 0) and ( plane (0, 0, 28; 0, 1, 3) and plane (0, 0, -28; 0, 1, -3) and plane (0, 0, 0; 0, -1, 0) and plane (0, 30, 0; 0, 1, 0) or cylinder (70, 0, 0; 100, 0, 0; 30) or cylinder (70, 30, 0; 100, 30, 0; 20) ); solid p4 = plane (115, 0, 0; -1, 0, 0) and plane (125, 0, 0; 1, 0, 0) and ( plane (35, 0, 28; 0, 1, 3) and plane (35, 0, -28; 0, 1, -3) and plane (35, 0, 0; 0, -1, 0) and plane (35, 30, 0; 0, 1, 0) or cylinder (110, 0, 0; 130, 0, 0; 30) or cylinder (110, 30, 0;130, 30, 0; 20) ); solid sh1 = cylinder (-50, 0, 0; 10, 0, 0; 15) and plane (-40, 0, 0; -1, 0, 0) and plane (5, 0, 0; 1, 0, 0); solid sh2 = cylinder (30, 0, 0; 90, 0, 0; 15) and plane (40, 0, 0; -1, 0, 0) and plane (85, 0, 0; 1, 0, 0); solid sh3 = cylinder (110, 0, 0; 170, 0, 0; 15) and plane (120, 0, 0; -1, 0, 0) and plane (165, 0, 0; 1, 0, 0); solid pl1 = cylinder (0, -30, 0; 50, -30, 0; 10) and plane (5, 0, 0; -1, 0, 0) and plane (40, 0, 0; 1, 0, 0); solid pl2 = cylinder (80, 30, 0; 130, 30, 0; 10) and plane (85, 0, 0; -1, 0, 0) and plane (120, 0, 0; 1, 0, 0); # # solid main = p1 or p2 or p3 or p4 or sh1 or sh2 or sh3 or pl1 or pl2; tlo main; netgen-6.2.1905/tutorials/test.dem0000644000175000017500000000072713504650527015503 0ustar kurtkurt# Demo file t = 0; camerapos (0 : -7,0,0; 1: -6,0,0; 10: -5,0,0); camerapos (10: -5,0,0; 11: -5,-5,0; 12: 0,-5,0); camerapos (12: 0,-5,0); camerapos (14: 0,-5,0; 15: 0,-4,0); camerapos (15: 0,-4,0; 16: 4,-4,0; 17: 4,0,0); camerapos (17: 4,0,0; 18: 4,4,0; 19: 0,4,0); camerapos (19: 0,4,0; 20: -4,4,0; 21: -4,0,0); camerapos (21: -4,0,0); camerapos (22: 0,-4,-4); camerapos (23: -4,0,-4); camerapos (24: -4,-4,-4); camerapos (25: -4,-4,-4; 30: 4,-4,-4; 35: 4,4,4); netgen-6.2.1905/tutorials/fichera.geo0000644000175000017500000000114513504650527016125 0ustar kurtkurt# ## Fichera Cube # algebraic3d solid c1 = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0) -bc=2; solid c2 = plane (-0.5, -0.5, -0.5; 0, 0, -1) and plane (-0.5, -0.5, -0.5; 0, -1, 0) and plane (-0.5, -0.5, -0.5; -1, 0, 0) and plane (0.5, 0.5, 0.5; 0, 0, 1) and plane (0.5, 0.5, 0.5; 0, 1, 0) and plane (0.5, 0.5, 0.5; 1, 0, 0); # cut off small cube solid main = c1 and not c2 -bc=1; tlo main; netgen-6.2.1905/tutorials/twobricks.geo0000644000175000017500000000065213504650527016535 0ustar kurtkurtalgebraic3d solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid cutplane = plane (0.5, 0, 0; -1, 0, 0); solid right = cube and cutplane; solid left = cube and not cutplane; tlo right -col=[1,0,0] -material=copper; tlo left -col=[0,0,1]; netgen-6.2.1905/tutorials/twocubes.geo0000644000175000017500000000067213504650527016363 0ustar kurtkurtalgebraic3d # example with two sub-domains solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); solid cutplane = plane (0.5, 0, 0; -1, 0, 0); solid right = cube and cutplane; solid left = cube and not cutplane; tlo right -col=[1,0,0]; tlo left -col=[0,0,1]; netgen-6.2.1905/tutorials/part1.stl0000644000175000017500000030145613504650527015613 0ustar kurtkurtsolid facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.055220e+000 5.027685e+000 5.332898e+000 vertex 3.066615e+000 4.897449e+000 5.332898e+000 vertex 3.305220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.312817e+000 5.114509e+000 5.332898e+000 vertex 3.055220e+000 5.027685e+000 5.332898e+000 vertex 3.305220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.312817e+000 5.114509e+000 5.332898e+000 vertex 3.066615e+000 5.157921e+000 5.332898e+000 vertex 3.055220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.312817e+000 5.114509e+000 5.332898e+000 vertex 3.335374e+000 5.198695e+000 5.332898e+000 vertex 3.066615e+000 5.157921e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.066615e+000 5.157921e+000 5.332898e+000 vertex 3.335374e+000 5.198695e+000 5.332898e+000 vertex 3.100451e+000 5.284200e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.100451e+000 5.284200e+000 5.332898e+000 vertex 3.335374e+000 5.198695e+000 5.332898e+000 vertex 3.372208e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.155701e+000 5.402685e+000 5.332898e+000 vertex 3.372208e+000 5.277685e+000 5.332898e+000 vertex 3.422198e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.230687e+000 5.509776e+000 5.332898e+000 vertex 3.422198e+000 5.349079e+000 5.332898e+000 vertex 3.483827e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.323130e+000 5.602218e+000 5.332898e+000 vertex 3.483827e+000 5.410707e+000 5.332898e+000 vertex 3.555220e+000 5.460698e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.430220e+000 5.677204e+000 5.332898e+000 vertex 3.555220e+000 5.460698e+000 5.332898e+000 vertex 3.634210e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.548705e+000 5.732455e+000 5.332898e+000 vertex 3.634210e+000 5.497531e+000 5.332898e+000 vertex 3.718396e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.674984e+000 5.766291e+000 5.332898e+000 vertex 3.718396e+000 5.520089e+000 5.332898e+000 vertex 3.805220e+000 5.527685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.805220e+000 5.777685e+000 5.332898e+000 vertex 3.805220e+000 5.527685e+000 5.332898e+000 vertex 3.892045e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.935457e+000 5.766291e+000 5.332898e+000 vertex 3.892045e+000 5.520089e+000 5.332898e+000 vertex 3.976231e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 5.732455e+000 5.332898e+000 vertex 3.976231e+000 5.497531e+000 5.332898e+000 vertex 4.055220e+000 5.460698e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.180220e+000 5.677204e+000 5.332898e+000 vertex 4.055220e+000 5.460698e+000 5.332898e+000 vertex 4.126614e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.287311e+000 5.602218e+000 5.332898e+000 vertex 4.126614e+000 5.410707e+000 5.332898e+000 vertex 4.188243e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 5.509776e+000 5.332898e+000 vertex 4.188243e+000 5.349079e+000 5.332898e+000 vertex 4.238233e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.454740e+000 5.402685e+000 5.332898e+000 vertex 4.238233e+000 5.277685e+000 5.332898e+000 vertex 4.275067e+000 5.198695e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.509990e+000 5.284200e+000 5.332898e+000 vertex 4.275067e+000 5.198695e+000 5.332898e+000 vertex 4.297624e+000 5.114509e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.543826e+000 5.157921e+000 5.332898e+000 vertex 4.297624e+000 5.114509e+000 5.332898e+000 vertex 4.305220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.555220e+000 5.027685e+000 5.332898e+000 vertex 4.305220e+000 5.027685e+000 5.332898e+000 vertex 4.297624e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.543826e+000 4.897449e+000 5.332898e+000 vertex 4.297624e+000 4.940861e+000 5.332898e+000 vertex 4.275067e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.509990e+000 4.771170e+000 5.332898e+000 vertex 4.275067e+000 4.856675e+000 5.332898e+000 vertex 4.238233e+000 4.777685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.454740e+000 4.652685e+000 5.332898e+000 vertex 4.238233e+000 4.777685e+000 5.332898e+000 vertex 4.188243e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 4.545594e+000 5.332898e+000 vertex 4.188243e+000 4.706291e+000 5.332898e+000 vertex 4.126614e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.287311e+000 4.453152e+000 5.332898e+000 vertex 4.126614e+000 4.644663e+000 5.332898e+000 vertex 4.055220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.180220e+000 4.378166e+000 5.332898e+000 vertex 4.055220e+000 4.594672e+000 5.332898e+000 vertex 3.976231e+000 4.557839e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 4.322916e+000 5.332898e+000 vertex 3.976231e+000 4.557839e+000 5.332898e+000 vertex 3.892045e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.935457e+000 4.289079e+000 5.332898e+000 vertex 3.892045e+000 4.535281e+000 5.332898e+000 vertex 3.805220e+000 4.527685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.805220e+000 4.277685e+000 5.332898e+000 vertex 3.805220e+000 4.527685e+000 5.332898e+000 vertex 3.718396e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.674984e+000 4.289079e+000 5.332898e+000 vertex 3.718396e+000 4.535281e+000 5.332898e+000 vertex 3.634210e+000 4.557839e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.548705e+000 4.322916e+000 5.332898e+000 vertex 3.634210e+000 4.557839e+000 5.332898e+000 vertex 3.555220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.430220e+000 4.378166e+000 5.332898e+000 vertex 3.555220e+000 4.594672e+000 5.332898e+000 vertex 3.483827e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.323130e+000 4.453152e+000 5.332898e+000 vertex 3.483827e+000 4.644663e+000 5.332898e+000 vertex 3.422198e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.230687e+000 4.545594e+000 5.332898e+000 vertex 3.422198e+000 4.706291e+000 5.332898e+000 vertex 3.372208e+000 4.777685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.155701e+000 4.652685e+000 5.332898e+000 vertex 3.372208e+000 4.777685e+000 5.332898e+000 vertex 3.335374e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.100451e+000 4.771170e+000 5.332898e+000 vertex 3.335374e+000 4.856675e+000 5.332898e+000 vertex 3.312817e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.066615e+000 4.897449e+000 5.332898e+000 vertex 3.312817e+000 4.940861e+000 5.332898e+000 vertex 3.305220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.066615e+000 4.897449e+000 5.332898e+000 vertex 3.100451e+000 4.771170e+000 5.332898e+000 vertex 3.312817e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.100451e+000 4.771170e+000 5.332898e+000 vertex 3.155701e+000 4.652685e+000 5.332898e+000 vertex 3.335374e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.155701e+000 4.652685e+000 5.332898e+000 vertex 3.230687e+000 4.545594e+000 5.332898e+000 vertex 3.372208e+000 4.777685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.230687e+000 4.545594e+000 5.332898e+000 vertex 3.323130e+000 4.453152e+000 5.332898e+000 vertex 3.422198e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.323130e+000 4.453152e+000 5.332898e+000 vertex 3.430220e+000 4.378166e+000 5.332898e+000 vertex 3.483827e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.430220e+000 4.378166e+000 5.332898e+000 vertex 3.548705e+000 4.322916e+000 5.332898e+000 vertex 3.555220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.548705e+000 4.322916e+000 5.332898e+000 vertex 3.674984e+000 4.289079e+000 5.332898e+000 vertex 3.634210e+000 4.557839e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.674984e+000 4.289079e+000 5.332898e+000 vertex 3.805220e+000 4.277685e+000 5.332898e+000 vertex 3.718396e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.805220e+000 4.277685e+000 5.332898e+000 vertex 3.935457e+000 4.289079e+000 5.332898e+000 vertex 3.805220e+000 4.527685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.935457e+000 4.289079e+000 5.332898e+000 vertex 4.061736e+000 4.322916e+000 5.332898e+000 vertex 3.892045e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.180220e+000 4.378166e+000 5.332898e+000 vertex 3.976231e+000 4.557839e+000 5.332898e+000 vertex 4.061736e+000 4.322916e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.180220e+000 4.378166e+000 5.332898e+000 vertex 4.287311e+000 4.453152e+000 5.332898e+000 vertex 4.055220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.287311e+000 4.453152e+000 5.332898e+000 vertex 4.379754e+000 4.545594e+000 5.332898e+000 vertex 4.126614e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 4.545594e+000 5.332898e+000 vertex 4.454740e+000 4.652685e+000 5.332898e+000 vertex 4.188243e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.509990e+000 4.771170e+000 5.332898e+000 vertex 4.238233e+000 4.777685e+000 5.332898e+000 vertex 4.454740e+000 4.652685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.509990e+000 4.771170e+000 5.332898e+000 vertex 4.543826e+000 4.897449e+000 5.332898e+000 vertex 4.275067e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.543826e+000 4.897449e+000 5.332898e+000 vertex 4.555220e+000 5.027685e+000 5.332898e+000 vertex 4.297624e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.555220e+000 5.027685e+000 5.332898e+000 vertex 4.543826e+000 5.157921e+000 5.332898e+000 vertex 4.305220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.543826e+000 5.157921e+000 5.332898e+000 vertex 4.509990e+000 5.284200e+000 5.332898e+000 vertex 4.297624e+000 5.114509e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.509990e+000 5.284200e+000 5.332898e+000 vertex 4.454740e+000 5.402685e+000 5.332898e+000 vertex 4.275067e+000 5.198695e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.454740e+000 5.402685e+000 5.332898e+000 vertex 4.379754e+000 5.509776e+000 5.332898e+000 vertex 4.238233e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 5.509776e+000 5.332898e+000 vertex 4.287311e+000 5.602218e+000 5.332898e+000 vertex 4.188243e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.287311e+000 5.602218e+000 5.332898e+000 vertex 4.180220e+000 5.677204e+000 5.332898e+000 vertex 4.126614e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.055220e+000 5.460698e+000 5.332898e+000 vertex 4.180220e+000 5.677204e+000 5.332898e+000 vertex 4.061736e+000 5.732455e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 5.732455e+000 5.332898e+000 vertex 3.935457e+000 5.766291e+000 5.332898e+000 vertex 3.976231e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.935457e+000 5.766291e+000 5.332898e+000 vertex 3.805220e+000 5.777685e+000 5.332898e+000 vertex 3.892045e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.805220e+000 5.777685e+000 5.332898e+000 vertex 3.674984e+000 5.766291e+000 5.332898e+000 vertex 3.805220e+000 5.527685e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.674984e+000 5.766291e+000 5.332898e+000 vertex 3.548705e+000 5.732455e+000 5.332898e+000 vertex 3.718396e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.548705e+000 5.732455e+000 5.332898e+000 vertex 3.430220e+000 5.677204e+000 5.332898e+000 vertex 3.634210e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.430220e+000 5.677204e+000 5.332898e+000 vertex 3.323130e+000 5.602218e+000 5.332898e+000 vertex 3.555220e+000 5.460698e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.323130e+000 5.602218e+000 5.332898e+000 vertex 3.230687e+000 5.509776e+000 5.332898e+000 vertex 3.483827e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.230687e+000 5.509776e+000 5.332898e+000 vertex 3.155701e+000 5.402685e+000 5.332898e+000 vertex 3.422198e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.155701e+000 5.402685e+000 5.332898e+000 vertex 3.100451e+000 5.284200e+000 5.332898e+000 vertex 3.372208e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -9.172298e-016 outer loop vertex 4.555220e+000 5.027685e+000 6.332898e+000 vertex 4.543826e+000 5.157921e+000 6.332898e+000 vertex 4.543826e+000 5.157921e+000 5.332898e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 9.289182e-016 outer loop vertex 4.555220e+000 5.027685e+000 5.332898e+000 vertex 4.555220e+000 5.027685e+000 6.332898e+000 vertex 4.543826e+000 5.157921e+000 5.332898e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 -9.289182e-016 outer loop vertex 4.555220e+000 5.027685e+000 5.332898e+000 vertex 4.543826e+000 4.897449e+000 6.332898e+000 vertex 4.555220e+000 5.027685e+000 6.332898e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 1.758162e-015 outer loop vertex 4.555220e+000 5.027685e+000 5.332898e+000 vertex 4.543826e+000 4.897449e+000 5.332898e+000 vertex 4.543826e+000 4.897449e+000 6.332898e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 -1.855524e-015 outer loop vertex 4.543826e+000 4.897449e+000 6.332898e+000 vertex 4.543826e+000 4.897449e+000 5.332898e+000 vertex 4.509990e+000 4.771170e+000 6.332898e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 2.035888e-015 outer loop vertex 4.509990e+000 4.771170e+000 6.332898e+000 vertex 4.543826e+000 4.897449e+000 5.332898e+000 vertex 4.509990e+000 4.771170e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 2.152348e-015 outer loop vertex 4.454740e+000 4.652685e+000 6.332898e+000 vertex 4.509990e+000 4.771170e+000 5.332898e+000 vertex 4.454740e+000 4.652685e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 1.743410e-015 outer loop vertex 4.379754e+000 4.545594e+000 6.332898e+000 vertex 4.454740e+000 4.652685e+000 5.332898e+000 vertex 4.379754e+000 4.545594e+000 5.332898e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 1.256074e-015 outer loop vertex 4.287311e+000 4.453152e+000 6.332898e+000 vertex 4.379754e+000 4.545594e+000 5.332898e+000 vertex 4.287311e+000 4.453152e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 1.458126e-015 outer loop vertex 4.180220e+000 4.378166e+000 6.332898e+000 vertex 4.287311e+000 4.453152e+000 5.332898e+000 vertex 4.180220e+000 4.378166e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 1.442865e-015 outer loop vertex 4.061736e+000 4.322916e+000 6.332898e+000 vertex 4.180220e+000 4.378166e+000 5.332898e+000 vertex 4.061736e+000 4.322916e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 1.855524e-015 outer loop vertex 3.935457e+000 4.289079e+000 6.332898e+000 vertex 4.061736e+000 4.322916e+000 5.332898e+000 vertex 3.935457e+000 4.289079e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 1.819131e-015 outer loop vertex 3.805220e+000 4.277685e+000 6.332898e+000 vertex 3.935457e+000 4.289079e+000 5.332898e+000 vertex 3.805220e+000 4.277685e+000 5.332898e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 1.797473e-015 outer loop vertex 3.674984e+000 4.289079e+000 6.332898e+000 vertex 3.805220e+000 4.277685e+000 5.332898e+000 vertex 3.674984e+000 4.289079e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 1.063035e-015 outer loop vertex 3.548705e+000 4.322916e+000 6.332898e+000 vertex 3.674984e+000 4.289079e+000 5.332898e+000 vertex 3.548705e+000 4.322916e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 2.152348e-015 outer loop vertex 3.430220e+000 4.378166e+000 6.332898e+000 vertex 3.548705e+000 4.322916e+000 5.332898e+000 vertex 3.430220e+000 4.378166e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 1.998129e-015 outer loop vertex 3.323130e+000 4.453152e+000 6.332898e+000 vertex 3.430220e+000 4.378166e+000 5.332898e+000 vertex 3.323130e+000 4.453152e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 1.884111e-015 outer loop vertex 3.230687e+000 4.545594e+000 6.332898e+000 vertex 3.323130e+000 4.453152e+000 5.332898e+000 vertex 3.230687e+000 4.545594e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 1.458126e-015 outer loop vertex 3.155701e+000 4.652685e+000 6.332898e+000 vertex 3.230687e+000 4.545594e+000 5.332898e+000 vertex 3.155701e+000 4.652685e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 1.442865e-015 outer loop vertex 3.100451e+000 4.771170e+000 6.332898e+000 vertex 3.155701e+000 4.652685e+000 5.332898e+000 vertex 3.100451e+000 4.771170e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 1.855524e-015 outer loop vertex 3.066615e+000 4.897449e+000 6.332898e+000 vertex 3.100451e+000 4.771170e+000 5.332898e+000 vertex 3.066615e+000 4.897449e+000 5.332898e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 9.289182e-016 outer loop vertex 3.055220e+000 5.027685e+000 6.332898e+000 vertex 3.066615e+000 4.897449e+000 5.332898e+000 vertex 3.055220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 1.283078e-015 outer loop vertex 3.066615e+000 5.157921e+000 6.332898e+000 vertex 3.055220e+000 5.027685e+000 5.332898e+000 vertex 3.066615e+000 5.157921e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 9.030055e-016 outer loop vertex 3.100451e+000 5.284200e+000 6.332898e+000 vertex 3.066615e+000 5.157921e+000 5.332898e+000 vertex 3.100451e+000 5.284200e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 1.076174e-015 outer loop vertex 3.155701e+000 5.402685e+000 6.332898e+000 vertex 3.100451e+000 5.284200e+000 5.332898e+000 vertex 3.155701e+000 5.402685e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 8.717048e-016 outer loop vertex 3.230687e+000 5.509776e+000 6.332898e+000 vertex 3.155701e+000 5.402685e+000 5.332898e+000 vertex 3.230687e+000 5.509776e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 1.256074e-015 outer loop vertex 3.323130e+000 5.602218e+000 6.332898e+000 vertex 3.230687e+000 5.509776e+000 5.332898e+000 vertex 3.323130e+000 5.602218e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 7.290631e-016 outer loop vertex 3.430220e+000 5.677204e+000 6.332898e+000 vertex 3.323130e+000 5.602218e+000 5.332898e+000 vertex 3.430220e+000 5.677204e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 9.091125e-016 outer loop vertex 3.548705e+000 5.732455e+000 6.332898e+000 vertex 3.430220e+000 5.677204e+000 5.332898e+000 vertex 3.548705e+000 5.732455e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 1.847865e-016 outer loop vertex 3.674984e+000 5.766291e+000 6.332898e+000 vertex 3.548705e+000 5.732455e+000 5.332898e+000 vertex 3.674984e+000 5.766291e+000 5.332898e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 8.902133e-016 outer loop vertex 3.805220e+000 5.777685e+000 6.332898e+000 vertex 3.674984e+000 5.766291e+000 5.332898e+000 vertex 3.805220e+000 5.777685e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 8.406791e-016 outer loop vertex 3.935457e+000 5.766291e+000 6.332898e+000 vertex 3.805220e+000 5.777685e+000 5.332898e+000 vertex 3.935457e+000 5.766291e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 1.760920e-015 outer loop vertex 4.061736e+000 5.732455e+000 6.332898e+000 vertex 3.935457e+000 5.766291e+000 5.332898e+000 vertex 4.061736e+000 5.732455e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 1.076174e-015 outer loop vertex 4.180220e+000 5.677204e+000 6.332898e+000 vertex 4.061736e+000 5.732455e+000 5.332898e+000 vertex 4.180220e+000 5.677204e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 5.079283e-016 outer loop vertex 4.287311e+000 5.602218e+000 6.332898e+000 vertex 4.180220e+000 5.677204e+000 5.332898e+000 vertex 4.287311e+000 5.602218e+000 5.332898e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 6.280370e-016 outer loop vertex 4.379754e+000 5.509776e+000 6.332898e+000 vertex 4.287311e+000 5.602218e+000 5.332898e+000 vertex 4.379754e+000 5.509776e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 7.290631e-016 outer loop vertex 4.454740e+000 5.402685e+000 6.332898e+000 vertex 4.379754e+000 5.509776e+000 5.332898e+000 vertex 4.454740e+000 5.402685e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 9.091125e-016 outer loop vertex 4.509990e+000 5.284200e+000 6.332898e+000 vertex 4.454740e+000 5.402685e+000 5.332898e+000 vertex 4.509990e+000 5.284200e+000 5.332898e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 8.128234e-016 outer loop vertex 4.543826e+000 5.157921e+000 6.332898e+000 vertex 4.509990e+000 5.284200e+000 5.332898e+000 vertex 4.543826e+000 5.157921e+000 5.332898e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -9.023020e-016 outer loop vertex 4.543826e+000 5.157921e+000 6.332898e+000 vertex 4.509990e+000 5.284200e+000 6.332898e+000 vertex 4.509990e+000 5.284200e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 -1.081435e-015 outer loop vertex 4.509990e+000 5.284200e+000 6.332898e+000 vertex 4.454740e+000 5.402685e+000 6.332898e+000 vertex 4.454740e+000 5.402685e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -1.235481e-015 outer loop vertex 4.379754e+000 5.509776e+000 6.332898e+000 vertex 4.379754e+000 5.509776e+000 5.332898e+000 vertex 4.454740e+000 5.402685e+000 6.332898e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -1.260569e-015 outer loop vertex 4.379754e+000 5.509776e+000 6.332898e+000 vertex 4.287311e+000 5.602218e+000 6.332898e+000 vertex 4.287311e+000 5.602218e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -7.165339e-016 outer loop vertex 4.287311e+000 5.602218e+000 6.332898e+000 vertex 4.180220e+000 5.677204e+000 6.332898e+000 vertex 4.180220e+000 5.677204e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -9.951860e-017 outer loop vertex 4.180220e+000 5.677204e+000 6.332898e+000 vertex 4.061736e+000 5.732455e+000 6.332898e+000 vertex 4.061736e+000 5.732455e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -1.041628e-015 outer loop vertex 4.061736e+000 5.732455e+000 6.332898e+000 vertex 3.935457e+000 5.766291e+000 6.332898e+000 vertex 3.935457e+000 5.766291e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -8.902133e-016 outer loop vertex 3.805220e+000 5.777685e+000 6.332898e+000 vertex 3.805220e+000 5.777685e+000 5.332898e+000 vertex 3.935457e+000 5.766291e+000 6.332898e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -1.726648e-015 outer loop vertex 3.805220e+000 5.777685e+000 6.332898e+000 vertex 3.674984e+000 5.766291e+000 6.332898e+000 vertex 3.674984e+000 5.766291e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -9.089365e-016 outer loop vertex 3.674984e+000 5.766291e+000 6.332898e+000 vertex 3.548705e+000 5.732455e+000 6.332898e+000 vertex 3.548705e+000 5.732455e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -1.081435e-015 outer loop vertex 3.548705e+000 5.732455e+000 6.332898e+000 vertex 3.430220e+000 5.677204e+000 6.332898e+000 vertex 3.430220e+000 5.677204e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -5.042276e-016 outer loop vertex 3.430220e+000 5.677204e+000 6.332898e+000 vertex 3.323130e+000 5.602218e+000 6.332898e+000 vertex 3.323130e+000 5.602218e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -9.421094e-016 outer loop vertex 3.323130e+000 5.602218e+000 6.332898e+000 vertex 3.230687e+000 5.509776e+000 6.332898e+000 vertex 3.230687e+000 5.509776e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -7.298031e-016 outer loop vertex 3.230687e+000 5.509776e+000 6.332898e+000 vertex 3.155701e+000 5.402685e+000 6.332898e+000 vertex 3.155701e+000 5.402685e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -9.089365e-016 outer loop vertex 3.155701e+000 5.402685e+000 6.332898e+000 vertex 3.100451e+000 5.284200e+000 6.332898e+000 vertex 3.100451e+000 5.284200e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -6.103807e-016 outer loop vertex 3.100451e+000 5.284200e+000 6.332898e+000 vertex 3.066615e+000 5.157921e+000 6.332898e+000 vertex 3.066615e+000 5.157921e+000 5.332898e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -9.289182e-016 outer loop vertex 3.055220e+000 5.027685e+000 6.332898e+000 vertex 3.055220e+000 5.027685e+000 5.332898e+000 vertex 3.066615e+000 5.157921e+000 6.332898e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 -1.759821e-015 outer loop vertex 3.055220e+000 5.027685e+000 6.332898e+000 vertex 3.066615e+000 4.897449e+000 6.332898e+000 vertex 3.066615e+000 4.897449e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 -2.036814e-015 outer loop vertex 3.066615e+000 4.897449e+000 6.332898e+000 vertex 3.100451e+000 4.771170e+000 6.332898e+000 vertex 3.100451e+000 4.771170e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -2.149602e-015 outer loop vertex 3.100451e+000 4.771170e+000 6.332898e+000 vertex 3.155701e+000 4.652685e+000 6.332898e+000 vertex 3.155701e+000 4.652685e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 -1.738258e-015 outer loop vertex 3.155701e+000 4.652685e+000 6.332898e+000 vertex 3.230687e+000 4.545594e+000 6.332898e+000 vertex 3.230687e+000 4.545594e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 -1.579028e-015 outer loop vertex 3.230687e+000 4.545594e+000 6.332898e+000 vertex 3.323130e+000 4.453152e+000 6.332898e+000 vertex 3.323130e+000 4.453152e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 -1.459606e-015 outer loop vertex 3.323130e+000 4.453152e+000 6.332898e+000 vertex 3.430220e+000 4.378166e+000 6.332898e+000 vertex 3.430220e+000 4.378166e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -2.434888e-015 outer loop vertex 3.430220e+000 4.378166e+000 6.332898e+000 vertex 3.548705e+000 4.322916e+000 6.332898e+000 vertex 3.548705e+000 4.322916e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -1.738258e-015 outer loop vertex 3.548705e+000 4.322916e+000 6.332898e+000 vertex 3.674984e+000 4.289079e+000 6.332898e+000 vertex 3.674984e+000 4.289079e+000 5.332898e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -1.819532e-015 outer loop vertex 3.674984e+000 4.289079e+000 6.332898e+000 vertex 3.805220e+000 4.277685e+000 6.332898e+000 vertex 3.805220e+000 4.277685e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 -1.758162e-015 outer loop vertex 3.805220e+000 4.277685e+000 6.332898e+000 vertex 3.935457e+000 4.289079e+000 6.332898e+000 vertex 3.935457e+000 4.289079e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 -2.036814e-015 outer loop vertex 3.935457e+000 4.289079e+000 6.332898e+000 vertex 4.061736e+000 4.322916e+000 6.332898e+000 vertex 4.061736e+000 4.322916e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -2.149602e-015 outer loop vertex 4.061736e+000 4.322916e+000 6.332898e+000 vertex 4.180220e+000 4.378166e+000 6.332898e+000 vertex 4.180220e+000 4.378166e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -2.242486e-015 outer loop vertex 4.180220e+000 4.378166e+000 6.332898e+000 vertex 4.287311e+000 4.453152e+000 6.332898e+000 vertex 4.287311e+000 4.453152e+000 5.332898e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 -1.884219e-015 outer loop vertex 4.287311e+000 4.453152e+000 6.332898e+000 vertex 4.379754e+000 4.545594e+000 6.332898e+000 vertex 4.379754e+000 4.545594e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 -1.459606e-015 outer loop vertex 4.379754e+000 4.545594e+000 6.332898e+000 vertex 4.454740e+000 4.652685e+000 6.332898e+000 vertex 4.454740e+000 4.652685e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 -1.446337e-015 outer loop vertex 4.454740e+000 4.652685e+000 6.332898e+000 vertex 4.509990e+000 4.771170e+000 6.332898e+000 vertex 4.509990e+000 4.771170e+000 5.332898e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 7.470115e-016 outer loop vertex 4.305220e+000 5.027685e+000 3.332898e+000 vertex 4.297624e+000 4.940861e+000 3.332898e+000 vertex 4.297624e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 -3.096394e-016 outer loop vertex 4.305220e+000 5.027685e+000 5.332898e+000 vertex 4.305220e+000 5.027685e+000 3.332898e+000 vertex 4.297624e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 3.096394e-016 outer loop vertex 4.305220e+000 5.027685e+000 5.332898e+000 vertex 4.297624e+000 5.114509e+000 3.332898e+000 vertex 4.305220e+000 5.027685e+000 3.332898e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -7.470115e-016 outer loop vertex 4.305220e+000 5.027685e+000 5.332898e+000 vertex 4.297624e+000 5.114509e+000 5.332898e+000 vertex 4.297624e+000 5.114509e+000 3.332898e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 4.372095e-016 outer loop vertex 4.297624e+000 5.114509e+000 3.332898e+000 vertex 4.297624e+000 5.114509e+000 5.332898e+000 vertex 4.275067e+000 5.198695e+000 3.332898e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -4.207050e-016 outer loop vertex 4.275067e+000 5.198695e+000 3.332898e+000 vertex 4.297624e+000 5.114509e+000 5.332898e+000 vertex 4.275067e+000 5.198695e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 -5.923291e-016 outer loop vertex 4.238233e+000 5.277685e+000 3.332898e+000 vertex 4.275067e+000 5.198695e+000 5.332898e+000 vertex 4.238233e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -3.264175e-016 outer loop vertex 4.188243e+000 5.349079e+000 3.332898e+000 vertex 4.238233e+000 5.277685e+000 5.332898e+000 vertex 4.188243e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -6.280370e-016 outer loop vertex 4.126614e+000 5.410707e+000 3.332898e+000 vertex 4.188243e+000 5.349079e+000 5.332898e+000 vertex 4.126614e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -4.011357e-016 outer loop vertex 4.055220e+000 5.460698e+000 3.332898e+000 vertex 4.126614e+000 5.410707e+000 5.332898e+000 vertex 4.055220e+000 5.460698e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -4.003141e-016 outer loop vertex 3.976231e+000 5.497531e+000 3.332898e+000 vertex 4.055220e+000 5.460698e+000 5.332898e+000 vertex 3.976231e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -9.236361e-016 outer loop vertex 3.892045e+000 5.520089e+000 3.332898e+000 vertex 3.976231e+000 5.497531e+000 5.332898e+000 vertex 3.892045e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -5.999263e-016 outer loop vertex 3.805220e+000 5.527685e+000 3.332898e+000 vertex 3.892045e+000 5.520089e+000 5.332898e+000 vertex 3.805220e+000 5.527685e+000 5.332898e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -7.272716e-016 outer loop vertex 3.718396e+000 5.520089e+000 3.332898e+000 vertex 3.805220e+000 5.527685e+000 5.332898e+000 vertex 3.718396e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -4.207050e-016 outer loop vertex 3.634210e+000 5.497531e+000 3.332898e+000 vertex 3.718396e+000 5.520089e+000 5.332898e+000 vertex 3.634210e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -6.861692e-016 outer loop vertex 3.555220e+000 5.460698e+000 3.332898e+000 vertex 3.634210e+000 5.497531e+000 5.332898e+000 vertex 3.555220e+000 5.460698e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -5.811366e-016 outer loop vertex 3.483827e+000 5.410707e+000 3.332898e+000 vertex 3.555220e+000 5.460698e+000 5.332898e+000 vertex 3.483827e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -6.280370e-016 outer loop vertex 3.422198e+000 5.349079e+000 3.332898e+000 vertex 3.483827e+000 5.410707e+000 5.332898e+000 vertex 3.422198e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -5.830240e-016 outer loop vertex 3.372208e+000 5.277685e+000 3.332898e+000 vertex 3.422198e+000 5.349079e+000 5.332898e+000 vertex 3.372208e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -4.138746e-016 outer loop vertex 3.335374e+000 5.198695e+000 3.332898e+000 vertex 3.372208e+000 5.277685e+000 5.332898e+000 vertex 3.335374e+000 5.198695e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -4.372095e-016 outer loop vertex 3.312817e+000 5.114509e+000 3.332898e+000 vertex 3.335374e+000 5.198695e+000 5.332898e+000 vertex 3.312817e+000 5.114509e+000 5.332898e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -6.192788e-016 outer loop vertex 3.305220e+000 5.027685e+000 3.332898e+000 vertex 3.312817e+000 5.114509e+000 5.332898e+000 vertex 3.305220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 -7.466241e-016 outer loop vertex 3.312817e+000 4.940861e+000 3.332898e+000 vertex 3.305220e+000 5.027685e+000 5.332898e+000 vertex 3.312817e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 -7.501224e-016 outer loop vertex 3.335374e+000 4.856675e+000 3.332898e+000 vertex 3.312817e+000 4.940861e+000 5.332898e+000 vertex 3.335374e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -5.787686e-016 outer loop vertex 3.372208e+000 4.777685e+000 3.332898e+000 vertex 3.335374e+000 4.856675e+000 5.332898e+000 vertex 3.372208e+000 4.777685e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 -5.811366e-016 outer loop vertex 3.422198e+000 4.706291e+000 3.332898e+000 vertex 3.372208e+000 4.777685e+000 5.332898e+000 vertex 3.422198e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 -6.280370e-016 outer loop vertex 3.483827e+000 4.644663e+000 3.332898e+000 vertex 3.422198e+000 4.706291e+000 5.332898e+000 vertex 3.483827e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 -5.284953e-016 outer loop vertex 3.555220e+000 4.594672e+000 3.332898e+000 vertex 3.483827e+000 4.644663e+000 5.332898e+000 vertex 3.555220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -8.027956e-016 outer loop vertex 3.634210e+000 4.557839e+000 3.332898e+000 vertex 3.555220e+000 4.594672e+000 5.332898e+000 vertex 3.634210e+000 4.557839e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -4.946788e-016 outer loop vertex 3.718396e+000 4.535281e+000 3.332898e+000 vertex 3.634210e+000 4.557839e+000 5.332898e+000 vertex 3.718396e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -5.999263e-016 outer loop vertex 3.805220e+000 4.527685e+000 3.332898e+000 vertex 3.718396e+000 4.535281e+000 5.332898e+000 vertex 3.805220e+000 4.527685e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 -2.848723e-016 outer loop vertex 3.892045e+000 4.535281e+000 3.332898e+000 vertex 3.805220e+000 4.527685e+000 5.332898e+000 vertex 3.892045e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 -8.496622e-016 outer loop vertex 3.976231e+000 4.557839e+000 3.332898e+000 vertex 3.892045e+000 4.535281e+000 5.332898e+000 vertex 3.976231e+000 4.557839e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -7.800093e-016 outer loop vertex 4.055220e+000 4.594672e+000 3.332898e+000 vertex 3.976231e+000 4.557839e+000 5.332898e+000 vertex 4.055220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -5.811366e-016 outer loop vertex 4.126614e+000 4.644663e+000 3.332898e+000 vertex 4.055220e+000 4.594672e+000 5.332898e+000 vertex 4.126614e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 -9.420555e-016 outer loop vertex 4.188243e+000 4.706291e+000 3.332898e+000 vertex 4.126614e+000 4.644663e+000 5.332898e+000 vertex 4.188243e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 -6.558548e-016 outer loop vertex 4.238233e+000 4.777685e+000 3.332898e+000 vertex 4.188243e+000 4.706291e+000 5.332898e+000 vertex 4.238233e+000 4.777685e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 -8.027956e-016 outer loop vertex 4.275067e+000 4.856675e+000 3.332898e+000 vertex 4.238233e+000 4.777685e+000 5.332898e+000 vertex 4.275067e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 -4.372095e-016 outer loop vertex 4.297624e+000 4.940861e+000 3.332898e+000 vertex 4.275067e+000 4.856675e+000 5.332898e+000 vertex 4.297624e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 4.204661e-016 outer loop vertex 4.297624e+000 4.940861e+000 3.332898e+000 vertex 4.275067e+000 4.856675e+000 3.332898e+000 vertex 4.275067e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 5.946236e-016 outer loop vertex 4.275067e+000 4.856675e+000 3.332898e+000 vertex 4.238233e+000 4.777685e+000 3.332898e+000 vertex 4.238233e+000 4.777685e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 3.259234e-016 outer loop vertex 4.238233e+000 4.777685e+000 3.332898e+000 vertex 4.188243e+000 4.706291e+000 3.332898e+000 vertex 4.188243e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 6.269672e-016 outer loop vertex 4.188243e+000 4.706291e+000 3.332898e+000 vertex 4.126614e+000 4.644663e+000 3.332898e+000 vertex 4.126614e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 4.005624e-016 outer loop vertex 4.126614e+000 4.644663e+000 3.332898e+000 vertex 4.055220e+000 4.594672e+000 3.332898e+000 vertex 4.055220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 4.005624e-016 outer loop vertex 4.055220e+000 4.594672e+000 3.332898e+000 vertex 3.976231e+000 4.557839e+000 3.332898e+000 vertex 3.976231e+000 4.557839e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 9.230350e-016 outer loop vertex 3.976231e+000 4.557839e+000 3.332898e+000 vertex 3.892045e+000 4.535281e+000 3.332898e+000 vertex 3.892045e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 6.002215e-016 outer loop vertex 3.892045e+000 4.535281e+000 3.332898e+000 vertex 3.805220e+000 4.527685e+000 3.332898e+000 vertex 3.805220e+000 4.527685e+000 5.332898e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 7.277298e-016 outer loop vertex 3.805220e+000 4.527685e+000 3.332898e+000 vertex 3.718396e+000 4.535281e+000 3.332898e+000 vertex 3.718396e+000 4.535281e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 4.204661e-016 outer loop vertex 3.718396e+000 4.535281e+000 3.332898e+000 vertex 3.634210e+000 4.557839e+000 3.332898e+000 vertex 3.634210e+000 4.557839e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 6.841904e-016 outer loop vertex 3.634210e+000 4.557839e+000 3.332898e+000 vertex 3.555220e+000 4.594672e+000 3.332898e+000 vertex 3.555220e+000 4.594672e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 5.796958e-016 outer loop vertex 3.555220e+000 4.594672e+000 3.332898e+000 vertex 3.483827e+000 4.644663e+000 3.332898e+000 vertex 3.483827e+000 4.644663e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 6.269672e-016 outer loop vertex 3.483827e+000 4.644663e+000 3.332898e+000 vertex 3.422198e+000 4.706291e+000 3.332898e+000 vertex 3.422198e+000 4.706291e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 5.821838e-016 outer loop vertex 3.422198e+000 4.706291e+000 3.332898e+000 vertex 3.372208e+000 4.777685e+000 3.332898e+000 vertex 3.372208e+000 4.777685e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 4.154901e-016 outer loop vertex 3.372208e+000 4.777685e+000 3.332898e+000 vertex 3.335374e+000 4.856675e+000 3.332898e+000 vertex 3.335374e+000 4.856675e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 4.366379e-016 outer loop vertex 3.335374e+000 4.856675e+000 3.332898e+000 vertex 3.312817e+000 4.940861e+000 3.332898e+000 vertex 3.312817e+000 4.940861e+000 5.332898e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 6.195033e-016 outer loop vertex 3.312817e+000 4.940861e+000 3.332898e+000 vertex 3.305220e+000 5.027685e+000 3.332898e+000 vertex 3.305220e+000 5.027685e+000 5.332898e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 7.470115e-016 outer loop vertex 3.305220e+000 5.027685e+000 3.332898e+000 vertex 3.312817e+000 5.114509e+000 3.332898e+000 vertex 3.312817e+000 5.114509e+000 5.332898e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 7.501214e-016 outer loop vertex 3.312817e+000 5.114509e+000 3.332898e+000 vertex 3.335374e+000 5.198695e+000 3.332898e+000 vertex 3.335374e+000 5.198695e+000 5.332898e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 5.796958e-016 outer loop vertex 3.335374e+000 5.198695e+000 3.332898e+000 vertex 3.372208e+000 5.277685e+000 3.332898e+000 vertex 3.372208e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 5.796958e-016 outer loop vertex 3.372208e+000 5.277685e+000 3.332898e+000 vertex 3.422198e+000 5.349079e+000 3.332898e+000 vertex 3.422198e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 6.269672e-016 outer loop vertex 3.422198e+000 5.349079e+000 3.332898e+000 vertex 3.483827e+000 5.410707e+000 3.332898e+000 vertex 3.483827e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 5.274486e-016 outer loop vertex 3.483827e+000 5.410707e+000 3.332898e+000 vertex 3.555220e+000 5.460698e+000 3.332898e+000 vertex 3.555220e+000 5.460698e+000 5.332898e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 8.036127e-016 outer loop vertex 3.555220e+000 5.460698e+000 3.332898e+000 vertex 3.634210e+000 5.497531e+000 3.332898e+000 vertex 3.634210e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 4.951050e-016 outer loop vertex 3.634210e+000 5.497531e+000 3.332898e+000 vertex 3.718396e+000 5.520089e+000 3.332898e+000 vertex 3.718396e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 5.995996e-016 outer loop vertex 3.718396e+000 5.520089e+000 3.332898e+000 vertex 3.805220e+000 5.527685e+000 3.332898e+000 vertex 3.805220e+000 5.527685e+000 5.332898e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 2.848720e-016 outer loop vertex 3.805220e+000 5.527685e+000 3.332898e+000 vertex 3.892045e+000 5.520089e+000 3.332898e+000 vertex 3.892045e+000 5.520089e+000 5.332898e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 8.496400e-016 outer loop vertex 3.892045e+000 5.520089e+000 3.332898e+000 vertex 3.976231e+000 5.497531e+000 3.332898e+000 vertex 3.976231e+000 5.497531e+000 5.332898e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 7.787330e-016 outer loop vertex 3.976231e+000 5.497531e+000 3.332898e+000 vertex 4.055220e+000 5.460698e+000 3.332898e+000 vertex 4.055220e+000 5.460698e+000 5.332898e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 5.796958e-016 outer loop vertex 4.055220e+000 5.460698e+000 3.332898e+000 vertex 4.126614e+000 5.410707e+000 3.332898e+000 vertex 4.126614e+000 5.410707e+000 5.332898e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 9.404508e-016 outer loop vertex 4.126614e+000 5.410707e+000 3.332898e+000 vertex 4.188243e+000 5.349079e+000 3.332898e+000 vertex 4.188243e+000 5.349079e+000 5.332898e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 6.543348e-016 outer loop vertex 4.188243e+000 5.349079e+000 3.332898e+000 vertex 4.238233e+000 5.277685e+000 3.332898e+000 vertex 4.238233e+000 5.277685e+000 5.332898e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 8.036127e-016 outer loop vertex 4.238233e+000 5.277685e+000 3.332898e+000 vertex 4.275067e+000 5.198695e+000 3.332898e+000 vertex 4.275067e+000 5.198695e+000 5.332898e+000 endloop endfacet facet normal 0.000000e+000 -8.000000e-001 6.000000e-001 outer loop vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 6.805220e+000 2.527685e+000 4.332898e+000 endloop endfacet facet normal 0.000000e+000 -8.000000e-001 6.000000e-001 outer loop vertex 6.805220e+000 2.527685e+000 4.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 8.052205e-001 2.527685e+000 4.332898e+000 endloop endfacet facet normal 0.000000e+000 -1.000000e+000 0.000000e+000 outer loop vertex 6.805220e+000 2.527685e+000 4.332898e+000 vertex 8.052205e-001 2.527685e+000 4.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 -1.000000e+000 0.000000e+000 outer loop vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 4.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 8.052205e-001 2.527685e+000 4.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 8.052205e-001 2.527685e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 4.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 5.978869e+000 7.512493e+000 3.332898e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 5.978869e+000 7.512493e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 5.978869e+000 7.512493e+000 6.332898e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 0.000000e+000 outer loop vertex 6.147241e+000 7.467378e+000 3.332898e+000 vertex 5.978869e+000 7.512493e+000 6.332898e+000 vertex 6.147241e+000 7.467378e+000 6.332898e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 0.000000e+000 outer loop vertex 6.305220e+000 7.393710e+000 3.332898e+000 vertex 6.147241e+000 7.467378e+000 6.332898e+000 vertex 6.305220e+000 7.393710e+000 6.332898e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 0.000000e+000 outer loop vertex 6.448008e+000 7.293729e+000 3.332898e+000 vertex 6.305220e+000 7.393710e+000 6.332898e+000 vertex 6.448008e+000 7.293729e+000 6.332898e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 6.571265e+000 7.170473e+000 3.332898e+000 vertex 6.448008e+000 7.293729e+000 6.332898e+000 vertex 6.571265e+000 7.170473e+000 6.332898e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 6.671246e+000 7.027685e+000 3.332898e+000 vertex 6.571265e+000 7.170473e+000 6.332898e+000 vertex 6.671246e+000 7.027685e+000 6.332898e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 6.744913e+000 6.869705e+000 3.332898e+000 vertex 6.671246e+000 7.027685e+000 6.332898e+000 vertex 6.744913e+000 6.869705e+000 6.332898e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 6.790028e+000 6.701333e+000 3.332898e+000 vertex 6.744913e+000 6.869705e+000 6.332898e+000 vertex 6.790028e+000 6.701333e+000 6.332898e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 6.790028e+000 6.701333e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 6.790028e+000 6.701333e+000 3.332898e+000 vertex 6.790028e+000 6.701333e+000 6.332898e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 6.790028e+000 6.701333e+000 3.332898e+000 vertex 6.744913e+000 6.869705e+000 3.332898e+000 vertex 6.744913e+000 6.869705e+000 6.332898e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 6.744913e+000 6.869705e+000 3.332898e+000 vertex 6.671246e+000 7.027685e+000 3.332898e+000 vertex 6.671246e+000 7.027685e+000 6.332898e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 6.671246e+000 7.027685e+000 3.332898e+000 vertex 6.571265e+000 7.170473e+000 3.332898e+000 vertex 6.571265e+000 7.170473e+000 6.332898e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 6.571265e+000 7.170473e+000 3.332898e+000 vertex 6.448008e+000 7.293729e+000 3.332898e+000 vertex 6.448008e+000 7.293729e+000 6.332898e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 0.000000e+000 outer loop vertex 6.448008e+000 7.293729e+000 3.332898e+000 vertex 6.305220e+000 7.393710e+000 3.332898e+000 vertex 6.305220e+000 7.393710e+000 6.332898e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 0.000000e+000 outer loop vertex 6.305220e+000 7.393710e+000 3.332898e+000 vertex 6.147241e+000 7.467378e+000 3.332898e+000 vertex 6.147241e+000 7.467378e+000 6.332898e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 0.000000e+000 outer loop vertex 6.147241e+000 7.467378e+000 3.332898e+000 vertex 5.978869e+000 7.512493e+000 3.332898e+000 vertex 5.978869e+000 7.512493e+000 6.332898e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 8.204127e-001 6.701333e+000 3.332898e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 8.204127e-001 6.701333e+000 3.332898e+000 vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 8.204127e-001 6.701333e+000 6.332898e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 8.655279e-001 6.869705e+000 3.332898e+000 vertex 8.204127e-001 6.701333e+000 6.332898e+000 vertex 8.655279e-001 6.869705e+000 6.332898e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 9.391951e-001 7.027685e+000 6.332898e+000 vertex 8.655279e-001 6.869705e+000 3.332898e+000 vertex 8.655279e-001 6.869705e+000 6.332898e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 -3.354013e-017 outer loop vertex 9.391951e-001 7.027685e+000 6.332898e+000 vertex 9.391951e-001 7.027685e+000 3.332898e+000 vertex 8.655279e-001 6.869705e+000 3.332898e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 -3.031472e-017 outer loop vertex 9.391951e-001 7.027685e+000 6.332898e+000 vertex 1.039176e+000 7.170473e+000 6.332898e+000 vertex 9.391951e-001 7.027685e+000 3.332898e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 9.391951e-001 7.027685e+000 3.332898e+000 vertex 1.039176e+000 7.170473e+000 6.332898e+000 vertex 1.039176e+000 7.170473e+000 3.332898e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 1.039176e+000 7.170473e+000 3.332898e+000 vertex 1.039176e+000 7.170473e+000 6.332898e+000 vertex 1.162433e+000 7.293729e+000 3.332898e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 1.162433e+000 7.293729e+000 3.332898e+000 vertex 1.039176e+000 7.170473e+000 6.332898e+000 vertex 1.162433e+000 7.293729e+000 6.332898e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 0.000000e+000 outer loop vertex 1.305220e+000 7.393710e+000 6.332898e+000 vertex 1.162433e+000 7.293729e+000 3.332898e+000 vertex 1.162433e+000 7.293729e+000 6.332898e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -4.245318e-017 outer loop vertex 1.305220e+000 7.393710e+000 6.332898e+000 vertex 1.305220e+000 7.393710e+000 3.332898e+000 vertex 1.162433e+000 7.293729e+000 3.332898e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -3.128003e-017 outer loop vertex 1.305220e+000 7.393710e+000 6.332898e+000 vertex 1.463200e+000 7.467378e+000 6.332898e+000 vertex 1.305220e+000 7.393710e+000 3.332898e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 0.000000e+000 outer loop vertex 1.305220e+000 7.393710e+000 3.332898e+000 vertex 1.463200e+000 7.467378e+000 6.332898e+000 vertex 1.463200e+000 7.467378e+000 3.332898e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 0.000000e+000 outer loop vertex 1.463200e+000 7.467378e+000 3.332898e+000 vertex 1.463200e+000 7.467378e+000 6.332898e+000 vertex 1.631572e+000 7.512493e+000 3.332898e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 0.000000e+000 outer loop vertex 1.631572e+000 7.512493e+000 3.332898e+000 vertex 1.463200e+000 7.467378e+000 6.332898e+000 vertex 1.631572e+000 7.512493e+000 6.332898e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 1.631572e+000 7.512493e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 1.631572e+000 7.512493e+000 3.332898e+000 vertex 1.631572e+000 7.512493e+000 6.332898e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 8.655279e-001 6.869705e+000 3.332898e+000 vertex 8.204127e-001 6.701333e+000 3.332898e+000 vertex 8.204127e-001 6.701333e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 1.000000e+000 0.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 1.000000e+000 0.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.305220e+000 5.027685e+000 3.332898e+000 vertex 4.297624e+000 5.114509e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.297624e+000 4.940861e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.275067e+000 4.856675e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 4.238233e+000 4.777685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.275067e+000 4.856675e+000 3.332898e+000 vertex 4.297624e+000 4.940861e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.275067e+000 5.198695e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 4.297624e+000 5.114509e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.275067e+000 5.198695e+000 3.332898e+000 vertex 4.238233e+000 5.277685e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 4.238233e+000 5.277685e+000 3.332898e+000 vertex 4.188243e+000 5.349079e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.126614e+000 5.410707e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 4.188243e+000 5.349079e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.126614e+000 5.410707e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.126614e+000 5.410707e+000 3.332898e+000 vertex 4.055220e+000 5.460698e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 4.055220e+000 5.460698e+000 3.332898e+000 vertex 3.976231e+000 5.497531e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.892045e+000 5.520089e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 3.976231e+000 5.497531e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.892045e+000 5.520089e+000 3.332898e+000 vertex 3.805220e+000 5.527685e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 3.805220e+000 5.527685e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 3.805220e+000 5.527685e+000 3.332898e+000 vertex 3.718396e+000 5.520089e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.634210e+000 5.497531e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 3.718396e+000 5.520089e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.634210e+000 5.497531e+000 3.332898e+000 vertex 3.555220e+000 5.460698e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 3.555220e+000 5.460698e+000 3.332898e+000 vertex 3.483827e+000 5.410707e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 3.483827e+000 5.410707e+000 3.332898e+000 vertex 3.422198e+000 5.349079e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.372208e+000 5.277685e+000 3.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 3.422198e+000 5.349079e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.372208e+000 5.277685e+000 3.332898e+000 vertex 3.335374e+000 5.198695e+000 3.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 3.335374e+000 5.198695e+000 3.332898e+000 vertex 3.312817e+000 5.114509e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.305220e+000 5.027685e+000 3.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 3.312817e+000 5.114509e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.305220e+000 5.027685e+000 3.332898e+000 vertex 3.312817e+000 4.940861e+000 3.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 3.312817e+000 4.940861e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.052205e-001 2.527685e+000 3.332898e+000 vertex 3.312817e+000 4.940861e+000 3.332898e+000 vertex 3.335374e+000 4.856675e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.372208e+000 4.777685e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 vertex 3.335374e+000 4.856675e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.372208e+000 4.777685e+000 3.332898e+000 vertex 3.422198e+000 4.706291e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.052205e-001 2.527685e+000 3.332898e+000 vertex 3.422198e+000 4.706291e+000 3.332898e+000 vertex 3.483827e+000 4.644663e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.555220e+000 4.594672e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 vertex 3.483827e+000 4.644663e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.555220e+000 4.594672e+000 3.332898e+000 vertex 3.634210e+000 4.557839e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.052205e-001 2.527685e+000 3.332898e+000 vertex 3.634210e+000 4.557839e+000 3.332898e+000 vertex 3.718396e+000 4.535281e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.805220e+000 4.527685e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 vertex 3.718396e+000 4.535281e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.805220e+000 4.527685e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 8.052205e-001 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.805220e+000 4.527685e+000 3.332898e+000 vertex 3.892045e+000 4.535281e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 3.892045e+000 4.535281e+000 3.332898e+000 vertex 3.976231e+000 4.557839e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.055220e+000 4.594672e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 3.976231e+000 4.557839e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.055220e+000 4.594672e+000 3.332898e+000 vertex 4.126614e+000 4.644663e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 4.126614e+000 4.644663e+000 3.332898e+000 vertex 4.188243e+000 4.706291e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.238233e+000 4.777685e+000 3.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 4.188243e+000 4.706291e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.305220e+000 5.027685e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 4.297624e+000 4.940861e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.147241e+000 7.467378e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 5.978869e+000 7.512493e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.147241e+000 7.467378e+000 3.332898e+000 vertex 6.305220e+000 7.393710e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 6.305220e+000 7.393710e+000 3.332898e+000 vertex 6.448008e+000 7.293729e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.571265e+000 7.170473e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 6.448008e+000 7.293729e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.571265e+000 7.170473e+000 3.332898e+000 vertex 6.671246e+000 7.027685e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 6.671246e+000 7.027685e+000 3.332898e+000 vertex 6.744913e+000 6.869705e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.790028e+000 6.701333e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 vertex 6.744913e+000 6.869705e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.790028e+000 6.701333e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 vertex 5.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 8.204127e-001 6.701333e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.483827e+000 5.410707e+000 3.332898e+000 vertex 8.052205e-001 6.527685e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.655279e-001 6.869705e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 8.204127e-001 6.701333e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.655279e-001 6.869705e+000 3.332898e+000 vertex 9.391951e-001 7.027685e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 9.391951e-001 7.027685e+000 3.332898e+000 vertex 1.039176e+000 7.170473e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.162433e+000 7.293729e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 1.039176e+000 7.170473e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.162433e+000 7.293729e+000 3.332898e+000 vertex 1.305220e+000 7.393710e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 1.305220e+000 7.393710e+000 3.332898e+000 vertex 1.463200e+000 7.467378e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.631572e+000 7.512493e+000 3.332898e+000 vertex 1.805220e+000 7.527685e+000 3.332898e+000 vertex 1.463200e+000 7.467378e+000 3.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.555220e+000 5.027685e+000 6.332898e+000 vertex 4.543826e+000 4.897449e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.543826e+000 5.157921e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.509990e+000 5.284200e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 vertex 4.454740e+000 5.402685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.509990e+000 5.284200e+000 6.332898e+000 vertex 4.543826e+000 5.157921e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.543826e+000 4.897449e+000 6.332898e+000 vertex 4.509990e+000 4.771170e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 4.509990e+000 4.771170e+000 6.332898e+000 vertex 4.454740e+000 4.652685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 4.545594e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 4.454740e+000 4.652685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 4.545594e+000 6.332898e+000 vertex 4.287311e+000 4.453152e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 4.287311e+000 4.453152e+000 6.332898e+000 vertex 4.180220e+000 4.378166e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 4.322916e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 4.180220e+000 4.378166e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 4.322916e+000 6.332898e+000 vertex 3.935457e+000 4.289079e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 3.935457e+000 4.289079e+000 6.332898e+000 vertex 3.805220e+000 4.277685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.805220e+000 4.277685e+000 6.332898e+000 vertex 3.674984e+000 4.289079e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.548705e+000 4.322916e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.674984e+000 4.289079e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.548705e+000 4.322916e+000 6.332898e+000 vertex 3.430220e+000 4.378166e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.430220e+000 4.378166e+000 6.332898e+000 vertex 3.323130e+000 4.453152e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.230687e+000 4.545594e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.323130e+000 4.453152e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.230687e+000 4.545594e+000 6.332898e+000 vertex 3.155701e+000 4.652685e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.155701e+000 4.652685e+000 6.332898e+000 vertex 3.100451e+000 4.771170e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.066615e+000 4.897449e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.100451e+000 4.771170e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.066615e+000 4.897449e+000 6.332898e+000 vertex 3.055220e+000 5.027685e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.055220e+000 5.027685e+000 6.332898e+000 vertex 3.066615e+000 5.157921e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 3.066615e+000 5.157921e+000 6.332898e+000 vertex 3.100451e+000 5.284200e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.155701e+000 5.402685e+000 6.332898e+000 vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 3.100451e+000 5.284200e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.155701e+000 5.402685e+000 6.332898e+000 vertex 3.230687e+000 5.509776e+000 6.332898e+000 vertex 8.052205e-001 6.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 3.230687e+000 5.509776e+000 6.332898e+000 vertex 3.323130e+000 5.602218e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.430220e+000 5.677204e+000 6.332898e+000 vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 3.323130e+000 5.602218e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.430220e+000 5.677204e+000 6.332898e+000 vertex 3.548705e+000 5.732455e+000 6.332898e+000 vertex 8.052205e-001 6.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 3.548705e+000 5.732455e+000 6.332898e+000 vertex 8.204127e-001 6.701333e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.204127e-001 6.701333e+000 6.332898e+000 vertex 3.548705e+000 5.732455e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.655279e-001 6.869705e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 vertex 9.391951e-001 7.027685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.655279e-001 6.869705e+000 6.332898e+000 vertex 8.204127e-001 6.701333e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.548705e+000 5.732455e+000 6.332898e+000 vertex 3.674984e+000 5.766291e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 6.332898e+000 vertex 3.674984e+000 5.766291e+000 6.332898e+000 vertex 3.805220e+000 5.777685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 3.805220e+000 5.777685e+000 6.332898e+000 vertex 3.935457e+000 5.766291e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 5.732455e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 3.935457e+000 5.766291e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 5.732455e+000 6.332898e+000 vertex 6.790028e+000 6.701333e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 5.732455e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 vertex 6.790028e+000 6.701333e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.061736e+000 5.732455e+000 6.332898e+000 vertex 4.180220e+000 5.677204e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.805220e+000 6.527685e+000 6.332898e+000 vertex 4.180220e+000 5.677204e+000 6.332898e+000 vertex 4.287311e+000 5.602218e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 5.509776e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 vertex 4.287311e+000 5.602218e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.379754e+000 5.509776e+000 6.332898e+000 vertex 4.454740e+000 5.402685e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.555220e+000 5.027685e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 4.543826e+000 5.157921e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 3.805220e+000 4.277685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.744913e+000 6.869705e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 6.790028e+000 6.701333e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.744913e+000 6.869705e+000 6.332898e+000 vertex 6.671246e+000 7.027685e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 6.671246e+000 7.027685e+000 6.332898e+000 vertex 6.571265e+000 7.170473e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.448008e+000 7.293729e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 6.571265e+000 7.170473e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.448008e+000 7.293729e+000 6.332898e+000 vertex 6.305220e+000 7.393710e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 6.305220e+000 7.393710e+000 6.332898e+000 vertex 6.147241e+000 7.467378e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.978869e+000 7.512493e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 vertex 6.147241e+000 7.467378e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 6.332898e+000 vertex 3.805220e+000 5.777685e+000 6.332898e+000 vertex 5.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.463200e+000 7.467378e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 vertex 1.631572e+000 7.512493e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.463200e+000 7.467378e+000 6.332898e+000 vertex 1.305220e+000 7.393710e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.805220e+000 7.527685e+000 6.332898e+000 vertex 1.305220e+000 7.393710e+000 6.332898e+000 vertex 1.162433e+000 7.293729e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.039176e+000 7.170473e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 vertex 1.162433e+000 7.293729e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.039176e+000 7.170473e+000 6.332898e+000 vertex 9.391951e-001 7.027685e+000 6.332898e+000 vertex 1.805220e+000 7.527685e+000 6.332898e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.052205e-001 6.527685e+000 6.332898e+000 vertex 8.052205e-001 4.027685e+000 6.332898e+000 vertex 3.066615e+000 5.157921e+000 6.332898e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 6.805220e+000 2.527685e+000 4.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 6.805220e+000 6.527685e+000 6.332898e+000 vertex 6.805220e+000 4.027685e+000 6.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 6.805220e+000 2.527685e+000 4.332898e+000 vertex 6.805220e+000 2.527685e+000 3.332898e+000 vertex 6.805220e+000 6.527685e+000 3.332898e+000 endloop endfacet endsolid netgen-6.2.1905/tutorials/CMakeLists.txt0000644000175000017500000000133513504650527016571 0ustar kurtkurtinstall( FILES boxcyl.geo circle_on_cube.geo cone.geo cube.geo cubeandring.geo cubeandspheres.geo cubemcyl.geo cubemsphere.geo cylinder.geo cylsphere.geo ellipsoid.geo ellipticcyl.geo extrusion.geo fichera.geo lshape3d.geo manyholes.geo manyholes2.geo matrix.geo ortho.geo period.geo revolution.geo sculpture.geo shaft.geo shell.geo sphere.geo sphereincube.geo torus.geo trafo.geo twobricks.geo twocubes.geo twocyl.geo boundarycondition.geo hinge.stl part1.stl frame.step screw.step squarehole.in2d squarecircle.in2d square.in2d DESTINATION ${NG_INSTALL_DIR_RES}/${NG_INSTALL_SUFFIX} COMPONENT netgen_tutorial ) netgen-6.2.1905/netgen.icns0000644000175000017500000063072013504650527014147 0ustar kurtkurticns1ÐTOC ic07Dèic08ÈXic09$hic07Dè‰PNG  IHDR€€Ã>aËsRGB®Îé pHYs  šœ@IDATxíœ^U°ï@z!½ÏLzï½'H „"bAÁ‚î‚è®muÑ÷vuA° ‚A:,M éôÞ“ÉL2©¤A%ßóÜ÷=“;3Lúû~ó÷÷Ì9÷ÜsÏù·ó¿ï”`UJ¥*=PéJTz Ò•¨ô@¥*=PéJTz Ò•¨ôÀÙô@U»àl.X¹Ö?¾úÜEÿ9Š}ªMtìg£cOÓ^E?Põaÿ úçüƒèÑ&º(útÔ#UFG‹££ÑبIôAZ»ÃÑ;ŒŒÞ޶ðuK´=ZM‰æp÷ÕýKÔEûGQ÷’A:Ï@c8–âó>Jw:ü]åï“ÿŒÍ¿…Eߎò¢¯E]£–q|±5PZAHº±çÖÒz/jÂRx;*ˆGS£õÑ*¾>ÈÈ>ø»ÈíQtWn}ímvWýÖÐ%¡ÉKô'ÀóPî'/!pGî07>tùû$Àˆèúhö×ÀÞæ ›}K®‚w`8¼AÔtT½4×mUà|˜^W‹þ-àj~ôW;áœËsQ´rRus£ÕPÌÑ×ÀãAYmÀ˜“ág©”."y¢"ø0%¸ñÜîY‡åÆ[4ã ¸8êLØ Ôrèjáµ'¼?xÃÖ‚ø`a5IÚCR{½l‚XEœcR¼ ë¢ýìý,Çî%Ö|‘‘dZqyæB 7Œ¢¶¬T¢Ñ6.Ž@»ôò3iUg4ì‚ ¡!h2U ÚA%  ø¦øP¥Dás¾ë¥ÑeÑ%ÂÔwWYÀRo5XÁ`¯„d_ŸÝPœÄêáÑÓã[ÀãÄg]ÿ<Ì cDôtô\4‹œÂHœ¶Ø•#"^b‰à‡ÅÌSÕ5ÿƒh–Éað;€o4ÅREÕøíÈ(ºÁ1“åÃ]sî埣ïG}¢— ˜»ê!`uØ üÁj ÷Ã!PÖAOx ¶ŸÚBÒ‚B®ó`XY\+)†:Œ€Ïz q”“oEË¢iÑ"j°uÆN*_¢YWð²ò¤7†~YžXÄXPå¤,åÂr4 |ãգ𭽓º i—çDÎýQ|E—ÆGÁ…°«ý}Ð °AÓrÅ9… Žm„.ð>(VÚPÓ DOöƒÞöõâ9$ëéa¿¬Á¡‚xï<𵡼‹™5’4ÜÍ$9‹Xo{«¹MÑîÚœèÿu,úÏ9 ÕzÜú0¯ò(|2ì™Ð ~— Pf`íð³äÍ7H÷ÿ>î‘Ô„³üUÓϾèL¼0¼oôÚìïrŽ—pí{Ù Š^0xÞóäï‚ä;¿*×&…%=ôÛÒ»Ç*è AϬ¯ †Ê=‚Ϙh¸¸ž¯‹®æÓŹÁ{Ë /Q÷Sw’§lÿÙñüyŒáO@R ¸X>fpÉÑð<´Õ2ŸÎ^0iêÃL‚Žzï~™·ÇçØõOç0 Ôïì »¾e´pö7 ~øÈ¥ó|ééÐ…`ðÜ] Á$HŠñ”$+—qP ¸ž5 ®ã3AªÓ1pï‚Aõ¥ªwç©‹QÊ”·¨>çúñóÁqÇZó¡í¾ãÁg$þ4; iKß“=1=æ27Â$HßâÖ†À˜ #ј³Pí>Òü|†´àœˆn;ëòŸü€æ;8ç!h:P§k†'ÓÓåûýuЩ…àœL±jpbç×̼™¾Ö½h°“â^Màxúkó’buØ“P‡­Ð,1f}Ÿ T™ž¿ì/Qtqø\’˜¦Ië×Éîb.¾Ÿ‡©@`K½™Ì}ÏDOOÂeé 3—jtN’à¬/ú0Ÿm>ÿãhâQR¸DeO¨Þ±œgÊ6L‚ƒP#}³­Á2ւσ©xÏÀ‹'Ýjò´OºõÔ9&­'½èa_®«xo7øZpui î—÷Ùûy„ì.OTÕ÷~x÷ûÈR¸M,óÚœr›¡dá`PLˆÿ…º°.O}jÑ:µ>k’iê-|G=þ׋£‰ï岌Ú }-Kªo êïÔ¸.çÐ0×gwÏÍU Šs ¦'y\•îw¤õžeÛy®Ûƒ•È1×ëmÀ(÷5‰’:rÛÒ.Šîø}=fµ‘ é̵j¸Ô°…àÓß,[iM€‘ S@“ ¼‰³4§hödø$Ó¦À!¸î„ïÀWPåW¥¿«dôôÅspFBð/|ž³üªZ÷ƒ7¡'x׃§Q‡yêLuûZ™_ÑÆD¢fÁ¤°jä‚óÞ€„³¹J­éºG`0¬„äIv¾ÇÎäIŠ º.+’º»¯û%È}™€‘Ø¿;÷_v=»˜|¢} éHÿ#°Lˆ¤XˆtE¦ôgàø7x|Þà»Ýx ~É7]ø&‹îYÍ=#y(Цqxr~y#ËèdW4­ pjb'ï¡u\G;¯:$¥!!hftO˜§Ù±zPŠ!Ãá%Iaàô°^+÷TFÂ츗úâøhA#°’ž?z‚×#.@—ñôŸ0yÕI{Ä~Z'»AtÁå0 þ–ô|¼.™å5xV§¡‰ÏŒÏ´_/$Âý4Ö»3–3J€ë¢è´èùÈ0ôÐ žÂ°×<!1óO8-®yÛó4-†~`0-ß ®Qš ´·2d&„§º5¬ÛA°øLMp|HÊ[\4ç*è™û|}ÎÊ`…’ý®fÿ9œ.bê¬ý´»Ð£+ÝLÁÀDx–€¦ë.eL†Ëa(š¨ºS¼H‹cãA÷þwê×é;§ßdº­Â+}Ï8ªÇ†òÄÿ‡/!¶{ „·õ”Q*â`˜»ÓA‡ï…ý°5Ý?BÛ’5Rçºf]PÔº%¬=iR¸ŽAOŠn»Àäª&ß3SLް2lŒ¢?ÝÍûÜý´A\3Ýw|>IÞF›]ÙȽŽÌÉ1Y²H'ÆêKÇ*›‡ $Å%ë@wxzϽW9X¯˜oZQõ.O[4í´doÚë9K·  ²c DãÅ“‘­Ëçb‹LƒÔ&}½ƒÖµjCûEàÜ Ï„ò´n“ÃJaRq2ã aÕð¾žl ÷c&Œcγ”›tb_\÷~¦mÂù&ŽAWBðSW±ž:ѨϽê$ãìnkô´?é.×à pq®zêûAKÈUx òÁà¿îk†*yF0e¯˜‡Iž}+¸>Içí©=:œ¤Ÿ#>ü¯áKæIjÆØèÁ Nvž'Û©7Ú‚÷q`ŒA1µ`%hå{ppn)q=ƒ¶êÁë =¡:ü ˜Þ3àmpy Wݸ¦íÞ7pâóy÷—V1˜!ø¶J£;š±èY…6G½´Éû¬ùý†é!–ŒËÝ~Žö~êúPêeÇÕ©ËéT€úÿÁ«©;{=˜Gf^N'34ÞàXNµB1ðÓ +Z¦Ó­ÁJoz·ƒiZ`ûV†Æà^Å`¢´…๶€Ò›ƒÅ`BxœŒÂd {ã„•Çä˜&¬ŸØöÃÓЇé7Óê!õ#±]Cë ý¦ØYŒÝæí[°Žþ&ÚËhói%˜N7·4÷4Cuf€¦‡-}æuhŠ•b3èJó̹ôëâŠ=‹R?{bäÔÄuNI>E÷¨ÐRø²O’P«¤h•“Z«„Á9 {Á¤Q|Õ\£¡èU­5¡L¢Pg×W¯ á —[GѾÎ'uæÇïræúø[ìsϺ]UŸ/ÒýZÌ߀ IÀ>  Ú$YÄ|bÎ~€¦Žegª)ùªùªlÎ~ šC^Ý{Ú?˜z©1RqÑ%’&ÌÚMÂöç‡Rúö>Ÿ=À4Õ õÁ¤Ð±â‰=ž> Cœ§Ø¶ƒ5Ð ‚£N¥["%ú<¸Þóài]3ÁùîW°¶‚õUÏZyôšÉçóŠ–{¯ <&€ÑûÏFÑ7Áyq Šõ º'õóy¯IÜEØð“óSý—HÈ|îu"aÊKþŒ¸Í_àZhº&œ ºñG&sÿ!ø4xNnˆ¢»i¾§$ª_!ñóÒ·ùŽåŸÙ9ýím²ÎÓ²)¨éFP;ìØP{“@ç$ÅùÖ±ÅÐ<Å>Öz‡¾æË0¦ÂŸÁû›`$8“N¥®÷j&Õ (€ýÐæuع-u•«Á5…õ®}•_Ý¢÷j{ˆh\h€“AÏ’¤Þ^ ùéHµ¿€g? ?IU‰Ÿ·MˆEТe$äXOæBkX•n_¦Ýæñ$Ðý ¼Iº“³¿¤kÝ«°T(Tâ-öüm}âWòu§Þè|µñäclü>×ùÍÁ“´L„¿Á¥`€qHI _{jçƒQfâç=µö¯C`¢ÍÏ€{ÈaÐÜÉp€÷Á=ß®cÿVhΙ5Á¤ôˆ9ö8—gÿ·d¢a>z«n– 3œæz{YÐÕŽ°ŽßtÂ//Â{Ükœš]òÕmUµvÉHéŽy­{λòÀ ™Ž:Ú’áq b¦,ÇuˆA0 òÀÔÝÖ@ñZmôRè)½j¶-`œ®·^ëç:ð¨ ΄iÎ_ mAOî†æ`âÙºÎØ·~Ÿoœ›ÆÖðÔ¢½€6lâþ1ÆW2Þ™6¾wm@ßà§š´íéN·2ÿ]÷Žy†®nž«6`Ž.×p¥,C1Tm(…æ¹Ô÷1\\tÁI%o¿Y3@{È£¤%ÝLˆ¤lᢨ'Ñ@jM“44±EjbpuœëÕœëÀ5¬É[¡<Û {Ï Uì¿îÓLÅ’__ýÝK[L¢U¼!åýï>ŽgH¼¾Œu]Îí’b@<¡%âþ:*x× ÂøE4ºJ·ô„ ïЙ>zeL´éO‚9Ð4E1Ç•`Á{/õÙñt7ÃI%‹©ežéø*‹q »â˜¼Ø‘Žš1èy`NŽÛ×îbk‚¬†LqšÇ'TOôNM\Óê<«ÀRx Znº5/ö€{øÜ^ðèP¡¼W L ÷çØ:Ÿõ¾±Œöé…žt·HÊZÆÆ«£ZûŒÇ’c@7´O­…q xºÇÁxÈ&ûÓƒÃh‹ÁÜV<[[Àdš¾ŸHýŒÞÉ忦~œͺ•n#ð Á¾þ|É”j è\- â‰Ö ¡ZØœC751øaOº¯•›aô£.M¡ èü°—‘3!¼Ä9»€=þm],¿ŒžSÃz®ìáºNºŸÉþUóÍÿça&¨îOÁG ì‰d87‹Ò4WU}M´ƒ0>‰¾ë£Î7h*$¡H•7¹}ÆŒÍMÏXìËKÜ=)ZáÄE †:º6X£¼§Øš¢:ÐR[Â=“Ç’îµ™ m œ¯·”=Ð ÌFÇ `Î~Ú ©¬s¢¹ÇŠ¢9=¸•Òï:ô¤w#Q:Ư=V¶kÀ¨°Þ7¬"&¬•"èD·”¸ 0Žæiúõ&×;l½çsé9öýiàz’®6­…ƲÝ|¯+³àà¶3Àüõ Sš0`Òä¦oô£}Æ€ÏIg3ÜE_Ä÷?n”Óž0>ÁX}·äíXjð­WCÁrœ¬‡¥l`Ií:%Ž))ź9xß¾A1pÏ‚'Øjàš>£T÷ÌgÈgvG/älŒžþàþø÷㠤䘞Í& øì|¬|+º¯UuuUãv½k$h¬ORg†b¼—–Ò>ÜÎெ•éW#Ø:Õ¼ïL¥¹Ì‹¤¸ bÎk¦aRzP×Z MÏORXº”Œåj¸N]8ÆðƒÂO¥þn ÜÊÚž0zóHëy¬-¬„ñðpK¾˜—Á¬qf‡§ÞO*®èµ}SÓ„I¦(—±3Ms¿÷ÛÐêÄí°|¡µ‡¥`Ð]ÛÄ8zlG4ãü[¢kò:Äç—}üDâñO%~ÄC£¯òOÖºD“..:¶µj”ó>‹©þ:(ù  ä€B_5UÉ¬Íø­Øÿ-®7Â5>ì\'„¾QËŒC2ÍTCäB_P€‰0Á‹´h~¦ŒbàIðül€wAé”úæøBºûãr¾Ó²Ýnô3>ÜZºÌö @ÇÜFZÍVSƒânÑà,SVcMÉrwºÏ‡Àë–F,Ë|¦˜íjÓÔ¬1t-3q2Ég¬ 8Ïà{_'*µ`ÁÕñKaûŸáJîŒÌ‰þÃýü±íN÷Õ#¶™»8–¾¿•{&ŸSÓσQ$Äsø¦˜~ü¸~²’ }ég©ÑMõ4—'㹡[=éçÃ80ÍAñŒmŽ{©/mhAwo•+š›U( —„®rVæØ(O¤bŠ™ŽžàlâdQ“-`ÚÆ Ð&Å1-Ò¹V7².ƒYw ¼ÈO8WƟݳ­À„S—%X_©Ý4⼨šzuÁ¾ÅJDÏ$ñ:¦9@ÛÞkä|õNpðMž[ø.ãÚ#‰p*o›¬®èÇø.È& ôŒ\ …)¾&L’©é†Æ×Å#©_¥¥GË6šXFZð_ïñP¶=>&@)ñF°ÔãÌ2‚#J²&¾ó ªÁÍ&;tCï/‚f`Õ˜=À÷K3£ÿÊê3&œžü‚À\_%úQIYf<Ñ™¦žz%Ô¸ÏØ»ŒùCŸøÃ[úþyažÏèôïÆ˜Á|ÐÃâz’ š§×Ç2¿—NÂô„¿Ðö…Ž` ­Êë!)&ÇQðc˜¹÷Ið\=™zÒË.Yàìç«ÛÄ5ÕÀ’ ;¸B40Š!St†Ù¤ëÕb092eze 7®?ä³ú9Ÿ\}«ïù|ÞsOÑK¿0‚—¾ö·zý´+̧mÅ3…áZªØy̽Žî4| ÖÆÊ+š>Úô½âs¯ÂµΘŸË¬é®±‚ªÃèÏ“éXL»eÿÉr|ß/Aå’;,ÞÛ L€­Ð ‚/è–'PSÓw…ÎÈ&Ž»Û`ð„û i ŠÖí“Ä4·F:eô]¾¾g]FU‹— ¼†j {úI~2AË3!‚wé>ÁØÕÁ[ê–Æð½Ÿ^cz¹±÷iǰÆZ.çîRØ ¯id™Cz2¡>–Näãñ4;e,$e$x øZpNPB’Ô¥Ï2±ú|67_,èn[F‚I¥nóæ½Š‘•°@¹ À½8˜{hušÛéœòÄàv5Ô3=@Ù4.ûÖ/Ÿ7A¾ÿ4èœ]¹±ZôõÕ)lJÜ/H;¯¼H /I{t ŽƒŸz¬}íÕƒÝkÛ@X›¡Î°>Õ…à]OáÃ…óM<ý`«ßlý¬ôDý×kü|a5ý,¢‹ãòLðÑ¥ÌU3áØj÷ [F4!S:õdD]Ì,æpñ°ݲb*„ ]ÙÇG\¨&t³L'xòM}Ï»éÿFì3¿A<ërCU¾52PZïɃ`¼;cëñÜ:è¥'½ç|±ïXz\_•Þ×¢k›ÈëÐñÇT–ßP¢o&øÃÐ^}%Îsû:ÚO¢×ò{‰{ Üïø3³'CâýÒcÿ¥t_Õ‚¨†Ë©êWRß…[¥Úä3ñê| ®EO½æÂ0ÐÎÖð$ä,á‹Oé´LiÆÀ>0€'³ŸâyjêkÀjà %¿'áâìÉ÷ªDõÖƒî+öƒ=!øÐ³€ñÿ=x°q2àêê<[ŸÓQ\›]/ÐÍ$ùÈoòq†S¼¡ãý¡=¬€pšB«&¾` X%¥)¿‰û%?ãEXÄeÝ—”1\¬Õ bž?…s6$Õ+ûU3JIK tcF´ñoû/À5д!¯…õtT^Ñ`?¬QÞâ,nE[þœ@qž»Ô†U`p]Ðç.€`ÕpŽ)ëæÛá®øû‹° gAE/Ý4ï–Bàqüú~ÿ_ƒ`ú)ÿ}x“]?Mù›IP[0>Õ1v‰qŒ~ŽZ¥m›cß1ç‘ ·æßÜ‘›FËuÉ'™p8ÒkÆÏøl1XzM¯T†B|”÷äËü †’ln$Å騻?Œ{•™Àmã‹,_Ê$@GBç ÉXÔÝ7f¼–¢+ ù‹àÑt4€NÞSÁ «‰<S °Zwƒ |ÞyÁšÖô=¡œøç"ñ„SøRŸ?/›õ¦¨ƒv-!`²: Fÿ>D½ÐñîçãÝü´MONMˆùc…µrB0é÷þ6UüóŒ¿ ë $ƒ<î~>Gt⟧h·‰Ö z‘ˆÃ~Í_—¥çÑqÙWâeóhý,Ð0£5MV ê”Üd¿‹<ˆ-`;ígÿxñ;éè04ˆb¦ô•uEà n5rÎpÐ:CqѤ˜-a5¤ÀZqær`s,z¤î;Qµ;ŸR»]p²:¨›:j`0”®}ÄûeðSi/} ›sŸ‹ƒT·ëôa¬>mã½þЉí¹a+?ì:1ì§ÏŒÈ<ð§9v°Ï|upާÍÖçlÃ8ןù-Cp%Ÿê88r« øèP†¡([`7˜ƒg»Ôw¤ñ`Ú´¸Á÷<´ mzX=ÔA?5×8Ÿr×LÑ*¼ ¢‰af;ßòQLµÅ€x.M‰XA|u¸Æ™K•èOÑcT§«ü>ö·Ÿ‹¢<Ö,?gy:bkTÐÛ6à}úµB p‚·|f¨}0ÖbßÈiŒ™ø$Lü9¨­>â~LXGûí›FÊdØa_ç«SxÎÖu|Æ95£èÿ|”À?Tö/]ß4=ÕÜö×äbX÷_ MRšaƒ¿åŒîÊ{Ï€ ð¦ç2œbºeÄ au†^ž–~>‰Ä‰€ñ_ïØª¡AÏ5ñZ§¬ƒúüï@ük".NQ~ÝÊoN~È+åXN>'à^~2–.ß­YªL†qaÙàìp­Ò¢q@€sÓÒ€yÕ»ðíÚu xj-ç»=KžñxÒ‹Óm5Úmð:xª¾û!$ExÐ)ÙªÌl¸š¿_hLÜE?!†e;õ]rô$6%Õ=þUJ„½Ž¹Hø4é!u‚:¨·÷,9–ð%›ìa°xÒOƒÛú°Z™Ù:ÉÄè} 9påÚtßyŸÆ-¹ñ? ᢂòŸübçAÔ5ø:¸5Ÿ×^¢éÓK?ïw9ãàÁÒÃǯN¯èÇŽHÏrxy=þ Øw9̹ð`Ƞͳ@?Í„í@Šÿ|§!íX Ÿ†çaè\#æ!HJØß ¸Ö ™7 ç†vMNLõ?NƒÉ%r½5pIê­^2:ç…Ží+Ä×jc¼<0ƦÜ[=Þm¼(³xsx3>¤ ­é·œ“¯€'¿=t‚Ž0t ›Oˆ~Åwïò_¿‹9Ø¿¸¦èPk™Q2žïëüáð˜dœº žçš• â!5Á‹²Ì NMÞê÷3Þ­èwì1F ìµ0ö‚„ÙêÀ¹à&ß±pL}æk3Iû`íà°E£á0$çú {ÝóÙ²É>Á­—!È:ÄUo—‘̨í õTGÕ=ë‚>¶/êò…É|ñt;I¥³ŸáX4̹ª`ðÜÕÒy ¡ ä‚kÙHÇS‘«È:P ˒ɧƒ àah £ä˜þZ*¸ª¸œªY@’¢êI¹¹;´51SWð“° ˆz%[i{ƒóÃ=ºqåÒÇ&ü6X&“›×l‰“ÿíæÛbÿ½=i‘d0ëqírŠ[«J6ÑæRb ÝÓD6¦ïYa«¸¨«•§ gÄey­É¥Ó ÔhøŠPqOmаáà¸âuR4Ìõ˜ ®¡µÕõ‹k(Î7è ûbÙo KÁ5ª¡Bn?F1R—´˜s»ÀиܫÔTú=ÝRâÙ*'jð}0 öÀØìßS_í!á¢Ûñ̰‹éhdR4D‚¤ã n¥ã®c*] pHˆ÷è ³-ˆs×BÐIo‚I66÷ÎÇ9w?—ú6#qn¹ì©ŠêL„?ÃgASÆÒÉa}ÿ!h|ÔAÝEÇ™!ê“›@=ç ®¼ Ú¥¾¶Úò-xfBwPš¶çkëôäø!® ”ѳŠ,‰¢é]øSµU©óáù3w^·Òžue£©%âŽ_¬`Æ2æ€ñš?‚pÝS¨O+»ê|HüÁPº¥ÄE}]ô³X±mž"55]Ít?'Ôàs½ÁdéÞs773uŒsqzÎí”ÇïnKe½ºj¸º¾niJ½#½vNPÉkýÄ­®Uÿ '|æMtܳÚA1a]ÀIðB*d‰éœçþ\ï„^ ¾G Ñùö=E»ÀÀ›ì+à-ÐfÓÁÎu^2ø\Æ×§¶ÏoÈt@7››Šn4~«*“_¥Í—)‘—ðÁe\™A#Aß›¨À¹Ÿöˆ6¨ßO§““èà¤øM‰¨øf ;Ky:Lp!‚/lÔ\ð ¸·ïÉ2+•à4•ñ~>[n%—8¢knM%톱£ä¿ÆÕŠþéÊdùè™Çùb¢Î†q°–TÜÎèþ™üšÿÈÇzt\áÐ}‘»ùFÔyF$Q›­ÚÄP<Ñy`B™LÚÖ¡ÒÙAêÒ±bÔe °í88üG6]ª¶§ÂI¯´$“Þ;KµÄ‡ôµû›‡… tž1{ô¾¨P¦˜ÑŽgîâ<áøº4.ìi0ëA0šž ç¸Ö À’ø³U!g>kƒŽ·2†¸¤Iz9< úüLÄüù3|19߀:|仇ÿÝå—ù)åÜøçx¥ƒÏ4äíóŠIŽŽôf‚φØAcçÑ”Œ{ÿ0˜0Ú½ Œœ~q3q=Ì‚QàÚO«R›¤·µhéNE6)U˜pÐW—:C PöƒÉiR¨¨¯­Ò‹L¾ñ§”ÊïrA?_<ÖžnàdŹã/¯ÝÐLV ´Õ"\{Ò5Ôçÿ®pӘϩÜôoÇ—çn‰|”žFU9yîBªÛÇxÒlz˜OXè–¯brÞþhá&¯'ý  º œ6yÌX[ÇuèÞ4Þ·¿ôig° yâÞ„LÁ/+Úó ~iê†KîqÙw!›ޤìXÄUCðá¦`ÐÕ½1l–à‚I\ü{»âÊðǹ°t,„>àÃF€€Å­†éçØ× EcÝ$)5¸Ð O€küÀrW¯â?†3…>be“ .íi•mÂIÆn¸‹ »ù¬¾’W‡ñ$O¿ýþ|jU?®u˜ö„© -øª¤*j“>ò˜ê}Ð ‚ƒ=DFÉÃÑÊ3®4`iÑMN—Ú”ò0½Ò’™{ ¼:x³È8¹€ú­„æÆlõ6)~–ó¾[>š ƒ§¡jð µr1 NJ5.LË_¦ñ½Á5–ƒ™¶ëôÿµªÍô+ ½˜S¡¸TEäv*׎%ügÙï*õOî*òh˜³7Gód7ßÝöM~mí»AÑ':1àë.Œyú}Fåõ§>‡ )ÌßæÈd SÀj3î4´eÄû¥d?jù@m8êd ÕCjº¼0 }’ÃúC:Óòo ï Ô‡2Å\FJ1óÖƒ†ú¼Bc1®õ‹y[ŃÏS±´M·&pEDÿw~ðãmŽé¼úðèÔQ°<á/ƒ î¸~qn ÓOÎñ™&Îk ?„93z¤. ªKxÎÖÀ|øjöŸt—"¦¤„u·»@.B® ƒ©é1¯3)fLnÙG"ÜH§ py¢[ 3h¤Ù¾¸ÕƒüSŸ9þ¹„ÑS’öÌ·é'ê'çOL³æœ™x"Õßj¨f–%_[Ù|­­^gñ¼àP.³Š>2âŽA_þ‹÷Y.Îß´ã, ™Rîé>§#ƃÇßT˜´r •îgŒô=3©Ò'Êÿ ¼ã]ÊHèŽàIJq˜ëÎÐV‚ïÒŠJ&šH÷:©rßž®±1G|û4Hýzƒ^Y©š9„^ÕÏD¬&—­ë›-V+cJ4öŽƒbbx°ûŠöÝ@öW‡FO¤~ú¹†±M­)é8¦IÐhôgŒ,Ihsc=t}7L¶0ô¡•S•+x@´'7ýðR–úLÙ?µKß=µ¦ÊȨ—ÿ±‰YKÏD/W 2›E§н@â—üx˜nq¾â:ÍÃã÷ëÍh j]X–²âÒ$ÄÈq)“<ô·<îï€it¸\½»ƒ:> ÁÀ{BC°éÆNÕ¶ôŽ©¯A´äI°xkêgLàí0ÑB`};ôåx.xXþŸç9îó§*Ú qíFûZêÿœëT—É:ÿý&ü<Ó“ bfqxŠZÂl0«CÐ9! ¶:ÖHRŽâ ˜®õ£"§×blÍc`<´í)x(õÛ ze%,Sê'|U¥¹{õuR[uò!«”{dÛ GhµoäCRjrậ`¼ÃA…CàéÆ}PÿY…lÝß9V1:£/ørÑXO“ŽÜE #“à2ž³„v_#ÀÓEb11 ÆnaAÐw«¡-Ì?•Wóý³¼§^àõûúê¹|e[t¶­û­73I´I ­1ñ[CÈ2ÛÉp è„ šÚ§¸®b ´~±Ÿ™dÞëfù4¸¬$>¯¶º±x€ŒÃÐAúιêAEú Ôgä ä©è›ñßðy’sÁÍ ZPÐìjƒa¨ŒFèÆYïs^‡YnU6)ÁaŽáðî4»a6ô†€¬N5e¿†Ø”ºó >Ź_1Ж^ƒà>Á±>dPêB>ÌõÕm×áö‹À y0ª€kê£y Ÿœç!P¼7ôÉî~Þ³õž}ÛÖÐ ¦‚‰´ 6Bð“Ϻ·óÛÁhÈ”¸wsæøi_ßý,þ]‡SêI13 ÃÖ8ÙÄøŒ÷5 aÖ¥[J8ÕÐ/nc¼–¥ÞÖô²KÖXÀwJM™¿ÜÛ…œè¾.îI2y ¤É1Ö€ó†zÄóÕu9èxõw~kpžbP”±`eî¢òâ~¶0å3¡ok"í“gl€>`åR|^†çÂZ>„½ï¤¯zg.wóQ7UŒˆ§Èk•ñdèXƒÛÖB §Œn‰X14De=ImàÄŸ†58SÓ÷bÅ6¯^JzÙEÿe•~|çu”Wµº).¬-Êf0¸­@}Ap®§y/¨«ön‡æð: …¼Þ Â>±ýúF;ƒ½[é»v2X>'*^ –tý4|¾1dýk¢ÙWÂs©«Ôµýõ01UÂÔ0åÔÚËP³f÷æ;Lkp3P0ë5ÂÀ{vÎrG+€3AL‚¤˜ÙFÒg‚äÓy tpH2ïaà€Åü&‡èëàg'*᩹*+ç•J\ȇIõSWm±UÓ™RÇ»€¶9n Mj«Ý« "5atr^@ÿ„ ±_|’]Ã1×Ê…9¶V¤%0 ëº#Áµ}…¸~à}ŸÑ ¼bÂýfŒC´°¾÷•/òmS½ÓüzöÕˆ¿¼2Óüða°U^¯šµ7€Šë$£¢8´ÄQÎ ÊØºN5°R8OåDâ»óà€·x…\Ew3Ì£0ïJiÁUùRn¸æ“ü¿Pu  œ•Ë ©W.(€Î3 ¨¯‹Ú®ïé“AÛ´Q|΀ôO·!œ³ ¼ÿXïz®¡ŸB mÏêë0ÇyÒö‚z7ðìoZá¡KùiÝ}qaã£S¥)¼ ßçâOÂ6òL!¨ ›÷T ÿó¡'˜É+ :¨°Ï)ö“”ÆzŒí‡kçÚoÚ2q}½̽ü-¯ÕÖé'·<¡ æï<þ•?ÆòtmKóÐæ @› ¦ã^«ŸssÓ×ò50I B竈c&€ÕÂUÂÚÄ+~uº~ðSxÆ ¢¯];Ü£[ªÿ×oA'hu¿É¡ìEÇ,Ö°#„¨ßÒ¯Eí•ñ[È­5ª'·=eh Žˆ3É of¨â¦AÜÈ$Ð`O@G(³O'<3)Ü;!× bJ¶éZáž{pµó¤îõy•ÿ›Å)•^bèéÔ‹æ0ÝJX¶ÜI¼¶¡²\£-ÀJ)êØØ?n½¿úÂû^ :ßje5ÐöLÑ.ǧÂG@ÅÌdƒ:´y:8ÇL·ªúŒþ3qŒ…{Ùw< —qЋ±þC3ü6„ŽÎS<¹3yCõƒ®ôÿŽ€âÂâõ |º*Ù€n,*²TPTF%4XeׂÏÚÇ¡ñx}ZçÑ‘Šm€uÂ0QjB×WòSóÇ?žÊó†éÓœ4ø>­¿N(ØñìßxªIPt¢ýdò꟣ îúËVÛµ)KœŸ ÷´q&Œ57a¬: ÀuÝ×dèÓ`4ý,®£>®cßÖk}hâ¹Þ"X_ăï¢*4ܸ)èÔà}Ð0ñ´ „lnu#7p3³Ì ŠåÌdiíÁà+M@Ï»‡ÏfŠAÉ¡‘Å ÓN ŠRSæ3g]*…O0ûø-Õ<©ük~ßö1ÓDœ¹ NÚØ‚½¯Ó×½Á@˜8Ú*¡¿™¾Ï„kŸõðè?}æ›èÆÂµs^¸Wþ3àj}8< ÆÇµÔËõ½ç˜úö‚ 0è9¾Ì3t褬æÂ`›É.ª"-ÀŔм¯R»@g„ 9ßl[ _7mIq-õ¤„¤ñ¾ãD06ÚÄSœ£#†€:'…ù Økê¯RÕùI>î¼ú™œUn_ŸŸTä_±å^lnà¡ÑÍÓx:Wzœ7ÁÓ—<•"ˆ÷Þç†S«}Û¡{bÌõ´?œdçêkÇ3GAø <CAÝL"õòcöwßïuåËÏ`x*=¹À…ƒ £3 T²%è–ƒnpUÂLtÞJPtÔ Xy 2IÑKÓ^°¯Jhߡ︢1ýÀµó!ŒÓõÔŒ[œÊaó­(õμS! ¾9édìÕ6ý¢o  IC–ƾ41–¤Çwndð<É®g<¬:Þ“ƒ`eô*G@¿8·.(a®ý·áë·¤«Ð€õ`Ƹ¹ï¡M ÂV‡‹™£QÏvP ãÊÑžÖ tóCð¨˜Ù­#@…zkê竨¥ßý\·t‚Áwl†»¦èȵàØðß²-kÌᜬäÿ#(súÉ®uE……`¬ÄÖ+OýQoEÛ½— V‚\íÑÏuÀgÒÛ××ÐOÀ€8%´úãµ³Š,ǽ¨Çn¨ú.ŒÓ~<‘Ÿùö¡£¢!¨¡¼tgŒS—OÙ:гیÅèøÇ˜–+7uq×”`0ÍPœSòÐSÒ–‚‰ö>èa¢é“"[*mí÷÷Õ`rúœ÷BKWgMx0õ󠟦~`ªV§$º£Â¢Ý$ðg_ÇÿƒékW'0ˆúÖ ÔWéÚÔB`µÁ@iŸ6ë—. ?¦C p1à3Ú«?ƒs{ÆóŒ¥¢nö­Óá8Ž»çf(NoºÁÏA%W‚¢âaà šåc1|•WÂ,(Ç]ßTT©* Â½À½mBR|Æõ­í@}LÅg×€cî«ÃÔ+½^°‹ú¥)€S]pÊòIb€½ïÅ…ÏSÏ«(Nu\Á¾lO·×úÝùÚ¤‰ÔœkFÖƒ`2h{sè 3Ádøè3绞âéX}˜ƒÀë»FñK¾DG‡qáMÐ|`싚q ¡1´3I\GE Ażgæ'Å@9WâÝ’zp'Žá3{ ô"Ð!ꨘ$Žë8“r¼Ã¯þ@•=½ÿ·ÔO]Tít¤ê¿cF#žô€4uÝ mÁ01‚ ô_[nxô~××Uq½H[m® ÆÆXé—¡ ïóÀÄp=K=¯…äŒçyG~Ÿ/{ ê€ zÃk÷ž ¨ÔFðÓ¼÷WÃpÐénâ\¨ždç`O·A#ƒ, ŒÒq_ƒ¤:¥`9Uy÷S‡&Mx¶ýTûaþø ?º¥ôŠÙžÊ:¦OGt‡Ö•úHEŸíC Ð§Š¾Ð^Á€š(Q´èýÄg¼®&DˆE7úoÀp­à¾¶›¡¼ö¹{'¡è:mÀ  ¸¹‰ ^TÇ,?mÁm}®143T¥LÅLvLcç‚„{tãŠâý¤èñC Ñ:OYÁµç˜Áz‘EÐõÇ?‰Žý‰ï5Vð}ÿ›Y¦TtÈ­NKpürÞ?ƒD}¦³]LšÚæRì›V•Õߢ½Áfý¼ôupϤÑGÞsLÿÙo1Òô¥I2~_jƒì±`°Í¨`€¼¯Bn$f®ÊæA¼ ŽgÊ~‚óM–y &Šzß}uJ¢Læ¾Åà:At˜Ï­…ä¸÷Ñ»ß_9l›¢švŒ7y÷”E7œ¶ÜÍg­öÄc+èG««Õ@ßÍ„ÕࡳÝžÚù`¥ÔF5ýw|ÖÖk ~t­~à\“m(Þ×·¶&•SŸg_ç/†/nä¤WaTº¯sÍ–× El» òá(8Ï1HIoÙó鯛¡5 < å‰ú´uà<Ô2E'zjœŸ ½âeþë Ç­IÞ=å~Ò¤S~;rnæ—~žÄ;Á*¸HŠØÆ–´ýÁày*;Á M°2Ý÷Z_E¥L}P®ç+1Œyp—‚‰bú>gÒ͹‰/.¼ :€ÙáµT…A€3KÞQŽ+:GÇó¼ö´j¤Á e-”;•bf»æ"ó½d«‚½`#˜µa_º¥D7$FÐùÒ_s¸røÔ¤ÎXyO&:q÷Œ`KJõ Ïóÿ©0š}ZB[зÝa/,•~ x°¬]C`è窌¥{Lýé3®žµ= Ía;8Oýºôoþ_ÜÜ@Xz<źKelEç…Ù`)öžÁWAƒ晡*áI5kí—'&NoXžžàzJXÃdrm“$dñúõÀ¹Î â<çkºÔÛÄw‹K£)üܦœikŸ±pÀVåò1 R_«ª¾´ ÷mõ3”V”vj<§=×ÓÀW‚‰ã‚IñZ… Dü­Ïîôu2h Åâ<ËPØføYkYô¹š0ÜÿMpžëêÂVZFÇþk´û…Tí`àìH6ÕO{å[PõŸÃ°)ÇnB>lm5¸Ž@'ðÔ&ÅòÞs0Z€¯Ö?3;•cä´šº¦bF_y_|à ¸Ø@xœT ¾’À±¾ð"ü¶`ù1a2“€¡ø¹ý´¾ZúƒA³o5Àgd#ô€àŒ°Cñ}©5XÒLE ü0Y}†õ›¯ˆŸ¿.jRõ­èmM:[¢ϪÜÈùèJÌ xŽ•°,ÉúÒxxÝŒÅr0 ’¢ý‹aX!­ÜVpÇU–µãïóúؤ²Ò»¦{Üô’͇͎Ð\ÈÓ­„ ¸ ÙäBn4GàrÐù'ŸŸؤi –qOÅÜÇPÁ\ÈÌôªŒdõ²ÕY¾>2…„Ê–<~$ºp8šÎI­ž9ë´¯Ïz¨ÉMèËÊ#À9C¹6@ÆAû< ¸Yúº!­±R¬ØEМûèÇúà¡Pô•13vÞ«úÎWÊJÿ¯~AÇàœ‘pv‚ï' Z=±\T%[ƒ÷ʃý2äƒÆdŠ{@W0¹ÚCRÔe tõ5Ë-wIašœ¤9?ŠZü+î<ËÁw«s’¬{þeTÿ/aÒl.ôvÄߣÓÄþ7¸»Ààëï›ú]ßÙJ§9x`’âôYœ u€‹§cfì^\Ltö° … ;n߀σŽàIuλ`|ÿ$â2Z À~Èôæ&Æ,q{@½êøc§4yIDATBçn†<°¿œk*îé«áÖ¨]ÿ}ÑfQ6-œyF¢Zg]ÓÏñ±å.Ìê‹â‡Øá0ÀŠöz€†‚>ü3øY§%dZ™Ï˜•43ô“k:ßêòÔ¯ø¢5N´¤œdß!Jò¤[rjƒ ê`﹠ʥq6Ñ”¼«C2ø¹ÀÍ“Ás^R<¹ËÀ„ ¢!îa¦Ú¶…"²Ž‰Äûà\my³Ç⦗cm87’ôõYÝA;”§xð¹ìËéwƒÕÐ!Ý÷Úƒj­#Áа Á{Ê{ õŸ± R‹ÎOÛEkV§€ïç‚l‹¿¯w’° Á¶m–Å€º‘ʘI±‚X +„›«X¶ d8.m}hÍà z6ìí˜ú˜„Á(×µ„±ÿ>OX}¾Å§ŠÆ|rx ^!Ì8'­…윊>pҾɿViJ_?é_—‡ÖûúÃCdR(ÆÄøèÇ !¶ƒ×>k‚ý–߈.ˆ.ŽË>EvãSy#¾ÿïÏp>tŒßå¸*Ož'¿ ˜LiÈÀKÀ»¬D<É[Á$²o™ÍíAO® šÑÞ_&X¸O7Þßg2ïéˆÕ¤Ùmh5”'æžûà«NR5¯Ï©`ã¨/EÑôáì2|5ì„^àg.c¡OMÀ䱪z¸ Òý½´ÍŠòñgø;º•†|;6ž?ïE /â/JúÅ<,=GÁ oxÒ}Gµ…¤XŠT8œ“™>oÖj€ = )¹èÞ Ùn6?ÍO÷^ˆÄËŇ'ÁäeÇïàb^ zó å¾C!»Ž€y`ô¸š[@ßë— !vpξúÙ™®>SiÆw“ÄPÞAø)Uóø—n¼:‚™˜Üm 3œ§¢V ðµáiOŠìóyPæòÓŠ»ù/ ¤¾Ã¥ùpåCM€¤iù…‡ã_TÀCâYú¾5¯Õ# øjäÔß÷{þ‹ñÀ¹ùR•¸˜?<èOàñ=üH>©×‰ßAž~«„¶Ô«p1àL/Z=¬,¾J¬Iñ3§€ï}×ðíÏ1ô‘äí»Ÿ©ú‡º?Ÿ­zwåÿÕ¥ß cg_–üM ¯=H¾¨šÏÜ›ú{w À‡.M¨óóúá´ VúðÝDÝøƒˆ‰ŸÖ'Y) ú+0L˜Z`²lå²Ðô‡ø—§›ãÏ o1þw”¿kX%  óÈè¶œÕÑï‰Z4áÚ*€_ůæ¤þáO(Üù‡‘±¼P¾ºSÊò¡³Á6Ü© £8ïú-„¼û‘Ò÷hjUJ¥*=PéJTz Ò•¨ô@¥*=PéJTz Ò•¨ôÀÿ÷øæôžÃëþÿÅIEND®B`‚ic08ÈX‰PNG  IHDR\r¨fsRGB®Îé pHYs  šœ@IDATxìœUÕö€ï(*"&!˜Ø‰” ¶>1ÿ¶ÏînÅîŽg Oìî@Ánì.@, ìVþßwîYã™Ã­TðÍò÷ÝÝûìXkí}îÌ`¡Ð$M+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дM+дÍ L>ÑŒ¤i M+0þ+Г.æ„oàÇ´»º4l šV iþa+pô…ÂMó £˜×ÇìVsèv…1,\øþóö/¼LþRÿ°97Mço^x~‹Lù7ëâñÓ «¬T(\±¡0fL¡ð;&¬Hx8Üoº®˜w*ñ …GXœ6ÿ ÔÈI6].˜ë>%²aòÙ½°[á'þAªcaªÂ2….…_‹|~Uø²ðváiò&Kò§(4/ .E¼üw$ùMãº+V(œ·Y¡0ï¼ezøüKAKôÒ»2†AÝM…ÂaO G“ÎîsRáõ£Éü±ó‰ö-¬ZØ Íi]èS˜¢ð 9jÑpô‡/¡ÔªiöÙoT¬ó,| KÂ8‘f…) ./|RxŸœóáCh’2+ 'f—Ù™Õ?¹PXbê2õòÙ’±=¸}'‚W³ýàcX ðÒÞ€ÿy)¥ÊÿK‹2GaöÂÎ…Å ë+,¼-j°ž×!öuЋÌBµ÷6h Ý!¾’š–øT0>‡7 ÷ ™oóÆz.âmrFÂoàÞØËÿ¢$sÇŸn³~¡p‘®ÅÁw¯î°0T“c¨À+AR_GÀ+W·Ba=МTÜÕýŸ–ÿU0¡[á,4¢7f_4xµ¬”è†AO8T™ZVÍ›Ãeiý» {AV´›“é¥é—„# £¹gÜÃëC]á5\€_dý¯É4Û U(tÖWê;=Éy(ð~_xt³~¹”¸¼¯Û·,¸e^»ôå«Û3¦?-X­PèÃíâ ²þ'¥Uþ'-L þN®ä]ß©UZ “Çß"%r-Ÿ~3ðS1Yñs&JÏ…-àjØ~€j2“š»+l ¯£ Ï†;þ±âûú™…ÂÒ'ð%§ô¼$ìΖd\šÉ¼†øã°%”»œ ¡L'²<„ÜJäП/ ”ÝÄkÃzDÿç¤Áÿ#g?JôkaÚB;¾üY·°¦?†¯éê’Óyf'q©É{ô¼K§…:ƒ­atš.Øç°1hÈÃ@ÃöÛ©ZW|8u½E¨á܃ -é´þžñ¹ÂÀ§¼D|ž¼Ç>Cé$//2Œ±3“y~É ³9š²ÝaúLo‚Ë¥ž BÜŠ‡àuØ!Í4Ïm8zÃópf¡0ˆ%_‹¨»^I+(þçH­ê8)Ïx#NÒ« Ë1·Ö«)žæÜÿ*Ê}”ö…ŸÒZ~ó¤érÆ~/¬ ¾ZLwCðí¾yšJkƒ!«–““nŽÅù )¼ÅW‰/ðµ÷³¤ŽÅYNJJìxÀø_©düNL9öNbc¸­o@è‘»^¾<ñ÷Mó"ðµààÍnÌí|)K5¹ø=?|ÒZ¿˜N£CUõŸ+­øÆýRŒßo4bÕLù L·4QFü²î{È~!8 éQý-)hPbèa‚~ e^¶¯’ ÓLwÅgÛfc¸ 4|ŸkßG`kèÇUy_^Rn,Çñ7§ó-¹QwW‰^˜‚³šëŒ‰G«ñï_¦î¿È?\®ýàðÓÀ60²â¥¬?ÜAµAüá>…ÂÐáÅŸÛd«ýcã®Í?KZ°ßu…%pÿ7°ãm¹*›n(æã ÆMݰ(IYþxÒgïšÍHß Þ <ÙˉÏqVX ÌDütؾ‡J¢öÞ>ÇSÞWŽO`ÈÏ…¬zñY¶uÌ߀s|­ð&?W^x§p8©Àž'q6­o+ÞcªÞkj§ù ¼kWiñåwaFØL»µ~%“ût0;òÀMâ?´ó§‰ÿh©¤N“êÄ,‚~ÌÇð+i+Ê/‚õ ¿ Ó‘w ¬ ÙS[-¹©ÏA…÷%éÏG1¬ðk³8´Žãð$—áAð·\í½át’ Õi›‘„Wƒ“þœ¶ƒáh\öÉ|ïÈ[ã ’ÿ8q®“¶h¨žpËrîoŸüšçFSifÎüVØ ØÝzQ«¸“¶„R§üä_ÛÁ—Çbûÿƒ|¹}kt:†ÖàØKÉ(25C¯ü!öëÝu!Ðx«íœNäfÐQiaƒaðõ$+ö;=L‰[y†^5ûÏùow˜q¯†ã7"—CˆOw6ã*3ËmœéÍü 3éL//C™ÚB¹Ó™¢±äir\’EÇ*)Ÿ1‚¢v°5ø±(N*&÷.ñ}àÿ€í^fF^ìÞ Jµ¥§ú$#ÿŒ¹´æbÝs™‹uWá•ZÔs8õ\5.df"çÀ¿ ÜꌦìXòâ‰{1¬¥ÚkôaWø òⸯƒCÞMIžF½ü•Ä;/Úš¼nXO#¿Ö„jkã¸u ¿Ã#öZMÏŒ®JÜIršÁSp4J¸‚1´|'‘¼¡ÌIëEÒ¼Œ½K¥ïÚ„J² …gWª)»ƒøÝpô„î°¸DYq™gò#Çr?—ai^ÈÖ™Ôã¥TtÒšS+~Œ{6ÎÿZ”sk†~-ü +A P‰Ë‰õ<>|?£ÐøÔ¸RÆIv"Ö}ºB´K øÐHoOÛr«ëq¥ö‚¼¨iŽa+ð>š—Éð&°"üž/̤%¾<ØŸb]çôÌåÆFQIqž¯Ckx <6}%yìËu\8™¯ò¦#¦ŒáNý&?5ñ>£(t¬+,7dLár}uˆ~i5h¹ðÒNYç°.èc燔Æá¤„¼D½A<úæÅ2•"®â„O~èõ­bÜ­•ÆOá2ðDÑ?‘3éKvý&¥Ù8î'ë]8ù÷íøÁ×W¤n…­ásðlz>†Má[¨WAâ!ªªÆ¦ö) »[ÿ…™y¥Ä§{î­dˆÚb¾·ŸYNlïdûüI®\X©1;ÆW èàJíàLä_€c ±?×eÐQ5F4ðÇAǪã¼ÖoŠãp=³ÏÓHË̇;¸;¸ÜùaoKÞEPNln·gtš^R”ŸJ|OÈöi¸,Y±Ý{ ªt€+ ;,Y¹‡„[õ2àCO;­PØ+[>©ÆU‰IJZ:ÚºÂLg°¿÷Iêíuµ3¼ÎH]6o÷ƒN!«$ëÿÝE-˜5‰UþPkµÁxV4¬Ÿ³%â¶YÀ4ËËíŒùÎõEÈ?›¬$ï\ÂJ”ë<–€ç \ÿ•Ÿç±é3]o­Xg—]×oIëëÍ ía~KéÌâ»}~(MŒÿ#e$Ú,G¹>ާ´/ì ʲðT+~BàöZ?oüÖ°ßp3Ìû€gÈ •>$¦€=àû¢Ù1[>©ÆÝ¢IIê~ª+´FÀÌINñã¦/TjoY'ø/t…!Dô ´†X›(3tǛÛ0Tzʼn¸Î€Î#êηƒë[IxæÌëâg*ÿ°_C¼¼ Ô*í©¸ ¬‡Ãpð¢¢rËU£šô¦Â1°<Ì .Ý…à]JEÕ¹v‚ž<’iõãÌ9‡ä$+“Mb#Ÿî„1…Ž? Ó×h²£÷ŠjZ7ó4¶µÁãá&¸4„f ÛÿFŠüÔ"ö©fy\„ø¬p,‘W)´ý; A†LE$kБŸ9†’W ª)ÓBµö襌ßjŽQÇó-¸fÕÄõôë@¶¾ý·€Í@Ks?Â9­ó¸]yeñ$®Ï/™¼ÿƒ‹K”Õ’¥X4Ú‹ ür©aQ<–ìJŽSqjªÂÁð ![ñ9ÞX’N,åóQ6)†ªÃ$#réÞÿ°ÂÔcædò»ªA:›0†ü¬Ô Þ£âÿàø/Œ„¶ð0, å ‡¢±Äq(D›O‰«Å¡yD+ŠÎâ_ ÆO Ž_ãwœµˆNL§¦Ñk¨:56ëPH–”•ɽ lWIt4Ó€ÏÊ‹óö¨ÝNŸ¯ÇX6=®á¯4P«¤ØÝt`X‹ÌwrßÀ‘p¬ë©ð5Tý™Û7$S±;qÁ¶ð(gÇ>@ëWkž„úo?O*2©8€ÉЯ÷?éȯæt@?Ô¼hLíàý|A.­ãPKtáîêG0¼?Þ÷ì«QÙ?‡éÓÊSª%¥Æ—V+p,«À0pZV5JªÔ‹Æ>?<€}Õ‴°­àJh¥ÄñØïÒຕ­K'àZÞ3€â:>εùÝ$UóÇÖÔ<쮚8,§{(ô‚î ¬wƒÎ`o¸Žƒ¡œ¸m]à Ðï…h$Áp9¬·è·ç ù^ñ­åF/U“šLà@Þ¬ìP˜ó’£YûJÆ©ñ~\㸋ß"Ж„¶p&Üj•'_%Qû¶€ËÀq©qjaceF|‘6Ò©äçèXóxTzkðØšž†a ñY·Ñy­ÉùU¢Áòæ‚Z´Ä1/ZG®kÊú>|á8È´¹¼†vRÇ-;0Æâ–Æy°-qôˆ? )þ9q~‰É®—MˆÝVŸú#²Q/˜Þf·íCh¯By;ÑIJjU•¿mRý¸e¡C‹ÎrjÝ¡Ê04Š«À÷ýJ;œíæuÿðèH®ƒ¯Á~ÚÃ<`¾åæÅʿօ«a ¨ö=‚Ž#d*"½†{,´…… úWã†l’I›Èû™´Z¹´Ó=A-µŸÓ`,±¦Î 3üŠF¯Cë ö×Ñø9§ß¡CÓ°aÝa$…Mf'Kñ y7A{è ±\DÈᤎlSLG° ¨*.A¶½éãaÿ4?[FV"»ðy n›mž.K'ì “„”šÛD3pŒÿ!ìy¥:5À“ÕU®$ãõ°;|T©bZ¦á=jÐ ÐZâ³4OØaðh(Ó‚ÏYTôÑ ¼ïÂú`yV¦&!Šá`ß®¾wMN:ƒÇÙn Ñ*¿ÀŠÝ)ã_æòœË ð0<#Ày8æÅanÐÐ}vV¬3 ´*ò*Ì:Çq‘÷ùFþpü™ãŠõð9«„Çá_™v÷Ö}r9±ýµ°tÌU²Ìå¹f‚m /{“qJ>3“>Ÿxx¼](÷ÀªÉ?9˜ü5r’71dÕj¢gWœÿƒu…º´å½ëôXC©E¦£^#9¹*ÍN#¸6_Ã÷Eo=(ÕÎ<•YCÕÀîßXÌÅ1j-›c:ÞŸ ‘R‡ÃYöP w8 G<#â†ó¨»cZ0¡[ÌI[³0”ßäçêKL—L¡ïôªˆËPN|{ÒI©:$å^èSìÊ ÌD-nõD%Ç3šø~täj½s¿ëøÐ@kwâ6X<=K‰³Öm{ÂÍ ¦UÊÛasP#jÇop | =ÁçjHa<¾6DœhYÑ8ÕðÕáJP#kiGµD¼]ܶw>yÑg‚7Á«¹ãþ5E‡àMAçÙv…Ï¡1¢ÃÑ"^Ç×ÜÇ¥‚1ÜÉZLîúf€}:¾Rc´ iúTÅaý %¬vY«è×0Ȥm¥6OPø ôo>Ã×€ œ8Uixt/ÁX½K‹/tî~…™Rú7JcÖñ¯¦ã™ŸEí3bW ¬?u'g%hµˆ=< +€UN¡ ¯IÃÈS‰ç‚ZEÅ:“°8xŒü•p]iè‰|=l _C-b{˜ŽCM¬$ª¤ÎÒ[Šs~l?ž…yAçÐù…ʬûz'òƒæ¿?©“ûá‰ÏÔéFœh½s0žŠ¾ô}°šr:lÁ±ÐX9›;ƒÃ©$.õ­0 è4~Ÿ½”ÇgŸ:™+`CX–dè¨Ãw›¿›ü†¬‰RÜú‰IÚ,ƒñ¯Êˆz¨€Þ©„çAå\ T¤JâŽÌ ž^îb^œñ°ä kvò4„Æ8€¨ï˜lëm`N`ç“{cc€š¤Ñ9F eSPû¶˪i¯ã˜†kPIâYaä¶{œ{{0¿X¯2Çß9Œc6Žê­PûK§¡±}¸ŽÏ¸{d\ r¾që²Ûçt<™eX Ö€ZÄG¼µLezêmOÃ!Ð4hQÈŠS8 Þ‚CA¿»'lHýL{¿»rgñBSÌÈ>Ý–‰FVâ±na4/:¢-`>x ì6pg44wµœ¬Híòuܱg |yiNÆ(0¬&öõ)|ó€Ú%Þ6•¿1bûß vÅËãÞ0òs!«¤ÌOî%KÊg:—Àç·‡¹a8Ëj…ªOáÏ)¼UÐæRnmÇüT<µ§¦c“ÉS"î|Ǽ‰VOó6p``UÅi1¬äß÷ªu—¦~8 ¦„‡!äM"'Æÿï4œ•PqË·ïL°¢¨A›¶µýD³Øâ/þ¬qÉÿüQa³·_ÌZ»½¬sÁtéq°tWø=˜J‰§¿§oìJÔQ¡5XݼZ‘]§óv¾ —V‹4~fÁ´ÌþÄ2”>ë„Ρ±’Ûh÷…GਦÁ:¯Ï@#¬E¸¦†À—Ð|ö¯ÀU>q–5 šÔmï‡Ñ×ÙÞµþ…ŸNNÅ÷’Œyˆé)r”ræåÄ)ç§í™°?ô†}a0T“¹©]Újõ-? 0àä7ÿ^&Üô¯>s7`z úT5Ý2ƒ2 ÅC‹—‚mŠ9×çDáØÌþƒ¸ÑÝÅÚÌC׿CcÔªº`EÃBÁ’Ö| ìY(%;‘y^¦@ƒ¸ú@^›2Õ’Ÿ=•ÍÈÅmë8އΠb+_€cšÑ¢ô+ÛTz&ÅågJWûg¡*·ŽÏ]5#ZV¬s/ô«k¢sõ–T«†`Y»?F}çi?áXŸ%´: t¾öç<ÄçëŒG~„K5ª-µ„¾xÛÅ~ð”“Õ)x¦\a…|‡¹ìÞ:Ö%3ÄbFú¹,áÿÂ:3AÿâϘVªu9iò—Èß=×§í©ü•åÎD\°~ò1=(–nפq‚DP¦äkâõ ç…û`0̱+ºaO7† ù0¨ù÷~²ˆJ?Kƒœ?jà· u¬FÆs³F¤£Ø4Z˳õI6JlßœÃmàÆ¼¬á;>Ó¦N Y‘C©¼ìïgz‚oŸIg£úêSá$°^wÈJ:üdx(ؼq”’eÈ|4-8—ðøb¼nç¢VnýíËûwˆj·M~AËÃv¸ºkyã²æBp-,•Ö2O—N°¼ÏÃwðèþ•Õ“Ô-%¢†l™Ê¨ñ¯ÞHÊI[ ž‚9KT°¯éa>¸4À)!;ã#Á©¶3Ž}:°¿'`Tw^J{x:@ˆÏw¡7†f}6É’b®ÿýвmÿ|{{:Ãpb= #N4‘\º7õOÆq¹³Ógýjø†ñŒ´Íedm Õ–„*õbÖ_\†ë pYIþç +f… LrAÛ‰pˆ!d똷<ì}`x®ýqV¬ÛΆeÀÛÃÑpà4þÅN7ü1ü­â’ÿÒö¾y'«SÓ³Z[¯K…()Ÿ«2´.Y:v¦³ú –ƒùAc[:Ùp\jÅ@˜l#jÊlÛ‡aF¸ÖƒJÆOqò€E9Q+~ƒ AÇô&ŒÏDjŸó¼F€ùöë)'÷ÔÄ-ß ¾ëÔ"ñ ‡Ž4DrK7€/ÈìÛý±®¡(¥ÂßÉÊöa­¾þ•”Ãó×ß±‹û@85ü`ºÖ1S5+ªÖað.Üó€<åqØ ô‰[Rí1-‹Õ’Ï•ùܶLRc¸ÔŠ*và+uêTü-cR¯T›ëŸ2ºãøu›wøéþèÝ;kd±ZDÇPc]s¬’òŸRäNëú¿ŽàŒU¶@¥Ry/NCV%·J™œØö±=ؾšèÀ¼u,]­"å*÷ûð¨}£Áñ< ]!Œ‡hÍâ\^„Aæ˜}†ÿô†qé—fÉšÝO¸¶ äèÅŸ]K~¢ì ÇAˆC?Ž/K+Cc¤œìI'÷à  º:UNKß1M·"t‹‚åq÷Gÿ„ŒÔ_/,û_'à çäqó€{Ø‚ÕÙÊÕ÷z_ÍP%¹Ê«Ôî–†QI,Ÿ4&ÅD7x PÞzå'ZV¦¦ä'plûÁe0-¬ßA^4æPÖZæc{Yp¬ ÃQ ‘Ï?BO°_¥,.žb¨†}ŽÓ#îUpÿ ‹À> ¦Í—€u‡Ã° (>Ç~²˜ï\²yÓ‘vîƒ+ùÙí„Y Šºd'c‹ñ™¯F^Ì!òX‡ùyÞoäßÅ|W '€ÑOfß69LZü&<ÃÀ-²úi DbªøiÅ¥yަ¾P‹Øn8½DeÕsœ;§åyuÕÏŸŒ­Çºøˆ›Š_ ;Ô¿Tbþì‡úœ%¶fÎ$¢÷T·ž†^¥ ‚šÄU{@¹ÑOIÙõ°)| !>ôÐáÌ™B5É~Ö UeG9“k0»VJMÄíÓý¯Ö+'ŽÛ¾Ÿ‡gÁÜ1€Î ñ/m!;~’‰6*ÞN4B5Ø“}=˜ tvŽå5ø–„X+× |A‡p 8ˆb]±n¶Ý ¤u,ç⃻ äZ\9•>¨’Ô±¯ÛD¿ÙzÆ©÷ký1a÷©¨FxÎv_¯ cê|Ax}9,§¸<¸tµÈ`*Ñ}òVõß!ÂÔ’·½•"³BˆÑ&þ¸M™:.ý5°eZ~áqS7{X˜ÙìVü†j˜y¥d·åÏ|îôå™=x‚‹¢L'¹knlcDåÑݽr¢¡Zž7Ûi`žN¢šX?»[* +¶ < CA‡ä˜B|nRäYî<=ißö%è·Á¢àq!hÄÝáFøPòÄcê5u*>ÏÛÇÕp$t„}a3Ð!|a(>§gš¶½ùöa7`{8.†ƒápƒ¬u³íö"ÿ|Àiô8¡âúIFúûdÒr×2ÖÉ´ñ,$#݉5žŒúC+utɺ3÷´Ý59˜ük‰ŸMÑÑ ?®Õø©š,ýÍF2âRžUߘW²ÈJ¤†6Èi˜p;TñxŽªáÔ³r Ê'ãœÙ3›ÿWų¸?ó™GnKïs€ >ø¾…øPÁ#îÎð:t(Ó-ûM¼Jµ&x²o_CcEÍð¸±íÐúÂhØÎ€@±ì5x<é}ö 0 Þ„“`•”‘„…Æç9V PцÃÝ0¬3‚Nâ+ÈŠ <¨qmó•lø1éM¡ÜW€} >£Kêë0quŒ¯ç‘ü:E)ý:‡÷Ë|ð—~’*ŽÇH¶ÉÈówºñÜ·(¿ãGþ]8ÖàâSÓW;ÊNœšºá¤H;¦q‡PJº‘é²\ªZ(%3“éV’…)t»4ôþpd-}.Ò»À•ÅŸF^@ôUøËD5ûÓ¥-g¦zï>Í‚z6F%m*zc6qêë¢u q¥ šˆ»:–¹”¨”[ÀXÊiBä—›Jìdú‚Ï9|¦Záªj8¯€NbUØTZçúüZC?Ð Ú‡Ï v"~ì -á`X¶Å6yÃ7?ƬƒlÖ%ʲ¡qù¼9 ÌõYzƒNÈ2æ~«M§WÊ$5Š|k~'ÍNþ¿ÚžŠ¿»1çñlHÜäŒÝ/ôùî›m…> Ö‹hcEÕ+'³Q°< .ý1W¿|‡97ôUÀAV,_œ}]ÌÒz´üeâóÿlùÏ‹8€álÙ}¬>&ÚWÉûf×>©H&u¬—œØÖ6–G:òlÏ\wÿ‘ úqÌO|·Iz#Öy ©.Î@âDk•©¸_•÷¢Þа~‰úÛ“çÑC/Q¥>kbö£Ñ»¼ÏÂ3à™Ñ®ßõŒêoDÍ #µŒyœž”îi«Exã\•V^ Ž{¸óB>P¨d%¾#ÔÕz i8@ƒ«4:Ë‚• ć¨RTWÝ—¸Y¡5äŸgžv²c¬$NLƒS«…óa؇cѰ†°|¶™|îa0-øÛ´ûá ¸4ë ÃÀ:y‰ñ[÷Ø0–óŠ:†¥â:Ǥ蘂á0 ºsi:©ÐÿÚ>#+ÑW6/ώ׶¦c Qé´¯»È_˜ñ´qŸhンnsR¾¥ãtn®­ëhØHiŒ°ë÷á48bøD G¤¯EŽO+¹ÅËAÇ4­I¼ÎcxFÛ4ëO\Ú?EÜÃÎ|Å…¾$ˆÑiï ]0¸;§"2 hVö b¼—ƒ•7‡ØÜP²1Í’“N§¡4 ÈYÕ¢>Ã>tÁ-ÀñäÅç;®râ8¦†GR<Ý=}MÏŽCe=ö†oàk¸ F€}ÿýA§gÜÛÄe ¦qò%ÿÛsëé vç× æMãÎCqëzë0Ì—YÇ1»þÆ}ž†~4Äümç¼-;) ?#ÜŒ¿s§ìq¢C(ïÏ#]oÙ<óC⹦}~¤ #n™’– \Å2ÇB8ÁÁŒu$†¿3zsŽë”–ÕEÕÄÇ4F4X·ÄÃUu߆y œø¬{a¸}¢ΊýrvÍuÚ€Z²z¶ðOŠ»¼†Ôµd"'£â«Ð»û¤¾=êìÿuãê³5‘VplYƒuu<1¯•Ðz«›­Ç¨M«+€ò1X^i'¬—w¸£s…¬Ni©\¾IwU£½tB‡Ã§àÜmÇ켂c£À¹õ…9À1gçõw%ÿKðJ„–k ƒáµ4¿'áÜ c±/?ùy–ëªó±­¡ëø2øÌçcNn>Ž÷Ði(»eö!}ŸÐ+3{cwCù0\*Æn"ļȼ£^Ô1í3ã‘OxÎkw÷FqüBÝäËDÖá0œÀ"´ÙÐ6ÔMôƒ Vq)Ü^ ¸±â¥ìØ ¼ˆÜA^ž&ãYðœëK€²6œmÀá‡ÜHä?pwÑlœÕŸ*.éŸ"\_]Æ^1ƒ:t&ù®ïAB½ÚŽëó13¸*nz3˜B4lË:€†5 ¸2/»¶2¨´®œå&pe_LÓ>°1¢Q- ×CgÈ.{kÒ¼ø¼Çý6 ƒ~°1|¶õ$3‚'¶}hìKC7hö¥öÙóµÝLp>l_ƒã²,BãÊ·àú- ‚v'¸Ž³ƒÏ¿œ‹é‹áIx4¨YAäxÚ‚sÿ ì×uUb\†0ùPÞ*Ðrÿ0Ç¡ÏÁÇp )ëiF@4Û™——l^Ä#´nÄyÎ=Ì·;a}že>ß²Ägâ9ûck÷Š¢95ªÊHj¨*.Qce¸l§BoÀ`ëÏ!¢Éß›]M8?ô‚î}Žêí’;^·2Ä~ß…!E‹P‹þTiÌzÕ<ly»ýÑ-h¡¾MÃÙp(s›åI©è‚îW‰ ,+Ž”MN~aæBÛ- WKÐø?„uàGñùIø|¦§õ%°nš&Hò‡Îª€&8aÇáӹГýÇóáÊn‡`4(QHÄ#Œü)‰¨Å®Ç›p|ûÁ ¦í:…0n¢õ–âƒÈt„¬ïjâcÞ²ÂØr&sÙͽ ‰1FûÈ0_n:Ú§Ýö8Ä ]K%Êœ£s5­Ãt á Ö¿m{FßdW|Z"KT«X¥ÜåU]€Ûýì ³A9y•‚÷a8l Í@qøBO´5œ›èÏð§‰[4Á»ö8_jz x°ŸGƒû6G7~4½5‘ß@q¯€n°5Ô"n|+xt$#á=PaöEÃT3CW_#шÖE…»úÆä³}¦Fî°hp³Âyð(óCШÝÑÀ±øŒ<¶qKý+Ö ‰úÍÉ Ý5S|MPû”hûñaIpüó€7)‹}9ŽX—RñÈ‹:¯1e´|fû*!Nízž½»ãÏæåËL[nݨ—ÆĨӹ)–9÷Õ¸ãPœ¯Ž×8¼HúVÂ-H¶…j2¡€Ïñ™ªg[ýÒ­(ûSzœCÖa7U¾™ìõàO—t‚J.¹«òkÒKÓkìéHâêà8~3>ÓI|îØ¼ öyg¿`vP–½ß pÌ ºy”46 ½] ¶Õ£\CPÑŽNGâܶ3ø¬…`qX¬§SÚç†àí㸠Ôx×~p}–Ï L+™üºiùÎMÝä«bQ©ÏéÉìÌÚ]I?‹ÅGhßÆÙ´ñH§ñ7hÃc óåËložó7Œq§á¬„]Év©>ƒ¹¡’¨ü/•*U)Ûò§ÀCî¸V‡ZDߥú¬çÁŠÂ6×ÁÐ..~ƒôEäOèp‚; ý–M0Ë9鬰/ Nô>¸u{>Bш&âJxEý4j7·V±®Fâê¯öÑ–…9àJx-e8¡ý 3C3P™Â騗˜Ö€/Eáè_Ã0°ÿ¶ ö €yÁ]·Ü<Û:'ŽDGòø¼Vàb¸¦Ùáä7N¾"t >·ûРŸrX:†ïÎ‰Ïø4ð@ËñÙoãr>­AÇÐ Þ€ûàuÐùÌ ŽÑñ„AEœ,¿´¼ê<|†ëTAÜõ,`$+ùt¶Ì¸å>; ïäùk1·)â™æGæE:Ækè˜â‹¸Œ.¡þÑeŽæDëÅ¥òÄ^±>§¶ÈPª€'xwPܪc`oPEbJDKЇâÍàyãß Ž]ù‡§ÙÍaů”IMx)µ.ãó”îdƒ/£'p't»§ÔÃÿ&¢ÒæÅ}z€+×ј/€ á˜<éœ}Ùw øžµõmÐÐ=e§ë¹âº¢‘ŠÒ†ƒ³.xd¸ÓË‚Úãd5Ú§ /h*¤}†bNM\ëø –ûÒø7‡7áøÚ@sXt(gHÌ'Òö¯¸º€í¬£8¦O 4*ò µ×DM~Û ÕاuÒú“ßË2MÚúUĦ#à"«ÇórýÕwa~ˆ}›6¤Ý)¿`DîKfÉ<ɪw|ÎÛµuÕ'C1/]s“—‚Óý?(%'’¹_©‚ynß pkÜv‡Ó$š|‡z á¦p<ô†% [‡d9…”þ>€'`Pö‚Å€±Wêªã,.ó“#øùåHz{Ôů@ÛTØÓ°¹øp¦¥ÄM[4„ 1S~€ú½À>–‚G@#ÓÐíÇgjLÊB`Úg„ĘtƒÁ´ ¦b©”Wƒ{|ýAƒ œÉä&\|Žã°‰¸ÎdAÐÈ^ Tg ãZ¿cõ™¶³žaV"sÒqŒ„UÁ¶­bùÜðÄZš§ê ;bj8, —'4ß¾¸9ô?“aLQ¬NNE±Ë¶ð f¬=♎;âD1óI³’€¼É£n¶]6nEÓ’/'Ÿa'—« ½ é»ÇEܺ}@Ãt™Bb˜‘VE>Iz¢¿ó¥y¥‚éÉŒ¡kŽ5¤/‘ŽÅâ#‰ù2ÌÏa|úî€Ç{ç*zøúÃ@ûЖ¦‘=ùˆ‰èX¢ÁÞ=AëU¼{Í î€¢aé®W•}\ÄcÃA;Ž`qøæJѸ½=\ ] 9¸›æçCËÜÝWa0|§ƒõ<å •‹©âg>Ïg>hrcˆµÊî¦cxVÛ[åù8E‰´âÓ[Á³°ûö$‡êII£>|ÜÓ|¸ï^o‰1FÚ0æeñ1„ÿþŸ¨dˬkÇmhÇ¢„ãs?h›¬}8BË»RE\2xvˆ¥8‘xþ`}Ëï—bØj‘|×ÑÈíݼLã‘ä?›dÊ·#®í(§[ع¸”îΗs‚H.´]Ykmäè@ìãÄ“waÃrâfêöîØàru#ßhX³D¡ÆË`’_ãÕXÆEtû£Á¾_Oö•@wî8CÙn Þ|¦yYTDô¸ <ù}mhÇ *|´³MÄ#4/˜š¸ýÍmÁ޲¨ohþ:`Ý0’ly6í?§n;Ø °€‹´€qg>|ì#ŒÃ¡Ô"¶›ÙŠùdó²q÷ßrÅ0âIFñÃ,üYbÄ:gŠÙe?‡PṙB­ÆOÕä럧¤²!ájà6”’¹È|!Wp*é‹Ó¼i …åþø¹TZ2a‚ åüf€ÍÖ5g\·B/ÈîÍ7î‚FRM<±Õ‚ï«UL˧ ´o 6Ä´dx42Ç!lA›=¡7¬ö©á¨Ù>ïP|žFd™ù¦€ãa X4þ›`°|Ø.ÁvYå&Y/æ[~hØÓÃïPN¬ÿè0Ô¢0ò}~ij¡}âÅ›bÈÎsØÖò`Np¼ö/›»›¬Í ÂVPJÔ’»`i(5×Rmìð¹Y‰gÛ§Æo¦}/Ì¢ÚåeQ2ÜŠ!ùÒ'Áq¹ü~¤÷†àØ¢øo/ÕV‡*µË„pu«pi¼gn Wƒ×­èØýx¼«š®$ßQ¸ 覣£Rõíü2й”Z•º< •Yi óøÂèM÷YŽÍS]7íÍæa¸æ™®ð X×qN:…åÒ4A½ü@laè§‚G€mBÔ(Íš`Y©¹’]RÚ‘;¼dIÃLŸ'XÅYO4,ŸÔ:8’0n@YáÙßSè…®ÁÜË6¨PPe}î¥éEàyt ì@?˜² ¼—ëÈ!-3ÀƒàRgešl"ŸOx6¨vž-¿mÊ7¥dÜ¥’yÕÒkÝÔüšËþ̇ýMÞ•Î"ÔîeìÃÓÄ“oß kO:¯?-˵û• °œh°žàw€³­uùœÈQ02mç.ø,Ãw¡h¸/€Ú´8¬“'šÈu|nÞçJ‰ èøvƒËá ˆ5¸”¸ÞÕg;þ,$+Ê,”ײ”Ø×Tà¦Ý ·0•}¸ÅéËÇU2m×gn÷3Çé+“]ß³ùÓ™²0¿væg¥Z9uÝ‚÷áS؇=ÁSµhøG• Ïþ7œÂøJw:xªL'Óü‡så‰ãËå¹ý-á\8 Ödb0a>}ÆxÉ:ü(62ºï7Ú›º,>àÜÛ}‰¨ä‘y©ü_XÜѼ¨1¯@G¨Ô·†«zjk¸¥4ìbÖ`; ²ø ïŒÏƒùׂù+B¥>™òí¿u+ÕÓÀ1<¯T“¡cÔÎk  i4yŒ†¬CRKo ΩhqC!šˆcþ ¦넘¯v½ Cà#X æá+‰ø¡ÊdÄí/Æk¼1íì'ÿrðžÛžpº('î?²èЬÓ!/‘c<ÙÐ ö/ÑþðÇÀ›d;mý¨Fßú¤ÌI¨xk]FÁ¡À2'ç„j¢Oœ ì>†@´&Ñ×>K—¨m_íḖó‡å /ÉØ …5aZ‰ú]Gt‚Hcç–èVCÑmÔk[pÑÐÝÄøÝÏæÐwYnÈ΂ j´LN O&•ó×\ëI_ëåòË%ÝÕ°¸åä9 º€ƒwÌŽárØ®…/`Ðð‚J«¨©Q¶ YÉh×d3£l·RøZá¦1^¬û½0Œâä¨ò•D}Þ~Ã)õfVH~ßÀûfܦ'~¬ öæ½:ÏÎNãœãuyŽM1Œx¥y&•ÓlýmŽç9D~:»ƒXçcW¾m¶žq÷B¨»Ã×Å7«)éo²V¡|Júaí*+‡ÁQI¬xú{SyŒÈm Qºl•Óh°g•F.óì°pZïÂãÓx>èAÆ-€ú}°]ÑÔœåx‹K>ÎÂâ,ׂÖîÙ«ÐÂFÍóÐñnæ&ë ,Œ %Z“ئ |­ UbüÍ}’¨áCcÕÀ¦ðäÇcÿ> ƒLN{À°ìº÷c`$h`ùöd5ˆ‹ô9ÄØ¡Ù<,Û;…ººáÜRß.Ü÷û5‰‰ÞmÃHWÛè÷©shÒî¹ÂɼoI^¸–çW£wåÙ3ñëds²vc¸Ô%ßt¦¶š½!ø ç¨pC8ù²Ø«úiEÄz1(óŒgË"ìDb®‘΄ÿÌêXêXÍߨÿ†²ý¤ý¤üSê? ²v?àT‹ Zòá˜WÊqIqÊn‹bu›š§oQt(ò2 Ý`°n:,bå…aV•ÞÔ¸t3A…%Kn0P§_#·£Éðâ·S䌟Ô2—rO˜oõzäá>¼rµ…7áp¦cæbŸ–'âfm Ô·PëÓ=¹„ÀÓÌvò,–7FÜå›À1ièÙqxº;¶…@wÃH®ËÝ _‡µ¡š6¸£¶[|…¡þdø¼ïÑÂcžLþ„è-JjѪ5Jœ•#TæCËöã§*Û$Žo~r¾„ì¼Y“öøòêQò£Ñù6(Lö™í7_'Óö$âûòܳYã]â(²œu;ƒþ~~%½uü[„ŧÇ9Y¥ÎúaµìUäY©‚ìKÙI¹òRyQÅ-¿ T™U!a9ÑXgÕ³š\J…®p6œV¡òŠ”Ç£æëìMÿ1ÞRi«*vŽÍ­Ì;Ì ¨uœ'‡Hò¾ÒP9ÎZšQïE„ÍKþI`C7­;Ì ±™n^9A C`%pÔ¦ï Q‡ÒX±ý“°0™¤OwõfØ>•ê ^eÖ½œ·€{`4l ?A©±;Î!Ð ˜oL~Qá†_‡Öÿº7¹¬Œs;Ÿ`¬\ÿƒnçÍØ®Þ;¹/µŠíBjÕ¤hCý7à#ÖÍÿ%ØüìÇ]Ä=#\ÎóÔ‘èÓ½2.8ó\sÇÆoÜþMÇsˆæÅ Þ£àvfåF™*YNž£` ,¡ãå겜ÉË•góÏ$ÑT³%³i|GÂgáxzÿ±:¤Æ]b‰ÝC{~ªs7_¿B˯Áó`xtvì€ÛÂ’‡óñ ì_‚ß‚Q`3B è Š†¦dGøiOý5@Mñt]34Z4ü{ay0îÀo… ÁçæànûBØB±T>çp%Ì «€óˆñZþ4Ì À ¾É85ù=“7IM ²_øm‰C݆ßÚjå_LžßŸýÒÀrâv=†—«9“¹.±vD$íÒ"ïyxƒïkG~²Ž‘`(ŽÑPC×è]kïP†b~LY;è«ã%íØ*—_*ù6™WÃF0o© äí'”)+•}4™ª‹}Þ/Ë’Lé Â÷áT8 ¸YñCñ|%5îKÜØ湌¿sN«ÃA–fà¾8h=™·óq¥>w@7—}*›Ÿ|Y cøÅMžV„ïÀºn°ÚØ®‡U ÛÉF‰†ÿøÖž‡> &øq+x æ„ /Žó¸–…ö Î zÇ­agî)_%jR÷¯—ÉѦ}–œ¯pü€—‹{—‚6¶Ðø¬±ºw!* r «± ë7=}—ò­ˆÏÏIë${q×Ú¸¡¢.hø®ªñp>+û<’YéOâlF&îyà6»õ•ÄîªgÐýpxÄð‰&ͧÁÖ*˜ÿf°9t„¼,N†õpâ\ºäË›Ž¥lT;N‚õ1ð5¦Up žvæ~ x¨Â‡d<º17îXܰ¸‰6j @'X¦…«ÅLþ¦ßö>Е֩ôHã¶Wt.¿FìnjÄö­`’É­d0aÞq‘•ˆš Ç[œô+ÐtN+ór²½ÿ”8ó *IÝ¿Oưþ?ú¼°ý ŒÐŸ×{¡©‡ýií«äg­ ¾Û?L¸é'  ¼›¼«Ð^*“âsó¸Ïöa¿½¡¨S7,#CÈïmË”[v.¬\¦<²cI<±U•‹Aõé!½ˆ\ ªr9ñíUçq̪¼V½”ÚŸ¡=S¸¢øÐÿZª^­y±ÔµÖOêÍÏïMøþ34r÷CBìôl8¼º$âu…û¡;˜.%±yßQ¨nvØ44OZ§¬áÞºëñY‚ihoß>×ɸ;À·à¤À60*‰c˜;å|—xi¸.ùՠЕJ­ÿÖ²m&+£_Þ”ù^Á:læˆc"t„I¶­íS%Eþ!ù›Âß­Gß›Pî—{G°–ý&çÈ>Ïx6m›@Gb^¹²c*”[¤ñ¿MÔ(;QÏá ö¡ O yy™ŒGáðì9B†y ƒY"3ÎAüa8¦ç1¼u^š)ntt\@ËmpjÚÍÛ MçÅü^0|ÿ«ß¸©ˆ{zŒ¾>ŸhYqUu_¦5–&´Ïà_ð&xkÈ*ɚž5^Û{‚o ¬j"ºÚÙ¡šñko01º§߸Vòþós½)E­‰-l½íbÌ¿#†ô k;Clåzd ËQ»îŠeO2ª|X_Ú  _ÿyñèãgû¢<©BüÊî¦ÎCìÍö¾C¦åI+™bŒ‘¦¨œ|F†UMzRátØ£ZÅLyLOÃ[Ã% J…ìLÄ7Ê`sІò¢ÊéLŽƒó…¤m¿œ ½ …moOÀV7Zzx0?NºK${¢ß ]¡ ¾¼bƒÅÁ;_)×HvÍb_ľ±«×Xtö%®F(ÑÄŒ+Ý߬39ø ãÍÁq̘¼opŽe"—Þ“N\®.Ùºdþ1ŸÓ]KÅõ×&+[-kíi·ë»ß”™Æöå†i|UƱŽ`÷Ÿø>8òc,aì1ŽHÛmäω[´Z.¯TÒ.¾/UPc^kêiü:ƒ[à$ØÎþ°:”2~²»Á¨“7å óÓY–¼ûA•ÃöV /qIk*×á;u£Å{0;ÄÞE'꼇»¡¶•\Õ³•Ìì w§Àøˆ£Ÿ tÈÓb\űhü¡ü:— 9”ëúêà?³W?p{;ªâ?yBʼnJÚìjÆ´IÃ’Ê)ßþ^ª\e¬Ò‡È9 ¤%ûþzõi^µ nR-ÿªà\ü~Zù–+þÌlÊ$c>²Ïª¥ùF¾Ü⌓_”Ë6ðP?v†èÔ½)+zïUàhQ¶VéN„ô ¶†å^/—…GÁAúŒq‘‘4ê*Zˆ_^^ŸÀÖ}¯…*.Ä=ž›p¡Eïª,Èu¨+ì²öäü\EÊ“ÕlêÉ:Å:nl­Pßnãc:â(*¿ÿìGÈ®FÄ£®Ï4Ž—8oÑšè>ƒJ:Ö$,æŒõù29½À.#^,=£j•©èuÿ°\xPeÞÏ•UKîH…cs•N!í+ÅÑ€ùh=¡D'.mͲ¿ˆëbz0zðéU}²{ ×.Ã;­M6¢Ú И‘4O»Ž»R<Éöôî ºÛИ~©žÈp>Û¥qûTÙôn[ÁÂàU4žu&_ýýÞ¨6ŽÆ¯¼ú{aéSNtßq.J6$®í#ÃÈ,¯oD¼”D9¡¿á÷ ²XÔËöo^¤#{e¾ñlh¿*¸'sæmÅM?˜-%w’©éJ£ÁU2ŒÂ–p, yqxN¥\Ÿ/,‘V}ŸIó]†åá‰4m ú–†=˜ý|Õ²i³’K^²0—9 âBÏ‘é†~ z;÷Dy¼ÄíÌ|'^U\½ÙásˆÎª6ªRáÊ×p7¨Éµˆõ­û!èW{¸ú»ƒ“q¬+À%ÉŸ@Dî$n9e¡ÿrÜ–êßýµš%ÍëË- ùBвüþ¸^õ[/ ý@zо¾_¢õqë¥âwISd51Œ?ÚÚŸ7ŸÏ#~)õ.$¼Í¼2¢¡¨§ª”iYÌ^‘`P…wPv ¨P'{ß“zý!«Jù¦=ÈðbúñH¤a,}×qS™#W\s2ú©¥Aó.ôSSÛÈŠ¼V‚̾f«”»3‹Ã;ð%ŒëNÑ´8°*\*O%Ñsqª$·\jbü¶…•á+ÈŠ÷ÐÃø ‡/Æï1²]þEñÙvœ2yùúã:ïZÅÆE\ÍHóúã,ŽÒ£Ìæ÷ÉtôAÛ=¹®ïí"´½bšº»su<ƒÀt´‰¬dïÜ¿Àg9BýòB„»–’“ÈÜìz\efOàèÇgzÖ¨+‰£êr‘³#Q&tŠYYÄC™ –,—i‰òÿêxZ«|à6×$\;º,LMoðYq0¾Œƒ¬Ê‚²$w´' ½ßL(q*Íp¼ y)ù‘LµäX.‡`&p|Y1­Âþ7ùÿEdK&úxŸ) Ç.ÓŒ- ‹0Œx~ôQF¸šòžëu3eI^äSåHÖç4×9ò²u}F6Æ0T KìeÖ ˜4( Ý3$ä"]#Q&´¾§±dÛf«/DâÁL†õT)Ÿé»}5ñ z4Wé Ò;æò²I— +HÜšÉp™” !ý¢r±$£‘øöêÂ`êp¸ >FUßc²âž‡‚‹èžŒ“hT½à&pVß„¶6è†oƒå`zpðY1O/v3¬¶+%^'¿ïôL©â‰8o¶í›¶òŸàªsî©%ãU£²i3M§šÖ %8˜[Ò1Yã´NNúSgïRN6úÏ®yÚw½á›Îö¯±;C°>nZÉ÷B²./gnŸ×s‚sðÇ^òÎ]‚_§‡Ì·„O©kžj ã^êFTCݣ͊o“Õðwù¯¦Èb/‡µŠÃÌ‹yÞãùBÒšC^¬ïóµAoÝ!݈Ü]üúÁã«Ôã¢êXaM€µ³)_F¾Es=ª{¡ø$×rjÐ+º±¿–5j$ÔO~1¨/á-ÐJ­Ùã$žØmSž&Ôˆ½Ò¨JLÆIêÞ#ß²¬8Ép|‡œ­1ÑÆWkV¸`=7+o@ÎÝ<ç&J~óHÃUo/Öñ %ª+?Od¿)güVQ9² ãy¡4aüæ‡Á:¶cÄ£œ¢¬lKÂ-ÔÂõ …!K³ZÊšÒŸ}†ñ‡g!Tˆ'?nTèlòøƒ%Žü7IÎky#Ä%/õ}õ|ä«–ƒ¡T“9©ðaZi6ÂO`VXVã-è®â½•TíK_µ…ž‚ýOìþøàZ¾ ‹‚¶êÆþMÒ†5‹ÛѲðLR ,­ÀÛÀnУcAà¨Ï#Ú@¼|Ã2¼0Öÿÿ¡Aµ‰0Ñ~ï©p«ÎßuÖØÜ}‰´aˆñ(Kã6õWt‡QÌ“oñ±¤õ•4¿¾ÿìs¢Ü¼ëŸÜHl§„ÑG¨R>,žoÝT"K9 ëX¼74s¿‚øe{2uøî³—…dÉ–ùLÇ47CNôþ^ÿúî^üƒJJ ÅìâTµ—Râô0ø¨ZD[{7W±iŒßÕj´8¶Zd=¿#Ä@½º°Æ‰ •ºÂ”Ù'ZTÜûo4®ŒJ2¡ÅIhì«ÂPÐà`{ð~·1Ü\ÿê'L4®-^ý¿*fLŸ;5+üwå)˜eœœ®s¡klÚPÌ7­¦h¤«LÉŸìº~ц²×á 6|eÊêÛG¶ 1^ê™d‡^50~Çšw*–• Cè÷Vâ³oÉ?Û0„wó-(>¾ Ó>êfCãù4Y‰D™Ïù ^„ý©>œÛÄó‡q¾’ïE–«ÿ¦ ²d—!_“îÆú‡C|t)éE&‘ädzïf*ìZ|±.“USÔí¨EfmG­6iM×G{™ÜŸ‘`^ Úx½4HÔçVŽ8*À<ðTZ=ŠÇKV¤õFàmàð”øôjÃË ²+NPÇtiÅŸ Ysb“e7›œ¿ù••tâÆ)®­ëí¼ÃøÃH %·þr3ÛMÃ"ÿWx„¾6×øKIôaßÑ<ÓtÚ÷oêIàø²ñ³yQFTy f×yŒíêGâTšnNèw9Üê¿K²­ýæÓÙ²ˆ{Õø»Á×m¾'ÎâñÃøg"Îã >ÿWsJJJ4-YHæ:p_¦pvâªa)éK¦Ëpo¦°c1îŠ6JÜžZdÆáÔš;SÓ Ýëeò²QõK™Å…«õ)ٌϳÀë0®}д¢8P•w%ð%ër˜ Ìï íáðEÎ Å¿ÓH"“ÂÇžSN[Þª5ÎK"n¨hˆ®±„¡–ˆ»÷ër %â{ÿv¾ªÙ>úˆv†‘—í;ò-³3Æ“ü–`Œ-Zî³!íÞ$k¥n¼-ÞÊ¿ÁÂiŸ¼d?BxÄݬñá`[Å0â‘6T²eŽÏvw‚ÖæxB²íuèÌç2Ž9|ÍpN%Ä.+I' }+}0­ÛRªMO2…lŸžKH©Ëx±¤Ì§ÛRUâ¯ä Ö—™š¾ÿ¿ mÓ<×ÅuòVÐÜ““àÝ”®mÌG§+ta}X¥U¡¸fqð-á p“/‡çÁ¼þp=ø,'å³7_ÏGÉ//™4dzèêøžÈù¸Aæã‘vŽ&Þt’°NПø·ú»üH– Oþ˜¨kXª}6Ÿ*ÉÚÆ3³¡ñÀ±Æ>òW‹‰ôD!çgÅð…Óà§cJĺËÁã`< Z2žö<ïYê|ÿ‚8†+µÿ–[ðêü†ø|™7m讘ªþé2.:¶ZdV*Ù&¤‘ÖÅ7ƒÈª)tk«Ê l‰ë“2t=(í@Çðx[v¿~†3@{?ÖQnÀpsQ¢ä¯èT¯ú6B©̈d½ÌNìøÚÔçV8PßU›”lªŠâ‰åóT7Yï¦ÄuXNÒÆ¶Nž N¾Z¾0é…Ä$ “†l4¦°â”ÎËuw½çdžËc/ü™¼ËuëÒœø/ÔsË\¦ \Û!ÍÉØgúoÖg6Ò‡°—SØWôk%Å<Å|÷Z”HFܲHG˜æqØÖÙ–îö'òÕÜulP‰vŸÿf„ÏA‰²|<)äã5ð€è*¹’oSÌ-æG¹Ï¡Ýƒ8¥ºÿðJpuqMbêú¿Zd%*ݱUåÚ,KÁÐ\!ÃüEu×þj•_ÙúÜ)æ¸Ó{‚:Î>±ÙK¿‡é -, KÀ(Ð)ØñEà¿,s'ª^Út34À@¥4ßôÌÐ ìÈ Jv„ºGëÌ WÂZÛÙ—Jú¸)‚ÏÑ[µ€•ákP£³}“¬µÿ-X¼>§8Ñ‹Iß“ü+ÿ7fJ&®h³š†Už¯ðÞL‹Z|æF¥Æí|ë€ø{=ΚMFüuöfrÂi©Û‚Púi ñdO Chw4wè´ÑÖ/O'ý-k= °­¯LîecPäÛWZ¾Z›ü[¦EÉ´]ka¾¦H^¥e¯€È|à~Úo@4‰{x ÛCŒ?ê*†Íà Ðz4þ˜sÔ%+©a¶m6n9m§}Šoë+¾ÁÆcw¢ÿPQìJt&œ Ú—b~ôsqÕ|—§n½WÑvlnN¢5‹¶ZQ®ÇŒÚRÃuw>ø,pÌ/yšÐÃ}œ†ɾè,:ÚÈ•IEÔ‹(+‚iÞE7_ðžIg¶SƒEÁÙ>ŸAŒÜ™+*ƒ§q°½À:Ë‚ÏqŠm•XÍbªá§ÎbØÖ±9FÖÞpOòvHd"•1|Ù·_iYh1À5P0ÿn‡ßŒ°…‘pð|Lös³H'á/iÚõËj`šäÑw¼¿ïáz³V_‘wNÖú, Ô(öP§>NÞwæ[/Sî•ÿi²v\‡ÓîX"߀b½×ÁqÍ îm´3T"­îéøg›ÈÏÖÓY]öÕrc#§Ø.ÂlÛ¤pìòï–á`<§…‘ôNë„?&¥B—~APUm‡ ¸´NãØœúÚ°„<`¿… Óø ×DPúÃ>ðx ;ØÐ™X_÷Ê5_’+ÚüF2b+‡a¶$.íÒ|ã–¿ Ó8A’ç`4ø/Á‡h¤ ÖiÜl´A'ýh/³3ösb“ #^œSñ¶¤VE¾¡e†®·byFZXFùܺܺã§âƒ¶»r›Ò삃™Ë:´I†ñŒ¡Gß'Ð×þñ<ê½D•e¯æÃ= ŸDló¸G‹@¦REq\!Žo1°³6-3Ϋnbe•ú³~´Ï‡5(ã¹?-ÁMÿ=ýŠùîÔª‰S»Ta/ ;ÃYPJf$ó Ø=-ÄV›=—ÄjøHÛ”¯Ù—߈ÎÔðæuÛSM[sîÚ^ÖÎ\7'ëò&ñyÀõOÙ‚ZVÀúÖãI¤ŸmÓ¸šäˆ_‡O`5xÚƒ›mˆŽ·ÌJNâs=àúD Ÿ"61‰«Õ-8§õ¯d]Xô“YOà}³#ubƒÂØÝ {Ø#ãJäGÜMŽ8e{`Ô;b˜çy‚f%ê‘w–ûEݹM\Gÿ&ýW‡[·ûä™>’ÿcpªHÌŽC¸œ|µ\c·ŽG¢Á¼ÀW¼´-±òqoŽ7ÁœàC£Í į„®àzD¾¡aÄ# ËÅ£ aîå÷mxrØÌ¡|NÓmðtïGÂí ¥YYùžo !‹îÐtç å$©Û˜^ x<:U'’ÇÉÜÖûV¼“olw#bÁ¸H¢)4tÆoCsØn†UA#½f†µ@Í!:Nâ3{Áõ°Œ†‰ÿ#2QIO~&t' ÞÌõ©››¥Ù¼PØ"âÖ„çÊÔ@44Åy†òÇ:æã®§õ²B©Í×ó’]âëYnŸÄ/DüßíJznëÖA:bïžJD}Ë}¶ÆÚ¦†0~¢‰dûÈÇ=µFú¡ÅY>=.‹b~HÄ£¯X#Óé<’ªÇÖçG[Çèøq4Ý×æÇ¥·$-’ó9pYK®ôv“•/Iœ .Þ/'+éZŸ¨]jÉÏ蹕E{®(ØîL}©áÆí‡^¯7±&d%Ò‚O_ œD¢3ÉGR4~ÒÜAÌ^?|H3p%7ó®«;lÓ‚'H©$»¢ØÏ ð,±±DÿVñêûfÐ;³ÿ Ò³»9ý |{¯£LE¿x ì*ÉXâœTR×'Èohä[O‰µ$ô==ù°XRüŒuʆ¶IÓÛ¥]ø…—“·éeÀñ-€²½w•'Dïu, hÒg<'Ÿ6?Ê<(îõÂ>´®#ÀÃÃ::ÄÒÐ}Ô/Ë4dï}¬o"ÑgšLêØg^Â?¬-_†Óþwòìþ‚|Ýi‡ä£b¹óU,sÍÜîÌÞîOòR¨IbJe+³>;Ä@â®ËŒ0´Å:±ÇÈwíQûìð7€r³ ¼ªØùÇàÉnÇ1 ¡¢èÁÃÈ}—3ÿEx¾ëoNÀÕoŒØ—«ôhdƒ¼Ää.à 3˜³À5ñ(Àîî)™“ƒI{ X4´’[áÚˆ Åü‰Ö—M®òYƒ´<ÛOÄÝ…t|ФÝ> §Ã^½)>‘ˆ{íˆ&?ã_а…‰T,ÌŠx´‹tZ=¹þ?HBý8öù^ø-ɹß.–¬¨Ä»§^¾ÿHK™ë}®í6F‹ÿ/¿Fr¿Ê;œx âã³S.Õ¤'™g‚ÃKÅYÔ,ÕÀâÎÉ9„Œ&Ò \»Rëá>ß ;€¶&+Œdî6ˆ%Ú(Q!ôÔ‹@(’¬ —Àº&Rñ¶aý¶Ð|®îñ*ÐIè•¶f™ýeû$Ù@ì¯%èînPòw$–ãoA/㟠™/ù²Ëœ –à—ÁÒ,3ªÉ[¨(¡ÔjJ„‘OÖdÆË­_ägêÛMˆÝY4\cæeð!dë?Iº xe–gëD:òܳ«{n¾ci@wÐѨ [BX™:}…S‹>¿HËêëD<Æsm:æÆ øŠ/bÙ£-·/~9Um^J삪‰¯r¸å$üWZ«^®zƒü²`ªÍ’-@kb¨mÍÙ§˜¯N –…sp’Ý ¹ByýjŒØ‘§þ»àõ/6…h":…YÒx©Àét\!=?F’(Òe„*‰  bÍ ³BGpÓ~%vȰ-lˆ˜•ÛÛ ‰37¦NôO•Åø±ËptK%s¹–gy#òÔŸœGüù¯V÷ái8ö¨Po¬¢˜e„cU £RY©úi”Î׳Í÷yÜ¥98OpNˆÕö9ñ,õC¸ù$ÎüFBNÛä§[R¦²Zßúè|3˜ ìÛµ´%Û<'Ÿ—Í/Õ&ÊËåðoø|²ôn<Æc»FÑ–*ɨLáÒüI챫Zœ);ZÖ`üþ.ÌË;j!æ‰-8(çé~i—1g;Œ´yâ:''¸›l^5ñ2£Rw…ì ¢}õk`mÈ;²êÅÅwIÄ6Ô÷6Cï®x<*¡ KWCTšõpÊ-ùzð’ä[‡Çê3êLˆP¥ü éh‰Â&¼çïÎW_¿²”/‘ç˜«Ž­=¸Fð7ú5ü½%rǧµ 8­£áP_Y>`“rcEÿ=;§ãoþÆà~ª0-áØTeõ&”‰h²w:îÛáupßUÈõA§¾è÷×[À 8^†á;ð¹>GÙ \[Û+>OÉ>7ò"?ÂÈÐ|ç€SNþW¿@ŠåÎ}ÞŒkòo›Y]N¤Êù )%«‘ùžM]—N1þ®Q‰¶‘Z¶1 »ý\RoyQ¼ób¹“Z•—^õ9ЧI©Á¢ìdŽ+>¸vƒ´g5ŒJÞ"À`½<ç‚:2²™~OÒqt¨ÚVŠQg†¾;i]ÎO“Lœh¨%#PCŠk]¼9>PW]^ƒv|'ºÿ©Ð¾ÐXø;>´\—ý—ÒöÔ$΃TZñ iýÌ÷ÝøX'¾^€ï~—}qÿîÁhë¼îMç]@ €ý€vûah¾ ÔWiwPã?€Fä\GÁtø¼©6ÊZtäKËŽÙÝøí˜ò‚¤!î_4`ûþœ Î¥á>ÛBèH…zò«ÁëàÕpÝ'óâƒó÷áqve+ /@§*kNûö[zö|z=õª5e(¸€§a]¸4²¿ÁW ¾Õ£:VgæE‰|ú¼å¯‚º4xÄ<Ñ–¢š~‘7UlãÎo¾,ÿ„¡38~©±ìw' ž¥mB"ŸïGŸ+»¿¦—Ê<Ü['…iX–rã\+Ø Q£®ÜM^uŠ>\Vž Æ€± èQlí^ttXÔ³ÛExV¡wSÛê3ÛjÀå¤)á¨ÖùÓéfW<à± ‘¾jv?p££¢C«}7›ŠÎ*C`8< -¡YÂxòè)p DT¤F§²ºÀ}°ho‚ýMWƒÍa—ù½ÖÓ£]…â4[K¿¢Â>ÑÌ>y5D]>½“3Þ[½„uäÆÀ» NÞõr,Lƒp~²5N§1)¦A{ñü&ÌÊÎ#=â|£v-[XÊ'[#\0º)ê#ŽÝÞ¨Gg¬%k€w€Û<ô¥àGHÅ·ƒØ\Z^*ïÞ bþ+èûBÈ{cï Ô'𠸞m`1˜¯¢®‡ùâM¥6 td¬^pH•cªŠºäYìgPÕXD}{S\ߟa'ˆ`˜ê7ÍÓdÝ[¯%ß Ž±„qÆâ"ÝžºG!t—Ž][Þõz Á à¹Ù~\ Ú®ûˆyòcQ•IZoA®÷øL8M¡Õ,?­všóf©)‡4j¥®°AºÞØS”©C{Ìôé\ˆõÖE;²Y~EÒíoä‡Î¢Bï„Þ gG ƒ£a‰ q¶Cá!ð¶÷ dÈo€¢O®5ئQ‘á`4í îµT•ø L†—á°&hÐÇ'5ÚŸWƃÈÖa3´¨^|Ùè§UßµÖGúµ* ¯†+ œÞ êG=d3IŸ#oªÄ³q¬Z´Š‰:²³äÓút,Û*ù¾…ÒÂyµâá8xžç=<Ë8ÏRýcšeãGêZW§õI›¥²Húäw&Mò\i¶®P3Ž~ªm´•Øërä'‚õ–åÏ1ôbªýî¥ó=îvØb`²õdw¸r ­Óò¥aŒ|õÞ¶oûJÖñíZ@%Ò„F™Àh©‘–›ÃÀø\]ÁýøÆ ‘0Ø×‚(òV²sJœJ9þ .»œ*©ÊDÖ&«÷âÍyZUtöNð €î0|mw¢˜,òu=;žAd=ðH›ÇYÆœAÙüó¥mJÍi½Æ«­z>^V×›¶| ¸nƒG`X”tíñœ/³œ³ý§v›ˆ¾VJ\öϹŠR¬V4Ï:%&°¡{6jX&êåsÉò8‡|y7Ú®ø8ÿ†ÚïÉÜ Þ CC‰‹ÓÁÔ”7©¢6Õš eîìÙù-ÍEJQò-‚d¥:¸qáÆÎÞܸkP©D»¡úz¯Ãë}FÒ—À Ê@X–¿{¹#{š+?Na–‡Á¿B-3æ 2m:„‡5uõW8°xFGƒ{vB]ÙLÊ=kñÁßà (׎ªšsý«w%=÷èoªgèäÚHX ÈQ¤ž‘uÎù1hÃÚc5 Ë‹Aã{Pb®H ¥™MŒE—ZV435ÞæÁ& D?§Ñì«·Y«8¨‘{r"Q‡<[dÏ4ôm£½z´Î3ëþn£FýV$ãÍïÀò„¢È–”ÐN¾ÒIBÌïFãmá3Б´Ò¥à8˜ ±²UÉ"ÅÖ_×ÒKcñõÐýt÷—÷5ïiݬÎð&¸fuá^{Ámð2°î~*Ğ暨ʛaiؾ̬©úÓ&ò°ëaüðvSWÁÕðg8t$;ëH§Âµ°?Ä€¦‘'›å£LÝýŽ…¼óGª2‰1¢¼-¥cÀ7%ÊÍ{ƒß S@ƒV\ÛTÐȧCŒÆnêùZ~hä^6ÏÀ§à|ëCô#›—ƛѕõÜæøH9óÚŽº°$l ŠÃz_h6ažd+’Z@k†pP'0P7÷ª3[&.ÔÔ  ‘¨£´Þ:íßßcáóøáÌ£¡1(¦6.'FÜ?‚Î’ÊÛ<¼–wœÁŶ€­ÀÃt R篯hxnÚÆÚc,Ÿ=À!°+¸qۥ⾛ ¢l§!Þ ž®cĸîãy¸”Žã _ð4×å`fTaϳk¥äÈÞ”žãáØþ €éž·Á`3íAD½iŠÆv-߃’oe¥Ê½µœO½[¿ô…/áG0`mÖi3“Šy’™æñY‰9 O…5¶=r †ÏÀ(ê¼Î“ˆÿ'&·w# ä¿1ÞyI]šmÆÃûÐÂLÈf¦®‰‡ÊÛå¥ÖÐÖ®S¨}É ô÷xáiQnêþÇ‚¾.öë {Á}0ƒ®e…õ8ˆ”ww%èT©¬Ëƒã¤¢“Þ FóÀ쾎ý©æx¬XÜðÀ@ÄÍ$®½?¬ =@à çWËæ½ž÷rdñÙò> r4JÅö*ïÀ»á07{#ÍCiÇÜnù!Ø<ãóɸk£€tÝ.¼hIæ.P7[Ã{° è1@‘éJp3tu¥D}äMÁŸÀ@ ØFÉ·çH]‡óê”öOƒöph7–ÛÞs1M%žc<‰Žaÿÿ% £EÚ÷âмƒ  sµ×d_ÇØ‡·¼¿Æ4JJŠfb p+NS{Ÿhv¡²uЦV§ìD‹`­bËØìóÊWýìix \¤¾`Ÿ]Á¨ä¿-rîÇèä#tR7¯cJm²o‰Jû†ãXí¡è¤¿QE»PÏÉ ûƒ [‘Õì¶¿·‡FîØÛSðT¬{ÿ€]@Ã÷ðßÏE½¥ð˜‰“ FÏZÆ™÷6Ò{gud³|´WÏæ¿€Á€«Ø'lìò¶»´CÇJÇŒõQœÕÅ\‘Z®-¤×m¾mÒ2ƒšJ´ß{0¾ƒ ¸¶;7âûÌ—y®EΠÎ.OÁÏS¨º»‹Ï$IÀ3i “¡=Äd¦ŠõîÁp¬ »vüxîÚvD+}Hµ…N÷ð†{"V"NV›¸¨~p(xøŠF£l ö×0´àaQؾ˥6q3Îa;ÇÒpnOC#sN7>Þ÷µ%¨8ûþlc_S#¦ë2`(ö½ <ÕÃÉq¬ßˆ¸lÏù8®€R²ßÍ”ºþSAãX΂¿€2oDñLUfêLíNj½cü zƒÎ¢hTêU^‡gA‰>‹“7yŽá™Ûv \Óà2Ð@{@xCºž|žf5ë7Ri;Û«“6°2¸×â™÷â;ê®Äˆ—É×"ËP7¾XowQŒ+ŠK©Tb˵¶¿p`שߨ»‘E¬ß<Ûs1К†^Lã\Ìkó}yUXã2튕$³%Sé½L'O%6aÙþ qhŒý@ (6Ç1ܨ†á¢SµÞÜäóÐk¼’ùa]è ŸCôw<ó À3ài­®Ë2 ~"¬]àþj翚¬¶YJÒ%Ì Ñù‚ AUÆ9¯¹#Ûd/¿œE¡û× ¸§ƒA/’Í$žMC–&£Ž6u:ž†³à}POê| xÎâ™ʧ ®cLÏDQaŠçýØf7Xúƒö³l ®5#ÆŠ”ê±,ÊóiM£Ï^ö‚pÃL*,ãuMy(¸ä—µ:œ±%²Y|{ŽóÔ²+§Nù’KÁð/pêl-Ø€3áAè¡7u‘â^}N¥Ç•üñÝí”QfGšÑyèFŸÚÄÎ(6ØÔ×’¦ öÌ÷ÊÙ/ûÀ0à€²÷,d0x3-Û‚c8®}ÀÈÖˆcß8I<½AÅmã`#ÀODÑÚÿ–ðäõFQæ[§‘ªÿ¼ØÞé|é(%žç¥*ª(»†¶7B+h úùÝùÑ t~÷÷añY#Rb#¦‘÷6P´Æ ¡¸ù3A=?‹Ãyàõ·<¬ ¤gmÐVôÇ ´,æ0õ¬.‡£/ÉĶži7hoÁõà: ®-ƒÇìÙ²¨3À¸×Rí(®UÜ«ÊûmŒiF.mY8ò²&÷Ã`7§ ÚÂ#|°±o%RkÐŽÝ“ÑGþ‡ƒZ'\èD°}Já¢,WLç¤ÓÆ[Ÿ1Ò>¶·ÁpЈoíÃ`Ü ÞÔË 6qó*ç.8tÇýþSÁº-›ìŽS ¯õïóè2‚Wá)è %‹1ÐÕ³1Ø ôÕÿoĆí@æ`ð <\MðY8Œôôòà-ýOïóõç=hòãL£Rªû•’³²ÿ>Ú+ø µ3å±;n¹&&eðHÍÜy•4¼çið õË£.MÍëØ­ax&Âæ°,¸%íS()]uÚÄ@7 ^ÚÕIàø:HöesãB)9’Â;ASÔá]Šíb>X*•&µ5üŒJmWY \“Å„>»æ 7|îo5ˆv¦.,ú)@ØŒæº>|§píªub•:~N2;â†ÔèUÅAº’®#@cÐDõƒÁë0vû¹ÉR¢ þWBsè¾µhˆÁž€óßM@Ø+Œ€¢ ɼ'Á¥Q8ÓM™_”³µ¸3!œßáÐÙ,kêàT~‹ø*¿q›ý"ÏPX­\KP¹Ž/>þ—}0Žî] „%‡ ˜F^ö…ÔùyÌ$Ú¤í£ÌvÏêyagaÔž¡õß‚} O…ç%xÐIôε`#ÐŽ &“ o;¼îÝvc!vR;“8¼±s©ñG_¬{Ž‚JEÓ­M^6nËÀÈb˘,R÷Þ:Ã`ˆrDÙ Êô÷u^ Oàû¯~dêZMjÄz-ô«8ŸÆ£‘Ü WŽ˜ýygKRÇȶ"„¸™õà@Ð0†‡éa¿ïƒâuy0t×=?ôƒý€ñ.:¹´óS›ÉüÔùÏÊž~;?´ÿ÷æ‡û3x“üú á«ßMx™îLØÈ'‡±Y¸Öµê+¿Ì§îփ易Õ/ ž‹눼Ah9Ðk¢.ÒhÏùÔót“î§' …w ìôHòÿûE_ua?ãèz¥ÁcuÐN|s´M)¡îM×[Bì¢Zõ™˜ÒTŸ20Œ…j$¶Q®Ïkú€zSN¤í¦§ù©Ôź-÷<"%[#Qžö50œþ4?ÌØ .QÃÁ`ŸjÄñÀ“`0ÜÏÁ±°7L‚b]ðÀòâo®Fv' û€÷À6ÞûÃWàÜKÂ]Ð &ðëÓøã¸:ö¶r].ñ0Ï…EÐìÍJÜ—Œ†Ö{3ÒƒøËø-x•ݽ/PÒ òóýü’Qk×ÇúäÆÌtí”0.ñyØÀ¢X§D›ÂSá9Ê#MÛzÆ[ÀRpxf?A8…·à‡ð$<^œmö†çëtŒE¶V¡Ý+•nñ Åú˜L„t n½.‡¦ÉLâÝW«t¥Ö}ê/3÷Çžœ\#݆Bp1±(S%ÚGÿ´~K&¸å8ìæ .–5/ýÃΣa5pQ•Š jWƒ·H{Ð=¸ÁCJ58‚çÍÁƒ/'¶×áÛÁ:0®ƒ‚ÑS »^hú9 oïœVXO‰~…в_SQ9ÓÈ­ÜÃOqÿ‹zúÌÏ-ÿtönó_ž\štmÔüç¦üŸùo2¯Ëð^‰;Â#`ר\ x­ Ä2%ê+ÉkØŠ©ç½4ìÏ©ý<SaSè €Ž2¢?ÙŠ„õtÍ/ÍÜÚ%?¾H´„¿B{°üCЇ@5Rgˆµ› çÂ೸OàI«÷0 ¼©Žy¬yŽrSLjgÇè«]?>”ŒNYJ4¶÷a»R•I™{SL‡`üz¯Ž.Xñ \Hˆý>µì«e]bûE`øz§xFNëSçÑ (¤#Îþõ”T,Æ.ÿ Ø6ƒ¹-ªëàcù1ÆÀ«ð ŸÐÇ{Ôÿ²oH(˜3òßëy³èH€Q—õêE°Ü=AcÒ_‡ýÀúô,Ì‹mˆÝÔ8°o´UÙi”‘­ÉAþnøì xÇq ÓúóŒ]¥pg¸<Å©N“ÒÔë,—7a=¨Vê ‹=ňG5ÀéO.@}*DÅ N1 z¶q±Ö»@}-òd³g7å‘:îƒyƒ`w§¯¦â®ÀnP*@8™“$n.¶Ñ‘۞⢌ʵ‰sŒƒm 6V®½ w¼—akh ׃†á†×äGW8Äü6ñ2.Ç ‰Õõ•sè¨ßÉP_{£kUâvúÂ÷ù¡Nß'æOå·Ä¯ðÕßÿJž TÎþ´Ûè§±…¨ã½á8</ J'o Šå£À³³|7àsH½Â Û/lÍͧ¨tçm7A{0(9æìói†!NéT_‚>KùŠ·gœBÒ®…’2?Ó­–jrÁÔÂo½kœX°“«¯X€ùãÈ\øo¶hëô…hkª”KÕݳDžNìhâ^<MCü\½6x0jD1uËjæVðP=ôCÀ¾±Ð¯É‡S’-)Žu?‹ÚÄùpäì•pRçz Ö‚tžxF‘þáÊnûñ[DƒCɆŒ3®€h̺†y—‡ÞÆÐw–ýS¬êê×`õóqâ~£°ä/ѳ¸&Ã' ¾õ ÏG£Û¶%l'Œ3Úijmüh¨¤eæ•%@ƒ]ÚÀX¸¶…%!u +•Æ[ðïÅ^Žó1O:­þçuö(w N»Ì·sLjð÷}¸?üºl0ðL”0DT|V¢¼ð4sy¾,ž#Õ ½@Û˜]Á·ƒ*Åÿ×e?MÆr\â½°{2Žu–Ç–4¹j¥œ‰×Œó4¹E %Lü1»Ìœ4@v¦…êw;ƒ}]`º‰x6|ÔçSýø•~øú-dœxèøO‚7Ðã`@Ø ÔÌ®ð-ä ‚¢ŠÄM} ˜RšqKë™ûÄ xbnJCp]¬·ñò|7H rÎoÐpŒ§÷Œ\Ή W+¥Ì|¦1¼dçKJœÄ«};¹ÏA<›¶‚À¾Ö[¦˜WÒ4íc™jئSqô&:¸Žý9x늯YNäb áˆd«ß©4¦íËôtì·àJèëÀŠÁÇÕ R,~_nýœÜÆÝ—·ðõ çðÿ‚ÔøJ>åΗ…À9¸£ †Öp @8uÚm# Öí^Ù—³“> *Ìs ƒ#;K>Ê"µm¥¢g|5Óv/%u¦BIéŸÓù»)HøN¾0| é2Ì«·ÿGøg•^PWhüÿ@‰Wˆu¡Ž‹0 F%eù4úÓd¦6Qnª?ð=ñÃîÀшìl‹Ä u#^*ÖqÙßâ®Hzx°¥d …퀛ÆæùásùSï|(Õ¯Ë ç€~¡ÎJxñ8_¯1æ´ÌâjàÙÇÀ¿5x~^é†ã {ñ,qª,h°þ¹ðÆ·©ý¢o©4ÊhVµ¸®c`0ÜFjí·6Á~2;'qê`gP|ö®qëÍàD¸|KÇW® ±wERWp®EŒ:©8‘oÀê3ü0Ÿ(ëAý;P´1ŸRªÜ2ýî,8~ëà`7œÌí*Ñ»¡d"-K&º@ ãYspa¥Ärßú¹o¢ì`;Ç™rsŽ—hn:Æuɨ²á†1h«ì—`4„Îuƒí` ÄÍkÙàyîÞnœYÍëfôMÓÈÓ¬Þ¢u ù:È_4Õ&š–/2.ES³»~µ >Ë‘¸s Ouü¬+¬~qpEÝ)NnÇ&êÆÄM¿©_ù\)1Îô9  ñѾ‘e¯ê[ÊFSK¶^â&^„uÁ ºÈ…ÁÂ@st€rb{Åøué|By›ÿÂ+F¹^s¥\ÛŸw7ÀlCØÒÇ…I 0Úl±|ãι+@#éžç(cõmM‰[žlvÆÖÛdzõŒ5¶‡Àó ¯0/ %ÎiðéÀPÁ.ÇËp1߈”¢ÌǾ$-.u¨e•Jlµl{œøÂÔ.“ ôº-yuæ¤.F”ØO<D™¶¶vQ©·}ƒI__y|ëðcA¿1|x¿ú d¹ iµâ@·Â~à¤jξ`Üt;P³¥Ä ¶€)¼QžÁ*}fámÅáÞâTÍa¹/™²=“nŸÉ?¡ïé…søMH›ßu¨1Å_䙬:üxÐX?ƒ©0”8ˆ4ÕȺÁÞ0 -Œ˜lƒŠÆÑZÃ0Jççrí8Ýç$MÀ%~.;å žõEM™hÊ{…¤²Ÿu†YÄÉ—ƒ—ëRô•Ô7\.Ð2ûy&ùòôÙ¼mç6è Õ¬3X·‚ à³oòzñÌüeï¸}Ï¡@EV²#šeƒã o5ˆ8î’Ð 4–×@'I¥sa'Sv^±ÜåjS¾¤zçÙmep8¥’íMcàÏÔM*úŒ‹P¿¡ÃÐgšZßÔ8CÔÇs¤#isœú_”GûŽ”¥ãHýˆ±-<À+Õ£§ð/vÝÈÛža‘Èߨ°¨8@*>Ï߀Ñé.pC=¡%mÛy(Mð»è ¨ü©ÿﱯ+ Õ–*EEº…êì"1"ÛÝaÒ½ð8OäŸÌz L×T‰¨bìÅ•´[mðñE~ÖòˉaÔÓøÖÏÙ|ú鸔â ìo 0Õ6<<Ëœ’uxmtó‡ »|%ìH“ÔæFƒqÄå5+üçU­Ô·‹ºä¿\tÑCK‡Þœ…òì Ú@ ®,©˜·½ |vƒ]è9êm?<§#`Dd².ò^Ή]Aµ<ê øžù+Ï ðùª•¸6Ü 'ýúƒÎîćÂç`»ÅA™ïòwŸð‰oóÕ÷˜Â¾<Å3À=Äú'“o ’eÆ”`ùIp)XçðÑÏvJ¤…§9ÿój¦Óá°:¦s­·b’£ äZGë¹Wý»#õü ÿÅ3+%ã‹° -ÁC1è+nLIÓ|Þƒi € Ó .‚9"Ú¦à)ÐxtÄ`½èÚºË4»˜º´¨¢­/б²uK%@™ÏQm¬³{+(êxbV¤îb¡æ=Þ€15ê ŠõÑf yÙ´XFR3^šÿ’ÏQ Î¥SEê\®I-t.Çy¯º±p_v}á o>Ê]•ï_Œ´6TÃ.ŒÎ݈RÆÖ¿!EÛA¬Ó=(:¿ó(Ö)1<[f›å@ç÷Öý#¬¶-%1f©º†.Û“µ//·}jü%êŽ(ü]¤ËK·WK¯9_õËèFßgZj* ôð=4Ïy‡ºÄq·”Xç­k)ÕF;ñÐtþcá0XÔS©q- NHŒûôŸe‹¡›qd‡KÉnÿÛŽåh<ŠÑ{*xˆ€‡? V†Ø ‡}'x@ÞRF(=”LQEâ-_íöÇÕø5NÇV48çL=̵¥âܾUè©hLÂ5¿3'°Y›Ú]\«0´%Uð ÉÒj%]^­}iøŽÓráb+16'ö#Ò Xtô%áød5¯2Þ8ƒÎ{0²Ô_z<ÎâÄ–)êx9ðÌ=b%Ÿ÷ü-s“Á·×b{ËO„Ëá@°,Ö)EÙº¢½ã¹Î¨7*\ î=ö@6ˇýE?ëÝ÷¥ð$ †¸Dlí"OQ&ö³lNÊ® ~Kq‚ÝHÿ^XZ,iNN]ÝØÿhtÎ/·Šõ!h @§qÅ£acˆÏ¬‡æà[‚Æð(*6È øa€Ð˜C|öc…i*Á¢p EÀ²èëA:Šâºp Y¤TY4ÂHµS‡0 \ò°Xç”} wsÕç¥:ꑯÿWî˪®›Ám°'èÁ›@ÃQÔïThêDÝøŠL”†HA2@IDATÊÎFgY¾£—rs¶”lMÞúTœç 8´X˜Ö§ý£ójÚ€í=£vð¬öUƒ‘’Í$}Nëµ ¢ûuL±^1y¢<Ê<´m`K8ú€c¸ÿ/æŽ1¬9¢mC¥1º½±ð"woCÛ€ãtÈ>§ŒbDóÐø<Xñæñ`Ãù-S±Ýà<Ÿõ•ë^ ¹¢Az@!Þè*Å4ûn ƒàr‡ƒF2-2Å´Úƒ£½Óˆçyv ,nÛå#îÜfUIE@ãD//v%ÕHt®Î¯¨³Ð®å.Ø=ëü¶Y6€ûa¼{€j½í=›HÉÖl$õm¥bÇ÷z²­ôh.*de2£ @,XKrᦴú–Ð ^‚UÁ[étø;t´N©üìoªÄœñúSÎR½Õ¯Çu½*˾џl8Æ&p%xfžc¬™lI±þuð²ù 7ÖbZÑíø^ð Ã9ïsx܇϶U—êÉ!DÛ]U»Ž…©/ˆ±~CéòD±®ÙŸ’†²ó‹S1£À4úåEƒð`§C˜ à#W«,ºd’ï§a¬ ßÀóàø ÈV+§m™:Õ Ø >Å)Á…¤úŸÚPÅò&¿Ø`oÇ ‡··º ñÙ³ ‡›F™¯+êEç] €ÕÁ6SàxàcOæˆ]H½]#@§ã8žg¹| Í@åX®è}ÀñtË-‹uäÏLk3'Á• ¦b½}¢ŸÏÎý¸g×f]´#›I<çÓtÆØ¶×êGª/`AÐÉW€ó Ĺc¿¡#ë+]O”™*1wáéןÉÞѨÑ_~-ù å.ä;go‹r‹w©n  h`ùv*j<¨LëdØž‡v°4¨¸jDC^<´¼T¼ªæá;¨‡„=˜º ·ç[KÕ.&òN!©þgØP¥=Ÿ×ðv Ýw,Ô@â"Súð|8D[Ï!­× W…CÀÞ¡ìcÛ4Ý›çþŲ´Ü7Œ–`P¬KëK=ÛÎ~›À«늶ùÔu9¾ÎudkòQfª¤©ùØ‹uæÕÛø3hW[íð lêÅrñ ”tŽ4_®.-7ŸÊõ…ßûKË~yMd}n‚.Ùau O¡Ètq:ás°!Ø#kðРJ9áf”{‹¼ ald+ Æ›¯Ôšô,=upÝ„j„ö›àÖ3èãð^ nÑåúBá³CÞW1é]LiåRmðïþœÆømaþdÁ…¥ûÌ¥g£Óhð¶ïƒŠÏi[ÇYºA?x¼åÝtÚnÏŽ³RRî[†Aa'PÂÑ"u ó¢Dy<¯NÙ[М+êc^Ÿåø¤å‘OÓ|ÿ´Îµ¸×Ap.´€KaS°Nû:®õj_%MÓñ¢®®²´Þ¼FvVá(ï>9/å¾z-{R!:sjt±²1dÖ‚¼ƒ/@™7üÊà«ÚVß¡ ðÐÛ¨Æ#\‹]Nœk8î„Ô9x¬U$ðãl_ÑÈ%jOA;¸´ïK`¯‚ù«ŸT³ÝlÖÔg{rãah2§{õF¾\pH8€g—¿¹šSæ8žS´‹Ô1Ô—ºë—ÃÓ`PµN\üÑpØÏ`pœuŒU*µ,ÊcMëóù©æ";“XsÎTQËÃ÷ÔuƒGÀWÙÚäyþ„ô ÇAp9úŸ:Þ¦Š%žIÖUÔ[êüÂõ½ÖL‰ñd¯¯.,¤#® OEƒvÿ–«»w £X—Çvi™·}8 ö‚Ka èX«ƒ}Ò9bÞr©mÓ5¸¦µa,i?_ÉTœí•˜/Í[ÖÂÁ·˜Óao0r;~ô+•:¾óÄÞmß þ ǃ›uJº6ÇRÒ²#Êb>?Ê\QXâÔ¬ÓoáG7þ”æ"þßžb1*-W©"š _#Ý>o£¬¯“:¿Ês£}Áȹ>¨€JäkùÆð.” ®Áº/ Rqíî©;< qs’Epc™Ûò¢Û \þp<„&Øâ¿ŠÅ$õ“z€øEkæ›Ã0ˆ½¨ \ãJÅMì n" ÐT'òÖ~±˜Ï×—z¦iv;Ú·'WëÊþ h ©gèƒ'æ)5–eåʽυ¿ŠŠ¶×“ï Jì%ÆðRúúŸ`;°ÿZ`ðRbœè“öàÉZþ:~Ìãîõ¯ qDy:Fš§IÍ|‘ôI2þƒH‹æ¥èÓÕ¼"wϾõÍP¬NcÑÑ‚`yø î`ðUTY l÷!, Õˆ¤+ ‡/¡ÜzTv5RØiá³ïótÔ@ó‚±­Àš­z:Átð¬½Dõ¶Í=œý–›¤þRn[uxÇ ~-‘®ì‚ÚÀ$h >;¨£ƒ†h¬ž‹›°.M½aß‚À`ž¯/õL³yŠÜC0þ÷ƒ`2xþ:¥ë: \ÃpLQ{ƒÇDè :ž(Îéz h–k+ε>Ä:Èfcê¸öq|YZƒm¶íH'´\‡!ÐŽÅñ×qÊI¾>Ú:®Ï…§Â³}ëÎ3à4ðmźÓúheÕÔ¿Dßù“eóX6"ŠÝÆ¿$³Jöa·.‹ôpšÃsàÁëàFdâæÇÀjàýÃÈV%ßÒZêàøÃÀ¹­¯¸.ƒ€o-ï€Á ŒìOÔ»-mÍåë V6ƒ+fþ%%õ“ºÔ]rT÷Ï«èY8ùÿé@,Á ´Ûº—›`upáÏ'ŒÔþ’:8™.Ë€`½’O£u*踴….0\ƒJSq¬×_weã-GjÙ ¸¡˜wmÎåÜÝA;sÍ*{QðÍÓ37¬ ã` x†¶ÿ?°½ý;ˆõS”‰ÏÖ)‘÷9ò4Ÿ½Õó}ÓvTgmŽ$½ N€¯¡ñÐûâÖ˜JÚÏ6n¥Ÿ‹zóºsY¦ì ”XšJ(@%[GÔÊ^ÇiW†ÔXxÌĶ#a¸þSavdE: Múh`³+-`¬z»ÂØG¿PxË»”G§u*íðE h®7ÂlK½@qÖŸpþäß݃£Tkø–‡•@§[Ï$•TwêÒ½ëü:^Ô…Ž#uŒ4¯3îÎi¹ý?€ž0,Ó†Ò¹-›R,[›tP´1ß „¡ÅTå\ yÇ0àÜ [Áðwøt|×o‰9óÏQ©õŠÏŠÏÎosšöi;ŠkÚïOþh¸Ô_©q)ÎÄ:·¿ÿK¡d®þŒílÁ—$óoÉ-š}CV¸$kq“ò6¼ŠÊÕ(6pCXtþR¢—t#b+ˆ'[oqÞU@åy£)®kvÅqw„°7èÚã Sh›cÀ­{®}à´szá·á¡KJë/¡úúŒÐøJ|à.ÏMGpÁ·©sy~A9qc©Øïr8()t—ŠzRìc^guü^ Î´Q«Ö1Ï'ú‡ó„}ÅxQ·§Ïk%ýV+æ-wnñüŸ„Í@ÆØd3±m”™Æ…Ú™æëß²|ÿ|»ű |ªcá2ø ëÒµ˜wígbŒ™Û¢‰ß™ýYïä{ž3`YÐØ- ‡6µíĵ…8FÌS[í]ƒcÆêop¹ Žƒëà|pÜa™bž$[¿s”’×4ļíM/¿‚ãŠk(•F{SQ×WÁ©p:hoö³N‰öŸ’èoüX˜O3os׼ǧ¦7³¿“Méì¾(3D&1.Ôaø™ÓœL‰J-%Zº` Jq#ÏØ<| ËÖCBš‘ù7 ¬ ÜÕòB6“6ü<¬å§^ñ¤c§4Àg Du|O¬ŸìLÒ–'û…4'³xèŠýzýðEaÉÚ¶[W]ƳÖÀÎlqƒH¹åV<8‹ºb'.Î¥q¬j,½Í¿ ûÀCÐÒýóX#.BýÉÂp?ìJÔ¥©ÎvüÂA­6ÚÁ°/8f”“­±Ë•riŒgªòûÃþྞ†Maq°^[ñ2ñíeÄœd³zÛ„Ä|>Ç‘7uï;ÀBýò)U³ÔE™ýôï+@JÅq.D9ÿðuá;ÐI\ÐË×d£1ù†ðeÇK”<o@µr:fðŸ.þWô&üjoáì⎔†í œ!PURtþ·a ø tš ã,5ò*¹5¡\§Á `ÔsÞ(dkh¾œ8O)y”Bëf8"Ph¼åd<ê;d™‡å“y{~¹°U_ ´7 Æ±Û f5Ù‘üôõ´É†Ë ôôlõ¦ÓŸçÀ2° Ôvî.D[lƒÀórË¢.Òá”é€{”™d¡=ÄÑ–¢¬¬TcDê<_mkk; ú÷aKˆv+‘?V/–û¬9·í"©å!îýf8œ7ê"¥¨¦,ͧc[Þz™`0Œý›Ÿÿ(~t„tP3±ÌEñÆÃMð1Èvoç;ÏßÕl‡Â¢|‡šã/ZŒÿ#ò¼NÞúV؃aÐ ´èJD%(C@J߯ðl}Ûb:’Ô . Šùî¤!Ï’qî0Ò(¯6]”ýaop7`fl$UI㤵{QG´Ûÿõ7ƒnÙ*ÕêÒo)}rÔÔO<îÙ•ÿòª2ŽK¤•o5ŠûÚ .÷d@®KܤútÛƒzÕn~ Ø:SÑ=<êœÓ¼b¾ ¬ì;ˆxKã1ÇzÇ+•ÚÆµ8–©Ìpؾ¥<×à8ŸÀ)Åça¤ÚàÎÐÜ“mD‰u:~ZfÞ 1?8Wô±m#:‰½D½^_¸¶ÂЋW–ÆÛ²¯Ïy(%NäbcÓû“w! ñ‹¾eþ?œt:ØÏè§£)Ì•Ýüœi‹#[±hñC`0 §²BPAc{ÚB'ð U¬ïCÁ›ƒ­· ¦§Åµ©¯-àQð°=¼jÄþ©|Íðó…ïC¥NƒoK¹jükMa‹é2ªÎÈ÷noÐK# Q÷ÏmT"êóš–Êg±Î`ð6¬ ê:ÚG}´5Uqžµö–GŸri:Ö‚ô½ z€A$êfw!lj±¬×yµ#½4ú'¨#mô4úRU²ÎvA:G”åûE¹m?ƒàqPoÚüÝ=Yk9ç§>û{ù[IßoiX^7ìÆó|I™¦²'×bo?ÿ9_}¬laúyxÞ®yç§(Û”s5Û¹N©4×âüxPö™û_¤Šúˆ‡h0s|Å æ¾»À ¨Ï>éV#è±Ã›uÆY.Eå9€ œíbp× &³»äXÈ ý±Õü`^a$„}D‡r©»sókƒv§m…2<·Á3Žv¦ù| 7hóÑÞzOâ\8µ˜>iê…¸œîá0 Ø7¿žÛ>Ú©öîXJm©uÑ7mkY”ŸHž³ÉþàìG¤”8ñsp=œÂàb­Û^‡X Ù’â!ƒñp hõ É@Ô~*3€Jl/óø¬a¼ «A^Ü‹t,ÜóCµbméš×öä5ðy6¤ÃÇÕ»ÏÐ ¨|Z0ÇR¡ÚúKÞgë;’ÛÞã1~¤ûwëÀÊ`àõö6xZ^›hgÚß ý…¡ëüÝÀó7ÍçãÙKàèŽå81V¹Ô¾*Ÿïb2gÔÆ,Ë3š2mhÙ¤.ÆLÛzjçÂÐn‚6`;ûäû¥Ïi>ÚÇø®3ê}1๞þp\§€ã)ù±„ØÑçàYÐé÷†©"Y;ß –ô¡Œ¸€Áà¢6_Ñê#FÀ{Aç7ò–ƒÍ7ðl·Ga7ÐxʉcºÏ»¡Y¹FeÊ?¡|%Pw©¨¯%À=§Á!mSI~<ªÃHB5*cÀç ¯ÿäVòG=[£¯À—àÿÀuêÏ "ô¨“—ZHKʯmAg{Kå¹ì©ùRÏ–i»‹C«b›h[.uýÏÀkt%íó9ÏïÀ¯§¨¦mšoƒ{9ìs„Ýx™éÀmÀyB ^és¬É€øt±‘—ztíg@SPlû!lq?–ÅE¼#àHБbP²%Å¥FÅö%juZ#Ž SÑéby¬‘¡äº¬”8Îp(¸¦RâØ®åJh¶UnÒMc„e秪FœëиTZ]² î„} \{ö~Ø£–6T•õÿ8¶zWAÍžåð,xþ—Ó*µõM¡Á„Áú¿Ä_Üzëû¶dpÞË^…}a9¸ Ônt-ðöZ, ýN%¯séÀ+‚AÖ:]ÒLÕŒ¤ÏæC:“¹NoÃÚÄ‹lì ®-ÆŽy(Ê|ÅòVàywƒ’eu‰cÊŸ`%8ܳ´~ ÃìcI,^ ÿôÀÔ§²1\Îû%„Þ|vLEü« Ö1ÜÜS06‡uák¨D–¡Ñ`èN¦, /ÂÇp8T:Mg•«Ã„^Å<ÉL¢s©¸að9¡˜ñä ¨’C Y6ßž¤ i]†ai¾~–›ã'ê4ð«áX=‘­S–äÓ^>‘†žµ6>ZÀ…0ç¬adFÊm¥Þ£ãð¿h[€¶¢N\µzövÛ Ôµež™ý!LÏQÇuQžõQ !?”‹i´É§ö‹2ó)FQíkWP¹i]ä]Ó}Ð\wŒE6Ë›FÛH¯§ìo`°S¢ÜT‰Ô±”xŽvÎÉÙg{סÏÝê X6„èï³¾ýÓñ(ži|Ÿ ¢]¤QÍÆÛÂÒðT+ ÑÁƒÜtÈþàx¬.Jƒn Ã‡¸±×Áƒî\LIjD9öC`[ì¿Ü kƒN©ÂÒqy¬S[yvÇ)%Œsí•9 üð@c²µ çñO ~}¹ Õ¼Üi=ûë»% +n­ÁäRLì}L‹ l½£j¬Jéjäo‡MÀ3µþ'0°®k‚çº.lW·âD0H8¦A#ÕiŒMqÍ<ù¼Ï*õSÐV :i?3ѱfÀŠ`½ó”j妻Á)Ð Rɯ1ž#µ­ù˜çfòÂØ‡æÐô ýÕT})éº"cYïØúÖœð{¾R¨\•Îe‘ØÆ>‹ë\ZCm¨Dd´{zƒí-¯DÆÒ¨-„ "¯BXRƒY€gÛ?:‘Û5~ :»›{4÷c’­XÓRÚÂpX J‰F÷´JæÑÀF‚{R7ÎQ›°—å᥆³ñ|í2Þ†éü6wBA <5¼Ôµ´ú̸:ŽúúyAŒótóÚL;˜í¡.]F½6k«¶ªcØ_ýê´Ú  ´ÈGj™kx ´%óQgê­{!ü ´±´Î¼âJZç¯ À@m#>TÍÔßgÅþÁö`Û·Àµ´íÈzËK¥1G¬‡fÙü¶µì;h:?–vSPž„ï³\á‡L‚t±IuMvr:¬QÉ*Ñø9HbAdKÊPJ»m£tÔ¾Ž?ÞƒOÁ9\ó0Œ AÅ\;Fàx³#îûEX\C^#)[ –…JÅ`5ܯÁ¬6a?;œÅE2ªãΠíÉГ߄ãüÈ挨ʆ–°µÿŒæŸ4k•Œ¼0yÏp%Іogƒëù”è—Oc]‘ƘöñÒ:º5?Öoå`XÖ‡T`¡´ D^#~N„ÅÀ1]пAª¨CÁÀó9n)1`¨°ƒÁ ²8ü\ãÊ qXæXÓÀHæoòØÖû+SÌiVQÁ÷áØƒacHÖ± H®UëTÔÁð4tƒÚÖ„þ6U°åÛizôƒ …?èœcÎÏ™ÊMTØëÊmùàbug÷?¼é´µkàHPOuÉR4¸vw #è0F¯–p94ƒÁV°h£Ú„í´+íÓTž}@ÇóY{Dÿ5L¶¦mô1UÒçÈ;ŽÛþJÔåûEúP7OÀî`¿h«í_G$å1E™¤ÏÑ/­sïëã¬?¯S,uB,*S¸¯O±Ðbu­‰Êu¡*¾T PJ_Xb3ÝÈë°:ik Þ“a .^Gw³¾Î…ÁÍ˧¤oÂÖà¿ÃÀˆßß1œÃÔ}®Žï:Vßz D±])qí·ÃÁ†ézÂvà8Õˆky60À|Û<Â/d˜ãcòOó¨ôâ´Øº«Ÿ£¢4¨ôa4n±/–oñ´ïÊÅÑÕ¹ù!°4´†°<¨ƒÚ„™9¾è –)ÚŒåÚÂð>¼ÚÉ0`tí*Î_­jÏúÁRàå³h#Šë [Ê r?b½ÑÆÏçڰž3ILjöVD~òƒãÁ¾1–õ>kw¾, i5bÛ/ÍÛà&"à3^%:â FEÆ›eu‰r+l :©>Ž)*t Ø<”×ÀH¤³^ ‚Ê7B·Ìö«ƒJŒµ’Íä-~Nƒ®àz5.ÚuÆÂïaÐɬèá›ê€oÃÇ0\CgX4%ö¤´…A°&h0w¡ðT+ŽëÞž÷FK6¤q bË¥|‡ÄZ/§ðxXÂù$Ï•Øú™¤9Qìßø¸6 h¤A»œCÁsT﵉3ìêð>Ða=“ß›ˆÔ¼…x~Máð’Ò¾´mE;p,×ph+ö­ ª³yLóíô­Ëà8ЖÛ(Ñ6òÎ{+aóiÛÍÏÁ Ð Ò±x¬3ím °KöâÇņ$3ÉÇ<© °6Qñ7@OÐYb²e%ÚÁÑÀð.ðF’‚ÝI=°râaõ…ÍA| À‘à:ÞÞè­aqc“­ Î}º&ý_XÛ â4¢£A#Õí£1Œ€®p7ì–×Wœçièé8æßçàŸ…щGU¾]áþÒLç¸hgsLÖåEl$ñvSfÐ)<R›XÖ¬A2ì†ì,âYùèeá9êC‹Ï?‘FßHÕ«í|öL7€@{ò¼…Oà.@ÙÙš´9í#Æ ›Iz^Q–¦Qo°ùØóLo±i[óúÅØ é|Ž%–™¶…{Aý¥k+Õ‡&™Xw:?Þü;™ˆ¼…ª_úZá[€F¾&8x**ÜÛWE:W:)™Äæ=ToTüxÞƒ-Aå?‡Â§0Ö&/ާܽÀq‚mwH™ Ía>P9ýAcòÐSqÍŽi¹©Ïæ=$÷ݶ€CÍÖïo踆úRJé PSûO眽‡‚Î:Ý‚mN)Øc+ÊÔ·ɤh6'Óún©Ò5Í×…Al`]uîÈ3@y–_ôAØÔS)Ñ&nµ¢ØN^‚Nà&ÄóJÓ(Ï—Ñ,ûB×sŸmŠ©kZôÇRbŒü³åJ¾üÊvÎj }ÍÆÚë“ ÍjÛ>Ç8åÒEis-±?²3õ‹¾–«ßuŽåGH+xœI¬ÓПü=(Íà>h+B>88m<8­õsø çl ÞÌ*ñ°n+øà1èŽbÞ¶€¯d·eû€o¡h²™k8ž‡¥X7z‚Ž[­8ërOîÇó1<«€ûõæ8 Bæ#‘­H4âkÀ½ÅÛ Áå´} Ÿ”N X•í^x?9„ì\‘&sx–Ÿ‡ñ°Ïaë3‘¶¤Ñ{[šú¬7„7`=ð,ò¶¹æ=oû+Ÿ•È›jß’Ö¥ÏSw\{g¢½sÃé#®)Æ$›=çǵÜ5iöÏÛ‡c8¿õ‹ãYå‘RT#Ñ~-JFÁ*ÅË£}Œa•kºßÈÒl”—Ô™c€­htü,»öÇÑ!-S|#™å c[· 4ǵ›RtÎ×AÕyÂùÉÖÜü.Vå*®õ=P9Žr8ÇWÊ&›Éü¼"8ïÐ/±ýÁà·9Øö6l†¶‡’ŸÊã]@:Ï!æ–”ZjƒÏm É áaŒüè¯A'PÏyxþƒmã’ ÚO1½Î>Úesk/}àPHíǬ½©c™¦y뼘.Ç!ÑNß{N»ƒ>äÅ…M€0bëÿ «Ã°¼.zoÐÉ=ˆ+&¢¨¤U‡ƒéúP[{Ç*uh[€Ñ7æ#[VšQÓv͵ðДA°#Ä!YV¨——¡8¦³¸·¼Xï^=d×îž4÷:X¼$4ž;©BïÛŸ_øþÒ®‡aÚ“ ÷OsOb‰s|F¢Ü`tØÕ³V>pyŠ¢núž:¾/˜¼x‰Œ€ÍÁ³ qsÚ½ià¥v ôÛZî܇ƒcY¦ØW‰t)òöý td×chR|¶Ÿm†Á°-X!üxþ¶ ÈÎ’/Wfy ¸ $J:Ž—çj8î·/VØ œ¨Ð¦pèt»Àw ¸ø{a èFU'*'Öiø·Ãž°äE¥è<*@¥?*m2®%=8k£¡kßbÝi×k°%T3nŒ¡ó¯± Õýyˤ†ÉcYQ/îÙµjœoºõ§ò½âç¼½P°»)Å·"¨qÙ¹*µmƒ/ähâ©—Ì àÛÀã°=¤g¤®ï†A» 1èß;A~Ѷ30¨ÈŽöã±&hsÃa=p<Ç tè×a3Ð^%êÈÖ<›×^—mb¸þåa­"3H­;†Àj`ðˆu;vHšúH£.žMßçnQN6û…ññwÑaÓW!+SqãÏÀ(0Ò~ 1ÙL4Úñð¬Ò$HÛDZÂPá:Çgà¢ì¯’¦Â«àztç¯TtÐëÀ· 0$ç3Шü-àg¨V˃SGCøÊ™,ªýå|âœPø@DÉÜ}b®ˆçðo6ÙŸ_ò $ß ´§ÔˆyÌ>ºu$}V‡¨7¨/¥Äq‡oÀ³Ê‹ºwƒ„6ÈD™åö×m0_o›°Û:ö°%ØÏ2íðmxlëZûÂà¹+±¶+×|ˆíJÕY¦ÏsK$“¥øyüaü¸ŒdûAÞHu¼à9Ø67ëâóâ-ç Þè:ñ°( Nªu.Œ8û¼Ï߯¶Ù­ç³›\/c(Ð>—+¦’î©Ãð8“hÛ÷€íR›kÁóµ°7(n<ùP„ëÑ‘mo½(Ñ&ŸZãD»…ÉÜ^ÄBPÆÀ8p íLÓ&‡˜yò»A9íÌÀõ‘:GØ6G¡YÔ²Ò]Ð`zŒlŽÛ+N¬“(QfšæUÊh°ÝX0˜xSƼdgj}-Ï‹|:'¶¿¶ƒBl–ìLb;ƒÅ‰0y¦šYÔÅSÐB©³¶*”¼Eâá/Y¦ó:Þ0pÝæ«Úw9—ïp>ÊÔöËÉ|jE•í9&cÁ<‘&ó`Ö)œÇÎæOá`rý!ðÌóçÓ†2½—ˆöY›=QÉ·üÜn^ }ÚOç?¦Cˆóicç¹Ü ‡ƒŽmÈfãØ&ìÀÔ¾ië¯S€`Ÿ}TøŽÔ‹jqð‚¶Ïú`[ó1Ž©—Õàž­S"-<ÚoÏÃp•ƒîvNÑáÝôàk°Š4P¨%Úšw3­Ë知‡Õ<ÀÖ°äÛù\­¸Ñ}á1Øþ ¥Äv‡B_PyQT#îË@e´ì ±²3‰ul¾”çq_ÍÀèmZŒäÂùâAVÍRÚi¯óR´³¹.8áÓ¯ð'ùgòRu3ŠÐ4æ°¿tAËò0Ö„°`’²¢Ýt‚[@‡3ÊM€e µ"$Ê-³4ËGh›OcÇxÜ‹y÷µ 臾å¤sØ'üÎÔgñâëXD[túÛ°e‘®¤ÎóÜr?tFIåC–‚Å 9¬}Á€á çc• [³Ryãh ös£FIoòuÀ1c#dkÛ‡V¹V®Å¸V-Ö…âŠY¢åºG÷Uª>kTü¡Al ׯïΑŠkñMÉCòcC]¢^‚Öu5üµ¾1zßè<¾û"p‡ÏʬDGЉ Ò‚ŽV ƒ·Î«]ŠŽò hïK@m›uŽ@òÝ‹Íy´iëJ¥Q¶0õÿý#œ:êtbçŽç45Ï1”Q•ÕÅsÔ›Nƒ¡GS¯â¢©‘ç"ø3|!Öù¬²#jzÛÅ׌—æ­×1›ë£ÎÔö`¶«MÑTgb7RNTÚ>p 4DP/+ÀH0ø¥òxmëIÛ›÷-åðàëöºÍ#ÕWøÅ÷¥ß„x/ÌKõ&ÇÛï±–cá3h—ž¹¨_Ïìð‚1L,>¿Oú^Â;äu mÖæ{ÒcÀ›ÜþlÇô8.M²3‰ö«­hÓ­ÁàáÚ,‹º4¥8û¼þ,iGˆ€ayˆ}µ¯Û`eÈ+Ýñ”HÓ|Z–5â‡ý/[ ½ô$cƒ€l¶ñ¥H5òXtZo£ášp7l:¶m•´mš_”º·Á ¤å‘WaàqP¹*¹6Qa›@^iŸŸxðUçðm&=´&<{¨«@¬l­bÿ /8®ã;ÎÓм5*÷«1ùªéD9aü漆÷Záï|±‘ÞïV^®Ç\-¯TustQØÔ`BbWÏb¬±0íË`«M[ßN‡s!°í£ÓÛG‰1<£±°|Ž} µ'gmó.ࢭùò`ž‰cG^;2Pl–”E]¬Ág×-dÁêÚ£Î4 ›IûØÂ÷5,·;M•j6¯ÊÜÂ<—Qø#þç½1£ïYM'سÈïI=›Åa0Hwƒûàýâó¤b_ÅsLÏÒ ÁÙG<í·7<wÃð-#llh»ÚÜ5 ¢l£]›Šõ–„m@‰zÓ ú¹v/=?–Ø7Ɖú|û´<òMèwùühÿßÞ¹@[Q\ ô¢ˆQù ˆŠ"Š‚@E‚"jDÑ!J šYg–˜LÐ1d&™eLFMf¹‚ËLÁ`@QFþJÄ ¢N@>‚ ¢A‚20{÷»õlšû}šÅ{Їµ_Wׯ«NsªúÞ8I ò_p3ÄŸÛH¬ꆫƒÀ8£`Âãõlî¼mC~¨ã5H+ŽíY¨2×ÐO";ç­Îå¢= ƒ¸øœrÅÝDÇ÷uÆÅ8ªÒ æÑÎWˆ\óA§- t°°éá\þÕJ\öê ü''íçø(à'ŒÆ]w'‰Pk_®™²’6Ä~h?}a&ØÞM¤'| þž0Ÿ…fTˆ›…~>Ø6ާìG@Û´Ï0ÞPG›i¯Þ7‚`Ä뇺ñ«å¡]¸>CÞÒ‘üx4ZÈ pRk³÷æ)¡¼ân÷{˶Â`pGVòµSXq$ñ>CýlQtq\­ÁúSÀÈýeE/ê޳Oåˆã5¹ø£ÀˆìBªàªˆF³&ÛßFâñ³™]f2+o©ø2(Qiïß&í}oÈeÙˆ­Üã.~&t”\öåæ7NíÂÝÜ5,$‡P¨] 'nÿöuô_‚›L8¬¯Ø·~å Ûus!ô?žÒ^¿„<ŸßtdÇòCÝ|÷ö¡Ýÿt?Œ"›!(Ǿž  IV><™NÞo!c ŒM2J»‹;X•,#+§8Žƒ /Lƒ¯ÂÒìórx 컘øLÛ¸øòLùnX .ăà‘r*ÛI1Ѿs›bW?ˆþµñÕ›øâ”®4íj'ÚyµvÛ9¯ó±Îwðí¹ÙQ%Ñìp.ŒÉ^›sÕv;€’oÝX“è»ó–Q­ŠÖ Îw2é^ð¼:v+PIgÀCÐô}âUHúYQ¹ýÿLæù¼Æ°ÚóIŠmãó¨ÍÍ=ä½5Š:lWøt‡9p häÁA“÷¡œª‘„{ ùl¸Œ¬A)–;Ð:›æ²Ûä¼Ï%¶³½‹¨²Ú‚ÏQ–ÇçrÜÂþloŸFÒuà„¨^´ÁðMØOÃÛYÞàj]Ø«8Grt†cá÷` 1:º8öi`ØŽ!)–-‚À±€ÇßÅ‘–ñakçä›ÜqdWGѶ«•-Ÿ`­šÝˆÏi3ntž®’ߵحÁIœÓÀÓvk,{.€­Û˜¯mhúÓ³ =i§}`´€ÐâÎëÚKx¶i%äÅﵩ#A»9:['^n:~¿–û»fòãŠÞ]u„.0êÂéà€¿Ãw\wí ¼ï8žv’:ÿ#ÐT²å°ÜûІdQQ:Ù°šƒR•`;ûkk`ô†±°^†WÀr!/£ n‡sRwŽÉñ¸ˆÓÁq¹˜.¾uÏ Fý^Ÿiãász0í|\Ÿ»žÇ2&š žÆ{ÿ8²ª«[­nãk9u»Îë@»3t„ s’ÑíÆtš7ˆ“ù ¬„~ð$E;¼& òÜëoö«­-m@ûènlÚƒåq¸îm«„²xÚ¼‰>cÐ&C=¯ALëÓߺ€€×(äf¯>ÀÕââJ2ßû€FÚ”0@ƒít”Ñp8Á'á2dÙbß³tàú8|>‚¤8.Ç-ŽK1môvL+« %\Û Ôu>ÅÄ÷¹±0^†ö`ÀÌ%>O\°•ðxß4…Ñüè‹ó?RíM‹+þ d2«¯8ê(Ž«ÍñgÖû€³¹ÑN8Dþ…õõêZœ Ú—¼,f@WpSŒOÒr& âÚy9b¿³àh׿è›*%øU°cóCGH{õ´ò0\ÚQ(#¥&c:“øÕ2œŒP†©Ð FFWùŽN2ª§‚˜×ÐÎl9([À²ÃÁ éàö÷i6íéb `p0’•ý™.U|ÖpìóÀÝ·!86•5êÀ{àÌWAŠiTe«¤Íð(´óãc㶨4¦Æ½pe¶¦†tN6]ìâX Ëà/àX<…­f‰äô8;s›{XõUY-¥9£ZÇ«Ôí¼}¾AZ»Ôv´Ù“àsPÜ'À pP\7®EÐ ŽøDm3zC)búÇ}pm¶¾áæ±Öc|é"®Ú–6¡MûÜÉÊàÆãõPÚb˜W(·ßáùá £#©LJyÿ ô'nQr¥C^èócê}F8#gPN•x¸Û…>!}/„z$Ë’5ÔÖa[CèÓ9\FÕ¦ RTÂVu‚RÈŠ9•ë  3ª‹x9·yÅþœ§H…ÛN}5¼rľÜIw»ñw{WeîVñwÁÊée¯Õ-Ue{e€Øc-Ö§ã¿ò’Î}&èp]-8‹6² :C|B:àJpm/ëYîš½ ¶?âm¸ÝM¬ëÆ8þ >ó FžJÚƒí ü‘<Åõýl^;®m QöÞ~¬ë¸”ð\¯öµº¾ažþ9l0'ŸëHÇ&>Îõ Ða”ù Ü] âµP:Yæ½v24 TT\¹>Se„g“,KtVÛÿ3è¼AÂxÂ}¡«ãSÙÃ\莻ñ9“@½~œm Þ&À G¹lQI—õlù·eþxgEX)©Iu¨TªÊöÊXwòTloÛÌ^¼1®â¾´†éд7$mõHˆoJ®³'È“ahÛÍÁ~­;΀|vlߎ»³D±ŸCÁ²¶àsìSo'ެ°ž‡¥ ­y*èÜ¡?’‘ßjƒoÁQÞóÇŽàk¤Û¸ñ>Dq²¿‚á°ËŒ6£¡7رy¡M®t®2šDmŒ@Êp—4øøG'8 T¨“30T# ¸6˜vâαq¡UÖ1 ÂÀ±æE2¯ø\ÛjLŽ_qÎ.¢¸¸¥Šõ7ó}ÿˆÌ¿øâ¿®(µõ^¯W®Ú÷总ÝÊ+¿ëtbv³¹*×ì¤B.‡ÖÆVà ¸ 6Á'°Nƒ¤èü/Ah ú@R¬3@°£díÑgk瀎ÿdöžKd÷¹v̦ 6Šºpë”l&—J™Mª øp%8·Wù_ a@¡œ¬ÝêÆï“iZçoG‚㸠–‚Ž×¬SUiHÃûÁÅzŽŸSލHwñ>ÙF*Îhï®P̪Uî¸â¢ã?}ã™EÒM2»ÎèŸYô"«²‹1ÕªÊé¡È#þžÅÚeM‘ç9õ^màÖ]ãþ mºöÛ€“BôÙ’6Ÿ”ídèÌ߃Q° ZÀûÛê;O6©=år~²£zgpý3¸©äÇi@Ò.´;ëi÷—ÃPø(ÃXÓàÖùœœdäp¡#OJܹ½7::`£›/§‹•-¦‚NªC© îõx°ŸyÙ{ÓU‘h¤å5€Îð2øŒªŠJn¯Âa%tâ³ `¶‹Ë'ܘ×{¼<™vÌwf–èüÕ4çwÌ5)ø½êø÷ø/"ÀgnúÀ§ #¹^S¡1è`›!—mº¶a(£ÁôxpC±| <}À‘´²v“$ Båˆý:Ni ³KàF Öúð+@‡VœŒ“û ¸»‘Ì%¤½ö„G¡> åÞÇÓÉ{~2¸#7­Ã•dÛ6Ð a$Ëû ãÐ3Ñ=Š\ª$ö§n¦€éB‚!E#YÏq Ož¦ I=ž2–‰¹9…ZV«2§\£dn€ŸÊë@d/Ÿqm®½»èù0Ümó‰›Yk¸ÉX + h÷¥ˆ lo@ؘKi—¬ãó ^÷Îï‘|ŸÄ6Ð@ƒ‘Ž#ý]p°!änuÌ7¢ '¶â}äKS-Úâz%¸3ǰž{'ÇØ¢|Ê“çÀrø²¢³]“àËX¤Ç,OËBb½|‹õe.D!ªƒVÇrðœ^ù6ZèiÕºì˨{¯MŒqÓjþ’àO0owníÚ@àÆ9…&gßÍ;À©ðsX éÝØÊ7ê«á`¿U‘:8ÜŽŒF¨à¬v¾œhph’•å᡾×ÁÆTJ²œ¬Ê¶!mßîœÀgÅŸÛHt'ˆcì:ï»Pê±™ª9ÅyŽÝy–"ÉqzüœS.±ÎZhž«0›w×¹yÊ¿†öfð·Ã'WþæyžŠ5#»Tçì®W¼ÎÇQú‹'W¥\›`&ÄíŸÛ( hcoÃt ~6p <:¾C_Юƒï,*Ú­›Ø¼¢5÷¬ MÎÇÁ~3–ÄÓàÃà{©‘áBb~À¼öªxí*A¥„r’{¤-wÂ=-, §Q¶8Qn8 “á0¨ª„1¿F*³˜¬ BkPyq±m[Ðò‰uâ¯HÉz~޲’AÍûiüÊǘ(¼–»O$ŸR-îkjPy»á³<^;ý;7:»›ˆ›Gg¸î'8&‚¯v€›Ùå0Ž}À“ã`pã¸fÀxðDèº'팬=Äg·SIõCž8=’F'£ÑŸÁÎ,X:§¯JÜ™ ÝÛþDX–m“¬k?*gœ›Mšd+ê¬ÊÖãR)>ç¸Bä¬,,3a4v,/€JÏ'Žý9èš§‚ú2‡@š§ZÞìðúå1ˆ†ñf66úÕCŸ£¨ñ¢‰ÕX¹¦bcãµn!fcƒ-ÝŒ\_cûÁXÐ>{ƒÂà¯ÇO³ÜF¢?X¶·æ` ˜ -¡=¸qhó¹Ä¶MÀòåÐЉ 0üzž{ãv·wð%¸‚©yM¦óÝS5Šnž(ÚxÛè`óÁ QÈÙ(ŽÄñ(FˤòìÏIŸ³ /„ú$Ë’Ôîs¡ ¨\¢²ÃÜ“å’Ñ^†Ž`Ý õHè¾[ PßC)¿eëýŒ/X—FûF¼7 k¶T5FV»Yc“£ØÑ·.<Ñé°:ð° ô)O¨®>qeÛÂÓ÷)'¨ƒzìÊ%“9 þš«<Ç=.†Ï!.>Ã9\ùÚ[ÿp¾!ÙÎ…C!±ÝJøQôÓäBUkrY9Ë_“æy^3^Ûi®û§°Ά?Áp5¼¹”P—|m¬h‹IÑ>ô»Y° .'Ãq`±Ëõ½Ÿ¯è§–ÿ˜(‚Àäa£ªâô¶ò¡Cov³müyv.¤ÄÝÓ0| »™Q ¥Dß•~ƒ«‘­\qW¶ÏçØöé3?¯¹¤X°Jœ çfÓ\"ñ„àâÔ>‰rrÿ08þ®çk»'À„äR“™öˆ4¦Ùì³’Ëö÷•Évf“{éüÿ|\›t͵›á°„ë@;Ë%ž_†n`É%æëèúØë°ܰôÎÆ`ùX ڪϽ¹â`ÿɯZŒKŸ3¡â„;ùZïŽ(zùáÅ{ \‰òMˆ¢‚2…Rω#£Š1*&-­”`ÿo€Çõ&Þdåp®*u@ÈÈsuŽ.È!ÐŒêãÁÅÉ'î·ñ¦÷ftܘ¯Ú¾’Ÿ\–}e^ÎùíêÇ†ËÆÕð n´E×÷·0ܦƒ¡Ô}$ˆö£¬_âeÜæŽ?lk›cacéN ¸§Âüæ‘õ÷–hþÙ‡tàÚ“ßY;“ãðyÐßö«MXÇ2 8p[“7©p$8ÉbbŸ«À°Ô2Q¹ÔP›v*ÓÀ >釡X JôY€NߌÔOAˆ@ÓîúKÑÀ홟r7ö )eÉk²"œßçT¼k߿ɵ!¸ã{p÷ÿ+¸AÌO¬ŠíNÚ°u|U8JUX°/ƒŠç&>?dÓìKÒ½3“Ü+blÃg gñç£ ûêà€¡Ï%FµMïhŸl£ÂÞwßf[j Ife¶]+or€õçFý3žšB:$Þ)üÖÄ Ñ§ «CÑþp-Õž÷]t¼Š>d&7dgã)r0¸ª?tŸ Ú÷% …WÝ5¤ý ïx(Uìs=ü›‡ÊLæg¥¶Û‹õþ…g×çûÓ¼:Ô¾;U ÁJT†ÑÒ÷hwä|A‚¢=ä5rŽOÊã0 Œ®ÅąߣéGà‚t„RÄ#žAÈñŸöw x2ù-߇̌þu‚¹Ûï$,í>?ñÃ0cì Ý-ü7/q*?‰wƒ‡àRp#PÚ´•'E7;?4<Üßí¦-øù@>q{·Ÿ…FW8ç«[ óUC8¡èæÍ ßcB;ù °Cä<ÿKùŨKçµ¶ëL‡`$-'P=Ф>ïDxŽ…zPŠJ¥ p0\ îñ3yË_ƛيÈùË e4Þw¤”¥Ûwf[aª‡ààý±ÃqïáÏC™ÝDè ŸCPˆàFG¯±Ú]'Г—Ã@pcIJ#œg ݰIaÃyŒrÁ¡’ÕkÚ½±¯6_yÜ̇)ðiÂw¢H7ˆùmGu! ä›Õü ¾—Û”".Ì8Ê º÷‡`hÂÇŠó3ÿÁ×€®Í~/ÁÞ÷GEœÞ‹oµÙº7ÈÎÞ^GŸ5¥h·kaX§+h‹=!ÔU‘ËàøxŠÓµ¾ö¹ƒyn'*þ˜(ºƒ÷§ÚÑÉ×#“áÏ誼 õáyø6xœ/U>¦â °¿ã ß Àrt:¾G5s“¢ÿ8͉%JVûsˆTЖoûó yØI³Uµ2µšb<ý(ɵ»{"Ø‚O 6øÙÒ*˜Æ?ÛÏÉàÞì-—ýZø¸…_;êÄ—-uùü¿´á3TñBÜw§…õ¤/_‚³Fƒ‰ûv 8ü<@ÑáÛûž&/²LŸ·EŸL"'•(¦òMöɬÆ~=3iкL·ƒØ2Å›Á F› ¢²ÜÔ8ÚGV…-|¥âß~×À‚9’L%‡Ü÷· Ô»9#üóÂ¾Ž»¯éŽŠêêÄÝAç.$~pgxyFƒ;½y3ùÅí¼ný_©ÞÅèR_.h¼ÿJv_ûnÜž~RÌÏ·ÍÊlÕ&;ÆÊ9îo›Zñ_FÅŠÒäW£Ïí¡°]zø¿è#½Û¿šÇ¦½¤øB…¯˜q~ÑOšJ5j Õ@ªT©R ¤H5j Õ@ªT©R ¤H5j Õ@ªT©R ¤H5j Õ@ªT©R ¤H5j Õ@ªT©R ¤H5j Õ@ªT©R ¤H5j Õ@ªT©R ¤H5j Õ@ªT©R ¤H5j Õ@ªT¥kàÿ[ÿýÖÐ3'IEND®B`‚ic09$h‰PNG  IHDRôxÔúsRGB®Îé pHYs  šœ@IDATxì¼\Åõ€÷'¸[Ü¡…"…œRJÑà$AŠ;¥EC(-îN 8)ÐB`¥”+nI°A‚ùïÿ}ww7—Ý}+w_äÍùñí;3wäÌÌ™3w7B!JÔ@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@Ô@ÔÀÄ£¶‰§©±¥ƒℚF)¶1j j`RÕ€6¸½LçN%î©øwŸ™ºÁJχôx¨¨èTTMLˆˆˆè ÜC-m?âã»buí…[ k&Û¿®‘ï¾)ì_¸—Ðf!ïdD_IðBï£D D D D D D Lø–f¾ï½Ç€»‹oÜî–œµÐÞ>s¡ýKxÆÌPh7ŸŒ5Ïc°oáKò[Nx  šˆ×¨¨¨¨¨ @=hÃäÓ §LËæÍM;»üwàµ,äO¯ß”Í·1åX&¼]êçd¥k¼D tªè1vª¢˜¡ LͳËÂ7u”19yŸ€¯êx&f˜50š~¹Bá…¯ ü¶/µÒݽšñ}—ôÀgÖ†™à4X ØìI—ñ)1?®óìýÿ•dŠQU4PmVy,&E $˜•Ïðýfú"«µ(Ûÿ^á‹ÍštæóOÎ(|\x©JþiH;¹BºsZÛ%j «5ž{û®U(ôŸ³PXeXƒ­ð ÿ3`Ø67y½êጴ_‚_±S1a .7”É£¢:4€UÄ@ ¤ šÉ €oñ×Éóæ+lXøyÇù~4)wÂ6 •šVb3þ¦êa‡L)™œüÿ$ÿÇ©¸lПA_¸–Ïô÷ŸæâðS8À@F²ýÈ$ÇÛ¨Ü4p<%õ¾¢PØj‹äP,›:K¢P¸\^oÁÕà[Ó‚àñ:ÑÝõß„ý …kX*ƒÿ¯8Óq  “(ãjÀI%j ­¬¡Lâvð]aÁÂt…] ótœ÷ÝäçHRŠï3Ÿ&ü¼G‚ÛówP¯ø šLFâëð ÜÁŸC}Œ<©ð!s(–4 Ž‚´dû˜N‹á¨z4æÒR_=ùÌ)9ÌyÊf¦ínîMË5ܸ|ç¦ï‘?ˆíÓ‡ÿ¨À?,ðW …‘¥›k œÉìæ*é6Ýw›þ´°pá…iø©ž?«;ŒmòK6A·@7ÌZE«÷¼ƒàlX ü´çlu‹Ûõ )Ûx×™lð\ªŠÁÔ¥Î~ßZø¥)_–&òeá™Â‹…ß¶Å·!%¡â‡OÕ£Ô£18‘k cìy=vÊ"|Í~/Ú΃?ÓpU0£§õeÁɲ-4+–c¹J?ð´¿då—¥ë\f/Ý?ES~FŸs/¼ÁðRR¼tS „ùÔM»ß-»½½^«uHrº÷äøÂ;DÏtQ0ïU`>_Ôù¦Â¸¹™£Ô»Á;!J7Ò@t&½Á^„.ý˜ýŸò½üi…›YãnZžøuý‚O ñá_néX¯&Oqã÷mÃù>íÛ¿¾ðháZ%–ý:Ìçž ÿˆZ‡q½®§×?æo·ôá Š¾0gÒZ…þâ"¼O e×ÀÌ,¦ÿc¹´ë_Ö3•ló@%1Ï×p+°'¿õÄ.£ 3q:ZÆHðÀPIÌçõÚ‚KømøœR|Qqbé–KKW’åGψ_ŒçȱzmÁþ¼{ÜÓqOBílm…S‹XK㈛³Y±ŒçÁãÌœ=zhe‚ðáœÕÄ2z€otœ\ÇAh7ÁDB]Æ¿ OÃaà³ÏÀî<›„ßn gcx1Ñ>æ#Q&A D`âÔïçä4væ_ -N‡fO¤­7÷Ç`SÐZeÅo ð(óSøòOÛ:2åL’oúÀ³¥+—–HøÒU ½<¾}P'ŠšO;=?æÞ#¡ò1.Óbü<¬¼ ’·¿Úy¿*XÏ,QÆ«½v†õáëùN\Ÿ­QI âáËa0P?é.Nkw]å%x Ö§Ö@•Äg÷ëÀz¬Ï8Û‘–p¿4‘þ¦a¬Ûõ®{ðØ-…ÂE¿.¾Û:—¨(“¨‚šD»7ÉwËõ}¬Áû»¾É‘ÁÍø« ýv囿Ö¬Xï{B¹Ó¶uõ7ã!Ñß¿‚ôé?”m¿ÜJ= Y¿Úi¥Xþ²ðOxf„râÛ‰ð†Ä6þ<•i~¾Šµ_ÆïWx­”¢3ð3x±t/]£0kÞcã]²Y±@e „å`A¨$!¿é —pùèO_¡°¹‡gû“6;ì çC5Y…DÑGÿ 8•o —.Óû”M …cn.¾ßr•·zEQE”®Ô@3nW¶3ÖU^{ó3¿x%Ý7ùñ››Lµ%ꯅ|Ÿ¸'¸á4+ikT®,Û¬R¹ôzã,ësèåÊõ-Ãæph®Z!YýÚŽƒàH¨Õ¶¹Ïnù—ðþB®áÎBÉÿÓÀÚädP¬­\Ï“ÄøÑ´Ôõh>rÙü³­¹Œˆµ²‘5Üë0ô§˜ Ô1Ñ9p"x_NÖ r ¸ª\b™¸…ˆó[+Nþ‰oý×Õ°æ×.øøŸq[©*’¢L¬ˆÀÄ9r=Ù"Úyý~§ëöº—f³[Èt(mwð Çj­Çeô ä)ÕL‘i~2šíg¹6?Dd˜7•èf>'Œ†Z€Ôã?êä kàzØ©p _´s¬û.a–äß<ÌGŠ{Coˆ’ƒ¦ä_ð¡ú¹ªM¯f«Y€šy­cÛ¾€‡Á©¦ÿ$¸age"ØÀ“ÿ‰P6­Ü½e_^]BÏKè¢æâgãÖÕeÑ@æjQÅDÑùiåRüðìVþX;›k[ò§{ëmº_(úª\Kâ ¯Gœ1¾'\<T{ÞÑ·Ö•‡¸1~³T)Ì·G†à×~§Øû%At‚<£ Ã"àW$Š:µAúX¯t£ËþOþ ÒÝ`[¾E#O6#ä¿0óMñ0H‹¥iÓ£”×@¢ŸÙyÿr[¡°¦¿/m•8÷Â:ppéÊ¥. Ëöv|«´aÞoÆÄ´0àú|—Ÿü‘L'I5 eû¬KûY¸ú°Êáún5~ïõoÿ 1Q&v „1ŸØûÑÚ?ÿ˜÷q~ä·dòÃ;7ÂFFo ž»þ°TÉ› Û™—ü‡‚Þƒ_BÚ °onÈ».…¼Šìë±ÊÛp¨ŸÃÉx _ðp¨Mþ½—(e4àìu䮸‹ÿåõ:Åpµ]¦ˆú¢¬Ì œ&ëÃÐŒ„òô³‡Àûð\ŠSÔeø{Xv‚zäod »_´ÏOóùMëø·›Sw}± Q&R ´t²O¤:™ÐšíµóïíGŽç›yúýºÉ&öàù­áÐÕ¯UÜtäÎôJ^ò6»ùÛW7&·„zÅÅç<`«j7I­rWŠ~ox†Ølý~er;lÙÍß²ÝR´’¾õ­Çð°'üv‚å`¡}¹žÃ¼ÏáGÞ—ó»±)wïSbÅœº«Øÿ‹^›¿ wJ^ k{ƒØ˜'ã°-4»ÝØÞ© V™“ŒK‚ÇÛŸ‡8ZïJ⊲ö;¯:ËÕeÙÖ¡c¥#®éz/S—°Ý—ðï'†1 r ³iN\ejÿùwò–ÀwL³‚ï1&eÙó|\&§óø‡çUpˆòž*¾äówºÖ1?ôÅiòQ*ÿá A¿Bø®Û¦Óú6X¸¿3o/&þ§Dùb ÊD¦MG” K®9×íü5Cx—מûõñHp c V7±àÖ`ëê‘ðÖ¢™Ùæ¦{2ø„ªñ”îvö.Øþ®pw=¹•GrQ°î¼E ?´Èï• ¿œë~°/Øïì8…q ‰1oKþ‡mœ’œC góõÆÙI›Ëÿ÷pLò#ò 5÷Ž{ [*QØ3ÛßÎ:‚0X›ªTTϯ’P×|„Ƹü<µßså\µ}œ–¾8ÜÀŸ‚¥!Ȧ¡ðضõ¡Ò`Û^ýñ§É²#ÿÐàEÂÿ(þ½€7F™H4à8G™p4lÂA|o}¿í.þÒ¿íû˜B/‚Cá«*pµë4ü >­!:Ë”Ü ƒù`5ð+ˆzEÀ_N]žrk•éÉè†x4ã€h ÃA¨Jb^­­»IØ ó\i–?;l×Àÿ È'8Ú&H:>¤Wºz¼SÇŠÿS£¿ÓÛWзɧiw1'¿ëp¿|‡t4´Â½IªÌù#¬­]*Σ;í30¢NåÁÄà/†¡R}§Bð€¶L\Ž{‚ôÌ-«Å—@Å2xl©.ûè”:@ÀR$Lûpï5Äýœ°ŽÅ€3åtüˆé¾ÁW!ÊD 0×'‚¦v›&æ_}Å/ºÛùIo[b™ZÑuOón¦špßûUW¼À!p TÛüH.+n¾»Ã•Píd¹‡­&èWCgí%K‡h½_‡¡à„ ‘Y¯ãóCèlÛS_ÿ‚g`/p§ÉK‚Ce;V„t[´È7ÁÊÐÔ]#âx©» “SÒ£h.8‹¾8/W¾g4¦#v­ðHæªÖmM¦¨†o÷¿˜¼céqOÁnx÷¤Š»•pð›¦&|8Ý<¥ëÿVêIMË(J8®ƒ´ê›.¸T€Êw”p5ì’ÜÖ@âTX4 —Âpø5 .H0¨‘`” Uéy0¡¶±{´ëG˜ëï’7s=øNvòä{vOšO<šä-Z-ß à&RÍ4k ÷†ã@Ã_-/ÉåqRFÃFÞ´*>PJð¬éñè°-õÖïf¬Ãs“½¢8f:CÀñ('Î=Àvç%ö'X ¯:Sé>çÉeª{”¸-ÊÄwuÔµ EÿYSµ~HxIxœV¡{y“O»è ’ÃÀáwsÖ!¸¶‡ åžiµ^ç&£K$²ÊÕ¹‘—Ã{¥Då°¯•âê¹ØÎÀ¯ fƒ‹á¨g$3´øÏÑÇ„,­p4'äþN¨m›ŒM~$¯ýgä5ùäÉ{À4Õòyh…àÈ{’Ô’u&®òOÀS¸áF¥~ÞÀöUKí»ÑFêׂkõušw‡zê7ïtÐHŸ+µs2<²m•67bߨï<Åþ8Ųê5àø^Æÿ"p}òŠèÉŽ¹9;k;×,ºžö¨Dç*;]“Ùü-}ø/¬ ÙÍŸ¨ä[«Þ\ç7·OÁ×õž~Ýô|FÖ*]ýv«µ»ù;Ý˵…è†Äö¼–ùK°ö[îßp<¦_õˆÏè8ÌN‡áÜtÂß’fT” Xε(ãW3Rý7œÂÛ“?×¥eqUÍ·‚+tŸÀä—h°uª9ž6}?x-hýšš¿l¬Gœ¥Íšë<Ž7ÈzÅ-ªšž*•·, :Z€e4+acW—•ä N‚£A§§+W¹: zz‹ð<àÛˆ àª73¢Ëñ—æbîg™3Ù¯|r±*xp¯u$×>˜û–f‘þËoá(¨UœŽg€W±‹úz=¡Œ„'ÀͶ±,Õ·(4ò¢*]—ŽÊk¥²6æjÙ›BZŒ3Ÿ/Š ÿ49:µŠÏ} +ÀŰ pnùñ/1€½¸ÍcæSL”¼5àVeüi '_¢ý—Wþ3&HWÜwŒºÓ«ƒÆ~Z˜­‹iSG.8 -Ö‘ðð4—7ŽWáï°;ÔkÍxdqÓ:Ö€ù¡Ñt<ÁžàFÞ¨hQ9&8×þj¹j®ÇàIØ Ô{=¢u6,«A3z|—ço€ƒÀ¾’Ø7w6-ÿÍà”®õënc[mçƒ0¶.ÝsIæv9çä=Ò.‚jNŽóÿe¾Ðù0Ùg½«$_1m®9‹ÑF%¾’®(~;äPï]1Gí ?'«›êZà2ûÖ€%Aqxªµå#Ò÷—ËôP‹¤Ë<œ*÷ƒ§r%^ŒùþS_3°: ‚ua}èµÈ2és^ š¨-àuÀ9:–³Ãáí²Íˆ2h Úœ@š8É5#,‚ù³¾O`mú$ÿY¤)í_õð9Ñx Ü G‚V ¡¥Ðº4"Ø?ÂÎ0c™zwhÊ¥]—hìµ÷Á@¨Eì·ý<tˆš™±Ö?n7¢©¡™ŽL[Áu e¬· š¼ÙÀqý h™ë-ƒG’“ü%\Ý]t&¾ƒjbow"-¹o{ºB¦¤’‡À~nößqtÜŸ€C@‡¤’Œwl|®’ø/ „÷+e xæl;újÿºóÍߪ¬V ‡{‚MÉPžV ÅàKÃ×BgâRwÚ_“u–¹”G`eXÖ„Î$ôuw2î+”8†ëh N£`Ey””ã@ŸóhËcK¢Öü“TE>¨˜Û(ã[“ït³úÃ䢭WaÚö=Ùü§AfS”JFÚÓk/è /++9aéW/¸Øe¬Y¬Ï6dÅöü ƒZ Ù2²÷nXK€ïNk­ÎT`;›­Ö?¼^*«‹FÖÄò¹!'͸zD]~G‚›ß`øêÛª#ò 쵞ƛÀMàt×´ŒÛ·hv:“É Ó²¼ ô¯m]®/ó“Ô…Š~ÌnÜF™@4𣠤Ý¥®×`“–%°prÚ×H§%¬FW}VÌë+ð>°,\×Cà´S÷w½_ñÌÑp ¸Éfå3"ŒovãM—kÔBže¦Ëï,ìÆrìn¨]%ö{~Ð^ õöß¶nlj5mþdKÄù¤ƒçÜU¢³æüÍöÑÍØa}¸üj«ñÍW9˜_íå½ÿ-¼vw®Õ!6ïï°„¥XÇãU³ÎCª³èèd¸¹ª&ë: ²ò!=›æ½ÏÍËËù7`ùˆKý˜/õpoÂú‚u]I_2<ËÀÌ ïÉæ¯ìJZ›(ˆ~4´£»4ã¼çx;7+¶ítº\Î({’¿v•ÄÕè¦â‰ò:Ø\Ÿƒbz-¢Ö©Èæ×p¯UÈSìóe`ÿjy³ð%ùlC¶}D5,:êxKè¬ Ök›«É5‹–Ú2/]kyÐü:c˲›jgÏ;G6†Â[Ðêï†<ár¢ój;þ öMò”1üTãÂâð6Rì¼<´ÛÈÃ5>£O&.³oJ×™¸:¼³St4è3™Þ Òâ°j*–Oÿ¯‚eå1¼ž%²/˜æ(•ÿ0W§Ò»PMtJ.€ýK™lÛsÀõä_ÿe×Ù½:¶ ~uò2TÛT§$ý$8´ÆÍŠã5´¤YW*{:´¤ç‚í®Wœ΋ËáypnµB#ÇÔùäü©$AÁ£âK žóûöBqz5SܯxØá¾¸TH-K±‘úœŠAt:\Žú¼KÁ:p>Ü §§{Ûq; —Ð$]Vˆ«÷jù:ýÀ©’ÓÔÇ ðkø¼•dEúÂ¥ ‹q¥ÝíÛó7%×/ú —’âeQT«~]7CNe ¹±W¡ý¡Ã9ïTÛpìÖ ƒo¹ºÞZ ­—÷zÐl…›GvÄŸ6ß$¸YXÎõ0ü ´JyŠuN »€%¼µ 8ޏ¡ØŽE@k—·¨gë_æÛ•7¦S`K˜=›Øà½õÌî2·Á{¢1þx úƒmnD¬Ó£Ý™°4,ßB^bùêg#è¬OÖi~¼ç‚ótÐqhÆÉr¬¨ûœkùG+è-ùÙ?QˆÍSõC@åXq»LΦ¦A_þq˜\³ÁÞÐ ýÜ™Â÷‚eS•„4£vM…SJ¿+Æm‡œHH^ŠùWMÑX^t°´ôþ[JŠ—.Ö@£æ¤‹›9QV§ýpMœr?›ÿ•3°ùÿ›¢‘ªE<ø.°q£þ¶­A—ûÏps‚+6-¶ÒÕ¨hel±†Cš|Wk™yK¨ÓÙW«>ònC(¯W¡+W‚ýwœtòŽõ]I¯'Áͱ™6Z§ïu7…¿‚c§ÌLaƒá °oÖWMLÿÂVð¼ óÖ_ýû&lw.Ílþ6Áæ¹ì’Ëh?è¬KdÉU¬Oð} ü®§Ã¿ Uú¹:ÜŸ©$¤} ü6‚ÕÀ4Ûœï†#J‘úzöEž·Óðüp‚ú3Qƃš1)㡹U•Îýƒžl+ìïÁí?§±>¦'à èLÌ£ëíI>»awö¬éž¢\žª¶ ›À† õÐø—`òºÖèh˜<™{ô ­Û·#\ žôˉ³Ó|yžTÓõ¨ç5ÀÓup‚Òé­ Û§¥ÁóÏePÉEÚg ‡8—ƒû!¯Õ?e ë‚í¬g¼<úüÎàÑÐy™ž›ÜÖ"mÓ±ùœÀ· ¥º6ÍJ(c; r¨\ŽãC\’ªösð\p+¸ñÚ¾G@Én¼ÅØæ>·çqý¹J² WÀPø9L$Ü¿ÉÝO!L¹M †ÌîùL Ù‹wñ³åãÑòŠºaëœÁ·ÇÛ²2ßu…(µlþÅœÅWänJÍ, ëë3A/ðøðøv`wð ƒ–Cf-ŒÔ ÇÓT+¬ Åvˆmû¢ãî‡Wˆò”¸ü“r‹±C`˜¬L©¦;ÍŒC™b“(˶oßÀSIÌ?Ü ­ÛM2/Ù˜‚î‡÷s*Ð~8wjup³Õú¼œî:înÓ@­‚kçÕ]Ìí…j}¦Î|.‡Oê|¦™ìªÃa_Ü€õÛ§}#—­~–yŽó‰Ó(oñEà‚:é}àX°å¦ò¼ÄŸ@õ ؇U‹”(]¨è´FÙËï‚=bá¶?{24ò½¦'BG§ÚYoÛÝØ÷O[ÁÅEØö°9Øf7žV‹ÖÍ%ÿ|…Š´&J«Í‚}W'@KÄú‡Ã¢0'´B´Ú;Ã0Ò½sà8Ø™CÍX˜š•Ê´-;îð/ÐwvZY•€€:ü1X¾Ïè¼ÜÏ_æx‰aœŽÿÝÕ×ùÏxjˆ’Õ@ßl|¼oLëÿ޳ÜñÌë•™ÅÿB!®àFŒ·Ðc€+hqh•hÀ­KÃ{h=–„ÉÁǯ Lû Z!3R¨uh|œž‘Z1@{ƒmhµ¨‡ËaeX´LÂXXZé„X×40 t@6ƒuáxÒzá6±¿çç& SPLIæsá§àލ#“—LMAî€NØ~¥pz-¡³¶™Ùø6EEêG¶P,ÞjN7×#!O¹™Âž7ò}!ÔGðò*1‚Ï”““‰üTáý¥ ÕÊ+e){ Ïý–Ô_Àšes}òë¿ïgÃÔ1<ê0 WÈKT2 -û¢ÒWÙLŽÒ ü¨ev×"ÝßÎßVhó0ôÏãùhtóüŠ€F¶•âÆªáþ´TÉ\×a*Øv€™ èä)Ö{"hͦMì̼Â7Ðâæ¢3r7¸ñ(ö·+œMã ®µÜ[°¦µBì¯cÍq+Ù)ê±ZnOꃦ:ÏÍŸâ’ò–çº,¿†×!õ·Íʦ¼yÆ8ÛÓb ÃàF8;\šC}¡Ù.µû`0¸ù+¡¾âݸŸ½¹]†Ýqw!#ÉÿG@{¤V­<’+Jxî'äx¢b®ïBþ‰:6Ûâ ž†53qú£÷yÆå9h‡ôcÜFÉSõ,ù<ëÔÊš|%¾Éæ04ùRLÙ—.¡{nfØFÅgÂPh¦¯I\jŸ€›ü¼Ð úÁ©p!pÊJ6¥{¹N®Öû ƒä”²®?C£²>#ë(Àir?¼‹C˜ÊK BZì×Èb„nßÀ¥EÈÄ·¨iM±SõæŒÈÂh×6}á ÖÀç!ŽŽ›X5y”™-Ã:ÜðßZ«bbþ®­È;°üN_nXö»‘õÏYþÐb¤¥«—¿–øh8Â+qûôQîjº› z¨†}ܵ» Ü Zî=`g:g–ݨŽy´¢øàpèôt6†êÀ1cÎm®STUqžûÁáÀ8µÁ”LJè¾Û¨ü`žU•Ú §¹C[¨†ßƒË·š¸¤{ƒuÜo£>›&À©YhB¦†«`ox”ÕaFpʧÅv íþ1—Ë J‹4àü‹Ò¸æ^ŽŸ©=ÎËr÷Š_0›8À”8ΓSqw)è:{ ÒÈS´®Æ‹àOà3ü ÜtÜ ³b›´(ÊËp¸º-kÐ-Ó‚b›ki·3ñLð˜áûUëÙ.7¥V‰íÖB¥EKlߎ„a#ø*‰ú¸œÕÄ>ž Õ,ö§¤ûfOð7ZÂáp+خЖ¥{ÄSjÕq1wùOë™ö‡AÐÜtˉý¼‚ãÔUbu™³³ÓÎÇö3õ؇sP]Kˆ#XVBº›èàðùl3ò[^|A×™„úÍ·è<øìœPlOæþ ™H—YKNMäجô€z Ù²ô1û˜¢{êjTåf‹’“Th”Æ40ëüÐõfæ¨ö¿?Æó/˜jÙðj©Ó©îf¨u¹òÞ5¦—pWŒsuÿ>„j3d2ÒÃ`Ÿu$,Ç¥m7nÀKêx…î¦RicÑ*ÞûÁP˜Ö†JùIªIl‹I¶/Þ¿ƒ¬à êÈÝ:`óÃwPNìï–àq¦3q ³íÈ>cÝ÷ÃhÐ!²ý¶Egå¼Rø®¶Ç´% ç½tgu¥¬8¦ÀzÐ ²}¶ÜÇáMp÷³Î®–Oð˜#gÙVû«x á$¢õV§:ðE’Sñî5Ty"yØÐÿjòWËê· ¡ûµ {xnOžsÚ;%/%¤ï~øÒíó²0à‡YjŠù-¹æ‚áJxΆP>ÁD^"ŠóDÛ§Åß^j­BwK9⥠Ô2_š)R|6™€ ó”îÁDê=k¯Ûúð¡k«Ûš§„ ù/ú.ä5bn&ÏÁ󠃡1U¼¾·À!ðÔ**B‹ò| Öñ4¼P »Yln.:’Þ¬ÜHu<Ö-Ãð1Ô*ꪜ¸ù[^¶/Z›žà1ȶ±?£aAÐÒÙ¿Jâ3–——ÌDA›BÖñ³ Ž‘ã†ULæÃ«\ÿÆÏ Ç‚zUBžâ]çŸÎ/õtlÓCZ£‹a;˜òì3Åu*ôqÞÃ8ý¿ÅOGìoÛ!¶ß±ôÚm UžDuóÁÖPNF¹ ÁQÏ–Ë_OÜCd>®¯ç¡R^—§fe_Øœ:µˆÓ}Qx¥–Ì™<¡ßgÿGp*? N+—|H'˜È¢ú2¢˜“óðGU_n©“ðEs¥v „‰÷霕UÞ L~Ñ¢+·X¦+eWøÃN°)ËÓž|÷‡ô)Oãé‰×•™6°Üv*n˜²H*çB„¿5gy:2[”Â}¸ž¡OnÔÖ¯ó heÒbS"+DðšÛtX~Z,Çü= [¦÷>gš&gg¸êÝPy¤! }·¿éytŒEì-ñš ~>,ûeÞ›À Ý4Ç!ÛO¢ÆÓ}“ññ8±ßßXî[0XnWŠmã SÛ›lþê%=om‡}4ó,ÝÏt˜¤<Å*•EàÉ$4î‡U›çð2Øì áÙpßèuU\»Á‡—.=7œë`›4 NÐv‚?mß`8öþAjõˆÐo—ÕN° pÒO¦ìï¹iéC³lÓLü!œ€1 û‘éôn\Žc”Ú5àšÍÇtîQSBOøô*>¦E0W±FOaŸAX9ÍV`9aSÖ N‹uÚ97FÄçƒhñÒVo+î·óŒ¬êDæãóT8°x›´Ëgw!ˆ÷êfpg¸ ö·Z_²IxΫí4ýR°íC!«/¢rÇ{lÒN·ãlpŽ¡(z£W€íVï¾EP_öAR‡F éÅ»q?íßÑ0´ðêÏüZ‹áZ¨ä Ô2aóŸ|K¾?Ÿ†lý ’ÃÐfÓCšÏ´H6¢ÜÛà1X¡T‡SÎaQmÁŸ+%å~y‘]Jn°dý¹%zquº}Õd{·µÀ3C½28”nþêè)pÚ—’W`Áâƒå²Ä¸4 Þ£Ô®¡¯òÕ•{Œ‡Imá›§óѪ͟¢ÑpÍ ï¯¹›1dZ¤p!hÜ?„¬x²; ~'BžýӃܛðuúó&a•¬€õkE5æŠ:ÐÊ–ÛäMwS y½ÏS>¡°KaìlFí&رïnr鮳ŠÔ¥Ï)î:A¿nü{BÐcº hƒ8.‹ƒe¸¸Ñï ¿‡ùacp‡qδJÏ=Ž e;¢kákžÒœy”¾&Ó)´§?N!-D–ËÒ:¹ªÒÕ*ä¹øµA?k؆ÏXe¶Då&NNÈÉK™ôÖ[í|½ô}ñE M¥¶/Lš¸Ó¦Q±Nu´2,§Â~­sâN+þüã5‚§@”&5Õq“ÅMÒϸ"?Q»“¿{63ÝÔþrAþà›”®l«å}*ИkU‚¯·NÛù ܇ÂGPi¸¸}6d‚-“÷à^¸0øÉ¿ ›––Þp¥6“”«X—ÞpôÞwá/0êÙ˜É^·XßeàŽÃ\ëpœÖ-ZY€ ;Ç÷ ¢~çó*^“›ÀãÞ›°#| ]!¾…rÎÛ.wµ»ޱ¥)@ÛœÎOfr‡„¶‡ˆJ÷Ùø¿“«]_Ê=n;æƒàXX °]&.U§Éæ9ÕèÆ~Ø_Bº)Ûï0…BØ{Ãáž`CÂÐö+À²‚\K`déæS’0…mçßê„êK9⥠„±¬ç™î–7™`x¸O>Žc¿½ÿÞ€{ó¡!ÕM6²•›“n90ùÂ-m´‰ªY\Å‚':Û]M´tntºøt~œÉmKä3J½ ö€°5hø×õÛÕ’u¬ß ñ¸Ž­V+WÑ;”+xzoÔñãш6;&'κÜYƒèäŒ2wÃVö—â;Äc¡»­:ävÞ¼ÎüüŠ>ìkšbÙ{ãÓq†Ý­C|HóZƒœCž´ŠÒLËÍ8®Õ9XU«Õ6‚:þgƒË&/¹š‚ü:à=pÊgå¯D¨ûšG?Ÿ£¨ËaUØf‡Ìé°Õ\‰:·/þ/­Ž JÕZu”:5à’RYÉÄšýþœ{íå3°dÈ¿ ~ ËﻫÃÀSµ35oñh1 <nÊõІ|8¬éïä¹-+ÎŒ¹AOǾµryY6F=ÑßQ\µ^ƹò}¯ú2,]¹ùP]Yq^v‚á2xZeÝ}óàXLÖ—ØÞ¯2…y¿n*Î1pÞî*~õág;(®¢¸ŽzÈ ëùå׌ŗ[á(>殪“ª˜/½„õg\:-ÜûŒý²J:O1¦ê§þi5@â^ðKX\BoA«¥<aùØÝáÁð.¨·[€aÏúªmÛGÿUÑÿ·QÐ€Ë Je 87G~Âæïä÷Æ=©ãµ¨.±ú ø9üÞ†Vˆ'7ëkDtá;V[gåh»b†LO=[©`?­W±;G­@'¡«%mBÝžLµ€Ç¾ÐZ% PðÌðŸVU)×M5 Ç;Ž‚ÙÀù׿í"¬Ë¹ÀÛŸ™x÷;ÿ”ø^Ì+ðÈÛ˜Ï÷ØNçˆíržŠ÷åÂåÒÌò‡0QyI úŒ‹×jµ„AÔ—؈iá h;l†³f±¾5ÁW::­õf=n¢W:ÍÊD †ë`:'Ørqc_n„r+Å£Öö s¢å-—‡è¦Eu¥8.Zà]A½sâNpÞo õÌ#²7,¶c,§èÃøÅ—GLõ@Ü¢¼iŸ“AÊ‹gêݼ^%8^%f¸–{²å!6¿%izhÊHî߆VIO Fm¹‹js´N‰a48nÒ§À!P‹XÆð{°\˰ì?‚¢Þ°½ÉÿþaWó—¦Ý‹—KqÕ5 ž£”Ñ@_Îót6x‹´ÿƒßÁO`ž…øp£rÚ~ Cø84–ž¸=-jšWÈæà;1T«`,“¯ nçzpšªYÌë«÷ç¡3Åò/†ƒàKPY1CŸXœ£¹^_@W‰¡:,'Îá6¸‚<Å:zÁ›`¸Õ¢¾µîçÇ«ŽYâ—#îIÈcNSL5ñõ뜽svºî8ØÿÞßEú¾8Ä×1ž0Þ9*¶5ì¶!®³«ÏHÈî‰ÊClÞÁàuØ®‚àóŸ‡XŽ'qU× Q-A® °œQŠÀ^&çM^%yŽ}ʰ%, •ú¾0iÃa;ØþY!­‡ñl)-ÝÄlöxŸÑ€Ó=ʸH&P~vu'ñvÁêð ¼½£o` p£×Ø(>É«Éä—8Ûr}\åÂ,04#nüÖ=-TZ5éòÍ£%Ð5? >„zÄ>n —C¥M°žòB^Ûe.5_“x$ð‹UÛ3Ô¢²µT÷@ë> nuž×ÊÒñ[†ƒuµRÔ§í¾t6³óUGL'ò %oƒV u·£Ë?êP1ÛÔƒ¨ÚÙíÄÿ]ÿ‹ë…´m¤íw-ÚÛæUŒKß§ÓOcšò„´blߣØÄà"x~ »@H'Ø”„rÂÕúZ% Sð3 zwû5|¡$]ÿVDj õ“Íë42®š¬Nboxþ 7CZ,?Ôwf1Òª Ý/ÆÆÏŠpšGù^N'ÐL¶u–"ð3ø ,—ôãÃ+ˆ'X7e7&ŸR,ÁªžÃ°*øê` 8ëg„FÅS²§å£¡–“¦íú°Bþµº}Ôðú:<ô‘`Ãb³ɯ`QÀ€×$ÿ¾°1h9-'6QLSâ˜i\QÛç—¨Ç!¯1(×.*õyl óãžûi[³—@Ëß"i³¯¬—CtBlGÀñ6Ì\Ð ðz2yu•tÞn;m›vL {MÒÒq!lZH'˜—X¤2œƒÀi£ºÝó’(h0„úò*7[ŽC°7ô‡Ïa ¸Q±þÍA[º¸ì5IõÈ=d^Ά¿Á!ˆåÛËÆo=Ë®¥(.Q:Ó€Ó=Ê÷p.=;š7SËØœQKÂKbÓw$6zÎø‹a{˜ÒbInØ €³ÿðl[I—Åm§¢á³¼—¡Ò/cB!–í+ŒÞ`g|¶ }܇³}l¤< ÝàP˜t ²¬Ö”ÙîÍ?ƒ@K:¡È·4dMpÒ µ8idëTt(-SO4í€vú`lçyðk8 æ7úrâ¼þ)¼ o—ËCs·ýzþ4­u8oÖÂVcXÓV§Á}8ÝӼϦ¬šóÈuà½áô½q!>„½*!><Ò‹©?mž®Å»êŸ+¼6øBÅîZezÊ Ï„ërž7-¼†ö®Kûí€ýLþf×k\MwÓV…žP¯hò…Åà\Ø” ŸÐ†UŠÑç1\?/ãggpjGù^7±·.®= Ö€ŸÀ'óÉ ¤ÄhæÿA˜…©ä$hqÃÞþ Îàm#W×wòdON–Wsµ¬jò»¤? ëAX)ë–ÐGJ}¬µPgÛ™°;¨·JíúŒ´«`;èYñ9(O«ÇC¥ÍФ.û(í7Ülûìï4àX^žâ˜Þ Ã0pŽW’qSõd®cÒìœH Ì|X?kjf7xÅ{ñ>\CØ{…ûvøbšô¾¡‹6ßzÏ{€ ê±k;’€³:+̶äµô(®iÓò!¸ß¾r=^ŸwSkƒÎäk2ôO`åòkœG@O°ÎfÅ>ZßëÐY+ÕåÆr7ôËêLìã” ©$s’°xÄø/˜B‘±4Dë»'8ÖÕúAr§â8.¯B£c­D}ýFú,,Áªâ[uî< n®yʼๅ¡u=dE=Šs2 qþNÀ¶ãlÄ8F‡I Ϩ7Ûêš1œ½OÇ÷!œ¾’\NôÓ³6"6õK¸ f„Ka84"sóÐÈÃtVÿ}dÐçµÍý/§ÖaWý÷RÖ¦ ¨£¥ÀsNZ¶áf0#ÎÐ2‹¢t¦—@w—d­ödn-Ž&<˜:É.V+¤$ôúÌ(gt¹U­Sp ÕNä$'b¦a-¸†á A5M+¢%¨$®¨]àrÀÐ#Þk=^… ±nV\m‡Ã PîD^­|û1=ÜêjCÈ£M“œ¬Êu<ZžzÛÇ#-ÇÙþ……Á±ur¹©U[’Ë 'âämÇ‘\-§Yq®þž‡= l–kÙ?Áhöx—®½Í|?ýXý©§,é¼é4îÃï6ax?Ä·I%i7¿¢Õëp_éòd¯<š·X…2'h"Tó¥p4ÜõÈædvÚé‹¶Jî¡`Ûv¨jÛ<h¢„Éáø(aŠwõ}jgåß°?¤Ë?ª4 Ný%¨µx?;4à”ïÎâÄpÎÜÅ"ë¿&À½J¹€”íB[C¥Ó‘%˜¶6¸BëѨá ¶Ž9`( gºFz2('nnöét{¢1Ö©Ø tZòûèkìÕàà}­¢>ìOHdîš— Ã])êk¸ÔA=m${ËäcJ^|§ë¸^“êûã&íU'¢Ñpgp®î ¶±^±îN¿ aJhVœ¿ÌùÿÎëk­½›zÀ4)môIØ{%VÊï×{¡§åX«²žÎz±ÉÉó^½±ÿ’‡¸ìÕ<ðL¸'©b·†Ëan¸^%t½xWùSß}Ö:òW.©˜’®w9¢ª¤m¶Ñ ?¤k–87%Àš\çƒ=A•5*:E‡Â¾àRwœƒ@±îPþí„™Ãp@´à¡Y£¤5àTî®â\qb<ò4öf-ÛÂ^  <æÇOÀUTMÔbOx ¬–?›¦¡ín’aØ F;;…ç!N«ð8™žÀá01ꡜrWVR²‰¿ÍÕÕ]‹¸B/…eaUÀ·L£_€ºS²:+Ævý§m[¶‡à˜ê•oy@ëw8ˆsõAp ×ßR4*¶gyp¡LÝh!©çzf>í¼ÉŽ÷Y|4ÄVJ÷០öGO—àL|Ænp§ãò{UÔ‡ºðêÚõÂÞ‡¸p%*‰ËÞŸ³XE]œ{€S'¤…nUVþIìÂò—ÍTG¤å¬nèwÂ!`Û‚¤ëYƒHÍ…yA?0}$4*½yðÐ\Úw˾|ë`ÙAš‚ûàœ†w%‚QÊhÀ©Þ]Źr ›ÿJN¢sà§ðsЮÝíȇîs-biÎÀf„Ùšü½€9¸zªWÂV qL‹FK4jŠ#i£W^VÁ\ÄòVƒ×à­K|¢”O‹n¹ØÆ à:Øtœ&qRÍŽßæÐˆøö@ç®Ñ¹æ§@')9¢#²%8W͈}zoŒ:+ÇvW"Ôoºs¦ÜÃp*Nd­¼ï8„4óV\?b$„Óׇäqò…{¯-U}7„o#÷&lS«‰K`Tµ u¤yª¶>—×›àt®æÇ:ŒAðû· ¬º×€fd[v軦ñ}˜%G°Ð.†\Ÿafˆ’Ñ€SºÛ 6az'Ï£0<\9Aå-g'‡A°ªè=¼£ªæª/Ñ•3\q¾ÈÚl¬õ8rÛÁà©w4¼ nÒv UâŠîlÖh©t´A£ÛˆÔRW¹r?%RíÁ×Ј¨Ç~ð¨óDïÏ÷‹ÏÁ…â¤Ü×Ömý¤g·Ň…¡ÑÕ–-Ür\½ŸÁ5à ßÕ8„;`1x¬w hdEñXM¢a¶¾g ÒÌ™š4Û£µ8<­6"ê}x *ÕU©\õf½'Áéàf›µDÕ$n֟טZ©c¤e½΀[áð½fg2<êüji“yt‚®­ñ #§ØçÅÓàø×+Ž ã Xõï÷ä‡|éug8}Ÿ-?¤‡«éé0·–é_|#ë¶8Ö9®æ ÎÁDë0Þ^m[6Î{%èß+qÏrYÓø.’m©Ç. WÀc•ÐÄZ§¿åqª¾¬ú†B:ÛšdGr9ýÛcžØµ¹;ç¥Ö²CŸl—¦(ˆËBŸú·¥ËÛ˜öíS3¸V))^JºìV ™™õ‚íÝ;Øþsòzï÷p5 Ä_¾%£T³Ppòc> m=ÏÕ\Ý$˜ÍÉj4¬ñý Ì®2{UÜW§¸Ê6†›À%ÔE0iÛ?¸¾ ®ìàQlHÞá©[aO°ŸõŠmóèr?< ‡€Ö¦¨c'ˆ¯¹g‡¼¥º™kÉޅ߃“ñk('öéuÛ@g–]+è|ì:ÁÚÌUìÇà˜íõ蘼«Í?â ÿS;·«I˜o^í[¸Ï>⽆px„û½¨óMž¿™vû—ÇùãAæ·l%8 ^C8¤‡+IýYóÇsí 5ïfæmB¬Þæªü¸”fX_|^ØÁ› òïOúXè [Á¢Ð¨„2ƒJÃ}(ïßΧûM'ª¢Œ$eo¸-“Ãþ_ WƒÃõ# þöó¹ìZôgn$* pÏëN’ÌÃÏØü7¡×+0!œ(Ú['I"ä¸ÜÙèû5WA=â&妫1ü¬-o±mâ†d£?:•¬ng¼âJZ€ùÛó%ØÆFE ¿ƒ£á P,û5x¶7šfûo»Ý€u ~V³aUí#8ÞE'iAX t¶ßcn åæŸ}Ò"_:™•óÙç=á`˜ZµùStâìmÄu3Ð*³™WÛ7-8‡ä÷78“S;ÖÆ§%;‡²éá¾\>ãLÃdãþÔõ2×EYü/Ì@tÙá5ÉhÛ‚¸®|8Ä©ûR™IÒ§å>Qq¨Ïk‹%éu¸$ÇÀHXfƒ{!4Å©¿C .eŲ€ÕaÐ|4+¡}SÐ6pU¦Àå¹wº0 Éoxï̤W»‡ÄåàAX-•qcÂó‚&üŸ¥ø§­_Ã^n,EwûK˜ÎÝE®‡‘oñql .'©Š˜2ÇÅà^¯hÌ}v{àûÆ–Š›¸>Î.…Oâ:¸Ä®ÓÃ&°u‰þ\u¹5´S¤ð¾VÑ./ÃT©‡ÔÛ0ªO%×à×ÔÞþŽË}n;·ãUÔ©Ç·EÀ1Ô™Óps/碛_ÃJ23 [}ž ¾…V‹kæ Ø œ{Õ„M7ù+ÌÍeptNœºBfçU %ç}VÒyÒaò©žŸ2OŸÇ ™‘úÛœ³ê4äójœ¸ÎÒWn“¸`=½†pÈgž.–Ù©op³u~›£¸ÊùŠvSÑt™WßÒ tÈSÜŒÿS¡Àe‰_ †*ä)̘Ó.+êá"ÐÆ+KÁ]I(9mP ÆÏ0m»‹&îÁ›­è­ž¦“ÍI XøT¸9„•ad­â3>k_@X}["–ÿ%Xßñp xªÒ˜Ú޵a\Qâ®Á”ÂSçÿV e夯ÿ#^GGCßì÷®p&X΄(al<]ÿ¶7Å iØF­Ú&p3üõĹu6ìê?+Zúß‚y,SºJt°¶€Ë ÜŽCt¢ó³¸€óx9Q®åÆ¥\¾—¾ZGZÒi!Ò¹öóªdó«{ûâÕv…µ`8´3Ä5N>ï»Xô½–§ºM} z‚»Ë6ˆNÝ›.…r­ë)7UÓu­Áí´Í索„ í$x³Lu°.ðê?§æØ¼øódÏ~Ý^Ê/&U¥ bò¯ó ½; =ǰ®Ý3µ»ïžË‡+£Qùœ/€ÝÁÕ Á\ÅU2œÆ¯ Â?aEpÅ}[‚K"nè{CvÔuv†)!-órãªü&IØr—žð"ØÏkàC°]y‰}Pò,Óñ٠㸚¦Ó·ué~|ôÉWi¶ãÿ l±wmnû1*ßWÕä÷WúÉ)¼˜kܱ° ûú®Ùya¼qÕÒIîÈC^³»1 aîÿÇöÛ® Xo¨ÛŒ†M W‚IØ+ñVû]:¿Ï(¡=Å».ût È àÙ`,LÊ_á)8Þ…t³¹Í]´³øzÉ?Ì9§Jéû“&KÃà”¯&ªö~PÕ†%¨`â#ïÉõFØ v„µY þ áQ㺸'uI¸/UW§§ ‚“ä#°ó&Ê ðòb|hHÃ*!X·XØðSxú‚æ-®Ø»ÁN¹qÛî…áaøèÄØ–´xïÆ‘”³ ÝNóŽ€[!«ó½ Ö{$¸¢?†l}D5%3ñ´Î‰jæ¦Júþá õp ¸¹jô”®l?臺ÔCìJ±:+³@?xÜìg„Íá°ý[ÀÕà|_A_p.âƒeÀ3D îpŸ÷uN t9{ºŸ£JáªJÓ¹ì ý ’„6NÏ]¿Éd´¬³A§â5ø-¬Áhâ`Ü„ócö ¡ÛJÐß$­ÇÞÉÏ¿®¥—}Á‰å§÷1lQagÛª`b³ò,<Û€HÞ29º9Ï+” ·#n·ÁAÐl½3ëÉŠq÷Àë€ÁL¬È1\­¯ÜJtCb=×°TC%TÈÙïÆþ\Öw,ø&ãPÔÁ›àB+â v™8Qmç}ð9¨û½a7à ÐzÀJPÎÑ#ºËDKÿ$ØVç¢÷7W~ îwÿ[Ü[C”µFÙ{ùháÓ’}&܇k6oˆ÷ wðÖâhøNïàiˆ³ü`(|Ö|Ú1­t½•¹ÿá#Ìk|*­#Lt«ÅjC—B]¿$`35 #J‘;p½¼îÊË*s:Ô²œ]jæ½4§åúFtG¼ý6O6_¸?›4Ï:ÛÀ~ð碭[%ؽ$;W&µÞ'Ë·ŸGÏ^=a#µëâz =q ¿uVä%κ+`m˜'¯BSåèF»ÑïéQœûÍáfø “Æmn¢ò‡Ñ°ìKÂ!à*ËC7º%ò(°BÖ3Ü\ƒ›ëO@«©LÛÃ…Àæ»8WÜàÕi51]«øØ–ð!Lágà\í&8^E½mxßɱËq=诿¸oÿÔ½¢*‰}JÏñt>ŸS/Ù>§ó‡p¸¦Ÿq)Ý ¬Ûa&â¶Ó©VlgÈëÕúÄúÍϼøcs$ŽÃ8i¦Ìߢ–àÇ„ŸÍ‚Ód-¸ P}rn¸ë`C÷¶L¾¥äáß5Ö`?\r}A;]­“~¸ÑW’?‘àyb5˜µXÜ)õ3º¥xæ™”ÅùòÉ?ø8œø¾u¢&6õ[ °§3ä!kçdÐqUhP¬ÇpO ƒ­áRðDÞ ÆÏ­î.€§á ØìûÄ"öa–Z¡gé>l.© ‚”Ú¤Vƒ?-Å#j+vÝÚ.­Þ™™ç»Â¢gªüÁ­ç/À¶è”*Äùzýñ´õ)×Ö0‡¼†pv|δð|ÈW.Žl‰„¼Þ„|Ž•ñЇ:ö¢›ðvk®}íƒéÖmŸ íHǤ§ÓŒSB=^s§l›—î’Ó¡GHÌ\u‚™³)ÛÂ/!§fQRu±­ïWÏ2Nª>¤âæ?¼ãM1]?¾šè}.÷PÛ•ü#ÔŠÿ÷w­f·“ôœ;ÿ÷8¿áé%܉:Œoùz±ZÚ#™s7åýaK¸Ò›4·M‰8®gsVtbtu‡=ÁU×jÑþFÁ.0z'Öf¬‹Ï†Á"ØrñÕùQ°/°$gƒ`ÐÃF@t"öy$„ô$²ô¡•=½”ÖYÿuÚîe!+޵å¿:soÁNÀœMt«ÙºNŸ7íVÿ+€ukíæÅ#­Ï×$SÎKSÞï`0è°>Î&Äz›Ê6{_IB›ÒúSçJ9›ÏøÇûPÁÉÆ§ïKaÿ×ÁÆ1[œÝô6t½@{Ë·Ló…6XŸáJi!oº]d¯G\FÏ€ÓAZ73Å)kµJh¶Ï8}Äéñ h+g€VÊÂþ",Rg%O’ß×÷‡Ãâež]€¸•àjðüSNv%rèšû àmºßŠ—´=Á‹siR•ÙÖåòóéÝ Ð.†‰Ö©×›À_X·ë6ç-ŸSààÊZ\ÅÍŠ«ÖÍE#ôU•ÂÜ ƒÁ*P… {M’6|†m§ÿ€/üW¦›R½b›û°/ö¹+DËp| C`pã|>†ÐÛç»ÔpO°CœOoB8ª™7-é{Ÿ·ÜK\•nŒÆŸŽå#`º–‹•èÚy`^ç•q‚Ïø¬úײ+>cŸƒ@gÔph[h¸’Ôѧ®!­Ò}ˆw‘ÙŽKaCضÿzË‘XóÅm{ØWÂóép:.èÍçB|úÒ3,!=›âÉÒ±>JÏù£DßR<Ç.»ÆãŒE¿ÐÞ`@|Îü`W“åhšúeºqéö†v˜/#éæšôx>…»a pø¼OKö¹tZ¥°MS|Ö:V†µ`Ø”FÊ->YþÓòîë6\Oùžðw„Ýa3°Ùç—"Î¥¢ŽÔUVÌ?¶„çÕ~zñ¨ä#§@·’0&µNÏŒgwßü˜=mç±0\¿®E±ãÓñуñÅMÌ‚J†œ| ‹³m6ø5¸’ß…f5®Ñ¿7öJN…õø¾ìfØœÞÍÖMãˆ:»~3¤Rì·ÞÕõðØï#@«Uo,w8ÀVˆíu¢„¶MCø$Ðë ÷B°¸'—â¹$íù=×´scYAÂ3Þ§ãCz:ÎðL`™ÉÿÒð² ÷:l‹‰í²­î:‹ÂàO‹}ðyóýnó? :6¶Ûùc½>ë¢ô®Æ®õ>ä :µud„{mËÏècâUQ²õe3Z®ò…k1ö‡:O§w6¬Bg`vw°JÐi0"¤ýc²ó|ÖæÖíCâXI§ã Wmˆ÷1ý³ÅÀ“þì0‚ø8U7$Nô”Mr7Oã°ì­s)ôC8¬ÁÂOã¹Àæ]£T9šÆ—Ëć,AwG¡f ÌUÛAE•ªÖ*£Cê$$Ρ YöiÖçØã *µt2®®Ù€¶éP8é@Ú’Z5äVø*üö‡/¡Q±s†p|ÕÄN»Êô€.O¶yޏÎÈ™`{æ¬LAÄ{à†e¾KA§Ag¤VÑZ±2“×Çß¼D]N^ »CЧ×ÛÁö¯{°"˜ÿ}P†¿Åpˆ«to|Z|Æ>Ù™ÔÍú°i)ü3®î:zî A|Ö¹`Û?õ$;ÆÎëq.>>süf…'à°nŸ ýå„8’’´r×tœõ(XÖ¤NÛí°ÍÓ±©QÞsêÖûz%”~.]N6Ý4ã‚îBŸ|¾³pªßsÖîÐi*ÊkS§¥çÝDVDÿOÏHÀzÒpûƒ{ÛdžT»gæv&Ð_¾l²Cþp ä)6Ûª%­‚tÿàæqpéiBèvÕü$×-N=§]£r-þŽÉð÷š¤gâËݺ \Þ%]ÜMp]*"8iKž&uBÐT2pØÅ±ÐlM"F¦1ÒûðmO>ýV‰ ½7Œ‚fµí*Ü΂°Y¬(nZ•a{Ð Ðç%öMQ™åÄ EË6 Wå° 4ãñxÃ6\þä ÒÚÍöÅë‚ ®ÜX? þÓà{Ò;Á¸ aþ„k6>Ü{MçñDn™¿0y´üÎÛ©T/ÇU ú”³¢é1qœÜM”å‹—äe§qcÁ¼çB0¯»qé2B¸Ú5¤¥û–;=ÝCïÉæÏmR~H÷¾ sN=±ÞPŽéÙ4ãBó¥ÛYcØ¡º™xÖOQ7ºOþF€õ”ÊÌ«÷–Ÿ®?´7¤‡{òÃú<¢”Ý¥ê‹ÅeÞJ±‰Nñ÷«T² i+Â^0?| .…<åF ;4OÈ–<ô"¸Ã²œ¹à?j—ÙÕ0'°ŒÖaI #¸-t IOÕI¡ÃÎíïnfþ›À¥¹öÒ¢-¿®Ý› i«E-ï VÚ¬ q›ÁNEh½D “UQ-Ûà†{h·õRK{|¾–|dG|Æ:ì·ìM{€ÖÃrÝ`Mï æÑ*aè ‡6z-´z·Lãì‡qÂ^!>{¯Sô.èõ…#Á6xlQG¡7gÉ–ʳí_”ò§Ûҳυû×Eàœ¹Kå

Œ>ç*¥'ó¬Ex;!Ih—*¾‡?‚KéÐŒ0%ÑÿMìq龞 *M6p—©°2„6¯CxôJâóöËé­Y¼˜Iþsxn_nu×'iqyOJrᢌ£“'=Ùœ ÐQÖnáJWáü!¦ ® PÇßÀM¼gõ¹}~-pCqæÖ#>ã†; ~èñ!nXêàD8 \uIÛdŸ<š8`A¾$pü ®­E%™Ž„ga8¨¯%À è8X¬g4(Ö¥¯ÿ8\.õ§ÀÉ1 ” ãpÕ1è Ãà4Ø‘‡`"!¯WÓ-ëL˜¾6Áäo³þB~‚U%­“©È¹ d¦¥Ó¹­ëÞg-Ǿ~.ƒ{@=zÝ ´²¾%QB}ék:<yRNCûøö™þ†lSUÒ«éÉq1oÀBÍž å„«é†CžN_Í£„2 “nã.g< ±sMƒÃɉ®ÚÐ×þèÈûoÈ÷-¨Âçç¶3@°£ †'q ½Gƒþ§~ã hTãAõùôƒFÄç¢ÂŽð>h*”a°ÜïM Ï_Iºù ¸5øEЈâÏdKî[…‡'èIÉðìö“¾|8ÜG\„p¶ÓwÎÇ™5R]!n|ÃU°8kë‘‘YÃoÇê}Öz4<½a}8 N!(…`—‰uª÷ÝáuÐ’sÃïÁvżÁ)(×o7õâ î ýÀr}ÆMK½»ñh|^=`´“Íy ®Z¡Á`ݶ#ÔQéêè°üi!­?Ÿ‘i`6X,wÐqÑYÿh¨WÒõh–tvÜŒ§ëL§s›H6.}_.âÔÃF°)èÝ—Ážð48vÁYϤ¯S’~´µ =µßÍоǽãÕˆ„ò}6ŒMºœ {׉BþäMCÈëó¡ŒtœaãÓqÜvä5œ–RóQÏéŒó@ÆÕéúóõg>§œ£è¯ÿ2`yòô1?áä7–ã}º>ÛëœõœÅfYjà¹ö…§€—"§!IÅe1SÅÔÚJC’üã(ÍÇ~ð*¸DúÁðs¨$áù+Ȱ=£s׿rÜz»¸‚+=6IÄk6' aÍÃ:šñ—ôÆI忝„õ¦ÝÑ^+=fàã`psè*qåô†A£­ 3`§ò:9<1j˜yO8v…3ÀvŒ/ùŠŠç±^àÆ¨û~4,aã'XVÜÈÿ—”RGpe$'{¯z„´ßw=<^JÓ} Šy•JWó›ÚæÐ,ÄýÎûÀ‰8;X·3H(?ÜW»f牫ֹ˦3ÎkùPF6µû®–aøËÒÕ{ÕÏJ÷®uápC·_áÙpµoO‚@ûƒ¼?2nþc‘¡øŽ@9†öÙÓø|èéãrù(¯.é¨üû§ÚPöòŒÉÃèæ-êš×Û!¥†ûO “v—îÐÓóh'ÅÔ"aÙ‡æÔòŒyÒj8ˆû½`exÆ@½å]À3ËÃc.›Û†d0O¾ÜÓ?Ö1ÑŸ­E¶#Ó[030ýW*=ÓÅ#Sªµ‹.š’IAe­]2Œžèõ9bÂúO0vòRp²&ò Ÿ[Á à‚í ñÔ46‡ëÀûZEƒo§4¢näŠFÉîFæjmVÔQ£b|Þ6¹yº1 /ÕàF”ó[ï– #£#¡Eójyáj8aÃlFÉï Väz2˜OQŸ¦+^ÓáçU1ÍMб õLÊð~ 8^„ÐvÇ.+¡Žl|úÞñVÒyí÷à˜²”–N'ª¬% eeÓC|¸¦ÓCœíïQ*÷®ÃAoú.è¶C ùÕ¹aÇÉ0ºš5ÛF¢ÓbV©$V±ãw'够7ëg<èßúHÄ6…6â“ÄLZ6¯y4(J(Ã+qÓ`O.åm@úÓ8“³7eÈ:UÊ›<¯NLi†ëBC]kÁ=MÔé˜È3`W–§@µìT\ºN±©:ÍÙy_¾)CpV#¼6h^:“ß‘áð:°—è²;ó'Y™T€ç2ï¸6m¹“ñ pÀ·mõöàsŸùxn>]ÃýàpÎ ºŒn­8¼ž k©K£<\ B³âFuû‚NEÖÕ©Ø7»Íáb¨¥/d«(¶cšü“Agæ¶°:¬½`$8NwÀ(0¿ƒ«N ;À^Óa-‘ý{6ƒþ`¿Ç‚b^%<ÂId*Þr,_c­óô `ì“ÿ“ ›½sÈ2Ù’㦣3+ê&ë8ž+—nš¨ët›Ó„çCœ÷!¯íφÓù ‡ü^CY᪴¨:7«Â»àØ»°\?Î ­¯sÖÝüknÉÿ†•ð¿ [}Vê«H» ¦õd2}B›ýÝ’åÒíO9 •…gB¾pïU¨7ÓCZ)jœ‹ù‚þJù&§¯ß8öÙØT¹|7—yB|6ÔofÅ´t¼ù³yÌ×q˜Ô{^âp¯7A/X:»ëÒÌ»ë–û6¸Üû ° ”“QDºl]Ö[À£@Ó2¤þ9ùµ¹$%Ï90^ÄÄÙÆÁfpÛfàzh{ÿ_À“  ÷ìGæ/Ì|*œ ëŽp8¨‰yÁÌnß‚«Äkžò? ûœ›À|`›*‰i~eà qãÎKÜݸ¯†P­ $W7Û——ØÏpr¶m¤oKÖ‚ßïà-ã6Ðy3ý¸†ÃÂð.¸9Û¦Vˆ›†õ†:Òm3>-åîÓó9<›ÎW.âÂÕ¾¹ nÛáE}¡R:ÄËíH¿ŽwN6"ú’~Þvš–®4ä qÞ§Ãáùl¾t|ÈO\2õKõ´ÓÇ{óÿìœ\Õù°7Hp î îPЇâN±„ Å‹š¢-Z´´¸»·ÅŠ;EK)”â—‚(ü÷{ž»÷Nnffgfgv7|yó{æØ{üœ÷œ{gwSŠLâðŽ©ât»¼ö…7ap»V“d(3µtHªåë,Ír5å¶å1X,;-ÿDÂnïçÀmëù¡yPÌ=°Ý§çeW¼ÃàG'còÀ9òç|.ÿ3.û¬Ï*D¬ Úæ¿ç·ç­Ü O¢<O#YœFÀdp(Œ›‡½6 ®ä aQøš%¶ÚÊ:pìÕv-Ì™°s'z$×% ¹ÁÃÖ Ñáð Ø¾Þ"N›2óãÎ.Á‡F”y-ù“)`8œ ÌgÃÛ ¨/Jê·ï®‡ˆó¹ hIB´>JœĠ{ê{ þÖ×¥™cêú´_ZV˱ŽèS~Ý´©~1>òD|%×õÒî…ûAKªÅuÌ^¤:6bûa ‡{‹¶ÝäÁWN¢üriµÆEÅ1ˆ°éb8+–oZ”eZQ7 _Œ9Òõ™çÉþ6€óOÏ›”¯Ø[;³×¿f=^ëÊ1p}¦í!˜I´/Âc ëPœš·ûW¸n¿›ÀíXMÎ'q(]M©4·ªÃâŸwÂZ ù³ýAɧ2ûkŒ¦M Ñþ•6êøN3ÓÇyø'3°hÇ\†·}w¶ÓJx\@?í6R× ÷ü¾´ã_«è&uæPA¿² ,s‚O#·ÃIp°Ù³ƒÚ¼Íò8¼³B%±À^ÐÌ‹ˆõ} Á”À fOÖãö´¸ 1 ÙW4Z/d»Â à¥àpW‹º)ÆÍ‹ƒcw!Læ =¼¥n=ïaíE#¬•—¯SÀ ›¢že_ §Âô ¾âeÊñtG݇C_x œ·/à{hD\£!Ÿà±¼Áu›¦̤W-œ¦…?\ Óï8ºW쿹‡Ú\`º›MwÜ H;ûçßè:DƒÉ; úg)…(×è(» RsÐö¦å™1¦EºqúCBÇp¤…:©KÚ­Ø‚ß:Çꉒ—ß~ì7qÇßø’yŸ˜yûëiˆc”ŠýuÍ*Q_”Õ;F}¦Cz8- –ï†Jt±#ôÃç¼3ƒÛ½™b}+€fmnÐŒïGÀP”hÿ$<šîõ¹ŠàýqÈyX”±ÇVïÁCÐÞNÒS -t/Æ^r_)Sä|†»‰aWÅ:p9XŽ+²šDGÔm…X¿Ùp( V|‰;ÐùØó¤’†‹åEZćEˆx×ß=`".ʶþgÁ5dZ¤?GÎáïŹˆrf£ßoæáŽØ2ŸŽ©’–×Sû§yÓ1+æŒtëŠýõEý‘ÇrB_WÉãÌZÚ¾¡gºeäºó;žôù«~˜.’‹1‹E¡««_ÏÚÈ2õÞïÏ €‡¿Ã±<<•$†·Rz#ñ–¹\ŸgÞwïÜß™³0 7ÃN\¯b§¿]šÕÎrŽ9é.Ï1NÜkìS{¨¿ ^Ë숓."ö\Vÿ ¸ñ—|x¸Äõ©ÆB¼%¨T”ØáW’àAp. W¶WCŸ ­D=¥\)£jÀûÃ>`9Åü¶ÏðRøÒÎlªLMi«Áu°ÛBTEQ·«m‹üî8wë4ðŒp ãM°œ^œÇ0Øæ®ßøVÃv™îü¼ ʽàÜy› ØÕ¥_ýÏ!æoÉ ÷Xþ…0R1o*tòð"² ¼sÁ‰à|Î!Åü1ÅøOÈ0¤}2Êå1.-Ã6EX¿ã¢ŽLk€c¢î@xœ‡¨#òØˉ0ÞìTäÔ÷Vü¯ÑQ¥‡ÿdÌã\ïPUÅz%‹ª ‰¶'úiRøÓöG\dµú¡é‰{-û׃|þhŸeÅZ‹º ùÏš„wÉØ›gƒwk“]YÍk‘§Ø6õš(N™f¬;Ä®ˆ[a/ð9ÃXE¹ˆ!pA1¡Ž°KT“áRž6Ïw'®f-Lý*øw€j¼eEr¬ /ÃÜV¥¸óIseŒ¼<Åß×Ì×o°®Ø7þºï(“éĺ‚ÕAÑff‡Fl,o ¿†õ!VÞ²âSžl;‚O¦€—‚Õ€]"Æõ`Š:ðV•OI=ÖƒAãb'Þ†9À¶ÚÉVŠÈ+º—Gr¿q‰ó"ðLî®Wœ¬ûa8¸ƒ7ƒ‹á-p,-S×ÃÙ“C¿(]Û81h=Nó®–shé<Ð.çfx-÷›×:kË’ðëZ¾‹é‹qZçù"°-¯À®0 Û0'Ì®±jâzóÂø/ð²bû‹qºq [ÿ_ÁºËóRaÇçUÐMó;ÖÖ—Æ%œ¦Yî©ùÙoˆ¿ïÐ|N]+3Ÿ—?K–’|ÇÎ$ÇG±ü¨#‹hà#ÊO˱üØ[Q‡z¡k5úÓ<'"ÎmY.Íè,>Ê0/uøC‚LŠŸ:çæâ´6cpL€^© u#ÞVÉt¼)üölU%y¹1t‹^V‡£Á;q*>OuåRr5ùŸ‡[ LÞ’üß`Ýö} èL4MÀÜÌÊFXhLJt§³¬cDzlý1¢±42ÛKòǨ˜ Ï>ÚùtFôÛ). Ù7Ú»wáÒ™øè±¹TÔ0ozƒ{5qÇg»—Fæ},÷ئÅ'•Ä6xè[·åxxa2Ñ(ý Ö€0PYB ?Ì›Uö‡n>ÆM—àhâ¡u0l×@´oM¢A¼…³`° ÃAã8¾ÓÀðÌ ¶mjø¼ÿ€;a_ðŠÕm¿Îw³sì|)±¬C‰p¸ÆMZ”'àRp1ؤzDgR.Î/Êtp=X®–Hù| G‚eÛÆrkÑvzù¢ÍêëìKœ–Ôxu ö]q\B\›ë²±éz3N‰zª¹¡GÛVÆ?QŒ¿ñHõçqyÄBŸŽÛx›™¥…B±?fޏÐ1®3Q7ò…n©2""ݱŒ>ë:R]óça‡ënô¶)ô/K/æ‰|¸Ù2y™‡†ÿýÀªÏ°,ëNóçºÄ¶DìGWÜFµ™äp«n«€2;¸-Þ„Ù y%·¶ËZÂQ ¤CiXS±< š,ÍMQ‡¨QdBÇÂaLKÖ!Û ®ƒ…—poï”óu36t]nríØõÒÓ¿{6öí{øÿ'û+³½÷̉ÇUåÓMˆÓ¹)lƒáCˆBðV*Ïž2}ƒ` íËpFîÿ×[ʪÀÊ©ø ßz¾n†Õ@}ŒcvÁø/nwÊ'T6àlGàVÓlc5’ËŠ%/ ŽáÙp,–ŽŸ1Œ¢îT09¼3€‡æZ°ü惥a 8·kƒå(Î{\Þ°ê†_ë°§ÿixö/D¦E_#„IÊ$òG8u­ãSPg/0ïàÁ» Ø^×ÃvõáÍô\Š®å(æ·,ßB¹fÄqüx0~{°ïæYÌmþÿ8J±ì¨CÈþ§.u:ôS«SFœöãiç6´ã}üOã· QÄ"Ó±Ô/ÅöUQ,4-CEåʌ@".ôÃíHý!°Kë>ÆèÛeGy†?ÓÂ5­z+a}®OЛ‹BÎàè[”KúMìš¶Ù»ç0'ÌÓƒKV3j¸3™·¿fÖå½!¤S’ÆiÎö/ž+Ãý`{Êé‰[Is¸uGó†à{ÈF¦{?œ#çj =Øú>ž!Æ¥“8œðtà9=d€¹‹ò>! ¿„8$ðÖ$qÀLˆö¢0;¸ñ½Z¹Âϯ¦¾ŸòÀ²üb;¼ €G@‹ ~ l›eõ‰j™X·;Òe>~ ¶»™b/:ë8 .'ÌCÏñõR—`6Žç¤àÎߎçð^°ý¦™×K™®¢þJaã­O™ì·º3!Ú·¤£_)–ÝÛùg\F½ÌÌ®çÿFø Ü¡çÓ¿—-ë‹vçÓýÞð˜¶:hµ<©Ì?„¸¦úD ÷;fJć[kœú‘‡ý°–òûQEìîeè¸}¦þUÒ·ÜtÞ,Ó¾Û¯Z¥XF”íŽp”—ê›f8ïxRÂþÏ~Y»"­ 7JšyM1·|ÞåXÓG2 ç¸X\dý1¸1dØ2¼”w̥$ç’°+8lnïØîxkMüºp¸E6…롚ÌN¢[2?õסîA,Á‹«åSÒ<¦z½‘ç’v>ÛˆyËõ»_>„Ÿöúc0.Û{®¢j«f Ò5¤·Ášè’\³XgÔ{ ~ òPx|ÚÝ ìŒ2?x†“ÁÎL a0ðv«Xï p<Ë€}©d”ÔÏ·’hô¼„€ýœœà/!ÆË²ÂïäºóÝy濆Á\p&ÌÞô¢]1^ºÞL: «¤µù\žPmHóF˜è,Þpˆz!©?⊮y‹»Ð8ðƒð ¬ ñÏÀÃàZU •cÛëUWÒ6v\uCŸºÅ<¦U‹‹¼œb}–ãÛ,æ«ô¿ßE=UÜÅÈ¿åŸMÛvuŽk‘hOÔÝYžbÒüÅ´bYê†N±}‘V.qêw¦“çUíAמE±YáåMgéÇ7ðþ(Å~{g{ç~‡áQ¸.E=E×éhDÌk™1Ûâßn†õ šh¦¤úù °s;¬¸ÖhŒ–FDZÛ;}6?ÿ¼_ùô¯sxÞ¸¿ÄótÐjãLó¼½vÙ€-![¼£ˆ£ð:hX]±Òð6U,wb°ÁïÃà“2;Ø)/ ^ þ’ûßõC=%^޼"O ÖøÒ+i¼™x@³#²?þ½8.Æ«¬xPÝ–ñØç#ÁCÖ±ñ·¯â8)^>´/À×ðÜNö® …\|ƒ`)Ksi¼RÍuÑœk2Ûúx3)†,סýç:ѧb;n«7ẋb\·×‚þ`Äzv­h=Íû_ˆ¶¤eUò£>J¡nšq•\Û/?Ãù+¬£ë¸ʼOB¾CØv#ª¥¨è_Dº—j•b^+ˆJ"­X^ÄçzWÒÆ¿Ãiö7$ʉ²Œ·1.\ý®m±Üð‡k\ïÿ}°ñKãºlÉ“Ò*ˆê’œ—çÞ©K¥47³o4!Þí`3Pšfõßrò¡Î¦gÂ?Ýóøb=Q÷¼¤_@Ö5i æLµ( ï˜'Å~öʰfd/ܳæþ×´0=üµÙîÅûà8Æã=»ôÏ=­}$žj½UÑCænؾƒVŠFÁ†ÇÊòÀ· “ƒ«ßÛËì0fÅ›O<åeÝðaû&Ûç.˜ãa”Šý9N¢T,CË~,öÁ‰ÒõRÀäfXæàa¾8³ÀL°8;Üà¡gúð4œŽß§nIëV:sÍ{4ü –/!‘·RØør:Îeˆó©u)®AÇe¨´Þ\ìÁ¢`y/ƒý÷Rà˜? ê| ޽ãgÎA”™ÖY?tåȬìbØèé‚0¢c(R³u&ŸyÎa-<ƒûGúq£åMÇÚLµV–æ‹BÃÓÓ°ñ‘'¯gÖÅ7̥ѣTk ÍápMÓoF×{¸±ö#ìЯv3¼ƒ×{ð9Æ5QÎËËêÉ €]uX–NöcAƒq‡Àáp¤:›"7PÊpDù'á׬p‡-+n§ßÁ¦° 籇¼»àc%ƾ·w`øÖå|, îâž’wAûïù¢-Œ½6%½ëÇ ¼’Èâ¡DÔh¢õºé¡ò1tçèØ!ÅÁÃ϶õ·AC±l ®RÅùmæký‡í³^/'îNÛ™ŠiÇ€‘޵»k°Ý—ÀM0ìÆNWԛ΅ãàbP¼ , >h±8h²v¨¯8áZ·¡ºWÁ‡ „Žnø‹ñ†­:pqy ~J¹<)Ÿiº1^”ãç+æÕ19¬+ìY¡?1qãöpL “Áz`?×çËà‚·>-—ëÁºŽûc[¾uBÒuþpÕ)ú‹áTÇ´¾ÀÜþõBšWuë”k(ã8³;Ò[k‘ÏPº ¶Ì] gw‰FA‰CñüW‚®ò ¹¼~†¬ŽgððUb5w„šûi»4hÃŽp6Ä`ã­(N„‡Øó0<¼çè§FN±í`üœTãœÔàXxÐXgF¼™ž:ƒ7Á½á(ø̯tæzÙZ þ'úxKyõ+Q–~ÇC‰v®Ö,}j½b^ ý’Bî)Ž£ýÙ^ÛëW÷$pMæ!gáé¾mø5^¾n€ÏÁq3=úPô“TJ7MQ7üEý«Ã%ln×a,Ê”{eÞ «DÝ=ŠDÝF¦mE©†€cRi^’ºûàß’ñ~Þ5X©¾4^„­Ãýb}Q¯:iýƇDýèl@œª‹Â`3º*{PÀÚ°ÌÐÕÂÈÿ4y–€Ga)°»1öuNÐܯ9H‡`—åJ°ÿ·'%q¨g& ‰ÅÛÙg ÌXßÉ;²[Ì)MØ®-ï÷Léâ}ø%| .… ´màÕÜ H7ÛK±‰×$êO#Á'0Wbw‰u®Â¹`zðÀ\lǺàMH±ƒw ˆvº‹6¸Lˆß¾¤}П† Ö%_¢}8è§ÀFËr‹ãíì:XÞÎ }omŽóþྠ>½í<¿VÀ>Æî‹4¢Jzúg-Ê5°>„ž®Rt#n/<—ÂÁö‡ÞL¢O¶Û…hرÝb}…ÿ.ÐR…8V©D¿Ó¸Ô‹öd"w„…ÀKhÔ7k›ãPì›i¡g[·qƒ9»Üàdo“|³àÁ5f¶É|úÃÅ[*«Z\Ô÷ ÷ÁëùE– ówQŽc,V¤ŸàÎõT+3Ú_M§‘´˜3ÊwØ¢²býÅDãBÂ_ìK:¾¡n!Í"|àa=üœâ®ˆeFÓºRN-y5Ko‚‡ç°$T«Ûíè—ë0˜ š%N—sšÊöâ°<e3"6…—`VÀüM¢¹S¥‰[¶éCËÿÞ„·¿‡IòÇHÅ…3#Ì”û?ÀÍ Îkð®‰õöÐÆq0<àŠFœ¨–‰†yo8>…-a0,"—ô€Y™ðš ØéÇàtˆ>Ûÿ Œ˜«ÝCeZˆg>6Âx«ŠúÃ9p,ìîNwÓÌðvöÀþ ¬GÃË0 l‹O¸×‚‡“—ƒ3avÐ:(êxÀž³Á"à¡f£ê(Öµéð7ÐZ¬ ‘ï(ú¶ùãGÂÕ°L OÂs`yÇÃ*0 l»‡¦yúËžv/¶Év;ÖNîa0¶­i)+†§ íl°¯³Ãš¹§”ÇöËÀÊàéjZ†ÓÀ§oœób¼}ؾÅ>¤¢Nˆ}MÃ_ÎõT¹lƒ}߬[±œTl"ûí‡ÅqÓ:ŠºÅ°—×ÕKp'XÖ§àØo B±Þ(£’Ë=à·|ÿÿwî–é:£¨®Š]³Ú=XkáÙ Úœöß¾Õ"ižÐ¼‘aÓ©÷rÆHû³¯ëA±-ÅöD\ÄëZNħy­‡±ËÖ»~×}†õxSù'—íº OP5ªÏ£ª:k‘zÌXU«ñÄ[Èz}^þì¸n÷ZÅez$\žgpÛí.Ù+¡Þ¾’e4¹„Í‹wã(÷"†A‘€iޱþ7`g¬ô]w-Ù%MÞ²MïûN±…þH±N¾ƒ.6úbÐn9I¦ÅÞ›éôÕcB#bfßó¸:¶„É¡;d*IÛlW¦ßÀQà¡[IÔ—Yðl\Ñk–a_/©x!8<”ŠbœÆÊÃjs8l÷Ž0^N„ãÀ:&ç`%؆€ð°,w“®ó^°Ø÷hk¤•éꪯ˜¦èŠ öÛ'Ü a˜¢ž©ñïƒÁCT1n+ˆ9Ø¿¿í™l«e‡Øýx31^1>ĸˆ¸rn?"¯pÌ•)ʲÍáÇ›õiÜsÀËíø ¨SÔ|º¶å‹\of\-±ëáðÂs# 7€ãæzø¤e%l™äÞÃßvÔÒ_˨Q¢ê3hçîôm.ò-‘åʰþjéåòÔ§ x=í_ø«Õ§N´)õ§uš?tôGX(Ûô2²(qòÌ»ÃГ]± 3À°¬ õнK3Ä­ùx„ç!­`ÝâK6Ík*1ìG¹ J#ÍË×jp7ÌØñWdÜÁcœDzcÃ÷¾ç0o|ƒ£«½Å)0h ³#‘®-ºv݃%ÁUR¯¸ÚŽ ¥»¿Õb¯‡9`‘BevîEp vÛF¥8ã†=ŠcäÓ³ùxŠ /Óæ‘æÿ<4oå>X žõ½( ¬?B´Á:=´D¿uŽÁO!âM ðfñºÆ)iZê7Íq=ËŸ†‚ã8<'€rxðYFj §R §iú;K}רf°>l öW‰ñéþiÜGBß<9Í“úM®6>p¾/¼Êþ°:Ø×[”‘º³×åE‹sñx[%‹p {–ù´I¥êÒ±6²”ÐI+Ò|ªj<”ˆ0QþNþ†ôñ^Ç'-¿X_„Sˉ²\‹¡c=ô'«/Ö¹nG0[‘n¸‚xO>4wÚÄZÅmzpˆ5M£¤—Á{¬f!=Ä Ö%‡¡½ ,äÒdiNÞ,Ä7Ü€L瀖¢œO„ÿs1°SËe.ü¯Žº:Êäè}Q.éÞ*ý<ÈÝž¿ž1Šƒî›æ·àPÐnå5"vÈÇò AoD4zG‚ñ"p%·Z¬ÃC¡(®2Wû ð8xíoTbÅF~ÃòÑÄCæ2(êûºz7øRqbl»ã6^¯ðÆk•¼ øDlµp­ç;ôfíP'Úþ4z©ëáôX.o†+ƒ‹Çö­·€írüí·eÚ®¨#ÂáVŠôr®y¬[KéB)W®yBÔu¬¿7‰yÔ ¿ñi8ʈ6„žñq‘ø ~Ë> NÇãrpl´i^Æl2ç»›¬ˆ‡ÿÌç7ÝQ_ô“î}¿¦*#O¸äÍÄp\Œ0Ü™¨Ÿ®‰tËäõEÕPšm¦[µ;DÛìvyÖ…×`v°›]9üÉž-_ÍFQì›õ¹…®)&ÖviWš’IÛ–E D}§gAxò± H̘!5­ëèÊB»¶µñ+æ…ÁÍþÓŸh¨öhCpðßlÂh’Ù9WdjÄGÓª!•ák†a^0Ü*ÉMá•V¢}ñ5õp°Ó©q Ø)×ß©é4ˆöFŶÉÃÃÃâðpº|[ ë•Ý>Ø¿˜ýv‚‡ÁŒ`½ö/Òñ–æÒ8%æ6Âiœ~ã-Sþ ÇÃæ xØÙN·«ÖÅÇ'%ʲoá7 Ýâ„®éE‰4ëþNÇÅù,–CÔhq‘ß4-®{kÂ_Áö[F±i¸?Ed!/C{Áþà {+ØÜ ‹ƒmñ„áÍŇ\@ür,¾ÕbµþþçAw³Þ¦+V¨B 23k¤“¬ž?o\lZ6fiûlg:'‘!Ú¯nb–û` `Z²ß¡Ÿ·Uâ–öð;>€!mvt…è†e9߀tèfÒŸÏMàdpY„Fd!2=šž¢Xï°œñìeßÒû7ùÛÂîÁÔÌLÒ»0Fˆæ±× ‹v'Óml‘Ïpã9~'a?ðJ˜~qÂ&ƒ¦ÖÎðQàáñ9¸Ê|¢l…x(x¨MS¡pÓÖëa;ppÒA Ør±>Ç%W‘Ñ p 0qÙÖâdßûk·âÁïdçaâÄzðï>™›V„¨R\%¿mÑúy!9O,k@IDATúˆ•¾þIÁ]=¢]x3±ÎT ÛgÛY”T7õõ ›îBöâἘ»8Yšn*ÕæÕ47À:p3 /2ižhsÄ…‹ZIϸ´ÝÖõàýç÷ø˜‡M¶å8~UºC¢žÇ™Û¹œ†;m³*¶OV ù˜dQQiž„SY"o’'++Ây¹¥Œ"ÍpøU4ì8—[¦'YŸ"Îe½Ì¿ƒ¬/¸]‘´ŒÃ)Èíú¸,´ÍJªÓÓµOû0' ·rQ¶"Âç‘óÁ¶üêiƒº'AŒÞQ$â%6üQ¾fæ§ð,,B²—tÜ)KÀ!.­Þ$ޱë}/Ý›á»m¼7´¡p„mÂ;ЏHià×wAWÄÖŒ„á*(÷ªœè¦H’îØJò% ›Âôp2L =-î†~p-,σ‡“wã;àá„ÁΈK€®q“Ã1`_v¸¥zù-G ä¼» ØÀWF?u€]a.ðä8nÛo?¬'ܨ³Žøz\ë¶Ž£Á6y‘³­õ”QÔu¸./-QÚÎð‡[Ì[.\N7â¼@­ ‡7"ñ$/2= Nõqã²ÏWÄf¶BÜþ»°vor|[)Vt±‹Q´›GÁ¼°*ßÕq²Œ³`E˜Vƒ›Àù‰ú#Ü ÷ Ñ®—k¿qûÀ¥ð9œõ´¡¨[®ŽÐ¹ˆ²•”o›ÖÇ@ùºÃÞጟœµ½Jÿ¯æãAæq!Üh ç‰ ï.øbRðfaìBÛð1hèš!º:Üú[!ÑÑÎÚìÓ÷ ° œ >Uö¤x°y0h$w„'a+ø| öGC-éÁcØ>Û'zMð@ JyÒtÔ3ëãa¾lÀn0V‚ÕÀKÕ°x9Ñ*š6l÷zð Xv±QŸ+³$W/7ûÂv`½¶ÇzªIµºl“é^ûí,çªñ©?â:sÍó-8?kPõTü4ö‹t£U{j:“ÙP¸šú§eÝû6±éBÁWPþ†±7›QA= £Ö`½ŽÑ ¸¼ó6R\Ú\ó»ÎËÕ$v‡¼@%•ÚŸöÉ{¿gý 4ê}òh†ÒòŠÅØç™áÂ$a]üoÀ+à±siǰì€wŒf.ífux®Y“’œíÛPØ Êëê´Ã(¢Qk–XW½gà½fÚ…r0JÙ]5)î£](§«Y˜3á_àSþ¹p0|—‡mg‡L1ì¿—ó«ãDªSô— ¿ƒÞà!â0 ëÅ-Ú ¡øq Ç­Ò`'g¡îÀì×ÕÙóô_ÔÙ Ùy¡;Åy~­Æ ‹Þaà³G=âÖ|¥† š‰¿ÁK¹®ëÃ-áýرš®c[hÑÆéé=\¤çžcï'V[½jžê{&¤oàì¢Ø™aFúº Y›ÎòËóIÎס%«€¿Yr¹º< j ÒÖàŽv€zBl«×ôsÀgÛâ Ã<âtE¹&……!âCßñÖ¯úÖç¡ï¥ÁŸðPw7^€QFšçâ]HÖ“¦«# ZöÏ \/4êuug¸F|¬x¼hÌ ­’èG±üè£n±ï†#=Ò ý4=âþË·k\¶v÷bÓKä?ŒõÆ´½½«sVèÏêXõ׸Úõ’Œ(ŶÆSÎÈ5XÓLä³éš‹Çá5Pf†·2ߨ/<l‚÷{·ywvêF‘ZëVï˜>¥„ÎýQayw*3¢ñf¢åö~7¯‰»W[ÛïqÈ£zµÓä-Ó¥¾ö_ŒÚN€_ÛÆ¡ï|\¤«b\,ˆtx>;ñ}NäãKh¦Ø ûá)h¶ôý§.ùí¥àa˜¸®œ]Wö°¸þÂÃÁƒÔxjo1\ô{a0Ï?a8é꥘ÇIö`Wÿ>¸Î×72QoZ_´c$é¾0\I\D~5p%øNïZ¸¬·™LÏÀ%àÂÝZuI³Îý¨EÓ ÆÛpø;s™/ç¥ ¨¿‡eêÿsx°óØfˆCëÁçòø1ˆãrRÙ·uà.!â¹ v·–y|úWzr¶¤þ{²VTÿ°¶ÙÙŒ›û {ið$2oÔ¥_u/…a~èL\/–7,^Ά©¡žË^_ô†çàØÁ~à¡Ññ s§í \³NãÔ%ª‚Wö­Áñ•2…^±9²Ÿú× w¬‡²nŠi^œÖçÈ<¦+º¦Ûo}ƒ` ØœËEAo…ºRIL³-šÖîS¨G\döëq8vŸ€}êLÞAáØ\˜­×ã 0'¸Iª É]‘>ÓR<²Ý±‰zº£•m0=7·óô0ë¨êß'HóšßqTòøkX‹Ã(ó@×Bˆiió:#¹”–Ƈ? U¸Æ»ÞÅrÃ.Q¥¸hk-ëÏ|5ÊuèíÞuW‡ßÃôà•Þ(ñœTœ†jmý‚Dê» ³|ï©àV2Ogr/ çÃe¹¢SSõ2~ž%ÄY)Oî•N,ûžnÜø¼Åœr2ZáÙâDhç‰Ëþ€ÜR¸žp%ñ»!£ÿùÉxZuø[¹Ô'J$—®Ž ù_…ÙÁ²_//æÇ Ú@‘Üe™\á[Áý0 œ4±áê°q¶O+ÃM/û™bºåÞZ£_þ0øïíOÌ» oYñáåäBø¬¬FõHÛê‚sŽO{ácðrRM÷³a´z¢ŽÇfp3|‘Mv}«Á˜¶ÿ‚)p ÒñOýM®¶‘â| ð'í­1 § “6BÅç 3ÊáßHczQ—¯ãáô‰[ñ6X\îƒc¡·þ4-Û†,ÁÊóªRA<<ü=K쵩÷®7¼µÈ*(m'”­cîŽ8­r¯–®_Méƒõܑ̓5¼N–vÿ  †S1œÆéÏÎ}‘îëùª­¨îhGÔa;¼ n/·Í^`>qº%{“xˆÛ·zÅ~»5¦„Φ1LN­uL†¢ÛD±þ¨CSÙÛEÓÑ“âXµ» Y„}\„Šçê›0oî·‘n¯¸­ÐŽL–æs<«Â(ƒp­ÒÌpÇ{à ˜mYGgë-X¬K«»<ZwhîNš¶Ÿæœp'Ó]ù2Ü ÃáVð¶÷)d+·^±ëÐÂyX7ClÓiàX ëÁ|`µ©p%h‰í³iÒ☟¶ë*p\ëÇÊ9qÜž‡¿Ã« Õ½ XW#ïÉ»¦žsšJô9k•ߺR)3Î»ÐÆÝ0*SÓÎñWm^!ÿßQ^¢—ÖÙMþrífF~·ÖŽ0aÞ&ïâ™T,Ëm6-ho—‚Ù òÍŽØÜâë@O‹K.ÚWO[œJó}‚Õ¡œlIäÚ ÞèLÔ} .‡ÍAs XßGÝÿÄ»¨q½Qšyü4Ò?Çé@üœ¤Ë`(gÃN ]2MQ9üYDòáÀwkgÜe[ÃÅp ü <ØêŸÚnWQ½yËÕãàxþ>‡˜ÊͺxC;ŽûïŽ´Ž“`(|öE‹ád‰:“ƒ:!l ç:Û•»àNïCˆyëË}°4XW#em4q\=T£màVx ´×€iÇ€éŒÑxèÚ‡TïÁ\‹xèš·Q‰ö™ß~ ÆÕ"êùs?¼Ž™—˜µÀ‹¤ó÷þýmG·TlO_hV&6¨Ô¨<ÇnœÅz؇5ö}Ø?.åÖD!ÿϘö :Ê(%•Ë÷Cu>u—¢” )&Œ¶ˆTÝh<œöŸ×oñn“´9.W!•b9¦¥å¾‚ÛúpÛxZ™÷uxކ"ûÕºp=%3P±OñoÂlu6¾kn Ç£0ʉzš’Zı: ,X¼ø,¤yÛš/Ï®è¸8´½NŠk¢;hÝŽ_û+Àžë³à ð2°/8áã$˜I"N¿“u?ì¸O)›æ‰8Ý"ý¨ecð)ö°AµÊÄ(î g·µfªCÏA\€#ÝUy8²Ÿlw—¸Â1NYÙNÂE0;,Z%Ó&€?Â<°fvjMÿw(q‹À³0 LùXŒ3-CÂÏ´×2§æqŽVÇ3ÄuäåªVŧáIØl{%q-hõÍãeA ¶LÆ­ ^^l›íø7÷·ùYHç¼(åæÍ<­rkXCPAT·)gÐF錄R·JÙ ’¡óæþ3ŠnäKû¦? ,]"^×zC7õÓ®Ò0ä8 õ¬Â~ЫßiÜ“¼Y7‰ü†ðÓ bó¢ÊBRÙàHb÷ƒß«[çHXV†¢\BÄ;p)xÀ¹|”zëíÈÕøçÑdõqzƒÆ‹Èr:V¶½\ûíÿ_AóTë˜>ˆîp:\Ž«ò0¬ÀÎıé½NÜî=%ŽýŸ¯åãcÆy \÷œ \»©í›.÷ãŒ&éÄèFÎÏǸ`ÉÝ%î$gû 8ê1Ú¨gïŒj9(Ô­W<…C °zËQßüöuðP´ÍŽsn´2 âñ)ЦÓÕ}ö€À¶ì ‹éZæfˆ+Ùƒì(ÐoÙˆ Ð>"ãÿ‚îÝÆ¹ìËÚ÷¿Ê¢û°H­åÿñ2Ëü6!É%3ÞèÜý–GšÃxs„~ì23NåøWI¾#ÁCü,pTËé§Âã`_5O}Á ¨x)á"°sº³cZNl_±ÃŽ}W×[±®róÙI‘¼m<š6ÞëFd”ãk“I[ˆ“ð£ñ D}ºê”ëS±,ÔF“¢N„u¡eO…Œê>Åó{&›BÚë“ÿ\‘8Zá?DD±?ÄTöYœÓù˜!W³ËžP›Ã<0#¤²=¯a'p™¹Üׂ«¡;ŶW[Þµ¶eгÂ[`™éøÝExap|jïðg‚¦mA0ï|oYz§TÚÖÝÕÚ™gJjrÜk;Ã?ÁQ«u²³}ìLJwŠõ¹‹Ü —‡·&)®¼š2Õ©äåäçp1x¸5*®ä»áOà¡mû¡_÷PðâánpRN€c`#˜ ®ó§O»»,Öíåkrø²ÎÒb÷³úîÀ×àƒx0»„ŸMÙ>³ ¦´»öOÊ”[ë\—ÉZŠú,û{–ÂáÙ&›1Z•I;_£Œ[ºÜd >s×¶¸a‹rbüH ÙÔ¤k\è—ë ó4)—‹>ž•Äñ‹2B'¦uE¢œb–[GÙC¯UéÇRŒÏtŲ"L]Ã`šâØ–—ruG\¸Q.®ËÝ †bqã˜y³ö)óHû­~¥þ“Ô¨Xì´ÀÝn1Þ{½oʉ÷Cy.Oô 4‡ÝÜP6¢š.ÍŸO|“±ÜYh¥KýÝB\-ÁÙQr{±Ì²q4åÿ’ë6wèûðz¬õ* ãÒê‹­žÐ uÀ}xû=¼d¶apÇYŠ–> oÂ,5´Ú‘÷0ݽÝ®¨x‹òÐÝ ~ ¾»ÓÈÔ+,æsbÂÕ8éW¿;àJðÒ!Ãip-hY<¤ôfʶ)ü>‚jåÛV¡?}¦Æ‹þ¸Ì×8\Ûÿ7sÛ ßn—=ïŒÆb‰æêN±Î F©p×ì ‡¾Äýïçà_Hš ´hξcàÐ÷6L'€%Þ #À´jÂ×(“á;£Æª¿Sã]n„".tªÕ—¦E¾4.ü œ4ws>}¾wÖ(+q½—Î^o;“ü©×»ö‹ì‡q©ø{Ê\–KéäyÙ:í>48?îéf)W¥cäÊÚWC{VGÇ<+À0x¼÷ƒVÉP öÉz5ДuE¼îGƒå¦âÔÔ+n­“ayX/Éìe‹;Þÿ4½MÆëÁq:oK\lìÇ̆y{n…ÁøJbýš_¿V1»Iùµn·à˜ ¼^Û¸jâŠñÊÝJ± ®¼á°¸òë#'â1Xl¯»Ã¯ 7õkI·ëS¸þfù¬³³1Q¿±m~ïmÛ>ƒjåÓî>3qØÏÁ÷ø§¶õwšÿrÛûßïØvû÷¶ËkD9±—Ý-Å:íÙ"¥F\ж?þÅàÿø­Œ…Ú–Åï\’™˜QðRðgpº&Ms ¸æ>€jãDr¶©íx™ãw¦ž)¨­ײ”b¸X`1½#רŸæ)æU£b¨å[Åk¬—µ˜ìßr‰X²p‘Xƒõñ0ÆD½R5ê”;- 5}L¦Ë)·ožqá{ OxøÊ šiyz;i¶i´q)”[ ªÛ$¹‘r—)+oZöÛ®7¾Ib”Íz(\w%˜öÊãLró¨.;]=øÓxPÿÜB´w0þë¡’A ©¬xòž½&X–ü ^ãÛ•ó:¾$&Ô{¤ÙsSkÏfe¡ÜvoGö÷€çÄ«àã¾ l¤~mš½þípn~ÿÃóòÁSKvó nÆ/ÁY虘Jî„Ë~šºÒkˆ/‚ÅÁv·Z@ú¯à=>Jí#)Çn:X÷áÿÀxŒXi•gYSÂàÄ^ ƒÀæt(|šûqš"SPʮ஫$.(Oß%iÆn¬¥…èÂÛÁ;ÎÖ½yV{`Ïz»Ûé•ógð¡s³MD3Kìš\¼´} 5ö®Ï4¨nä«úôO‘eÅzj¬«lþ4ÒÞJ£’´C¯KpmÖîß}õ˜Ë“¬ßëà7Ä9d™¨œŒté· ÜKÈ•”q#x½yˆw(ðoiùêB6†*F_,[åp+ùM¼]S‹I«°Å†D\t;‘ޙëe@3ñ4, ‡A³ev |êm[¹vD"ñ)àΦÅi‹1À[—Ø÷¥@ó˜K{Š{sÔá´u=K{Bff@ô\q<‡<ü½…ùÀ2Mûîdx³ÚãW…}ÀsE»¶d£>'î ð¦àáÿGpG;›*j[%_Qð*€ñÌÞ+yàùTZN^É#mowˆfzXdσúc¨&ŽÝp:|–“âd¬ð¶Áp\ÇÁ 0 8öNàVàµ[+ÜUqaÜë€mpŽS1Žùžp»¶öo–nëóÝmßµ?Ý6ß÷÷f3ôXªšûÍ1&H±®&gÈ75ÿâóÓ¶ûÚ®à‡1Ë.dë3:_6:™zÙ®ö ¹+2vŽkqXËæ)Fš)2ÚÚb‹‹úåÂiåÒk‰+Ôk‘ÜÛ~ÆÚ¹ƒu¼¦kgaK‡¿e.]~ðûþ*\&ý9íŽ?¹?¸¦$mþ8àÍ› ú$.Äg㢫„Ûjú§mØîÎK.צˆ»îÊÙÏ”æê59+ %^^ŸÖ_Í€b£Ž,¢‡È³$<Ù@Þb–hË/HДì çæJ!ˆÏtžm?…› ?]Ö]û‡÷¨„z‡ÄYÛÝ­ùÚÛQ ¾{P™©ÃÉâ}@ž Ë+goeoÞÀÝ.{ ×ÃÞýã[}÷„kX|(µßð0µ°éA#ã žŠi'‡”²8¸:Õ±ÀÉ!6\¸D5,ËÓUêQÓ¿áRZ“Ñþ9FË߯•úìØ(Z?Ç4P_L?|¢¿<'Ó<©8Ù[Á®°Ì ú¦UjIeåmb‡Á&àEÃü.ŽùqSým#¾êøý‡ý;=ôÈö£’öüw>¾çï¹|ŸÍ’?ùÿû`jÞüL•½sÍ;é¸~×Û0‹ósŒ·iâ^m²8ý.A›_’´_y¤QÓçõßÍ©?Få úù'Öõý„Y/m“§¹P²eåZ‰ ÂøJn­zæW·¸gÒrËô'MîÌ n=îÅJ?4~ šL·w#â0Ûägó̺vñ.X-kÔÑ µBv¢Ð­ÁãÁû¯îÓPM8DzuãQ¢IsíØOMÛ(ÇAêY9[ûéïnY݇E×Ëu6 >0n n¶]`p#zsòƒyß>¼ç|ÿG\ÖÎ~ffqÆæâcͳF™¾:,×ÍèZQwŠËôï´ýzêvYV·áiàR·»²^¸vþšIqý+€™ä+¦ÓîG‡Ã5³þ4œ˜|äe'1?xM‹JcN~HmØçÁTëö²’é «OÚé,Byv˧bÇß-ÿShDÖ$“³t3Åö]«‚G‰m,'÷ù%¸Þn‚‡Áñ5ÈÊx€ƒãÀžr©4ºWH:?ÝÒ *lÇæ·sà÷qÀ°5™Ýž wa8<ÜôÐOý6ÚÅÙ|¥õ!,àJò‹_qz˜ÿF@%ñ p£;cîŠsó0NÖ(]Wé¶`™!ÞJÒYŽør®Öä°3;§#~-þ…`Ahâ&§´úħÀ Á•<>‡Ü fãs áýab°2ü <%w'O¿ã}¬êt&n‡)àjpg­ÃgPmLóùáx|w ü‡+Ë5ÙîBŽv­³…êÿwÂVä]Ðúüý’åðÍ #ál ÖÕŸ’¯6 hŽ"öW£ÄtOÀ6®AåþÍÿ’”›u;²¾µ=Ú#È|Æå*ÜmÉ´v1{Ÿ(Ã|JÑíˆíˆÏËŽ¨L×8Û”ºú-×FëÆM+ G:É%=ã¤Aq[;€f§VÑ|y 8¶Ö èÙ‡`ЦÛí£¡DÞªzš,îlM—({JþnNjØ¿f=ŽoñïKƒyÈ8/^TŒÛ‘?1paÇ#Ï“{\œ‹î’XúíÏS£ûâ ø^†«`6ð,va˜{ÇŒÆéŠ{ô¯ Ýw!­Å!ö¡x¦å!ð°]â0Ã[U¼‰(Vt?X¹+ì.°QŠÖípµ*^:[®Ë{ö7W€¡Í\œ­¡ý¼v€yÁ9 üŒslc¬³7'ËçþpÝ}àß`?µŽ;ªÙ8›ÿ¸›þ Õ2¾(¶÷X<øWbD7Fó¦ìG0=ø_€±R}YW¢²6‡ÿѬù%ù«€íKl×Öç÷l²"µC§ÓO—ÁÖ”jmNÛ†ÞI¬çYhë†ôuSöñY¸;°nqÚþÆÞÏ~0]á×~†_7ü,Üбî%]/i8ü‘aÔJ³¥¿±·’[åá:ò…ªÍ¶ I»éõºQŽæô6¸ Þƒ¿ƒé¡ÊŸš¤*'w)ÅáwÚ\ á ðˆ8å^m#`ƒ½C`ëj›±ZZ”ÚÝnÚ£bÝîå\ﯬék°Ÿö.?}ºŒðâ7`ÍýÿhR®ßÅ8ÃAZ€qÖí^*'¦åm+—ÜhœÕ./7X€—‡ð4Cl¢9ÝV·¸ñnéC ñÑ*q¹ˆÓ¡ÉÞ 4×3C=2;ÊšÃgað8@â¤êõàgº-º£ÓOI- Á0”ûÁ[U­òŠ.æM ´_J"§+¹7¨å9ãSÀT9âºB}r¿ Þ€-að©×'ØÈgÞ8ó` /€i]Qévñµýoàð@wµF; Üíác„7{S°=îɺ ®Fß: çÆà8Û–/&CàK˜¶á[£™í{ø3]Wç§}ùÜŠñ¾’ù¦E®$é~«¤ÓñÕÚ“Z¹\ÏúÂÚž¾ÐÇI_ˆ¸ÉãOÿ¿NØÃ)[aÅþò“3[`Ýêum‡{¨(yû²èJþbžÂNn: 5d)©xßþ°j¾g:Šô`µ»1Tšž0ŸxËÊ3Äj~›!αõ]ѧçfØ 47¶±ñþ¨ù:¢/ñÔñü»Þ—Ô´¶º1ÍËsåšÔ2 <WÈkÔï ÇÈ£Ë:ê½Ú~ó•]ÔÎÜF°?xõõàn–ĦµòÁ°s^°#é[‡_Bš>YïSƒ[ŽÓ[Á]ºx{DÀ7Àþ(¶ó8ØÞ²+ØNãÜ C¬f¼Ù¼ƒë„¤ñ¦5*ޱ\7Á=Ðæ†/À‹Ê$Ù¯âsÄcùà+]¯>èË hoë3#úk¡¿ëù('®ÅÑï)‰6Tª?5¹î¸ÿ@ÿœâÞKVÑú¤µ³§—åà’¤//šÒ²¢¾è{êêB¯’k›ŠãaË謕ÊM⣋Ò_¯˜Ï§mïýÿ©7sú£/ýÁ÷ðRN4YÅ),§W-î ûÇÅ'°1¤Cnù—Â\…x‚5‰ãv&¬#ò¹™ôÎÑãÂï69އàyæ¤:7Ôó° \©”Ûc¦Ç¤L‰P~ײâáK…ÙßxÛ ×ƒ£‘ÕO¶Šò-)âêñJõâáìŠñ‹ÂàáæJhÖ¡IQ ‰+Ü]¶Ãv.¿à18 >€âNAÜ`¸FB1¨†å3rn—mtÂmËëÙç²økŒÏ"Æ~44Kl>»ím9˜§`†`¢ÞÆ¿›2û>¼Ò(G|3ç¾³.D•ôlKÒžøƒ>p¸ÞOÒÅãç}ÂoQÙò/”iž¿O@"²9c±,ãðKÆ¥’êÐÌ?“ºG‰:ÂDý4.üq½:\‹H›‘úë(&+ãk2¬¯À\õdn@×vdŸ¾€A)ö©#¶óÏ4ߨ¿žÀ÷Àá9Iu×&Ò—»ëÃ9° ¤é«Š—û±\ƒaàÛÍŸ¿õÃoHÓ3RÓZnRÓ†û y$xf2Ù¯„㔤³: š»Âyàmªª¾³ëì á|ð0nµØ1/_æ Ç®^áÝOöV'{ñ0®°›¼§ðŠº;D£CˆS<„÷†O¡8à¶ýØÔ+¦ÕeùœÜuS;ðŸügßì·tdâ~+]ýϯmòøs·þ?õpØ gtOÅŠ•~g·Z=ÎDJ5ÝFÒj-Ûu˜®Eòü=}zÏÅô+.6c âV„‡ÝƒŠÊ?8™ÿ\ŒÞØ=®«LÂ̓‘?ôJaÓÓ>„ßxËHÃÆŽxÃuŠYOƒ3êÌWN]ó¹&xÏoµÄpö£¢ý¡Ï¾ƒÿ%n¤áÍ^ZzÀÖ"æó0÷Iÿ>pª'Í×=JZ‡ñ¼ÊÞxŸ Åt¢*Êb¤øÜôØ!×Ú˜™ºöuÈsµÆa+t‹,ÊÀÿjOªò¶å+'ÕóC©e@Ý ZöÆÀóÜ @§·—/QúlVîLv§Ø±bÑéHû,ÓAOŠ»È+~*†g†}Á~8EéKÄ3ÀŠ.›^Ô¯7ì;é‡ÃSYæ‘|®À ²ØÚ,qìGÃ#°Æ±ãµmâÿV{1û8æ|Oæ`y÷ Kk¡Üz(VŸêDÁEjá45½H³Žb=y7añ¿!í°|ÿ•ÔðLHÚ<¸ÿÄ]>úeæ®?+°iQÞ ±ŸQÎå*,X”¢ŸòKûÄ4ÛàÍôÕi¢\LY÷5©¼õ)g7x fmR™³ ²X¯ÓóXæ…ùà>!iLÁÍøƒ¦ä>ðùÌ<“C=âyãsÐ’°_5í¶Y4•7Ò¼Oqs‰•ánu—îI'ãYÜóBñ-®vÝ3Y2„Ê ù³³ò߸N†âD³øþZQ¾"â88&„Þ$»Ð˜òy÷•ÆdbÄ.''r6ð¢ÐlqbßõáBèX<ýð=ü„&ËäÓðs¹Ù^²`MRnA'Å{Vâ .%1­^Ë᪗R…5x’6—´óuû>çâ?´ÔÁ\ÃôüÀÕ'ïsžZƒ ãýÿÞä­â:”u¢oRqLÒ2RªõæíË’l€aóD¼nøñÖ+ ƒ‡U½‡]¥z4ŸŸCº*é6;~q Ü ¯{»Üõ2`›|*HÅ!œt¯ƒáð,KC#ãaYL{ö$2n=b^§wx6ÏøZ‡«-ë ç…uÁ©w×]•G°/bø а¸|ЙD¿Žóˆ½2~'³Ïù|Xh%™„%À÷=½I|r.xp0Z>ÔÑL±ýîÀf‰ý÷º,~×s;¸=¶‡o³ýœ/'Âc¥Y#0ÍÆã¶]·Ó¸CäHçëqÜ»Øt¯ºñR1=×I£»ÝoŠ+#7«K²·nÁp4di‹åÖmŽáò¿îƒÝñk’Rý¡Ÿ¶É¸r•W‹‹´p)¢1›ÛS;ÛL¹žÂækfu”Ãø yfTãœãwáñìô¤° ¸8MðL®&±¸<߯añ±<,¿¸Þ$~×î5ö Ð/1x»U|Ír2¸ÃŠßsÚñáð ë¸Ö+öËÅ0†€å-;€—Š%éù긗¶ý„OmùXiþ8 WÝçØççY¥õæ^UÙïЗ„ý½˜ËÈÀp**T"Õ+çO/–Q Gž¨[7$×€¸•ô#¹Óð³¨)*†r¸išþT'Q?›ýúkí6äB¼,—xÿ›Ó´šRÀÈHHý–§—ñúCÏ´%²ød¼~yêQ‹aù+™ö…×SFWtíŸuzàoÛ˜švÍ‘K%ÆoÓź-ß—”CóÒk©Ï ƒâee$húrñÛÇ«•ÒÎ>q5øêƒ‡ˆì¿![×Á; Š{ âÉŸý-³p;»0DžŠ.7ôìy¤xÀö&±ãSÂ!0ÍÃ8Ý.®ŠÁWqB\í^”FÁ4° œ ^ÆV‚ÅãÉ_içMMþO€™ýÆJóG ìöjË…ˆ˜ÔšéÏѼ.úwçÆL%tsýR’‹Xg5Ìœæ1œJÔ•Æ©o™¸~'ëvÛh£ú¦+iû"ŽèÿK3“$>¢*ÆçuZ®4é .¶×ò¸·ßK@&î!ë ŒŒ}•ÆŸJ¥v¤:¿YfJ/ï ê W%çÝ çn<£ý[®†µÀU³±;BÃF®êâC¨âtEùoà˜„ñVýéóÔ q·Ïý·wÜẽÝî¸|[-SÅë&=;D'͇ÀÎÄ…ì¹ÍžjŽX ¯ ƒŽ§Ÿæ”ÛŒRbuKa;À)F¤å×S†«ÜöÅ‰Ø ®„ØEJaûrlçÃáà‚pZ×lp ûëÖì=Í{„ÆJkFÀѾþã ;~8·TEX6#bîcnr%Þv·ýŽ“ò/¦•³ æ ð6M*•i’¶ÏÇiþ^ýgbÓãîˆEߨ±×ßñ‡B¥ä&e§õŒæGoÖø¬p Æ­ÏmmOÒ–’Ûo8ÄöYO—úC¯—¥;z ê ©øütÝPîÆ2=C6‡Èg†‹—ìÌ^¼ó•ÖÀ„3ôáþ8î©E³>Ãi\L¦åâ[€§‰96 s,i¾PV'%â;sÓ<áOóXWԛǿ‡Þž2†s©ågÒ=^ìŸy#oÙ.DŸ*åKã“–åBÑÎ#ßþ<é<Á^yÁõb{ì“nêOÛ›)Õþ±ªŸCZlí¹ëÓô®ôÖ¤¾¬uiÿí'a°_ž#!†Ï e/¸î6Ðd)×WŸ‡œÚZÍa4iQ<ÿ/SwXÔyuɶR»ˆÒ}è~ ´ïþ±§ðVÏŒkÀ‡Ír-';%®ßqƒýü* ·5®¨õÀÝ|3<^»{R¼jŸ{BjÐ*µÉó üþ~¶Äõo&¾IØö£Ô3³7{ÿêHûÙ¢Øø÷ã·­>Uìþr2‹Mgcô“¶)y/É/pFebËý)3‰²:sC_7-'-?Ñy…òödM¾‘þfíÌ"“LQ®Q©?TB¿\ZÚÇÈùr·öÜ…?x<[Ü31på.‘V(³³àD(¸½¢ééw%}2»¥k} k¤.¿ôMñð0‡%úÏG¦_ÃUÐjñ2ò¼YGEN÷M°8Ì\l†à, Ý..ãVHÌËm»çÀ°9'¨ÑD~p0œ]þîŸ2F Ý<Ð|*­¥a¨uI¬Ãw¨JŒPG¨ü§ƒ·5¸«G€ë1ù5÷/ÕÄ~N ÀCàîü%¸ìS*ÆìÊ„{JöÃŤÉcýM)V§í •bçÇ:Ô TYŒs^Üm˜ÓEHߘ‹ªj‘”¥ûy›í–*èðXï×|Æeä\Ÿ¡ð[å( Š6’)(—¦NµôHKËr<#^×v@;íºŽ½ðöÌŸxd^ñ«ŽLþö@&è”D.%ÔæÑm?™%݈E¶ †Ó8çøÏƒÚeso‘_ª®É(£×6”‘ì×û(oAê?Ÿ ÉTy»J툺Ҽiœþrñ©nèE\ê2%1Þvä|ö'•±5“Fðb˜‰½¿F˜éª¯ÝŽØš?ŸES“–(5ç늢OÙ›t¥€B^‡À!œ4çÁä _‹„Þ](ï®%o#:‹’éXªÕ5ˆôË!d{<†=ŠÏ:œîýL—nSkfýÏx*Ï~îƒGÀïJ(%)Ö»q©ßôÀs$tñ6_¾£H+9…ΞlQé’Ø™÷a&È DMåå+$;T¯%Ç–à€v·¸ZÒ‰*W¿»Õ•~:ìZ#ǹœXÖ̰l6͘ƱÒâhŸ¦OÛW·”{‹äÚL7[êFuˆ_9|Éyׇ:ú[%QõxˆŽÇÅòUÖ˜÷ÒQÄv%Ký©^Äë†?Ò#®èšq¡«›îqü~OíŸÆø÷áièèt_tqÌ^¡ìÇa+èNqÜ_kb…ã`Ÿ™j‘0‘©îjæ/)ÍruD¹š±ç#PÁu9ø6<î®ÙÏB/Ññ2¥eçqZgêoe…þwÚ™8©éú~”°çB¥/=|Pt°ÊÙ)¢K’–YŠlÄ3™–‡›¡•#ÒHÛÒ<>E/»ƒäëõî_ßü¶ëM%ŒŸÈ×ü¿É;ËùÑóêüXÛ‚|ºÆJkGàM’ÿ|œsVNÒø˜×¢^¯>“~0Ö1{­k#tâÀ.–Qk8Ío™ù𲮥0ßqm,Ù¨S·(i\ê½4.õGº®ñAÄÃ6Æ1ˆF¥þÃuÈèzÁèn±¹#ÀaèªÜF–shûk5m1lqÞµ$û⻞)Å4æ±§JCUN¢ Ê%V‰»‰´¡§ž~:3ÑUš^9‰‰ð9PóžÉk|Î’[¼QEúÐqQ­1°xKþ4Îø.‹z  ш.Ú¢üNÄ <΃‡€o©8aÏ‚¯pŠßÉøÖäŸàkž—ÀK‚cÙ™8ù^ºÞÉþËùb©å›^ÿÌ·ú¸Ù1}²×Ïæ¯dµOÓŠá¨;÷ϿƾÉÞDšÖ2=ÜÒòÔ‰M\ÎMuÃB©—”9”õsL¾î3õ4å‡i©?ÒÃMuŒ‹p¤ÛŽ4¿þˆSÇp´ÑpÑoX±úápòÜŒ{qwFº:uHd[<€×QD—Tí¶²><•ùêÿ¸›,ÒW€í÷ @=mˆ¯ Ò¼–w#·§ uú­C³;Y…|¦û³¼UAÇhnSù‚€—è<ÞÕÝIÕZæíÕÔ ¾ãrÎ$®çÔ]>8jóˉ“½ÖõV´)øÀÒÒ…má‹Àœp.¸’ZZ!åwU&¡€uÀÕf›§€VµÙëøY° ¤+Ø:}O÷øÕÆîð8éÕ„’ý)//—´]Àç«ÕÔǦ5eN¼y¢¶I³%â&K©T|èDz1ñ¸»sI<67_¥:’ôôàëtZŽ…Hq-ÑíÂû¤ÍíÑM¥áT'üIšÞÿÙ?}<ŠÄAñº§¢áh¯á´Í®é a†áBÊqÜFžÛÕ©S¬z(¸=•hbG¨{>m¶÷þõ¨î.òÜ>¡_ ¹*KLꬆ —UVírŠov†À™J²-?/ƒÎ&•ì ÆÝ<û±ÂÓ+-5ŽéÛ6Ð¥Qšžðèjt#ï(RL‹p¢¿ eìM‹±Ñûàw‰”Ê,£?Jù•i>üÙÁŒ»À[òç:YVÒGÒ þ†;£zHÙ*ÿ:ǼkyÊ—ÔµXûa—4Aµ°Ñî™Ð÷âà©w,oYJü6B”åD™šgáHh«)~†—)Ûvlö9dÁ[V:K/›©–H28ƒ7A«Fˆ¢›&¶y\¶ùð2Óè’²<¿˜ú*/ÃÝâ$*>ùo®rǦ¸š‰ª*ã’êÛ‹OJ׉ªêc»<³l=~ÛÛN@9®‡rk"âË¥Uª¾¨›—15kâ+×O“ÅâfMe?”¼¾Ž@þY..UHÓõ+i\,ʾS½4lÞè§ÆH¿„a*ú©údõP´ ïß³‚U'É„F·èT£G÷HŒÏ¯ƒpåľاÙÁ>Ú׉ Yâ¹áyә܇‚æ,¦¶3ý4=¦.+çWÏ>Ö"þìÆæ Éínqš-,ÀƒÀ¶C=…{.ü|3ìù 8ˆ1àá7Shå‡W9wWg;°•m¨§lÆÛÓ‰p*xÕ ØŠøÌ’ð®e{mwlê'v}X4Ëè~mdf™Ç~Ô6üþùs»¹é"i1EˆOuÃ_Ô%Þåv{óÒ·izäiÀõÕÿî”w……ã/ýc”õD¸œ«NHøÃ-Ÿ–©ß½ê‡_û)ËŠ¸ˆ7®h¸Òp¢Å>E©sÍ[A†ÿhôàÐ\< WÀ4Ÿ%ê·x%“s>i“ÁÃyÑ×<Ø­Î@j{¦ÎÝF3ãVMœNMe=—›èç——7ðv›Œ×‚š²?ÃÍ ô¹‘Â7_qt&ýPX¼8iÃÐn],V¸¸ú¯…ÁàëïnmõÕ+¶o8xøÛÞ Àǯ—>©û«|õôÁý?öÎN²¢øã» 9ã$9 ‚(YD¢ * HF²€ä,I2(H (A‚ˆ$% ’A$9‹üïÿý¾™Ú«}ûfvvwvïЫÏç7]]]]ª«û½™Û; I…XƒÐñ \/ér­¤‘žT+y³Ra„ùœmGŽýßïóáíçDpÐQñ¥n~cj'.ÛÄ=× …Vtû¬ãû›UÁàp ðš« ;V’ýsœT=ïïàX ÷îúr¥×†‘è`à\|¸˜Ÿ€þÐäTº<6ô?véOw?åuÜg^âœâðÃÓAé#–ÆF“Aáã¡òœfý,¯óLÀÿÏÁrÃD˜F7LV¨VŠ4ï…åëìÃñÃ5#€ôf¨\žó™VCfó!oÌˇlA–ů x囆,Ò\&߀Tßœ –[Mô6xÌo¦NÎ×ñTº›¼]öwׯÏ3ÁÂd4–É>Ï ¾ò©”õÿå«€çsÅ:ÏSÝŸxÛè7ËÝq®Oý­á¬úx ØÔæ@óömL’íÛKÁNÀ‡Ïe@+dø›¸Eí{ >ó`qòW‚'Á\@RwPŸ—Xè¦*ƒF†øv’üç™Ã±è $ÏÑÞÜ}öðŒ‘zÓ×öÌŽ«ýE ‡ ö^Ë? 䟬>ÞÇ]wÌX ؆ôWJœèÝ€Ad c×Îêà6Pû™GÁŒû”ˆí±Ñ×9€{¬ul ª¦Ë~¡%)×É|”J£?|ò¿€SaöÐ?Œ˜e»£U+9³• 'bc!Doý ½œÏ|”›*²Ì[f›e™yÇ>l¯<ÊBnrÓ ëKYV“tûŒ®m†ÔêLà ´¥Àzà^`ÅŽwþñHŸ˜ÿÛ@IDATc¯~¨‚¶mÇÈË¿ù àMóžÎòÐfÞz&—ß;?òè$—½?{òC†«ùæw °? õÈ·3u¸­>›D?|š÷‡êW·JÈaDÚqºNǃij`?}C€Ü&çàâ‹ÔÔ­6èÔî €>+¾5>¸ ãƒfäD¹ßœ)Òr½ð¿˜Üšö z›, .bÑAرšœ0ûÿ90 ŒF½r2ÐŒ,ßxµn«; Õ†t7%GƱq4x3àÊ_ùÆti•#ÊÄæ‰ÍÔ¨åò¨¯<óÖ¼|ª7=›ºë¿ ¶¬´§‡ÿÏ@ÓÃ?·«íÞòÑ~è™f>Ê FR¹Ì±¹÷cŒÁç¼õ">„¾2)ç£N­¤×OÏ`ãébà~p(º‰Q7’ñ„ÚŒ>gûñLIqWßñ¹ž:y,æ¥Ð™%ñÈ»®(-bËãËÕx»5Tä¥ãËàWÀo=[!çðwÀp—ïB­ÔíMÇ¥˜p¨÷ X¦\à´"·KV Wokc½uðáW6¬3û*é+f9!©hhY;±<ðÚö(ßLõäÜ”WƒÃÀÞ€[{Ó±¸(ÛcÀëÀ«}o‹‹JÒÎð|±ì¯õ('hû x'?6ODÓ@^ǕӪ^•ur^ý”/šçésÑ»¿e®2›e÷ÜjüåÂî”lwtj„<´Ëù²ÜrÇz‘F{‘·ž¼dÀJ >òqAV.ÅÜ_ûÿñU_“‚ñf¤[³ÒÄSào|Ã"E_£OÊ2o>(Ë3å¦!4Ë2å^4Œž¾w€»øÖqº5à!Äoßc#ÍA§þ5[›úò½ƒ`»&s¨½p¿â;_§L^aQ_y,b¯< ¿0ð•Q_(ü®/uú­û5w·»ß?½¥ê#ƒ”Þè€#Á™àÀ•›”ÉòëõN—7x_½Ævµõí",œ7Žo>;÷xÝ3EÇJ“»A]»YðxU¡åd+)t¢0ò¦P=é8 ßÚÕËf/mè›ð•¯„•l†Ãx”Uå»ëLè6J£oa+RçOßy¬ÊÇáo™”u˲(/›n8!o©‚w]!3 YN£®õ3åzÁG=òsÀ¿þ[Mü¥èz[|„’Ž˜ Þ@Ø‹4Ùíƒee ™i®#ŸË¢¼.{׎ S\FbÞ"µLDÞTHQVN«ÊŠ =?¬´̆ ]ù—T;ÐåÃøþßë³#bb+5âQ«Ôk¤ŸåÖ•²¬Ìó„_¼Uœ…Ôà>YÒg=‹Ë€—•ã›{FÜndO=þe ²¡&—Þ!Ý Îí¾lŽÍ]@áwÒÈ”Òóky¿¨­T4(Y·CÛˆ½°ãÑXsÍÐØ¹'{" Ž4ð<AÖmu,#dçßœÞÑþâÀ„ýT‘“8ø.X,Xç W7³ÂûÄoôßyOàÆïm1|:òZ»LákÀ£Á›Q³tvÜu‚OcŸpÌåMäft-”éÇ"(òq8FYÈsšuB/ìT¥èÌH#Øôþ¨Ï¯œŠ?¢„NäëQ¾1ÿ÷=üµ]n«ÅöºÆö­€Íívµ¡z`jú‰ÏM9WÄ‚|¤V’Ïs¼eQ/Ë”W‡áöÈ}b<í~Tç¥{kðCÌ|›t 00Xþ¸㢤ý Ì+Ëùà#mTžåÍt[‚5ÁjÀ‡$ý,(×õ­À<à›Üèûî vqÊ_¨ëfÕ¨>Ti±Þ4öÐìu½Sߟÿwê¹®ÒQ`÷‚ëùáåò…øð‚ä·H;éßócÍÉŒ§ûfÆ=ü½ÔÞôL:CvˆÌ« –ë ¯ƒ¯ ô”—‡¬Õö7䤔?ÇÃ`ã->¼#&Ûq€v^iw«ç£œlŠ@yw±œÏö('h× «ÀÅz^Ü‚bîc3™*‹Ë±vÁ[7ƒl¡c¹òœFHÕm@Ó£sß$¼äI°ê©ïÇt|+³U¸ô‰¢mÓrÿ"o™”u¢^­¤VÆü,Lt¿ÝË}ÌQÌ]äÕ——b>ƒ]Óeݺ8'¡úÂN2§ŸÈkþß“™xXnæçƒi€ÕJs€§ým(£Ôºôªd¹<óYWyráçEÄ ÀÀX’õ«xç÷èÿ› Ã_¯Æag«=Æ2QÚor霒þÒT¤K•Ë_›Ãþ“fú@.åuýéIÿÑ n¸ slÍöˆÝ"m%oH§ƒAùýÁFmÜϤ \†¨)9;}­ÓÔ`_ = ºÞ‹™1B1‘îœíÀåà;à8à†6H]7>OJÅEa}Ò§AÕø£»ÊÞ‚Gƒ7®Ì'¯LÂ?»wÞcƒDklZF^;ù 7i޹LÞ²e^Y™âèK½üFúëZ£•Ã?Ú*§å¶‹†ê XÈõêÅÝ|—ù*ªÆ©ão*B/§êF>xÓqç©M—íù–€“K#4 Ú‰CÀ÷Á_€kªÍ ¹aæׇ "ÍúÁGZVÏòÌg½›Ú¿ëÀpàáe°=(—oª æð½3y±ú»ZvGãÍhoê’߀k©ëƒ¬>YE.»ËÑr¸bÖ^*-Nù¡5ݘ©^j ¬ØmÑN*¾:óñð/6Rëîõ¿ßÄ¥¶<âªú1‘šµÜM4 +ŸõûKzÙ9à ð óbaÌ“‹ÁSZñïþ&™\ˆùÀ5àWàQð(ÏÁ”Èj^?-\Õ’"Gm˜™–íàý‰MiVùÀ ™ «çÊäÕ‰|¤nX£Eèo¾=›y“¯—¾Ä…r$¼õüÁßI<¶å¥RŠöªÒÜN¹Ý¬_³T}è«ub.b~,·³!¯â• )뙲H••èò#xìô wG5ß&j˽æ%|:à…€ù*æ%Ú#[è¹WÝo1¦\Þˆ·nPÖ©’åòà]×êOà>°°Rèd>Ë ¥ôa™}÷¤uŒìè8yü6n#Û_ÊSÒvëUàÙô\ TÔq˜.m9—93~-]Üøn€Yøþg(ÉNÉŽ¼ºëXÌúz=¤Ê'Î ö—ÑüÚàj01ˆGØ‚§Aë0p,ð¼>ûj§ÌFñ¶ ³øoκ‡5ÇQ{f`¶uÆë¸÷Ê ;&Åœw½b aļ-ä¦A¡1ä9 ×UÞ´…®å¶Bt2¾t,{uÚººŠ'à¢ßúOî“u¥¨©:Á ¥|cYOýÕûU9ŽèGŒ1tsª­(—:eË$Ú½²a÷ØŒeÁŠà u}³v4°»ˤ(Þ¼‹w¥@ì=غʤ²št´¼·r/&w‚‡ÁÛÀ}ÿ°¯Uu³ •J,g¬«ð×ùóKüIá_ó—˶ÕdŠ&¢€Ï6í í® y¹Ê¶™6gÎå4׫²Z[òͶ{Ÿ`p›QaÚCøð÷a6¨íȼuœvú‘#‚Ô)Ã2eSÕ1%©ä§Añǧ§%%tûªeƒMv܃q3ð[ð.ø4ýž8gÓ€ÁîÀÃ~Xl¼¶ ”—I;¾ ÙlnÚðÚ¸Œ¥Yüb2ã¨Í3Ðɺ:·m3<„èÇÓ¿ zHÅAeêFRäsºê¸¾"“QC™iFèÖ£JÑDèñê˜Ù ì™I¯»Ù ¹v‚äˈ~؆eQÏ:e];æêd™ù( ¹iæC'ä¦R9_“÷äµ)ÛrGÿ£èÒ^, <좮ûpo03ØX&EyæíßrÀ'ñü®ºJ7×kÄ÷VÏ9|ÜÜ×{€×€òFu)*ÈòF:Y®šOƒkâÎF›tt¬Cù d‡š–Sì7¡¿oSãÚÔÞ…à³Ml~ŸY«Iy;‹Úö€uúèzæ9bê9Æ]ã¼ÎîÍGÀò@Šr'(“rϧØËîY@ø»rÏžâãÛ¤Vð-À¯@¼†ˆ'YDƒJŽ[7ð©@G.Ñ#ûbc!¼y9g>ù;¡>u8wzý瀓«î«à°=pl‚*ò¤ýoß l Nwƒ‹/ `ÆQgÀ5^¾þÝÎŽÉV×°ë%bíÔp-"ïÚJ‘ÿ4dý¨§,ÊBW™:R’ÕB×2¾‰˜‚C"â€biqé]&‽¹;0“F„mµŸÚPÔEYžù.˜,Ûa¿œÆÜD}óQGYäƒ7md£.7‰.Ì6Ûì,4&¤8è²}Ÿ®O>Õ¯ŒR´QÅûlè޸ΙšÕ ½Ð‰Ty²ŸR~<ð’õ>ppQÛ·,(ë‡,Ò(31®×ãåãªüûq¸<_SR%æ4ª Vªß¾ 泂җ1p#x¸‰!ϸéÁ“MtÚUTÞ›}¶{65¶¨×š–ÔÅq¯4[$ÑX¡^¦XÜðŸöçúyoOÚ÷Bàeôƒéø8¼|Zã!Ô¬c¡ÓŸ4e?6—û3¦)&Ó§‰ÝRg ¸^”¼©I¡WËu_v/5»€CA£K€6 F’Ábá‚óÃ1ŽÚ;ζ+1ÑÔ|n­D&oÀržânå‘7<ìD]Ëää}TÉ>3uç{×›¥ƒh”A!¨¨D†ú;³7~?9¿ ÝONêJ³©íÆxõ¶ aù£Õ²hÏúl²L>äê˜òàs¹:‘ÏzUrdvsA>Ñûâ‰^Q¶àï#}l¼L—©¬o¹{÷j°8¸§ž'éa[™Te£VÒó3ëºÿW·ƒ7Ai‘4¶íŠé#—Uñ:qêß¿`.¹áÎÃAðXÖK¦‹u ë÷‘¶4áZ¡¡æ€/ú+ŸswÚág®å»1cê„> ¾ –1¹ÏÂÛ'hCà9òxx9¶žûÈW÷ü3`8xÎmÞˆ/­ç5ò}ÀSFA¦{Z]/^äm ¼1õ™Ü”€=À~À ‰ö‹²GÉD<Ï߀Â>LYçãRbŸœLõZ!õœOÇçBõFöeGpR¡Øj+½YW>[ä#þ[òÏw\Ëæ˜ˆ¸Øq2s]ü{Îrö5ùì‘r>7ë„ìƒüñÓ þ™üŽøÑ$IöuÿÉá=Cùª—ì¾VÏÿ”ÃØk|ÕËíeqüi”{‘vgÙÑ1;6.¥ü-lúÏòz¥ÔÜï®ÃZÑœ–ùȇ~ä{KcÞBúg³ç¶tÏfqøÃvõŹbŠ[6éy€ñwQ؋Ԃ̛÷0ž <¼låù¬KqAYÞˆWQ?ðIp'¨_Òàju#UšùºZW’ËZáÞÁ5üÓ¹—xÁ¸9ß*Æ|wîÎÌNöI°Dwq¿rvó2°ø-˜䮓í3L‹Ôò<|f!®<ƒK­l¯^{°WGÇ×ÃM@óV๢o;QB?*“gÉMÀóÊÁÞâ¬tô;ë¹öžgòuçöò¤÷cG7ŠCÎôD`EɃßÙ÷" Í ZE'Ý8 ‚Ð:z…þ¼¡ÈöJ¶å ~pØ´e–±#9IN†¤Ý»ADrÒNšï¸8ÇëdÇ\ÀvãÍ7#_»¬®ë‚ÞæÅ¾xø×ñ8mGŒ£~΀+7 ßÚ—?àtpçïÈ•®estûáŸÆkšµÔu575ù_üX°žS‰@ºXAøÙÇøÑeȼ„D½eñ»w¯l[2¯GÅdF¾/©m îƒLô ¶©7 8ù['óé’Ž£þÏ€+Ç?ð㧘0«WóÀlGç1Ò®=ÒÈ|ñvÀ åÚ˜BÜ– šÏ Ï Å)/Î>¸ä}–ôæXkeuòo ¤l-“ò9MíG”EšDÓЇ;¦ª Žfÿ¾ˆÿ’Žº5¯æ•pìÇb\d»kyí9SÛA9¯Nä³nÖ/&"é•í„n=½™tÍ™¶ÏÑü˜±^¡¤W´;’²sÀáàm ŽýB?óU²B™ë{¡0(º Y—lW>ËñŽ™·/ÅS×I¤[ƒt¾ðçºT–å|_y æ:‘ç€è\„çŠýð…ýù)óÕåE'FO¡]n…{\ÁEÁʽ¶ë±”ªÊï ž6®ÿ6?ùˆ2tß  QŒá\ÒóŠÜ }´åp"ó¿½A'õM¶9pæG€a@_“|Ddß“å„åõ^¹¤½3Àf@Ÿ·b'³:*Ϥò2iÀ× A‹Á,QÏXöpÉ;3®Ä©õpjs]° þ ê©÷Adڜ΄½—Aå&¦F°7Øø~ú¸¦?xEaµ0£ðñXï;þŽ{>Îýoâ{t×?H¿ú£©›Éê„ß…Cô*òKºì¹øø! ýXÞÍ2µëäÚìAõö yÒí¡§ Ês¬XÛžlpßBÜIÿ§¦Ž¿3øüvì÷='¡BÌA؉Ô>Û†ùeq—<ÆgyôK»UúYU èk°7?Ù†È=êMRI)Ríz‰¼»wc °]z™ºY–yãÂÁÀ º Èq&×¥¨ ,+ó>P|K\fF?ÞÁ—õu“•óUúÍtÊe¥ü(oÄí³ŽÃ‡wå§V±Æê "E3†ò€êm9¼p™º¨È¯IæÑºÀ.û¢G™dCä| ìÀ–©l¶\Þ–¼ÇÜ€Ésθ_&êCëÃ`p:˜¬þ¶úª±¤<Ú<±òåxó"²ùq¡ã¥ÕNÙ¸Z%7^Þ|:¿ìö"8(s³îò më_ ìH&;m_Ü@€µÀPžqóyð¶ñý25P˜%'4ë++·­l0èCŒê¹îo}åví›WÚoƒ9Á`]D0ý?DÎ䓸Ãÿo‘.'€ÜªÂE ìJÅœàwçâ#ðÛp™Oà/&s8›¨øK](êž“åM>e”…ÿGyQÀGø§ùrYè4K­o;ÙNÖ>ržv¬PÌ}<1|†öNÆ;Ù‡ŸLU e;Ö¹,d¹ÜvCŽnq~æò(+ÉÌ:tû÷™Eøæï÷HÀ¹â¢éHü÷õì[èÁvQÈ"í*¨`´1¸Ä¢«–ë©å™”{¡Úp°ß«rùêOsÝà#Eµ œo…zÒ*ÎÛp:á·"»×¾v^¾Qý6ÊÝ.Û§9öžëï‘À}¤kêÝ2÷—YrNmÞnÊÇŠq ¨/ ìÿÞÅÂiÀ3A£îσ•¯M¾®‹qìDÅõC²8ÁBûúþD h¸7#êµJ6è@ò y {•Ëí¸²ß,é‘-@7’!¼(øídiß v(xÙÆù ¼Å¶ÂFèŒÉÔùpƒcw‚ jäâo˜+Ï‹:ãÒVg`J;ùDžämÊ(þ³òñ ÿÉýëÜŽŽU)|< –º’侨–yƒ¾†/™‰5ѯbí,WžeòeŠº¡ŸË£,d¹Íåý¢J¹^è4{?¶ânlþÝðÃiyc÷ùœÂÇïz£aýl#ó1î,«ë›|€/E »ÇÃ4t*ê8EÃøøÏcÀ=*B¶iop?pÿh ë)ÅÝ(˃tv4¿«€è/l·6ÌE]Sûr XÌt¤(‡mÈ[ÔŠ~Ö±^³|.˼õߨÙéöï™Ò;:ž¹½ö2Ô¢Á ×1ê”L q³÷œKþ3Ph´iIsp” 碛8ªžâý£€‡²~gσ?/¯ß,®ž…™œ@¡E¾\ö( Oƒ}ûhÈÈÎ囋 ë—Ê”èIòûˆÌO|\ð–ä÷lŸ‹L=ÒA•Úî-û g‚í똑”ÍX\”^"u,楚w ØÇjÆþ§>§àT˜WÅ3ó›•Q|ßÕY|¥¢ï=^{!dœŸ î2uý« \}WEÓàa >—‡Ì4 {˜ÇšZ7xu¤ò… J§¦Yû¬Ûó©þæyHÐC¢­Ðë͆UèÇkî)t¯ÅÎBøæ‰  ÉÏüKƒÝúšÛ>™Í¾¼Ûvõ)t¢E‡r¼ìBp )(•wÕ ™kw8p︇l(Ê`»ø*Y./óæ%ûhà¾ØP×u=øØ¼¤°i–•yóAô£<Ò¬§,ç[äGq2wÄzïÉ¿V¹¯v óíH=«¼‰|xuÙþ $Ϲ’ÇA/ôå3÷¢ÓïâçSpŸqí‡X¾i˜Ÿ3芾¸2ø1xxñÍ1âmò(¯{ìÓ ËÝó^6ô÷1Nv®êÀö`<Ä€\i&©¸ýÿ†t½zÙU¤[íĺ½r#;Ö‘ý ¾á0 I¦ÓÞê¸/)þêéMpã¨÷pfµ‰øwÝ7ñ÷ág.¾N9ÏØ©›†‚_ttìæ{hH²’•3y ¤°\Ë® Ü͚ˋŠÈ¨ùOê:$e»a#ôË:‘»u}/(çpÊvrxŽ2†ÍÐÏyùœ¯ë&ëek`žãõÀn†¹Ý>AádƒOŠKQ¶SÅ×íUJ¿Eþˉ}aßšŒ¾îMÁ'œ*[Ö§Oyø¯†÷y•~• ÕJݲܶ·‚/' 7{–;÷§/%{Ônþ@¶‹ÙS!Ê"Ͳ0Ш,Ës½Fò’½QÄ£NâÑÂGs1»¥ö’Å)–4QøI‘ëùQ. •/“Šº†v§Æ ®ôx§û'`0ú•oËUÑ­èûåi¨Pí·hÀ€Ù˜''ê܇ÁÔ`1àÉIsêL2)(/R9ºvسçGÀ €rã“ïÿ)n~¬ ¬çyhÞ¶^|‚þ3àöT¼)p_k'nl&Gï\8†›Á—À²ÀÃ_òz|jñï.òã>šÍ€3ªë^ÅoP¦æßÄ.Y<‰q8¿tåðCjoÔ–@ó^Š–½RÕ¦PÆ¡Y|l8ùr¾¦Uû´LÊú5ÉèÏÐ IŒ.Ò¨^l\2‘†~Uýª*S† ¿ö8¶ÑþÉþ»¬DÐý›ò{D0R?÷1øœÊ§þZÅÃ{ä§žÏá_ü ­ÑáoýéÀÎàŸ`'°øD;°]|•,—·Â/Òa`[P?=¬ÖÕF™Ÿ§Øô` àÓZiÌ]uõ*]:òA­ê7Òk$×~EÙ(/ÈðÌqKí`¨õ,º”ÉêS2õnvUŸ‡t=ð1˜|”Éi: xžyÈöÈö‰6Aûh°\E­k­U!o§¨¾]úoÒ˜ï%×3MZW¸ˆwݘ`‹§v/À¿žy™œ@‘©œ·L™¶ÿÆGpv°ûïøp1˜ùÀØDvÚëä àP@@*þ®¾›”€^¼ÜNjpº |èµÔM¬'ŽdÿÖ§‚ÕÁ\ÀH+ÙçõÁÝ\À’qT=zÉÏ0£:ôV`2ðeàœNŒïØŸâçd%÷Ù•`nðh™lI²/©’|&óêeÝàÕsís¹²¨#¤žu#­IG·[¶åÒèw©¼3Ég¡lÚ÷aXú5eì½ñ&¨‰ºÿ²T·ª¿wQgMúùæÏa¾À|M^OäMY³âïÈ~tv0#htøSÔEaCA_yÁsa½Œ7²a€^ì|èPWj¤_+íùÙ.ýVí4ÒS>/3¾ÍùWµg)ò*ÒUç#Ûë$pÐ<˦ÍÈú/ÇÁšà· ¿ä´‡?fGÛƒM±EûÝŽÕ—6K'1¯Ù"綠œÜ(Q—L^Êe5ÉèO;÷«ù),KÁ÷ÀOí dÇqÔâ{6ùOÀ4`J°>ÐÕwB/Nœ:c#¹H{‚ã@ö$åŸã¨÷øLñ ?ŠGúõŠ_H•€7ë¼ ÞêùEàçP¹ è">-ô‰´öMó†Êe-çÕ X.…N¤ÊB§YÚª^¶a)ÚŠ´&íÖîÌÈf¦|&i‡ÿL\ª;ÁwÙSÎ[WåËv”AÆ­eWâù¨øá~TWj”º0>Bz‰›ä:d»êe>leY3Þ² èûÔìp1¸($Ͷ™‡â_êøöníRÙ‚²þPò®³s`­ Þ´Ì#*(÷o^F.U;Ø}¦’<ÄóÀi>Dz_Rþ0 ˜ ôvø£RÝœ ¼RËöûsAjzøcc å•l¬Ù]¡ßt65ÿÆz“’ò:Ô$5™#ȇvÖ“ou„걋‡M@ʶj’±äÓ{½Ü\ ô¶¨é6à ð} J†@_ü±½÷:°#ÐÖ>@{z‡«º1 °cŒÜ”îžçÀpàXßX»0ômì 9éÆÄûwñG4F±–û#¹  ô‰5žðgü|Ç÷<)“SîT{wœ, úD±N®Yö'}.Ê4Xµ¦å:êYOÊuk’ÑŸÖ“B'Òštôg#ùhî}ÎòŠºþàÕú©ð;øñ9dn¦/ÓÂ/”ëÂGõágâucçùÈÌäy¥¨kÞEú+øøð}q3*Û(ëæòÌ«ùH•ypΞ^<,‹rÇþ&ðÄ»¼ 2…^¤–eÞ±W­o蟞ëE‡â‚¢NäMµ¸ ÔשÛ|#î"Çy°MëIÚ[ñÓŒ¹øñÆå,D{‰À°Z1Ÿí¡I0s80Ä6@“1„ 3 ;lWQ6`Ñ€.[Ðü¹aNÂæ©+±¶¦LŸñÆõ ¹v’k,_Ö·L y-W{H^Ì{ày Ý&Gé$;yÐ;ÞåŽúfÀ`ᆜ©÷~=³éײõçê‹U®¯ÇÙW¬À*€Ûw×3`ÇQ0n¬Çt:‰×VSóogGñíÎâmÏ=”üä'8n×»ÜÒÁŸþoLî“ËÁwÀ³À—G}¦Ølúš—È[|¤Q§¨P/Í­,ôÊ|Ô‹ròÅôÔkFQOà“UC§®_¨Öe_Cæ7#ïVu+yG߸µ> Œ1³}™a\HsÍmŠÉ€¸ÀàeTo·È©Â*¾JV¶WÖy…+À¢À‹È+@2X¾ ܨ ¬|¤êTñU²²½F:Ê ˆ+€ŸžÎŠï†Ö&=pƒ Ê¢y2ÜËÊ)R´5ül <'¡£ÞÛ ôCn*µ[11ìšÿX̘‡gäp¾«µ=D>ÓŒÔx8eý¥E¨x3p± ‘ö×f«õ|°¡Wû¸’bP¦á7¦!·’¼È”óN†öŸóý[Š6ÕLîÀ9MA‹›c€ktøST”mCêáífk•b|Ú×ÉœC€“à{$/@潈œ Fê4ë Åm!û´ ø>plãÈø"¸›¿Š5Š£¿³øñ§‡¿OWâ'À@íáŸiJ2ׂK÷Æ»‹[€ñ½lÑÀH? Š(¥,Ë-·,Ê͗˕թxÐlRzÝÒØÝ„õL_m%Î]'¯âWôÆ“l«ŠWf_Üs>‚ЋQ¥LyPèFòœFY¤–e>ë$uãÒàz`´ÿ¸¸6ÖÝlò|*/…4Û—“®,§¨ ¾Ê£^9md§‘žRÆ €Ç£Õx#v/að¯UµJú ÒYÀ?+K[Ž_RËÃ/µ5«K „^ºÚÄ©~¢Q¡ŸÝ ÜSÞtâR Û£ŽºAQ7ò‘*wmcÂòD|6•†"µ]ƒù¾À× ©7)x Lò`ȶDÖ‰UtÓû*^»¯õ§€›ödài þÔ ÏSÚÅD%¹ùt °1÷.¦h| ~ø¬ôÞ„|Pü}„ßÔ·ÂH]×İ-ð•–këaªÎN,ëåÒDlËd=—{zðj˵ú¨Xö›ÜQËÊåÍÌ稙^UY_Ú©ª_—­Iº– sñ7\ƒ°iÔ¼:úûêàð2¨¢Ð4t"iÈ#ÍrùÜ'uœï7AÕ¡<1òÅÁÂ@ZXÿPàeÅù¶¾NâÃAÀJ™TîKM:0y3»a¿œ–ûᘌ{¾þ5x8®Ðcn:yÀšìû,Õ¿zý®Šý#§q äKSÝgÆd$m§M*mGG­;WŽžFjYøm<¹—õc Ö ^È+{Ì´%…ýÐׇ—w<„?øÌUÕâA!gñ °$øhõiû}t}ú[ è¼o€R ŸHœ(oóÛ8xl/nøöuižà„z8ÅÃö‰¬ï&¼‚åñéŃÅïÓúk±OÍ!eGã[À» oc¾^Ü|ß¡äFÜúqRƒ²Öù p>ȇ?Ù"0sY›—`¥ G\¶¨/zJßßßì‹þèÆ ”ëÚ™vP#ûm°½{ãÚK0´ y;é‹ &QûÑv¤®¥kº?¸½3…^¤¹L>ä‘f™ü„~@QîÛûûÔ2ù€}Íä›@/$ž&s‚i€2ÆVøžqÇýï% Ǫh qW»U2Ë¥FeäµZ£?éµ*÷0ðt¸”Döq{¬ó,ž{V¯Ý×·›VÃàM`•~v¸w€ìnš‰iX•ß7Ö~bú®òvRv§þØ=:³¯c`Q/ò1åÔuv}7Ñaë¨ôÌ~~ ¯{–#£“6Ù ŸÜi³ønlyÒ¾´ëtàuVºÛ+²ý&ûæát|!Ðÿ5ñGQ@údâ•þ¶@²Ž)IYodä8ð.çÏø÷#‹¿n`MKûbÍ:c;9žíÁŒ¼Ú·xFî/à.àœ{`HoƒËÁ.ÀíìlHZ˜œÐѱà}µ¿ð×ßÃ_s’¦=G§‚HñvÙT4 ;øÔÊj·¢ÓæžóÀDìsóÞù–Á5ñœ}Ê©¼‡é~uÓIã—õwÕoć¾å^Øsþò¶ÓŒÜ«?³ë ßîŒú“~g\q\Œ±È{9ððŸ|| ŒyÌd»õ'÷­YYÖkÄ÷§¾u‚®;ççÀ14ê?rÿ{æñ¿Êwí¿¯ýC´ÛFvÇó)š7/ß*5Òu‰ö„Wi@ïÛKqžöÙê<ŒŸÌ„„€|Œ!ôãë-Ääx>蛑/׋'ýzµ"†êïêKÑ^-W{3ð.…Ey(Eá`¥n¶ƒÀÊ`)ЗÃõ‚tâo-Á7·ØÁ è›éwRzÀ=À $ybøã§X0õSLαA%/\.—ÿ'Æ’ìܱ ¿|ŸžÜC`wðß@á‚s3˜Ÿuüœ;;ì«0^ŸøïEú)çË€|ضλÃ%çÜùÝ‘¿ô÷tGÇ`=ÚE bÈ;j<¡˜ÚfKGñ‘n4ÔTŒŸ ØæÂó˜‹/3'{Ò ×'ƒä‡Õ€‡Î\ÀµsC/RD]”eÁà\äȯ•òʶö#¼L?¢Å>:d»où)ÀÞ` ½³À,À=,9>÷û­@ß|||.¶g`6&eÊí)Ïù¾òíªoìÝìfާQ_(²ü½ÍùM$ãÿÝõýø{Úh@.‘t ` /$Ì÷—bºÕÆàH@‡¼¿v«êéý¢“qûKy¾Ù†Ú?ÿª[)wRß:€\#'Kÿú`=:ÎÖ1‘°ÝÖR¹°~“ãŠ:æåß3ˆú:}¶¼ÕœVó80aûLNˆÎü3°È%Ûvú8Y”_8å³YA,¤g?À º1ÇÅwýÍ¢·ÁäVA{'6æx\¥xRöLz |šÉz£øŽÿFŽo÷‹ÿ¬/w<«9 pmÝ î:Vš9.§ñ”Âå`:ØÁ U0Ý`ïŽ5t=ÑÅÂéæ>ù_øK˜ypw×ìA°.0hI±‚÷ » 8xaSÏuÌzd Y¤ ]w×[ÙßÁ¦À8bþ*{ɼm…„ ƒ[ðåTÛúßœ`e îFÀ Á¢@ÿtŒÆ©%°ø*°Ki Ì±}Êí*o…ŒúnŸ‰Ï^ÀŒ—úBQ.{Xôš²A U±ét÷—^¡¢Ks/ˆ¥»X^íWÕÓmBÓ¿MíÉ@î |äM=‹'ú“~§ÌsE ÊuB¦®ä¾|ì ô_)Êä­kÞ‡ç—À°Íùð0 Ûvº ‹3€ùAŒ4â„8Af¨)·)ï“D¦ŸÉn™Ád ¹e’‡ß9 Yx”øX—/ ìt2ÚQ=ž7Pki"ÎÜ<¯(1æíNúû0ˆÝ”çJƒÔ–à,à…+v7láÜo^ŽÚúµ¯•-Žaš)–ó9Râá§)éÁ[CÜ‹³iï¤cùàð/ö¯{XŸ5…í"eÜ®¡‡Îä .éY?øHQëzb×7NýøñxHFúi ®Ö‡ˆ)ÙVð‘ÖÕ‹ä >µw ˆ é%]»e}óÂ>E›×Ã{8 êød“|Ò’²VørÂHý£?õÝ7öy+ðsà<*˶Èv£\¦î×[ð¯ké¦;ÀŒMM8ÓS÷ÕÔïOU§³ßÔ[å<÷ш²r|ÌùÐ˲àcO„޶ÊöŠ“«j<*$5<¼¦í bÈæ¥öÝÀƒd¾YjåòÄÛ‚ÁÒ§§Fól-€O’ú.äöf¨5œ0õlñ%Ï+Ï‚¸ìZ>6‘#pEÞäIê‰ú¿¯®¹WöK€—·ªÍà˜ÿÎÇ€xó¢îsÀKÔ5àx0¢–-û3%m§ï`Q,.žEÿKäY·%~ØÉ¶ø_äôË‹À `ÐwïMÇÞ¾ f±Ž¡ƒ¨ÐWO[Êÿ 䀑@Êz5IwY.—÷Bc,Û ì Þk‚Á¢@Z¸Kí{P¶²Fi•n•,êç2Çú'p288×¹œlAY–y ÍóÕÉøfýYÇØFò¾årOpt?íVÝ+ûiª¥jUa«¥Š*ý¸Aίþd~b JQnš)òQnYÈäXce¦Ð-§…èä*6*ž>sÅðú‡ô>À œL¶ßäÊ{Ì<¼ ´Ë.¦ÞíÅòy”»q·_å50’Ñ-Bz*ßP~‡ÿÞáÏ„ÉgŠ?óð RÝjL3n÷eø…Àÿñ÷«—âWý[x"åÒ÷«À ”Zc µ` 2ïS⯀Îx8'7€Á‘€Ãbe<|É “méÆë‚€gÛÿ]Ê 7Ü’¥#Jz•Œk(ôÑ7#$×k*pÐ×qáSëZÎSeqÀkϧqË£— I_0fHQ¿Ì…-”»—ž^\܇ƒOØ6Í [P”›É¼ùÖò·'L?v|^^–óck¹n³|.Ë žó‚FÔÛJ4*×ež¶!ä]Äþ[ò‹ÕYº®ïQr9}¼—Ô±Mšù•ã>ÌVï뤷[‚õ€zãƒ=xÃJÄPe¨)&æ@> Êb/Áþ×P'ûû÷YŒÏ}œÊÛ—â˨¹Icð¥½ÀWÞè%Á2åJ%¾ë%ak° ø6Ðïßúy­°)EÝ(ä‘v+$rÓ©€¾´+˜D< D…¾‡óOÀvÀ§±2•õ£<Ëããa︟±qÐà} ˜dÊõÂ{€\Ü;k‚w@P#»–7* 9k?ŠËÜû{ógé ­Ò(NtƒFä²»,(ºQUî’ųEUy»eNq¿ÉÃ6“«šLõb¿Eªl6ð 0žZ7OŒû&â¬i´•u–ºÆRÉr}µTuƲ¾’«òKp0X 9Ÿ þ´2ƒÕÁ^ìz¨nöÿ"ànpba»6;†AYR×úgr„n¥Zžú¶nîQ“×þ:´Gm3Ò%~58xx ጰMé/õÒ/’:>/ ƒß‚³@ø¤„‹Ñ¢¬¹w¾1Ivenð,ðœð<ùo£ Yù#h××}V&×%ûè¯ÉϾ âéeø•ûÓõ½ èßÙ7Bq—·…×Ej™ùHkÒÑŸ!Ï©‡ÿ2àVàBÅXBQ—]ˆ€}¬ÒAÜPnY&Çæhçl0!8  ôoËó¶ÒU*ɺO‚§€ŽªyE܃Zi³®óDŽC¶á§ gÔþ`[Ý$7Q¡R|k2+ÏW"ÓÆçAR•joíTÕé«,»n_ë¯:Œ•ჰÓóRÎÇ ²¬¦ÕóÓ‰z›m#ê”óÙÞl”ë¹h¤¿äì¸ÉöÇÀ`“·ÜKÀ÷€‘yl&çÇ›—O;/ƒÁŒàRp>08–çRd#€‡â» L.¤‹í¡ÌÆ,0‚V<¬Ëx†_ML†tæ&˜Š²[x?ªÂ†ü=`Np0ð²ðÂçØ|²Y 8žìld{óà\6ŽÛwwßæxTøç ãü+¢ÞL£2$d?t¿å‡¤µÑLë´ Ö<ÜíM6§õR#¹±‘È dÊ\÷€ÁvÀ5} \ ægƒ¿¾ðØ‚²Íà# HC©ò*>döKÚÜÜ[Q)¢.™|¦F:YžõåsYð‘êï>i9G·ßì|S‚_ JRPÔ1“ùr>Êëëàd°È'eè .(ç[á£^¤×Θ\5Š’æ.WÙqê qeòNå^(ן¾ö7fËêÎWõ¡e£®½å[ÔðáGŠÍí$o*$mY”+“÷MÛ’Àýç%6×ɺu««ÿg‹‘¥¿äÌ<ÎçƒytvÐÈ6¼t,žÞ~ìØD.¬}ú#`à«B¿7€«T5_ë;ƪrÄ]¤cHê^pÝ?tÛ³íFóy ±«\[ûp=ø=à0®|ôuŒKƒ€íøôSEŸEèIþàEñ~àÁq˜ð”Ñõú’¾v^Áôá Ï#¶‰Þ¦•!!ûáÔ ö‹‚Á`÷qqÚ¸Ü Vm#ô:¿ÒúÌñÁŒã•ºe4 ÌwÁ ÀCçvÀú¢û2Ò+‡íà) "¸fÊ6ƒT½*>˪lY.Üc¿€}Aø1l¥]åR•ý,Ë|Y?—e¾0œ>ì‹sbÿþ쟗f÷æWûüPEÙnðîù‡Àùàl íF$ê Òm¬äzþ¨ÿÄŸdSYÞ&Z;ׂ5úhoôíÇï€ÓçôîÊèîå1äÕš7~„¨mä~¹\ßñêððuþ]Ç_€À‹re±žÊ·ÆöƒµÓž¤î[WûˆråÁGqäíÃÁp‚û³óÂìûBÿp÷o‚è4ì “Yüìò’#äø'^ªÜ˜>*˜tÇ€ÞC¯Ù<¹¨w6]ŸÈù¨ºÌÙ¶{+¤CzPO VO€iÁÏ€O-‚”s¿ðpߨ›Ç¨Ý»Àƒà8𸠸³^õ­#9¿Àogc_ÈÓÿlJ•±–¢/‚;À}Àa¹ƒÝ×¾nSºÔ˜èìÕtzÍé÷þô?|ÓÉ ×Ðõ÷Âö4øx0p” ëUñU2õ³¼·úêê£\^ ÿwßÌ ô{)ÛÊ|¹Ì¾ûæÍ`‹ØL?—µÂÛžñ`pðð~ÜV ƒ{¦*»îëèx?œxmë/¦ºÍW=?Ê ÊWø>´{zÌ«e ‡fXqªó0[5éù•÷]ì¬Ûé¹¦ÍÆ9ÛT©Y¡=r}]«è¡ø%Ø4šWcë Ï¨oÝ€“ྠ{‘"ê’ÉKQ'xë.æy€²ã©ÔŒ4æÊéÄ>ĆRšžÖ¼ >6¤­ölÌùð°l ¶ÃÀà{`pñÜH½Í•Þæ‰²$hÙžÁ»ØžA~ð@ö±s}ðPÞˆ,s¬+‚=Àt œÑöŸƒ]ÁV@¿ñò6¼Âù­gý¥iöjîP¶;Ó:ôí(°,Øô¶´¨ŒUt'kô­ÍéÒY®×I@¬›=•Sýòo`Oð[àÓƒ°°žg¾„—íP\P–WÉry𑪟yóSûô°pß„?ÁvQ¹^ÎëƒÇ—)——󹬯¼×Áº`3€¯oØF’6 æ¶cß¼¤Ý\·÷APœo…/×Éyöw'N~†ûœµÎæTëé2™úk³¿õrÛ½ñÞ¹BžµÅÒ/Ë{Äs!Ÿ¿ÈÉ1î»ãw™ô‡ÕÁõÀËeÔƒ-xÓ˜ ˄Ѧäz>4Q‘míCƒºüg€è(ìÓÄõó¤u'œ;b` 9¡žº™hý¾ÒøTpq†’tDçsSðSàº*« ¦ˆ{N:7ð$Ü<t:o¹sŒS€ä…É:ASÂ8‡ËI/ ù§ ý}|¸§<ƒ¾üU>8ü» è|Žé,Ück/q«c€:ú|PÔ‰Ty+|¹~¹^£rýó4°,ø0˜Uµ—e¨ôÐq¯-öî½ÞôQ)(ëõ•ß÷ââ¥e7ð"¸xñõ¢ …Ýiàÿ™ÁQÀ>Gl7ÊòVx+g½Š¼ÿ"À¹žg«Ú·ª´ƒ^ÂÈ—Á0VîúLUVó²²°á™”^âPW¶Ã¹Ó–eY”…,òõê]‰±õm09ÐFnƒl·6ÌçrmŸ¯“³¨Eð'é•&BccpˆŽ÷ZiÜ[€s€üP“îæô`t£:낃‘Þ₨×há(jH±Hñº†ÆL€ü8àIv.0zííkÿí»†Ä¥@»›ƒG€ì"à%CdÛ¶ç¥c°MÏ1…t¬§ïÓÀË>T®8I™vFúz6>NV\ðAmžøO ÁÀµÎk|¤w£,oÄG…VÊíçýà5àEÆ:½ÕC¥¡ŽuµY¦F6ÉsýF:Yî<ê0î¿ ÁÊàbຄžO›ËÆŸ(ƒí3of”m«g^ðð¼€6@IDAT ãt÷FUÓØ¨ŽaÁ0ÚWrJ¼C•»ÚW;­è$çíÕ´­H9J3Á¼PϨˆòœFYز,óú\—æ…Í<šÔUu4Þ>OùæOvŒ‘}š< šõ ŒÑ9xœö΃7(Ÿp§-¯6ºè! &ó4Rh“Ü1Mþ<¬¿ÇÛ` ¤ÝÅÀcÀÝq\ VUojÔÿ=˜à[ËÜ ²¿’ëÉþžLçσ±•t1­_|·+¯î®Ûà»`)ðGàÎ 9ºÇ"EJq7 y¤öÆ·Rîþ°/ç÷áG ·z¨ ŠŽv3E?"µ,óUºÊŒ^~Œ%;€'ó}*pœü"S¶Ý oݬWÎ7+ãbøúYµ·Î¹ ™×^³daÞá o6Ñ)9M‡€íAy:ʺíÈû,Ô6Šù5ußé»AÊÊû+d6ûuÜÿ–Iú!2/…Ý(¹ñþ:0å|\ÞU¤‹Àú`BàJ 䡲X \ F‚,ì€È'U¨;ÁsÀ1›®<ÜÌ¿ ÚÕ¦º^AêåƒEþÐÏ1¹S=©‹×¾¿cÑ™µ{x¸®‰¨š#p  O¹†O1­< ¸„õ·T#ýµïO€oƒCÁ¼ ]ä49Åý&:y;\ÿí<™y~KÓß¾ø$À“=éIàv`€pôõƒ-Á¬ÀJ‘6â{+ÏõzÓu’§úØ]à,ð*ÈÔ› u«t´\¾WéG›UeU²²~#ß¾xùš ì Ö:Ô­@¹õ¢¯9F4²—åTí6ör¾7]ÛåÀy§~š‹âÖ/‘!äLð·’¼QÖÃupÐ {#»h7$¿E””•»^´éc¼vØÉ”÷\¹lÜ[™²®róú…›_^Ø)ë¯WçsÐ YÎgžªÅd¾%3|Ut±ÂÔ€§³âÏÏMZî0¢1Fzƒl[`Ъâ–ÉñjÃ1‡g>?˜ì ô|=Ý ÞÛš+Þ Ûm7:ç8þž¼Ò+¾{\žÔà×_r¾nÇ‚‹Á#àHpp‡W‘ü§€@×é<òÔ£‹Iƒ5ôšõÁýŒ¾ÿŒf:±š7“È!>:Ý ÖúÜlÀõZ|Ì|+ÃE¡x2u–Ý""Æ Lƒ‡íÆ›—•‡<ÒšöèÏ›ú˜è!è¥õ@àáÛkÍt8؊߯x©ð2í›/óå|•N¶ú‘Zæ\Nˆ¿Å‰¶;éNÀ˜ã‚_<$¦ûƒÀžÀ±Gl¯z·þ—ó¹^¹Ì|¾òðª57QN]މ³ ÞóÇ¡´J¹«òÙZµÑ½F!¬/6zèºîƒo7´yƒ‹EJQ7rÐÖÿˆ ˆº‘·B£úÊ£ÌËÅ<}mrÌFÀÍäÂV`/`PÈedÇ 2˜- ܼ;€@È+¥ÁЃé.p(ð`œX愽 ‹t„K€A ßîÚžýöÎÕæ@Ï~ô—´ëÎõPðFû'p ЙÍ;ÛƒãÁû È9v­VèŒ"Ðm{äàëÍEêýæ\àþdkA0öÙ~ѼÔrŠûCž™_úoš†Ñ—ç«ó³}áàþþ1ð1¸¾ú¢_è›k€ A©|¤!4ä‘6’[n?¶‡C÷¸.êFЍKÖÞ1~è³î_É·bµ.½Fúê©ãÜyÉì \ÇspOÎÔÏo×Lrÿœþ ¼¤¬cýwê)I7Ê}³ ç3_.ëf¤^o1~²8ÿ-ËýíùË;_ÅìUàa° hDv³ÜUu•9ôÁ"·F[(©6æåÁ•ù¨“Sã¬õ³nLDȪò–•å³)ô†°…£íKº˜xÐŽ­ä†µ¯@Ûó­’cvSzÓ–|›°iÁþ0@ ½M#>¥çs í\‹7>i crμêo œî’£€ÁYÒW>^:j¦ûÈèO¾±9Ž_oQûz+«ü7ðN1²XÊ%H}ñ2P*Oe«ö\Ž=Tv7 ɽïaò[p °‘gÁ0ðˆ`2>üÏÁRà El%ŸË³NYn™òœº–wè3l]e(ìYžù¬o0uì–gÌg}ù(‹4ËB7—gœÃkê…ó‘^Þ«çÝWS×yûã>y¸€3ƒ°eL–wÝVAÚ2vX·… Ëñê*ÿ,ÏEÄ»Ô2tØÝ[4]ÎC Y‹&ú¤fÿÚBvÒõÍ7 ß ¨Ì<®â÷8w“~4¢°6ªòQ–íÏ„ÁŸ²©w^f™ºuie CæÙ®u‰·e×ìðwBÅ‹@2B;NÇ÷ út1Ñêý"ûÕ®yvbœ·Áûô¶0ЄÀ¶LÙÞß©upŽ~ ®îŒ(t"U^ŇÌÉó”±^8¼+“B'Òšt´¼‘N+úÑFØÌi®|¤¡g}¡\×ï94‹Wúî‰-ÁµÀ½bÞ»Q›Ùvæ©RÔNjü²Ìõ\¯žnM:gŸÔvD¶ÑˆG­Wš‚;"}ž9ÛèµRc»æ49EWF&¥Ñœ!ú1à´=’ʃmËÀÎSïìl¤1;,þ’SË$Ë#®ºÆRL–òlËúAa7çåsêûW\®uT]®|è Ÿš…Nòzª¸]{àåÉ0Py¸ÿ8>S/ K‚Këük¤¹Ù!#ÖÛÝâ` Wkûïÿ½à-ð{°X4 4W’öœ¯ÁHpXü%çîu°)ˆ§Ø‚|B<ì Îöé0À;¹dŽ:¡öþ[FÚEž»÷ƒ£ÁžuiyÖÅmMfý¢¡ÎêqbÌ{ê#Ï×ã:à-å!p8¸¼2ÙÙ Ë®ßÆ ý,(ëUñU2ë†ä‡¤l›¢^éßøÓ¶ ·ÑÝwk]6L „ì¢w§VÑoô1Ë^¨çç$ÍdYPÔÏyù°r'P_œ+7«GafÕàP¦ìtå²1•w’W[€õ€y=ÉK ‡Má)Ô ¾pcºÞ’6¦È>ž ¯‚þöÅ y ˜¸ÙÜI:O_HGÓó­kžŒŽöíJð0ðÕÑ ¶‹Ô#@óÿéa`ªo€ÞÍÏê>Ôß¡bíSEÛÑ[ã²î¹Ø &ÝÃÄ®êf§áQ{’ºbðà¾þp¼ Ü#{€DÈvåCî‚qoî!h#Êaò–It£l2˜CAsV£zäT-(—+Èùà >¥ý¬òÉ:ˆ»ê*s¸w=t÷¯çí»2÷ß© öžs\eqAÍÊZѱ~ìCöY±_Í_ÜÏ^ÂÓÂÀ`ÿv=OÒW*þ0ûøÀ³@½²ÍOÞªçû’l޲!f‡^*å)êEµmÅ.q¿È}b‡M%c³ë Lßp-DÖ![™×ÿ¤#ëðŒÐžñ×½m5³i™¤ÏôÕ…ÀàÅ¿ò! ×\Ïúlî©Õ»Ä`n¦m‡ÝT­z88ܶNöfÀËÀ‚À`å„zAÛè:ÔÊœä~;?ŽÍ §Š·Ù€sÖ×ÝhÛ§Y}‚Ø S×ì1ð"X,"èÀö lpðä[ÿþ;/ ŽææõÌ}Úˆ§âŒñît.Ð-‹þŠ_¼µ=ÖݾÝroÌV{¼™€k¾98¸žÏûBß*“2™vÖÓ÷‚r*¾Jf]åÚÕÿ¾s€Ô¬^M£Z'×kfÇù16DndÓ€§Â_àãqŽçi&ùpíGª<óå|.k…/×7sæºx0þ hÏýû=p0nØçЇm‰¬Ã.ºÑW@£c£7»+¨< ‘75Ì–‹b©ûlßÎ휫2݃@?׿3Ylj4 Þrù™Á?ë¼:BŸÍ¤žd™”óòúƒÒ~ öÒƒÀ:;›AñKàF+âXh¤¿d'.­¬œ·”oƒ lSòÐñ ý1ðí9ÀFc¢hŒRÐX¸V;£¾|?ðøœ«*Ç+ +>œƒØ›`sð}° aÏCû `{ËÞqûw Ð_–ÿá[—=k‡¹ÿIZ…Q‹MÁ—À< UÒ­]&—£™«¼@ùÖ^¼¶áJÊŽÃ@¬©þó°#®¿ò2…,§ÆãÀWÁmàmå°•|³r^”ŽsÀo€‘=¦fõP+¨‘N”›6ÒQ^5¡Y߸bIõ—ÆÆþª/bΣ~¤uëC9ßH/Ë­ÓŒ²®„°?óËæßÞFß+€í€{¹·ýŒJ±—ŽL"3{ô÷(ÐuÁ*²ëyhê¶¾ îKƒÁ Ûè7¹G‚¢ó¦Ì]á?nf×'§OÉGuu Þ²\žu”…e>¤yŽn î¶ùð

\K M–‡.lAÑH¤!7 ™ë|põŸ*¿]Š+Érûòà^מû ûÙ‚²­Áäc’íχÀ˜±^уگ9ݶo¹‡kÄʪ>eªÝ(—UñÆGå1VÎzå|.˼zaÃ})ðºxH?ÆfÇ+•mÔ¤µOíÍ3yÀ¡r}]î´ „ÞjPÙnä®dÞ;Ì`’ÓÕ6rn³ÁH Ð4|¯<™Öø´>Ì¢>lAÚ¶žú½Àý­làšŸŒß’~ë*}@Ò–û×; ŒOèVÄ?PòDyU6P+£z/€©ƒ›؆—‚í“2ðªH€ìz”rIrD+sê'Ï‚“Á0p 0x·R_‡°­§ÀÛÀÝs0 ýè$Ú²ÉÔ¹œ.^¬¢¶ißyþ xü hÇš{‡Ú_RGú?M΃Ëàž>Ìf¨Ñ”—õu÷ΛÙZÞ|ñÆï[˜—À¿€Dc>ì n­þ±W#¥Z±õ¡…Á#`8pï…N¤ˆºd™·Ü>Þ~|;aPŠz‘"jHY'ó¹B–ïsÞý¤ß> Çà`Œø#з½ay)¢n3¾P¬´¢Ÿu Þ]Àþè(¹Œl·|.Ë|#½ˆ_FaàÞÝØÎ Àò%€þÒ(F"g*Àþžµv‘K3EÝX³¡Øµ ²^Èšê"m!çs p%˜HvZ8à œAYî>óAÍõ1PܼX6ðÒv1Ð]¯W±^þÏ |7úÖö¢­‘0ßäæy…òÑâS4 jåPïKnX'`Sàªý° ÝQÀÉxhÒ\`YàÝØCMöé/`) PÕËŒì.Þ/7µcô2ÈTÓ‡sáæfM‹¯¼@8':¤»ÖC]{±Ù–ü@ýÀíçr²Ù?wì¹àð8\ Ö\þ¨BUÕk%ÿ[ŸÎƒÓöwðm0-8¸Ìý" Þ€ÁÏl@Ì~ t?Ü.Ï ×óT°pŸd²SR¤™¯’¹o~ö#ÀÀýT¥‹¸Kn¹þw p?þÐQ•½*YÔ·Lß×ßC/Ruô÷³€É2}ø* ¯æ—Çh@Í”m o[žpÚ6Nä6ÈvËç²Ì7Ó³L²ØûîÙ¿ƒë€ñâq0¬ô™²mæîέù#’Gמ±ÐíJmÌ¿a^ nÉ&« Ûî \®Á$]¨-d¼ýø8”çQ!‹Àå‘×bôY'@µƒëý|903p_­\[ëÇ!öLƒlË „}4NïÍÇDwIú"+ÉÎO öNðôÀ9PoOÒÜ`!p ø< ~[ç'uðÞîs}²ƒFn²[Á ¼Ü˜ ëøö“‚ÅÁÚÀ $å…¬Ij¶&#£ý»ÀoêüʤŽÑt:`›¯2)Ÿì6óƒh¶MÄ Â—ÀïÀ±ÀÈày6þÉE`*ØqÔ}bé¸ÿ/“Ëzpú£ ¶%ºJëlŠëk:¬ŽùðÒ¸—å§ëš÷·eR¤e¾(,•+3p½OFð¼ØU¶”Äð‹â²¸éH©ªžå!4dÙ0o/Àe2à­œ IýûÁÂ`ip-x ¸ˆƒÝ(ÚQXÅgY#²Ü|¦²FeY/óêç|æ³­Ìë ÃÁŽÀù¸<v‡cбÑXJ·º4°i÷Žšµ)©Üåœr/Ì—¨8ˆÔ¶ €}4ö:@ï °L>æV´éÛàj°-0hÆ'd&01Þ®¡¶ÊvÃ&Eiã\°ð¬±ÞÞwó{—;aå ˆÆòPtBöf^è¡ïD-$yYà!ë-Êqþ¸áåÕ7¸ &œ"•Ûq<—Ø@®î  Ñ'¡Ì~»Q¿t¸/çÇ6tË…eȽ98x¸¿ªHÇÒaNßöñdà°8÷Ù†{@£ñ¡2Žj30ɯSÿp‰œÞVè ”–ÿuv1¬ ÎúAö_z ­l̽ ¬å²à#µNð¦úåë 7²]”u>žÛ/Ý™BWY™7ïž2o[d¹ýP¶Ès@¶°i÷ƒ{\²ïļâ/6E™—”sÀÀMÀ~ºobÿ•ûFQj¤“åVÊùÌ— æ²F|_ì•í;oœ?ǼØpرÑù&°ý/p_XŠ;Â=µo ‘ô‹ôu›®"›‰¡f^÷muTÙmEÖÖ @¹ÁTÈÍ; S'C? 2?9poË?ná‹ɼ6bb¢°«N”ÉK긶îÛN¡äØNf$˜4:¨ÊcO›ˆ‚ÏÕ Fjþ8pL]¶4éŽ 6DyâêjýNbqª Xæ¡J`/þz^¢±àQ'l¸h†ôL0ˆr‹"ØÉ7"/C¼רŽvïÍÁöà0p:0ØÖË&Ý©£ã¯dÇQk30jºòçû»UÒ=GYÙ 0;x ø´à:äõWg>ð7à†}Û¥—õ•K!‹´&íþ©/œV×ý5ô#ETÈôá£ÁEÀ(ž©¬k™²ë“+€Üw²ÅwôïÈ@¡+_ÖËe±§Ô“w"z^$»}ÀJf €|¶›mö•×f£:–ej¤—åê—óÙF_xÇh<GNÀA_|=r,©}æk¤—NhX-ðgtßæ…yùHíÎ`S[/1Ù ™: S5žÿ è—/€#€ûæÏ`u°/x„-'%x؂¦™2¯,Ú‹rSÉv6ÿ8ƒ¯÷xb5 ŒMdçíèà0Ðë ãsã»á|íûD°0(èä{uœìáõ”¤ÐmtPZÞˆî§À€67p¡m÷-à!z¸xÓÖ¶‹kŸ ìêÈë§ŸTÔ¹ ˆ-s>ú²f¶ý8 8§SÇY&Ó6ìŸå¶)$°ßÎÕ‰€¾=K¢IÕæ61ŽšÏ€KçùizX4£§)\hôd¹W#óÐ?¤¼þú×àO JØ‚B/R…ÁGZÓý™åÁÛ®ÊÅÖ·ßQæ€Ü;;×å7‘¾ ”GàRWþIõ&÷м}·n®C¶kO„ž²Ì—ó¹lb ··ƒèSÖ×ß]}û8`p<xa˜LÜÙf+ê[^EeýÐÑ÷¯_±Ç,Ëúæí‡Áx°Ø¸>¦ß:º—àLe;Íʲnð¢^ÈÍg>ÊsÚ[yÖm•÷¢ó2ø pÎÿйÀîfŸÌ}à@õfdwoÇ‚]›)¦²Ùà½0ü¢v¬Ú»¶Ro}nÖØ)‡³‡õõ hÌ߸WgÅðùÛá°áÀ}ìàéä>š ,~~N¸~(™Úáf=Óг͋Ád@?¶Ÿ–}\ö\› AØ1N/Òƒ«ÀN`(úâÀ?.NœäÄ?Ô‘ìϾ ìŽæ?êˆôuÁmà50ø¸< $Ã^'‘_,¬/tŒh¶Od=J‡2@¯ž–íé´JºcðE0?8 | 蔎 ½9"¾?^‹§¯#ú)Îõ{A‘oõãAcš[­ã]ͳfx«*ôœêò4T¨ š(ÚwÊÚCê-Bú&н\†{¾ÉÇ0°D]{A’©Aâ°5øÈed»ò™Þd^C7RýÅXè«’ýÀ¶`à!¹;˜èÃs‚¨kÿÕ‹çžsœ{Ýçóùîõ¬g=k½k^ëÝçÜsÝLFB|®ƒùlBç/Nup¶¨”·±Î–ó2ЯÕÏwn#TÞnHkÊ dƒtÃQŒ;"yfâ í»ÏÁ`{^€²¢­òÛé¶OY ¬ÿMp?¬ ?ûýïìT\:>Ç=â]ðp,Sj)Ë6¡ïã<ˆˆåÍîs7‚sI}püÜ×Îklmhƒ›Ø‹X€÷5C«ðxß_Å242н§§§ºއÓà°A®¥iÀ1v]xv”ã­(¾º!\ï†Héog:Fó&=å$­ “¦¯ºo—2Ù?v Š»•{5e6îy¸@RaÔ•úFê"ˆØyn*u¹çÁÁŽxJî ó7 ¶Çô VÓ<ÁÕ:öÁ†.èMá§à ª¯>'©›¢>›Áw õÚý ðFà`;+ðÃñpcÎYœûãÇàiø.샑“‰<®­úõR”kæT°ûë÷·^ò».]3#Nrø7"¾ 8Åî€ûa%œþ}8Їk2ë  çÆþ6ø5¸VʉæJ/ÃÌ wÁ6ýÊ`K"+A»ŽÊóN"Ýú]π⡛z¹PÊg7,}?Û¥ÇÖ×sÂXé§î@;IüvÓ£R÷iX;ÛM·òvp€VF×ÎÏÁÉ`z¤|†¶2ÞN7o½K¿”›°[Z|º8©7Ûâs0¼ö›Ïs ¹ô¼aãÆO0‰ ™X|°PuÅ.¹…2èŠSÐ’9žœsöáÝð~8Ü(µ‹ Ižà‰§á¸´öÒ¦½Œ×óOzÒÌ£ÄÞˆ5>µég=Þ?º–Ÿg¼åCM#Áˆ‹‡ÖpÂn,‹W¯ÇS]³%M}(e¢.wR“7€•£ª|¡¢Í~VÔK´¥qÚëb-€{±óNIõ”[Ê1]¿Rb7Œ_B7îéj¬™2ψé6òx¸Q¤a¨£R¼9[ç¿»ùIàÀm×ÂÑàûìÂ`QpóÈ` ™XæŸÁ70'¢õ²½N;Ó¯àpc~\ì·À1° lÿòMs:¿ïõ‡Æ?/Ç2øÈï4Y‚ð4X&W±;'vèÆQÆìm:ÈaRÆ{«Ú²cVF?šb%X«c׊›O*U†ÎGñ2§<ÎIó_Ì—7{W_øú؆ep?1¯Ç__[½Àyýü_e~¼ZÛîún˜Þ€²©¥¾˜ZmPïOºå³ì«Á·¯4Ãø'Ä<Áó:¥Õí®ßôØIè{Âæ08ùM·ß#e~me¼Ô㟰L+õ¤÷ÚްáïÀ¹r-<^"ÝŸì'×»õF™‡²mÆÖp |°/›Vê$WbW¶³7“'*p[”8þÇÀ `ßÞ×Ã÷ÀK¡b¥Eߺ´KóÅub~ÛôI°|¥ìˬÇãS>/>Bóø¼ÁáñK÷ôö¿Öo FLœ„ž[@Ù€«@r9PG‚ Ë ØºÚŒ»ÈÞ¾MÛ雹m:®†5`0ßP´Õ績õl ªÇ›Ý%à‚w‘¿Ž7aãþ¿†á‡`~‰±äß™ò·”¬£Ïh#©¾É7Ã`s½GL‘ö=p{s5¦¢#_v.=é÷²ïÕsÃNP?üwwLç×8x=#w%9gOç߀ÜTý6‹3ã·p”’'–¶þô²v¥ïÒ­ÈÿQ‡àiêáœ; nëj[”z)ÝâeZ]7î›ìAàAçúk'e>ÓËx¯º´ÕÁýòð¥Àg~fÛZ—Neë×)­´×Ëk×p4ï÷œ©Àýæ¿°,Îû'‹µ£ï¥q_¸ô•ÿH´£o? >ÎêXÍ4-zZŒq§¸ÛØpˆõ”¤âf¾þ ›{g)]‡ôyÊqÞ»‰ã¤üÜ×»bÍ£ò¢VRÚR^Ò’'ñ¤—eh³ÞžK[sXŒÝŠç8¹K'¢Ã*GQº ÇÅëÆ0šÄr \àgÀµ°*¸˜ƒ7‚þ£à-p#(;ÚCUÙœ(¶Uÿƒá9È&ˆ:`ñ9s®`Þ~õäð<0–Õ/‘-@¸"8©|¦â¤ºî€- i;;Õg“¾âÊ1cVÀÜj‹zÉTñbQ‡ƒÕ²zIC"z€NÚ›ÎúßA8dSÎJ7l;u-ØæçŽ~ÿm²á\ðKئ£û/¨~Âïʺ ž†NRb'¿Ù§bky‘ËÆ[Èö7Ø ®Iøp¯‰´«AiëOwÞ»ö‡zK“7a»g–itó%Íþ·þ®³gáfø¸YCÕײ¾“s+¿ºbZJ7¿Ê¹Ã‡ù}«Ÿ¾î;Îç„ë~Epou®är’gbê*äÿ÷ºlY—Nü Ï)›©-ñ„Ú|Ç: |±™jb µÿ^o)žå·(íúÖÆÅ^oèïIse|~†þi8œOÉ[æÃ\•[Y¶zòØ‘ÎHüÇï tϯe¶ÁÆ$ÿŒ©Ã,VÄE{, væh;ÍuA}ì(7­mÁMV±þºƒv¸ù¤CQûÈ´Ä>n„ú¯Ÿƒµàï0Pñ9sÀ°,Öźy ±î{Óg;‰JÑ÷Øšb,m4OæÊÆï±2 ™ï“ai¸Ü-ÚªN‘Î=ð:i߃H_œÍñè΂ýC`Ï .h7tÇvYˆxÔÏÀ¯¨=ZÝÅ\]$éU ÿ˯Cý‚'o„7ƒ;ïep@3tþ·ÛÓ$·ú¢“®¯ð7°/”kª,‡¤–”ö^t3–~)ÈCÞžv\߯W‚MÀKÎó©ç‘÷˜úú¬û%=ÔÏü.¶M›‰^€œ¾Y:W”zù kÉ"*V¯¾þÓ4Ãv¼»ËÀð^¸ †C,°â}¼êÓ3 Ý]‹ÊÂàXÜõÆaªlUf#…ØI–aC^ÄZ P[$e¶‹—iÉó ŽWÃzàscG­$qŸéþÆe0£M¶‰´bÇà Ê9¼ÎvÔïÀº¹€O„£`ðÐ5½ìL;ï%p!¦CQ'ýÜ ç„“ÀbmÐ.Ýò’ÜG&fݬÓü`þKa5øö¯ëZŠ6/2ûF&àø«¨Öƒ;üS’óøFxÞƧH÷xÚdçD9§êsÁ4;up¬ÿ ÿïÃÉ9‹ý<ŸV_è¹ ½º‡?@^W½ÊÙëíu6X Ü…uÁËK¤î{=ôy®ñMÁµ|oç“e:oêëÓ`¤×j•e;%­NòÖC}K›÷ÜEá x†S^7ÈÂmÓWø¸ã‹(‡ƒãXŠýÂm\}K›ñºXÆBð7ðñG­¤]¼L+uó—sÀ¼JÂF¬á33‘£ÿÄÇ%FÄa¨B+ôoØN…ò†LtDåõ7ÃW`Cø)¸ÿ<õò0 ‰LÏ3Ý­ñûÃ-Ï&—ÕJ cW6õ? Ä·ÚÏ Å@KM¬gõ-@¹âlÐâàøŒƒv’†&_ ŒÝ<Î׆û‚ç±—Iýã‹ÚZé±%=¡>JÒ£'=aåÔü°þsÂìwp¶­Ð4uðž|HVd$Åç¹Q¸ \ n°nF÷oV'‡~:u1ï]p6 ¾ ´Îr7†#ÀÙt œKƒƒ¶(8™77Èà XŽÓOûÕ I;±n¶çgp0< ¬€±3ð¨kùå½CùâŸñõxìC²ý ^¬$ëv‚o®‡Oš°*èWB´5NihBÓJñ…nsð¬ü8Ø¡å'_lÆ££¶:8züG⟼>ã]pܯ™§ŒÖØ=(ÇÃ1ŽÉ81¡·XË› \$#!6Ð7cGÝK‡_“O.Jgé¢àmúe°ã•nm¾tìmÁͧ›/ÉÅ|ù iô7?ëû[¸ ©ûœƒš¶e =À—‚MÁ:{¸·Ëñâà3N @›އP/áOÑ^Ùø½²¡<ü)½’Ïóé— kÃâ°¼ÖÅî˸o©²cK›ñˆ ÑÃâ‹p¼ŸQû³ìY¶áÓª/VÎÅê,p™³ÌMtTÉlÕZ³M‘™QŽ/NçðeàZ:¶ƒ¬CÔ>­+[ê<>>o÷“2½ÔIê˜Vú•z™§´wÒKuGǵç~s3Ü®ã½á9H9 1U2 ŸìÁÕßæpz xÐ{9šôÏ>Š:ÚÄêYmï(ÛƒC¯Íéüø”bZЮ>Ü2Q+çœóFSŠãíœê0nº’´Äc+}ì4÷úÓ`epDÌW–=é†eÙÆË²7Tâ«7¶wÀ7ò{I\Ʋ É¿ °p£ã`Wðæ>â3§7–`ø2¸0=øÝD¬› ¬±³Üz-×.†è ÅÛ£à*gX'Ÿ±-ŒƒýÁI÷6Ðß6tÛ4lÓtØ…pV0åÿß¾¼LR–³’9Ј Ýçºõf¸›òZûy#ÆæÄŸ¡,/Õzùêî´ÜÁÛžÛª¿1æ ¹ "Žò¨—©–䘞¤ª®·³àð!ȺS·s®£a}`~ö‘²µn³ÁåÀ>U]ÊôR'¹µaöª—~eYôÒ¿®ÛÆEà­àè­Ÿƒ5 25ŠkݓӶ/«ƒëÕõn{ÝkÒ'õ`yD[¡Þ×ú“²{.Æy+°êÊûÁ¦ëÓ›ïùS¦™è €ãÒILsž¦1Ž—ºaš’xôøV‰|xF:ʱŽOl–§bš’g%^ãchZüz‰™®¿ƒb?” uPâá³6œnz©ê‹ ±“Q.4eKðísµçù.ªˆƒz6|쨡–ÔÇø¸aÌ »CÆ —çzÑÙvW®Œe£ÏJŸ\‡:Rò>$Þ»n€¥áµ,µñ®%sÑo©†áàÐ$ípü¼7Å u’’±c3ÿ¬¶›ÕS°0d®£¶ô¢ûµÑÁ7‘´:!¦Ê63á'à<ðÛ‚2h)Ó†C÷aý•ëFíxÛn_O‡;@ñÒw&œa9\ë9(zYïæNy/×å¹—\ÕhB»G¥ ³çœLšMŠnÝÙcæ»f' ÓËD_:Õè$ü ¼¼Æ•4ÆŽ)õw¯Ž˜¦âÅo¸–%ieÚË|¥nšÒÍ–´„ÎUŸã9Y]ɼ‰LŒø¶¼1œ ÿ„4uHÄòÄ@ùœ6ÈÃÚÅd²áh¨X¾el¶ãñ9~=x¬ KÂæUÚ¯X†›ÉJ0;d`±O¿þ+û¥n#)?æa6çbð>2'¼Ödkü‡s›­~‚ÐAp|<=Дc«Ùõ?Þ æj&éÏëþ³_zïÁO€¡¿‡éaqh·¯¸ù8ß¿ {€ ¶Rì³çÁrÜÉëå”ë»"ZÿŒK·EbÚÓ<=ùµ)±«?—À• |>^<ì=²Þqvq~BÙŒvÏLº[­YžØâoÜ’†Úêç½â³"é8ý•vñ”•4C%a#öÊ3ãŸÐóÙ^Ü/º•sè§œÛ.Êz˜úù, vL*Ž:QbçZ–·jß¼E¹±º€ÞüvžõP\ôCQ&Å´Ä~r þK€æ;!—Ô®âÛį@ÿ€›‰u½…¿¶L¹÷3iÆ¡®>Eö+>÷O𘎄ùáµ" ¡?Z•ûá.pñ;ç†W¹×XGþ!p˜³êÈ6ªdÚÖipõò ÉuÙI<Üí`+°7²©¢Vy%< |¡(¥ì­þto¡¥Äß ðx ²P’Vú›ßµªÏ@FjüÝ«\óü®oå pÍZ.ëtR“t‘áE0,nÑõ;\éKrk’Ç^ÚÔ‡Z\v%g’Û‹›çM]´}ã{qæG9Ÿlìtà]J:!{øµ$. V:åÄ¿S<öòyÑÍ›gį]y>ßo*JÖw²zSù;”í*Ï‘zl yh× ý$zл@~¾n{CO6˜Ôµ(®êæ|¬ ¶g(ʤ˜–ÌŒvü,ûÇð¸}΃' ÛsíÛYáX°66ÒêOûRÞ~—7~Ïk×bL.±úVÓƒÐSî+pÌ“»ØîC}›®7ø«àMtÉ É#èWV?è¹í!PÌ6yˆsóDXœÛÝĉò$^’üõ}àIâÜötù$Ô7ß²·¢[–{†'P& in¼G€ˆØQ[’üJ½å€b}¼¨¸Q*¥_7ݺ<35óØÎ«Áõ'¸ Ö÷šúɉi4Jš›ÐaR·ú±¥Þ‰ÆG‡Áe‘tÔaÏÒ‰‘Ù¹øwŒ­ÏA õÅó³°3¬i” TÚ50¶øègç- ûÀvà|Sô©û'^9ÚCaîS†ö²Ì2îúXιŠßYaáŽÝ‹òžjfб›Ø€caÈ"ìæß.ÍCмJ.!Žž•zL ^3]„†?”bÇÜ·Âú0” Òñðß –ÛóÈåŶùülR¨År~o†€[åØy«ýÙW~;fÌ{1±9ÊlðXÜû스¡NV’¶Ä<»mõ2÷Nð:foÉ?Š}±úëm“§ü€fùVä†öbMt2xðo 'Á\0?øâúx;”kQÝ5`>;<âMss˜±iHšû„“Ï5¦Ä®nY‹Â¼PÚÛéÖGi—ÖÍ^Nv˰=î×߀l»€ëÙôÒŸè«"Œ›w›ZVÇxšŸ4·l‡O)Ó–Wüw{åxiý+h·ú©‰Þ †\šeºÜù¨UÎã¶…xYóÌÑtB:*ó´nOz õx 8W/;UŸ @üËx©ãÚœèyvüJ»º’gúÌwÀ%äÇÊòìíHÏèbo+ftƒ»€þüqé#¾u¿oR.ÔÿÂáà8 d9ì†M,û4ø*ئ¡ë>+¬‡€e»jܘ"¶Y{9PI+Có]nn°N>ÆÊ?í{+}åÞ2Åê^îÍ£±=íêT ã7¯Ê錉óÙqmÈL|ßóâ°ýÉs0JäoÔãƒà@÷7ŸË*»l _‡Úððpv?Pì[ߦ?õ½À5vd‚é«zš¥.±'ͰÜáËôÒ§W]¿nâ ŒûÚÒ þ>øÜ g—‚´uÄå?<ñ‹ü§ŽwÐ-O½òô²[rÖ¹ýìׂÙê’<†ÁsNß9Ànk¼Ò\Š:ä’£c°ÛÆ~ŹëXÚHçY[ê˜ûH|c´SÃÏÄÐ õ‹¤<㥞ô„)» “VÏ—xBÛ1Ž¿žõø&”U #Ž:xxmg€“·?ñAéÕéÑ÷»àÀ×-­ÃE`ÙJÙ ËÐ:+m¼ÏìåÍ¥—XoÛt–¯”ýil Ç@6/Ô¶².Öa põ<6fÌ—Ø<Ü/G»¸s&ì‚Îýr²§õ;ïÇÿ„âzk³yc«‘š®Ï!ÓLš,ƒihÕçáD(Ö^ëzñ’¼Ì{Áöðgˆès x©RŒ+†î>?6Ô–®-ö„eºz]:ùu²›¿L«—WÆõóàpýï./6ûïÕëÅMýßÖ­)i’a]÷K »ÜûX™N´/íõüú=Ñÿ‹t”ÍTþ 2¹Ðgju¿ÂØŽnêíHR%éˆN¡çÃ"pXñ”…ZIo§§\“ž0¶þâžMúxÎìy¿'g]¬ £þUÐÏ«]]ô±ƒÄÅy7< {€“þK° œ ß˰ô)ñë›Çá›ð]¨¿Y`ØfWĽ°x«ófo»Ú‰þN¤Nm¶ï¼Xù툉/ÂCð(„jWò–cJʨë:ŽÕµxå¼Üügv>fÿÍÙׯV³À£Ê~-ȃS_ÄL>™¦27«‹´ó{ âËÁÂð¬¾!_Òäb‹À5ëzñÒ^†Dû,†raDO¨o]Ê´^ônùëiÝâî // ‹€ûâ]à:w/³§ÞnKÞˇnb¾ó9d±uË;i펮•kß;°*œ ^Ô»aZÈ8Ù8õ42!¦>¿½My¹}/ÜÅ70ÄúJÊ/­–§¤Ü2Ôžpûõ¾þâëî©I±^·Á…ðcx&¦Üœ«ŸðÞIè><¼Û]Ž0WϺƒp1°.uÑöœ‡ýÄÁÿÑïðÓ–§ÇŒ9ŽºÇ_öã)Ã*ÛPúžà}k—a}ÒȾºóJ–Þ¯Õ£™íÇT_b_Û¬A–æÈUèÕyÒÿóþ»žcù ;Qa#pOèUþ‰ã°<·€å(‹Â{Á+•kÁµZöl;½l•tJëÅnü¥üÓ½b9ø|lŸ·å‚? -ŸGt$ÄGæ±¥îÖ´l3Í!SÊôvqm—Ãò๙rQ‡M&úàmÅýwð©x†•—ÇèOà^=Ø96.ó³lh©'×JŒûÍÂádpø|푲ÜÒ–r&Í0ù˼å³Ëô2ß“dø†YÊ7õÜrÆ~–vyðÿlìŒ03¸ -ÜðGðX3>/á­Çíç L¼oÏ·Mtn|4dÓhL•”‡[l£!ü•ø9|\lƒgóÉàeÈ>HgöÚfýËŽ&Z}“°/á­À¥ËÿÉpüñ=À»Öä&ú‡ÀpÔ§¦Q-Ö÷™_óñ{~ýåê'x£º¾#Z9÷wùï½ðcØ:½I‘Ô7Ó aØ\k3ÂÂ=ç ô•@9<´|f'1_¤]ßÒ¯¯§¥ì¡ í«™à[ð$xññ2ð.®çû¢Æ«ú¬ë7î\åvæ#ý¢wøe„Ûhªaµx<¸Õ)ú8-ÞÁ'`¸¤¿³»—çÚí]ÅÚ7„tB»‰­]HÖ–˜ž35Fmí$ö”Yú”¶ÒOŸz¼nsÀR;ÒKöì1üŒˆÔ) £ ŸTvoß,|sø ôð·#|ñk:Hë¿ìÌìÆÔ³Ü…ç³°L3‡ek€›å|z|cœf#:¹Šóðf˜ì»wR†ì,¤±jûM*uñzº/¼Üõ¯‡^ÖŠy~÷Â3EžlZ®Ã•á\à’\}EëïɸI¹c×wþä#©µñÕu㥔y´—ñR/ó —nxbž—ÂCàbÑ>B¹õƒ¿l²_ºL ÚÚá=Ìaö¸0ÝáxæÓ´Y¾¿ö€Ø’a‘ú4èClÃÜÖî1è6o½ ½þŽI:µ¥—¶Ø •¤ÚiãàAHg•éu·>R¦'A›Ò-¬§å¬7ôR¸xÞ[©nCø;M_ë[·þÄë«õv°¼ÂDÌû(GÃ/À7ÁöÁ4äu€Å7œK˜cóò3¥Uø~üKðËrLºŒ )“¥¸®l£ëìÿ`èÐe¤eüµ'ž7Òž$Ÿç›ìzàMï·0=t'„'Äþ°Ìõ…`™¾õ;q.€Â·àðwCý9e¥ŽkŸò’fÞ‘ëô4ìnÄîAÙƒ»N¸MŒ”]ácürò}à¹P¦­âËÇÀ·û©š6ï~Kƒ?NÏßsrƯÏ}uXZ0±Û7½7—ë [a/’îy0xN(f•¡ˆÇ^vblž«ÂÙ[j%ú”RÆ“?é‰wò©§'nþä±~®¡½aó¦îz\öþ%ßAœ[Gñ«9L¨£R¬ãUp| ¼µõ'¶Éð€>~ [Ã>ð8Û#N÷«apuœ”5ž7˜µèì ‰þ&Õ_ô£ê’¬~7—/Á–ÍÜ£uJyWc“;’jú}Mªß¬õ” m¸óo÷Ù0ô'ì3ÕÑ:Ð s¤>1,ûpX'Òõð}P\Ã/¾øM@IDATežR7½Œ—zi¦¤8ÓøQlõÏhv$¼ N‡×A½˜†Jìñ<Ú¼gy?‹=!¦ê}èXÂÏÃÌ`šçˆò|#hå#êAÑmÈÅnI-;æ¸x Pf€48S¶®Ôõ¯Çµ9Ÿ¿ŽqÆ5~†µ­ß2=¶2o™^êúøÜàðX |ÙÝ \¿»Â¹¿åãp»à,„£U ¯ŸÞæ6Ú~·m¯¨ó°;|> ^$¼íG÷O7ßÊ>¶q˜†XÒì„nvq]L/±Š¡6‡[‰OüÖáû² @/Utî ¾ Úà4µ’Ä{ í¸wÀŸÀ E:¬]^’+éäcb™Ö)^úøLçÓìp<,þ¸\Cבgè"ð›¿ò‡].!C¬ú6€`Ô‰‹ÆÍÇ+©zâ,÷v½j“ ;$·;ÔA‰è7 O—‹ñ<çAÔ{éÇ–ãMô5)‹ÓêkaAèe¸F²“®¢J|´ϼ}$Ÿ;Ù<ËoÍ> ÿ÷© ›xØ}¾ n<¥dÓŠ-q/3ÁàÚõ \ ®ƒœF¨­±®×ã)Wûhëô"Ì~³ò9°f!^4Ùò~IÑóûÁLJ¤cjÙÔ·Ü¥áFxÌSú6Ò @•¶aÎ9/¥h¯KÝVÆÕå¸|ñÌW)¨•ÔýÛÙë¶äéêošsç,˜ îÛ”›j5x®C×±vÏÄ•aûYŸNBŸ‰C< )qpb=ž¿\ º ¤oΚÏÃp&¼€nùHîI¬‹‡ÿz`/nSö¹kØ—¡ò'̯Iqs¿¶Ë~>Šz ù×·)2aô¶ç:¹×€s`Sðà@·}=´½”R_ e<º Ê l^ðY†µÁt÷©<3þ˜*)㥞ôѦã¨Ô{`-xÒ6Ô‰‘4ß0]özôÒnùÆKb3|ÜßT½MÆîOûßü´×—Áš~VÞ¾íÔ¿œö»Î(mt²Vbù^ðß'jÝxø$,}µu‹{6ý®‚¯€—™zÿÝààº5ÝzîÏSÉw~‰3sW"nÜØ1¨XYîPØ|ëh'6ÄÃÿð+œ³Á6<éÔA‹å;ûäùl×(å‚mjŸ±,WêM××T°­µ΀_‚–[—UËã°QPÑV…C¦¾›ŸÜd#ê¯vúy:ÜP¼YuÚ±]?OAÞ®ê £Œ—:YZë×ò]Û¶p$ø†c=,?Ræ/õ¤ÖÐv, ¿÷»{áq𴄤é†á!t×d†Ø0iõ¤*ÍÇ»µ&Ý<Å0¿—¨GÛ°HñœA—ÿÒͼ7ÞHöÌ‘yÐ=ð<êbKÖ„ÓÁ³'’Æ'n¨­”ø$´£|‘Þ¿•Nžø`jÙÚ饟éJÊhÄqm³ÀÉàú8 žHò¤<ÛŸsÄGÛßp¸Œð,2/xŠ…Yqo)uDÄ™çÿ2#±«áy¸¡OJ#Òœ*Rêʸºkú 8ܨÏ÷‡ `V(Ë2/I“„xÒ>îw^l—ñ`€R #é»î ðå¹;jKbKè|¸­*ÚÝrÞÔ ”¸7bCø™3{¢Š¤fµ†žcÊ8ø'ø–ïܬ‹ùøÍSÙºÜ~ªÎ­¥­$i‰;vo†?Áb`yñQOù¥Ž¹ñn2‰^ˆm×÷À9ãà¥lŸ§žçþ]ÑÇ9W¦{vº–޼ÿؾ|/:eìæ”á·ÞÄGB¼¡x¨ïÞÖRyÔJŸÐƒÿ÷àÍyQx¸!MŒØQ3ƒsmþ w ¾V™‹è§`!¸”Ûa[x¼8¹°Ê~'ÚVʦ´u˜ŒŒ™[ÇÒ&à€úÛa¤Ä:|•YóÝÆÈgMµFª “÷s\«ÈÞðv7Â,ðmø0¸I¹±–âZë$eZ©ëW_-ýƒÐùgá}à~1©Š3Óúï näÎÖÇáð­Îôþ„}ú¥MYo,4æ}õÅËì„nß»4x®)‰7b!<•Èç fôC yP‡MœB-6ju8¼ ZqÓ©=WÌ“9Tï”ÄË÷–”vu/¾@?Ùô¨§kÖ‰?í¥­·Wsd3Èù\æ©ëËá÷4Ü öG™N´:È!ü$\Âx87Ññ_"Â% ºIMG˜L¨C.Žüµ°4¸¹D|¦qÃ5À½¬ï„ÜlP%lPcç&çW`~¼É­ê±r³@ÇÒ|yØ¿¾ ?€wƒû[Ù-Ýô2l“µd­¹Gû¢¸e³µ#ÑÍgŒ÷.‰¸*#ñèÆ“^ Ÿn"o€/‚ƒëºt#òíüÓðX.†üÔ¸>e¼“Nö–øÌçaYø(l¿†uÀ‹GYÑIN^¤ÆžÚ^j¾ö­o¤SAò2?±¤_.lúÍHè^õ[øØ5õîIÜpZP.C«1”£ac8sÅ<ñn1­ŒÇ>¹†¶uQ¸ÜXì¿áŸ¹Ý|OÿÿûépWeô—?1“Ñ5èæv8¸”a!pAÌîNú, ÔJÊx']Ç2­‘³±Q©{8nn´^N7ÇIYÜ„=¼”½`UØ–Óº éž‘»PüÒÄ;SÄî´Ãà»<¿÷¾ƒgK|QGDÊ3vbøOÎñn6½è\Ý…¬‡t¦ž$þ†‘9Q‡NeÆ·š¿n³ 빬Tnv¨­ÁŒž0å8^.Ÿ†Ø ;é$Uõö\~ §ë˜³²È¦þ-†§Àg›ÜK'ãÖQ¼lßÍrí¸«`mø6xÚÚàŠgý ýÞÞºs‰·)/0r‘âðOÔ›áÛ½óÂG—iñ_ûò`Ñ·‚÷‰¤¡¶tmíìú¼VÄö;´öÝÞ§?ˆ©8×yé|™ ¼Jé3&“Âþ÷Ÿ“‡ %îîðð'¢ÝMçIpà#ƒ] íòY®ß0 î€ë¼\°D'Iñd>þ ·ûbÙD;ÉÃ$,ØL´ÛJÊ<±»f,ÚP‰ÝP›g¢K5¨üüá:r=/‹,ÆO§~Oiè¡DçÐûAÿþv@¤Ôµ•q{ÅxBΘê-})BËôàU’ÞˆõÍ[üìøÌcÏ[ÏÇŸ‹G!#Q>sëeº›¯çèB`}2Ш•”õŠn(Þ ½I>FäkG4æâßùÎèúm0zM¤c?Là–ëõ±^8¦Žâáüد­Ò¿‚%á\°ó +Ó‹xrëkçÝ e¯õãÆ!äKÂå XUïºûø„¨•>á FÓ•øØ§›5ù(¡/?ŸýÒõ<$µòG7œÜ%}f\»À÷À¸iC)QØq°qÏP–;™•5ËëÞ7æ]ÿ›w"[åú½ .{ûϰ8°î û€o±ç€›¢öH©kë/ÓÚéî=>C~+Ê`L›Åvºñï ûÂ30¼Ü|ºÈ8Ò<´Í^ŠEÖIºöi ·æøå=$Ïçæ]md¨.Vmúøà«Àjhè&ΓmáÓ°¤ñ†Š›T©kK\]ÑÇ?‡¶ß/Ãá°)8f¦Gò ãæU´åY)ÏAq³´-êÏAéO´’ä3Rꉻþ|þ,à\ªK™§ÔõsÔ¤r»:!ža–qPãgCÆ÷{€OR»·…H·èæqxÃðôÜæþp&zè&vØ Ðìô±tÐøSˆ[&¶ü‰¿síÙ­hTuMJÙïÆµßVám`ºRQ鎩i—ÁvpxÑZ:åigǽ*Ïpr•ôõŠ4ÐiC8±ÙXû$éMÓ ïŸÇ7®}× ª€×N¦%_·&ÛÝâì Íõ1à¦ÏH\×ýRð^¸\0î䨛ŽkÓÎÄGí£÷´[†›ÚÇau8`iðÖ?©Š/@»Ã±p7x, åaBTI—è’w&m÷Äã[ÚOÇï³Pžò—¿FB†òP]þ²©xyÞtýœ?»Á¾à9¤¤“ê½rh~ÄžP³Ï\> ÛÃcàZPRF†õ•Ær˜7ÀJà`!pƒ+ŸA´O¼L‹žÐCïTð’s¸n;=Ÿ¤V¹Éohéa'0¿€ÅÏoüK‚¯ÜÆucP<=¿o…úƒ0U¿ôgA·À.°.̳C}ÁúPË­•3–Ãü~ØIW<à†r1•>ê¢ßp-lW€âxEô³\¥®k+ÓŒOβs¨/®¹‰ûÏéÄ&ö8³jŠtî—«Éùrg‡®)îÔ—‚ù]·[À9°>8 Ù¨P'Lô$t‹—iô”cès}CZn†ßÂàhÐî›ÔÄ:»z˜¸_„9ÀM½hÓ´D¿6Ù®°Ëjk‰^ïÒKHðÞäË«çEÿŽll¯ÅS0“8­†TÒÀ¯PªgŒ›´ k'Îå·À‘ðQHÇ•-Oy¥ ×>kÜtqÜ~;ÞàA‘2ÊzhÓ?i¨Õ%佄ç‚kÞøF’×xô”Ó¼ÕyQ¿¼ˆÔ}1URæ‰^žŽ/BìË6õónõ2’/þ+àó1°óÂí½°ôí¤ãÞ±Ž¦MNòs#§ÓaÐÒ›ñÓ7†È¢§H?=0ÖuéÄŒ°Î«öK„–ãÂó[7×òæà›†®bšëÙ5œ‰ZI·x™ÖIO9õÐEûð `}ð’r&X§,hÔIJÜH<v€Àþ<ž…¦x€Þ_»=ÝfX’´Ò6>ž;ªÝå,YLVÊ À¿¸µT›Ë–„GÁK=T݆o{Á×›þÚì°šëqmåZJº6Ï5ïôž6×L:µu°˜æó|“ÙN;Å9ÛéÐN\ú”cܲLWÒõzž¤*õtóF’V†¶×8pëyÆÏ¡Óm«b\1~'“÷ý\U§Ã8µº™…ôáò¥œ„Žkê[êc±±•>êÚK›¾¥{Eë_ š¦$=ºaYŽÏµ>®É¿Áêp.dìQ'(£]ýâg˜tõÉM¼(¹ÞV¿©u¿ŒØGo¤«¸”ªJ†v0ÅMöyè ™þóGšI§ HìY:yÌwáp¯gƒ“^9 â‚y3¸°Íç†Êà´&?êz9b½è–1ñ ð’â"¼œdÖiRûÔ¶l'6a1É. Úã* ÕÝ[•ø5bÕç@ŽÐ"ÛÀÔ¡zHÚôz ô𽜋½ˆ?ZY.çüô`ßÚ)éPƉ¶:Ò´çÞ[á>p˜ÏAòr?ÔJ÷M÷G07¬ú)ú)½„¥OôäõB~l3@Ò˰lciǽ­¯vËšV†?Àòpxø? ~cS›a^.,# ¶ôºÍ4¥½´Å'aÒʾ1-’tãu½ôQw¬×¿r ޹s)y #±/õvñä™B×¥íõbx|îÈxÄö·Æ¿–@¶×¬ëøj3|±ç-±q þýu.8‘½;™/‡Cy‘Pߎ¿W®K}Ò—éÒJ{é?ÝMÄiݯƒ+aVªS‡¢FLìûöÝð¸.nü݇Ã=g&˜¹ª·‹ë§{ÕvàÞ¤Ÿâèkÿí÷E–×ð‹ÏJ™}J[~½Ž³—Ú'À¯$÷pãO‡£‡¨e¹q)Ž…º¡éõç˜ß7~×ͦ¹lµ:ô·"\ > >'å&ÄTIâ†y¦eÅ®S©'nèÅÝŽžž‡RêyÊ´vzÝ¿[|v p’¹Á?úªo×ÂÃPö]½,’'hSikç?ôøºÖ€S!oÿ¦EÊç”zÒËÐüÛ6 .ÇÀ’à¸Õó×ã¸t}'I»ís×Þàlp>d^£¶•èF8D—ÌéÞvõËÿ»3ûN´þ&‘? ì Ë‚› ¯‰æs¡œ ߇ò¢Õé±á­ðVP,K"tÓ»¥%ÿ`BO´µÀúŸ ÛÃ.SõUë4cOwóÞ ÜÈ}C½)cúÎo\•²ëñ¤yÞÝ7ÃÊðOpÚ<þÚøõÎûQ‡]†ú°ØÖœw[Pm vÞæVc_×űÿ¿ÎõÅáý`Þk`m0ß¹`YnîéDÔ©.9Ì´;ï|»±.§@ò¡Vº·°ásà!¡6?ÔJ,§Ì—x§ÐLI« hÆ-wg8Üh½°ë§X~™'zÒKŸè†IOýêñ©ñ9¼Øya°­‡Ã8p†åЮœz]ʺ¶K£¸V[’›a™?öØ~Žáp’×P‰Oºéæqž(ÛÀg`S¸¼À»oêS–M´OÜ»tŸ%x xÖ¥<ÿ$¥9Wÿ'€—¿Óšq‚>â%Ðø,ø)8×ççïš`^+¸({Á;Á¶ã|N$sÞ4Åt×ÒãF 1]ßSáÝ`yŽ©¶¤¡Vºa½Üø™¦$^ú•¶”9¾·@ê—°î›v%½|Ftä—Ï-Óï%r!œYcúzÚÇçÊàÁûOH=P+I¼ Mð¹±UŽÍm¥”õKÓ;éõ¼å3zÕëå_®†9À…æ…Çñ.ëG´O¼[š¾J|±IÿÓ¾qóy–‡« ¸Ñ}b̘_Ú.}Š­mŒûÏ8ìýM­-ÁžuÒ»!FŒ»©ºxÛ‰ÇÚ°',ÑtÈój.õ¦[+è–ÖršÅW_7BÛçÆ¿|†Z¨•$^†&乆J=½amøµKO~ÓÔź¾”²¼ú3Êôè†õ2-CI~¿žó`sžy™<çVž‡ZI¯—S¦éœtõ=œ§ŒE:SuA3Ïn`…åZøaSwM, Î;q-p­X–å~~ +Âep5x } ò¦—åD7tp½À»n=„:=3yp©Ê2Ÿ6%iÝBÛÿcxN×V§6Ú/+Â^`߸–â‹Ú’/ƒÒí ÆgY-ýÅ˼£YOû·iVò'„¿¡yG6ºæ¨Ñ\÷QT7§Ã—ÇœÁ¿Š>ͨß@¶„ÏÊàbì$n<ÇÀ—¡ÛÀün4Ÿ„uayȤDíªçÍD¿Rܰw7”NâÅdkÈêä»~K4#Ó{‚}âá¿)øFðœ[IÓævüŽ…ëÀ¹¥OÊMˆ©O½Úù”¾ñÏó’f¨$¿u\î׈ÔÓÛåO^CóÛ–Òh+nŸ ¾Õz!/Ë'ÚŠ«§\Ëœ®„yá>p*Ûß<—äJJ u¿véœOÓÝw/D)?ù0µê\–mºÒ‹Ý/q÷Hùxéù48gÞ/A¤Ý3LKâWÖ9éÉ›¸ai3>š¤Þ†Ô-uf£ðÿ}zgìSžzàMôØ4Õ_[*:²Êù]>ݘ\„nZÝÄ…âÆáõäèOüªt?øyá軸QÔ'°‡ðÚÍt‚>bý|Ÿ½uÂÈô˜êåNèõŠ%m¶ü;a XÎäñ0‰HšmX’êÛDížy_›êyUú:4·âö=bºñÂx"¬‹óßyéÏêu±C”¬•ÄÖ çWÒëþv¸6;UÝç©+ÁJp8 SCÊA­Ä¼Úú Þ¯ø¯ç)mÖeðõÍ3ÏMLäOZB}”zü.l¿…c!}›ò1µü“/¡i~»è¾à…-Ò®ýI3L~C¥ô7žôR¯ÛL{ê–Ô;eë§”öNzü’7õª h–Q¦9/.…ÁÃÿapœ¤Ý30·ìÒËvê_>ϸ[#6²Ÿn>¹çÉîïö?>ŠØiã&èÇO2ïdiÁ«®ÀÏw«7[œl{“ìtxú›¾2®Œú÷*.*o¹~õê@úœßÃñPßõ=ŒÏ„òöK´%9­Z†6J&J›¤~MÖÍü.:¿šÛ Ö‚#À>Ó>ÚÄ:só‹“ì6!XÝR7î—‹gNòFGUÞé‘Ê0œõ©0Ïú7‡Ñ»™O7nHiþÎ/¾ à¨o>˜*ñ@~ÜãÀ¸¨Ø#¥Ô;7iñ3ÝŽuþ¸©9÷7‚ëà X¼hZ'ĵRŠå$¿eµ‹§næ3=ñè†JòÛî«Á‹üÝàE@Iz»üõ´FŽÆgžãåûFXʵšçë]–“| }©ø#Ø'þc¥¤>ê)«]9IÊm—§ôuA(³6‚ê3å‰^–[ÚÛéÚòüvzò$ÍÐ'þ ì»OÂWàc ¤¬´EÛ»àx 8GROÔJÚÅM(˨û4rþ³SyÚÓ4‹¶Žõñ…Í$Ï–ûÀ‹`]<«ðw9?PO›oÛcùçzËT7*;Ü ÆIv,l ÀÓ`Z’ÚÉ9qãû3| fƒ—à}pnS'è#nF½Ô§O¦aˆ¸é? 'ÃWÁ‹À›Á“s4 ›î ;ñÏ©é³G\dMQ-Éþàg3Ló̉ݸCu3¢yD$Ók¨6§‡’snpÞ+€ÒNóÌ5²/lǃSıÓÌk‡jKYÑõI:jåc],kgpó¾.7¶Ÿ‚—ìmÀú¿±ì”W/?qÃHêd¼®Íg(Ö)`|š^êe<ÏÕ¦Ì ö™ëf?x l¿Ò®n)7¡~êò 8vƒA›Ò­ÓSVé[·t/-–ýnpì•ä+Ë*íý馗}”º§Üä_â~a¿߆_Âá 8#îÃ{êçÁù‘g vì3ÓâWÖE»’ö6bÝ?ËöÅÓü߀²®¦éëY“9a}? ·A/by7îGéÅŠOs ÏÏûÿZtÿÄ}ëñ ãC07¸õ2àîÎÁ*0Ð €?;| ô-À‰àÑNz©O»|Ãa³.~éàxøXé(ª§]üVI={z@­ì3¨ ."/Ùo0‚èggÓxôoSl8ä÷×óâÁ…sU/Ÿ¾6ì nœ6¸“Øz׆RúEOï$n9vºv78íêeº—ïCaKÈëáö|.ŸùYؼ ¼ )§×,•ÄßH©7RÏú‘àëàœ.¥ž§Œ«+iŸ?ºÛo•OBÝ?¾$õI3®Äß6/·@&2j%ñI»a¶véÉïBP¼t•õ¬ŒÅGYF©.]Õ2O©›©ŒÛo“à|ð…éãðMÈÁª¿2s#hÕ»[ý›®ÉSÖ!NyNâehÚ.ðëÂè<Úœï¥8×W+ ЭߴpLã «›õµì:žÛá…ÕÏ?az}ƒ®x8a–„L$Ô~e&“µàÔZiˆŠœÜ‹É0­R}57ÍÝ <„<'P¯â„ððßœ ƒ7›EaA˜>©Ï`ˤˆ!Ûxl ö\]ì37bâ—›Aè7£¡þTÃ*ŠÝÐê%î=îØriw½êã|8üŸ7‚‘ût.i éÌ<Á[P§M®¬€¶3õÛI:´ÞÁ±§œzÜŠØáÚç†'@1®]q}ü67ÿ!s,å*íâ”WÒÊx™GÝr/åicÊÄÔ±üòùöå·Àõ<5()£ô‹-éý…öÕà¤õÄve•6\ZÏn¨”~¥ž´MPŽ/|eztÌ-{ô¤¶Óãg¨Ä'zâÉ_ÇϽsAØ~öKÆ uIyIè·\çœ uq,ß>£Žå<^^ żŸë†úð§èJxáJ•cšvî‡ëŽjB/v¼r H¼é¹qF|¦“ÉÐ çñBq!<Ú_m±~¶ÑͶ›X7#ã§áf%â€×Épkwoöåáxp!•iÉ÷wìMÎó8ÏèvÛÓú8"òóìeZôzsÇÐ7Ë{(ÈNj×v˜s&b¼”ä‹áý°ø|ý ½˜? ^L””ãºð æ¥óƒàe`]°“̱ÜäÑVÆK½L+íê–g¨XV™®­ŒG/Ã;ð/K/@ÚŽZIʬÇcoêë3<…û`NHÛËç×óãÖ§OŒ—þõtó;ÆYñÕ¯›nzžÝN×6üíÊ0ìÎ…£›8o.û&>ÞJâ¶éðÛ“ØP[uú0zævÅCýFx«‘šØ?e9IngKÚP„Î).Ë.›íãìö)Ò½¦#yªª·¾‡æ›Æ`êò:1–¿&ˆLƒónp.ã„£à ˜ Ö}û; q™`·´Ü”ŸúÍ¥#âàÏ ez;ÿØÌc}.…å _¡›î³îJé_ÆcOX97ýÕ­‡í¼6}aÈäM¾„$µD[)iklI×îØøœˆ¶2½Ôõ1žò¢—>Ñõ­—¥-yÚéÚêeÇÏ|éãGÐíóÕÁKÒà¿PŠsöV¸Ê:©‹ó«“dn™^æ-ë–¼ílIŠp a­¸ÅZ•M–%ü´k'æ‘»­ìºì“±_Oºw,‡Òû—— ~îçûö²Ø4¨ä¼ꇦOætCôëõá$èeM̃Ÿ—…û¡.騄éÈÄËÐ4o8ùŠÅ4Å:, 74õ²×“ßyæ&èEÓ‹¸˜?C딕¼‰'?®ÕÄ0ÞÎÇu§ýîZz=?É­rL›v‡yaCp¨çé5®ŸÿĵYîþà·7îI+};ÙJ²ö)ß4Û°5|\¥;—Öó£·ó‹­îSÆK=þ½†æ=ÜåS¾hy »—Šmy6ƒ_Â… ÿ¼8Ø·Á DH=0MÐ'ílñ¯‡úNŒÜHæ¿5¾ÀvŠZüé¿æaA®TMlwùÁöšù¼á;ÑVòVH´_1¿›V'qós²® N¾Àl0Ø:“uPâá  ¤ÖÛ ékp\½¾Yâ:\b×e±¨‡Ò}Án6ý,X£ˆç&Í£eÄe¸¾HCÞOGÆÿ™ÓΕº¿s<вuEų.^¶ßâ–‚íaf¨û'ž2qiùÄfè›à¾°äY¨ø–¶Yˆ,×€¨|Ñ*^>£]züêa|µ+Æ_€ŸÃòP¶5¾eXê¸WRÚÚéöA¤]ºi±—º¶ØK½ôQWâ=ñvùêi¾á»@·÷œ{á$p^.…÷‚óÔ¶xè:_Êò£FºÙâc¿v¶Nå•ö²Œº½,3ºó곟Û”°ßøÛ÷\Õ×y÷àûCpóq¢ TœtÈã Üú+ÇÍì Xv‡òJ´­8!œ°óÁN`^ßn†ûTà•ø¤ôwYixµÿÜó9°¸AŽ”Ðßv]˜u=¡ûÂýà‹Cö‡É³'>ŸCG¾ öüˆËˆ µ Þׄ‹j'±³ÜtõN’N¬‡ñ÷ðvLWâçºòòx9¸á)umú)¦©;x–éH±IV·»gm‹”þD[Ïë¤Ûù3e(e/mûbô­Óøݳ’'aêx=4=å'­´©;VÃ8(Ç,~ Inµ·n3MÑnOÂ\͸¶H=_ÒêW×7l§'OÒ7TJ»qÇÄËê?Ào*¬ïrò§.t_¶öÇ$}?L•ôש“öH|J›i±Ç/aìüëöä{¢¡<•ø”°ßx=ÿ¨ûeþÄçøê¿?u"8I<2)ú-¢éàmss8 \x½Š“öv¸ ΄Y!jOâd> n‚{Á2Z²Œ¸ØÏ»Á`ßYçá®·›6Ïrß΋X¹Þìz‡à-ðgð‹œ¬7Ó¢›×3ñˆ|UÄan¹Â¹iÃ=<„­ÁC¬›èë:ê&éÈø”ƒàÈ­«´ëkü%x;Ü™/Y3ñ'©5X¥Ío>²ßü,ÇË~JÂR/ËP÷«‹`ðòZOÇT‰v×ö£ÃÈíJa½]ñO^ã±ÕC}ü&ÓoÙ–ÛÔ–^Ú´+ÚJ´ÙNûýpÕÓ1µÊ,õøÅf<ÒMï”/vC/‰9ìÏGÿ8¾Y¬ë£×÷ãä_™´Ùᘴ+IoÄ:Çã_æigK9ýùÕŸ[ú—e”ö2ÏÛwŸl¥õ,SâöÀ£ÕkÞMl#N$Å e>x¤©ô+æy7§lJ¨]Å·ç›Á‰»#xs5þNèööDrqxRí §ÃŸà>èoÆåU/‡áoP‡Eì+6 »:k§ =Ô¯÷þN_Ã{à?à]oU8 ñÃŒÛP_î ÀX6Ñü˜¦9OÿvÔ‡áÐíáÎýËC•è’Mºóz /õù«¿âÛœ3~ëf~%aô”[;øŸ×{ìνԹž—¤Ö„QWœ·J§<Ö×ËÒi°¤SÏ<£¿0ýD­:”et²ÇÇç~®'xž‡Úê³Ø𦤠Cë1xøg+Ó“7!n<+iíÂvþ±*Éçó½ÐØ·;€{ßŰ xázÇ4yœ³î«¹\:v‡gÁý×q´‘ä«ÇµGJŸØë¶Ä“nÞÒVÚË´ú3ÊÀÄ™ªzkvaäàù8\Ý69’[âFõ X²0Z‰”é±_ 7À7ÀWÊÙá;°¸h*–±ÜWÃ}Ðkp¸ñzx•ØŸ†“Àþ¬/ LC)íÖ’¶¹`MðK ÷mî [ÁÀ— «ªìܸ®Üˆüçp mZbÛ§²±lŠãw!ü&x3ú=8FÄÚ·ëoƒ—‡nRDô›Éðp޹!ÇŽÚÚ ÝØ•™ ô)}£*‰«[Ç'ÀvmæðFðÙ¥»2œ ƒ‡N&Eò:q,oøü”Ò'ñþBóØNE]©‡±¥üÄ+Ûyx(&½’4AZi³=še¾2]])ÓՕرF¼Ô“^†e¾Øí/!† ÂÝð°<ï®bžR.'²Œƒ”çî KÁfàí>iÉ_ÆÛÙÈÒzV¾IOžvåÅ'aé[÷·ñߨ‚ê9ôz5r¼6?æOœ^ÌÏg«6³,Þô…‡¯@¯;ìMßR@?á,¤_O‚„¯šÓ± ø5å`FÑs2ÓqIJñ`~;xÝ Ä[þvj7)"~6Ì2’fôQw0¨Wu[›‰P‰Oº­]Ü‹„›þr°+ìoÓÁ·wËjn²•N´õûaYø-¼¾°çùæw/®i%i†Ê@ÃNuI¹Ê´~ +€/y.jKïdÓî%ÂKÝáMÿø¶Ó1·µ÷⟼)׸bÎ Âp=l«û†û¨cRæ+Ÿ÷0iw)/Yœ¾€M)#ù'©J‹½]\›Rú4,Ýmå3ÊüÝìλ/²>Yïn>£îžGO s¬¾—?õpSáQº¤Ýåfçsô"²¾Q8A»‰#ãB\ ÜL×'¬â¤»½Ò&þÃúx[ÿ ìÖk¨gÅý”ù¦!.×ï×ÇuöbäF5Lbw÷Tu§Bθ¤%$©òñlú+|]Ã+ÿ­áOë2ò¤‡¤¡n ß7ÒEìT;4ó»‹kuÀ¦£Ëçt³Yþ¬ðwètY(Ëòù‰«+‰[–eXÞ¼ðx –ë/ñ-Cuñp¬ûxS\~ÏB|Q+)ãÑ •þâÖ·OòÖC}Í#w€ëJRj¥'Ô½©V{b¹—Ôó—ùJ=eÄf¼—¼ÉçÞê~c?û’s5Ü îq¾8¥mÊÇe‚ö•Ï7ÝñßìŸ_ƒR÷©ÇãS97?:ùÔ퉖2P»y}[¡<ΦH÷ÏÄ_-Joæ.ÌvâDs œý‰òð°õë&n ëÂà—Áw'÷ã“à„ IÙGS˜Ïœ\(C%¶;Ϫ2-Ç:zCß öÇbĪ‹‹þKôùà…Í4ïSVCßèO¢#½Ì†ç0|ŽÔàÞ^ÿå%`ð-ÊŽx<*á[Õ)° Ô߸0M ×¾åØ }¦RÚþEüðBâÚ2M)Ãèíò—¾eºoë–y¬_ƒ»ÁÁ÷Ë6—å~›øî7G'Ë·`7P⽯œšeZüëéú„Ò'y“–xéã8¾ îÛ¢Ä/ùbKÜ0뽓¯y”¤—zʉ­O™æÅÑñøÜ ËCöKí¾Åg¯MÙ)3q\*)㎛+6¾:”éŽû1àKþwA΂Nypi•ÑΧ´•¾ê‘Ô¡“o'»crœÅ·tS.éÐöáôcæç'XO3\ÁÁW½N›—>'4wy´öb~7Áqà@'qB»yì'€7i'rDݲ¾¨q¨Ä7$'õFð‹¡*tʱÿ—ƒŸC§qh5\0Oñ’ÇXÙååºRw¸ç†ìúøÂó^pºüöùs#xõ>‡ª[úkÁŸ~ÅóÿŠ—ós¯¦÷7 ÷†¼I6Í­À¾v»J’ÁxGÛ÷PJ=n×Ý"p/O9u¤VyI+}ëé^B¼ì\ä?€“ÁK ýQýš zžo¢3ß(^~< fƒòy.æ¶uíÏ7éeþLä¤%,}b3´n—ãxd™Vúí#ö…Hütˆ^Ï?»ûä\p$ÃWá÷ð;pú¶Û®lÌ•½ž–¸û¯+v™Â/i˜Zeº7ÿ¼À}\øÖKÑ?´‹—6õHòԟן=ù Kß²7(Äe8E:÷ÀÌ|÷;þ× ü†ñØêþt{ÓvSÙކ,veÛë_7CßFêâ@ùfrœ_'¢›cÄò sÀâà)S¦(±,7‰3À épÃ*'ÑQ'/S£›Žý7#Ll=ˆNä¯|>Ó‹»ÇǸßl™æ{ž€9aw@–„¡©ªÐ|t›š)§ßéí ç¦sGq#Þ Ž‚NkÉŽ].ó÷'úÛ(}=@m ãÑ ××ÛÁC"£L}ýz\?ËWR^ýyÏ‘æ¡t ,>ãØ¸LV7Ä7zHÜŠß|Ô¥’T¥åy‰Ç¯S¼“ò•a½ Ó÷*ë舯ɃÚÒcËó¼N½´)yÛ…å3Ô-Vpÿ»–¿¥˜Ü/ç‚ P©—Y·uŠ{µ¼ÕÀ½År”zyŽïóp>‚ ¿ô#Ú5^úö¢×Ëë/Oü퓟6~çûRmSd‚hl ‹ðgv~É7»&ýZÈ&6{að À‰ÒéàñTø!l n†'¡4ÅÃÆÛ²oMn„7@)ô,p¬‡áŸãdù¼œØ.8íóØ'.¨z›ZVþ>ã³àq Å5wºWþyŸM‡gðÒÿ h˾‡{ÕTmwçÍø·6Eó«&#y˜ÁŽP¼Àzü–‡ËÀùÐNì%à/ÐkeÓñæMïFïz 9ˆÎGó+ñU/m½Ä“×Pqpb| \§ëÂŽ°7|\×>ÃˈëùrxØW) µm{bϳâß)^ú×}Êv¶+§ÌkŸ×Ò·,SE›ãgè¸+ñ‹n±Åî<²‹Ãp ì [Áúð¸'¦ÜäKœ¤®ieºsÃ=¹Óᯯ’gøMÉlp(|ü†'iåó1OP‡N¶Ò®Iy)¿»cí¥óÊÆ¿@0y¦„­pÈíÒ{ø§vËT øÄœt½ˆ›Êw`¨_^ÍC{!X²(P+q¢ý?{g6Wq5`RŠ $¸%)…â^ 8ÅÝ¡xpw Aîî¤H°RܽŠhqBðJ…ÿ}ïîY滹»ßîç ÿyž73sÆgΜ™»IéC° ¬kÁ/!_NÇyœ #`GK´ÍÅ uyРU£âZèüNר½Å¯N×eiðß TJzÞô=áàÇjê³=_šÀð¼¹\qÍ|:ÑD[ít©÷Nm‹À"üÕwƒKÁÅqñö‡ A›/ÎzžÆzIJÖI7)cª³-Ó–]ž„O@Q§Dùˆ7FÙ´ ϯ8÷Þ๽æÈ/jžOW«W4®¨y‘v úè¿óŸòeÒ4Ù•}2b™ –μ(W­ÝÐûàíQz#­mþØd\ª7YоÙß{=Bª^'d3¢Ùà}póS1íïk*>Þ‚×à2è ¾²ó‡UæHÞ%œüB÷•™ï U›Šcù%,:/ÇÛˆ8¾`(šS#mÕ[Öƒ¨cu?î‡Fö‘ây‰3¦ž3”ý§âÿJ8ÌsZQæcâ3Ëv<ì”{• Ó¥½M%?Ánv(é¾/PÖ½˜/]Nÿ‚ÐsòT•üTí¥Ð‚¿À)±iŸê"m\ñìx†BÒüh#ÊÖ›¶­¨c{i=ã®…—Ù àØŸËñBÌþ=€ È3¦Í†Ý¦í ®ô}µ$Œ6mOIÇk:m3â_¡þ¤¥;ŸÈ#Z‰{þüP9¾%í//•ø±¾iÛö1ï—µýy–õ­öë!ôi™´Muiº(®NIóÒ´mç×$Í7®Õw§ãÎï!ªJC5]ª7}¦õÍ }”‹Ð1è¬JÁÿÿY°·â~‘9…?ëAmTÜ€iAˆ·—ýÑù…xÈ=({À0ðÀä7UE¦ ¶üü™Ëº:‘ZuÈn3YŽ–ÆBü<›Î¯Í:iÆ\ŸºÏÂ(HɺDçõÝo›ô7%hú‡j>BŸî–•ý_¸A4'-1éÖŒö¾çy‡ùRtä~9úž|Î yqAµíj¿¤åÝÉÀË߸¤viZ ]ä³§ÙOÇ+Þž'ËØ·võˆfb^ª«•ŽX´E%ê¯Õoäûx¹ v‡sA_­¤ã‰´aŒ)Õ¥ú|ÿæ)EúTgæóÃ,¥.!™¾E~Šòã:LÇ[õVŽš w5èáó‹XÏ ¹éüæ›mú¥„j7þm˜âë߃ý <¿å H S–ÿð@|:ÎïÁÛåðÚGGˆ‡ÙÈñð-L >hOW÷ãhkÁ’N‰hMq/x<œöxiëô»Þ_{‚[ÓÖLßGn•>q]Д¶)ýW |6uºtäÀå;è,þFìÖç^Lû]ó€gÀÅÙºjK©Ý{ -þDïÁ­W¬[Oyûó%×<ŽÅ Um¸©©˜—êòéZeÍKËOFz¸3ÀŒcðÃ` hlÖ9 B\«!.óÅçªBsŒºÖ1ž†$+úŠ‚ˆ>gg¸ Ž×N‰þõ >ª”ÐE%í¸ú«Ï=p#h¨®ÑŠpx°ì3K´‹:“æÚ·PQ™Ð¥awÊöû°oóB¢\=é¹(´-ì ×€¿´-’…cR¯äû*i›þÙ\m…¾»MÍ?åòŽAòKWÒþ´þŒe;”iÏÌ m~·ý×x·ì³­¥+d«^:~ú).þ˜Vž†}~9Ü‹0.pëVøA'Ák.kßGD¼N‰vˆè4À¥ #×éÌSŽŒ#®c¬E­ùS±öé>¼µuJ«@=ÇŽ#ú†Àe6ù ÌúÓy^,ç-@¨¸Dˆ®­KHG>\Øê§ó¿uÛìX@IDAT‚sÂÔ»GÁáàYðAkÅŠ ƒdØѺ%븎Ҿ趂5Ás8Çaª ÉëÒt·~\È©>âï“oÿ³ƒs]¶‡¸lŽ nYÏúýsòQà˜Ósÿ=éÇ@?bû-;zb?Î#ú޹™íO%-õÒP?æ#íføôoæ+SÁÆ0 ô…ÑVôí•$“cþè#×}ÛFàiJÚN7/m3Æe¢®aHÑX¢¼¡xX¢\äY?ti?êóiuŽUpMÜç¿‚€"‰vÍ+j+tæ§eM‡„>-;1Å}`ƒ£Üÿ‡ÙîÍËèÔìsퟤ`Ù=pm!n¼—¿xykä'Á{°Ì ^D±iD«ŠÂËw&ðð_;”ã&–‘íÀí“vLγHtX'ƒÏ¬o‹ t€Î1{á8æëá9ð†Ö‰Õ!nE ßßo=A¿«.°Œ[¬?ó>98p¯œ ]B:òM˜Å¹Ïð+î`86Ó–.v/?í¯£S!ÂD³‹_;w±«í“ ¯}yÖR‡§>/æéuÆçÂAp Ħͤ¨^^—¦#aÚŽqÇ ‘CAñ\8ÿ£áÐ'Äœ ŠmZ÷L°Ó¢Ÿq-]+Å:£ ÖÓ2–·ë+éZD~¦ebÌÑgÔ’BŽÅÇË  _° .œì¿Œ·¡>+Ú%Z‰«óÑ`ýãAÃ|þ áK|y‡X^‰1Dܰ¨ý"}¾N¤£í¢tj{1ï(ß\:Úsƒ›@¿ã<µ»|;¨ÖY'ÆQTßýJ³·—þ-®ÝþÔ%Ìe þGÜçg¯éá,É÷,}[]þ.úöp<~-¿G‚Üêñ×s!º¹ˆáðp;η 7¤‡„d‡‰Ž7c»þaÔD3ÑøÙ¼ x¸;S\Ë-@gÛ¼<ê«‰çø¸œ~è õ†nÛÿ$쯗\à¢]BÂÿwä`²>uð^l©¸hü,™é½ìSñl\ ý` (ën#!܌ؠ4ùŽÁ‹Ìþ´ÏÐ× #âMŒ ÒF9C #±/çëKQ²4x‘?b‰:Æ£ž¡cìÓ>Dÿó Ñý^ƒÞàe#óÃò`ûö-î…]mÎö¯Dhß1Ž,£œ¶þß`6p>©X^‰¹è<81çà£áx_¬IôýG©´g\‰2EñÈ‹úùtÔ‰üZió”´lšÎ·i˸ßÓÃE /ô+?ù?Àñÿ€c¹;û—±eþâjí2y9zÀÜ€=`ÜÈi Ñš¢“Û®€¨ãWŠíÇ&í±Çän Ž©hÕuöXB&Žw0ø5Z4Ö¬Pò¶áYUô™NÃwƒÍÄô#î¶œú´¡|'å¯=r:Ob.9‚ÿâÇ®+KïÀìëÐK#ÄE<tŒ;@:Àx¤:Š4_žß"qcÌ}NÓ±yæ{ÆÖ€ëa0Ï:Q¾(Mv&–+ʽ…"n؃Wà°Å5™Æ@Ú/ÉJ}ãJÚžiû÷Ã@½÷ ˜Vüÿ è{B4Øm` ° ÅòŽeYpQ?Bu¡Wg=Ç< Ö…!Ð B,ãù3ø1p'ÜVŽ»¿^þ^PÑ>ÑŠ„.Ö׌|\åÒñ§qó‹ÒEmGYííXcôí jÒg¤ £LÚ~š¿‰'@Ÿ¹¸ùñ£ª´c<ßVª3}éG£Ü¯ôO5¼~~Ê¢éÏÌß3½ÊáûÿW·ì_yziµ…„“ò@û"öPÜ ö:·Äéámï”õ›² ¸K±"ê:MÂL;z½ìxU¸Ö„CÈLDü•ë ˜7”„–Y îƒåÊi‚†ÄË*.ÙtŒ+q™}K|òLóãNY&ê»{ù´ÅÕÛ~šmÆ®Ÿ®‡ `,¤ù^4;‚óÔ.=ïÑ.ÑLÒòiÜÌ|:lZ½âú?éxô}—Â0ˆ5"šÍÙ 0-«Þ1º‹™(K´oòð'²Åaw°ýgá/ OÔx(NÛz¢ßX?T•µLû¯OËGÜ0]cµ6BõôÙKƒz/ÐØ‡hÕ8kmD™jiíì0ÐOžÇ‚³tHfR­-3£}ãQ.¯÷çÈ«J?¸ÜiÞOP\—j?þ#¬Kc˜[O4ˆÔù,Ù¤„hK%½ät×mº‘oƒ†? ìåOÁ&…º¦8òQàEh8nè#°2xÀÓ'Ùiâ8¼ùö…á°Äoá/_º’8Þ¯`Ex –¿š Ä;èXÐÕ„[ƒï:E£JÑ4‰À{ä_ šײªs‚Î2™½YÃ#ùHô«Ç³gÂepPÃH8þ ê\`[ÂÁK3ó~nŽç£šØVsø(ô1h{=@‰:Æ=׊:¥¹tZ׸_¿Á»àx^òe<3OÃmp„MFŸùò©Œ'-úÐEº(ÔþÜ $ÊëǼÈózçü ¼Q–hw~>$Î,ã:¾óÀì°((/ÿ|;m­·½j}äó"=‘À½Š=0OIÛjI:k„?ìãx®ÏCµu!«"ùþÍ(ÒyvxÈü@žSÐ7ýTå\˾™Wî‹Kyºp¹ª¯ 9u.[#±ªnÀ’àš·ì˃—__hTt:Ĺa¡reÓîp mz¹X§:ŒQà¸]òå°*Ì]MÂi-ÅÀtTÞâ!î;{°èö¥ÆáV¿Ÿ•ó-*óÃFŸÙ<ÏÃ>ÀcÀ]‹u ŸÞуù»xéëÒ¯ÄÙ¹!^±aWgVØ „³@Ûqå| ^H^*©“$Y—Ô³ú3Ó’¯7ûtc½ì¢^^W-­^1Lë÷<ÿV†j¿úWàp<1Žh;Ú%«"i*I{;H´oèšo !‘çX|¨}¡‹Ð5ÓW…Œ â/ŠþóYìÇz&­ó‰x´—×§åÓ2i<-c\‰v‹âêÒ~"ºHGõ¦-u¢­H›§¸†;ÃÍ`Þ“àúE¹¨‡ª¢3ú(—ꌇžËß;Éd_õ?q¾±Dk¿˜/ñ¾Ù¥¤‘?Ézèôób-ž‹ši¾ž_ÇãÑ‹€8ÈÖï Þ½`8†ÃdÐñSS6*WöðÝë—Ó]1Ð9Ï »”¹†ÐµòQÔÅýro}‰ïé^±ïݹůB½è¿E3 â Y= Â|dó Ð*”"«*åtŸnGgIÿƒùù þÊy'FpxÑ„¸^Â^0éuõzBzélXl'õ6¦=Ë'ÁVà¹õ2öÌÅîEÙZ!Å›”´uü²w^‹‚ç$Ú!Z‰«ó…ù0, ÷B<”b¨š”7yÖWÒ¹F?‘ù†y]Z6Îl”‰Pÿ&‘ŽÐö^×=Î~)˜—ÐÝþ¸Y/wÄQgíÆ\TæË”Jþøg¾Í¨“¶¥.-—O§yÑ_„ù²ÕÒꛫc×x]ðnÒq<Úœc6žo+¯3åÓ²ošQ:R¥Ø„ÿ§Ó Ór uËðÕ‹RÍûéˆv„jr%Eœ–w3§„íáìrÆÞ„ûÂic(gÕ tÇÁÅNÒ ög¢Y!6›h]Òhù|£Œ]GîëótØtx]YŸVo{c`ZÈç£*Çm¦quÑßWÄ=QÎ0æñȳßsá pÂ&‰fuòåS}>^”.ÒŸÓÐr!iŸQ&ò"¼‰ˆƒï`rÐ'€>p?ð*Îþ×qH6™é´Ÿ4?âi™¢x”‹µLÇj\Ió"y¦ÝÿÁrEeQ7Ù»Ziól#m?ߦvÿèh^(‡Õî›|]ŠgzÚÙêðEOºþíø<ûéQ½ šÌÁ„œ~?œ`[G2 t͉_ÿ·‚N)/¶å%œn`¾L¤Ï"rD$­ã…¨0¬G¯¨#J7õ}ÒÉJ`~½âÜAüZQo=Ëy€7†_ƒN©QÙŒ >†æ‚Zcvž~ýµDZ2®|?þ…(G´jÜóâì :ô|¨šè"å"Ýš°¨n5/ËåáðÁ2;ø)æÃgXôikÀjå¸>)] ’•9¥ñtN©¾Þx­rù<íͽºz@ì=ÑLjÅùü"]Q‹7´k¨š´ë¼ÕµLª×v¶ÀŸópèÄ ØóÙwî—ÄFÁ³bu‡Ð•%?ÆÙìüüï€ïÉþe휤¾g§±¸FÄ™{ù§‹ØH}Ôõ Ñÿ\sÅqx#,^¢EŠº"^þoÀ8 <@ŽI…`JÐ!Ô»[:ÓãÁýoT<Ô7“?õ´åø.Ìέš¸.«B£ëïWÆrëMt±Mó½µk‰ëiÙp8÷MKÿ„ã¢cÀ"qùú‰õ¡l‡”~÷9Ÿh—§ÕY’-/«rÄ™¬å¤,·6Qt&\Py<;.´—Jw°7B´ioÚA#b{ÚsÚ–qÅ3·\k‚ã‹òöu‹Ò–³}Ã^0xød‡¤._7-qIÎïUÐw¤õ¢ŒaH´å"ϯ']­ ëæÛµ¬³=áø,sœ;ƒ>ÀÜGp<žÉ!`yý„uòm£Ê$ ÓJµò¥ÜÒŸ–Q¢¨[ÒŽÛ†{=xKjƒùò¨’zÆhƒ–Óö®ƒa ÌùþMÇœˆf’öážÓˆÃp#>)M]ÇõÚƒ4†-y,û>æfGèXÂTÒ&S}GÇÓq8õ~0?üWä2xÝ•²ÿ™Æhœø”,¶Ö…@v¡ØS£âˆ¦Zöb[ÐWmˆ†}ln¬ŒZ25™g‡DcˆÙkˆ–sá&ØÜÇzÄ6Ss}Wkk-2Ö«–ÙŒþmòË/`_p EëìCi(h¯ˆëÿµíh Žÿ—`ù"±¾%Ë.oÐäK¥â»’ÔXÕáåCÐÃðÜw2})èzÖZªŽí Ëð1<#½- ³ôê ýéå|ž£o`(ì>¸½ô‚CÊq‚†Ä>аíàh¸¾‚´ÉнyÉ+Õò½Àƒ_½Ì9;³–U¢NÄ#Œ|ÛÖðN‡àœ#/ Ó8E ËÔ£2Ñ^¤Ó0G9÷‘‡rvѯDþÏñþ^‡Ñà|¬ãšøAá~{¾áˆ6#DUÑW"/ÂT—›Vê-k9™ÛÂ10'„¤m¨k.ÝÒ2SQßïÏAØÑ&’ƒ™Ö]žWóè}ˆèXSñ’´Òðذɹٿ_rË·f,öãÖÒ÷µ·õsêgÿÃÏÉKñ%¦Ìœõ‡h‡©a9ðÅî«y 舑ÒMö÷„:Šuap-ó2%Š-a$øµRM\ýÁ6~ ±½ˆ÷‡màð.œƒÆQÔ'êN÷àØ>ƒ ÁÇÀ§àÜò¶™××JOæ‹`ÝjbÞCàºU/ÿSaZp=¯;K+´(Q³ÓË?âÿEÿô+ç÷&ļôJé`ø9É.'µ–ª£ûèÇô4Ç”óPd Ùùõ\ ÛÃu cþÂKm•TóHo³>èS|§eã\æCŠe’êõ¿/Àáð¤yÑfª£HÖ—:Lö8ç¢òyÅ2‰6ëM[®ZTñ]§awX<(æ)ÿ†AÿèGÐÀ<}àB Ü¿‡éàm0?õgÑêJ»Î9Õ›WM,§D¢¸º´œeÈçû«'m¦í§é¢2:•žpL®GÞgæÛ£H¥Ÿ=De3CÜÅKiÁ,Všä¹\96ªÑÍëeï›R|p\;D\rß‚qÌÿÇÿöªgöÚí0Ù£àWÀð-l'ü0´·x¸½ˆ7€y 5\’ Ë{Ôxv÷AÑ n”¬ÏÌp Øïê°#è\ºš¸“î•Æ¬ó>ö‚³Á‡K^Â6óúZimÖ‡WsÒ›µÚ÷< _–*—Ý”dø€rN“À<ÍoXúÀ–¥Ýè’—?ëùV2¿Cä~Ù‡—½«‰‹«3[Õà#rcqFˆ¶JŠ6X»Ò·|æç˘ŸêŠÒ¾´ŽƒcÁyDC%ÒÕâæ{Nn‡_Ã}àœí7êFˆ*ÓJŒ­ÞtÔ‰ö"Ì+ÿº4t^ú^ý”cKóHf á›bL1~Ëzî|@œ3AoðQ`»®_Ô‰vQUúˆ¸a´YrÕÚŠ:Q·‹÷‹}†¤í«+J«:i_QÞPIçiècܵt üõÉuù[9=1¡’–MûôÞëÉkªÛa” g–Õ(ø#mÄCˆN{xæ¶Kƒ˜ï¢¥èR'îfZÏx@þi~Ÿ][$’³ùƒXŒ’ °M'lûŸ‚׿<÷ƒâDí×y9ÆwÀ %.^Ë×ròd·©L·âúîÉ cKÛàPí& 5Wu‚`y`´ÝuÑN£î|ѯv™b+F1Nn5ñWžÞð!ÌY.ä$Ô·VÜÀ¢r£W/ð¥a&°l-É·ãg“v¤_R¢¯ˆgÊ:þC™¿ÀbðÄÓ2úˇÉ$ô-M[/Úȇæ¹îŸÖ>/xqæ×ȇŇLø¢™XÖ}·ÞGð¼‹ÃáмÐ\ÿo!¤hc|–ÉÇÕåëXFIǺkÑ/}Á±)i›ÕÒꣽh+ÒQ§Ñ2Þ†>0ðI•»&߇ûñ8ðZs8l8­ïëã*x®/à^p?Ó]‡.=˜Šn²ì.ò?á ðÀܱpžxõ8Áá˜އ8 D;Lã³e!Ô¸k‰÷PØ<0¦SéAbGðåëÃf2x.‚•`)pœ*>6„sÁÜ’îÉN}Jç¤M)sÛp¬ÚAW‘8ì®ÿéMô—ú¨Iþ/‡¾ípzäñRP±àr²ëy3ꬑ}ø>ÿ&™5^´;#ЖÃFòr‘ÏN?X -ĵïð9Ѧ—Îrp/ìùs[T‡byƒ˜e~>þ½ì¢¨!YMÆzCE?ç/~ 1•´|:Ÿjú¨ù‘6Œ>µ¥~:8ô;>伨¢^´i¸(\ oÁ|e¢]÷ÖuQÊÝ÷wŒâ,p¡k‰²ÍÁ3±\= ­V9Ú‰Í5ôqº2ü ô9©1D9ÔƒHÛÐPî‚uAŸ¦äG]Z§V\ÿ»)Üé8Hfm¤mÇØj…Q/ÊD:ÂZíu§¾¯ì ~*ùñ›ÖÇïC@É·«.Æ`èš{‚zÇÀìpè7ŒÛÔIÛK㑟†T«ÔKãiÛIõ-77¦jí:†Èsï?Ì<°Ì‘oÚÄñ(~¾#ú¼Ó%¯aѳͧÁL°¸é:wøÂà%åWÓ?Zˆ³=©vÁ‘•‰}ÜýÀþ¿…޾4\ä[៰´v÷Ãàæîcá€rÚ‡ÖûeÝ,„ÕÄ5p»ƒ‡ÇKµ'tôÚÐeE|A_ ý è (:þéá<Бw%y•ÿõLi㌥¡çMÓuøû€GcyŽæQ‹wYé*hðƒüõÉÓD¦†Z«æ¢»à^8ÛÀÉ íhkm%Ñ¿aÄ=ë+Ÿaʲ>ò#D]qÆ¡Óþ ¿Lòˆfm;§(_F¾•Ì×x>žï´ÉJ:[¦ÑtZ'êFhž{u3l >Þ•t,i}ŠwÅóå2YÙóõL;oM®½>R_q¸çöícÀ pˆúD3IÓõÄ­”–‹tÖX•<ˇÕMó-W­LZ.Ê„.M‡Î‡Öæ°ì|¤TÄImô?¿æ½¥bgúßa}XV½œ—p ÌMõ¥6ÚKìk2pÓ]Á‰v†xà|ðŒ…uÀ—m£âe˜:,/x„_íúñà`mpÞ§ÃPt‰¢n">ˆÖÏFûD´Ã%æXkÜníjAQ‡h§ŠûÌ/Âa›œh,£Ë*‘öˆè—ŽÏåÙ¸äÑãþ/gÈézÒ•ÿŇ|;„5ê.j-q<AðÁÛÖâ+†ö§xÉ]~•jJB„©Îy¬ ×Á×e"D•é"T_ÏëLï€ç§V{ù6IÓt“ñEÚ6\ýð5 Ï‰1¤í£®è{itQV]>ž×¹öb9ýÈLàã‡Çyö×Ï= gï%m/ÒYF9/[V‰:ùt­¼|ÙzÓEm6§3?$Æê÷jàzŒ,gº¶8 ‰îÔ8º—•- ¼`·„;ÁMžÜÀ8 D3±ÓƒaL í!Že0øê9~±àD;T¼ð¯…í[Ø«‹ä"pŠü¾àKÎ5?¦+ã+Ï/×¶Þ9[nmÐñì­µšhX|ÈhŒ¾Øó6“oÌü¥ÁîC¨«{&ç. ¶éo`Gð˜|ÜG£º¼t¥€Çâ7;ñ‡g Þ¹ø}`ZðBhk±}Å0µaý‘›žæˆf_æ£ ½œÂPŠÊ[6ôir]õ¹õžŠ6•¨8õåàÏk7Á¡à¥WKÜœàˆvj•¯7/ÚB/îõVnãr^À¾âûÃ9àË»µb›®·kçeíåï-¢s1ÏõœÜø–ˆã {/ÆXO¢í.ÿ¢ûÓ(ëÙÎðGðPÇãˆh§6ý3œ€÷Qœ;Í<àú±4/_¯‘´í¤åÓv#eòåJ5Kº“Ãð-Ü ÚÂ5ð¬¯á^6D²ªxÐôrÑCp1¬ ×Áà4'^†^ЇÂtÍ®3ßÉ= xÔìÿ4b^Bû‰WÑ/±wÀµŸBkÇá¾Þ+‚ëæƒë;ð`| öçº:ï–ˆcü΀KÀxkÇMuÉK”ò'Ð>u•.r¬§€Øúùà`­<Œ¿Ea½|›ÄùLý[4øãgï™Ò?uWÇ ñèw%Ñ4·öË‹sï¸.éN©ÍË%¯$ôiw^Îm%áK 57ÝGúg†A4Ë3t"^p›6’OÔKÛ¶\ªxÔKóíËïèñE]Ô^¾~½éè?BëMá pn‘—†Ñ~è(V¹¸}¸œ‡€>0ÊDÉÊ$Ÿo:ÊÑ'/ .ׯ‹ÑYmÁ;.­í¢ÎÆaè£í4Ý–ñè/ÂZýiÏ>({”™…p/Øvíßý†-Àó@sb‡.Ê{ Óý¼ìO‡_—E½¢1z¶„PïWE Åq]cÁ¾68¶ÎçöÜ ­F¯®5¢A>a+ðë|uðÁ¥|€ÝÁ^[ôçÞ ½~Ñvpî™·g½â<Ýócà4Ðè;C\Ÿ)Ëï_â&SßñWÑûÖ¦h¶M×—þc§w“/¤3ßWE fÙïþ‰&º4%f/*UÖYX?1^}Ö#ð:xf|•-n–—NkÏýÙ†íÍ^0ž[õ¯)ó½Øž„õÀtômhY%GÛy}”‰úQ.Ú°¼>ãh8 ö¢…´>E*ã‰v¢ó”HçÃÉÛöƒ%Á•(C´"¡‹0·:ý›ëå:yϨSÒrWŸÏ²iÛs?Ü—=À:ƽßÖé£àãÀ>Ý—T¢-Ããí¥y-IÛn´a˜oÃ9øŸæ9n}÷S`yE{>Ò{Öøá¾,ìÆTwám¸Ì kÀÜ GH_¬$ë޳CÁI\fDçp Lk–k:áÎ×ÊËú÷°?¸AêZ*ÖÕi97ÈÎð+P×M>ö„©!o¨¨Û˜´Ãáb𢠃"Ú¦â¥ì Žß1¹ß¾l}°l ÿ‚ŽÎG÷Ã&šh}~ NÁ-2Œ¸zoz}âÁ€ïÕýlãxÜ»¢<¯ÿr5kÉtdnž‘ áPNö –»´)õ­@ût|ž£}Á~´÷È3|tä}@QW$¶õ̯V®¨®:ëk+Àp/,i;ÑêLª¥C_-œ‚Ú>0ï @Z–dEbNšñۉ莄Càß D{i<Õe…ʨW¢]×AQûìô„«a ø1©<êÝG%ß–ºI!Ú1ãN˪oiÚ;8ÛyV†ô`z¯ƒã íK»7-ŽÍ¹þ 2Gï «H,lÅ3áq¸ìÀÉÚˆñÖˆío :î ÁƒÑˆx1n kÂÖÐh}ª´©øÙ †€kF@´añ!áÚÛžšëãåŸ_s÷â}˜ÚòáãZjô:EÇàµô±GÕš2 ¹Á ðÏš%«gêÈFÀ‹0Oõbí’ÃCobjÿÜö}gt4ø#ÅlðfÉSküß³]Q^À<˜‘…SÏÒ³t\ú2íX»Ö©zA¹9ƒŽóXØôK~z¦<úª€h݆`ò5ØNè=Ï—ÁîàøC!ª&º4ñ­SÏëL{¹yÖÒ~Ô§m´&}+•ç†ù!ö%m;úmNç÷Ê ÖË?­C2“´½È7#⑺TŸŽO¿ç㥼 _ÁZðk°Ž<-¯Îãàqp«õEVeNK|UðÃÑq‰÷ˆâ¸»\õ݆ðGÑåïI×8>„ÍÁÉ_r°¡¶’ÉhÈE­§Ý0‚(|3töåï9~Çs5Äøˆ6,®±/Ͱ è4NüÅh9÷É>¯U[‹ûl?gÀQ #mkÑûÁ¥Ÿ#ªºÅõß F‚Þqw„Øãö¼i.™8CŸwÊàÙëˆG|¼M±«Ê ìÛW¹×$âF„¸ WÂÎà^ék =£ž³‹á$8¦œÖ¯/ÁsÕV/kaˆ>l§9q úÙËA#ÐqÏ †gÊüÔg8¾0¢ÙxÓ´:E>ÀÐ:JÄ£|´¡eûö°8/}p”'ÚDÒzf4—¶Œsúœc¬S¾ýh'BŠVÚNuê•%ánø xµ‡ºêüÍ‹v Ûˆ¸{a\"®?rÿŸ+‚\þš3-ü´ Å{ÑË[±]×T‰öK©R¹GI„¯Kóµ­{À|×0ľ?aÔqm½£M‡ŽhEB—®•í¾“õÅþ=©8‰ÏÀF=“Ãm ._U›È¢´2 ƒå!,É&âøÇ  ! _<1Q¢.À;à.8 <è-7Æù=WÁjàÚ €g!£}zÉ ®WIšO²MEg¸x¹nµöˆì†äçåÒõ8Òæöõ}6ì :Ú9 Ñv/ŒmKÿgŒ—;pyD?¢ŸX ‡Û¯v)íÖ,$ݵ¶\Mšk?‰­j¿ZØ2+8òwü:|÷„6ªÓvU§‚K`~˜ ¾‡ãëƒþM;Ñçù2³žgX[ îÐkp'x>M¿ Š6ËfV.ó±GÆ 9ö¡à…ñX ÒÉq,#,Åñyþ ÕÅeE´¢3å"mh=ççY¾/ÀvCÒþŒ×“v,=ᘠ\ßð‡Ö‰¶"m˜êbÌ¡3ô¢Õ÷{Þ"Ÿh%®N‰:i\eŠêG~”MÓ^Àê_}áA ýÜïA™§÷æ¡ ½¤b¢¿v­òbÝMáHý–ûbÅúéø3%¤v .ÊE~¤uH›Àwýä¤àt9(v6Ô+·—ü‹†·†`MÐ0óý9á0<( ÁîC´ÃÅ1M—®ü*ðRV_¯XVƒrퟋ†u\ »‚È×dê¼4º°ϯª6k1ð!x ìm±öÚÞm°.¤ó#Ù"q>…³a3¸s{Š{ˆSú²<~“.—xnïƒ àø;p‰vcÚÉ*XK©F'þÙÞfÖª©áeaŸÆž&Ögõ‚þ°,úº¼L…b¸ô}ýÀ³–7’ËDÿó(h»žÛ»Á|E_¦ó¶Lˆ;ìŽÅ3}L†>ïvÐN-“B²jºZ^ªx„1†½L5ÐÇáðAy†TÍ.ç£ —‡u@_¦ØV´é4LãÕʹÆïƒ¾ñd+ Q6ÂTWO<­W­¼eò庣s¯mè~¸–†ÿ€y;Az‰“ÌÚÑOl>òí¢ÊêÛFH¾L>m¹zuÚëð›óÕ&D| < NÄLQÜ4†Žû~„}Àƒ—ˆÆb»ÕÒižeb Q·žÐ zUð,Ÿ~L¤’ö¡>Òù0òôMwíÅ|£¬e”|:Õ¥yP?ç½ô4è£ÓÇE¬Q”%»Ò:¥¨L)§ôgQÝÈOëZ.|ÕfÄõÙG” j‡åÚM´k(ŠúhÃt臄.íÛ¼HÏ—)ÒEó¼Kµ»¯áé`SðµæÅ§{¡ä‡ªÝÅÍõR? 4"'î€ûc\ \€vtè´^[\Äà 8 æ†t3I6+=(qüNçï¼u [ÂYà£Ä½PÞÞ n+ÀÑe·‹õ:Rœ§ûäø‡C!"цD'yè¨]¿æ:ÒFtl#àepÒƒC²MdRšåëñÂÏKwŒ]ˆÛfø'è sÂv°3V}j韙"9ÞIz¯u©ÁïÄh†a·ÙYûaÄ×…zÈú/>ÏœgëJhοŤhöH7 ¹,"åжÖÏé&Ý^?ÂlÏq‰z©H"/BËÅ«é,ïÜõEûÀ à=–'9NZ]*–ç,d/Ý‘„ñˆvò¡u‹tê•¢¶™/c^è¢\šÖÞô·ÙEkx-¸YQ(ttl¹Ž¯éä Ø¼à—ã¸|Q¦d§Î>ûû@×ή÷vÅ5öáµ5xðþŠŸ‹ÛÃ% .«{aþ.p!ØNšO²ÃÄùö…Å€OÙìß*„ý¬[œ“{>uÝ5+è˜v)>Ô<¬í!8¡ééËíHñ]4Ü.·\³™ (ó)AKVŒj+]öà²pùg²%zIøËRsK7æ$ GÀõ°1ÜéåB²nÑRÑî¼Ó÷òX.t0¡}ëïx¼dFbÙ´<ÉŠxnŠòÔ+æ¥e"^-ß:>”Ûa HÛOë§m§zç|5üü"ÖG¤ùi{dUòŒ‡Ô[Þ=ëïBO°ï¨K´"ê”țӲùxZ¾(õíógph/³€ýì'ƒ)ó«µOV–gk“ŽW½’Ö´aÔ ]š]ZÎväí‰ùÃÍÖ; |’d?WEç$³ ?mÌc¢†¸}!ßy*ÍfÙÖzp |ÃïA—™Ž‘d‡Š}ëýŸpÙßû§?Û¡GÂ\§à^x¼nëÇåï¼}èxQ…ŽhfDÖ·ƒ -×›æZ$Ža5‹ÃtШ|G×TÙ^¢#š \Ã_Bº¶$[%ÚÄ£,ÁŸKÛcÓnµKã´F~arXn† JûëNŽ—â¼º¼ðËÜCóN4ÑÊ^àõØ–¯_¯úF¤KÃs@•¯8¢­ým*s“Ð(Þƒ•`øå½øÐ÷<­Úï¿@[KÏ}šNã–1]MŠò-¯ñö†gÀ´†œ¶›ÆÉj’g›Ö÷ñðð+=_UE—æE^i8Üì×‰Ï óÆŽjq†ƒvçar-ÚKbío6pÓ}hi¿Ø_ß3øõøõÒ²IMcFX‚/áQð“óÝ‘`(¸Bí9cšoi‹£Þ>#KZÅÿ{÷*çp]Ϥ—i-›´Œí¡w¹¬þçcè íµSŽÉË~8¼@Wý®ç|è‹vkØ42}‰å›í¨3”¢ñF9²3±œzCû\>É‹5í#m7úÑØ7ƒÃa^àLdù–Õ…ãË—±lè"ŒúižkÆùËN•÷Aˆu”tn¦Ó¶ª•±\5‰úÞËÀ­ „ØŸãX´§Õà6p¯ŠÖu&Ñn­´yÑF:ö´NZÆx”Ó6z’j+ÃW`æ?`S¸^„y :‰DUS4ÈÖŠ}Nýaüú€7ïн¤÷Ãzàeü°œ—tL˜h«Å~{Û?¸œN Í2^€Žíy8Ã`9 EC°Ü—ç|lsƒ0ÄGƒÆãå?æ‚4Ÿd—mHCŸ<Œ®—ßœ¸¦oÀ^`í)î‰öáÅ#¬ m±–œ‘9^/Ý_Ó¤Ûì]r" _À$ð2Yß•,c(IÅ¢ã¥x4Ç ÁOœÌ@×Þž;Õ3äþ×}ŠgNÑ6×…Á°èwÚCìÓÕ>·…«ÀK^ß¡áèô-NÄôM ß³üíà¹1®TŒkY6§+ʋҶW‚{A#ÎK´ïºøAyÌyÖw䓬H^é-ñ+•«äÍ‚þÙržeó§*m§Þx´cù¢¸Í›ÃÙ0¸‡©XÏçBðø«­÷­â^*1δõÍ¥£LÔ´a-c^ƒÿõ‚ŠÁX)d"ƒÀËHCkDÂø©“/;)г`c˜³œ™>@<Š tßtÔ+ É®H”­(ˆ„.Â|ž>÷x ~]ÎŒ²ªn˸{åÚëGbˆ6™»ýyϺ—¿…ëÁõÅütL¡Ë·—O[.tÖW"m¼šÎì£Lƒ)ñtнHcC‰¶»8h7pzøT»0ÉÊ&sðòß²¬{ŸÐtäÍHühpâŠ//FºXꕼÎñ¸Xw›7|Ñ–k³¤‡oZÒÞ®cŒh¡Ä&=Bî¬àã&³cµ?ûø9ܱQU&À¡w)ÙäOÛ)šs~¾M*µ"a»«ÁyÐú@5ÑÁºw7ƒsí(qŒ[ÃA ­¹®-¾~¦a.`OFÓ®MË?Á#Ϻ&ᛨ,ÙŒÄøj’ã… Á®Ur ·íŽ—¹çÔM*Ï ›—§e´Ík`C¸ ’Í$ÕzIý…{ƒ~ìJ0­8^ϲ¡å'6—ý[‚ì±²+aä¯I\ŸÕ–ÐòÖ5T,kÜP‰x„êüèYîÖ1ËG]—Ãú`®]´G´Ò¦q%m»¤ùQ—æE<Â(›¶y®Ex–„ÐGˆª¢Kãæ+1ÞæÊ[NŸåE>ö„¯!$­:Cõádؼ¢lô{KV&æ+‘ß\Ú²ù2©Îë£å©£øÃDÃD›ˆÆ>¼P80Ù?_vÛK4 Çó'x€tQIÖÇ㛉øuIéÑį‡@ñKÝW›‡ ë/n‚ßÅz΄_ÂfàÏ8#À<ÅK÷ærhúð‘:Ä Çö¼%þûAÌÙMœþWÁIð<|˂㴟Øl¢YùÓo4‘ðÚÎYg0L!¶çœÚB¾¥‘þ°Œ×&/î»sô{Øò-ÎÕ5Ðæ–‡z÷Ž¢M{±©o9Oq¤þLú Д¿—þÀ¼vÄ?Ž":ÞKj~ãÃd¯ûóÃo‹²[5›ó|?Áæ oPÔ_}ah©½PuñRÙ üåг©º ÆÂ.àW¤ˆVâêBôo¦õ/ú*ç`Úö/g½>*¢-Ϧ~/$ô¦#þ6ñÛAƒv|¡·Ý+`vð¬ëÏ”È7tÑ‹Òi9ã!Q6MW¯DXJý˜žÅâð(¸·Î)í›d&Õê›}G½ÐEZ¿ì|?‡AàþD{¢ÊtQG½qýðv0f‚|yT™äõiº¨Œºè#-›×iC{ÏÁ?Ôö²ée­:ä2Êl .®“hkñâ^Ûßô˜éDH¶X4‚îcÿ’ø0ð€¤b:ÕéÁGÃ& 1éáu®]\¤ŽÑÃÓ¨8çgÀ€NewHçìCà`?ûÀ»pl Ãap\n¨Zq~Î3=ÈêÛ¶^:?õ^Àé:ëv†pD3qŽi¹²ºÙÀyÞ Öï®}ÚŽÎj+Y‡ªÝÅ5›.ç–àÚ7"ÎG½ ëëT4•éaЄ>·äJ¸¥tñû éÎ÷’nåø4™=9bÄ3Cø…ü¦C±1h¿>¼c²†^¬‹Ã¯ ÎÑVIþ`c^6‹pxÞ•8ã1¦|:ôÚ¦yå_@_㙿âŒëÓ®ËXöpM¢õ¯ÃP8 ô‡Šk¸$ؾ—¡b¨W-zC¥¨Nè³å2©.íC½sòƒâ¸œS*Q>Bósfÿ²w¡ó­VŸ¬qò\ßwḠÆ@ÔU&‘6t?¬›Jä7¢û”Âˮ̻¿ 9±¢€ƒá¿PÔ1ê‰m}Á/a¨g\k±Ø§†bº'\7–•ŽÅÞ q§‡< u‹ÄþÞƒa[ðzÑ»É:ÃÁ° ,ZË\˼p;Ü 4'ù9[^G cñRq]îBˆó½Ò}Ñ&l³щ9×w@»ÓÁ„ô"²) ´ÏÈï¨Pçv7|ëA½ca¯ºÍÀ–ýޝøòÑd4%ßlÁÂ಩[X²G¨²Ñ Bê5®6ÙyVá?§óÞ <[Eâä|¸gC|ÙÍl_ÝN0µŠ6¢€Í:ާá#ØôÁŠú V:ò¼@¢¼O¤=óÎÃsªýß~HXÖ2é%:-i­÷OàúÍkÃ¥0`ÜY=‚L¢¿Zió,§T ‹òªé|¸-oÀh(êL¢?õħ¡Ü°;Ì ©ÔSßòú]miUx>†juÉj’éZ壌a*îó¼lØ÷§”µnV=bg^€ûÂpÐË¥ Ù"±/·c`D?DÛ]ì×q †ýa7X v+Áƒv(œŒÖŠ}yȼP… .¤‘ƒÁ¯s@LJÝñþ–‡¾à~8¦ãáLðº~J¾ŽÞƒŽËuÚ¼$o4D¬‰m¤N‚ä8b™‡Àpp^¶;\󹡳Åu ‡As󉱺GìËù÷—þSßžíSa-ø%ø®sÙbEß,ÍÞ˜`D³åµK´ó}蹇EâðÂû<©XÇ|7¸½Å~¼\ó6©>D«JÓ¡7Œ<}FXŸoÅ´üÁâ·>D_¶y%ø8Qô•Øzöï¡î#ô2ôã ;Dû1Žè«VÚ<Ë…¨+e* "¡‹Ð<ãÞO_Ãÿh­ÔiI\ðCxÐ_57/ŠŒ#ŽOß§SxôçwA|™ím2Þ4eSÄÍWòm„Î{ç{ w ðe[¯Ø­`(„m‘h,^†ÛÃuðä'‚ªÍů—¾F€óšnó6àxÜÞÐ k qÝ}DÙæppÎ!ŽãtØfû¬Õ¯o{çÃæp5Ä…L´nɯ¹}êôòre¢Ðx7Ǭ؆ù> ”¢[Á2kÀ¹àÍ8+¨û'èܺ‚ÌÌ æ…a™:ä¾.ý¯V]:—„dö£Œ¦¦™â“ÌŠ#:aHÑV/3{G~ ïÐŒØ ÑÍÊ‹û;|úÓŠ¶~ì >Ž=³íùXˆö߀Ç`yH}CŒ ufa¦µ´To^Hä…5ZN#U>÷‘75ñ-Ásªè÷]¯a8bíSô} Ê¤¹t”Kè¡y°Zyçc™ô‚Lë4÷Þ|Þçî!WÒvòió”X“ˆš§½M>ªôå–%­[+Ú¬sUòm¨sì«Û…äÛat@´nÑÎ`3˜/__"WÁ“pøtKÆCµB±­X 㯗Ó>8Ϊ?¿hèÆ5Ü—a8 7×z߀„áFpœ-û8a[“À»à¡:v×4#ÑfÅv#άòS£h¶: 8þí`d$}l]}„ì :Kűôo ç¥ÃØ®…G`6htÎTiq¬›Â°8¯Z¢<ÌX)½™¬~ ¬ n±fîû®Ã¯¾O0Á‰Û:¾Êˆ3ù%—/ß•7f7›4Žè®Ç@ÓsB²ÍDcòãëRølú§pöD3Ÿ¥j—Šaä§ñ,³ü‡ùQ^•qÛU"~9ñŸ•Ó^TžaýŽ¢ÿ4ô-Àõr¢_¢MÆ‘OǸª…–É—Q_¤Sï:øˆçlfûâxbLQU“ú¦‹Êô@? ^￸?óíUX_}*QOÿ2N‚£!Sä£Ê¤ž´µ=ËŠsññr'LüÊ|E$ mXllðÐà}j0͵é`üÒ» ¼`Kö³{kÇC3™¸x±€¶yh”ŽËË݇‡í¹å¸†êOE^TÎå5Ø òȱ.ÏÀ¯ ‘îœ'/×¹špMðEíêZ¼÷€âºx¨W#âüt‡Ã•°=Øg{‹}†¸ÿCÁùvo¼p"®×<àÞ÷Pêp€^0\ó®"Úˆûý'Xjí·kÏ|57ý£wˆªU@Ë1>dA0[õ#Nh|–å–æ£z6…K«›çÓl^>Eq ©ÝG9ëœÚ½þ¢¥¢/Ú ôQEv§åè?x´d>dsÂï!$6Ã00/¯W—¶u =ãú©ÁÁò Ïy Ï`˜\ †R­­jú¢:Eº¨_”÷6ÊáàÞ¸oQ6BT]µ¸ë}¸û»‘úϤZïÓç`ø°Ÿ´,ɆÓù:3ÒàêÏóW’ãWX¾+4"^¦ëíð*^¦µÚíAþ90;ÌK‡®Å≇Âñ< •ã“Î.¦ù›B\¬qÀ'Aç˜Ãb°xi]Fò`Y ©^™–‚ÎÙ:+ýxº¶åZl"/žZëçx5Äu`VÈËÄ(Þƒ ?Øg­öÈnq½uѷ㾜ŸÎàCpþ‚Wââ°¤Ϻñ€ ÚáÒ‹7„[ሹm"ØÒ\§ñAôvé-¼,™ÃÇ 9åãàÞL}t>ý&(©¶4ãÓ$ç^ˆ÷ÿ|Œ¸7æÅͼ <¯‹€6žJäÏ‚r 0ÝiîmzŽöaðy(“ÐM TÇ&YO‰t¾Lªr¡‹´áô°9\ GÂñ _{¦‚“Á5ºôCk–ö‰ºÉXj¥‹òŠtéx݇ËaXÀÂHšß\ÜõºÆÂÖs Zµ|^>öy=‰ôQ`_i™4NV“¼¢t^ç½à—ÉÑýð».D¾AT-7ýø hnt^ìÏ‹ðBðp- nL£‡ÄËÞËD‰IÝRŽÛÖ2°x‘XvNˆ>ÒËuf¬&Ô8Ç¢ãˆíÔrù 1çóÉXœÿÜà«øði85x`RÃ"Y(¶ér6EuÜ è8 ŸB[î7͵HÜ/űŒ/¡;8ž¶t>^“Ã{vÅ@IDAT!öh&> :b>|oq÷ï<(r²¨}Èüz·ÒÿâÈ÷B˜4%²2SÜ¿è`Š«r4TMp¢Éïòúhf _ò|i_©-’Ìü…>¥È¿™¯½h§À\à9o©è«î„]`6(*‡ºªLAÎV0ô¡µÄ‹÷ X V€ô,ÌÄ ŠMJÃjq+åëDYÏìžà/úÝÐOOÜùîsBÞÒ§Fç!yNÏé¶à¹š\S%“ñh;‡.¢¼¼nrö¹¬Ò¨!ªŠÎø”p?ÜÃà°lµòdUÍKëÔ*yOùè¿ÿ£2‘ZmE±´Œñ«Y€“{ÑH4ÎzÄEZ¦k¦°›úºÐ.Ü`ð¥ìay޽a:°0†Q9=ÉÌ8Î"ü§‰DüË…%Ù5£^£a8Œ…sáSHÇD²¦hÔ3Áz aèÚC¼(¼ØG‡à§ßkàfº‰€‡Sé“âMDç°7œùCÖ¤ Öc ñnùK U§È´ôêxþŸ6¦ÍèÀ–¢G!êLt$1oCŽk¢C\b®æ-Ú³Ò¨ýè¨þ Ú±ûnZ™ ¶,ÓS‡¾e~°[»b?lÎN“A¶î|‚•Ö˜sW[”_,ÇGëŒüg6ÜÄíàëܽè6§ÕìT»ôÒç@¾ T5E›­÷`_=àr˜Ö€°}¢MÄŠÍÒÿ*‘NóÒxZÆ:ïÀ#àøôyiYûíWÀW¹<’YY ÝÁº§€çɵóŽ×Õ¾\·¢ñ¡Î$í;ÕÏçÍŠîWð*|”ä»~Q6âžmýøë _ÒGÅ8ˆŽSÞ¼¨›Æ£¬a*i[ê#¡ãs }L–Ë~PgõÒ´:%Ú1¯'ÌÙ û4ùÿ*&YS<6Òœ¸qŠƒõpðšÎ~>Ù˜Ð6¼øR±íåa>È÷aÚË?&B´Åb[nèy ±m³À? %ík¸·‚ã·­Ð 3Oј½hzÃà ÿ˜AÕ"Ñ9Ôû°Ëß ïÂ>ð´dÞTkqž72[+÷È5¼æ€U š#«‰8¿T|Üݱæ¹þŠû²¸g!õØÇ‚ŽÉõãLù³þ×¥ÿ¤C¶)ÍÂãð$\ŽÕ‘mÖp–¤8¹ I¹–·èÝÌȳÂ#¯‰ïÒ´Û[` T›¼¶vô…EAèW´é­ÀK¨¹_¢Mí}çr/¬jâxcÌù¸uòº´¬g×uÑÀWƒ°è(ãœ]—>°„¤mª‹´cö<é >Û Þ#úË›À6=¯ñp¾"$«É|Òt÷cèipON„¸¢Û#ð ìúŽÈ‹UE—›Vê-[TÎ1¸‡ãÕ§Y.-K2“¼.MOI‰~ð§Áü1'Tk„¬qÄÍ~<µDÃ^Ü4 ö Øæ€wÀ (§‚Iźnp{‰›î×¥ߦ0=ø´ßÖH8/V äpÞÊ0,öc~[ŠÎ¡‘€}û({ „c ¹=¥H»‰ã? ¶÷#/‡ àælñµqPˆýPgž6ª](îÏEàG7ö8M'õ ƒ £ú#üÚX˜¨þJS–Q”8–VxÃÌHÒkb‚—u‚ÎË7¿çÇÌ™Õ,°8¸çŠ“õB: ._}ÕD»9v©ª*зä`3/×Öð=T“Ø0Ãzâ¶c¹Ïa(xF]|]Ó÷‡`ð|¥eH¦-åìø—×f`{ÂV`»4×5$êE¨>âùÐs¿&è«ãR%šI”µÿÓádˆ=·@äWÒt=ñZuòy¦½ýZ ^‡O •´Oõù´cŸålDþw‰o,Õ ä­VÝ ÆW“/ÏßÀ´àf¹Q_‡äj8¾„taI¶‹¸Ùwýž½À~[Û·õ»ÃÐ|ÅzÉ\ ߇׾[ÛMŠí7ú°!÷òïð,ì:±Î/ã÷aÝ*?‰ÞŠùmõxJíØ¶#í!ÛÜCÅwèd,ã~†LMÄ/?óq®ÝÎb‹ë­$=Zú)·]sßݤ–7ÁKê'ˆÉ²ïÿÔöôk© 89ϵ¶à™oÎ>õÇÀ „Ý•Rµÿl‰ÿX”&Ý Ïx-‰¶ óñÐ¥¡m™Ÿ¡¡+iãÎw=xÞƒÈ'Ú¤Ÿ|:êZß»CìãxÆÂ °*xVÝ“Øë*Õú ½¡çÛÿ`;‘G4‹Û?¸<БŸɪäÕ·~µrù¼HÛ¿{ù'ðNõã Z‰GùÈ‹ô4”YÄÿ†iÉåOµ&¤DÜU¶7}#°cR1tà3ð ø%åë´‘Ã@ñºÅvmßËîc¸¦Ç‹C´Eb»Înp¸I;À0PïÜýÒlm?4QS<Ž¥qL @x¼‘Šm\ÖƒëZU»5<è>Þ†¶ç8÷I¦„«àò2×n ÛÂÖàmî:Ë—0¶ÖÏËÿJ¢-§ä¶ï»r=ü$.'ëÜ'$х̸?`^Âßâ !¡­x¹†¿ó"ô+ñh8| TíæjØŽ/·ðD ÅüÞà%ê‡Kså)’‰’~pøx™ªù ÏC‘„_6ßx”ó¬÷Á'ç7-cÜ=×fE¸«œ&¨K¢­èÛõvüª}ÀuX¼SžöŽ‹ä8iu£á{F›E´MįÑ_‡›Á/'¢MÄ/·ÁAàâï qŒ­çø9Øöyࢠ„/ ™˜Â±Ñ^Þ´ó»ë a·Aƒrsæ†pDÛEÇe°>\<î<¿ƒ“Á½ ´÷xé¢"®Ù­p.x¹‰‡|FpÝûB[ØÍT•´}㮩öêúì:×h=˜ÌSz÷½OTs;\ZÍÁ·0òF)øiüÇeBš­sê±$.åx¶|0.`+@œýß °̵D›±Áþ ïÐhj‰å½À÷‹@¿Z¯X·'xÆõ¹¿…zêÇ›iq}Û`,ì>€”¨c<-ïØõ•³Ã๊¶ˆ6)ú#¿ZèX”)À‰óíÓ'ñM‰Ç>ÅíOFÞ%0?,Ö÷¬ßOÀÐO)Q§”jšNóê‰7Ò^¾,þ&ûUâBǯ¤}æÓ–Ñn.Àp³ÿŠÚB|1ɵàų<Ìt~@¨Æ‘Xl B4/%u±ðDëÛôö²Öy G‚úØ|¢UÅù„!OBüa].ímϹMûƒÆï%ìcC œ^ËÁâ„h»ˆ»%ŒÇÒˆ¸.:ˆSÁC°:Ôã (Ö*ñÑx'¸–kCP¢ãˆ_\—Âtàav:ZÂV¯6r=¼Œ­×¥ÿ9³[ÞåV¸¸ôOŒ´@kÚÊ/NtB”î³ðÑ^üU´çD;tƒuÆŠ>ã>Ð6V„ÿA-ñ…øG°­Àt-Ñ §Ã·µ äiuæu0#è—šë"™ÅÆfFèeâ¸Moúã‘_-ìE™ÕàQø¸\¾ZÙzõ4Sé×øà>¼ /oŽïyÐ߸'>D\?ûø”à8\§¿”Ñ¿{Åxˆ6¯U§¥yÞK¯À•p„­¥ãD]«óÝÞÄœbãˆ6,v¤3¾þKÂ̰´äÒ¦Z¶y/¾ÏÀ\°#Ø^½ßÃçeqøØ~ Õ.4F Ñì5õ{·À9zHæÛ´ì°0ÄáÑãÇ¢ûËÂè_Öy¡ ƒ¥a1c#ÚæÒš€ƒ‰uIÜ_`V‡ö|´ØŸŽh}ЙŒ…æÄ9ÞÚÂæÐR;£j›È$´‚3œâ4~a}êÇ{âÝú«Š9h³þIH‰ q²?ジÿŒ‰&ZùfçE±„qó/À„æD?|ì ú¡ZÒš@´;ŠÈý°è»ê‘ØÌ°b}¡åð²LóIV¬=âz1¿·Ã1 ?LëFu“6"]OeìKýÄ»`ÚÁ¾à¸íÿðaÐôy~ÈŽsÀ1F1¶ɪŒÝ¸R-¯}¾~siÛÔO/>n¼{b¬D3‰~ ËËõ+/Eí }¥~F—ÑfE¦#ökwOØæ†> 1Kk$6émy†ƒãóuæ…/7¢ãˆ›x#Œ„àKÕGIÌ϶Ýxçbúxxµ¬ÐXœSo°œxQYN1]mŽnÂ8þŠe/ƒç`¸n±1DÛLÜ“-Á¹ÿ£•­Ú†:Nη=Dg§Ñyº¾ÕÖ”¬&âx×ôË&9Ÿp,ür2ÙÆ¥èÖ: ÍÍé O–þÍî#DR¢OPåø oÜûùà}x~ê<‡>Œ×#ú¤ÃÁÀ¥~ƒh»È/hõ)Ð9þzÄ¹è³ ï °t‡˜gäGHÖ8âáð®Ð·Œ„õ@]¾Nµt5=MT$ÊØ®(^ú}Á<å&0>5¬ >¬”‹ÁyõËø@Hçm£n"Ñn”53WW­~>/m/ò ók­Ãyæ…WÁûGÉ×wϾr¦‡ƒÁ†>„õÁ¯UˆÅ"ZUlHß&_K»Æ"m•ÄÆÍN+² èM7Çy,øHÇkÿÎiSØ®€õŽ[yŽÎbMÿðbUÅ¢ëÕ["ö½øÙ\3 «+Ë îð‚ž¤ª=jƒ³Â÷ ôáÞôƒ¡°´t_¨ÚjÑlWz›¦—¿í> O)}ó”b?¡?'ä€&¸þÞü· ø˜Zh#§À,ð øNýg]_Õœø`ÛÀÙ0)¤þd&v¬/ Ÿ[Ò6ö§çeG8ük?Ï_=g(ü ~Þóª?+#êŠ8^ëEÖýÒ~£L>Œ:ieBéCoX¤‹ûàò,ö,oSºåàXB¢­9PÄz¨S"aIûãŸQWMZ'G^ÚFZ¯(ß»äX´7ýjZß=öÑÕí"ô.º”ÞàÏ©ƒ@£;4Öé@ qŸ€îIJr¡€F 1¾ÜL]uþ¾_‰Fx:h€n˜Æìø—¯ ÅK=/nÜàS\(çç¼Ã˜ÓÅKãi±Ø‡‡Ææ8º²èÄÎmA»èmµ4•9„:N×¥QY‚ ~ż } 3Ä=ý óɹ4šÑ,®ù]˜îêè?&ú“—gBç÷~òü’ûßíhþX_?çÂò°0诚ñbôñ°è¸Ã'­ÈëÄžý ×±/?ƒ `1ðÌ×#úÙ+`¤þ߉M¯š§?ÓÀêàújø+¤âXýÍïéìè‡ØÇ"Þ]©ÄC—¦Ó¸ùi:çóL{G_Ž{P _¦âløû’ÈFC˜4ØÛÀN–!6r?øB:4”oÀºˆ öØWKÅÇ‹FóŒÇò,ê}àø`Ð0=€J:N7ÇËßy†>BT™D:ÂÐ×úønB~­­o¿oßÀìC«% ÕÆ™Ñ€qH•Î8…P8ÐÆp8·¶oÈaSЮíàAðá¶­5êv×û8|ÄË%_àré&‡{`hÉÅmEô')šú/||œ±ÿ#¦åq'øÑnž•[` ô‚àÖrš YqÑ„¼„ôg- Ö§K`XšóEž»á°,Õ.îtóõÇJè"œÝjàaù ¢Ѭl”‹tµ0-g™´¨“/cZ\C×ù¯ _ÞÆÂùà+^ß’Ö·¬EúîTþM"}™§òÎtÓ6"îý u1ž4ŽºÉX«¥½§Ÿ†{áP°­hh-"o8©tpfæåS¾@a­ŠÎÍwB©ÄDR]µ¸egûNû7&šIšŸ×i¤[€þ0Ðãþ¬ãÄ¿Ë8ß´ˆGHva~^oº^iî`;®ñSðhD{€õYKŠ#^H[B[=ìÀÃtÌ8¹6¹hmóqðKb]ÈÛªºÄùþ_{çgWQ=à BoÒ•*Rþ (RA齄Ð{—ŽHï ˆ.*‚¨*]Aé„*½÷nÉÿûîîYfoÞÛÝ×v—ì~ß›¹ÓîÜ33gÎÜ÷²h\5[‚cÞWâ3¼Ì_6=™¿¿„±ðR[è”Dýã®f4Y.«ñh$iPJ£Óùs£46þ“÷àmñWè±øqØ4î®ñÇ`kèíüÔÎj‹Ï„Ó¡l"Í67z×U;E{è¦þ-˜RûÈe§˜^í@à`Ç€—ã6æÅµéÓpü|æÞÖ¥hg›i<îS)­»¼÷¨ðcø>h“Ý”/„Õ`ðÙ£¾aºùGúk¤A¤¹7ù|å}“¤Â–îG¸¤Ž”yŠm8‡bÞD›æ)•®§'})ø;xHw/?žÉùÉFDBÒ6§÷ãäóf„]À9ÚFS)·e§Êi–7Í_þ !Q6BÓ+ÅÓ4ËØ†ƒä€»Á ßþê8™õÜB¢~„¦÷&õ{öư-uù Øçc4žnIªI¦¦´Ï~=¼å BRÝr95¿óCª·ztR_Ã`ªzHêLG|ChÅ3'·/ŠÁøêüšÐåâúÕÿ%ÚùšGõK &σV\îƒBXüϓº.–7²?C¬°ÊCN´[qSw£=¶zåV‰vb;8 ŽŸ£’h_\³À;¥QǶŒ‹ñT"/Bí÷ܰ?$Ô6Ô*Ñ^„Öx„i›‘¡{Þ~0Ô½}w¼v‡}àX˜â™ co±¡D–…4Mãph Òt.‹ƒë„‡€åÊâçvs°~*å¶¼¶Œ‡¡?Á’ðpHiûd>bÓµóJ„iükENûä[…¸FÕŽ] n,>ààd¬TŸäŠéiYK§Dz„fTЧiå2žÞÕ—Í@N7«¹ÀçN'TÚNoâTo™h êhM¤8É®N؈GÿõÏ‚=áxP/Í’­iè(8*MV’{-Ž™ÞòŒŽO¯H jˆ~.ÖSA]ö…°à¦æ^Ú…Póˆÿ«}™/Èôz¼/º1ï¡ ,rá¹ü³ÿùøªufžx=ÐèÏ ³ÁJp¸¾S»ÃeU±s¬8=:·Oƒ˜h±þÊ›Eê7cבvþðþå¾j³´O:íÑ¢’–·ïJ¦Çœ8NƒßÂdð ¸Îk'—öör¦3îÍÂömŠØ¦¶sx?¿Î4MÆÂWÀuëuO¢B¦FÜðé‘×_%ý_à=#/ʓԙfy%ÊDý¸Ž0ÊF™4Íøcp1xH|¢n„$‡^"qŽIe Ë훦D™r<ÊG¹¸¶\÷Z#£3æ¸FÜku•^‘ë?Ã@‡ªøkG›ÆÄ‰šñMÓzDN¼²è|n„»‹Wü˜-6¬´-ãq!I]$Ò#4³·qOúŠ›¿2­gºŠ{ÜX¯ß`XG+iù4ÞžÛ÷ŸorË“ÀÁ» âùˆQÏN¼UàNˆq'Ú+™žRGÀ‰ÐÝ)¢W• -ÀµsáÅRz“/‡LGƒ#øz]ø.“?ÁÙ\b7bzé dAa+‹2 3©r/œä!Sab4ÎÃÀ f'p³ñÔY‹Øè,ð8t¼MÓ™h•Ðaqß®qò~X¨ãš ×¢½û\ 2_{í¦u …¨C´3n}%òâÚ0Ò*…ÖIïmÇáVX \ȕڊ4>ÛãÚ¹‡D{¶¥Äu„ѯËñrù¸NÛ2^®ב—Ö3MÇP§`RŒÓ1„C†óá$TìHHÄ#4ݸÔh®Žk‚ÎzQVg·€õxÜB¢¬×7Œx9Ýk¥R~¥t'¨ÞõÞPöªËm°‹·,A8\L©s“–'«ßDý9x{ÀS ·Y«± JËÅI6 î…'!w.«ŠÏr9l >goëQ´Wò)¥¾ ×ÀÔЂq-Œ:Žäpvú·:ÚŸŽ[á{5Õ\G˜¥CîƒNØÈξŒaB¨7éeàuøLµÎM^sÃn°hww7ËV(ÙÍd&Øöþçai¨µïT)ÄzQ×Ð{Dš¡veÐþíS’–éî:ò"LëUŠûWí©£Á,/ºyò¶¨8P$<Ž7Ÿ) Ñì£ÀY%׃íè ¸Y”y´ëaðäk]O~½fØÈÀj;ûo\‰4k?ƒÀõé½ +µõhªhk(¡Ù¯!6r¢ãÝ'M‹¸íÏ /ãªØ¾R¾O\GØ^ê³òÕê¤éå¶£­já¨|2Œ½´²*•ÒL'À¬à*Q.§iE¡ŽÓß…«A÷@ˆvˆÖÜ–u”j÷3OÏ׌2šW–rž“j;¸œÐšíL¢ ‹ú,ß³žF]—€Þ¾odYtToºØ''Ûpü»Ó¡óÁòõ=ªöZÔ›Žìöà½Y‚QüÖ˜öŸÀØäX¸°½í5 4¥YJp¬â>¹ÿ±¼hÜ‹%¼<&·yC~J¢¯Ôuœ_¿?ê­píkÜC|‹æPíàÝ Mû¼ioÅõúOpí–Åõú pyp²¯öÛ s9Ðù_ÌûêŸÛþ–Ÿß4Ÿg¸6ï¸&(¤\'½NãŽë}ƒqølê.$úå"Ý0MsÜNÆ´xû½*!‡‚Šb=¥Ús¶çvm?Ò"LïmZz¶yöåÙùcfˆGhšâ&x.\ žŒS‰²šW)ng¼¹~S ;€õ"ì.=-SŽ»~‚µ,åò‘Ÿ¦;éO_M ÁÜà„nD\¨.ª¯@¥¾ÕÒ¶:}·ãaè}6Ú.M4Mìß(8 ¶€y Rÿ4·Ã) i¥¨7êbð$ÌéØsY³h8þÞþËí¬~Åq°ÿ•í/I¹ÊRÖ@بrú`¹öùzGïÈo_W#Ž¢½Ñ~i#Ö†Jë…ä.òWWÀd©6:=hFƒ‡¡u l¿Iª*ÿ&G×Õ6*‰¶Ð2ŠëéøÜ :ó¯ƒëz_ð™¼w#®í ±¦âŸ '´}%Ú/‡æ¥õ+•u߸t˜öŸÉvD}Vj3M‹r-ôíÎŒk±o¤eI*$ÒÒëhǰZÜòi^\¦b™Ÿáð™x¾‰Ì1x0S‰0â*Ö f X ÒÉX.KöxõMS¢¬¡Æòp¢Œ-!QÖëˆG˜¦U‹Û¾Ê_æƒZêR¼³¼õôduÆ€N€‹ªqnׂ›c³ÄMór±ˆVŸëPPG:e}!.~ïw ”Ð$¤çØ’:…\¶Lž¦eçàΠ¡ªWSt¿ëõmm«°à¾€~™.ã~ݾD¿Fî=õ6=¡×s賸•\Ì´Ÿoœ-®7¢à6ðóª[™\…°é6¬c+æCA' ÊíQ\‹©m®Vaj2´;ca]Ð ~´ŸG€¿SÁM»ÞC”{Oªö²â÷'þº³ÖKë{­Ž"$Úö ÜÛCjÓriùˆGå¨^¼=P×Ú¼ï‚Ïl~wRnÇòÑfÄÓúižéq–‰¸yÓÀÝÈ¢ð”ÅB!•7*ë4ºùGÛz‡ß_omß°?îK´KÜk¥Z~šþ妅¹zY>­›Æ'¿{K8F‚ý7¯^™ŒŠl8•îëâÞŽ…ÓÁñm¤Toªè”- ‡t.©oûþGØÞ†¾’9¹‘÷f®ó¦ÔÂ\÷Ûvó¿\cˋ͢¶¶Y2×Ùò ¨6Ø€ÎAfÃ|Ôu«u³¼ #gWÂó@ÛØLL¦v%ç¶¶êK0+ü fç}³ÅÍw8×»o0”CÀu톸, õÚ?Ÿ)ÄMux´Ñ±ik÷Òråk²ÇËè´øö]')êEHR§TJëÌ$b¾Ê’ðXìSZ¯7qªt‘ju,TÎ3-ôàæ¿ ©øûêï&D; Oʼn¸-\*$u¸,$na¤G˜¦§q'€ó4¸n€U ÊDHR·ii~Ä],Z'Ex…•Ú‹ò†JZ¦=¥ýÓô©` ƒ«Áw´M´ßűÑé96‡« /7Sn×­h 6Aä‰A1T§£ ’SJrËÄW~;ê‡àªUX#ãŽÂçb.8ínƒkÛ[š‹!ѵÈÒ4IYÚ5p6öìã‰ÿ´-Ú_7‘íÀµ=%˜V mv*…ËBTòöàÆv>¸Q~ õÌwªUm®kÊöc3²?Þwvø9ü¶7oŒÏYO?â9ÝË®„-@£D^7-®#LËù–åL8t”ȰRZäF~„Úä­áwð¤:á²³ý4ž¶—¶ÙSôd„ë ÞIKÕ–Éiyw1áÊ7›„—!6âr~+®5`G‚§©× óúCσ†É¯"jô<ÅüèƒínÿKÀŽœ³8ï´.¬¥A\v .Ÿþ—ãÕ·òf{Nþ6Ð|˜)6é!ß"ñrÐÙ\êY³ÚÃ;ÁMÈøÂphãu€›!öËýÅ£›êÚó}… `]xð˜‹ÿ+ÏB`Ò}ŠËE›7Ü,À.ö][Ÿê,l¿iî77ÀqàFåÒ2$w¦±l”‹4ÃH‹¶|qO]´uå2Q–¬ñ$½O”Kë§q+§×“q}Üçæê«½¥%àP¢pÄ'"ò0hÍN dH”ÐôJñJiÕÊFÛÞgC¸œ$_ê *Þ#MOïg]=®¡RßÓzÆ•´~{J÷ŸêNàIðÍÅ×Á´¢UÅÉÍ;ââY](­’iØEq3Ø?ïý3œ~ KCºH¹l™x_ÇÄÅ¿+¬/‚Fí ÐbŸ\œ¥W`~è­>0Î+žßþZv¤Úú0. Ëì ‡8KÏÐÜdùLš"§ä.x§ßK\iÓ´np§‚Žj­6Ëõÿ=¸œë¶á„ýøõæPk›TO¼Ï0ö·šxè{V†=`Vx ƒazð€Ð[»`ßç…·Àv]æÅ3•¯M·íÛ`5ÐùˆòQ'½NëGÜP±\¤¥u#Í {˜FÁ” ”Ûòåö*Ý'ê—óÒkÛѾþÑ `rP±*¨ÒÉ5:îu+hœ«m du¼Hãí¹]ÓÒüJqg½}ÛÆÂßab¨T–ä.é^+QVE‡ƒ“¦WŠGóju゚N'ì@¢ãî$Ì鳪½Ã¾Çwš4hû‚‹}1˜\ìÎÑ´\ö‰¨«­a ØÇžÄ>NËA…7%çãÏO}6À­º°§ú9¿SÙèTEg¤XlHw¼N’ Ò® ÏÂæ0tðk7{× ›î>°Œ„î6l²{-nî‡ÂÉེûñ¬kÂN°l [Â] ƒÒцø,\Õ›ÏÜO’ÿ_øråÊmP|¼v#-Âr÷‹ïš‰ü4å2$u¦U‹—딯Ózl†-Àø"â@hôÇÁÞÊey†½! säGHR·iÕòM©Ô–y‘î€hŒuRìG%‰²æ•ã>çÇI¥r~’ÕpÔ‰»,¬ gƒØ@õà8‡`(ô•8Áõt“Mˆ‡aðSÐá;·ãz[Âó@G*êèÈõ•¸6<‰¸{»6º Òž¼ëÇ€Üà IJpûož5W…³ß]õœ÷™´ÓY*kàšÑüc€—;ò\ tC7VèZíöt èD8‡=-zÀƒ-~ « ëiîS¤GÑæ.sŸ@[ГØŸÅTüàoºø^ÿAÂÍÀ~Y&µç\vópÌ‹}#-kz`ãî3§ë¸Ó”4Œ:=¥E=ËÅ}Ó:‘oÞVàÞö&TkŸ¬.yÝ•KË–ãÞïß°†8:ôÄ}øû $ò¼> ‡Jƒ––³¬’¦¥ñöÜöÏH°»z–‘c@ƒ¯€¢n„dwo'õàäÑãªV–¬.y^×+*ù+0Ü^o#-¬çXÏ Áài¢’N|õþhh9®Êvpè||ÕuN%®Q°½€hËÄÓÿ{½lýv;ó+e]þØ´qÖËʹXh ûM´5¡…šàæÍöI¼ m³ÖÞ0 .†M¡q~_;ÀE SàÚZÆÂm07ÌÿzÅ6µÇ¶¡Ò~BrU±þǰ3ÚÛð½˜}4âóŒ†màX˜´ÖµœxÒÎÜÚ©j}‹:R´³ã•$ÊFX.£.f`FPÇÕÊ’Õ%/-—ÆËå¼öW Ð&ɸð"ÍЋtƒ_4È1È®Ä§à‹ ÂBB¹šžÆËåÊùQ6Â(ašžÆß¡À/Á?4ΕúErgbs³´-ˤÒ]^Z®·quc8fSè•è€ÅéÅ_àq˜¿Ž…n£ê3DâøæÜ9 t6CÔÃuðAG‚:œ¸Š:[ìOèÌë•À²–ÓIÝâ¤c¿u>óçÛQ¬ñ"¡ŽO-ƒ`‘ õ½'÷˜jþÕà¿ÛÿÜ‘ü®zþ¥ï…dÙÕ,µi <­j«=á—vÊ]üö<æã¼¢·>Sÿt¿ ÚÃûaI`>v®-¢UÅ-ëä¡Å Rqí¸±Þw‚ky>hÄŽ}…ú:ö+B½í3~›6ö)ø=< :ÚŸÃöc3µü†ph#Ü;´Šoïm—z‹çS/Õ$ê¦ù•ÊWJ+×Q÷kÂyཱུ3Ú³´jñ(aZδ)I¸‹ðæoó±xÓF¥¾ /‚Jðú^¸ <™g£ñà’Ô™–ÆkÉïm=ïï@®gÀ0x¯ô~\â&t78°Ë@ ,Ñ.å+ÕµL£ò |.ûþ%HûÀe!öóZp‚¦_d¶øÃó4,¯ÂK càâ/‹ ËEe¿¿…õŸáxܨkú¬FèTO{ÖùØ®{ÖÏá}x´SƒÏ¢QGÚù­A[kÝ¿Âc°¸ÖÕWè,âê!Mãr¼ëH³\¥ò=åë”\ÓÃ}IÛ"¹ó¾Æ•èWÄãþq­´«Gã-ý Óå{tW ™PÅ÷*jX´biG¸¬ºy¦mYN‰´4^)­7ùQÆt#¹v¿R›:[Àåà„©T6òšz¯©a ¸Y­C*“q±=\NÞ¾”)¹Ù៰ü¶ÿ€ý]©ócAc ˜>/8WÃ-ÁE¥XÞEgØ[±îÉp<Üca_x ªµ£aRöG ñ›ÓþÎu~ØÏè[ô¤ne(¹;ÉàýRaαñ“q¯Óòï?û†¥¥r¼ Têš4E'f^3’I7|¸‰¬ :à„ Л¹îšwý¬sBY\O?Û½b_ Z“ØW;¿†× ™î†þ2h3´ç€Ï~huÎ…MÀ~< wÀf®íèS9¤Xg{“W©|šVŽk«®¹`YPçJÜ«žøTú \ãF Û`Ä õTζ`gV%ÊT‹§ùïRȧi°7íT+cºƒ…ñ-þZÛù„±IDû†SÁöÀ ­˜ ûdz_ˆ‹kIX¢ŸÞ·?ûáBxÜྠ[‚‹g8¨CÅr{Á§^ ^/ ©aÑ€Ô+nÚ#@Õ ×yx/ÜÛAÜ—h·b½ûæs9mÿGà¼Ñ19æÅ¶»;‰è$í .¢pj|~æ]ø Öo¶ã¶Cnk7·“𥠤CØ@3ƒ¢ê90¼á\ÔÞ®gÁ—aap^¯ ®ë™¡'ѹwÝW[ ÞcCض홫ÔpÙ£h·/Ûø)|Íû>c¶yh×`!8v€Ó@‡@Ñ>¤öKV’Ø×"LËTJKó+ÅÓ:ÆÕ¥¯w: ÇØFÊå+¥wTí þAL§¢0ì6Г؉SÀÉp|O…KùÖ½Ò“lt2 c’EšÍ¤ñô:M¸}ÓÛ=|]ò pb¥¢á·\HÔõ:G~«Ã-¹ÁQp 8áúZ{­kúì.ŽàYpìÔã/Á2cÀ /d2"i] L³Ä¾=s€sÇù1/üÇÞJºˆ­³`GEÛ÷ †â†~¼>ó&à²n¹>I…Î!Ü.î¸ÖiÚ†ßR¢n1Uijo‡, jÀ¡ÊR›þÊüüšózZØF¶ozØF€öÒùÞX_ÐFO×;—…˜¦Ýð>ß‚aÐS»é"Ú¿½Aû­TºO{Ns>½Ÿk,ŒŸÍƒêœ×Þ?ìL¥¾Ä¤,‡T+ÚMÃ4Þ]ùJåLS·ÇÀF0?„n£-’:ïi\©–§=Ûd >ÂÓŠ‡+‡6bš Ý žã’u¼Žx„‘æ+˜5@…WçéðARÀvœÀÖOÛŒ‡·hšצÙçp4XÞ4Û96†Y ­›ÆÉêSqAnöMÙ½ÐÃEÜE'\ö(éÀ[Øëj^ùSä ê&ÄV'onpqÜ ;ƒzüÊí“ÔѹØ~á7¼§ÀmL® åq'©eRÉPÁ“°¸A·BtıqL4Ÿ‚‹Ï>h ç‘ké'pxÛ¸Ã_hrlûoww#Å’ý=»èÂç_º[Ÿÿ§kÍ“ ì†ýX*Kp3Àõ¾h Ü Î‚ÕáËàœ®&®í¾v|=¨dKH.ĵ¢½qCõT½1¼½í–„ûΊ  jµØ·kÀ½Å v¨£ûàeP‘©Ý™km6³Ü?˦“5â’=^¾yZ Ãrœ¤Î4ãî'Ââ ƒòTª—¶G‘¢ýi(xg£æiÜ›•ÃDE¦&r<œnŠSäu„/›•›v*åú‘éš^ŽûSA(ÔüظÆÅïM‚ƒ±'Äæ¤RlÇ ä.¸4âð™°ÌJÚö”þý<ŸÛo,Ú¶Ñà$³.*uŠàhð9C|nŸ3Ëm .ƲX>&Q9ÏëÇáQ˜,§cz&Ú2ñ™g€ à*H ˆóäpØŒ·Z¼‡ýQÏgwÄ Šùé‰[aþ¶q«<Ð6äÏíß&DJ:c¹ÌÒˆÊS¿‘¶[ÝÉfâüöCþoêÚs7º9a9ÐNh;/‚­ÀüîD'àzps^þ ÕD{q¼ ÚŸÍ¡¼_TQ¬ãš·O¶Ó*qMkWGÂN0ØWíÛå°˜¦í¹â°¡Ô6zPÔ£„¤6âZ&âå0ÍKãQÎ4¤+aAXBÒ2iÜ|û~üxw>6†AQ J9ô&¿==O8Q޹ÁAºD I¯#¡zЧùv<Æô/Àí*Û¾þ 4ÆnRLöÂS²¼“Õ‰è³l·ÁºàdNïÃe§˜®§Û×âsúª^§ëFø5¨w'éaPöºÕÍwÀ 2=‘Å ¼8-Síy£n¥ðqï½á{àäbLˆ¶D·Ó`5XÒçqœ_„Qp28[ÝnQˆóFqÎÝÜwŠÛ}‘ÙXøÅ#ÚSëÒ6U³TÒ€S=K}øäuþñÖ>¼L¼”·ÈëÑÆ…ðE`ÂNí.„º¬gƒëL›Si=is¿Ú~çº&¹ì"Úa¿nP´:ò£Á:•Ú&¹Sf!öxV‰ûÈ´àžà[¯Ýüí­ýÔÞúÌ®ùåAûißç÷ÁÁ³`Ùµa+;:´|Ô û[)bãI”3#Ú0î¡m&x´…•Æ!-O‘âùìkñÝS¢C¶§¶ºâž€U Ê-^ “P¥¨¸áàC‡D[š^K<-kÝh;Ò¤¥ ”cºJ˜»#ÍÁû¸)(ö}h¬„žæf=¸h“h±ŒN÷èkñž.e÷™G‚ýJÅçžœ©Dý4­‘¸}zÜwƒ3àh¥8ÿ³ ü<>ï°?ì ®¡/Dƒ²4‘=Ú_*ᯌa¸FtdU›YQ3‡5j ;5*¬\;:óæ˜¼«Èp=Ç<Ž™z.i›€üÑÚ|.;e!b®ËÀ¢©•#Ѷ'é-A›:l[ÛUMÌ?¬£íŽ=€hSÄÉt1ü.ÛOm¨×~ÀÚ.þ©àÄI¾Ï¤ÍUuiþu þ¼ž N°Iæ[ϼžÄ2¡·´l¤Ú×5áXø*Ì e‰ò¦¿®Û“¹A!n!IiÆï½œÅ  ÊZ(¼‘F´3^)ÍüTj)“–µ ¯¯ÝÌcPL? BnšnZB˜çX$UÛp‚ö‡LÍM·É%à¨Î+IµôJeëIs²Ùu1ln¸Ã¡Õ÷Žûr«ñÄ~MïA}òfÑ{YûÃ/¤+ª'Kó5àrÎÒ˜ “8¾ûé~ݼ†Ã¼ }w iwÆ‚¯Š‡A5¥k¶½]{a?¶ Î²°-xˆ¬fC,¯M_®f8´)>Ÿûo4ß…Jâý=e‡#ÁgÖæTß ø<ÊËp ¸÷ø|‡‚‡8ã_û ¨_ÓR=WŠWJ³¾úÙöƒy öéry÷Ç­þû`¸Ç½Í…RŽÛ¹'aœoR.çÃþ|p_C{¥\®=µþô´½´ýH°|ŸH7ôUÏcp ¨pÇBiD»È]®úöÂ…¸%¸£œû‚¶¯EÝyʾœ7Šã~ , C«Dlc Úi$ÆxeN…𸉶T\`Ì÷iá'ñFÛ#›sb¨†lßu–·´ ƒ­ñþ˜þ¤Žq˜/¾oõC¾å<'œ æí¢¶ÐMχ@öŒb³2/7BË< ‹Ã§n:\Ž'æ» j×&‚[á9ÐŽ¸Žm3ËÛŸW@›3 Äz'Z³xêwCþ5¼º¨*Þ_{²!ìöÛþWûoe Ø Ö à @çÅ_Ô‘1þDǵ6Ôçs‚»—Æ>Ú“>)ZôoSÂÓA{9D}¢…LEC7»ÏŽ|ÒÁLj\œ*çzxʉ:Þhiøèñ,ݵMv!Qß‹žâi~Z¾œ^4œ´—æOIúÍðGpãwpî‡û@™h'q  aŠâ° Ì ¿¥ }..ûDþÌ]րЉ}PWcÁ>9Ês„¤†Å }låI{_ûõÌÖé a±Ïv ß4=×vøÒæÍ¿åZoÅky§ð \Œ¿~{{ÏYt’xçZ¶ÏÚÈÛà/0l åÍÒµö«Žt7;mBoE§ã¯àþò0èh|*9úÚfûá}¨G¼ß-àóè°¬ µ´¥ÓðEø:„$Úk™¼£¤v]…=sÓ׎bO Ñ©:,Þç׿Æ5Ñ.q¯uFÁò°Ä><•FSùj6¾!<ô¸wÉ ±Ñˆ%ÃÖ6/|âa#¿RèµÜ/rDëŽ×ÒFµ²üà5Ø TŒ~}˜.…§aoˆA"ÚïâⲿcÀÉ¡Ãò{8ÞuÜ¢^?'bˆâø'ìµ,~Š÷(Nèß÷_bBOÔÅ]àÜ^ º+KvCb¦á 1‚óhÛ]GLÞ¶ê»=4t»\ù3 xhÌÒ< Œ}³Ïž´·;ËìNBmdˆÑ7`˜ ®7¯TÜ@]o7‚öªù„¬ïfü:ülÇ5–ŠvÙ²ö±žI }xžíþPËæOñâ«mðó^Ô!:6¢ú6øÜÁÚă­‰ÚÔ!ö,±ÁTÄÕQª' Ë^>›yÚÐKˆ\}$z\êÁ¥•#>åÎßhtÿ Jä—Ãö\þæ$‘3`˜¢Ѻ㵶á½*ÉC$¾@xRnVz^†N•~ `Ø»ô—Ë!öó«°9ì3B‹bUð” Ó˜Ž— ‹ãó7XzÚн÷Òð/p.¶R\„0]m{%6ÿ [y¿Üv§ê±ý•s¤¢^aSœæÎ‡‘}¤JÖþÏ +Âkð”Å2.ÇûCbår•®=ظqÍ›Á°)h‡Ó~×~ß ~jíˆ}¼¶yÁ{Ö*C¨°+œ Ú:íY mŸæí`6‘pBz8U/›t°¡vH½öϸ㸸ùO…=ô*!:!I]Ò4¸z)ß‚PR”¬N‰4rNØì¸7W"¿ÖxZ¯h¨ã#Mï)n¾Êý ë¨o`Ú÷ÁÉîä°¯sÀÉ ’§9Ä1°Šãå¾ D#¥IDAT7+Ø÷#@g­¿å:p m3Åñs\(½‘©(^oÊ×[Æùò|±Æfóä!—Nû,­×€ö,Kó5ð>ûâñ’qZÚvƒ´é!®ÁÝ`Øþ(³qƒ;ákP„]ž‚Ênp_‡]:Ò¸Á¹Æµ9åþ‘4žh;ìßÁðè¼ ˆmú†âm˜âù‰6UÒ‰îAë<ðÞŠzðˆ×t0íPî/ƒcUxsš¨¨Ìˆ‡‚ß#CÏ"$Í/§Åµa”›”¸JqãŠ4¢5Ç­íDhzOq•¥âöƒË@/HÅ…¸©ÚGËÅ£ãã$qò}6%½W{Jß|:?ûsÄ++7 ûí@±/êùtØbžíSQ#aøøŠ±™ógfĸbL·}3ï‘ÛêVNµ,­ÑÀ¿â€ù]&´›Í³ -Oå.΂³a¼ÚQÅ5¿hk$×°÷Ñî­¿¥nnÚi7ó+áQˆ{OÌû+ø,G‚‡”â$L؈xÀ8ÔÁãnÀ\¶D´2Ú2÷3±:2WÃ¥ ?&~_7’\|ÏF9ÝÌ"n¨×u;¨lë¨ì4ŸËB"Í‹ˆGhÚ|°80™*æ“Ü)i½žâ=åÛ¨eT–åßá$p#pàMOÅçSIÿ„˜H–q:馃›Àvœ|ý!öG§¤<ɦ%m¸ÊÏER¿ˆN‰CO»Yâ¸Ôêa»8<¤ãÚ¬þ¸†Îfé½RüÔÐVÓYÙ¬»ävºÑ@,ÕnŠä¬4ð0öÿ‰•9ûœK#K1Áù:wH¬Amëk-X܈m¥vÓrSÁŸaEÐvÕkŸÜðæ7º§@;¬m™¼ÿž°ØŸT\‘öç'`ÝoÃÌ`{õö…ª’êÀ} 9+ô‡%Pç>—·ëÁÚ ^îÙ‘7s=ªîDÃíÃ< ÃÛ’>X¥xšfØX&¾ üÇÄD¢|„fõï)?mc..†WÁIRmà5ækÂ^°%¨À'îbð<ÏÁâNÑ>ŸçZðmDôQ}Ì.ˆÁÅVí9ÉjŠÜL+.¼j:Jž‹ßþ¨»F›õŸ߂訹Ðz#öï;à¸îê¨Ñ¾¨oŸíüï¿ç’g¸ÊÒ˜¨î9˜néR¹”½`MæüdztÞ-=½Ü\\›Â(8fíÓ·` ÐþOˆvø›0àŸð_Ø<…Ûm¥›ñXv„yÀòÍ”ÐÁÊ4úpÿìoÑFé€yø˜^a‡¶…ž6s+j¼}E²¼•Är!Ðtãqí¤9 ö'F¤—C²:󺋛§DýJqóðV‹¯;ÜØwƒø(SBÚ¶innxÛ€èw0šnâ†ïâXƒ¡ü $õ™èè- …Jú¬§#c©4LVCeÇÕ9¼7h j©KññD΄f$¼»xÂÆ+“úLÝ-é>ëÄ|£0!7òŒ§°ÑÿÄC”o@##žÝÍÆ“¶›ì°kǵ›¶‡%mð¹à›ÁFD»b›KÃÆð'ØV‡9ÁŽºæÅ•¹˜ï!Dûn?[%óÒ°öåÑVÝ Žv«s¬·Ï ¢7’`Ä ­pŒ„؉åâÚ0Ò"Ló"ß sn8†ƒ^Z”¤Î´ÞÄÓz–‰t½Íap81|–È#ZQôdO…ïÃJ8ùPBºF<Â[(7-,©D¾i/‡Q¾RºN€oÜd—%êt—ÞS™ÈŸ„FŽ„£À¼ÒýHO¬ïäuãênð,·Œ†­ ÑS%M4Mã9àðKèO ©ž\ø.§îtJvË¥^":fýóxŠGÛ¾BìµHÎaÿi ?§wÿ=uÿÝÙ%¼<üCûçš®6ó’·¸Aëx/Ðqý{B×Q³D£cq5l›ðp:øæ¶/å=nvŒ-„{QˆoZa´ÎC)þ±Ÿñ¾{·S*O‰ÐÍã|ØÜH¤Ši¦‡DÙM¸ñ pè¥Ez„$ךØS<ò¡¿€•À¯êõPmbG{ô±p NžêP¤Ïd*îdŸ|–þ©KÁ71|ÿîÜñytÐêAßÜ\õ ëÜ 7fæabY€Ò’êhy4³šØ¥Þf9œHD;^IL_<ÿ´Éóƒé7B££ëÙÃÅýp=h‡Ÿ†Ua5pb\ /ÔÐW¢r^€+á èëI:%ø ÷= £5d{ç;\„ÄF™†Æ5¬Çu@CæsYHwiè)ß2nʳಢÑBâ:B{Š›/NO½žÈW7´.—=Šƒ¥·:ì_51Ï I]?ßnLµÞ“*Mï¿ L.<þê“zÒYÚ .‚zß–¼EÝGÀ7õ<‹uf„3¢½ëMÍKxqñbS“–e€h ¯mëyì~íF±üØ€×z’¿¤{$]©f_Üì=ï:Ð7ÁàÀ¯h‹†{#Úí»÷²îHø!<ÚÜ¡ Þömÿ,àû¨-´þ Õb_=ø¬:;“B_ÉäÜüûc_ƒìŽO tsWÙ¡ðr¨B‡iakø”(—Æ+¥¥ùÆCÒ²¦yýXþ*&-ñÉ®˜Ÿ¦[Vt,N…™`H.{-Z”åàNè­uqò­c@=ºÑ¤ÏÀeŸ‹¯Ýׂ/ÂÉ ~šÑ'Ûp!©_'zoÅ983`4êïå©ÁùS¯,HÅç æwoÚñ;ÿÑ<éÅÊ8—*µ¼.|doÄqxÎç»[Øã5XÓ¿á)&YŒYaAˆ5«½þ¼œÎÁ§ð œà\{QþßÄÝ¿7öïÁUð~GC¶¯-Ñ{ü%ÜkƒöèK0'Xƾ5ClK»wlÚ¾îöZ²k¿÷€›ÿmôz }ê*XñæSÀ±àf´*¸Q:·Àð?¸!+–‰x„¦G<Â4­Z<-›–±'o)æ‚PJZ>âR¬ó™þBü&à™›òwi¦ûusG\}¥÷îHî1p‚ .=Q'v3ÄWWÛÃ%º7íúªÌÉ>¬õz¡Öß <ɵˆzô~0è, .ºžÄgÞ ®çv#bf‚Žgá5*Ž»o7Žâ~\üŒÒTWR=3ÀºYZ¬'ËÀÒÀºØókµ7‹³p°ÏCbÜP׆Y“þº¶—Áš°¸i7kÅùöð"ìþ> úC´xKëé§àú·b|oð`úoh†ØŽÏ¹hƒš!êù8m>ÜÈ=)…ÉR‰n†ÓÁi0;lz__‡¿€F/ê-$ B#aš–Æ{ÊO˺Œ•bß*Õ-§MA9õ_° „óB´iâ›”­à¨g³´Ïz}cÀÉd[N¦FÅSà}g„õàð8æµJ#€÷R/ÓÂ&p-¼=ɤØÔe­NG¥¶'!QgÈñÑà¸0Ãiüüóùâ‘öÆ5)ªåþÓ@=S¸ÿz;Hî|ÿ {¡ùøú{–ÄÕ0,Ñ~9$«È³ü𸉸9GY¢M“©hIçâ ¨ÇˆŽ„êW/ëA£¯´qÿgàBø¼µNhõ⢸êÝŒ½§Ž§›ÿº Q¨&Ž­ŽËúpTZ¼$×,ŽéQp8§\û¢×Š?Zï“ÑH–¾Ô€65ËÒ€¶…}åV‚[ŸæŸþïËŸ¹˜‹îÖ¸'î•à=˜víÌùð¸Vmî2ð\±¡í”8x2Ÿµ#õB)î3Úqí–ÁþÖ³ç¨mçðChDtš<øÒÇß²±oÀ¯UYY†¶­Rú)›°ó*ÅNºŠÒR– ‰¼M¯¯”V­l¤kxUðHXÜà¢I*&yžÒn€ƒ¡ì¸ÔTq ½§§^Q—«‚¦ŽË‚Ð_¢¾æ†½àPp"ê˜ôµ8®sÁ}àÜKç—]Ä7UÛÂO¡™Ûr,ø™m»à½V´?ŸY>Gpúd@ؾk_ÅÙ_b/xÇ{M×"íW”+Nýž <0í ËAºpY³Xß·}g×`¨Öf¤OA™­`Ð ñ¢sÂDîW\ö(Úà3aS¶÷#Ú£¨'‘0‡èóU¢ß-6ÂÊgË7‹ÓµV¿Uø2KWÙ’Çú·±sâM£“*%âD;ã•ÒÒüîâ®bïáf¤g£”ÛSÑ»€¼i.›*n6—ÀF ç×ÈÉÓ~n:-~M3 ´²ï4_U¼¯®¢Î“±¿d.n,wÂÿuÓ ç…caŸ›é¬øvl X³˜yöäyHg:—Yº²0°Ghöæ»tñ¶mùWÚ‹Ù\ee‰ ÖÍѵî‰ÝÓ÷)àžãA`a¨÷ôMÕÂ9ˆð@pí/¶×h#Eq°/GÁs03¸?x@ü*(±g¶_Uþô­Æ•°7ØŸé îA´ª¨7wë£ùéáŒë5ZÖ‹í¶£©Žà2þÜ‚TêÖÉmËv9kH(•ôaTDºÉuWgÀšð+psOŇ> |m=%¼ }!q2Mû^ï}u œÜ:1žÀç†8…íSq̶„‹Á…ТN§ÇÚx%£@rKÄYÿ ¼X,;í“›¿ÒŒ‘no)ö‰úrÚôÉM€7‰ ê|žm‰o´µ-»uèÓ ›à^0¬zxg¶r&XæßÔ#q¨ü5ø&Ôr°°¾{§ÿW`4x(Ì[–÷?û˜>—]Ägº´ÁCÁú݉mý˜Sÿ=í]¶»² äy›îº2Šü:ÛÊ¿_Ÿ—ø±Yúà‹À’z5*Ù¼´å4®Q î* r"ß;®¡äH'©¥¢'º\ ¯CwƒIvb¿ý‘ˉ°:||ÎZd2 o¾Ð©¨WlçxÖǦ'±ÿ.Âõà*häþT/&½næ)àý+éW7×û]:ŠÊT̪¹Ó¨âÇ>Ls¾OÊò9Õ@¥)ó9}” ¿Ûlæ³°Oüc~ï=»/xHEãû ˜´¿n¤ÿ OÃËp2˜®M¨gèX\ _÷ªÞØ?Šuïë¾¥ð[ðúˆY;ÎE%[9ùî+ÃAà3VzuÂaiÜdc±âr, q(7O;:ôþ§[³Q¬×¹û`nZóv”0pðt|¸©‰l¿7&ºø®zS u ¸l¹8InU/-žhCâdsп³Cª.»•f9ÞDýn.¶· Òä#¹S¼÷˜–‡púˆÖ%.ðÇà°”õëÂú …•!u(¹¬I|¶éÐôµ<åè⢓:ê›SËÔtÛ\¸µèiʶöî¹õš5Àšž;þá±,º»09ÛÑÂ;Zq`o7é ;òµÇn˜ÚÃ`%Ø ÜKê‘¿SIgÂF£¶l"Ú°ÏïvàõÀÝÑÍß›ý÷>©³œý?,ó”'õ 芯 †<Ûþ­ƒ*è¢Éž°¾‡CðG^›,Zt\¯è@ð*J˜¡"¿Á÷ÁM÷(p£*; $õ™Ê΄z'Z¹£°á8 :6åA'©¢4Ópò9a¨ƒ3«»~LIþnp8Í߈l ×Bùþ““fßöR½âÓÙØ£ç™5Y& t7]'€Ç› ¡ÓôŸÇcz’®$S‘¸¸9zÚqàoé¸X…°ž<Έ¯Ô‹ çA¬ÙâÚÏxmþ0 R'€ËÂ9жêì|`B‡hO„¶çÿf¤Ãt­ªš›`µ.Ïq>WnHžúÞ vþÎÙBZ_ŠÝ8 Ò ØŒ>81tr.ƒÞ:Ít✌:#N´îžQÀ19š9zÆ»Ã((Oþ#IÃû-A]âÚ¢ðç©«~®4`5 ›åó©7„=è Úý÷ < žž¯„]ÁƒRäk¾ÏÂŽà~ñèè÷Vlï Ð ðä]K]Š÷(±ãù :0WÁ\°=ìÚ6ŸûxNîÀ]Þ狙ݒ—lþßäòó¼ùÓýbËpØDÕ¬Þogg~šõ}¾å¹âOx"T9ò2(*&(ZüaϦ±Ùb›N 7?½CïÕâ}§„V¿ˆE¹çLìß+ó“/l¡Ê~ˆ'sOõ1À:ôµÚ mTä-œ€g o߸ÑîÓ¯fÏÈ.D{«}¹¾‹BOu(Ò°ØÿØüµƒ‡Ý¿rŒ‹u·%=AJ¥çÞ•'UeÊü0ì'ÅkË÷ ChJ/®Yƒøm¹Anÿ…f‹“ûyø5ì öݧ¯$­p¼‹Í¯^¶‚pªˆv‘V9ÞÄû_G€_‡¨“ßÀÌð5ˆq%ZQÔ×PJýÍ=Iüæ¶=ùÔuû-d™@5 ¿—åó«—µK÷lßöþ…ßé¾ÀÏŒF?<þ¾ Úqžð7…Cà\ðvR›¡­Ø‚@[¶|Þ…jb¬{̾ehµøðöÛзÌëÂaí™ í¯ ôdúÚKMxŸåçv˜ü¹ÈgrKÛ½\¸]}ˆ©?¯Ï¡nàIv9ˆÓ¤›ê¿¡‰M_/-âõ´S­Ž}œ6†ïƒO™Nn.[.xàÅ+0àç³O}).¸ùá>X¨ãÆZ÷žôí,™ \H{`>å/F¼Q¸Rw’e×@Øÿ ü1Íãypÿ7ëþ?§qØ›ýÝWûKƒö[qÀµ äµý Þ†j¢ã0´W‚ö?œ ¢ÅìçÀÇK4?q:6ùíx4žñUî9kóï0(Zồç|Ø6yñÓºMŠ+~{Xbcëi";><:‘V7êVɶ¯:¯²ÊÒª7ÞG/t[¸>‚²LK “àÆÛLQÇ×Þ· ÞëÁQý&T»Ÿÿ´oWÌ»ŒùÇ…+PØjdpÉd™°4à˜ŽÃMäxø;ŒmBØíÓÙ‡•H'©‹xˆð€°QGê„+€o3«ÕaC®ûOõRµ×âýÝN€'?{¼âù{ÝH.Ø[ œJÁAÿqÚÏš3ñ?'^•—F±ùÌJÎ3”_៟xy¢ÔTqã{þ;Bºéº :ùõPcÛ#Ú4Q+¾vwV®ó‚inþÁ 0´B¼ÇÁì¬~w(è1;2¿‚ð£¾g‹ŸùXêhÈ2ˆ5àBÎ2áj õ:<âìËðö¨¬3p'nøºܰ·7êžD;ú&<þÚNû¢]ÛLׯkw^ߘï«ú7 ÖI§ý´ÏnúgÃKmmÇòVâDñŒD³  8\kƒ>¦ï ã4<²xw0%×z›»³-~Ü1tõi¢‹è™êÙ^z«1ñZíp«BâópA} }áp›¶`}X ôÌ@Ï#ÑóG„ÿc±{Hu))yí´ëaÐ~Öj‹­¢&Ÿ;tåùü‹M´ípؾÚßßÁô°*øUAOâäq“´áOÃyphãmS»§µÑ޽ëÓ§âßõs{çBÆîÙd–χ|>8M|u´4¯‘®)NÆ^Ï Gsõa‡C Ç§Çبurrêž §€²¯ŸáXæ'òEÐÊ74_¼–óÍÆÎ03艿Qüï:tž‡,Yht‰u6”#Ÿ+ ¼: ¿û4ÑñtûnøYG÷Ï%¼´]íÇ·ŽŒ^SSn_x.wê˜dc‰ûÕã–оéF|“û6¾F° 7|€, –䙜nW:C8µ)6ì"˜DqÝÛÐ7;Áhp2ö•àl½Vy Õ€‡ßÉPœô½zæ…,YU5PﲪÚ`ÎðpÌ5š¨ç¶áëûùQÿf\,nÎóÃvp à(Ô´ëÚð`HÛ…ÝÛÐÃÈàof‚o@%'@;©ó óqX[ñÓ2¿Mýd<˜ƒG½üVʯ&ãótùw¥zš¾®r¢)Îj݇¸6-ä"çÀ>`½­á2ð¤ÜJ±›ƒŽÀÇp9¬sB½¢W¬ø¼~÷¸’)¾pJl=¸”XëíWù3k ¤'H–Á­alúc|e?+æ“WøC–#>-< óÀªPÏDÑÖz(9^ƒeÁÙý°¬6M´g…kùm"ï+­²(Ùµëa°~:•.…زÿ×¶8ÿ- íï Ú½Éÿ£„Þeˆ³Æ×Éõ<_'¶¯Èu Z)¾móƒ[³?˜ÑÃþz+:4."eÜ›¿²Üô}¶ÇÛžáOwÞFÌ›B–¬š4à4Ê2x5àøkb†Ãl;ðg¶Ò6îªqmC^%ç#r<Ši·cµN˜°_Öó¤MôMìoa À)7–f_&Ž=~÷îö[y>ó§Ñ?¢Y²ºh`A®Ö‚ÿt¤~Ä/ Žä·sw–rƒßœtºGÂ=p#øÃ•Z6bŠ×,N~Ïä§ÀM°TzõEr±ý‘¤KÈ䤞Î:ÐÑ1ý~þˆç›…+ãÕßà/ äµÒ®‡üYƒjµç54‹~Þ40;Ÿ“ÿˆÿ]ɯí7kÿWC?g†ì!sGö$ïᣞߨ‹IA;ühµFØÃ9Úý“¨¾Á#%k  |™JLãNywàñâÊíÒMÿC˜‡Ø\?©âÓºIZHïë„÷K,ݕ A!•)H9‰;>›$zÿµ-ϧËÎoÈ\'ö,KÖ@Ãhtz7ÜÜÀ€ÒÀÄôæ¿|‰ÿƤ“´Í°ÄmãÝ¡mˆ‡¨—:º¹#á `Áž'—+D;8<)Ð,2hÐâe.Ñ,YMÓ€gê²üïÍ·bö]PÎè¼^ŠØ÷Á¯gö¶K8 =â²üoÆþÓyª7×5¢cœ%k épreÉH5àœÇÁeì–g•7á“ßÖ6ó>+¶µÈÅqph=»³LOáLœÙ^ßsr7¬]ÄÚ?Š{%×9š50P4ð-:rðrª Òu¦ëÌÒ„VsY i ; ©oPU¾ƒï ?™Ó¥õê¥ÜK9ÏQ©t5…iNŽg  äu0xÆ:?iÖÀçZ8ŠÔý\+-w>k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k`jàÿŸ±©ÚWìIEND®B`‚netgen-6.2.1905/mkinstalldirs0000755000175000017500000000370413504650527014613 0ustar kurtkurt#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain errstatus=0 dirmode="" usage="\ Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." # process command line arguments while test $# -gt 0 ; do case $1 in -h | --help | --h*) # -h for help echo "$usage" 1>&2 exit 0 ;; -m) # -m PERM arg shift test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } dirmode=$1 shift ;; --) # stop option processing shift break ;; -*) # unknown option echo "$usage" 1>&2 exit 1 ;; *) # first non-opt arg break ;; esac done for file do if test -d "$file"; then shift else break fi done case $# in 0) exit 0 ;; esac case $dirmode in '') if mkdir -p -- . 2>/dev/null; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" fi ;; *) if mkdir -m "$dirmode" -p -- . 2>/dev/null; then echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" fi ;; esac for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case $pathcomp in -*) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr else if test ! -z "$dirmode"; then echo "chmod $dirmode $pathcomp" lasterr="" chmod "$dirmode" "$pathcomp" || lasterr=$? if test ! -z "$lasterr"; then errstatus=$lasterr fi fi fi fi pathcomp="$pathcomp/" done done exit $errstatus # Local Variables: # mode: shell-script # sh-indentation: 2 # End: # mkinstalldirs ends here netgen-6.2.1905/ChangeLog0000644000175000017500000000000013504650527013541 0ustar kurtkurtnetgen-6.2.1905/doc/0000755000175000017500000000000013504650527012546 5ustar kurtkurtnetgen-6.2.1905/doc/pictures/0000755000175000017500000000000013504650527014404 5ustar kurtkurtnetgen-6.2.1905/doc/pictures/meshingoptions_2.jpg0000644000175000017500000012165513504650527020407 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·Áì™äþW°«/ý—¤0%༦å”HhÃÀǶ}ëÓÿ°¼ýû/ü?ü]>x6âUе–Fè‰xÌO~ª^&œ´h9#Í ÖõkEÒÖHc](ÌйRÎæS—ß“†'°ëP}ºOµÅ:èš+aåEfB>ì}ï›+ÿäÿâ©{Z;X9gÜò[MOQ´AE©]¤{|£eÙØ1ßÏ##¶+kAñ5¶™ÇX‰®Kê-¨,QY,¡$'$ÆYÁCÔsž+Ð?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øªZMZÌj2G«›^óV m¦¸»{¨À<ǖܼúŽ+FÿĺÝõµÝ¸]6Ôޮ˫«km“Χ¨fÎ9ï€+Ô?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øªnµ&’karK¹ç:Š®vYZè¶Öð´:DVÞÍïÐŒ†¶ìŽäg­dµõçü#öÚ/“e%½±&¤ˆ™¡ÜA`¬9Ç9½sþ¿ ÏŠÿßù?øª‚¼6N€'þ»ÉÿÅRUi.Œn2g˜Kâ=ZãQÕo'‡Nu#Ÿi4,Ð,§²À=zÕkÍgXÔ-µhn¤¶íO!fÄeDI e0úæ½dø+í€Yäÿâ©?á ð×üø¯ýÿ“ÿŠ£ÚÑì³îy\ÚÕõÆ /.,´Ë†KHí#I¡r¡P’! Éäôª·÷z†¯©I¨j2ÆÓ2,j‘.z?žMz÷ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿT«ÒNé ÂO©ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU_ÖáØŸdÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ;²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿJ|áÀ2tüúï'ÿGÖáØ~Éž5å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸v²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}nƒÙ3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª>·Áì™ã~W°§D¢9‘Ø| ó¦+؇‚¼6N€'þ»ÉÿÅRŸxpu°ë<ŸüU/­Ã°ý“ID‹löžEÀlg$}r"[iá•·LÅH`äa‘Ó‚k׿á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øªY§Ø=œ"vŒÞ¤ 1E'÷ÿ‘EŠ\<ê1+€ö6HzÏü!~ÿŸÿ¿òñTïøB<;ÿ@ïü'ÿGÖaÙ‡³g쳆ÚX­ÓnýÇhROS\ç‰Wm¤?ïÿJúþÿÐ;ÿ#IÿÅWœ|`ðþ—£èºt¶¾K½ÁV>c6FÓêM5^÷RƒZž•à¯ùô?úñ‹ÿACÄ—÷1^$ÊÑ®ÝÙC‚y#¯§Á_ò#èõãþ‚+Åò_úæ?ô&®îÍzÓë¦ÖXb¸ÕL2NÛbI.6™('“Èéê*·ÞÏÜÿ÷ð×â äÓµ;°e°ó/lâ…îXÂ(W“&EgRP‡ÆWqá¸8×’Ï_º“QžÞîFY`­¥…ÿw*²Ÿ%TùØR2‡pySó’ÒuöûÏùûŸþþ>ßyÿ?sÿßÃ\~§§k1ù±X\\Ën|©¼¤É#~ðI·…yòN"€U2Øé”“·_ÞˆÖÖ/,Ç&Ͳïò76J©Eù‹+üp€êþßyÿ?sÿßÃQ[ëÞ@³ÚêO<-²E9e888 㨮dC¬$Â)É„¤HZ3–vàx;‚g)?1-@KˆôùVêÖKi Ôò‘’¯+8?+ѱõØ ‹¯êzUªù«´²Ý(,S ò9ör=«ÑlìâÓ 6öå†,ÎÍ–‘Vcݯô¯!×ãÚßþ¾ùöi?Ö?ÔÓCD ©[¿—¶ö&óehcÄ ï‘wnAÏ,6>GQ´úŸÌï·ç^I,pGw:‰,¡×WYÔš;YµHÙ-ä”]¬Oån?1i pHç I»J 'Åøvíµs$³Æ#µVÔÅœÈ×Ìû*0“!ÊUŸsè¢íZáíÖà‘UÞ0ÿ2«‘ÔU°{í>•'˜ÿßoμúMÄ%ö ¿j·¿D‚;(â¼À’î3pSÌ%‰b7¦UÝã%Ø&ÐÕÚj¶‹¨i¶O\%ÄDÐÉ#F²R6–PJƒœdGQ@ µ×ôËí>kûM^ÒâÊ ÞmÄW*ñÇ´dî`p0'=_óûíù×saâ øƒm¶¨×ÓÚ¤VRM5´ÆP\ŒÉnÊ‚%,¬mÜÊ €gñ-®¡¨êt‘hþ!–K—°ÕVLˆv „MÇ'süÜ )$†@ÛÌï·çYÚìkq¢ÝrÆ(ÚXÛ$u«)ê5ÍiZg‰“Æ·W×s‹!,ϸÐÍ$Eà…e a’c#qÜKõ¿üo¿ëÞOýÐ>³}u¥iR¼ÅdžÎ)ähþRY—ž½«6}tÚË W©†IÛlI%ÆÓ!ã…òy=E=ä ¡ÿØ2ßÿA®GÄ·pZj~Ó3Ü[ˆÊËqŽE°&I~o/,ÜÇɇe¤IÑŸÚ‰ä€ëð‰£Ý¾?¶ Ë´ÙÈÀ>˜5í÷Ÿó÷?ýü5ËêVsêkRÚ*Íî’Û::âFý÷CžŸ:óÓšÖ³ºšç§ÜÚmÆ<öŒîúlvé€·>ºme†+TÃ$í¶$’ãiñ‚y<Žž¢¥T¸•KG}+¨b¤¬ÄŒ‚Az‚>â°/ ¸Uº•tÿ¶Ãyk¾ÍèJ´„ù›Žv‘ û¡Ž™«i¦êVN“Âdi^ö養Iñ…Œ¬ƒ eÌgv Ätàuo¼ÿŸ¹ÿïá¦RàJ±éDŒ¥• Ç$ džƒ#óÃØiÚü—1Ãr÷°YyèÎ|ü9_.`ã&i[ùC†ê Z´¯t‰¢Ôì/ [»Ão…7Œ„èÈ\äeÒᘹG £í÷Ÿó÷?ýü4nþÂ)nRf‘£˜,¬YN}k™²‡R_ÜM$W&Ñ÷ óÉ…ŒmU•”ô~í9,Nwk_ÿÈ:ëþ¹?ò4€ß¿Öonlôù<Ï-§µŽwò²¿3ŸOjÉŸ]6²Ãƪa’vÛIq´ÈxáA<žGOQSÍÿ í#þÁðÿ*â¼KsµÖ£o-Ų6¥§-².cÊ Ê7¸voï*ü­ÇL°;_·ÞÏÜÿ÷ðÔ_Ûý—í_ÚOö}žgç›1ÙÎ1Žs\~Œ·º”Æág¹’ÒK« nÞck}ò*¢AV µƒ~QÃ㛨Zx2çM†Öín£·X¢t½;Þ` oB_ä!HnFì¾ßyÿ?sÿßÃM¥Á•¢Ò™C2 Ž@9Á#=äk”Õ¬õ»«©®ìx1f†8Zp?xc·h%woò2O2A ÜòîÆ³ª–¶½k9mcVàÒ Û„cx(HdùFTœŽ @t?o¼ÿŸ¹ÿïá£í÷Ÿó÷?ýü5­†²t©<˜5('yÕæŠ{Ã6cÚÃdDNÃm$—BÜöù*ýŽ‘©I0ûuýèmbòÌrlÛ.ù#sdª”_˜²·ñoÇbê7ªÁ…ÜÙ<¹#ò«ÐxŽúÿCº•ü¸Þ;Ö¶S# òO>õ‘F•ÿ"í÷ý…¤ÿÐ>çX–ΞëRx!\n’YʨÉÀÉ'M>-Râh’X¯¥’7PÈé1!èAÏ"°á¾y0 qª²²ž€Ý¡Ç%‰Îè!·ÔΉRÛ_ä¦XMØó倗(A'Qº<åÁÂ0äp@:¸õK‰T´wÒº†*JÌHÈ$ר ƒî)ßo¼ÿŸ¹ÿïá®=#Ĉ–ñùÒE—”ùR4ò1‘±$AVC‚¬8?"ò¡Ó4똤{›»«³1¸œˆÚmÉå¢íéŒ ýáÓ;~ZÞ:Ýý„RܤÍ#G0YX²œ úÕûýföæÏO“ÌòÚ{Xç++ó0éôö¬ ÿù]×'þF´&ÿv‘ÿ`ø•UŸÄ)mu¬úÂÅq.<¸d¹Úï“€NNOb]RâžYo¥Ž4RÎï1@êIϸ¯Ý倴y ŒÏ¦Ü[ù“\ÅC)@¬C8m£Ël¶N@ŠçNÖõª2\4Ð\ÛÜy,Œ)ÑÕ„H¤Ë´2Â5û§æ9%˜Îóí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¹(mõ˜&K.íâŠUimÚå]çm’«²’Bì%¢!NÀ6NÈÕÛSƒO™.®¼»çIÚÞÜjÂÁ̲òŠß’ `!ÆÝª07Ð#ÑWQ½V .æÈ9åÉ•uÖ.5›¹nV5h.ÞòÁh FrO<×]Ãïùj_ö—ÿAJÑ×W•|sÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMkKãBŸÂw ÿ‘Cÿ¯¿ôF±á˽FñgŠ{d]€bG õ'ÓÞÈ¡ÿ׌_ú®†oùgþà¨ŸÄÆ¶8ïøCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š›ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽRð§y IÝ€)(sºFè3þϽwŽs#êi´SQEQEQET¶íuaqn…CË"–<AÔôP(<|4ý6ßí6{í¬âϘØ,£—¥7þÛÿùú²ÿ¿ÿÄ×[E+ Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,9y<%zö–1 ›=Öö±Âÿ;`²ŽqÇJ‹þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰¢ËÁ·öÚUÅ«ÝY–ù®66•w­u´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÆÜø'PšÒh–êÈ3£(ÌŒ‘þíZ“ÂW¯ic¹³Ýok/ó¶ (çt®¢Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿZ¾Ð.tK+¸ng¶všíçS’ g sÅlQLc^XRåm¼ä3²)ÉÚöäÿœòÏŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQP=í¼z„6-&.fŠI£LQ 9éÁ‘??cSÐE-żs p’(u##FyV©ö Þ€$¢ŠŽ9á•åHåGx[dЬ FÀlC†SƒØƒÞ€Ic†3$²,h:³øÔÚzüÿ[ßåÿ©âOù\ÿÀ?ô!W`_]j—šdö^Y$os¤Ä$ݳw…'qƒÐŒ€7ûOOÿŸëoûü¿ãGöžŸÿ?Öß÷ùÆ¡Žï³isjQ%„–‘>ÆxíÃÇB¨bû ï…w\É,¾‹ì%—M+ƒjË2Ê0À¤²(n…9eßÚzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð¨çÒôø¡2Gclޤe…A=Ž(ÁŒ…$}((àd£~UâÝkPÑ<=æé‘^jRe`†[˜áLÿy‹²åG ää2Hå4ø‡RÑ´Û_AœWÐ,ÜR%ÒdüÛcc´ä ‚Îë…ô*(¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEÅÝx2î_]ëp]A²ßÃ:€fEªÌ +”Eà €ÌiEyå·‚õ¸õJæQ¥˜¯"‘_cÖIšXÝ')(á“˺WpHE$½v.6›oqì’Èó´†äæ\d <œ`8.Ë„]¡ºtPuà˹|Mw­ÁuRË ê!š5ªw00H®PA 209šg€5+ N9¦K«‰àá¾Ô‘-á, K>Ûl—ùs‰ àïubC1oG¢€8}3ÀìÇJY·Ó¦²²‚î?±Æ«åæY!e ©qÈÛ˜ÔSå,»Î¾“á"ÏL—R½ÔgÔíàg‘5KŸ*IQÙ¼+W'+ódärk¡¢€8¿ø_PÓ?¶ ÅŽ–Ñ_DA¶iVo=¾l &û:9_™2 ™·g ƒ¾¥çƒõÏøEºÑôél`[k–¸²#U ˆd0±BûWqÀ* s‡^þŠáÁâËMQÚ {hü—Dµ’5k1j>Ï6åÌE”çl‘‚$q³®í¯ésXk>"¸“EÓ¬îðIö²{¥Ø>yÓÜìÜô4PW‰?äsÿÿÐ…Q“ÃZ•æ³®Ãqa¦Ûhº½‘±‘­/ÏUÝpÆP†»ÜÜdÜœ¶kSYnt©¡i£…X®dà(Ü*Ïöí¯üþÙßÑþ4•'†µ)ï×]¸¸´mjÝâ0Gd·u‰'@9e..f9ØJ I°™+¿æ[[ËX¯£dÕíäµÕã …yf•ž“´î¸™B±lC–òÊÉ»ý»kÿ?¶_÷ôÛ¶¿óûeÿGøÐ½CwÿÏø:ÎþݵÿŸÛ/ûú?Æ›&³i"kÛ<IGøÐ/_ø{BÒ×Vñl¤Ff6­6Ì“ŒíRTdõR˼ëé>ò,ôÉu+ÝF}NÞyT¹ò¤•Am›Â°%rr¿6NG&€:Ž –âÞ9Ð8I:‰‘€#<«Tûï\‡ü/¨iŸÛâÇKh¯¢ Û4«7žß6“}¯ÌÀ™ÌÛ³AßRóÁúçƒ|?¢Ýhú ô¶0-µË\NÙª…Ä2X¡}«¸à…9èEp‹à‹Æñe¦¨í½´~K¢Zɵ˜Ž5gˆ›ræ"Ês¶HÁ8Ù×wKâkµxzê-³²ŒË ^nå A’2€åÓrŽH  j+Í|3à˜®õ//ôû#¤ù·;Q`öqK¾;EÚ¹8PÐIÃõ`®*F–±á-VëÄúeýŒ–« ›[*Ï$€\,(àÈ…Ú•Ë.ñŸ9‚§æ.ؽí¼z„6-&.fŠI£LQ 9éÁ‘??cO‚e¸·ŽtE¢Dd`Ï*À>Ä;פø2ûOÔÄöú]Äi¥Ïc,fGÿ‰„®b>|ÙR¡¤òÎÿ•˜q–“€³éÞ ym<5o®ÛÙ\E¥irYO‘¤ŠWÌ©Pql0á¶ã%CÒ£ŽxeyR9QÞÙ"«Q°Ðá”àö ÷¯1ŸÃwÃPÑíî£ûv­ ºsËus§=Ã(Âeho7Š?ÝÈÅf2qûÅ®Çú\Öψ®$Ñt뻼G=¬…žévžA´çw»7Æà!Ô´m6×ÄG§ô #Áw‰t™?6ØØí9 €3‚:ázß_ø{BÒ×Vñl¤Ff6­6Ì“ŒíRTdõ‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQYšž¿¦è÷ð_Lé-»ĩ ɸ)P~è8$º(Y™Td)ƒÄÚ;]Åoß›æìÛIœM¹cf¹‰±µP6#œ®˜½p>eɦk–ºµö§goÒI¦Î-æ3[´jÌT6P‘†?ÈýÖR@4袊(¢Š(¢Š(¢Š(¢Š(¢Š§ªY¶¡§Kj޹_˜ö?Ê´>Ó7¤­GEIö™½#ýhûLÞ‘þµ'Úfôõ¦É4²!F ƒéš@ 8&—Ëî7å@Ú¼w÷vâÖÚ mž6I’ð3 Á] cëž¹éë‰eáëë;=3N‚ .×N°™$Ž+}à€§ž¹É9$“É'$×Yå¿÷ò£Ëî7å@ ¢å¿÷ò£Ëî7å@ ¢å¿÷ò£Ëî7å@ ¢å¿÷ò¤ ƒ‚0}è(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQE«izUÞ£g{©JíÕ–$yB)>l2†õ$<ž¸ê9¬ xOOÔlobº¶’KH¡Œyëm!‘¢cG.È]XCò2Œ®qÉÏG{ Sø‡HŠhÒHÛÎʺ‚Éèkcû#Lÿ u§ýø_ð "×ü׾´fšâxn$“6ЗxæYah–Q’ሶ•ÜÙݳ}*Êêþâ=B÷Ó‹‰L¸ #Hð=±õÏ$Ö×öF™ÿ@ëOûð¿áGöF™ÿ@ëOûð¿á@Ö‘£^xšr}ax6ùH>λtJÎ ’I]ø;ˆ ©*C¦XˆµµÅ7q6¯(•äŠxà;U?tBqò*®NHÚ!²Ç¬þÈÓ?èiÿ~ü(þÈÓ?èiÿ~ü(„¼ðŸ‡õ>ÎÖ÷ZK†²Ü¶ÒË“yQ°PcXÌ>X_‘H;7 `0Šê`½Ò­mã··¹²Š”$qÇ"ª¢€jÒþÈÓ?èiÿ~ü(þÈÓ?èiÿ~ü( Ði–:tövº²GçK<Âa4eãydy \‚¼3œdƒ9ï˜Ú6—ÿ¶Ÿ '‰'Ž…¢e·2‘NP®ª'hÉ99ì?²4ÏúZß…ÿ ?²4ÏúZß…ÿ ãæðÿ†'ñHñÜY5Öå‘ÕÒÞ@Ò*…WÞèdR®:Œ¨8ÉlßÓ 67ÚÅlj ìw“‰a†i# j»@ؘÁÆGòãvæn‡û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ–«{ÞDñK·®Ç ʬÿdiŸô´ÿ¿ þ·†Úi#‚âLƒ¶5 3A@Aþ¹åMóûíùÓ ÿ\¿ò¨è+ÝJßM´{»ëØ­m£Æù§”".NXœHZ•¾¥h—v7±][I“A(tl08<‚? Êñ}µÕïƒu›;Wººº³–Þ(‘•IgR åˆ äóÐdñ\ö›áÝbëVYoæÕ-¬n>Ñ-ÏúZE<϶Õ"óŒ(aåIƒ>UPÇ,á€;ß1ÿ¾ßcÿ}¿:ãgÓuÕ×”¬šŒî³Û˜/Ò¥º[(ŒL’¬¡¤|O‚"l »~JXxÀi‘Ãvn‹YéÆÐ5­Â´—R!wÒ.Nb‹n„s.Ò²Úè>cÿ}¿:<Çþû~uæ×šg‹åÐtÈ£ŽéR˜Mw‡$©Øý±H÷£hq‚‡ohýÆ+ˆ4ûhnî~ÕsJ²Üya<×ÛG ““Ó4gÌï·çXÞw—ÃöÒHÌîÆFfc’IvÉ&µë¿ò-ÚÀÿô6  Š(¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢©Ã5ýÊ4‘[ÚÄŽŠd¹e'kÎ6OZ“—üð°ÿÀ¶ÿãu#,QUñ©Ï ü oþ7F5/ùáaÿmÿÆèÅ_—üð°ÿÀ¶ÿãtcRÿžøßün€ ¸ŽOíÝ2uš8D¥È2 ÔÖÇÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùQöÄþ䟕gcRÿžøßünŒj_óÂÃÿÛÿÐÛû’~T}±?¹'åYØÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãt£öÄþ䟕lOîIùVv5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝhý±?¹'åGÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùQöÄþ䟕gcRÿžøßünŒj_óÂÃÿÛÿÐÛû’~T}±?¹'åYØÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãt£öÄþ䟕lOîIùVv5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝhý±?¹'åGÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùQöÄþ䟕gcRÿžøßünŒj_óÂÃÿÛÿÐÛû’~T}±?¹'åYØÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãt£öÄþ䟕lOîIùVv5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝhý±?¹'åGÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùUf2gpj¾5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝZI&ó;Tp =;ɬ_øH?ê«à7ÿ^´1©Ï ü oþ7F5/ùáaÿmÿÆè?þú„jßø ÿ×£þú„jßø ÿ×­ j_óÂÃÿÛÿÑKþxXà[ñºÏÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëC—üð°ÿÀ¶ÿãtcRÿžøßün€3ÿá ÿ¨F­ÿ€ßýz?á ÿ¨F­ÿ€ßýzÐÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  ÿøH?ê«à7ÿ^Ÿá¨eƒÃö±ÍÇ"ïʺGÎ{»KþxXà[ñº1©Ï ü oþ7@(ªøÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãtbНKþxXà[ñº1©Ï ü oþ7@(ªøÔ¿ç…‡þ·ÿ¦Á<Ïu,‹PÑ*—ÎÎT¶qœ ïžœs@æsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶)éÿòõñqÿ£Z¬U}?þAÃþ¾.?ôkUŠ‘…Q@Q@fjúí–Šm饻ž8"Ž%Üļ‹ã耺åpYAÓ¬_é:ޱkoockh‘ÏÙíb͉"‰)Ï\ƒÆ(j¹ï øº9Ú}Ô Žà´Ó[±UŒ2G+:–S¸nQÀ5oìú÷öÝ„§P²:jZºÞB¶Ì¯,ÿ.ÖBXí^¼ãwd©¢xe´›È%{‹V†Î m¬âµ²[p©#£¹)*ÎLjrŠƒ%¾^F:(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ +&ÿÄšv›¨…ì—+ÌÉka=ÆÔbÁI1£’×ÐÕ¸5;[NïNßíV‹Ê( û¶ÄaÚÃ*N ynŠ( Š* Û}KO¶¾´“̶¹‰f‰ðFä`8<Žë@ÑEQEQEQEQPXÞÛêZ}µõ¤žeµÌK4O‚7#AÁäpGZž€ (¢€ (¨./mífµ†i6Éw)†‚w8Fr8éò£}>”=3,è]€“çFC•%OŒŽB0FA¤ ²tßù5Ï­¿þ€kZ²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[óÈ©{ÿoŸú×'m¦YÉk ´9fE$î=qõ®²où/íóÿCzçìÿãÆßþ¹¯ò¨`È?²lç‡þ>ßãGöMüðÿÇÛüjí„RþɱÿžøûÙ6?óÃÿoñ«´Piz›s¨Å¶Û‘³‘½‡b}koþþ¿ùOñªº'ü…àÿè&´¿µôßúZßåÿhh¤|= ‹Ä·þËûÑ<›¾Ñ'J uÿoô©áÐèÿ‘äÿ_íÔÒE¼·hãµ—{ T…ËÅŒœñSÿké¿ô´ÿ¿Ëþ4Ær·Ú~™ý­si‚Ä–á9ó]‹–îxíúþdØÿÏü}¿Æ¬K4SøƒR’HÛÊÃ#Éê*ZB)dØÿÏü}¿Æì›ùáÿ·øÕÚ)¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ­_éQi>Î¥¢Œº$á²0pO½W­mþ?&ÿ® üÅ1™Z¶…ªÉâó¬Ù[ÁqÙ`‰Qõ{‹<r³ry4Á7¶Þ ] #ˉ¢QåÉå ‚‹µ§”42#»á?vѸR7o,¯EPÑm.,4K;K£› B2 @¨ pà`d*ƒŒ…PvŽOð†©toåIL–kÍH¦ ž`º $“¢G´ã÷yuœe‚ü™&CèôPži%‰-ù`XüO=œS'’ш&…ŠT³4 8e!‘$–»Ë++}>Ñ-mcòà;#€œí\ôQœOEp÷^ ¹½}V "Ó£7«v­«‚íw"L,N€()us¸Ä+…S´¡sá-S[ñ$:ž´špµÝ™iÒ7ÉwjP±Uó„$ ©e —î( [Qð‚ÈVßN‘-¬.`ûü ¹·Û „LýÐMUÛµfÈ?»EªøGR¸ñ×ö´ë§=„­"Ý­qBÈ"tòw0¦wÌÊvghùU{Š(‡Òü#¨èºV™oem¤#é3¬‘Gh…ë$¥•ÂŽÂ@Ø ø)í»*hÞ)ws¯}–ñäVòÚ‘Hn®fósò8¦Ö²à79nâŠâô¯^YxÖãY¸ºó#if•&GŒI(rvÅ ò7˜Ð630ÌhBŒ»^ З]—II•ÖÖðÏq³1<‰cÛÇÞȹSÁ]Àäª(„ñ‚õ JÒÖÛBPGk‚ÔÊÊi#†Ghe`£åÚ±˜Šl»²x|#}‹,õ3ö/.Þþ{™nw¿Ÿt’G2¢¸ÆßÝyŠ‹’ÿ(;L|£v”P¦xoV°Ñ4øÒÓK†çMÕ./mí!¸qG/œoòM¢sŒ!Ë7|´‚õ¿?O•†—5͵Ô÷&éØV’æIX$…Êà2“²XØýÒÿ*0ô:(¬7þF sëoÿ Ö¬7þF sëoÿ oüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÆu¼ s¢Inä„–[”b½peqÅYŠÚÒ’$³·Šr™8ç“Qéÿòõñqÿ£Z¬TŒO*Ûþ|í¿ïУʶÿŸ;oûô)kßÄpÏ©¥¿ëk4òÚ[Ý1,ñoóoUË|1à˜ß ØdÙò­¿çÎÛþý <«oùó¶ÿ¿B°¼SâðíµŒ‘[Á<—w_fQ4̓åÈãQÙ˜ù{UB’Å€F¿}SI‚òT$“vä†FuB‚¤²#Ã)PT‚â€/yVø#ìvØ ©ýÐä‚?*ƒû;Mÿ U‡þ¯øUŠ(¿öv›ÿ@«ü_ð£û;Mÿ U‡þ¯øUŠ((í,¢Ï—§Ù¦zí…FjO*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô(ò­¿çÎÛþý Z(<«oùó¶ÿ¿B*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô(ò­¿çÎÛþý Z(<«oùó¶ÿ¿B*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô(ò­¿çÎÛþý Z(<«oùó¶ÿ¿B*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô)È"&;xc$`”@)( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ²tßù5Ï­¿þ€kZ²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[lcÒË»Ežä³1ÀÍnM7û_Mÿ …§ýþ_ñªóÈ©{ÿoŸú×3iilÖp3[ÄII%ƒšå¾Çkÿ>Ðÿßµ¼=il·ò:ÛÄab¬d4\.I}â -uy4Ë]QÔ&Šî$kfUÙÕAó$BNcn€ö«vúª\kwÚ_ÙçŽ[H¡˜ÈûvJ’o®ž nà:w5‹¬xNkÿ®¹o&‘ç$Åö†–nšäpñ°‘ dÿÇG5b÷ÃSj:ž·%Ýò}ƒUÓ—Oh"€¬±¨ó>a!b ýôŸÁýßC¹Œ½ˆ´;«xî-õ:XeœZÇ$wHÊó‘ à¹ÃÖ¤“\Òaû›ªY'Ûñö=×>ÑœcËççÎå鞣ֹoøWQÝZ´z†¢òÍ+:ÍÎVI$@“8Îè˜r^˜¯ðîÚâïPWÓËcuö§Ž!,Áà’à8‘—2˜zK(ºæ$‚Z;¿ _Ûß]k3Þês´ [L†i!hÖh÷Ʋ–G%&ÚD¬p7Ü"•|E¡²Yºë:qKæ)hÂé1pÀí">~b <œVyå§Ã¹î­ã–þúp×>j_ÛË,€Í ÜM0Vû<±§™¶w 韺1Þ‡@Q@Q@Q@Q@dé¿ò0kŸ[ýÖµdé¿ò0kŸ[ýÐæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶1æÿ‘R÷þß?ô7®~Ïþ±ÿ€Ÿýz?á#¸ÿ >±ÿ€Ÿýzc)ÚxI·´U’ñAi%p1àÊägŽ9ÁçšQñ.‘>™w w{¤’U[Œ’¤Õ¡ÿ ÇýõüÿëÑÿ ÇýõüÿëÐ;gÿ6ÿõÍ•M[Ÿð‘ÜÐXÿÀOþ½ð‘ÜÐXÿÀOþ½+ ƹÿ ÇýõüÿëÑÿ ÇýõüÿëÑ`±‡EnÂGqÿ@}cÿ?úôÂGqÿ@}cÿ?úôX,aÑ[Ÿð‘ÜÐXÿÀOþ½ð‘ÜÐXÿÀOþ½ tVçü$wôÖ?ðÿ¯Gü$wôÖ?ðÿ¯E‚ƹÿ ÇýõüÿëÑÿ ÇýõüÿëÑ`±‡EnÂGqÿ@}cÿ?úôÂGqÿ@}cÿ?úôX,aÑ[Ÿð‘ÜÐXÿÀOþ½ð‘ÜÐXÿÀOþ½ tVçü$wôÖ?ðÿ¯Gü$wôÖ?ðÿ¯E‚Ækhñù7ýpoæ*oøHî?è¬à'ÿ^øŠr:>±ƒÿNŸýz,4謟íÇÿ .±ÿ€¿ýz?·þ€ºÇþÿõéŒÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¬7þF sëoÿ ?·þ€ºÇþÿõéº7.¥«]ÉismÆ‚â2„áX?æsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶2ìl,$³2Ëai,q>ç’bq+¸«ÙÚoý¬?ðÂ?þAÃþ¾.?ôkUŠ‘•ÿ³´ßúXà:ÿ…ÙÚoý¬?ð¬Q@ÿ³´ßúXà:ÿ…ÙÚoý¬?ð¬WâvÛIñ_‡–ïÄV¶6æv3Y¼Éä0OûÉ 9)½P/A»9Üvíê?³´ßúXà:ÿ…ÙÚoý¬?ð³oõèYõ]+G¸µ¹ñ ¥™¸ŽÅœgqË Èà¹ä`2“À˜<5s4÷‰ ÕÕæ˜«ŠæíJÈg%üää)„¸FgA›gû;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øU-?ÉþÚÕ"ŠÎÖ·ªaT8e,rG'œ{p+V²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[±Oö]k»¼©.ŸnqœH玞(¼‘×Gʰ´ŽŸ•iMÿ"¥ïý¾èo\ýŸüxÛÿ×5þUhÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Í moT»Ç‡½€ÜGÚÔqøŠµö­{þ…ïüŽ£Ð?ãòoúàßÌVÅ1˜áõ•¸{…ðÊ UAwæU$¨' lÛ­Iö­{þ…ïüŽ­Eÿ![¿úáþ…-Z ~}{Q¶™¢—FQ"ýåˆqßœ*?øIo¿è ÿ“Kþü~j_õû/ó©é\W-ÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Ë_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\µÿ -÷ý¿òiÂøIo¿è ÿ“KþVŠ.-ÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Ë_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\µÿ -÷ý¿òi­iúÅýýÚÃý”±®7n<ϲۤ[ñœghÆOæh'Rñ5Ö§Ä ­”ú·šRk{‰çòÀ‰ýÔ üˆœÆ y‹Ï+º¥‡Ž›Qî%×JÚ@n$D„ÜÇ G¶0H3¨|°r¥ÎTnÉáÝ]2-2MN{[|v­j†$ny Œó7 w>µb-+N‚ßìðØZÇèßËHT.ä à eB&m‹Ž‚€9¦ñ¼ÐèÑê·Z {È#¸ÓÒ+“$²¬ ’0›”æhóå‰qóNÐû^Ö'Ö´ù'¸Óç²–9Ll’G"«ðäó¯ÍŒ”^C3Ç¡é0ý·ÊÒì“íùûfÛthÎsæqóçsuÏSëV,¬m4ÛD´±µ‚ÖÚ<ì†Â"ääáG’Oã@ÑEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkc"Di<1vˆ¥ØUQ’O˜ü ©iáëµ³^[tq†RüƒŽœ V¶Ÿÿ áÿ_ú5ªÅHÌì Ÿùïmÿ}Ÿð£ûçþ{Ûßgü+bŠVŒûM2òÇÏ’)-Vˆ¢…É#“ÇOóïQù>%ÿžš/ýõ%jQLfJZxdšmúA–@‹òm »ÏLuùý{S¼ŸÿÏMþú’µ( ~××èg’{‹?2išSå»`gê*ÇöÏü÷¶ÿ¾ÏøVŬ+ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅX,cÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?á[Q`±ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…lQE‚Æ?öÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þ±E ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅX,cÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?á[Q`±ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…lQE‚Æ?öÏü÷¶ÿ¾ÏøUÍ3L–Æid’XX4E@F$ç#ÛÚ®QNðQEQEQEQEQEQEQEQEQEQEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|LkbžŸÿ áÿ_ú5ªÅg¬ímáë‹„¼Otê¦DŽy¬í6÷Ĥ&XF–Š[÷ž`ëÓ¦jFS¾²ÔßÄÍ"G9¹7P=ÚŸÜÁf}¢&í¹ˆ“‚ bñO•˜®O¬iZÕ¾µc>•u}:Awo5‰e“…}Ȭ1 Pw`eŽÐTɺï“â_ùé¢ÿßRSU%ÿžš/ýõ%ekX,Þ[ir¨$oŒHTッހ:š+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ5wK½Öo¯rý"U.åË`võÿ>Ô»EIed{Ö<úÚM«éÖ–s[IÆC1ˆ†?*ä:sü¾´©Er^6¸ÿaiµ-­˜;J]:9åÚ~Ó$0±ûᙿåA »ñW‡î$¹Ö“í:\·rÁqy,$ÉZ„ó!F«í¹B…$œƒ@¥ËxÄZv¯áÝ5›[ÝMtèæ5ºY& ±C—-Ç’{žkkR—V‹Êþ˲²¹Î|ϵ^<zcb|÷ôÆ\ð~ŠŽ3[Æ×‘ÌT7.ªØä 3ß>‚¹mT·72Žfö+ö`÷7tµÞ"KùXÄ‚_—*Öà­¢¸}Ä:¦«¦xV&]8CI{™î'2\ž/!H~ç;¤e!œy,J•jšõMS\ÒíàÓ`Š+È­¥ÒK’Hå‰$yšUr©¹Æ ba¸vzñ·}É»›È¶7›/šbؘ9mà‚¸;ëšóÏøMo4ïøNæÞx&ûe‚›Få㑨ˆÉ<*df.~ùoÝ·Êy*éTW‰µã5Ä÷vVV¶Ö·övRÚîi&ßp–ùÁ <·œÀ6ð1„Æã“©x‹ÅÖš¦›û5ôº5ÝÊA™q¶òÆcTr—Û;~ñ”IÆà¬éTWš¶©©ëšÈåd¶!Ò0äJ@m™`~r¥S¡ê_Û:ªy^OÛmb¸ò·nÙ½Cc8Æqœ ¿EPEPEPY:oüŒçÖßÿ@5­Y:oüŒçÖßÿ@4ßùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Œy¿äT½ÿ·Ïý ê/ È.Oúçò5`Äóønê×t’5Ú¨Î2LŽ%ž‘=ž•öh5†wXÃH Þhä ‘Ÿ©íÛÒFiU[?õ×ÿõõÿ´£ª¿Ùz¯ý Ÿù"¿ãHºF¤ŠÁ<@ªÏ!‘ßìC,vªú〣 õ  Zá4ŸùCÿÿÐtÿÙz¯ý Ÿù"¿ãQZxb;[T‡ûCvÜóä‘ß>´˜™•Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%·ýüÿä#þ4`Gÿ?ßùÿ ”VßöóýÿøÑýüÿä#þ4X,bQ[ØÿÏ÷þB?ãGöóýÿøÑ`±‰Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%·ýüÿä#þ4`Gÿ?ßùÿ ”VßöóýÿøÑýüÿä#þ4X,bQ[ØÿÏ÷þB?ãGöóýÿøÑ`±‰Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%khñù7ýpoæ*_ìÿçûÿ!ñ«VtvÉ ¹ó FS^==ý¨Ã*º2:†VYHÈ õ«Å§XÁ(’;xä^Œ‘(#ñ¬ÑLaEPEPEPEPEPYšv¦éW =¤.¯·Ë@ó<‹ d‘+"Nå@ʼ|£tPEPEPEPEPY:oüŒçÖßÿ@5­Y:oüŒçÖßÿ@4ßùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Šzüƒ‡ý|\èÖ«_Oÿpÿ¯‹ýÕb¤aEPqÏ ¯*G*;ÂÛ$U`J6`ú2œÄôM<6èyR$,¨Ø(,Ä*Ž{’@¹ W'áXo4™uÕÔm-çŸí &·v”ˆ!B¤‰˜™ÑÛså›$ÓåMC^Óôfm,Ö²Ç6~ê4ÁT;ù@e9]Þ\¯ÆìÆÀmSJ´šÃH²³¸º{¹­àŽ).dÎé™Tç$œ’3ÔõëV袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬7þF sëoÿ Ö¬7þF sëoÿ oüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÆQ•àðÝÔѶÙ#k¶SŒà‰Šça¾Ö¥‚9?µq½CcìéÆEoÍÿ"¥ïý¾èo\ýŸüxÛÿ×5þUKö­kþ‚ßù,•«ic¬\ÙÇpÞ ò÷çåû‡—]>ÿ ‹_øþ„h@Š_Ùz¯ý Ÿù"¿ãL‹OÔæ†9cñ.RE§ì+È# õ­z«¦ÈÃþ½bÿÐ1™·Öú†Ÿe-Ôþ$o.1’ÁI=€÷5™ö­kþ‚ßù,•¯â¯ùîÿàúÖM&&'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²UýûRêû«4Q©vEìvÎ8ëþzÕÖÐ?ãòoúàßÌPÔn‘?™#*"‚ÌÌp’M`7ˆ£Ôµ½6ÞÊñžd3(B¹Â¹Èïþq[´SÉxÚÊ+¯°É<|Iæ.Éô§Ô­÷¸-d8“ƒµú(2Ë®`ƒÃ–“ø«Ãú•߇ Žåt¹^áåApñ\+Zùaç —‘@p®NNŽõÚQ@_†5Æ´ðV“a—ª>¥kamA6Ÿq‰0‘œÈÑíÚ¬Ùb7¡˜ŠÅZ%¬>QfúµÍέiutc°i÷2É‘„jbQ“ü£³1-ÜQ@=Õ¹ÅóË6„÷×òê05ÑIÛÚ¢RuBª¬ÄÄÌ›Ánðžð¶‘mƒ´ºW‘¨ q)·ðÔÖòíR†D™ÜâåIz!EF=fŠâô·&žº^ŸaýŸòÈë{“ÛCJ# ÑÛÉŸ&BÎUQ¾RQåÃgkT“EƒKñMœV:cÌ!khíĶR³Ã ª!òoU¶Åª³Ÿær$‰F{ú(Ìu_ ÙYéž'k/ZÄ_V²yz_šØ}œÐ’=Ë!e^¤7|ОƒW¼Ñâ±Òtˆá† Óp×^–c){m¤A#)T`6ãŽá}:Š‚Æ×ì:}µ§Ÿ=Ç‘Çç\>ù$ÚÜíÝŽ2OsTôè5È®µ=GN¹‡n-¬ ‘Éf™ÁÏî9ã:(žñ-Õí½ÅšÇq¨ÚX2Èf¹Ó¬þÓ0”òÓg—&ƒ)'gTQ¸g M7ŸhW76­ìš4ñ]\%“W/ ª4‹½îLBïlg©Ü u´P«âAc<6£ö±–¼YtÆÛiuº0"¶Ù2!Ý0߉ÂìF;†C×¼Ö_™»nyÛœã<â¼ÿKÕJÇ‚ÙùýŠó[ À÷oþøè/­àHÿ ƹӵŸh‘kGÒþÛm$‘ÚÉ|©bùã]ΫÆQÎC+«.C*ï!6´ :m+F†ÒvBêÒ8HÉ) ³³,HH"¼p½Pè¶óÅæ.¯­½Ó›‘ÕX©íê %Îmmk-ÃêÚÙH»¹ÀãŠÙ¢¸xÖy¢IWRÔ•]C7$lãš“sÿAMGÿ +ŠçkEq^MÏý5ü4y7?ôÔð Ñp¹ÚÑ\W“sÿAMGÿ MÏý5ü4\.v´WäÜÿÐSQÿÀƒG“sÿAMGÿ  ­Åy7?ôÔð ÑäÜÿÐSQÿÀƒEÂçkEq^MÏý5ü4y7?ôÔð Ñp¹ÚÑ\W“sÿAMGÿ MÏý5ü4\.v´WäÜÿÐSQÿÀƒG“sÿAMGÿ  ­Åy7?ôÔð ÑäÜÿÐSQÿÀƒEÂçkEq^MÏý5ü5¥¡Ù¼·å¦Ô/äXÈîÒF1ŸQÏJ.:@ 8&”£’¤qBH±7˜ùÚ “€IéØMsÇP¹ÔµÍ4­ž¡ ™O>"«’„×£ñ¦3SQÕtí"Ýn5;û[(Y¶,—3,j[à gñìj¼Þ"Ðíõ1¦O¬éÑ_–T¯t‹)fÆÑ°œää`cœŠ£â[KǸ³½°ƒQkˆ–H¼í:Kq2+”%vÜ,¡(¤œîT †lz]ì:¾<ÖÖ±%¦“=´âÓå†9Y­ˆXÔó³÷oŽ8 3Ú€7`ž«xî-åIa•CÇ$l]HÈ Ž#½I\׃QµÐ4½"ÿD½²’ÊÂ(^yd£gEU!vHÍÏ$dn•­©i÷7ÞWÙõ‹Ý;fw}•!o38ëæFý1ÛNsÆ/ÑQÁEoo3Ìè¡ZY†rÞ;@=xz\%…Š-AŒ:Šæ{{…7wAf”G:»Æ¡n$‹.Ôà@™*6í?»ïê o­ »·´šêînwy¼€<»F[jž[“Ž•Ç[i> Õ¼I4ú©Ôl4©Zwðj8ùLv‚%%å;’v;Ù[/~ßןð™\ßÝßÝ\ØýŽÍ&Kr“KL~`# ±I~g8àP¦Šó„±ñ›jº‰òn¡³Yån²‰ã% v¸r¤Å窰Kq’¤…!vIªé~&—O´|Z¤6K,¤ÙÍzfº\„ØZE¸ˆíLpg“ï¯@‡EAcÄ}´7w?j¹Ž%Yn<°žk€m£…ÉÉÀéšâítߥ—ú­Q/¢ò$½’]D4wÒ$ѼŸgMÇbº¬Àä®$PËõ`ÝÃÛi> Õ¼I4ú©Ôl4©Zwðj8ùLv‚%%å;’v;Ù[/¦úf¶š´vÉ}<ºlÒÁs=Ô“24K†B€¡dd„• ‚ã;w  †yáµ·’ââTŠ”¼’HÁU ’Ià;Ô•æ³h)Ö%ñŸwöÖZ…Ê÷nb—ÊÚÞ|åó&qA—†NB®ì ­ÚKasi¥^ýš8®-ŕ֤$—s´L’Ììì6©IGÊÒ0W\’ªÖÑ\_„ô m [{PÕî²ùQ›ÀéòÛ@³nû¤YÝœrÉ´¶âx3Lñ5¦¡q.»w;~ëdªÀ´w’™7mQ†ùDp‚$(Ú€v”QE“¦ÿÈÁ®}mÿôZÕ“¦ÿÈÁ®}mÿô@ ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØÇ›þEKßû|ÿÐÞ¹û?øñ·ÿ®kü«¦Šµh3[îÛæÉt›±œfG§Ã¥iÐÁBÙ˜"…ÜÒœ dâ è¿ò úîôWj­Æ•¦][¬Z3D®\'œànÆ3ÁçëëUáÐèÿ‘äÿc-ißñçÿmçÿÑÏMÕÿä }ÿ^òè&¡o ènª­`Ä Ú ÜIòŒ“Ï©'ñ¦ÿÂ1 ÿÐ7ÿ#Éþ4ÏÙÿÇ¿ýs_åSWJšf›*-ž@y­Óó§gißóéÿ‘üiXV9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9ŠÖÐ?ãòoúàßÌVövÿ>Ÿù¿Æ¥‚ÞÖÕ™ ·ØÌ¥IÞO ¢Š)Œ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+'Mÿ‘ƒ\úÛÿ赫'Mÿ‘ƒ\úÛÿè€ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±OOÿpÿ¯‹ýÕb«éÿòõñqÿ£Z¬TŒ+2vÊ}LØ£>K4QÌWK*g|hÝ ¨f&9éÖ-¿‡!ƒSK=ÚÖå»·µ b)åßæ>øSÀ2?Q°F&¿¯Ááëky¦¶žãÏ•£U‰ãM»cy™¤tUP±±$š·¥ßSL·¾Xw¢;ÆçièwF̤‚cÁŠº&·{¤Æš½þ—q©[_µÕ´ÇN (fòòŒÛ·*¶C+)¹°Åõ´}7û+NÆ_:F–Yåp»CI,#í8]Îp $ OR~Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ŠURÍ€2h‘L[|«¸íPXrqœ^?…%CRÖ,ô¯(\™ÚIs²+{y'‘€Æ[djÍ´eAl`PO#5?á+Ò§o§¤—RÍr¢H)¤ŠD;~u•P¡A½2Û°7 ‘@TT7¶ú–Ÿm}i'™msÍàÈÀpyÖ§ Š( Š‚ÞöÞêk¨a“t–’ˆf#k”Wž¿+©ã×ëSÐEPERÇSµÔ^í-ËÙÎm§W‰¬€+cæ# ¤A@袊(¢Š(¢Š(¢Š+'Mÿ‘ƒ\úÛÿ赫'Mÿ‘ƒ\úÛÿè€ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±7üŠ—¿öùÿ¡½rvÚeœ–°»C–dRNã×Zë&ÿ‘R÷þß?ô7®~ÏþkŽ0cWáÐèÿ‘äÿv™s¶ŽÏq4q!¸ 4Œghãš›û_Mÿ …§ýþ_ñ¦2•·‡´ˆ|Ï콿<‰´H~ë²ú÷ÛšK½Aµ²žãû/w•>ß´H3œu©ìµl×̼·MòÌëºU”Ìø#žEGªjš|šMê%õ«;@áUfRIÚxÐ1›e41Êm•K¨mªí‘œ šöMüðÿÇÛüj{?øñ·ÿ®küªj’J_Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ­_éQi>Î¥¢Œº$á²0pO½W­mþ?&ÿ® üÅ1›+'”L›Yö‚v®2xè3Åsêºî·§Ü\i¿fŠßÌÜÞz¾w.;}?Zߢ˜Ìi7ZÙ¤´·‚i"Þ§uôöRØû³B mùFPŒ1Úr6dƒI½M_H½¹»K§³Ó¦µ¸˜¦ÆšWh𣀔Čñ{mQ@÷„í5Í/HÓôNÓNHl¬ã·Yí¯V‘‘UrQ¢PŸ¼qÀç­ijZE¶«å}¢[Ôòó·ì·Ó[ç8ëåºîéß8çM_¢€#‚··Ž.R5¦GgbÇ,Ä–>ä’{מiu++[åšñ%™Ö4$È5²+¿Ú@­—P—iˆIÙ;½ŠóŸ ɦC+_ÛZÉ Åä“ÅlšdÚ¥¤Ã*A|¦TpÜ0›Õš€uK{ÝòömŸfµ´VX„Ö­(­ Ÿ%ØÆÌ»l¨‘ÆÓ’_Ò¨  Õ¥Åþ‰yij`ófˆÆè AŒŒ•`3’¬ÓÅè?®"»‡ûv++>´ùvB@ñ([mR‹Q•Ý ¯·`™[²ÃÐè -ŸÃwÃPÑíî£ûv­ ºsËus§=Ã(Âeho7Š?ÝÈÅf2qûÅ®ŠïúÍýŸŠ-ím†¥yųE9rè‰4rj‡XpxbFX 7aE`øGB—Ãú'ÙflHò´†$th¡ÎØöE…8Ü@Aó3s“½EQEQEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkc:Þ¹Ñ$·rBK-Ê1^¸2¸â¬Åmi IYÛ„E ¹Lœsɨôÿùúø¸ÿÑ­V*FG%µœÊ«-…£ª’T4 €N3È~Uöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«PV UP«ejD8¥ò­¿çÎÛþý ZÉ×uÏìU³Åœ÷-su  ÂD²J‘—fvß÷èQå[Ï·ýú´PyVßóçmÿ~…U·üùÛß¡KE'•mÿ>vß÷èQå[Ï·ýú´PyVßóçmÿ~…U·üùÛß¡KE'•mÿ>vß÷èQå[Ï·ýú´PyVßóçmÿ~…U·üùÛß¡KE'•mÿ>vß÷èQå[Ï·ýú´PyVßóçmÿ~…9QäÇo dŒˆÅ%QEQEQEQEQEQEQEQEQEQEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb“¬zYw`¨³Ü–f8y­É¦ÿké¿ô´ÿ¿Ëþ5^où/íóÿCzæm--šÎkx‰1©$ çŠ€:ïí}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ük#^‡N×a‚âF²Ž)RlZËÎèêèO˜÷Yãç9¨ô}>Ê]R’ÒÝÔîÊ´`ƒòŸjßþÎÓèaÿ€ëþÆb~çûnÂûþÖh-­^ mHv\¹Û‰a¸=1ÛFàÅ…¾“e¨ É<@×’GAn.®co"6*YA3çb|Òo”sËgTÚiâþ8?²´ý­ ÈOÙ×9V@?ô#úTßÙÚoý¬?ð€#þ×Óè!iÿ—ühþ×Óè!iÿ—ükœ¿Ky5«»aeiVáàUÎW$ž9ÿë}j/±ÚÿÏ´?÷À¥q\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| .:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ¥MSO‘ÕúÕŽVe$ŸAÍrßcµÿŸhïZÞ´¶[ùmâ°±V2Àš.:Rìu>µÒC±DóÇæLHÉl ŸÈóšxv.Š€;TœqÆO8¬(ìuyõ{+»æ±ÛoÀ€¾NåǘË:ž°4ë‹{Xln¯ï'W‘-íŒa¼´*É‘•p  Æsó "£x˜ÿmÚi±èš£ý®/>+‚±"ycË̯"È»Lª ” ×â¤ñ„Úí¼§:FÅŒ:‚ÝÂÇ6ÝÊCŽ@!±†lƒD–úÙµ .çí“Íö l³pwÉ6ó ÞïÝ¿sÏ–ÏäÞ•¨Ã«éZººÃyw¬€ ê‚Fp}jÝ`økHÕ´=>ÓN»Ôì®ì­-RÞ!‹Ã'È‚Ìe`x (äöéWõ-IÖ|¯íM.ÊûÊÏ—ö«t—fqœnÀü…_ªkšLòÜE©e$–Ò¬3ª\!1HͱQ€?+ù@<“Å[‚mmã··‰"†% q¨UE8ÕÉÚø.ò+[ˆeÕÐ!he·‚ÞV¤ŠE–?ÝÉ4˜@P ‘˜ÆÒG÷Jt7Zæ“cç}¯T²·òÖùמ_ÜûÙ<­¯÷×ûÃ1ÜkPÁ«¦š¶×Sɵg†0Ën²3,eÆwÌŒ2¡¶í%¶¯5“¦x=­|Iý¹~—×[§nµTòÞXíã%9;@ìS¶L$Öí<%¤ÙxšMn $—ì°ÛÂÕ òÄŠJ°é”uL qŒ~=sI›í¾V©dÿ`ÏÛ6Ü!û>3Ÿ3Ÿ“[®:JŽOhqi‘jrk:rXLÛ#ºk¤;sÀ|àŸ•¸±ô®hø ò]Uïîuç¸uSö1%r² á™YÃLS PËÄ'p¸±¨ø.óQx¯[WHµUi “[Ã-¼N®#R6Ã2HN!–‘»ñ; ¡¹¤ÝZIwoªYMm^sÍÂ2,ya¼°8 ”qžŸ+z±ceo¦éöÖ6‘ùvÖÑ,1&IÚŠ'“Àk‹_†vñéööë©Î$ŠÕ"2+™PY„qµƒ*ÿ¡&T6ïœá×ÐQ'ˆ´8´Èµ959,&m‘Ý5Ò¹à>pOÊÜØúQ½§MªÏ¦5ÂEyæÝ"•ÕZfG+ÆrÀ,‹ž8ç·'ž\.Ÿ vÚŒ^™d–æñ…á’V`Џº*íRì E8|xA?Óݯ<Ë›Ëû+É.^ó[ù8F+€racÀÔ¡žxmm丸•"†%/$’0UE$’xõ¦«§j Ù_ÚܤêïC2¸‘P…b¸<€HŽ„Qëoö®œm„¾L‹,SÄåw’)DÜ22»d Ž£'þ­@ÝǨZµFóRyá±UC‚ Û±"@ í 6T®ÕP huÍ&âh!‡T²’[Œù(—Z\"Èv€yù[ŽÌB*Ä7Ö—G“uŸhˆÍÉócr뎫ó/#˜zŠÁðǃm<=c,˜/d“컥kp¤ýž£Lòs†ˆ¸þén=M½Ãé“N³¼ÈÃi¶ÖåÌiè2ÁxÀÙK“$jŠ( ²tßù5Ï­¿þ€kZ²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[óÈ©{ÿoŸú×?gÿ6ÿõÍ•u6‘$úCC"îŽI®U†qepjêHÑF±Çµ@UUP  >Šì¼ù?½ú <ù?½ú ,8Ú+²óäþ÷è(óäþ÷è(°XæôwHµH¤‘•C33œ’jÇü%Z/üþÿä'ÿ Üóäþ÷è(óäþ÷è)Œçá#Ò_PIÅâùqÛȬJ0ä¼x“Ðôô©¿á*Ñç÷ÿ!?øVçŸ'÷¿AGŸ'÷¿A@/Ú¡½Öõ‹wßù{[g ŽÿJ±]—Ÿ'÷¿AGŸ'÷¿AJ±ÆÑ]—Ÿ'÷¿AGŸ'÷¿AE‚ÇEv^|ŸÞý|ŸÞý mÙyò{ôyò{ôX,q´WeçÉýïÐQçÉýïÐQ`±ÆÑ]—Ÿ'÷¿AGŸ'÷¿AE‚ÇEv^|ŸÞý|ŸÞý mkhñù7ýpoæ+sÏ“ûß  Í!àûQ`±QLaEPEPEPEPEPEPEPEPEPEPY:oüŒçÖßÿ@5­Y:oüŒçÖßÿ@4ßùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Šzüƒ‡ý|\èÖ«_Oÿpÿ¯‹ýÕb¤aEPEP£>¡&¼¶V—ßfì¾iýÒ¾Nâ;þ•lZÛÏokÜÝ5̬7(¯`="Ž;¦ºTQ; Œ¾2v‚N=¹?ËÒ¥gg9c“XFUYÍÎñkHÛgÞû»ŽêÇö§.¼ÐÜêWPÃw=Å­¼%´–¤¨ªÄFeY•c%Œ¡“rH¸å1_G¾Õâ})®u›«Áw­ÞXȳŠ"ì.6F§$Å'ÕxÀ$¶=+N‹S—SŽÂÕ/æ]’],*%uã‚øÉ*ðOaéQÝèzMý ´¼Òì®-„­0†kttó’_iÜK1'¯Ì}kqë2Nò]LÚ>…¨Åf_¶;Û˜ˆÃ`J_|¹ädqrÊÆÓM´KKX-m£ÎÈ`Œ".NNp9$þ5=rÞ8ÔïôÛ],Ø>¢ ׌“.›2\V-ó9'šÍƒÄÌ÷ =Ž­¶‘çÜ[-Ô·ª²„È$-~æC•v8•vÜ[¯ßjñ3G úN©¥ØÄu‰ÈÆÙ `\B„äÄÀü˜Áá³½„zV§.§…ª_Ì»$ºXTJëÇñ’>UàžÃÒªEáoAiqiƒ¥Çms·Ï…,ã .Ó•Ü a°yé@õ]~âËP¸·¶²‚hì­RòöIîÄ"c 2¥Y¿u&w²(ù~nI[úæ¥ý j:§•ç}ŠÖ[+vÝû¶3ƒŒãÁ¢MI›ì^n—dÿ`ÇØ÷[¡û>1/“W¦:J·<Ý[ÉoqK ªRHäPÊêF ðA¨‹—â$‡û%ÚüN-Ò(ÚIQ›3«’cŸ­'Æ#9Y;w0Km㤇M¸›EžÖÚ|ýª{µž5€+•fâB€ î˜B •98NŠïJÓµ™/l-nRuD•f…\H¨K(lŽ@$BIªïáÝK‹K‡Ñ´æšÍQ-¤kT-¡Ê8Ê…=éÚ€1tOjÜÇý¦`¸Õ/lmî¼ÅÜÍ“², ÄqÜNâË÷H;ÎÖ»©\é:c]ZØ=ì‚ì]ä(?ÄB#¹¾Tc’2å…ű´O/m¬ åJÓGˆÀÙ#nÜãÑŽ÷ÉêwSQê:V«Û­¾§ak{ ¶õŽæ‘C`Œ€ÀŒàž}ÍdziåðÛÄ©äêÉ ÁŠcû¹ \ÆUã @hÜùl¬ ÷–«Ýø£Q°¾ÔÍΕjúf™·W6׬ò"ªïT(Ñ*ùŒ¸;Cü ‚OÌ›¶¤Ðô™¾ÅæévOö }uº³ãòøù1µzc ô¨áðî‡o©N NŠü³9ºKTYK6wàg'''<äÐO ë÷ZßÚRïJžÊH6Íë³Â™¢‰‹ § .eääSÄž®¾'Òôm6+¨Òx%¹k˜’\£Æ :Èà˜Ç™— ‡9M÷±½§iZv‘nÖúe…­”,ÛÚ;hV5-€2B€3€9ö9‚¸K†‰ Ȭ‰!Q¹Uˆ,ê*¹öJäõ/ͧYÝj ¥£Ø#^CnÂä‰dšÙ&g›0ˆ~Ï ÝÊŒ½›w¨\ù¿oÓ~ÅÑ¢Äë.å9á±÷dù€Ü¼®Üà}I’îêíô»&¹»ˆÃq3[¡y£ ŽØË.¡[€¬Ëh³–qòä‚`Pxù|ÁÉÇ= Ö‡¤ßjßÝévW°mò®%·G’=§#k‘‚Ièh›CÒn&ži´»)%¸Çœïn…¥Â4cq#Ÿ‘™yìÄt&€0uÝ\²ÐÞoìYàžk«h"0O ¬‰4¡2w•Q(Î1ó fO™×~ÖjÞ,¹ðÆ™j×=ô‘À×£cùðÄ9RË IòYãFdb¤.võ“A ž$•+…u ) §žà€Aì@5SRÐôgÊþÔÒ쯼¬ùj·IvgÆàqœÈP,þ0kK{½JâÁ‘]F²¥Òý¡ÞÜIæ)‚Œ&Lmv8ÚJ¸­¿ ë÷ZßÚRïJžÊH6Íë³Â™¢‰‹ § .eää§•§E©Ë©Çaj—ó.É.–ºñÁ|d•x'°ô£NÒ´í"Ý­ôË [(Y·´vЬj[d…gsì('\ñ,ÚMÅêÃb—é¶k|ï9–dÇ”¡X;â8bƒîóÉÅ;/Ü_ݼ0é°7÷Zd,× –¹„HÃzª‘²EœŸ˜>B¸sÑ]éZuýŵÅå…­ÌÖ­¾ÞI¡Wh[ å S9ƒÒ«éÚ¥Ì÷[£];LMË¢™vË3Lɸvosôêy jÏÄÚ©ø]&¯v-_U‹IKæX.Àv¢ÝæœÄB9Û! ±—+Œ‘œ[ñ¿áÕ¥µ“Oó †Õ.U› ÊÏ#»qÄv²wrÅ€K.óèzL–—V¥Ù5µÜ¦kˆZÝ M! —uƲÉçR +N[w·[ Q À¶¯…v´*XÈÆ Í…è7Z¡£zþ"Ö,cmgo=²´øI ™‡Íˆ÷!Ý.0€AÌ‹Åz‘Ñ.52É•cÓÄ7“L/»³ X7•Àb £n ÍÂaÎóèzL—wWo¥Ù5ÍÜF‰šÝ ÍvÆYpÁãPEáoAiqiƒ¥Çms·Ï…,ã .Ó•Ü a°yé@í¿Œ5íWI¸†ÞÖÛJ’ÎòKÑwpИš ãŽGù¢ÎæÚfàÇpB¢µî¼@Ún§â½‰þǦiÐß(ŠErè|âØRªUó.À€§å;«I4=&;K[DÒì–ÚÒQ5¼+n!C¢ã Ù$äsÉ©#Ò´èµ9u8ì-RþeÙ%Ò¢W^8/Œ‘ò¯ö”ÎÜx³S´Ô`ÒgÑ }RicUŽÞûtA$ŽvV.Ñ©àÛ>àáH#qùk{GÔ¿µtárbòdYe‚T ¸,‘HѾӕ܇€HÁ t–‡¤é±$V:]•¬qÊfE‚Ý,…vi+ž¸8«pÁ º‚$‰ 3•E 1,ÇŽä’IîI4%Q@Q@dé¿ò0kŸ[ýÖµdé¿ò0kŸ[ýÐæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶)éÿòõñqÿ£Z¬U}?þAÃþ¾.?ôkUŠ‘…Q@Q@Q@Q@Q@Q@Q@Q@Nòº p6ŽÕI7ü³ÿpPçÉýïÐQçÉýïÐTuÅé0[Ùê—RÍ¡Þϯ¥Õܯu¹C$ä1)¸b©"ùf%ïm§fBùd qçÉýïÐQçÉýïÐW”Ëy¬ë> ñu†¯c{{°c2ØÊòI;‰Uf‡;Yb`Dgil–þïK¬êZ™Ô"{YuK{gµŽ[%¶Ó¼ß´NKnŽp똔Þh~ûåÆ @ÇÏ“ûß £Ï“ûß ¬A5ׂuû{xžY¥Ó®8ãRÌìc`’Ií\–±ÿ ^™«ê3[+Î P5ü1Ÿ1¡V»mÛV˜£V Œ6ìFäô¿>Oï~‚>Oï~‚¼ò]SÆvúd‰öW¸¹ºÓ€´–ø†oßíwÝ䵚°eE‚ª£ã¥ñ„]x'_··‰åš]:á#Ž5,ÎÆ69$žÔ½çÉýïÐQçÉýïÐW-¢ÚjÐø¿V›T– 2ÂÍ#žÞÑàŒí’ä•Ã;å†àO=xîzZÍ{ˉ‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶)éÿòõñqÿ£Z¬VtºO#_ÞÄäp-䃽ËsÁ'®:öíš‹û?è+¬à_ÿcR3ZŠÉþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±  j+'û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€5¨¬Ÿìÿ ®±ÿýØ ÿA]cÿÿûÖ¢²°þ‚ºÇþÿö4`'ýuü ÿìhZŠÉþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±  j+'û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€5¨¬Ÿìÿ ®±ÿýØ ÿA]cÿÿûÖ¢²°þ‚ºÇþÿö4`'ýuü ÿìhZ©j:î™ap\Ý*J#RT+63ë€qU¿°þ‚ºÇþÿö4`'ýuü ÿìh¿ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáNþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ± ÿÂU¢ÿÏïþBð£þ­þòÿ…;û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþïìÿ ®±ÿýØ ÿA]cÿÿûoü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øS¿°þ‚ºÇþÿö4`'ýuü ÿìh¿ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáNþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±  v:…®¥âÖšÒ_25±ÚNÒ9óî=ÅtU“ý€ŸôÖ?ð/ÿ±£û?è+¬à_ÿc@ÔVOöÐWXÿÀ¿þÆìÿ ®±ÿýkQY?Ø ÿA]cÿÿû?°þ‚ºÇþÿö4­Edÿ`'ýuü ÿìhþÀOú ëøÿØÐµ“ý€ŸôÖ?ð/ÿ±£û?è+¬à_ÿc@ÔVOöÐWXÿÀ¿þÆìÿ ®±ÿýkQY?Ø ÿA]cÿÿû?°þ‚ºÇþÿö4­Edÿ`'ýuü ÿìhþÀOú ëøÿØÐµ“ý€ŸôÖ?ð/ÿ±£û?è+¬à_ÿc@Õ“¦ÿÈÁ®}mÿôGöÐWXÿÀ¿þƬéú\:k\ ÿ‘Cÿ¯¿ô[µ2ø˜ÖÆ?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅ#1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÝ0p]÷4žOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}T3I ÅÏ™1"4%°2 ?Îh'û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÚE.ÁGSëNòé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûê'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾¨òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûꡚH`–(žxüɉ 9-“ùþs@?ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@V:UÔ›_]êjÃää„ÀÜcõüëÏþ9ÿÈKÿ¯£ÿ šõZò¯ŽòÒÿëèÿè&´¥ñ¢gðÇ‚¿äGÐÿëÆ/ýVíax+þD}þ¼bÿÐEnÔËâc[QR0¢Š(¢Š(¢Š(Iÿ×7áüª:’õÍø*Ž€2m_Ìd ?¹ø?½ê6æxoA¼³×ín$µ½¶¶°°–Å#¹¹ŽX³BQ ÙÉDMóÈ«#MÙÆ´¬}GþFMþÛÿè¶+Qÿ‘“Dÿ¶ÿú  Š(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€$ƒýrþ?Ê£© ÿ\¿ò¨è†µª¦‡¢^j’ÛÏq¤Fi#ƒný‹Ë¹€àdõíÆNTÅ:ZYËq©NšI†³M¡4q˜å(.àÅ (ÊÃk¨ Oâ2moú†•Ê[=änfxŒÆÖ;C.N Ç<z˜ü/¨Á|Ú¼­¨Ö%i ÒIdÍnÊë ± C)Å´\—<ïã‘´xêºrß%‹_Ú‹ÇfD·3/˜Ìª€\䬬G`Àô4ZjºuýÅͽý­ÌÖ­²â8fWh[$aÀ9Sx>‡Ò¹ÛZiº|Ö–×ë.¬&<@ÉåÚFÌ1»>KðàzÉáGá»#^=Ø‚²Ù™$œ´Pår¤<¬™;#åËÀu5¨ÿÈÉ¢ÛýVÅcê?ò2hŸößÿ@±EPEPEPEP^UñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5¥/?„î<ÿ">‡ÿ^1è"·kÄÅ;ß»øm4Û{¥Ò¬„åÙ ‚2SvÞqœg4Âõ¿ÿ %·ýþoðªt¤ÝДÒG¶Ñ^%ÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ½ŒûÁÏÖï]’îFµ]9`'ä—-|qþ{Ô?ñRÿÔ'ÿ"W•Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÕâ¥ÿ¨OþD£þ*_ú„ÿäJò¯ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð£ØÌ9âz¯üT¿õ ÿÈ”ÅKÿPŸü‰^Uÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{‡P‰–6ÿVÜÛÇÏB€ÿŸ'÷¿AGŸ'÷¿A^iqðïQ'š;ËX.…™Ž×fìBÙ»t‰[¬q¼öåm„R‡8™­ä[wHæ*Do"UlpJ‚ 푟Q@ Õ5¨t}2ãQ¾•ÒÖÝwÊé HU{ª ÀêN8'Eε õ•œòºÍzÎb*̪\‚ÀmS´1‘œg¼þÃÁZí—‡|M¦¢éÑNÍmí YÕbÈ‘dùVÑ(;]?€–Ø`1ާT²Õ¯o|;q½ûѸ¼Vºq·0¼DGû¿Ÿk¹Ú² Ÿ'÷¿AGŸ'÷¿AQÑ@yò{ôyò{ô'Ÿ'÷¿AGŸ'÷¿AQÑ@yò{ôyò{ô'Ÿ'÷¿A\WŒµmB N`¼šÄ!±”É,G8ëÐWc\ÿä5ý{¯þ„Ôè3ÿ®oÃùTu$ÿë›ðþUTUÓ¥ÔåÓ#¿µ{øW|–«2™Qxä¦r̼‘ÜzÕºãâ±Ö ±½ÒítÔKÅžúêÏTã0Å$Í3ÆÈ>gÞ<Ь 3– ™¥è&•-î÷T¶´kðn!óŠÈ±& |Ãs;vh—ÁR»”)ùè¿3· nÒ ™Õ#,72©ˆH—'¶áëRWÚ¬š–—ªKo{y=ŸÛ-#‰u7n­žC¿ –€9ûew+‘Å;ÝÆrßkÏåÒ»Áyög‰ñ¡•„©7×1â9Œüç%œÑèªn™ý›æâúöçÍÃ?Ú¦ó>~w8ãåÝÇʸAµW'7袊(¢Š(¢Š(¢Š(® Æÿò‡þ½×ÿBjïk‚ñ¿ü†¡ÿ¯uÿК€=õÍø*ޤŸýs~Ê£ Šæ’ç[“V’’x쌳­µÌ¶@ï/ "‚‰Ný­„/±Fáò´åÔ¾#ÓšÊ[‹Ë+üÝm,í…´· åK”O6fV`Ûï.7ëÒ€:Z+Â·×ºŽˆÓê;>Ô/.âqܪâDUjä d€N2y5ƒ júíö¸D²ÝMÔo`xÚÑRµŽI•$óH$Ti`väùgaî(®O¸¹Óþ\G¤Øj6ŽšÊÄ‘Ù< Mrò#Úm…GËãv0¸fZözŸŒï4«ëç7P=–œg‚Ûì?5äé-ʪ’ñ«é%•QïR¾^p@=Šâô«ïÏã[ˆ.×ʱIfÝ£ù~@$DѰ€)þìg~ üªF´ Š( Š( Š( ¸/ÿÈjú÷_ý «½® Æÿò‡þ½×ÿBjôÿ×7áüª:’õÍø*Ž€ ‚öÆÓR´{KëX.­¤ÆøgŒ:6FTðyþÌËâ]Z-FËM:_ú\×÷0;JXŽy ÄœåcŒ’¡Âüá‚«W.5mrÊÝ%½°Ó£‘§Hâ¶¶»yäºÈmÈ™Ž0® Êá[qE˨ìCko½¼I1(HãBª(Àv¢!·BD‘!fr¨¡Af%˜ñÜ’I=É&ªhׯ¨i0]Ë$$›‹CŒî ¡ †Ü¸ÚÙ r§*¿tsZ7‹¯µ ìRý‰—í÷v†Ú$q4qDÒ…¹bÇY1¬G®öûàæ0ÚQ\Ÿâxl~\^Ùj‰taÔnm¢¸šQtª¢åö $yPåmÁy9LYU«Ùø÷YÔ4«íNÞ 8Zéºq¾Ÿv]§)-Ìl‰±Ê¨qoÛœ&qûÐr=Šâô¯ꚇn4†³`ŠY’H‹Ä³Ccûã#+˜JŒJâ/ÚPEPEPEP\ÿä5ý{¯þ„ÕÞ×ãù Cÿ^ëÿ¡5z ÿë›ðþUI?úæü?•G@èl™Ô#…ÄÛšES3˜‘Û;"'b9Ëe•A;Û'æléÖñ­«\i‰§ù·vþkÈ‘Ü'ͨ)³8̾0Q¶„Ý–` fF]øƒRƒLšìh/hadu+¤A l€Èó™ŸvÕ ´,Éâ€:‚ÎÊÞ†Ú?.6–IˆÉ?<ŽÎçŸVf?—=íΙo>£d–WŽ»¤¶IüáþîüN1œ g8$rptÏ6£©ˆÁ#¶mFçKYVé]üø¼ÆåùPÇ9$6HJä©¢¹+-zîÇÂ/uq7ö…ò_ÝZB&^ã˹‘ÛLKГ²3÷I ‘R/ˆ3\ZÝ]C¢9·°³ûeëÉ1ŒÆ©$ñȪ¬™ónÅCÈÎãâŠå´ïI©x‰ôøô‹¯±‰æ¶[±Äˆ°bäÄ"Y²1ÉPTÛzš(¢Š(¢Š(¢Š+‚ñ¿ü†¡ÿ¯uÿК»Úà¼oÿ!¨ëÝô& AŸýs~Ê£©'ÿ\߇ò¨è±´O/m¬ åJÓGˆÀÙ#nÜãÑŽ÷ÉêwSQê:V«Û­¾§ak{ ¶õŽæ‘C`Œ€ÀŒàž}ÍfÖåÓeÑ5Dò¢yÞáV)PF¹¶Ç#IóB®Í̓ò¶$(°kw¹ò5í¢eÍqa5ºÂ¤¼ÕRP‚W;r arÀNÊÆÓM´KKX-m£ÎÈ`Œ".NNp9$þ5ONÐtí.g¸‚ÝéÚbn]˶YšfMÀ³{œ§SÍ\²ºûm¢\yÀ¯’©:l}¹à•ê¹88#8 ‘câ»KíAmVÒö${©ì£¸–0±Éfõ5“iâYm|#>¯«ˆ$’Öê{yL –èÞ]ËÂó¤ ¹Ú û ð*¼_´›ˆZ{{{ÙàŠÔ^\M#G[åGfpÛ[cBùX°åŒÑG¥iÑjrêqØZ¥ü˲K¥…D®¼p_#å^ ì=*ÝsV~:ѯ|LÚ2æçÍ’o6#¾HÃo_,9‘q±þfES·‚w.î–€ (¢€ (¢€ (¢€ à¼oÿ!¨ëÝô&®ö¸/ÿÈjú÷_ý ¨Ðgÿ\߇ò¨êIÿ×7áüª:ɵðÞg«M©ÀoVæyZiA¿£w+·&2ûÊpc¿ueo{äý¢?1a•fE$íÞ¿t‘ѰyÎrßÄTVñÜKz‘Ã$ó[ $TIÈ #(†NNËב˜‹t)mÞ{=A5•iˆ×Œ…#r¨;O$cŠÓ²²·ÓíÖÖ?.ó²0I ÎÕÏEÀQÀVF‘áM?J¹’ïo›v÷W;òÊ¡¥‘ÛvÌ•ó¿—æcqQŒÅiéz®±¦[ê6.ïkp»âw‰£,½ŽÖàõŒÁª–~&Ñïõ±¶»ó'Yd€þíÂù±–ò6ùƒk6ÌîÚ7·šŽ ii‡OŽ;¡ž×*Æöc*JÙÜÉ)}èN[;Xg{gï6K è¶Ö7–qÚ¹†ö¶¹ó.$v–6i‚ÌŲZiNsŸ›¯¯›¾§}hð¼SÍo,6‹%Ñ Í*70%s÷xž•øÏ@IV&¿Ä†!3/“&bŒ³!yßݪ²2¹l#·# ít{;-BkÛqfçdoÞ4aŠå¾]­wGî˜Ö}ui°2q2(þ¬ ãŽA ø‹C¸ÔΙ³§K~Ú¥Ò4¡—;†Às‘ƒ‘Ž0jü“ÃÄ’Jˆó6ÈÕ˜í‚Ø§ ǰ'µ2ÊÞ[[D†kÉï$\æyÂnsÈEUã§tükFð§Øn~Õww<¬—÷w±[‰7CË$¸q‘¸7•)R ìÉ'io˜ô0Ï Â‚T•2F )*ÃŽà‚ìA:®qxl࿵–è+9&Vpªåí8 “Ø‚:Ð)ð]¬ž—F¹Ôonb’éî¼ÉÖ;Ý˰)åùn¥™›‚r0UvÇaà-/Oѵ .)îŒ7öme)ýÚ•FyÜ• TæáðÀF8çNÏÄV3èm«Ý·öm´rÉ ¿n‘Êt•¢!˜1_¾¤ œŠœëšJýŸv©d>Ñåy¸OÞù™òöóónÚÛq×iÆq@º‚ô7ÄSëPBŸh•¤·„”‘Î]Ä›<Üœ·Èˆèj¤z®.§.™ý«ß»äµY”Ê‹Ç%3>eäŽãÖ­ÐEPEPEP\ÿä5ý{¯þ„ÕÞ×ãù Cÿ^ëÿ¡5z ÿë›ðþUI?úæü?•G@òh:ŒºõÝæ£}§^ØÜ+ÁöY4öÝ ?Õ+Jà ’™|`ð-}OÃ}œrè:"ZÜÇ:Ë»IH HGMÊ|·8‘—€ؘv£Ötù~ϲã?hº–Î/‘¾icó7¯N1åIÉàíàœŒÛ†e  p2|èÈr¤©à€q‘ÁèFÈ ÐO…4É´ŸÇk::9žâp’JdtY&y]‰;œŽ[y=NNáK«[Ãuw2Gj׺Š[¬*É#ͱ‘ŎÚA`qó£+\<>ôUrJ0\@Ãcü§ Ž3ŒŒ€sQxcTO ͦ6¶‹q%ä·B{{y!R$‘¤d`³Æçb ȧ…#pj?ÖÛJÕ­¦Ôk­CN–ÃíFÝ‹D$–âV »³Lë['Ë’OÅËiÞ ŽÃÄO©5ãÏn³ÍuoÉ>ašRÅÛo•ÞH†$䞦³!×ôÙõ3§Ç3™·4jÆ;®w"JFÇq†Ê«66GÊØ¹y{oa Ís'—K àŸžGTAÇ«2ÇšžŠŽI–'‰92¶ÅÚŒÀä…“œ¤%QEQEÁxßþCPÿ׺ÿèM]íp^7ÿÔ?õî¿úP Ïþ¹¿åQÔ“ÿ®oÃùTtÏZxrkͨ4èÖ¥žÞÛÍ*Æ®Áz)\¸rÆæ\ã’ø/àÍVÇ£˜ôëC£5ÒÙÛÊÞX]äu‰¼È €¦P@10ÌJFÒA^Ò=WN—S—LŽþÕïá]òZ¬ÊeEã’™È2òGqëD:®q¦N ûYl³›¤™Z «Çx8ÀÁÉÏ4ÅËà]UtÉ,m5$H¯tácv'!Ê/ïþT+‚‹ö’TÝ9)UðÖ£}}âÃoo§C³¤­œs ˜HÓ*È¡¤Q1‰vçs#^p½…ÂkžŠÇí?ñ+“ììÖÂÑï’I—ÏKq!çݾ˜rèŒÜ&kkÀöi¾‚ÚhçÜÊ‘ÇDo<Ž˜Œ’cYNÃÊçkvá¸BðJ’ fBÈÁ€e%XqÜAˆ"¤ <ñ/†5i<7©Ú$pKmoý¥}nð»¼÷OÀy[p¸7 Äì(ÝòØ“Àou§^Auk¥œËk4Vøi"žXd.óH\Y&Så¹>c´+·žxmm丸•"†%/$’0UE$’xõB?hré’êqë:sØBÛ$º[¤1#qÁ|à™x'¸õ  ›Q’ëÂ÷Øi ú\îòÝ£BÑ´~T?!ÜuÎv1/ Ÿ—'UðF£|5Há]:9®Vóþ&EÛíK4rªA( ‘{ñaG{ú(‡Ö<3¥í¾™mjl®VÜùÜ” 2L’È)VW`ÑdV,Wq!‘MkÛÇâ .ÏÃö6ÖzuÄJÂ÷yBB¾ZªÄaFB¨$pˆ÷} ™úËxŠî ì­SGX#k{•œ™^R[z”Æý9mÄ!¡Ï¬ÜXÈúå•­¥ÐžUHí§2©ˆ1Ä9#¡Â’Utè ¸/ÿÈjú÷_ý «½® Æÿò‡þ½×ÿBjôÿ×7áüª:’õÍø*Ž€9­ÖòÎçû>ãGßW÷w‰~òG娖I]|±’þf%Ørª1¿ x ™ö-jO‡Zݤzf£kªË=ì–‘Gurî–w–'’à½wßÂà ÝÜQ@µý»¨øžî-=uœi6²A Þ,kitïq²YT:.Ü8V`p>I8+'†“[¹ÖZí¤½xT¿Y'–ð<-l²Ì‹ ÅÕd`vŸ‘qæcŽîŠáì4ÍvïHÒ¬î¯`‘j×-rd¾V™¬Ùg1©Häž$ë¼FÐõƒâ†Õì´©ígÔo„1é¶ïªÍi1IJˆZ#?k‘£òÆ;UÏ2“^­Edø¦ÊãRð†µci™ssa<1&@Üí2x‘Ö²5Ï\Çá_¥¼—ºÆ­¨Ø5š¼Í 9]®x U2»Œòy8Q]mÃøÖ/^ÛÚO¡Y]Ep4‘„œŽb *‹ˆã 9"e?7ÊùÇѼQ»ÜY_Ý.¥=åúsr-Ø\|'+€ÿg9ÚÎ+÷FÑÜQ@>‹ÿ ‡ü;«êVšü±¨km-ŽefPw0v¹œÙQ·wÔ%¾nŠóW¼¶›GH´;ÙÖú]“²´èCalÉó`ò1Á#® ;Uµ¨  È5;©|Ew¦>“u¬G*j ËåJÌX9Èǧ®@KéÑEÁxßþCPÿ׺ÿèM]íp^7ÿÔ?õî¿úP Ïþ¹¿åQÔ“ÿ®oÃùTtçk}câBãIҾת¥H’\ؼ2䣴{îÈ爷–‹UœŽ ]®õ/x¦ÖTÕ5k&°Ûh÷ÚaK‡¹`ã`‰bBUHƒlà³ß/ËètPâoY´·Õ&Óm5¾Ñ¤¬šRCdY–ä K— ¿!ÂvɌઆl­?F¶¼Ó|e­¬ój“Ç}uöˆ”ÁÙÖ?&%ó Ì3Mű†*yzëh O¾Ô×Âpì:¤ 5K”»º]+eÒÀd•ã•aò°ÌäøˆÛï¹ JÆo<`öºÒÍt‰e§}¦Òb»ïdY.<µ|®AxÒñ¨VÆ<¾T÷ôPÂÜé÷"î>ØÄÞl^Q—z`åvKddmç¦+Ì]¤Ž2€Do1@|®Ka+´’exžH‘Þß2‚Q°W#Ðá˜dv$w©(€·ñT: ð^¥qz–“]ê76­]…ŽáV9ãÎÅrŒ ‰¾Òêå¶­õgŸÆºî¡eö˜¬-å·,Í&PwÇæa°v1*‘"~é®–Šá<3â J éêí)mü¨õV‚Îi&¶S Ž;<ë* p@|²(æº_ ê·ÎŽo.­þÏ/Ú®a0œesÉ †a»3‚FsŽ*Þ£¦Zê–ë Ò9ÛÑâ•¢’6ÁWBN d:*K++}>Ñ-mcÙg’Ä’rY‰å˜’IbI$’I&€8ï Yê÷:¬ú“Ü:Ú®£|Žï¨Í9ž5žTXü‡\AHR 8Œ aÛi^%[E-–­k$?Ú×v©ÞÜ5ÌV‘ fhÚV. «.çëPäðEp â P꺧q¨ÚÚi’Au ÿ£Héx릪Ggá´ÉtÈí´D°™·Éj©‰ÛŽJt'å^Hì=(®¹ãÑõ{Û°I’ÇN]RâFºTo 4ö& g wa™>]Ú~)½¸Ó|!­_ZIåÜÛXO4O€vºÆÄ uªBÃÂÃP[¶“M.+xà…ŒF8<ƒ!£_áaæ°ÈèÆ;éϨh÷Vò[Ü]ØË ªRHä‘]HÁ‚í@ø¢þãJ𮫨Z¦ùmmd˜ Œ€ªI*J8Ü$eH$xª׊n4CP†=/϶ӬPº¸76ÄL¡•W´˜ˆ•)ç,˜™à¸-.-!±Ð#¶¹Ûç‘B]§+¹@Ã`ò3Ò®ðâÛ½º(Bð-«Æ {Z,dt(6 Ü}h7Nñ„š—ˆŸOHºûžke»L@x‹.LB …‘€+#•A-·©¬ˆÛÑjrêq)/æ]’])ŒJëÇú‘ò¯ö•oû_Mÿ …§ýþ_ñ  ”U?í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùÆ€.QTÿµôßúZßåÿ?µôßúZßåÿ¹ESþ×Óè!iÿ—ühþ×Óè!iÿ—ühåp^7ÿÔ?õî¿úWcý¯¦ÿÐBÓþÿ/ø×ã ˜.uhžÞhåA£`Ã;›Ž(7[ÿö£ÿ_RÿèF¨ÑE!Q@Q@Q@Q@Q@Q@Q@Q@ÿÙnetgen-6.2.1905/doc/pictures/menumesh.jpg0000644000175000017500000013630213504650527016734 0ustar kurtkurtÿØÿàJFIFa[ÿÛCÿÛCÿÀé#"ÿÄ  ÿÄT W67—Õ %Vw…”•˜µ¶Ôר&(U¥$'#8Ffg"9EGH§)DXe5:r†ˆ·¸ÿÄÿÄ!ðQ‘!qA1añÿÚ ?»!ùùu!uµ]]·•ƒÈ{ !Y½÷žÚ²ßûY·w¸¾û{wsÿos‹þ}÷¼?ðáðááðåç.wªñϧ=àò ‰ëXéò°ÕKªéïKõþœëiÔ~¹è~¹Kë™æ½3Ö*üï°õžÛwµ~~ß~kýÍ]ª»almÐöç2ßeã–:d|QgÓ=/N5”žA}>» 7ÖÊä5t¿„ÛŠáp¬hcÓ&®”Ü})aÁ”ãpw)ÎÉ ©v·IÂÍ£/»“Q±ã Óê2ÑÚ:’aB±ž!{á²a»èíhÈG¯*£K«º£º«—ʦڶT˜0$Ç™Fô}í½Î/sº§¿ëßítßgj‹.`„éŽM"Š8Ä¥vœs*6,Eb•†70\ã†*bn¥Ës.ˆcF Ùä"Ê €q¾˜¬­]'¥ÐWÓÃ'è­¼‡æ±…Éß슩±¶’§¥lG°7K›.G¥!¥…¢{ª{þ½þ×MövÕ=ÿ^ÿk¦û;TìùJù€ b‡@Þ´û¨úçéòLܾJ4¨;Ž¡¨™Õ6$«à&<ùº ï/ݼ»–yG¾®±ÂQÁºYsc‹w·2s›:=‹•-É7Ü<ïx¦·1oãSPÍ‹ƒ­¸Å÷ ÙY!} ëPÿˆÉÖÂ$…E&¨ ,qÂ!« ™Gä!jNêžÿ¯µÓ}§uO׿Úé¾ÎÕVóW"ó[he 63½ÞøÊ$.¬¨Ìc»dár¿Öc ²lã­žùC‘%ÄkÊ䀟30ƒþçôËâZìÉÝé ~5+ Þ/Áç£[M»‡ë;\Põ>>ˆîÞÜåMŽוï%u2gªÒœxx´¶{$“Ê×~Â6@°!0yy%AÇ_ÈF“QP^íO¶a[AாàßÜ¡³ D›e5ŸH÷¾¿îÅÈ­®:Ù’Wæú]|#ë¼0:à“ÈNô:o;}qä¥út >[{ï3~êžÿ¯µÓ}ªhs3È}ì»Í>UìÓ"òß’™õʶ=lhëÖÀ˜ÛQÛš¼e¹ÚÚøÊPà¥ÕâOAPDCÃÕàV¡p3 šA0äû B}’Ë®jY•íË„Õ!ÁŠÎûZ¢¾›†ãØ +„«u Ç7~`¨–9o2ž~ò­ËêC„w [9’½.œj¿bB«d-IÝSßõïöºo³µ„å6gWvá¾ÀíùÅúÈó¢n ú%’)å:¡|]è\3úlàoÏÁõñ;Ÿ%}OçbzŒÞggïë’m“À1ߘ°ˆö];xé‘9½@™ÄZÕÎ*¥\Xdn¡·—i`ÚnÖ°h3%Q”ír+ñ¨ã·—u; àö¨#š´}ÅŽ’îã(£;mÓ—ØŠÜæs[²Œ¯yìdeµÒ.Ý*r6ø€däF¯FY†ÄvÅô4rc–‚o HQo-‰`Sµ`ܘZ1ׄ(P¼÷uO׿Úé¾ÎÓº§¿ëßítßgk^é Ø]Õ=ÿ^ÿk¦û;Nêžÿ¯µÓ}­{¦ƒawT÷ý{ý®›ìí;ª{þ½þ×Mövµîš …ÝSßõïöºo³´î©ïú÷û]7ÙÚ׺h6uO׿Úé¾ÎÓº§¿ëßítßgk^é Ø]Õ=ÿ^ÿk¦û;Nêžÿ¯µÓ}­{¦ƒawT÷ý{ý®›ìí;ª{þ½þ×Mövµîš …ÝSßõïöºo³´î©ïú÷û]7ÙÚÔ$ÖÓèFÈo*†o m)hí­«CFd Ä$-Ÿ]DÈc#ÒŒˆD„#^_HÙÛª©VV27³>\}ËÂZ¾VQ¡ ÍAžd°Ì§›sÇËñ“þY›U`ÜÓ_l¯Q+þì§s óB¢´ð£¶´)²Þº]á}Úž`,±'»*EUÄ Ð°×uO׿Úé¾ÎÓº§¿ëßítßgj®È°ÏY)ɧm­“´m5§5ec£"XjøÈEÈ–ð>4½Çª"Ê^)åóU›qݪ;-æM©Ãby&:Á+ÙjAiš­öû ù€·ž4X€ñáHfB‚Ÿªäñç^4Ck«ZúLª½V׊Ϸd¨/Ž/¬7›;¸Ó—Ùg6Ń *°¯†jH<ÝSßõïöºo³´î©ïú÷û]7ÙÚƒœgæÞ}f!E­ÂÛõÈÃ8fóhÏÎ'Ua>CÇjœ[[©ñçx#z¡ODuᵌ;9âÂ;ÏjåÔ7çǬ¢CÖg3LŽ¡äçNQ›ž…a̛߾ŽUAˆ å讲aÁ! b%4bK½€0(xš–ez9906¶/´ÙǦøËUŒKî©ïú÷û]7ÙÚwT÷ý{ý®›ìíUÛù¨ä'+Ì Ë·¦Ñ¿œ7„Wé¶âåÁºs˜3Ã2’«xëñþ£-Yc-;¾»‚®5¦%äßävnÂÁf¹‰"'ìc[PÍàƒR·X‰SŒs8a„R$Xòj¥™®­lãxnÈ¢¹Þ©ÝÿúgWlÞVŠ™Æª—1ððãd„x!ï!rË'wž­Ý¸ïæå4:Ö!euPÁé•}Pí̺*¨°hì*)b{*Úè¼2wãÀÛ“e3ÂE¥žôËI³fHkŸ¿NίÊÓøÆçMa™Üßù 3;›ÿ!k†¯ÏÛï͹«µyÊó²±…ÀÜtãÕ“_rŒ´fáœZÆI0ŒΡ«ÊG˜†‰Ù#.ŽÍi ÁwÃRÀ²%^ >ðJ²<*+êû)Hö2zÞI‘Œ7ƒƒ9@…Èæâõ2H[?˜xyˆÓS¨Vƒ7–$œ2ƒøjl‹6gÆ9«¼™9} Õ$ Û³s>W˜t½N+­qêŽCÚf„Ú赌¤$I°nÙe*ƒµYˆiÚúŽqÝîá,@BJ jYô>cu±× {™Àfâ î~&Ù$èÄd`Ý,{vǯ jà- 9Fö…’$UD#Û«>¼>«ÛÜ”LLˆbIfI6ØË~ÛľæÚònïy¤IƒC\JÂÒòÕeKÌPPe‚%|HL’¾ŸªÄ=GUo.ÒéYui.-mK¶,‘+òcÇo½#{oo‹iè8ß•æ2Tî„Þ=Q”­2"É2Õ£GlZÆßŸg‘eûÕÛ„1’¿õµå´zͺy֗œ#v"Û[Ce$µVÞåw.<2« \ÆMûZ5^SÁͱ™Ö,6­¹¦W×ZÜÜÇy±ØöÇ3Xn3Éw³¶gJn”C´ªØ¦¢²….Œpzº¯·µ¤2;#“’˜2È<ƒ2íúÓÝ\]ÓÅE~“ÕeTa4€hÉ çùòrJZÏÁ”³|¯ó³|µ|iröHdß-Ü̦J¹»“xæÜa§=†ÈI þñ/¿ª‹}š ¹µMÝEP"%æÄ™ÑÚ5¦A‘}tº6ÅÜCRè÷`þ\xd j½¡Mû[ÌcàY'.ImS[ZuµqS=|[bfs-®¨aО"„Û[Ç(1¡’„¤+ÁÊIÐ:šÇ N-˜-Ö=ÏN/aŒsÂNµ·ô ÀzäÅ>“EÒòÓÒèêçNôêjÛY¾ÃËWA—/wf>ádÇ q­—ÍÕÅÏQ¯lp2Nµ¨õÐÊÂ÷>“{®ò¯Õ(í ÎôëšÚëX^ßËXÁ‰/kz>Øqâ'•æc;cÁÔǪ03¸—a¾Ŭk eÙ#§drD…D¦%1¹T&¯ hFC,­•!AÓö×´°W0dDÛñâè³¼qL3èlƒ6 õ¶þ2wG²ÝBU[Ñ=ç†ÊüQy`“© D¬ÿRßú?²ó´•a¹¹/wëH{Ç&=ä}ÑzËüÃvCÞ;·Ýˆùñø§º—ª¿ø—¡úGüþƒHWrÝÁÚ0ÅÂìgÂÔ™O5@@÷ˆ€ê¨òjªÖæÚ—½:î×=×$QÑñZ¯èÃ+EÀjEaƒ†Qøqù^`tL‹¶Ê¸¸õGÏ|ÓyÞNŽZÆÙ^Ý;D© ¨…VÈݳm‹Lg€ÔÊôyƒ1q¼[JrZLÇ­·ŒÀ¾µ&—Ñgy˜Y¹ÐØøleèü›îdzxªË­»0+ Ù•ø~¢ŽxÀßMŒO‰gþ.º õkä¨=VÃor'ïÐp,~W˜"í²®.=QÆsß4Çžw“£–±¶W·NÑ*Bj!G²7lÇ…bÓà52½`Ì\oÒœ–“1ëmã0/­I¥û„<¸ðÈ­1‘Øù~›óê ¶wÞdvAˆ÷ «¸rB Ók£/_„sœSΓ¯Älúx&èlV7¤ù(”{óìâMíí4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@׆M’XÙ PÛj:ù4vÑÅ/ ‡§–Ò’o@‘·GlB)TLhMG]iÅe°õi”û¨2+a“PÈ“·kÜÓA[Œ]äîäæŠ9ŒZ¹ÃÜiÆ•cŠ êÿܹRè€Él:+°‰«W`O!àE¦'c¥Y#‰ˆÍQ(ë-öCI-Éh줜G8‚D¸²>šhâg.<2J{ªvÉ7Ó^äò÷aÿ¨m[žÙ{Ézz~pÚõŸYú¬ÿ¤«éßoþô/e³ìû{MÇqLbJ`71ð7·êÿPôˆP•úOU•^_þ6¼$'ŸçÉÉ.¬ÿ ÝMò¾wÉBòÕñ¢DØÝúi ¬K÷éÙÕùZcÿÜé£÷éÙÕùZcÿÜé©Ó­pÕùû}ù¯÷5v©Ù’dhÛÈñà€ÏÞn•äé“0%¥£ÆÖ׫%±I˜™|FÃUõGl/DèmÌ×qU³DkÐe$^u}xôÅ=:»¨*¶6k­¼ÜM® ž¥’¡l>hÓªÊW‘­q“'=JøJ¹°Z7dz4Qâf,:’ûê8ÑÄ…6#ÔÚÜK³²2=µ·‡‚–·†0TJë*߀ÊîgY™Nól½Ånw‡ÊNÃû—,“Æc1¼.³¨ÇyØÙí·Û €æ·à¶gªö×ìKqZR†ñls0Ÿtsÿ¹—2?ÿ¿ÿª‘Úè¼;儒ņÆI>o)÷“Ë0²(Ã\öÈá*&Â\mõ³4¤ÀËe‰i|š:ûÅ{.j®àlšínÕðXYpØ÷Ód¶q†\®«à†¢ðÓº„ Ž'Bp{é°oj}d\𥧥ÞUÖÜ×yè;þJÖº Œoe.$}í°¨Žb“\` g“®á Ot¿¨óp™á¿2ÛøÉ8°;ÒÖž_„%»£ò$ZxÑ´-ܹFxíƒÖ"lcYëÜ‹¥" LÊâÇ·id”üÄ`L£InýÍ¡Һ”k›Î _=¦ìVÛä%’rä‘ëxŸZ,÷ ¸¬¿h°‚½g›oØ Ç€Y2öä·ë%±_[uBø “¹L_¡¸îÚWyñ·¨À“Õa»€yåï|ý n¶.ö08:’çÎê³ì?Ħ°Úì5£‹˜èÉPÑñ ©…’KCµxß :®!åÝÍXUXÈÝoHÔZÈ0¨áøÇòõ06ã…u9Š–d]8627­ùQºmœ³®m|NÄNat˜(Ø~0·¼wì,ùB..ädª²˜@mß³¡ÙHF»«:«1f¤ =Êš¬ææÖ°§zå:èMÙ÷:‹V“õOAõïÃCÔ?æ4Iåù—y@àŸ÷4VL‡ÛL¢C¶›@ó¯nIÄ(h1²AE†íU\˜5lëÀz±ª‰U¤Çï‰$’mÎ2³¶ž_qqy?HbÛ;()p‘.kLÍ|Â0k¾y˜âƒ`pýÝpl§:Dµ_/à«¡Rõá )ÕfW”Ukë-àæA–ñ Û‚‰çå€sù7s¨N¬’ÉPŽ]ÝµÈ OŸ’4xÊþ¡#.ÇIÁ8ú`³b+²~¼®_lå÷¤n²n”4O> 3„Ã9ךּK¯q‹:y§­µ×€àŽ_¹¸È÷›pk„ÜäŽ9Ú4lb®­qx–’_H-iïF·xÁ½ßœZNHXÄ;&··;g1 ÂÖË#næ-—Ì~‘8_÷ LÛ Ù´(É êº½"ÁósúlàoÏú1ež›è÷Ч×y¹>[Ûqæú§¶'cŠc*³kSïàÞá¬o>å—}t&Y U ÿ›mPlúüA{Ê?\ô?\ã'õ^9}É£ lú9x\7«1`˜·–×!K\³!¼&埧”#9Éd¶Ÿt§pÛ= åÖ=ó8$I¿ÙÇA&½ø¤Z“=Î_¡Þ¥[ѹãÄ¢®_ÅÙ ®j:›ÉÖÀ®w>*ÑO–müsà`ä@Ž6+èlû7Cj*0l âý¼vž=8j îÙ¬VI[¦‹$·¥LáFÙ°•‹~çH™z[¹Ïj›!¼&FÄæbùÇË"c›©ñ±Ð)?ޏø=c6D–Í’b„Pf¤»s†î„n–¦ŽlxœuÞWgÃÄ|ŽLrÁsóGMg!—»ÿrs{&3í4Õ;*¡L>“ aUU ªæâŽ¿»îõ¨Q4Tµw%\EWÐéÖ› ŸN#‘FyŽ9˜ËdÀnAãá—p ¡éîž*õn”*¼ ¿ümF6OÈÝV~¥…æ¼—…ækäÄ—¾ÈìŽLbJ`Ë ò Ë·êÿOuqwOúOU•Q„Ð~ £$'ŸçÉÉ)k?RÍò¾wÎÍòÕñ¥ËئÖDŒï'ð±K’ùF<ÓÇeFO}ÓööpY Ô¶y™ÇBŽ¥TÍãú0ØõŒµÛNÚЀ֟qE}w’Ð@Œ¶EüØ»p=̽Yw3—Oèú·Óþ2èCù‡þ!õoÿ'­ßª²ÌÙªØæšÑàå .!/‹îu;ØR² \-¥´dfùÜ…éBøxªˆqYbpÓÝŽj&y&¾B…©BAŸWzR¼/„Mo„rÐôzþ\>æ=q×Þë.—»Ô»“ëÝóòwÝïuÞŸûz~_x®šûÏó Ûo[ôïò¥èz héªbZ]zËÃîw²Ø6ºðw#¯¹´†£,Û5¦ç;$›‰&žGd°ë;‡Ä“Š®¹XMVÂrú¶¾ –ÜòÖíÌ:ˆ×GLóî¦/ŽLs §²S[QæCù·ÌÄ;À-š=™iŽaø•²`­1¯¶G³ “ ‚:pV œZëQÎSÏÇ eÛP™–¹»T´ár]4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Ö½×®ç-Û¬eAânZxìz?ügŒ#œÆ{þÖ‚¯{þDŒPê‚ÇÙxn{>BÊO”™·" ¯c6,˜ûZ¿¯6~¾ÿfŒ‡þ—êŒÛöfß°ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬ç\èúÇÉîÉëR܃ȼv/VÞ_ÛS!M†à@#€P74jìe”®i„µ‘­ ? ®è$«/ÉI)á\¯ÈEdM ðºÚ]y³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ¹Û p•OÊr5b°¦y ñ¦rîh´]Ç;Ì&ÃU°ÂÞàHttIá–®]人QúmÝÚaúM› šM›»½›RûRR[ÎÂÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ëIe"­²ÛÝ׸÷gžì™N¢Ë >‰²¡­õfJc¨:^»×F‰<øDþ¤ëõ´Þ}+ÙDôâZ¯g½íú›X7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬çM`Ýy³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ³5ƒuæÏÃ÷ßìÑÿÒý:ógáûïöhÈé~™Û1Ó1»f:ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬çM`Ýy³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ³5ƒuæÏÃ÷ßìÑÿÒý:ógáûïöhÈé~™Û1Ó1»f:ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬çM`Ýy³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ³5ƒuæÏÃ÷ßìÑÿÒý:ógáûïöhÈé~™Û1Ó1»f:ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/×¥POãu?jº8S‚æîÜ­ï„h·@,}¨q7æÈÝžBROC[·Ã>ï³ã°²Ã¿½ì¢ìxîJߨÙÜf7lÇLÆí˜ê¶ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚ׺ØM_Ÿ·ßšÿsWjByšeFb©°6¦¨Â¬Âqb³œ#&î,2…H1°z~—CMÆŠàC[ÎBnµLü„$-¸¨±²°¿–;»}B„Ði®=Ï|J-Åô¾`Þ=UŠTkÖŒnÀ4­ÆÎZÀŒHAOck)awy0ÆH†ËLJE Xù˜UQ5¼ú@à Î=î1Û-ÍœŸžaYSË·ÃFhÚbÂ(ò,˜QØ2ź626‹MÐ8¨ÈG UU³hÙµdcTÛV—ŽÀ®Åú‚8òöâp‡}i®t¯Ì J¶$g†Õe:Y—¤¨ÍIœâ•îÕ¤ÒEÚÚS…ŸG›rÐŒÓsn´ÖØ®-Liûœï$@‘Å÷ãθ§ÍS rÓee`Ëœ!V¼öϦx±T æhÿW`.»Ý]^Ä$£Zw.ðnD¥¯P‘lu•UNýOµ—/ŽÀH®šÂ Õ³Œ2™Ž¢`„5„~£ÓÇ‹‚Ê€ËßHµEmèÅ3í(í=.ò®ÊšÇÈÎßòVµÓ«¤û)q$líñ s Í–Nr( ˆô 2œëJ½~Ô«©Ã(@Ü­¼)GKÜ[ÀF<ß×YZˆô™¹ºÞˆAE"`H®šŒìnæn§Èœ‹æBž‹ Œ)iË’ðxåòLi½L7>Æ‘—ºäCN\ oF/S™ ÛL'&(U Ò¶Úß-ù½„“XÜÌ[9W`(þ¿×P–¸ZØ'¥(buqÍüñ¾›ŸŽÿÖm!z= Ø—>Z¾NÌŽ0Ýúj3³™êK°9ãˆkµfd$¯FlªO)£v† e <ÁéÌ€ÚæmXýàý[6œ¶MNý$éûð7+vwcÀwÏk·€^i&±#5\âV2KÔ7œ#-‘@‘‰"¼“Š}åWóŒvÞÆÐ*óŠÐd’·†¤–-dÿã×ü#ùŠ™ûqÃi馚ši i¦šši i¦šši i¦šši i¦šši i¦šši ¬K÷éÙÕùZcÿÜé£÷éÙÕùZcÿÜé©Ó­pÕùû}ù¯÷5vªí„Ζ~Àæœ933  òmsiËæ®9+DZ¥ì> æk.Öer2vùgÃŽ+eeµÅe•Ñ30ɇºö¢ØÖ-AI ¢Z¿?o¿5þæ®Ö½Õ ö™‚95„ko¹ôá—O”ûÑ1[ß&›&Ù8tž_½\øâgšô1 #AÛVï䕨Búòô؀Ǡ]±ª§Š‰XÞ×V0Í•ÃSú-ˆ“Óïo¹Ô­F¡3]’£æŽBU¹’áÃs[ ˜Å„‚°¸ùjž9h±¼8$%,föe $mȤÕ0Ôäôp,ý¦‚¢\˜1<´8“A²aGÌÄW"yÞg¥M z$Ê I÷ådÔîýÀ ÷ͦ;¦p#¤“¸ÁÆ%Õã˜í¨¤‡HAǼ¾äéËÉ7ÅŠÙ…T×åÉÌÄ ÆûŠ©W‡¶ ÒRd6YÙ^]ãiÇý^CÞÕŸ©‹©ŒÇA˜XèK²Å¢›Àæ€ õ cuÍ4Êá8 ©S¿È)3 wÖa=Ÿä™´½Y6%[ÃCEÅp(zÚÑp¬?´ Ü»e«¬/ Ù÷;àTbþ! ‰Ívá #“ÝÊAࣤ;ì‘lŸ¢_oPWnœ%A©¨„øçq_T+„ë«àG©Ù‰7šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šh+ýúvu~V˜ÿÆ7:hýúvu~V˜ÿÆ7:jtë\5~~ß~kýÍ]ªò¤ó™ŽIÀÏ#ômN”GÃ|úÈ [ Ʋ›P<åø ƒ$ *$|œ™’s-3€BYÔc7W¸ý|½„ƒS8›nBâËtnÃM_Ÿ·ßšÿsWjµØ¸!Ì? s [àíá£/'y˜äþCã»dÝÃŽ5X¿F½yˆ24/‰9³F%OCnÆ$^ƒ¥mHéá×VJ$½“°öÁ#2̃çm«Â#»{}²iôeãaä’-ª«mõcÅ÷" ¼ÏpšI²(ܼ-´º£w®¥R¥Ÿ2ÆßP1Ê~íkž>-™p¬|2Âð.Dy;›ƒ8ÕxÕ$¼]¨ÍMÕ\I36¹×ùÌãÖBá]7†Î1íŽ*–PWÓ@lήd˜µNÖK…ö>S#Ç}ì ºUÝО;_.¾þδê?OØÏñà^Q\¹¸ÄI‹Á/ƒ—ÀÛ̻Ž)šVœÀKMPÆÙóì+èí±›*Œˆêéo•gWÔ‡cƪL ¡ JÆù5ûœŸml=¤8ùhóåO‡X£±Žôe¬¾^ô"ýñʺÅ1&S‰P¼2h”–r¢7ã[!+G0AÈ´·c›«µÓá6$n+Iªï@Yù‘ÉŒŸ µÛbíK%›d=’íª0£­Á>ßSrîEÀF©Ú<0ñróä5ò-®Þµ7É‚LªlO Þ¥Ûrº„Ì*º›F¬J´ˆ 5²ß¢Ù㮟)r_tW ®3³ï•CŸ!sàVÝckéØ5] ùX„|ˆ¬¾®÷!²Ø6B~ bR7è;Ï_·Nÿ-›b=ºé>åõfý쨞!ØIîfBKLÄ,æ&z¬[5ò‘YjãªÇàGiü  Ü!7Om˺­;A·Sž#—ïã9‘ì׫²O >;´Â’,ó‡np fç+2›yXxÏz<´&$bFÜžQ>HÚY 4ÜW¨‹F‹coQ–Ⱦáß²¶ŸNcøozè슮=Ï -íY”(ìšQó æ?މ{oRÂ\(+ÇÊfRý*f/k‹ik6¼f­´‚@‚CxÔìzž u&kŠ«ºæ@•‡Ø[„Öqæ6ò¯È¼SarÛð£kˆ`1ù4Ó³¤$Ê i×b5#ÃåwÕÇf´|'dÖ µ$4csì QG0+sèÕ¡Ø|Ç9žüŸY_Ëmpm"<å±Ã°%ÞxGµåo—7 QDµ.«(·? ¦7iD¹rß—A$ôåµMÅM‹x{6cüÏ}βG—n)®#„·ó)ÔÁ'”Äû^µÐ˜ÜNyP¸(.஢?'8'''ƒ?r:NuЋ’,6`Èðù’`£ 33—¼­±»Éâ$¬æf¢É¦ÉP5 "äo,1NXFpõa\©v—W—V’íaÔÉ£ 4A>4{"ºÝšøÈâœæJ埉œŒ«£`äpw3[6 ¦“¡„ñÆÜôdÊýÏ$‡»Ç‹ÉÌõÈþ5õ~Ùyˆâõ¼°[Ö‹\’ŠTÐ|£˜eÞ~Ãw“üqÞÿv_\íãW³ò=+Ö^ïžñÝ îóÞÿHÿ“íGtzóª¿Àž×áíxqù¡àt¼‹¶ÅH¹ G%ÏBÓF^AŽ$ÆÞ^Ò»Ki ¯E¶Ï-°î$msL›€(ʈy}1²[tr$L¸­¨’À¡µ‰h®\ŽÐ|Óym;ðrñà¿+æÓ{Ÿèܗ̵sŽŠÁ²®; ËlS2ñ´)ȵ¥M@öÅÂÒNìØ˜<¥¶˜¢/8ÚfعœQy‹bÎ:aÂò>oP6ò¸¹ÍÒü2̤hD¸Ï£Ö]D£¼Êr 15ø8í˜bNî5ÛT½„rjÖ‘,9túã ¦‚çl‰ŒI•b™°ÑV$m<Ì^XJ©•@"ÏñÙŸMZ¡#}lñ*o2"²·!±/+ÒØ öU¨¬õj†LÊØÕY\œ¸ó4¯–_:¼| Mùöþ[sMjäv>÷ U¸ ‚Gþ4›R™züӘÞta~]gÓÆ×CeQ½'ÉK£Ø°ŸYm¦´ 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Ö½ÖÂjüý¾ü×ûš»UååcÌM±‘9k̯_»÷–ö‰ ÂɈØÊq ?fŒný¥eÒ­Ë”U6b‹š ·˜í ¡5nCdPnDÏ(‘c2, úXÿ«Í¡Bv4ÕgqS¿Q™ó’ɼ‰²8¢ÂlM÷J¿Æ`•¯°3±[8ê˜4†Âñ-«6·¾¸*¶ˆFÔºz¦uÆñu +2íÙ½æéËõ¶lœº‚]èâ|íg¼*hØl ¡“ ¿T4—^‘´L2šª~ïX_F öMX)}\†§o†8c‘É MÓPÌ+™“ž‹•¶_är%O”øVúJ{³K÷¡@ŠÒÚîP»Y‰o/~-êÛÄ©—š 5# 5ñ¼³d§ áZ4We›#Þw¾P¼ÄTebŠ»"Óp5eàv©ô¨Þ^Àp"I.!QÀl-w8n®­"QÄ´º«¿hÔ­âä—sA‰ª˜ öÈ¢ü;ëMBûÏ:ØXýÍÄ¿2$¼³Ä¤—%öu•«EA¦’X0–ÙoIxHv#]–ñÏ-$>Ä¥Úžr‹kt#f=õbñ+++)&R€gìïÁ™¶e¦æýofÁ60± ʤ—ôåR´³t¢¸8ˆVwÁ Ú7–0Þ'ćהá›]^ØñÙ$‘.Íu›Z¿?o¿5þæ®ÕyI9dÕãöò¤½ÛŸYO˜-`¥"öÊùOšëݤ~LbÝ|ãï_Ú6"6̬o…Uà+½…¶°hîÏ«¯½¡B:±_œ `*<|ôÈa¶™"¡mGËퟌxÏÆs³ÃeO’£f5ø×ǧu‚ÎRÞ8Á ‘Œ,‹° ™s½\If[uÂmI†EG¹ÜÙ¤¹Ž±¢¤¨Ü…ü»hÕD×pÝé'ÒN!·P—®Šƒ¼¶ÖëKHTk»JÃ-œ¶˜¤™:$B_[!ƒ"¶Ôf³ÜprN[6j¹žÇköÙyÌ(# B‚W ºê¬f÷ ¬ XD¦‰ÀE»Fpcx83.Ä&¦]éa•ó‚G¯ëeͯ.¥ì ÌsÍÈI'{˜Åá3ÈÚŒ>¥LëÅd0ÚJxP•%_6Ê€Š3>;ñª__nXîŽXuÂ7>þèÂ{8+ \m„=ç§1—³·’þs>ëhñÄíay‹ÔáíüBÎe†HîO9ic­Á¸u+­j(^Ó\Ç4³]8D-Ä鯿Àµª·[Ÿ¶ 7m Jj?Lée`›Ë¯1ìî£(2ÉFEÂßm@>I\B_ÙmB…:µ¦*_qJð2Ší®%(u‰¼2Ë ª]žµ¸„ƒ‘Ló¬tæ¶=Êš9.c7˜»pÙr‚ãÚÑ{[?®Å 8LvPC¬íÈóÚnÒøL·q|&XðÙË t€tW‚ª}y,˜û›ø‘| ýÇÿè‡ÜÛ´}!ÿ¯íî?_uGÿÛ=!ÑþõÕü'AǹFnØÈÞhÉŽ\㮆ž?#E°öç7òÁ.I² ÂÈx±IW4(ë©Úè::ñy÷†æêfy#¼‘gŰ-ǻғŽ\ùkXÔDÄiå’5cË8ûš&?Pº6g0”Pì¶u9þ7Ø»ïŒÚî3›ù$„3›$ÄäŠPa¡°CŽ8sŠläW(ð‚{Ú˜Êôƒ¶ór©GrF{V6x½m©Ë CÈŠÒù2¿Üß/o+<¸õöà Ý;uy¼´93³i XìšWÕMÄ8ÑÉm!½— ´g"“Žü|+EÀVoc Û…°ë`^á,ÛVCB¯1Ó­Ï+Š~>Y³ ^6Ç3 ¶£ính:,o™wPžr‹ 쯔ùTR §/©÷Ìv'·˜Ü}9äºc¹þ±Ö=#ëmyéþëþ—7Íú,]Xœæñ²ušj<5a¨•%ï;̧Zf Ÿ#©2Leã›sâ=˜êÅuð"ñŠ HGsGRõyÏ¥-§’u‚DK±Ï9K9Ö Zìvîq÷º'- ‡z©fU•E+f‚‡iH)ÆÎ¡Gy\pGµ[MrU:q5 °`*âº00s;U¬àÕ˜»Èå…‹MŒQ2£Ï ÆÓÚn+|RMŸãˆ6ÜD–Kl±adZø¼äÔ,½ŒÓ6ŽV)dⵕ^$»$¸™¶Œ$,Œ",CË“,]¤ê~@ûel‹s<ŸÔ|ß$E˜g—%¢ vy"y‘(6§,«l•N¢÷%lxttkB»XÑ;Ñ÷Jê†XÜ¡†ë¢ùoógÊûLe墛 ðƒ…æs;Ùøã³˜ÔLøu¦un}Ö–•"y‹ ¸Ü)GKÜ[ÀNh¹Á­]Uó³x.Çj¢Ó©±c“o»GÉUþcz×äÊ÷äÿåNw·ß?¨õBû¶Ý¶õïüûÖSÿ {û ìà ^^ܠߪ#}”ùePÔàð9¥ ÷ꦎû„÷$ÐL¢b„l½ó9g ·U½£!Ý,‰b¡š*œ]Ž£¨˜wwÔO0”ÜWÌŸz·>j„ˆ®<‚ƒ]õ˜ãJïêÿ5Ý—8ج[|ƒ í­˜¸é8c í¨z†\²AVo«zøMæý| »{}½®YÂD ®0b‚1"QkÔl10ˆ¶.2þ°3>ë×áÄɧùÇë™qÝE'‡^z÷fºOP{-šj8›Qéàõ6¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šh+ýúvu~V˜ÿÆ7:hýúvu~V˜ÿÆ7:jtë\5~~ß~kýÍ]­{­„Õùû}ù¯÷5vªí‹˜ ‰æ°öæ@öÎñ[ÇÔ„N}dþ¡”Ĭ†bQêu’À WpF­XíxU‹4ÛµvÑ Y'1änïBgŒ ²•Pô{œt(YMVw)P6¸½Ì&?âݯŸèo•L}E'" ØUKPÂD¨õ•m©Ñ¸ü ΂1ð"ÿpuB°–T7jR½QÝ9¼üæíåœÊaÌPõ†:­!W”T\á~ISÂ¥«½Æ˜®µ«™ÔEö?ÑN¨}5< žÄàá4Ý1ýY™ÁVÜúëH[¶›*= ³š€Ï•?)„ñC¨XøÕÓyDÕæ-òqbU“5RïÆTÃ~Õ—3Ï!²Å‚¢lpÛ¾•i b{ó¤S[2ÌíÊ‚çŒ×Šî’YIZòÇ4v¦bãw.£|âJ„Xº’Üï1çf $“²¨r(0p ‚Ä¢œŒ<Ý«aÕœZK´·KÅ\XíZ‘²Af’SØÅ 8ኚÓ\CË· Ù9gŠ ¬œcÙ¤7ûíê¬`1t<ÛârÚâgȺ”ôòöê_pÝëÏ)8yØEL(°¡ªdÅ!®^×ôvõéu3S—×»¹Ÿ1÷®oa¿Ê‰¹dpXå»Ì4Q·æ‚ aê® ¡ƒƒk§®ý°…]司ØÍÂ`¶¾†¥*±-&ÉZ»´Ýhz@D.¦¡ïs.Öß6±ó—ãÅÛNOjŒËÈnÙ¦Hµ-f¶¨b匫ك‘,záy»Ô³nå]Dg,òÒ}ŒÊ½­ÍáÝŽNs{ÏìƒSòŽÜS,ð÷uåÌ‚™rHlNHZœ<“÷ˆâ«­¨ì†ˆÙ%õ”|1êxo‡§ÕO`oBâ&Rp^x …Ÿ´ÕD—‡ù¦ÍÎty]•eø C‘ØWŽ˜%5€ÜpP¢qð弆½›*·Ïf\:^@j;3=AR‰pÜ,Òg—Ç¢’Џ1²•ØT<íJ•knj%Ïå×t~NŸu¹â×A(ç>_8}ìèkë„˱ó(oޙɾ’gqqÄ¿`Úß‘u*Úæ!°zÊo¥UÂ= é¨'}fÿ3ÀìËÈœÏIaéc--F£¶D•ca»Sm$m=ÊÆŒž2xÊØÛkÀ¼I_Íc”H¯µ¨k‰Qˆ‡“Âê|Êl—~0²¥~ùTÞV&o9#2S Fòm’ 6Èʦ¥“ö%‡u‰£±ËÒƒÛhFfí ‹Çá‡`Vc¦ªÊ¢z™¢~èÓ?ö¬‰*±ç!N0_Žà”U ÚÅ~à©CwŠh¤Ù‰XušìKu#²è2I ›äz Y½½U]m~WæÑœþpéŸ]ÓP.9=æ!æ-ŠžÕYÕ ð÷2f*¶öw™”«è•ü]ño¡[­ú+ØÑšq†Ã‚õðJ +èâT@ „é¨ Á~d9ßþ¡"ÿûÇFO˨o/UÆ¢8瑸L¶“S}þÄgäÝë5xÖêø„Â6Á9 MD¿â¡‡~CdºrM€¿,Ss ÈŒ«Â^g)Ì¢½Å‘÷PW+'“1•ŽÁ*ì¸ÆÜ‘Çó2Å+/{„8¹W”Cób8Â7—«{»öúÔÂŽ©vy{3ˆi‚|·m]¦´Õn00²Õ3qÉ7Ú!ØéoŽ9»€°#©¦€Ïeð;Ud˜Ó‹àǼVÌB".°Cê3àM±».á €yᥬ+Àßc t¼öÈúši i¦šši i¦šši i¦šši i¦š Ä¿~_•¦?ñΚ?~_•¦?ñΚ:× _Ÿ·ßšÿsWj#Ü®í7±ÖJ­ßù…ˆÎvõèóЫžÛÁÐð!¬6SÁ2ÂØ#MH÷ŠOxÊ’`qÂ@‚B#úËnàC'£—6¯ÏÛï͹«µÉÎ\šÆìséÏx<ƒH"zÇÖ:G¼­p5‡Ut÷¥úÿNuµý®z®RúǦy¯LõŠ¿;ì=B'¶¡C–Byd ÀÌð`ú¤ÁßhO>óV+ëcc[VÙž_ÕKŽüc¿ˆJGmIÌÎ ÉíHXœs†oª¡™‘ÚñG¦ðà«­Õfüšñ|éNèVL>ȱ٠ìú$æOTÑeÓ‡6y@K½]á¹~—$£ ‰WKGKWʘnùÕÅ.É Ü[%‘hÏ4”Ùê*¨n%d»L£²&CVÆ`‰oÏvÒÁ2¸!QCÚ·âÉ£©³­+²¶ Ûºn ä©Urö%nm=“rîS±qЇœM‹tÚ]4ퟹÆkïKȵSÛrîEðSa^9J6!WŠq «’`kêH“¨ç]U˜°ãjÊŽR(8Kd€ û{)Ù‰lÞZó–ãl8#2œî7â–‡l0'…À`\'iÐ"­yV"»à £“¶* 1ÃÞ-ç¯ÝÞÊn°ƒfjÙgÒ=Ç`„/û€q@²ëbÊN¶d•ù¾—_úìøHpIä'z7¾¸òRý:Ÿ-½÷¤1/VØdÃ\(®Î7ׇös´x šÊ‡t1+ÝKX÷¶Ê4P¸Èеá ?yÃer$ ¿Jµ#$±“mc.ÞFö¸„Ã’Ú  ÍýeS‘™¼¶Pe;¿ý‘8¶°ÆA¶ 節iZ•D{!›õájòÎ`ñ–í QtiÔpcðT×­”±&XBáš¶q†S1ÔL†¢ðÔzxñpYBp{鳨­½ f}¥§¥ÞUÙSXùÛþJÖºutŸe.$°â§,„ ø•ȰÃ~5œ%Rq‚5N/0£'ƒq—zNìˆ(b‘êÑÙý67çîøÂ¬Ó“lk[*²ÐóZC…ʈ™{ƒ ¹Eãv9üŸýlï´ù8}êû!ÕD€sº«ÞÿÖ{•Ý_HZÑúç¡ú來é†ôÏg×ú›ï7=´‹.«ge3DÁj/ýG§”'—¾‘k:ŠÛÑŠgÚQÚz]å]•5‘¿ä­k§WIöRâHÙÛ^³VÂÆ`k‚f@ã ©Õ°½,¡¨3cô=VÍé¯A‹ØOx_Òr#Ü”tôŸªßÙ±¶ò‘7x7¸ƒ[œ¨q}å?˜<ÆEƒNæ?2J<{©uÕF,§¨€?†ø(ÔÊ-ʱh–”·”¶‘* ¬£œY0†ïI)`ųß“p)iƒ¨ù5âúâ@RŸd^RÐeš°Ug”U™^˧qÏzO]’[ªÚ¥GÂêc­5(ÙÚñon´5 #ØÝk‹T²6%§MKUòqÇIxé“8êàsfOGÊÊ0A–+‡$òí˜í¥QÝÙš&€Éøª*ÇhÔ¬²–p½Nøu¤ ¢Ò«ØÌ(æÂ# Äì<^ÅÏvj¢˜“²+)òR㤜H.ÊïqmihW¡•a#4ÔÃàëÁÏkºMù©uhNË%²guh\Ý6;¼à©—WÔÚh#¨Û–B ðÏ9Ï­ŒõdùíîËbÁ¶aF µRâTHè6:„Xv¨œ0à0ž¨y‰Á8šðæªa˜åWŠoŽ;A›'ÉoŠÉëŸH8é“«ä·ì×YÌí·º‡¯zǤz§–îÿ\zøW¬û«ç=þcËu?ø]¼Í[3:»· †oÎ/ÖGYBWÑ,‘O)Õ âïBŸ?¦Îüü_¹òWÔþv'¨Àæv~ýDÍ[™ž.X!l5_K÷<ˆ²†ÜÍq×[ס]x/_>Eà‡WÑÇ‘r/Ô0kº‚«czƧÍÄÚãÞá!Å>[Á˜¨)w(3yÎ!±Žà£-üŒµ…T¦WmÚ‘[nÅYÇHÑ&=ão×ãQ7¬¸®ÛË Á@àÒüƒd{sUƒò{IÀvn0²0²0íÙ‡§X))í‘#¦À.:2‰M †Å ëVCQȯ,‹Î·ï 8*šwc[#‚¢‚Ò©A+¦ ÙKN°†;5lœ ¹c·X! µàç§u 㲄2‹Õí`ÑTúÉA4úº:¿T¼´­¦®óÓ¶<í­ŒèÞÖ\¸û;Ç”œºT%¼º ¡”´÷-9d+ ÔHm‰7b\p FÏ’BÈk‰ÍÝ­ ™ב„«l«d†Ê²I¿:dªÙ•{›ñ»ëM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Õk¹m#OÌ©çÑʄ걓–µ9ôßKÈÜn¯„¬ØCxYÄ›Zc…tKúeculn5Þ´n³ƒ$Á¸l¼L‰0*x7áYE«óöûó_îjíFEò¼Àì¬ap78õGd×Ü£-¸g–±’L#³ hjò‘æ!¢@ÅvHË£³ZBð]ðÔ°,‰`WƒO¼¬ €Šú¾Ê…—Ê¤ÒØ+˜·"ÄÖ„#ás«¥¸YSа(U÷ÖÁ™N¾³´ž6p6o=¦8&9wVD¶H²c@§½MƒÍMZi”¯˜¶(t ëOº¡Î~Ÿ$ÍËád£Jƒ¹Øê‰SbJ¾cÏ‘‹¢òýØû˱9g”{êáñ[%¥‘'68¬€x‚»Ÿ‰¶@‰:17FËÅݱëø HQ½¡F¤‰Qöêϯªö÷%2ᘒY’M¶2ß¶ñ/¹¶¼›ƒ›ò¼ÀæJÐ;Ǫ2•¦@äY&Z´hí‹XÛóìò,¿z»p‘¦2WàcÂ^¶¼¶Y·O"ÒøB“„nÀ„[b«hl¤–ªØ#8Û.¹šcî(„½i;sÙUÍ6ƒ±iÞØ­@2W8ÝS%ÛªòQÀµÆòYxòÃw¯*"ˆð ËZϾ ¿&¦$¨q¶ËçNf2rùS¸"4Ùn«9„dr3žÆF_Ï_V‡c‰kB~ê|²¢yŽÂz´F´í 8†ê, xq ø$®­(wwÀŸ :•“m"¹kT© QZÉ"°!ÇeÀÌz˜¤ö’qëÅ܆!+ÍkMryÄwb0B3SI^÷ñÛË#{™‡+5qMC_+ZksîNAT5e¡Û|Á[KÆòíKtÁáZcU5p’l¥8‰o’8äMï ;z#íl’ÇÆ9÷s³A½ßgyöG5Ä%D=TçgúO\™Н/=×=¯ü<9èⵞWð=·‘í‡xâ˜f9ÐÙlëmüdîd º„ª·¢{Î+ %•ø¢òÁ'R @‰Yþ.¥¿ôeçh=*Ãsr_Bý-+ÙDížI’ñ£Å:´,íÌ™5ÉðTBÀ¼‘¶s^[/)k6SÌ8¤KðZ2W=•†J»­Î\ÝXYžüÉlç²f嵤{ïºir’WUX㚢íNÆ%£;$Üñ‡IhżCÚo%궬‚w¦’S›Å’? …“x3É×–ÐY ñXž0ÑŽÚä]NW‚E¨>mÁ\½ª'DzÛ*Y†ìðˆ-¨í¤V m•­ÁhÇÖÐʪ£ÛÚµ*Ò¦Óù8ðËàßÿ[ß(çÒWþù¿>|ÿöóè«ÿ#h œ›™–nPã¡]Qíá«.—îƒí¹PÖ·AÑ2,·k®äð­2§ĨÙ}gm_RXV±OìÒKax-JIÃ)‰o9w[f劣9Æo(Kèr-¯Rµ7†Þlâþöõ-ℙѷŒ„7HØ8œWᤑ×Õ¢Tü["UÒºzL‰;ÅdÃ~W˜ÉSºxõFR´È‹$ËV±k~}žE—ïWn4ÆJü xKÖ×–Ñë6éäCZ_RpØ‹lUm ”’Õ[tZSÀj‘ é:23ƒi|룃3ÖIõ¯É‹ŽÇ?¼)a±Î%ñlìÎ,:( ¾ñª®¦¢ÚŸµGGO]+Ë3!÷±4ù¨0¬‹ÊŒJuç×5(öQ¤/[ƒj·nq‰dDËj›àÙDb”·ŽÌe:~‘XW–š@ÃÁ˜BäÄsëâˆpqê‹'3 –ßt)–·¤?y™6á¦Û÷_S->¿jùYFÿ‹zÏsĬå7Ëþ©ÛÆhè/4 {v§eµ[rÓu™™Õ"cAJ Înß1ì›ð•àc5‹€:“ºðÀʨ¶5cÔUõä$Q­C®œ¾_szeaÃ!(òPo€´ 'ÅÄ•SÏNÅyBL¯@d‡ØK´ºV]ZK&"£ŠÖ¸d0‡öb3˜Ä÷âçLVÄÐkH{¸¦=ä}îº7üÃvCÝǸ=BUô1×ÍèÞ“õΈùñøo¨zkª¿øo®zGü†·~¦šhi¦¦šhi¦¦šhi¦¦šhi¦‚±/ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚŒ:þf8›|HÏ ™‘l»DËLÕ"Δ¢ÁÜàp ‰6sø+Mg+ñØ´BMå è»’v«o&ìï@Ÿ[kzM]|É2xÕùû}ù¯÷5vªíÊ g-n‰9²JC;qÑl!·Îƒ;£ÙQ·qq–í$–IÃ=w¹2Ú Xn`cõ]}ý^í<8ÃÛá¶sâOeeºM6=´ZªZ, Íc†'Ìëç§а‚Æ9á§ZÛú`= òb‹ŸI¢ƒiyiétus§zu5m¬ßaå« Ë—»³ssóKI…*”q- °ö§?+eQ˜… ÆÄ©ñëa»LŒ‡(D¨ödIÛܶ£+¼¥1¡Ã"Öðrº®$©›0Ìôô‘ÞÂçF¢ÈŒiãJçpÇ Öà. øð7‘{.€i¶lÓö%D¹‘øò–Žýå@!…Ü4òxíÔôp7‹ ·ñÄSrÉ aÉ2ž:&É’ÓŒ˜÷C.íµpóI„$ ÄØÞ©ñª:6(KKW.ò]],1"mÙQ÷¶MW»ÖËS-›åýõàÕˆ]d˜lÔlxÈ4†Œ´@¶Ž¤˜P¬fÚðÙ0Ýôö´d#וR%ÕÝQÝUË‹eSm[*L ċ#z>öÞçgWs¥åÃ<1pÏî8P7 ®oÌ_Ë5 Î}­Í/ 6ËÜù6 ä,ɸ/lm`U Æ(°!Y^7y*¹Éþ‘z;˳êL/ md°rIg¡£µ;qæ’Y’…å4Õ|"‡<¥r-O› ¼ãÌ'¦3/Ë<ÝñÊ36Ôm=I¶ÀAµS lvQ /Ôô{îp„•Í¾àŽøØ¬zøRš6ý˜÷}r· É P¨cåÑqÅÞCdÙÁžQ°@Ë/Ï,¨qó¼ó#^‰ãªÈ]›dÝN§Ù¦ž¢»Ð¬Ö ui­Fä ïðÝÜâ¹mcÙÉÒÝ‘“Ô{ÅêÊ=Ò´˜ méQ3 eM:;T‰ÄZ^V2æÔÛŒœ[Ð’S’ VYÔÄZ3Ãk"£$Ãf£cÆA¤4e¢´u$Â…c6Ð/†É†ï Gµ£!¼ª‘.®êŽê®\[*›jÙR`XÀ“d9Ñ÷¶÷8«áÈÿ&±¹‚„ê\’È4‚Ã/Q.üŸ™Ì#a®<ÉŠçßÉÛv‹€ØŽÿc¹þ±Ö)åï焈ÄT†úPÂæÝ ? yâÞ ye~,cEfDao,r~VFY,|:µÂnáÔÃð¥¬dÍŠ+» #1vúGÂARÀªòt¦™ \²¬¬ 骗*òS13ûîsx-§zFó.B9odmJjìß0ÅzÚ …yAõoŽÄHÔ^TVÓžWŒÚŠw:ÑŸŒ©»É âa\g)r½aƒ¯TÕ†P»í€œý yf³39ŽSéùŽ˜hD7\Vعȫz}ª0sŠëÂ>Êçó>®Òµy%‹œ+lR]Z«€8,VÓæ9†IOz¾æ¹:kÜ“±¾óßôñ«sÛ/y/Nì·Íðk^³ë?Uô}Õ};íÿÅž…ì·½žï0ÉD-SúØ…´þV8ØùGEw¸Í6Ñ–¬Hw'€"^7†ô~¸GlL/] {ÕKj ïHƒmÿ±ÃÅK÷õå®.PýÔE¦1äþÒñtqÊš¸]ãïfvçµ´dïRž.;ï²E¾Ã—Ú¹våh?"BShgB*)Ûã«›«Ê»ÙS;Ò¨IQštØÈ§l4×-pœtV¡§ÁÉ÷h¤ûVÁ§-|•lÜG­ÚhÁ«g^Õœ(†oª öqìl.MšB¥s@±ÅN¶Y1ÃkeóuqsÔkÆ @› ‡Ó­j=t0â†0½Ï¤ÞÁ«¼«õJ;H3½:涺Ö·òÖ0bKÚÞ·›ê¬¢ÎFKêû–¶7äÎX»ñ“K¹!f,ì‡ {_cÓ%ã•õ«añÖ>ávL\ÚxX{¾(/ír–ý_qµ†ûÂ#S"«˜«zªê8˜B¯%30o¾ç7òÚw¤o2ä#™öFÔ¦®ÉÐó W­ ÈW”VøìD‰ÝEåEa­9àUxͨ§s­øÁz›¼¾& h骉”dY/ŒÄG^sL¼Bqã':-äRdÝ"E°ÞÇE˜ÁL¤ ¼Ó˜D^ Ó%dVÀ¥fÕ/Y~ÄCq_¸Ä—d8=0œœ^SÝXèæ­"®È±c´fad:³É7¨ÞP&ÎD.ê/íÔàyYEL^åVG.\¥³0½…[?zô7„ôÌXú`KNši i¦šši i¦šši i¦š Ä¿~_•¦?ñΚ?~_•¦?ñΚ:× _Ÿ·ßšÿsWj>ɹy` ©! ‘– áéiymå±1YY63%¯‰ ‰/§Èµ¼!!¼µ —iuyui.U•µµ”©3ìgÉ‘2déÛ›œ]‚ño)ÅÚEDÌõàíÜDó´÷¦£U°üÈíDÈÞj¾ÂÎ<¸þb$‰[×gƒÚÆßÙßÛûí­Þ.-MßÔOÆ¥/Ö8wÛ:£6ý…·ì>ìDbI½>ŽÕ²V4-hφF옋á#YãÃma¾ ÖˆõÂZ‹94l‘.!CꘑàñqQ‘G±«ññ‹ Ê1$HFǵ±c'ÚË—#{syy`Q ñn áè‘x•åI0¡XÎ3%¨II(gǵ£!¼ª ‰iKyKi-•Mµl¨Óë§Æ2™;{œ;£¿¨ŸJ_¬pï¶tïê'ãR—ë;í3¶c¦cvÌu÷>F$šÄ‹³&ŠuXÉ/PÞq)ŠÏ—ÂF$ŠòN)ôv¼D+»Â*‹@«Î+A‘».+a©U“ügQÌñ‘æ*`nG#MbEÙ“E:¬d—¨o8‰”ÅgËá#Ey'ú;^"ÝáE Uç ÈÝ—°ÔªÉþ3ǨæxÈó07#ü;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ^P®2ãp/jº'݉ëžÈtª  {³}ÏóÊíW¤PDíçpüܾ¹éGêß5#×ýCÛî}÷¹^ŒIT³Ãj“ªÊÁmá©3œR½|%mºHÉÁTÅ!gÑÆ¨Û«>¼>«ÛÛ­5¶+‹m<¦ß;Éãððíø|;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ^U2ãpµQåÎ>$(Úë&}5 ¢©Ž¶ Þ\/+«è#Ä/^H.&C³cB>¿¼/S%ï,#Üc }¥}Îñg¦:#¶]9îø¥ôÛw'¼½¾ô~‘ôþˆîÿýUé?/è=Éÿù§ü)­™ßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΙÛ1Ó1»f:åþ`x\IžKÕúÕ¹FŽ2Z`&y@´¯žZI‘‹ÕéÈ‘Ýzr¥“\Ï´IÑÝZno˜ SÝœîOÙÝ£»¡§ª(:ï­j^þ¢~5)~±Ã¾ÙÓ¿¨ŸJ_¬pï¶tÌnÙŽ™Û1ÖÝÃüJÈH&Oœ\ÇGi}eašÒ¶êIhÉ$¯…>ÊÖôÃ!›«H”q-.®,£TìJÛ±>ÚÊfÔ~ånnç ÔbK Fà†¾SªÇh…eäbjÑFêøI’7^I •T24fUUq/"UÝ\Vƶ؋·?bµ”=©1çÊÛÝøwõñ©KõŽöÎýDüjRýc‡}³¦cvÌtÌnÙŽ²;Õ’Ø¤Ì ŽL¾#aªú£¶—¢t6ækޏªÙ¢5è2‹/:¾Ž¼>«ÛÛ­5¶+‹m<¦ß;Éãððíø|;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇXwâVàÙ¨næ.c¦àƒ&`2ÅãI-8†Ï†ÒP+ê“Æ´|C>5e4j*ºšªÕ…MäYð`VWÃSm½¼à™’5$!22N« KËU–Ȳ²eð•ñ!2Jú|‹[Äé å­D»K¥eÕ¤¹VVËë)RD¬gÉ‘2eFôíÍÎ/‡Q?”¿XáßléßÔOÆ¥/Ö8wÛ:f7lÇLÆí˜ëÊ6Æ\nf-„SL||H0 ÿ@è5Q²  ­lÒ”2ÅEúDö‚xÀßMŒOœ9AèÕp½†lºzï-_'z?qz²[™±É—Ál5_TvÀòôN†ÜÍq×[4F½QaEà‡WÑÇLQÓÓ«º‚«cfºÛÍÄÚàÙáÇ;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ^UŽ2ãu¸cqm‰ EãŒâs5ºb¨šÔdÚZÓ^Ù0Xâòh7hÎ,o®gA´¾—kEMc"~亸;ÛÂád¶NS.Kà…ZðsÔzx p'BEêö³¯m½\f]_ª^ZY\Øù;vÖÆuŒŸk.\íÌs¿¨ŸJ_¬pï¶tïê'ãR—ë;í3¶c¦cvÌu¶´Ö¥ïê'ãR—ë;í;ú‰øÔ¥úÇûgLÆí˜é˜Ý³m­5©{ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ[kMj^þ¢~5)~±Ã¾ÙÓ¿¨ŸJ_¬pï¶tÌnÙŽ™Û1ÖÚÓZ—¿¨ŸJ_¬pï¶tïê'ãR—ë;í3¶c¦cvÌu¶´Ö¥ïê'ãR—ë;í;ú‰øÔ¥úÇûgLÆí˜é˜Ý³m­5©{ú‰øÔ¥úÇûg^½yNQkˆež¼"»íü•=¨Õ½¬Ï-zdŸ+__g"\/>ü­ÿe³Çì£looî}îÖ× 1»f:f7lÇUÌ~ý;:¿+Lã4~ý;:¿+Lã5:u´YDD n¢A½¹‡kÓ½”h–scÇÛûú˜œ~Ïggƒoƒï÷8ø÷8¾÷‡Ãï¸ø¸¸¼ãÅÅããã‚õq_ã9ë«/æuµ~~ß~kýÍ]¨ßxóÆìzÊüXÃf97oå·Yt³º‹B#Ópü:_¹^ºiHOAÞr}¹Ë„‡£ ’w“Sn!]ì, oÂ…ÿêâ¿Ær×V_ÌéÕÅŒä?®¬¿™Ö=¦ƒ!êâ¿Ær×V_ÌéÕÅŒä?®¬¿™×62élœÉ¬JÅ2jC‰Ì<ÊïÏl.h«heQ{¼/ëXæ½yc`KWyWê”v‘â‹ôðéGµàÞØ¶ôHœ<·:›Aõq_ã9ë«/ætêâ¿Ær×V_ÌëÓAõq_ã9ë«/ætêâ¿Ær×V_Ìê92O˜ŠŸ xÅT®È¼É¦ ¹½j/ÆD” r²ÛÕô7A᱕Òõ0¬ª`Rm‡”´*÷…çÞÑ[^WA•(†ÔÄ\´ Ì5µÙðºñÞœ¼ 8²\1Ó™±µQ¹Öfp¨FŒàÓØÈ±‰µÔkÀ6 õåíTáSZ>-éÑo6îi*C±ú¸¯ñœ‡õÕ—ó:uq_ã9ë«/æui Èz¸¯ñœ‡õÕ—ó:uq_ã9ë«/æui Èz¸¯ñœ‡õÕ—ó:uq_ã9ë«/æuÍà™˜f9ß8øeëmüdíw{Äzxª·¢{Î+0Ùkø~ÞŽÁ'R @—gþº¿ôeä¯ý*Ãsn'ïÐd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù|÷Š ¤mnìo‘^ïìoíñìïlï[ØnmomnpøðnmníñÈâàÜÛÜàâñàãàãðñáãáññáâðñðññð×…¦‚±/ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚ¦… >tó(DóEÊ”8õh†e4éªpW™ØüsB§åÂϾ´Ä2d˜T<‹ìrÐd ÅAhqš”–«|‘ËünBöÂåÚ ™ /ÄõƒaÈpZ1ÃqÒØw7…<œ±à¯Ø¼·½~š 5á€ôÎÏÜëc†DH¼5´¥£ç·ˆ™´1&$ˆÂ\§#„?Øà¶€ÀVÞ ¦.()äÈ$ –!ÁC–¯†ƒsƒ©Ö¡;,Ùë ÎÉw…øË÷?4m÷Fn^1 yJwÐØ°Ýöß,1E;µ¡&އwZgÁ…Ê`^oñ(žl¢²ý‹]«vëq; Á±6{வ„ÓvµòU§Ýw½í){vØ'Ÿn XX'Æùz¹ZUÂV.êë&m«×QhöÆÖû$„uA±)¨'ìSà {1‡±õËÚŽhc<Œt]äÓ¥YR<™Å<"&Oа¬+29h[#!˜Ãmg"¥¦Éâ¶.Ì¢câ6\Ai4‹[ eX¤#5U|ùòbDì–æ›OòuXíT7ï1¬‡q]‹øŽÏļACœÂIlxÚÇT•°Ù`“Zl@K5¥ÎDŒ‹m°—F4´”ŽŠ‘ûùôcT“±¦‚º„í Î_\Òy‰åIÁÆ=(9–„a%v:eí­º…pÑ],ØHi‹ƒÆ‘jè­@¿wư…dã‚H\¡®Wï5®j+üxÆ,"Ë"2Éù¼¥3mó†~<¬9ú(h­ÚŽŒh“¾sËSat ÚFe>;'W¨.ì¤;‚¥j̾ÜkZ˜¯êw©íîÛ5×xÓAQ"eæòï–) TVG^d® si¶3ÎÌvG6i%§.;²‰y’œÅñJó& Ýî†Á´™va‡†DƒÖbWÍjÝ‹»jg-¬ÞtÌýÙ|øýÝÿ÷^w¿ ýÄz{èc¯;þ¬÷â÷qõOÂý÷†öž‡Ñ廪ºË°ò½k«¼i ¡§0ĺõXI÷A&@U×”øUyÊpËŠø Îl  ü‰ŸŽ¯·ˆUå±$ûHÙæ´O¯ì™ù6T×±¼ú‹ „L; ›—›¿?…D™|Óù«2 'hñ<¼’–± ´KñÛ’¹A ”±?(ü´‰Œ0Òµõäìš½—Lx2›=$b\\±îê*i$+𤵗\ÓAOg±¸ÌºPã.J„´Î0†©§ŠöÛ‰xÛ¥\5Eœ¾ò^>P:–¤0D¤K/aÇ¿ wº"XQ†¹ÈêŶ-3á¡’ à3Sß‚¾9¿ãø‘Å^Qc’C ²o$‹¶N ›&nP«Ç!œ±W ÐdŸiJéØÜFUn°;WW0r©mD­QÆÝ´—EmrÎeâµVi Ë1ЙÄïL°=qý²€0PÌÈ3r4È÷ ‹R’+ó1ø C¤µ&ª…Æ%ms$ü¼dŒ8ó•Â}ðÞAs 8à¼âeó1iì>¨6É«ÆéI±f±LZÕ/KW2o(P;Õ†–×õUÆ;ÓÙ™II½rL´ëà  ££©©B627C=UðõTx•t´tµq"ÖÔÔÖźhðáÇÙ³··Ãîhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦‚±/ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚŠŒæ ›,œäQAèe9Ö>”zý©WS†Qß ¸=[x$RŽ—¸·€Œx=¿®²,µèÿ3su½‚ŠDÉWjüý¾ü×ûš»TÐG¢sO[ܘýˆ·†ï">f<ÑQPJ’Üu­t–Tl£K1=åÀ’•ŸyŽ‹ÌµR€C+½ƒ<°J™$åÈV}ˆŸ‰!? yÜÍÔù‘|ÈSÑaQ…-9r^¾I7©†ïçØÒ2÷\’iË„ã­èÑåês![bi„äÃe*¤VÛ@â…¿7°‚rk™‹bç*ã Ò ÿ×úñª×+[ô¥ B¢Ž®9¢¿ž07Ócà‘ßúͤ/G¡›âÇËWÉÙ‘ÇOfG+—⛹ñbª1pg‰!Éš‰Ê>ï )1|n» »°LwW.­’çèH6íõÄÀw©•tàŸýef€¢|×Pú€ÔÃ`¾Àªó¥k}sØÀ¸¸„<ºYVü¶tŽW*û7½Þ~K*Õ”®"‰çÇÓ?½¡)TUõÙÎ@ë˜þ¨Gd&GiÒ¿6®. z¿GÈÖq“‹)›æ|¦r…j¾Êwvbƒ½èBíN1Äò½½“Q šSˆ|޹Çü¢e’,ïv†ÔËòšëɵdÎuZüŠ ª6ø<‰ÛØKÌYm˜«l¹rû …Òƒ2öƒî¯vèK–Çkd}¡W¼G\ú0ÀÀÀA8Á?Qû?T!¡¥¡ƒëom_'ÌGêa|šÆã€ËÖ8VA¤ ׂÁÌÒcÁv¸`âÚ=©å† éEMüº:€‹Å[>›x²Âtz«UÁåwþb;5ÕIÃL‹ÞÂÌœ‹M‡­05BëîƒÉs)‘‚¶ƒÄŒ^ð.ímÒ«e†ú7 hö¸+é&.Ì®ÒÌYê®:ÕaA…ýP=uÞnfLºÅoiÑ^rÌ1I§ç¥››ËâK¶+Dþ:t–ñ®7£‡¼†iíè ¶{&53¤n2̼F7Bä¡95Ìűs•qiëýxÕ k•­‚zR†!QGWÑ_Ï鱉ðHïýfÒ£Ð͉qcå«äìÈã÷O4–@Î2C8•ŽÑ ËÉ#6Ej&“$n¼’ ÛYƒÓ¯mîªâ^D«º§²“S¿+n~Ä jÙ›±øcÏ‹¹»_ eF>1»š‹UŸœá^>ö·ßZ·Š£‘"ľBב‰{¬&†h1ËÔN1§Ö¨ã™u4µ³ˆñqà*™÷ûâJrþŠäÅLö‚[švlDåà’bmæ5Õãkm½…+ Ê j–ÆÎú ʹY†¬ê˨ðâ®`’X ƒZ¿Œ½½¸ðcx(Êmû5B à4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Ö½ÖÂjüý¾ü×ûš»Ps˃™ï¾.HóÅ6ôô(L&š‚|QçV§z¶9®•™+p‹/ Nþm"yœ-–ˆ³šeðéÉøÛ&ŒÉ–¸ÛÛÇHëJ:ÒCÁ²‘*­ëÓbXTû=õ ˜æo-² «räíøÆ)z/¼E[xÕI²TýWCXF Ôé¦ð0Kƒ¹•÷ÑÔþDov/·øÅWPOU>Èvöš„<Ãç®åÓ”Ù…‚æ –:û»ïK p.ÛÁ~UfêN’‚uvÒe§ºÃV27ŒTç•üPC<¯ñ»Ò8”Wõû]ô…ÏÌAÉÖÃ)vQ›5Ôôt…¼Tf#æì˜0É”`8?VÚVUÛŒÞÑ´•3¶£fë²h$»ô `["ì-5yë̽Žñx\i‹8¢•o¤Ú—¹…™"-ŵá˜Õ•Ì ”ªã„]Ї^Tœ Ħ¦#/’ÇtÓUK¡e Ń»Pgàèè´Ža;TŠp]¾kÊÌqy1ó kT3ËY*|ˆ$9ÞÞ””1­§á>/TѰcÅ £Ú€æµ§Ÿ[¼¼VeÄÀaVH„þÇÆO†U»ƒz²Œpà=š!:¸„¨Ì ’kÁrÁ\1À/˜kƒù|;Û0KJï¼*¬nh·gîÑÞ\WNÂ1“ ±—;£#!xî8ßc¸ o̘ K0ÎG™ãã¹6g¶ Žd~Ê]Õ´Jë2iPo‰‹ˆaAx^Oamƒ´ùŽa’SÞ¯¹®Nš÷$ìo¼÷ý½¦¸…?Ìs ŸL‘…R­ÉÔDììv¦Òjñª(¶xö2û€q·îøå1 PdBØxîȺì©ÉçÞг*æF*lî"vö¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šh+ýúvu~V˜ÿÆ7:hýúvu~V˜ÿÆ7:jtë\5~~ß~kýÍ]ªŸƒ`72TÔü³|ã]û#Œy˜ó&´WU°Ô Yˆ9ø6˜£~Xnx;øâ^#žI”VGð/¬6Ä HתzÞÈX†àøhRÞØ _Ÿ·ßšÿsWk^ê… —9¹8dÖâ‡.=$CüØ;!Ê9q†dÌv"ÿnÕÏU€ÊàÊ“Šk™û±ºPâooöE+¬N…V¡—æwpgíN ñ²!¤íå¾ÚÝãv~\rœö <“JS"2‡™YžA2rîÕV±*\‡ý†@Ѧ{SxE~‹Lx‡ñ ʯ„…‹Í«±~%@Ðôùé ©sGù¤»9tóMJ^‡;ìbd!Æ"”aÎ-d¾Z¬ò1έµ7R°rš‹c$.í(íw•{Ô(“ÆÖÑ ªÆi@« âÞ{a=Ü\ÿ-Ÿ½×Fÿ—Ÿ’ËÝǸ=B+ôÏïiÜÞé?\ë˜ÿ†ú‡¦ºWÿ†úç«ÿÈjStÐE–t]fo&½|/Ëá!Ì?˜ N»Y_š*…4ù"}¼X¶ëhM@H$°€'¡ ”ßB.fïyð uó2%¼9Zfšo—Æ4Õ)–tf¬´?6•ç30|—\{Љ*ë;ÍÚÌ']dK#~È@–ðA Y³~ØÈ•©%Û^ðw…ŠIÃQfÔµ¶š —ežsÉ Î|ä0q¥IóËäº ;δ­Å©-V9Úñ0ëŠ/< ê†*£H<¦²¶Þ Ú3ð½Q1݃”lB¹„Ëqs³9šr•È0ß[Pc'¿—{˺„V·¢{΀ Zþ·¼€NIÔ„ð%Ö„ioýÙyÛÿJ¯ÜÛ—Ç)ºh*]‹XiÍz¿8°w ó $pļÅ~X:þ½LÞª}Ðå¸ëTPm،ƃsæ0¤#†Ö/iWÌ“  ¹£H{ëÀÛñÞå±ùŇžï˜m‹I¼]ÄC‡‰å0R íÝó2©‹Þûq”ž9D§ßa¢Ýþ2ß±oK‰îƒ ­‡Ÿt[Ga7Ó禂°<¢¹r;qˆ“‚2_/;‡7™wS4­9€–š$¡³çØWÑÛc6$UÕÒÞ;*ί©ÇT(˜B@•ò2k÷9>ÚØzÏÚi i¦šši i¦šši i¦šši i¦šši i¦šši i¦š Ä¿~_•¦?ñΚ?~_•¦?ñΚ:× _Ÿ·ßšÿsWjV<Íæ$çξÉe_¹®<âc½µ†Ê>„Fª˜sü‘\Š­úùŽùïmsl"É o2۵ >Ô4EKæuñBîÜJ§Ö§ù«óöûó_îjíAÍV"æÖ"¹òðÛnñdéA˜goýä†IÙ6–½ÊòÑP*‹Öõ;( iÚNòm“Ó3“—pżˆexÄ6¿ˆ£rÎ… V—ç)K+Šó<ò[Èg™‰¿*Æœ\JZ¯dä-Ù%ùr°6ìÒùÎZ¬Þ_ÆÛ™Ã_Gtà¾9⵪OØðK¦‡¼Íîq3Ô•*+È95Šm5Ò¡ÓŽù#F7^I3ÎÔT4†Îq÷]<‚¥cHB~Ôä{~Î>ž`'yU.ÈPi­$¹‚á³' 1C—ÈJåŽêËÖç?DžG;٢˅³ƒ+Ü3¶ôL¨IA_oÂ#y%è‰`ò–]l=êy÷ã´u„7röøû ÛÊÛ“8éÍ>S-˜¬Ë^e÷ˆ›y`¼e¥˜è¤Ûº=Ìp_l•ߎ 2Ëï ÆÅ¶!»œ[´"Ý”îÙ#6àðU†ï,æp¶Ì¶NÛg"ÕàŠ^RÍ,Ü8ÂÂ/O¬ÙT¿‰G,Úò o‡R,šdB\Tc)8²üCvõ%dL1Ó¿ qjŸw>nت®±¬ÆÜÞ —s‹4Ù·OE:Sk/8ƒåï;â÷Í€B¦ñeh¸¹”wr-1¨fL¸ŒÐŸ Æ8q忆ùåÑ–¹Yÿ+)ÇJ‹GÇ%÷÷/ˆ££×l½˜îÖӀрÁ"mE”‚U`(y3sohtµ€IIloUkª²`Cz³ä‹ÉÇd‡ÿË©òEüä<ÿ¼ã·Ñ¯Ð‡þdùùÿ¦º§ÙÏ)%yÞ.<‘*wä*ÅÊÈ1–¸¼¸M Å*˜L\¢ {Ó>_NDÁ½!ÆØEþÌ{aÕHˆd`ÈS‰¶ˆä³¼!MmóŸFl÷*®÷2œtá”é $¦ܪǢ¾ìe{ÏÕäW#­UÆE›cÏÂ΢ŸzáßñÊ Oçj &Æ8¶‚+½Ëùis N+›¸ÆÏÅ‘ÇR¯’–¹ Í‹oCDüs‚3àTì©í"ZU¯*Êç,¬ÈkldÍdì Æ:SË Ý½¹áµyIdÏ/Œqú·Tñð“"Òy ” k>z§ÈéãmYñLž•i‹x÷h/F{hÑ·3¹€ n6a½cz¸¬QˆoÓÙS„Ðâ^]-³ 1†PHpxœw³±ÅƸcÖÐÂ3Y¹Ôv±ëŒngœ/ý”K;ÚâÙá¨¬ê«Ø;<7›w‘néªkÞçÌÌܣȼåLdG0;ÎWŒ»6™=O+èÍ\dCBÀæÒI¸I¶LW•le“zA ሇHp³#Ébï%XÌJˆÔ#̲Kl^O¦£ jr1²´î¡m šg&ÑU˜J¾ž§°ÞHŒ‚Ê :Cy§ÒÔ~-}µr‚Æ÷ ª¥ÕuXœ;›èéÉÜHæÉcyo‹$í pâVL4äp1^GûnÜuÇC8ø®‚…Ó ÀªE£¦‡$Þ-Ç6yƒvÞájïx¤êÊyÈäd˜wÒË.¿ÌŠû´Ÿæ÷Ü„O.š¤k*ßòÝóòhæ‘}pTKÜï¤ïTž'ZFóÈJ¸%ê1W®=Ï/î”ørÙIæ¬|ç£Ë dZýv–§e6%ÏÄ=ë(FÃ7€KãòkNÃ[Jï2ø‰†âlËá"h¬„+H©|=þ\9#Ù‰Šoì->HZ/|º‡yh›QeÉä£1å²øž)BéÔ-¼¨®¨£jD¼Ø¥µ5\[q¤èJ*ƒm襴¢'4†ò‹ÉsùzØÙ!iòpü£½ïéRCÉÝUïÕ=µíW«­hýsÐýr'\õwCzg³‘èM÷›~ØžfY áÌÜñ(:Sæòçp­!‹ÆÁ8~F¹Ïo² UnUEò½ Ürd7¼êܶŽõ]@¤R±¶ß1«JZ+{%… $Bco~f(5CÁ§om…± âà*ÄHSÓìÅðZŒ¶q«îƒmד­/Vibé UùFö@Ú_ø.H@¯èJrDê… vé¨ÎFf”ù¹jÀK[j<´—Ë9}šVY¬3z7J6퟾˨K̶T†ÒÙˆTѲdqn6joEÖp ]G£¥—Wµ÷sˆA¹ã0šª~\†Jl¼f2ùŒQçL€tØöGQO$Ãë¸U•2Y@btl)\6DÄ3åÏ] ð[Lm’C¨! éªÀ¤²Ï4ïssšs§ Óמ6˜)Ž˜–V¼Ä!n`<`ªt¹#u JrF*Á¶ºˆ‹Ä¦¸FLæB¼< g ·—•uˆ˜úº«JžÂ[óÂAÊ[gãË^—×e'šâ“Š6^&•YC±Æª®K³ã‚'%ÞœMaíÚ* )ˆÂEÃж«eÜ1ühøŠ¬Bo4Ô/™óP{cÆ å–Jæ·.¶ž4—ãMЄqo\éX:œð;ªõäq·¸Txƒt·”¬¸›Ñ;Ã6äŠõí¸Aü“‰¢~;¿ù æû *T‘i›eø©x xs¸9ŽŒQ·h4ÒáKe»“lKiox?h:d ˜¹jîŽ.Íi1‰¶°‡‚LtÔ!ð[²s§šN^ã™3½Þ¢ÅÞ^Á¹·90Œe_'mrÏ‘«6YüfQ£ÑE¸º}  ÝGñH1$Š˜™Š2-­ámTÙÞrÍg2?.5·7Öäã:þK³Œ-ÜU3KEVì“ôÆbP®h–¬U…߯œ&=¥¥Éc¼Ž 9SÖúê}Å@?ü¾ÎÀY‹MBFó.sŒ-¹ƒ&¶R¾í¹¨‹ÂÜÔ@Ó—1ÅX”$øÝµC2¯Í,Œ< Š<ïGœF½6Ç2вP2vHå8©”š+µrŒi–Y¿-®@2;Œâ­‡•i Ž8ó¨ì“\˜lÕUá*•Ü\§Bû³Ñ–^^^[«CIªÃ1ü«ÇÄ„xý™ÓÐ)‚ÅzjºˆÞy®|ƒ¡Áé|¾}‘?0^þÑãý=þWŠ×Pø•c#&†­ÆBlGG>Àm 6 žPsËdVÕÏ~É\*¨±ÆÀbÉxå:–œÌ!¼ùÄž[ ^/ªÛ´w’%Ïmg2qû—O2ì”Àl÷w´¬ÝøçÁ)›5÷×9_ËøÀÜl=¼§»ãÈ÷ ;«ÖÉì«´CþË`Haí;°ÇI¾ujÀ „é¨'Ì~rD˜Ts(ÓJã¥KÊ‹Yy”{P[š“×Ê{q±fà:ý+ŽŒ‚,_ê÷¶E³ãŒ\C\\¨P+÷ ðUÒpxͳ¯Î,9°°«†'á•ãæý×Ë8+™2ßtÅî ŽÞÛ6-㧨UŸìYÕŒÞXÕð§§&¾?¸Ø)$©Tqœ>@Bh4×:bVR)óW™@—y-hÚ£™mG¶MK¼>IQ>–îÔP¬d†«srL}›Á"úá{iöCvê$X‹‘ ˪¼°è½M4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4Öl 5¢ÂÒ„¹v¡ÑM²Û“‡ƒsÙoÇ߉µÁÇ¿³Å·ÇÅ"? Ž=ÍÝž-íß¼áàÛßÚññÿŽs4j¬ºÄ&!•Ñt udTÒIaÕîlÖÉØŸr-±?zú‡osbⳋð¬û\|s6|®ü­ÝýЬK÷éÙÕùZcÿÜé£÷éÙÕùZcÿÜé©Ó­pÕùû}ù¯÷5v u­Ë;/˜“òyu[Í)§Y‰YfÓ¹-a&ŽÎ6ÀR’7z.ñÇD›õ€m:­b¬8«%™TŶò_dhˆ7ƒv BÁ³;JŒ¨¾žŽð˜{n©o?€obØR¨š¥œ3*|7’¼òh­Q™™iy–qù„«ƒY2E269âlc%Ϥ¢ž´/ܣܬ²[­Øû&¬ h'›‚¤jkØÓA æ|«ÞÙˆ9eY­ÌQ§’Åù-F´dW%– pdĹŽëAy m"XÝÕåÓ.^ô—A6ñ5A#A{PØ@=)g‡}bòŸ&–E6ÊnáËåžé\PQÄHUІ21¹}"4ÔWW€)FºˆÄ.±.¼sZ²KM¸¨',×›¡+ÀI„ÓAx±É·Ý£äªÿ1½kòe{òò‡§;ÛïŸÔ?ú¡}ÛnÛz÷þ}ë)ÿ…½¿ýŽïÁÞ_n|La>åÿ­¨1“ÞO½â>ïâµ¾ô}ç*-6Zþ·4-'IvHœ¶]ŸøFêÿ¹>ËÉ_úU~æÜHÒ›¦ƒˆrã_ŽÓ-޼Ã{™g@uÏ OaAHïÛ°¿ȺêÁN:J¨Ö paÏTÛ(/ÈC¦Ø¯M:bV-©ð«˜¾‰yh¥£™SG¸Mu¼@Io>êîÔ¬¬˜†×sn4}ëÂÒûëâ‹hôõô£uóíäW Ī£¯è½4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMT›_òÚj[I3‹¦Šq_Á㓵mG_s&ÝÅ ˆ’áoA%Ú¨Û¶3oã½»±C½[{*ºî-nõ–·\×ïDƒÅÇeeÅá$”®Ó†ÄÀÒÛŠLÙÒoLH÷vøl/íåØYÙMãß—¹ã±r|ŠØÐ`û(›yÞš Ä¿~_•¦?ñΚ?~_•¦?ñΚ:Ñ®qËFQ$îSpÃÑÿáP1)3·GÙPUìÿÈð£Loø}¿Žß™“çÈìã3zGŒ_) Æ4º¿ w¾1¾ÿNÇíŸ[í«óöûó_îjíkÝQ¶ý•ûoÙ`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lúôª¼*§íOÇpíìmÊðð¦#ž—𥕻½b?ÿd@­÷Ü9»S¶ö«È+8··£mmoïqÅãߨÝÉôÓ{7òæL}ìßË™V%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖ¸jüý¾ü×ûš»Uå““ÑYÓÍYlçb+1ÅÑŸ\ÍYë;SSÁ°yáŒF6U^do†ÝøÕ_í¢5äº;à°âeÌÙÆ–yªŠy—Å{Öøjüý¾ü×ûš»PáoÊ ÎõYE»¾ìaù›Ì¬ð1ÞˆÒ˜}’ç¡Üo­¨/Vua6 b‚àñ*\{»}=lÎ6²aŸph n… êb×1æ=UsûæNj"rß+åXó^ï_É’"–„’掄˜ÐùÙ¼Œ!}x*MZV¶%²Â$»‹k „ðÈHÖ¬fòƯ†à*âÛb‡z|°bÒñÍ©£ßJÜ׸þÃDD ê±Ð˜O¢AÂz>Å)l¡ÜŒ³3Æã5œnêV>;ŽÃÙí9ŸØÇàœ=‚ªW¡+jk€{‹á›P®§6<ºd·¹eó’ÄWõ G†Ca Æ@3`§ëo¨“ U¶A¿ÔlÔa`À™¡)Yºüâ0D.:FÂúԔꆄª»‚È=š]QãbLKy‹»hY|ôCa‹+7*ùdc¢º†ß“H[Ç<´û˜›ˆ-ÝÝ£}˜÷Ôq‹Ä«kkcÅŸ²7¿:«)–››¶™×(¼nfã.Nc‘ù³¼²ó2Ž9-“—$€r²i£|À:^@œWâµá^„." S¯— !xúÙ~¿à±­¤¼¼¼!±=ùH ÞÎ|—to7²Q/1Ò‘™>špF[9*¨wÂéìÄÈï+Žèö¨«©üEÉ(.èi- Wwȃ`#¨Û›¦mqôŒuÀN,Æó<ƒ(9º\ ¶¦ú;&›´( ¢e@ê@‚O!€nä¨Rø'ªåµlYLß즙™ºƒœHǵfN~'Rôv<žÉyÉ'Ô§ƒ–¢ h†f;!øäÌ<3à)ˆÇ8 ^q/¬I[ÂË…]žÑ5Z¼â~’ö?o|‘xÝøìïÿÝeòEüäÿ»wã·Ñ¯Óþdù‡ÿ¦º÷yPâý õå­ƒLÖ®—–uO* ÒbÊxƒe¸¿]><É–2ƒE„‹ã4ï£ìîU[ ŒÓìÀ—#rŒZ–Ó†-”`çNY\Àòó,!ÔdçŸP2°…_“õY#‰yG‹Ë`g9%õT# c‰tþ#bŒd/ü ‡Í‚] á±R*;ùtcå5óøìÅfó\ …¼¿ÆðžM0îLfÈlAYD—Zä+šH2½{DItO±\( ¶³¼â‘m~¹í!¡È‚ôXUX¿$ZUî Êï­M4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4ÐV%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖ¸jüý¾ü×ûš»\œåɬnÇ>œ÷ƒÈ4‚'¬}c¤{Ê×XuWOz_¯ôç[_Ñúç¡úå/¬zgšôÏX«ó¾ÃÔ"{n±jüý¾ü×ûš»UÊ劲[7rk1æE¯‚ òˆƒ7›âwŽ'CÄg'ã¯×”ØÌr¸³±"A¨¼¨™½\CÆ/·#j… Þ–Þ1÷D*ìjhPŸ=5M¤>Cä^5b s†lŠ5¢4³î‘Êp£Jí—´ŽU9&1 Omká Þ\Ê…~íVOkîïHg 6á1®÷ªDÝÜuž”Îko‡±®s¨Â—bñ•iËý§‚´¯M¡e€Q&@©ò¹ŒÁ V»‚G¶Ä ^$¤M‰³¼ÉIì¨7™³ÃgO«Úa2‚ÝÝÍ[w'³]ÁîÿDw7µ]YCÜžÛz÷J÷¡¼ÿSôGSÿ‡:³Òý׿ùÿPÿ—ÖoªÎåuߌ™ß•cÃÍ~à&>çS%2 AøÇIbÎãóu¢)‘§–Ò®X EÿòÕ1ë”1êa(l¤ÒA&&¿8“pSk˳‹™¥UuwŽnz,¾>A”ÜàÈoFñ±³kºÉ c‹Ô§D¶I„‹(ǯ/ìw­é1Ýñšôš 'ƒ׌Xà`ám.æ­»“Ù®à„w¢;›Ú®¬¡îOm½{¥{ƒÐÞ©ú#©ÿÃYé~ƒëßüÿ¨Ëë7ÕgU™2yyÞ•.>h„bäF§Üê%óô\+ñº ÍM}}‘¢FŒ-Êg>C«w”IT{—‘,WìKò¥µVüãn*èŒ8qOàé àæ<7ŠÜ™®u;ïœÄ¹‹b¦9b˜ ?‰•yš´Å’ >"& Íôò?wÝùiºMf²­c‚$Š«±;H-ée’˜ƒama †jÙÆLÇQ0B‹Â?QéãÅÁe Àeï¤Z΢¶ôb™ö”vž—yWeMcägoù+ZéÕÒ}”¸’6vøó—u¶nX©Ú0óœfò„¾‡"Úõ(ÛSymæÁ®/ïoRÞ(IxÈCtˆÓ‰Áu~I}Z%OŲ%]+§¤È“¼VM]GñÛË#{™‡+5qMC_+ZksîNAT5e¡Û|Á[KÆòíKtÁáZcU5p’l¥8‰o’8äMï ;z#Â݈jÙÆLÇQ0B‹Â?QéãÅÁe Àeï¤Z΢¶ôb™ö”vž—yWeMcägoù+ZéÕÒ}”¸’6v׬հ±˜à™‚8ÃjuGlïK(j ØýU³zkÐböãÞô…ˆ÷%=ǧê·ölm¼¤MÞ î('¥¥{(¸·É#^4x§V幓&¹> ˆX’6ÎkËeãÅ-fÊy‡‰~ FJç²°ÉWu§Œ³J|ÐjcµÍ¥‘.ÿ–„IžùS÷3`dF^Ò£æß¬hf|ùã{$‹ÔߺòØ{Æ×‡ŠÒºŒšÐ*Q=Hõ”Û¹âð.#Ì&*‘U¸Ij¶ÓUeMóÌÒ¾Y|•2ýÉçÛùmÍ5UŽ9]ÛÅT^à& ù,tè£ yÑ…øgP„Ò•FôŸ;óbÂ}œ¹º°³=ù’ÙÏdÌËj1H÷ßtÒå$®ª±Ç5!DÚŒ6KF6vI¹ã’Ñ‹x‡´Þ2KÕmYïM$§7Šÿ$~ -ݺj©$Ü̳r‡Bêo Yt¿tmʆµ¸2†‰‘e¸û]w ¶€õi•8–%FÈ»è;jú’µˆÊf’\{ ÁjRNLHÓy˺Û7,TíyÎ3yB_C‘mz”m©¼„6ó`×÷·©o$μd!ºFÄiÄ຿ $޾­§âÙ®•ÓÒdIÞ+&úÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4ÓAX—ïÓ³«ò´Çþ1¹ÓGïÓ³«ò´Çþ1¹ÓS§Zá«óöûó_îjíFû×—di™#˜›òì3‚e“(ñVÃj LÛ«bú¡*+õó¨¡ rµ¼t„J£¦Œ&Õœ_CSUOµ]QIvdÉWçí÷æ¿ÜÕڈƇ8N^ òG°Á“ÖòLŒa¼Èr.G7©’BÙþÃÃÌFšDj´¼±$á”ÃSdY³>1Í]à,ÈñËèn© P¡«9‹r± Ëd âÚˆ ³Ç”®o(^m…tkTðe²ž3R3˜-qZžàôsƒnæYKƒáp&4«[+›©&t–ü{s·û ¿ñ:3ñGq'Gzv^–8FÌo N‰G,¾RvIûDÐŽù®ZÓÞ¿UoNÒ¼7œÂž8! P–—Œ4WÆŸ©†I†ÍFÇŒƒHhËD hêI… Æm _ “ ß@kFB=yU"]]ÕÕ\¸¶U6Õ²¤À±&<Èr7£ïmîq{š!ÞådžR-J/d&ý½áÆ,žay­Îó «»j_MC;Ö;mÁ\½ª'DzÛ*Y†ìðˆ-¨í¤V m•­ÁhÇÖÐʪ£ÛÚµ*Ò¦Óù8ðËàßÿ[ß(çÒWþù¿>|ÿöóè«ÿ#kwãŽG&2Ù0xøeܨzD»§Š…=[¥ ¯oÿQ“ÀòãwUŸ„éay¯%çayšù1%ï±Ç#“l˜ È<|2îÔ="]ÓÅBž­Ò…W7ÿ€ ¨ÆÉàyq»ªÏÂt°¼×’ó°¼Í|˜’÷à ù^`s%NèHãÕJÓ r,“-Z4vŬmùöy_½]¸HÓ+ð1á/[^[G¬Û§‘ i|!IÂ7`B-±U´6RKUmÑhqLce¨D7¤èÈÎ ¥ó¬HJŽ ÏY'Ö¼w&,;þð¥†Ç8 —ų³8°è ‚ûƪºš‹j~Õ=tÞG&nt6>z#&û£Ùž*²ënÌ Ã6e~¨£ž07ÓcâYÿ‹®¨=cÚù*U°Û܉Á»ô 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Õ;2LŽU\˲{—Ÿ0„:ú§{æ»>ylgDchl¼ÒE¡ôœGCM…ؘ· :|F£‡‘Æg¸wÄ,;]%>öQ4 KÈ tÃoHc¦]å´]¹[5öÓ*ÍÜÁæbÎÅ ÄÀëc‹…:‰NHD6×Ã/3âH‚¼Ã5¢É>ÛÈñà€ÏÞn•äé“0%¥£ÆÓ@(Ä’¤‘ˆd®N«ÅíëÎfÉX øH8‘ IÃ>òׄ…‰x;Q]hkyÃhLIeÃlK*΄òÉž<Å´ýÉ ”bJ…°Lù£N«)^F´qÆLœõ+á*æÁhÜM‘èÑG‰˜°ê6Kï¨ãGØSkq.ÎÈÈöÖÜ~ ZÞÁF·8"¸•oÝLjpqÄÃÍ5ø"]‘-âþ£W.3#x/Î%¬ ™7”gÇ÷…5&Ù~2@ÞÝêúâæLˆ…1+ìl…ñl!ùá2±Ã%²-ʘjòΠÊò!Óe‹‘íM’“sÊ–°¸¨êjÔTe5~$¥ëuuxŠÃdÂmpØhòü9L º–’¬eÆã®êõ¶>$ {íÐÝïê¥@y;aåûkÝ_W —Ü>ÞyH ÕÞ±Ò^V? z°ÛûÜã¶Knä÷—·ÁßèŽÙwW¤è{“Ûo^ê®ßuÏê~ˆêñIú§ ú÷á!êó^|“ «ùúâvDÑЪX ÒKá¼ÃëhÆãæžóìbS6¹w[.Dî‹LáJ Äo&—ZÅn„ªþLPß=ÉFo­çÇ:"°|€Â’}“ÆÉ¢Î’ô ø²nߥ§‘ËŸM`hïV¨ÉF)Ù´œ–IŽž´SÙ“ÀÞÛ³d¶q†\®«à†¢ðÓº„ Ž'Bp{é°oj}d\𥧥ÞUÖÜ×yè;þJÖº Œoe.$}í½ ÓÄÕ±Nº°ÑEBKÆ¢AК‚¸^PÔ.;Ì0[MlGL¸Ý£‘åï ì‹,iàÌ¡ê ]ùÛ’m"K²‘cÂ…îFMÓG”²ðC,]ù^;Ì3—Sߘ=ëÚù‡j”í †®¬ÞF¬´3ÅUÉŽ&”2©ï‡{ˆf³º¸O™4$.Y½÷44‹Ú~Wˆ™T¦–,²š3ÒcÐkgÉ|Q¾¤ÉáùÊlˆÎäA5Fc DÖ‹eàhT‘ ‘‚’A™³`Jná:KR@ åp²œ¾X¦l¶@TÂJÒGÉ"´K€w…ˆÄáà—iuyui,—‡„”ª}\ò«Ï Éò'ÏŸ7¢ÂVKeŸWvá|¿îÅû4ó¢DèE:Ù’Wå:¡‚]èP u!Á'ƒëå—>vúãÉDõò|¶ÏÞDs"ñ)ÛÌ3– […§{#ž L9»†&KºC‚ü‘ú[¼1ÌÖ ¸ëh!%-*Ò'Œ½èËñWDôÂ'Œ‹gd_mtY?¾ž#ý•ø±ËÓ'ø•I.VFLø%ÓîÐÉm¹ÐÐüÓ d=vÈÕA_»n<íxäÕúÈ2(ج;혌瘙‚žž˜R¶}/VKb“0692ø †«êŽØ^‰ÐÛ™®:â«fˆ× Ê, H¼êú8ñéŠ:zuwPUll×[y¸›\<>u’ȸ!¯”ê±Ú!Yyš´Qº¾d×’BeU † •EÕ\KÈ•wW±­¶"íÏØmejG yò¶÷B°(óó(òî]ßY9Uén¦(G5›‰$ªªªÑ›#Àl~™ÞàØ‰º‹ÊFWž…V}Õ~¾ MJiESHcæs²JùeòûüÄ8$Èfg8UªÉç÷ù}pç`- ?Ýf¾lĺI¹XD †©ÄÌ<ý aSdÿªÀà¨$ ó· ½Y-ŠLÀØäËà‚6¯ª;`yz'Cnf¸ëŠ­š#^ƒ(°"ðC«èãǦ(ééÕÝAU±³]mæâmplðê¸ø‰Q -Œ¢âæ:F/¾i<ï 㤖›$—NÑ)äÖ¢Ž+kͱžK˜Í¡©•ód­âÚYå¤Ó+mãH¾µÜ–.,geDöM”l×Ì! º~irجÛw\E€®Å÷(Ù(¡ÅÚªÞÕ\KÈ•wT2•³Ká˜ÓãÙ Ñ–;ЪKîY‡¾ã722EŠ ?xÓˆá?tÆY‚=TÍÈãÅô,2™=—ÚfjÿŠò~Þ±,|õA#TQmÁ>‹Ö®àtl›hû²ãwÿ§Ä‡Ó¼×Ñ@ýäýAÿüé¿ÿUþ~ûþ–8ËÖáŒuŶ>$-Ž3‰ÌÖ芠hcQ“ikM{dÁc‹É Ý£88±¼¹œXMÒú]­5Œ‰û’êàïlò¸§v‹©ßᯠˆVd  ~a=©Aà¬ò(·+'ã²÷xjö³Ú¯&@‹\Ŧš¿¹&­·ÜkE°9„7d)tºú½ªš 1Ö¸Y-“”Ë…ø!V¼õž\ Ѓ†Qz½¬ëÛoFWGWê—––W6>Fǵ±c'ÚË—#{s7Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4ÐV%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖ¸jüý¾ü×ûš»PrÀç2¡÷ż ÅLÞ|+0DâÅq‘Žäú¹]º¶3ö{LJa–C¹nÃ<í,¿7ÂØ±¶ª¡‡ÀÄ¿Yr2uy8Í_Ÿ·ßšÿsWj–™ˆñÁÕãŸ6XXîÊ~[¼×Ã÷Ë (Å©=0Çåð­·ŠT‚Óvª[KÆðC¾&Ñ´$Óš‘†K¾ôÙ£µ%dª÷Ï(P¶’ÉŽã[/›«‹ž£^5Øàd>kQ롇0 …î}&ö ]å_ªQÚAé×5µÖ°½¿–±ƒ^Öô}¼ßTÚÏpâG.Z½nrÀŽ©ÏC÷),æë!oGq?yz'‘tŒ³;x<5…ä£gk\é¤ ¸Ä÷l*AÑ ˜Ý”–9ÅC G› Œ‚©­Ä •ì•û˜,»Ÿ¹$›fî{Ó˜;%ÁtV:ûnÚ¶m¬ÆØ9¬¶]ôZÓôËjÁ‘²IÁ»2i—<ä¾½ãÞÞôú‡ý ÷YìO¹ß» ÿÒ_^éÿrú£Õú º9¤b‚srŸ+#Ûœ5˜j/jeÀdȦtNz†ýpFM\Ð’´£$黯XÌ«’-ñYµ\s·Ç¯.åÄñƒ¹"º Æ@+iî\?t"*¶ÈaŽbÆ»#qê’ñ† À°îû,ðh…./ÆM\%·‰›Œ^²¸¡jU ¨¨‰êÆöÃS°…K¯q‹î‚ÙKDmuà8#—”µ͸5ÂnrGœíÊèJê×÷‰i%ô‚Öžð„iÛwŒÝùŤ䅌C²k{s¶sœ%7(óiOФ‰…±ãM¢òÉ Ë‘ì~C%Á·ŠØMyâSÃöäW\^OTÑ®h ›“6YkѺ`j²Bi\3¶8¹›J|ª$s­‡Gjç–7ÞSd Ð ¼(ÂTO-ža´"ÆâŽyZ Ú@<ì ™LËa ܃Z q[Eྃ±Ç9FC9Ǧ3ßò—[¸ s„·Žª±’Keî=¶"e({P&Mvêv„ÊÆdƒšð!ÍÅü½ÃŸ>©€,KjgˆrD†a»y¶g:B=åÖ*¨¹ä®Ѻ­I*W¹Ø–Zíc‘ã1®åN胅X³ |¾;9§¿‰³¶sáYÒÐ B六µ¤1Ç#“l˜ È<|2îÔ="]ÓÅBž­Ò…W7ÿ€ ¨ÆÉàyq»ªÏÂt°¼×’ó°¼Í|˜’÷êËË/³6+š,)ÿª€d|ºŠÖ\îi¦uQÂþö†¡CÛŒy_d•s›Õí*ßUn04ð6Îû&2×p‹†ÀÚÂh‚pvûëîl„Ôá¼*–Ô`ù4-xËˉ[JÝáÁÈÖGd-hZÙÜeÆ5Y"Ù¦¶áÛÜÞV•ÞNa)Á‹Ámo……ÀS ÂSq‡8YEŽ—¹/U½x›¼k ¹ÅÛ‚KÖ<’%nîj˜£ÙG´‚­Kx;WQ¶kgRW}}@5Ýäz¨ö\;{Y¾%d˜Þ`㢳%Ã@ÚkaõÂaAG@¼æß Ý­U Ué5_ ­]tSP‹jÛë8€Ä#dpäy{m½¾ Àç¦;¿Y‰<ºñÒ)ÅZƒî€N˜ô,šfôšZ¬[3W“îs'¹‚­¿:Þ°lwaA½ å]ÀV‘ª5 '®D‰A7¯ „5©óÕqŒ©Ì¯ÆµzÓtç&%_.£õÂxÊÅn˜¢Ì@xw#'£ŸÄ¯×,å]-±'Ý׸ô‡~óyN¢ÄP>‰­¡²ô–KŸ¨:^ì»×IFü€D›ëöTÞ¿}ÚÄôá«_i½ì8ó“Šñz»ÇG4UGQ䪠£0²ÌñnŽ9Aã¢Ófîî£lÁ9Š…†L»Üt eÁ7˜` 2$SÙÝßVÒ]Ü_ÓÚ͇·Ï3ï2˜¢W”aW‹<Ñç@™&xaO s“VÂo °ZD'ÛÒ–`²+hÇD E o-­G) Ulñ1)väXÍI¶÷„‚ݺjŠ‘€uÜÊå_ÇÆRâ„•í{x·Éù5µ„¾`¨¢< ssh17W‹|!sDaŒ„â½Hˆ”q~r°ˆ=:à2wÇo û½|¨ ß” ÞŸåTùE |ž¨ïŸ¯|=`¾íHôùR÷YèþûÔúïøß¶ÞóoÿZ=OAmrÊŸ.–Î<šË\S¤8‚ÃÃ^Ãw>æö¶†(eï¼:þÉŽÐv5ä¶—–ž—GW")GPŽ‹ù+^=ŠŸ[‰ÅÇ;n¬¹AÜžäçg«uÇ˵ò‹.~J?cëÝÉ÷%õïÉv[ÓÿèOºÏb}ñ=ç½{þ’ú÷P{ìÕׇ˜8­/˜?“&øõ䜥¡V`¸Ï/R±j—&ó —-KqÄJÕ4<‡¼UÇâã®È²gRRÈ ¦®VË.èI±2ž<”FnD v÷·üÈû¸ößô!ÞÞüôùnùùУî«}7ÿã.ô?˜âVÿòzÝú«/®¿¹‘u3Ä á©”CŸrË뮂ȢH;%Žü¨|zƒ |k»2%ˆ°ãÛ ”$cïɾ±lµÙÝ݉KÁÅxÄîW^Ueœ…²At q}ΦL¯,Whs{T7™ˆ à>7NZðºLK ÀÊ|{P3l­Œ2 1 =⸿Œ†LxUòI//ôÓUÅ´ºõ–_s0ËSW^åfº†rD–!¹Í„÷`Ø­ ƒÌ_ ’K(ä´`¥ä\;53ö7 ‡ªcÖ‚%”CaíÐ4ÓMM4Ð4ÓMM4ÐV%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖux·”âí"Š"fzðvî¢yÚ{ÓQª‹X~dv¢do5_ag\1FÄ­k³ÁícoìïíýöÖï¦ïê'ãR—ë;í@&UÿÞ‡$/nÿØdZКÓüŸêÜßîŸäÿVæÿlíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöεc̃r$âC=ÀkªÆ ˆ®Èe ¿„I^6É· ¼œ=2×zê®%äJ»©[õ2l©í lOÛ»2¶|~È»µÜÓO9Õ¹±íç:·6=ØAŒ¸ü’N¡ƒ^à6b %bùD)dLÐ_Í$°[ TÑÎ!™U½KW.ò]],]ûi5´õ07çîH݇[?Ü]­§ßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöÎýDüjRýc‡}³ªÄé§œêÜØöó[›ìíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöÎýDüjRýc‡}³ªÄé§œêÜØöó[›ìíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöÎýDüjRýc‡}³ªÄé§œêÜØöó[›ìíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±ïg»l [9Û¶•sbYVY3Ϭ+¬käìÌaa]´ˆsaLǹTIQ÷6÷ãIØÜÜÙßÙÜàÝÚãâàâáâñkXi¬Ù¿ÿÙnetgen-6.2.1905/doc/pictures/MeshingOptions1.jpg0000644000175000017500000016020313504650527020137 0ustar kurtkurtÿØÿàJFIFa[ÿÛCÿÛCÿÀyÕ"ÿÄ  ÿÄd    WX¦ÓÕ8Fw†–¨·ÄÖ6V•—µÔ#$%&'(57hvx§"f¶ä !4IQTgˆ¤)9HUuy…¸ÅÆ1e¡¥¹ÒñÿÄÿÄ<!1Qa‘q±ÑA¡Áðá"Bñ#23Rbr‚¢²ÂÿÚ ?úüooZêµ3srkŠÖ«¹²Õ‹¶lòµê÷6êÛ·nÝ[tè·nÞ:®^½sV‹Vmh×zö½´k׳Ý^Žn§»vÅó ì\×fõ›Ä:­Ý³vÞ­º.Z»oZ:íÜ·¯NÝôkÙ³V[6éÕ³fÝ›vR9½u=Ó+ö.ܱ~À ë7¬ëÕní›¶õ!×ní«š6é×nå½zvkѯFÝš´jÙ³V»6ìÙ¶£š —ßë¼{ó—ýÊœ¾ÿ]ãßœ¿îUŸdÙíŠÂ¤„#Šd7Â$áŽÃ2qüsL’Ä%  /P„Ðz}Ⱦ?/ƒ`ÈçB}OR›LÏ!‚¯ŠÄ¯¡5‘SŒ97¾)´Ã$Ãf£cÆA¤,e¢¬m$Â…c.ȆɆß'uc!|jP­­éé­ZW&—fÕJP8 Rb5“Þ·sPKܾÿ]ãßœ¿îTå÷úïüåÿr¨ö”/¿×x÷ç/û•9}þ»Ç¿9ܪ=¥…ËïõÞ=ùËþå^]ð}ÐuÒóKŽ©M¯s^zvíÔR}[ul´­-ݺtõ©®ù:¼^Nz5é×bõ»Jm]³n.Œ¤pÉŽ6¥ØáçˆãÉP NG!Ýέô0á…0»Îé}BÖø×½Ý®ÝÏ-­Î¨ºþÌâ…"»W“Û¦rYáÃÆp0¯3+\Æ$Û…YV;©io'hEd‘ûuåšÑ³#!³û“âVë)¬;[ÿA~…â¬ímvvfocok±³3ø.G4âßcÏžƒ¾Ñ§4âßcÏžƒ¾Ñ¬73ŽËä37-Ì.þfVïØ×¸î¡¡v•o®[½©*çEÝ…­ ¥]µÅêz®¥U 5Ûµ¯ÔW?}µ„{§ß\œýöÞZ6÷šqo‰±çÏAßhÓšqo‰±çÏAßhÖ 4«|rÞ­hJ Ã*ìkÐõD±Á£üxfÛÔ¹%F£^æ0}hí–ík@ãØwƒR¥ÍjQ­Qê)ßmaéÊuÈï¶òÑ·¼Ó‹|M>zûFœÓ‹|M>zûF°iY˜ÒFñS—T`P.^fÄÑØ×ëíÃ@nÁ en[ÂÚ]mi·S¤Ž—±¬Zzíó×6¥X¹ÖêQNûk÷NS®G}·–½æœ[âlyóÐwÚ4æœ[âlyóÐwÚ5ónÇ–˜îFôÐÐÏ&µªBLèÞ>yq¬9"º«´ÞÞN‹™“C2qâ§jÛ-Gçd…ûÑ¥·S&•Â% Ú&11£Æ•o‚Ž[Õ­ A¸b¥]z¨–84 Ûz—$¨ÔkÜÆï­²Ý­h{ðjT¹­J5ª/}·Ç–îS®KÞô‘òóN-ñ6<ùè;ísN-ñ6<ùè;íÄ*Tï¶°tûë’wÛyhß¾¯W•ä{Ÿñÿú{Ÿôû¿ôþøÿÅ^šqo‰±çÏAßhÖ9ÀÒ$€ðÕžìNç&.ŒaÍø´Ð"ÌâLô¹¨U¨…3Â7öÁÆå+n¤co|IjÚW„M–R¦sMoE…¶ïÚѧNÈéññ”e•ܑݬ|t}­ÁñýýñÁ#K+#+JK«ÝÝÝÝN…µ­µ {ë\ß²‘K7T(»nͽzôêzi²‘|y×í1õ^ÿjiHˆðºµ˜²|î†èóN-ñ6<ùè;ísN-ñ6<ùè;íù·hËõ]Ô ¦š×(k||D¨HmW12Ž2¸<»ã¢w1—²a­ë~×ýŽû¢KH¥•ÈqÑÕJÆo»ù{Y¯¨zp°×‘wˆšZÚ-a–bÜzme VøÝÁ¯D©r6·µÃ$ˆšX¶‘ÉXûâtWo^i_¡<ïzOöùN_}r;Ηü_NÓ‹|M>zûFœÓ‹|M>zûF°h@Ìhñ¥[ࣖõkBPn©Wc^‡ª%Ž ãÃ6Þ¥É*5÷1€»ëGl·kZü•.kRj™¸\p4äg!—‹‡³v=îVfþÒ.4Õ¼W¥joÞO¯ŠÐµ¡í΋‘6£íJ­v•룳å¨QjÞ¹ßmáé÷×$ï¶òѼ¼Ó‹|M>zûFœÓ‹|M>zûF¾mÒe„ ¡”áåyƒ ¥èà šS0À$ˆÎNmŒCÒiTA#%ˆä!™Iì ­ZÛ,—°º¹&Z2Öà´‰Ö´ö.öÜ_îŸ}N÷¤ËFÞóN-ñ6<ùè;ísN-ñ6<ùè;íÄ*êî¾2§zo¾î×d‰Ù­Ýñ­‚ë‚KoNL£êØÐ?»·µë»¥rƶEÄÃhÜظ‘µYu·lÞvA¡C¾ÚÂ=Óï®G}·–Ñæœ[âlyóÐwÚ5Ü2™’ª¸„lÀT…u”úÖ]DÆ@Ôì®ÚKw-Y¸§Zd*¯ÞПEå-k½«FËzn^µon¯.æ:°ª¼±Ñ!á «ëÀÉ @1’¶—á÷5¬ÏMjô:hÒ©¹ÑºúeÈ”iÓ¯V—“_µsfZ¶lÕîmÛ³j:m¯tûë‘ßmå£è1åõ„q%·7ÖaäThGekãš&”—UÜ·zö„Ö”.½bεì§¿wM:öÜÕnÍíztíÓk^Ý>gšqo‰±çÏAßhÖMŸF¸¦¼õáõs–*CDN+\Ö¹«^@þÁ¶óëêÕ oß¼©áêòd×]œï븵Êâ{Ö_½ªÕ½ºkT‡'€E,©_ä"–±”.N–GØ,+¹qCÑiJÄ‹Vµ…ƒ ´¬ˆèñúËrÝ íoeäêÓê@>Èä»V„ú¬ôÛU²0ó¤ý¾§}·6Å"&è¥[óÍ8·ÄØóç ï´iÍ8·ÄØóç ï´kçÎ7™£ig|§$íoƒ»‹ÂŸ™ß‚d}õÛµ°qì^nÖ;"q*6ÕnÂÜ^0ËÄì:l°o5i/û·ÇÆQ–WrBGv±ñÑö·Ç÷÷Ç,¬Œ­).¯twwt_u:Ö¶Ô)ï­pp[~ÊDi,ÝP¢í»6õëÓ;í»©þ8Û®G{Ò]ew7Gšqo‰±çÏAßhÓšqo‰±çÏAßhÖ $3\hÿ%rëLÅÄ ßZ;ý„hñØÝŒQËx\K¡­NõtŽ Òö4kT/C¹ºç$¨Ó¸µ]]ê)ßmaéÆÝr;í¼´mï4âßcÏžƒ¾Ñ§4âßcÏžƒ¾Ñ¬3µ—Q15;+¶’ÝËVn)Ö™ «÷´'ÑyE‹ZïjѲޛ—­[۫˹£N¬*¯,tD@$xH*úð2BÐ d­¥ø}Ík3ÓZ½#Nš4ªntn¾™r%tëÕ§eä×í\Ù§V­›5{›vìÚŽ›kÆ#Ý>úäwÛyhú y}aImÀõ˜yÕÙZøæ‰¥%Õw-Þ½¡5¥ ¯X³­F»)ïÝÓgN½·5[³{^;tÚ×·O™æœ[âlyóÐwÚ5“gÄDQ®)¯ }x}\åŠÑŠÇ—5®j×?°m¼úúµBÛ÷ï*xz¼™5×g;úî-r¸žÆµ—ïjµonšüþf4.ìÆúåØ]$r…a‰{õ;ä•Y|†©·®F•Bvî¨< ­ß¶:ÝBƒ^êÝöÕkt\Ú‰ež›j¶E—ý,žÖ§}·6Å"&ØŠU¼¼Ó‹|M>zûFœÓ‹|M>zûF± •;í¬#Ý>úäwÛyhÛÞiž&ÇŸ=}£Niž&ÇŸ=}£X4 f4xÒ­ðQËzµ¡(7 T«±¯CÕÇñá›oRä•{˜À]õ£¶[µ­aÞ J—5©Fµ@@Ìhñ¥[ࣖõkBPn©Wc^‡ª%Ž ãÃ6Þ¥É*5÷1€»ëGl·kZü•.kRj‡}·„gåÊuÈï¶òѼ¼Ó‹|M>zûF»³Ð'Õö™ƒ^]u½•µ¨•Ázž¢ÍÅ7»:4‹.¨½Õ'³výÞ®Þ®®Í«—uù6ôjÕ³ «ú+VÞ­*ô ”"\‰E•hÖ$½q2´ŠÓ\Óy:¤ª,êÑy:„÷´h»fõ­z.Z¹£N½´êÓ³nÇ}µ„{§ß\Žûo-ÆææØÊC«Û›{3ZN«µ9;-NÜ6Û÷­¦³²úÅw-'³¶ê‹Ö¬[ë.iòï]·kO»ræ:¼4âßcÏžƒ¾Ñ¬k857Â,L{30).y}Q9+{w' vsyVÉ)»43*u^ê­Z· 7.5¶^WvõÄ ×5¢KªÒmZ­må)ˆ@4àq|£øäQ°0Y¬2<åWâ^%1¸ÚÚ' (ìâáäÏ‹ihì3ªº­Uܶ\ÔôÛU³g /ÂyÁßmÍ&""±R¾ Îiž&ÇŸ=}£Niž&ÇŸ=}£_>q¼ÍK;å8A'k|ÝÜ^üÎü$ƒï®Ý­ƒbóv±Ù‰Q¶«vâñ†^'aÓd…ƒx±«HáÓ›™Geò›–æ3+wìkÜwPлJ·Ç×-ÞÔ•s¢îÂÖ…R®ÆÚ‰bõ=WR*…íÚמûnêEŽ6ë‘Þô—Y]Íåæœ[âlyóÐwÚ4æœ[âlyóÐwÚ5ˆT§}µ„{§ß\Žûo-{Í8·ÄØóç ï´k¿c('دhÉ0ñ&ÄGnÜMÏ‹µuÝ›j¾À¡GgíGSÖùoQ{«òº«žNÔM;œÇ‘ ¹ H9 ¤ãé-¿; ½[H¨ÀwB¤ºU¢]¡::téQgMý–ïiÙ³eÍ:¶lÙ²¬tû^1>_}r;í¸¶i1ÌRø}(Ò”®—ZB¾ü^’ýŠ£Ú£ï†ÿ¤¿b¨„™¥{ðÙ Q3àS£Ó³KiÊqµd‚KÜP(FŒ˜y)ñh‚—Æ­º´§+&¼½"{oƒÏMz•6© —ƹwƒz5"Uã9G‹8ý!ã¦ä‡ó’MÉAþg†ex½Í‚yT1-/fȬu´–o4Ê"5rÁ šBŽ\u1Û ´èÒLb² ¬éq;—²{‘­,rD0ô!â¦OÚˆ£.™G¢Ú6ÔÎ|ÓM*O1ól+Î/‡ÁòÇF"m“1 ÈØ]P' 7W))\Ý­.ݪߥ™åó4²-êr cP23»@2ÀÚ»$)• È«:8ï°±©NZWaCKSÂD¬“Ú¸ŸV‡§-*fôØ'ÑýÊMÝØÝqOïøÄš×7?Óòq‘´„ŽÆIG˜Ó¿1 ¾§iAd‘èlIy3¨ ó³å´ú]XÆ] Lœ‡šV*¼•yi2ÆÔé”?:ÜWaþ%JÃqØl£‹˜é$ˆD,z†baCèJ41‹Æõ cjÔ=±‘ ¸µ…1êkmÔÒ4•±ÔÌhö§ìí(-§ ÃòLÑ’"<êÉã‰K•½]³ŸwÉ¥ø?¦\…0<Í>1ŸÛ9Sf=マ^¦ìAÖ·4,¼²óR!4ณ— &)`ŠvèÝØfNôQœRžd´Ûl›ºGìä¼±Ñ:hÃ!&6¢c¬2ƒÙ±Wß!³Hº-kºŸ$fØód¶Î7ËCÏÏ寖‡~˜“Œ¤$v2J<Ƙ½ùŒxeð­;J $CbKÉEŸ-§ÒèâÆ2èjdä<Ò±Uä «ËI–6§L¡ùÖâ¸A>âRBGc$¸¹Ž‰‹ß¥1éÍð­<%Y$z›D—“:ŠLNÏ–Ætº8Êc.†¦NCÒ ÅW‹YW–“,mwL¡ùÖâ°‹:2ÿónô}‚Qú‡¨¾@ünéÿº§êÄU¢C##aCcÁ¡£ÌbBLm#"‚ƒ-(FÆFØP'jccjN‘­••­"VÖ––Ô©7 L4öSÙ·oNvÈÝ ?÷TýXм}/ù'ß„¼]7ù>°ÉlÝ÷—åßø`Ÿ~ªK*vã@n'Âpî(bæ)B~IŽofÎYc…Ä/Óâ)kìœQ›Œî3„¸HQt}ó3 ;o¼^³v¤ðKrpL| Ðe s]Æ7WF†@EzÙV\µ¡í¢ë¢"»µ‘´öÑׯò@×´ŠY]\-Ø´•v¤«ÒÁqœñCÓy%üÅÈ»ÄM-nìmo÷A0–ãÓk)¶5ïí îšðÿRämok†FÖ»·§¿m#’±ö5 m^¼ÒƒZ~X˜§Ö¶×*M‘8Kš&)õ­µÊ“dNΖæÒ+q¯â¥íb+æ>•wÔC—áÓ)¢¸“/Æ‚DZ!hèÆJVÖ "zhNßð“+‚AËDä ”²Ç–™Îá"Òìc¨òL€ÈG¤-sMë͂٧"Ç7%aÉ!¼|Cµ•8ó³IR›¤"©ž)“ÑjŒ˜Ä$#ùá¼€© ° u·»ŽÑŒQº€ ±Ä¸‘¯#Çu>Hé,MÑ„ à‘´¤Šã‚ׇ4#qüG„ìtpz~-!^J¨YQ{“Ñ¡R—B%¶\ô§Oï á\Ø,z73ˆ£èìGtð 8£øXÆàiPÂÅÃÂέ*ØÙw+µLÍ;µ mÜÒ¥Cr>¥ë–u&cε×v9]ÝDÌyÖºîÇ+¢Û©êð'¸”•Îw7tžƒ'bj%ï&Io~‹rO£’±ÚyT¶œ‹‚íF=% °É2{HÔ¤ZOŲcA}ÇÃÅ„· ´-fe ¡Ñ*SSuHM†¡¬†”âpÅåîÍ­­ ßJ6‡†1Z"¸ßeyµ¥oŽº”:/X¦ôîÒÁÈ@]—‚EÔn––î WÃݨ@c±¤³¸Ôðˆ§h`jì7¸`{¬I«r¶önÑ¡”}%Ô lˆT:>>_DÐÞ‘µ%ç¢g§BG{©ÑZ³f㡳£ûㆽ•»=98:/º¡rÅîIšÅ)»Yç$Íb”ݬóªÌ~ÄêGH±†Báü™(cœU ‚HÚZYJBBQ͘œÅ3Þ;îõÃíïI"9>;Û>³;äV‚M"ú:¶3+C˜ê"™ŒŽv¿1å£"e-™'’à@DV=™y,$w(Ds ~…Å­¡ :€Ø¨.ÅÆÓ‰^àˆøl€N0ÏdxkE›âÈŤýòWkŽ@Ûe"f»Ld’Sx€ú3òTöÚ,Øh|1Nßl‰Ù®Í‘ö V›×¸¨InÛ#E½´émE²Ï„+Ŭc<_mÔãàƒ7K;תr+ˆcâ%ö·é+é›çV±ÜybäÀ ˜­×ɹ³x’‘>¾«ëÜ(±µ¾ú×K&,®sãeV6·ßZédÅ•Î|l«:g¡¹ìв kœ 5‡ÁØ"ImÐß:ޱDÑ=çR¹H8ó&KË#8hñÒ`(k‹”?¿I:ÓDÀnÄJÜÂ^ÔH÷ö·iô"°•ƈœ ÌÅäsÑ€ ¹ !RÁg„ªEo>™ˆ-jmfkX.Pé­Sã¦Ö†¤ W$ºµ }vÒÚêË1×O™C†Î ¨pÐv;kÚǰF!$l Ìº’5 ÔÐÖðȱË^¤,Œ¨¶·²ØD“jF†´ûmu-é4Z˜é3XˆÃíüÍÞ¤Íb#·ó7z˜ëÿ8×ýпúÝFw-¹/.ó›úŸå÷5¿§¿«nvã¯Å_ãGâ¾ôü[þÿÔÿž¤üuÿœkþè_ýn¼¹›±@Ó“¹Dpè»±öS0Äk‰Y»2ô«/nÔ²à}Ýâ=Ö¥›ÜQ×È@¹UÆþÂé¡’9þÝßýK>³ÿ´©ÊC÷`¹CJ$XÃ'çb‚§:E}ÒÅ7 n8"G?r”µ±ìŒæwѵK#ûf±¨„Ëá‘Fg­rÒ‰Õò¤ñ?~„ûþ1ë[7kËÆø¢,4y8žå.†% Åre¦è« E9´½ ²ç{öä‡À5虞§d,]úJòüÑXH¸Þtâ·˜øK•¥ÜÃ5G¿`³7X^EvÞAmÍœ¼nus½êñìQ41éRÃyÜ¡ó‘(lêúC“GðáX¼­‡7-«P(ÄnDZ‹¾,|rXO† ÂïŸÁ-ª£Æ.(ÔÇgÛqkÙ%jhÇ8!©­ö&ÖØ†>B1Æ‘†H}•QëIÓñà{sx¡ŸUoG !FÄùÛšÓYK¢O' 6áî3.ᆓqN'`iáƒFѸ‹Ç·ªE{”¡—µªÝ/í½™Ù»´¨ìjìõ×<«;Qe+ã_¬R·ñŸªÎÔYJø×ë­ügêΘ‹l‡Ëøû|ÙÀ¢Bž8­‰›##ü¸:–ciˆ–ÄZE(·:—ãDÌš3ƒ…å±±B©T6æ.9’ Ž_„™¢æ¢»q92äåWöZþª¤Ï‹ã?öqÊ¿„b…ÂMd€ÈŠ0‘ ··žŒŠ0ï÷dïϼBRÔÒ‘ñë}>$Jòí¼—)Þ.É“¸¬ë–Y·{O÷K_ÕT™ñ|gþÎ9Vfkïß¼.ff¾ýûÂå‚%þª±ü@Ÿìåú¡sã(žKâÉ ó»[0 ³\Õ‰("pIm—^Kê‹/ÄhÛ‘*»«J3Ǹ´g#„Š;2}ZÇ ¬»Jmce—ЗúªÄoðy³—ê£ËЫä·Û›ùå(‡¼‹©$1È ,¥Žó²ñp…ÍÊÎŽí­Ëq»5o{CJšQ§µ¸´(Pè©ÆÙ[n¤yìÄa)±JEn§¦§xoÕ’å¬H_»Œ!NŽœ—çCKþæ% 4)@.gŠF±©Z7Me ÍbùWõW;FÈ ŸvpºymQ„”̓MƒSÈp†GJ°¼¿Ñƒ“ÓÑs¬î¼Å³är¾6p‰¦ÑKLN)y|/+ñôŒÖú!mÇ)(hzØ›|e°\usF»Ž£–¤…Π±Œ”ã²èÂVÐr»˜#f^iŠ0©yáh‡¢Í»¥ð©A®î4ßOɽÇeב¯s²®Ù Å‘ˆ щ ,rE":l|ÄÄÇŽ^´«t_¥ÜÅѽâgM+žÞ–ìpz¾µ^ÅnîŠ6]ëœë»{Q¥´û_XÊÊ]HŠø·Úˆ¥-§ÚúÆVRêDWÅ35‚É2*eYŒI•¹¯¢Ù¼mòì¢_ Œ+˜zA¦1Yñ¼‚]s‘/;ºŽö!÷{FIÙ_™ØÂˆÂZQZ+°Rõ+º1ʳ”0^mâT‘Ê%嬬À’¼7Q0'-¾LæêE3:ÙÈÄ ÎS«ür,Ihw\%¢3\Ï¥j„aq”ì"‘`0Æ“†;+0ð£+Jn 4v’;;skJdvxFD}=êìéÜNÅ-]‘ñÅbëÞ@@Z½íÚ„ÔïòãwÞÐÀÓ{}ðÇ »u‰5oŽ áçõs³/ŒnÕi·Wdv£9úGü}"u§Œ¨Î~‘ÿHiã,ÕahÓ2´9Ž¢)˜ÈçkóZ2&RÙ’y.EcÙ—‘ÂGrˆôG0Çè\ZÚ³¨ Š‚ì\m8•î؆ÈãÜöG†¼$ô7!ÝšAMsF°ø;@É-ºçQÖ(š'¼êW)dÉydg :Lmqp2‡÷é'Zh˜ ؉[“¸KÚ‰þÖí+Ŭc<_mÔãàƒ7K;תr+ˆcâ%ö·é+é›çV±ÜybäÀ ˜­×ɹ³x’‘>¾«ëÜ(í 1×O™C†Î ¨pÐv;kÚǰF!$l Ìº’5 ÔÐÖðȱË^¤,Œ¨¶·²ØD“jF†´ûmu-é4Zv¢±+®¶ë)áõ¸íEbþW]mÖSÃër¦Bí’TÐ=ÌÉÄ ï0ã¤u¼¡’݇ay"_"+É~#–Ðð ¡))á ˜rÞí‹OÅ›8ò<%á¨ûƒ.¬µýUIŸÆìã•zÛLl©Þœ ,45Ù"vkhct´Þ’ÛÓ“(ú·Åì š-i\±­‘q1"Ö†õî$mV@ø¡«7—ëQ䥯êªLø¾3ÿg«35òáèÌÍ|¸Dz,/õUˆßàòÿg/ÕŸ­l"ÿåŸü—åÝ^_ê«¿Áä þÎ_ª)B¯’Q(Ñ|å(F¼#î,`h Ç'ô „ºÐ±«3mp—àYL¡œ¡x¹[¸’ÅLdMˆ5)TÝi¶Îö~ºí|í=šxD¦ÍÑÿO§„Jˆ'h4LÓ¶çßQÃ/H± p™D–ì®6½ôŒ“ãS”Hí*µxü]09s«˜ñë+Œ¤"üa¤†ÊÁê öÈqô¤=,»8IñùO´ÆÊ&(§.¬ð]“™}DZ0 Y†D,×q@¸[ˆö.É®ƒïrÏî.ó²vÙ¢Ó²ÑMà€½Ó¸x@_qñGîmÀÓºxÓ9‘Åû»²v>(æ'ñ÷õ;Û?=¯~~þ¯1É_™<æåaθS™?Ð<+øõºx£ñ_ø·ý)ýüýûÞ¯kÖ̬¤xY~YK}¯[2²‘áeùe,èt_+É”:R$]»Ð»b÷xÇ`<±v@"ùͬr‹H |¡y ÚO༠,“°ñª½[ÀѪØâ¸F<¶qFaöJMí €Š Z4}^úêø_m‰Ý¥c^‚‡—B‚g'Wý)v;8¯"}X­]åî á\ðjØaÄE‡Ù(u7´(V(D5hÑõ{ë«á}¶'v•z ] œ_ô¥Øì⼉õbµw”;¸\Q;Q‡xî¶Ü®‹p¨ÃƼw[nWE¸gD8Äi#)ÄÜß&Š$¡upFf¼‘—AìôÓ+4€O¸è7!$ãÁؤ Ä¢9"HÌM$!ÍK›ŸÜU‹™Èã&:Í^]¤ -ƒ†7€»/‹¨ Ý, -Ü"¯‡»P€ÇcIgp ©áNÐÀÕÙopÀ÷X“VåmìÞ¢¤Ír¿Î}ÇÑ&k•þsî>„;ïÃûÂýq¹Õ`Ÿ­l"ÿåŸü—åÝYøwÞ†ÿ÷…úãsªé‘xÜ9’¬£ƒf#£ÎŠŸ6°ZޱÞHexz¸“b×w¼‚„ft(ßyDÐà3`}_d#|NçuÊÍäz_¤yìÑ6nÜbŠÁ”2z±³ü‰4…JZÓcÇGîC»ËjÙ.2®V$~ïlF@Ä‹Glëí*BHèÔ„G!JØÞ›ßm†2“.sodi˜šµÔ¹ >Ê÷IÀ\ˆ<—£k$¹+Σ¬Ç4’oY½d&XIÔvè.þÖàrÆ^ý;Ù‰ŒÝB-4³¨°ªæŸC8Ô¶á¶‘‰ÞPWŒoŽÃòÿ‚ck›ëz)SüãDjøÙä>;('þ/²ö×í=¡Ûx£Væ…¼Ç\}e1‚¡À±Ù¯c€À'„Ž2œ²éHèƒKA‹[;"4$ÍzP½½"ØÞõajM‰ÝìµÔ¸+Ñvö¢3ºÜm‹ëL,¾•ˆ­•ö¢3ºÜm‹ëL,¾•ˆ­•œÕœÈ9UÎ~Oå yÌ^ŒªŸœ÷Œ×ÇAXr‡"£~Ã{ù$ãÞdÈý†Ü1Àp»¿ ³p;/¦ì“Uä2±÷§wøjXkP¹“£W6²zÀÁ)3-åmªñÕl#,(ë‡Hî^²o Ù­É•Ù&£$ 7–!Pþžåî‹#£@Xä ,ŠDtØù ?‰ˆŽ=½iVè¿K¹‹£;z5ÄΚW=½-Øàõ}j½ŠÝÝl»×8+×wÌÀ1+‹\AÂ+•5–·µ’DÑÜt.ô0¬Ù âw÷Æ+Äœu:-¼½u§¶¦WÅ`â: Zа EiX²±wÑmžÉX²±wÑmžʦD-ƒQîNA‘äw‘Ò„ÂM‡ä–èÐ{;¯šx’öÉXÁ§‹Îî.®šùŽÖ¤¹+ †Å©bk¨¦ôD" ¡öIºMe2Ÿú‡:ù1þÙT'Œ˜jíš5™ÆÜ3:Ç#B†7ãXZ§cG`7YJX:b".â‰B@å4VÛu[" °±æ‘;èÙBmom—æÌ§þ¡Î¾L¶CÕ6©[&¶E¸û»ìíÒ“I¯é¿=Ç;ßOT¥+¹Þ£ï†ÿ¤¿b¨ö¤(ûá¿Åé/ت= R” R” R” Wö"¶•3Í…QLPö —wñS›è3[“©f湯[­¹³N·ÝÅ£V”ì»ÇeýÖšÕ›Hú­–öm¯ã¥=Ñù¿c÷è¤wÕStE¾oØýú)õU•)F”Œ#HsÝo›ö?~ŠG}U7D[æýߢ‘ßU\)JF¤Œ#HsÝo›ö?~ŠG}U7D[æýߢ‘ßU\)JF¤Œ#HsÝo›ö?~ŠG}U7D[æýߢ‘ßU\)JF¤Œ#HsÝo›ö?~ŠG}U7D[æýߢ‘ßU\)JF¤Œ#Hsnh‹Yøtcö?5ñŽçâíÝŽ¡â®ò÷ökV·æãënn}çÚ·gY¯±u^¯uº"ß7ì~ýŽúªáJR0 ¤aCžè‹|ß±ûôR;ꩺ"ß7ì~ýŽúªáJR0 ¤aCžè‹|ß±ûôR;ꩺ"ß7ì~ýŽúªáJR0 ¤aCžè‹|ß±ûôR;ꩺ"ß7ì~ýŽúªáJR0 ¤aCžè‹|ß±ûôR;ꩺ"ß7ì~ýŽúªáJR0 ¤aCžè‹|ß±ûôR;ê«ùÕŽÄN  _Ž˜ìµ Ô÷’,F®"R‘ZE6õYP•R{Ö5ÙPEzí^³wF»wmëÕ£^ZumÙ·õ¥)FR0!ýwRF÷’4 ½@×P³ aGv/a¸‘}ªÞÛ-lM õéÛeµ¶Îݶ6#Ñe;{vèObÞ»vWóÍû¿E#¾ª¸R”Œ#H)Fçº"ß7ì~ýŽúªnˆ·Íû¿E#¾ª¸R”Œ#H)Fçº"ß7ì~ýŽúªnˆ·Íû¿E#¾ª¸R”Œ#H)Fçº"ß7ì~ýŽúªnˆ·Íû¿E#¾ª¸R”Œ#H)Fçº"ß7ì~ýŽúªþuc±‚EHã¦;-Bµ=ä‹«ˆ†T¤V‘M½VT%TžõvT'Qg^»W¬ÝÑ®ÝÛzõh×§V[vmýiJF¤Œ#H]Ô‘½ä/A5Ô#ìèXQÝ‹Øn$dj·¶Ë[B}zvÙmgm³·m¤ ˆôYDŽÞݺØ·§nÝ•üû¢-ó~ÇïÑH类¥#Ò F¤9Íû¿E#¾ª›¢-ó~ÇïÑH类¥#Ò F¤9Íû¿E#¾ª›¢-ó~ÇïÑH类¥#Ò F¤9Íû¿E#¾ª›¢-ó~ÇïÑH类¥#Ò F¤9£h‹[˜Y…[ñûŒoGŽ¥abÞë58»nf{´7µïG z׸öö;jÍz•)ëoêÛ¯ktE¾oØýú)õU”¤a˜Â4‡=Ñù¿c÷è¤wÕStE¾oØýú)õU”¤aAHÂ4‡=Ñù¿c÷è¤wÕStE¾oØýú)õU”¤aAHÂ4‡=Ñù¿c÷è¤wÕUo˧(ô3$œuÆu.IP2#E¿!ÂôjJX™-ºìgxF±¡rö]®;ÝžÛ²½èPÝqmqGnò6ª^sûÖe‘?X¢5&"“d]> 1›"éð[JR•¦’}ðßâô—ìUÔ…|7ø½%ûG´ R” R” R” R” R” R«¦Tä* [‡õL.¢†i%<{ŽÜ˜†P=lA9d_¬| 6/4|O#\*it$?^Êœ-JGGÔ«’…‹¥E„3tN5§œ–1¹ELc$#†Bwo 8@uy¥xž6JdÒM|“]X¢Ñ˜ý )$œHJ42ÒDþDÊÚººgþ7wnÅœƒÈ9~ÅŽôð„2ˆˆÌ³xãpa³øàãù²°~8à~8elxxleCÿ.kZµ­§{$IAw©P„Ë“XÝŽ|9Þ á'ŒwÇó–WŒ8«‡·^ÿáÎ6cß›~2ïÙÚ·føkí½FðI×E‡Ù± CSl•O'ñd c™ól³.Ë"QèÙa&A–å`ê8í“-l ißñià•6«ŽkÈÐ=¹l´ÆÔœAR÷p¸T¥WA ÀÄ©màÈ (ñÐÜ@uŒü˜€¬Bm F؆âtβ™ Ãã12Ö¶Æ8Ñ®DÜÝ–ª°€5ÐrÂ% ©ÉÙ.. J®„Ù‰ACd&FYGŽ‚BR›´VVM6ÆŒ#c3k ¯é ã©2F¶YM•­"§'hùÉRbÖä ”,XÑe=›—4÷…5ÀáŒR9®AÂáHE™4dð¢W #”:±'XŠŸÒ1»„_|•#k%ë”0Ýu‘ÀÛ´/Ô¬¼zˈMô¯Á&ÆÅ|ÂòA'3ɱÆà,axælƒ„{t‚»—©â°„\ÀíeŒ]½…7õËôq#7mŠôäXÛ–AEð€¦†3¹,Ê“åRñj4D˜§0cÜ,e¨lmF½:×Ëeókã96«Í«ÁI#GagV5®Ž 6Ž…‹¥W@ÀÄ©XnD2‹²$‘…I4²V6Ɔ#qxÞ¤ŽºHdGÁÒg°¦=Mc$ŽZ]‰U6 Ú€yñfÅ¥}Äð„ëÒ)°R ÕÈæ,4Š!(³' f’@©ÚZr,c‰$5·âç2¶·GÙLÑÒrF9­§¦ rÈÂ<2Ðþrö^ õJ‹")ÎȵÆP4ÅM¢ ŠF\Šâ)JIo$DµÕ`òçÀ×w¦´‰ޙܔ´ßUm}„Í«.§Òz[—{Ë2ll 0^GO „_8‚,–0Ý /棫aÂåêc æ;áHË0é\¯‹ÝHØ›‡·Š·vû*HhA½]›úÞ£y8¢A×õ}oSÛÚOÖõ^]¾³«ë<¾¯¬ÑåûžO—§Ýò¶{•b!HªB®Dê•#Qy"›\$í¯«Pžæ«7­ùvÔ뷯ȹ£VŸ*Þ½Z5{žîZ´íÙ·o–ükþð²þ²M]¨L6~G22!cº`LVVLì„ldm‡[‹«á 㪄l¬l­i9;;9*L¹e (²žÍËšCÞðà‰‡¼úúpà‰‡¼úú©Ýæ±»Îþ»û²ÿZà~ù7Ïéÿë¿þÊ??ü‚†Ù5Ñœ’# HùGòü¸8*6•ÀÅ$“n+~V*/ ϯè É8áÆ ÌÖ·|?"VÎÝÚ\^O -x‘è{ϯ§x‘è{ϯ¬ûË Ø„±T\Tø;ÎQö:KùNÒÈl±+ıéùú­#+5»êcsO£PZÔDšË •Äk´¹&Ñ)›dÖ7FrHŒ5#ä!Ëòàà8¨ÚW’M¸­ùX¨¿ƒ>¿ '$âBt ‡73ZÝðü‰[;wipMy>€¶<8âG¡ï>¾œ8âG¡ï>¾«R‰ÎI!4Äj¦(±4®üøB2ǨD¬ÈOD‚@Ã2XóH]Ç}$Ž/ƒ1¡¨lˆBÒ¶òöPbÑ’×$阚œ×C‘Ü%€çìŽÉhBc1¬#Y´ŸÉY’%[»jg^ µ»Îl1¤8•Ål/Œ\pgy0óJ½jîkêƒH8p ÄCÞ}}8p ÄCÞ}}QwÜçÂQ`À9›11dr<•8£–¹´Hüëeˆ×€Ê “±—ðƒâ„ìÅ<¹Ç‡ÝoÙnvìŠî質ÓPH\8âG¡ï>¾œ8âG¡ï>¾£ÚPH\8âG¡ï>¾œ8âG¡ï>¾£ÚPH\8âG¡ï>¾œ8âG¡ï>¾£ÚPH\8âG¡ï>¾œ8âG¡ï>¾£ÚPH\8âG¡ï>¾œ8âG¡ï>¾¼Õ‘re­_°:û~Åûz/Y½e¡Âå«Ö®iÙ®ÝÛW4'բ廚5l×£^»tëÓ·f­;vìÛ³m~œ"Wù0Cù•Ëöj’O#ˆb@iªG_qŒ]ÅŠS5;+tpP¡M†öƦÛ—%Kµ{»¢´Mˆî8-ok°¡]»î®M­Ö•.OøÕKÎzÌ£ò'ëF­¥Oe¼“Æ™G¯"”¥U)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥©îr ’ÂÁ-BƒÏ„Ή3 £È™ShóJ÷¥é†Â³ûŒŒˆT#mN¥E–1!²gk–ô aev|uP‘­¹b«7 ”ecä’†|fÇÖÏ' ±€áÇ(áÿ-öÆ¢Žc©]Ý¿UöÆ]cØFÊirLÈj"cîðÑ2B@¸ˆX÷ÉÉf˜l¶*ÆÂ¹’2Ï¡·þ‚|?Çiqs a,¥$0-‰PIŽY†ó8lÉ‹Ù*_¾'“b«lÃÆÌpä%"¯`0j•Î:F-Ǿ­©AˆgñSV9FÐÀÌJsÒ-‡²NÁxþ1'Æ8žž\DÕ0š7ÄñæI…CðNX1µœc«áÙ šˆõF<M|áxiŽf9I V½p„§‹Øö½úm!|ÈÜV‹º%º>±ì¸5¢/W /q-Í™5ŠÑš¯(´ALX¢ôfÔW°“ ÞI\~ÔôרQÉN´Òƒ%†a`·  {_NDÝÍ0‹lhMjÈQ"iaë‚#!°ey…8“å’õ6Ø­¨e²Â¿J—›´$UrÍɠ̇âäøï‡3|8øïÐÒu ‰…bˬ $®R‹¹fˆûcí R?$™Üi`F2ûê~”Õ@róå¹5¼_é˜dlÔl„4ÈyŒ´@µØd¬P™¥ðÙ0Ûò OƒÄ,n©Õµ½1½5«TÚìÒä•J T#Xžò{×-ê«8é8­ŠdšÌ¡hññ´¾ÜX%3•ŸK3$ÚH ¯Xê-Ço“|":F‘cc¢Ý®Z£èýPГ‚ô kÚ¨a¸Ú÷<Ä£ÙG£çdfqÀ±G<…\§\DÂ(Û)gÌkþHYb(ª']No!)1£+d‘Nb¬k’<…1ÌM»¨ŽÏ’Y®°2ñù›JqÖSO‹l}6Í·&¸l|J[,gŽ9•Äj]c°¶,vBù 㱑jQÒlYY~"Û-ÄNÊ„ XÚ>ƒéA«®â髎3ÍíP(™ÇMÔµºǃ3îJµMý"Ó–5º¬‚¢Q׉M s@/-à†Ä`NÕÄv…ÚØÄÌÙk£ò-Ì{a#n(>8½c§ü#;¬ðNF²+v²¤r!’ hFpQ`ªäP½Žm`D³m›)e ÒLz ”4éèÅÒÝ?Aô ùu$'àbì@9õ+ôçž$#w•ú7±”Á²=Çó€U ñÿ£Òð66¤ì’>˜éŽG"”1öñ#ÊH›'YBKQ*¶)ÖœöƳ3Ž×cäK䱨è{éQƸÔxE‘¨B63‘ûŒ Â*Gk›ãÀ H&ô„%‘ÍÈ}ªÓƒú”[±‹;¨nØJPbþLœ¸¯l%Ådò˜’~•7L7_}ÐfBÆébÈ&³»ƒ¹ºÛK-0£äYŠ¡I&ºíM0N6q«¢èu`Ð…GmÚbvÑFñp8ªxC‹ãÁcŒv Š£ˆÕ„¨³ËѰ¬`\Ì ¢Ú1pŒx|Ô3*¸¿´§OÊPÈáqÈòM*ÄÓÑ÷a‚™ð' ƒxŽjŠÂ #èÀ¡ô„©Ýª8a8Sfñªð07ÅàÁzDéÇŠ$ÑáFé$€2ÅWbÅa–´1i›è=ãXÇ÷…—õ’j§½'c$†¸YÒ<øZ^[‹Ùf2((2Ò½ø˜‘ú(?jccjN­ÑéñéÑZVÖ––ÔªW¸¯R4÷”^·oUÂükþð²þ²MUHã7ñe)¡z]²Ê{S'Ú©¨pÑé­NÛ.ÊííPÚòÐ6¹¥Ùï'¬FæÖµcrôú­ªD©Bk¶®ëV"ù¡X‹æŒÏËœeÿÎÊì|ÿ™>Æ\qà£ÿx®üÇÈK‡˜>!·´P ÿd}±ƒñ6¡ ÍêQôÌÀXA7ËÒþzòŸ»i¸N5s:6–7ö(B¸ïqtø2ÈÞî›’Ñäƒ/?÷1йNÂî’c‹ø…ÀŸMËÚïߟ|Qô&Eû£Nüø³â¡2/Ý•ŒcXJÆ1¬2#4„»ïN 2ë„|Á)æ0Cƒ˜ãW5ƒ&6lŒã8ùé}­3€˜™Æ/OPÔ£'±FRÁL“mÕü]óå NO}ñmhÉr¤¦9–c®‘g1ŒÑ8ÅÎÄ\KÅ v6ɈÚôÁìûï$&\t“àóŒx—ÁdóG.zd69°Ãì*¦¸{«'*t'sÚîüø³â¡2/ÝwçÅŸ} ‘~èÒ±ŒkcÖšÌBfÛo¦˜Ä+Â$ ~g8ÚÝK`­VÃ2m¨S£SchàÅØ•P£|)—ÖÉàh\ Ñ5:½ÊÌúÞX–(µm°¤£&5lc Íé0â_èCÍì'a!Ÿ°!°À™½à3 £\\jiŒ`H{’¡ ›¶CÔ®q>6Å–wW}Þ8äYñƉ}>¿¡Þüø³â¡2/ÝwçÅŸ} ‘~èÒ±ŒkcÖ–r˜ç&U‚t‹5ÄWGSD."å½Á“ œ ¦/›ò=tß‹E•˜u4Kð×6[äx¡Î?G"‚B0ÜÔÚôèm =·…©kÛÌeŽ¡ÌnÇȉ‰˜àqŽ+„"ˆá˜zMq w’XšÀØ[™¤hás¤xèpÖ‘®ÊÇ7'ůÖ©\­Žê#®üø³â¡2/ÝwçÅŸ} ‘~èÒ±ŒkcÖÒ•RûóâÏŠ>„È¿tiߟ|Qô&Eû£JÆ1¬ŒcX[JUKïÏ‹>(ú"ýѧ~|YñGЙî+ưV1am)U/¿>,ø£èL‹÷FùñgÅBd_º4¬cÁXÆ5…´¥T¾üø³â¡2/ÝwçÅŸ} ‘~èÒ±ŒkcÖ”´y–êÈR !ÆvQ1æ],ø£èL‹÷F¤ög÷yîåç)=™ýÞ{¹yÉœþõ™GäOÖ([JÌL­ÊØ J€B‚wÑ3× nÆÎ4ní;¸ÐuÙoï×aÔ öz–ô Ô~øWk¬êº«^]ývíëÓº±5™¦ê±5™¦êR”ª¥)J)JT¼ç÷¬Ê?"~±DjÚUKÎzÌ£ò'ëF¤Ý;§‚MÓºx-¥)Jª£ï†ÿ¤¿b¨ö¤(ûá¿Åé/ت= R” R” R” R” R” R” R” R” R•OgÉòm ›a¨†¢ÉL¾S‹'™uÉÊ]žK`±±‘¸,·V!B°72Љð‰Ó!™ï¦M}œur×+·\•¨V•.¸Tª²Ç-ÏŒja–Iº"„ å¹¼‚3Ö†8Ê'LaPŸ.·˜³)“àÜ}'‘Ž“Æ—ƒÜbPÇWV0Ç%ÓÒUƒ†­¬}Þ¼ÀÄ«cf¦W2-ˆFÌq4ŠW®m4€Í¨Ýa‚WÍDÛŘåÖ·f§(ÁÙñRÈÛÖ (vNµ5ËbéT†IéÂX­«Љ²ZÕdùÁÀLa*¡™"]±uþ\•—8œ¸·1Ý|O<¿( Ýñìp ì‘ ² Jy=/„¬Ä¬c«ä­%ÏÒèR&o¶s²'•&OÒy¡ÞÐD%ަ¤Aâ’„„‰}ÁbY‘B…ábéYÔeÒ ÕŽL/ŠóŠ3îʬ|ã@ìY“C 1ºIuÉ™$„Šô-6rMð·’ÌcNò.O1EiœLÆ@lÎ.}[8.±N‰M$‘€k®Qã£a|ÚÆM 8M±¢"ItnI_­ª:!ŒÔ“[t>c>t·q´)ØQ+²•öõ£cP½FVö‹¥B5ÀælQÁ®AÂIŘÈd ¢W3#’T5¾§˜…ÝŸÒ>;œ_c•#›"mèT?]j‘ÀÜt Ô¼zóŒ¦BL6$;©Y ËZ·Á‘”®D.ÈP)$5$i N±ÉBd÷Ÿ KߘÅZmÜÔ½ø‘饩:·Gio­hA½]›úÞ£y8¢A×õ}oSÛÚOÖõ^]¾³«ë<¾¯¬ÑåûžO—§Ýò¶{•b!HªB®Dê•#Qy"›\$í¯«Pžæ«7­ùvÔ뷯ȹ£VŸ*Þ½Z5{žîZ´íÙ·o–ükþð²þ²MBïÆ²ï ×ë%4‡‡¼Hô=ç×Ó‡¼Hô=ç×ÕÊÀÂ̯“qU^­ò=@ú˜‡¯u×ÄlHãâi¨tÝL‘§”QæFá¡§\"ZÔ}ÞS‡ìÞ|‡%Dì~Ü£&±¸ÍŠ85È8@BC)8³ ”JàcædrJ† 7Ôñó»³úGÇs‹ìr¤`ódM½ ‡ë­R8Ž„’^q cÀ^$zóëéÀ^$zóëê§dÖ7FrHŒ5#ä!Ëòàà8¨ÚW’M¸­ùX¨¿ƒ>¿ '$âBt ‡73ZÝðü‰[;wipMy>ŽŽ/ȱ¹`ÈHYV†1¢øJSÔÆÎ µÒI,m·qZo+‘E®#mtoctÊÀØü‡J=¤HÜsr|@ é©…\Þñ#Ð÷Ÿ_Nñ#Ð÷Ÿ_T^GÎ|%‡ Þc‰w11f+Ç7wÈùƒ™±ov¤/­;ä\˜¹­ñ¯z1º6¼·vä6;kSŠÝjEiï\îϳ¢‘¸ìÊQʾœ8âG¡ï>¾¢äÃjɃR±©/ac&|Nì‚ñ#(Ùjòf¡Bf;j5:71“:6;,KeÒñ"dmª¨au¶“¼ ¸p ÄCÞ}}8p ÄCÞ}}y«"äÊ-Z¿`uöý‹öô^³zËC…ËW­\Ó³]»¶®hO«EËw4jÙ¯F½vé×§nÍZvíÙ·fÚý8D¯ò`‡ó+—ìÔ$žGÄ€$Ò)T޾㺠‹¦jvVèà¡B› íM¶/.J—j÷wEh›ÜpZÞ×aB»wÝ\›[­*\Ÿñª—œþõ™GäOÖ([Jž4Ê=y'2^E)JªR” R” UKÎzÌ£ò'ëF­¥T¼ç÷¬Ê?"~±DjMÓºx$Ý;§‚ÚR”ª© >øoñzKö*jB¾ü^’ýŠ£Ú)J)J)J)J)J)J)J)JgVIãºiã6±eABY½º<Ŝ۲êk KÓä ºLÈå¬Ö.G'À'QÃæ®)cgv5,R¹y€+*„‰ï ²i«1 ,7ô\ôp³’G™ÁÑdc©ÿ`ôsn7M¥xðL),Ÿ¾ã¢øÊSt8|8t”å¶VgÛŽsYkQlÖó*ˆ ("›c  ¥¦›Z["òQc”åˆþ"é1‘¥û“]¬8-‹r¦]ÇB~‰—A$©»#Hцb-”ãÙŠQÅ;ÏÃXäöS Ä€³~ØÅ‚±|ïf™eÕö«±³ ñÆ)÷»…JÎ['à^ ‘x.da%9Ñ-òLÁ+‚¹ïƒd1ü©ŽšHeçõÄÑhqÙ˜«P9¦¥¹ ͤÁ3-Èø{0Š0äS轚 ¦|“i-"›u^€ó¦ÌߜΠbÒâuÝ!&LlQÜ| ø.’íOÒÁ©kkè¦)’Åï+ YÈøm’R˜:BY$HˤÅ@&{¾b9PF6a.: ä|Nÿ°L@8œò^É|^.ÆO¥pé,À g'æœZ½ ¼Å+GM-GoïÏk~Ÿ©Aóq•6Ê[:t FÜA”çIŸ+%8âŠH``Ù|„¯£ã ™¢éS³²øÜ(Ç‹²Yó|õ¤ß#"ÀaO‡Q!´€;$² o¤Äà6Ø$Ф®0|—ZîJpczQAà¤ËÚI¦Øù¨6OPÆå®Út p‘zÖ9œ˜ÖÞ­«ãa°i«EÇAdvõw‚qÀ`;ôšL.ͺß&3„<Ž»xº­â36¸Ú>ˆ¼ögÊÒ4uäV=»˜“µµ]Ü[ÚòŽ.N>ރЈþ5ŒxYY&¯=›rÍŠh‘øDâ@åûLŒmÀq“É&Ü(á÷„cá~Öƒ‰ ;æ`íÈ·ÃòÔ Ý­7ië´{qƱï /ë$ÕTŽ3Rš¥Û, Wµ1A}ªš‡ šÔí²ì®ÞÕ ¯-kš]^òzÄnmkV7/OªÚ¤J”&»jîµb/šˆ¾hË;¸«ŸÐV:B&å2Ö:Kø¥)ÙÌÃÀX3æ•3l™!½g l:`ó”Ï †²žA‚MyJªÅp€g’ÙU¡¶9Æ5Éáþó#±—Ž ø@¯8ÄâvßœµíG•Lœ°èËÆHp7XÀ­ÞCåæC$6åVàß%3¥*áÞqaßÉÐŽüø³â¡2/ÝwçÅŸ} ‘~èÔ¬cÂV1a†½%±LÁ#ô®Gûb,‹K¢\ÇHÏ\‹8² 6i^„‰íä¾Wij#úÉN•Û^GD#Üf–#Øî1[‰-òäå-‡§ÛpŠlºÛÍÞ–ás.Be8ÆZ¨33ŒÈ¥¼;ÕÑ©ƒ#ÙUm4b 7uÞ¡†ïq‰#€(Â<âÇx3LС§“dm-ºߟ|Qô&Eû£P„ý,tyecTq=?ód'eî[Jp^;dÖFhužä“e̘N>âdm,¤Bq‘ãž7dƒ‘0Y˜Ž7F0Ãv) оH¢r6BW Œd‹ŒªÓæð><ȽQd#µá·Gü18q8¬|y9Ÿa| M¸‘;›ã·ÊÐ’qÜø† øx V\#Lï4³Œk¿~|YñGЙî;óâÏŠ>„È¿tiXÆ5‚±Œk+ÝM¨§£w¸û£ˆ­Œ{©³.“lI1ÃS¼Ê&åR hà‰zÄ£ô­˜ŸÒcgh:K/­qV:ÎÑèÜA'¾FšÖ3”kÈ‚\†ñW3˜Æ ƒ¬̧©ÙÁÚÆÖŒlj)µ5€‰é'~|YñGЙî;óâÏŠ>„È¿tiXÆ5‚±Œk QËl{FK½%1̳t‹9Œf‰Æ.pà–"â^(K±¶LF× ÈFgßy!2㤘ßœcľ 'š9sÓ!±Í†aP55ÃÝY9S¡;Ÿ·ÌÑ.¥LÌå„|½/ç¯)û¶›„ãW3£icb„+Žð÷OˆÓ,á¾é¹-H2óÿxÓ«”ì.é&8¿ˆ\ ôܽ®ýùñgÅBd_º4ïÏ‹>(ú"ýÑ¥cÖ Æ1¬3ÞkÆ^:ü!Ûë8ÇžÝ)½;ÿzECÎLnŒ?‡oŽÖÀ¯˜p„yÙ2ˆûnøì³.óÝýA·“eÔ-!9É22Øó"öôÐA3òó(še¨õ?DÜ-£¹IJÌe.³ËlqnG?ŽÙ)sâIXäÈqéx³¸¿Sî­÷çÅŸ} ‘~èÓ¿>,ø£èL‹÷F•ŒcX+ưÌŠ7jŒÇbŒ”3yx:”Ù·'ç‡ùÏCçÃdĘ;=á×>Bñ'¡À™;@D™'(ú"ýÑ©=™ýÞ{¹yÊOfwžî^rg?½fQùõŠ#VÒ³+r¶’ #Р£ÝôLõÂÛ±³…»Nî4v[ûõØu}ž¥½µ¾Úë:®ª×—]»zôî¬Mfi„z¬Mfi„z”¥*©JRJRU/9ýë2ÈŸ¬Q¶•RóŸÞ³(ü‰úÅ©7Néà“tîž iJRª¤(ûá¿Åé/ت=© >øoñzKö*h¥(¥(¥(¥(¥(¥(¥(¥(¥B¼ËËÌe áÍùÞ2o†·žøÝœ¸ñ» òˆûëpâÕÈžÜý­¨â­ÿ½/n=Êð}+ÄHòlm<Èòì‚ǃ›»ˆO$rÆpÆ-îê…‰§|”/kckÞŽ¬ÍݹuŽÚêâ…¹7Z­Z{7ppJ¨fH—l]—‡eF¥Î'.-ÌwBÓÅO/ãÊ7D¼{;$B¬§B„’žDÏKá+1+Äjù+Isô§z‰…[߯Äíœì‰åI‡SôžhD·´EƒÂ c©©x¤¡!"@ŸE°X–F$P€axXºVut‚µc“ â¼âŒû²«8Ç;'VdÐÂÌn’]rfI!b½ M‡œ“|-ä³Ó¼‹“ÌGDZg±3‹ŸG–ÅÎ ¬S†`bSI$`ë”xèØ_6±…CŽlhˆ’]’WëjŽˆc5$ÖݘÏ-Üm vJ쀥}½hØÔ/Q§U½béPFMcp9›pkp€„†Rqf2(•ÀÇÌÈä• @o©ãæ!wgôŽçØåHÁæÈ›z×Z¤p75$/¼ã)“ ‰ NêVBÆ2Ö­ðde+‘ ²T I ICCG“¬rP™=çÂÒ÷æ1A–›w5/~$zicjN­ÑÅ[ÁëZoWfƾ·¨ÞN(uý_[ÔöÅ6“õ½W—o¬êúÏ/«ë4y~ç“åé÷|­žåXˆRj«‘:¥HÔ^H¦× ;kêÔ'¹ªÍë~]µ:íëò.hÕ§Ê·¯V^ç»§V­;vmÛ儯?¼,¿¬“WG* …_‘ÌŒˆXÄ„®˜•“; aaÖâêøBBøê¡#[++ZENNÎÎJ“ n@™BÅŠ,§³ræ÷¼8âG¡ï>¾œ8âG¡ï>¾²¢ÎkLì‚óü«†§F.—ðµ/DòHª|š‚XMX›KoŽML±ä)Gi»˜K$â™/0I1<~¬®L‡Ä- —QCv˜£&±¸ÍŠ85È8@BC)8³ ”JàcædrJ† 7Ôñó»³úGÇs‹ìr¤`ódM½ ‡ë­R8Ž„’^q cÀ^$zóëéÀ^$zóëë0ÿ¦>“Ì‘LsLð6EÃp,;NÐøKÞ¤…Ž@‡²PÍ…¥n® qC¦BiPÀ½™×"Àq¸u‰Ôv㋽“XÜÔ¡‰FAÂÂ$ÓVkÒ¸§QÚ+3}Ž$ù¡»[þ•cáĆ,LxXíe#˜ãè¹ öçÆ‡)ÂØðà‰‡¼úúpà‰‡¼úú¢çoÇî±± 40cÌÍZ²,¢‹…52ã°”wu‰ãÊn7“¹øE™PyÚà`£ª 1—e*]æp {°ÀÄ©XnD2‹²$‘…I4²V6Ɔ#qxÞ¤ŽºHdGÁÒg°¦=Mc$ŽZ]‰U6 Ú€yñfÅ¥}Äásxp ÄCÞ}}8p ÄCÞ}}V¨Šs„²mq” 1E“hƒcâ‘—"¸ŠA’FÛÉ muX<¹ð5Ýé­#âF·¦w%-7Õ[_a³jË©ô§^–åÞŒe⹞y„ž‡8\žåqSðÆûæ1. ¬áW÷£ZfñNÛ/Çùð2×g2¤Ü•ãç4í£8Om cÀ^$zóëéÀ^$zóëꋌå”l 2u—¤—àˆfˆ&òØižj‘ä60Âþ^:Ågäo*Kí ZŽ8(´ÊXîÜÎJªïºÆ¨N„ÝÄä€ëªe:)Äljø"o2ºo/†‡¤øâCa% kàÈ$fgb6gÁ›Dlf•ó\£‡t/-[­Õårå.›UŒ(t ÑÀ^$zóëéÀ^$zóëên“cgv¨áõ¦Atc˜û(ž[‹VµJ›Ð1æGmåÊe÷Roðp„ñ ÞtíaŒO% úÆ6µË¬Ezó­š™\ÊøoñzKö*jB¾ü^’ýŠ£Ú)J)J)J)J)J)J)J)JP\à{¼mrŠ ùL´B,Ì"RiäEK¡ ÈÛö f´hØB¸ >;¸Çpìø4iK²1µ(—‘6írP‘=í·ôߪPcÞuIî³ÜBqlÞ¤`7¡%™ÛßG‘™ÆMc¸`òg'5™xÍ–±K;áÃ;à(>ÙŒœc8üâZ9 ã§V¶š±5 Žå»‘pŸH°Sƒ'H³6UE͇a³ãbi»c˜©^L!„ã¬e½KØp½7Å2<|#ŠÒ„ù©˜[ò²…eö³iV8ú+¥¦›Z["òQc”åˆþ"é1‘¥û“]¬8-‹r¦]ÇB~‰—A$©»#Hцb-”ãÙŠQÅ;ÏÃXäöS Ä€³~ØÅ‚±|ïf™eÕö«±³ ñÆ)÷»…JÎ['à^ ‘x.da%9Ñ-òLÁ+‚¹ïƒd1ü©ŽšHeçõÄÑhqÙ˜«P9¦¥¹ ͤÁ3-Èø{0Š0äS轚 ¦|“i-"›u^€ó¦ÌߜΠbÒâuÝ!&LlQÜ| ø.’íOÒÁ©kkè¦)’Åï+ YÈøm’R˜:BY$HˤÅ@&{¾b9PF6a.: ä|Nÿ°L@8œò^É|^.ÆO¥pé,À g'æœZ½ ¼Å+GM-GoïÏk~Ÿ©Aóq•6Ê[:t FÜA”çIŸ+%8âŠH``Ù|„¯£ã ™¢éS³²øÜ(Ç‹²Yó|õ¤ß#"ÀaO‡Q!´€;$² o¤Äà6Ø$Ф®0|—ZîJpczQAà¤ËÚI¦Øù¨6OPÆå®Út p‘zÖ9œ˜ÖÞ­«ãa°i«EÇAdvõw‚qÀ`;ôšL.ͺß&3„<Ž»xº­â36¸Ú>ˆ¼ögÊÒ4uäV=»˜“µµ]Ü[ÚòŽ.N>ރЈþ5ŒxYY&¨C2!®ñÎTãçðw=£ÆâíÏÄ<+ÌñR€ž#ÜÑ~n=ù¼÷>úgÞ}—±oFþ¿µÙ›ÄÆ?¼,¿¬“UR8ÍüYJh^—l²^ÔÅ öªj4zkS¶Ë²»{T6¼´ ®ivA{Éë¹µ­Xܽ>«j‘*Pší«ºÕˆ¾hV"ù¢‘MÓ$±–˜¾u‰wq"âÌŽÈȲì8 ŠY]âð”èÏf9”¦”ùJ©@ö2ä£<(o~@Œ iPŠm”ïXi x"g„’Ú¨jåM²–ηe9ÒgÊÉN8…â’˜6_!+èøÂæh…ºD”ìì¾7 1âì–|ß=i7ÈÇȰASáÄHm É,‚Û'ߟ|Qô&Eû£^ O(0”úM&8Ýo“ G]ÃRÒÞ#3k£è‰ ÏfqV‘£¨"°1íÜÄ­ªîâÞ×Ü|tyrq•ŒcXJÆ1¬*TÄ&rç,c½1´¦æÿ,t˜ôbex€ô[!ƒ=A1´…ÑGÈJ%ѧHщð,’ –\‰£r"Ö™=–=v—†ØŠ5"4WÑÇØËïFߘùÿ=çH®MJ;Ú(ÿÞÈlƒ>íŒáÇ”r¹ý‰pkÿâ%hG~|YñGЙî;óâÏŠ>„È¿tiXÆ5‚±Œk Àr—±¸:p׎S|…Á‡A ‘‘x¾QySu×#ºdq¹Úq}N Hè‚ Â¸M7žB£ÉÍÊ<“câRá»Cά•aȬɾÊ|‚›ÜŽ1JÉ'b "’aY&P¡ü— #|a„³š,fŒM"ØÄ>Xä¶.èç ‡ç»ÜàÓ0Íù!ŸMzߟ|Qô&Eû£Nüø³â¡2/ÝV1`¬c³t}„ Ü™òþth·›ÅòWwøøºoÌœw†1{œü£4w`_F¡00Kï¼ß+\/“føa³î1p¸Ô°¤b8Wm’SÍ™´d’#É|kc3™ÁXå lD(`ÒZD¤o.WÆ C§,`IÓ•ìc‹òj)Æ3Yœ¢Óò4X‚Û”dhX‰dqý¶é¿>,ø£èL‹÷FùñgÅBd_º4¬cÁXÆ5…JɈ0o¡¾ŒöHvSÈè7r.´HÔ= œå†ô§#í»œð·µL»ÏxuæÞV„wçÅŸ} ‘~èÓ¿>,ø£èL‹÷F•ŒcX+ưùýi†Ëb¡¼l+™#,úkè'ÃüpV—0–ÊRCØ•˜åXo3†Ì˜½’¥ñáÒy6*¶Ì,ø£èL‹÷FùñgÅBd_º4¬cÁXÆ5…´¥T¾üø³â¡2/ÝwçÅŸ} ‘~èÒ±ŒkcÖ”´y–êÈR !ÆvQ1æ],ø£èL‹÷F¤ög÷yîåç)=™ýÞ{¹yÉœþõ™GäOÖ([JÌL­ÊØ J€B‚wÑ3× nÆÎ4ní;¸ÐuÙoï×aÔ öz–ô Ô~øWk¬êº«^]ývíëÓº±5™¦ê±5™¦êR”ª¥)J)JT¼ç÷¬Ê?"~±DjÚUKÎzÌ£ò'ëF¤Ý;§‚MÓºx-¥)Jª£ï†ÿ¤¿b¨ö¤(ûá¿Åé/ت= R” R” R” R” R” R” R©ìù>M¡Sl5@ÐÔY)—Êqdó.¹9K³Él627–ãÀjÄ(VãÆC:>:d3=ôɯ³Ž n@:åvë’µ Ò¥ÓÑÂYžÔF+.]ÊŒHày¼ú ‘Ø‹&°ÂhÙÅÔ6iÉä&‘”¬âé`Cæ.5ÍËö”‚Çf`ì-2 “PÆd‘óËÍлԪ²'–ñ º94¬¢F„"Ác„ QÄ§Ïø¸€VT QŠöZ®<íÏ6’îèðŒð«…ßW¨uW GálÞÓ³:ØðòOHîÅmXìTM’І¨ó'Îc U É틯òà0ì¨Ô¹ÄåÀ幎è@ãà:x©åüyAè—c€gdˆU”èP.õ*¬äöVb¢œ~]"%ìÀó<Þº &:½}ÖÛTLÔŠ&åaE¦‘×þ¬!““[O _ŠFAo²éñ‹<~Czã42°3 ñºTÈä¼@¬ áô&;I}ÖÓôªf&R| ƒKé{â~ÐÆ þD\PUñª1‡ ¥Ãk-Ñà sãPZjT m“XÝÉ"0Ôp„/ȃ€â£i\ RI6â·åb¢ü" úþ€œ“‰ Ð.`ÜÍkwÃò%líÝ¥Á5äúÙ5Ñœ’# HùGòü¸8*6•ÀÅ$“n+~V*/ ϯè É8áÆ ÌÖ·|?"VÎÝÚ\^O &úT m“XÝÉ"0Ôp„/ȃ€â£i\ RI6â·åb¢ü" úþ€œ“‰ Ð.`ÜÍkwÃò%líÝ¥Á5äúÙ5Ñœ’# HùGòü¸8*6•ÀÅ$“n+~V*/ ϯè É8áÆ ÌÖ·|?"VÎÝÚ\^O &úT y“Xݙَ$üƒ„#‰ @Cìšœ òW3¿ 5>“H6EÈ_ÛŸ.„1ƒš¼¾–hC©…¡¨@¡ÅÁztƒî×’ ²k£9$F‘òåùppTm+ŠI&ÜVü¬T_„AŸ_Ð’q!:ÃŒ™­nø~D­»´¸&¼Ÿ@Mô¨@Û&±º3’Da© áþ_7ÅFÒ¸¤’mÅoÊÅEøDõý9' \8Á¹šÖï‡äJÙÛ»K‚kÉôJd$ÃbHº•±Œµ«|JäBì•’CRFÐÑäë”&Oyð´½ùŒPe¦ÝÍK߉šXÚ“«tqF–ðzÖ„ÕÙ±¯­ê7“Š$WÖõ=±M¤ýoUåÛë:¾³ËêúÍ_¹äùz}ß+g¹V"Z¤*äN©R5’)µÂNÚúµ îj³zß—mN»zü‹š5iò­ëÕ£W¹îéÕ«NÝ›vùaƱï /ë$ÕfDËÝÎÊœƒáÎ1äLc8̼#¾8{й`*PmÛÿu¾n=ù¸÷føÜ¯³µvÝÖáÔvKÁd8p ÄCÞ}}8p ÄCÞ}}V¡éº'%‰ÔNHŽ˜Ûb†Ö2b3"Ë·P ¼ìŽCO$¥5²>é>FNƒäLRÌ€„h’1$%=izmC]#<ù€Èñé¿$æSpŒ^fùî]fi¡Íâë NsDÏiÍ4ÊÙ> 1Ãb²6&ó0~±è]á2ÕbnŽWCH8p ÄCÞ}}8p ÄCÞ}}TãlšÆèÎ6™d|ƒ„#ø‚@Ü*›Jàb‘±·°«*á—×ôœH0qæt[¾Q+xní-é¯(Ñ?ç¾% M°, ë:Å–Kòb,[.Ã[dèÒØÙÀÚ’ØÔ6:B8±I‡BgÉÑÒG¹~ L(Îü‚NAÊXܵ(Ô•ph'x‘è{ϯ§x‘è{ϯ¨ö”x‘è{ϯ§x‘è{ϯ¨ö”x‘è{ϯ§x‘è{ϯ¨ö”x‘è{ϯ§x‘è{ϯ¨ö”x‘è{ϯ§x‘è{ϯ¨ö”x‘è{ϯ§x‘è{ϯ¨ö”x‘è{ϯ§x‘è{ϯ¯5d\™E«Wì¾ß±~Þ‹ÖoYhp¹jõ«švk·vÕÍ õh¹næ[5è×£nÝ:ôíÙ«NÝ»6ìÛ_§•þLþerýšƒ¤“ÈâšE*‘×ÜcA±b”Í@ÎÊÝ(Sa½±©¶ÅåÉRí^îè­b;Ž [Úì(Wnû«“ku¥K“þ5RóŸÞ³(ü‰úÅ«iSÆ™G¯$ñ¦QëÈ¥)UJR” R” ©yÏïY”~DýbˆÕ´ª—œþõ™GäOÖ(IºwO›§tð[JR•U!Gß þ/I~ÅQíHQ÷ËÒ_±T{@¥)@¥)@¥)@¥)@¥)@¥)AY'Žé§ŒÚÅ• föèðGsnË©¬5/O&é3#–°Xx¹ŸGš¸¥Œ|ñÙœ ôšëQ7ºÙbpV¡Á›Ãža$1“ôÄfôºEòjW\ø”ªcu¿$ºaÞi<¤È9šG‘Vœ‘œZšœc#ò¼”PèüÐgn0baD­¬%¹&¦ÒƒÈ`ÂBÜÃNêW¾$頜ҹÇËÞ„“ …t4††ÌIÖ94)g²Æ%‘Ì,bƒ2 »šP0ͬ­,mNéÛ‘¥³Ñ¸ÅްÆ@Èó|*pÍGý0«²P³d[ ™•º½†J] ,ÐI,´Å¢OÇÒ÷ål«­ýî04u¶f¶E35Ú™¼>I#`ÛÊPR¿Œ¹©"à“´}Ìxñ>SÉ|Ýfqâð˱OG–vG\ÇnRÅŽÐAáÀðî&³¥…ÝÔ½˜]GhV@… ¼êšqó$d,YÍIM°âVWˆ8C–X¹Š½¡áÌ’’L›ðîE:q*Û³ßs_`(4»£~דR7I|\„}|x^×o(>grÛÑ’ä/ILs,Ç]"Îc¢q‹œ8%ˆ¸—Šìm“µè2ƒÙ÷ÞHL¸é&7Áçñ/‚ÉæŽ\ôÈlsa‡ØT Mp÷VNTèNçi³™„Íû$˜ñÅ^SMSG ”rß ²£ó”ÏlmF›Šo‘ù) $†&xò?cĉ*É–Ub‹T`Úru!BóÍ9“o)AˆyÌÂfÆý’Lxâ¯)Ʀ©£†Ê9ï† YQ€ùÊg¶6#MÅ7Èü”Cr™í£ÈÓqMò?%$ÀDÏGìx‘%Y2ʬQjŒCnN¤ hCy§2kLÄà6Ø$Ф®0|—ZîJpczQAà¤ËÚI¦Øù¨6OPÆå®Út p‘zÖ9œ˜ÖÞ­«ãa°i«EÇAdvõJt ô"?cÞ_ÖIªžôŒ’ágHXhhóáiyn/e˜È  ËJ÷âBbGè ý©Œxy©:·G§Ç§Ei[ZZ[R©^â½JthÓÞQzݽWGñ¬cûÂËúÉ5U#ŒßÅ”¦…évË(íLP@Ÿj¦¡ÃG¦µ;l»+·µCkË@Úæ—d¼ž±›ZÕËÓê¶©¥ ®Ú»­X‹æ…b/š)ô’JéñçX›<¬6Éó†ì£˜<„OÛZ…ùp¥y uIØÙuÅŒ•)ªÆÃ"Xˆ¡Œƒ¼8aïK1 á"/*¬ˆ±ºÀ³V+Ï’þ3Íæ@áSN¸u’°(ú"ýÑ©XÆ5„¬cÃ0!˜Ýª+ÅÌo=t3{ß.œg«ÜU1¤2^’`h+rñ÷!±®QÆqXs/’G(ú"ýѧ~|YñGЙî+ưV1am)U/¿>,ø£èL‹÷FùñgÅBd_º4¬cÁXÆ5…´¥T¾üø³â¡2/ÝwçÅŸ} ‘~èÒ±ŒkcÖÒ•RûóâÏŠ>„È¿tiߟ|Qô&Eû£JÆ1¬ŒcX[JUKïÏ‹>(ú"ýѧ~|YñGЙî+ưV1am)U/¿>,ø£èL‹÷FùñgÅBd_º4¬cÁXÆ5…´¥T¾üø³â¡2/ÝwçÅŸ} ‘~èÒ±ŒkcÖ”´y–êÈR !ÆvQ1æ],ø£èL‹÷F¤ög÷yîåç)=™ýÞ{¹yÉœþõ™GäOÖ([JÌL­ÊØ J€B‚wÑ3× nÆÎ4ní;¸ÐuÙoï×aÔ öz–ô Ô~øWk¬êº«^]ývíëÓº±5™¦ê±5™¦êR”ª¥)J)JT¼ç÷¬Ê?"~±DjÚUKÎzÌ£ò'ëF¤Ý;§‚MÓºx-¥)Jª£ï†ÿ¤¿b¨ö¤(ûá¿Åé/ت= R” R” R” R” R” R” R” R” R©Æf0´•3@É;{PÅL/Hzõ){cKÂB†÷¥äëö„j/YëÒ(°¦Ï—ÖX½jî:ôÈ,8 ‰k_Q©‰úÔÊÝ›“(·Çr^޲Åõ–m]ÑåÛ2ÑsG—o^­>VZué÷}Ý:¶jÙ³nÏÇßÔ7õ¯øYý5|ÿøsøsó×Ëÿ?ü[ã‰ÝÏäkå?…ü»×¾Õ;ÿŒõì~oÓücæ¯u¾¯N·Öz>“kû.£ñ uhÛÛŠô±×¾øOËã=[®u¾«ÒuMŽ©«c¤é¶6ö©ÑOKþt}_¥ÙŸÓ«kbÜ­XjWdðÔÖÂîêÆÆÚ™•™ÉsS;;R4íÍmMmÊ®£ommoGnÊD(¤³e*4ilÚN™=«v,[ÑkF;>p¥ˆN*–玕¤…]¿„áÖo’¿™fííݸ]mž*ç|Ë6ä4IØÝÜ”?ñÌTAÀ|gÅÀÊNº4#ý‚ô/¢ºVÊÙ#˜Xœ7ŠØ’É3ã¡^G `+itpšϬÿ›f)¶9@*.!Å¡6“¸‹ Nö¼ívÊÉMÀØ´ìµõC0ü ¡à,¦û¥‹Çܺɲ’bn\2B4@O„8 ›œlÚy*É(ûÕ¿d7A¢;ˆ–'½× DèwàóÕòñù…^ñ‚¥æù6Ï&ÃSiXOŒ}%“Ì­‘xô&@뎒Ì1’RžODVñâÍÆ8ö/$ˆÙ&9=]ç<À׌¹ÄÆ´R;”ÆÃrý§*Ò˜F¦qøÉOg«0&BœâÞ+6L1x£¤–“¡þœw± ž†öÎS&[A¢O„#1©´®hÆ(ÿ#7•;Æ#’úUazR>¶®JOÔ¬ ~Ɉšã©*níc¾ot:>ÄÓºLËŒ+j“Z¤>Ü~J\ãeã{‘:3ˆœóƒÉ@,Ÿ!†IÑÆ»¶C‰Ò?²ÜÓ´—fØáãàd1eâüŒÈ·hMÉâ]LZ¸l4m6/ä¬Ö°å Xk“C¡à›¤4Îî˜û› %‡(ÞéÔL µ,¾ •–P¾]d‰œzOd„6G’æSäÞ §nm< šKA6ĤØFé:E‡/ Ë’°I}ŽH$ ‡àè¢èi|8Zl4:u9³ˆ½›ìR°Ÿ¦¼Ë‘a(Ãæ=ˆZÂz%ºåÖH唓rá’‰¢|!ÀlØ<ãfÓÉVIGÞ­û!¸¢ ÜD±8Åî¸b'C¸'ž¯—Ì*÷Œ/7ɶy7]0‡¤[0²NBÅw²è•l1”ìr)1 †çÔa{F׃>ËÐ Æ_ÌÀ©ñ—)XßÅE‡îÀÌÐ’²Áøq6¢Hí«¼¨7b•„øÇÒY<ÊÙBd¸é,Ã%)äôEaÿ ŒÜcbòH’ccÕѾsÌMxËœLkE c°Y Ll1/Úr­)„hÚgŒ”öty.å®@ô?dDä‡ãLȲ¹²9ŠIiaQ³¾Ž<ñ,‰Œ Üž'ÇÇè ¡ ™áˆCG’’¶YTlîÉøoñzKö*h¥(¥(¥(¥(¥(¥(¥(¥(#ã˜Ý’Ct‹•¨_¥®6•å=M­·l¥Pü´MÞ–†kŽ7¬«ØÚ‚ó»’n·ì¢R­SZ%Hn5¬p°ö×d’›ˆ"R™bhûªR’ý•)îq[ž¾®ý‹šnÚ×ä\I®Þ¿"æ:¼zuhÕî{š´íÓ·nͱu+çÿ6~~üýñ_„|wç¯ÃOÃÿ>7òÿgòŒüÛòoËŸ1üWàŽ±±×6?(ø‡Æ>×:ßÃ;=o£èúÖÏö]7AÙë;Di5ÛŽã˜é®óã#\ðøàõq·UçÁ± ¥N¶Ô—Û-+.¸T Ìè÷£1_ò{0µbL¦ªAƈІHJÁ¢Q'a¹ ú O`Ž$s$‘"ű¤–á »Ì¤²LÛG¬­#pÅ's5¸]Þ\èÈ€îÃ0MèØÔbÎb³{„˜BIjÁ©ÿf “ÑÑõlsxœ†}ÇJÈ:•!Ž/Â6¸;¢r=¥!gÁö­L&m²nHe<òøq7ãdæ¼®Z? »Ã$Æ2¬dÆqômÀ±C‰d\L²>ˆ†Œä~#"\XfâùdMÜZÅÈ1Ü’[>.|HéÒ›¼ºa¥J É¡)ŠT„šÒÆÕê±Û›JÜ“¦jTÊ¿I#xòËŽWZÒ93»Jt «#ø‹ ò‹°½œ]äÆSäV] ö·&¾Iɾô|xÈÿÔXíA =í¤~mnÝOÈ7 Nù%ݯ¼IãÇGøÞ7F÷Å2c0Š¢ˆIŽBƒqÀêf@¶ŒÏW¥Ö„zòqÁY.icŠÆÓp$"Ó“R\à‚'¹jØŠtílOíWê”ô;,È@¦9‘sS4øðMÆRëÌNò7’9ÅHPžŒÄY(¾0Ä’ôr™Û!&©‘yç#3õ2º6) £¼ ÄXØ?¨á¥ìáCð¯(•8¹0Ýu#á e’ñM·˜÷Ó $Hï×Ç’¡ ÊîB!Ö™£fqOÙ˜Ó®q´Ô «8눱¶2pÿ½œ;pÞ,âæ"¡âç&ýlm‰<ÝåÃÚ½Ì4ÁÖ=󜣜¬õ .]ƒq öW뙳®#LðI¥ÄØo0¥1ÓX±ÅóóCa‚Iž ^Ýn†òxRt k˜×5¾ž,Í 62ʽ|/6 §Vë·v)AO`Ì[@À0îÏ)ÍZÙpö>ŹËÑ"A²Ô гDM"¤"MlH½3ò{/Z^¬Y$²ZuÖ­²ºiÓ¥7·ˆqÚÌZrQ(¾KRœÍ%šÅ‘tDTk'Ù‰Û—¼ ÃòAHakµ²ÃÑ\L …òÂŒŒ+pRÔ6ñ±­·t’&'#*±t «8눱¶2pÿ½œ;pÞ,âæ"¡âç&ýlm‰<ÝåÃÚ½Ì4ÁÖ=󜣜¬õ .]ƒq öWëãÇGøÞ7F÷Å2c0Š¢ˆIŽBƒqÀêf@¶ŒÏW¥Ö„zòqÁY.icŠÆÓp$"Ó“R\à‚'¹jØŠtílOíWê”ôaF+ñã`¾Of¡ I”ÕH8ÑÉéX4J$ì7$?A‰ìÄŽd’$X¶4’Ü"á—y”–I›aÈõ•¤n˜¢„îf· »Ès£b6…ß m¾S˜âyÁ‰f2Cò  ÂECL&‘´½©Œh°Øo#„ „K—#%óy´¥$ÄÌ Âb1¬‚*ó(ŒHú+J)J)J)J)J)J)J)J)JT¼ç÷¬Ê?"~±DjÚUKÎzÌ£ò'ëF¤Ý;§‚MÓºx-¥)Jª£ï†ÿ¤¿b¨ö¤(ûá¿Åé/ت= R” R” R” R” R” R” R” R” ¢¯ÇÖþ)ú™ÆœÕ=ÿ×ßþÖÍìêñíONƒêµ»1êA¡é:kl÷R(pkL豩jõŽMÈ×´«r@‰Z›*Ö6¥viPàžÍÄv[.ßÒºÅ9äþSyâ}#¯iÓé3§¬Áô™ÓÖaë±TôÂP‚CÏÈ”/9r||r×£j…j6È%V,Û·fÅ») B’Êvö¦¦ôéZÙÚÒ£jjF¹T¶ª¦YcBó™¶ÔÈwŽ yñí‹ïâ™™ Ú‹1™È‘l–évl‡ Iå{~%J²œŠ‚O0:’Î`i ‰â—´Q±Ì¡®QxŠ®Ýx2-ä´X/oÞ%á­÷ü5»77mß$NïÿÑ»Á׳vmëÙ?å÷úýË­êmÆr®+5I*&°9ŠoÇY©Ð V-$’a¢ÇN,‹‚ߎKAÈâÙÔkVîRÉ¡ùœþÌJ–^cÞŽƒ¬R+XahÑ‹¢·Ñ"è­ôfkþd9âX‰á©Ä¦~ 0¾g1™<甘áÒ›ó´p7j0¢Èq^<‚e+ËàŒÝ2³D ¦é¸J¾0‰®2=ÉGoáúž¥Hï-3¾na˜éŽ<„1ÚzšÂ2ÎGŸŠ&ØÇ#^…FC1"Iƒô<Äxæ`£æ­]ãÌæÂWn™£·X¾Zì ˆYqªò‹õÑݤAm…¥‹ÆÂü||ݤ¸ÎW½ ½ ÉòEGy3*ßÊ&\‡™Øå /k$¢î¢V/$eƒÅ ÈFÔ5ܶ¬éÑþ7po¬ äÆaJø°Æv2‘ö¦d|Ú|7, lÑ-MÊ22c%†9p,îóI0bYß"£²X(̧QȈ—ÊÂ\¯‹’’61ae™Ã ð;Ñ[+úõ+CÝc>3Œ]K£é4DÚ/!ŒÅNËU„§í-—Zƒ3œr{%ñ•^U¥¶Å;OÓgKLS¼ Å9);G£cm³,Ì£ØÏ3=dÓáI º¬i˜Ìµ MÓ¶•ä9ts?JEsxjçtB1r4‹¥y+>¤lMg’å(+,±ú=?„›qeÉñl“lj½„ä,ø-¬A¨<–$|,"‘Îc)$R} `:a˜ck¯£b6R*þ‚Ìï”è$猧ÍìˆI(0ë™Å2n €ÞHØ..[©#GÑ2èD¢2$ƒ ɆÑðn Ž#ùL FÄ,Ä*‰¦¬‹™Ëâ‹‘²y4Hè I d).'™ag&'Ģ저±`à$ØúŒ")ƒCb@aeãÃnHY»Bƒ-¥áÑæ„ý/bŽÊìMA”ô×ÉÍ›gÊ-q³Ì½6J±¼ÜcÊøãD×5-e3‘,›r€ \ƒ(’°µòè\•Ð±Ñ Üê~Ɉšã©*níc¾ot:>ÄÓºLËŒ+j“Z¤>Ü~J\ãeã{‘:3ˆœóƒÉ@,Ÿ!†IÑÆ»¶C‰Ò?²ÜØLŽ€C2~2„ONË8yÅ |d`ê$ƒ•1ŸÇ<|bͯJ±óˆâC:]zË‹VÇáôŸYŸ®„ð}«S ›l›’O<¾MøÙ9¯+–Ã.ðû®+I1Œ«DZœ}Gð,dâY S#l¢!£9ˆÈ—¸¾Yw =Ò-˜E¹¡¤JÆM¤Ï¢lMUaî}=¦„‚¦le2É5âÚ §l¾ J /“!4IpGH“ $Êì ë>¤˜›–"³*2eÖm:…ÞidÅ”¬s–of> ÄMÎ-²Ö·Qî¦y‚¹·'¤w”Ä»îhóHE×bhËç5Œõ³'Ì(5ŒÑtqX¡îñ±)aAà¦LfÌh¯"ɲ¥V/LÈ`•3­—g-JCO×¢ÂÙùòf&Ç»“¦¬}~“Þœ]bõcn+ïJƒø‹ ò‹°½œ]äÆSäV] ö·&¾Iɾô|xÈÿÔXíA =í¤~mnÝOÈ7 Nù%ݯ¼HÓ"ôŠdBTØÈ Æ>q œgà¼Ï+7bÎ\eãS{WGìùk^_cŒTÅÅJ¤æþ{IÄ"o͉C ͯ Ï“Âà÷qå¦wÍI°è4y@2üáfaÄÐï/Æ9¥¨1×çÌ{‡FäXÎ 7QŽòû°Döß&./‹e׈ŒÌ02E1r?!p‹ÜcéªÅt|ƒ)½G“†EÁò\S)團'+E¥1îÒKÈ3ZX(šgˆ¨°>E‹ä(`ò,uÇÆš bÇòA%ñ|lòÊVœ‘ÝíúTŠ1,2'uSÈs|ŠOð„»3—ÌÒs¬¬f~Õ8ÂGçæ’y‰zwr…DðHʆ=­.ÃÁ‚íO$#Áà ƒ™ÄC:aIÓ6§œÂµÏ§ð„QÕÂ"a9%Œ…ËRllo$á®uã^5Ì%ÑÛÚÉž$ݼyØï8ã›ùäpZýL$RC1BI¯˜Ú¶ŠÊxñšÓ!^EÆðÌöQFÇr»„íoÌñ_*qîB ^È•ðìfËY,˜¿z@Ÿ!w‡0Ã(”p7#:½äð9 8 mˆôÒÓ±áx0ƒÜxV !JaEñì§’Ò ¢†•Qëªò‘,¼È½™A?Á„ÍÆÉ0Þ˜°ÖKn¶ÜaŒfmj˜™9›¸ƒ±Èü„jc‘950COÐle.¼Äï#q)#1|P„… èÌ@%r‹ã I!G)²j™‘ .r3?Pc+£bšáR” R” R” R” R” R” R” R” UKÎzÌ£ò'ëF­¥T¼ç÷¬Ê?"~±DjMÓºx$Ý;§‚ÚR”ª© >øoñzKö*jB¾ü^’ýŠ£Ú)J)J)J)J)J)J)J)J)J)R˜;ªöAÑ®ÿe\—…:‹ýU›ÞG\æ­=ßÜ”[»gW•fíÍéÛÕîy^VŸsVÍ:¶YJŠó |—ƒ±ºO~6^>ùijg†¤m(ݧ +as¸Ú¾Ë~•M‹õµº-´Õ¾êgF¥-¸µ,Dâ™*»2¥2÷ãÈËß"•`‘Æ2ÎÉŽ20Ù¸ÔâLÍì‰Çxl€ÕÆ@xÆ'XF|’q2K‹Å¹wrc‰S»ði[¤½•Eærvb :ÐpéŽQ°Ç·Ã\ƒ’Tc¾8¹ñ£pGIÀK”ŽhµøŽ^/üÙÅa´D\f^¹ëRB‰<)v2œßÔ1èâùFìzÔ‹¨ M¥bü¥Ò 24 BZXÌñÒ4/•ó ?àžÌõåNUK@؇6ä4l)²Üe¿²K•Ÿ Åâ„S¼ ë,ÇñìKgZ¥öÇTHB#èk6³/&İÄ>9ÇHvg˜Xóh‡"dÀiøÌA M£º^ž*ÇçåøÙ1[|˜¦)0± fj:ŽI!õXÁ«IÌ€‰5½A´ª Ѧ ‘^1¾ª2ica/S˜]#Ê ØÆHW–²’^éÊ{#Ån£!N„ÌmΚ•#i!r ^ô‚Êw%ƒ,*ÜjIHcÉw-r‡¡û"'$8è×dnE•Í‘È,PšKHs ôqç‰dH l`^äðÁ>>?ETȧ Bì‚<„•°Œ‚Ê£gvIãÀÝŠV=ãn]fÑ¢œ–æ†LYÕô‰qo Ç‘ƒl´×/c¯@rFZc×IÅd¯¡™Û¡X˜:fÝÑN³!‚ý¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(RóŸÞ³(ü‰úÅ«iU/9ýë2ÈŸ¬Q“tîž 7Néà¶”¥*ªB¾ü^’ýŠ£Ú£ï†ÿ¤¿b¨öJRJRJRJRJRJRJRJR‚JŒÕ¨@¬µrKR¤`¯ÊÓ]òtkêÔ'¸‚õ›žEÍ:íëò.hӫɹ£V^繫N­;vìÛKÓŒ¤/ÉäÌE…ìv<5}g[¹Tö7V§7õ]™cB„Š;:´önõ ¬_MwÈêïÙ»kV­¿7Å)ÆL›BÞ “ ¯l&rdâTã»]#رÞÛ§&‹‹Ó ²«CU¥‹ô·'tº{’'†ôŠYiÓü’E OC/¹sÛ™š\˜žr 7ljwGy½Á/iFòZ~БEë]z[öÚòúË­]Ó§^™ô™ÓÖSé3§¬§ø]ÕÑú‰ß—¼½<Æ€Ž¯«8º:º8‹µ,prrpYròµË×+½yRÅŠ¯]P¥EÛ—ïÜ×w^­[s‡ åÒL~›zT§Ô,neð—D¶3Ë¢¤É—­p$‹zVŒ˜Ð£jretVÆ­Ñ•-‡dͯ +ï ¸¢Ò7$ 5[UkOE¸(+·oNÞ}—±ogFÓÛ»hWÙ;_dí—µªìýgUÚ/yf¨]ÄXÚgïGÅg;ÛbÈþ"ÈûÉ….ä†ûÅv°â4ë»N.÷›<ínO¼HÃstˆõ#V;ÎÿEÑ[èEÑ[è«ÓŸHh “"DNx³&Hr^äfHâhôs²Eá9ò~Æn㤴í!™¶±ÌÁÏ™ !Èw,\RùÃr’8b4Hö ¼•zBP2 •Ìð“;ËÆÝÒgHIÅI P h+Ã6v—RVûJØç¡Ë,µéׯŽT˜·†ëwc®ó¼D6õ6ÇÓʥϖËãh²bˆ˜ÛS©A¤mXÜÚ[®vGq¶ë¥÷Æ÷L~ °<¥Â 9“ZrmvPµ©S-tŒz? 8Þ6É8‰^£‰<Éþ3.?#M·€à2–– H†‚Z_# Y‡ØÊMÁq3–”Ñ/š)tB¬ZŠªÎ¡þìæ²x¢MŽÂ yMÑÕ4åS$ŽƒzBq6òFa²âå!˦ƞy„qØøê><‹Ï°Ærm’ȤSz <¢±WÔgöœþÅÆ)ã„ qÓ+¤R¸l&š_†Û†ÃæœDø¬å×(„šåM…®BT-dÔ! @¦ExY·“Ê·B¥F~Ž–«±´ËJ™}›ÙÇ1â˦ ^Q2ËÁ‹x.}a#}$ŠÀcÂɽñ!­oìÔ,ËÎ;‰­½I}Æ5Å $všFƒ¤˜–]@hqHq1 ! Ú«‹"ã·èôšM†KšdÃÆ>’"XÉsù›h¤¼ÇÁ©GÒxRG¢ÄäÑÈré EãŒxà…4Q:1Î!ÚIT&^¬’æE‰2Ê10NÄZ´71“A¡YljBðò9y’Úø°e—ixëûðèÙõ!aË,µ/bH´k”e#dä³|Å)Igãv0²–†1}ðN’ãRG©O #LŠÆ™—a¼ÁèŽl’l=G‰Kî·GC7{)1°o*¢uq{áä§:[|e& ™àr„3´PHÓzâeD1<бˆ‰@+á(ƒ‘\bRìÔß±{Ì`|zqE¶²—-:üD¹…àÒ ü $)O‹ñ‰Œ¨"$ÆeQèÂ(œÜlth¦s‹¤(æNƒIbÅÚãg¶±²±Âði$bòâ0¡¢þÅÁ–EÙ…6¤gË è±£#±Û£;§9XÐÊòÒˆIêm¬ Ã˜¹ñØ{k®ã»‘aáÜ,¨¤yÉkyk(“úqµ„Ë^î+¿YÏ—RN2q·²;pßGWH†]!âæ×åýl“‰=Ùypȯs°u|ç(ãfÛ=Có—``ÜD£}•Çz÷b½¸è9†ÅΪ¥9@w2¿ ­È²KÙ)$Ê7›§1¼—“G’¹ß¸ˆíÎS’Î㻄ªÊ Ð4/:6ØÆÄÚŸX¥?³£ìlŽVÉìÂݰövÁ­¦Rì‘»’5A3ê½-Ä)FâAQò›:ˆµ ªiœ˜P‚O<^@ånp'–šÆbæØô"Éw.³jïGÅ ˜²¿ºN,缸e¥[î6$ïØpØ'x’µo#‹]Ù;^y¾ðÛ ½ì#Ôôx_íï;‚+Ê.‘l²¸N‰XΆñAòe‰Páî}OÇ9HHõGSä°<Û’Øð óâ«æ¸æWˆšO&Åê¤$ L%DñühF<³n™K¸‹Lýèø¡ìá{lYÄYp90¥Ü‘°ßx®Âö¼FwiÅÞóg­É÷‰nn‘¤jÇ`yßñ\•Ñþ6},IÒpæLf×:¾DÓÌYÌÈÁ¥bHfË #9 ¡3<4øcˆ…Erƒ¶4K0‚ù= k~QyÑ%÷•Aî3Û!Nqo¤9†/c4’Ò>DÑÜvÄL‚BzØs9L‘ü$øB3Š›JæŒbò3yS° b0é! eP¥!#ëj乜ý’95ÇR0TÜ!ÚÆ#|Þèt}‰§t8™—VÕ&µH}!¸ü”¸ ÆËÆ÷"tg!8ç’€Y>C " “£wl‡¤e¹°™†dü0ež:œ1–póŠøÈÁÔI3*c?Ž$xøÅ›^•cçĆ,.t&ºõ—­Ãè->³>1Ýqg]3àûV¦6Ù7$2žy|8›ñ²s^W-†]á÷\V’cV2 c8ú6àXÈ!IJ.@¦FÙDCFr?‘.,3q|²&î,{¤[0‹r B!H•ŒšIŸDØšª*ÃÜúz-M LØÊe’j3Å´NÙ|”_&Bh’àŽ‘&I•ØÖ}I17,EfTdˬÚ&u ¼ÒÉ‹)Xç,ÞÌ|ˆ›œ[e­n¢ÝLósnOHï)‰v$%ÜÑæ(‹®ÄÑ–!Îkëfâ-ËLïš“aÐhò€eùÂÌÉ¡Þ_Œr5KPc®'Ϙ÷ȱœn£å÷`‰í¾L\^5˯˜`dŠbä~Bá¸ÇÓUŠ èùSz6 ' ‹ƒä¸¦SË90NV‹Jcݤ—f´°Q4ÏQ`|‹ÈPÁäXë =Ž=4Åä‚KâøÙå”­9#;»Ûô©bXdNë§æùŸá v g/™¤çYXÌýªp3„ÏÍ$óôîä' ‰à‘• {Z]‡ƒÚžHGƒ†3ˆ†t“¦mO9;…kŸOᣫ„:DÂrJ% –¤ØØÞIÃ\ëÆ¼k˜K£·µ“Bï,a† Q(ànFu{Éàrp@Û饧cÂða¸ð¬B”‹ãÙO%¤E *£×Uå"Yy‘{2‚ƒ ›Œ#’a½1a¬–Üm;¸ÃÌÚ,6<Ô'12(s7p/b‘ùÔÇ"r.j`†Ÿ  ØÊ]y‰ÞFâRG bø¡ ј€K 寒B>ŽS;d$Õ2/"@\äf~ ÆWFÅ!4Â¥)@¥)@¥)@¥)@¥)@¥)@¥)@¥)@ª—œþõ™GäOÖ([J©yÏïY”~DýbˆÔ›§tðIºwO´¥)UR}ðßâô—ìUÔ…|7ø½%ûG´ R” R” R” R” R” R” R” R” T¦ê½F@tk¿ÙW%áN¢ÿUf÷‘×9«Ow÷%îÙÕåY»sGúvõ{žW•§ÜÕ³N­•c0§Éx;¤÷áSeãï–16¦xjFÒÑ r¶÷;«ì·éTØ¿[[¢ÛHÝ[î¦tjQrÛ‹RÄN)’«²›-&ËR¥)Xö÷2É0:ž’ãȈp ºCqéMÁx¨xnGx~ vçÜÑ+;'y&k |òXäw+ÍÅHE̸eÖÒÕ Ç Ô <†ÂR²Yû,²Ö ½–ÂÓµ¬t9Q‹lxm’ÎZ%€ ßÂɆX5ÊÂÈH¢K’‰e<1×%¤!­™¢GA¶6°Ë*/´ãw™gœRô2ÚOÐø8AêH¹¬(g”WõY‰“òJâÁ³a˜É ÒS‘B"è²{Ù} Ì1®'øäº1 -xö/iÃSiX†Åž¹¢ˆ}Pã>Mý ð,¦sŒ™­´ÆÕ—Ù"H‘ÑTi’£fRQÄF­S˲‰J8&C-°É1Q à ïŒdñÃìßwÚ±Ò5˹Ç‚˜³‰…Ä! øå-GMJøîEÏV•qÒBlÈ–˜ãsøÚ®R6\ÀwÍ@ÆP”ÌŠÁ—;†¦Ò³;82¢dÇrKË>±ÁÐhÔYrD}žI°‡*s¼mí{ròÛ²; >*H±²Œkc„„„L¦G'¹mª¡(6¦Mpt}Êoƒ2,’Z›K•h‹ˆ6aîd[TZ¾Iw$É"ܱf+Ð))ÜF2×#Å–à°Õ±™j8ü1ygr'$zS¾52…Â¥cÞ>å^me—)šã‡Y‰¸Ÿ£«³$ðäÚ,–¥^Ç$å_xdåÀŒTÅ9DýpEîS¡x`/y™m¿G›…X㈼½ÌÛ%PÝ‚²jyǼ_¨þ.ÃÔ3–C`*ß“t¥Ã¬ÜÊ,‚È)´áž4@Ç&Nñ6è"/c%NäÈ;8焬{'Ï3§¥¡ð[F§1ÔáôýJDZœºÍ¬¶åßsöLY†wßGV9æÁy6ÙjgÞÒN^ó#“0k?, a.ä”…ÌéÁo?*ßáœ+\ìOG–Y¿˜QôÛjŠâÀ‚ñl= Ÿ”bæ}gøÛìÛ,Éa PÓJÌAŽ‚"ȱÒ¯Ï2k=òÓ$£7@±áBƒ¤¨Ch)Tô›(ɰ‡5L¡‡Á"ñ,=vÊ2¼x&y^ÂH2Hà (–!‚PôŽŒ¯Œ®‰»<¹¦^ܽ2…Ë쨳q—N=J™c˜R¶%gü]?„1‘:tKe\šá,„á6}a˜Ü_6FŽ#¥ðz½9ž3q®ic1k<´KHa䀥»PEò.ÃxY‰;òôáôJÂ|¢éÌ Û+„à(•Œèo!Ñ–X•çÔüs”„Q„u>K͹-¯0*¾kŽeqpX‰¤ðbl^ªB@¤ÂTOÆ„cË6Íò–ae¨Œ…“ŽA¡ØèAcÖabæ&Š“/’Æä)Œ“,Á°µ½Žé œÕ¤ n cˆ¤¼®JZìfÛäùhBˆíi¿…[”$àÖšV/Íç’ñsŒmmª,-Ÿ™3è# ž%ÑœÉCÈ÷hÛö çL¸=†ðËeƒ‘#»¬HÓ±ÌêP;µ'˜Šäøö9¼ü&,Í\à2ˆF.F‘`Ô¯%gÔ‰¬ò\¥e–?G§ð“n ̹>-’bxñ7¡œ…Ÿµˆ5’Ä…„BR9Ìe$‚ŠO¡LL3 lAJÂr‰³?%L}‰®J¸éJñIŒ½Œ²)P„U4˜Ãó¨Û‡Ft£—ÁsÄU«#£A¦41¡ÃSYü ù'Iè,äðt¨),îé0‰œÞíšÓ nP ÆòÉDY 0dZˆ6?‡¥|WÊ‘Ô ¯)@œBzK‘;áñ§-E£ú²:‚E7 9$Ã2'Ñ©]¦ÄÓJRJRJRJRJRJRJRJRU/9ýë2ÈŸ¬Q¶•RóŸÞ³(ü‰úÅ©7Néà“tîž iJRª¤(ûá¿Åé/ت=© >øoñzKö*h¥(¥(¥(¥(¥(¥(¥(¥(:CMGÎQù„td‚<|%^=qI‚Á4ÆŠšØÕ*_}S#ƒ£[^…îjµ"±qÉÏKªt­z“ØjÞ+¼3Ó“¬fŸd¡W@£\¯ßC/]‡y¶r(-»´îçŽÈ¿~´¿ p³Ô¸ H£÷º»]gUÕ]òìk¹o]á¥Iˆœu”˜‰ÇY*¬b,lIÍÞÜöqkœùO޹tQÙ˜mö ';®p#\5²„;wIŽ8¹µÇz¿/ßfÛ˜•ƒy1pݦ¥UBù>I3ŽPÙÆ<ö„#<|‘ÀË‘0ÆÏ‘´`ý=¾¡lV.âË{yñWxÃÆcdO«ž_R°7Yeoêo>WFžŽè& “b£‘gIÌ_›’d±\¯{½óÔ°:b ¾3¨~ ¶¤š4c$4@âÚÕ$»µ‚FhÂaŽè$`ùÊ9ŽmqÞ:b+¸l'+Þl”±®5_­doª8e6“Tœ?¦’føÊC)Êp Å”bÓó8¦gà8ëܰì@øY €® ?åÑDT½ªG‘R97jHâ<˜g¼ÃQ± 1 ¢i«"ærø‡"älžG M:B™ K‰æXYɉű(»( ,X8 6>£Š`ÐØYxðÛ’nРËi}¨øoñzKö*h¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥()ïHi1 Vç!i à‘x–äÉ0¡X˲öA’FXÙÕŒ„yñ©BGFWÆWD‰\š]›U&^ܽ2uˆÔYQfÝÍ0†-bÓÔ°‘Ê&QÒcd¼Iè†Í¼¤&éa‰Õ SfØ¢äêÚ³YÙº 5|Ó ›J¦Q•è߉^MpÈu¦Ê+ÏŒ· &¡®ñ˜ÝxùÄ|ÏhBW†¸»sñ ó< ü'ˆ÷ôcß›~o=Ͼ™÷Ÿeì[Ñ¿¯ív|Dp#›Mfl˥܃œˆòÆñâxã娬ÍÓ­j]e§sg<ÆÆÅØŸ.6¸¸öèàz5$\Ì›t+qNúÖô%ÒÐýãvG ÐB¾íÑeY_ žfN{FØ“Ìçã4ÌB`±ÁDš?$“Ìs|˜N&¼—¾!‚:w[Já! ²šá?ô¢/¾6ç)Æ˜ÞøY‡`.?t’É¥òpØ Æ>̨'â'pfxý±õAVEµˆA÷Þ@í4Cæëî²Ïð¶±Àu²Á‡£Ï"ᡸ•.,æ«J^#€°¦ H¯‡Ø¾É2–YÇDVá‰ú;Õ-:FÒ˜k¤.¬ÔÂZe2Däh XÛJc÷•‰]æùWÊCyrÆë6¾.tḚ̂ÈȘ mÀ‘x: ±F²m!J~<%|,Q”7]‚#´ ÃÔ[c¾ÚÖJ•´T"ɇ¤û¢ìš.š1Û„d84#$¡XÏLëhj~ÌxÞǦ‰†b+²A§ ’œzH“$®7?ËpÄ2¡°Dß9$Ö½½¶,éx²b%ª›"(²a;€å<# J݇™ƒäœO/ æüÚ;†«fg&(…8ô¦_Ìd±DÒ ë†Ã\¶È¨$¤gƒÖ›$0|ô÷ElskäJ_,E˜j5” “¯ˆ%Œȹ£("IICq}÷1¹l—%Š[&XØì¸ „;5[,° ÎË€™F,d\Š$VÏ‘9dÇ$:;ä^#M¬àìÉÄñPÞ+M°ÜÞ¨@Yd#ÊïO“ü^ëhÄâGžN^"g¾ >Ö0äÂ`fvÎ Óg£üw‹"lŽŠr/£U:Ëú2GYô%&ã¦eå,>Úì!*ÆMGmÏ„ÇaR†?ÉãÆ˜ü÷ *pœãiá¸4X‚ýdFAãž2ª˜Ý¡þbËÿÉ;H [¨ª|œ$Xh:f–¤FXñ½ B¹~Cdq”‰ƒÇ”¶vã5Á6ûÞjÃnnH ŽžGá·ÃàŒ@–ð†üj ’p;&¦ ¬Œ ,h(eVvW!È£,Ç‘óJèõùP`›ëpôš>øbÞDî2#Lò3UCŽÓ.¥ÿä„áŽsŽ#ö­Ô+>Aò,Ê"³D²#Ô†Þ¬!$¿=¸Å¤Æ*\Ã;pbƒýà§I…«ý “<^šw™±±ÍP±Æ c†rVJ ›£lëŸc° da$Èp:¶“™ šXb|¦8©…C¨(ýërjPÃÍ'>ávWåzyyº hÃpƒY fȼ•(í žÊ28?@/§° äã7ÉLpÔªI¡–LÆ8`AÔq¨d®znHJŒ¡?Gceƒ'¹^EžòeŽA•äùOIR©ìÅQ<}àE´d¨lZ å*Igk_$C·9qIŒ’o3—ÞCzEgÒ<&ÞÀŒeöS•q‚g|Éäç$¸þÇé¼Eâ–7à¬zxrmȰÓû¹×*æð.pÌíoGì³Ô0ùÅËM RŽ ¶‘ð2ÈK¥¡úÆì Ž „$)}ۢ˲¾A<Ìœö±'™ÏÇ i˜„Ác‚‰4~I'˜æù0œ My/|,B uî2 ¶•ÂBAe6‹EyÎg‘L`3ãæù1gs!öO•ev¨ß‚"®~™Û쉨 •ßæö8£A¨£R‘q‡ñå¤Âl‰Uë—b¶<‹††âT¸³š¬q)xŽ˜%"¾bû$Ê6Yg[†'èìST´éJa®’<º³S i”É‘ 1cm)ÞT&uw»ÑÔ ¼m7™Ýd§Ã÷C\tÆxÊá3Ûq#’üx-É"µ’Q ¨j!qO’BŒ…¹©Ù€R: ^2¡K--oéXÆ‚TŒŸLÊchøšGå\†F&úyqCQÇ. ÝØP8ñ«”ìeü ø¡p÷3'°ÔA»·³u›IÙѧ´ÅÖÙMÞÉæøPÊ?äÕS!ðÑt¥ÌUøúûÎýŽ„åˆ8€‹·ÛullÝò¾èxZÞú«}¢lR:ïÕÆLFbÑ´|3#žsRCb<“ø]¨˜æm (Ê8)Šò†1/|N¸‡…Ù”_jÞ;¥ºõÔ‰,ëÕ*`_â¦@ÿŠ™[õhuXºwzÂÅÓ»Ö³£ÚR;œp¦¹I÷Š$Ùƒ1¦R‘Iwc;'ȸQasîæohhÞä©±hì­è‘Z°šÜÙ/þ*hÿÚ:V¹×“Äè/ºþ,cN4qOww€!¸/w' ñ‡)#¡À)áÍîAÃüAÃûÛroç½ÕÚû÷rê;eïY/þ*hÿÚ:V¹ÔFCô†D"ÙgcQö2•äŒYµb²Óæ&܈Ç‘ÅnèHn-bzRl*Pz½J}Ї_m]Dø$…5·rÆ—„¨F;à[F4X q³ _1¾4¿‘‘lØz‘F\Mƒ{W†hZȽñ¤6E“Ž>.`qOl…ä:Â'‚¤ã-O¶_4Œhf×|Ð8Î0 Fn!èøÓ;ä3G¾´ÏÃO’ƒS;‚½KÀÚŸã¾8uívÔ”;, ºê@Ém‘Ö‚+² >hc–[t±ÉØáȹôŽ g|Ž„Y™ øf>2<ˆÜï¼»¸!›ÝLäC¥íE÷вÞY±&v G|nJrq1.ãé;æø²Ìc*ßšNù¾,³Ê·æ×*R•T¥)@¥)@¥)@¥)@¥)@¥)@ª—œþõ™GäOÖ([J©yÏïY”~DýbˆÔ›§tðIºwO´¥)UR}ðßâô—ìUÔ…|7ø½%ûG´ R” R” R” R” R” R” R” R” Ut›eÒHÚKÃðÖ4,jÚò"É¢#+îÉ—ß^Ø6ˉYG<¥\3u’èŸ.ÂBªº¥zA¨mÀ…¶ÛNŠÛ^{Éû#¡Œ` j<›Œ¸MŒŒà>2B܃&3i¹#˜°h´|ì^h Æøê•Hf‘Ì2d’xªT™8tž?å?5G’©\msÍûXäIÞeˆ1óŽœ6ZPËΣ?)…kaRžÌ0ìØð¯ÜfTægŽp…™</˜¤üïÅHá8-[Ô©ªpÊhj&fºBg $8V1!¼hq/5 l3ÜN+¸a3µ›Ái©UÑï)"tè”êßãI9ŽvˆíŒ²ÞBI)/È—°ÁHdy¨ÞàzqçÉT¾EiQ$¸ Н%Nã%ƒµ¾3ÓЮ•œÐÌÑä«™ÃÓ“¨s4J¾OŽ&P`I  íYØõæ94˜]²6¸Õ°õAe†0ã)¾ Ȉ»#£GÉÑÆØàéŽGˆeè<ÌTσ$KLÏ 3p,xn“µ„HaDÍÎ:Ç·S›Q  ë”þí¦ÈMôªC>äã¯txã!ql„!ÓžÇRÅHà¦d!œ—ùE §1Òb¸€ÝÃw„K÷ Û…Õ•:ïT¨P=^oò$®òÈÇ%2+fLz¤¸qñ‘8¨Pbñixlg0ºC›Ù\d¹EüIð W˺NJœröNŒ‚É¥¢@©˜Œx/Õ+%²Ï¤\’"²f<‡Å˜ßÔc>çD–’›2/¸7·"ñØ¥î%I±´Üx‘Õi“¢Æ²½ëˆ™H‘Ó,{*i/—ŽÁAöCó>Çç²VÉ¢<ù/Bcæç4ÄdÌÚDzŒÿ¼<ådÌ×8ÅŠÚá tüì Z™{ rÑÓ¥ î½Ú@c^0æAšS¾»îV¥n6ZSªìŽ=c…ôÊÖZOÔ4¢^£O”™«n»:liê¼W6\×oNº©ˆ¹8ë'Œ …Md!òÔã;“¤ŽLà C0“11l˜ñ™”„®Oàî¿|D®"ïÒ{ë­÷S5ÚÇo:´3;\g导gÿ0×ë'±lÄf±lÄfóÝë ËßE>îWðdÞ8 'pL<`™®Ó³Û±§P cªë‹ãâ½k\ÜÖ¨¼7qB•J/kÙoF«×uìJŽÂFäšl7¢FšÄÿåhOÄDaسŒ ¸øÅ“ù «9%ÍyYËpWò~KÆ£© 4.×o!:È”Åd%âqõÙþËrë ™$6+Š:7yþÿ2ŸnæŸwÈÿ¹Ç{þå\ÌïGÞcš}ò¶ÿîÓÝ畼¿ï[þ–õïuÄ}Þÿ•Næ?ò K0c‘f¬rGÝðá=.û±\uæsF­ä?wN½:´jÙÂEû=Ý:¶mÙ·g»°gfÝžîÍ»ãÙ·fßú6Ô‡ßæSíÜÓîù÷8ïÜ«™àHûÌsO¾OàößýÚ{¼ò·—ýëÒ޽ßò©Â¼ÇþA+Oéf¬r,ÂuŽL–¦hR[Ð(•FLÌ1ûPr4m¬ñn¢@ôjÔ<¹jqruzQ¢>\ìì¾÷’‰‹jÜõµ¶¤o·µ­µ Õïk{H—‚¦'"v9ã"$áóT£¤s'ªˆBo\q´¯Ky*UK[¸kM×&›zvùzÝì¹'SivË›UoK«[ ¨¹ññÉ3+6£W‡‡U‰ÛšÚšÛ›ÈV8998,¹e"RY¼©bÅW­'LžÕË÷îhµ£V­’cg ®ýÙF“8MwîÊ0‡å÷úïüåÿr¨ÂÃÈË“™#XáXùuÑëÂÄŠÆU(pll&JÞÜæ¹‹k•ĉ’-^Ú‘Ù¿KžÆÛ‹·8]P̲ý—¦ÇVä?3“,w(É9ð9=4¶å¶ø‰ññ>JÏÐà 0üäÖ´ž*9eÑ;0ó'™;…ÂU9We„©ø©„T%DmËh}²6Úl/}j(bžÉ˜•væB,ž”ŸYÖõ SvƧtbÎ ê»2Ë)Õ§í Y»Ô*±aM¯/«¿fÕÝ:´i•‰šE¾ãšV&iûŽk•JRª”¥(¥(¥(¥(¥(RóŸÞ³(ü‰úÅ«iU/9ýë2ÈŸ¬Q“tîž 7Néà¶”¥*ªB¾ü^’ýŠ£Ú£ï†ÿ¤¿b¨öJRJRJRJRJRJRJRJR‚æS£Äøc'ÆÉÄíÈœ§}‘Îc‚„xσpï-¡O,×fé> pÝæòøV‡íf©]wR¥Î è\7}ë5e¢Œ¸Èx<[@¹O ðæSÆ+²cÈ\w‚òjhÆVDÊ7C3ŒG3ÉáÝy»ÀSù6¹ëdèþ5“ãVù;ã‘×¢ M¥ãN1äXÌäÆêûRœs´t˜íË&×ÙW'™2X“L$iÑ !â¢;Er9”Ç ÌO²˜lÄ„dRL ]p¬H)yÃC%ÍÀJ©ºÏ™œ¶Žzx£DañaÈ„¥Y“e„G 0 Ì8c=¸«$"×Ç›3¦g® m Ŧ€ØÚLÉ"Iv>TW'´Vd=ôP¶2ãt™$ˆÌ²>>B¿î•M¢€2¹$'…•• ð‰Ëëòq¾'^¸ƒs:"ÜïËU¼7vg7”k {ÈÌG—Ÿr5¸á¼ß“‘æ[B¯¡±çI¤£‰XÝl0‚ †q†sË(¤.b |KÁ¬qÌ…t¢8ÇŒ¤u˜À͘cuÖYÕ‹lfE©¹‰Ê‘(ˆÈ6ý|kÊ|‘×!Þ-M}@d9›Xù.Èï=¥åsrK¼9”îë*.:»î½ÒÄ…Ññksj»MJ ê±LÌs+׸:*ë1v+8“r³Ǻ†­»&²Í`ÌÆ—{'"¿!«åZ·|¡“úó]1ùÇáà¡aÑ»X(µ™­8”èÞ6>:ânEήŒØNA¸¹Ò(ñ‡d‘ÆPb¢ 1bÀ‰PnDAqd‚¢n¸ÔÍ-ŠÎozøÜÂã\æÖ|•Éë锿#aŒ°šÎX²1‡˜Æšä…ü}Ã$fS²d7fXŒD³øuD<= IW‹ÞXÄS̱33L§*ƒÙ-@úíÒâD%¨˜}¾acÆE˜ÈÙ=(Ãq»른³¢˜Î$!™PKÒ çŽDå„'$¼”‰@+á(ƒ0ÐÉpÚ`n$>iÚµîÛ[!zÑíi¥/•Ä™S‘24ç5¾cSäÖA)ô;FñÉü£ ‘Kñîgм¥æ2ô±y¹ÌPÆ‚a+gj—ÎJ,į— Å–÷";ògˆ¢¢à†r~“€ƒNùÌ,‰ÿu>cpp¬9™Î±ÎÝ© œ,œcœ@ç“ñœzÞØ` òg̘”–y}uŒÃ6¼G,£ndó——ÁßàŽYsW„Øy“ËmýÅ\¾ãžÁÄüÄÿÆ>Þ›‡ v áû€t‚ÿPà_ã{£/ÿä‹j7Ǟ˖fL½¶_Íèÿ2q ³ˆESsc—øŒøwv×WÍ£½àÆ2O¸¾NkSÊ~`sÙœ]k€ Õí‘ã(Úc yŽ%Øø"T÷wÈâl'»¡Õ ëNù&@èÆéºßÛ^[»rý‰Õ¹ Šn©ZD÷­÷c##aCcÁ¡£ÌbBLm#"‚ƒ-(FÆFØP'jccjN‘­••­"VÖ––Ô©7 L4öSÙ·oHbþCàdÏf_F¨9ÀN·¢Ë¥¢6{P¬ÍŒÍÍr¬b“U‘ð›ù†Öð^ðrûß îv…ú"¨Ÿ´ð·AA‹"(/{ˆsGQd,gý_ƒµ$xpbM7Èœ/ƒ±¿8âH2^EyXy9K†f]ªj5‡&>Ù"ë|™ã–¤1é÷a+£&5! 2c--cv+&i@ü6L6üCSàñ ªumoLoMjÕ6»4¹%RÅ•Ö'¼žõËz‚ƒ`Kéšp÷!” {Ɖr8•ñ3|nÆË¹ ËnZÜ®4IànyÊÖ®,VÖÊöôðjA¨u|€t½<§ àá¨sCcikD¶ç.(J(€9ª?˜JâÖvÔnnO*£oaСéÕÉÇVž¹{³²ç5vì"DÞ‘µ¯[k^ÛkÖ¡Xöë(Ìud&J‡°½I{ ËZ†™Jñ#(Ùjñ—R±æ—ˉõ:71“:¹´£UeÒñ!•ŽIÔ¨aj¸’IÇÐî5bùŒ¬IY1ü´[%ªà«ïØ“qR6>½"}ú…ž¥ÁîªÅÎÙÕ£Ô“Ë^¢þÛÞD­¾4§Óœù¥mñ¥<~œçÍaéJUR”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{R}ðßâô—ìUÐ)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{R}ðßâô—ìUÐ)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{R}ðßâô—ìUÐ)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{R}ðßâô—ìUÐ)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{R}ðßâô—ìUÐ)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{R}ðßâô—ìUÐ)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{R}ðßâô—ìUÐ)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP*¥ç?½fQùõŠ#VÒª^sûÖe‘?X¢5&éÝ<nÓÁm)JUT…|7ø½%ûGµ!Gß þ/I~ÅQ픥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥”¥ª^sûÖe‘?X¢5m*¥ç?½fQùõŠ#RnÓÁ&éÝ<Ò”¥UHQ÷ËÒ_±T{_Ù´µpXÉû³8ÊóB àÏ C‚® - _Ô7¦D’ãÃê´--(,ùWº¸ª¿rêV´‹5¶·¼»vg Î ¦ó;úAÇ^Ì©]úLðJïÒg‚ÚRª_82›Ìïé{2œàÊo3¿¤uìÊV3ÒyŒôžKiJ©|àÊo3¿¤uìÊsƒ)¼Îþq׳)XÏIäV3Òy-¥*¥óƒ)¼Îþq׳)Î ¦ó;úAÇ^Ì¥c='‘XÏIä¶”ª—Î ¦ó;úAÇ^̧82›Ìïé{2•ŒôžEc='’ÚRª_82›Ìïé{2œàÊo3¿¤uìÊV3ÒyŒôžKiJ©|àÊo3¿¤uìÊsƒ)¼Îþq׳)XÏIäV3Òy-¥*¥óƒ)¼Îþq׳)Î ¦ó;úAÇ^Ì¥c='‘XÏIä¶”ª—Î ¦ó;úAÇ^̧82›Ìïé{2•ŒôžEc='’ÚRª_82›Ìïé{2œàÊo3¿¤uìÊV3ÒyŒôžKiJ©|àÊo3¿¤uìÊsƒ)¼Îþq׳)XÏIäV3Òy-¥*¥óƒ)¼Îþq׳)Î ¦ó;úAÇ^Ì¥c='‘XÏIä¶”ª—Î ¦ó;úAÇ^̧82›Ìïé{2•ŒôžEc='’ÚRª_82›Ìïé{2œàÊo3¿¤uìÊV3ÒyŒôžKiJ©|àÊo3¿¤uìÊsƒ)¼Îþq׳)XÏIäV3Òy-¥*¥óƒ)¼Îþq׳)Î ¦ó;úAÇ^Ì¥c='‘XÏIä¶”ª—Î ¦ó;úAÇ^̧82›Ìïé{2•ŒôžEc='’ÚRª_82›Ìïé{2œàÊo3¿¤uìÊV3ÒyŒôžKiJ©|àÊo3¿¤uìÊsƒ)¼Îþq׳)XÏIäV3Òy-¥*¥óƒ)¼Îþq׳)Î ¦ó;úAÇ^Ì¥c='‘XÏIä¶”ª—Î ¦ó;úAÇ^̧82›Ìïé{2•ŒôžEc='’ÚRª_82›Ìïé{2œàÊo3¿¤uìÊV3ÒyŒôžKiJ©|àÊo3¿¤uìÊsƒ)¼Îþq׳)XÏIäV3Òy-¥*¥óƒ)¼Îþq׳)Î ¦ó;úAÇ^Ì¥c='‘XÏIä¶”ª—Î ¦ó;úAÇ^̧82›Ìïé{2•ŒôžEc='’ÚRª_82›Ìïé{2œàÊo3¿¤uìÊV3ÒyŒôžKiJ©|àÊo3¿¤uìÊsƒ)¼Îþq׳)XÏIäV3Òy-¥*¥óƒ)¼Îþq׳)Î ¦ó;úAÇ^Ì¥c='‘XÏIä¶•RóŸÞ³(ü‰úŧ82›Ìïé{2¢YÍvSM1aDiÝc†¸—r sÂ:yì[˜‰¡ÿú7Èjí=§uvOù}ާ¯ëÿu꺛’fɾéðžI3dßtøO&‡R”­4R” R” R” R” R” ìP4;:õ»­±Å˨êúþÀ‰JΧ­òú®·³Ú¹Õõ]ίË÷<¿#_“îù:½ÎÄJÿ&2¹~Í^¤EZ´R"´*”#Uk„º¥)/\N¢ß–ì¦Þ¾®õZ.hòíë×oW“«g•£V­;}Ý:¶ìÛ常¯òœ‡óÓ—í4+ü˜!üÊåû58D¯ò`‡ó+—ìÔââ¿ÊrÏN_´Ó‹Šÿ)È=9~Ó@á¿É‚Ì®_³S„Jÿ&2¹~ÍN.+ü§!üôåûM8¸¯òœ‡óÓ—í4+ü˜!üÊåû58D¯ò`‡ó+—ìÔââ¿ÊrÏN_´Ó‹Šÿ)È=9~ÓAùÞ&Ojíû㯶,X·®õëך-Ú³jÞºî]»sZ}:-Û·£NÝzõëÛ³N;6êÕ·fÍ›v×EU¿,Œ‹õ!ÇÖÍEDš›^ò¦oyoÔøçµ ºîN69¤Ú«¨^’ûS[­”ʭݳmɵí4ªFží»!LrþLrþJR” R” R” R” R” R” R” R” R” R”‡„Jÿ&2¹~ÍN+ü˜!üÊåû5{©(ˆ«ÒD/¯(ÒÚÝÝRdŽkS§·å´ ¹¯«³fþ‹z<»šõÜÕäéÙåkÕ«VßwV­»vø^.+ü§!üôåûM„Jÿ&2¹~ÍN+ü˜!üÊåû58¸¯òœ‡óÓ—í4ââ¿ÊrÏN_´Ð8D¯ò`‡ó+—ìÔá¿É‚Ì®_³S‹Šÿ)È=9~ÓN.+ü§!üôåûM„Jÿ&2¹~ÍN+ü˜!üÊåû58¸¯òœ‡óÓ—í5T³|àÑ.,Ë;R—”&Ú­ãR­©È¬íRÖôh6ÐòÚ£mµzzäÍ+–µ¹£¹å'^ܱR%Vî¦QvÖ´Ù8dLà±”¥(¥(¥(¥(¥(¥(¥(¥(¥(¥(¥($!ÏÄ)#äë›õÔ„9ø…$|ýs~£Ú CÒ’X×éUªZ‚Î&³Ì}Š¥Ùì0t2-3‘;©w˜\¤Í©cDÆ#Ò$îÝŸ=5M.±’9êÙÄ”(…u!†sB6‰0—=ÄqŽT„'ÏÁ§HæØúòpÃ,FÎXôš%<‘ñDD¹Æ2)rì|¤à2¼Q`!“TÎgŒ8ò“ Ž•óðErÍi%ˆ†Ëeˆ¶\|\øµÒc’[ÃE/)@¤1$—dM©TŸucj•e1!¸ìթɱ{ {3MÂW4/k‘­Ù«ß‹kæxK+Ÿ"ä‹g)rÇÃZ†ÆFåµòX•õ‘bISͶÄîÏ‘±~’F¨uè”­°n4A:Nw6[±¢D{rNÖsˬÚÅîð¼ÛdÅ’žÍÑÕ–ù±rå¶ZEËY'¸‹`Ùk‰‰usè!_ÁÆr·IXÜIðtA‹PB }t”Ô‘× 'É>Ý–çèÄÙsƒ°F,DÙ< Ìó—™Ô·åŒv!Ž57ßx’žtV‚¥åþ?âÒÿî:¶•RòÇÿFŸñi ÿ÷[J‘|ïô„‹ç¤¥*©JRJRJRJRJRJRJRJRJR‚B•_¿ø_êfêjB•_¿ø_êfêh>u"Ìk€àΆW4¡”"ÉhW£ªËMÄ0Èš3—Œáì~ž#Ì…)Œ6 Ͱ„ÚN%e¦zŒNžœšÚœ”>ÚPÉ$2ŠÚ|’Ë¬Ú SŸ’Ü.É‹:`^ŽÞâ¨òOm–%ìŠáx7ËL…áù8P•ˆ3; +,‡C;Æ)È~#”YÍøDMréfø³£ŒT2ŠŒò[)çhWy.®†¤r(`,0Mû]Dž ÷÷—Lnƒ IQåÒ°¶E Â3̇>:¥BT`Ff<&F>œz6#iÌÎn|_;å¿ì—þpÕ´¥Jg:îåç8¥3wróœU/ùõÿd¿ó†ŸÏ¯û%ÿœ5m)Jg:îåç8”ÎuÝËÎqT¿ç×ý’ÿÎ>¿ì—þpÕ´¥)œë»—œâS9×w/9ÅGˆãL°’ŸbÎc+Ç„ƒ ÐD–«‚¯É6TðªËýzDûõöûÝszõÝU‹¬Y¥'–½=—¼»ÃJR"žòˆô")ï(B”¥U)JP)JP)JP)JP)JP)JP)JP)JP)JPBRá]Håo‘ë~8¶+_jØÒS%òk‘N¦´(’·ØXù}‘½µ¦Ê÷.Ë©Æëj *³ö½_;×¥ñÇóëþÉç [JT¦så)œû§/9T¿ç×ý’ÿÎ>¿ì—þpÕ´¥)œë»—œâS9×w/9ÅRÿŸ_öKÿ8iüúÿ²_ùÃVÒ”¦s®î^s‰Lç]ܼçKþ}Ù/üá¨òV3:a~ŽI•ãB-×ÛU1_•S:ÚÝMÏ©»-÷i4yjÛ,[¿Ö¡¿å&×{E¾ªî­­ßzR™Î»¹yÉLç]ܼä¥)UJR” R” R” R” R”ÿÙnetgen-6.2.1905/doc/pictures/viewingoptions_5.jpg0000644000175000017500000007360513504650527020431 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ0¡"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…nøRÓMºñ­¦©›kpƾT«7 FïøÖœ¶Ó,t«mNÕ$Õ5lYÆ\°U†7 #mdÇѸ"³HEÙ¢”[ØãüäÿŸ üü(ó“þ|,?ð?ð®ÎÓÀ²jwÚœ‚G‚Ú=R[E½³M¬Fâ3ò õ$Õh<ÓO¶¨‘57Óî€"Š\Éœò»Tž‚’«H|’9_9?çÂÃÿcÿ <äÿŸ üü+¬ÿ„N-;P´[Ë…7ZM:(LG'ÌÈnp=zÒ?†tßø˜ÞÞêɧ[E­Ë¦F‹jò ŽF0IüaÖkH9$ržrÏ…‡þÇþyÉÿ>ø øWM/„á±›\mOSK[M"DŽIÖ!v|lAÏ9ôÍgkz'ö?ˆ¦ÑÖaq$B?œ.ÐÛÔÆ}ê”é·d'-Y•ç'üøXà,áGœŸóáaÿ€±ÿ…tú„ ³UŠU.5 &$–öØBʨ¤v¹á°Ï¦Õ¼i§¾µoo¬­Íî“ ÜOnmš?Ý ;²F@=j}­!òHä¼äÿŸ üü(ó“þ|,?ð?ð®ÏSÑt}g¶¶r;I¨EjòBð¶ÙUÛBÛþ\ôØ1õª’øfÍn/îoõôûOíy4ëP4›Ü1휪€:’ÄUi‡$Ž_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ êÛÁÖ–VÓˬk)cäêÙÇí(f(HÁîp8ïÚŸmàW›RÖ­$»cý–èŽ- 3K&á•*€Ž0yçó£ÚÒIœŸóáaÿ€±ÿ…rÏ…‡þÇþbêÙ ¾¸·FvÈSt‘ØãÕ[•>Æ£ò…j”Zº#R?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ ¤Eqa¦€Ã#6ÉŸýå?üøiŸø ŸüM^·‹ý.?€*—Êö©Ðf:±iŒCOÓ÷޹¶L/qRùOÿ>gþ'ÿSÇüLåãø¢ÕHô¹/Y›P¾÷®¡#1{Rm-Ò@Ñ.æÓôâ3ƒ‹dãÿ¥Ei\Xi 0ÈͲgÿA§ÅdaÝä+!]îrN$Ç?•Iq %]n>ÎcEq!è0:j.­{µ"òŸþ|4ÏüOþ&¡iš7;-m`š6e‚GF†VGF“s>§rÒLM¹‰F-†Al¾r:zT·QâyÏùû¢ˆµ%°4Ñü-_ÿÐkÿ%aÿâ(®6ŠÃ’=Šæ}ÎîÕ ÓíH>D}Ýñn73n~+Ô|)á÷Â:=ÍÅŽù¤³‰¼×;G`Õ®|áÁÖÀ¬òñTž& ê¶)S•òá[T-Âʧ™`ô#×úÓ|¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅRŽ&œtIƒ§'¹ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUWÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯e ðáé`Òy?øªC௠ƒƒ`ÿ®òñT}n‡ì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñT£Á>##OÈÿ®òñT}n‡ì™ã^W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xâ«#«¡ÚÊrê iê>"ÕõXëW¿dó¬ýž(Ñ„y », ’qœÀêð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUKÄS“»CT亞TºÖ¢b½Žæ×L¾†îñïZÞîx㕉ÉL0#®:šm¦¯ªiún­gh¶P¦¨˜$EV AÊü¼1ûW«ÿÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñUÚaòϹå—æ­w{¢\\f2¯Ù€FùØmù¤ç“ò/LTž¥wi%´¢ÔG.ªÚ«”FÍ`FÑÏÝç§_zõ¯øBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*Ÿ¶¥Ø9%ÜóËfûZ»×9#Õ7’Þ+1<{ÖpAž{t¬gSm{Äú†°–ò[E9A >7…U ÇœgŽ•ëCÁ^=,úO'ÿH|á°pl?õÞOþ*”kRŒ¹’cp“V<·Sñ±©Û]ÛÈ,"ûj¢]ÝCÙîq€Íœv«^'ñMη¨ëi–Öö–ÞZKpÐm¹™@*͸¹ é^‘ÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅRö´o{,ûžZÚæ¢_Io³éìúYÈ¢o4ªª1 ‚¹öÞ–ßÄ´ä¼mОù¯ÄW0HfbNäù{“üëÔá ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯mK°¹%ÜòYõMVîÄÚÝK Þf¥ý§,¥v—nÜ Çl~5dëú‹j÷º¬–:L×wS,¹’ÄeT(ÚCIéóx;Ãñ4³Ù¤Q¯W{‡P;u-U°¼ýû/ü?ü]/mG°rO¹å3Iy}{s}0šêæO2F>€vqMò½…zÇö‚?¿eÿÇÿ‹£û Áß²ÿÀãÿÅÖ‹¬½œ'ò½…W°¯XþÂðG÷ì¿ð8ÿñtax#ûö_øøº[‡`öLò+ØQå{ ö(|ወ–X,ÒXÛ£¥Ã°=º†§Âá¯ùñ_ûÿ'ÿGÖáØ=“+ÿäÿâ¨úÜ;²gù^Â+ØW²xpô°é<ŸüU/ü!ÿ wþF“ÿŠ£ëpì?dÏò½…W°¯fÿ„#ÿôÿÈÒñTÂáßúäi?øª>·Áì™ãÒÁcyd–÷‘—U*Uº¥Ek¥èÖS‰í­ü¹ 0^ÍÿG‡èÿ‘¤ÿâ¨ÿ„#ÿôÿÈÒñUX§½‡É#È£¯) †Ç=¿ÂÛiå™·L¥‰bäQ“×€kØ?áðïý¿ò4ŸüUð„xwþßùOþ*›ÄÓ}ÙÈò[d´ò-Ãc9ƒë’I4»,æ¶Š+„ݳiÚT‘‘ÐׯÂáßúäi?øª?áðïý¿ò4ŸüUY‡`ör<‘…‹Ü$ì3*ö6@=ES»Pþ|Š>R3ô¯gÿ„#ÿôÿÈÒñU[Pð_‡ãÓntü2Âä:N¸?íP±0ì/fϘh¢ŠÐƒê¯È¡ÿ׌_úª$¿¹Šñ ŽVvîÊÉ}8«þ ÿ‘Cÿ¯¿ôXþ(ÿªÿ×1ÿ¡5yÓÝ ß·ÞÏÜÿ÷ðÑöûÏùûŸþþá|g|-¾Ô«©GÉddŠ¿’ÕѾ|:m˜’ÚzlߢK=~êMF{{¹e‚v¶–ýܪÊ|•SçaHÊÂ5åOÌrKH×Ûï?çîûøhû}çüýÏÿ qúž¬ÇæÅaqs-¹ò¤rò“$ûÁ&Ü:çÉ8 Š8TËc¤jRL>Ýz#[X¼³›6˾CÈÜÙ*¥æ,­ü[ñ«û}çüýÏÿ Eo¬KyÏk©<ð¶vÉå”àààƒŽ¢¹‘²µa5Ó%ëÙ¦ªZê5Ü𠌺Ž9+œÈüÅr0[k6Ú ¼’ÎäyGæG§ tGa,®C‰HuÎÖ<³|ǃV¾Í¨ÚßÈö¶2IO4é ²Dbf`ä›bÈÌÜîù@g#m0:KtÚ,qª˜V%VÉq´ bB““À$=Hªóø®ÖÛËóõøbóPI™xzŒ2yÖ²ït¹RÝ.Os¨ D< ‰"¬¿»Y2›@vXàc’ü’++ÃŽÒ¡ἒi±µHVŽ`€à¹.»¶ñ¸’8¤¡ñ]¨žH¿š=Ûãû`Ü»A-‘œŒséƒV-5Ó–ÏU71†Ú^àLƒ×‘ù×Ö:¯öv³aök÷Kz!RÖþ@23²Aó2r<Ç éÑÙiâÒYg’æ{«‰UQ¥›`;W%Wª0 1éžzôÃfj7VP«¬«sw,eË ppsüóSjZ•ãjq"*9@ˆùÖ$ßòÒ?ì!ó­ ÿùÝ×Wþf bVÙIÎ÷hן™×9QÏ$mlŽØ>•/Ûï?çîûøkÎÝcYãŽÓX¶SáHd½B±;‰ÕfO$´Cn9àù»†¶šDêÍ~^IP$†åÌXÜ–Ú~Q…‘H*8Ál±¨Õ. ­¾”ȪLrÎ èp#O]FõX0»› ç—$~UÆ>—«H·7Cφé4Ø’Ý#¸áçC)]ä±$Ë•fe%ˆ%ñººªB: jx’þò{ð„i³·‰îùÈ9Ë pz œ ó]l—kÄ’\y›djÏ‚í‚Ø§ ǰ'µpÿ?ÖëÿõòŸû=hø×PH:©8C ¦¢^@×0ÂHkiÐ`Êè¤åÇÎ2{U <—kÄ’\y›djÏ‚í‚Ø§ ǰ'µÝ­­¼—(bRòI#íTP2I'€ï\ˆÖdñׇu]©í⼕/…µü ‘FceÄ¡&(çsDà ÄzƒËxŽ-KTÔï´« ß¶ÞÏö襅59’A#Y,ØãŒ1…D¹Ãÿ-3@ÏWšímÐ<÷$,¨ßh,Ä*Ž{’@¹ Tžcÿ}¿:áuŸ ê7Q^Y¬úÝš5ìeïÙdštÚà) »KF±í_–5b ì ‘Öéba¦[¬öïnê»DRNfuQÂïsÏŒnå¹ÏÌßx€`ÞÝI§x²âÞØ*C>%ä©Ù¥WUÝìH<ã®9æ°&ÕncI'šúHãP]ÜÊUTu'Ð ØÖÿät?öŸÿF%qþ ¥ðÞ©• ör¨.ÁFJ¤ð¹â“~ÏÄ)¨ïû°·>^7ù;öç¦pxè*±©q*–ŽúWPÅIY‰‚:õ}ÅqVÚ¡ÕmþÍmuwxÑÊ%ž!yj'–-¤a 6€û $¯9ÅfßŨéúCÛÜ]l¾d¸xaûsÀæF–F @›r|˜ÀàoÅzOÛï?çîûøhû}çüýÏÿ qñYk‹¬ÝÍ,÷"!沘v‘"ùh¡åÚ¬2¼˜—”9b -ðßÁk4w±HŸ>PÍ#3ž9àË.?sòŒeŽ¢×Ä7öW–0+¬«sy.eËV889ÿô ò§ÿ®ÿa?ô*õZhh(¢Šc (¢€ (¢€ (¢€ «©ÿÈ*óþ¸?þ‚jÕUÔÿäyÿ\ÿA4 >B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"c×zâÏöȻĎAêO§½ ÿ‘Cÿ¯¿ô] ßòÏýÁ^tþ&t­Ž;þÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢¦Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác“Á:ƒÝØÊ.¬¶ÛÝG3þñ²UO8ùzÕ«Ÿ ^Íw4«sfݘeÛ8'é]EX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&‹/ßÛj·OudR[·HÙÜXýÞ•ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç'‚u»±”]Ym·ºŽgýãdªžqòõ«W>½šîiVæÌ+»0˶pOÒºŠ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xç|+ỿ¶¦×SÛIö¹•ÐBäà Ýr¨®ŠŠ)Œ(¢Š(¢ŠÄ¾Ðnouó¨G5ºÅý-¦×b{2°=:`õ«7þÛÿùú²ÿ¿ÿÄ×[Er_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]m¬+—ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E sx+P7º|ßj²Ûowî<ÆÉU98ùz×käÿÓHÿ搜Šc$òé¤÷ÕOý4þú¨è  <ŸúiýõG“ÿM#ÿ¾ª:(O'þšGÿ}QäÿÓHÿïªŽŠ“Éÿ¦‘ÿßTy?ôÒ?û꣢€åá´·’â{ˆ’(ÆY‹tªÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢¼ÇQÚ‹ÍRÏOuº’}F%¹ä–i"Hî ²µ¹b hâØA9-‘ÌϸÓ¨¯5ÔßÅcQ±Šê;׎ÒüL·pY¬Ò$F;ØYÀ\)o-!“$<ØØÙH«XÞêfo KyìŒ×÷ 'üK÷æ ’¤3JDdÃ!,ÿ«Ç™ *!@;J+Î/uO‹íx@Ž†Þ Æ‚ º•Uo!¢ÿGÚÒ1ò‰S3õq°•.kö:ýŽ݌—÷³Go.Ÿ¨}¦ÞÖ0I fH×cnXÖ%‘Sæ“8ŸpRÝÑU4¹š}2ÞGY+×h©+ÀvPRÀnƌજƒámB;q>“=®£ÑÔoœÓçXŠµÌ²)óJlÁR;¹Èh©¢¸M>ûT>†;f½ŽéµK˜ßu¤V—“Æd–Eh’dHšF]ŽÄ® ù§ïŽ24¹¼Oqµ­G=ïÚmlQ$µ‰¤»– «Ð9A°ü¡CˆÀbYJ²ÿ©Q\–my¦øË[YæÕ'Žúëí)‚?³¬~LKæ˜4f0›‹c TòõÖÐEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQETÕc½—H½L™!¿x$[idT”©ØÇƒÀ8=Ðк+´¾_ éšÆ±-–£m¢ÛÀ’ I¥ŸÎ]þ{–8bP-µ™d“8c#ÔñÅŽŸ­ÚB°>×w!¿ÿ²”GŒïó\ÿ…gÖÞþ¦óþüÍ'“â_ùé¢ÿßRSU%ÿžš/ýõ%ekX,Þ[ir¨$oŒHTッ޺šá4ŸùCÿÿÐ&&hÿmkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE ’mkŸÜÓ¿'ÿ?¶µÏîiß“ÿGE šÚ=Ö«{,uö%‚ 7•·zc'üþ™ ©¼ÿ€3ZtÆQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@b î5}BêYÖå1ˆÆÝŰ íÏò?ŽÕTÕd½‹H½“L…&¿H$kh¤8W”)ا‘Á8GÔPìÿçûÿ!ñ£û?ùþÿÈGükM×-ôËMRþóSžMÖ(äûuò•NKyÑãh</å ò»¼cDhÏj—­p&Óî\£Y¤Ú/Ù¾hﮉ|£‘ɳËà•^GÏî÷ÆX,nÿ`Gÿ?ßùÿØÿÏ÷þB?ãX¶7º›ø™cy'7&êt¼´aû˜,À³Ê½·1ò ,^PAò±[E‚ÆgöóýÿøÑýüÿä#þ5§E ŸØÿÏ÷þB?ãGöóýÿøÕÜÍÅšMuug¦2Èe¹´RÒ ÁO%8 pĹn•ç~ÇžÃ^…_JÒµ‹‹[oÝÙ‹‰,UÆw<À¼žÝŽNB±ÚH,'þÀþ¿òÿ™4Émí&Š×RX¤”¯ï ¾í g 'çüöà´Íkí«wwáíwíJÑ+<_oûeÜ‘™c\ýœä@ȆFXÑHc"†@TG]‡†§š{;ŸÞ¼ö 9]>æF,óÁ±HbÇ–˪¹å•U²ÙÞÀeê¿ô2äŠÿ"é’+ñ«<†G± ±Ú«ëŽŽƒÖµh  ¿ì½Wþ†Oü‘_ñ¨­<1­ªCý¡»nyòHïŸZÙ®JÆ÷S,o$æäÝN—–Œ?s˜öyW¶æ">A%‹Ê>V"ÚþÀþ¿òÿ?°#ÿŸïü„ƳnüDu}\øQ¿µ®šÚi¬¤‰ž¹ÜÊ%eFn œ|êøunjÃWÖæð®‹pÏ{ÛhÖòiªÄ?Ûïv°e”‚ÙR¡ Wä’G81Xíÿ°#ÿŸïü„Æìÿçûÿ!ñ­:(°XÌþÀþ¿òÿ?°#ÿŸïü„ƴꦫ%ìZEìšd)5úA#[E!¼¡NÅ<Ž Àê>¢‹ŠÿØÿÏ÷þB?ãGöóýÿøÖ.›®[é–š¥ýæ§<š¬QÉöëå+ œ–ó£ÆÐx>_ÊåwxÆ6ˆÒˆüMö}~Óæó´Ñk ퟑä}µË>ä‹iÝs&ÑȇÈÞaÞyދޣû?ùþÿÈGühþÀþ¿òÿű½ÔßÄËÉ9¹7S¥å£ÜÁfýžUí¹ˆIbò‚•ˆºÚ,3?°#ÿŸïü„Æìÿçûÿ!ñ­:(°XÌþÀþ¿òÿ?°#ÿŸïü„ƨø–æh.,Òk««=1–C-Í¢–N y)Àc†%Èp쨇;ö<öô*úV•¬\ZÛx†îÌ\Ib®3¸æäðìrrˆÎÒA`±?öóýÿøÑýüÿä#þ5Àhú¶¬ë!³¼ž{“j­}åܱܽ7›‘ä²-gTi™mÐ8f ¸o-CwžiìîzóØ$åtû™³ÏÅ!‹X.ªç–UVËg{ ÿ`Gÿ?ßùÿØÿÏ÷þB?ãZtQ`±™ýüÿä#þ4`Gÿ?ßùÿiÑE‚ÆgöóýÿøÑýüÿä#þ5§E ØØ¥„S?šdÛüqŒÿMEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEG<Ý[ÉoqK ªRHäPÊêF ðAªJ( Š( Š( £0B× pÑ!™‘$*7*±€=@%W#¾ÑéRQ@Q@Q@Wžiš„MãûË{ Z{™F²ñ\[}½çX­¾Æ–X„Qs…ÜÁ;2Û@ü0Cn… ‰"BÌåQB‚ÌK1ã¹$’{’MI^yÿ ö¡à´i—vW—/¬ý†y­îÞ5(מ_ÊÙ‘“z2c ò,›üª »è5ÏíÍDImÍœ×2J57Yc‘$ˆd7•ûá“ $âLæA•ËwW7ž ­íÙ%÷Ûï!¹ŠfhÖ#K‡‰ä~|­ëm–r—eRƒâÿü#|†Öâax°IsP‹{xÊ Ì.š"w.ÜЃ"dr¡À=ŠÌðýýÖ§ Ú^Þ@Í2–Än®®¹;\f\2á°±»›9>ñp'Ó'ÖmeÕF£|‚Õî•§ ·2í Ý€€`c…µt³Á Õ¼–÷$°Ê¥$ŽE ®¤`‚Ú¤®Lñ-åׄí…Å­ì˨ÜÛÜÝÚÃ-ÚD«,›d¬#<"¿Ê% >EÅdØø·_”k:ÆûW‡OÓÄñI ± 77©µ"fÌO"Ä2ÌIR oáôê+’ѯï¡ñ–·§ê:œ,·[ììÅ»ù¢/&"$y C¡;B™3È-²ºÚ(¢Š*3-p— ‘YB£r«XÔUr;í•%QEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQETÔtË]RÝaºG!zŠªänÛöÄ'¸ëù‡þ[ïúäÒÿ…Tºÿ‘“Sÿ¶_ú-+Šå¯øIo¿è ÿ“KþÂK}ÿ@oüš_ðª´Qp¹kþ[ïúäÒÿ…ð’ßÐÿ&—ü*­\.Zÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E –¿á%¾ÿ 7þM/øQÿ -÷ý¿òiªÑEÂæÎ—©Þê38}5`…^Cp¯@Ö­fhêo?àÌÖ1…Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEP\ÿö=ÕÖ¹©\ ‘ÄÆ0!Æì Î?Ïõ®‚ªj·sXi·–ö¯w5¼K´yÝ3*’`’F:½(—öÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þ[FÖX¾ —š­å¬]N0±ÂJ€ªÁÎvKr~w¯â=v÷N¼¹[vHÅ•šÞG ®[QrìžBwƒåÉß4]¾I…cGûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ γ×of×¢Ù Oyqföyj†+;¸Ý“.!Æ:ËÔÑ`±ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…lQE‚Æ?öÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þˆ5+‹[»KHï Ó¢–)§{û… ˜‚°Œ‚@ùf<çdRcçKúf¥öí?O–æ/±ÞÝÚ­Á²•¿y ¼`€NÒê ÀÁ#8Í ¿°.ç½·ýöÂì Ÿùïmÿ}Ÿð®}ujÒÖçRŠíï´ÖTlº†4YäEó TÃý¥v2·*ˆUÊ’õÑh7·Q^Áq'Ú>ÅtÖÉw€>ÒT–Àùw+3FÛxßp¿uK†ÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?á[Q`±ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…lW-g®ÞͯE²žòâÍìþòÕ! Vv=pÿ»' \CŒu”°XÑþÀ¹ÿžöß÷Ùÿ ?°.ç½·ýö›­ë†ÇLIì#{·–sl$‚ÞK”†àÌé,B”eÀÆ[ Jä²òÖ~0ÔçðΟæbx´h/ÊMÆÕ'bQá@@Ç̀姄Œ¯Ë!`±Õÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?á[Q`±ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…lUMVîk "öòÞÕîæ·‚Ic¶;¦eRB rHÇC×¥ ¿°.ç½·ýöÂì Ÿùïmÿ}ŸðªÚ6²Åõ¼Ômo,í`Šèêq…Ž$ ì„‚TP®s²Xó“ó½={ÄrØëíhMì6V±êsZB˜‹HÌgXÔDIT̸lÆÆÉ`±»c¤ÜYÝ­Ç›låa|Â2p@çsQù>%ÿžš/ýõ%eYë·³kÑFì…'¼¸³{¿¼µHC\?îÉÈãeêiŒÉž óüö} ȱ4i‡¹”’F9ûžÝiÞO‰禋ÿ}IZ”P?‡õ)/®nî§°ó&ÛÄNØî>•cûçþ{Ûßgü*jW·v–‘ÞA§E,SN÷÷ 51aóÌyÎȤÆΗôÍKíÚ~Ÿ-Ì_c½»µ[ƒe+~ò>xÁ¥Ô‚Fqš,+`\ÿÏ{oûìÿ…Ø?óÞÛþû?á\…—е¨-b»žg‘/lÖå^ê8ü…HU§€G‡ñ¬ÅØNUö„äbB;öâê+Ø.$ûGØ®šÙ.ðÚBª’Ø.åfhÛoãn¬7ûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ Ø¢‹Œì Ÿùïmÿ}Ÿð£ûçþ{Ûßgü+bŠ,1ÿ°.ç½·ýöÂì Ÿùïmÿ}Ÿð­Š(°X­§XIa À’H˜É·=3þ5fŠ)Œ(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€(_hºf¥¤ÜéWv0Ics»Íƒn‹1bÜtmĶáÎyÎy« ciV±%¬ ¦>Ϋ)A°ÊJñØ‘SÑ@ˆ![‡¸XLê¨ò™T’ ž¤ÍÛqõ©(¢€ (¢€#šn$ñ$¨\+¨`He<÷bª’èºdúݾ³-Œ©[ÄÐÃrWçDn Ïé¹±Ç7è  Í;ú‘p×f§YL˱¤¶µHØ®AÁ*Æ@ãØUø †ÖÞ;{x’(bP‘Ç…TP0€íRQ@Q@F …nábA3ª£ÈneRJ‚z 6mÇÖ¨kóÝ[èÓ=”©ÁhÑY™UŽçU!7ü¾a„ ò—*®jÓÅwö÷ÖºÂ÷ºœí:…Ôæ†ÚHZ5†M’4A‘ÉI·œ  ¯à©Òt]3A´{]*Æ 8W™£…v‚ìrOô€0a,m#ŠÖ$µc´ÇÙÕcC…(6áùI^;+’²ø‚5=FÖ; ök)¾Îo&Rñ™£Iü±´[UeBÅ¥R0Ø ºx|cpÖV7³i°%¶¥öy,¶Þƒ#E,ÐǺD* °¡Âï\‚ ©`¶ŠäµKu Óé·>Oöv½g§Èñ2H³«¼Dl©Û9”€A:ŽEXÕ|Z4½~ÞÃìŸh¶ya·šx¼Öhe•‚ª¶"1¿;¤VÃd)ʆéh¬ kº†½§Ú_Ühÿb´¼µKˆ[í+# €HpÆweHÝí‡ V./n#ñ~›b²bÚk ©¤L]$· s×#þ~€'¾ÑtÍKI¹Ò®ì`’Æçw›Ü+bŸèÛ‰mÜóœóDš“7ؼÝ.ÉþÁ±î·Cö|c_&6¯Lt•·÷ø¾ÏN)‹i¬'œ0ré$JC.Ìð$!û¶W€kŽ»ø‹u<‘ÛÙÚÚ‰ —É·½Yn£_µÛÄÐͪ¬22ÌWÎÖ 3ÆhÐÄ­ÃÜ,H&uTy̪IPORfÀí¸úÔ•ÅÞø“^{ý6ÒÎÂÉ.ÓT{+Ø^ñ¼§?diÔ,žIb»J±mªC&ÜKWaðÝ[Çqo*K ª9#`ÊêFApAèJ(¢€#šn$ñ$¨\+¨`He<÷bª’èºdúݾ³-Œ©[ÄÐÃrWçDn Ïé¹±Ç7è  –šVaqsqgakm5Óo¸’UfÉ9rXäžO©õ©à‚ííâH¡‰BGjQ@ÀµIEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Ï7Vò[ÜD’Ã*”’92º‘‚<GjÉ“Âz¦ÙMµû¼Û¥>ÎVI#‘‰Îè”rO^›TPI4­:]N-NK W¿…vGtЩ•žã |ÍÀ=Ï­G‡¤Ãöß+K²O·çí›mÐ}£9Ï™ÇÏÍ×=O­_¢€3&ðî‡qf,çÑ´émC+ˆÕ*S´Œd `éR]hzMö¡ ýÞ—eq{ß*â[ty#Úr6±$‘ކ¯Ñ@Á6¶ñÛÛÄ‘C„Ž8Ô*¢€j©©hzN³åjivWÞV|¿µ[¤»3Œãp8Îä*ýA4=&;»[´Òì–æÒ! ¼ËnáŒ#c*¸$`qɪ–Þ¶Šñnn ùvËzQźïG¡˜îŽ#ºBí”9$ª(¥Î•§^[ÜÛÝXZÏ Ëž9aVYX°# @Uäÿtz ·EQEQEQEQEQE`é·ºœž/Ö,¯dƒìÑZÛMmCî’áIf<³0Iàè3‚̽Ebë£-½œv7(‰yyö)/Sk‹S‡ó•ß½@7Ýrž“ÅÚ›Ù=Ðò"kKV¹‰>]\‰ž °ää+…—is›˜9`1(wEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEV=çˆí¬ï¥´6×rÉ7£ 9ýëb¹ ¯ù5?ûeÿ Pü%vßôÔïÈÿ?á+¶ÿ ~£ÿ~GøÖ}®+šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¤ž'†W ›©;аOëT¡‡F·ÔΧƒ'Šü³9ºM-RÍÇxç'''<äÕ½þBðÀ¿ô]˜ÿßoΘÎSO‹JÒôÉôÛ _AcpÒ<Öë`6H_ïdgÆ:*üšªÊñ<š¨ï ošÏ%r9àá˜dv$w­6š_íXSÍ}¦ÞV+¸àñàþ§ó5gÌï·ç@Öš“ÝÏåÿfj dÉ<;~$ÿ*¿Yºl&»®‡v`‚ÝWqÎÒp?OãZTQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQE̶wwâ RH!f@b]Ùg`ã'ðüÅtÕSUÔaÒ4‹ÝNá]¡³‚K‰0 E,@É8´™ý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿXÒµ+¹µ ½7Qн·Š+‚mØ´f9K…`å1º“Œ¾]Ŧ¹â9´Ë‹ß&’.Íu íä†hI‹oÄR7ÍòªÿtV‡ÿbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ãLµñÓêp…Ýäú}¹ù¢h|Ýìã¦ÆòdªNw‘CE‚Æö&£ÿ>ÿøúÿØšüûÿãëþ5½E ?Øšüûÿãëþ4bj?óïÿ¯øÕWR»‡P´Ótè {Ûˆ¥¸áŠÆ#ˆ a•îc"(8À›æÚ­éZŒ:¾‘e©Û«¬7GqÈ`®¡€8$gÖ‹ŒÏìMGþ}ÿñõÿ?±5ù÷ÿÇ×ük5|OªZÍsöˆ­ocVHZÅ$QAró$I ™ò&œ†tQ³Êl¦æ 7t}FkÑymt¨/,'û4í"9ËI($ ȧ;NFXİX©ý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿoQE‚Æö&£ÿ>ÿøúÿØšüûÿãëþ5½\õ¯ˆæŸS€4,.ï'ÓíÈ'ÍCæïg67“ ämRs¼ˆË‡ÿbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ãVÿøúÿØšüûÿãëþ5½E ?Øšüûÿãëþ4bj?óïÿ¯øÖõTÕut"÷S¸Whlà’âEŒÅQK2@έ ŸØšüûÿãëþ4bj?óïÿ¯øÕ+R»›P»Óu KÛx¢¸&Ý‹Fc”¸Q–îS©8Á[åÜQhk>)‹O×âÒþÓ¯—wwRÍËû–f^±FÆ-+‘å2ÊX,Oý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿ2×ÄsO©Àw“éöä扡ów³Ž›É r6©9ÞD}  ?Øšüûÿãëþ4bj?óïÿ¯øÖõX,`ÿbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ãV5]JîBÓMÓ¢ïn"–à†+Ž"†T¹Œˆ ão›hF·¥j0êúE–§n®°ÞAÄk ‚º†à‘œZ,3?±5ù÷ÿÇ×ühþÄÔçßÿ_ñ¬+_2¬—0A7Ú¢F‚%…àI$±Dˆ%bËsé†fˆmsƒæ ®£GÔf½–×J‚ò³NÑ#‘¼´2‚I¬Šps´äe€ KŠŸØšüûÿãëþ4bj?óïÿ¯øÖõX,eéÚmõ¥òO%³@Ç ë“òœÍj׿è^ÿÉØëRŠc1Ãët.B`RT]Æwd<žÜ)õ©>Õ¯нÿ“±Ö¥›£Úߥæ«y}gö_´ù;ÍWû ƒÈü?:Ò¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€1n¼+¥\xvûBŽ´³½VY>Ë!Æ@@¨S• ¡1´m«rhÚ|ßb3ÛùÍe!ævvÆ71$¿*óó"·ÞPEú(¤z]”ZœºŠ["ÞJ»QÔŽ3ì €ž¤"‹‹tQ@Q@5.ËV·X/í’x•·…\ )Y”ä yô;[Zk%굂KtE¸aW*I)œòÿ,䪕Ӣ€1tï i]»[[Çtö­ÙµÍì×ùXhŽGe:dt&´ì¬­ôûDµµdIœKIÉf'–bI%‰$’I$šžŠ(¢¸ûïÞÚêz…’iÎâ ZÎÊ;bKö}åÎì‡|Žw)‚ÈT°ª‘évQjrê)l‹y*ìyGR8ϰ$*zˆB.9mW⬞!‡OƒÍÕ4«YçXLÐHÊ;Y˜$¤ª©*J¾Ç#;A Wñ­–ƒie&§i=­ÍÞò–“Ü[FáP€Ä»J#þ%à9'wNZ‡káû,ì互7ž[‚nnfÜìX€X“ŒŸÇ’rÄ’'‡ô¤·Ó`HcÓURÐ1'ËUhÉ9` £`çæDo¼ Š:Œlµ[¢š}ž£sl­½Ú[þéD±Ç$mÉÜA(8RS’áW g·×ƒC¯OVÛrׯz]ö³c¦ÚïÞÀ·ÊÏA‘¸"7u•ÆÞêŒÈ$`  ‹¡xšÏÄÐÚÆèlØ+ù’D[’ÔW/ùOË"£˜È mPMGK²Õ­Ö ûdž%má_×À‚ÊGFVe9ƒ^}ÖãÄVšãÉt.­`’ÝnDUÊ’Jgü¿Ë9*¥tè  ›_ èöžpŽÓ|rÄЧ‘å"o½#’±ÆpEHUùF/ÙY[éö‰kkÈ“8–$“’ÌO,Ä’KI$’I5=QEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEBMO—ííóö‹¨¯%ùÛæ–?/cuãT|ÞAÉÍú(ßÂz-­ÃÊ–®áà{_&k‰%…!r¥£HŠ"Š6¨œP|)¤tˆGtެÏöˆïf[†,;¦æ0!P`±Dþêãj°|S¨êÚ}µöDl³ÝyR²=ÆÅòä`v«¦2ꋹ˜(Ý’@æ€5íì­ífºšöÉw(šc’w8E@yéò¢Ž=>µA|5¥¯ö—î§oíD×î¥lÈ1µÓ,|¶\ÚFÅÆ6®0cñ…ÚiÓÜ2A;iv­yª(Âv‰&¢7¸óÁ.Ir¤ âMéÚP x;F}>K&KÖŠ[¥¼‘Ž£pdyT(V2oÞq±03€Td Þ¢ŠÅ‹Âz,'+jä+FÑ«ÜHëÉEX”± dC±0§b‚ /ü5¥êQOÄS…¸ºKÉL7RÄZTUTl£À0:eAÆFkZŠ¡&§ËööùûEÔW’üíóK—±ºñ*>o äæðÖ—·’yS³^]Ey8’êWXÙYÄ. ' …QŒ+ZŠÉºðÖ—w4Ó¼SÇ<Òù¯5½Ô°HX¢!у+yPpJ)##4ù´ L_Ïö©e ®#{ɚ˧É-åä;x`¯5§EfiÚ †™p×}ªIŠì]ÞMrȤ‚B™YŠ‚Bä gjç8Ó¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ ͺ×ôË+—·¸¹Ù*crùlq‘žÃÞ´«ºÿ‘“Sÿ¶_úkÿÂU¢ÿÏïþBð£þ­þòÿ…dÑJâ¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü*ž£«øoT·Xn®œ„mèñy±I`Œ«¦N d:+KÃÌV+²Éýk[Ï“ûß ¦3[¯*Y§Èßcbð–ŽFmÄî%‰r\%³—Usó(#Oþ­þòÿ…jÛ^O$·aŸ"9ö/å¡ÇæÇó©üù?½ú Ãÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ Á²¹šòÕn.$i&±fnüš±Jâ¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E ›¶zæ¨\y³´²`¶N0=I#´k3@ÿSyÿþf´éŒ(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ äæ‚iüIªùQI&<¬ìRqòWYB~ì±O”¹ÜÛxÉÀ?€ð gìŸóé?ýû4}‚óþ}'ÿ¿fº1ÿ¾ßbé>']Vâ$Kwp» ³ö˜P_”9t;O;]ÞÞ¨¬+~Áyÿ>“ÿß³GØ/?çÒûök¨óûíùÑæ?÷Ûó¢Ác—ûçüúOÿ~Í`¼ÿŸIÿïÙ®£Ìï·çG˜ÿßo΋Ž_ìŸóé?ýû4}‚óþ}'ÿ¿fº1ÿ¾ßcÿ}¿:,9°^Ϥÿ÷ìÑö ÏùôŸþýšê<Çþû~uË[x£\›W½ÒΗa-Õ¤ $‹iª<§v5“|I´½ÉˆTû¤²,ìŸóé?ýû4}‚óþ}'ÿ¿f´¼=¯>»§Ésˆ‡—)̵¸óà—€wE&züÛIÀÃ+¯lo1ÿ¾ß ö6›ew$¶wnX Xâ…™›¯AGöãÿÐXÿÀ_þ½lyýöüèóûíùÓ…«$?hé©3N\ µ9P#EÉíÉSÐö©·þ€ºÇþÿõëcÌï·çG˜ÿßo΀8Í3M¾N‰^ÊáXg!¢`zŸj·ö ÏùôŸþýšê<Çþû~uŠ|J­âDÒ!’ß*Í­5×—!F$Ùx&R‘˜ü¡CŒ;€VŠ?`¼ÿŸIÿïÙ£ìŸóé?ýû5{Iñ:ë½õ´RýšÞ'Šé›å¹YU܃®ÌÄpÇïg#åÚ͵æ?÷Ûó¢Ác—ûçüúOÿ~Í`¼ÿŸIÿïÙ®£Ìï·çG˜ÿßo΋Ž_ìŸóé?ýû4}‚óþ}'ÿ¿fº1ÿ¾ßcÿ}¿:,9°^Ϥÿ÷ìÑö ÏùôŸþýšê<Çþû~u“âyô->;œD|ÉD~eÕÇ‘\ºY0ÛåÚY‘{ä ¿`¼ÿŸIÿïÙ£ìŸóé?ýû5—bÔÁ"X žiDw {rmÄgÍ’-©¹wI#42ìMªHC»aÀ=g˜ÿßo΋Ž_ìŸóé?ýû4}‚óþ}'ÿ¿fº1ÿ¾ßcÿ}¿:,9°^Ϥÿ÷ìÑö ÏùôŸþýšê<Çþû~tyýöüè°XåþÁyÿ>“ÿß³GØ/?çÒûök¨óûíùÖN»âÑVÏ·7-su § É*F]˜ñÁaG-Ø`3)`±›ö ÏùôŸþýš>Áyÿ>“ÿß³VµÝéÚÝ­›ÚÄ`¸•a7ƒí3·sÅSº4Þ ’ÊT+¤ZxÁõÝBKo&$ÄF\CuæÉo‚—r›G“/Í÷2ܤƒ?/%‚Ʀ‹ÐCwæÅ$yÙêFy5~œ]ˆÁbG¹¦ÓQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQE™§hVZeÃMn®p¾Tí¹m¢$CøP‘œ{*ýÔE]:(¢Š(¢Š(¢Š(®jëÁ^Ã4W:¾©.輈YÞ6h".ŽÑ‚PùŠÞZ+y¾a`'ælô´PM:Î{+vŽãRº¿rÛ„·+°(òÑ8ÏLòyéVë–³ñµ­æ§i§%»‹©õ›'B¬>v$Ý·?“€3×x˜Ûj6Ó¬ôïµÇ ì¬.­íÞݬ§ŽUÈ9ŒÇ¿oÞÁÆ—`;¸ –ŠÉºñ.—eäý¢YãóbYŽme>Dg£ÍòþåxndÚ>VþéÁgâmÿPkk¿2u–HîÜ/›`ñï#o˜6³lÎí£py  j+&ÏÄ×ZjÛ'h²G¶i¤“å•£æ?,H#æ~SžHŒrxZëDû$I=ž§<–í)‘‘áuŽGÁŒ®s˜X¥HÁÈUƒ7„ìfÖæÔ¼ÙãûD°Ïun6\I LÌWÌùJ¡ ®åèw6í©ÌËo#[¢I0RcI¢³c€X@Ï|zæ¬<`VÄÞk¶öºtr^Kcl ¸’妚6•Yqå)É1 d¶@Àb¿¦xOCÑu{OLÓmlæž·e·#PªÌÙ@9bÃ<ó±=+j²eñ.— ¥½ÛË?Ù§Ýû嵕’-§æ°\C´ä7™·nÖÎ6œG‹t)n&…u_!¥ŽY$FHÑâ-æ!‘€Pà#6ÜçhݼÐÕ‹'Šôˆ,⺸’êÚ9§û4Kqe4O$» …Td Ä…8ÀùÊ2Ç$¾%Òá´·»ygû4û¿|¶²²E´áüÖ ˆvœ†ó6íÚÙÆÓ€ j+/èRÜM ê¾CK²HŒ‘£Ä[ÌC#¡ÀFm¹ÎÑ»y¨ßÆZQ+Ïs=»<¢†âÒh¥gefP#dwynæe*2ÜPõA{o-գà äör61< ¯9à:²óÓzþ5™'‹4X’'k§(ë½™mäa‚T™°¿¹«‚dÛ‚Ž6¶-ǬéòýŸeÆ~Ñu-œ_#|ÒÇæo^œcÊ““ÁÛÁ9É»ð6“s(hŒöÊö­er"ØÆêbÌŽî¬ãs3–eef,Ib@#¥¢Š(¢Š(¢Š+'^Ðλ RöÊ8¥I±j"ùÝ] ó¾ë B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š* ëÛ}7O¹¾»“˶¶‰¦•ðNÔPI8žé@‡ÃMoo–è$—7ªR]¾q0q¹p@{à‚ÂóÇ9šgÃÝ+K†þ8gŸuçK¤6ðùO ™#uX¢E,çæ  Ž+kLÕšúââÒæÑìï`T• wWýÔ…¶6åÈÏÈÊFxdln]¬Ô|O¯j: E5½Žs¬B“ê ³Nä…‰Ê`Iã’ÀIÀÐ{ïé•å¥åé{«ˆ$²]à Á¸Pìøo26Ø2ïÄ{8l P»Úv—jöð3²<ó\äºYFÆ\ãÛj…¿ˆáŸSK!ÖÖiå´·º$bYâßæ&Þª–øcÁ1¿A°Éµ@Ñð]¬ž—F¹Ôonb’éî¼ÉÖ;Ý˰)åùn¥™›‚r0Uv–~ µÓí4k[]Fö(´«©n£TXHòÜðÈ  \õŽ–Š+&ZCö=²N~É=üyaÌ“yÛãî=ñßÉç:ÔP5âŸi¾.Ûöé§4_$pÉ…=×Íü¶ÿi6“ÆIÚ¸¶|5l-íãŠêê·¼¹¾ŠT(Ye˜M»ª@óÜ€GeÎyÎÕÅ¯Ãø,ÓO‹O½ž†ÿírÉŽÝ—K”HcXËn‘IÜ¿0bÊÔš¿Ã#Y±ŽÖââèYCÈRÚF/#26»31& Ge@½…™…dº5æ“"¼ÖwrÓ+¶ ÝÝ×+‚d`1Èç<Ön‘à}+Fkg·ÿ[×ÚD‰mosåDˆ êóI6ÂÅK 4 ʶïãð´çÅ–ú“ÛYE­Ô·QÏò3>øäB‚"Ï™¹Ù÷b¹o—­¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( «K¨ØÁ)ŽkËxä^ªò¨#ð&¬×} Rø“Ró#GÇ•Ê>A@?ö¾›ÿA Oûü¿ãGö¾›ÿA Oûü¿ã\¿ØíçÚûàQö;_ùö‡þø®+Gö¾›ÿA Oûü¿ãGö¾›ÿA Oûü¿ã\¿ØíçÚûàQö;_ùö‡þø\.uÚúoý-?ïòÿÚúoý-?ïòÿrÿcµÿŸhïGØíçÚûàQp¹Ôké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ5ËýŽ×þ}¡ÿ¾cµÿŸhïEÂçQý¯¦ÿÐBÓþÿ/øÔsê=Õ¼–÷v2Ã*”’9$FWR0Aà‚;W7ö;_ùö‡þø±¡iÖGtÒXÚÈWf7§}¨¸\£sa¦Q³±ñ#ZÞÞEå DÝ,³Æ£!3íPHê,Û·±s&£i¦jvëoqâY¼—ƒì×q­Ì;o#Á8Û„$É‹a;ºü«·{û;Mÿ U‡þ¯øT6öš|²]+iZ~"›Ë\[¯#b7?‹c3¡ƒÃðjfù/íò¥Žr¦(¥|ï‘8Àò}ØŒ$-§ý¯¦ÿÐBÓþÿ/øÔŸÙÚoý¬?ð¸ÛU†úÜ\Éil­!c¶8UTrp »û_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| WΣû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| .:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| .:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| .:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\êâÔlg”G å¼’7EIT“øVköÖñ%ä‘Á>w*pIÈÏà?*ئ0¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š+ºÿ‘“Sÿ¶_úuõ {m5n¯]¢·R<ˉœ€ªõf=è9>´ËÑ]›¯&§æ¬bxf‹ ¸‹Ë#gcí<í`=e8ee Ô|Km¦\,79Âù³º&嶈’’ŸáBF3ìÍ÷QÙU…cŸ¢º|Km>¦lRGÉfŠ9Šb)eLï¡u‘ìÀdÇ ]/>Oï~‚‹Ž6Šì¼ù?½ú <ù?½ú ,8Ú+£ÔµäÓ<¥O4Òä¬ñy’\o}£ªÏ©*£,ʦäÂêÞ;‹yÒXePñÉ ®¤dGÞ‹ŽB´ôÛëm>Æò{©–(óäó““À“NO@’²ß[^éêb3[›˜—7(W(ŠYÃn’0•\—)9KNÖ¥nÒG¾9#o.h%P$†@(Àdg‚A0%H$°XÎÿ„«EÿŸßü„ÿáPÛøIˆÝJ÷Š[‚Éò1$ãÆ29¯¡®‹Ï“ûß £Ï“ûß ¦3þ­þòÿ…sšOüƒ!ÿèF»ÿ>Oï~‚³añ-´ú™±I%š(æ)ˆ¥•3¾4n…ÔG³“@9ú+«½ÕO´{«©¶D˜É ¸’N¨,Ä€I$ 5“ldÓì/wN°ÝÚÇxäÆÙ`q•’b2sÆrz1û¨ìªÂ±•Ev^|ŸÞý|ŸÞý mÙyò{ôÉï…­¼—¤PÄ¥ä’BQ@É$ž½ …Ñéºòj~jÆ'†h°Z ˆ¼¹6v>ÓÎÖãІS†VP]k† B¡žêåö´‰OÜFN<Ç,@ p9fÃmVÚØ,9Ê+ ‡Ä¶ÓêfÅ$|–h£˜¦"–TÎøÑºP9ÌLrÒóäþ÷è(°Xãh®ËÏ“ûß £Ï“ûß ¢Ác¢º=K^M3ÊYóM.JÁo™!EÆ÷Ú9Ú Œú’ª2̪nA|.­ã¸·%†U‘ÊêFApAè°Xä(­oÙ΋,ÑÝZÛÍÚlæ•…äYE ¡fÉ2Ä0W&EIÈÚv°5+v’=ñÉysA*$2 F#8 ä!*A%‚Ç1Ev^|ŸÞý|ŸÞý mÙyò{ôyò{ôX,q´WeçÉýïÐQçÉýïÐQ`±‘ ©¼ÿ€3Ztö•Ùp[#éL¦0¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š* ë+}KO¹±»Ì¶¹‰¡•2Fä`AŽ éSÑ@ôú&«™ªM§ê¨úýÌ 7·PŠ©»Ë?;’Ø?3“·hXÃïü7ý§–¹»Ú×V«g©ˆcÚ·Q Çj‚I—qIÛ# îØé½EbÛør54¸óÝ­až[»{R"ž]þcîêÀù…<#õ{TQ@Q@šž’××÷v×og{¼K:"¿î¤+½v¶F~E`qÃ"çrîV‚ 3QÓõ=.ßN¹µƒÃÖ–mnöm4¥†Ñè=}ó»p)µErZ„.ã†æ-OP²¹{.Io-¬ 7RO‡ŽW‘¤um¬2®ÑÀ(Û[ÚV›ýŸï$¾}ÝÔ¾}ÔÁv‰$Ú«ò®NÕ Š dœ(Éc–7è Š( ±mü9 š\yîÖ°Ï-ݽ©O.ÿ1÷u`|Çž‘ú‚=ª(ž·Ð/51!ñEÚ]ÝAy-żÚ{KhcS½Pe6v9ž‡qš§mí4KM-o§h¾Á~N[íp.ã´$Ç˸ùO #(ÁÉÖÑ@Q@A}eo©i÷67qù–×142¦HÜŒ##‘Á=*z(žŸDÕ`Ó5I´ýU_¹a†öê±U7y`¢àgçr[ærví §¬ø1õB+éo [–µŽÞáþÌÇiBÄKn<ÌC(2>×o0®F?‹w[EbÛør54¸óÝ­až[»{R"ž]þcîêÀù…<#õ{TQ@Q@šž’××÷v×og{¼K:"¿î¤+½v¶F~E`qÃ"çrîV‚ 3QÓõ=.ßN¹µƒÃÖ–mnöm4¥†Ñè=}ó»p)µEqö†ØÌ&»LP’ÚÛˆf–E‘$Iî³ æVX1P2ÒeHrC¥i¿ÙñNòKçÝÝKçÝLh’Mª¿*äíP¨ªIÂŒ–9c~Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+CQÖÖáa[û‚¨2ð@YAôÏü+?Á_ò#èõãþ‚+v¼ù|Lé[ÿðÔ#VÿÀoþ½ðÔ#VÿÀoþ½lQR3þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(—Öµ)u-"{HtMd“n Û8`{jÞÔÿäyÿ\ÿA5jªêò ¼ÿ®ÿ š!QEé§Õ^ ÿ‘Cÿ¯¿ô[µ…à¯ùô?úñ‹ÿA»^|¾&t­‚Š(©QEQET±1X¤ àñQT‰þ¦_ÃùÐçÉýïÐQçÉýïÐTuËx¢ÛT¿ÕôÛ;K¼²0\K:Mu%´k*´B&ó#F;Æç*8äo2)oŸ'÷¿AGŸ'÷¿A^cáýwÅw—¥Ü—­s¶1›s`«o··{¯9ÀÊ2 Ô/æ8O¸¶ü#«jº¾‘o>¶.¯¬îtŸ;PI´à# U6,Aó„‘™€/Èldùtè~|ŸÞý|ŸÞýp~»Õl¼;áH-­^GO‘6Ÿ>-å …DŒ$„hC« x„+äWEákÛKÂ-õÜžeÍÍ„Jøs´jIÀàrOJÚóäþ÷è+#Ã÷3^h\\HÒM!rÌÝþv­:Çð¯ü‹vŸð?ý ¨bŠ( Š( Š( Š( Š( Š( Š( Š( ¥‰ŠÅ!ŠŠ¤Oõ2þ΀>Oï~‚>Oï~‚£®?ÆöºmÆ¡áÇÔ´wÔa†òW—nš÷a"0H§!Q° †.;ðävž|ŸÞý|ŸÞýyæ•qâ‹A¥ÙÞɨý¾%³ˆÛq-¼ñyq ‰e¸Úq"“>˜¹1§ÊÛ¾xÖûÆÖ¾±œ´÷—ךZÜ\«Ú¾É"¼‚…F"O.I˜« xþTÆc çÉýïÐQçÉýïÐW;áõkÍÕß|+y,êë)ûÀÐÃónߌF£nÞ¼“½@¶—wþ«²³G„F½—*IüÏôô­*ÇÓ¿ädÖÿí‡þ€kb€ (¢€ (¢€ (¢€ «©ÿÈ*óþ¸?þ‚jÕUÔÿäyÿ\ÿA4 >B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"·k‡ðÏ‹ü?¥ø_LÓïõk{kËkd†x%%^7Q†V¡ŠÕÿ„ûŸô²ÿ¿•Á(»½„ÕŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷ò—,»èèè®sþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::+œÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.ŽŽ£¹¾¶ÓìežêeŠ<ªä󓞀M`Â}áOúYßÊ?á>ð§ý¬¿ïå²ìE¿øJ´_ùýÿÈOþÂU¢ÿÏïþBðªŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùK–]‚èž?è<¯Â#ÌÛäevÀ\Ÿ—“…Q“ØÚˆð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèè®sþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::+œÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèê;›ëm>ÆYî¦X£Ê®O99èäÖü'Þÿ õ—ýü£þï ÐzËþþQË.Át[ÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ ©ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”¹eØ.‹ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáU?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ¢ßü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øUOøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚è“Cº†÷[Ö.-ß|Oäílœ)þ•¿\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”ùeØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèê®§ÿ «Ïúàÿú ¬oøO¼)ÿAë/ûùUïüuáitë˜Ó]²ghT :’ /°]1Ñ[?ðˆø—þ…í[ÿ¤ÿâh®þdsÙŸÿÙnetgen-6.2.1905/doc/pictures/menugeometry.jpg0000644000175000017500000002540113504650527017630 0ustar kurtkurtÿØÿàJFIFa[ÿÛCÿÛCÿÀ‡­"ÿÄ ÿÄ?  67VWw…•˜Ö×%U¥µ¶Õ &'"#$(9ÿÄÿÄ!ðQq‘2±a¡ÿÚ ?Û#ûûpFâÂÅ–ò°bùa±äo£Û …#wþìˆ[»Ü_êÞÝÜãÿ¯s‹ü¿Õþžòáðááð„ö?3Ìb§Ì×îpâÍWa®tîáC±îú1ÌWèž²®ÌtYÁ}PA¦Gyè;tQ$c{X’ãïnJkWãéï²ÿ“ÖAïÜ[Ÿ‹«|Õoüz‰‡¼Í0^õ´ï+_˜Æ'?[CȺ±å‡{&»ÊÏm†?\¨[ÜXîn*êØ^aP¡Ä¢âo_/ç,&05ñê«ïïïáa¿·iê«ïïïáa¿·k2^7ýÏvNòøå¡o|Uï+*‡=S­ÆêqW&ìŸ`‰åzJ Æ¹h6cŒõ…¾ÛXŸ™ÙþK¥ŽÔ|ð E™<{)g¯‡žÛ’ŠKk"*|—9.òYå-bçk†Ô8ÐëII6üh9.Í‘ªÔz;nï7Æ42º¨qâ·5‘g”¸˜ZˆðKA¼¢}U}ýýü,7öí=U}ýýü,7öíeÙ ,3Ç2r×é ó'AâÐ ÿ‘=?l»©Ô%sgl¨ä]‰eÃàȱhñ)B†—˜Uu<ö½N=½X,U]¥nù¯,[“®R[¡Ëkr>ò– ®ô øK‘•à»+°gÖÖÛýYš@H{œBÇf•û4pQÄ­ø2-Ʋ¼´ˆjøÐ'E»ÌV‡ÇæH)·Î`ã¥$ÞLfaª–í³MÖÌ„æÏ$* nEB”–Y@¦Æ-±rüñ$¡íHâ‘VÞ×ܹs¾«Ç>Ü÷ƒÊ B‰ï±Ú>²ØuUaÝ]½Òúÿnw´à}s¡õÀ½c¦y®™ÖùßaÔ"{j䌸Ý{`£=µ’XùHYù{{]ù?˜ »b¨Ca²e\û:a¸½]p$±€ßôãöu=apPÜ+©Ê«Ç¢¬XÐѰ˜á>Cî\˜L·+(1$¹[d®ŽÉ¬tÀUJºˆÆ\…ÝwÔöq©[ÛÊÊl¥r:½;ãh¨‹¾ëÁkov­g= £5¡ßÀhj¸Ê(w`k¢·Ò-Jñ¨öóåpa!á0ïH+8nŒÐ³ÂPN–pY Ä|Œíÿ$TtáÒ}”¸’6vü®¢æ+Cä $äÚ0qÒíoK1%JŠÙ¦ì–Aëp§1†p4Ò¦ŠD¡ ãd–ß‹·bya°÷dpÈŸow! U÷˦v‡þâ”+?JÊæõDz…â˜DÝNUÎW×óa§) ³€±ØxVÜTbb#PîÁDãÚS#ÓÝÂ>Æ ñË™§.L{ƒËÇSbX¾ó;8‘’ÓTdK&¢QÐ϶ʻ>±I Ç¤7¾ìqáÐÇ]N©…5”ºL‚ aÅ0ÄÍ}™J[arr~¤ ¤ ³3[[7¸µ•°0$8ÂÂp¬h‚ƒ .$¢E‹•è¤L™#f>Îæç–SYßUägqû¾e!{vwGîïF¬:ªÏí^áê¸û&q·×:®Ôü¯Sèå<—·éòý*s]Y[´ós“E!+ÀÙ°¹û"ò Ý® üL º‹"Ò¨i{˜vžÞ×>Oy•4¥ûU»•&*Á ê¶tÊæ¥§nª±v” ü·–ôºâŒ¿ùö5:˜«µ]ÕÛ"ONðM¾ª¾þþþûvžª¾þþþûv²í‡¹…̵B’qÌL†N´íìJÊZax2޳𡑧-S”¸­)Ôo†$ðø2+c¥»ZÝž }ùT0ÙjÓÖ‡u^ÙýAm¿¸ÅlÎËå»Û•°»þájßñÒÙºöÓãU‰Õ >y¯ëy:( DYSl›%‰VM­,µêP’íÌaÂÂãd¯ Ûñ-¨qÙUü`iGÕWßßßÂÃnÓÕWßßßÂÃnÖ-0ë8¹šdpNaÚ3s¡æMïÞÇj”êõW ì˜O0XRc‘Rš±&ï°)©nGW'S u³z‰Mœq5o¡µlnâ¬æ‘wõÈütïvs{öúöw1ˆmøóîk™];Óýœ»“#T;¿v}gIR‘ñ\-˜L”íNZß±NPR³"NšóITY ƒ§´33Ù¯¢ü¥¬U_ ý»OU_ ý»T‹Yóhó Êü^!Žné ¸»^á ¶Mf¢òKCyu ó(á˜Y¨pí¸·€ÁXñBËA±,óí‹<ä°ôȉVBvÑåy®ó@zª¯¿¿¿…†þݪpæ5“™ØKYX¸_“‚F¯#òHì<ÑS,¬CçJ)%OŒ4³ø‹âö¡lß›_³—¸/féBœsm7T{Ì·åÙOê”õ‹æ§/õö ËÆ}}ƒ@–¯ÇÓßeÿ&ªŒäëËjѶîw¬am¾Â´Ó®ë ? õ¶*§°­„=“ OÔ0WñÔk©Îg#›¬õÑ]–ÝçËKfɹ®éësµ~>žû/ù0íVEóCÀìS°¸*;§!AµöÁ¶³¬PT¬k¶ÂO[EF‡h4°Ø‰t‚uˆÉZZMð±8KXV F€q´d‰ OEÆa` çÊÚr¦[R`íÑuñÉì)R¤qMdYžZÓQĹWŒjMñž²?q…gÀçŠÙùà–J™8¢²äÁ|=ëÊÛ—ÆJ²Q­wN)Uå1¼%:z,xÕÖÑ•§Ž$±[MK&º õV-Há¶½VØÚkÐ 3 µ[{T3&Þhx™Sã¥ÔK!AšDËsÖq·…JÆ´ÞnI{Ü7×”*jÍ9¶×’p ýèiŽ"e%Dža\¹GöhRìÎâŠÏÌAÈå»É®®»ñ ÆC‡W².-Š Æ‘d£'¬À"Hü‹]6í\¯[ÐÁŠŽ“n[3(1Ë|Ô…xâ(”× 8 Gq[žQlºš¼8î´ÇM¬JGea¶nKx t‰aoZ#*ÈþE€ÛH0-ûÜ;‹3'ìK6®·J"éQˆD-ÂõÎÈhŸí3S|¯òP¼°øÑ"lCÔq\¶­aB˜EÉàfÛì+MÆ‘¯ q Ûbª{ ØCپƊƒ|š@FºœáàfOá´±b•ÙmÞ|®ã)ï‘a%mŸV=›[S‰†l{vÁHªëÅÎÜ/–;`tÀ]\¬BzËC4ñ`ÅõC…†ç§lyÒ¤`Žíe˳¸»¹:òÚÈG—«"ÈÆ{-ö˜=ÕëZ}fýmÑp-xl-›ft‹Uv®Ö쳄ì¸B ³<<Èa‘uP™2Òä),ñ íï®W˜’³ëR¶ž=á)PU‡èÊè•`ÛcP³Öé&e¹©¥éÞ ”;m YÄ YP}|gpŠE¶ÇPaêÙÏÜ¢¹Ža–F¹­×Éåì7”…›6µCµ+ËVs·kfñM§@X4ª½ôZœºR%Ek3%²ª‚ÞH û¤KÏD-é3{@GEœDÅõ,t^ÄaT%Y/VA‰^H3'u¯dÀ n;L9 \£ŽÚsy¾6Û±ff¾´ÈyçŠC±ÂÄZåÊ1½qÿ”ß/ü^s¯,JR‚í·ŠÌlÕLÇm;ªÇ+ZŠž*ã]]E™c¸v’C¯öÑÆ„0<0\Ú6_˜x[Ta)œ2RƒEa¶’?õa#ŽÇȰ`Æns¦Ó;0­‰ Ëâ —‰Çp}q feqÒº«h¨;Ò`–ÿ£‡‹¸¬¬tËŽ¶¯­ÚàÏq×–¢BކÃÓŠˆë©`3+™é'`‹8/ª)wN24qX^ß˃^Öô}°8|ƒÆº+«buGT©xSÎïvó°HÅ:1Y M,÷B‰oòÚ8Žð8È IsZê’ä¯/sÌxGJS•æcäóÅkLzÂQ²¬b£‰?¶Ø×,÷ I™n¥M›N·Ì¹_d5U‚Ô(úÙQ:¾`Ü"¥_­ˆ0 Bà·W˜¬“ëMqO—a1YGq²›ìs›é”'l;VÔ*±[m9±Xòkä26ëËܺé Õ†Öuñ¡Myp sœ½–†ˆÎ:ÜǬÄSyk²( LzÞÚzžäøÇO@OF+a5[%kj‰u­ŒêÝV²Ý^ U´È„:ôƒ$˜$å­oHˆlÂÓ@B³—Ržêž™S}µîIë—»ü‡j™ôËÞK¨úÓñä¯y÷ŸUŸòƒÝ}»íÿÚ} Ùlû>"o)¾_óiŒ| ýéÕæ(¼±ñÇx§u-Y4ã›Q7£†Rnåë]Ô/ª9”î™c½Aݸx2‰O#á-7tŠé ! Þ[¸;:¶ÇÊ‹sÒ#ט³Ö¶iá›ÌA»\Sxk6R¹¢Â Â9b$]`̓hvQ&ô̇êSdÝàŸåÈÜ‘ÅêuÎ_Ǧ¬¨¨Ñ.ì±’²àÆÄn"^Ku´Üt£jü}=ö_òaÚ‰×.2ãvFvç¼>R·guŽÑõ–¨C³ûW¸z__íÎös¡õΆ¬tÏ+Ôú8¿;íú|OcE÷–[œµ2 ®0ÕY—î«Ì—~_Î幑t =È ·äw2*Y&8¬2*{Ô…°‘l]ûÂ$8k,³',JÏãY¬ìvA/µfÜîEä.>zJKqÒÞµé€xÞ ƒ™fF Z-ç­$œ¼ ñiðÙna‰xª4Úu2‰lz×iöS ˆÜê%8‰ÅfêÙÛqºÌ­”i«)  ¯úaÕNÕB]l“Ú€eª«öŠ1ÐÖûmb|åÀ\.Žl°ã¼°ù;ÑøûŠâ²­©ÄÀÕÅE_$UuâçQíä:áL :`.®VqÒÝ]f°bú¡Â„Œ‘ò0v<éR3ˆÉö²åÈÞ܉ò?˜ÅN,xøYe`-Û‰Y+˜XyŠÂ¨*ÇxÛÍu"»¾ãúÐ;­H]Ts…ËÇÎuKN8m²Pö%v}ŒióÕö}OŸ7ì¼eÆ7Ç_û¸»UóÃ;8 ‘ý®˜SX6À±ë¿;.ãHܰÎÖÓ«!êï Ø wN^Òæñvb'ñ( Ë5 1Ð-–êr;3•ˆ&’­<¶²D°—­È¬,ͰÖvOž9×RT³£–*B\ý› eyÓnG Q¤£H½AœÎ¬ÚÚÝÉ®K(xé`¤7åoTù‰:¸lÄç'ã×öœ™r cŒŸ±%!jW‚!ì‘^àhŽ7#E+N¤ÇÝP(8MYÊ»ñ®æu‘h•w»eî+s¼~¨q;Ìܲ^S,$Ë2ÞW¬Äc¼ìlöÛÎöÂE°‘½kq×£fq•¯Jã¹ÜV•R0‡¾ <ëFšÆ\nÇ>ã÷|ÇÊB‰ïÝÞUu‡uv÷TèÇÙ õÎ‡× t~§æºgX)佇P—í¡îò¤±bØÉ+äàJ²ß¼¯,ÂÈ<£M¹ËQÊ@­Š]núÙ‰U0³bÌ"Úß$ûÍ{ Š0§ƒeчkq<_\$@¤7AJUFh‰²ÈlZuÍ®“Ž•c >Oݪ“ÊÛœµòVÙ1jîÕ£]œqZÓKÅD²xC^Î=­¥É'H ®@$ìqõ5k’ɾrÖÆü™Ë¿1¥»’ÖbÎÈt›Øö=Y7ŽW­—×l}Æì˜2SÀƒ×»å@|®RŸ¯Ç˜Ú‡Â{Â%©‘C¬ZÜPàq4ŽÍFRN¬Œ.NTíXÚÞÛV£ÚÙ«å#̌ԑéò œ§XN,¡ª°ÑIr‰¯‰J’¤F|™&Þ‘½¹¹Åðݱ—¬ÊÙFš±ñò°* ÿ vTíT!µÖÉ=¨Zª¿h£=ao¶Ö'Î\Ñ…ÂèàfË;Ë“½Œ ÎÕy)˜™‚{ü9¼͵wÒ'2å#™öF‰¦³Ð¹¦Uõ´{Cð߈‘=T¯ uø”=dª§©Å,ü`;Mœ‘_3*ü4–Œ‹qåñ˜”qÎi‡(NX¹f‡‘u•iV£µ‡yÕÀ®ÑAÏÅ› z`ª¢î™oõÐMô¸;ö8•û·7œÖœÕ®+mn²žEF˜œÂ¹Pó\¦k‹mã51usÑ"|¹2zÕªYÑïV¬<㜗¬‹µýµÓ—Â-Çã".ã“M–¡V(-´Â̳ŒPV‰‚¤¼ ,ø‰‹L., vé¬CæGÿ2ùñû»ÿòóÖü7÷íüõþ¬÷â÷qꟵý÷†ö²?õ»º»ËÐ?ü^õÔÂKfÞu°¹›¹ra´ÛpÍ·”³{1vºœµ°{y››!äi¥kv#%Ûf³Ö>KC%|­%I#lIV™”7²Wxfç¶×ˆ]¹LcŸ¤~²¹vw®×z8Õ_íæ¦ê¹ìþ­ØÉ¿íPg:\èe?Ü,}Tg•ý°p·í±µ…Š´I|Ëë~’ÉÚ±ˆþçø|,*ÎùÅÜmÄ{>’F]yZI°¢µrºÔݰܫK0 ²¸’"g‹a[Uìòöõt© ¨%¾Yƒ¸¸ðklä·—2©0dJZÉч7îû|㬶3xin5fHöQëÅB¡ÇO0š’yfeSüP#Ö)$„ø‹Y@$ v¢]½õsß4פwzw¡>—ʯh=½L\ž§ªÌjÿžz´¿Pý<ò¹hþËÚMR¡‡ý¡íüÇ·ëù²V:¯øž#ã»Â8=ŠC’ÎʺU|†çUžP ö©…žÅyõ†È%fÊá!~…ákf¡°¬®FP­¢6/= qÑñå=WQb;îóaDÏþ—‹·âF=|%Ëûò"ŒÆìJ*.¥ 9¢rD ¢éˆõêUy*¶‘ŸµÂ9anièpÙÖr$[´SfJHÑÓYÔä Ø‡>Np!Óµ• :•AxÇOMrç䈾Á9øÏ¯°hÕøú{ì¿äõçºú÷;nØË)’}¸SÇc£ÿœõŠ:æp¿í@ ÞÿÁcTC4²ðÜö2|)>Rf܈2½ŒØ²cíy~lý߆Œ‡ý/ÕZóZós¦¸nüÙú?¾ÿ ú_§~lý߆Œ‡ý/Òãu˜ì\n³Κá»ógèþûü4d?é~ù³ô}þ2ô¿KÖc±qºÌvw:k†ïÍŸ£ûïðÑÿ¥úwæÏÑý÷øhÈÒý.7YŽÅÆë1ÙâY«ˆµ¶wc-—Švé·…ÊòÔìÞá3\!ÎcØ ¶8žŒE™i¼0q@lR>ytµ¿;b7”—»tiM®¿6~ï¿ÃFCþ—éß›?G÷ßá£!ÿKô¸Ýf;¬Çgs¦¸nüÙú?¾ÿ ú_§~lý߆Œ‡ý/Òãu˜ì\n³Κá»ógèþûü4d?é~ù³ô}þ2ô¿KÖc±qºÌvw:k†ïÍŸ£ûïðÑÿ¥úwæÏÑý÷øhÈÒý.7YŽÅÆë1ÙÜ鮿6~ï¿ÃFCþ—éß›?G÷ßá£!ÿKô¸Ýf;¬Çgs¦¸nüÙú?¾ÿ ú_§~lý߆Œ‡ý/Òãu˜ì\n³Ψ÷™o˲ŸÕ(/ëÍ\O~lý߆Œ‡ý/Õ=s3ÙÝ}¬loínloìU!vw¶w¸8¶÷vwvÜßx76·vøü8xö÷6øø|x8ø8ü<8¸8¼žû/ù0íyî½ Õøú{ì¿äõž^.ng2s ‹ˆx"@rô´ÈTN Ä2à"&EÛLŠóÌzXcÂÅ#n”ñ$¢³tÄ©-N@'Üañª†´Zð›*u(½5Oy;Ì{$hX˜ò' Ò W™©wã6>TBíì“|¤¯Äk'%Ó8ØÆŒÈŠj6$Y êïOÎaUz„³jÙÇ IDp»ÒæNÛëŒØ²Jgxl·hÔ„{HæK ¥qxµû,F ®x3QTáþtØ×r-ó†.t²²ç&FW/tw2€X®šñ š¹}Üñ» ò·;ÇКB×¹{G¬v÷uz`†}Û·:ÿK9ÐúçCéc¢˜éžkÎô²ÃÊoVp®jvÂ5OŠY5”†µÄ¬³LÎ|Óy!³qÀÇù½[îÕä²ä=Kã0º’¬”-ì‡uÛªíÖjÚ{"ÔuB1·gº¥ï˜è4×–?^t•RÉ]¦Ú7Y[7ÛÇ8–jeGëI9’Ðdáž Wõv ˆ¸âާ8J3-ⵜÿ ì áøÇó mÈ[·%Ëp\¯›Š¬¤” œŒ²5®Ý°T«e² “`+ z Ç"áEË9,XS£ Ø•¹?~’S6£ñG+shSÓP‡™n%)gL~^ív85›Ê]X³cE$ÂßZF’Èêì%56‚0“äfýì‹mŽxÊÍY¶—Å<õzhK0©Òø˽)ÄÞt‘ëaš†qU†¯$ qÙœ©6 ‘aIn^Êô˜¬,ÕÔ2ûÍàAÉŽÚ©¿±Pñ ol³/níÈâà47ŠH§¦¼@6Mcsœá{ é¶G‹²†×C(æFɧ;n×ÐUàŸß9-â«\I›N<ÃÈâŠ"Í\I±··}¿@4ÓMÓM4M4Ð 4Ó@5G¼Ë~]”þ©AX¾jðµG¼Ë~]”þ©AX¾jsñŸ_`œügר4 jü}=ö_òaÚÈ?0!/û %Eš£Hr–HìYu0d^@­íÛó “ÞÒ,íú®²d 9 &Qù;D£ÄÙ…toÍíŽ3AöçÞÆšæ1½ì‰å™rªdûLÑK/r¥e†œ¶+»`û$º®ÄQ½›²­xÇÙᆲ&zlIí3D’]ŽLY¡fÒýšÞÌÞT8wʆ«Æ|§a¼ÒKYå-»jãÅ£@ÖØ†™C™ÇY6£Œ‚Y »LƒÈW§îU¨)V“%[À‡ylŒË"Èx-úšÓ@f<1îØ…‘|ؽ@ÅkO.89Šáí+CòûgA«öoºIµ<' +-Ob64ñCˆÀáäsšbp´±OW¤§À¯NZðŸdÞH[IûlŒÇ»bƒ»p¢òÎLV´ù­Ñµ×,äì;s®j*¿g7Ùó¤kj[}’SªK«‰zGC·”§‚“pàÈv1=xjÍŸkŒÂVÉí?i 3áQÓÖÅÍm>B´ëêtç%ú« A¥ •Ù»ÖñþØMÈtW6ºzĺ· m€€’ª&É3Ãiج¶nø S–Å8Ur^ã¦"e˜»qJm iªæîs1³²¿13IJq€õ=»D˜dbdµÚ–s7Ëx2_§32´³iú’EoãÇ>ÏiÞ¨˜U2u6³I«`ð×nš‰ùLaúÚ•±Ìvù¹1pÍå/›No³R=™I@ lI¤vU#aª¬V•˜ÍûÕclsÏ; (˜âR=²i¯j‰|Lpï^Æšhši i¦€i¦š¦šh¨÷™o˲ŸÕ(/ëÍ^¨÷™o˲ŸÕ(/ëÍN~3ë쟌úû-_§¾ËþL;YvâæmŸ×>Eó Ç\}€µ=ý‹Ö™_¬žYºcd^Z­¬0ÊBÄôFæ¢Ñ6Øè‹$¬ê§…59Þ†CF¶ŽWµÎú½ó`j&Õøú{ì¿äõ—n`T–xæºÞJb½áÊÃ/øäí6Ì#Í`—µs[-Д•jp{Ãe¸ãfM´é¦µÊ´•ÆŸR$RÈX\Ób„âPQ]Ù»h¢Eæ¦\ó ÇaX<ê'Ýf¹÷ÑÊ|GÅ3”EIضëž59ädéOÒŒÞ5Þ\×i§¦®ëŒ#Çl,Ö ¦aR ðGbÛòF{}q•y"/™¸n_ÖéAàÇ.¢9tÃfWcåVT¥“»•sª!-3^W@I«ÍÁ¼$FÎ.Æx£œIÌq™D#8_–fžä[­%Ê"®M$s#Ûñ>°ÐÈ e™€"ã#5{êMK¶­ìÃÂüñ,¡£†ŠKŠÊYpk#ÃÉç$xCðe‘±2ݬ²R¶ç5“qjÓÈ6_,èØ·¿>¢xÆ€¬ƒ-ü¥%lîÄœ»|ßÔ”Àp” EÞ’hnñ ž)æ†Á‡·/hÇ,W0-ÖL~Ĭ£¾S`ƒ&ßIc¥Ûnª f>jÙJÚ´fr†¢AJK, X»£ 0&~ü ÉPÉ@‘Å·+j¡syÅešKÌåE¬¹¿­Œ§ó­Â·N¬îF}žõÑJ7¦D 6 C ÓJAw`0ª4Û[ÊUNßi¹EØ®R[H¼ häß/,«J^¦^+û~çÅœ”®){‚¡ÛsÚsk®Ÿƒd@³ì ‚u’$€â1ìù¢†Š7špŒ]X1…Y5NfÖÛ¶=iÛ•åWÈ30©ñ‡¼«òý &‘í¥fŠÓ¤‚j(p§K.tîò 47ØyaÍRåîìÇÜ·¿¹°Æa¹ùjÒ˜BÊØ˜©²YŽ„¿/šÙU1T—ˆàBëÊàÍ9,ëÄÛoÀ ˲JÚ_+ˆ€VÌ1d:Ø3NŸJùˆ/™cTîÀeï §Ôø–ø¸Ä[6óR„Ne¶kd«FzäZ¢Á´êËìúµ݊¯`K!!Áh/ûˆª'À^\y›Jùÿõ6›í¯rO…[Þ{þCªŒúeï%Þ^‹|_y+Þ}çÕ`|Ÿw_nû÷gBö[ÞÏîQ¼³rùn½å÷Ëɱ*7—}oæ‡qð=§[ÈTjùåÎØ©«Ô¬€cŽ×I´ßÏß,év|W­Ø5íC¥ ÚŸc^ÜnK«\iûM4Ð 4Ó@4ÓMÓM4M4Ð 4Ó@5G¼Ë~]”þ©AX¾jðµG¼Ë~]”þ©AX¾jsñŸ_`œügר,o!ù„ÑI·]ŠŸ¸2Ä=1HÿÁR@€ðâq~$QàÅâ:Ê –÷I5xùÚ'æµ÷wçÍ4ÔkËñ¼¯/Åþð>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍW6^^*wõ’Å8{уQƬïì3Døg™Jnîím ,f?N(æbðmîqÊÛÞñÞÛßáâØáàáÛÜÝi¬œ¦bŒœ¦bÿÙnetgen-6.2.1905/doc/pictures/menu_refinement.jpg0000644000175000017500000002514213504650527020272 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀõ¦"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷Yeu”€ØJÆÒÁq9ó"EçÚI›:yл׿\•È—=Fu§ÿ\߇ò¯8µø}}gáŸìØï¼ÉÞÂZI®^_%ã1ùÅæQ»a³Žë"íDï5j.Ýfº•Àv؉-,’6 ¢Ìp ÀÐRCª%Ç`›ÎŽâ#4RÄ»£dùyÞÞw9ädŒàㇳð­ŽÅÄñý–þ[™¡·¾h’4h^=±y£æØßq~ô¼ÇvíÆ•vÞ:±Ö!µ²û4vZO1”¬í½ÑÔAU1÷aþ±Ž8ù€:/>Oï~‚>Oï~‚¼á~ÝÛøzÆÂÆâ i×K[mBDr~×*¼ ¡‹+nlsF7«I0®Vº_èRøDû,͉VÄŽ9ÀÛÈ¢P§ˆ>fcÎr@:/>Oï~‚>Oï~‚¸íGÃÚ´Ú…ÒÚId,®õK=JW•ŸÌI€•@Ç"ÁÉêví|A¢ø1ôM?O†;{)Ùtg³Ô"’F+{>" ½Š’Ñ€²¨ÜÅ|*ãŠên¼Aog§Ã{<“¬síò£Ò4ÎHÝ´DylJíÈ I ¾VñÜ[Î’Ã*‡ŽHÈeu# ‚8 ŽõÅAàë« Â6Z„žTº6ãìwóÆ»Ä 2l;‰(y¸‚wO}á‹»Ÿ5úÇdÛî ¸Qw?j´Ž0›­ãNc}ŸGïßå<îì|ù?½ú <ù?½ú àíþÚÁá ?L6Ö­z«d—ò;³¥ÊÅ,Náóþ°b6T >PvªH­¯ èwzÍ¥ÕçÚÔʤœ·îbYèÏ*Ë!ää¹$’Mt^|ŸÞý|ŸÞýGEIçÉýïÐQçÉýïÐTtPž|ŸÞý|ŸÞýGEIçÉýïÐQçÉýïÐTtP3ãMRúÖ;$·º–åËym´œcŽ{š*§Žÿæÿm?öZ)ígÿ\߇òªš®qsogks5«l¸Ž•ÚÉpTä¡ô«óÿ®oÃùWœ Ä‘iÓZi¶óÚ-­¨·€]<ÐIbµ’2’Ú4u̬ŽH„îBƒètWm¤ø‚-2Ìj+«ßZÆÖïì×11òÄyÝ1tf'37úÕp£e¿ìÿÿk@Ó}¶K‘-³%â^²Å¬~|rF ‘ˆŸ äŸõ‰ÊcÚTqÏ ¯*G*;ÂÛ$U`J6`ú2œÄõÂ[hž(³Ñ´ÄzŒ÷2éÉý«æÞ†v•^ ÇÜ9‹í( äíf}ØzÚðv¨ié¬=ü3Åö«ñ5ºÜ\,Òy^D(¡Øua°©É'+÷Ÿï°Ôš®§™%ýª_Ì»ãµi”JëÏ!3’>VäÇÒ­×}¤êO©ê‘Ø»Ã}«Yê+x$AIÙ÷#‚Û÷Ÿ³¶6©2ä›lvZ·iàëRÚ†©6°ö¶ë·Œ˜(eDlá$Ø$Ed+’Á™‹aÀaðÊò¤r£¼-²EV£`6¡Ã)ÁìAïRW–Ë xº4ºx#½KiïÞo³‹¿2à§‘n‘‘'€¢9³#sŒù¼I]N j«¨]ÜêÚΣ4±OÙ%Å"¬¬­å ®Ö@U³·’›IÜ@:š(¢€ (¢€ (¢€ (¢€ (¢€8ïÿÌ?þÚì´Qã¿ù‡ÿÛOý–ŠB;Yÿ×7áüª:’õÍø*óÍ>ÏUÓ­gÍ•ÒÿaiÒiº{Bù¤Às•mäC «åQ¹i#0òÕŒïè¯5kíKQðšK­i×·ÙëÖjÿÙóI1$†G—Û…3.á ¿19n¦æy£øƒ§G²éíßNY…‘h¢“|e|å,ò¥ðv'•ÈCEy¬~#}Q/îmµIg‹FºYH³‹k·{}ñÄÛO™mܧd…‚¶Ö˜ü«rxƒV°Ó¯µ õ{TÒõgÌÖö[çxZÔ/–öÊÎD’þX€ÚI íÞ=:ŠáåÔ¼W7!†;w´±f‰’”´fŠÒùŒº‰óT~ýU>R_¢ñ5¿Ú¼=uÙÙNÆe†/7r‡† ɇ@ré¹G$Pµæ2\kúf‘m`öV <¥¦²²–ßqÛÍ–Í ÃB„™]€~áæa÷¡¼ñÖa‡Qšê; Ð*ÛØØù–SÆQ<éV\¡fáìrpà…物xºKxÅ´·¦öO³‹åºÓ¿ue;\B¬áSÍ‹c\eƒ>5;×;šÝÍç‰m.¥³óµ-íç‘ ¼K–[©<¸$‘Bªye¤YÇ–” È‡%€;Š+ÁðMkàÞâ'Šh´ët’9«#ÔAä{Wck«XÛ風Ïg«%¬6úÍÄš{âk–¸µV’BBý£ .‰‘Xà;×p$Ô¨®KU:þ™öH#Ô/nâ>k%ÌV1Ë3Ê6yPʪym™ràDTÐ回ðÜþ/¶—ÃÚiímb³³AÑH#h„ æ™1nÛdÍP Ñò©”#ï€zuÏxN-uô>ûZÔ^k‹›8ÞâÖKE‹É”ªŸ—*~öðÙËr»Úz(¢Šã¼wÿ0ÿûiÿ²ÑGŽÿæÿm?öZ)ígÿ\߇ò¨êIÿ×7áü«Í<7«ëoáéu;‹[X[ÃS\-Ô—:ÈÀZþúue@ IùÞo˜u,g£Ñ\=§‰/çðo‡/¬ ywVj×Ii>¢#”*ƒ—ù„“¿.Ìv˜Èl³ ¡áßk—6²ëÕ¬ç¼Ó’HNòÛ®míäâ4F—~>}ÙaòŸ˜€z=‹â¹æ·ðü’E+ž}ºÜJŒTÇL‚fÜ9@#.K‚ €[#Ö•«ê’ë/¤è7–³é’µÄ–—×’IvQ¥¦J>üÌ<Ù¦S—àÿɰ€wôW¯x›TMF=ÞÖÎQ¨éð½¬O#LèÒÀÏ2¸0嚙ϒ#5,<¯ß[ÜK›ddYm£0Ë,hmd–â8¼™vK#îÿÌÑÆTÆr‡;@¥QU4ᨭ»&¦ö²Ì­…–ÙEÀ9(ÅŠäcsgägh·@Q@Q@Q@Q@Q@wŽÿæÿm?öZ(ñßüÃÿí§þËE!¬ÿë›ðþU2òÙäºv·Qƒ‘<¼=П֠ûŸô½ü¢ÿãtÆE©höz¯”nDë$YÙ-½ÄH ã+¾6VÚp¤®pJ©#‹pA ­¼vöñ$PÄ¡#Ž5 ¨ `Ú¡ûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºæ\"¦›á-7K¶Ó¡·>Ãt÷jÑà >lÇ—XÑTü²c€ʹ'œÛŸGøŠÓYûuÒ=´[­²ˆü¦W*Xœ©låðÃîVÈKOèÖ†êÚÿ|RÊäÈ<å$ G•ýãeB©’‚CøËCÉs:I/™ˆšÒa"”Ù•dÙ¹ù‘…V±‘ƒ¸f Ÿi7zM†›pg’ °ÄceCBÁ˜ÚÌÎÚyH8¢ÇÀº5ŠÙ…‹wÙw‘²( 9–C²Äˆ¥•­âd Ðñâm®â·ŽïÍóvmž(ÝàÀ(¦` jÌp¥;Óî\æ]xûE_ßjú|¯|–ömw$2(@q¶r*®F|²~}µ‡Ã­ OÔlobÌ’Ò(c}¼(Ö4ríu`ÈÊ2¹Ç'7ÓÂ:`Óì¬eóæ¶´ÒäÒ‚;ãÌÄa·îÄKÈÇSí€ {+ȯíæc|àOÂürŽǽ`ÞøžîÃÄ“XK¦Àlbû&땺>oúL­ b=˜âE9ùþï#'å­­:Ŭ-Ù$½º¼•Û{ÏrÊYŽà(UP  u'$’s.|-Þ¿&«>¡zë'Ù÷YþìB|†2EÈMÿ,Œ_ïrNWå  všÔCUp¯³N ‘R)L™XÕÏÈP~n6n 6Np*]øš%Ó ¾°‡íµüwϾÞX<Ù2Q“váæ#m`¹Sy… xµ¸¦Ô/fW”K*¿–LPWj"•}Á‚áÜÛ¨[xÊËD—K´Ô¯m£–þ;ö’­£>d{6€«@ ÄÂä‘É9 €mM¯é°jcO’gnXÙ„.bGlmG” ˆç+…fï\™rËézž ,­%åhšhÙ­eHåJ‚ñÈÊEùÓ•$ÀŽ*; [\jovn®–gŠê{5)åM4{6HI]à..‚ƒ 峓£øNòÓWkÉ,„VsYÂm.å™xÑñÅ0)nÊw¯Ì$ ÈaEsÍáÝI¼-§é#ÄúŠ^Z´-.¢ªžláR# s“Óqq¸5éôË©|Ei©¦­u¬Iéê«åJÌT‡'Èǯ¦ƒ€iÑEQEÇxïþaÿöÓÿe¢ÿÌ?þÚì´RÚÏþ¹¿åY–:½¥öm­oû=”ö«wºà„òãe—9ÀÀ<óëZsÿ®oÃùWeámZZè·ZÅ”¶ÖQ[‹V‹OxÜI£ÆÎLÌsÜ )98+LfÔž"ÐâÓ"ÔäÖtä°™¶Gt×H"vç€ùÁ?+pcéF£¯iÚ\Éo=Â5Ó´ [#©—l³,*ûIf÷?^§ŠÅºð–¥sm3.¹å^ÜÝ}¦å¡ŽhavòÒ5Ú±L’.5àÊA%‰åÙRßáë[ÙéöKª#[ZOevÛ¬Õç·H£Èbß"4p€7Äï+” N±«ÚhZq¿¾.ÙeŠ7r@ æH±†bHA`I쪃Ś‹÷¸Ô­ma²¼û “ÜN‰L#W*¬N °GaŽ*Þ¯¦ÿjÙGoæù[.­î7mÝŸ*d—G]˜Ïlçž•Í_øK{%Þ¨}†O4˜£‰eŽ8â0ÁLC,lqöd#æÚ#iÀ ©“UÓ¢ÔâÓ$¿µKù—|v­2‰]yä&rGÊÜØúUM3ĺN«¥‹øo`Ž5µŽît–Tm‰æ)”v|¼óǚ̷ðŒ–:ͬú}òYiÖËkkÌÕ LÆ7$(]Ím AUaømôm*ÂÒæÕŸ§=/hÛÙàs6Ee}Ж6C0låyÝ}Kû ¥ì7Ö·÷s¥½¼‘\G¶WfÛ…bÀ1c€IùHž(›ÄZ¾¦4Éõ:+òÊ‚Õî‘e,ØÚ6œœŒ s‘Y2øcT æ.¶qäWF{‹y&P#‘dTPÓÆäRKHÇ–h[wZF­qâhu!©Ù(6ˆm%±wh¸ÄŒ®%Ì`J†*vŽå÷iÚjºuýÅͽý­ÌÖ­²â8fWh[$aÀ9Sx>‡Ò­×%áï·‡|ƆÿÏ–Si§Épn$ò#8áÕ¦(ÙÙ|µŒ|¼ãYø¬ø[O·M[N]qwtÖ¥¢‘C0rG~3Î{@†ŠÌž e¼Ei<¶©£¬-ų@L¯)+±ƒçžÞ¼6àSN€ (¢€ (¢€ (¢€8ïÿÌ?þÚì´Qã¿ù‡ÿÛOý–ŠB;Yÿ×7áü«¼M£­¥¥Ñ»ýÕå¯ÚíÈÉ–<ÆÑŒ–&XÀ\n%€šÚŸýs~ʼòËáéÓ¬t¥·¶ÓͶ’m.w<Š%›u»‚Œ¸hÆè¤`ë‚®þ`VbÙc;M;SµÕ-ÚkWr¶:KE$m€pÈà2œp@È ô ÔwZΟg¨Cc=ÆÉæÛ±Š®ãµ7°Ss«¸Ä¹ß1 Âñ¬É7ÄÌ•9_™ 2óó É¡ÚÝØèu¥üÿh½‚Ö(î&Þ_Ì‘TmÇ“’ Éä×,žÕÄRDkm - ±[Çw4°Ï$3Ç*ah˜—d{À– €wBëYÓìõlg¸Ù<Ûp61UÜv¦öjn`Uw¸‚'Šå­¼s}âIµ?ŧ][ÌÓÈÖ±—hòñÚ"++ HìïËpNÇ §„׳ð¼vž-ŸXÝͽ¼H×ó¿Íšº–ÚÃk¦3Ÿ›spÄ’µy{oa Ís'—K àŸžGTAÇ«2Çš-ïm†7Ii(†a‚6¹Ep9ëòºž=~µCÄšGöîŽ, A$mum$©8ÊI•rK•$²´þð‹øsûËò¡ÒͶ ÈìÍs8òv1$e•BJwÝ €8mQ@Q@Q@wŽÿæÿm?öZ(ñßüÃÿí§þËE!¬ÿë›ðþUBÓUÓ¯î.mìïínfµm—Ã2»BÙ#ÊœƒÁô>•~õÍø*áôm/Q´ó`›N½[[ -¡…ç€ÈŸt,V“FUü²‚ÓrV#Á †3°‚xn­ã¸·•%†U‘°eu# ‚8 Žõ%qzv‘­êž‡V—TµŽßK’-Iø+Ëp  l¦->L-ìYX‚&ó†å ·'kq,||¸M++}vh{ÕÈKA¨ÝEp¢Ù®s ",r²üËü´QР,óÃko%ÅÄ©1)y$‘‚ª($“Àw©+Ï?á×®ü+—u{{$÷ú °ßÉu|Ìð,B!òžfPÛŸy9=†„“G¦,rY]Z"±ÇyvngÛ×.ûŸœ–Àß.ÞGÝP :+‹ºÒ¼Lë- 5ßHšmôíun^}:+ˆmßÈ€Ì`óceÌë&d|à+Fzî4èôW¦êšçØlõ>öKhôi†®e°Ìs]/’ËðeÆÀQÃ|»°vÐKÝZÃá·†a±·Õ-®RÖg)nêñ´q…dd6ó8˃åãåÎñ•ètWá©|Q«–¿ÔîŸOÖì¶-d5´-2’ß9Ú@¸ «Ü\ £kÄÓêvÞº›H‹Ì½]›@*…ÀvQµ²Á76¿ |¯÷HµÀ[j>+þ̳’âK­’4Æ) ³2Îò,Eèðõùùm‘«ï%›3N½ñ™¢x~!%ì1[ÿeYÉÛʈ?ÙÖHîVOß,¿;p˜Z3ÁÜhÔ¨®/Á—Þ)½Ô.¸¾\kï¡‘yS’0°“jc8$I7DÃu-Äm¯¶³¦Á£ËfàçÖ—û:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  TU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâèÕWû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€9ÿÌ?þÚì´RxåB.œ«œ( ±'ø{žM„vÓÿ®oÃùWá¿j×××¶·ÑAw$k ¶¶¯lY ›Ê<Ù Ë¿©*ÀFp¬~`k¸Ÿýs~ʰtÿ ibN¶±Ý2ÈŒò^Í# î}ŽÎZ2Íó¤@'c(Oã[=;Ã>¯x Ô`ŽU Ål¿2äË(E<ð›ÙºãpV"KÏhÖ^&] iqsæÇ7›Ù$v/–\HÙÞŸ2£(Ýɵ𮘚ežj0ÚÙ©H Næ2ª{Y`0£SÁ i¶·ÑÝÚÂöÏ„[ÌñB@]ƒtJB1 ‚TGðŒbê>3•<+©k~‘z˃ÞÙK2'•rr‡Ê® ±WØåsµI ;ýn{M*ÊîM>êÙî/ ¶xåX¤hD’ˆòÛeÆ@ʳ¸§T–¾Ñí<á¦øå‰ 1O#ËDßz4G%cŒàŠª1òŒG7…4‰ôÁ§ÉчÏ[–a{0•å\mg”>÷# Ìq±q÷Wljm­õ7´6·M SÅk=â„ò¡šM›# ¶òO™*¥Fñ’0ØBñ]¦¿öS ¥í²ÞZý®Õ®£ çF6 HÚdAóp*Yy«shlú˜Ô$…ÌÛ–FQ3ˆ×]âc¸Âá™Iå\Ii£iö?`û5¾Ï°Z›;o—Ù•äóþ©99Ó91 ùK1ù †ÜC^(zŠ( Š( Š( Š( Š( ;Çóÿ¶Ÿû-xïþaÿöÓÿe¢ŽÖõÍø*ÅÒüK¤êÚ|7p^ÀždVò42J‚H|ð Jê Ú͸;“ÆkjõÍø*óÍWáèo èºU££¥„ÙH©j%V¹µ’Y¶¾W8Ø© ¸±Îz3¸²¾´Ô­îÆê «i3²h$ƒƒ†A…dIâ˜"Õ®,ßO½[ÝEg-÷îü•–EŒ¢ã˜rer·$Hd>Ó®ókÖšv­yq9¸w–É|´o.8ñ¹r£lIŸ˜ä‚z` ðxN³ñkv‘ÚÃz³«@ÂÕq¡hG=1*ÃKc•,®¬þ!Ñ–ßRu;YSLV{Ñ ‚F· ;ÕrAù[ŒgƒLüÚE-å´öKt–‹mvñÆæG#Nýòß#1à€ µÍAðÎÙ4MCK¸¼ûTrX5…”“ùÒ›hÎ0JÉ3!`R&ù1”àÝÕ|;çhvú^ŠÖZTP]Cpª,÷Æ<¹D VLeÔsÓ=Î@™Õtå¾K¿µŽÌ‰nf_1™T;¹É!YXŽÁèj»x‹CT¼vÖtà–,íÒb݉Úœü¤F9ª3xRn5;…™kýFÎõäÁmÌ%c'9#0¶o0ð{äiߣ°Š(›Qy…«[­›ÈÓ»E SÅ)BfL·“Ê*ŽPÔÝëšM… »¼Õ,­íŒ­šk„DóSq8Ü °#¯Ê}*CªéË|–-j/™Ü̾c2¨vs’B²±ƒÐ×~ t‹û;Wž Äq3™Wyñc ±37ú26wùˆÚx#JÙY[ÝÁfÉMycp„E¹’+QH‹–¹8$ñæ9ÓÐ|K¤ø’åÒï`¸ò%xäT•—k²!I¶ÂÊ{ŒÖ¬+H¸Òîn¿ßbòÍ4VþH Y ®]òwa™‚à. ï8#Z€ (¢€ (¢€ (¢€ {ÄÑýáǨ¦U ˜/oïäi.d·²V\p9G“ìÝë€;pEs¾;ÿ˜ý´ÿÙh£Çóÿ¶Ÿû-„v³ÿ®oÃùVF¯éº­ÃAi3³íó¼/Ì™|LÀ S•ù‘ó/?0μÿë›ðþU暯…µ¥Ò%µ„¥¼-=¤k¥ÍÌèÄ]BD«*m’5W>\O€ï-M1æ¡©ÚéiÝ»¢Oð×ü#w7°ÛYivöRË,‚[h¶Í6ùÑ\¬a™Ëä`˜ÚdñW†á׆;iúuôÖ´©o~£Ë•Z6FBÛX¨Ë+ýÓ“Œ ¡¨/o"°´{™–v1‘3òq ,zöõËOá}F}yoftÓ4öóÿj Éql±ˆ÷ÁÄG!GÏïïØ;û ¡¤kzîž—Öv¶|lymä‡x ÊA*AaÁõ« {o&¡5ŠÉ›˜bI¤LË…9éÉÿ/q\>©à}JóÃÓ–[YŸK³[yí¥)äÈá|Àe‚Q•ØÀ~ìH~eä6”þÏñ5¶«i •Ô¿e‚Ú[ëåßtžPpd ç’DpŒÅ—AùÇË@mÉxGú†‰¨jÜCeWXb‘H³Èì ´¾LNØËdÈdf';[@Q@Q@Q@Q@wŽÿæÿm?öZ(ñßüÃÿí§þËE!­ã+è5{¸!··Å+F7†$í8ÎA•Oþ}KþxZß ÿÅQEð›ê_óÂÓþøoþ*øMõ/ùáiÿ|7ÿEÂo©Ï Oûá¿øª?á7Ô¿ç…§ýðßüUPÿ ¾¥ÿ<-?ï†ÿâ¨ÿ„ßRÿžŸ÷ÃñTQ@ü&ú—üð´ÿ¾ÿŠ£þ}KþxZß ÿÅQEð›ê_óÂÓþøoþ*øMõ/ùáiÿ|7ÿEÂo©Ï Oûá¿øª?á7Ô¿ç…§ýðßüUPÿ ¾¥ÿ<-?ï†ÿâ¨ÿ„ßRÿžŸ÷ÃñTQ@ü&ú—üð´ÿ¾ÿŠ£þ}KþxZß ÿÅQEð›ê_óÂÓþøoþ*øMõ/ùáiÿ|7ÿE™«kw:Ï“ö„‰|­Û|°Fs޹'ÒŠ( ÿÙnetgen-6.2.1905/doc/pictures/menu_file.jpg0000644000175000017500000003067213504650527017061 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ+¨"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷Yeu”€ØJ«cª&¥§Û_ZMæ[\ijDûq¹ÈàŽµ<ÿë›ðþUÃÙh~!ÿ„:×Ã×–ÚZGiko’+Ù$^QLÆêa]±ÈªÊÇ-€Çån”Üyò{ô樖¬×3yq´±ÂÜüò:¢ve5Áßx/R¹ÐþÅ®‘/xnFš» £ËT'’ÞEÁ!Ü ’ÒŸ˜`ï|¬¿ös]Ïesw ¶Ï,Ҵ؃Éó Sš6hÞPX]¹@x=÷TM>ÑÙc$.âI8   ³@ $$Ôzvµ©nÓZÊä#lt–ŠHÛá‘Àe8 àAèAªzö6§¥yì‚hç‚æ1!!]¢•% H¨b›sƒŒç<ž¹ák¶ðË}ykrë<Î4ùZ&†%p›@w¶på6> ˆ6%#x¡ùò{ôyò{ôÃÿÂw­Šð]yrÛ#¿ºµÐ.¥‚fŽ@\de€8ôàÑUüUÿ"ÝßüÿCZ)ÜŸýs~ʨZjºuýÅͽý­ÌÖ­²â8fWh[$aÀ9Sx>‡Ò¯Ïþ¹¿å\ž—®ZZ\[ÛiÓ¬VÖimÔð“J–²ÄRCU?ëYŠCó!ÜÊÆwtW£ÙøÎ×Niö¹º†y¡·µ¾›(a’(Ê»biI+:ç-+0ŒÊd¢‰Bñ5¿‹-5+Ù4Ø<•ŠéØÉû¤C¤£ÏEi–L±†B<ÀC €¼óÃko%ÅÄ©1)y$‘‚ª($“Àw¦Y_ZjV‰wcuÕ´™Ù4FÁÁà ¨x’ÊâûG k™,7V×"0@2§ŽRªNâ’HÉ‘Ék>.¿ˆ\Ãgöh¥ºšI-m•rÃlkJcºŒ3(I‘1þLÐè®/û3ÄqêÐ §½»¹Im¶j)8ŠÔ@«d·‘Èœƒå¾<Äù†ß“&×BñÍ®‰+};K-‚‰D·FgWf.™.˜Äßa•×ï Þ¡S`£I<1^>U;Æ@}hõ/ÇâË k¿>dò£[¨l­¤Kq!ç!䀫¨b["t8v3 8iEPEPEPEPE¡©Ça¼^SOq>á *9r1ß 9$ö  ßÈ·wÿÿÐÖŠ‹ÄO,ž¸yâÈÁ F~ßxÎh¤#¡Ÿýs~Ê£¦^YA-Ó»ùûŽ3¶æT=€¨?³­½nð2oþ.˜ËTU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâèÕWû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  TU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâèÕWû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  T›Wy}£qKc’p?Sùš­ýmësÿ“ñtg[zÜÿàdßü]QñWü‹wðý h¨üI pxbí#ߌ¡ùäg?}{±&ŠB: ÿ×7áü«ÓüC¿ÁZ^»}e»µ¶Ån¿~Y‚EÜx˸Q¸àg’MtSÿ®oÃùW;iàíÊÐÚB—¦ÛÊX–u‰5R ”Vr”ª•eÁ\ Ld¾5²Óô·¼»´ž "º“ÛOqmÅ!O0Ï(Œå ·Êì~nœ6+ÞxâÞHm¥Ò`žæ ®¬ ûY„ù#ÏxŽÒ2[Ê”8b»2@'wËZgšA·H„wHêÌÿhŽöe¸bÀº`þc „Oî®#_h ö@¶[O$Àžt›Q¡Ûå¾ÝØ2Š»ÈÜTm$¯cÄš­Æ£‹Ë[´Kö«hD#q$ñÆBå”nÜdœgŠçdøgc-êê6ï †Hex­¤x–$.ÆiAÌÃå$>eAWÇcyeo Ãs™ËÀdž7WCÇ£*ŸÃš¡uá­.îi§x§Žy¥ó^k{©`±DB7£ V8ò à”RFFh¥¯Œô»ífÇMµß!½n!•ž8ƒ#!pDnë+½ÕH*Ácð§Šÿ·ôý0ÝZOmwy`·jÍÈæÀA)ŒX*´Š>p7KkJmÂãSóýªYC+ˆÞòf€2ãiòKyyÞëÍèl6ö°C Ä––mcŽgVŽ †9ýÚ|ÙÜ6ðzÐÏ7ƒ4Öð¶Ÿáãq¨‹;…âu¼u”˜˜2åÁñ·iU"ôú­Çˆ­5Ç’è]ZÁ%º"Ü0ˆ«•$”Î ù–rUJ€iÑEQEU [RþÌ´I/6i¥H!Fmˆds…Þø!=ù'€¡˜ª›õðCuo%½ÄI,2©I#‘C+© ƒÁv  ‘}¨Áâ}?L¸–ÖXn4馑£‘¼èž$eÈD¿wŒ}ãš’=YàÔ/l¯“tDn‘íci7@IÀ(¹a Áþ<™ù‘º ‚êvzúS]YÀm¡v¼™‡–z†RØrp , %T“•¹keogçyíiåi¥bK3¹îIäð@οŒ’X½å£Ëý¦­=¢Y´r1$jî_k;¼Ñ€WåðNÕ2ÿ۪ϥÞBÉ>•ª,knè¬%Àº¶ÓË#/\Sib îhçÒ…à»û4¡Ô1,ŠÎñ»„í¼HùïÝY‰’ÇFÓôï³}–ßgÙ­VÎ »7—ã ¹'Âäõm«’vŒVñWü‹wðý h£Å_ò-ÝÿÀ?ô5¢Éÿ×7áü«–ÐüYý¯ö¹ÚŠÞ/5ÒÚçíÓ9à 9zü‹¿”qœ»©Ÿýs~ʹ©§>o((X#¾s• ¸òTŽ1× ÐÕÏ7‡u&𶟤ê)yjдºŠªy³„`YH Œ1ÎOMÅÆà×§Ó.¥ñ¦¦šµÔV°A$O§ª¯•+1Rœg#¾˜ n§EPEPU5F6Ýd‘^I$o."É4„A gœ’±!A"ÝA{eo¨Z=­Ô{â|dT‚C)«  €AP85¨ú=:U·írÛÅ,ÐÂûwi‚SŒi ©ÇÌ2&³ WvúŽË)-ÕçÝ$ƒË’?ëUŽ#x<¡<ü¥¨¿„`Ÿ^´Ö.µ «‹›eEBðÛ«|£þz$K ’ÅC…;˜ci+ZÖšt6—7!ž[›–Ì“JAm ˆ0 õ$噘€f?Ьí<Ÿí(ç³7^cÚFÐÈòIì™UvÌΡPüĺ om‚Ûë0Çqhͱ´ëÅO³ßG hÚF?*¶8]’¼êéŸi¶‘¼ö†ÓwÙ­‹â8A’B®;UàB«œJãnÕ[w‡­4è´Ø–IæMµKkU™í]†L3!_”·a»w6àø«þE»¿øþ†´Qâ¯ùîÿàúÑHFäÿë›ðþUÍiÞ6Ðõ4±x.ÑRëN}L³È€A Vó0ß)ˆôÌn3ò×K?úæü?•pòü<·“IÓl–óÊ’ÊÁmŒÑDci¥F¶d•аa² 0l\LgB|E¡­Š_6³§ 7Vt¸7I岫b8 3*“ذMIu®i6:„6z¥•½ìû|«yn$“qÀÚ¤ää‚:šÅÑü›©ÙjSÌ—7–ëpd‘–W/,¾R‰K$ޤGO¼r è8ª—‡/¯®—kug`×–wN {±°¢?:²ù¨ûa«ÉòÆI|u¶š®qsogks5«l¸Ž•ÚÉpTä¡ôª÷úö¥êv¶7× n÷0Op’Jꉶ…Á$Žpû¾ŠÄã“áGá»#^=Ø‚²Ù™$œ´Pår¤<¬™;#åËÀk]èÐÞë–ZŒû-`–! Æi!‘_'¡S#ޤŒP4ïé:”ZnËØ"¹ÔmRîÞÎiQghÙw³9<œdpy≼K¤Æ³y7°]ÉÔ6“Åm*HðÉ,¢%ù~cÎyàðqŠçt¿‡Qé×V%µ¸µmšh§A$ÐG#…I„`fÛ ŽrÍŒm’?O%”öWÚ”ÙK-»ýŽ+y>϶)’Mž\³HHMSb€Ç*ØP m•õ¦¥h—v7P][I“A tl0àòü*zç¯tmf¨Í¡êV¶÷WÚŒ7N×6ÆEX–8£t0É""sÇR¿)ËÓÁ¬·ˆ­'‚öÕ4u‚E¸¶h •å%v0|à3Û×†Ü iÑYšdÌWÚ›êw¶³ÚÉ8kဣEÐ ¹$î9Ïês‚4袊(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5¢È·wÿÿÐÖŠB7'ÿ\߇ò¬Ë bÏR»¾µµ3™leÜ -äŒ+ã8”ãå'†SÐŒéÏþ¹¿å\]φµI5Ûkë}8ÚßêÖ—ˆ†f<1¬Šcg0%ðNKØQ^b|ª[k:}´ÑZëVÑApå/Œ‹Ä¥’·˜@`®ò¤Óa–@['ï|ë­ƒu/­i­of‰­_ûfvayı‡‰RJHcrß¼ëäÈnwv7×¶únŸs}w'—mmM+ਠ’p9<Ò§®.Óáæžž:$Ñ@·Óékest7J@€!ˆß±”ÝÊ…Ú8®‡B³šÃL[y,´ëV&;M<*=³µww1!Wïcˆ’k:|_hßq³ÝEg/Èß,²y{§9ócäp7rF/×}ॼÔõ DÅjo&Õ¬ï`•‹eb‡ìûãñ¡O80jÈÓ<©XXêqÍ2]\O· ö¤‰o `ZYöÛd¿ËœHg{«‹zÞÛǨCbÒbæh¤š4Áå cžœóö5=púgÙŽ•³o§MeeÜcWË̲BÊR8ã·1¨§ÊYw})^L“-¸4ß-õ¡½’ê{õkRo º f‘*Æ.áܻȸÚ|¦Ç™Ì»~@Òyáµ·’ââTŠ”¼’HÁU ’Ià;Ô•ÃÇàýFóáôº}¾¯{¤ýžä]^³'Ÿ°m$®p‚§g ßæšét$š=1c’ÊêшŽ;˳s>Þ¹wÜüä¶vùvò>ê€\këDó7]@¾T« ™ ’6ݨ}ïL§põ=pú‡…¯nu=Rù Ð2ëv7QB·8ŠH¢û.é çP“qÆp V2´4Í'ÆXêm¨]j/rÐÙ-ÊŸ´ÌXfH™îˆD>B‹rVO”+*ìô3<+p–í* YÒ2Ãs*Ô€Yr{nµ%pšw‡ukëê«{kµ­äR´w®³I¾HÛÍ’EÉG?$­Â.X1­+SÖ¢}LÔô›©n'Ó„·Ú‚´~TS¨@È@=I-Ðc¦Št4VMž¯ys6°’èw°-Œ» fhÿÓFÀÙæÀäã’Lw*Ï¢ßÜjš%õÖŸ><ñ{IÈ/=Ž?®¨ _¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5¢È·wÿÿÐÖŠB7'ÿ\߇ò¨êIÿ×7áü«Ê|h4¿ ¯“¦ý“[K^ÛÃÛͼ ’Iò͹ö†!“€Í¹@ܬg©Q\þ³®Ç«ÙZ\Ýj6i2Þ=êÙX,íF·ù9V.Ÿ8Ë…r|ÆÊGŒC<—ŠúÐ^Çuû5¨60Z‡³x™c7ómm®„ÜmjçËåmß8qEp¥xŸYømt·šœòêZŽŒCÚX¡)9ŒaGË»æWÝžNWÊÆ+¨Ð®ãLRÒj3b«q¨[¬Ì:îØ €IQ”RvçÄNŠâì|1öŸë:µÝ†–ñ-üoÝi»îm´8h§-ò¨pz)å[œô·¤L²ËâØu k©íEã7ïôÖ_>)PcϬˆ0ŠªŒT¦Šó_¶ø†ÃÀ¾‡N·½¶,Â-äYã–4ET(mæ`§óåãåS¼dÖµ¶Ö,¼j—úŒ×²Iyai Ãc5«J†_4dÜ‘§˜$]άۈðv”W˜ê^(ñU­ž‘E<é,ãÿHO&e¿›íVq™QA å²ÌûrèNó›TÔúŽ­â¸ìâ6m¨½žEKç´1ÝÈ¡#+¾5µ¨Þnú•â4;†G˜èôT?kþ϶û‘öß)~Ñö|ù~fí¹çnsŒóŠž€ (¢€ (¢€ (¨u N;-âòš{‰÷aQË‘ŽýÉ'µfø«þE»¿øþ†´T^"ydð¥ÃφFZ0ûöüëÆp3E! ÿë›ðþU2òÊ nßÏÜq·2 éè¬Aýmësÿ“ñtÆL`…®á¢C2+"HTnUb z€J®G}£Ò¤ª¿ÙÖÞ·?ø7ÿGöu·­ÏþMÿÅЪ*¯öu·­ÏþMÿÅÑýmësÿ“ñtjŠ«ýmësÿ“ñtg[zÜÿàdßü]Z¢ªÿg[zÜÿàdßü]ÙÖÞ·?ø7ÿ@E¡é0Kq,:]”r\ʳNÉn€Ë"¶õv |Ìæò5~ªÿg[zÜÿàdßü]ÙÖÞ·?ø7ÿ@¨ª¿ÙÖÞ·?ø7ÿGöu·­ÏþMÿÅЪ*¯öu·­ÏþMÿÅÑýmësÿ“ñtjŠ«ýmësÿ“ñtg[zÜÿàdßü]Z¤Ú»Ëíˆ [3úŸÌÕoìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâ芿ä[»ÿ€èkEGâHcƒÃiüeÏ#9ûë݉4RÐOþ¹¿å\v™âkïôÉ5u‚‚Õî^ÌÛ½´ìÆäY%o.áFpeRˆÓÑÁ^ÆõÍø*ÁÂz,I*-«”uت×0A 9oÜ€UíÁD#W eM/ÇZ6©J²ù18I4’Äb‰ãTr†TvBÆ7Þ6±ùQó‚Œuø‡£kZi³,ö÷3ù*ÑÜ4QÉ ’ª²Fñó |è TeòÃkmÓÂz*YËhö¯ÅùŸj’Û–Û´rEbØøªconú¦¢í&!²€ÚÉå BÌñ\:˜ˆ2Æ6–%ƒ+Ž…è¯l­õ Gµº|OŒ€JAÈe#•`@! ŠÌ>Ò ºD#ºGVgûDw³-ÃÓó¨0XŒ"up¾¸÷ºþ––’Á.“¨érÞÄÞS,™V‡$ýÒ³”¨ ޼àPÖqÓÎR@'…ldà¥Ð4ÔÔìõáx¦²€Û[¬S:EGªˆ”„Ç Õ…º1¿„´+[‡ž==Þµ"WiÈr¤Â‰?”aÚ¼à Ç þ·=¦•ew&Ÿul÷[tcw$Ž€ÒÏþ¹¿å\èð´]AæÔ/f[ëø/ÙË9!hÊ…Ú€íÄQ©É' ÔIcñž€¾H[ÿ9çó<˜íá’W—fÂÛ³|²#Œ”mã+óUâm®â·ŽïÍóvmž(ÝàÀ(¦` jÌp¥;Óî\⯀á³Ömnt«Û­>Þ%@a”ŠZÄC«+'—lA»’ä·áðnjðÇk5Ô´5‚²˜¤’‹–e2eDQp°d¶à ÷^>ÑW÷ھŸ+ß%½›]Ɖ Š'PÜmœ€J«‘Ÿ,ŸŸmtVW‘_Ú%Ì+:ÆùÀž…ø8å;z§…e†#ðó«Í`–bÅ„†x‚lä®9#¸Ç¶*ÆbÖì’^Ý^Jí½ç¹e,Çp*¨…P:“’I 3x™“Å#FK{\†UÙ-êÅs(*É $bHÔ[p?$€T·kâ=O΋L:äDÒ@³Ç$1ÜÑ’B˜xòW.›€ §Ã%æ‚—º‚Ï5ýé¶óc¬w©…䌫#r¥× ˆv«*’¹ îmÕì<-#P½>M«YØîòÏØ¢m¿,'Í÷#æMçäòÙ±£köú®Ÿ¤LËä\êvú;|–Ú˜Œ·Í€82 íœô늚oŒ,5]{û6Ö+§ìíîá¹³yr,¡ØeŠmQµ <–+÷”Š ð…µ¾™¥ÙG¨ê*tèÒ;…‘W·m¹ˆ•P!#”+€†’_gáKM?ûÏ,{<¶>ï—¸ƒ å³&Ÿá«k Mu#uus|VU–yŠ1“ɘ*ª‚Þ%@ “šÖ‚xn­ã¸·•%†U‘°eu# ‚8 Žõ%`Øøn]6ïGû.±zº~›aö/°°B“à(Ws·;€^ÞØÚ7±g¤^[M¬<ºåìë}.ø–?ô!°.#ùpyäÓ ÌÀÔU ÂãKÑ,ìnµ õàˆ#ÝÎyHîqýr}I9&ýQEQEcø«þE»¿øþ†´Qâ¯ùîÿàúÑHFäÿë›ðþUÍCâûima»:v£Ë@-.4)p²È‘£‚•‘°N•`:Yÿ×7áü«‡“À t÷k¸²hç–'•aÓ–/µ…ž9I¹¶Í!òÊî  y’¿6ÐÉâ--2-NMgNK ›dwMt‚'nxœò·ö>•q¯­ÌÝuùR¬2f@6HÛv¡ôc½0:ÃÔV ¾»‹\ºÖtíJog•ȦXÖ7ŠÝv«¡-›d!² Â*Zø'¶†ßTºµ³µ»€L€)$`gývð ÃøÔ C­j©¡è—š¤¶óÜEišHàÛ¿bòÄn`8={q“U#ñN––rÜjS¦’aŸìÓG¨Mf9J ¸1BJ2°Úǃêø‡L›[ðî¡¥Ar–ÏyÛ™ž# EqµŽÐË“‚qÏž‡ž½ð-ÕäßÚXòõg–GšXRxa`é ©èã‹xºÈÃ;Ž9] HÕtæ¾{¿µ7ˆÊn&_1Y”º‚¹È%U˜áIè(´Õtëû‹›{;û[™­[eÄp̮жHÀr§ ð}¥sKðúÊ%µË‘OÛÄrÇfÏä99b~Ä 6xÞr*ޕዽ/ìøÔ “û:Áì4ÜÚ‘åÆÞ_3|ÿ½aäÇ÷|±÷¸äméh®y¬üV|-§Û¦­§.¸ »ºkRÑH¡‡˜‚9#¿ç=À¥éàÖ[ÄV“Á{jš:Á"Ü[4Êò’»>píëÃn4袊(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý h£Å_ò-ÝÿÀ?ô5¢[Ë´ŠéÐÅtÄc”¶‘ÇOP¤ƒíñÿÏ ßü—ÿ‰«Óÿ®oÃùTtÆUû|óÂ÷ÿåÿâhû|óÂ÷ÿåÿâjÕWíñÿÏ ßü—ÿ‰£íñÿÏ ßü—ÿ‰«TP_·Çÿßüð½ÿÀ9øšµEUû|óÂ÷ÿåÿâhû|óÂ÷ÿåÿâjÕWíñÿÏ ßü—ÿ‰£íñÿÏ ßü—ÿ‰«TP_·Çÿßüð½ÿÀ9øšµEUû|óÂ÷ÿåÿâhû|óÂ÷ÿåÿâjÕ‡âIDÞ»uITeï"hÏß^Ì¢¤ñWü‹wðý h¤#rõÍø*òÛmSM®‰dñÞ·ŠkÉt©"”s·Ú~m—ŽPÊÍ2kÀH z”ÿë›ðþU1œ&¯¨xŽÆÆæÒ'Õ%h/ü¸¯Ò¾X¼”˜Gm.~yAX‚þëƒpôô_ø£RÔ3p·Q̳Ù/Ø’Äx-Þåds–C‘ÙC;Ž3/Ü_G¨ã‚žWŽ$G™·ÈÊ lÉõ8U=€¨ÎZëÄ:µ…í» Ùäû}Œ¶óÍc$qE¶î2O”ðÂûqóß.é‚úW7ší­Ô¶Wwº¼zu¼òFº•®ž³\Ì|¸E…”¦d¸–0” s»¸¢€8}>-jßŶúž©ý¢³_éÖqÉii on³/›ç#>ÒQ#2È `¥ðtV~"³½›XŠ(oCi2ùSî´o;þìc/Áè2OKkQ@óxÏM_ iþ!6ú‰³¾hR$[7iA•‚®Pq“Ôd7wPz( Š( Š( Š( Š( Š(  È·wÿÿÐÖŠD™¥fF’$Q*웈†qËe€,fÿØäÿ •ïåÿ£ìrÐJ÷ò‹ÿÕ;ïÙÚnU}ò%ü›RI6 Tl|². Â’B–\ñ~#ü[sáómt%†¦ yLl_ÌÈ-³j€#bØbJŽTŠÐûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµEUûŸô½ü¢ÿãt}ŽOú ^þQñºµU5F6Ýd‘^I$o."É4„A gœ’±!A ~Ç'ý¯(¿øÝc“þ‚W¿”_ün³åñF›eq ž£p^»E ¤jòF'¨X„›@/ó´á¶üåBóVíu/3PšÂæ/³Ý¦çwnYâΈp3Œ¨aÕIÈdf—ìrÐJ÷ò‹ÿÑö9?è%{ùEÿÆêÕ‡âHÌ^»VšYŽPî“n~úñò¨Tž*ÿ‘nïþÿ¡­„nOþ¹¿å\t>´‚P£Q½’Ú8„v‘JÁŽÖ…£òNÚ¦Î>J‚O/¿[Õõ/íÛõ× ©;¢ªHTÀöCû_Rÿ …ßýþoñ¦3±“Á>Ÿqjº¾¨s¡5ÆøÞG–1ß¾…Bî‰h00¿-i\h°Ï«¦¤·7PIµd†@«p±³4aÎ7¬ìp¥wn!·/çŸÚú—ý.ÿïóÚú—ý.ÿïózµå?Úú—ý.ÿïóÚú—ý.ÿïózµå?Úú—ý.ÿïóÚú—ý.ÿïózµå?Úú—ý.ÿïóÚú—ý.ÿïózµå?Úú—ý.ÿïóÚú—ý.ÿïózµå?Úú—ý.ÿïóÚú—ý.ÿïózµA{eo¨Z=­Ô{â|dT‚C)«  €AW˜kê_ô»ÿ¿Íþ4kê_ô»ÿ¿Íþ4Öê^k“¶úÑ—í–ws¤²*Ç<ÉéX"‚\ÇݼGÐ~a½i§Ciqsrå¹¹lÉ4¤Ú ØƒŠ RNY™škê_ô»ÿ¿Íþ4kê_ô»ÿ¿Íþ4êÔW”ÿkê_ô»ÿ¿Íþ4kê_ô»ÿ¿Íþ4ßx«þE»¿øþ†´WŸK¨ßOŽkˉ#nªò±ð&ŠB?ÿÙnetgen-6.2.1905/doc/pictures/meshingoptions_5.jpg0000644000175000017500000005051313504650527020404 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W®xpu°ë<ŸüU'ü!~ÿŸÿ¿òñU>ÚaòO¹åÒø\œÜoû Ç&Ÿ&œ$m²(ŸŠå³»É'éIg¯j¶Z,ð¥™:+ÿäÿâ¨ui5k1¨É+ÿäÿ⩺ԚI­…É.çœê>*¹Ùek¢Û[ÂÐéXK{4¿B2FÛ°;‘žµ’×ןðÛh¾M”–öĘf’"f‡q‚°8çäõÏøBü5ÿ>+ÿäÿ⨠ðÙ8Ÿúï'ÿIU¤º1¸Éža/ˆõkGU¼ž:uÔŒ^}¤Ð³@|°œnÈ#õëU¯5cP¶Õ¡º’Ùÿµ<…›•$-”XÀ8ëšõ“௶}g“ÿФÿ„/Ã_óâ¿÷þOþ*kG°rϹåskW×€¼¸²Ó.-#´&…Ê…BHl†7'GÒªßÝê¾¥&¡¨ËLȱªD¸DEè<þy5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUR¯I;¤' >§ù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU[‡b}“·Áì™äþW°§D¢9‘Ø| ó¦+Öaðçƒn%X [Ydnˆ—ŒÄ÷è­xpu°ë<ŸüU/­Ã°{&xÕÖ—£^Îg¹·ó$ Ä=K6vOogE`p¡[©úׯÿÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU?X§{Ø|’<‰Ùí<‹€ØÎHúäE ¶ÓÃ+n™ŠÀ3ÈÃ#§ׯÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñTþ³O°{9Dí½I@bŠ0N9ïþ5"‹¸yÔbW3ìl: õŸøBü5ÿ>+ÿäÿâ©ßð„xwþßùOþ*¬Ã³fÏ!Ùg ´±[¦ÝûŽÐ¤ ž¦¹Ï®ÛHßþ•ôü!ÿ wþF“ÿН8øÁáý/GÑtél-|—{‚¬|Æl§Ôšj¼%î¤'µ=+Á_ò#èõãþ‚*‡‰/îb¼H#•£]»²‡òG_N*ÿ‚¿äGÐÿëÆ/ýV?Š?ä*¿õÌèM\3Ýšô1§×M¬°Åqª˜d¶Ä’\m28PO'‘ÓÔTÿo¼ÿŸ¹ÿïá®7Äɧjw`Ëaæ^ÙÅ %ܱ„P¯&LŠÎ¤¡Œ®ãÃpp¯%ž¿u&£=½ÜŒ²Á;[K þîUe>J©ó°¤eáò§æ9%¤ëí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¸ýONÖcób°¸¹–ÜùR9yI’Fýà“n óäœEªe±Ò5)&n¿½­¬^YŽM›eß!änl•R‹óVþ-øáÕý¾óþ~çÿ¿†¢·Ö%¼gµÔžx[;dŠrÊpppAÇQ\ȇY,I„R%“; H´f?,íÀ2ðwÎ"R~b2Zþ€—éò­Õ¬–Ò©ä #!%^Vp~V#£cê±  "Ô,n¬¡WYVæî8XË–*ààçùæ¦Ôµ+ÆÔ'âDTr€#0ó¬I¿ä#¤ØBçZÿòºÿ®¯üÍD5‰[f5';Ý£\N~g\åG<‘µ²;`úT¿o¼ÿŸ¹ÿïá¯;ugŽ;MbÚ=Lj7…!’õ Äî'Tm™<’Ñ ¸8ç€KæìvÚi«5ùy%@”w1cr[iùFE ¨ã²Æv£T¸2´BúS"¨fA1È8$g¡Áü;í÷Ÿó÷?ýü5ƾ—«H·7Cφé4Ø’Ý#¸áçC)]ä±$Ë•fe%ˆ%ñºº;ëu»ÓîmÚ%•e‰£1»”#†HÔr)–¥Í¬—Pk -¼Yó&Žçr&NH8Õ¯·ÞÏÜÿ÷ð×5®­6«bÓu, –Í$Ås¼nÆ^"«å‚Aœýü‚]f»»«GOÕ„eÌÖ·Â"¸9òö‰UryÜÜñÀ<åX_Ûï?çîûøh:Ýý„RܤÍ#G0YX²œ ú×)ce¬¯ˆæšæy¸y#&9#9Ø€y¸R\‘œ¡ùŽIm»ÿù]×'þF÷úÍíÍžŸ'™å´ö±ÎþVWæaÓéíY3ë¦ÖXb¸ÕL2NÛbI.6™('“Èéê*y¿ä¤Ø>å\o‰nà´Ô ý¦g¸·•–⊠`L’üÞ^Y¹’ ËLŒø®ÔO$_„Míñý°n] –ÈÎF9ôÁ«ÿo¼ÿŸ¹ÿïá®_R³ŸP‹Z–ÑVhït”†ÙÑ×7ïºôùמœÖµÔ×;üí>æÓn1ç´gwÓc·O|u¤¹õÓk,1\j¦'m±$—L‡ŽÉätõ,z¥ÄªZ;é]C%f$dëÔA÷yÄz­Ô«§ý¶ËXíöo@ŠU¤'ÌÜs´‰Ý x ^Akà]^)e‚9/-d´€Mq!¤‘ ºFUã’yÎà•“p÷ž'þÔÕôNy#K‹ìZj˜Öý|æÛ'–åK.èRLln €UŒï|Çþû~u7kp…ภfBÈû€e%XqÜAˆ"¹M2Û[Æ·—Áztù7¨’îp.FÓ¤ì‡Lgi%œ°!êZÙë­áh-ç²ÕÔC¨ÎÓÛA~×=«4­¤Âl‚¥áÎdSˆØd‚vÐݭ‚àJ™ #aÇpAv Š“Ìï·ç^W‡|mvp©à̳±–ù½ÔÎfp³@²)W‰€(ãåaå¦J·c¡h×°M-ö¡¨›“ytV¹ßÙÚi i³•ÆÒŒß.à£eik±­Æ‹teË£iclQÔ¬§¨ ×%>³}u¥iR¼ÅdžÎ)ähþRY—ž½«°Õÿä }ÿ^òè&¸ÿ.‡ÿ`Ëý“!ŸÄ)mu¬úÂÅq.<¸d¹Úï“€NNOb]RâžYo¥Ž4RÎï1@êIϸ¯Ý倴y ŒÏ¦Ü[ù“\ÅC)@¬C8m£Ël¶N@ŠçNÖõª2\4Ð\ÛÜy,Œ)ÑÕ„H¤Ë´2Â5û§æ9%€;Ï·ÞÏÜÿ÷ðÑöûÏùûŸþþä¡·Ö`™.<»·Š)U¥·k•w¶J®ÊI °–ˆ…;ØHE8#WmN >dººòï'k{q¨K 2ÈSÊ*?~H1€‡v¨Àß@E]FõX0»› ç—$~UÔxSX¸Ölnå¹XÕ »xË  )É<ó\ut?¿ä©ØF_ý(CG]^UñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5­/  Üx+þD}þ¼bÿÐELJ.õÅž)í‘v‰ƒÔŸOz<ÿ">‡ÿ^1è"º¿åŸû‚¢Øã¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ*l9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,8Ù<¨=ÝŒ¢êËm½Ôs?ï%Tó—­Z¹ð•ì×sJ·6a]Ù†]³‚~•ÔQE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,9y<%zö–1 ›=Öö±Âÿ;`²ŽqÇJ‹þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰¨®|¨Mi4KudÑ”fFÆHÿv»*(°Xåäð•ëÚXÄ.l÷[ÚÇ üí‚Ê9Ç*/øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&­øWÃw~mM®§¶“ís+ …ÉÀºäQ]Ç`¢Š(¢Š(¢Š( Ûvº°¸·B¡å‰‘K Žk›¾~›oö›=öÖq@çÌlQ‚GËÒºº(’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¥aXä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMjø[@¹Ñ,®á¹žÙÚk·LnH BœÏ±E1yaK•¶óÎÈd§'h gÛ“þpkË>9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:+3[¿¹°··6«–k…„y íÓè*]8jޝ%ûY„j¬²O©$ÿŸÃœzqª©7ï=Rò*Î×/Q\Ö¹â½7þO&8û/FKøw©;¤?hÈlW÷+Ó“ÏLIÿ ž–ºž©g6øF™—»Ç‰ÇÊfÇ9Æ He'Q ƒá¿é¾(ûJÙ²Ûl2ÇçC6³´î…Ý9ÚÜnÈÇ  ·£4¾'¿ÓSÉ·³¶¸Fî-#ά8Æ"\qÜþtW=7Œ´ëWšK¨n °§oÙTÅ$‡iP*±“*"—’€‡åw>­–“w¥^Øý—ah®¤·r³mHeòºç‚àŒ>eܽEsQxŸûE¼9y¥ÉéúÔÖÓMÎ"•¾WVÛÃÂÊHÜ9SŒ¥â-Fm#ö§n¨ÓYÙÍqÈ RÈ…€8 ã#Ö€4è®.ëân¡zº•”öpE°‚;ƒ2I,†}ãsÈ# ²†*ÛKBÖâñö‘9ÒDä›l‰ŒÐ¢« <²<€JC‹ÌèFBÀMËi¾1YŒ‰}gu//-cž+vhähd—ª‚]ßʈ¶UJ’ ƒ»å£þ8.¼ªkö0;%’É•ImîHÚ¡‹~îm¤rWz±ã¨ÈSEbë^ “F¸·ˆhºè¸eŽ7µh>iŸ+ȬH± `($œŠ–~:ѯ|LÚ2æçÍ’o6#¾HÃo_,9‘q±þfES·‚w.à–Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Š—6ݵ¹™w%*ç‚ÀgóÏáV™ò›B*Œç媖¥™r˲y’ÕbPX±dzSl5~_7"uyã ôäÿŸjÅû>u{s~%jE¨èn«p³ÝÂìû|· 3Ƴ&IÙ*©Tå¾W|ÍÇÌrÃá­.K¹nn"žé¥ßº;»©gˆo6ØÝŠ.U™~P>V+БF£âM7û[ÎŽvþ˰[ù¶(;£>näòß¹n¸ŽzâÜz®.§.™ý«ß»äµY”Ê‹Ç%3>eäŽãÖ´iÚl]»Ao%Ó£6ònn¥¸làFb3޾¦ª_øoNÔµ}1½Žå¢XYíoç·ÜŠX¨"7Pp]ºúš·§jºv¯n×eý­ì*ÛKi–E €pJ’3‚8÷™­x¦ PKk>öH¬—’]Eå˜âŠ2¢F`\9Û½I ¤x‚ƒá®å¸’ÓÍówî‚YàÁÂLj̲ÁA;ß$îlÆ<)¤ wˆÇtî̯ö‰/fk…*f/æ(œ`0wþófüz®.§.™ý«ß»äµY”Ê‹Ç%3>eäŽãÖªYøŠÆ} µ{¶þͶŽY!—íÒ"yN’´D3+÷Ô‚s‘@ÇáM"$Ó‘#ºOîmÿÓfÈ•Égf;ó!%›;óÃ0èH:wÖVú–Ÿscw™msC*dÈÀ‚29Ò£®œÖïp·ö¦nžA2íXX²œ![ Ðí>”Cªé׆ΠûYn‚³˜eg ®QŽÐs€à©=ˆ#­W¾Ð4ÝFâK‹ˆ_í±§ÏŠ¾Ý¬„?½eH$9 â™uá½:÷É&öXâ‰aòšþ.D¤MûeÎpw†Ü89©ìµÍ'R‰%±Õ,®£’S 4ᤠ¼  òÛAluÀÍ[†xn¼¤¨²0`IVwGb   i¯oKªG<×1˜ætd–Q ‘ƒ'Γ¿¸Æ o i¦^iòGu,7ª#¸iofydAÑ ¬åörß(l|ÍÇÌsµEbÝøWL½¸¶¸™µ5´fŠHµ;˜ØGH%d‰*¹'$í'­ÚèövZ„×¶âxä›vøÅÄžNXîfnجO%‚‚I$žNoÑ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[º¿k1¿bCr³9ÆI ñ#üñZ?»H|¸÷}ìüÕ^{˜-=ÄÑÄ„à4ŒgÓšdÖ—.RÞê \ •Ž@ǼV…9TUZ÷–‰ùwkÚ熦ծ/Zä·‡R³[ äx ŒÐƒ&<¦ ¡IËwŽiËàÙîîõAqªyZ~¡ñ=­šIË( ’WwÌX²F„¿$ಷEwªéÖÖ÷—ö¶Ó]6Ëxæ™Q¦l„åŽHàzZžá¸BðJ’ fBÈÁ€e%XqÜAˆ"µ‹á¿¶‡ö™®n¾×{q±}÷÷i’«‰¦”ŒsÁæéÞ ñ†.õíA]u(-ìžÂ{ á6¥ähæ)æ}à+b5 •`I œ–£Â×n²¡™]ã 7*±!I@%[¾Óé@ÖàÈìXÁÀéh |¨éo>¢o.µÂÐyMg#,öûÊY>×,ªä‰ÙJ±U Y‡ÍŒô¾Ó&Ò|?¬èèæ{‰ÂI)‘Ñd™äUv$îp9nAäõ:vWÖš•¢]ØÝAum&vMѰppÃÈ#ð©è¢ŠŽá¸BðJ’ fBÈÁ€e%XqÜAˆ"€$¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkc\²’ùl!H„ƒíˆÒ÷BÙ'=¿ýU¥ocmcnËVñ³°-å(qœ~?>Šæ–¬«6î•·Ó_"¯¥ŽkRµ¼‡_¾¸GþÔ¶Ôl!³1™#XУL[ÎÞså‘0ûªç¾^²SÃþ#²´’].êxu ‹ýGýtàÁ2—…¼¾TþôÂå¶³üÄ·*;º+qya¤xš--ÍÓj’[¤3iépb¹xÂ8&9šîR2í #ÍAˆ›˜‡°š?ˆÖúæê1Ó<;â]ÈYeùcÁQÎþ‹Bѯ`š[íBÿQ7&òè¬/s¾/³´ÒÓg+¥¾8]ÁFÊèh ;]tø&òÚ=&êÚò]Fæ_(Ü(”E%Ã̬†)ЇU Êïðm ñ„÷SYNúÛ¡Ó£òoV5¶™®.„J»ÛzÑ72Bp7,§•õj(„ðÒkw:Ë]´—¯ê—ë$òÞ…­–Y‘aXº¬‚@ŒÓò.<Ìb0û 3]»Ò4«;«Ø$ZµË\™/•¦k6YÌjd9#ç‰:ïd´=wP”ø¡µ{-*{Yõ'[áÌzm»ê³ZLq,¢ˆÆÚähü±ŽàUs̤׫QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lax¦ò,c†i¡3^G4,U°A㊻§iFÆ7–K«ÙŽÐ.%,{ëíõ«eT²±²©Ç àŒÀ‘øÓ‹3 'êkšT¤ë*ŠnÉmÑù•},yßu¬õø– Z{}Kûî[KX¯Ý<Û•h¾Î<ÁdbÆ@©ß‚m¸Ö>'»¹ñ2Ø4–M¾ê{y4äCö«Hã¶âC¸æ7ؘù~ý>cÆî¶ŠÜG%ñê+? G+ß}’O·Ú¤lu³ºe­"…òÌ„ðpl|¼fÛêËð\—Z«Ç-Æ£s,—lx|¹Â–ýúd@VŸ(Ü®þŠáçñ–£õÚà ­ìÑ5Òc@¬/"X–B’¹ II h÷cý|x-Æè$ñ5ì·šA¶¾µ×Pj!Y´Oݬ ÚÜ“o”ÆJ”W?¼Ï+•)~þŠá./µsYЭa𶏵¸º–KKÉmÚ#–$ÆÓ.Ñ+²@ÛvôM¡kjÃWY|{¬é-yk#Ãgk4pÇ#yˆ “xe.FGÈÛ‚©Äˆp¦º(ίk'Áÿ\Á­»‹FÔ ´ÔY¤VY¤07vâHò° ùƒ(ä7=³¯[Ûkòõ/²jWNª ÄÊ2áYwm\`LˆF\ô´P‰µá¶ãìVW1Ï}aii4rHð}¡‘šF;Ww‘°®'~á÷¿ ë×ú¦¯©XÞH’¥´ó$ƒKžÅ³#J)3@òÆqÉ«¥žn­ä·¸‰%†U)$r(eu#x ŽÕSMÑìô¯4Û ÚIq¾[‹‰'‘€Î|ŒÍ´eˆ\àb' 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØÈÖïîl-íͪÄešáah;FAôú —N£«É~ÖaÚ«l“êI?çðæ{›HnÚÜÌ»„‰•sÁ`3ùçð«LùM¡FsòŒW4£[Û)&¹-ªë~š•¥ŽzöÿV›_ŸNÒÍ’}’Ö©ÔnßhóUXyXòO͵þøù~\5 ?[Ç Ìº´ÛA ÕìkŸ$ù)ÚK³yQ,fAîùkkQÐ4ÝVág»…ÙöùngfL“²UR©Ë|®ù›˜äéRÛÇo-’I sÍr#–S$¢A! œÂi897N7‹añ JÕ"u²‚{‹Ñ*D–pMo+ÈY]Æ%1–)NÁù:|˺Eñ”)®Oa`yüÌïÜwg Ÿ\Ô¿±´ GTò¼ï±ZËqånÛ¿b–Æpqœc85‹}¬kš ºlwëk¨‹ËÏ!M…³¤˜&}غ4ùËíÃ6àw–x!º·’Þâ$–T¤‘È¡•ÔŒAà‚;Vm¯†´»I¡"žIá—ÍI®.¥ž@ÁÞìX¨Y$“€]ˆ9  ÍGÇÚF•cgyx(nT“Ìšh&Ù(*Ò«db ùÇÊæÝ§ŠúYÖ×IÕ$HežÜJ!P’M:˜Ô–v9Âr°o”ž Ðï¡–m§Xæó|áÜÐùÂGgu}Ž7®é…l½°MkÙÙ[ØBÐÛGåÆÒÉ1'ç‘ÙÜóêÌÇñâ€3<'¬]kþÓõ;Ë´šâäeb»_r+oM¬Ä!$à1 Ç"²|]âMS@ÕíÔÚµ¬–sÜ´RZHìÍGò™UÂÂŒ$ǘëµ6å²C¦èÚ~‘æý†ßÊó0]›jŒíEÜNØ×'j.rpMA©xkKÕõ¯o¢žYcˆÂ]J±´d‚ÈÑ«el Á  ¡{ãk®®&³½û?hTºUB“É»I ûÃ*^YUNÆås>©â»M+VM1­/n.äò„iomí"ÎTrF?ãÝÁ'eI n+`øgGk¹n$´ó|Ýû –GxpC°„“³l°PN÷É;›1ÙøOE±¾Kèm\Þ++›‰n$’GeYK31.BÍ"å³Á¢®2uCk êz}•Ô×6–rÏ*˜ƒ-¬ŠdEY@l‘æÃ"à6$.ϪøûHѵ[Ý>ì8šÖ 'ÄsBí&ÈŒÅDbO1NÀÇ.ª¼uåsnóÁšü2Ãsa¾)¼ß5<éËæ;Hw€ß6GeÎv%vš/<¡ßÍ,—6ÓºÉæî„]̰æDd‘„AÂe‘òÀ–'99  !ñ$2]Z[˧ê6Ïw?“¸„(pc’@ýxDß)éÆå\Š·£êöšîœ/ì_̶ieCùr4e”‚ART{‚*=wKmcLkE{\ ÑÞZ­Ìü/ ‘œ0Ã) ªrFA“GÓ²´áleó¤iežW ´4’ÈÒ>Ñ“…Üç’@À$õ 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐE^¿¶ÔînÛj‹kP¢1l¯ø’MQðWüˆúýxÅÿ ŠÝ©—ÄÆ¶1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(©ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖ逃‚蹤òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûê'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾¨òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûꡚH`–(žxüɉ 9-“ùþs@?ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÒ)v :ŸZw“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßTy?ôÒ?ûê€0ÿ³µ¯úäšÙÚ×ý¿òM?Æ·<ŸúiýõG“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßU ÒC±DóÇæLHÉl ŸÈóšÉþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÊ±Ò® ÔÚúïPûT†$$&à{¯ç^ñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5¥/?„î<ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¦_Ø(¢Š‘…Q@Q@Q@Oþ¹¿åQÔ“ÿ®oÃùTt“iâM2îR¢)[i·’o‘.°@ñ÷Ô»ë¹ù]ž|E¡­Š_6³§ 7Vt¸7I岫b8 3*“ذMqz‡Ã%MN´µ»º¹x ·²f•¥WAqlï"$Ìè€, v ä oÉáTx¦ÏWŽöÕ¯BÝO-ÓY†fu¶‰TD_x(›•|î'kl Kê©¿Öó‰&µ’æ9þ_,„dV_½»póôÆ^«ßZ\yMÔ}¢#4;$ÍŒmË®:¯Ì¼Ž>aê+ËÃSiÚž‰%¥ò}ƒJÓ›OX%€´²)òþc `ýÌÁýïQ·3Ãz åž¿kq%­íµµ…„¶)ÍÌrÆš‰ÎLj"ožEY2nÎ0 ¥cê?ò2hŸößÿ@±XúüŒš'ý·ÿÐlQEQEQEQEQEQEQEQEQE$ë—ñþUIúåü•G@5­U4=óT–Þ{ˆ­"3Iwì^XÌ'¯n2p*¤~)ÒÒÎ[JtÒL3ýšhõ £ŒÇ)@áw(IFVXð}Aé“k~Ô4¨.RÙï {s3Äd®6±ÚrpN9ààóÐäÇá}F æÕàÕmF±+Hf’K&kvWXT…ˆJN-¢ä¹ç ÇUÓ–ù,ZþÔ^;2%¹™|ÆePìç$…eb;¡¢ÓUÓ¯î.mìïínfµm—Ã2»BÙ#ÊœƒÁô>•ÎØøÓMÓæ´¶¸ÿYua0™âO.Ð@6aÙòXç€ ‡ÖO ø2? Ü ñîÄ}–ÌÉ$墇+•!ådÉÙ(ˆ>^©¬}GþFMþÛÿè¶+Qÿ‘“Dÿ¶ÿú  Š(¢€ (¢€ (¢€ (¢€ ò¯ŽòÒÿëèÿè&½V¼«ãŸü€4¿úú?ú ­)|h™ü'qà¯ùô?úñ‹ÿA»^$~)ÞøEßÃi¦ÛÝ.”íd'.Èd’›¶óŒã8É£þ­ÿý-¿ïó…S¥&’=¶Šñ/ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð¥ìgØ9â{mâ_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáG±Ÿ`ç‰í´W‰Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Æ}ƒž'¶Ñ^%ÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{öxž·xúì—r5ªéË? ”¹l{ãóÞ¡ÿŠ—þ¡?ù¼«þ­ÿý-¿ïó…ð½oÿè mÿ›ü(ö3xž«ÿ/ýBò%ñRÿÔ'ÿ"W•Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÕâ¥ÿ¨OþD£þ*_ú„ÿäJò¯ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð£ØÌ9âz¯üT¿õ ÿÈ•v:¼ú½•ÝóXˆí·à@_'rã¿á^]ÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{‡ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W«\øWÂV{~Õ0oÎß6é×8댷½Aý…àïÙàqÿâê}µÃäŸsÎ¥ñ¹9¸ßöŽM>M9 HÛdQ>7Ëgw’OÒ’Ï^Õl.´YáK2tx¥ŠØ:1Ýæ 6ü7>ØÅz7ö‚?¿eÿÇÿ‹£û Áß²ÿÀãÿÅÒö´v°rO¹æ6šž£iƒ‹Rº+HöùF˳°c¿žFGlVÖƒâkm2 ޱ\—Ô[PX¢²YBHNIŒ³‚‡¨çç•Í­_\jòâËL¸d´ŽÒ4š* !²ÜžAJ«w¨jú”š†£,m3"Æ©á óùäׯÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñUJ½$îœ$úž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅUýn‰öLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñT§Á>'OÀÿ®òñT}n‡ì™ã^W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“³ÉÿÅRúÜ;Ù3Æ®´½ös=Í¿™!!êX ±³²{{8Ê+… ÝOÖ½þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ©úÅ;ÞÃä‘äH¶Ïiä\Ær@× ‚)¶ž[tÌT†žF8&½{þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿЧõš}ƒÙÈò'hÍêJQ‚qÏñ©X¥ÃΣ¸ŸcdÐW¬ÿÂá¯ùñ_ûÿ'ÿNÿ„#ÿôÿÈÒñT}f˜{6yË8m¥ŠÝ6ïÜv… dõ5Îx•vÚCþÿô¯ áðïý¿ò4ŸüUyÇÆéz>‹§Kakä»Ücæ3dm>¤ÓUá/u!85©é^ ÿ‘Cÿ¯¿ôT‡ÿ^1è"±üQÿ!Uÿ®cÿBjážìס>ºme†+TÃ$í¶$’ãiñ‚y<Žž¢§û}çüýÏÿ q¾ ¾M;S»[2öÎ(Q.åŒ"…y2dVu%|ewƒ€ y,õû©5íîäe– ÚÚX_÷r«)òUO…#(wו?1É- w_o¼ÿŸ¹ÿïá£í÷Ÿó÷?ýü5Çêzv³›…Å̶çÊ‘ËÊL’7ï›pèWŸ$à2(àuS-Ž‘©I0ûuýèmbòÌrlÛ.ù#sdª”_˜²·ñoǯí÷Ÿó÷?ýü5¾±-ä =®¤óÂÙÛ$S–Sƒƒ‚:ŠæD:ÈñbL"‘,™ØJD…£1ùgn—ƒ¸&qsó’×ô¸O•n­d¶ÝO I *ò³ƒò±P}‰è`ñ¡cue ºÊ·7qÂÆ\±PÇ?Ï56¥©^6¡8"£”€bMÿ!#þÂÿ:пÿ×ýuæh!¬JÛ1©9Þíâsó:ç*9ä­‘ÛÒ¥û}çüýÏÿ yÛ¬k£‘HD°x….mdºƒXYmâÏ™4w;‘02rAÀÀæ­}¾óþ~çÿ¿†¸ù­ui´m[Þ›©`T¶i$†+ãv2ñ_,çïä@2ë0ÝÝÝZê¹Ào— j~‰­érÅwlg’y5K÷šÞk°° gk‰"F@Ý!…‹íiâ>èÚ;o1ÿ¾ßFnÕnÝ®™Õ#/ó2©ˆH—'¶áë^o¤hÞ.šö+kÙ5KM/íQ¼‡í[d)ä܉ãs;í,mÇ0~e À½mj~¹·×4JÕuDÚA5²«jORÒFñ™à5Êçì6nYÈì¼Çþû~u®Æ·-Ñ—,b¥²AGPJ²ž ƒX:e¶·o.%‚ôéòoQ%Üà(\¦5IÙ <˜ÎÒK9`Cô:¿üo¿ëÞOýÐ>³}u¥iR¼ÅdžÎ)ähþRY—ž½«6}tÚË W©†IÛlI%ÆÓ!ã…òy=E=ä ¡ÿØ2ßÿA®;Ä·0[]j6òÜ[#jZrÛ!’æ8ü¢ £{‡`vþðr¡ÊÜtÊ$í~ßyÿ?sÿßÃQlKö_µi?ÙöyžwžvlÆwg8Æ9Íqú2ÞêS…žæKI.®¸y­÷ȪˆX6Ö ùGŒ |:n¡iàË6[µºŽÝb‰Òôïy‚½ ’<… dq¸l²û}çüýÏÿ 4j—Vˆ_JdU È&9çŒô8?‘®SV³Ö»°iàÅšáiÀýàYŽÝ •Ý¿ÈÉ<ɃsË»ΪZÚõ¬åµŒ![€H7nà¡!gåRr8%Ðý¾óþ~çÿ¿†·ÞÏÜÿ÷ð× ¶ÉÒ¤ò`Ô çWš)ï Ùk ‘8# ´’] sÛä«ö:F¥$Ãí×÷¢5µ‹Ë1ɳl»ä<Í’ªQ~bÊßÅ¿u‹¨Þ«sdòäʯAâ;ëýêWòãxïZÙL`Œ(PsÉ<ûÖEWü‹·ßö“ÿ@ûb[8{­Ià…qºIg*£'$œu4øµK‰¢Ib¾–HÝC#¤Ä†¡<ŠÀñ]ÄpxcPG’5kˆÄ’¤a”€2äS× =j„Íq­}ºÿK¼‘Õ,“ì±Áv…ÐókHÝ §<îÀÀaöûÏùûŸþþlz¥ÄªZ;é]C%f$dëÔA÷ÍÙC©/ˆî&’+“hû†ùäÂÆ6ªÊÊz?v‡–'; †ßS:$QKm~w’™a7cÏ–\ YFèó—ÑÁêãÕ.%RÑßJê©+1# G^ ‚¸§}¾óþ~çÿ¿†¸ô"[ÇçI^S¾&åHÓÈÆFÄ‘Y °àü‹Èn‡LÓ®b‘înî®ÌÆâr#i·'”dr‹·¦0Tƒ÷‡LíùhxëwöKr“4lÁebÊp3ëWïõ›Û›=>O3Ëiícü¬¯ÌçÓÚ°/ÿäuÿ\ŸùЛþAÚGýƒáþTV¥µÔv³ë ĸòá’çk¾N99›qoæMsa ¥± á¶-²@>Ù9+;[Ô¨ÉpÓAsoqä²0h§GV"“.ÐpÈw×ä–c;Ï·ÞÏÜÿ÷ðÑöûÏùûŸþþä¡·Ö`™.<»·Š)U¥·k•w¶J®ÊI °–ˆ…;ØHE8#WmN >dººòï'k{q¨K 2ÈSÊ*?~H1€‡v¨Àß@E]FõX0»› ç—$~UÔxSX¸Ölnå¹XÕ »xË  )É<ó\ut?¿ä©ØF_ý(CG]^UñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5­/  Üx+þD}þ¼bÿÐELJ.õÅž)í‘v‰ƒÔŸOz<ÿ">‡ÿ^1è"º¿åŸû‚¢Øã¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ*l9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,8Ù<¨=ÝŒ¢êËm½Ôs?ï%Tó—­Z¹ð•ì×sJ·6a]Ù†]³‚~•ÔQE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,3´ 2m@²Óç’'–!š"Jœ±ð`Ì„uÜØ#šÖÄš&£g¦è;Å«/˜“ȬË=Ô’»JgÙo&ÔÉV80¶¶ÈßÑ\Öž±Gñ\hìç‹Ï°´ß?Ù#–Di·~ónÖ`²D:“Ž?„ãJšæËÂC§[j:mšê×k1‡MužÞÙ¥šHÚ(^2H%¡^°¬Ü¤¨Epjþ0ŠÆåb²ºžK›6K ¼…VI\,rÈ»p²Ü¬ îÛUR@½/Œ šëÁ:ý½¼O,Òé× q©fv1°É$ö  ª+Ï,Óô·þË´ûû¤÷ZW†e²• Øå E"¹•¼ÀªHVÂÈNïVL·þ)Òü#2›Û[›h¯¯^+HíUâ‘®n|ñÌÎDD)å'rß) Y¢¸K}KŇÄÚŠÏû‹H>ÐÛÚY£(o)ãT€oþ튉Ø\S€šÞ ¾Ôï4û©­ëH’ü“]&ÍÀò€`¸ÆrcÇÌ0Ç -ÂxÉÕÝ"’ Éap¤ÙˆÙ@Séh¬VÉÖ]:9þÛ©²éË?—n¬žrÉ#gvôBÅŸkcä.›ÔQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢±|Q ”úA[ý-/â •X}µa}¬Cù˜qòsóvaÇÙ躮‡kmmcS ù'`£ÑX¾+žkÉ$R¼)çۭĨÅLp4È&mÔ2ä¸ ¨²1‘ƒ'ˆ-të{htŸZǦLҲ꺴sn¬¢?ܤ¬èd,]Ø1‘°c‘GÝÂwW% ëž!×n&˜ÙÙY[[ËKk8“Ïýå¼2º–à+Fe=TïÆÒ#Æã’¾6×­ü=c¨ÝYÙM.£¥­üQÛ+lÀŽÎ]ÀeÄþaÆ!Rä~ðzÂi>'ñµ.Ÿmnš\_jŠêQzàJŽ‘4:ÇοzWB¾oðîÈû‡·€ÌÖñµÂ$sD˪¶9ˆŒ÷ÀÏ   (¯-±ñŽ¿¾™t,g3jö°Ü•Ô%Œ@ò=Ŭ_¹òÙš8ö\†\ü¨Ø,d/½qâ-v¸´"2Îé­ç¿ƒLžé¼¨¥Eñ¹uȘňW?|ÚQ\>¯®¡â/ Ïq|‘^jž{‰l–á‚3“©X‹œðq’¹!x“Áž-Õ‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEpþ*׿ӼO½Â9³†î­ãKÓl×rïpñ 5Ä€,{aCæç&:êu-ÏUòÈd‹;%·¸’ ewÆÊÛN•Î U$p1n!µ·ŽÞÞ$Š”$qÆ¡U à;W-c{©¿‰–7’srn§KËF¹‚Ìû<«Ûs ’Åå+u´QEQEQEU KG³Õ|£r'Y"ÎÉmî$‚E]ñ²¶Ó…%s‚UI _¢€#‚mmã··‰"†% q¨UE8Õ%PEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHÌ]S]–ÃP[Hl~ÐÆ!.|И#¸öª¿ð’ßÐÿ&—ü*kþFtÿ¯!ÿ¡šŽ‹_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\µÿ -÷ý¿òiÂøIo¿è ÿ“KþVŠ.-ÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Ë_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\ÖƒQÖ®aYbÐ7#t?lAíéR}«^ÿ¡{ÿ'c«ºwü‚-àú©éŒËûV½ÿB÷þNÇM{Ýr(ÚI4DPY™¯£Ô“W4ÏùØ׬_úª>*ÿ‘nïþÿ¡­Sÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E+Šå¯øIo¿è ÿ“KþÂK}ÿ@oüš_ðª´Qp¹kþ[ïúäÒÿ…ð’ßÐÿ&—ü*­\.Zÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E –¿á%¾ÿ 7þM/øQÿ -÷ý¿òiªÑEÂ坸Io¿è ÿ“KþÂK}ÿ@oüš_ðª´Qp¹kþ[ïúäÒÿ…ð’ßÐÿ&—ü*­\.Zÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E –¿á%¾ÿ 7þM/øQÿ -÷ý¿òiªÑEÂ坸Io¿è ÿ“KþÂK}ÿ@oüš_ðª´Qp¹kþ[ïúäÒÿ…ð’ßÐÿ&—ü*­\.Zÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E –¿á%¾ÿ 7þM/øQÿ -÷ý¿òiªÑEÂ坸Io¿è ÿ“Kþ¹e-Äö‘Ísn¶í ܱ‰7ü½‰8Ì×[üyÚÿ×þT BÑEÆcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒÂ½Òîo¼GæÆb[@¦G8·ž©ÇùäT¿Ø?óÞÛþû?á[P?öÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þg®ÞͯE²žòâÍìþòÕ! Vv=pÿ»' \CŒu—©¥aXÇþÀ¹ÿžöß÷Ùÿ ?°.ç½·ýö¶(¢Ácûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ ¥y>©/‰–-6öy–c[ˆ(…¬¥„®xÒ•,TFp3õ w<~×ouËe¸d^Ùµä¢á´ç©ä?rIÞ>lðËÛ䌰XÑþÀ¹ÿžöß÷Ùÿ ?°.ç½·ýö¶(¢Ácûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ ³¬ê/¥i3ÞÅg=܉´,0£;1f ¶ŒåˆV @8Áãô¯ê7úU²Üj)fæ}CÎÔ®¬ZÇÙå%"É·Ær~bÁa”d8.…‚ÇOýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…]Ò®æ¿Ò,¯.-^Òkˆ#–Ki3ºe¡È œt:Uº,(Ém«Aimobúv# ½§w䓞ŸçŽaò|Kÿ=4_ûêJÔ®K^ñ¶:ûZ{ •…¬z…ÜÖ£æ"ÒóÆ5U3#î1±²ÆkÇiâ †_HÅF7¼„ªrô¨5 3Ä•Œ–“M¤,rc%@x ÷ÕNÏ]½›^Š7d)=åÅ›ØýåªB¬ìzáÿvN@¸‡ë/S@ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅP×/_MÐ5褂9-­e™^à1J© ¸_˜¯ãœt¥aX­ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…s–úγ ÛiW7°4òÛÇöE-ÍŪÊ&ùÿr<’¬Ñ,qç$Hçpa±[¨Ð5µ]¹Õ³Hã$ʮʲ $üŽ:òxaËu%‚Ä_Ø?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅX,cÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?áXñkºÍ®â¯šÕ®-5 MŠ|›H¤ŠÝ™˜ð]#ó]Ù‰]ÁIù ×õ3i¯¨Ak¼· ýµlðËÛä©¢Ácûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ Ø®j=[S¶×ü@·©çÛYØAumieù-p༌"^8£8,Å‚Åßì Ÿùïmÿ}Ÿð£ûçþ{Ûßgü+˜ÒüWªj&úÚiÞI5híÁ²’±ŠKepš‹½üÌÆ –•¦ÖXÏY j3jº47sªf‘ÆI•]•e@Iù(uäðÖêKˆ¿°.ç½·ýöÂì Ÿùïmÿ}Ÿð­ŠÁñî§§xCT½Òd‚+›{Yfóe¼°‘³eW£6@$œØÚÅ‚Äߨ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVV½â9luö´&ö+ Xõ ¹­!GÌE¤ æ3Œ,j"$ªfGÜ6ccfK=vömz(ݤ÷—o`÷–©b³±ë‡ýÙ9bâc¬¥‚ÆöÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þ±E ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVUÖ³«Xê)77QÅc¥Çyh¬ŽÑÅ“r7HTolùJÄ(à| 75}gY†í´«›‹ØymãûF¢–æâÕe|ÿ¹IVh–8ó’$s¸0جX,tØ?óÞÛþû?á[!<¸`Œ²±H•IS‘+/@ÔfÕthnçTÍ"Œ“*»*Ê€“ò8PëÉá‡-ÔéÓQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(1+p÷  U@£s*’TÔ€Y°;n>µ%PEPdÞÐî51©Ï£iÒ߆WOj(eÆÓ¼Œä``çŒ ¿Äò¼q"<;FU»`.O©Â¨ÉìíRQ@Q@AöO'Éû,W›çlòÆß3™¿Þßóg®yëSÑ@Q@T»Ò´ëû‹k‹Ë [™­[}¼“B®Ð¶AÊ2§ r=¥[¢€#B·p± ™ÕQä 72©%A=H›¶ãëRQ\ÔwW—Zæ§+ëc¶Óïá³KvŽ3 Áâ…þbFÿ0´ÅWkŸ+r¥¢¸} ÆW§Ãºlú½ª%ÍÖ’·–ò¼Üܺˆ•ƒ¬hv’dبßu[d°ñÅö©wŸg¡gP>x•gàŠ#²L‘ 6•¸^|¼îÁS¼t¶º“c§Íai¥Ù[ÙO»Í·ŠÝ97 Ê@稫õË[뚯ü&W6×PZÛiBÎÎL\]–)%i” *ÎΪ›|Ì| ©%ˆ­?êÏ¢hrÞÄ›äóa…vÒm2J±†Ø¿3ã~vŒÆÍkQ\>™ãFîûûÏN{û”iÑno7Yec[wÝ*4{”‘påC–PBª¿È?ÄX^ãNû=­ªCzÖb8ï/D7R-Á!XHŠ$Á;‡Ì’áÉétïèzEÃ\iš6e3.Æ’ÚÕ#b¹¨aW ´ŠÐZÀ-¡ÙåB#a6¯A´¨#01Ò¹–ñ Æmâk‹·žùlõHíícòÆáæÇnQ?v™*cÈV|vcÁ×ðö±>µ§É=ÆŸ=”±Êcd’9_€w'˜ˆå~ld¢ò € Ö¢²^öâ_.æ}žmEÈàvY™ ‚z,xFm¼æHùQþÞÛU/©­Ýú¦b-Þ0#ùpCr g #@ 5-IÖ|¯íM.ÊûÊÏ—ö«t—fqœnÀü…@<-ááwØÐt±sÏ*agôØM­Œ¡@鎔ýQ›UÑ¡»P;4ˆ0BLªì«*OÈáC¯'†·S§@Ç1<¯H3o‘•@.Ø “êpª2{;T”Q@fCáÝßS:œ6ùfst–¨²–lî;ÀÎNNNyÉ­:(±´’+¨žÖŽï?hVŒ6T!Þ?‹åyì©è¢€ ©¨éZv¯n¶ú…­ì*ÛÖ;˜VE ‚23‚y÷5nŠÌ_èj–hº6œÅ‹Ú(µL[±;‰”’ÈÇ#5|A Ü=ÂÄ‚gUG(Üʤ•õ lÛ­IEQEfCáÝßS:œ6ùfst–¨²–lî;ÀÎNNNyÉ©-t=&ÇOšÂÓK²·²Ÿw›oº$rn;” €ÏQWè Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@W¨jšì7.ˆ\ÚÂöºJ\éáv……˜Ü€Îï€Iò‘Žp«Óœ`Šæ¼1q¨BþÇU¹½–å"†áåà}‘Hd “H™·/Σ µŽMt´QEQEQEQEUI4­:]N-NK W¿…vGtЩ•žã |ÍÀ=Ï­[¢€*+Nkt·k S @Ö©…v¬,hÀÆ«•èvJŽÃCÒt¬givVxݳۤxÝ·wÝ®ÄÏ®Õô~Š‚[Iîíîæµ‚K›mÞDÏ/á†ÚÇ•Èàã­>h!¸@“Ä’ ep®¡€e!”óÜ=ˆ¤¢€ KHîÚí-`[–Îé„`9ÈPrÝyÆ?à è+2_ [IqÛ«¨¬"h¤le¾èŠ˜Èw Rˆv£*åy-»jŠ¡‡¤Ãöß+K²O·çí›mÐ}£9Ï™ÇÏÍ×=O­X²±´ÓmÒÆÖ [hó²#‹““…I?OEG$Êñ<‘#¼-¾6e£`®G¡Ã0ÈìHïDðCuo%½ÄI,2©I#‘C+© ƒÁv©( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘™Z޽o¦Ý­´–÷2ÈÑùŸ¹@Üd_j­ÿ ]·ýõûò?Æ©ë_ò3§ýyý Ôt®+šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹±ý¸ÿôÖ?ðÿ¯Yã[êgSƒÁ“Å~YœÝ&–‹)fÎã¼s“““žrk¯™ØLÀ1ëT¯f•"ˆ¬®¤Ü@§ GU~ â˜ÌM:{-"Ý­ôÏ _YBͽ£¶ÓÖ5-€2Bàgsì*ÓøƒÊBòi²(êÍm€?ZÚóûíù×9âid7ú\fGØL¬Ww…8üOç@ÿ„®ÛþúýùãGü%vßôÔïÈÿÏ¢•ÅsCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÖµÑ¼¶YþÏ4 üªÌ 1¸ñ\Íu±ǯýpOå@ ESÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR3Ô,®oÿøúÿØšüûÿãëþ4Ë_Í>§hX]ÞO§ÛOš&‡ÍÞÎ:lo&@1ÈÚ¤çyô4X,R½¹Öä¢ßDi¡ #]"î÷Ç8ª’>¹pbI4&DY£‘™nãc…pÇOZØ¢˜Ì¿µkßô/äìuBöÇ[Õ/¬ä“Iû:A¿'í(ùÜÓÒ¨jº¥¿ˆ ´·û,Ñ»F œpHòùLpÓ<À„„œ…e;ü¢·6ÐüG6§qeç@‘êY¶¡c°’Ë1‚²çø–6ùr>f_ààþÄÔçßÿ_ñ£ûQÿŸü}Æ·¨¥aXÁþÄÔçßÿ_ñ£ûQÿŸü}Ưë:½¦ƒ¤Ï©_>È!Ú Èf`ª2Ä(Ë0bÎI&¹­ÆWzõ•´VK›R–[Âþ]Á{tŽÞ`›w¸³¬á¶‡/ƒ€ŒX,kbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ãZzV£¯¤Yjvêë äÜF²+¨` Áõ«tX,`ÿbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ã[ÕÍk>)‹O×âÒþÓ¯—wwRÍËû–f^±FÆ-+‘å2ÊX,Oý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿ2×ÄsO©Àw“éöä扡ów³Ž›É r6©9ÞD}  ?Øšüûÿãëþ4bj?óïÿ¯øÖõTÕoNÒ/o’4•í ’eŽI–%bªN · >ñàu4X,fbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ãY6^*Ô¦›û9¼‰on%Ž+k‰,f³TfI‹Á+ ªÀÄ0 9;]¬Ã¥Ñõ/í]8\˜¼™Y`•n $R4o´àew!Á 0H`±CûQÿŸü}ÆìMGþ}ÿñõÿÞ¢‹ŒìMGþ}ÿñõÿ?±5ù÷ÿÇ×üj¥¿Š/Ež±=Mk¨Ãcml%ç3$_šã ÓÅCÆüeˆüG¨Ï|Ú$Z¶±H&’BÉnëÂä®2À¸¸ˆ`ça.rû°X·ý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿiéZŒ:¾‘e©Û«¬7GqÈ`®¡€8$gÖ­Ñ`±ƒý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿIâ-Z÷IŠÉìíTšòÞ ¥•ð±$“ÇÀ³Ÿ3ŽÃ“ÀVƒPÕuKAioöY£vŒ8à‘åò˜á¦y 9 ÊwùD+nl)`°ÿìMGþ}ÿñõÿ?±5ù÷ÿÇ×üišˆæÔî,¼è8uK6Ô,vYa0V\ñ¿Æß.GÌËüß¡¢ÁcûQÿŸü}ÆìMGþ}ÿñõÿÞ®yÑ.n-à’P%}± Df,ÝÈùq…ä’Ê2ÊX,Gý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿA¬ø¦-?_‹KûL¾\QÝÝK4/îY™xFÅ´®vG”Èmÿ,–¾#š}NÐ °»¼ŸO· Ÿ4M›½œtØÞL€c‘µIÎò#,ý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿoQE‚Æö&£ÿ>ÿøúÿØšüûÿãëþ5ž"Ô ÔÀ¨ êB 9¸·EQE’ÞÓŽ­&¦¦ö;™eY¤_Ïnꪠ´jáÊŠG sš·i¥ÙX\\Ïkl‘KrÛåeþ#’–fÀãs»uf&ÝQEVd¾Ò§±ûÖI%·Ÿ%ÎÇ$þñÙ™ÎIλ‚:vR6’+NŠ(¢Š+3QÐ4ÝVág»…ÙöùngfL“²UR©Ë|®ù›˜çN¸½?ÆhºEΦ=¶µkÕ²[DUí·Ëo£–r$æårÀ'Ü'iÜêcÒì¢ÔåÔRÙòUØòޤqŸ`HTõ!„\[®[Vñlöš½­†“uz´ZÆä'”~Ëö°¼Š2C/'Œ#Ž»s%玴k/.…4¸¹óc›Íˆl’@»Ë.$lïO™Q”nä­´¥¨ç‚«y-î"Ia•JIŠ]HÁ#µdè>$‡Äð\Á§ê6ö×-Ä\ÂeR@Á%H,Íܔޠµµö£ý¯c¤é’ÚÛÍq÷-=Ì 2…¢]¡Ðä™Îî6‘ƒœ€ "ðÖ—¥Å·•<«q·Ì’âêY¥ùNS;]­–\µ‰a‚sZPA ­¼vöñ$PÄ¡#Ž5 ¨ `Ú¹«OLš­õ–¥`ñ‹{È-Z{pZZX¡(¬í‚äË)PQxK&9~!èÐ__Yʳ™í%XÚ8+‡|Ì– ³ 4‰ò°W9áI¶Šåµ_ÚË£¬ÔYîïÚ{y+"mäXʉڧ!™p® ®¦€1l|)¤X=ÛGÔ¢ñJ\¥Ýì× 0!TîI”ª«’3ŽœTòxJ›L‹N–É$µ‰·ª9,Kî,Äå‹n`䓼;†ÈfÏ/cñ;LVi$‚â+ˆ’â´÷óç·F–(‚LŠr$ÌÈØ\ÿ€J“hx¶7qk“¨Ë©†u—O_$KA32ÈÄП•Éýàã†ÚÐÑ\õ‡ˆ&Ôµ}­Â 3TÒ^þ4’"&FV‡`ÅpVn˜à¯SšÃÞ:ѼM¨Ig§ËºAž3æÄþl`€[ìÑýåùdß7NZƃa®¤)ö¢°tX/&€n0'ËeÉT‚s‚21PEá]2 ï¶DÚŠLZ7}ºÈYQK¯™µÎÔPK»æ§Ö5¬…µª¡¼¿ŸìÐ4 ˜ão-ä,ÀH  n8PK %—SݼQ[@ÚkDÆiŒ˜u~ÀËŽs–$¦À$’ÓK²°¸¹žÖÙ"–å·ÊËüG$þ,ÍÆçvêÌMºÌ±Ôf“W¿ÒîU ÖËÂI!ZZ@€‚rØ à0Æâ«§@dÁá½:Û[“WŒÞý¶O¾Í;#› c.ShÞÄ.0¹à Ö¢€(K£ióE}–ù[éViÈvÈªŠ®¤«`®*Áæ­Á6¶ñÛÛÄ‘C„Ž8Ô*¢€j’Š*†¯£Ùëº{Øß‰ÚÙó½"¸’à‚ ±F©åOÒ¯Ñ@²xSH™"Icº”F¾[y—³1™2[dľfL³adÜf`oÇ¥ÙE©Ë¨¥²-䫱åHã>À¨ êB 9¸·EQEbÿÂ)¤NãPxåLs¬×³Iˆw|9Bƒ{ávàn8¤‹ÃZ\V—ÞTò­Æß2K‹©f—å9LHì]v¶YpFÖ%† ÍkQ@Á6¶ñÛÛÄ‘C„Ž8Ô*¢€j’Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPX±øOE‰%EµrŽ»ZâF(!€‡-û ¡=¸(„cjãjŠÅÂz,6rÚÃjñ$³ý©¤ŽâE—ÎØÈ$ ¼9Q†`rÙlçsfx4 6Öú;»X^ÙãP‚+yž(H °n‰HF!@PJ’¨þ:¡«½ÜZ{ÍiecåfIg½€ËÆ' H˜ìrNŽàÅ•¾›§ÛXÚGåÛ[D°Ä™'j( žOuªú–gªùFäN²E’ÛÜIŠ2»ãem§ J窒8æ¢ñ^­o¤µÍý¤[ªj å¼-öwiv"!-¶P‘±`Ì@e ½;JÌOéQ[Éo’G “ÃrcŒ•Q$B1¢ø/NNjGàÝ;”œ[NZ=¾R5ÜÍ!dIBÇ}¨¡âŒíP cŠÞ¢€*j:e®©n°Ý#½)Z)#l•t!”à‘FA#¡"§‚mmã··‰"†% q¨UE8Õ%’|3£˜tèM§îôè’Qæ?îÑ'Qל4s÷}Îjk~‡SN&iþÑÂÊU¢¨!€Ál‚H#¡¢€1l<-¦éÏ¥Kºy´»1co#\¸PȤ#µI%zªÿtbÞ›£Ùéh²¤rc5Ä`g 3Fqµc‹ôP¶Vú…£ÚÝG¾'Æ@%H ä2‘ʰ À‚EOE­•½ŸäGµ§•¦•‰,Îç¹'“Àz`ôQ@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE#(_kZ~›0†îãË‘—pñ’;cU¿á*Ñç÷ÿ!?øVnµÿ#:×ÿÐÍGJâ¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü*½æ»áÛøV›Ÿ25–9€Ù ùãut<̪j÷‡˜¬Wd“úÖ·Ÿ'÷¿ALg/w«xbþâÚ{©Ym›|LÑ?Êr§#*­ƒÆäFêªEÏøJ´_ùýÿÈOþ«my<’݆|ˆçؼ–‡›Χóäþ÷è(þ­þòÿ…ð•h¿óûÿŸü+ÊækËU¸¸‘¤šBÅ™»òjÅ+Šæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð­;È/íÄöÌÏ$(W8ôÈ®bºØ¿ãÎ×þ¸'ò ¢Š)ŒÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©Ìj±I7ŠUbÝ…8U$ãy¥ûçüúOÿ~ÍtÊ;:Œ; ¤ à~§ó§yýöüéXV9°^Ϥÿ÷ìÑö ÏùôŸþýš½oâuŸSK*Uµšym-î‹q,ñoóoUË|1à˜ß ØdÚóûíùÑ`±Ëý‚óþ}'ÿ¿f°^Ϥÿ÷ì×Qæ?÷Ûó£Ìï·çE‚Ç/ö ÏùôŸþýš>Áyÿ>“ÿß³VµÝéÚÝ­›ÚÄ`¸•a7ƒí3·sÅSº4Þ ’ÊT+¤ZM'ÄëªÜD‚)bŽîwa#6~Ó* àr‡.‡içk¡ûÛÕ Š?`¼ÿŸIÿïÙ£ìŸóé?ýû5ÔyýöüèóûíùÑ`±Ëý‚óþ}'ÿ¿f°^Ϥÿ÷ì×C{¨Å§Ú=ÕÔì‘&2FX’N¨³@ $$Ö §Œ./l­Ú.äêKt‰,vó¤bùٻYÀÎÐÎ¥‚Ã>Áyÿ>“ÿß³GØ/?çÒûök¡±ÔbÔ´ûkëIÚKk˜–hŸ‘¹#‚:Ôþcÿ}¿:,9°^Ϥÿ÷ìÑö ÏùôŸþýšê<Çþû~u‹©x•lu{m1$·ó¤h¼ÖººòVFe@™É#“jÎÆË/˸°XuƒÍ¦Ù]É-Û–(8¡ffëÐQý¸ÿôÖ?ðÿ¯M·ñ:Ï©¥¿•*ÚÍ<¶–÷E¸–x·ù‰·ªå¾ðLoÐl2myýöüéŒÂƒU’´HtT™§.Zœ¨¢äöä©è{T¿Ûÿ@]cÿúõ±æ?÷Ûó¨/¯žÇO¹»òîn<ˆšO&ÝwÉ&ÐNÕ^ìq€;šäôÍ6ú=:%{+…aœ†‰ê}ªßØ/?çÒûöj;=ôOqZ\ݼ© ©ÓïþÑm4Œ®Û Ûk*ÆÎãi!J‘¸°ZètÍUuKº„Ê€³ÆñÉÃG"1GC‚FU•†A ã‚F + ÆØ/?çÒûöhûçüúOÿ~Íucÿ}¿:<Çþû~tX,rÿ`¼ÿŸIÿïÙ£ìŸóé?ýû5=¯Œk=Rêk;ÈÎò;H¢~%¤HŒ)ÆÂÆe1ÈÝ· ñd®âÆ+fÖ#gYì’`Älì²6YbÙГ" ‡(X,Aö ÏùôŸþýš>Áyÿ>“ÿß³] Ž£¥§Û_ZNÒ[\ijDüÈÀpyÖ§óûíùÑ`±Ëý‚óþ}'ÿ¿f°^Ϥÿ÷ìÖ–»âÑVÏ·7-su § É*F]˜ñÁaG-Ø`3-}GÄwzv·kfö±.%XcÍàûLÄíÜñBî7‚䲕 çi,*ý‚óþ}'ÿ¿f°^Ϥÿ÷ìÕí'ÄëªÜD‚)bŽîwa#6~Ó* àr‡.‡içk¡ûÛÕ6¼Çþû~tX,rÿ`¼ÿŸIÿïÙ£ìŸóé?ýû5ÔyýöüëßÄë.¯«Y϶–ÚlÎ×W-å««4ªÌä"˜[æ8Ï$|¸f,(ý‚óþ}'ÿ¿f°^Ϥÿ÷ìÓíüd÷It‘X\¥Ð¿6p\?–Ó±g ü~év31~îó²¶´ÍUuKº„Ê€³ÆñÉÃG"1GC‚FU•†A ã‚F  _`¼ÿŸIÿïÙ£ìŸóé?ýû5Ôyýöüë'ľ èz˜µ¹¼h"y1qªXînˆ )$Ÿ ˆRX,fý‚óþ}'ÿ¿f°^Ϥÿ÷ìÕíKÄ«c«Ûi‰%¿#EæµÕת²3*È&I¤›Pv6Y~]Å¿‰Ö}M-ü©VÖiå´·º-ijſÌM½T-ðÇ‚c~ƒa°X£ö ÏùôŸþýš>Áyÿ>“ÿß³]G˜ÿßoÎ1ÿ¾ß ¿Ø/?çÒûöhûçüúOÿ~ÍZ)s¨kvãN¿eÒíRàm\Éu“("8úža Ää|¸f£aㇾ‰ãŽ+K›·•!µ:}ÿÚ-¦‘•Ûa›bíeXÙÜm$)R7 E‚ÄŸ`¼ÿŸIÿïÙ®•¥­²°!„*#qUôÍUuKº„Ê€³ÆñÉÃG"1GC‚FU•†A ã‚F Z$±É$ýiŒJ(¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEfC¡YA©›äWÈf–8Kf(¥|ï‘ v“îÄ`É!m:( Š(  Sáù^ŸU‡ZÔa3´f[uX6TËF\'Þ8 0]ÈÁbj};B²Ó.kus…ò GmËm ˜â„ŒãÙWî¢*éÑ@Q@^ØÚjVi}kÕ´˜ß ñ‡FÁÈÊž ±m|£XX‹[žËÍ0–ЈdV˦ää#jÔBdV Cko½¼I1(HãBª(Àv©(¢€ ÁÕü'c¬êy,³Ã$Ö¦ÊèDý"Ü’LLYK*Í’…IÏ_•q½EfC¡YA©›äWÈf–8Kf(¥|ï‘ v“îÄ`É!m:(  ¾²·Ô´û›¸üËk˜šS$nF‘Èàž•=‚ž€ùÓ\ê·Zƒù{/äòÖhvoÙ³b* y’uS¸;+nS¶µì¬­ôûDµµdIœKIÉf'–bI%‰$’I$šžŠ(¢Šç¬ü%~nõmGPŽý„³Gqä¨ó@EY¢]DI‚Á759ðÅ‘·Eón–è3<—Ñ˲âRÀ 7:ㆠ£B¦Í†4+µEGÚÛÇooE J8ãPªŠpªJ(  {C:ì0BuKÛ(â•&Ũ‹çtut'ÌFû¬€ñŒóœÕx|74³ê)â PÉ/•ç#%¹YDjRL[•OÌÅT¨ܨ]Æ·¨  Í;B²Ó.kus…ò GmËm ˜â„ŒãÙWî¢*éÑE‚¾S­Ýê7­íÔwqyÙO»@ñ3ldƒmkÿOñ[ÔP=màÀ^>Ñ,d¹.V[XÒ6·‘c¦<.qÁÈ>d€‚®AÚ²²·ÓíÖÖ=‘&p ,I'%˜žY‰$–$’I$’jz(¬Í{Gþ‘>˜÷×VÜ+G3[÷‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAzþÛS¹¸mª-¬ABˆÅ²¿âI5GÁ_ò#èõãþ‚+v¦_ØÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢¤f?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[¦  >æ“Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿïª<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú£Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿ惘i!‚X¢yãó&$F€ä¶OäùÍdÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[H¥Ø(ê}iÞOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}T3I ÅÏ™1"4%°2 ?Îh'û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(*ÇJºƒSkë½CíR|<˜ì~¿yÿÇ?ùiõôô^«^UñÏþ@_ý}ýÖ”¾4Lþ¸ðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­Ú™|Lk`¢Š*FQEQEQEI?úæü?•GROþ¹¿åQÐM§‰4˹J‰ü¥m¦ÞI¾DºBÁÄOßRìc®ä#åtfyñ†¶)|ÚΜ,ÝYÒàÝ'–ʬˆlà€ÌªObÀu5Åê •4M:ÒÖîêåà‚ÞÊušV•]ų¼ˆ“3¢°1؃0p¿'„uQâ›=^;ÛV½ u<·Mf™ÖÚ%Q}à¢nUó¸­°€u/ª¤zü:C[Î$šÖK˜çù|²‘Y~öíÃÌCÓ=x"¬C}iqäy7PIöˆŒÐì61·.¸ê¿2ò8ù‡¨¬[/ M§jz$–—Éö +Nm=`–ÒȧËùŒ€÷1ÿ÷½FÜÏ è7–zý­Ä–·¶ÖÖؤw71ËVhJ$91¨‰¾yd`É»8€v•¨ÿÈÉ¢ÛýVÅcê?ò2hŸößÿ@±EPEPEPEPEPEPEPEPEP®_ÇùTu$ë—ñþUPÖµTÐôKÍR[yî"´ˆÍ$pmß±yb70 ž½¸ÉÀª‘ø§KK9n5)ÓI0Ïöi£Ô&Ž3¥…Ü¡%XmcÁõ üC¦M­øwPÒ ¹Kg¼íÌÏ"¸ÚÇheÉÁ8烃ÏC“…õ/›WƒUµÄ­!šI,™­Ù]aR!(e8¶‹’çür6€oWN[ä±kûQxìÈ–æeó•C° œ’•ˆì†‹MWN¿¸¹·³¿µ¹šÕ¶\G Êí dŒ8*rÐúW;càKM7OšÒÚãýeÕ„Âgˆ<»AHÙ†7gÉcž2YÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû¯ew|Ö";møÉܸïøW—Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛkʾ9ÿÈKÿ¯£ÿ šÇÿ…ëÿ@KoûüßáI­qñ–ñ4IÖ-(ZF×bdS6ìM¸%q÷óœöª9Aó=„äš²?ÿÙnetgen-6.2.1905/doc/pictures/menu_help.jpg0000644000175000017500000000267413504650527017073 0ustar kurtkurtÿØÿàJFIFÿáExifMM*ÿÛC  !"$"$ÿÛCÿÀ%["ÿÄÿÄ@  !"1ATa“Ò#$6CQScqt‘’²Ñð24R¡±ÁáñÿÄÿÄ1!ÿÚ ?·2Ö´ÈXJÖÇQÝÔ?ÍB´ÿ zzõn²ÜbÏq¸Wk4‹Â$:óa¨Ì°XKÉyAD!h/¤+y Ø^HÆù”ïâ׸uøßÕZ†GÑm–‹4ˆø»ŠŸ»ÝD´{"¨ÆZ[LXìአ共ž‚“œ+j¼w~ ìw+íËPHm]æ]ößubzíÈTˆ¨Š"ûgke|™@¨®‰Æò¥±õM®r®¬Y.‘ïSíeH•ÖW!·AP ©%@!eHR@YHÈ9#(:÷N¿¥-z–eî5¢ ÎÞÕÁŸde´Â’Êø¬eXSÍ$œà)ié'1ž¸0Vã܉zå²"Û•m²½,Ì{’°vw:Úå©¥ä´Á!”0=¯$ÁLàö<;¥¹×´Šdno[¦ Ôb4ÐTrï¦Pð*mÔ¤ï! -Ûa÷2YWú®x×~QϽX­/f§4Í«OCuçcZá5 — ¸¦ÚHm%Xg @ºÉPwã]ùG>õ8ç~UϽ])AܸéøEŸ¤äUuÖŽMW]ÜUÆb}Øê@+ØXUßV{é»}uïÆiÚx±³Èœ$ŽÎß Ž¯WéÄòÄ‹³+1&±à€¥{sÏHeISÛMˆZJˆ-¸#œ ”£•‘¼}ž;úÿ:ÐrxÕËÒúj×û^$»m²Æ€âdá Äq¹–×ÕÉÌf™yHÙ†àn2Â’J– Þ½¸hý´ìÏPêÏŽ3§¨¹µ¹¦;N;¦ôÊ‘!Äi)O¬Z¡qˆŽ”8Òù:ZK/séNxé~Íp{¬!DnÎÕâßtŠíÖÍs¸\ç-á2J¡-¸ØH –!xÒâºJØ(ø`.Ïtƒwˆ©v÷øæ%ø¥a u—VÓ‰Œœ-µ§ qHß^Ï£ÙŒ~¾=Ûª Áž‡:2uÖ$Fœ…k“!÷ÃðãJ™Æ¾·›mÔ¥)JÀqM%9sm;$q láÎIß¼çúÿÏ×XqúÇ`ð)ŠbJb˜ äUwÕžúnß]{ñ𱝷ìªïª°uEÛ¤‘îçºÏÎ*‚mª8K»ÅÔSâÅo 0ñh¥(à ä…íXîtïýÊ×å/×JU˜‡:wþåkò—ë§:wþåkò—ë¥(éßû•¯Ê_®œéßû•¯Ê_®” s§îV¿)~ºs§îV¿)~ºRÎÿ¹Zü¥úéÎÿ¹Zü¥úéJÂÿäV½ß4¾ÝßÏãP›¼×æ]$Ìp6•ÈuN¨'kQÉíøÍ)EÿÙnetgen-6.2.1905/doc/pictures/viewingoptions_2.jpg0000644000175000017500000011071013504650527020413 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ0¡"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…nøRÓMºñ­¦©›kpƾT«7 FïøÖœ¶Ó,t«mNÕ$Õ5lYÆ\°U†7 #mdÇѸ"³HEÙ¢”[ØãüäÿŸ üü(ó“þ|,?ð?ð®ÎÓÀ²jwÚœ‚G‚Ú=R[E½³M¬Fâ3ò õ$Õh<ÓO¶¨‘57Óî€"Š\Éœò»Tž‚’«H|’9_9?çÂÃÿcÿ <äÿŸ üü+¬ÿ„N-;P´[Ë…7ZM:(LG'ÌÈnp=zÒ?†tßø˜ÞÞêɧ[E­Ë¦F‹jò ŽF0IüaÖkH9$ržrÏ…‡þÇþyÉÿ>ø øWM/„á±›\mOSK[M"DŽIÖ!v|lAÏ9ôÍgkz'ö?ˆ¦ÑÖaq$B?œ.ÐÛÔÆ}ê”é·d'-Y•ç'üøXà,áGœŸóáaÿ€±ÿ…tú„ ³UŠU.5 &$–öØBʨ¤v¹á°Ï¦Õ¼i§¾µoo¬­Íî“ ÜOnmš?Ý ;²F@=j}­!òHä¼äÿŸ üü(ó“þ|,?ð?ð®ÏSÑt}g¶¶r;I¨EjòBð¶ÙUÛBÛþ\ôØ1õª’øfÍn/îoõôûOíy4ëP4›Ü1휪€:’ÄUi‡$Ž_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ êÛÁÖ–VÓˬk)cäêÙÇí(f(HÁîp8ïÚŸmàW›RÖ­$»cý–èŽ- 3K&á•*€Ž0yçó£ÚÒIœŸóáaÿ€±ÿ…rÏ…‡þÇþbêÙ ¾¸·FvÈSt‘ØãÕ[•>Æ£ò…j”Zº#R?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ ¤Eqa¦€Ã#6ÉŸýå?üøiŸø ŸüM^·‹ý.?€*—Êö©Ðf:±iŒCOÓ÷޹¶L/qRùOÿ>gþ'ÿSÇüLåãø¢ÕHô¹/Y›P¾÷®¡#1{Rm-Ò@Ñ.æÓôâ3ƒ‹dãÿ¥Ei\Xi 0ÈͲgÿA§ÅdaÝä+!]îrN$Ç?•Iq %]n>ÎcEq!è0:j.­{µ"òŸþ|4ÏüOþ&¡iš7;-m`š6e‚GF†VGF“s>§rÒLM¹‰F-†Al¾r:zT·QâyÏùû¢ˆµ%°4Ñü-_ÿÐkÿ%aÿâ(®6ŠÃ’=Šæ}ÎîÕ ÓíH>D}Ýñn73n~+Ô|)á÷Â:=ÍÅŽù¤³‰¼×;G`Õ®|áÁÖÀ¬òñTž& ê¶)S•òá[T-Âʧ™`ô#×úÓ|¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅRŽ&œtIƒ§'¹ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUWÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯e ðáé`Òy?øª«7‡<o+E:ÚÅ"õG¼e#¿BÔ}n‡ì™äžW°£ÊöëØ^þý—þþ.ì/~ËÿÿGÖáØ=“<ŸÊöy^½cû Áß²ÿÀãÿÅÕ¨|ወ–X,ÒXÛ£¥Ã°=º†£ëpìÉž;å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸v²gŽ*²:º¬§ Ž Öž£â-_Wñ%޵{öO:À/ÙâGÛ²À±9'Á^¡ÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅT¼E9;´5NK©åK­j&+ØîmtËènïõ­îàgŽ9Xœ”Ã:㩦Újú¦Ÿ¦êÖv‹e j€‰‚DUb| ËÃßµz¿ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿQí¨ö,ûžYq®j×wº%ÅÁ¶a£*ý˜o†ßšNy?"ôÅAq©êWv’[J-Drê­ª¹D`|ÖmýÞzu÷¯Zÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ©ûj]ƒ’]Ï<±ñ&oµ«½q#’=Q£y-â³ǹíg€AÉç·JÉÖu6×¼O¨k o%´S”£ãxUP œp Æxé^´<áÃÒÀ¤òñT‡Á^Àÿ]äÿâ©Fµ(Ë™&7 5cËu?kµÝ¼‚Â/¶ª%ÝÔ0mžáW ÙÇaÐ µâÜëzޱ™moia}夷 Û™‘T¬ÛˆÛz•éð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU/kF÷°rϹ孮j%ô–û>žÏ¥˜ü‰Ú&óJ¡Ê£Ø+Ÿ`}émüA«@nKÁ¦Ý ïšüEst†f$îO˜×¹?νGþ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠªöÔ» ’]Ï%ŸTÕnìM­Ô°Íæj_ÚrÊP‡ivíÀÁÀ\vÇãVN¿¨¶¯{ªÉc¤Íwu2Ë™!|FUB¤0aÀ‘^¤|áÀ2tüúï'ÿIÿ_†¿çÅïüŸüU/mG°rO¹ã³Iy}{s}0šêæO2F>€vqMò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿZ,T²BörE)úW³ÿÂáßúäi?øª­¨x/Ãñé·Nº~ar'\ö¨X˜v³gÌ4QEhAõW‚¿äGÐÿëÆ/ýU_ÜÅxG+F»we 䎾œUÿÈ¡ÿ׌_ú¬ÈUë˜ÿК¼éîÎŽ†oÛï?çîûøhû}çüýÏÿ p¾3¾ßjUÔ£Šd²2E _Éjèß>6ŒLIm=6ïÑ%ž¿u&£=½ÜŒ²Á;[K þîUe>J©ó°¤eáò§æ9%¤ëí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¸ýONÖcób°¸¹–ÜùR9yI’Fýà“n óäœEªe±Ò5)&n¿½­¬^YŽM›eß!änl•R‹óVþ-øáÕý¾óþ~çÿ¿†¢·Ö%¼gµÔžx[;dŠrÊpppAÇQ\ȇY,I„R%“; H´f?,íÀ2ðwÎ"R~b2Zþ€—éò­Õ¬–Ò©ä #!%^Vp~V#£cê± ^'Ôô«Uò%Wid ºPX¦Aäsì:ä{W¢ÙÙŦ@míË… Y›-#¬Ç»_é^C®ÿǵ¿ý|/ò5ìÒ¬©¦†Š¯é‘ÝÝZ>¯h·6‘®!k• `]×9UÁ'ŽE2ÇÄÚ6¨û4ýrÂí÷Ûov’Ä3Á<áãÑIìkŒ±Õôû®œš•”qÇ;iï­$d¾LbàNÏ'*ãh*Œü™¾tÝRÂÓJ™4Éîä´×¯¯$‚ "åJnÂ0.ê¿òÚ3Œçžœb˜ÎÛÌï·ç\¥íÔšw‹.-키3éÒ^JšUu]ÞăÎ:ãžk¢²¸–êÑ&šÎ{99‚r…לrQ™yëÁ= 嵿ùý'ÿщ@3%µÖbÆîl“žùU$ñ42Y=âk‘µ¬mµç`¢ž8-œÈüÅ:Yc†'–WXãE,îç@êIì+Òï’ö fµò縴Ôn.ÚÒ+¨^WŽC(mr¼yËœ‘Ðõã2IÕÏâ»[o/Ï×á‹ÍA$~eà]èz0ÉäZ°šé’õìÓU-uîxÆ]G•Î@ä~b¹-µ›mP^Igr<È#ó#Ó…º#°–W!ÄŒH$:çkY¾cÁ«_fÔmoä{[$Š'št†Y"130r M1dfnw| 3‘¶˜%ƺmF¸ÕL+«Hd¸Ú1!IÉà¤UyüWkmåùúü1y¨$̼ ½F<ƒëYwº\©n— '¹Ô¢FžD‘NÖ_ݬ™M ;¬p1É~I•áGiaPðÞI4ØÚ¤+G0 Àp\—]ÛxÜIRPø®ÔO$_„Míñý°n] –ÈÎF9ôÁ«šé¿ˆËgª›˜Ãm/ Æð¦AëÈüëkWû;Y°û5û‹¥½©k Ù ù™9žcÐtèì´ñi,³És=Õ΍ÒͰ«’«„U˜ôÏ=za³ˆµ «(UÖU¹»Ž2劆889þy©µ-Jñµ À¸‘ Ä üëoùéö‡ùÖ…ÿü„n¿ë«ÿ3H†±+lƤç{´k‰ÏÌ뜨ç’6¶GlJ—í÷Ÿó÷?ýü5çn±¬ñÇi¬[G©Fð¤2^¡XÄê³'’Z!·ð |ÝŽÃ[M"uf¿/$¨Ãr€æ,nKm?(ÂȤ`¶XÎÔj—Vˆ_JdU È&9çŒô8?‘§®£z¬]ÍsË’?*ãKÕ¤[›¡çÃtšlIn‘Üpó¡”®òX’Fåʳ2’ÄøÝ]U!ðxŽúÿCº•ü¸Þ;Ö¶S# òO>õœú¥ÄlŠ÷Ò«HÛPˆ,pN<œ~€Ô:Wü‹·ßö“ÿ@‰â;´°þ˽“iŽ ÂÌ ÑÆH0ʼA9aÆsŒÐBú¥ÄlŠ÷Ò«HÛPˆ,pN<œ~€Ñ.©q O,·ÒÇ)gw˜€ u$ç\ÈÔV›H¾Ó£žX’áÖäCu,jPŒ8Y ±ÉFÜ@¡88zÂ^^ÞÜØÚÜý¦â_µ#Æ·²+„0Ê^Ü€ˆ ˜À|üß+0= MRâ% %ô¨¥‚‚Ó2HuêI{šwÛï?çîûøk’ÔtK¹ÒâÜKw=ºµµÊº*òJ²1”ÚJ„Âü¨‚6ã#zËÌQ "h˜.<¾cÛswlc<žsÉêPÚ_ˆïžþ{òÚ8¬Zà9q`ØœôÇãïYój·1¤“Í}$q¨.îe*ª:“èA¥ÈÅ}ÿ`™?ô1YÞ ¥ðÞ©• ör¨.ÁFJ¤ð¹â˜ìüBšŽÿ±k såã‘s¿nzgއò«ê—©hï¥u T•˜‘H#¯PAÜWmªVßìÖ×Ww¢Yâ–¢ybÚFÀãh°’Jñ‘“œVmüZŽŸ¤=½ÅÖËæK‡†·<did`Ñ˜Ô Ù·'ÉŒüP3Ò~ßyÿ?sÿßÃGÛï?çîûøkŠË\]fîig¹5”ô‰çËE.Õa•äļ¡ËIkþ†þ Y£½ŠDùò†iœñÏYp8ùûŸ”c,„u¾!¿²¼±]e[›Èás.Xª±ÁÁÏø× W•?ü…toûÁÿ¡WªÓCAESQEQEQEU]OþAWŸõÁÿôVª®§ÿ «Ïúàÿú ¡òQ^‘Ê}Uà¯ùô?úñ‹ÿAk»Ôox§¶EØ$rR}=èðWüˆúýxÅÿ Šèfÿ–î ó§ñ3¥lqßð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]m6 —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E .¥à-Nò’;»RPçtÐgýŸzïæF#ÔÓh¦0¢Š(¬Kíæ÷_:„s[¬_ÙÒÚmv!·³+Ó¦ÿZ¶è KþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢•…c’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác“Á:ƒÝØÊ.¬¶ÛÝG3þñ²UO8ùzÕ«Ÿ ^Íw4«sfݘeÛ8'é]EX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,rV^ ¿¶Ò®-^êȼ·Íp‘±´¨û½hÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%eàÛûmVâéKbÖà ;‹Ÿ»ÒøCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,qÍà­@Þéó}ªËm½Üs¸ó%Täãåë]¯“ÿM#ÿ¾ª:)Œ“Éÿ¦‘ÿßTy?ôÒ?û꣢€$òé¤÷ÕOý4þú¨è  <ŸúiýõG“ÿM#ÿ¾ª:(O'þšGÿ}QäÿÓHÿ搜ŠK—†ÒÞK‰î"H£f-Ò«jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(“JC$Ò6ØãRÌqœ2j·ÇÿÃ>Ôöøÿç…ïþËÿÄÑöøÿç…ïþËÿÄÕéH¶ù’mÜv¨/Ôã8¼ ÎÔµËm+Ê2\´’çdVðI<Œ2Û#Vm£* c²‚yÛãÿž¿ø/ÿGÛãÿž¿ø/ÿKa¬Zê‚f±¼ *;ÆÄ®Z4‘pz0)"ŒŽjߘÿßo΀)ý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5sÌï·çY³xŽÂ Liò\Ê&ܱ³¤1#¶6£ÊÄs•³w®̹›íñÿÏ ßü—ÿ‰£íñÿÏ ßü—ÿ‰¬Ûoé7RËME,pÈgÓî" $ŒŠˆK ‰–>:á³ÓšÞóûíùÐ?·Çÿ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€)êÿò¾ÿ¯y?ôZRÉåNòmgÚ3µq“ÇAž+7Wÿ-÷ý{Éÿ šÐŸýs~Ê€9Å]N÷[Óî.4ß³Eoæno=_;—¾Ÿ­/‰4›­GìÒZ[Á4‘oSºú{)l}Ù¡¶ü£(Fí9;ÔPƒ.Òk‹ùî ¹ÕÚþÎt¾ £ãKtŸjˆÚA …áƒ*±ÀÀ©màF(*éÐMl°—š'mÚ´ÑO «-ÉØ 90°ÏïHóÜäãçïè  _i7º\7¯¨Ý¥ÕåÜë,’¢m VáÝŽ€°ˆ9aK• ¸Ô¼Ñ5'ñ2ÞÙ˜-âic’KˆîæF*¡C#ÛŒÅ+2©O1ˆ*p3“ÒÑ@¶£áýF[}e­M«Íu«Zj$²²)XE¶U˜)*IºÔ{âùÓ'֭ѵ¸žÎh™‚&™«Ü*• rÌ‚"NAàƒŽÇ“[TPOöKǯ闑>m¬ì.-H–Fy v€©Ëd·6I9Érk3Að}®‡áˆ-~Ãkq¨9mn·ÊÆ;¶Y ²dmRÊv)!@­u4P wá-bëÀº‰,Z\²ØD‘M²:1DØ®¯-¼€qœ¯—Ÿ›‡NóKð=õµ°º¼ž õ±ua(½iÙR(í’}¬FU¤J o ¡Ž8ÝçÑîlüNo,ìP½¾q²\éÏg4“3ÂP\NK ‡>[î–0W;›ë™/¼¬^øWÚ|­dòév¿fšÔȤ**Ê ¶ò À!ãËyŒ`Þ‡EqqøOP·ñe†¡ ‚X­"޶Þη*ǵ‰ õfä|“*ä—*IenÒŠ(¢Š(¢Š(Å_ò-ÝÿÀ?ô5­©?Ö?ÔÖ/Š¿ä[»ÿ€èk[R¬© ÑEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQESÕÿä }ÿ^òè&¡ñr<º-Üq«;±UTd’]p©µùß×¼Ÿú ­ ÿ×7áü¨7Oð펚ïqš¤Àa¹lg®2N+ÆÖQ]}†IàóâO1vO¥>¥o¸íÁh#!Äœ¯ÑA]sÖÑXa¨{ JŸ3•ºÉÝüØÛ»¹ÀiPx‚Æ[ëõŠêØ>£b§NeûFõx-"™žc–F7aÔ¯Í.8¶§âƒIFIUa—SŠ[«jâx|È­¿v Èc7#*e'ba²ÃwEn#×z­ô7·:­«Úo|‹wÁ1(†0ëà&Çï •*kÇÃiñγ«]Øio߯ñ=Ö›¾á¶ÛC†Šrß*‡¢žU¹ÏNÒŠå´‰–Y|[¡mu=¨¼fýþšËçÂ`E*Œyà‘1UQ’ “ŠÈáo…Æ™z÷6r韺þÏ•æá’?5¶,¸DnÇ à¸gÐè .òûÅ?ðž-¤ åéþl~Pds °mS#1X 3æhùTÊ~x<<úÝç‹ì.u8ïO—¥Ü­ÁšÌE½ËIn^Üc|coÊH9‘$œìîè kƺ¦³¦Zyú\ÒÅi·}¸•’3s›Œƒ…(îØÄ6‹oä@f0y±Î²æu“2>ð£=w¸²ßXÛxÍ´-:x®N¨“GºÑâWFŽšXÉŒ‡`RfÊ«ä€v¾à°“JÓ¥ÔâÔä°µ{øWdwM ™Qyà>2ÌÜÜúÕºó‰õ_GáÛIæèM,ò0ÙÎÓ´@(c}‰‚Ûþ_!7.Âåmþ‡-¼rB¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š(  z¿üo¿ëÞOýÖ›(k¼‘ÿÖ¬Í_þ@·ßõï'þ‚kBän’EË ÃRAäv#‘@/5¥ag þ’dÜå‰ÀUÏÜãüôÉñ,úšÜYÛéÒÝë#ÉžÖßjm¥ \|†1¸î#æ Ñã‚jý®¦Y\¥Å½¶ÉS;[ÌcŒŒw>õ>£¥iÚ½ºÛêv·°«oXîaY6È Î çÜÐ%¤x¾öin®$/t¯¶YÀ—©ûž. ¶ÙåÄrÄy“mì «Œ ¨±æò´éæÒÑ!ÕV ¬J\–c “Á2‚€#smRàá†á€ORÖ6ænµ¼ÙVi3;ä]»\ú°Ø˜=FÑè*¼z“Û|­.É>ߟ¶m·AöŒç>g>w7\õ>´…¯Ûø/&´\ÛC,k¹?¾G‚)ƒ`€W‰@Áô÷ÀÁÔ<_=¯‰¦¶UŸÊ¶¿¶ÓÌ"ÊFŽ_Oûkšžñ„ž$¸ñ(º¶µš´ÛÜ4S)•Àrñ"‡!@pß6-Ò˜!k„¸hÌŠÈ’•X‚À «‘ßhô¨-4­:ÂâæâÎÂÖÚk¦ßq$0ª4Í’rä ±É<ŸSë@:ΧªÚxŸL³Ó­’ê9ì”Gó+À¨ûŠ“€d9øK•TàøwÇ·—Ðéòi—WŽðY¥íÜpJO,1¹`#Aæ©mÒ!váwwfZá.$3"²$…FåV °¨ªäwÚ=*¢hzLwv·i¥Ù-ͤBy–ÝÃFÆUpHÀã“@µ÷Œugr?³žÎò+ËE†Øî󧮣ŽEli8p¥‘ÝAqó€UûŸÞ‹ßfÝZêÖ¶‹ ÎåQ+BAš?œbhÁPòø …'ZÏúœ’%ާZ¤ŒŽëª fC¹ Àä©äÇ‘R^èzN¥Å}¥Ù]G$¢gYíÑÃH`rå¶€¹ëŠÉ›Å7ê×/ýÎþ n¾Ð73Ì°ìØ˜ç 2†É\ XåE 7Ç’ê:¡³‡L‚âCk%ȵ³¿G»‹kƾ\ñ8EŠOÞò¥Î 0çÖµ£ù›­`o6UšLÆùn×>¬6&Q´z ¡a ¥– /$¿½¼’8š qtêÞDlT²‚3çb|Òo”sËd2}GSÕµ{ 1WQÐDÐ\Ü;ló7”Ð*Ì©°ùÍž7eGAÖ¦ŸâAooŒëþ›ý¥°¾ÕùðÛ„òn,¾d¥‰fWKã©Ôt­;W·[}NÂÖömëÌ+"†ÁÁ<ûš‘¬mÌÝky²¬Òf0wÈ»v¹õa±0z£ÐP/Ä3Ô°®’÷!™ “Û´n£kˆ¡Ü¯,q¡'ÏFÔó—Q‚m꺿‰ ¸Ð¢‡L²Š{‹ù ž7¾&)T[É"íqm¿.I*¤4xÁVÝ[QøwCŠò[Èôm9.¦mòN¶¨Ûx|–ÆIÞªÙ=À=E\½±´Ô­ÒúÖ «i1¾ãƒ‘•<@?…exŽxn¼'=ż©,2¬o‘°eu,¤GÞ·¤ÿXÿSX¾*ÿ‘nïþÿ¡­mIþ±þ¦€EPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEOWÿ-÷ý{Éÿ š“\¿þ̳žóËó<½¿&ìg$¿G«ÿÈûþ½äÿÐMM¬Ø¦¥o-¤ŽÈ’ÜW®ãò  –š•ÔÄO¥­´*2Ò€ß@KÄž"þÁû2í²O?yóõϲۮÜ|¦M­ûû*¸ä+œü¼ô!£TeHöîÆ~lÖn¥¦Ëå4îŸ,ye©C¹N2 Ȭ‡ çnFà íý’úŹúòÞÞV¾» Úú¶^/²ŸUºÓnã{;¨'Ž-þ}¦H£uó2‘’Ò×-‡d!Kñx³E˜ánœhÖ6{yfß"Æ­D,è7¦ToRH¿„tËM>Ko>+fºµ¹T†ÜB#PH'n-Ó9É9<óÄø&ÅaHZòöHí¢Xl2 ¢º:ˆðƒvOï7ÿ«Î[vâ7­ïm†7Ii(†a‚6¹Ep9ëòºž=~µÎ¯‹&›Å÷: éíçHŠOªîdSJΈÎàŸâÚy­¢hV^³{[q0c½·*,h¿ErKL áù"Önu mkQ·K©Òâ{DX Nʈ˜ËF\±¨8aß  ŸðœhíªGkÛâ6²Ü´»\âDòÓneY ¸FL†+…ÜzNž1Ѥ‰™õ¤YLMn4ëƒ8`ªÄ˜¶oÚ‘üÛqó¯<Š¡/íá…ZÖyîd·µ6––÷“ Pï‰Õ  Œ¾Rí——S†%ö¨bøoi}m#ê¿%ÛÝ<éûÁä«Gl›î£mùòQ·~è8ÎࢠMº¾ŽÒÖg¹y8–Þ– ï¥PQIRÀʈgN¹çðuƒëÖš¨•Óìj‘Û[Ű¢ŒWXĪNÐø9 ‚¤©èh¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5­©?Ö?ÔÖ/Š¿ä[»ÿ€èk[R¬© ÑEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQE^æic{xà‰$’y îP +6rþï¥XªóÈGLÿ¯†ÿÑRPKþxXà[ñº1©Ï ü oþ7VÑ+Û@öÍV[»yogµ‰Ùä€)íÀ²@÷à~¢€+ÝÛêWVSÛùV æÆÉ»íLq‘Œÿ«ª·Z>£wu$íw*9Ù¦UWØ V›ÄÌž)2[Úä2®ÉoV+™APÆHa#F òÛù$ 4z7Ž4}WD·Ôo!¤µŽá¢Úí’ÛAHÛhó™]Ö2$9 @bOÿýÿüÿ\ÿàÙ¿øÍðßÿÏõÏþ ›ÿŒÕ»MÔn#··™þÐë#ù2ÂñH¡ nÜ®CûØÎC‚2jåí¾¥§Û_ZIæ[\ijDø#r0Gu  øGïÿçúçÿÍÿÆhÿ„~ÿþ®ðlßüf¨Âcq‡»y¦Á“uöi ¸7£äŠic@Ó£c6ºü¬  kÿÂI§?í¨/dŒKä¼qØNóFøÝ‡ˆ!tãæQÃ)þ! ÿðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍI‹t)ï¾Ç ’˺4-3F¦EVt€mPá×a'NÕÉÞ#ƒÄv·Cmu†ya"{yc,Ž€‚è ’%FJ“´ó@ÿÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã5'ˆõmGGµ·¸±°µ»I'ŠÝÄ÷m V–DÄo‘—ç¦ã4Eâ4_fÜÜ$z”mW1F®ñÁ+ª²«I´x[nóÀù?øGïÿçúçÿÍÿÆhÿ„~ÿþ®ðlßüf­ÚkP] U¾Í:v‚EH¥2ecW?!@Iù¸Ù¸0ÚA9À¨þ2ÐãòU®gÍæyvßd›Ï%6n_'fýÀH·nvØÚ  þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ©%ñf‹Ä1 §˜LÑ"Íoo$І”¨Œ4¨¥¶ô 8u=$¶ñãYmB$µM6óìÙŽF—Í n„ ïo5W`îàÈ ÿá¿ÿŸëŸü7ÿ£þûÿùþ¹ÿÁ³ñšø¯Hé(’éÝ™“ìñÙL× TwBÌP!ÉP0éýåÎÕ`ÿÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã5Ñ×b³>ÜûfªZ^Cl·6ìÍ  Ì1œ3€2?á¿ÿŸëŸü7ÿ£þûÿùþ¹ÿÁ³ñšÉÇéö)ïg·²ŽÚ)mÒ]ºŠ™-³$xºB Ã"‡$¯Ì3‚ã⽠[¤¢K§vfO³Çe3\)P ÝO1@ ‡%@ç÷— ÿÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã5mÿ‘fÇèÿú1«Z€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ*¹þËe=ÆÝÞTlûsŒàg5]L{}îÛÿÒcRÿžøßün€,QUñ©Ï ü oþ7F5/ùáaÿmÿÆèÅW›þB:gý|7þŠ’Œj_óÂÃÿÛÿÔ3[êr˪YFavpVè“Ê2ñ˜ñüYä”bíne´x­nÞF#÷†=øÐЧ¦i“Y\ÝÜ\^}¦[››Ê  ŽÇßôªðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍX¼ÐR÷PY濽6ÞlsµŽõ0¼‘•dnTºá‘ÕeRW$ͺ£x7Nk.×κL³–Ò]˵¡tü¸.­om<åH8§ÿÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã4¾ ±ŸlÓ^^É}晞ô² $Ý%BùLäaG0Œä3†Þ±²·ÓtûkHü»kh–“$íE“É൑ÿýÿüÿ\ÿàÙ¿øÍðßÿÏõÏþ ›ÿŒÐ!ð…´V°ÚGQ’ÎÙ 6–í"·X¤I Æ‹—,Ø 11êþÓu–¹iæœ5Å×Úœá™yI˧Ý~b¥†[ gÿ„~ÿþ®ðlßüføGïÿçúçÿÍÿÆhLJü=iá»´³’y#o+&fþîáþ”Ÿr~ú~‹y<ðÜݤi-šAåDÒ>ùK9-–-·$.ÐH5?á¿ÿŸëŸü7ÿ£þûÿùþ¹ÿÁ³ñšÓÔtèuKT·Q'†à ÑH²(ä2ƒ>ÙéEž •ÕýÄlåï§#„i1õÏ$Ögü#÷ÿóýsÿƒfÿã4Â?ÿ?×?ø6oþ3@ð´·Ú…ìÑêò‰eWòÀ‰‚ª  ÊíDR¯¸0\0;›tðF›á»¿´ÚM;Éûî pÆŸ¼†ÂE(ÿtèV'9âøGïÿçúçÿÍÿÆhÿ„~ÿþ®ðlßüf€1_ÀòEq§ZZ„[ 6³ar/fI[˜È[¨ò¦såó R_”ùc:óø>ÎîßZ·½»ºº‡V.dŽeˆ¬R P…@8ø}Àì-¹ÿðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍP—áö—&‰o¤¬¾U´R´ÎO²ÄÒ²  ò‚ª§s]L­½¼p!r‘¨E2;;9f$±÷$“Þ±á¿ÿŸëŸü7ÿ£þûÿùþ¹ÿÁ³ñšÒÔ Ô.LBÓP[D@r<€å‰>¤ÿžJ°þÌÓa³ó<Ï/?>Üg$žŸfÿÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã4Æð…´ÓG%Þ£¨Ý3mçÈ„À©4sl 3‚ÐÄ ³a~ð$’û A&£q©Zê¶WÓÊÒ4ðylB´q# Œ»O‘霯EðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍA4H.í¦‚9ãŽßÊÙ””ýØŒ.IË˽±ëÿ,ûÒÚÔtèuKT·Q'†à ÑH²(ä2ƒ>ÙéYŸðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍIâ? ÙøšÞo$t±eÄqJ§#¤¨èO£mÜ9€Ì g„-´m–£¨ÅkÂ$·Y-ÃEFŽì~vÇ!YTíåH, ÿá¿ÿŸëŸü7ÿ£þûÿùþ¹ÿÁ³ñš¡aðóGÒí/­ìÙÖî!u³µ/Yæ0ÆdVæï'Îy­­ D¶ðþ˜¶6®ïbùeD>ˆŠ¨ƒÙTrNX’jÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã4cÂÿò,ØýÿF5kV}•îŸc¤Úâ÷ŒIÉ'´CÖ¬cRÿžøßün€,QUñ©Ï ü oþ7F5/ùáaÿmÿÆèÅ_—üð°ÿÀ¶ÿãuÌ÷¶–ò\NšzEË1»n?ò]¢ CÿS| þT´QEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FOWÿ-÷ý{Éÿ š¹Tõùß×¼Ÿú   ÿ×7áüª:’õÍø*Ž€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3»dÞ"3½àçr«”Œ)Œ-Ó~%C·¨€Ë:ÁºÒ5i¼Uk«E©ÙGmoÀ¶íbìæ9&|¿šìÄ0vàgÕ½@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@cø«þE»¿øþ†µ±Xþ*ÿ‘nïþÿ¡­mIþ±þ¦›N“ýcýM6€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEH©êÿò¾ÿ¯y?ôW*ž¯ÿ [ïú÷“ÿA4¯¯%–¬öqØ^ÞII=ÁµEo"6,ˆ,ó±þX÷Êxåršv½§j“=¼·HÓlî¢]±Lгí›Ðàý:)š®{&½6¡§jIf÷0Gms¾ÛÍmˆ]”Äwû×å•ÇÝùx!¨Eá‚(½çÙåT»Ôžx`Pîó,ê:änQ2€Ì>XÁÀÒ‡ÄZÅ™¼ƒYÓ¥µ ÈgK¤d ¨]†àq€±€'¥A7‹485}?L}JÔM¨@n-›ÏM².äTœ’åþ\»kc¥`éßäƒY‡QÔu4¾0Ï ëÅ3ŒÄ— ¿4ÓJÀ†¸ 0p œÖõþ‚ÒÞZÝé—I§ÍÏ·W&tyF@E`Ä0Él«g€ 5ïÚxzÛιŽyu4Å P̱ÅHîA# ®zn‘Æê"×V;K‹½^Æ}Ú ¹›QžÝPî8ûÉ#Î8ûê÷~ûf‰®YÍwºïVŠx^ìÇ’‘¶ñÏÝ_w7Ø’÷Ãë¢>¡y*¼¢V‘‘ÏC¸DÑ¿aʺŸ”d•Ê òkšL?bóuK$û~>ǺáÚ3Œy|üùܽ3ÔzÔ‘êºtºœºdwö¯ ï’ÕfS*/”Î@ù—’;Zå´ÿ]é¶R[Å«Àÿk‰à¿iìÌÞdm4Òüžd†ÿH'š H<†·§x2;>¤×=ºÏ5Õ¼$ù†iKly¾V?y Dd“’@:+»ëK„·—P[Æwa¦ ùT¹äú*³e'µF5]9­ÞáoíL)Ý<‚eÚ°°%d'8B¶¡Ú}*¾«£C«]i2ϰ¦Ÿyö±Æ;äEëЂáç•QÏ]øâ[-VÖ×Yû2ê±\CtÿeÛiå@™l. ëdÀ ¾Yæ€7¯Ñåy¸OÞù™òöóónÚÛq×iÆqDZÖ™>·q£E}êVñ,Ó[ùÑ¡#òún\ãpÎN‘à½?M¹šic‚çϰ[9VXÙ÷fId˜î‘ŠÈÒä©'Úý½Ž§Н¯¥¸²m6kXb†$·ÄáÕœÒg•ùŽû\Á.JöÂÛRñ­µ½Ü^dFÓ%wÈ-èjÿü#ýò<ŸãPùíëÈÿ6«ßÚúoý-?ïòÿR>ÐEâ[ÿeýèžMßh“¥:ÿ·úT¿ðŒh?ô ÿÈò/ö‹êi"Þ[´qÚ˽„ªBåâÆNx©ÿµôßúZßåÿåo´ý3ûZæÒ ‰-Âsæ»,3ÜñÛõü"þɱÿžøûX–h§ñ¥$2$‘·•†F“ÔT´„RþɱÿžøûÙ6?óÃÿoñ«´RKû&Çþxãíþ4dØÿÏü}¿Æ®Ñ@¿²lç‡þ>ßãGöMüðÿÇÛüjíKû&Çþxãíþ4dØÿÏü}¿Æ®Ñ@¿²lç‡þ>ßãGöMüðÿÇÛüjíKû&Çþxãíþ4dØÿÏü}¿Æ®Ñ@¿²lç‡þ>ßãGöMüðÿÇÛüjíKû&Çþxãíþ4dØÿÏü}¿Æ®Ñ@¿²lç‡þ>ßãGöMüðÿÇÛüjíKû&Çþxãíþ5µ­YÛØø)£¶‰cVŽ7`;±eÉ'½R­OÿÈžë„?úÓCFäŸëêi´é?Ö?ÔÓiŒ(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# §«ÿÈûþ½äÿÐM\ªz¿üo¿ëÞOýЄÿë›ðþUI?úæü?•G@Q@Q@Q@Q@Q@Q@þÅl×Ïy$K$­‘‡P™$Œ{çŸÿ^Oìí7þVø¿áV(  ÈÛÃòêréÉg¦µäK½âë8Ïl!#¨„à:æßöv›ÿ@«ü_ð¬k_M§iÐØZ^O¨[€šf›ÍÞ®zl_:B1ÉÜ ãa2t4v–QgËÓìÓ=v£5'•mÿ>vß÷èRÑ@ å[Ï·ýú‰§x›@Õ-ÚæÞÜ¥ªÁö“ss¦Ëo•€w $ER0sצO@kr¸KO ¬+–´H‘½¬²Mö¹"–)!’`ø`©äí ½ÈIU×ÊÊãOÔ-êÖÞÙâ|à˜vAÁVeXAR@"¬yVßóçmÿ~…fèútÖBòæéÞ_Ïö™Ö"Lq·–‘…R@$FN7œ(!F'•mÿ>vß÷èTsµ­¼—YÅ J^I$EUE$’xõ-TÔãš[öv·s+#Ç Ô…#,¬Á‚ÜÓÈ:€ Ï­è1隬†Í,nÕ^»•—p8# ËGʪÌp‘<—úLZœZs¥šÞJ»Ò#ÉãØÈHG#!æ‘áýrÇHÑw:OJ³:rbWš!eˆ4‡åF%`¼‚]Ãvô}§ƒ?³â‡MµºÎ’%´¸Ê3?™l±,`ío""N26¸Þ `g•mÿ>vß÷èQå[Ï·ýú´PyVßóçmÿ~…dKâÅi}uþ,V7Kgp`¶iJÎJ f̈0 àœuÃÛøkW’ÏX³¹Ó4‹{[¹áº·ŠÖþ`#hRHÁHã(?qê~RGÈÀ`€tðhK§ýºxVÖ7ÊÍ化ì[‰Û"†Ú,[X’±þU·üùÛß¡\†Ÿá}GNu¿²u•Ò´©‚n{KXe† €„ð‰pA.ëÁo0tºV‘¤Yi–ìí œÛÆÒXª(PNÀô  ^U·üùÛß¡G•mÿ>vß÷èRÑ@pëZ$ú™ÓãŠ6æXÚ0‰Ýs¹R»Æ*¬HØÙ+`[ÐfÓ%Ôb6rZÄÛÒıÆÐªX¶å(;á\†\áÜøwTÖo¯âÖííd³¹[‹xç‡Q“u¼.¬Šc€Å°Iµˆ.X·Îø;p‚y<9¨Ï|ºÜóÚ¶±FaŽ0ÉnëÌ€6rÀ¸¸”äga(0û ¤¬n­ã¸·‚ÎXePñÉ++©Áw¬ß6|5rª…Q€õ«>›ý•§ c/#K,ò¸]¡¤–F‘öŒœ.ç8’'©­â¯ùîÿàúÐÔŸëêi´é?Ö?ÔÓh¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ*¦¨&“zˆ¥ pª£$§Vè  ·º¨¼”[èþt ádk¸×w¾9ÅAöíoþ€+ÿÑÖµ“öíoþ€+ÿÑÑöíoþ€+ÿÑÖµ“öíoþ€+ÿÑÑöíoþ€+ÿÑÖµ“öíoþ€+ÿÑÑöíoþ€+ÿÑÖµ“öíoþ€+ÿÑÑöíoþ€+ÿÑÖµƒ>¹¨[8K2Ú'#!dÔ¢S^j/øInçÊËÿÿn[1]Vøƒƒöx?ô)j;/麔I-Ž­eu’˜Q 4w”[h-ޏ  øInçÊËÿÿð’ÜÿÏ•—þ !ÿéüù?½ú <ù?½ú æ?á%¹ÿŸ+/üCþ4ÂKsÿ>V_ø4‡ük¤‚ø][Çqo:K ª9#!•ÔŒ‚à‚;Öeߌt+ DWž Òíä;°³]Ƈåb‡‚{2²Ÿu#µgÂKsÿ>V_ø4‡ühÿ„–çþ|¬¿ðiø×OçÉýïÐQçÉýïÐP1ÿ -ÏüùYàÒñ£þ[Ÿùò²ÿÁ¤?ã]?Ÿ'÷¿AU#×,åÔåÓ#Ôm^þß%ªÊ¦T^9)Ô™y#¸õ  ?øInçÊËÿÿð’ÜÿÏ•—þ !ÿÜMrÎK{»„ÔmZ6t¹‘eR°2 ¸sÑJŽ ôïV ¾VñÜ[Î’Ã*‡ŽHÈeu# ‚8 ŽôÍÿÂKsÿ>V_ø4‡ühÿ„–çþ|¬¿ðiø×OçÉýïÐS ¾VñÜ[Î’Ã*‡ŽHÈeu# ‚8 ŽôÍÿÂKsÿ>V_ø4‡ühÿ„–çþ|¬¿ðiøÖÆ«©^ÚÇl-LFYîæ”nÏ¥29|C3Ì‘\èîð¾ÉUYÉFÚ èv²œÄô•ÿ -ÏüùYàÒñ£þ[Ÿùò²ÿÁ¤?ã[;|Oýý+ÿÿ 6øŸûúWþ?þÿ -ÏüùYàÒñ©`×5 —)o¦[Jàd¬z”LqëÅi7ü$Ê¥‹éx?ÇPØ]Ý\jú¤WoXE¸@eœsý=(?·kô_üŽ·kô_ü޵¨  Ÿ·kô_üŽ·kô_ü޵¨  Ÿ·kô_üŽ·kô_ü޵¨  Ÿ·kô_üŽ·kô_ü޵¨  Ÿ·kô_üŽ©j£[ÔôÙ¬ÿ±–?3?Û#8Á§á]ç9‘ˆõ4Ú( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š([Ó¦Õô¿i–ì‹5æ”-ãi ÄÊ À'>••¨é÷þ"Ô4»†Ò.´¤†ð‰Œð­ËD ¸R362…[xó€˜ z)d¹‚êöKk6¸w†UÞ¨B~fôtÏQUþÝ­ÿÐð::ãµÛÿeA ÓÝZµÐ¶•.·6­äy¹¸Xyb#¹ÄÄå·(9ßÑi:Ù[©õ=CTó庻Q¼;³Ë'–Šü¿)V 1"𻂕íÚßýWÿ££íÚßýWÿ£  išÞá» Iíš?.Ú{é¯ÁM±$±#3(ŠŠq‚ä˜ÀRݯ†§´ñ\·6WWV:rYÚÆ#‹—YnA!‘YÉýà%‹±É6’Ö÷PûEĪ÷la8eŒ'þ>!å‰zŸ·kô_üŽ·kô_üŽ€áûkÛMÒFáçº K´‹µ”J¡ùß%A ’ìNÜ–$æ¹è4mQ®í, ¼öÑÙê—·ÿÚ(ñeœ\ì‚Ky‹ö…Îô ò7'ÛßnÖÿè¿ønÖÿè¿ørÐx?SÀ=‡Úî“U´ß=ÂÛoŠ8dŒ˜ƒlÃ$;®wGVƒoYÓ5‹}SK]& Ûˆ Ä’7˜A$…Ë3IåMÜÇ,äÅ*ó•LîVÞûv·ÿ@ÿÀèèûv·ÿ@ÿÀèè°Ñ¼I/‹o_Q¼º[iòñ;å…²#H¸ýÛ¨(w¬(ÙŒüç%ž¢è—zw½KD¹ÑõK"À@c·ÔKÍu" W0å›d_*•^¤n/á~·íÚßýWÿ££íÚßýWÿ£ î—e¦„¾TñbêÜywy’'·6æÎã“Üõ¤ðÖ}¦^Û5ÊDZ²k)gFËjn]_í:‚óódïžnß<¸“Wº0™4õ2 Wñ˜gΧû~½ÿ@fÿÁ„tÓÑ\ÇÛõïú7þ #£íú÷ý›ÿÐI7ú‰?Ý?ʹ­/þCÚßÖßÿ@4ýxŒéþ:]Þõou+»ËQmöƒÄ¬ŸuH<Ãó  j(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š(  [jíu+›;]3ígÛ¹üðŸxdpGÖµá3PÜD°ÌFZ5}Û}³š‚ÚÂ/¯.Ü4rS#8 p?¯éøÜ‘÷¹lc5…?oígÏnM9m{ùߦû[æ7khq1øý>Å=ìööQÛE-ºK·QS% –dHTdPä•ù†cpX`´|W¤ t”ItîÌÉöxì¦k…*;¡ æ(ä¨tþòæð…´ÓG%Þ£¨Ý3mçÈ„À©4sl 3‚ÐÄ ³a~ð$’û A&£q©Zê¶WÓÊÒ4ðylB´q# Œ»O‘霯En"ÚxƒJ–ÞKˆ¯RHcžc$`²™%˜À `†GÈÈùºðpkÚÂèZWÛÞ™ðBÉflI*GÄoÎÐ2qÖ³bð&‰Ý´ÐGçD±Ô.[ìò\ØC|Ð(iLk&Ы•³3mQŒ¹(8 H|Y¢¥ºL÷Ofed’ÞD’ iP®èB]¨¤B/‡úö,1¼v-qK„Û4ˆT¤Î¥v´€¨ÉÆ£†@’×Ám¥´6sOi$>b¼ö‘Ãnó$…K£ãUòã+ƒ 9$[CÔ¿¶t ;Tò¼Ÿ¶ÚÅqånݳz†Æp3Œã8›¨x–k}[ÕììRâÛMYJù³˜¼ö„°˜ + T¨'ï0<ö¶•§C¤iZe»;Cgvñ´„*Š€p=*…ÿ†­¯´ÍWNK««[mMJÌÂϘÈHRàüݳ–33Äæ+yúÙ-ï!ÔaÓ¥HÞIbH#e"Aq¶Uå•Fÿ— ÆÛx›G]ZM,Ýÿ¥Å*Ã*ùo¶'uV@í«»z…ÉŽTd‚K Gq¦=¡Õµš[ȯ§¼_'ÍšXölÈ1ìyqpª3°g9lëYéÐÙ]_ÜFÎ^úqq b0F‘àqÓ¯\òMdèþ0°Õ4ù¯$ŠêÑ#¼6Ÿ¿µ™1œÃ Éb gal61Võ ~ÞÊÚöéW΃M—n¢A!­ÓËŸ èÄМe€SRëà ¶·Ëi+Ê&f–+;‰Y`ÚA+•)‡Wg„„±ŽP•5ô ,uå½ê$1^Þ}ªâÎÞf–7$Œ¤’:†”1A#’bÄ6à[pS\µ¯Šî`}RM~×NÓ,téãµ–å/žQ渉—ƒ˜™Abx äcšêk&oZMöÍÒN>×ü˜aÄù;@ãîŸ!3ß“ÈãËâkc Ô,äKy™I š6ŽGeH» FpÀáAÜœ€ÀÕ»­bÎËP†ÊàÏ“mÙ!·“É˪¦]»‰à)`I ÈÌzæŽ5ËíZúêÌ$ñ\ -„{‹FÁÔêÕOOá²n«à7W×íõ‰æg‚XeP#…þhØ2€ïH‹•Te“Œ³=§Œô ëCum¾)eGòdr’#Êþñƒ2¡TÉÁH @¦OâÈÅnôøtMFÞÂé.R[Y!2´jGL’<ØÛA<ö1ÜøFÝ4› kOßI¦Ø}†Ùn\…tÝ d²É'îl‹÷ Üà ©eàÉ›Hº¶º¿º²’çQP"ÚèÝ4mÆL·Ìãt*ü¨Ç ÊŽ@7f×ôØ51§É3‰·,lÂ1#¶6£ÊÄs•³w®̹“MÖ,õ4ÙÞ8ñ‰ZÞDŽ@s†ÙBȧÜ„ŒsÈÎlÞ Ò'ñHñÂu¹du{xd "¨U}î†E *à#¨ÊƒŒ–Ëô? Úèz…Ýò]OqsuþµÞ("ÞIÉfÆØŸâ}ÄdàÍ ê(¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( $lùÚ3Šk|²É]à+‘pqøÈÔWW[ÙÈm­Zæf ,aÂ}I&³4ˆo´µËËO³}£ÊÚžb¿ÝGáùÐÅAc{o©iö×Ö’y–×1,Ñ>ÜŒ‘Ák™ºðî¡7!Öá†É"jùòȲɷn*4;Ó9 ™T¼«ÊÙ¶Þ¹±Ñ´ËKFµI#Ó’ D­ü¨ð0I‚Z2±ÍÌÄ—Jåh¿¢¸{o k6ßéͧXÊ(M>&ޜ۳Gl9¶9Â. ðÉOŸ©ÐôßìmNÒüß;ìV±[ù»vïØ¡sŒœgÆM_¨-ïm†7Ii(†a‚6¹Ep9ëòºž=~µçú_ÃÝJÊÖùf¼Ifu 2 MD,Šïö€+eÂ%ÚbÒgvNè.|+&™ ­mk$7’O²i“j– ¨a8uò™QÀpÂoTEy®ƒàRÞ÷C¼½›gÙ­m•–!5«E +B§Év1³#nÛ*$q´ä—íõý:mWFšÒ@ìѹI 2««4N@?#…(ÜðÝÃÉá–·¶'DÐf·¥?Ø’Jÿcˆ¸)1°Þ<·éß¿}Í%½ÁQi÷]j’ÿh_ `x/ZGóG—o lÜŸ‘£mØ'z°àu´Wž/ÃÛ»XØXÜAm:ékm¨HŽOÚåW”1emÑíŽhÆõ`©&ÊÕ'áòE.Ÿý©ÅuæÙ<Šð«ÈÐlUDŠ(Ìx…œ©A‡mØ'æÝ­½¼p!r‘¨E2;;9f$±÷$“Þ¼×Þ Õ?á°­¤ŸÙÐ,ñ1=ùÝ žUÈ`J…XÞ®6ÊøU_ÝJše¸r *|ˆÎrÄ(àq“ÉèIÀÔ•ÃÏáMDh+®Ÿ¤$Ë«[êY ™mìV#+³–1±8Eæw냺ÝÇ„^M[QÕSÈÓj–·6Ó—mÐÀ‹n²ªñò3¬r)Û÷ÁPǦ³½·¿…¦¶“Ìe’pGϲ8çÑ•‡áÅO\< ›MÒµ7OÓt„¶»iZ&0I>ùKªÈDlª‘+2+"¸À!W*w¼+¥ÝhÚ V7Kj†6b‘Û*…E'8%#Xä“‘u‚̵EPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEbx—İ[ÚÞZZ_m¼\ § än±€qžùÞ€6è¬Ï\\Úè7sYÈépª4vï3d8TW9çïl`¿x«AäôøuÝcQÑ&’}FÅã³¾Ž{é-ÔÈÀËnT.øcNÒ>xA! x’€;ú+„±ÕüMu5„×Q^Û^ÍöF bE«Déä¡1È…§Â™þíÖÏÏ{ÃZˆïnì!Õ,çmìod‘Übp1ó‹¥ÂäaU¾ëÆH[ErÞ2²ºš]ö ÍFÞ+Æ’v°f‘U ‘„1»1ÜʸðìHà2Á>¥®¶¼¡cÔ`vžÜAbmUíÞÙ„fg–eV "f|*äÆ˜VÝó€vW5¿Ik§@¶šŠM·T¸6CàIn²´CoÎéN˵J9ÆÑ& ‰ µÖ5ML’GTŠÙ-oc…Æœ‘NPµ© µ”*±up D¹Tl)âBÝÑ^y§ë4¾×4¿´Û}Ž9¢¶‘àhdXJ4HÓnýÃí1•T4Ñò©•=^LJŸ[¼ñ}…Χéòô»•¸3Yˆ£·¹i-ËÃŒoŒmùI $“€ÝËxÊÊêitKØ/5xl¯IÚšEV‚DÆìÇs*àñ#€Ë&œ5ûýbþæk¹ìm ºˆ[ÙKkß‚;‚wa™Â”l+†É ¥¢¸û[ëØañ‡•£$ÑÞ¶“ì^K²˜c]ÊÆ,J•À!dm¨¼>T6fƒ{âíjîK›«Û DûH{³eûÙ‹fŒ†–Ô6é&\ù@F$y€Ðè¯8“]ñ4‰¦ßN×VåçÓ¢¸†Ñmüˆ Æ69Ö\βfGÀ^´g®ãW[ëo¶…§OÉÕh÷ZïCÍ»~1»zòMK‹ÍTx¥á3j1 ž%µ·†ÄIm<SÌ’IJüŽ ”cÌSò!ùÀ:š+Ï4Câ=ºU»‹Ûúæ‰-B)cXQ~VmÛ]Ùƒ ŒGbË2h7¾.֮ᴹº½°´O´‡»6_½(¶hÈi`Cn’eÏ”Ta‚G˜=ŠãÒ×R°ñé½¹¹ÔnîÎÖ¥ª}Ý ¢MÄ©1"ï ÒK2‚ø ; (¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ +7_ºšËD¸¸·}’¦Ý­€q–¿Ö—N´ÔD-ÖªÓÆƒýX$ú‘ÍaSJXQ“÷§{.öÕÿLi6®hÑXºæ¼ÚMÄ0Ej“»A5ܦ[……RŠ fßûÅÀb«×.¸çÂ)Ö5½6̾—ö…Š+U¼¼ûB#HòÛÃ)dpeËW»ÉØ7ÚQ\ZøüiC§ïŽYc—4¾\Ñ5ÄPÜñ*ŸõèÃË2)ù‡Ê[{B×íü@—“Z.m¡–5Š\Ÿß#ÁÁ°@+Ä `ú{àkQ\•ϾÉâiô©tÿÝGu¸&Ë6án Ù´cyÆã$< Ði^;ºÕ­'º·ðõëDm~ÕjÂ)ÀtÊà9h”nÆÄFl…}»ˆPà¥ÅÇâZûTÒ¡±²‚Içµ»76o3ÄÉÛí24‘,«òHp<¼Ÿ1N6üà²ø‚5=FÖ; ök)¾Îo&Rñ™£Iü±´[UeBÅ¥R0Ø ¸´¢¸ýÅwZωôË%-ìîô™uãY–FxÙ᳌G¤Êò¼ðÎAÛľ&“B¸³´¶ÓÞòêéd‘T,ÅU#(Ÿ&)[9‘qòã®X­&•§K©Å©Éaj÷ð®Èîš2¢óÀ|d™¸¹õ«uÃê>5ºtµ6–Ogš…“µÓªN’La•£0°éäÈTŃg嗉Г:5«“• ·½inas41,w¬{¢}ÓÊ»ÈØà d¿¢¸óã-Lé vžºó¼ö†E’+‘† ¸·3wc&%\£‚ßwYðÝ[Çqo*K ª9#`ÊêFApAèJ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( ç·Šê#ñ¬‘’ VèpAõäTí+²à¶GÒ¨j·ÿÙšlמ_™åãäÝŒä×ñ¨¬/5+©ˆŸK[hTe¤7¾€+9U§¨JI7²êí½»Øve««Kï'ív°\y¬Ñy±‡òä^޹èÃ'r(´±´°ˆÅgk¼gnV•B¢ª¨öP;U}KX³Ò¼¡rgi%ÎÈ­íäžFm‘«6Ñ•±€YA<ŒÇ6¿¦Á©>IœM¹cf¹‰±µP6#œ®˜½p>e΂ðî‡ÅÝÂhÚrÍx®—2-ª\åÜeƒ õïWá‚t)Ig*ŠbYÉ$“Ü’k&ÛÄ eµ’Õ4Ûϳf9_44qºƒ½¼Õ]€»€["ƒâ½ [¤¢K§vfO³Çe3\)P ÝO1@ ‡%@ç÷— mchþfëXÍ•f“1ƒ¾E۵ϫ ‰ƒÔm‚©·‡t6KÄmN)|ÁîÔÚ¦.ÀÉÇÌA$ä瓚©iâ«;ßI£Áò(µ†æ+¨¡‘áH$?|.À»PÛ°ÅŠŽTŠ×¼½·°…f¹“Ë¥ŽpOÏ#ª ãÕ™GãÍGi¥iÚzB–V¶ÉºD°Â¨#W!˜. ©Ôi¡é1ÝÚݦ—d·6‘mæ[t `UÁ#ŽMA}â;Mʯ¾D¿‚Â@c“jI&Â*–EÁ8RHRËž#Äp?‹n|>m®„°ÁÂao)‹ù™¶mPc [ IQÊ‘@íô­:Îáî-¬-`šFwy"…U™œ©rH%Š.O}£=Ž•§jöëo©ØZÞ­½c¹…dPØ# 0#8'ŸsYžñ^Ÿâ]>ÒhdóÚ¥Á‡ Td ဲlf Ås´à6 Å[Ôõý7G¸·‚úgInÞ%H^MÁJƒ÷AÁ%Ñ@êÌÊ£$@&Ò´ë‹Áy=…¬·AUï ³…W£qÀpÄÖ¨[øjÚ;‡’òêëRO!íbŠø¤‹.W||(.bd.Ço^[2híw¼w~o›³lñFï.E3cV`Ë…, Þ˜räohëiitnÿuykö»r#re1´c%‰–0‰`&€ |-áéí-í&Ðt¹-­·y½œe"ÜrÛTŒ.O'kZ²eñ& ¥½Ã‹ßôÞ\Âs9 pÌa 昨2óó éA<7VñÜ[Ê’Ã*‡ŽHØ2º‘AGz’Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±BÎÎ íšyÚéäiæ-ÜŠ0ØSÿgÙú]ÿàlßüUHËUìû?K¿ü ›ÿŠ£û>ÏÒïÿfÿâ¨Å_û>ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øª±Ed]Éakx-E¦«<¦?3\ÊØ\ãûõŸmÿ@}þþMÿÅÐ݉çÛÐ_ÿ¿“ñtyößô×ÿïäßü]mÑXñIk,ÉÒõ¸÷o’yUGÔ—­ìû?K¿ü ›ÿŠ  Uìû?K¿ü ›ÿŠ£û>ÏÒïÿfÿâ¨Å_û>ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øªn¥bš•‹ÚHì‰!]Åzà0'•] £*G·v3ófªgÙú]ÿàlßüUÙö~—ø7ÿYÊ”%%9E6¶}U÷·kŽìÍñ†àñ-¼÷W/11,[[̬ØÀ$M€@ÎÇÞ=j ð.Œ¾!‹Yò·ÏÂDñE9wDŽe‘PÀ*}×®z–'wû>ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øªÐF4þ³»·Ö­ïnէK™#™b+ˆ!@Ž>p;AËnŽ×ÁVZ}¥´zmÜú}Ì`û]¥½´o"ÈT¸dy|ùqòÝŽzçwû>ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øª¢|?n5 {¸®¯ahâŠUg'í -‘›.v³1á†íÄ>áÅ[ÔôèuKµ™d‘$Œ€ÑÈŒd•eS‚8ä‘Oþϳô»ÿÀÙ¿øª?³ìý.ÿð6oþ*€0‚lcÑ—ey{eº†çÌ…‘Ÿ0ì/ÎŒ6¨Š 8ÉòÆâIbÚW,3êé©-ÍÔmD™!*Ü,lÍsÀ+;)]ÛˆmËÅ[þϳô»ÿÀÙ¿øª?³ìý.ÿð6oþ*€(éÞ´Ó²|™'oì»°‡{º3åd¶-û•éÉ㦨hVZ¦£i{v®ïj¥c@Ø\ù°Ê㜇çA5oû>ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øªÂ²ðM„V¶ðÞ^ýг³Ú³!IäQc‘ÎÍᇕ ʧ`ÊòÙŒxÍ$z–¢¨–o§ÀŒb‘!¶cò‚ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øªåçøo¢Ï¦ZY»96­#G+[Û8Pûw(‰¢0 ;ü‘©È'9g-ÖA6¶ñÛÛÄ‘C„Ž8Ô*¢€jû>ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øª±EWþϳô»ÿÀÙ¿øª?³ìý.ÿð6oþ*€,QUÿ³ìý.ÿð6oþ*ìû?K¿ü ›ÿŠ  Uìû?K¿ü ›ÿŠ£û>ÏÒïÿfÿâ¨Å_û>ÏÒïÿfÿâ¨þϳô»ÿÀÙ¿øª±EWþϳô»ÿÀÙ¿øª?³ìý.ÿð6oþ*€,QUÿ³ìý.ÿð6oþ*ìû?K¿ü ›ÿŠ  Uìû?K¿ü ›ÿŠ£û>ÏÒïÿfÿâ¨Å_û>ÏÒïÿfÿ⪖¢–ÖfÍR;–7QÁ–¾›å y?{ÐgŠ¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJا§ÿÈ8×ÅÇþj±Y+¬iúm”qÝܬnÓÜ0]¥Ž<æçõ7þ­þòÿ…HÍŠ+þ­þòÿ…ð•h¿óûÿŸü(bŠÇÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ ©¬M}oªÏ&œ$óÅ”aš(üÇŽ#:‰]s¬eÙW ’Úßtìx^y§²¹ýì—z\Ó®ebÏ=¾Ä!‹\2*¹åÕU²Û·¶:x‡JZ7ë~›~Ïä…1IŸ½’z}*ÿü&z_üýÇÿ~¤ÿ éh®kþ=/þ~ãÿ¿R…ð™éó÷ýú“ü(vóýZ¾*µdIâý&P^&Ï?øRÂU¢ÿÏïþBð  Š+þ­þòÿ…ð•h¿óûÿŸü(bŠÇÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ Ø¢±ÿá*Ñç÷ÿ!?øQÿ V‹ÿ?¿ù ÿ€6(¬øJ´_ùýÿÈOþÂU¢ÿÏïþBð  Š+þ­þòÿ…ð•h¿óûÿŸü(îªfEé·¸{i¼‰<¹ã€ÎѶӆŒ— ó·¾1Þ¼ò?ͤi3iÌ—1™âî—U:•¾å–ó¦hŽü¢+#Hª¾dDeœ«vßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿá@üšëK/‚o5”°º½¼–?%/TGs‚]­µ$d`Ì `2ûKª†$äÀaù T9í4»µ¿Ó-îRt¸¿ëã£IHàºIØHÊœA&—ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øP1sâ SB¼ñ‹Üê6³KÍw§Ø½´›ö%¬l¯Ÿ0â«!8É» m­/êΓà­vÿPŸK†H­ZXYUU$ÂHubÝdVRKƒ±v€Ú¿ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿá@ÿ|v<9oiwe5¬ð¼ tCù{ncHÓ $ŒýÅ”ÊJò¡¤ÄÚðÛqö++˜ç¿¾°´´‰š9$x>ÐÈÍ#«»ÈØW“¿pûƒsþ­þòÿ…G?ˆô «y-î.XeR’G$ ÊêF ®#µr:§‰¯n|3âø¯µ'ì:\w×QY\ér,®f 1#î?4H,WžEix“Æwú~¯cm¤Áks ÔÍnï,!o™ØNóFÀ_™D¿ëTíÑÓu/ é^i¶»¤—å¸yç‘€Î|››h˹À,ÄNoÿÂU¢ÿÏïþBð øÂy­|¯Ü[ÊñMpñÉdaA‚zŲñn¥4ÛÌ0^YC,my5…¼Ò5ººM˜6rí,r$!¾Pq.LiŒÖçü%Z/üþÿä'ÿ §¨êþÕ-Ö«§!z<^lRFØ#*é†S‚FAބнá½VãYÑÍåÕ¿ÙåûUÌ&Œ Žy#°Ì7apHÎqÅsW^+ñ |÷±ZYOæ]jVVÑG#Hò@.7nyÏÙöÀÉ'paƒnË]ðîŸh–¶·;"Là‘‰$ä³2ÌI$±$’I$“V?á*Ñç÷ÿ!?øP1«øþçûUáðòÚêVè±:˜ãy>Ð|«É]"e8b~̈Cf`C´PêkWîeµ ˜Qo ­ÜðÜÝÄbs„’o,–f@ . ^Ûþ­þòÿ…ð•h¿óûÿŸü(½ñîµö½66¸Ó ¼“È•£D°«•€ŸÌdr©Ç”œJr-Üi¿Úß½þÔûÝ‡ì»ÆÌç1ß{o?Ë»'äLs[þ­þòÿ…ð•h¿óûÿŸü(bŠÇÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ Ø¢±ÿá*Ñç÷ÿ!?øQÿ V‹ÿ?¿ù ÿ€6+'\ÿY¤ØJëMÿ„«EÿŸßü„ÿáToµ­?R»Ò¡´¸ó$]B#c2Gqî(÷Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØÌ°³ìÚGk­Ïq>B]ʃ‰[²°gìvÞ·¿ø7ÿMÓÿä?ëâãÿFµX©Øí½oð>oþ*±ÛzÞÿà|ßüUMECö;o[ßü›ÿŠ£ìvÞ·¿ø7ÿSQ@ýŽÛÖ÷ÿæÿâ¨û·­ïþÍÿÅTÔP?c¶õ½ÿÀù¿øª>Çmë{ÿóñU5Øí½oð>oþ*±ÛzÞÿà|ßüUMECö;o[ßü›ÿŠ£ìvÞ·¿ø7ÿSQ@ýŽÛÖ÷ÿæÿâ¨û·­ïþÍÿÅTÔP?c¶õ½ÿÀù¿øª>Çmë{ÿóñU5Øí½oð>oþ*±ÛzÞÿà|ßüUM=í­”1‰­â/œy¬8ôÏÖ³ôKÙµ"¹öù’$(À1À µö;o[ßü›ÿŠ£ìvÞ·¿ø7ÿ^vÞ3Ô5[ Ô·¹²–æ+û XʾVÖ»J4ñË!ÚÀ—Ž2˸„8e]+Ÿê6—Ré׺†‘§½´òC.«u -³°Ž 0†QµØNq™ú–8çåì¾Çmë{ÿóñT}ŽÛÖ÷ÿæÿâ«·ñ¶£+Åm6’ö·÷Ú­¤‰HdÆ@Ù —eÎbÚBGîÚºfêîÇIžîÊ´KÙ…ÚHÕ‘QGY  :Ûž(ÏØí½oð>oþ*±ÛzÞÿà|ßüUr:¿Š=Z[«+M>]fÞw™Ú35·šŠÎ:ŽH’U ²´@eH-‹w#¹Å/§­:“Å v#››ÄeBfŒ«d"—aþ­‡î_.£%:?±ÛzÞÿà|ßüUc¶õ½ÿÀù¿øªãá)¹‰oþ*¦¢€!û·­ïþÍÿÅQö;o[ßü›ÿŠ©¨ ~Çmë{ÿóñT}ŽÛÖ÷ÿæÿâªj(±ÛzÞÿà|ßüUc¶õ½ÿÀù¿øªšŠ‡ìvÞ·¿ø7ÿGØí½oð>oþ*¦¢€!û·­ïþÍÿÅQö;o[ßü›ÿŠ©¨ ~Çmë{ÿóñUKQ0Ù›5AvÆâê82×ó|¡'ïzZu“®¬Ò?ì%õ ø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­Šzüƒ‡ý|\èÖ«_Oÿpÿ¯‹ýÕb¤aEPEPEPEPEPEPEPEPØÚ]8{‹X&`6†’0ÄN~µ$PÅB8cHã^ŠŠ€§×=k6ºÚð°˜8µ·žk‡¼(»n!aû˜€Ç`H%¿Ñ`¢€:+„Óïµ5ðœ;©Rå.î—JÙt°%xåX|¬390î"6ûîH¶ç»½^’oíÃ^L²—Ó2LF99dÚŒa|´c9‰r¨Ê aErZtÞ#]BÖâîyå‚ãT¼µkcj`¶S;E! nÜ|¸Ô1!J¸ùKç'ìú†«à ‘ɪC=®³çÈÿÙëÒÄ—žo™å4@3yx“åL³Œ`’Ê@=Šá5½\°Ñ5[›žo/Fó¡k£ rÛ:yÙ¸šB¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÅ=?þAÃþ¾.?ôkUН§ÿÈ8×ÅÇþj±R0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢¼Æ/]Zkׯ£Û"ëRÏ|âêçGXÒÝeæJÅ®ÊõÍø*#“Ähi´E…i$àÄœS¼ŸÿÏMþú’­_ÿ©‡þ¾ ÿÑ©V©ŒÁ½»×l<é´}Ò")³c“íþzÕ?í­sûšwäÿãSx—þBzWý¶ÿÐEU¤"Oí­sûšwäÿãGöÖ¹ýÍ;òñ¨è¢árOí­sûšwäÿãGöÖ¹ýÍ;òñ¨è¢árOí­sûšwäÿãGöÖ¹ýÍ;òñ¨è¢árOí­sûšwäÿãGöÖ¹ýÍ;òñ¨è¢árOí­sûšwäÿãGöÖ¹ýÍ;òñ¨è¢árOí­sûšwäÿãGöÖ¹ýÍ;òñ¨è¢árOí­sûšwäÿãGöÖ¹ýÍ;òñ¨è¢ás¡ÒÞú{!q|mó!;nã’O¯ù狵ÿ ‹_øþ„jzc (¢€ (¢€ (¢€ (¢€ É×?Öiö‡úÖµdëŸë4û Cýh¾*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+bžŸÿ áÿ_ú5ªÅgK¤ùÑ"5ýìAGÞA;Ü·<zã¯nÙ¨¿°þ‚ºÇþÿö5#5¨¬Ÿìÿ ®±ÿýØ ÿA]cÿÿûÖ¢²°þ‚ºÇþÿö4`'ýuü ÿìhZŠÉþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±  j+'û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€5«+SÒäÔu;±Ã”»žz€¿ÿZ“û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€ýüÿä#þ4`Gÿ?ßùÿ3û?è+¬à_ÿcGöÐWXÿÀ¿þÆ•…aÿØÿÏ÷þB?ãGöóýÿøÓ?°þ‚ºÇþÿö4`'ýuü ÿìh°XöóýÿøÔ·v:•ÅÜ’Å®¬±ùc[0ÛGÔœŸóÒ«ÿ`'ýuü ÿìhþÀOú ëøÿØÓ§HÔ™£2ødT‘dØÖ@Uƒ àƒÔô¿Ùz¯ý Ÿù"¿ãMþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ± äðõÅÍÔ^k~“»hû ^£¡úTÿØÿÏ÷þB?ãLþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ± ÿ`Gÿ?ßùÿØÿÏ÷þB?ãLþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±¥aXöóýÿøÑýüÿä#þ4Ïìÿ ®±ÿýØ ÿA]cÿÿû,ýüÿä#þ4`Gÿ?ßùÿ3û?è+¬à_ÿcGöÐWXÿÀ¿þÆ‹‡ÿ`Gÿ?ßùÿØÿÏ÷þB?ãLþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±¢ÁaÿØÿÏ÷þB?ãGöóýÿøÓ?°þ‚ºÇþÿö4`'ýuü ÿìh°XöóýÿøÑýüÿä#þ4Ïìÿ ®±ÿýØ ÿA]cÿÿû,ýüÿä#þ4`Gÿ?ßùÿ3û?è+¬à_ÿcGöÐWXÿÀ¿þÆ‹Xa[k8mÖO3f~m¸êsKY?Ø ÿA]cÿÿû?°þ‚ºÇþÿö4ÆkQY?Ø ÿA]cÿÿû?°þ‚ºÇþÿö4­Edÿ`'ýuü ÿìhþÀOú ëøÿØÐµ“ý€ŸôÖ?ð/ÿ±£û?è+¬à_ÿc@ÔVOöÐWXÿÀ¿þÆìÿ ®±ÿýkVN¹þ³Hÿ°”?Öìÿ ®±ÿý áøâ ¤¾Ô¦òeYU&¸ »Èãm7Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+CQÖÖáa[û‚¨2ð@YAôÏü+?Á_ò#èõãþ‚+v¼ù|Lé[ÿðÔ#VÿÀoþ½ðÔ#VÿÀoþ½lQR3þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(þú„jßø ÿ×£þú„jßø ÿ×­Š(—Öµ)u-"{HtMd“n Û8`{jÞÔÿäyÿ\ÿA5jªêò ¼ÿ®ÿ š!QEé§Õ^ ÿ‘Cÿ¯¿ô[µ…à¯ùô?úñ‹ÿA»^|¾&t­‚Š(©QEQET±1X¤ àñQT‰þ¦_ÃùÐçÉýïÐQçÉýïÐTuËx¢ÛT¿ÕôÛ;K¼²0\K:Mu%´k*´B&ó#F;Æç*8äo2)oŸ'÷¿AGŸ'÷¿A^cáýwÅw—¥Ü—­s¶1›s`«o··{¯9ÀÊ2 Ô/æ8O¸¶ü#«jº¾‘o>¶.¯¬îtŸ;PI´à# U6,Aó„‘™€/Èldùtè~|ŸÞý|ŸÞýp~»Õl¼;áH-­^GO‘6Ÿ>-å …DŒ$„hC« x„+äWEákÛKÂ-õÜžeÍÍ„Jøs´jIÀàrOJÚóäþ÷è+#Ã÷3^h\\HÒM!rÌÝþv­:Çð¯ü‹vŸð?ý ¨bŠ( Š( Š( Š( Š( Š( Š( Š( ¥‰ŠÅ!ŠŠ¤Oõ2þ΀>Oï~‚>Oï~‚£®?ÆöºmÆ¡áÇÔ´wÔa†òW—nš÷a"0H§!Q° †.;ðävž|ŸÞý|ŸÞýyæ•qâ‹A¥ÙÞɨý¾%³ˆÛq-¼ñyq ‰e¸Úq"“>˜¹1§ÊÛ¾xÖûÆÖ¾±œ´÷—ךZÜ\«Ú¾É"¼‚…F"O.I˜« xþTÆc çÉýïÐQçÉýïÐW;áõkÍÕß|+y,êë)ûÀÐÃónߌF£nÞ¼“½@¶—wþ«²³G„F½—*IüÏôô­*ÇÓ¿ädÖÿí‡þ€kb€ (¢€ (¢€ (¢€ «©ÿÈ*óþ¸?þ‚jÕUÔÿäyÿ\ÿA4 >B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"·k‡ðÏ‹ü?¥ø_LÓïõk{kËkd†x%%^7Q†V¡ŠÕÿ„ûŸô²ÿ¿•Á(»½„ÕŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷ò—,»èèè®sþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::+œÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.ŽŽ£¹¾¶ÓìežêeŠ<ªä󓞀M`Â}áOúYßÊ?á>ð§ý¬¿ïå²ìE¿øJ´_ùýÿÈOþÂU¢ÿÏïþBðªŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùK–]‚èž?è<¯Â#ÌÛäevÀ\Ÿ—“…Q“ØÚˆð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèè®sþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::+œÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèê;›ëm>ÆYî¦X£Ê®O99èäÖü'Þÿ õ—ýü£þï ÐzËþþQË.Át[ÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ ©ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”¹eØ.‹ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáU?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ¢ßü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øUOøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚è“Cº†÷[Ö.-ß|Oäílœ)þ•¿\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”ùeØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèê®§ÿ «Ïúàÿú ¬oøO¼)ÿAë/ûùUïüuáitë˜Ó]²ghT :’ /°]1Ñ[?ðˆø—þ…í[ÿ¤ÿâh®þdsÙŸÿÙnetgen-6.2.1905/doc/pictures/meshingoptions_1.jpg0000644000175000017500000007166613504650527020414 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5lx}ºi¤ý&“ÿЬ& ê¶4TåcƼ¸VÕ#Kp²©æ@Ø}Çõþ´ß+ØW´  Ð1¿ïìŸüUð‚hô oûû'ÿJ8šqÑ&7NOsÅü¯aG•ì+Ú?áÐ?èß÷öOþ*øA4ú7ýý“ÿŠªúÜ; Ù3Åü¯aG•ì+Ú?áÐ?èß÷öOþ*øA4ú7ýý“ÿŠ£ëpìÉž/å{ <¯a^Î| áõ릑õšOþ*˜|á°pl?õÞOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ;²gù^¬½ýÿöÝ'ÚâtMŒ0ò¢³!v>÷Íž1ÆÇjõÃ௶}g“ÿФÿ„/Ã_óâ¿÷þOþ*§ÛQì>I÷<º_ë“›ÿaXäÓäÓ’¶Eãq\¶wp9$ý),õíVÂëEž³'GŠX­ƒ£Þ`ÃoÃsíŒW©Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT½­¬³îy-¦§¨ÚG Æ¢Ô®ŠÒ=¾Q²ììïç‘‘Ûµ øšÛL‚c¬D×%õÔ(¬–P’’c,à¡ê9Ïèð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU­&­f5#ÇÕÍίy«6Ó\]½Ô`cËn^}G£â]núÚîÜ.›joWeÕÕµ¶ÉçSÔ3g÷Àêð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU7Z“I5°¹%ÜóGÅW;,­t[kxZ"+ ofƒ÷èFCÛvÇr3Ö²Zúóþûmɲ’ÞØ“ ÒDLÐî °V㜃^¹ÿ_†¿çÅïüŸüUÁ^'Àÿ]äÿâ©*´—F73Ì%ñ­q¨ê·“çNº‘‹Ï´šh–SÙ`½jµæ³¬jÚ´7R[?ö§³b2¢$…²‹}s^²|áÁÖÀ¬òñTŸð…økþ|WþÿÉÿÅQíhöY÷<®mjúãP—ZeÃ%¤v‘¤Ð¹P¨I À†äòúU[û½CWÔ¤Ô5ci™5H—ˆ½ŸÏ&½{þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠªUé't„á'Ôñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*¯ëpìO²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}nƒÙ3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ¥> ðà:~ýw“ÿŠ£ëpì?dÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ; Ù3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª>·Áì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡`öLñ¿+ØS¢QÈì>PyÇÓìCÁ^'Àÿ]äÿâ©O‚¼8:ØõžOþ*—ÖáØ~Éž5u¥è׳™îmüɱRÅ“ÛÙÆQX(Vê~µëÿð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUOÖ)Þö$"E¶{O"à63’>¹H-´ðÊÛ¦b¤0 ò0ÈéÁ5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU?¬ÓìÎG‘;FoRP¢ŒŽ{ÿH¢Å.u•À û$‚½gþ¿ ÏŠÿßù?øªwü!ÿ wþF“ÿŠ£ë0ìÃÙ³ÈvYÃm,Vé·~ã´)'©®sÄ«¶Ò÷ÿ¥}ÿG‡èÿ‘¤ÿâ«Î>0xKÑô]:[ _%Þà«1›#iõ&š¯ {© Á­OJðWüˆúýxÅÿ ŠèÝŠ**œ œw5Îx+þD}þ¼bÿÐEt3Ë?÷qKâfËb•Þ³eaqmoy©[ÛMtÛ-ãšuF™²–9#ê=jߘÿßoμûÅú¬z6¹¨)¸Ò<íSN·¶Ž=Fâ’mÆhÞDc q”Þ~VùNj“i¾.¿›Z»³Ôgxî-nžÊ{is Â:7ÙÒ6ûFÔaº#¼BœÆ~s¸³ÈÏLóûíùÑæ?÷Ûó® \Ñ|MÚ-ô›»Ùì›ìòÊd¸-4î|ñ(B%ˆ§?fmªñ ¶ŽY}+úÜ×#ûWWÕ(ì òLSˆ¶OæNÇr‡“sFìêøËù„;o1ÿ¾ßAe©[êV‰wc{Õ´™Ù4‡FÁÁÃÈ#ð®Am¼L>!Gt ž=-åe„åá1˜!§8bâ2BÀ„ì2_[Â1^C£Î—Ú|öRµýÜËÏ’Îò©Ê3Žç¨=°H†¯©Ïc¨Œ#ù÷I oàò9ëÅr:–¥xÚ„à\HŠŽPbþuÑxý^›ÿ_ñZä¯ÿä#uÿ]_ùšLLˆk¶ÌjNw»F¸œüιʎy#kdvÁô©~ßyÿ?sÿßÃ^vëÏvšÅ´z˜Ôo C%ê‰ÜN¨Û2y%¢pqÏ—ÍØì5´Ò'VkòòJ 7(îbÆä¶ÓòŒ,ŠAQÆ dµ¥Á•¢Ò™C2 Ž@9Á#=äißo¼ÿŸ¹ÿïá®5ô½ZE¹º|7I¦Ä–éÇ:Jï%‰$n\«3),A/ÕÑß[­ÞŸsnÑ,«,MÜ pA,2@>£‘HD°x….mdºƒXYmâÏ™4w;‘02rAÀÀæ­}¾óþ~çÿ¿†¸ù­ui´m[Þ›©`T¶i$†+ãv2ñ_,çïä@2ë0ÝÝÝZfã¤H>ècÁã¦jÚiº•“¤ð™W½ºi"’|D!c+ ÀÈsÝ‚ãq8_Ûï?çîûøi§T¸¬FúQ#)eC1É g ÈüÅpöv¿%Ìpܽì^z3Ÿ?W˘8ÉšVÁ>Pá†:¨­+Ý"hµ; ÈîðÛÅ$!Mã!º29A´†8f#nC‘èû}çüýÏÿ [¿°Š[”™¤hãf +SŸZæl¡Ô—ÄwIÉ´}Ã|òa@ãUee=»CŽKÚ×ÿòºÿ®Oü 7ïõ›Û›=>O3Ëiícü¬¯ÌçÓÚ²g×M¬°Åqª˜d¶Ä’\m28PO'‘ÓÔTóÈ;Hÿ°|?ʸ¯ÜÁmu¨ÛËql©iËl†K˜ãòˆ2îÛûÁʆ?+qÓ,×í÷Ÿó÷?ýü5öÄ¿eûWö“ýŸg™çyçfÌgvsŒcœ×£-î¥1¸Yîd´’êèw˜Úß|Ѝ€Uƒm`À”pøÂæêž ¹Óaµ»[¨íÖ(/N÷˜(Зù#ÈRG†ÁÑ€;/·ÞÏÜÿ÷ðÓF©peh…ô¦EPÌ‚cpHÏCƒùå5k=nêêk»ž Y¡ŽœÞ˜íÚ ]ÛüŒ“ÁŒH7<»±¬ê¥­¯ZÎ[X¸4ƒváÞ ~Q•'#‚PÛï?çîûøhû}çüýÏÿ p«a¬*O& J Þuy¢žð͘ö°Ù‚0ÛI%з=¾J¿c¤jRL>Ýz#[X¼³›6˾CÈÜÙ*¥æ,­ü[ñÀXºê°aw6AÏ.Hüªô#¾¿Ðî¥.7Žõ­”ÆÂ…<“ϽdQ¥È»}ÿai?ô@¹Ö%³§ºÔžW¤–rª2p2IÇSO‹T¸š$–+édÔ2:LH`zsȬÜG†5y#V¸àŒI*FÙH.@õ=zÖ¨L××Û¯ô»ÉRÉ>ËhP]0ᶱт ÚsÎì vo¼ÿŸ¹ÿïá¦Çª\J¥£¾•Ô1RVbFA ޽Aq\Ý”:’øŽâi"¹6¸ožL(cj¬¬§ ÷hqÉbsºmõ3¢E¶×àGy)–v<ù`%ÊIÔn9ppŒ9®=RâU-ô®¡Š’³2 uê ûŠwÛï?çîûøk€Hñ"%¼~t‘eå;â`þT<ŒdlI`Uà«ȼ†ètÍ:æ)æîêìÌn'"6›ryFG(»zcH?xtÎß–€7Ž·a·)3HÑÆÌV,§>µ~ÿY½¹³Óäó<¶žÖ9ßÊÊüÌ:}=«ÿþA×_õÉÿ‘­ ¿ä¤Ø>å@gñ []Gk>°±\K..v»äà`““ÅX—T¸†'–[éc³»Ì@P:’sÀ®+Å·q. -H#3é·þd×1FÊP+ÎhòÛ$í“"¹Óµ½@jŒ— 46÷K#Štua)2í ‡p~éùŽIf3¼û}çüýÏÿ o¼ÿŸ¹ÿïá®J}f ’ãË»x¢•Z[v¹WyÛdªì¤» hˆS° „„S€r5vÔàÓæK«¯.ùÒv··„°°s,…<¢£÷äƒq·jŒ ôôUÔoUƒ ¹²yrGå]G…5‹fÆî[•Z ·|°@Ú‘œ“Ï5ÇWCðûþAZ—ý„eÿÐR„4uÕå_ÿä¥ÿ×ÑÿÐMz­yWÇ?ùiõôôZÒøÐ§ðÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š(  ¦.¢-'<›”™Œ„ŒœÇ^kçÂW³]Í*ÜÙ…wfvÎ úWQEr_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]m¬+—ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰¨®|¨Mi4KudÑ”fFÆHÿv»*(°Xåäð•ëÚXÄ.l÷[ÚÇ üí‚Ê9Ç*/øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&¢¹ðN¡5¤Ñ-ÕgFQ™#ýÚ쨢Ác—“ÂW¯ic¹³Ýok/ó¶ (çt¨¿á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš,¼m¥\Z½Õ‘yošà#ciP1÷z×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E mÏ‚u ­&‰n¬ƒ:2ŒÈØÉîÕ©<%zö–1 ›=Öö±Âÿ;`²ŽqÇJê(¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ5«ámçD²»†æ{gi®Þu1¹ ) raê(z(¨ãž^TŽTw…¶HªÀ”lÁô8e8=ˆ=èJ(¢€ (¢€ * «ëK'íwP[ùò¬1y²ó$nˆ¹êÇrjz(¢ KëI"µ•. hîñövYeK‡ø¾P[ŽÀšžŠ( ”+7@OÐRT±’!ƒƒÅ3Ëî7åG–ÿÜoÊ1ÿ¾ßcÿ}¿:<·þã~TyoýÆü¨óûíùÑæ?÷Ûó Ëî7åG–ÿÜoÊ1ÿ¾ßcÿ}¿:<·þã~TyoýÆü¨óûíùÑæ?÷Ûó Ëî7åG–ÿÜoÊ1ÿ¾ßcÿ}¿:<·þã~TyoýÆü¨óûíùÑæ?÷Ûó Ëî7åG–ÿÜoÊ1ÿ¾ß(2°È.~™ òßûùQå¿÷ò§~ûþš~´…¥^¥ÇÔšiVQ’¤}E%d´²?ŒØ¢Øž2 ŸÐ~U­@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ ó|â ?FÑ¿³åº[ØtCk:Ëu¼BÛíYáç\ 8 `•DUM¾EyÄúOŠö–Õæ™§’O&6`L( íöå‘Îw0>sŒ9FnšhšÚj:Žª¦xnæÕ-%ŽÞ°`ò¼»hî/™ò¬ª7Œ€¢©9=¥“âgxü=téwö]» JK( ¼n ê F¥r¦Aþ¬ÿÃ\_†tíKZÔdw¿½ËpYëS\E.c´Øá±#(uœåqµƒ®pHoJ¢€8}bÏÅ â}2Kº–Þ¶ŽK‘0Û,[ÇœÒ'œˆ©~ü%XàµÑÅ{eåÚ¢ýšú_2høèÇù .ÕÆÑÑ'ú™çQÔwW‹ee$†æ$¨Áv?‡øÐ‰mon.,Ú;}FîÁVA5¶yöiŒ¤§–ûüÈò€ Aúº§\Ïìÿÿk@Ó}¶K‘-³%â^²Å¬~|rF ‘ˆŸ äŸõ‰Êc ¹ÿ ýB5oüÿëÑÿ ýB5oüÿëÐtßO«Ýª}¶ÊÚâXÞI"¹ …Ü,LFIäʈ¼þ<¨ƒ ÈUÖñ&©Á§ÛZhòkWQ‰]Ê‹­þXÀá¤70LÜî#20ù˜Ä{w?á ÿ¨F­ÿ€ßýz?á ÿ¨F­ÿ€ßýzçåÓ|WqãHn¥¸{{2Ñ86ìe†(Â/™4a‹009ÔîÅcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±P^Þ]Û[ ³²k©þ`%XÂŒzšÎÿ„ƒþ¡·þõèÿ„ƒþ¡·þõèßÚºïýÛÿR)u 5û»ûv€L#XÑ¥`(9sŸÆ›ÿ ýB5oüÿëÑÿ ýB5oüÿëÐÿ3ŸýÃÿö¥lVŒÒÞø™®þÅwo³òóŸs7Ú ¶òâgóîc‹Î2>QÔò8GZž¥9h$cáéµ? iw—•®¥4°+Iwj…#‘»àAƒÀä•~èÞOõ2þ΀;þ™Çÿ|ÑçÓ8ÿïšä¼Q~º¾›¥ÙÁ¨Ê—\\¿ös“‰¢s+*ì\‘ÎâPºœÆZ棧Eª\C§-šÏ§ÛÉjþdu±$Ø@qŸâÜ>_”Ìè~wý3þù£Îÿ¦qÿß5Ài^5M__Õ4‹ÙàKµ¸œÎ®¶Ò[FŒªD›gwFęˈYJ—9 ?‡¼Cwÿ¯…îÄsêv×:XYæ·S<­v0¨X.OœŸ Fæ^àÇÿLãÿ¾hó¿éœ÷ÍyÆ™ã{½CQЭÛ]ðô^ÚÚÜÝZKYcócR#F3üÒ;•vªAlü¡ïø3ź§ˆõ ˆîìàŠ(âß"+Ä$³‘ˆdU™Ü·ßå’" g+“…î<ïúgýóGÿLãÿ¾kŽñ}í½¦¡b5;¹í´Ÿ²ÜÈÆ+Ógæ\)‹ÊÍŸ1S6°Ÿ»‘›mã-]üIa¤¥“„‘mÇ•¨aº™5w˜ƒ*SsîT…Áh˜;=Îÿ¦qÿß4yßôÎ?ûæ¼á?ÕÂß/P°^|CÖ ±…¥ÓàÓå2•š[›!&&XXK4 I‰ÊýüŸ%ˆLÓ¼ïúgýóGÿLãÿ¾k‡µÕuh|j‡Uº‚Æ Û O+LhžW2“/˜‘:¾Ödb¥Ü! ghŒš^µâ{¯ Xë“[iÒ¥Ô×-¬r³Å4fBI˜ÚGT¨P%Îh´ó¿éœ÷Íwý3þù¬ëSkRêÆKg·ŽÖðA ËI f¤ ÊI “!88 `Z—𥖕l’^J‰½Ê¨e,Oð9ÿõЯ;þ™Çÿ|ÑçÓ8ÿïšÇÿ„¿EÿŸ˜ÿïËÿ…&™¬_Q¿òYÖ‹jÎAÜNyëÇá@½üÏâ5±Â,ÐÌB¯%·×Ø?¥^¬ùœÿîÿµ+b€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEAoeok5ÔÐǶK¹DÓ“¹Â*ÏO•qéõ©è¢€#‚mmã··‰"†% q¨UE8Õ+M“I4‰k·,ìúšJGµ¶»…–ê–5!‚²†äg€*ké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ5'öFÿ@ø?ïÊ…Ù7ýàÿ¿)þö¾›ÿA Oûü¿ãT5%Ð5_(Ü߯²E’Ûß´(8Êï•¶œ)+œªHàcOû#Fÿ |÷å?Âìþðß”ÿ ¯¡£ÚÛÇoowc1(HãŽDUEµIý¯¦ÿÐBÓþÿ/øÔŸÙ7ýàÿ¿)þdhßôƒþü§øPÚúoý-?ïòÿÚúoý-?ïòÿIý‘£Ð>ûòŸáGöFÿ@ø?ïÊ…Gý¯¦ÿÐBÓþÿ/øÑý¯¦ÿÐBÓþÿ/øÔŸÙ7ýàÿ¿)þdhßôƒþü§øPÚúoý-?ïòÿW½ºÑu Gµº½´xŸà)†RU†@ ‚*çöFÿ@ø?ïÊ…Ù7ýàÿ¿)þCN“CÒíÚ[ëp·»ËwæÉ#` ³»c€I8€ ·ý¯¦ÿÐBÓþÿ/øÔŸÙ7ýàÿ¿)þdhßôƒþü§øPÚúoý-?ïòÿÚúoý-?ïòÿIý‘£Ð>ûòŸáGöFÿ@ø?ïÊ…eAsÏŒ Ûͨ,0Z6 3ætâ·k>?ìë]dYZX¤Ss+H¨«òî<óøÃB€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEfišŒ×º†µo" KÅ·Œ¨9*`†LžzæF鎬ŸøO´yªY°´ië#¼i42TpŒ~I–eÉ—ËÀ$œrºmá½8êÒjjoc¹–UšAüñÆîªª F®ü¨ är9ªéàí9ZH’ö&1PE¨Ü †2ÊÅ"À‰sp›FœP M%·‡îôÍ&{Ø5;©au†{yŽV°›fâcÏ FÃ`W[Y?ðiÙÿcò§ÛæùÞwÚ¥óüÌmßçnó7mù3»;~_»ÅiA6¶ñÛÛÄ‘C„Ž8Ô*¢€jâ'ñ~³e¢k—ÐÛ[ n’Á­%àtÆW|Œæ5ÏÍ$ez æ(Ú¿l´K)5;Iínn÷”´žâÚ7 „%ÚQñ/É;ºpØ¿káÓÎÚoŽXšò<±¤M÷£DrV8Î( ) £(ÄgšA·H„wHêÌÿhŽöe¸bÀº`þc „Oî®*ZøãL½›ý Ù-<Ø"kß'l*gHÚ¤1Ýç"à)*y` ‚zäh­ä‘!y²ÅPÎ@û£q'§$R+ ië®_jÓ¯=ÍÒ\–U":ƒ¶M­u,ÒÄ®'jxVâÞH¸I£Ý‘€#2Tû‚í@4[ûSD³¾ºÓçÓ§ž ïi9â'±ÇõÁõä 4ÿS/áüë3EÒmôÏJµyÞ H„HÓÈ]Ȥÿ!€:´ÓýL¿‡ó  ZûQþ×±ÒtÉmm渂{–žæ™BÆÑ.ЊèrLÀçwHÁÎFfãÛMVÚÚfÓ¯aWû*O.ÐÐÁ%Äq¦Yä@ … «y˜o”‚Äzf7ùh¡¢³$ñ‡™§&³§%„Ͳ;¦ºA·<Î ù[€{J±&«§E©Å¦Ij—ó.øíZeºóÈL䕹±ô  tUõÍ&o¶ùZ¥“ýƒ?lÛp‡ìøÎ|Î~Lmn¸è}*øJ|=ýŸöÿíí/ì^o“ö¶Gåù˜ÎÍÙÆìsޏ  j*¤š®§™%ýª_Ì»ãµi”JëÏ!3’>VäÇÒ§žxmm丸•"†%/$’0UE$’xô%Gqh÷ÖÝKl¤‚Ïo¦pqPiz¥–µ¦[ê:uÊ\ÙÜ.øåN„0AÈ ò ò*ú©—ðþtÿÏýFõ/ü ÿëQÿÏýFõ/ü ÿëU™5bÕí´ÆWó® –á´,m°<ç9•qÇcø‡R¶ºibD7M\¦å@ÁA)Ø$œùH$[þŸúê_øÿÖ£þŸúê_øÿÖ¬äñðö§­C¨A-¶æyëѳü®È¸±ûŸ&HÝ‘ëWî|Ecg¨Ú·Ûì®®¢¶YìäIL’øeC§nHÏNÿÏýFõ/ü ÿëQÿÏýFõ/ü ÿëU™5]:-N-2KûT¿™wÇjÓ(•מBg$|­È¥[  ¿øFê7©à_ÿZøFê7©à_ÿZµ(  ¿øFê7©à_ÿZøFê7©à_ÿZµ(  ¿øFê7©à_ÿZøFê7©à_ÿZµ(  ¿øFê7©à_ÿZøFê7©à_ÿZµ)ëeݹ@Î94‘ÿÏýFõ/ü ÿëQÿÏýFõ/ü ÿëVÇ“ÿM#ÿ¾ª:q%ºL,aKªœíÎqŸÈÿ“@¶šU®«nþÑžæñà ,Òï"=Þœsý}ëV±ÿæsÿ¸þÔ­Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQE‹«xcN×5{ÍNÖÖòX'‰m®mÖU-#DwÜdtþ#Èï%§‡í-õ^öX žMFê+†-ÊùQƨ ç;Z2àñ‚Üzj(–ŸÂ3_¦³¡{kqk©j6÷¾OØÎb1f6Ëá’Rp9,pA ,\øjf¼¹¾µ¾H¯Q„X Ç}•mв†RãnãÃ. @ ô4PpFÑ[ÇÌó:(V–@¡œ÷ŽÐO^€W/ÃËy46Éo<©,¬ØÍF6šTkfIX«û"ÁÀeÀ5ÚQ@[øátøc¶Ô`ŠôË$·7Œ/ ’³PÅБWlh —`J)ÀÀ«ãÃ7ËâµÖ6D›<ÕŽ'In  RÒmBÌØÁo'!p©UaÒÑ@%Ç‚/’úãSŸRŸTt‰–CºJΊQ"´’¥>¥{i%Ô»|KåÉ$K»u¸#k•ÚFAo»ètP-oá,u›Yôûä²Ó­–8ÖÖ˜;ª @™ŒnHP»š"Û@‚ªÃ¥œLÖò-»¤s"7‘ ª¶8%AŒöÈϨ©(  ÏYÞéÞÓìµ-d¼‚ŽF´‡Ê‹ c ½€ £®Ÿêeü?GQ]=ÚÚ:Ù,v#rBß§'ô  ­[IÔnµ{OL¿µµšÚ íÙnmuu‘¢l²!‡sÔÐtFOiº¬·ö¥-lä¶š´`ei 32·˜v Ę6á“C¿â¥ÿ¨OþD£þ*_ú„ÿäJ¬<.Ïcªésj.t«å¹Q q*Ȇá™äfsÄm˜ 8`çމ¬êZ2ZɬÚý°^CtÒ›b'WTHÄ€,ŠIgcËc¨[?ñRÿÔ'ÿ"Qÿ/ýBò%g\x2;¾ª×ŽÖ³OÔÖ$à£TÀ$«Š6ÃFÇ óŒêkþ*_ú„ÿäJ?â¥ÿ¨OþD  Š+þ*_ú„ÿäJ?â¥ÿ¨OþD  Š+þ*_ú„ÿäJ?â¥ÿ¨OþD  Š+þ*_ú„ÿäJ?â¥ÿ¨OþD  Š­}äð$Vw‹jCnfòD„ñÀäàú¿ñRÿÔ'ÿ"Qÿ/ýBò%ÙÚ×ý¿òM?ƦÓ4ɬ®nî./>Ó-ÆÍÍåÆÐGcïúT?ñRÿÔ'ÿ"Qÿ/ýBò%ó9ÿÜ?ÿjVÅcØØê_ÛM~ÖŸñïäoïßñ­Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEV.¡¨j)¬-ŠÚÿÇ¿œLῼGcô­ª…m ]A¯Š˜Ä!¹rOêO­e]T•6©;K£{ Zú…¢Þ-²æ€ÌÃv (‡''üýk•мG«êzä°Ðìc”’Š¥—'¢0®Éܹ€R‹K²ŠÆk¶Fµ¥yb“çW2³<™ œ‚]¸éÎ:UÁ5͸ŽjÏâ>‘|-­î§¹yÖÝm­ž†,ÑÈèKE# ÉqË ¸¶¯ÍVõ麥•Χ ö±ÜïÞ'’ž„Ê<¤Æå|ã+˺ݟ…4‹+侎;©n‘•Ö[›Ù§`UdEÁ‘Û€&—ŽŸ1=qRjþÒõÝÿoŠsæDa—Ⱥ–6>~GòÙw¯ÌØ 76:œÐ¥ýÜž*Õ4ÙŒ m­µÄ#*ãÌi•ƒÄ71dÞÇ8Íd'Œ“KðÂj:ëÀg7÷+äm%xæ• ²mL¬E¾gí€I è´{8u»]ÿm¸‰a‘Ä… /Ý2Û2O}æþñÍH|)¤A¦>8î„>{\«ÙŒ©+gs$¥÷¡9lía퟼٩‰ÿ´[ך\>Ÿ©ÝMm0tÜá’)[åum¼<,¤Á³•8Á;Z®£‘¤^êw í œ\H±€Xª)bHÀõª÷ …Óé7Ú™ôÖlßl˜ØÛ–Ã~ðã —ÎC0?xæåõ•¾¥§ÜØÝÇæ[\ÄÐÊ™#r0 ŒŽGô fãâii,· <2Ç*ÃäLÑFYÉ‘HÞÎ#h'S—1d2’/i$@A©¶È˜Í *°“Ë 3Ȥ0 ˆ¼Î€ôd-§qáæYekO*Yvæ[yRFܬ„bf—,¸-æ0$ƒŠ.¼7§^ù"äÞËQ,>S_Ïåȃ´‰¿l¹ÎðÛ‡4CFñ_Û®~Ëwi/³ì·ÇÙ‹ço–Y<Ííלù²px¸XxkKÓb‚;x§+ot÷‘®¥”¬®¬®Ùv'‘#ätËŒœÐe׎¬íìn.¡Óu¡iÜ_Gˆ5¢£HŒ|І†Qòû‡±RzYäh­ä‘!y²ÅPÎ@û£q'§$R+–×¼ i¬Ãö@,–ÊO;ÌK›!q$M3³É$)¹9;À*˜Q‚­ .ÏÆz„¾ðÎ¥>‘:KªJ‘É "»KºÕå W;Tº¨B02[hù…ø¼kiqrÖöún©<±D%¸X  ä/™,N ó2<. ¦âÝP8Éí|3£ÙM Öö›d†_6"dvòðŽW'åVIÆ>EÜpOc£iúmÍÅÅ¥¿—-Æ|ÖÞÇvd’^çžiÞÇ@ɳñÖ{âfС—7>l+y±òFzùaÌ‹ó2*¼¹wW°ø…¥j‘:ÙA=Åè•"K8&·•ä,®ã’˜‡Ë§ àü>eÝ´šš—rˆ]’í]'·y­Ü9ËþäŸ,9$…É,ÙûÇ5ÁÚ2yͲõå—ËÌòj72lß·dŒåÓýdƒå#!Ø‚hdžõg×4s|é³7W1*˜Ú3²9äw+|Á¶¨È8ç<•­U4Í.ËG±[:Ù-­QÒ(øU.ÅÛ°Ë À«tQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(î‹fI%.âY°õ5JçR´´Ò¥Õ&›m”P‡—i8Œ.âØÆzsŒf«kê׋%½ ²[g‡Ê&V}ç#ð0:ûÿJ±¤±èñYùí«n"ó¢Á(Ûq¹w2:Œ‚=ET‹_-..u[iôXíö—mEãTÚÇ |ÅvNOÝ‘Æ@ܹžMsI‡ì^n©dŸoÇØ÷\ ûFq/ŸŸ;—¦zZåÃâlÊÇ{kep“¤ð¦™k%²2¤ˆXÇ¡÷²ÊÀ²È¹Û<) n/=œ- ôGuj-µ=³\ùÃ|®Ìždµ™§”Ÿ3Í®AÁܼúæ“ÝÕ£ê–Ksišâ¸@ðÆ%Ýs•\rxäPúæ“¥ÕÛê–Kmi)†âf¸@ȳ…l0yäW=©x"mFÎëOmQÁÚòkuÄË×)2¹w߇Aö‰Pª~îXàî·yá=Ú´Z–›sœ¶Ñ[Çi¶Ý ^RÜ'*¬¹R—,pT‘ÅmiÚŒ:¥«Ü@®¨“ÍnC€è¤hØðOClt¨ß\Òc»º´}RÉnm"3\B×À»®r«‚OŠƒÃZxoC‹KŠo:8¥™Õü¥‡•¤j€£±ÀŽè1u/M¨ÙÝiíª"X;^Mn¢Ø™cšå&W.ûðè>Ñ! OÝËÀ ëšLv—WoªY-µ¤¦‰šáC vβ@Áç‘PCâ]&E‡Î½‚ÒI‚+™R7šH¥10@OÍó1Ï#œTz‡‡¡”Xͦ [ËClÿf UŽHÂ2©RP,Òm† ÏLƒÍEð¾"ŠÝu'{VW‚ê%…f§–P`–5ºœ«/L*Œ‚ÚCªé׆ΠûYn‚³˜eg ®QŽÐs€à©=ˆ#­I{}i¦Ú=ÝõÔ¶Ñã|ÓÈ',x?¡¤x~ÓJ†Eò –W¿¸¿ó|¬$•Üç¿Ìü½ÝH‡‰tâ ;hã»{[‹YÅÄ2«HmŒ„-ÑñµÛîºóŒäd æÖí¢ºÒ#âU™ º‘¢FÒŒÙ!•‚ Ž9ÆFd}sIŽîêÑõK%¹´ˆÍq \ xcî¹Ê®9‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQE(œ“JQ€ÉR¸¡$X›Ì|íPIÀ$ôì&¹ã¨\êZæšVÏP†L'ŸUÉBëQøÐ¦£ªéÚEºÜjwö¶P³lY.fXÔ¶ À,@ÎãØÕºçµØõ+]sNÖ4ý1õ! ZÉoÉ,6ð\… ,OÆrIQЖ^wGÓ¼M§h~—3̆]2_µ ƒÃoÛ$±„|H˜äb…Ts“»(@=£ŽxeyR9QÞÙ"«Q°Ðá”àö ÷¯î¸|¸Ln5.|_¬Á¥\̺r5ÆQýÙT[–•cÜ›˜-PI1Éû·…‹(b@qEpšO‰üG­K§Û[¦—Ú¢º”^¸£¤M±Å3¯Þ•Я›ü;²>á¶šŽ©gãÓ¥¨ZÁkugj!±X¤”É.e[pÜT•g/îÜ Ä°¢¨k7Wv:L÷vP}¢X6ÈЄ.ÒF¬ ŠŠ:ÈP0QжÜñ\Õß‹.Ç—0½Òô­6êY®£¨FZ&Ž?-UOïKJÆYƒàÆ€àä•í(®>×Z[x{í=æ¡¢M4º\·-”}вƒ oÎ7m…nË™'o¦·ÑíìÍ’êW6±}¸<ékr×°´d2ùònŒ¶á„Î3È¡Ñ^kyñX‚Æ—OƒO”ÊVinBl„˜`™aa,Ð&'+÷ò|–!0HOC±–â}>Úk»o²ÜÉ´¶þ`)È®áÃ`äduÅOEpžñu爿´SV† ;íZK¦[ˆá’ÀÿÏ9 NÎþvXJ˜ÏÊ ÂÐÿ„ÖóNð/„îmç‚o¶X)¸Ôn^9Jˆ‘Œ“¦Fbçï–ýÛ|§’ •Ep‰ã y5fŽïK‚+eº¶·–0š‘mF”¬Ûï ‘ Û’…‡õûë{‰cÓlŒ‹-´fe ¬’ÜG“.Éd}Øwùš8ʘÎPçhôª+€Õµq'µó5]:Å4ÍY­¯¯^ÙÖÝÕ¬üÄg_8lLÊ©†s—ØÀºo¿ŒþKM-gµ³*!QZë.›†ô2¬±A+ä¸ ó3(-°°¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPHÊ®ŒŽ¡•VR2=A¥©SËÞûºãŠ¥c¢Hlíã‘z2D Ä ³U¬ï£¾{¯)V Ú ±åŠ“íÉý? û׮ôÍo^kÇô3KŽüG Ï;¼ÜÅöœy ”gxämÉéh¬|Wi%ÜvÓZ^ÚÈòƃí„ÂJ$ò¤n~Ev+a÷•R£p¬Ûÿ‰ZœaûCº$ŠÒ–y"LB$tY”3ƒ*6Æeòƒ±\|ÊaE`Úx¡/¥mtRD†YíÄ¢ $Ñ3©Ia×aÜ'!KùDžÖ.µÿ iúå‹ÚMqr2±]¯¹·¦Öb’p†ã‘@TV.«âk=#W°Ó'Ì׬«"‰FX(ǘê\äò±‡aÆ@Ü» ¿ñ–§iSš¦„OwoµKn·Y™Ï-Œnøçºçà¡¢¹m_ÆÃF’ítÍF Zx ƒíR8a3„YvÇ“ÉòØ£ä!K®MCÆvÞÓ4ëwb¥fiQÒª¸ùü©eÉVƪì§+óêh¬ñ]¤kž[KØôÛo8>£å†‡t;¼Á…&A´£Œ²Jà¹wñn›â´­‘Û-¶Ã,~t3a[;Nè]Ó­ÆìŒr ê+šñŽ´o êÙêíÄ'ù±'•$ú´Ÿu¾X÷ËÓ•Ìï®=Ž·®Ç¨Ëiº}„Ë"DÛãFóƒîäîÇ“‘€:ã©Þ¢¸¸¾'hR[4Á'>\¡&X¥‚)<¹d23E#.аJJ‚_åû¼®d¿ø• i¦ºw‰ÙYçI$‰Ü,d3ƒ!ƒy‡äã;—paEsÐx¾Úæá¢‹NÔOïî-"vg¸„ɺ$%†I;8N0X6TS°ñ¡_Øø‡VÓ§¶iâ„• #—EmêÍ&ÄŒäãÌe=Þ*[EAcv—ú}µäCÜD²¨Þ­ÃG*Jž½A#Кž€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEZúͯ¡H¾×snªÛÙÜ)cîqŸóô«4P=7M‹L†Hã–Y<É ŒÒ°,XžqíUn|5¥ÝÝê77O$š¯Øîº—cÅ‚6„ݵz·*˜çæ9Ö¢€(]hÚ}ì·2Ü[î’æ(⑃°;cfxÊ~VVv`Ë‚xô 5®-'޶{UHâ“< ±Qc :/8V ÍÉΕ½„- ´~\m,“’~yÏ>¬Ì*¾›£iúG›ö+ÌÀ9vmª3µq;c\¨¸UÉÀ5~ŠÌÔt Váe¼ûT€.Æ…o&Hd\“‡‰X#ƒ’`r89UKÏhóK-Õ‡˜Òy¼yÒO5%Ø¡°›Ã±m n$1ËFõ啽ü+ Ì~dk,s’>xÝ]Œªj†¯á­/]ßöø§>dF|‹©`ócçä-—züÍ€Ùsc©Îµ’|3£µÜ·Zy¾nýÐK#¼¸!ØBIYƒ6X('{äÍ›zv›—nÐ[Étèͼ››©n8†‘˜ÇL㯩«tP ­ÎïP†úA:\Å·Ä‘o rªá p­771Ìm i¯©ÞjBòÍ{¶¸YfwŠH‡E11)Ž[¢ÿxçNŠÉ_ ifŽÞh§»Š9ZU[Û©n~f¢`|Æl©Ga´ñóŒóBøkKŽæ;ˆbž RV”´RÇæ3HÒûXy‹½Ü…l½€(šÙïüH- ÝÔ O3I·-¿Ö®Â4ŸôÕð#ÿ­@G£iñ}Ÿe¾>Ïu-ä_;|²Éæon¼çÍ“ƒÀÝÀ¨<)¤%»Á wVèì­›{Ù¢e XÕ‘ÁX×sb0B.NV®˜¶€ »»€Àqq.à9ì:W)âÿ‹ðwˆm4{ÁçM#ÿ¥WwÙ##†p9$œ£¹?Ý ÕÙY[éö‰kkÈ“8–$“’ÌO,Ä’KI$’I5=fiú¯öž§z"’-#ŽáÁWWRÛƒ¹ÈÇlb´è¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEP/Œ šëÁ:ý½¼O,Òé× q©fv1°É$ö®>}?No‡^(µ·Ñ`k™­YDv^žÇÍr¤Bn»+ó¸— ½O¥Q@?‰5O¶¯bº"J‘ÓZÖ‘«ÞI«‘l·Ö&;[XÙ§"å[ÁO”MYgÊ Âц翢€*j²^Ť^ɦB“_¤5´R+ÊìSÈàœ£ê+ŠëÄwW¶¶ºv¡ª6Ÿ-Ò$—÷ú`Žeƒ"ì1Æ‚¶å\¦7¾ q”®îŠóÏ/ˆÆ‰©i‘Ë{y¿K’;²Ø >Øíæ,‹68FXü² ˜÷;6Õ~"Þêž7Úð ¼"u*ªÞCEþµ¤cå¦gêã`?*z=Éx5 /ÁZì÷Þ ½ÿV\ÙY¯nØ;¼°¿òϦ7Ê7/F^šÅ·éöÍæÏ.bSæ\GåÈü]v®Ö=ÆÑƒØt©è c_–(¯om:}F?°"›HUØË™Ôa‚Æ>~p²›†Ö)ÔðU´º4Ëoæ*5Ã1„i’éðÄv¨Û rˆq¸òAvsžHį‰ÉÌ?cò÷ÆâùÇä+_í‰ýÉ?*dùûbc®ÑŒýkO4’»¾·¨†f$âä(ÏÐ.j™D—Hàæú×—øËÁ~ñw‰-µk­XYb—&ÞØ¨½Œ´7 ƒÓæá¶ät¨w§iöº}íÚE{-ÕË3y²o+×nNlþ­*ÀðôAoõŠÂ[+R°$<>XUU+€:08Õ¿@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ +Æÿ°QÒæò¯ì¦d‚&•ö%ÔLÄ*‚Ç ¤ðJÍñ¿y>‘Ú$Z¼DÎUåRÄË…ÎÒm+wG·å ¸8Vì(®?ÃRø£W-©Ý>ž­ÙlZÈ*0khZe%¾r´pAV ¸¸F šß‹’eò]\Ks§Ir?ãÙíŸ[†’ÔÄ­!EŽY|Åv?'Èç*@=:ŠÁðŒúµÆ‰æêï¾F•¼–uu”ÇÀýàhaù·oÆ#Q·o^Içµ#U—SÖ."–ém_Ätße[pDªŸc̱ƒ»â^T+‡ïè¯5°Ô Ó`¶ºÕ´g‡Je¿ó D¶Ûâk‚Ñ$ˆË›’cݰ*-w!¸©Ø®—ðòØG>¯¢BÚÛù+a§7š"{ç(†&L¢+ÁøF;Ñë Ôõ½J9/¯aH<­‹»G̼ñÏ¥lW/ÓêZ‡î¤¸ÓÒâÔm¢RÏ=¿• *rà9™.ªË†Ý±€7¿áOú ê¿øÿÖ£þ¤ÿ ®«ÿýjŸÃÐß[èǨ™<ðòYdó8‹±‰²w:ÆQY²Ù Í÷Ž¥bÂ4ŸôÕð#ÿ­Bi as‚úú|‚6Í6åúãŠÛª·Ÿ~/Æ€8ÿ|JѼmâ¼í7s²•µ„ â,á¤9à3Œýâ1Ð1[úwˆíõÝBÙôÙàŸMžÄÜG$K÷É}¼ç‘ŒŽ9‘Å˽î®äõ{èÙÎvGpWØ* M*×NÕ·hÏsxðiw‘áÏN9þ¾ô«EPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( ªZiZu…ÅÍÅ…­´×M¾âHaTi›$åÈc’y>§Ö­Ñ@Q@Q@T´Ò´ë ‹›‹; [i®›}ĨÓ6IË2Ç$ò}O­[¢€ (¢€ (¢€ ¥¦‡¶ÖuI¤‰ü¹LA¸^]¢€,ý±?¹'åGÛû’~UZгöÄþ䟕C4ÂgMªÃÎE2ŠóïˆþÑ|kuÝiÚª]ZȪ·Ö–Ù/~xòzޏ8àò2 ¯áë+k=R4í&ãOÓ­¬<ˆã’"€ùëÎIÉ$“’rMuTPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Š½m©ÜܶÕÖ ¡DbÙ_ñ$š£à¯ùô?úñ‹ÿA»S/‰lcÿgk_ôÿÉ4ÿ?³µ¯úäšlQR3û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­ÓÐsIäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕC4Á,Q<ñù“#@r['òüæ€2³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­¤Rìu>´ï'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾¨òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûê'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾ª¤† b‰ç̘‘’Ø?ç4“ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅ•c¥]A©µõÞ¡ö© >HHL Àö?_μÿãŸü€4¿úú?ú ¯U¯*øçÿ /þ¾þ‚kJ_& Üx+þD}þ¼bÿÐEnÖ‚¿äGÐÿëÆ/ýVíL¾&5°QE# (¢€ (¢€ (¢€$Ÿýs~Ê£©'ÿ\߇ò¨è&ÓÄšeÜ¥DþR¶Óo$ß"]!`â'ï©v 1×ròº3<ø‹C[¾mgNn¬épn“ËeVÄ6p@fU'±`:šâõ†Jš&ikwurðAoe:Í+J®‚âÙÞDI™ÑXì AÈ8ß“Â:¨ñMž¯í«^…ºž[¦³ Ìëm¨ˆ¾ð Q7*ùÜNÖØ@:—ÕR=~!­çMk%Ìsü¾YȬ¿{váæ!錼V!¾´¸ò<›¨$ûDFhvH›Û—\u_™y|ÃÔV-—†¦Óµ=KKäû•§6ž°KidSåüÆ@Àû˜ÿƒûÞ£ng†ôË=~ÖâK[Ûkk lR;›˜åŒ+4% œ˜ÔDß<в0dÝœa@;JÇÔädÑ?í¿þ€+b±õù4Oûoÿ  Ø¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(H?×/ãüª:’õËøÿ*Ž€(kZªhz%æ©-¼÷ZDf’86ïØ¼±˜O^ÜdàUHüS¥¥œ·”餘gû4ÑêGŽRÂî P’Œ¬6±àú‚þ!Ó&Öü;¨iP\¥³Þ@öægˆÈ\mc´2äàœsÁÁç¡ÉÂúŒÍ«ÁªÚbVÍ$–LÖì®°© ”2œ[EÉsÎþ9@7Ž«§-òXµý¨¼vdKs2ùŒÊ¡ØÎI ÊÄv CE¦«§_Ü\ÛÙßÚÜÍjÛ.#†ev…²F•9ƒè}+±ð%¦›§Íimqþ²êÂa3Ä ž] €$lóä±Ï¬žðd~¸5ã݈ û-™’IËEW*CÊÉ“²>Q|¼0SXúüŒš'ý·ÿÐlV>£ÿ#&‰ÿmÿô@QEQEQEQEå_ÿä¥ÿ×ÑÿÐMz­yWÇ?ùiõôôZRøÑ3øNãÁ_ò#èõãþ‚+v¼HüS½ð‹¿†ÓM·º])ÚÈN]È#%7mçÆq“Gü/[ÿú[ßæÿ §JMÝ M${mâ_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáKØÏ°sÄöÚ+Ä¿ázßÿÐÛþÿ7øQÿ Öÿþ€–ß÷ù¿Âc>ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÕâ¥ÿ¨OþD£þ*_ú„ÿäJò¯ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð£ØÌ9âz¯üT¿õ ÿÈ”ÅKÿPŸü‰^Uÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{‡£…³1Çßœtq¸«=õ÷ºÙ¾\8«=õ÷ºÙ¾\Tê#©ŒŸ†:Ï)–ö1Ç' Ê^…Æ=*ƒÌàVL×mšc_XõÄýŽ-a׈ú½eÑ9Ô^>ýÈÔâÌû¤ƒUñÅwo¡qV{ëïu³|¸qV{ëïu³|¸ÍüûÌžÅÄVlÁ\qªß·.úƒqòÞþq‚ç¸eZ °Þ%-‹ÊãÿFŒ"—K·†l‘¶+­ºý@­ñ±Áí³So–PîÜïLVÅN+£8 `Ó69KM¬ë‹j/(4朥ў¾CäÉ4î™ ®å«ÚâpˆkÒv†Ø „×a\:j“Ç–WõKÜ®hçÅYﯽÖÍòáÅYﯽÖÍòã7éþqÌ2¾¬˜ÅUUÜ›Å'°8±Â—Eµå«­¯?lG-¾Ï—,Æ ÁPdâ¸rê¨zà¬æyû,(œåIºLa¥Íá'¹ÏÌAžd[Æ(ÄîÆ7{É•òÚì1ÌRFÞç5+$:KlÖЫE|q-Q`ÚuKú0ïgÕ°Y¼ŠÂ¯P+pQ02ìGä\­A œUžúûÝlß.UžúûÝlß.22YÏ͵_d¶Ì2yŽ<¢ž´í*FÑÔq€ÛzH –ÅC’ÊäY#¯$i­¹òL× ›¥¥ôµV}DÉ Óxm­fKáÒV6¾§õŽa—8óÆOÜ~7öeê>Z¼gí#½[›Ùó³Žãv†ã[ÿ<áG ·óu~úƒqÿx@Ò*Ï}}î¶o—*Ï}}î¶o—s‘\ó8õQÃ1šyUFçóñ›ÍXU5Bżã3:*TÕÁšÏK<®6èù†ÝwÁÕé4kEñ^Wƒ\÷+S¶³ífØòÆÎàã³7¸9êù²ñýúOº²[†Sˆg ÷¢½—SwûU’ÍÆºÛnÚôºçZªßB:2¹·Ñ0jp¥ùÕ‚jndâDÅq â¬÷×Þëfùpâ¬÷×ÞëfùqE䫌±jÛm×Û/ ×™•8¥«Œmîm€«ˆó<‡aÖ“SÌÝRŽ*¡ò!½ìiõ—uŒñ¶.ÕýŽ(\ȯke>Õ¦¡qV{ëïu³|¸qV{ëïu³|¸ç¦/ó<ó²FùÃ0²[|Ý/5e[kÐÏ“&üšmmqA ¯`Ñ´s(ž™®ÇšÉ#5ci³É ºk`<3 W9€[ºM› ^”ñqV{ëïu³|¸qV{ëïu³|¸ùåæù祯rcï ¶È%,u-h“>¥8«1øôrõlX‘¹=^óDÂÔU‡»ž_eä\‘=€¯’M¦ÛÝÐjh²»<´GRFã¯O{7zM·Ьtå\Ë!XâTÄJÓv£%k¤Ñ+†ÂŒÝ¬/jŸ)Ù ëIy2Úl»i>»WÎUÂikt2‹cF£©&Ù <â¬÷×Þëfùpâ¬÷×Þëfùqƒ¹sÎß^ÖU>']øû8««K/œÆªÁü–|»˜g5Úú6¯ZÁÓ½´gQI»…O/£í:Ý<=#ƮȑmnŒ¥Þ$çzeuÕ¿XÉš¸Ë˜|QO–^÷¾R3zâà…?Ãl ¾É¬æiúNÆÛ4Ú°¶"°{9ôªÛžšR8¹ÆSµ.~ŒË£È—(|ˆIÛÚBôqV{ëïu³|¸qV{ëïu³|¸ç¦us¡eÕ“‚8ÊÝ•æHD޼ªîú?´Ë4™µùÞf³§Uq;àSs\– Æ¢ïNù/ˆ*‰oü‰º¤Õ¡$×xéjô›© Wâ¬÷×Þëfùpâ¬÷×ÞëfùqŽ/λ™5ÍÇŠx·&¤,[6g¶kãÌ…ë{¡ØK¯äv<úÁŠ8×sMÄ“‹Q£Q.1ËÇeu,áÖ1:Ðz^#.Òí/yÏkI âÏ‘öåY7µò‘òâWŒøcKe¬ý´¾§˜Øº5õ õX¾åRæ:ú OµiÉŸë­ÜvIɨ§mÙ+žªîWÅYﯽÖÍòáÅYﯽÖÍòã0ãÜèx-@¡Ö)¬rf´˜{&ÏeNQ蕌ô6+B¤ŽÐÙ•†¡cl9J}È”½…ò)&©µ56nF#+³­~‘ѹb]©Yf®2ÜvM}QW^ñØv¦,ÄóVÜÛ£¯q–pü‚3²úÙö*ÖÆ×ÖŽˆPîkË“u€‹éúKŒU"M-eaz8«=õ÷ºÙ¾\8«=õ÷ºÙ¾\sÓ:¹Ù2êÉÁoû÷+*&HDŽÃªøY»ÌÖ;kó¼1fü]UÅpí×-Ñ™,AñGGc—¹*nè2&ï¢uÐC®§¥¤ÒP…Hj¿g¾¾÷[7ˇg¾¾÷[7ËŒUš9kCób> ß3=¼buV]2f×zNeÑm?$©¢ò9Â9 æ·™_YÖñVNZáï(;¶ƒÜe|¢Zžu­¤¡­=F©²À¸_XæqŸ€Üdýøãf^¼áå«ÁŽÒ;«¾]Ÿ;Gn7gž7õGó>qG7«÷¨7ã÷x â¬÷×Þëfùpâ¬÷×Þëfùqòí]óÁ_7U°øñ}ÇJ6eçi€ópµWY ‹Ù¸’ذãoº;;:qKQ¶!ȹ҈ìÏU gÐдý¢®+¡“ö]·H¢›E¤Üñ\ÛP¹$†),Éæ8ë¤7"ݱBv©Þm¡×7³Bõ º‘[2e¯ÙˆVÌnÊ$ú‘K"tù¬&È+ëUÖ2}k©lµ‘@×>*Ï}}î¶o—*Ï}}î¶o—¿psŽa• dÉê«RäÝÙ=Â~+:"¯-Y]mGqÍûn9Rvƒ¹aÐgúƒ7éÓIC/§0?ÚaZÙ*SÑ£Í ü;+©ÛbΤ,ì…c†Yt³å@Ém±¼D¬m4Æë¢Ã©\Ì&2½v´A†¬R¢[ g—ÜnÚ5=_$ž@"Ö„Î$žDžƒO8«=õ÷ºÙ¾\8«=õ÷ºÙ¾\f3§”•Ç‘ Ù ÆÙTP pù5¼ï:‰XÕŒ’²bL“ЦC­[Ù0è–îÇrÆälŠihüAÙÒ½ÃI†¬Q.ÙÖlÓ:sžá~§¿.y]¸ùˆbÛå}ÈFyý-|À-Š•}±­ЬKèibÅy!c°væL{Pé6u¯‘hò¼)jvTž1&Õh <â¬÷×Þëfùpâ¬÷×ÞëfùqŽ<5VÙ‹#¨,8YØuH8ÞŠi‚)j²¿LâªXtÞ rØK¦µdë¾t„Ï­aΊòB³g±iˆem;ˆÜ²Y:zÆBÅ#u´ø_”Ì9™Õ^A±C'ÿ!yÌFm ²bDý+ŦÎ-qû¿®8¹lÞÆ –ʶ¶žô%kbï z2äˆBôqV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞙ՒyudÓœàÚX§d„.¯3+¶OÞ_[_•LØ»^nBNoê>ʦ)vøòš:c«/¸Xë4ðjŽÓ·-蜷!SÂkºÁÊ _ʬU] ˜h®nK·¤˜½É||â¾eÚx¦i:s€Ëf”’8Ýž½Á½Û±!ªe#ke|»çOÌ“¸ôÖ¡¢P5D –üŽLÿsÉôëhòæÍËèÝ{Í÷Íå,1±Q¼Üyõ¯š9DZ;‡:Æò _NfvÅM^±ýÆÝ¯ ´çï÷Ìžg¥j¡¯j+„¶c^Ûs(ìkcéøòËõqæoØßþ”×Ö9ýaÕ_ØËí“ÓŸþ^Z¿úŒB-îl¬âv ò!DfÞ¹Ã'ùEs®røJÝ‘QÚbgyã*”ÉXYÔ×\:Q©Á‰Ãÿ]¨vBé!“Wö ©æBÒŸNpŠ!‘}h€>n,noÛan:PRj Ÿ)9%QÏAVsŒX˜÷&Ë­„È»¶ {] –ÙR>ܰÜꆜ‹²X6™çîÕŽ¾JÈëÔ JêÝo[Ó”gRïaF/“Æ÷nN½#gïs+\}/M`ëVý=E{šÓ*¥˜¾ÃIM"™ƒdÕ•¥s1ÈéZ«vÒg§ãrÔ$JDÚùC2u’Ä”&|~ˆhɵiGßI4P ruiÖM¶Ù¨±5‹|¤ó+lSu Û`Êò—œKnûÊÇ æÈÀ$±›ëÉ$8GVKtœªÕ±èm#vJ¿>_’÷ˆ¶›L.Æc|¾aËëäíJ¥ï»u(ÎYVs_ç[Œ¼ÇëdØÝ8œÉð~q¬Y9DS9qÇëñš–™TjyX^0;z¿Œ-ÝHÂdïï‘xõõu˜)|Ö®ÚÉ#+êöùµ¹ªæjè>o$ØéŠý–dú|RÃüÀ¢+<•j³SWœÞYКÏU’h¦7™£“ßSŠO,GnÔ]…Ö-u^_’)+”J½ºã -/Jî5n XXßae ¡|ÆßËÙ!XSˆnR¹Ty¬×Íljðhœ6yЬ*{t®Ÿ/‡M‹;!aº¸ô®ØjA4Ò§+Õš Ume—=^8ÜùmÍ—’ØùÞ [ö÷F#¼1X§[n¥ÿUMŸÿÏógÈÜa@ŒFÞœÿÎoHºWBèHºK‚”‰5õ4‹ö7îž<ݹ/ƒx×VU•Dó"êÜÈŠcd~§¡¤“Jöô®X«)dñ&­c¶ªÊrˈ šÊ#K¤S–%ûlR:¶›?¤U¦×Hh®nK¶šw–•߃—…+çi}Ïú7%Óó€Ëkœt«#r­· ñÛã3.WINEÔN,0ˆöƒÅè‚Ó{›I¡ò›nL@˜¥ó§àË/ÕÇ™¿cúS_Xçõ‡Uc/¶ONùyýjÿê0¹9¸ó6WÍ—ÏWŒßO·òÛ6ÕÈì|ˆñªKÄ bIãLÙ–e×ëg)£N›¯åÎ{½6zÊ“uOBVǠཱ"ß© Åþb!Æï¬¯œgbèåÅœ¢¥rç²ÌcSžj…pÊ–ÉÇ-8Å?bBs.§cº"vƒpU±É-„jÛ©ûñúë‰Æ!©‰>Û­ìViàNTåoŸ~e@WŒvœCœ!šNM†ò¸Í³MêÆï8Ý‚ ëfÈcÏŠìl¬l­i5\š]¦ £¨&h6“¬„(‘§V—S[êØó›<Ù¹}‹ÿÊG1§Oš¬|Úغë!ÛÐZëñ>6ÆùjFSé¤xqt…>m:Fu!±•[l.6ñ$wiU¯!oˆr;JÚ¼<ˆæú¿/>nžqøÝUÍí8 ²‹*û!PÏps„©Ë;žüu¢æõ„¾Tã'ŸÚ¶œÊ¼…B*4Ч0ŠåEÑÉ3´¢±·UqWjèA¡Ë>¦€O˜)‘yŸÙG`Cclm•EÛÌOvà¤RÓ“J™FÛò.ɺdÏlq¹ }©SÕ–‘$mé,‰ÚTÛvdÐA¦¡5KßötÙµo×7Vç¯0—j«Öªàô⛤)ºkZ*®s?+á]Kƒ>ÈßÔ@Ô>BúònÇ-QgÎg½.¶Ù„ʤΑ)Ä–QUW—x>|9ÕY1¢[ÎKÍB«(&{ËFÓLy±&¿ ÙIqã\qhÝ»R0Di9 ºn?ØLov¼ Á+´^)@Ã$‰ê98¨hÛiÙ[£ôø¿šâ”_æ=svÉ0…É'áÝ3ÌN«qòýÆ^VSV,îü–öÑl­©¹{ºº¯¥Øzû1DO¶,V ~²g¬«ÝeXÞ]%ˆí6Ds}_—Ÿ7O8ünªæöœPYE•}‰¨g¸9ÂTåÏ~:ÑszÂ_*q“Ïí[Ne^B¡ES˜ENò¢èä™ÚQXÎÛŒª¸«µt ÐåŸS@’éÚ<š±yÇ¿Ê$Æoøð&ª)­îê}ÞÞ®@Ø!;ÇÔhùÔ}yÔ}gÔýtñÕ+¡u£‡Ðt½iÃe[E¦sË3_B#–©ºüOž1DØZ&v>ãµk1B·òPÞ;ä¿tÔ(f‹ï çßj×Öniè‰5vôv¦à|Ä߿׵ÕýíXÿã/ßëÚêþö¬ñ‹È<ï;éòËæÛ:Ä™Ì^y•s“ƞҶا‰CÙ¹:©·U½š>ųnÚL­£U¹ƺ5N+¶ôµ<:;¼¨psW ú¾™¾Þ3ÛÛÄ å¥´µðgïï ¯üÜW³zG2ÚÒ9–Їý_LßoííâòÑõ}3}¼g··ˆËOÂdzkjrócÛ¶ "«¯#]¼3ËXÆ1u»ª&ž¹”I—µ±µõ£ã£k3wN]¡Ó]\P·&úUjÓèê{q™4nkL¡²9lBZÆÓ&ŠJã.È£rhÛòî¬róãR…moLoMjÒ¹4»6ªRÅ”ë¨ÖO­§©´¤s- ¤s-¡åý_LßoííâòÑõ}3}¼g··ˆËORC&Ä'u•ÈXã-jß#1”®Rd ¨É&²F˜l6÷pj×Ùû«¼=iÔǹ/ïG×FõÔýgÑzÏ©Ý:Óõz¿¡íâ‘̶‚‘̶„?êúfûxÏoo/–«é›íã=½¼@¾ZL¤s- ¤s-¡ú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–“)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤ÀðݤѶñ–§É +¤ÕñDfÚìì¹|¶H’7!™*FQ¬Q¢¡ùñ4B%+•¨ijÓV¿F7¾j'ÙkerT™Hæ[AHæ[CËú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–ž¤šM…Fä3)”…Ž%‰1»I¥r¹3²Üf6ÂC«ä†Bøê¡#[++ZENNÎÎJ“ n@™BÅŠ4Sèêjlû‚‘̶‚‘̶„?êúfûxÏoo/–«é›íã=½¼@¾ZL ¦M~_&jc±½:BŸÆfM­.ÈWĤŠãqé’Xô™5Ê_Ä%±IZv—]4‹õ£rhóæš}¦·¦ÕJTŽe´Že´<¿«é›íã=½¼@¾Z®ĘZÜŸ2+9Ù™Y,uxxuÈJé¹­©­¹>¢Ç''ˆtR!@…&޲¥‹ki'LŸKS__ScKckk’~T¼çþË6û“ÿb"b"+OoÕ6‚b"+OoÕ6‡tjÀø³Ú F»ÿ=•!Uô¿A¯Ç8Fíý¶¢}_û% :ZÛ?³­¥©±ÿ—§³ü¿³û[?˳˳µËè}_LßoííâòÓ¹Hý­ÿߌèôR9–ÐR9–Їý_LßoííâòÑõ}3}¼g··ˆËHäú󤪙%w ´n*²¶—ÛÏ›Qšš)>°bPé%¡$Ù^ÆÕµ®ØäNíΓWÍ—I4m·i¦4•Í"ù >Tý!ÙšŽ¦)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤À G2Ú G2Úÿ«é›íã=½¼@¾Z>¯¦o·Œööñùiê'“FÕÉ¡©d,jeì,qé3äQ;² i#,nZ¾LÕ»1é¨Útnc“:B¦M±çe‰tP=/‰I‘¶¨R¡…×M!ÚMa_j|±²ºM_Fa­®ÎÈ—Ëd‰#r’¨ôeÅ*ŸD"R¹Z†–­5kôcq™ æ¢}–¶W%I”Že´Že´<¿«é›íã=½¼@¾Z>¯¦o·Œööñùi0‘̶‚‘̶„?êúfûxÏoo/–«é›íã=½¼@¾Zz‘™4nkL¡²9lBZÆÓ&ŠJã.È£rhÛòî¬róãR…moLoMjÒ¹4»6ªRÅ”ë¨ÖO­§©´ŒÉ£sXÜze ±ËbÖ6™4RWv@ý“Fß'ucÇŸ”+kzczkV•É¥ÙµR”(§XF²}m=M¥#™m#™m/êúfûxÏoo/–«é›íã=½¼@¾ZL¤s- ¤s-¡ú¾™¾Þ3ÛÛÄ å§6K‹4âôÉ×7e&sº7­ÐÑVͪóˆ:5¸£Q§³¬•sk›{”(èmì(F½tŠÓêi¨M­«£©±·µïß¿ÔMÕýÒØÿàç‘AQ4¯÷K\ƒ™…"±äaÚ4)ˆ§#Ñ£ÇìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡ ìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡ ìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡ ìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡"C†PG=-­vÛ÷œ-ÃCcS—GoY ¨Ì¯KgWggcokKkSB-©±³©³±©§·Ë±ËËɵɳ·±µËÉü›\œ¼¿Ù؆)ößÎ/í)·ô™gи¸6UÛZí«Ö7ëíϹtvõª×I«µ¥µØÛÚÒÚÔÐÛÓÛÚÓÚÛÓÓÛåØåååÙåÚØØÚåäþ]žN^N7cßlTä1æÇ·n†š®¼ŽuvðÏ,{ÅÖî¨XšzæQ&xkckëGÇFÖfC¦º¸¡nMôªÕ§ÑÔR9–ÐR9–Ђv!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“'uÅöÅqìzŠèiµ+ÉXîôò¸±‘Î!½P깉۩¥—‡F7N«|krfqè+µú«ræå?D­"9¾÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤ÏçÔÂØ6Š´TßüàèÕ:(ØHߤ¾ÚaAÒÔmêihòiém¬Œèiòÿ&¦¾ŽÎ¦×.ß&Æ—Òìrêmllírrë{¥}çøÓ—™+!Í‹ä~|x{ägrÆF¦ŽGw5®\M{Q×§}¦ÖÞEšúÝÓ³³«¦Ò4¿DŸ•ÅÍÁo.ŸIZ§WQHŠz|þ"¿õ‚‘ôùüEë—õ}3}¼g··ˆËGÕôÍöñžÞÞ _-:Œ»Ò¹?Þ¯‰) Ri4n̦R8”B$Æí&•ÊäÎÈcq˜Û ¯’ 㪄l¬l­i9;;9*L¹e (ÑO£©©²¤s- ¤s-¡åý_LßoííâòÑõ}3}¼g··ˆËN\g>Üs6jâ¢ÌLYµ,9Xîô¸È:–q3}ꆥϮÝMŒË:­­ÉåÇ ¡×èMMËœTýDŠ5´í0¤s- ¤s-¡ú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–“)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤ÀðÓÉ£jäŽÐÔ²52ö8ô™ò(Ù´‘–7-_&jŠH]˜ôÔm:71É!S&Øó²Äº(—ĤÈÛT)PÂ릑Hæ[AHæ[CËú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–Ÿ‡kn¾Ý^ Â7Ÿ~8e»›ØÃ×ÜIá·x}Ôý?¬7ã„Ò®éô~¾á·ïÏ@Ýó¡7Že´Že´9|‡ Q=*$y#œìû‹ùš¶_ð …Îs§+kRM–Ý¥NköÚÝu¡ÑP£I­±ÉËSOezú2«é›íã=½¼@¾ZW»ƒûSaßÿðé°¾Ö¯§¯ß…ü¸DGOiýDþ£B":{Oê'õ8oÕôÍöñžÞÞ _-WÓ7ÛÆ{{x|´˜±Úó¤˜mˆÍ ùqUŒ·”ÕDšL;X1&ëb[I£!RªC®–;èËߘÓ'‰JõÔ;53«A££êê(ÙØerÚL¤s- ¤s-¡#ú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–“)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤À G2Ú G2Úÿ«é›íã=½¼@¾Z>¯¦o·Œööñùi09-ûýDÝ_Ý-þyŽe´Že´<†¼N©ß¶Qí°dÖwÈ4\´6µªÝ‘GÔn¨õt:V‚æ•­, : P“ù¥^߬¡"”œ»*“ëj'ÚÙÔåv!Š}·ó‹ûJmý&Np»ÐlwþéaŸðÕ9þ¬{튜†<ØöíÐÓUבήÞåc#ƒÃºÝÕ O\Ê$Ï lm}høèÚÌÝÓ—ht×W-ɾ•Z´ú:ˆˆ¤M:~¶‚")NŸ­¡ìCûoçö”ÛúLv!Š}·ó‹ûJmý&ºk2)œŒÞ>Ï™SXÞÛÔûÝÁ«Æ+gî®ðõ§PoäÊ:¯:ë©úÏ¢õŸSºt/§êõCÛ÷ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“;–÷JûÏ!ñ§/27ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“;–÷JûÏ!ñ§/27ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“;–÷JûÏ!ñ§/27ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&~zØMO¥«¯¯zs‰èhhiíëkkkY­zzZ:Z{<»zšºº›qM===ž]½½½¾^MžN]­®^NNN^S»ot¯¼òró%NË)”¿i>¶mJ¤›M¯ySJ·¼·í>9ò¡w@ÉÑçAšNU_@½&ƒ»S[®ŠeZzº:nM¨lllªFŸWMHŽŸ¨ÄˆøéúˆüC!®m¼T‹Zöi$'&§<¬2צ— |žù®Ÿ$/¨ꦑ¹®nÓǹ.ÏÓ¿é¹r¦[¯"\±Õ"wUúmëV¨lF8•ûý{]_ÞÕþ1y5í§:r²Æ½´çNV__V¯þ ýýá5ÿ€›ŠöXKWÿ~þðšÿÀMÅ{7nΩksS—8lšc8®8—'ÇÜ!Ï0Ê=Ȇ‚f²gcX·¬g34hÇiÛÌ20ë8uŒC0Î3}KÐ5TV4-ÊQZF2 Z¢yOݸE”3Œ,qcÓ¶vEóJ½ØªbЄPhe®Mgg|ï‡Ø,2¸ÞËÅm‘nØâÙå9)lŠYu<’J×dHá{ŠËËäúÓrã1~nâ»6Óäðž¸áõ•Ê«;ž±ÞN«Ó–pªï¬Ÿ!öý[¾ìÈ'<>›F÷Þ+°¢#,ëˆÂõí ybœÄÕ=»F¹RlnÕEøÆÚÕtÃ^&/,ç¶ÍeË9m‰Š§9·G¬‹ztVö_“ê—md\âI€I¦V‹óým_¹F‚¬eµÑa6^mi¦âÆáˆ>sI£q© " )@Ó$Èu‹:®´d)ùd±·eOŽq Ú §v××Õ_[I"Í3ºÑDBw¡Ë$Úœs[WÒØU-l¬’Þv¼Û0³Ù¥UˆÑI6 Œ¯‡göV±È¤Ìz•5;Wº(|µ99fSäòG) mºIµ´–®VÑÙŠlöø¦â´7ZT½ª¼|pž>cÔš3˜Û7%…aX2LR¶ÝX÷!ŸØÓëK;œ>V3µÚ{,îÒ¹ºõÐfH…Lø¡Ö¨„C¡L]¾K×µ|’Ä“ÁŸTZO›2i\bo9_^§’k/|y|ªÇY"êÒ±|œI$² …žíZDâKíiËÄêÉQ*—©Ô{å¦pÜÿLßïË"äó¹7¿Ó7ûòÈŸù<Ÿ1Ú0Ÿ1Ú0îEÏXÌnÂÑÄŠ¦Ô1ʱÆÒÌ(Dg##³” ë×èÛ=OtØTz~µÉ>Ò&æ96h±v2ÎÒ­rŒåâ!G»'•3ÚN)mú!=e[\pÇšâݯ¡¥y#êíáØñ6Ä1÷ªP¾´õÌ^LÑÓªßÛ^[ºr~„êÜ…Å7Ñ+HŸ[NªÞ«t3[ UYøÃHIão±àxÓ’oIŸ+ œŸ ¯Ù퇬ãOòcósË¥û ï;%=ÞÿJäD"_cä*¼ÀH~7Aa–½lënЯ8š¦˜È d·n<‹J Né7dKE®ëe@æïÖ á E3`NÚ—La؊Ы p%¯%·=Xøð÷_ݶí³r^—lgEú /®œáèn+¦ÀŸYz•f¤n}2×MN,”©©Û¥²'+ ¶’ÀÖä“ìøtÿ7P¶LbÕªé½Ý“×üXáKZÛÕ•ÖÔwß¶$vßgÊjc9¨1ó~œ95S½pV ý¦®qTÝ0ìæÎ¬)+Zy›µ擽m|«âûw¢we:çFÕPÈd}úYƒ¶&TÁlÚ’Anf°ã3†•t:¸Ý¬‚m-²«kÖјɫªúƒchƒ@bÐŽo«œòé~Ã{ÎÉOw¿Ò¹—Øù †Ã¯0ÐXe¯[:Û´+Î&©¦2G™-Û"Ò‚SºMÙÑkºÙP9»õƒ8CQLض¥ØHö8ÓH®8ÂX!½1‰=GÙñ³xeJ¸»tÄËž­|Rá+èU.ˆþû+’tž¶ëõO'@Øô‹ˆSüÜxeBÙ1‹V«¦÷vO_ñc…-kl;VW[QÜs~Ø‘Û}Ÿ)©Œåþ ÇÍúpäÕNõÁX4ö˜V¹ÅSthó›:°Î¦»³.syauÙ(Ë›¾aÙÉØ+iµ’Më˾Ä+tŒÞ·E}!ŒZ9Ôý&O~Klçí9†uW×9å©y¯± iî÷Ú±¯œZͧBøy€xe¡‡tæBË1VÇQ¼o9ÝΫwÇ ò‹÷ˆz(u#ö«_ ±ýÒ¬ZÝ"Wp¹Ç 2K>C€°xUˆùQNÞ³ ÂÛ¯í8öÊõkë« §›?ÞàSUôO‘Ôó¦8Ô½µ•ÞMXHÜù Ö¬m#µoa·½A%2&g§õqá—øóÁ¿ßŽ7öšê>!Ú¼í#º»›Ú³ŽüöyãT<â¿ ·óz¿~úÿ~?xKO,®!“‡êÊM(fëGÊrp¾Ç®u‹ª-Ü™ºVÖ D¹ç£7.H‘ßéëËRyêçÔîZ]{ÖÚ(tßÙœ›ƒ óË"䙂×ô/°ùTm×x —7ÎoCãÒÕúëà– ÈZ'ˆJ&íˆàËælk2Öž¿]äÖ•VæåšFð‘Ú·žF$TnZ±ê¿û™qóžL²5ñ=Þî“'­qBÀëÊóctÖf’Œ¦rNÄfË)FJä}”NœRÒ»V®8ã·UµTp6Ö¬yuaëÉØ’ì$‡i‰\W#¡/ðÞŸËn¼íÙ¼2¤¼@ÞJb_ÏQ>&pŠtÚ‚¿ˆÄrUÆú7TõúO “¯sz[Ä.n<2¾¬™=«jS{Å'°8OÅf´V«­¯?mÈêNÐtÔ:rÁPdâ¸ré'eãTyû,(›"ªzLa¥± UœÕ¸2Ž™Ùw,–O”ð|n¯w5þ59ÆÊŸï,wƒVÚMQTòɶiUVNÚ|ð—î…”¢Â‘Ýi0ñÒ8ƒÛ ÏÙt:Ún´¥LüBéY“U¶Ÿ=NQY%ÂŽÌ{MæÏUrÓÕüîqºÔœÚ˜+fOáw›¼¿elÝL"À„E«¸g%%¡¦u›«ìÒxû3µºt:)ÔÛ ñê×™¼Î&qÉÆª¹gWq%»¯8 CpusRÞ×h¨ ‘¥o޹†4²WRÞ1À'íWGãulï+ÈãeÞCŽ4Ä®+‘ЗøoOŒe·^vƒlÞR^ o%1 Çǯ稟8E:mA_Äb?¹*ã}ªzý'ÐI×¹½-ÞT¼çþË6û“ÿb%´*^sÿe›GýÉÿˆ±O´öŸÂO´öŸÂûHý­ÿߌèôèR?@«÷Ãã:=*³:KH¯‰\‡gRP\tʘÞE>CX3[åúQ¶[µJøÆ>×°Í=ž»Yú¹–±ëP)¢Ž :ȸ]o~–äÆÐËjÖ´hÆu³¦1Ѩ´rg2±>iÄ©Šk˜Ÿò'q~Åg©ÞkÞZõ†§ç q£*[]Ãf ûy.c¯¶á¨¦Šõ£"šrí9—M›¤–¤Æ¿Ñ…EâÛCcáV2ÚÓ7™ü¶´ú <Ç«´mU©•X5dS;RóD_(c5œª#ÊxCLaÜA®‘lö|1ºñ)‡#bÐŒLem/>Û¶%c£ÂøÊ­j±¹®-V(£4àÑ¥q žUImFä1ªvҦ⎬ÕEËVC˜%Òôuµ}mÃf±*·Z_,r®Z"Î’gÅ«Ã,¯©öna6o ©W÷n˜™cã/óÕ¯Š\%}  °%ÑßerN“ÖÝ~¯éäè‘=ó}\|ç—KöÞvJ{½þ•ȈD¾ÇÈT6y€ün‚Ã-zÙÖÝ¡^q5M1<ÉnÜy”ÒnÈ–‹]ÖÊÍ߬ŠfÀµ/o£® £‚dÕ#Ye|Ÿ)ã’ËˉLh%Õ>!ÌpBwdÁë÷k[ Å76Ñe9ôzLO¶>«Îµî/Ó¼r¯lØœÒ"ç}j£–A-5?ÍdžT-“µjºowdõÿ8RֶõeuµÇ7퉷Ùòš˜Î_ê |ß§MTï\ƒ@ÿi…kœU7FŒ;9³«œW_UDÍšq ŽN4•ÄúLJq)5ÝyϪ¬Z—FöxEO¬‰5+Cõ41ÙprÜšºA$«aýG^Hß#+Ã,°%fMSÔ¯2“ÆIoåA“t…mFL1ñΞ¯Øá&¤|ßó\ƒ§&•$Ù“gFßlœE[ñÏbkrÙóûnj:ÙS|*G7¶Ã!1¦'»åÆKÖÔÝaYå‡ef6ng¾m ¹‰EUŽîíÕ·åêÔ±ígdñ™D]xÑHh$ªã[rª: ‰)Y»0fú‚Ê¡ØÛ'6vÂG±Æ˜ŠEqÆÁ èŒIê>Ï›Ã*UÃýÛ¦&XøËüõkâ— _B¨, tG÷Ù\“¤õ·_«úy:ǤJiŠ'ªxU Ý^£¤),qkýá•>tZc÷ûƒPßÞ7ǧÜî'ÎxT}4ªCן½OXÏÕá™Ô-Ó—Ù±$¤#¹ÇÍhy³°Ÿ0$°Ø +œFí ‚Ìu÷ÎF›U¢á(—¥ÇJÝ>=/jÙ¬êi]OpKÐYÏš›Y'tޯܒ߬±æwáÝ»c¼ï‡jbÎ>XóÉW54uìÎqRÄdÒ‡ž©bBÖÆ×ÖŽ‹—us3ksR/§èÍÈR$ÒÑO§Ar›ªb®IL*ÅjeQ o^q:ÇyÜy}JÉclëáú•Í}qJéW+¯6ð÷]®;°ŽÁÄl…† @ô½»–ÕªäžÒšµ$Óe¦»9ãv>cæñïi ¢šÞî§Ýíêá„ ‚¼}AÖG×GÖ}O×OYÒºZ8}KÖVýþ¢n¯î–Çÿ<Š ú‰¥ºZãüÌ/ßê&êþélðsÈ ¿¨šWû¥®?ÁÌÄùŽÓù„ùŽÓù‡Z@ ÿ5?ûÂÿ–ÌÃÖŒÆææ:®¶lyÕÒ–ÃØ,›ܤ­(4×Ǥ–½©wCsbCV¬PŸECóâh„K â–K²MG…õTnycJ¢×’4¶.žæ§ÿx_òÙS®\q¦/ÍÜWfÃz|ž×>²¢²UgsÖ;ÉÕzrÎ]õ“ä>ß«wѽ™ç‡ÓhÞûÅvDeq^½¡HcÝíqß•ÌòÁñ¦ÇÜðžÂ9¯¢ú¶Í e©Éþ%5dæWÛØ‡U¾¬ˆÝU¾׎w}$“F~¢ ­b»hÃ%:®ŒÚSÎJÖ ™£ÛUgs–×tþO"“¿Zp$ókOê,G»²öµÂ‰]ÛZI2à ¡øÁx®z†á¾¦µém‰TNä§”Ì"5r÷9lÑÖ :m±¢-5‹o×/6îêC/8Œs„-ŒdÜ"ÈTî:Ò''[5~ë4Åg<™{Ú™<®ïE'°$ÒõÙìð¦ü™ê³Ld6K¬ž)vd"æãÃ-Û ê§šoˆŒ­ê^Ñ—‡jÝ–M±ºŒ-‘È.óܶôæmoíðͽ¹EOÐg(¸Ný¡·*®7^N¥SưRFÓÌÚE’”SNUñMñ¢qÍ,£.+šª•ÌàÌ9·œNX­mVV|~šn¤+Ëj¤’¡ÉׯbTÕ’ªÔFSØ:‘È|ùŸÜÕ¶ò¦¸’[jœ²UòňbÞ}aŽ´1ËjêmºIzFòù~jYŠ•Áᵕ›^c¸#Çtç Æ„•õÛ;•뵑éߜڴ.ôqZ½A:JÇ^>::Z'tY™ý³rZÖÄòÂÆù$]D8ËîKBÀ˜Zò:©þºŠ,‡BfJ ÍZ)Þtã|­r¹b'¾¦íŽ4Ãæÿu¤7¥q>ï¨ò:sûÃ*ÐëËž‰à— ¦_Íß4z³u{9Ó_»Ìý_|ÜïÞ67á•uàcÝ}qóžZ—šûžï}«ùŬÚqt/‡˜׆ZwNd,³luÆó Üà·|qª(¿x‡¢‡R0ïjµð±‹Ý*Å­Ò%~Ï’•Í{EA+ÌÉ´ôöòC§œN”˜>Oªüh•ëE ÐÏ;þtý]¡ŒRµÒvûNÏ—ÕQË/jE5ÔŸW°»a­]–¥UFéË1úm¦?WqŸ<ýøãi®£â«ÁŽÒ;«¹½ û8ïÏgž7õGóÎ+ð»7«÷ï¯÷ã÷„êm¸¡D³ØI¬æØ«âI#u¦ºîcmز,ýªö+l=A­ÚîW:…Tz“-º¢ù?`¾mÇ ?V% eÑ´§3W BÄÑ“Yi¥¨ȯ‹Úª¯n¼Lv¶&Ù‚šÓ©jìºß"Õ†µ…0©óZrü×UdþÕA1ÕWÌ@`ŽdÂë§obfÖ±`Ø >¼§ÍTõ[k£xkIHWãå“`gÄO%,ÖÊC’ Ç BÁ®q…¹'éζÉÈ7*ÉuÓmKd ¬1Їv#R –¾Ž×Ü“§é\V}f½Ë,(û{þpšïê$×ðÖI´ÞÎX¾ ‡¸ÈW«rpTÚŸc]:ÆÔ¨Sië"Úéjº+Y¤ÐÔÚ“EbçGEèÛÛ-qR‘6¥yú°sÿ¼ÿû6÷裹züSOì'¯Å4þÃ…Uù1 ÈIõžÝZGÐ6×Õò›3îš¹2§IS¤¥4‘[òÅšD­Z­hõZ‘³6¶ì4l(ÚPÕÛ]ÕÁ#³j&¿¶ŽNýáÆ/ðb¢É•³¿¶ŽNýáÆ/ðb¡Ó¼þ$éÞ¶’ïJäÿx^¾$¤w¥r¼/_Rr{6¸†\uµƒQXìÛÇ^Z‰eqÞWõ1¸|2ÜÝìëÍ÷ôüɼ;˽_ýe×oüüœYµÄ2ã­¬ŠÇfÞ:òÔ„K+‰ä{¬]Z:ö8a_”3u³æ·Æ¾´ct\‡¬Yœ›Q}?In\‘^–Š0ǯôðÿõ¼ÿúÝ›xqÎ4Æþq7s~8ßÚ;®÷†Uýsön싾][×Qýž£íÞè«ÿÚΣßÞS·RîíM‡üAÿæÂûZ¾ž¿~ðfâ„ÜÚ›ÿøƒÿ‡M…öµ}=~ü/àÍÄyïú„yïú‡=2[é_°ù¬6äÔ¬Ý «®îpíI¾“<)†PHRiÊóut:éëGöë+N²¼£òä²M^™xÆ™%jÝ ŠhÖIêËOZJ{&À>磔I­:š!nlÀiÆ K )'„bËѦH¢qe¿Mõ,îrÚÚ´½µ%oÖœ)­Û"ùµ¡Ø»hfk…›a³[ 2Ö²¢2JaDðjßÚª,š±¥Íò4ñ¦ÕöÆÖ»2Š5Kù!QK!§L­Œ*Æ[ËŒ íZÓ{ØïèFÄå…+™X+k 2}ØØkœ?Ö ò¦êóVïŽ$ƒÁšb9ž2žü‡0Á¡1è­’ÎÇŽ7¶xpl Åjõé+xøèéhZtÑdNgöÍÉk[Ë äyuã/¹- akÈXê§úê(²u™*ƒ5h§xmÓòµÊ刞ÂÅ×7è<1š/&³gã_XôëÇA[5Ìä}5ÕsŠn¹CQWÕ]y¡Õ §bnÝèÒµ5¡ÖvëGÍG'—åûýDÝ_Ý-þy:ÑÉoßê&êþélðsÈ ½Çî–ÿ S”wœ±D‘&1±*†´±¿KÓf7 ˆ£šB¾%z’hó‰âÆ£L†VÕšºFXÜ]6R£v¶Ãe«ÙPk(rG~P›M©]âÂïA±ßû¥†ÃTç`×ËQ…fxÍ׬msŠÊÇB‡¬]Zþ‚gNY1;v¸yé,Ë›•êî凋Èz»YF£S¿UõKêF5®-ªä{Ghü${Ghü1ê󱬚^ÉÈ\À¸êZB±ËÚCšË-äøå®dO×}mpVÕ‹ôÏ´6-«™Ê½Çû9ç…6sv?¢ŽÓê+ÚņÃwØRªòØ»ä6u‚Ç‹|C:2⣠ò§­|ßœd4bÜæ{ÍÛòLûGc½q3‹Ûؤš™iŸ'¨®ë¶¨Â:C$c®)(¯&ÑYõ£\5EôW×YÙ'wÚ¶nÄÚ‘©ì™"I]cš:$«-zGi,›KYê6çSÞKë§+f !†¯Ö׈IØæê*x›¶”‰Ó[e*†¤ZÉßdHÝ«¥5ÍdžTNñîM7×›ÕH3ã+Ÿl;W#:.71õ§BÇÈçh9ÍŸ¹Ô†¿\+늢#Ôp9еõûŸQ²õ}U!Ê.`Ç-è¶,ãæPfõ›aűfkhÉ)ÌWæûLÛ¥V¢é¥m<–¹rEv%­/¼Ý+uÈe°9ÄÂO_Â%by|Âÿȉ\ÎÀ¨f“=üš•¿¦2YÊO“tƒ¬ŸKmFÝ/‘nÖ•\™©k¬eI4aåÙo¹ÀœVÆàØõxùµ®jÇŠ1¶)"¶nI¤ncI; —µ#§n¶9•€þ×õd%®7m©këí-“¥Jß‘Ôm”îj´õ¬`þ·8Ãeۢǒ:¹/£Wc¦ž´¶e”p^oX<‘§("ÒØ’=Za. ÝÓue±“ÎÝ^`¶ìRRñ[/¬aúl×t—n^öÛµ­%=ÇL ÅlS’mÌ©jññ¶_§VD¨Æy\úÙ¹.Ù$>’‚¯Xë§k·Ë¾À±+J±±Ño+–Õ}_ªDœ cXæÐµDu‡Q¶á!––cáQ`Ië§ç$ _"KöZž9[VX®éÓ:l%O¬½·Ql}í¯§´ªÖÕkuG¤å®¡±ÑÆ×4Ž)£O3·<ÁÛžaWåYùŽÏŠ ±]‰Ža:²à°­}W%6J4ñ¸ô…óAì“M3» GUé’rõ{R§M„îŽhÞ¥vnjZÎáååú4ÿíiMÿÌe´*^Xÿ£OþÖ”ßüÆI­=zža&´õëù†߿׵ÕýíXÿã/ßëÚêþö¬ñ‹È0`ÞŒÁɉû¬‰î¹§#÷û )Ç+£½Æ›-ªX¡ Y­ƒe².®Y' Ù`@¿Mߦ½é0¹lI§k[yÑŽém«“Ò^(å7{²Óò1]~¶5 Ó×Þ|ÚölÞž¾óæ×´ëfKñG)»Ý–Ÿ‘Šëõ°âŽSw»-?#×ëcZ0Þu›_¾¶L7f×ï­™/ŦïvZ~F+¯ÖÊ9MÞì´üŒW_­h çYµûëc çYµûëfKñG)»Ý–Ÿ‘Šëõ±?¦.õ/^\QÖzã)^,mî_ Ö±œ±q6šv'YÆœoAñÏN–ÇØmq_¥¦Ìà­«giÉ*GGzËZÛ5Ùt¤ 7Ÿ6¯Ï§´ëc çÍ«óéí:Ù’üQÊn÷e§äbºýl8£”ÝîËOÈÅuúØÖ€0Þu›_¾¶0Þu›_¾¶d¿r›½Ùiù®¿[(å7{²Óò1]~¶5  7f×ï­Œ7f×ï­™/ŦïvZ~F+¯ÖÊ9MÞì´üŒW_­h çYµûëc çYµûëfKñG)»Ý–Ÿ‘Šëõ°âŽSw»-?#×ëcZÃyÖm~úØÃyÖm~úÙ’üQÊn÷e§äbºýl8£”ÝîËOÈÅuúØÖ€0Þu›_¾¶0Þu›_¾¶d¿r›½Ùiù®¿[(å7{²Óò1]~¶5  7f×ï­Œ7f×ï­™/ŦïvZ~F+¯ÖÊ9MÞì´üŒW_­h çYµûëc çYµûëfKñG)»Ý–Ÿ‘Šëõ±;ß¶TUÒ5zËG¨Ë×Aë6ÎÄжî“ÕÎ)‘=i°8hý ‚Š?›«ÒúO¢ú-_ÛÐÛÔÓÛÙP0Þu›_¾¶0Þu›_¾¶P;&®yÒX[Ms ÊZ‘–&çM^Žž'²Î$.n»Kµ–,q‘O4R!@…&Š$­­Í: 6Tm:¬qusÒZÚ…“‰ñG)»Ý–Ÿ‘Šëõ±­RzϘé{N¶)=gÌt½§[2_Š9MÞì´üŒW_­‡r›½Ùiù®¿[Ðγk÷ÖÆγk÷ÖÌ—âŽSw»-?#×ëaŦïvZ~F+¯ÖÆ´†ó¬Úýõ±†ó¬Úýõ³%ø£”ÝîËOÈÅuúØqG)»Ý–Ÿ‘Šëõ±­a¼ë6¿}la¼ë6¿}lÉ~(å7{²Óò1]~¶QÊn÷e§äbºýlk@o:ͯß[o:ͯß[2_Š9MÞì´üŒW_­‡r›½Ùiù®¿[Ðγk÷ÖÆγk÷ÖÌ—âŽSw»-?#×ëaŦïvZ~F+¯ÖÆ´†ó¬Úýõ±†ó¬Úýõ³ _æ™%(bzŒ¾É2Ñs$‰¥É‰áaøn˜ÔîY½Á/IG%‹uŸzXîû:6žÐ·­_Dé}¤t^–«£ý'ÑtoØúM«ÂE>g”¯ÏÍ'[ùžR¿?4l©}¬Ù§-=ÿÔcµû4å§±¿úŒ¶€´ž¾;u²ÒzøíýÖÊ—ÚÇýšrÓØßýF;Xÿ³NZ{ÿ¨Ëh'¯ŽßÝlRzøíýÖÊ—ÚÇýšrÓØßýF;Xÿ³NZ{ÿ¨Ëh'¯ŽßÝlRzøíýÖÊ—ÚÇýšrÓØßýF;Xÿ³NZ{ÿ¨Ëh'¯ŽßÝlRzøíýÖÊ#h_ÎvlU¢³YçýtÌ× W&×Ú«ë¦ø³£Óž»v‹Z^Gwe.Ž›hì¬åHØÞ­½½J‡eo Ý!cÔià¿Å Ö€J_Ÿë·”¥ùþ»yd¿ñhÅ Ö€0ß§Œ?_&ôñ‡ëå’ÿÅ ƒZÃ~ž0ý|˜oÓÆ¯–KÿüZ h úxÃõòa¿O~¾Y/üZñh5  7éã×Ɇý2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„²ÝqWÛöËÇDò 9µWOÑ÷\…ÑJV툪ȭý4ÈX,9½™v“®³º‰k¾5ΔIR®cnnFÜíÖkuyR¹á#®¸®JPT~EÁ[ä 0›úŸ­.¸s\±+rSlVÔ…²Î£ÍòT,äÚR'yJÖøòÜÇMNŠWÛJõ²Ø®ï<·Ê¬¾ÛiÇL`ºá8ñpWسµ—eÎa`óƒ^ìbŽ7e*¨¦TìQ0œªs柔奓ŽÐ×Å3¬êH¯[¹Zí¤Ù3g¥bÕüN¢û/âÆ4ãFôïÇgz›¢÷ש7g|8I]G Ó»o ÝýàÝþ¶êN¾{ê®—Ð:ÝËè:f°wðŒK½+“ýázø’’ó”b]é\Ÿï ×Ä”.5UèâŸq)Éqª¯@˜øËˆÃíÎÅÿ·ýsÿñeͦ_ó k¬‰bþQs“3[Uv_ÿJ[ÚUì‚­ÀœáÈ$ õvàuc¬úÅcÐ8óf×ëzYO"nmšr^¸jxŒ¸&roIÿaµ­ßþ²Ìuû9Ïÿá;ΛÿøÜ þ À´³†—¸ µÔ2Î~Ñ:‘ug\*Þolú£§iìV‡†÷Úû¨­+ókür‹ý,ͱAÏ´ô¹£Ùõ#¹9ÓèW{ ±o@ÁŽÔÿÒníiû“¾Üâ/a>~÷p»±Þ÷½Ý ø£ÿz~1užûÝ/°Àü“e‡eþG9êè–oiwmÙ˜¬á®êÑ0l—~þ`‚>©ÎcÐ)+*5ýÀG*é]u»ˆúDµ¹Ù…>ps í9½QþP=¥PÇlMõhñ: Ùg¬¤rô¹“D©æ…Ä8&Ý;©CªÈ¶àèVj{Q‹ìc‚™‘Û3vÈ¢©$m”÷{Gór'›ï¹…JÙ/ÜŸªÜtäêlR˜‰Î?EVEv(ʧU±åÂcù»|ײw­y¡Uç9‚»7#nnjtÉibì/y¬Y؃èù4²*²TóI%ª›G#ñ©d†™å»^TÅš8ËáÒW˜ö’§v¸ü±Þ:k<®I Üúã –!kR©LqãI€Ä¶¡‰Uæ¶fPN+üÿžq^€Ã&Ê›lŒá|‚O²³òµLÖ­²£TŞnjµE¶Ë>Ç-¶¶üÖ]QâãÄúÜš*}Øë|±–lWü°²$úùÙnÆæÖö@W´üNÀ©åy³ùÁªÌ`Çýzv —ÞÌֹÊþgƒ®$Eä‹´4³Ÿ$q//ðö9‘HòR#f§ñ« ®kl>óC›‘<ß}Ì,‚VÉ~äýVã§ ¯S`tz”ÄNqûú*²+±FU:­.oÍÜkæ¼m(˽kÍ ¨×9ÌÙ¹ssS¦KKa{ÍbÎÅ`2›ÉW–®y ƒ`Ÿfþ­­EÈ$³.mÚº h]ñzÏbiæÑÅy´q뵱ö<§Î²ìyòž·ÛïŠ Ú†͢‘ª–Sbdv…¨¼qû’þ¦±ñºésXQøkRà«è×Iç[_mÆyrܲ¤Pêæ½‰³ ÐXîû }wY¶­N‹rè«L–u'×f„ĤòŽÀ`8ŸKì›ЄдIGÜòÿ›GWetEíÚ:‰®rǬ˩Ӧ"akC"Õü§#j™ÍÏ’Çf.˜êRzP‰E’Ë`Gñ.™«ã¡¿Å@´³»é¹Ûí;”XKaYÄé¤R€ÈK"“¤:;SµÚ!늲YBã¯QA^X,ù§lŠÿpj),ZÞ›îýe(Êܤ¼¶¬áÙqPás¤zàSk]Tý©uÅ$¬Ôå„óM7Ej7¸c…¾Yo·±kÂc’Jfˆv“%Vç´ÜǯËc:Ãå7>0[ÙÁ–öÔJWnä^(ͪ€ª1–qÕ,Yk!¨y²³‡!§yâ–Æ¤àM’¦úÿ ñ¢œ˜Ôµ­~–¥AÆ["Ò|Qjdt¡¶Ï«kfÌCz£i<†ßb]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@Ÿâv,Zöœ*ô´±¦€²®Ú×w8uqOéºêciÀw:F²aÜ«Eq–ÅwVZâá)Žuº£‘¯XöÙÑ\ÕkªÛïàF%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#À­­dQô¦T‹ŸY‘ªÒë¥L­Íu¶ì¿Scé4uµö56?oOocSgö¶y?kckgk“ùvv¹9yjóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó%5”ki(“Hµô5tõô5ß]õ´u´vöu4µ´µméêéjlríljiêlmrmìmìròìíìòòmlòòòròrž ²Î‹åg’8Ã\Ns»°UA`Re6~žuÖ(E7Úɬg˜zÅ^Dw£,ªkb1£ô1‹bÕyꪇ玅Ö*©ojèìrÌlç_¤§’)|ÎÓ϶·\ú”bFÙt½XY~Ȧ$Å;Ö^Ý®‡^¬Çð“" S|a[Oc¤– ŒRK2„nšÚÚo´Î¨Îiµ\’|z@ÀŠï ¤ý·¬ìX»¨ÛJ¦†ožÌ·y zè×ó‡Ý)³äaŽùc­rtP²»eªtÕèª%›±`Μb^_Î{¶th—(ö0æLo*jɃ‹òé}o^Æ#wŒ¶-SòÜŽc:×oeEmi»D&ê ÷Ú:Š’·Vó•GqN«NX¼æLb ²ÇNqåŸØ£9–bUÞùÙH4Üh)ªÉn76oŒ ŽI¼Y·ý|é`å;|"=H%œ^ÕôV'³mV<‘×Þ¤ Ô:Í rÉ=ރݻìë]3mÔw|5\îiKµ§¥j¬ª9œ!¬¬WÔîÎ,zS‰äáÁuZ¾ã5­®eu?±ë W^%ŒÊ%!ÛÁVrzÕ²`Šqúº¨”Bì<’»×SQéÝ~°a•ÖïÐw¦D»HÞkhÌæ¬|Ÿu» ångCi@z•Öj†p¥Ñõ$MDVÆVÉ©ÈêÝQ|°ñ¶ïCMHguÄUú¾†X»ÁAÑyÓ#f­¤Ó›MòÕ wÓlÅu¥>ë§XRéÂgF$’Äðx Z` {É¼ŠŽÅ³jyQ[|æ½+Èæ,ãU^G·£`üG™Ø¶Ö_Ælçž¶ËJ6×|ê:¢©CÕÐç&¦¨ÿXô—4:ªä)ÔmÂ3–äN 9¡KròæÆ]œάµ±ï) %O&_?ÓöI ¶šuØíTØXâ5EËb#Œ£¨á¨M£n-.NMSYZf§Ý³9ìnÏ|·±‡0±ÍÒ»ÃÙ®r´CnÊÞ½l’ZTMjƒae‘§U¶ç‘KN½PëjœSü®¬³â«ì¸.£Üa[‹›“8iˆ3©ÿœž¶Šo¶ôQOáœ!%ñcõý^ÂÏÃü>_½Ý/fÝc;Mº…¼?žtLr}èàŠw&]ô8k·»o= xó“ÖÔdÎîc_De=‡^bç {R_Õ…^ÂýPÐ|Hji˜joÃÔî7iÙ|4«$‘KšæìõX\Ü-«¥Lr WCWª­©h¨3ªãç'­©wëý#½”ó>'Î!Ñ<›¸+꽆E[SL3JÚ¡¶Y«öõçm“{„[šoöj BiY53 Y.²«è¬殓Øþg>å¨,,Ùcµ±ÂÓÁ1Ë"á=S2cÕ¤•èÚRÛ6 ‰ÈêŸe.ŽC¼?ìZw¯‘È]k¹Lš)YRQZž[Ó¼'µTî?d¶³†˜‚¬Ç2aùÉ…Ñ|»²ž²“µN)¨ž¥}#ˆÖÓ7åŒ7]’ÏY4Y­rÊB×¶ê(D Ácü²å@’ÍÔ²jJÚñ`Í«æ¨Äе_<›äÕËÙϲ ÷s|xHZ÷.èõÆïoW oómÜëþ«|ê>¼ê>¬ëŽ¥xêΕÓz­Ãè:&°vðRæÆÉ>HÂñó æ”…³ÅšBë¹b2êj”žP[À)æ<Â_ã’6 ¶CdŽþoçiW6w†Çªûqø|è‰k\ã~+ƒÝà§¹¡:»`0jõ¡Ö|b¼Zicwý‹¤e¹lU4“¥{cmjÍézb¤üÿ-´õ­tÕL.6ã­WÞQ*ûF`ãgY4¼æ´…Ì%å•uîý[@ÔÚ²\—„f¾)LçÉUc½á\¢­nwë&õÉ|o'¶¤õ¼gˆE‘8¬ÓÇeU¸~aеXQYŒg>…%–Ù!¢ §·ŽmTøü÷e±Íc–›ºŠ¥ä2MÀƒkO—¸ Í\‹c-\ž!/];™>1Nëç§YŒf9p’kÆÕ3é×6 ½Ã’#¥Ä*‰¿¯Lé”UÒŠ—"ñr´£qÒ®·T¦Øhú‚Ó’]“l‚¯6PÛOUÕ©‘’ý4)êfù-šš’VkÒI!w/%úäé{¦#’ Óbß&á¨ó2wó¾ö$á%ß_ÂjêW}¹º`ѳÎ!㩯.èÙ7Ž–Mœý×Öu“ehõþ¤£]‡üÛÔM õ"Åβ½~*Ùù(Žß•Zvýi@áîHcLQšÞ7/»m{Úú½³åOŒÕÐØzy%§rúþ”†´ÆZÛbuƒ4µBuLí5ÌmÂH»`4ÄÕ­ÎO[FØn•vÅ”ôÌ⃜c N{OË*ö½’½‡/l˜ýOIÙµ–Å;¸aT!înå'`^‚Ÿ›N,”Õƒد”ÎG£Omœ ºI³“Qù\ºFm:ÕLbÕî¼oí‹Á|·`³ù”*ИD,‡ËÁE±Uê3ébãæBèÔÈ,xƒ®LkQmn[K4ý:¾²zÛ‰;±ÀŒ§áj~Åý¬¸^ÃÙë´/_pów>‹~øí¹vÿ»¸ÀÎ9þéq#«ÿÏÁ'9=l¦TÀƒZˆÊt‹ÆS˰½Ç"Õì;tÄS!cw<ÚƒfŽ?ê!­³”Â, :(ňÝÑzÊIF"•YšúydBlä<"¿ YQ|â3É\ºQhâUÞÁaÈ2Ÿ qÆ‘®#kq»iÖï~ª-ìžnֆėjå;ì298§©\o”>Þ²zyTVÒyœZM£¯–:Gø+3­Â‡dù>ŒAï2.»’L­7Š¢E˜Âckµªuí•<¾áE6ŸÍ+ù´ê¨r«$L¦h³=‹VXV\oBذbü[–Š{„‹tÊ›vIIÓûRÈj5rù-§tœQL™2÷(ÜrI’YWã»æBÂÔäÂé-c¯]-³§h;lž¾t‚:¢ŽuPù§/e„PvuÛµvܸå|¿U“ù}iVP×cm—QV²Úb6ã¾e¹G][L­ûíÓaòéÏêgf 2 µ‡J Q U š…Âά«ÊÉž8e63·(KÖxó$¤2Ra»ZíHÀZ¢÷~ Ö[ùK‚øê¿Ù„QÜz“I.­·i½q ‡PkíK¢Bë$w¨â©h¨3«8r²gPÈ©Z¢œKÒg»¿[²¾Mv¥-UUgg;cÓ“sÚ1ÙwòN2ˆ³MJÌö’™ú_䥋 ±ÑN(41Y;ë'­¸“»Ê~v§ì_ÚË…ì=ž»Bõ÷7sè·ïŽÛ‘Çoû·ñ»ü ãŸî—:¿üüŠƒ:´¹ÉëeNª[›¨Œ§uH®ïº±núÝW°ëµ[™GHLíH»å\híNôßõë97±ÐßÒFhÆ!¡(nŒ‰ªì8e‰†ØªŸ$ãw´ N1´Ò'˜±ß²‡xº Û©ì,m¶"Ô…§HÙ’–gרÚKM%–õ,cŠhÃÝfpkCjÊ೩ A‘úF,eÚ¯$z·´OXÒž{ov6àG 'œgþßWgûIqËr=7þŸ·C²ß¢¿Ð~ôu¿ôÞX»òλvnÚk¨gê²/²êËæìr²íÚÖ[sÆÛ£t4· ‹ Èkhm¿B:m¾L]2Eý4ã^ÌÛAA_¹0êÁdŠ&Éd ¸@®˜­nÉ.ÊfY2BÆ’_´ò“•©Œ¦^Û‘É1· ­ w|œÇ˜]\Ÿ"Lv¥\ªtÓr“Ì×ÁPH“ÃÖN§Jõ%ïV, é&¨¤YkI_)W1éÄ+ltÊ:‰ñµB•û2ErK¶ËÃù”QsJ=6ÝV½v6ö¼~™hHT¬x@½"÷8Γkk²u®ª™aQ]¶&Ž;Xڵñ«"ٮƈ}ЦZÉ^Ùq·jžß ,ˆ3ŒÞÛ&’Wšõ¥é/‘B'  VJÉÌn6‰ú òÀæçªŠá2Ê­Ä\‘Õ±`÷Ö÷H"°Ý9ŧù“dÂ*×)ã¤2[jsyX¸ V×yœ²4ÐùjN1èT³Iü½úN0¸ººX¼‘Ø»ZF(ÓdŽqVb-“¥y¦ë‡g¸B‡ÌáÇU79?jµH÷C›þýÅ7.k©$Vïôö©yC¼ÈbK Fò⣣>'CqÑPK Äkµ³±ëg¸Ó€¹mÆv8­E…d\ª[©±#u5i¯*Ì›ØzyÆ+®™´Ôµ °e¸öŠ«·Ð"Ab#WËm”ñ¸å—bðæ·±z®¢(­§XBú‚ ¼ùYÔÌ- gZºÉ-èä¿(Ê®<ÛäpRùP?Ø”n¬Î|Ý™ÊZ«ÚUõŽo_(‡1ÝàYÉêªÉ©Çë¢O|°ñ¶ï]rÇ –<©ú¾†X»ÁAÞ˜ìíy²c0kMòÕ wÓ”ý¹á [>ë§XR:–¶$’ň£j«&§ l[u¤È8Bêò¦iÔÌ ïœ_ÝËFk6G&VúǶ™ÙVÞ3ªÓÄ[&qJó²W /p„ï™ÝÄ~*qr~ÒjŽo7ýŠm¼G×MV­£è,:®Bò»vPËþб™Å?I|Pº:Ýí»Pwk$·5Å"ØégV™\øËnªj»%º¨dˆi,vÆÙ–2N«6ÚúDÀ®¬´êŠ-ñf®BjL¤«àrK+Eµ×møÜf……~€e‹X‰ock­é:ª*|YÆ6Î1o•f-Ô–-£ac,iª·™í2ä]çÓØ©±õ¢ wܘòö’Ù „ÒlPÍ[…ªg6,Òm¾òÔ‘K½“T×hÌnÈ<|Þ=Îãµ!kÓ[ÝÔûú¼O¿Âw¨:ѯ:¯:Ï©ú韬ú/BëFÿ§éz=¼Hkšç$g# È<ƒ…Ò7 © ®šˆÄi«®y~ïÇg˜ó6‘ÈßæØóÛ‡¸}›™[ÙÛløâ ¢Õ®}ÇH’qw€ˆ^lWã³T-Û§ˆ¤ž8ä–É¡Ö<]KÌ2ó†&†LÙÔRï2ömI=1×òw¸¬™ºêŠG¬X¬= …õe¥[!€H³ª}‚ù#e&ÊëÑ;†,ÓùE}v—B Q˜Üò}P´Y<Ý—ãýñX+½n͎ýxʯj3–ÍšiŠú «š#p¸ó§«^·Èe›Éi&å­ÃcZ–ͳ«ŽÇKóš‘Dn]Ìì¹’4o³ÆÁÉËE¥òÇ’Öµ3äÚ!+Út€ÈPV5‚ )#îÍW"Œ¡kòÞVeÞŒÔRF\µ»o•K˜õ"N:båDÆÚJý©"I%%eæÊV¹Ù£n“^ƒƒ^@Ãt#ÊQ¼/^­{d›Iɵ¥:&¥OV,MðŒÚ§.ü³”TU,Ú•æBÝñ –<ëcåeµLÌØº£qºvŽ<Ãã8Yy1íþÃåäúÜð†y¯ÓZŸè©kmV‘FƧ+Êœ»ruŸ$Õhã£D¾äÇNnÖ†:æÅÓ–ÝT’Ë· ²‚ùÊY]gk¥Ô‰W“,t²]'ðÚ±\­3|µÖ$²m rª›T7µE¤:ÒǸY( v;*tæêÄ}äÊ|µbð,Aˆ¿ é5¶(d3|O\·fOPñVpý»:*Š*Ý6ÿ§¡lyœÉ7ÍöCíólE²d¦º Ü#KŒüâØ1—Q~–äý§Ð+ldú»÷ñ‘ÿècZýpíÙ&ÇÝÖîµa_×pž¹’°u“îíè¨ëîn+&¿Éò¾Í<ÖShÂüÞ³r‹µýƒM¿I35mfO%—ïÐD7zk¾¿·å{‹YdiͶ¥U‰È{?¯“³îÚ›OÙÉìÓÁ®»„o?Ö-Úë§õ“÷PðÛëkíçÔ+vºÃ~8Aû¹Õ½WÔд㵫`°(O·tÎ+ï#g1•qe¤¥C_¯¹¸¬šÿ$WÊû4óYM£ ózÍÊ.×ö 6ý$ÌÔUµ™<–_¼;AÜdMé®úþß•î-e‘ý§6Øb•Tn'!ìþ¾NÏ»jvðPœE²c}™zsÜ#WƒâÙÏ—RŽˆäý©Óël›úÄ7 ‘ƒé£Z*pÓÚÚ¸Þæ×ªaAÔ“n¦’¿õkòup+v_®Ü¦Z®s§$ÈÓ_8î†7ª¥µ¥ƒe²¨²l†Û¡3š]Uè¬$„pw'¨ÞƒóÂû„Ë.Ê™#Õ½ººìóÛ{¶Oø§<ã?öøúÄøqÙ·»‘é¿ô½ý©=þœ7_­ÿ¡©Î«µÚ³ê¬°ã¤þ×­ó“Ù­,«.˜¯\i+æö¨çu4çjÉAP_rM‹NZcu\ÁbAù+=ˆ”šs`OŸ£S¨Û&;šß tÅjŠIIÓû19’æ5rù-§—d­4eJ÷(ÜrI’YhdCä<üêÚÂé-c¯]-PV™Ã”b¾t‚:ž`² Pù©e±`ÿÙnetgen-6.2.1905/doc/pictures/menurefinement.jpg0000644000175000017500000003274213504650527020137 0ustar kurtkurtÿØÿàJFIFa[ÿÛCÿÛCÿÀž¤"ÿÄ  ÿÄF   68Wg†˜§ç%&7U…¥µ·Õ×$'5#Vf"(4:EHÿÄÿÄ"Qð1q‘¡±Ñ!áÿÚ ?vG÷öàÅ…‹-ê°bú‡¼`õ™¿#߆B‘—ÿ,ˆYss~Vl¹9ÿùòs§å~O/úrú9y}-›«Ÿ%20¦¹uÓÕ&õ#…–ZÕ¶_@²,²Ÿ QÅæeYb p)H’†–J,iã§Æ‘d|20äÇËp­_§¿uÿ&Â>Dz,úîŽT«ŠwV^*„[©Ësãñf>wRÇcEth–…F¡ÖÞ ³RnÆoTŽØ¹ûyˆGÃégà¼Õ}ý½ü,7öî"Ëwrõùn •ó°e$ Läe‘­vëus[-d›‘XkÐN9f .YÉb˜%N Y'ç€$”ÌQù£À•“×5låßQÕ^ççUu5†ï^m¬—œy†ŸEÕ;^䙯eX3Wƒ–í“[Þ®×^5•¯¥°óAX°Õy+Ëd¾\±Ýb¹"wq·|}ÍùÍèf9WíVP}EÄÛ)¨±èb q§Õ5ÎYœ¬Øe.¯X€9ŽlÅQ4UÝ \…°03åÉD¯kó§¢y, 6 q´Pî4ÀÖ=Eo¤Z•ãˆöóåpa!á0·ƒ4,ò”SÂÎ $¨ÎÏêEGN'ޥđ‡oæ«ïíïáa¿·p–š ¶[pßL{Ÿú^°·Ò( {Ÿð«A½y«-h×uð2QmNGˆ×ÕÚÍz­^W ñ9NS2¾·èL‘d€ïsWˆ< ˆ-ýÇÂWÔ[T;í§æ¥ô¹×Óà™3|VU*sØõ‰ÒE–¾B±çÈÕÕ ½¿,|ÕÚœ·ÀyêåõR09Z92¶Dlsâ~j¾þÞþûwš¯¿·¿…†þÝÆaôî-»„j{Fó¬œÞbíq4iWy6ka×Wóf r¡fº1ë# ª6%§ÑôÖHõðÕ üØT‡Jíé2$ækfÅû“¨ææªtËëW°`.OP·õ'ªm«®:øÝååU+ËúanÿÖ”©¾5JÃ_©,X Ã;…Ø+#TŸõÙg3€2\ sÍWßÛßÂÃnãˆö¢‡æO“^o¤y¿ÙfùUã dùmãÝ«æc~OsöGsþŽwg…ø~gõÿÿoÂÉl®Íu?wõâ^§7ÈÄ~œ”†µÞt˜:ùJØ…r-«,[ÒY'€}e"ÀíGæ}ı9„s)\3&9¬£¡¼Ô·=XÙMˆ´vl­´a†RE~Bç÷%ÆöѼ½qPÔ8Üñ9µ¹úZÜkÀÖ«ú-o¤ÇÉ,œF±ÿ4PÑFç7¬ÈoÆf ¾*-ÈOعÎT6ÀU—j€Ã’VI5ÔMÕÍ’¶=’¥f/N8›˜Ð¸‡" 4”‘9åcŸ‚a³2Çå>.L²Ÿš¯¿·¿…†þÝŸê]·µ6ßMŽš”6Êœ×iú/Õ›Úϳ*êná°fh€2™§¨(­I+EÚ²¥d`ÊÂ{8#öÅ¢ŒŒ²ƒ–ÀLošép¶øk]J÷‹w…tJæ¢m4;gê‘ÔÑ# F»¦sÖ$ÌëËoŠë.óÖÙàzƒ:Ûò¿¦Äð EOhf¼‰n·<Õ}ý½ü,7öî5_o ý»„ÐÚM÷êK¬ú°ÌÁ¶ÀßãôÄÒC0F5Τ îy¾Vëw~Wáú +U–éBÖ“z*±.K!D´ýÝT¨$´ªZÓÓ¢ñÙ©ûqÔkKv.îö‘ö7ö)œ©t­kú½Í®Äk¿;½˜:rÝT%m"Du¹…«€ÜáJ¹­Šc" ¶Ç±=LAn7š¯¿·¿…†þÝÁæ«ïíïáa¿·qðp…æ«ïíïáa¿·pyªûû{øXoíÜG¼!yªûû{øXoíÜj¾þÞþûwïbþðm>ÈBÙP!¯ 5\䢦7I‚<µ@ì²g€¥$,Ró”6C.R¤±K)Ïš(ïLÏ6$CˆyþTÖÔŸéÒmÍýy¾ÿÄ[s^o¿Å°ËÖ¯ÇÓߺÿ“â™W:•®•JÝúš›VÆ¡´–§tl£4Ãoëv……vÀ‚*Õ" ø«0¾Pn¢ÇEY lXÞˆ‰á­Å6f96Õøú{÷_òaÜde¡Ö§…>É{,9^§$ÈÖ‹‹;ÀƒBìu¹^Ó,³ý——¬KN§¨kE“„Y9e'ò‰$Ù†|g‘gfGŽÞÐH,ví½0´ê§×Ja®£8YCQŽCaÖs×MóؤçŒÍÉœLtä}ò /<@| ÖqؼËap¦Wq… ‡¶AĹÜ&h ×sõ4’%& FFƒ²×µwñÇp+H*Þ%KRDQñ‹~8ü/ILÌÖ\7Bl“K9g-éo2XäÛL²Ì¶ê¶¼äšÂ µA´–eFµ’Ð-³-ž¨6イKh¡râ’Xl©0À“d9£æÇ“›Üà CVtãÓ*SÙSË*o¶½‰<òöaÿíS>Y{Ix?J÷Ÿyø¬ÿÖuöï¿þ‰ø½a÷¿ ߥæ‡Y5=ÑH=ëÐ6šÓ`v-“mme›llóÉì[~aÙ-5–¿C+}lp´q˜ÃȇZP ʶA…[¬Km,¢‹_®„(q¦50ª"›Ú`ØÞ,ÖùÄXZžßl—â¼æ\lÇ8ÓaØï ù°áœØôÐÀ{Ò(p`X§â 8è4öÐèëÓjåd½šì=a\¦Ë\lºb~¶ÔÖÛžTçú ²c&§¿PR´ðÈ’ÇŽu¤” rÂ3÷Ee .嵡¸é‚&ÇSeÏ|ëâK—ÛúÉåwê=¼Ô7²|çU˜íZþ.Ã'r,@–OôDÑÿ÷¯R?áD2c‰ÎKJµ”¹íºf#ZzÁÍîHZ®6²wyX¼ÔLP­ÔK¡½[V(ˆþ^1™^ñâ:Y~¹âÓ§I9),?ÁǦ_3ÿü¬;Wäeó7ñçïõ«ÿ¾xî/=ÕÖ]ssK¬,û/þ_±Ó2-\&Ø…øÔ+œÍeh DR*¶¿-" úñל‹ç"Wf ’½8y±ˆ{Ì\ݾ¾l¥µÕ°Ëw\m¤‹Ž¼)êX{…$Übž Vh¬Ý®Ü'ýqGx ŒãènCA9­x¤HÌ …ËÉêþ€! S§™]5 +FX”ߊWšê‘&²¥ñ°íT·4ZØ¥]–•d¯ Ú‰+–™‡Š³/*]ަqÌ (TQÞ—è rÅŽ“S)©ZèZÂÖkG%X c~›ƒ{YÖ\‹3 §­ÔKvJ0ÊѹyyP¨TI`墴$IŲРAéTŽG/¿úl_…%±ÔÆÆy¹äÓ—xùw¿k«ú<Ô½Ú·=aá=ò›úT ŽxŽ ý!\ñ…R~µùœáx‘ï BŸN=2ºýªüͦû—ÛoÈßiïùÕ æo³o‡y-ñ}äWfvg…@ý_v§q{ÇégŽûîo|›Ñ5Ƙ¬î{ç`ÒS|ßÙ¿+¼ïnî¢]íä¬Ě×ós“Öûmb|±Ÿ¢!@xǾúéÿ!¾I¿ƒ€8888ààààãÞ•5£õ'út£ÁÁ¼ÿ*kGêOôéGƒˆ<Þ¯²7«ìeëWãéïÝɇp›&ÇA뮥Û=ÓϨ ! x«¾ù¿=67ˆDg=e¿6h’cL'Úá ‡Ìo¨¼[Õîã¡à×_+ý§°U# Ѝ*B€NÕøú{÷_òaÜS&?Ô¦Ûb=ò׫šèÍyD8²Íça¤«CVÄfD¬"c&°Ç±I,ÉoÂqJ8xKc1Ë<¢q ‘t>\7.,îØÝ[ií¬¨ôA‡¡?´ uC:îUÁÓÍR/cæ â.|ЏÉnœÕ Ò¹Éù –¢³X¯k{=¯8ÊÞ8¶ÌæýŒ·¬+"íÒ\Ün£Ç5\LôÎNÙã[Áª·ê6¯-í–éÃmK®ÝA%ì«ÈäGZ³•šMº¹TÖËéœó XK¯Ìᤇ‡^BX`û—Yu»c;sÚ_) Û³¼c´|åªìþÕî ñþÜï`<Ç< /ŒxgªøŸƒ‹õßðøžóî[´e%°+pSošv¬»TŒÌ5Rݯ”¬•±ì  †7!…Ä9Y£cÁü ‡ŠG,yò±åì»’þؽ8×K›ym:·N\ºKÜ€{™Q3ÏÐÆM¯Ø¸#/µ¼NqÉG"è:–`—¸2uÁ{œ8Jþ|á­WúóÅ^ª)juªöSq7÷¹Íä¾m«¾‘9·)H3lhšhÛ=çše_[A‘W´1¯ ôà‰ÍJð@ÇPï‰CÖJªyœRÏÖ´ÙÉó2«?[´e%°+pSošv¬»TŒÌ5Rݯ”¬•±ì  †7!…Ä9Y£cÁü ‡ŠG,yò±å÷ÖU³KšŽÍ_$1Øu_ty`øuL w:ã¾aëØm H8¡ÝàãÇ ÑÛÓ‡w¬Gõ¸˜¹0ò€¥«;Kµõ†ŽÞ´Ñ ¡»ÊWˆ}zfÙ›c´Ã5~k¦ƒ”b[×lØ¢áñGxq‘puýg‹(6¼“bÁ•RXº«‘:ït‹NL¯ú¤õÙL@µž.u…×ÖǶÊÞnpŠã¬îžvjàÍžÂLÛ9ÿ&ò§Ao6mÍPR÷%™À!'vÑ”•»=4U;V P»N:³\êƒëå(Kvë%“UŠÃgƒŒ#·ãÂñãêY®)ií01òC9"|~^\~‚»£)*†yµ5;VUå ¬²®ëå$©ì+uJß*m\¼rbÐ’ ­”9yUDÏÉ"rß/(5Øã…ú=x¨&eºû¯OPuå„Û^ü×M=7¡ðÜË@0Èw]RߢìJ}8K,‚<é@ù¯%“.æ «Fܧ«›¹1&ºMÊ=ì­æÈ?]=Ò6Ûi ÄqK\Mì^ƒ„¡íx°g¡­åذ&éÝÚp­ùRK‚)å‚QÉOÑa\`ÇÆ °0 Å21·<ünÑ”–À­ÁM¾iÚ²íPr30ÕKv¾R²VDzB€HT6 Ü„äAfŒ Œ[\sð@,J)±çÊÇ”a£)&Úž= ×NÕŒÔl@k+1i†ùHÕOm+0™)«Ñë¢B$¨a¥ <ë"q‡å€0Q9EG‰Î:61e’mo½´PŒn&á1kŽønöí³;-f\XTío+U‚“½§uUíZ,UKzëVl–°PXŠv ‹a5áÄÖJ3©‡$ÆV!Öw[&¸èµª*Ù³†«K/Ý?£Þ6 ³eç×sï=t–’¨ÒM¢ÉÝ:Üd¦úø­e®ÒØÊ§C|ësYNAÂMlÑuÃ)cÖUµÆ˜f¸·kä‹R¼cðîáC±ÔÀ¼&ð‚°N‰ñ•vh”ð³‚Æ™ëÐsú‘QÐHÆ÷©q#æÇÑÖ]n.™c×µò)^\o¬Ûu P‡52Ô²J t•ƒc«É”ÃÁ‹‹Æg63A(zYPAˆÈŸ’X¸9°³¶áýĪh=\¬ o‡­³µ{¢ºÎ‚‚ɪÛ\ϱŽzÿAØq›ÈÉÔ Šè·PG³Ûï9|ì 2•aÆ"+ ÷µ²k¤f-q¤½œé„ÚkÍ˾öìîáÿ•v9ûÌû«¸ZŽ5~™<øH?ð?íÅïÍq|1T80ÿùü?Ö3µ—[„&WÀ|¤×”ãÄ6¢CT!ÂLªì‘eL`× ñ€bŽð8ã ˜-‹0EžˆTé’1çã–RvlóppppÁÁÁÀ Ǽÿ*kGêOôéGƒƒyþTÖÔŸéÒy½_doWØËÖ¯ÇÓߺÿ“ã0Óú‹ÒN´–ö_"•­8ê=í=ž¨®q¤)bdfdÔõ(®V,êÂgybÍ4.^< RZÌ%Ï#?—ŸÁ«‘ý²¹´òÕøú{÷_òaÜ%¥mT>5é/ºHy³W}f°·»Ýa¼fšI­ÓëkÁêX÷qK_, ~u“…TÿaÚ©>¬I ý¶ÏÏ9ŽmËŒFnRÞÀ²S¢“i]‹¡véí}¹J—;5q$=nÉž"0:U†ÅÐh\M‹ˆ,ÔV²ÕÀÜe `RÇ ä6‰ñùqòå¸\'¶²ùÏí#¯žÎ?(oþj£ÈoŠ¿®~üåwÇ¿ÐñËôWÿPþhõÎ"Í/fÕhCú¦ÑŒ'#m)ê³iÙº¡ª-ra°mª–¸ßBˆ0í ;2G/9‹Y¼w@n2Í‘sYaQ›bC‰"5"zÇ,¶Ò­º­·»YkM¬¨‚<.W–§yvðkhpûÀj® xÈå–Vðqý`â)C½Eˆ¾ŠÏ<ŸT—–DݾÇlu1©4ÖÁì——õÛÝÜÝÛÍM~Ým@Ò@~`IÈÏ?×ÙÙŒüØoªúï®Íõañ¥ËÀ”z—Kר=<=ÎöÛ&Ž8»±Çº´¦Ñ„í‘®ï8Y2RVžÇl²íNÆåô²s V3 J‹è_ KöÛtÌ1Œ^—L÷æGë=YY-tÆ¥\µÅ|ñn{õÔ=º|ªªu3Ï·=[W F•ZSèÀ Iî·ˆ^`Acçd¢¸Ê ™Ìeƒá˜cÍo©ú“ÖÏW=?¯–¥´ú™oìbG=ƒ®ê;'Wç J¬îÏPŸ¨^î„'Š­ak;:²ºUÖJ—u&B’§˜ƒXœº+ÂêmÆÇSO®~—Ö¹{@ym»ÚÏ¿w-ªˆ¼Ôz˜¡iŠ¥VÝj«|¼‡CÊ ¾ßðó«•u@ô,3W+Pì¼·ˆ®H9]4gT XXzÈíuFªpîük÷S¯ËÚFÉ"ÈdÀ¶‡lX58% òÕÍÎQµÇ1ÆÓ†ˆaf±'a+zÌvÒÙB¦®úÂÆÝVÔæÍjV©³xaîWŸ>X4 ¤À^ÏøÛ׿ep_Š)*¿o.´zé^LØ x$N^IÙ-7 G§ë:­¨@g*xäm¥=VoBÏP¦¶‘7&ÖÚ©k‹i[•zø9jGåç#±k7“­ÖIôIIY¬°¨Íµ<ÃãR'µÏ$³¡Rª“Û¦în: Cxj#D×¶»Z×µí¶¶ôö–Ù³äuÙÉ(ì Ñ[ت—Z©šé®U–üËôy*³MØ _*ð¹ÁÂÜ{› P¢Bè.¯nd5S™¶9¶¬¿©¯¥¬‹<ô•©3ˆ2½ælY1ñEýù‡æþûû4l?ø¿‹ÎïT^wz£Ýf^€Ú¶Â¨VAȂٖ^%)e™‘)’4P$ ™!yÉ4°õ#˜cÉÉK2¡À¬€gòÇ* °â‘"ÌÃUL$d½‹¢v‚ÐÙíÂÚ‹/XªÆ:¢‚DZvEzUn¹€ÜÒ¨ÐíÈ*«©*yö›:†r í¶-œAÝ‘ÚÈd]%°²)¡œT¿ù‡æþûû4l?ø¿ƒ¿0üßßf‡ÿðš­Û[‰ªÝµ¹ÜðqÃwæ›ûïìѰÿâþüÃó}ýš6ü_Âj·mn&«vÖçsÁÇ ß˜~o￳FÃÿ‹ø;óÍý÷öhØñ ªÝµ¸š­Û[Ï7~aù¿¾þÍþ/àïÌ?7÷ßÙ£aÿÅü&«vÖâj·mnw<pÝù‡æþûû4l?ø¿ƒ¿0üßßf‡ÿðš­Û[‰ªÝµ¹ÜðqÃwæ›ûïìѰÿâþüÃó}ýš6ü_Âj·mn&«vÖçsÁÇ ß˜~o￳FÃÿ‹ø;óÍý÷öhØñ ªÝµ¸š­Û[Ï7~aù¿¾þÍþ/àïÌ?7÷ßÙ£aÿÅü&«vÖâj·mnw<pÝù‡æþûû4l?ø¿¬{‰O„::áŽA q¡`ÈC^/‘01æ•›“.y¥ WÆ ‰ËÏ“—šI3"À‡‡ÑÏ"dœñäËÊš­Û[‰ªÝµ¹‚;Ïò¦´~¤ÿN”x87ŸåMhýIþ(ðq›ÕöAæõ}Œ½jü}=û¯ù0î#Þ$+WãéïÝɇp¼¥ú±mŸ¨-÷Sh½YbU=6/ch[)mÑ0‰l:ÀÖ|ÁÉ>ÙK)³u(Ò$@q r»È>ÜædæÂ…yvAük°Ù®\ÝŽ*ÈÐÖïfêCk,{Q#_ê €H­]ÌìÂSúÖCÇc«¨“"u§¶;ã¶=zTИŒÿÓÎ:Yã³Nâ¬mGTJÚ•¹ô«\©¬´…Ïoï?‰Ÿª§9lˆš˜U”eØåŽªx³Ëó韘]}®1*ó`n¯KÐíÐHŽ8Ø›ÁÅÖíû¬- t¦.›ý¯]5¡¾äx3®¹6ú‰º–ä-ÐÛ9l†«ÜK8:"Ö+Ï,Ÿè“©0€Çyd/“è±~ÓZÝäÇ´w´!ìóóóæº“»õ£ãý‘ñßô7þóãWè÷ý¿û>›ø8„lÖ·L®,q;H¯.7ˆ5•Dø:×Cš™jY% ™6¾®#Ê áà‰ÅÆÐTÖg=,¨##£ÀÉ,\ì8<4íÀÔ«‘6¿Ú=tzo¶˜f«®ÚÑ’Ë[]žÞ)…FiÅ‚)_>0Yv)('¤7Û#…£8ábø8„=¦µ»Îgh:CÚæÍt?9þ*÷ßê»ÇûßâGé—ýÅ_Òú÷œxr7R¢2 M•´zé¼õ¦ÃFT‘vÖ˜Y ]ªSÖE5Ó¢Aäfå(FÓY(êš5†¾‡3hYí«0É ð¬rÀ±|PZ©n¥\û}°B©cƒ‰ykñÅU™CM7Ö˜ [l†“˜œœ—¨èc_ 7¾œ£ãªœ{‰È¦}hÈ>P±òòD™*?nïÚ è ®õe’ß“Ocn+ÝÙÚIn"ß5ÒJ–˜bn²l B0ÄÔiùù†@—y(ùyaHÒh 1àãùz¯ÉªEná×.¶‹Mž+zÂþÔ—Ù*\»]Íîekƒ‘ƒþàÆF¼ÅH1Äx;:ˆ¹šª Ø~Ç› <¦…zy´UÛfµº³²Ti«`é þß°<°ê§k] RÉvî³ÒÕUûEéø ìÈÏrà7ÆB–w¬š? †‰ÜŸ:÷7|uËŽÚö$ö^ÿ{¿Æ|Íö’ª‹Ù¿û\Wfvg…x'ÆV¾â÷ÿüÅï^¡’ÅÔW%°+sœ¨kЬ»T’²I®¢°T¬•±ì  +1zqÄÒæ…Ä9Y ä¤‰Ï+ü ™–?,yñreSàâWÙ­nxs;\%l ßa«Ÿ½½Î Ú6„Ü%z’Õ…«&˧-Ͷ)˜åa!­.>Ç•§£N­+ Œ³¢¥¬˜’6Y„À±ƒ³ƒ€ÏÜ›]?4þí…ÜÑ ¸urÓˆ/_Žuhf¹FÙT“n“!¦FG* †Î†Ð³Ë¶8Y¼bÃ]@Y«YóÙ8—#)Hƒåcâôÿbëm_º%Uš¹±jËzý6Õa^é ˜-š” rЧªÔÛÒÏ2…’ L‚kðêøa“[ëNl#ù‰–´Vpš%×88K­Í)×AêàÚ¾‚Ýëyç÷EužÏìvË¢“1¹Ø ‡£7¢Þ7Ëe#^W þVê˧ƒz$ã{TUQXÂ̜Ɣ7Ø®>ŸÝ± 9EÕËN3yïuÚ½yœkI6ád5©JSÙŠª\EŽcYå(G]J:¹^°fJÍZžÚÍ0ixÒÉ-Éx8D¨­Omͺw•G²USœƒºìê¯biª‚’æÒÃÐ s‘~@Ø«fP$È I@uëzµ}…d“ÈꆑYÔÌ×”GáêQfÁèÅ’×Ó/¯äiÛÃ&ÃYal«6Œü|Åš£Ht–Hà²ê-`ؽ[ÇlKÜ2Ox‘gg¡ªë&@ܪe“ˆ”x˜a@Ê7žflæƒãŸ»žÛ…«[_~èï[½º‘«×z‡Ô1ã§Þ:'Qs+C°ïÏE1¬ TpÕË)¡j¯0Øq}áøÆco”e¨-T\”3£XK³Äôú àðúÒW›¹l[Gµî·Ô}‹ ¡~UšŽ×J8ê®±PÆ*}‘@aÍg[å÷‡bŠ*¼§Zu÷:itaª‘ßÔY æWHNYžg“g¹/*M못k´í¾è®6º%ÚuñM¿«:\×f»rË×xBÚm%­ËX8øº¥"1ÃÊOÓÉM|  /²8sWWo:H¹Ì™Mõ¥vì†Åî=÷¦”í§ÓÞ˜°zKÒ¤eûv¾mÓB›§ˆ$“4Ý—¬QÎÉÈO«F@,k×”/:¤ñ$‘õ¦u_®M7‘øðÙ–VÝVØS\—¶¨6ƒ,²Ö¨Ì&å¶e³Ð$ 8¼Â ¬ybÍ4.\¡¥„’‹&dC™4|Ù1óžÚëm7¨¹Ø¡3ê §¬—>¶ë¦äÒ÷Ãõ«[°l$Ýqw Ø:»´Äz3­ì¨©ãaÍ -Uð³¬Au 1‚æ—#<9ƒ­±5¬ŒÍk0Ò·ë€^=çùSZ?R§J<Ïò¦´~¤ÿN”x8ƒÍêû óz¾Æ^µ~>žý×ü˜wQÓ¿n¬¶öçó"@OfN¢Û5¨¨}’4ðß­©ŽÉísmÞ:ÊÉëïû’w’ àe{ÔOZïy½ÿUí_§¿uÿ&ÂòèªöÙiS'PpnZ±v€½êc¶IX¹TVFç[/SÚÓÔa¥ËÐÛúµ¼9ÉñÕe’’¤|ÃàŽfLE=$¹sE›÷óPPö,>¨¶]€Ä^FŽ )ò­óƒq–¶æÚâËSVζŒÉUE}iÚÀYËÖkÓºí…a@ˆ>BzÑ®FßI_àê9¦T-’ÏUZ—'n³×þSù¬RyjµÖÔwžg¹×*Oh;•9ýA¯ôCÑŠ@_:žPÿ( ÑR}Y`°Ãñ~òé›·Ì•ïPNžJh@ÎѽG7ëèso;Úp¥½zF°^S-‹f½u×ùæ9-wkMý °—XEEË:½· [CÛ\,j'5‰kŸ‡ê÷£ÝSöæØÜš±¸9uë×VPõu¦&ëK£ª}rŸGacZ•Õ‹«Q®­ì5§°ÖZî@É.ÖZûJÝo™¦¨7ž×T¨Z-VÂõêeDèEOlz >ƒåØášéd\u5i%ϲ`fž'4DJÄÝ»‚«;ž±«/&Tª¸k†Ë[-´2œ¶¸áÊ`aL‚½Ïk«'à”öóðD7þ¯k®ÜðÓÞ[y“ìÓç/‚x?r÷?dw?û ïðö½Ëâ8ΉÔ}ÍŠùÕBÁ¤µãÍQý^t…5W·Ú­ªª«jÔ›ž¡Öæ*[Ê«Wr¼¬X^a,<–žŒóQ¶3ªà¹ÖãÖOÒªÞÓÂn÷³Ïð&{"öoÿPß—³—Ý«úçöKò˳{³Ç;#ãÇæNáî^Õÿö^9áïøÃÕ¾¬”•½ÒÂ'R[ È0Bëº°Ñ ˆT]"¤2zõÛ_DÆ)¾°UzÇ'IË%¿˜G>¿¥<=Amq[²ê>b|ðŠ9FÇÇ¢ÝZT­ÓÛiàÔï-·9y¯%TñRݶ›#¼újƴÚ‘[Ò•ä+Âç( V¿B~ÂfôG.¶±<œ^s%r1® Ï]5˧†æ¢IÓªÑ>ÔÕÓÉ:6Cpƒs¾USë­¯éíAÖÕÇ-ž:BÛ-•"ì°ém-q*Î Ö› (­\¿† mUÅq'Ak¤5gKýâ«u—¡üÖmnxygÑ÷í³”E3· ºý~LÛ šRÓåax¡ÛÕúÄÞÔXùÅuëéT«„“‹õ©lѬCI`0{oT=L©õÒê%° Í"m¹Èk:ÛÊ€¥cZo7 $¼Ü3¯(TÕšsm¯$àù¡¦8‰”•z5„L=råÙ¡K³*ÍÛÕ¾½R½ºX橞*ÇÍ>ßp{hm’ÓŒ塿NjZ°Z7W'ÔKëD#Íi¶Úç¹j’TäúÙÆØ=afƒP®¦ ´²zf„, *dUÒÍ®jî˜GÏÖg,®|k:µÔŽz6ÚôïÃ~r7I{u vVˆ.õ9˜[›&k6°e¶ÀÔæì¼Hê÷ Pú‡Fé×Ql¶@›7j±ù¥aê"FüDÛë75€lª?• u:DüäDµ"À»_>7%À°|EÍxëc³TBž‹Œ øZztû({nûR¤{4÷Ç–]óáþ=æO®z¿—ÞUv·›ýñáÿ¥ý§Ø^=å·ü§ê[þ•qÃÛGÊ&jãæ´\”† v§QjÏI-(7õy²"Åž"U¼5“F ®‘¡XtæÓã– dø»®[ Ÿë¤Ø€ØÔÈ” «ZK±h:éÔ.+–†ƒÚvû­ẚÿUeÛ@šÏad¯X ×ó*­‰¤v3J–Ó]("TÌ"I9Rï8ѹž†Ì5ŽAh/Ü@íêJÏ®šDŸnd´î2”W]Š»i0_×=Hù±u?OŠøÛ®0röËÏÌ¡dÚbd$ØL-võlÀÌ–L"×1¢$°œMôâ%„•W9:ZtÛ}ˆÏfMDZz³µšÎ¶in•F!eÛL<{IÖˆ×hƒ%2¶–$ÉXÐý$cHn }ƺo¶«mc':m-aœ$ß’¬R¼Ãª?T×%$ÈáI=O˜)Zâ®ÁÝõývRË« ”…éÍ`×ñYT‡Ïž2ð¤1ÆK5¯qöQ‡m˜ÔN­Û^¡zénë"3ƒ]“ªoz­¦” žÃX¦êW¥Œ²öjh;¬˜›aO ÑaÔœ®CPGÒ ðf¶•:Aê “K­\omx×˪ªÒ ]fØ S~lÑW¯sÁ"EkJÓ‚lKj¼­éTC\µ¤òú ÔÞZ¹ºe©*úÝ©2 ‡( óààààƒƒƒ€^=çùSZ?R§J<Ïò¦´~¤ÿN”x8ƒÍêû óz¾Æ^µ~>žý×ü˜wï«ñô÷î¿äø^^–=Dí‰Û^¥z£~ç8\¥!¸[1Y^$'á¶~‰©l°µ»uD$š¥rBiÍvÑMa$ÐîÅg´@ص™ øZÿ‹Í¹sv88T”.©]AöÁo®c–œ¬e)CƒÔò>êãu€ÌÌ‘ê{:×¥–üO[iD­, åÏL-ÆÚŠr¾²F¼fôÏ6˜°­b‹‰iÒÓôõÙ[Û`v.¤ôWLAì²"…XꟿZw¶ôa¬›§JÞÊaüIίª*ŠøÐk¶»*å\úՖì+Î~WU°·Üö@,úðàãú„í&Ê)oM-&¦eÚuz&Ú¾KY×MNZXR`U5Îbq–P½;‘ñ@ :öAX–•ñ!†™Èy°j…¹ïÐã_æ÷(¶º¡|UÅoé5ÖÓѺܹH8]¬Û-QÓè1=osÓ’*1VX“Í ì{½€ç4©è5=…Üшò'-–ÚÃ[†a88Ìå.©´‘„m‹`°*‹×ë/YõÒfÚ¹kUôФ°MZ邽ç‹iÖ«0ì#Ê  óHŒN¶?Ðö<Ý[p ›Z]"«VL£cO®“ºðëvCˆŒÖÝÞ`–gVCnØpPiÔ1%eê‡2eŽÐÿy‘Ìßp,ƒPHªNVE+ƒ2žÌ«LµÙ«‰ÚÍ ø¯,tçÂàmçÑšÝd±5)†ùÓè í†÷­t-nêàÖhÓ×Vì¶FzÒC•%†1*ø  nE',à-€ÂDñ HÄX’ÔŒ%B_ ÛmÍ»ÜõwRŸWÜ•'€ÿwN}úÕÊ«UœÊÖÍ♚'{1E¤Tí6„°›OÃ_ÛÀ¹Š&‰i[¾E.È!I3€Ó\e“—WMnGÖ]ÕÚÂÉ7|ŠóDv«QmÐÖÐò¹±Ù*i\7\“eD]#9ËQzTLÌJ²Š†g<…¨ÒãÁ‚D°ú®ÖÊ5qê*F­nöÂ]TƒÆ¿¤¸À i.i‘ý£+ù ƒq[4ÅŠ­^W ñ9Gp?t2Ö>®T¯9%¸ŒéНíŠjo÷Ñ#c¶sôÈnÞlS“ÁV{­âÊðd™«Ôbí0”2Õ°€ö|‰\󲨥– ²z…ºÏMfÊ ÔXì(C\p͸Y­›`NI¼$5ò½Å_£ûkq{߇ORõ.¬cI¥ÄiÎ;-’Îd¶+ŸJ=Ÿ.û².5%’œÕbQB6+mT*Ï=F}¾c ŠjBÁÒv×qð£}}æþp|(ßAŸy¿‡Ü1Ã^ƒ5áøJ{'¨¶MÇÔ¦–Ö,›Hƒ^i¯¶O™áŽ’=Ìï´=* ¸Jì1ÃÖŠ)ágÈ”ÑÜ,Jþ¤+Ÿq>7/›ž:yKô„d—ÑwI툳o’ Þ9{:—çžÚ¶“6ͲlUnXtg…Ä¢ŒÀÇæPŒî½$j”óP0²ÌD‘Ž1'…è3ï7ðûƒáFú ûÍü>áŽðüá¯Â`éѶ»?s6#huÑgj¯™Ï6iôZÝ–G_B-º­’liµ,§ "5˜ãmüx„ *êÐ*J|t $K^.„s³‹>½‘ÿÖÔ‡ÿާÁñ‘óå#ÿ­¿V¿©ýÉñóè׋‡ð£}}æþp|(ßAŸy¿‡Ü1Ã^ƒ5áøZj2…¶*}§u|U”¾¼«M=¯¨Q·È 6"ÚE°›K¯aÙKÊÎP—c½Zo H±à°³À…qÈC9'JÁƒ3¢èOPݯ²t0·R!æ¢ï ÷öwZ"X§vFç¿+ƒÓ䂜“åe^W”Í!dDÅ]3^éékÌ\*HRyA´«Á¦,_Âô÷›ø}Áð£}}æþpÇ x~ pׇá;Ҝ螩z“VYš{šÞÍÂϺ(N¯ü÷HK`#ŸYØvFÞuq•AtÙ«þ”ë@1Éòð¡ n°ÏzÂcÖÝiÖÍE²iΠKv±˜ÚDêór½¼° ‘éN`½ž)SµÃ¯~ ´,¿8R<¥~ÞbhõÑ\™³–ðI|¼rEŸ 7ÐgÞoá÷Âô÷›ø}Ã5áø1Ã^„§ÒoQléÿAjºm!ŽÃªüÓî5Á#ÅÓ&wÅÕcØâ|‹2ÒÉ® ¼lR>¼º;ÞŠà‚7­ÄÅtœ²×î‡wu«š•A´^) ~ªù®=DWn WauB~Þ7íÒJmnH}1àü}ó]Ù˜N¤@™é¦6Ûc1á8[¶ÔV›¯×Âô÷›ø}Áð£}}æþpÇ x~ pׇáAmî‹»"÷AìBˆ–½Y9a±õ¼zê«Q$ÛÃ_(;¶`ÚOb"FTp_Š(Ã-è2Èà&£Š“æ(“›•.ñ7Ùz;cÓ†¹t{G°ß®ùϲ5ޏ¾ÑÒ•¶& ØW¬y+݈r݃TJt|sÑk€J1)†@I¯Ä&Ñî|(ßAŸy¿‡Ü 7ÐgÞoá÷ pׇàÇ x~‚·è×°Uþºj…6)ú¬.Šë@›ÔTmI–˸+Ý|ÕõcmY¡ë%#c9%ó7Ù'Ç'» †´jˆ;#Ë›ÔÓœøJze7¸i–¶j-“Nuê[µŒÆÒ'W›•ìmå€`DJsìñJ®{ðq¡`Åø¡Â‘å+öóG®ŠäÍœ·‚Kå䃒,øQ¾ƒ>ó¸>o Ï¼ßÃîá¯ÁŽðü5£ƒŒ—øQ¾ƒ>ó¸>o Ï¼ßÃîá¯ÁŽðü*^óü©­©?Ó¥"[ÎÒó¦Óh²ü ¶»—Á?2øŸŒú—ƒ.ˆÿeáâ½gÖ|+Öÿû óïþñÿ—Þ½û!ÄžoVIæõgÿÙnetgen-6.2.1905/doc/pictures/solutiondata.jpg0000644000175000017500000013172013504650527017620 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀUÄ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æî5 ï¥7·±Áyup«4³O ;³2ƒÔŽèààSî!{TäÓôⓦøÙmã NzT0ÆÖØÿÓÿôUîÚH¶Çœ»iè§×Ûüú׫7ÉÒÐåŽ®Äæe Ÿìû døõ¯åGœŸóáaÿ€±ÿ…$*$]ÛÁ#Žßþ¿ðô©|¡W5r^ŽÄ~rÏ…‡þÇþyÉÿ>ø øTžP£ÊVB#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ éì´(5 °¶ÿ‰­µüQÊÁ‰ß §jñœ 1ì: µ¬izH‹Å£M¶…"ÑÚÒÙ%vrZF}²6KayàðGËÆ+'V Ù¢ÔÔã¼äÿŸ üü(ó“þ|,?ð?ð®ÃQð2é·Ö6RÞÜnna·óE‹y?9¬™Ãc= ¬é¼76·“›Æ"ÛX:Q nIb7€ =¾èëMU¤ÅË#ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ í_ÁQi÷:-Ô²Í5¥Ö§ œ°ÜÚµ»üÇ= 'ÏOUÒ´û}2þà¬vÑGâi4ñ"£;ÇRxù°@ÇLgÞ§ÛS¾ƒä‘ËyÉÿ>ø øQç'üøXà,á]µáÍ;Im&4Õ¥šãQ`ËY”’8‰Ç˜T1?AÔöéZ‡Á¶7EÍÕÍÃY]jÙÉöm™n@Ú[;N1œŒgÚŸµ§k‡$Ž#ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ ëΤxªÖȉ¡Ó¬n¦ 4.¢±±Nü¶ñÊ ‡ÁÈë›jh5©¬>Þ–^Km1ã82t Áã ­0ä‘ËùÉÿ>ø øQç'üøXà,á]| ²¸kd×j7ÚjêZµ«r¥IÁ|àt<õàñëÈÄh–Eû¬2*ã(KbZkq<äÿŸ üü(ó“þ|,?ð?ð©<¡G”*¬„Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYØÛÍb©§éÜ ’mSü*_)ÿçÃLÿÀdÿâjk¿y/Ñ­]ò½ª]†dLL3éúvuµCÿ²ÓÄN@?`Ó±¶Oþ&¬jQ£¯Åý 2úÑîníà[‰àRŽÄÂØ'}­'d¶ˆü§ÿŸ 3ÿ“ÿ‰¨£c+2®Ÿ§‚¿{u²qú{šÚÅìõŒÝÝN¯6&pØ ¯LëSYÅþ‘sÇñV¡YôDSÿφ™ÿ€ÉÿÄÔrf¥ôý;ã+lŸüMTžîæ ·Ó–ã1³…7l 0ç?!ã½>µ¯yØ"\“†'©àÒ‹Mì 4SOx›Ãˆ,tK춇2²¡'¡”ígŒ’z“EsºàÛ~ûùš+)B7z›±ÔÚ¡:}©gȯû¢ž-Ææb£-ÁïÅz…<#¡ÞøGG¹¸±ß4–q3·šã'hì¶?áðïý¿ò4ŸüUKÄÁ=VÅ*r±ã~\+j‘¥¸YTó l¾„cúÿZo•ì+Ù¿áðïý¿ò4ŸüUð„xwþßùOþ*”q4ã¢LnœžçŒù^Â+ØW³Âáßúäi?øª?áðïý¿ò4ŸüUWÖáØ^Éž3å{ <¯a^ÍÿG‡èÿ‘¤ÿâ¨ÿ„#ÿôÿÈÒñT}nƒÙ3Æ|¯aG•ì+Ù¿áðïý¿ò4ŸüUð„xwþßùOþ*­Ã°{&xÏ•ì(ò½…{7ü!ÿ wþF“ÿŠ£þÿÐ;ÿ#IÿÅQõ¸vdÏò½…W°¯fÿ„#ÿôÿÈÒñTÂáßúäi?øª>·Áì™ã>W°£Êöìßð„xwþßùOþ*øB<;ÿ@ïü'ÿGÖáØ=“Þ;”ºÙi .÷C•Èf @8-ÏŠµË—R°i6Áo–ÿu½±ViGvËç¾y÷¯Nÿ„#ÿôÿÈÒñTÂáßúäi?øªŸkG°ùgÜòÉ|C«M,Gìúd)¤ºžÈbq¾qÜå‰ ÷ý1QgSd)$6+jÍ«º¼lA”‚6ãwÜç§_zõøB<;ÿ@ïü'ÿU-<;àËû‹›{5µ¹šÕ¶\G ã;BÙ#åNAàúJ=­ÁË>çœ^xU¿Ö!Õd³Ò ¾Že—í6ð¿˜ûF±f9_ojŽë]Õ®‚¨‹O¶EÔ¥þgïÌsë^­ÿG‡èÿ‘¤ÿ⪼¾ð”vö“Aw7;¼ˆ^éÃË´e¶©l¶'(ö´{,ûžg.½©Éwª]-®™ 𬖳ˆbu $9gûßß§µ/ü$ZÒY%¼_a-§ØÅñƒ7+÷Cg¼ã>õêð„xwþßùOþ*øB<;ÿ@ïü'ÿGµ£Ø9'Üò»}{TµÕ,uÒÌËa§®Ÿ²6Ó‚2ß6K|ǡڲ-­>ÏmY`ÆkÚÿáðïý¿ò4ŸüUT´ðïƒ/î.mìÖÖækVÙq7Œí dŒ8•9ƒè}*£ˆ§9>§’y^Â+ØW¯]x[ÂV>OÚà‚ßÏ•a‹Íºtó$nˆ¹nXààMXÿ„#ÿôÿÈÒñU[‡a{&xÏ•ì(ò½…{>ð½Â‚Í%@Ì…’áØRU‡ ÔAˆ"ˆ<á{«xî-ìÒXePñÉòº‘A ‚ïGÖáØ=“e²¹ØÒù”Þ¤g¨ÈúW®ÿÂáßúäi?øª?áðïý¿ò4ŸüUY‡`ör<†¬`“ÌC)|mË—n?úR[4qË+8`äqžç®>µëÿð„xwþßùOþ*øB<;ÿ@ïü'ÿGÖaØ=œ!Xtåµkaò_;“aÁÏ\ÒOä´QÅp‡¸# w¯_ÿ„#ÿôÿÈÒñTÂáßúäi?øª&ƒÙÈù·Ä#n©öÐüTÓm4¯µµ”^T?g¶î-ÉÏrMj\Ú¢¶‡ºx+þD}þ¼bÿÐEn×3á ®„¼=oo Nï§$„Ë)@ªÊ½úVö5/ùáaÿmÿÆë‚_:ÅŠ*¾5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝHËU|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  U|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  U|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  U|j_óÂÃÿÛÿÑKþxXà[ñº±QÜÞ‹9%ò§•‰P©cøëQãRÿžøßünŒj_óÂÃÿÛÿÐv‘=ÅÞ­©]MÔQ¸‰bT€d ûäñëXš¶›ª_ø¶äE¦N-%þÌÛzÒEå£\¼ï‘¿!‚—ïuÀù«¬Æ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ _MÑ5›ÆÒ]ê7zÔºrEu Åé`eÚ •!€WA¸Ž›Ï.ùýâæh¶Þ6±òî%‚y£†YcKYçŒMöwÜs<™oÝܪ–•ˆiî¡;{¼j_óÂÃÿÛÿÑKþxXà[ñºƒCµ»±Ð4ëKùþÑ{¬QÜM¼¿™"¨ Û'$“É®>ÛG×­âH­-. ‡OXV(çšeŽ9ác¬©‡1´q:Ÿ?ioÝg>;|j_óÂÃÿÛÿÑKþxXà[ñºãí´ŸjÞ$š}Tê6T­;‹x5|¦;A’‡rÉ;„aƒ Ì­—¿oáËÏøL®oîïî®l~ÇfŠ“%¹I¥‰¦?0†X¤€¿3œp¯CKþxXà[ñº1©Ï ü oþ7@XøÍµ]Dù7PÙάòÆ·YDñ’;\9RbóÕX%¸ÉRB»$Õt¿K§Ú >-R%–Rlæ½3].Bl-"ÜDv‚&83É÷׎‚.ï—üð°ÿÀ¶ÿãtcRÿžøßün€Æ+ˆ4ûhnî~ÕsJ²Üya<×ÛG ““Ó5ÃÁ£ëÐZµµ­¥Ôö-ºG4ÐX„‘o†Îhö¸F‰wLUò!9RŽß—üð°ÿÀ¶ÿãtcRÿžøßün€8û›-i|6ÑG¦j7êÖ·Ös]G-ÄG$28’G”†%£”޶õ|Fº…Õ½¤ËÆ©gt·"è"Ál¦–0 ݸùr1P•só;KKþxXà[ñº1©Ï ü oþ7@¾¢\è–º½ƒXê2Âís/ý¨ìÓ‡‘Þ5‡t™GÚä;“ÞËçx®–zìžðòjVZ¼æ 3ý­® ±\µÈS*Ì¡“ .G™Ï˜¤©#åì1©Ï ü oþ7F5/ùáaÿmÿÆè²Ñ¼Q{Ëëû©õ(ï,‚,w [´^]ºÝ8€Cb~pFäUc“ÜU|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  U|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  U|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  U|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  U|j_óÂÃÿÛÿÑKþxXà[ñº±EWÆ¥ÿ<,?ð-¿øÝE4÷¶á ±éëæ:ÆŸém–f8~î€<ã/ü­ÿ^±ÿZ(øËÿ#ë׬ÖŠï§ð£ž[žÃàŸùøwþÀÇÿiWK\ׂäáßûý¥]-qKâfë`¢Š*FQ^c¦ÇªXiö±i:#Úk œZž¤öÒfK“<+7˜…UnFß5¼åvÀßó.ðÌéÔW%âÔ4Í×̽½Ôš=RÕòšrÏ#Ä%Fq"Ç(ÁÕP‚¨ÍËQñ+ëw:ÊÚ,w¯ê– Y‡…­–X]¦iz¬‚@êFãò.|¼f@ÝÑEQEQEQEQEQEQEQEQP_6Í>å¼ÙâÄL|ËxüɃʮÖÜðÚr{•ƒc'‰¯"œK4Ëå.{,YS’¥%¶w ä&Р0"Y:Z+ÏÉ)HæEÌMæþåðÎ" “#î€wWuo {YŽÎ+«ÝN,â’Ù ·YT|™ó!L‚@]Ë;î-¸*©ýÞo•âmkÃ-wwz±ÛßÙÏ,í;c™^_–KX·*¨WP±’YHËgezUSK™§Ó-äqu’¸ÝvŠ’¸e,ìaHÎ ©È袊(¢Š(¬sýf‘ÿa(­kVN¹þ³Hÿ°”?Ö€„+ 2« û,bÖì.í|E®ŸijöÿÙp¼KçnÓÓ#h\=±¸8cñ¡…'–ÖtŠî%ŸMÚC5äléàdlbòÅ€ä H„wªkiZ—ö„S¤‘yv²ùP†Ü#“j·ÊØ”««€pÃ!NTdG¦x]XÚîÞH™|¸Q®†-cÈ`AŒPÀ©È*€#Œ-ý:mM·hãÔíä’Fó&žYÐÉ4„]ˆÀÎP€½Oû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ  ”U?í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùÆ€.QTÿµôßúZßåÿTÕ4ùQ/­YØáUfRIôк(¢€ É×?Öiö‡úÖµdëŸë4û CýhÃþ2ÿÈúßõëõ¢Œ¿ò>·ýzÇýh®ú 9å¹ì> ÿ‡ì ö•tµÍx'þ@>ÿ°1ÿÚUÒ×¾&n¶ (¢¤g3â„Y5)]C)ó²dtZµ¡iÖGtÒXÚÈWf7§}ª¿‰ä'¥ÛoýU6úÛO±¼žêeŠ<ƹ<ääðäÒê.¦Ÿöv›ÿ@«ü_ð¨mí4ùdºVÒ´üE7–¸·^FÄn5Wþ­þòÿ…Coâ=&#u+Þ(Yn 'ÈÄ#ŒgÈ來˜Íoìí7þVø¿á\mªÃ}n.d´¶V±Û*ª98WEÿ V‹ÿ?¿ù ÿ¹Í'þAÿÀ¿ô#I‰“ýŽ×þ}¡ÿ¾cµÿŸhïSQHD?cµÿŸhïGØíçÚûàTÔP?cµÿŸhïGØíçÚûàTÔPÎ×ûbÜýš‚X~ìp@$κZÁÑ?ä/ü ÿA5½M QLaEPEP1¶·¹ñ‹-ÄL‹§n *ó:àÖöv›ÿ@«ü_ð¬ç¹†ÓÅsÏq"Çid³7oÞRÿÂU¢ÿÏïþBð  Ii§µìð+OÛq¸?g\勃ÿ Ö¦þÎÓèaÿ€ëþ“ˆô‘yupoFÑ€ìl’ ¤ñŒ÷ôäTßð•h¿óûÿŸü( Ö «ÛÝÖv¨±\4H±Âª¯Ÿz_±ÚÿÏ´?÷À¨ìåI澚6Ý—R2œc ò*ÕI$?cµÿŸhïGØíçÚûàTÔP?cµÿŸhïGØíçÚûàTÔPUmpØZ$Qª …NÕ<ŸÖ¤¤‹þ<íë‚*Z¢‚Š( Š( ©êÿò¾ÿ¯y?ôW*ž¯ÿ [ïú÷“ÿA4§iÇG°fÓlÝÞÚ6fh’JŒ’qK}k§Ûi÷7 ¥iåâ‰C[®2<ÕhµÝ2ÃMÓ ¹ºT”YÄJ…fÆTuÀ8ªÚ‰t‰ô˸c»Ý$º¨òÜd• v  ¶ÓtÅvK±àãþ=×ü+Ä1YÙÙAäi¶Ó\$LÂÝräœq׌U©¼Q£$ò)½RC•F#¯b ckºÖŸ©Cg ¥Ç™"Ý#±‡ŽãÜP?cµÿŸhïGØíçÚûàTÔT’Cö;_ùö‡þø}Ž×þ}¡ÿ¾MECö;_ùö‡þø­áëKe¿‘ÖÞ ë `ƒ ð8ü ¬úÖÐ?ãòoúàßÌS±ESVN¹þ³Hÿ°”?Öµ«'\ÿY¤ØJë@ñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-ÏaðOü€|;ÿ`cÿ´«¥®Gï{á[¬ˆŠú9oV ¯î²>VSúôÈïZðˆYÓ—ýùŸÿW ¾&n¶7¨¬øD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüzͳ fæ+‚Šfˆ0F#;wc8ü¿Îj>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚£¬øD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€7¨¬øD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€7¨¬øD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€7¨¬øD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€6Ò(ãºk¥E²Ëã'h$ãÛ“ü½*>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:vs–94ÚÁÿ„BËþœ¿ïÌÿüzøD,¿éËþüÏÿǨzŠÁÿ„BËþœ¿ïÌÿüzøD,¿éËþüÏÿǨzŠÁÿ„BËþœ¿ïÌÿüzøD,¿éËþüÏÿǨz™4I<2C"îŽE*Ã8È#±?á²ÿ§/ûó?ÿ£þ /úrÿ¿3ÿñêèFŠ5Ž=¨Šªª€ï>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚>Oï~‚¹ßøD,¿éËþüÏÿǨÿ„BËþœ¿ïÌÿüz€:/>Oï~‚ƒ4„[ƒí\ïü"_ôåÿ~gÿãÔÂ!eÿN_÷æþ=@ÔVü"_ôåÿ~gÿãÔÂ!eÿN_÷æþ=@Õ“®¬Ò?ì%õªÿðˆYÓ—ýùŸÿTo ØésÚÎÑfkˆÒ¶óœž:ÍŽ:óé@7ñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-ÏaðOü€|;ÿ`cÿ´«¥®kÁ?òðïýþÒ®–¸¥ñ3u°QE# )ÁŒ…$}) àŒzJ*†›®i:Ï›ý—ªY_yXó>Ëp’ìÎq¤ã8?‘«·Öšm£Ýß]Akm7Í<rp2ÇÉñ  袊(¢£Â×n²¡™]ã 7*±!I@%[¾Óé@QQÇ<2¼©¨ï l‘U(Ø ƒèpÊp{{Ô”QEQEQEQQÏ<6¶ò\\J‘C—’I*¢’I<ze•õ¦¥h—v7P][I“A tl0àòü(z(¨-o­/¼ï²]AqäJÐËåHË‘z£c£ ŒƒÈ  袊(¬$±Ó.u}jãTˆ-’7i$”¢Æ» bN@9=1Z¿ðŠhŸóåÿ‘_ühÅ_þMþ|¿ò+ÿðŠhŸóåÿ‘_ühÅ_þMþ|¿ò+ÿKa§Zi·rGiX‚y$ž=O4ú+ˆÔ¾#jÖ^5‹L‹ÂºÕÆŒ™ŽçQO•±&F_š5äÔç+£I£ÝOvú“O+9KÙ#\ÿ €€4袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š©ªj–Z.™q¨ê7)mgn»ä•úüÉ'É$É«uƒã *ïZðÝÝ…­”×3Å,(÷r˜ÄâxÌŠB1Ü‘Ž2 äw’kŸ+é=3N"YÙu^3"Ãa£&5.s·¨ñŒê~=RÊ]N]9.Q¯"]ïêö$BGP Àuɧj–Zµ»Oar“Ä­°²zàøUèÊÊà ‚yÛ¿hE6›uu$Ëwqˆb2åeY$Ú¾|¤dî@q°™5ô­6îBïRÔeïn"ŠÜ‹u+Ž"åN“¹ŒŽÄg_›ivÖ¢Š(¬sýf‘ÿa(­kVN¹þ³Hÿ°”?Ö€™sÛöùòÄÍ2\ÞÇ>Ôòåἤu$¼xf]¬9u·oá¿\Zè&ãTÔmÞßQ–wb2[DmäA“+Ü;Ï;q1WgEqóéz¬ò­”QÃöÿb– ‘µ¢ˆÄ¼Àg!f |¶Ç™Ì»~JöþÖSÂ|sjZ¼š¬«dšŠ¶ AÀ–#.HØV1"æ2 ‚Kolî( <¹Ó|bºØî<ûÉÖéÏmrÁÛý2åBÏòÌÍ?ÆÜ(íÁKzN¬ÛkÖÍý­ÕÅýÖg Û ò‘A2󌑆ÚÀ‰>EEeÞü›·žâŠãÅ®ºmüIVúŒI&£Ö¦[Åf–Û ’ó Œ¶É¶‚So˜¸)ÎÚö:³y©Û­ÜÚ½žŠä­³j$ΠýŸbK"»9;ÖáÁW$) XR»Š(†‡ý¡ý§kÈKì±}¯îÿ­Ú7ýß—ïg§•~Š(¢Š(¢Š(3_´kÝh£ç‘Z9cXäTpÈêêÈXÞ¥C(o”aI5ËÿgkrÞYj—,­$·PÚßHûbXäá’8ÛhI— ÿtÕ%I^îŠá5OoéÛÅ;,?eK‰£¹ß¦áç—X“vÓ âݲ6T#žâÏ_–ÛÅ«ci=”÷WñMm+¼gψG rÙ efXŸhÏο2•í( <»Òµ5ðDj–šÖ¥)Õ •-m.<‰íÐHŸyÍÄ…ÔÏ“#cxæ0“Ð袀8¿i’ëgŠ4û}*}Jâx’8aŠTEI .ß{ª•V ÿ µ€Ê‚;Û‰nìãžk)ì¤læ ÊL9(̼õàž¾¼V]„sZêºËF w0Ÿ7?*àŸÌþ•¥öÆÿž?øõZ¢ªý±¿çþ=GÛþxÿãÔj©I›u,{™w eIqØŽE?íÿ<ñê‹Î+3ÎccÆB)8p(þZÜIoq®iM’95¬Œ ¾AµoiQéÐGsš¬±E9GÎypq’O ü+•»ðÌÞ-¶ñ=Ç„Qõ;u¿Ûk0Æ×eÆ ¨SÛ?ì®Þ—A·º‚Æ»ƒÈ’{§˜&ðØ qøÐ­Q@Q@ex–i`ðýÔÈñÈ»0ÈÄóŽâµkÅ_ò-ÝÿÀ?ô5  /&çþ‚šþ<›Ÿú j?øjz*I ònè)¨ÿàA£É¹ÿ ¦£ÿ§¢€ ònè)¨ÿàA£É¹ÿ ¦£ÿ§¢€ ònè)¨ÿàA£É¹ÿ ¦£ÿ§¢€4ì´5žÂ)åÕõpÏžçŽ=*øGáÿ ¾µÿ#ü*îÿ ‹_øþ„jz¢Œx4[{‹hgM_[ ,k"ƒr3‚23ǽA©é¶ún5ãjšÛˆÀ‹ 2IÀçrkWLÿ=‡ýzÅÿ  £â¯ùîÿàúв[-¤k¼Ž¾W,ÍîI§T“ÿ®oÃùTtVN¹þ³Hÿ°”?Öµ«'\ÿY¤ØJë@ñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-ÏaðOü€|;ÿ`cÿ´«¥®GÃ\OáElv»èåKy¾YUýÖH;[ŸÃ¿QZðßÿÏõÏþ ›ÿŒ× ¾&n¶7¨¬øGïÿçúçÿÍÿÆhÿ„~ÿþ®ðlßüfÍê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê+þûÿùþ¹ÿÁ³ñš?á¿ÿŸëŸü7ÿ  ê«©X¦¥bö’;"HWq^¸ ÇåYðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍkÿgißóéÿ‘ühþÎÓ¿çÓÿ"7øÖGü#÷ÿóýsÿƒfÿã4Â?ÿ?×?ø6oþ3@ÿÙÚwüúäFÿ?³´ïùôÿÈþ5‘ÿýÿüÿ\ÿàÙ¿øÍðßÿÏõÏþ ›ÿŒÐ¿övÿ>Ÿù¿Æìí;þ}?ò#dÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã4¯ý§ϧþDoñ£û;NÿŸOüˆßãYðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍi]hú]êÄ·lë!Ïp''€Ï•_þþ¿ùOñª¿ðßÿÏõÏþ ›ÿŒÑÿýÿüÿ\ÿàÙ¿øÍ\ èr0g°f Ë\HxuìßøF4úÿäy?ƪÿÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã4ÐHûܶ1šm`ÿÂ?ÿ?×?ø6oþ3Gü#÷ÿóýsÿƒfÿã4½Y:çúÍ#þÂPÿZ¯ÿýÿüÿ\ÿàÙ¿øÍFú4Ö³ÚÏstÒl¸ŒÄ“jlá¤ÏÊ1äÿ‘šñ¿Œ¿ò>·ýzÇýh£ã/ü­ÿ^±ÿZ+¾ŸÂŽyn{‚äáßûý¥]-s^ ÿ‡ì ö•O¨Ï¨I¯-•¥÷Ù£û/št¯“¸Žÿ‡å^f&½:•Z®Ñ[MÙ#zІÖÞ{{XÖæé®ea¸¹@{+‚¼øƒ=„×wmóD’ß@-ÒHã_³$ÌnJìv!Qœ\crõ)ÅJ;0=ŠãüIâ‹Û{«­;EKY.¬çÓDÍ%ÆÜ ‹‚†26ÒB¯¾ÙwTžÿÅÓY¥ËÅekršm˜¼ÔÚ;È×2+,?'ïL‚Ëä(ÈÉÛ@u4W-wã¦ßjk¨éÏmge³G#yžeÇ–»Ê¦c1(®À,¥°9U!‚ÉuâKí>Òåo¬,“RË0ÛAx󉃖À!2î9"0¹‡ØÒÑ\”!¸Õ[Â÷ÖÏ=¬Ww÷wvÊ|çz’>áÁù”šwŒ$Ô¼Dú|zEרÄó[-ØŠbÄX1rb,ŒYä¨* m MW¨xƒ]ƒSÕ ‚$6pëv6«rdPbŠO²ù‘ìÛ’XÌpsÑŸ•*€;Š+–—Ä·V6úÜòؽ̖z´1ÛÅ:ë(· T•@& µ‰ù²7íÁ!ñû áoÝ\ÞZÎmîRÂâŽ6òã‘HiZ"À¬«ü<à€t4W<Þ(d¾|šsÅ$öÉ ´’®çŠU,ÎYrªPEsòî9ò8?:澛⓭j÷:BÄöâX%šÊþÜHË$jʾb™aT'÷ˆÃgš§œœcpSErÚ‰™ô¶¦é¾÷D:Í䎱ªX7’0Î'<·§Íâ?]+ÿ"WAEs͈#¤m0 #qQ!8öVŒÒÚÚYµÕÔ¢(QY䑨*¢ŽI$ôw«Wñìÿ‡ó®cÅš¾(ÒãÓ%´‚{ ï•%žh÷°<å‘:à’3ƒŽ  Qø‹J¼Ò¬5-:cwm"Gˆ@S¸à“Üc#`ãœiW¡ø McƒO´´´³QÝIw /BÀ:ãÀÏA]Šon4ßkWÖ’yw6ÖÍà®±±ƒÈhZŠâåñN­eªj©{erEkhm,DÏ'›#½À©Š&s‘`±ØˆL¸Yàñ·Ú,­&]?l—›á‚9&òÿÒo%Õèdq\9\œí(®Q­¢±n5Mê+ j2¼k!†GžÙ"™”£>ie @•ãpÈℾ4‚[;›½2º…VÜ[;4ªn%•<ÓDäÊÂc“„n瀦Šä ñ ƪÞ¾¶yíb»¿¸³»´hƤSç;Ð8Äq÷Ì ð ïÚiº|7w6ÿë.¯á0¤ ÉåÚ ËȪq»>JŒpdú€u´Wž+Õî¼;­]A£%µýŒt_l3Cm&C^h¢9]¤‘€¼¯Î2JõšÞ6¸DŽb È‘¹uVÇ 1‘žøôBâãQ“X6"×þ=üâgÝýìvü*O³x×JÿÈ•^O¶ÂK(°òѰ|ì\Êb-“·#v1¹s¸hxNúãSðn‡y'™uu§ÛÍ3ís´jXàp2Ié@þÍâ?]+ÿ"Qöoúé_ùº (Ÿû7ˆýt¯ü‰SZG©-ÎÍA­66‹pÙëÜšÚª“œ^!Æ~QÓë@ú†³£i7¶Vw÷Éoq})†Ö9+œÐ}JެX¯¢ŸQ»³‰`›™ˆä°'ìüÿ>/Ä_#ñN±.§ªé3° ¦K»¯‘EX(@2I=I®—DÒ¯té®d¼1“*Ä‹¶Gs„R¼³üÄã’Iç4±EPEPEPEPEPY:çúÍ#þÂPÿZÖ¬sýf‘ÿa(­xÆ_ù[þ½cþ´Qñ—þGÖÿ¯Xÿ­ßOáG<·=‡Á?òðïýþÒ®‰"Ž;¦ºTQ; Œ¾2v‚N=¹?ËÒ¹Ì-ü3 Jc–Mº1ù"BÌÇ÷<+Sûqÿè ¬à/ÿ^¸¥ñ3u±°ÎÎrÇ&«-¢y{m`_*Vš>RH#ŒÕˆô­:-N]N; T¿™vIt°¨•׎ ã$|«Á=‡¥TþÜúëø ÿ×£ûqÿè ¬à/ÿ^€5ª±´3u¬ æÊ³I˜Áß"íÚçÕ†ÄÁê6AT?·þ€ºÇþÿõèþÜúëø ÿ×  âÐô˜%¸–.Ê9.eY§d·@e‘[z»>f óyš·Äò¼q"<;FU»`.O©Â¨ÉìíY¿Ûÿ@]cÿúôn?ýuüÿëБ‚¸K†‰ Ȭ‰!Q¹Uˆ,ê*¹öJ žÐ㸻¸MNY¯ÒæEµ@Ó«œ¸sŒ°cÔ½éŸÛÿ@]cÿúôn?ýuüÿëÐé¡é1ÚZÚ&—d¶Ö’‰­á[t €’VÉ'#žM ¡é1ÝÚݦ—d·6‘mæ[t `UÁ#ŽMAý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½Oa¢éš]ÝõÕŒóßÊ&º’5Á•ñŒŸÔýK¬I‡ÄŸò¹ÿ€èB“ûqÿè ¬à/ÿ^šÚÉq‡ÐõfÓ<ƒ‘Þ€: ¶‹p÷ !º*<ƒ™T’ ž¤Ì@í¸úÔžt_óÑ?ï¡\×öÓÐWÿÀOþ½ÛMÿ@M_ÿ?úôÒùÑÏDÿ¾…t_óÑ?ï¡\×öÓÐWÿÀOþ½ÛMÿ@M_ÿ?úô¿s$mnÁ]Iã€}ëÅ¿Úáï+H×âѵ#–‚iDlŽGð°p~Sž£‘ÁçOí¦ÿ &¯ÿ€Ÿýz‚{ë{§qá½Ffhi,C=9úÐ7 Ïâ£i¿ð’x’=GS¹¾¤¶€ÄÝ'oîÀÜs‚IÈÈtËwÓÁ Õ¼–÷$°Ê¥$ŽE ®¤`‚Ú°’âÊ7WO _+©Ê²éà}E[þÜúëø ÿ×  wzV¨$É{akr“ª$«4*âEBYCdr$€zMG‡¤ÚÚIio¥ÙCm$^Kú*4yc°¨+—sŽŸ3zšƒûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖª“éZuÕŒ–7²ÙÊÅä·’hÝ‹o$©$·ÍŸ^zÕOíÇÿ .±ÿ€¿ýz?·þ€ºÇþÿõèëáÝ RÍFÓ‚X±{E©‹v'q1ñò’@9äf¬ +N[ç¾[ Qxì®÷ó•J)-Œ’™Aìކªn?ýuüÿëÑý¸ÿôÖ?ðÿ¯@ø_A}ëF=”zmÖ|ëhaXÑÉÇͅƆŒ iA6¶ñÛÛÄ‘C„Ž8Ô*¢€jÍþÜúëø ÿ×£ûqÿè ¬à/ÿ^€5•Ž¡âI-5k{›Y,øn#WFÄ Œ«pyþµ¦éúFnÖú]•Œ åÚ;X’%-€2B€3€}…bÿlüåÿ°µmÄOÙ9 tïî:_í¦ÿ &¯ÿ€Ÿýzé|è¿ç¢ßB:/ùèŸ÷Юkûi¿è «ÿà'ÿ^í¦ÿ &¯ÿ€Ÿýzé|è¿ç¢ßB«HÊ׈U½aÿm7ý5üÿëÐ5·#DÕÁöµÿëÐ/ã3âù‡ÿ^1è"·kŠ_7[QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¼GÚ&†=?P˜Å!‰š(C ÀãÖ®êzŒzNy©ÝE(ŠÒÝî%p_¥ˆàž=qïF•§%‰¹’Yžk§œ('ïÀýn½§mèzž˜%ò~Ým-¿™·vÍêW8ÈÎ3Ó5…)Vrš¨’WÓÍyÛ ýSR¶Ò4Ë‹û¹8a]ļ©' ]ÎUA$€2@ÉÑqªéÖw oskÒ2"G,ʬÌå‚ É,Q°;í8èk&ÿF×5oêºUö­§½€Û¤Ði΂%`UÉS3n$9<Ý*=GÂÚŸÚÓ\ÜÁöÝGF],ΖØò¿Ö—e‰ÚÆE;3ü$õˆÚUÓ¥ÔåÓ#¿µ{øW|–«2™Qxä¦r̼‘ÜzÕx|E¡ÜY›È5:[P̆tºF@Ê…Øn ØzV-§‚®·=èÔ§1g¸µPò—¶žmûCHa8ó$y=ÆI9-SNø$Ì:Ž£©¥ñ†xgXÞ)œf$¸Uù¦šV5Àaƒ€P`dæ€;H'†êÞ;‹yRXePñÉWR2#‚ïY6Þ ’ãÄSèÇEÔbxH÷.ÐyB6.ø¶ÆÀ ¹d Ö†mФ$HYœª(PY‰fk™bûDênÚ(‰hÑ ÓHc`ìNõ Œ»[.]FškZjioqc–K*Ú.>ÎåÊ€…YŠ<6 d7îðB¨´º®¿Ú&¿µŽÒ'˜ó(]ȸÉ8Ê„|ŽÛ= Fúæ“¥ÕÛê–Kmi)†âf¸@ȳ…l0yäW5«xãS¶–Èk>M›y4Q}”3¹Žurí»æÚÓ±\ÀÈ;‰ 4õß Zê–v±ÙÓ®,Ù À¬€*#¢¡òž7ØY0×÷v ặŽâÞT–T·ýzÇýh£ã/ü­ÿ^±ÿZ+¾ŸÂŽynz÷„I¼1áÛu¹–Ζ$cRIQxïè>Äè'ÿ|ÃÿÄV‚äáßûý¥]-qKâfëb¿Øýïÿï˜øŠ>Äè'ÿ|ÃÿÄUŠ*FWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ±EWûÿ ÿýóÿGØýïÿï˜øŠ[Û}KO¶¾´“̶¹‰f‰ðFä`8<ŽëQ®§jïrˆîïk:[L©1I#À鉓ÐI#ûÿ ÿýóÿGØýïÿï˜øŠ±QÇ2Êò¢‡&ØÛ‘”€Ü0Ãr23‘Ô#ûÿ ÿýóÿGØýïÿï˜øŠ’i–áÈ,©ò#9Ë£€ ÆO' 'RP±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ«P±ú ßÿß0ÿñV÷ý ìÀꃵÅÂ@¼B,zŸ“°ÍiVN¹þ³Hÿ°”?Ö€áõ\ÈÍ:+2?hré’êqë:sØBÛ$º[¤1#qÁ|à™x'¸õ«ðO Õ¼wò¤°Ê¡ã’6 ®¤dGÞ€$¢¨[ê©q­ßigž9m"†c#íÙ*I¼¸bx1¸;€éÜÔvúþ—>˜š‰¾µŽÎF•c™®#(á7åƒ+#llÝr9‚BMsI‡ì^n©dŸoÇØ÷\ ûFq/ŸŸ;—¦zZ’=WN—S—LŽþÕïá]òZ¬ÊeEã’™È2òGqë@è¦K4PDdšDŽ5êÎÀøš­ý¯¦ÿÐBÓþÿ/øÐÊÉ×uÏìU³Åœ÷-su  ÂD²J‘—fb7ÝdŒgœæ€,ÜxŽ57·ò­až+K‹ F"ž]žZmêÀù‰–"uÌ{UÎ MÝÅs6«Ò.Ç”=¸• 4ˆ¸S"ã‚)ÇîãÙ¯ý¯¦ÿÐBÓþÿ/øÐÊ*Ÿö¾›ÿA Oûü¿ãGö¾›ÿA Oûü¿ã@(ªÚúoý-?ïòÿÚúoý-?ïòÿ\¢©ÿké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4rЧý¯¦ÿÐBÓþÿ/øÕ˜¦Šx„È’FÝ@Ï|=uâ{Hm­mg33}¦uU0’[ÌŒzüÅC/ 3߇5Én&DŸNxnµ-FæfŒZxÒ>B‚ ܱ밯ñŽÂŠó+À¥Ž›¶œ’Ag˜d®¦Uâ}“î7„}ñ²V¢þìØ Õ Ò."†ÓH{‡Öíµ;xšy;TaùŠ1yMÀQµ²ÝŽþŠç®¼94úñgEÓ'žË«rçž„ õ•Žìàa¼Æ"‡ü#šˆ³ñU°±Ó–-Róí6ñÅvцÊFŽdýÉŸ/y]\»+2[°®kÃÓê—Z„“µì÷º\‘3EqÉ&FÓlçò¿Ös!bG–U˜Ä1¼-ª§„4ý6;M"K«=F¸Q˜D¬r‰8.ØeÊĘî —·}á‹»Ÿ5úÇdÛî ¸Qw?j´Ž0›­ãNc}ŸGïßå<îëh KÂþcù~B´:Y¶Ô™®gNÆ$Œ²¨IBîû¡€P­¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+'\ÿY¤ØJëZÕ“®¬Ò?ì%õ øËÿ#ë׬ÖŠ>2ÿÈúßõëõ¢»éü(ç–ç°ø'þ@>ÿ°1ÿÚU»|ú‡ÙÑ4õ¶ß¿.×°:?Ïüax'þ@>ÿ°1ÿÚUÒ×¾&n¶3t[›(n~ÖÑg¸i”NѸ_¡ªshWskz½ëÝYIm`–kk5‘p»7\ù˜u&Y2¸\£#ê*FrV¾Ô­­¡f×<ÛÛk¯´Û4ÑÍ4(Þ[ÆÛ–YžFÊÈÜ @)|Ûî[ø/CkT]SKÓµ;­ÒÈ÷hÇt’<¬p%S|…ÉÀ=IÉ= “o¥]Ãâ«íYï kk›XmÖÜ[éå³°%÷re“£ø}ìË/̶útzí­á²Õ¦Õe™EfJvá°VI‹ÏTc?5u4Psðê;‹§‘µhnZe½€´ñ¬Ð½ÄÓlTÈ3‰ÝIpàðBŽA×Óü;ygâ)õ©"ÚÈÒ0³·ŽTC¸çæV•ãÎNâȈÌÜçƒt4P?Š¿ä[»ÿ€èkXcµÿŸhï[ž*ÿ‘nïþÿ¡­dÒbfƦéí§;ɧÚHÞixTñíW¿³´ßúXà:ÿ…gÚjvznºòuˆ=Á 0I?(ÏŸÿX£þ­þòÿ…1–­-4ùíüÆÒ´ð|É‹uè²2Ð mõ®Ÿm§ÜÜ&•§—Š&u n¸ÈóTmÇkÿ>Ðÿß‹?øñ·ÿ®küªj’H~Çkÿ>Ðÿß±ÚÿÏ´?÷À©¨ ~Çkÿ>Ðÿß±ÚÿÏ´?÷À©¨ ~Çkÿ>Ðÿß»i".5TEUT` ã벟ýs~Êš9´ñu¤Š,¯ÙOB±?ô*wü%vßôÔïÈÿÂÒäü ÿB5v‹…ÍøJí¿è¨ÿß‘þ5$^#IóåiZ¤˜ë²ß8ýk.·<>H†ðƒƒòZ.#þÜúëø ÿ׬Í:H¸k3Á“ÙL˱¤¶ÒÒ6+pJàã qì+«óûíùÕkI¥ioCJä-ÆÕË•ÀüI?1”?·þ€ºÇþÿõêñ<19I4ÝIuV€?ZÞóûíù× ¦;Ëa’3;±ffc’Ic’M!ð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹¡ÿ ]·ýõûò?ÆøJí¿è¨ÿß‘þ5ŸE Ÿý£™mn!8S:…Ýë“þ·PißòµÿÿèF§¦0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬sýf‘ÿa(­kVN¹þ³Hÿ°”?Ö€ÿøúÿØšüûÿãëþ57ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øQ`±«k–Úu¼R®×]ÙÏ|Óëþ­þòÿ…ð•h¿óûÿŸü)ŒØ¢±ÿá*Ñç÷ÿ!?øQÿ V‹ÿ?¿ù ÿ€6(¬øJ´_ùýÿÈOþÂU¢ÿÏïþBð  Š+þ­þòÿ…ð•h¿óûÿŸü(bŠÇÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ Ø¢±ÿá*Ñç÷ÿ!?øQÿ V‹ÿ?¿ù ÿ€6(¬øJ´_ùýÿÈOþÂU¢ÿÏïþBð  Š+þ­þòÿ…ð•h¿óûÿŸü(bŠÇÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ جsýf‘ÿa(­7þ­þòÿ…Q¾Ö´ýJïJ†ÒãÌ‘uXŒ8ÉǸ øËÿ#ë׬ÖŠ>2ÿÈúßõëõ¢»éü(ç–ç®x>¸ðÿ†ÖC( ¤ýÜ­ÿ–]Ôƒ]'Øí½oð>oþ*°<ÿ ÿØÿí*邳 …'è+Š_7[}ŽÛÖ÷ÿæÿâ¨û·­ïþÍÿÅTä8 ­D'…®ÝeC2*»ÆnUbB’:€J¶}§Ò¤c~Çmë{ÿóñT}ŽÛÖ÷ÿæÿâ©ÓO ºžT‰ *v 1 £žäîH%Cö;o[ßü›ÿŠ£ìvÞ·¿ø7ÿSQ@ýŽÛÖ÷ÿæÿâ¨û·­ïþÍÿÅS§ž..%H¡‰KÉ$ŒQ@É$ž½I@ýŽÛÖ÷ÿæÿâ¨û·­ïþÍÿÅTÔP?c¶õ½ÿÀù¿øª>Çmë{ÿóñU5A{}i¦Ú=ÝõÔ¶Ñã|ÓÈ',x?_±ÛzÞÿà|ßüUc¶õ½ÿÀù¿øªpž¸{u• Ȫïa¹U‰ Hê*Ø=öŸJ’€!û·­ïþÍÿÅQö;o[ßü›ÿŠ©ª9'†'‰$•æm‘«0Û°=NŽ`OjoØí½oð>oþ*±ÛzÞÿà|ßüUMECö;o[ßü›ÿŠ£ìvÞ·¿ø7ÿNÂ×n²¡™]ã 7*±!I@%[¾ÓéRP?c¶õ½ÿÀù¿øª>Çmë{ÿóñUÏiv¾M/MþÖšÒËçd&ºòÚv·»†ãÊŒQë[ÿðŠhŸóåÿ‘_ühßc¶õ½ÿÀù¿øª>Çmë{ÿóñTßøE4Oùòÿȯþ4Â)¢Ï—þEñ }ŽÛÖ÷ÿæÿâ¨û·­ïþÍÿÅSáÑ?çËÿ"¿øÔ–æ-3J•£FX MÛb°2NXûI>¦€ö;o[ßü›ÿŠ£ìvÞ·¿ø7ÿ\F‰ñ\Õîõ‹kï júDi’i×7N•S8”•Ú¯X;s özc¼ºMœ’3;´ÌÌrI*2I  >Çmë{ÿóñT}ŽÛÖ÷ÿæÿâª(õ]:]N]2;ûW¿…wÉj³)•ŽJg |ËÉÇ­O ðÜ!x%IP3!d`À2’¬8î ŽÄ@ û·­ïþÍÿÅQö;o[ßü›ÿŠ©ª¯­'»¸´†ê .m¶ù𤀼[†WrŽW#‘ž´¿c¶õ½ÿÀù¿øª>Çmë{ÿóñT駆ÝÏ*D…•;˜…QÏrHw$ $žž$’TG™¶F¬ÀlÀõ8V8=¨¿c¶õ½ÿÀù¿øª>Çmë{ÿóñU5Øí½oð>oþ*±ÛzÞÿà|ßüURÔ|E¡é o©ë:u”Ì»Ö;›¤ŠäŒ€Äd}_Â×n²¡™]ã 7*±!I@%[¾Óé@ û·­ïþÍÿÅQö;o[ßü›ÿŠ©¨ ~Çmë{ÿóñT}ŽÛÖ÷ÿæÿâ©ÆxVá-ÚT:³¤e†æU 1©²äöÜ=h†xn¼¤¨²0`IVwGb ýŽÛÖ÷ÿæÿâ¨û·­ïþÍÿÅTÕÛ­?´>Áö¨>Ûåyßgó™åçöõÛž3Ó4¿c¶õ½ÿÀù¿øª>Çmë{ÿóñU5Fg…nÝ¥A3«:FXneR: .OmÃÖ€ö;o[ßü›ÿŠ£ìvÞ·¿ø7ÿY²éöº—Š„7qy‘­–à7Îüv>æ®Aá¿][ÅqooÐJã’9Ù•ÔŒ‚lG9  ¾Çmë{ÿóñT}ŽÛÖ÷ÿæÿâ©¿ðŠhŸóåÿ‘_ühÿ„SDÿŸ/üŠÿã@û·­ïþÍÿÅQö;o[ßü›ÿЦÿÂ)¢Ï—þEñ¥¶ÒltËàm-Äe”dî,zû“@ ö;o[ßü›ÿŠªZ‰†ÌÙª ¶7QÁ–¿›å y?{ÐÀñÄ c@ñ ¦Ÿ¦x[WÕm–Lß\[ÙÈʈG Û†qO8ãnrIY®µu rÒJ`[ë# H†2•›• yäžÇ¥y/Æ_ù[þ½cþ´Qñ—þGÖÿ¯Xÿ­ßOáG<·=‡Á?òðïýþÒ­ûÝDiö¨E½Ôîï÷mã.@ÇSØV‚äáßûý¥]-qKâfëc'Ak‰c¾žâ9ãinÝÔN¤6Ü.:û ~Ç]øcÅs‰$¶¹µ‚iï5,J¨c¸Ž9cagœHK&E¶&T$óνŠ‘œ&¯¥k~${ùnl/m-û>k[Q¨‘Úäy‡îßjÈË´/ÌF|²YJüÔì|Ap‘›{]F'ûǧˆµ.,§ñ%Ñ.<àA€‘ûá”a³—î( k]ѵ™4½^M?_Õ$¹–ÖàZڳƂFFÄjã Füð2O5SijFÔu—yÒK¸åœ´’®ÆD‘%ÌlUdC´ •~Šó]oÃþ+»ðÌÖ%ïo§›Kxmö\­ºÃ#7¤êÒ8“1´Q©&S”c½ y•Òé:>§l·Z…Åå캇ڮÚyï?pЙd0Æ@ pQ·`ºýÜí+¥¢€<×KÓüsnÒk:€]Ž$<g£Ñ@ðûé¾5]FÂÂw¶šÖÞÚ5Šõ¢‚ØDd º-Ø+±×bª0Üvd¹Â°Ð¼lmîëR½ŠäËl²É Jßh¤š"óÈB,¿'•`à8 =*Š©§ië¦Û´Ü]MíÈ.fi™åÙfÉù‰#$€¨öWx©u/íMj-‡ B¬ÎXÕdÊ+mç1ÇÃSZŠóË}?ÅÇNÖ’½†Yü¶Ž[éó+&]URåÐ3F\e ¸ ·nÌr[i> ‹L³Šê÷Ö»¦g±µ»û5ÌL|±d7L]Ù‰ÌÍþµFÜ(ÙßÑ@"ÃP¸ÔtI'$°ˆ½Íט¬gg‘¡Ur»¶ÈĪŒ¤xSÎÍê( mïï4¨,ÓC¾¹Ó.m w“iíj$º_2PmݦueŒ+1ÊüÄËò²m;½&±416£[ÚÍópÝ2Äãõ­¶7üñÿǨÕWíÿ<ñê>ØßóÇÿ  U‹yoe>•9Ô¥Xì¢dÌòP«“– Ž^xã=«Cíÿ<ñê¥q<öÖ/ö{V¹˜aÂwä’h—¾]KåZë]Ä»Y„P_yŽB‚Ç ®IÀñé]=‹BÖÍn¬°”Æ­Ô.ëÚ¸m/Â0hSj÷O„ÒÖãSVWqv„D¤r‘áLüÛG` vútO™i ‹¶HáEaœà…Ð7c¦ê6þ&UK9ãÓ㺞à‰Ú -×ÌKÀ@‰Y¤ä?ÈÊ ‘³9£LñE׆,í-†£§ÞÁ¨ÝÈw|„E.ØÈë#™]àR¤¶v†Q“ßÑ@ÕŸŒ-ô­bÞÚ«™®¬æ´°o·*ý›d·[³Îö‰àÚÃsOÞûÕ½z’xËXºL&M:Þ+yå™)e¦b§igP|å)ü-í»¡¢€<Æßþ$Ô4­BÓR‡QñOewkÞ4rHÑÊZeVûTÍ’ŠwHª ½t·ê¢ëÂòÁ¦ê*Nëu߇Àcd_;tƒÍ|˜˜ãy Üêh UÓ.ƒP¸Ñ<­5/^v•r¶ŒªJòNâf…¶ôû’)Î3•Ü `ÔïtÖ{o³ÜÁ,SËrfÞИ|¹,Ìd‘2Œ70ä˾™ÒÑ@汦ͫj³ÙÀчk(ÜÇ)!&UY¢rù$U(Üü­Ðîx~ÆâÖ+éî#û?Û®Úé,Ã-C*‚¹.æeioän[ï´QÃ4^ 7¡‹ì¾WÞÁ-¿?Óõ­?¶7üñÿǨÕWíÿ<ñê>ØßóÇÿ  UR|›ÄÁÁÚ9üi~ØßóÇÿ¨Ì†K…‘—hsÞ€9MDxÇPšßSÖtÛ{ÕlËΡ¶@O9`ÏžAÏãQÈš,W:zh̲)¾´‘åF,ެ¡RIÏäqȪž%ðÍ·Š5›-GRð’ÜËe!h™î‘|Ôç çrä†ÚsÏ ±,7¿ÚðÞ^Z}›í•¦Ôóþè`y‡ç@Qñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-Ï_ðŒ¿„4)`™aa¥ƒ”ÞT°ŒçáO~¸ëZ?Ùº¿ý ÿ€)þ5‚¿äGÐÿëÆ/ýVíqKâfëc'û7Wÿ¡¿ð?ÆìÝ_þ†ÿÀÿÖ¢¤fOön¯ÿCà Ùº¿ý ÿ€)þ5­Edÿfêÿô07þ§øÑý›«ÿÐÀßøŸãZÔPOön¯ÿCà Ùº¿ý ÿ€)þ5­Edÿfêÿô07þ§øÑý›«ÿÐÀßøŸãZÔPOön¯ÿCà Ùº¿ý ÿ€)þ5­Edÿfêÿô07þ§øÑý›«ÿÐÀßøŸãZP̳¡tfOT•<28=Á’€2³uúÿSühþÍÕÿè`oüOñ­!2µÃÀïEW$£Á$ 60OÊrÈã8ÈÌ”“ý›«ÿÐÀßøŸãGön¯ÿCà kVMŸ‰t»íA¬ –4K$!¤µ–8ä’2ÁÑ$eì6· I±èìÝ_þ†ÿÀÿ?³uúÿSüjÞ™©Úêö+yfîг:~ò&ƒ#`UÀ`C)#µ[  ŸìÝ_þ†ÿÀÿ?³uúÿSükZªj:®—n³];€í±(šY$l…D˜à€' &€*fêÿô07þ§øÑý›«ÿÐÀßøŸãWì¯mõ Dºµ“|Oœ AÁV•`AHAŠŽ NÖãS»Ó£wûU¢Æò£Dʾí¤1`v°Ê“‚¤ETþÍÕÿè`oüOñ¥]+Xs…ñÿ^QÿhÃ<7^ RT ÈY0 ¤«;‚#±Uˆå§û†€2±µ¿ú7þGþ4ckôoüüjÝÅí½¬Ö°Í&Ù.å0Â0NçÎG>Tcϧҋ;Û{øZki<ÈÖY!'|ñ»#Ž}X~POìmoþƒÍÿ€QÿØÚßý›ÿ£ÿÒ¢€3±µ¿ú7þGþ4ckôoüükJŠÍþÆÖÿè<ßøøÑý­ÿÐy¿ð ?ñ­*(7û[ÿ óàãGö6·ÿAæÿÀ(ÿÆ´¨  ßìmoþƒÍÿ€QÿØÚßý›ÿ£ÿÒ§¬N˹ZÊþÆÖÿè<ßøøÑý­ÿÐy¿ð ?ñ­o"Oîþ¢£$odܥဠí8Χƀ2[MÕ–CñÎb¿c àã>Çò4fêÿô07þ§øÓtïù5¿ûaÿ Ø  ŸìÝ_þ†ÿÀÿ?³uúÿSükZŠÉþÍÕÿè`oüOñ£û7Wÿ¡¿ð?Ƶ¨  ŸìÝ_þ†ÿÀÿ?³uúÿSükZŠÉþÍÕÿè`oüOñ£û7Wÿ¡¿ð?Ƶ¨  ŸìÝ_þ†ÿÀÿ?³uúÿSükZŠÉþÍÕÿè`oüOñ¦ÿc^Ësk%Þ²ÓÇo:L승*}AúÖÅóÏÆ_ù[þ½cþ´Qñ—þGÖÿ¯Xÿ­ßOáG<·=§Á_ò#èõãþ‚+v°¼ÿ">‡ÿ^1è"·kŠ_7[QR0¢Š(¢Š(¢Š(¢Š(¢Š(Î&𾩇¡éO¦éÀE­ÜÜ}š ${aÇs ÈD(„Éå}Ò¼Œ«PÀÞ Õ&Õn­ÄV¸þΊ8fs KyîZÜãk=ººª ¨pW %[Ó¨ ?UðÖ£}}âÃoo§C³¤­œs ˜HÓ*È¡¤Q1‰vçs#^pµ5Ï Åcö‡‚ø•Éövkah÷É$Ëç‰%¸€óîßÌ 9tFn5ÝÑ@÷ì&Ó|)´Ð$Ϲ•#ŽˆÞy1$Æ6²‡•Î Ñ¡xZ 2inîKÍx×—WææWŠ1,Ò2”ŽÄ}´•Pya’ ÏCEqmáÝnçÁ·zUÄ:Xž{ù®/0MÇ$Í67I *°gêbpBq´°)™gðûQþʾÒÚɨÿg}:O9™mfܼN0ŠªQeˆ+*›X(QÁôz(‹Ò¼yeã[fâëÌ¥šT™1$¡ÉÛƒÈÞc@ØÌÃ1¡ 0ïx‡NŸRÓãKx`–Xå*Éq%»t#äš?ž&ùº€r7)bFµÂ^ø?V¼…ÃÙ^Nö¾DW2»I¥6ù–(ZI^5ÞLlÆÝ¶[åèm¬uüe¨êEj,'³‚Þ6YØËº6‘²S`9‡ ~àþ÷˵EsÞ ÒæÒtiíçÑtí!ÚòyFRçk’@äŒqè…û‹ÒÃÿ-?Ü56Iž yž(Zi6‘«¸ýO€1üA¡.».’²ª5½¥á¸”32¶<‰QJÈpîŒ ¹ W,þÔþÏ$2Ie},¿hXonŸéî÷J.a  ¤J„…òþhW Œêÿ´u¯úÿäâ…Ú:×ýòq?€9÷ð5È·v³»K-J{Ë÷šþ's"Á8¸1¢žä‰ö«¹ ›“Á^ŸÃ¶÷hÙÎË‹{y"0¨P~p#‚îÁ;I!ž?Ú:×ýòq?Âíkþ€?ù8Ÿá@V?ö޵ÿ@üœOð£ûGZÿ þN'øPÅý£­Ðÿ'ü(þÑÖ¿èÿ“‰þ±Ecÿhë_ôÿÉÄÿ ?´u¯úÿäâ…lUMAõCå&ž¶{Típ[$“ØóÏ·4¿´u¯úÿäâ…Ú:×ýòq?€ø©êÿ‘*mÆæÊŸµ´FYîcå´n×èjíkþ€?ù8ŸáGö޵ÿ@üœOð Nÿ‘“[ÿ¶ú­ŠÇÒ!½þÒÔo/->Íö+jyŠÿty‡ç[QEQEQEQEQEQEóÏÆ_ù[þ½cþ´Qñ—þGÖÿ¯Xÿ­ßOáG<·=§Á_ò#èõãþ‚+v°¼ÿ">‡ÿ^1è"·kŠ_7[QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢¹ïZ-Þ‘’7–(çñ›&¼‰†Ö½HiS$áð¦°a¹Öm-m Ž-GN…`ÍŒ6Vd¸—Ì“å‘\eD%cg‹`‘“xÙ”ïè®-u{þvkm{ý—,­‹,,c‰LÂEe€(Üê¸ÌïÃࢷ SO¸¹Óþ\G¤Øj6ŽšÊÄ‘Ù< Mrò#Úm…GËãv0¸fPþŠá<=qâíqË]ÞO¦G ª2y–ë¥Ü .]•hÒ&u ÊWÊÎCã&ºðN¿ooË4ºuÂGjYŒlrI=¨jŠãáÒæðœ6—özrD÷™Ô‹¤‹ÁäÈÔÈîD¬œ¯ €5™¡ã+‹}bôý¶×ìv²ÜÚÙ=’žU¸º `e1¤!‚Ç(UÆIpC¢¹+Kbë[žÚkÍR ^YãxRÁ>ÍxŠXædÁºN]Œ|¼[hõ+„wºa]^Kû=9 .ž’~øFÛÇ–|ØÁ*ÊUÉpJ€z=ÇøƒSÖEÀ“M:ŒhÖi.V%–êä—ÌW;£&„d˜±½þo—å~7ˆ×Pµ¸»žy`¸Õ/-ZØÚ„X-”ÎÑHH·.5 HR®>RÇyëjX Èê×+àkŸµèwijš†/îSÍÔ­¼‰°ÚhùGèr0˜Ø½L?òÓýÃ@Ÿ'÷¿AGŸ'÷¿A\׊,ïo/<=ö bÔZC:Ãæ,`ZÎqýÂJ©ä›”G-mqâk £ÞÚ\ù·“ÙÛÚڙ⺹k»†òævŒ”‹NùYYîãåôï>Oï~‚>Oï~‚¸7ºñ„ïy{Ë™¯/íà±–ÕR4Ã@ìÜ6KGî,ªUÇŽóÁWZåݽܚ´$!•`7ºM»~C[À6cf0‡ùcÀoŸ'÷¿AGŸ'÷¿AQÑ@yò{ôyò{ô'Ÿ'÷¿AGŸ'÷¿AQÑ@yò{ôyò{ôW¾Õÿ³–ÒÖòá˜~Ïð¼ñ“Ó×üâ€.yò{ôyò{ôÿ <Ÿô Õ¿ð.sywÜ÷‹:¹cÌ›JÇ´cüóš[K»‹UŠYY£„B#^Ë•$þgúzV•céßò2köÃÿ@5±@Q@Q@Q@Q@Q@Q@<üeÿ‘õ¿ëÖ?ëEä}oúõúÑ]ôþsËsÚ|ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¸¥ñ3u°QE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ G¹†ÒÞyî$XâHÉfnÔµ$AImà )8  ?øJ´_ùýÿÈOþÂU¢ÿÏïþBð­ÍñÿÏ/üxѾ?ùåÿÃÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ ÜßüòÿÇãÿž_øñ  ?øJ´_ùýÿÈOþÂU¢ÿÏïþBð­ÍñÿÏ/üxѾ?ùåÿÃÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ ÜßüòÿÇãÿž_øñ  ?øJ´_ùýÿÈOþÂU¢ÿÏïþBð­ÍñÿÏ/üxѾ?ùåÿÃÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ ÜßüòÿÇãÿž_øñ  ?øJ´_ùýÿÈOþÂU¢ÿÏïþBð­ÍñÿÏ/üxѾ?ùåÿç4;¨ou½bâÝ÷ÄþNÖÁ‘ßé[õN Cí:µõ ‰Q-Dx9$±`IþŸ¯ár€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€>yøËÿ#ë׬ÖŠ>2ÿÈúßõëõ¢»éü(ç–ç´ø+þD}þ¼bÿÐEnÖ‚¿äGÐÿëÆ/ýVíqKâfë`¢Š*FQEQEQEQEQEdë··öeÔrm¶û|PÝ ´‰.b@3é,‘1äp§¯CËCãÛÈ-mÓ.µ'¸ƒûHù0Jζ³I!E©F»HvEÈ;|Ì;¹à†êÞK{ˆ’XeR’G"†WR0A‚íP]éZuýŵÅå…­ÌÖ­¾ÞI¡Wh[ å S9ƒÒ€2`ñ íÕÃ4û_²É=Å¥¬’Þì’Iá26p„Äü¡vÆÌnÛ™¡ø«S›Âúº‚Êã[ÔbƒÊŒ]íWKæÊDypŠ\VŒ•êcÒ´èµ9u8ì-RþeÙ%Ò¢W^8/Œ‘ò¯ö•èzL–—V¥Ù5µÜ¦kˆZÝ M! —uƲÉç@6~.Ô5é­,t/:KX„—Gíj 0šx]#Êüͺ)¡ùŒ|¯â›Û7ÂÕõ¤ž]͵„óDøk¬lAÁàòZ¿ocii³ZÁØ’åF¦v'»› ÉÇZ|ðCuo%½ÄI,2©I#‘C+© ƒÁv kL¾Ô,%±PþוõÃj©©›@Ð…‚Yw¯Ù×›pÇ=øïB?ˆMsýÕž–—Iw5Ò^)V'¸ˆ”ÂÎÂßzŽî ºàìolm5+G´¾µ‚êÚLo†xã`äeOáQÿeiÛ.ì».T¤ëä®%RYˆn>`LŽH=Ýs@0x†öêáŒ}¯ÙdžâÒÖIovI$ð™ ›8Bb~P»cf7mȳñ6ª~I«Ý‹WÕbÒRù– °£h·y§1ŽvÈBìeÊã$glzV§.§…ª_Ì»$ºXTJëÇñ’>UàžÃÒ£}I’ÒêÑô»&¶»”Íq [¡I¤$î¸Ã6@9<ð(7\ñ,ÚMÅêÃb—é¶k|ï9–dÇ”¡X;â8bƒîóÉÄzŠn.õc›Kò-./îtøfû@fya2å¶ÄeanIܤaδš“7ؼÝ.ÉþÁ±î·Cö|c_&6¯Lt•almËÛkùR´Ñâ06HÛ·8ôc½òzÇÔÐßjz†,Ú­½”3­Ôñ*ÙÜyɱ$el 7#Û¤”]¨å§û†³4LÐm×J±‚Εæhá] »“ý  iÃÿ-?Ü4Îø“RÔ4ë iñyíq~ÑMeS,bÞg*¥†e¨$YA&°¬|qvÚeýߨþÕŸö«Ë·¼‰l.n5Hö|ÒWÙÈ\œ’Go$Êñ<‘#¼-¾6e£`®G¡Ã0ÈìHïU%Ðô™å·–m.ÊI-¥i g·Bb‘›{:’>V-ó9'šç¥ñÓYÛÏ}}¤¼ZlsÞÛ$±Î¯$l&f!0B?%ÝÆÝ¿9ÒðÞ¿u­ý¥.ô©ì¤ƒa ÑαÈ<)š(˜°Úrà^NHëchž^ÛXÊ•¦²Fݹǣï“Ôî>¦£Ó´­;H·k}2ÂÖÊmí´+–À!@Àû ·EPEPEPI=Ý•”Q©bŒÉœy’Î=3õ¥¨'±´ºp÷°LÀm $aˆœýh?¶´ùû´ÿÀ…ÿ‡MÔ†¦.äDEŠ+†Š2»r€9ϾIü¾´ïì7þöŸ÷å§‚Ú d)o q!9+…õâ€34ïù5¿ûaÿ ج};þFMoþØè¶(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(矌¿ò>·ýzÇýh£ã/ü­ÿ^±ÿZ+¾ŸÂŽyn{O‚¿äGÐÿëÆ/ýVíax+þD}þ¼bÿÐEn×¾&n¶ (¢¤aEPEPEPEPEPEPEPEC\Ô¿±´ GTò¼ï±ZËqånÛ¿b–Æpqœc84~Šç´O®¤#k‰t‚—ýšÙôÍA¯å´Œ¬|µB.{çیۛĺ]¼)<’Ïä4²ÄÓ-¬­M”ÈáJÆ¡ù˜€Np3@ÔV,ž [=OZ‚þ$‚ÏL³ŠøÜ¬Œå¢o7vP.AS p dߊ·u¬YÚKs†w–Ú(æ–(-ä™ÂH̨B¢’Ù(Ý3Œdàs@è®xøÂÀëšn WS%üJ³Gk3Ù$Hö0 òYƒn#Ë*¸Uèuý6}LéñÌæmͱ…ÄNëÈ’‘±Üa²ªÄ‘ò¶4éÚ;È%·”°‰Ð‡ ÄdwÍÐõË_XÉygÔq¤òÛ‘snжäb¤€Àd~ƒ† xå§û†€1ÿáÐç‡þ?'øÑÿ–ƒÿÙ  øD´ùáÿÉþ4Â% ÿÏü~Oñ­‘ÿÏ_ütÕ[{¸.žq3%0³ÇÌÎ?<~ONµÒ¬onítäe‘Ž[ä¨äú1øiV>ÿ#&·ÿl?ô[QEQEQEQEQEQEóÏÆ_ù[þ½cþ´Qñ—þGÖÿ¯Xÿ­ßOáG<·=§Á_ò#èõãþ‚+v°¼ÿ">‡ÿ^1è"·kŠ_7[QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªš®¯¤^é— ë ä[ÈÑ+©RFAÁô«tP)ðü“XÏk}­j7ÂFŽH¤™`V‚HØ::yq¨$0S† >QÆ2f¹ðóF×4ûKiíí­m~É"Å.ÈÀÀÚfG(Àmc’v®:Ú( []êz¥ÝÝÕÔðêVkc=›yCv0UCƒûÉ9ÝügÑqBçÀ¶w©xou-Fê{Å…e–àÄàùFB¿º1ùXýáJmÈ €ã}u4P5gà› :ÊÎÖòö²yê&…’7xæ“Ì–?•¢– ‚Yv¬¼æM?ÁzF›â)õ¨!O´JÒH[ÂJHç.âMžnN[‚äÄt4Pf‡¦]i62[Þj×Zœ<²‰®UC*³m`üðp£^ùiþá¨é“yÆÞT·•b•×jÈÉ»o¾23@õ]:_H½Ó.ÖÈ$·‘£ 0WR¤Œ‚3ƒéUõ=2êúûL¸·Õ®¬£³œË40ª•º]¤l|‚q“üøÝµ–/ìíkþƒßù&ŸãGövµÿAïü“Oñ  ±éÐÅ«ÜêjÏç\A»©#hXÚFR8Îs+gžÃñ·XÿÙÚ×ý¿òM?ƪ^›ý?gÚ¼IåïÎßô9Ç^ŸQ@ÉiÉÿCOþSÿúÔiÉÿCOþSÿúÔÖÑ\—öœŸô4ÿå?ÿ­GöœŸô4ÿå?ÿ­@mÌZÏw{8†ÛĦI'O©éZØÚ÷ý?òR?ñ  J§§µù7×–ë -¼ÏsÆOù÷ªo¦kQº£ëê!~ËHÉÆ}Çæ(þÎÖ¿è=ÿ’iþ4Â?ÿQ}[ÿúÕsMÓbÓ!’8å–O2C#4¬  gœ{U?ìíkþƒßù&ŸãGövµÿAïü“Oñ Nÿ‘“[ÿ¶ú­ŠÍÓ4ɬ®nî./>Ó-ÆÍÍåÆÐGcïúV•QEQEQEQEQEQE|óñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-ÏiðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­Úâ—ÄÍÖÁETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*9äh­ä‘!y²ÅPÎ@û£q'§$R*JŽq3[ȶî‘ÌTˆÞD.ªØà•3Û#>¢€0¥ñ¶‡k§hw×—ig²¡íÍ̉Å12ùl‘Ÿ™Ôw­c©[ ]4±"¦® Sr ` ”ÎìN|¤ŶðÅݯ†ô+Ô 7Ú.߳ܵ©ò›lOßüŸÝ¹èãæÁéòÕ³£^ÿÂE¦ê_ÚI$6vrZɶٖbå 9ueU9‰8 ½ê6€H|K¤A­öò⸒y–T1ÁäÄ‹#gåaæ©ÁèÎ;½uý-lìîno­mEäâ%žâ0Yobb¬NIR@çÖ.•àë'P·¼‹Rä²ÒßK³ d>X³ˆÈCn‘—aÏ*§wÊů‚vÙh÷º‡ýj¶êÐÃåù»&·–2rÍŒ}™Cs¸‘·¥uµB=sI›í¾V©dÿ`ÏÛ6Ü!û>3Ÿ3Ÿ“[®:JÍÒ|¡éÖzbÏ¥é×Wö0A¿{4óY¢EU|H?(Ç<`sÅS‹Á× §[XÉ©@ÑiÑEšËdÆ"’9ÍbÄÉÌî å†ù¸ÎÒ€CÄZ·‚àk:w“p²<2}©6ȱ‚d*s‚¸Ž˜æ¬WN[ä±kûQxìÈ–æeó•C° œ’•ˆì†¹ÑàŸ´j‰©j‡›rÒùó‹x|¤iÚ²m˜ªf€‚XÌA^ÍÐ<u§Kqo5Ú 5žÃ-öuó.VÒ -•ƒe›îVÝÇÝÚIfì"×4™å¸ŠRÊI-¥XgT¸Bb‘›b£~V-ò€y'ŠŽOhqi‘jrk:rXLÛ#ºk¤;sÀ|àŸ•¸±ô®yüö›++ ëø.,´ø¢µµˆÚ}ëtš &Ë‘#0·EÈ9c´ä&­ày/õ[NÛU{k©gyrª£Ål§É–6'6êAÝŽH*NéN«§-òXµý¨¼vdKs2ùŒÊ¡ØÎI ÊÄv CT4hzÝÝ垥jÐÙ´‚á¼ô>R£2ïl!e'ªóT ð=••½Ül$×–7D[™"µˆ±9aû“‚Oaàó›ö5îšoRÛRO³ÈÓËmÛgd³HdfîÀv;BìÂ’ã†ô½RËZÓ-õ:å.lî|r§B?˜ äyyVþxmuÝ.ââXá‚$¸y$‘‚ª($’xsNðõîáÝ>ËQ’ÖKÈ HäkH|¨²0«Ð08qª8êÖ6úž«aay™kuÌ3&â7#G†Œ‚zPÖ™¬[ê¾jÆ“Á4X/ÌF96v>ÓÎÖ‘èC)••t+/JÒÂââòêòKÛéÑ!{‡EOÝF[Ë]«ŸØœrÎØ »Qu(¢Š(­çß‹ñ¯8ø‘©ø‚îî; kznš!‘d¸žV”ÊΧ!XÙBð7rs÷HÞy÷âük’ñ¿Ä 3ÀOÔô}RkiøK«TFŒ?]„—69är3Œààj3êzÔ3Ý›Sxºv˲1os·z«`‚ã8ÉÆO[Yv¼Ú¥Í´Ù—kCrb»À™rû@e…ãœg<€pA¯@Q@Q@Q@Q@Q@Q@Q@Q@<üeÿ‘õ¿ëÖ?ëEä}oúõúÑ]ôþsËsÚ|ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¸¥ñ3u°QE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (½ž;+n >aŽ&7c8ãô¨,gk« k‡ X•È^€=ÂGâ›Ïøeo¯åŸVfÕ/ w”ÇG¹¸$¨HÀfÙlp2Í÷”tŸQñøÓôä¼þÏó¼Ÿ?ûBšY 2쉔©håÚÒÛÔ|Û@;J+’Æžg‹-ô_³Ù/u-·–ר¼dr?˜Öû8¼¿•·ò®ß[øŸP]'Nìß´ßÞê—VOÚ”,m\s¿bæ1äãîîÛΆ­¢¸½GÇãOÓ’óû?Îò|ÿíbidx24l˲&R¥£—kHboQóm¶ž(Õf±Ôo­ü:ó[Z5ä1ˆîCI44Š0s±Œ{sËll+ó¦«KiæßÚ݉ µ¸} ¥€Ë5¤øšË[Õï¬ô÷K‹{X ˜]Äû£”ÈÒ‚ã ÊûÊHÉ+ÁSXºåïˆdñ}ÅŽ%éXl-æ‰"ßg¼“ŒÜ?yåŸ-så|Ø ŽH ÛΟþzÿã¢:ùëÿŽŠâu¯öö?ìÿ´ÛCæâivÉ,P¼¬Œæ!Ç•"²;0WïmŸ\Ö¼Gm£¬ðiPZN×öq§›x4RΨUˆFÛ'!XUCîWr1@?üõÿÇEtÿó×ÿZÊãíV‰)h œ¤¢ |ÄYíu ¬äÇ t©èfw »îÇN1Y:Ž›¨ê»N%€È®µš8B¤9cÔ}FF+ZŠÊ±Ò® ÔÚúïPûT†$$&à{¯çZ´Q@Q@Q@Q@Q@Q@Q@Q@Q@<üeÿ‘õ¿ëÖ?ëEä}oúõúÑ]ôþsËsÚ|ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¸¥ñ3u°QE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€3ïtM?Q¸óîàidÚ+ Øp*ì1$Ç k¶8Ô*Œç }BËCÒtØ’+.ÊÖ8å3"ÁnˆB» € ´•Ï\TwžÐõ/´m:é#gtYíQ³ÎFG$÷<šÐÔ.-´ÛInn%`‘ ©’}ú’*ž¯©eYGqåy»î­íöîÛ6d‹=MùÇ|cŽ´è)ý­ô·÷³Ç ­=½¬®­22²–S·yáÜf*`…Û=–‡¤é±$V:]•¬qÊfE‚Ý,…vi+ž¸8£RÖ,ô¯(\™ÚIs²+{y'‘€Æ[djÍ´eAl`PO#5%ñf‹Ä1 §˜LÑ"Íoo$І”¨Œ4¨¥¶ô 8u=${ÏèzŠF—Ú6t‘³º,ö¨áYÎç##‚Ç’{žM\6Vÿd–Õ#òb—~á1¹%˜Á K¸rsœÕ}gRþÈÒg¾ò¼ß/hÁmª¹`»°vƹÜ̓µCb³m<[júd7Waæg -›PI•q¹ã1&‬J.ŽêXö™£:ââêkë«ûÉÕ#{‹‘o- @#U\îsŒüÇ$€¾ …nábA3ª£ÈneRJ‚z 6mÇÖ¨>¿¦¥Å¤Fgd»Tx.kwpŸ¾Ë޲K.>ðÌÞ \k-¨D–©¦Þ}›1ÈÒù¡£Ð€íæªìÜÙ<þÐ¾¸Ñ´éo%R’\Ij#©]„#$ùqéÇJ¿<Ý[ÉoqK ªRHäPÊêF ðAª ;SµÕ-ÚkWr¶:KE$m€pÈà2œp@È ô ÕºŽ!µ·ŽÞÞ$Š”$qÆ¡U à;T”Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@<üeÿ‘õ¿ëÖ?ëEä}oúõúÑ]ôþsËsÚ|ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¸¥ñ3u°QE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ )@$€:šYÄ›ä*‹2Ì$àÄœP.­¤ê«Nª¬vÒ‘û•¶cç=‡ùâ¬ëRk:q³{‰íÿ{Ë4w£Ç"ȤnV_¼ƒ¨5bâöÞÖkXf“l—r˜a's„g#ŽŸ*1çÓéEí½ü-5´ždk,“‚>xÝ‘Ç>Œ¬?(!ü74žLÍâ PßCæ,w»-üÁì-ß+fÒcC»²>ö “uà¶:…”PAm¦ÛKi"IõÂ2¬2¨ðsÌDA|Æ €WƒåÝ¥PÕõ‹= O{ëó:Û&w¼VòM°If¤…±àzЋÛ_¶Z<|ð3`¬°>×F ŽÇ8 ƒÐ‚ xJ4qu­¨Å©–v—P_$Ë(q²•1˜ÀÄ0•ýØç–ݵeyý¢\³¬oœ àx_ƒŽQÀaÓ¸÷©è–¿ð—«ÙjROuæÚ4ü¹˜˜˜2þöTiT£!\–'–blOàû;»}jÞöîêêZt¹’9–"±HB ãá÷°d¶í«Û}KO¶¾´“̶¹‰f‰ðFä`8<ŽëSÐf…¡Ùø{L[$@›‹»¬BdcܬH‹œ2piÑEQEQEQEQEQEQEQEQEQEQEQE|óñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-ÏiðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­Úâ—ÄÍÖÁETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠrIè sÚÕ5+ËU:SCW‰7˜Ó¡;A=TCêk~ŠÉ×,.îÛN»±=Οtnä1¤¹ŠHˆ.ŠàJ[;NvãŒärÓø3Uk­:xãÓšh'–í¦šQ"Ã$·1 ÀÄ….äxYð2W W¿¢€8½+Á×–^5¸Ön.¼ÈÚY¥I‘ãJ±H<æ4 € Ì3£/Câ-:m_ö™nȳ^YÍoHHPÎ…A8ã'Ò´è /Å~¼×õû[Èî±l±$D$µ!˜´°—‚R$!‡*c Æ¿1ãmôðÛ¾­%ÅÔSXÍ,û¬[sGuÁ•AùLóo@Ä­ƒŸ0ÍÒÑ@>—áGEÒ´Ë{+m!IdŠ8ËD/XA$ ,®ìvÀWÁLomÙSFðKû»{ì·"·–Ð4ˆCus7˜«Ÿ‘À6°%ï¹ËwP oàBj:¤—w›ö‡ŠDºX$›Ì  óV5 >s`ÆŒ`*ëx3A¼ðþŸqms”1¼¾bEj±ðpbÑà œáF6d`å› /KEQEQEQEQEQEQEQEQEQEQEQE|óñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-ÏiðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­Úâ—ÄÍÖÁETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠeÆ¡o¦ÙÉqs2Ä€ª‚FrO`;ÖV“«WVÔ.[dxÀñß?§µlQ@µýµ«|LÑ®[Ny&NºOµ‹&e‹ÆPBíS´O€HÆâ?Œg6Âo 'M–I纾¹ÒÅìÑ=ªB©­q¢yº»ï‘¥o%]e1ð?x~mÛñˆÔmÛ×’w¨ ?ì–£Å÷²ê:MÕÍü—‘>u³(q…¬Å£, ß+y€4z5î§u榵íÕ³XHÚ­µÎŸˆàŸåýÌF ñfr>o›çí( N¹Ôm|áX júmªiËÔ–ºsKsñ¬j±˜š'!%%¶cä\0 7ih#Åw÷\ê×ah%€}‰mTÄù·…¦òK(v)VùX™ :Ú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(矌¿ò>·ýzÇýh£ã/ü­ÿ^±ÿZ+¾ŸÂŽyn{O‚¿äGÐÿëÆ/ýVíax+þD}þ¼bÿÐEn×¾&n¶ (¢¤aEPEPET}SOÙúÕ]NZeCÍ'ö¾›ÿA Oûü¿ã@(ªÚúoý-?ïòÿÚúoý-?ïòÿ\¢©ÿké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4rЧý¯¦ÿÐBÓþÿ/øÑý¯¦ÿÐBÓþÿ/øÐÊ*Ÿö¾›ÿA Oûü¿ãGö¾›ÿA Oûü¿ã@(ªÚúoý-?ïòÿÚúoý-?ïòÿ\©T ‡s&ã»qYßÚúoý-?ïòÿU¾›CÔ¢H®ïm¤p_µmõá†ýtkO¿7ïx|¥`¹hNBÉüI®"óâ ö]Ý´ÍK}´kI#~Ì“0u¹+±Ùü†FppËõÖ3èzl- ¥å¤q³n#íó€;ŸaM•¼9=¿Ùæ:Tî‘ü·1•Üნ2Áß'¾öÏS@:§‰õ }_gÓ~Í}§Ø åŒ])"ó0KleYG•'˵Ó!~fx‹ÆßðjÒÚɧùÐCj—*͆åg‘€]¸â;YH;¹b‹À%—Zí¼9¨$Ézt«”Q%YŒn$T%”6z€I „“@o-»Û©Ò„/Ú¼`ǵ¡PBÆGB€3az ÇÖ€3eñtƒÄŸÙ0X¤é3I­Ê´Â7#g(ïäùjÔìw`GÝá¶æØxÖúÛÁš-Ö¡mÖ¯}¿— ¼!pð´‚Y8K¦á¼"8qœd¯Aåx[û[û[ËÑÿ´¿çóyßwoßûßw޽8¡âð´–—VŽÖ×r™®!aI¤$î½²Éç@4mEõ]& Ùlç´‘÷†dde*ÅI‚¶ÓŒ©*¤‚ 8Ñø‚Åywu§m°µº¼³g†åd”Ën²Èw€Z8‰˜6âݤ9é Ô4{[xííîìb†% qÈŠ¨ `Àvªu¿‡4¹žâ ›ºv˜›—xÌ»e™¦dÜ0vosôêy  «êS5½¿ü#“‹»‹¥·Œ1šŽè¥óC¾IÜ+7’µ®5]B+ßÅ=ŸÙ¾Ûu, · ÛYa•Æ>C¾3å’Q‡É‘Ë(}”^ÓbH¬cÑícŽS2,$ !]…Ài+ž¸8©.Û×÷ׇJ¹šÕ·ÛÉ1ÚÈ9ByS9ƒÒ€2nümö¦¿ºÓÿâR²ÝÁ±Mºv’Ýei3P¡OÙåÁÞIù2NÚ7ž*Ö!ÿ„´IÏ£épNmíîÑ•¼övY dîòÕY#¯M§st‘·‡"ÔåÔã:R_Ì»$ºS•׎ õ#å^ ì=*¸³ðŠØ½ŠÛh‚ÍÕQíÂE岫PW¡™˜ʼnêhu]~âËP¸·¶²‚hì­RòöIîÄ"c 2¥Y¿u&w²(ù~nI]êÄ’/ Mö/6=þÁ±î³ãòÿ¹«Ó¥_þ×Óè!iÿ—ühåOû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ  ”U?í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùÆ€.QTÿµôßúZßåÿ?µôßúZßåÿ¹ESþ×Óè!iÿ—ühþ×Óè!iÿ—ühåOû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ  ”U?í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùÆ€.QLŠh§ˆI ‰$mÑ‘ñú(¢Š(¢Š(¢Šùçã/ü­ÿ^±ÿZ(øËÿ#ë׬ÖŠï§ð£ž[žÓà¯ùô?úñ‹ÿA»X^ ÿ‘Cÿ¯¿ô[µÅ/‰›­‚Š(©QEQE™#&œ6œfâãÿFµZóäþ÷è*žŸÿ áÿ_ú5¨×/×JÓ.nc]ãhf8É þtsÏ“ûß £Ï“ûß ®wÆ7·–y´ù'Žå®­aSn#2bKˆÑ‚yŸ&â¬@ÝÆMT’óSÒ¼?gq;ê2Ë>£m¢þKdžä™#ÀòchØGv»|Ê@À[çÉýïÐQçÉýïÐW%qã #ñKéiWÃ'¦Y£Ó’{ÖWÃtÌT’ë%FÜb³•ÁÝË2/B\u6÷Úœž*¾±–ÞÉtØma–Rã3—fpwGŽå8?ìð[$ ¥åìÖö7¡£œ8ȪVÒø–êÖ„m0$¨CÎÏ5.§ÿ ›Ïúàÿú ¬í.ûTOèÖ2Ié“hòËH¹wxͰÞÌz­u =2IÜhíñ?÷ô¯üü(Ûâïé_øÿøW5ŒuHìR鼉ZòÑn¦FO—F&háe›¨FmÅëiùPqQáû단¯ ¸“ía»kT¼ º ªK`|»•™£m¼o¸_¸  Ûâïé_øÿøS[þeRÅô¼Ÿã­Údßê$ÿtÿ*‚_ìêò¹-À%N=+[$Òǹ1÷s Ï~G‚k‘Ó>¸ô› !vª“yw7,++³.Addúšô_>Oï~‚>Oï~‚ˆ‚’Û†@RqTPθºzBª¿f3—ÜI'pP?Ÿéø€_óäþ÷è(óäþ÷è+€ñ.³¬Ûx½¬l./Q>ËkäÒßì«q,“ªý¥œy‚61¢þìç°ù™AŸZñøÑïocþÏûM´1Naž&—l’Å ÊÈÎbŒyR)Û#°#~öÐãÏ“ûß £Ï“ûß ®JOÞÇ|º[é «;Fm¡’ï÷{$Yœy®¨v8ÒåT8ÎЂJäé^=º¸Ñ.µ´K¨lÖâúíÞáU’Ô\\,b!²Já a÷•Næ;‰‡çÉýïÐQçÉýïÐW¦øÛíºÿö\Ú•¾êkxåI·çk\*’ Œgì“’2qû¿½¹¶mkº•Γ¦5Õ­ƒÞÈ.ÅÞBƒüD";‘ÛåF9# .Xkùò{ôyò{ôÅÉâmEõÍáréSi×7­-ÛF!hä…d'tY=Ì0Û2KTf=kÇãG½½û?í6ÐÅ9†xš]²K/+#9ˆF1åH§lŽÀŒûÛ@;>Oï~‚«j7·i—sG&Ù#…ÙNÁ H®_\Ö¼Gm£¬ðiPZN×öq§›x4RΨUˆFÛ'!XUCîWr1[7WjðÕÜ¥ 2}žT”A/˜‹"‚®¡°3µ€xä”sOw—K²’Fgv·™˜ä’Pd“V*®™ÿ {úõ‹ÿ@j€ (¢€ (¢€ (¢€>yøËÿ#ë׬ÖŠ>2ÿÈúßõëõ¢»éü(ç–ç´ø+þD}þ¼bÿÐEnÖ‚¿äGÐÿëÆ/ýVíqKâfë`¢Š*FQEQEWÓÿä?ëâãÿFµT¹ðþ™ys%ÅÅ»I4‡,Í+óúÒ½Ž `HàÔ–Ô,’¹ n$ݾFaÉ>„q^MGý›«ÿÐÀßøŸã@SA ž$•+…u ) §žà€Aì@5£¥iÚ½ºÛêv·°«oXîaY6È Î çÜÕOìÝ_þ†ÿÀÿ?³uúÿSühÜšV.§§%…«ß»#ºhTÊ‹Ïñ>fàçÖ£CÒaûo•¥Ù'ÛóöͶè>ÑœçÌãçÎæëž§Ö þÍÕÿè`oüOñ£û7Wÿ¡¿ð?Æ€/ÚXÚXDb³µ‚Þ3·+ aÊ¡ÑUT{(ª94­:]N-NK W¿…vGtЩ•žã |ÍÀ=Ï­TþÍÕÿè`oüOñ£û7Wÿ¡¿ð?Æ€'‹CÒ`–âXt»(乕f’Ý–Emêì@ù˜7Ì äh½ÐôJ'ŠûK²ºŽIDγۣ†.ÀäËms×ön¯ÿCà Ùº¿ý ÿ€)þ4?ö“ý­ý­ý—eý¥ÿ?ŸgO;îíûøÝ÷xëÓŠ¿Y?Ùº¿ý ÿ€)þ4fêÿô07þ§øÐµ“ý›«ÿÐÀßøŸãGön¯ÿCà kQY?Ùº¿ý ÿ€)þ4fêÿô07þ§øÐ”ðCuo%½ÄI,2©I#‘C+© ƒÁv¨.ô­;PI’öÂÖå'TIVhUÄŠ„²†ÈäIô$š©ý›«ÿÐÀßøŸãGön¯ÿCà [þÊÓ¶\'Ø-v\©I×É\J¤³Ü|À™{»棋EÓ Öî5˜¬`MJâ%†k¿;¢ôþ_]«œíƒû7Wÿ¡¿ð?ÆìÝ_þ†ÿÀÿ¹©ÿÈ&óþ¸?þ‚j¾ŸáÿÜEa©Üi\šŠÃ ‹©-£3U]§yÈÀÁÏ iZ«£#ë商61GçKý—ªÿÐ|ÿà ã@ ki ÌñQæ}ò²àm¡rÞ§j¨ÉìíD iko½¸†"@‘ÇQ@ÀŒW=ý—ªÿÐ|ÿà ãGö^«ÿAóÿ€1ÿt¾t_óÑ?ï¡L–XÌ.ŠISÞ¹ßì½Wþƒçÿcÿ?²õ_úŸüühÞ®d>š85o웉Øo0å¾2>Wᇎã8 ò<óI›Å‘øwT“Å>,·½¹säÁgha °8Ë"†;€8^Êy8^Î} úè(¸Ö`™ÛæiѶ3×> ÿ„ZOú[à®*ßž¹·’ wä]®ŠäzdsU,t]?M™¦´·òäeÚNöцmñƒæÆ7a=Wæn1õ5NèwWÒ_\hÚt·’©I.$µF‘Ԯ ’ ü¸ôã¥3û7Wÿ¡¿ð?ÆìÝ_þ†ÿÀÿ·w¥iÚ‚L—¶·):¢J³B®$T%”6G H¡$ÔrèzLòÛË6—e$–Ò´Ð3Û¡1HͽI+ù‰“ÍAý›«ÿÐÀßøŸãGön¯ÿCà _[DòöÚÀ¾T­4xŒ ’6íÎ=ï|ž§qõ5£¥iÚ½ºÛêv·°«oXîaY6È Î çÜÕOìÝ_þ†ÿÀÿ?³uúÿSühÛéZt–ö–ïajÐÙ²=´m •a aJŽ„tíUçðî‡u}%õƧKy*”’âKTiJì ± ¯ËN:S?³uúÿSühþÍÕÿè`oüOñ  )à†êÞK{ˆ’XeR’G"†WR0A‚íTõ!µðõÕ½¼I1Z:GjQB€íPÿfêÿô07þ§øÓ&Ò59á’5öhäR¬>ă ŒôLÿ=‡ýzÅÿ  µQ[B-­ · ¼EG¸Œgjœ~-QEQEQE|óñ—þGÖÿ¯Xÿ­|eÿ‘õ¿ëÖ?ëEwÓøQÏ-ÏiðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­Úâ—ÄÍÖÁETŒ(¢Š(¢Š(¢Š(¢Š”,b5fÝ–ÏJOÜÿÓOÒ‡ÿSãüê:“÷?ôÓô£÷?ôÓô®Zó[Ô­¼L¶’-쌱ÇšÒb· ÁFñr¿»‰·1U†X b‘SGñä7ZŸw¨Y]Cswgñ(ˆ*ÝHÆ4eˆÈlÑ 2mx`Jå€iûŸúiúQûŸúiúW;iâËõ°¸Š{³¼IÉAå:˜Feb¥›í0•ÚNwcƒÅiéZŒ:¾‘e©Û«¬7GqÈ`®¡€8$gÖ€/þçþš~”~çþš~•ÅØx²ò#3k‘ɵvØ­¤°L’´‰Ä!òîù ªQ*OÊà­»ß\6œ—6}–x5K[+Û[Èú dH7ÚlÈáaØŒçOîé§éGîé§éX³x†Ò¶nŽsöKø,$ÂŽd›ÉÚG?tyéžü©áß_ëUíÕ΋u–óÜG{¡ý÷—,ˆq!À@±UÜx;y —÷?ôÓô£÷?ôÓô®jßÅ]#Fž+­BóR³[´‚Ù#‰Œ{P³‘$T" »ØüÀ$Gkã2öoôh/d´ó`‰¯|°©#hzÇwœ‹€¤©å‚‚ êsÿM?J©©ß[éºt׌’¸Œ ( d“ÏnMOXþ*ÿ‘nïþÿ¡­n…ŒF¬Û²ÙéIûŸúiúPÿêbüG@~çþš~”~çþš~•Îë_k—ÑÚ%²Óî’ÖXeüÉsrYap%R’ŸxnÊɦêw³K¯Çq\>Ÿxb-“cH†¥U;ßÿy·9PpË@ß¹ÿ¦Ÿ¥¹ÿ¦Ÿ¥rÐxµOÐÙ,oo®õ[¶C¬ ›€–Îé6Çþ´™ñÁ‰*µñÆ™{7ú4²Zy°D×¾NØTΑ´=Hc»ÎEÀRTòÁA€u?¹ÿ¦Ÿ¥¹ÿ¦Ÿ¥sOâ¨m-õ{›Ë{¡†£—¤ýà„)‹‚f À ƒ»‡ ñlnâÖ'Q—S ë.ž¾H– ‚6f,d‘‰¡?+“ûÁÇ ´¥ýÏý4ý(ýÏý4ý*†•¨Ã«éZººÃyw¬€ ê‚Fp}jÝC¥ÞCªiâõQÒ6'j’3€Äsùf­~çþš~•á/ù!ÿèmZ”'îé§éGîé§éX:µö£ý¯c¤é’ÚÛÍq÷-=Ì 2…¢]¡Ðä™Îî6‘ƒœ€j:ŠxŸOÓîÕa¹Ó¦¸’8Ã3G4o $$B%þà?.{ào~çþš~”~çþš~•Ë'¬M£]Ig{jo-duL]À ƒ"áÎÅýäd™|¼ÉÀV+^ïâg¤é÷òøÿó 1}²Ôecm¬|Ã0ˆà•à9<ôá°Øþçþš~”~çþš~•RÆößRÓí¯­$ó-®bY¢|¹#‚:ÔôWN¾MJÅ.âFHä-µXäà1þUj±ü+ÿ"ݧüÿCjØ Š( Š( Š( Š( Š( ž~2ÿÈúßõëõ¢Œ¿ò>·ýzÇýh®ú 9å¹í> ÿ‘Cÿ¯¿ô[µ…à¯ùô?úñ‹ÿA»\Rø™ºØ(¢Š‘…Q@Q@Q@Q@?ú˜¿çQÕ;ý=¯Ìy¾¼·XÁmä{ž2ϽSÿ„þ¢ú·þÿõ¨Y´ 6}LjBæmË#(™ÄNë®ñ±Üap̤‹ƒò®ÞÑÚÒÒÔÚ~êÎ×ì–àHàÅc#iÎCd6w ‚ 7þÿú‹êßøÿÖ£þÿú‹êßøÿÖ Ÿ è­n‘=«¹FgóžâF˜±e¥-½ˆÛ“´Ç(„kA6¶ñÛÛÄ‘C„Ž8Ô*¢€jËÿ„þ¢ú·þÿõ¨ÿ„þ¢ú·þÿõ¨±øOE‰%EµrŽ»ZâF(!€‡-û ¡=¸(„cjà›ÂšDú`ÓäŽèÃç­Ë0½˜Jò®6³Ê{‘…Ææ8ظû«‡Â?ÿQ}[ÿúÔÂ?ÿQ}[ÿúÔëÏ è÷ú‚ß\Úy“¬±Î?xá|ØÊ”“`;|ÁµW~7mIÛÅ=4 6;‹¹ã…ã–é]’g]Î_ËÁýÑc†b›K0 r@5ü#ÿõÕ¿ð'ÿ­Gü#ÿõÕ¿ð'ÿ­@ _ i ¦YéñÇu6Jc·h¯fIcCÕªáöp¿)l|«ÇÊ1:xJŠÞKx¬’8dž“dª‰"ˆÈàÇÀÀùzrsü#ÿõÕ¿ð'ÿ­Gü#ÿõÕ¿ð'ÿ­@â¯ùîÿàúÑÿÿýEõoü ÿëTrøf)â1Í©êrFÝUçÀŠèýL_ó¨êþž×æ<ß^[¬`€¶ò=Ï?çÞ©ÿÂ?ÿQ}[ÿúÔ,Ú›>¦5 !s6å‘”Lâ'uÆ×xØî0¸fRFÅÁùW¾ƒajú›Ãö¥}I‹Ü·Û&$¶6årß»8À1€ªÝ‹þÿú‹êßøÿÖ£þÿú‹êßøÿÖ  Oà,Ë¥"yñÚi–³[ÛÆ·ù±ù&ß½p#+€~ë•àpd²ðn•iªÝ_y ™gŽX¢ŒãcŠ8ãFE;\!zn!l¨“gþÿú‹êßøÿÖ£þÿú‹êßøÿÖ '†´¸å¼“Êšòê+ÉÄ—R¸2ÆÊÈÀ!pQ8\ *Œ`U5¿ C©‰ §4ÿhž-FÄ^C$žZÆae*áQTÀ`¶A$gþÿú‹êßøÿÖ£þÿú‹êßøÿÖ  ºV‘¤Yi–ìí œÛÆÒXª(PNÀô«uÿÿýEõoü ÿëQÿÿýEõoü ÿëPžÿ‘Røþ†Õ©YñéIºlW0ħ>dlžIÆqê{z}j¿ü#ÿõÕ¿ð'ÿ­@u-ÏUòÈd‹;%·¸’ ewÆÊÛN•Î U$p1èjjvz„p¼SY@m­Ö)"Ž#ÕDJBc…ê¿Â¿Ý‹þÿú‹êßøÿÖ£þÿú‹êßøÿÖ ÇáM"•"Žê!"ùkåÞ̦Èmù…2«•h!T€…4ƒn‘î‘Õ™þÑìËpÅ€tÁüÆ* #ŸÝ\;þÿú‹êßøÿÖ£þÿú‹êßøÿÖ  Š+þÿú‹êßøÿÖ£þÿú‹êßøÿÖ ¿ò-ÚÀÿô6­Š­§ØÅ¦ØÇi ;Gp\‚y$öúÕš(¢Š(¢Š(¢Š(¢Š(¢Šùçã/ü­ÿ^±ÿZ(øËÿ#ë׬ÖŠï§ð£ž[›'âï„]ü6šm½ÒéNÖBrì†A)»o8Î3Œš?ázßÿÐÛþÿ7øQEJ§«Cçh?ázßÿÐÛþÿ7øQÿ Öÿþ€–ß÷ù¿ÂŠ)û(vyü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQEʃžAÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿ÍþQG²‡`çÂõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Qì¡Ø9äð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáE{(vyü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQEʃžAÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿ÍþQG²‡`çÂõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Qì¡Ø9äð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáE{(vyü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQEʃžAÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿ÍþQG²‡`çÂõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Qì¡Ø9äð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáE{(vyü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQEʃžAÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿ÍþQG²‡`çÂõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Qì¡Ø9äð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáE{(vyü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQEʃžAÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿ÍþQG²‡`çÂõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Qì¡Ø9äð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáE{(vyü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQEʃžAÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿ÍþQG²‡`çÂõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Qì¡Ø9äð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáE{(vyü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQEʃžAÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿ÍþQG²‡`ç‘=‡„åøÆ'ñ,º‚iOŸcò0;U[víËýüc¨¢Šç•IEÙ(¦®ÏÿÙnetgen-6.2.1905/doc/pictures/topologyexplorer.jpg0000644000175000017500000010605513504650527020552 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀU"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æî5 ï¥7·±Áyup«4³O ;³2ƒÔŽèààSî!{TäÓôⓦøÙmã NzT0ÆÖØÿÓÿôUîÚH¶Çœ»iè§×Ûüú׫7ÉÒÐåŽ®Äæe Ÿìû døõ¯åGœŸóáaÿ€±ÿ…$*$]ÛÁ#Žßþ¿ðô©|¡W5r^ŽÄ~rÏ…‡þÇþyÉÿ>ø øWU­Zé‘x?AšÏGŠ+ýNG‰® ćg–ÀÚN>o§âµ¥ðõŒzõ߇ôÿ Mª5‚D.ï[QI¹Óp(„… ð÷9ºÐ] ägŸùÉÿ>ø øQç'üøXà,á]Ö—¥h«àRº±Ò$º»iD’j«ÚµÈqÁãéLÐ4]/Qðõ¥ÅŽ›g«êR»››I5#o$ ” ÇÍÇsÿêN¼ôØ|¹ÄyÉÿ>ø øQç'üøXà,á[š•߈g[ø^ &–{¨ÜüÑÅIV#¿~¦´ü-§iZÆqx¶VW:´·GÊÓ./ÚØ$'‘°ŽXöçÿ×R©ô%E³ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ»éÚmϤÐ5? yFI[‰/\½¸nÛòà8$dF¤ðÕ¾‡®Ùëš”š ¤VQÄ!ŠçR‘"ÜYÃ3H~îFÑß§½K­Ðj õ8Ÿ9?çÂÃÿcÿ <äÿŸ üü+»Ñ´}?SKo ÙjÙ%¿Ùmlµ'’'fÎìK‘Ÿ|ô ŠÂñ}†Ÿ¦ø†+;Ä,m#–æØMæýšSœÇ»¾8ëýiƬ%.[ƒJ期óáaÿ€±ÿ…rÏ…‡þÇþÚK'‡áðWöáðœM7ö€²hL7oÎ}{b©ÅàÕ+ Œš¤ÛrØý¹l„-´§'g@ØŒvëMU‡U`ä}_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ ëbðm¥ÇØíâÖTêWºbê0Zµ³ÊA;wç¡çÛ ªúo…­¯mt–¹ÕRÖëXßö áö÷fw'Z~Ö¹$s^rÏ…‡þÇþyÉÿ>ø øW`|*·Ö~´¶Ž;{˶¾“³…ñÈöäqÖ¡²ðt:»i³é:¢\é÷²I¹’ˆ ,r¤ú9ü©*´ÇÉ#•ó“þ|,?ð?ð£ÎOùð°ÿÀXÿº»o i×ÒhæÏ\ómõc:ÛJÖ¥2Ñö ¶FNGåëXúž4«)î%a{~’HmLx0¢¶ÐXç¿8ãµ5R›Ñ ÆHÌó“þ|,?ð?ð£ÎOùð°ÿÀXÿ»ë-DƒÁúMýÅŽ’÷7O*ÈúŽªö€írÜpN>•‹¥xb×UÐηý©½”"F¾ÝM®T(ÝûÌôŠŸkNí5°ù$s~rÏ…‡þÇþyÉÿ>ø øWS¦øWO¾±Ñ'›Z6²ë-2ZÂöŒÄ²6ÜxëÓ=é"ðòÜø^â‚?íWñökJXáTFr=0g8Í7V˜rHåüäÿŸ üü(ó“þ|,?ð?ð®§þIäņ®·I¥vÆÜ¡†F`™ŸœgŽ¢ƒío5Û½/OÕþÖö+)½1Ú>b(ÁBªŸ¾ÇÐpy4{ZAÉ#”ó“þ|,?ð?ð£ÎOùð°ÿÀXÿº÷ð0‡UžÖçQû<1ém©‰¥·`B)«¦r¤wÆÍÐôí.ûÄ2º7Z5š™î|¦ŒXy0r Á'‘ßj½¥>‚å‘Ë£‰"iú~HÏ6©úT¾Sÿφ™ÿ€ÉÿÄÓìâÿJÿ€æ+CÊö«iÉ4K¹´ý8ŒàâÙ8ÿÇiQZDWh 23l™ÿÐjõä_è­Çuþbª\ÀòZYB³K˜Ê¥â8ll'ÓÚ¥Ù-‚ÂyOÿ>gþ'ÿQ+˜Ä4ý?xë›dÇò÷"iÒY^Ú‘}y0‘ÙJÌàºO§µXŽ/ø™ËÇðÿE¡4ú ¢)ÿçÃLÿÀdÿâi’‰w6Ÿ§œ['øíWÔo.4ëÉ"ŠA*ÈàŸ³d“÷}«JKsšªei±·÷Œr[‘Í%$ݬ 2œ~2×¼1•ÑoÆ;ƒºH£‚2„Ž T€py#ÀÏAEbëëµàÍý(¬çólRnÇEj„éö¤Ÿ">¿îŠx·™ŠŒ·¿gÄz{Ã¥øßJ¸û Ú¥œ­q6Ï7qHãaò±ã©é޵¡ÿ £ÇôÿÉX?øº‡‰‚z­Šör±—å¶©[…•O2À+èF?¯õ¦ù^µ¿áTxïþƒ?ù+ÿGü*ÿÐgÿ%`ÿâéGN:$Áӓ܇QÖïõ"ÛIk*;[oõ2¤N&CXƒ¸Œ¶9㹫ƒÆôsGp‘iRÞÇ–·Ó[pÆà@ÄéÐÔÿðª¥ï.åУр€Y­Ø¼-´ù›ÂíÆsŒcÛñ«²x“Zû0Š!b³ o²-ñ€ý¥aþèlã¹ç÷¥ÿ…Qã¿ú ÿä¬ü]ðªËca`ÎÑÚéÖß&\Ä«7ÍqÔc¶)Ÿðª`Ý’é‚)ßðªãÄ:×ÛÅÓ‰mMšØ¬èÞIê¥IÉÏsœûÔ_Úú‹Åy“aomwqɬ%mÊFI9ÏrOéV?áTxïþƒ?ù+ÿGü*ÿÐgÿ%`ÿâèU©-rO¹›n)÷>ví# gÓü*ô}æwšk`ò9Ë1É­øU;ÿ ÏþJÁÿÅÑÿ £ÇôÿÉX?øº§‰¦÷@©Éæ;XlVÖÕJ¢à*àà ç½;e¤ÖÑG>ü¦:n1E^ÿ…Qã¿ú ÿä¬ü]ðª±}ªÝiö‘Þ4PDžD—–Š,ŒÇÉÚÙlDoñ–kȆ“:u”—×¹½PBC4ÐÎ"]»¤!¡Ê’0a¸Æp°ŸIÓn¬%°¸Óí&³•ËÉo$*Ñ»ÞIR0Io›>¼õ¬=JÑõ­;Jñ ip'Útû ´dGŽÓËñù(Ã/žÃpÇ`hK_Mqª[ÆÖ¦Ÿw{q§ÛN. ”Í›¿|{Týĸ!ØŸ“*2vÓÓ5íFßA´Ïöž§sªÞiöïrë¿•-Æ ¿»€ò¨rØàd‘ÒG¤é°ê“j‘iö‰¨L›%»XTJëÇ øÉ*ðOaéUãðÖƒ—6—‰¦¦Ÿ3ï–ÑmPDíÇ,˜Á?*òGaé@ž±ñ/û+L’èØØÇ$NÒÇ}¨ýœM$2IÇlÞ[yÌ&à„8x‰¾b[ˬYi& ·óê’Á¼–·HÖfIåù|ʼnYTãr¹*X)5sRð½¶¡n¶iwwg§›qi5©E‚h0G–T©Ø6–\ÆQ°G?*í‘|>ŸÛßͨ_\G¯=½¤Î­²²³)Ûæ@œ¨€ ´bŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ¼fãþJ—ë÷JÿÒw¯f¯$ø¹âô*6¡¤ ¤àôwã=¨Ðm´ØŸD’ ×?k\¿NøqÔg¾k+ÃfTÕ㶸ÿ‹vh߯8S†çœÎ{Õé´ßÉ3¿öݪd“µa_a‘ŸÎ¢Óô«»/Û]_jvÓK0d‰µ¤Â“œØw=¸ô¤#˾:ÿÈWGÿ®èBŠ>:ÿÈWGÿ®èBŠï¥ð#üDzÿú¿…¿õãsÿ¢#¯ «çÝý_Âßúñ¹ÿÑ×ÐUÇ/‰›-‚Š(©Wà½wQ‡À¾‰<'¬Î‰¦[*˶a\—槯 P+¼®ÀŸòO<5ÿ`«_ý´–ÚÆ«ªk:ŒrOwá˜4»(nñt¶Ò,»Úl´Ä3(G ñ·/’>R OÇsi–Wz“iQ¾ž{³ ¢%’kd™œ:lÂ!û< 0f?s*2võšN›¨\ZÜ^éö—3Ú>ûi&…]¡lƒ”$eNTAéQ¾…£Éyuy&•b÷Wq.fkt/4dQÛeÀŽrmñ–â/ì˜þÛ-êØªµê¤[ØÜÇì£:ÒEÆ2Q‘€.|¡aüw7Ùo."Ò£dÒ­ä¸ÕÝ1ªK4L ùšw[LFï/#gMÄ/A©x{MÕ®­®.í£w…É`QH™|©bÙ&AÜ›gãÔûd—BÑæû›¥XÉýŸ±n·Cölc_&6¯L}Ñé@ö¾#ž_O¤ÝX}޹mæ˜Êv8_ÝùG*€YY¶¯*`¸÷^!×Oƒ Ô,á€j[[)’kQT_ù ªâTà %mÙ,¿7Qk¡hö:Œúž•co}>ï:ætI$Üw6æ'$sÔÑk¡hö:túuž•coc>ï:ÚtHäÜ6¶å sÔP7ªøò]>ö;;}"MFx­Ö{Õ°ó®î†8Œp°g «‰ C r>m½F­<Öº5õż¶Ï¼—ŒV`¤ƒ!„’}3QË¡hó}‡ÍÒ¬dþÏÇØ·[¡û61/“W¦>èô­ áì|C©XÏý—*ß]j·Æ–öºÁ·…Ð2LûÚ[`Éå•·(\2œü¬¥nnÝÞÝxfâdµIõ;­>öÔltvŠ+Øb»°$·Ê‘· üËÎÄ~ÐaÒæÒâÑ4ÔÓæ}òÚ-ª¸å“'å^Hì=*It-o°ùºUŒŸÙøûët?fÆ1åñòcjôÇÝ”—wâ&Ó5OµôR}JÓ!¾Q ŠåÐùåˆRªUó.À€¤m;³Ž|a­C¬ë–òiqÏ6ŸodÒÖsuFbÇŸ2«eX!•H ‚È*8 †ÖÞ+{x£†$qÆ¡U à8ÅI@Q@Q@Q@Q@Q@Q@Q@Q@Q@yòXüYÿa-ÿD5zýyòXüYÿa-ÿD5z„Ÿëêk&ëþF½ þÞ?ô Ö“ýcýMdÝÈסÛÇþ@Mñ×þBº?ýp“ÿBQñ×þBº?ýp“ÿBWu/Oâ#×ÿÕü-ÿ¯Ÿý}_>ëÿêþÿ×ÏþˆŽ¾‚®9|LÙlQEH¸?뺌>ðôIá=ftM2ÙVXå³ àD¿0Ý88=yú]åsþÿ’yá¯ûZÿ襠~][Ä:ÇŒ¦°ŽÛÄzM¬V–ÌRìÖòÌ’LY ´„®`&OÈß/#:‰ã µ°ÔµkDÒ4÷½I&ŽåVû;È ÎÆãïnq·oï+¨B·p±F'tTy̪IPORf vÜ}h†m¤Gg*Šf,ÇŽå‰$÷$šáÏÄ;¸¬‰ŸÃ·ix÷ º.ü© $Žyka)*°¾vÄÀnNpX¯Y¢jO«èð^Ëg=œ’n ñ²2•b¤€ê­´ã*YT• ÀŽ? h0ésiqhšjió>ùmÕNÜrÉŒò¯$v•¡ÚÛÅoopÁŽ8Ô*¢€ ãÄ·š-ý楪ÝݾŸÝ„H#·–ÖU…$."¬&YÂDw>MÉ*Œe±®xƒWÃ^&ŠDKÖ4Í3ûB9,æ)´‰ s$KÉh0)ÐŒ6OËÔG¤é°ê“j‘iö‰¨L›%»XTJëÇ øÉ*ðOaéUãðÖƒ—6—‰¦¦Ÿ3ï–ÑmPDíÇ,˜Á?*òGaé@êÚÅžµ [FŸè÷·rC+‰@ ˆ%‘AR‡r‡8e …ê ÏÝøÊõõí"ÚÖËýçP¼9ã3] h§Y£íÙûÔM¬‚1¼¦Bž¢] G›ì>n•c'ö~>źÝÙ±Œy||˜Ú½1÷G¥hZ=Ä÷Ï¥XË5Î<ùÝ¥Â4cq#æù—Ÿáb:@ü5¯Ë®[Ïö«hí.áqºÜyÁ‚ò¹C€HpÒÓ‚H nU=7IÓtkv·ÒôûKË´v°¬J[d…g û ¹@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@yòXüYÿa-ÿD5zýyòXüYÿa-ÿD5z„Ÿëêk&ëþF½ þÞ?ô Ö“ýcýMdÝÈסÛÇþ@Mñ×þBº?ýp“ÿBQñ×þBº?ýp“ÿBWu/Oâ#×ÿÕü-ÿ¯Ÿý}_>ëÿêþÿ×ÏþˆŽ¾‚®9|LÙlQEHÎ?ÅH÷&Òí¼½Vâ§ÞLm4Ûöµy]eµU9FÑ#ýæîqÍcéþo‡ÕíB:¬—-ª‡e`ÜôÇ5Új¾Óõ›‹{‹¿µ¬öèé–·³[0W*X© ”Cƒž‚°ü£ZÿÂ=¡kòË}s©ÜiQy“ÝßÏ?úÄß îUrʧ€: Ï—Vñ±ã)¬#¶ñ“k¥³ƒû5¼³$“–Bí!+„ “ò7ËÈ΢xÂíl5-ZãC‘4=ïRI£¹G•¾ÎòÂ3±„xûÛƒœmÛûÊê­ÃÜ,Q‰Ý@£s*’TÔ€Yˆ·ZÏûd6:õ¦¤q¥Õ½Õát€É$[¾P9,Ó–'=Aëž9sñî+"gðíÚ^=ÂAn‚ ¿*BÉ#žZØJJ¬/±0“œ+Öhš“êú<²ÙÏg$›ƒAèô¡ô-KË«É4«º»ˆÁs3[¡y£ ŽØË.W"hbp ÚAÚpI ʧ¦é:nnÖú^Ÿic9vŽÖ‰K`   àŸaW(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¯ ƒþK‹?ì%£ÿ膯_¯™Š|Tñ£)!…î’A~Îôé“êš|w#ßZ««ÊÓ( ç¡æ³žîÚëÅz'Ùî"›oŸ»ËpØù;â±~Çkÿ>Ðÿß´th#Ö­Ù XnÁTýÓJâ¹æ¿ä+£ÿ× ?ô!Eä+£ÿ× ?ô!EwÒøŒþ"=ý_Âßúñ¹ÿÑ×ÐUóî¿þ¯áoýxÜÿèˆëè*ã—ÄÍ–ÁETŒ+Ÿð'ü“Ï Ø*×ÿE-tÏøþI熿ìkÿ¢–€: òÿ ijO‡ï.´ÝÝO§Û—ÕS]uAæÇH@7AÂîœ^¡\ÜÑmmâ··—Y†$qÇ­Þª¢€à8Åaè^(Öÿá^i“ÿb_}£û*'þÓÔ.m¾Í»ÊΕ¼ÿ3ËÏÌÇnìgŒñQ]±Ôtý=[R¹¼–õìµ5µILootUŒ°f1øAày‹å¿ V»Ë }3N¶°³Ëµµ‰!…7µ£'“€Z¯c¡húdQÅa¥XÚG¦tH-Ò0²(\8b¤®zàã¥rwåŽe‚ßA»ºžf½ŽÝ&˜©Y¥„¬F8˜9-¸ó @¼Œ¶Î‚Êæïþ]bÊK©%´K+;ˆae@!giÑ ùJ~byÎ08¨ô{]Äz‰­M¢X¬’Dš…º¼)!¶’\JÅX¯ Xä°Á$g­jG¤é°ê“j‘iö‰¨L›%»XTJëÇ øÉ*ðOaé@þ¹»ºÐ™¯n¤»ž+ÛË>EEgX®eIsµ@*=fûTµñ/‡¡‚H#Ón®ÞÆÝÒJ~Ï<€sÂ*˜Ôñ’ÄÿS¿SMÒtÝÝ­ô½>ÒÆrí¬+–À!@À>«ê^Ðu›…¸Õ4M6úu@‹%ÕªJÁrN`N2Iǹ  Jâî|Q©Ù|9ºñ2ZIyxöòÜý•Da,c$Ç&æV"6M¯ÉrÛ°ª0«ÚTqÁ /3Åhó>ùYTí´.[ÔíU=€¨šjðGgk>¤¿ÙR]J Ž Ù¢ÒB *ì¬ÍŒ€¤ŸÇ"£ñ,÷v¾Õî,%ŽȬ¦x$‘‘U$J’_å·¼Uɬmî/-®¥|ÖÛŒ$±Â,¦ìdÆ@f€Í›æí«x‚Îs¤Ï}ª¾¡q,‘³’à@épÊ#>RB³fÝ‹‡.ìvb+bÓ[ÔF‹¤ß=ÇŸ;ê §ËhÈ¡æyˆ“´q4JŒîS1’àmÚ鹆´t¹´¸´M54ùŸ|¶‹j‚'n9dÆ ùW’;J¹ …¿Ùü‹H"û4F6FÊŒíÊ.>êü‹Àãå‚€,QEQEQEQEQEQEQEQEQEWŒÜÉRñ¯ý~é_úNõìÕã7òT¼kÿ_ºWþ“½tõ¡¢È^øþ‚k>´4Où ÁÿÿÐMI'˜|uÿ®ÿ\$ÿÐ…|uÿ®ÿ\$ÿÐ…èRø”þ"=ý_Âßúñ¹ÿÑ×ÐUóî¿þ¯áoýxÜÿèˆëè*ã—ÄÍ–ÁETŒ+Ÿð'ü“Ï Ø*×ÿE-tÏøþI熿ìkÿ¢–€: (¢€ ãüTqâm.ÛËÕn!}äÆÓM¿kW•Ö[US‘$`í?Þnç×aYz¯‡ôýfâÞâïík=º:E%­ìÖÌÊ–ÄêH%àç  ;ðõÆŸÿ½ÅŽ…®ïtI™ôõÔ„±¿d),K5ÉTŒyŒª2Êâ¶%Õ¼C¬xÊkí¼G¤ÚÅilÅ þÍo,É$Á¥»HJádüòò3¡à-×þí _–[ëNãJ‹ÌžîþyÿÖ$nøWr«–U<ÐS“â‚P‹v³eo{u¾óÐÃ"y%²“oÇ‚_M¹$íÎj£Kep!Õ>!A£ê×PÜØÉ6ŸM²êÔJûž^Y–bÈò¤\,¬w(›lšŸŒoôX„ú<S–Xã‚ ;©.Qƒ¬¬ l„̼A'H˜—oã?†7:Åž¯öˆ5;Íþ]ìæ]‹´ùŽÊ?—¼®áÀÍGgâÏ…ripiv÷: Z~¤îÿdkeŠ&dÆL¨Ê•p\ ØÏ^ʧò¿¸WGe¢jO«èð^Ëg=œ’n ñ²2•b¤€ê­´ã*YT• ÀÏÓ/µIúu½ž½§ÁÈÉm +Æ1†À†۟áÍgØø³áYÕ-5KKBõåt»6Ë¡†w™¨1–ÉåÊîÏÍʧò¿¸.Ž»Ä:”ÚN‰5ä uxÐÉ(%!VuV•À#äX»r8Có/Q—­ëÚ–ƒ}¡iöúUöª·Rù2܃nR!•ð3$`I˜Ã”&ÝÀsPÛüPðEÏØü¿Ù¶oòüÂcÛ³¯™¸/Û~ÝݳQØ|Ið·Ó­ìõí>&FKhðaX–1Œ0 †6ÜÿhöU?•ýÁtu_o³þÑþÎû\nò¼ÿ³yƒÌòó·~Þ»sÆzf±üo}ªi¾ Õo´‰ †êÚÒi¼é—w–6lªôfÈd€3¸îÆÖɱø‡à¼Žî ~Én5L2ge D ûÿÔ¨ùŠ«m³±&;¯|6ñ½¾¡©é\»¼1ßD £ —."8$ûwgŒæeSù_ÜGE®ß\iÒéÓÛɿͻŽÕ¬ö‚g0”ýàѨi8ÈØ²dttØ®Kñ×ÃhLM;SÒ-D™-UbWpieG’”6Ýä3Å\·ø¡à‹Ÿ±ù~#²lßåù„Ç·g_3p_¶ý»»feSù_ÜG]EQÑõ‹ I·Õ4»•¹²¸¢•A€$rÁô«Õ˜ÂŠ( Š( Š( Š( Š( Š( Š( ¼fãþJ—ë÷JÿÒw¯f¯¸ÿ’¥ã_úýÒ¿ôè§­ þBðÀ¿ôYõ¡¢È^øþ‚jI<Ãã¯ü…túá'þ„(£ã¯ü…túá'þ„(¯B—ÀŒ§ñëÿêþÿ×ÏþˆŽ¾‚¯Ÿuÿõ ëÆçÿDG_AW¾&l¶ (¢¤a\ÿ?äžxkþÁV¿ú)k ®ÀŸòO<5ÿ`«_ý´ÐQEWâ¤{ivÞ^«qÓï&6šmûZ¼®²Úªœ‰#h‘þów8æ» ËÕ|?§ë7÷kYíÑÒ)-of¶`®T°&'RA(‡=qz›áÏé0ižñ[¾ŸwödÚšOµc{PŽ«%ËFª¡ÙF7=1Íx¬–ú=¶{©ÞZ[Kxúµôj¾ kϵʱ¬Lª|† %̸¹3uÀ8ú ÀZ5¯ü#Ú¿,·×:Æ•™=Ýüóÿ¬HÝð®åW,ªx ¯»øEã[Ç´YjNPy =ݽÀ>7M½¥Bò«Qw`àô2ú„Ûœ¹QMìsÚg€gÕô«imïR+ù^Ö·&%Ú’Ê‘Fà,.›e¢Q´’ ùwG¦øFÇX”Ïc«N4Øâ‘æžîÖ;wR­»å73GÖPzä}Àûò|?ñüoká‚u°NóH,ÍÜ>_Ù£’<È#óöoÝ(% 8Ã’º|7ø.§§$ÚóßÃqäÅt×pRן˜?Úræo݃·“óó^·×¡¯ïÝÿúó#•ö<ËZÓ“IÕ§²Šò ¸ãÚVh]]X2†•,»†pÀ3À€H:×–ú]¿†Unl ´Ô(ÞØ,²½Ô„•&IAýÒÄ˼ª€$ÿT~e%Û¨Ÿàߌ.®$¸¸±Ôeš[Òd’G¶fxIÉ”“q“)?ÁÓýº¿7È÷`Ó'›^–À\,"Õîàh…ªãkl78Þ016Œž­ã¨>_×ò+ìy·‡ôèu]fIÙÂ2Há# <̨̱! üîT"ðyaÃt/µÓìu?:æ]cKÒwJÛmeK–Ú½FÒ±Éòó–ÝÇ>§³ÿ…)â¿ú^ÿÇÞζ¿ñïÿ=?ããýgý3éþÝI?Á¿]\Iqqc¨Ë4·¤É$lÌð““)&ã&Rƒ§ûuO‡oøŸ×ܯ±ç?a»þÏþÐû,ÿbó|Ÿ´ygËó1»fî›±Î:âµüe¦j>/Òìµhç–Úâê(|˜›o˜^E\3uUÁ$àq·;—³—áŒç´·µ}>÷ìö÷l±Æ>ÈŽZc‹Žf8iÏ £Ì€$Ó¾øóH¸k2=^Êf¸òZKiíãckw· ïÈ»û¼ž”±ôZçWù‡+ìp%•¾¡¡ñìò­dº[½ÄLjHVt¬ŒV>pw²`õWɯU»øSãÍAæ{Øõ{—žõ Í4öîd…ªÊÙ¹æP 7Õ?øRž+ÿ eïü}ìëkÿÿóÓþ>?ÖÓ>ŸíÕG‡½Üÿ0äg¼|1¸û_€ín~Ýöÿ:êòO¶y^WÚ3u)ó6î»{g××1ðúËYÓügˆcÙ«´·] ÈròO#çäùyÝž=k§¯•ŸÄÍÐQE QEQEQEQEQEQEã7òT¼kÿ_ºWþ“½{5xÍÇü•/ÿ×î•ÿ¤ï@=hhŸòƒþÿ šÏ­ þBðÀ¿ôRIæä+£ÿ× ?ô!Eä+£ÿ× ?ô!Ez¾e?ˆ_ÿWð·þ¼nôDuô|û¯ÿ«ø[ÿ^7?ú":ú ¸åñ3e°QE# çü ÿ$óÃ_ö µÿÑK]sþÿ’yá¯ûZÿ襠‚Š( Š( ÀŸòO<5ÿ`«_ýµÐW?àOù'žÿ°U¯þŠZè(Çô ayyá$¹Ó;qj¶ò|êb ·aÝÃoç=苺ñ¼·0x²óJ“ηÓ4¨î#ÌDem÷;¤VÙ ù£Ž9p*ÊPà&º ÝQ‹Ä3é:~‹öϳZCw,¦écʻʻÌŸºÊ‚BœÎ˜µ/47QIÒûO´ºIÑežq"£@Ù…bH¡$Š’ÚÂÎÏoÙm ƒlIò£ ˆÓ;á]ÍÐdã­szgŒåÔüJútz=ߨÅÄöËx!˜€ñV.LB …£` ÊÇ%PKÔñ%İiѬÓÚÍ,¢4±$—6 Ä$Ê$d³¡“´ ër='M‡T›T‹O´MBdÙ-Ú¢W^8gÆHùW‚{J5-'MÖmÖßTÓí/ W±ÝB²¨lœ3îh=ûGûí_øûù³»öî;7íù|Í›wíùwnÛòâ©Á©]Í­ëVBšj*Ec@÷[‘\K—#‚Û¢^Bå$ËjXØYé–qÙØZAikvCb4\’Np2I?H`…®ᢌΈȒ•X‚À ªHï´zP}ž±$¶÷WŽ—w£Án›ÚKù`ÚW±Ìr8@É-޽ùÆ„Ãuoż±Í¨9#`ÊêFApA棾±·Ô¬ä´»Í·“HËÖÇU8ÁSÃA*Åqú7‰¥ÔÃvÖ©xtT–Àùw+3FÛxßp¿qnG¤é°ê“j‘iö‰¨L›%»XTJëÇ øÉ*ðOaéV ‚­íâŽ"@‘Ç…TP0€ã%Q@Q@Q@Q@Q@Q@Q@xÍÇü•/ÿ×î•ÿ¤ï^Í^3qÿ%KÆ¿õû¥é;ÐOZ'ü…àÿè&³ëCDÿ¼ð/ýÔ’y‡Ç_ù èÿõÂOýQGÇ_ù èÿõÂOýQ^…/Oâ#×ÿÕü-ÿ¯Ÿý}_>ëÿêþÿ×ÏþˆŽ¾‚®9|LÙlQEH¹ÿÉ<ð×ý‚­ôR×A\ÿ?äžxkþÁV¿ú)h ¢Š(®?ÅH÷&Òí¼½Vâ§ÞLm4Ûöµy]eµU9FÑ#ýæîqÍv—ªøOÖn-î.þÖ³Û£¤RZÞÍlÁ\©`LN¤‚Qz ó¿ß\iÿð‹ÜXèZáŽ÷D™ŸO]HK öB’ij\•Hǘʣ!À<®+b][Ä:ÇŒ¦°ŽÛÄzM¬V–ÌRìÖòÌ’LY ´„®`&OÈß/#:Ñ­áеùe¾¹Ôî4¨¼ÉîïçŸýbFï…w*¹eSÀu‚Váî(ÄîŠ Q¹•I* ê@,ÄÛ­qú§Ä(4}Zê›&ÓâI¶]Z‰_sà Ë"ѬYT‹…•Žåóm“Sñþ‹‚ÿG€êrËpAgu%Ê0u•m™—ˆ$éòàýòöý±ý¯ý•cý§ÿ?¿gO;îíûøÝ÷xëÓŠŽ? h0ésiqhšjió>ùmÕNÜrÉŒò¯$v”&‰©>¯£Á{-œörI¸4ÆÈÊUŠ’ª¶ÓŒ©eRT‚@'Ÿk‹ø|i¦¬zåôúUÔ·w­«ÀÓ(“ýv •Yv;cåm%™¸ë ‚­íâŽ"@‘Ç…TP0€ã^='M‡T›T‹O´MBdÙ-Ú¢W^8gÆHùW‚{J¯âJm'DšòŒº¼hd”«:«JàòF¬]¹!ù—¨ËÖõíKA¾Ð´û}*ûU[©|™nA· )Êø’0$ÌaÊnà9À®¢£‚mmâ··Š8`‰GjQ@ÀŒPo³þÑþÎû\nò¼ÿ³yƒÌòó·~Þ»sÆzf±üo}ªi¾ Õo´‰ †êÚÒi¼é—w–6lªôfÈd€3¸îÆÖ؆ÆÞ Ë›¸ãÿH¹Ú%±bBŒ*ŒôQ’BŒ ³e‰1êZN›¬Û­¾©§Ú_@®cº…ePØ# 0#8$gÜÐ=vúãN—NžÞMþmÜv­g´8‘€,§ïCIÆFÅ“#£¦ÅS³ÒtÝ9 K>ÒÕ GHVUjìÂàp€$¤jåQEQEQEQEQEQEQEQEã7òT¼kÿ_ºWþ“½{5xÍÇü•/ÿ×î•ÿ¤ï@=hhŸòƒþÿ šÏ­ þBðÀ¿ôRIæä+£ÿ× ?ô!Eä+£ÿ× ?ô!Ez¾e?ˆ_ÿWð·þ¼nôDuô|û¯ÿ«ø[ÿ^7?ú":ú ¸åñ3e°QE# çü ÿ$óÃ_ö µÿÑK]sþÿ’yá¯ûZÿ襠‚Š( ¸ÿ#Üx›K¶òõ[ˆFŸy1´ÓoÚÕåu–ÕTäI;D÷›¹Ç5ØV^«áý?Y¸·¸»ûZÏnŽ‘Ik{5³r¥1:’ D89è(Îü#}q§ÿÂ/qc¡k†;Ýf}=u!,d/Ù KÍrU#c*Œ‡ò¸­‰uoë2šÂ;oé6±Z[1H?³[Ë2I0id.Ò¸A€™?#|¼Œèx Fµÿ„{B×å–úçS¸Ò¢ó'»¿žõ‰¾ܪå•OtÖ![‡¸X£º*´Ç꟠Ñõk¨nld›O‰&Ùuj%}Ï /,ˆKF±dyR.V;”ͶMOÆ7ú,B ý©Ë,qÁÔ—(ÁÖV¶Bf^ “¤L˃÷ÊtØZ?öÇö¿öUöŸüþý<ï»·ïãwÝã¯N*8ü5 Ã¥Í¥Å¢i©§Ìûå´[T;qË&0Oʼ‘ØzPš&¤ú¾ì¶sÙÉ&àÐO#)V*HªÛN2¥•IR œnÓÅw·¢Ò^ »kov‰ º|ªd’)"S)]›/·i#K6çT^Â!µ·ŠÞÞ(á‚$ q¨UE81A‚¸K†Š3:#"HTnUb z€J©#¾Ñé@þ!Ô¦ÒtI¯ X˫ƆIA) ³ª´®$jÅۑ™zˆîµý/ȶ‹FÕu}±.ë¸^Õw7C¸<‘üÜdíP¼ñè6*8 †ÖÞ+{x£†$qÆ¡U à8ÅGöû?íìïµÁöï+Ïû7˜<Ï/;wíë·ÒÕ GHVUjìÂàp€$¤jåQEQEQEQEQEQEQEQEã7òT¼kÿ_ºWþ“½{5xÍÇü•/ÿ×î•ÿ¤ï@=hhŸòƒþÿ šÏ­ þBðÀ¿ôRIæä+£ÿ× ?ô!Eä+£ÿ× ?ô!Ez¾e?ˆ_ÿWð·þ¼nôDuô|û¯ÿ«ø[ÿ^7?ú":ú ¸åñ3e°QE# çü ÿ$óÃ_ö µÿÑK]sþÿ’yá¯ûZÿ襠‚Š( ¸ÿ#Üx›K¶òõ[ˆFŸy1´ÓoÚÕåu–ÕTäI;D÷›¹Ç5ØV^«áý?Y¸·¸»ûZÏnŽ‘Ik{5³r¥1:’ D89è(Îü#}q§ÿÂ/qc¡k†;Ýf}=u!,d/Ù KÍrU#c*Œ‡ò¸­‰uoë2šÂ;oé6±Z[1H?³[Ë2I0id.Ò¸A€™?#|¼Œèx Fµÿ„{B×å–úçS¸Ò¢ó'»¿žõ‰¾ܪå•OtÖ![‡¸X£º*´Ç꟠Ñõk¨nld›O‰&Ùuj%}Ï /,ˆKF±dyR.V;”ͶMOÆ7ú,B ý©Ë,qÁÔ—(ÁÖV¶Bf^ “¤L˃÷ÊtØZ?öÇö¿öUöŸüþý<ï»·ïãwÝã¯N*8ü5 Ã¥Í¥Å¢i©§Ìûå´[T;qË&0Oʼ‘ØzPš&¤ú¾ì¶sÙÉ&àÐO#)V*HªÛN2¥•IR œFñ4º‡ˆdûI¾†ÚK»:Ö?%³K ¾~b<ƬR>ሀ;9u$õA ­¼VöñG  HãBª(ÀqН“¦ÃªMªE§Ú&¡2l–íaQ+¯3ã$|«Á=‡¥Wñ¥6“¢MyÆ]^42J HUU¥pù#V.ÜŽüËÔGu¨ßé~E´Z6««í‰w]Âö«¹ºÁäæã'j…çA±QÁ6¶ñ[ÛÅ0D#Ž5 ¨ `Æ(?·Ùÿhÿg}®·y^Ù¼ÁæyyÛ¿o]¹ã=3Xþ7¾Õ4ßê·ÚDCumi4ÞtË»Ë 6Uz3d2@ÜwcklCcoåÍÜqÿ¤\íÈX±!FFz(É!FYŽ2Ęõ-'MÖmÖßTÓí/ W±ÝB²¨lœ3îhž»}q§K§Oo&ÿ6î;V³Ú œHÀS÷ƒF¡¤ã#bÉ‘ÑÓb©Ùé:nœ%ŽŸij#¤+*‚5v áp8 ÀR5r€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ñ›ù*^5ÿ¯Ý+ÿIÞ½š¼fãþJ—ë÷JÿÒw ž´4Où ÁÿÿÐMgÖ†‰ÿ!x?à_ú ©$óŽ¿òÑÿ넟ú¢Ž¿òÑÿ넟ú¢½ _2ŸÄG¯ÿ«ø[ÿ^7?ú":ú ¾}×ÿÕü-ÿ¯Ÿý}\rø™²Ø(¢Š‘…sþÿ’yá¯ûZÿ襮‚¹ÿÉ<ð×ý‚­ôRÐAEP\Š‘îžº–2ì…%‰f¹*‘1•FC€y\Vĺ·ˆuMa·ˆô›X­-˜¤Ù­å™$˜4²i \ ÀLŸ‘¾^Ft<£ZÿÂ=¡kòË}s©ÜiQy“ÝßÏ?úÄß îUrʧ€: ë­ÃÜ,Q‰Ý@£s*’TÔ€Yˆ·ZãõOˆPhúµÔ762M§Ä“lºµ¾ç†–D%£X²<© +ÊæÛ&§ãý!þÔå–8à‚ÎêK”`ë+Û!3/IÒ&åÁûå:ì-ûcû_û*ÇûOþ~ΞwÝÛ÷ñ»îñ×§~ÐaÒæÒâÑ4ÔÓæ}òÚ-ª¸å“'å^Hì=(MR}_G‚ö[9ìä“ph'‘”«$Um§Rʤ©€NHÕ‹·#„?2õzÞ½©h7ÚŸo¥_j«u/“-È6á¥"_2F™Œ1ùBmÜ8ÔTpA ­¼VöñG  HãBª(ÀqŠíöÚ?ÙßkƒíÞWŸöo0yž^vïÛ×nxÏLÖ?ïµM7Áº­ö‘$Ý[ZM72îòÂFÍ•^ŒÙ wØÚÛØÛÁyswé;D²,HQ…QžŠ2HQ–cŒ±&=KIÓu›u·Õ4ûKèìwP¬ªdgŒûš§®ß\iÒéÓÛɿͻŽÕ¬ö‚g0”ýàѨi8ÈØ²dttتvzN›§$ c§ÚZ¤é Á  ]ƒ8\0Ô€M\ Š( Š( Š( Š( Š( Š( Š( Š( ¼fãþJ—ë÷JÿÒw¯f¯¸ÿ’¥ã_úýÒ¿ôè§­ þBðÀ¿ôYõ¡¢È^øþ‚jI<Ãã¯ü…túá'þ„(£ã¯ü…túá'þ„(¯B—ÀŒ§ñëÿêþÿ×ÏþˆŽ¾‚¯Ÿuÿõ ëÆçÿDG_AW¾&l¶ (¢¤a\ÿ?äžxkþÁV¿ú)k ®ÀŸòO<5ÿ`«_ý´ÐQEWâ¤{ivÞ^«qÓï&6šmûZ¼®²Úªœ‰#h‘þów8æ» ËÕ|?§ë7÷kYíÑÒ)-of¶`®T°&'RA(‡=yß„o®4ÿøEî,t-pÇ{¢Lϧ®¤%Œ…û!IbY®J¤cÌeQàW±.­âcÆSXGmâ=&Ö+Kf)ökyfI& ,…ÚBW0'äo—‘hÖ¿ðhZü²ß\êwT^d÷wóÏþ±#w»•\²©à‚ºÁ+p÷ bwEG(Üʤ•õ bmÇÖ€8ýSâ>­u ÍŒ“iñ$Û.­D¯¹á…å‘ hÖ,*EÂÊÇr€@ù¶É©øÆÿEˆA£Àu9eŽ8 ³º’å:ÊÀ¶ÈLËÄt‰ùp~ùNƒû GþØþ×þʱþÓÿŸß³§÷výünû¼uéÅG†´t¹´¸´M54ùŸ|¶‹j‚'n9dÆ ùW’;J“DÔŸWÑབÎ{9$Ü ãde*ÅIÕ[iÆT²©*A ËéÚÞ­/Š ón'67:…Õ’îH¾ÈÂ!6ð¥¢>™æi–l^=AäþdqŒ|ƒ=÷«¤ûOÅÏOäÝqËâfËcѨ¯9ûOÅÏOäÝiø¹éàü›©èÕÏøþI熿ìkÿ¢–¹Ÿ´ü\ôðGþMÔp7Åk[x­íàð,0D#Ž4ºUE81@•EyÏÚ~.zx#ÿ&èûOÅÏOäÝz5qþ*G¸ñ6—måê·>òci¦ßµ«Êë-ª©È’0v‰ï7sŽk'í?=<ÿ“uoŠÍp— L茉!K­Ê¬A`P U$wÚ=(„o®4ÿøEî,t-pÇ{¢Lϧ®¤%Œ…û!IbY®J¤cÌeQàW±.­âcÆSXGmâ=&Ö+Kf)ökyfI& ,…ÚBW0'äo—‘š¥¾+5Â\43¢2$….·*±€=@%T‘ßhô 7Åe¸{…ƒÀ¢wEG%ÖæU$¨'©³;n>´­ª|BƒGÕ®¡¹±’m>$›eÕ¨•÷<0¼²!-Å‘åH¸YXîP6Ù5?ßè±/ôx§,±ÇwR\£YXÙ ™x‚N‘0?.ß)ÌÿeüDþØþ×þÈøuý§ÿ?¿f¸ó¾îß¿ßw޽8¨ãÑ<}—6—‡ðÝ4ùŸ|¶‹i8‰ÛŽY1‚~UäŽÃÒ€=+DÔŸWÑབÎ{9$Ü ãde*ÅIÕ[iÆT²©*A Í¥ÿ‰-¼ogkrd{K»‰ÑãÝ …`TvŽH•WÍÈÄK#HÁCË…V¥r`oŠÖ¶ñ[ÛÁàX`‰GitªŠpb£†/Š÷—7Ùø;«­¿h™"¹.Ñ…ÜÖÀàg¥w^!Ô¦ÒtI¯ X˫ƆIA) ³ª´®$jÅۑ™zŒ½o^Ô´í O·Ò¯µUº—É–äpÒ‘ ¯™#LÆü¡6îœ ÁûOÅÏOäÝG|Vµ·ŠÞÞÃH8ãK¥TP0€ãè_o³þÑþÎû\nò¼ÿ³yƒÌòó·~Þ»sÆzf±üo}ªi¾ Õo´‰ †êÚÒi¼é—w–6lªôfÈd€3¸îÆÖåC|V[‡¸X< 'tTy]neRJ‚z 1¶ãëUõ+/‰ZͺÛêšwÃëèìwP\Ê¡°F@lŒà‘Ÿs@Ö»}q§K§Oo&ÿ6î;V³Ú œHÀS÷ƒF¡¤ã#bÉ‘ÑÓb¼¶ÎËâVœ%ŽðúÕ GHV.PF®Áœ.:` ©š¹öŸ‹žžÿɺôj+Î~ÓñsÓÁù7GÚ~.zx#ÿ&èѨ¯9ûOÅÏOäÝiø¹éàü› F¢¼çí?=<ÿ“t}§âç§‚?òn€=ŠóŸ´ü\ôðGþMÑöŸ‹žžÿɺôj+Î~ÓñsÓÁù7GÚ~.zx#ÿ&èѨ¯9ûOÅÏOäÝiø¹éàü› F¢¼çí?=<ÿ“t}§âç§‚?òn€=ŠóŸ´ü\ôðGþMÑöŸ‹žžÿɺôjñ›ù*^5ÿ¯Ý+ÿIÞº´ü\ôðGþMÕoøC]oëZ׊eÓ Ú„Ö“yzcI³÷1ºcçÊž§¿N(¦³Õa´Òg7$…¶×hÉ œ`~$uõª^¾¯ÍÇü|\3HýxÊœ/<à1Ú¶äÒ´¹P¤–A”H27cŸZž [;i–X­¶ºô>a>Ô„x¯Ç_ù èÿõÂOýQGÇ_ù èÿõÂOýQ]ô¾c?ˆõÈ¡ÿ׌_ú­]rýt­2ææ8Þ06†cŒ’ÏçY^ ÿ‘Cÿ¯¿ôV®|?¦^\ÉqqnÒM!Ë3JüþµÇ/‰›-‰5™R&y$Ô'°Q·è¯ %€ ŠÊÁ™Ž.ÒIl’+Ê÷_Óü>_ø˜êW¾uÜI¨Og·ÊRŽðÄU¤Ý"œÀÜÃqÚ t×¶6š•£Ú_ZÁum&7õ$66–þG“kgˆÃÈÀò£;r‹Ž‹ò¯”z Åñ.£¬ØêZL6²‹«ÇŠe¸œÄ%p¹¹)»#œ¨†$Fþ,ÝvòZÛAq¤Åuog%Ú\üí$â#FJ¼¿‹-¼½€p7o^ØÚjVi}kÕ´˜ß ñ‡FÁÈÊž £“JÓ¥ÔâÔä°µ{øWdwM ™Qyà>2ÌÜÜúÐj7Z^ˆ·Vjï0¼´ËŒ)iî#FA¼…Ë+’F3Ôuª>#½-¾Í!ºµÕ­l/Ê¢V„ƒ48ÄÑ‚ ¡åðA OK4Ü IâIP2¸WPÀ2ÊyîÄU/t='R‰â¾Ò쮣’Q3¬öèᤠ°9rÛ@\õÀÅ`êþ4þË×ãÓ~Ïeó][Ûl¹¾òn%óY̆-‡ÌwòÛ‡) þ–x[Ä–±¤i6Ú”Oku¨é"êÈäF‘Ьk$Œ›v!-*²˜÷‚‘¶¶¯4½Ôy¯ïM·›íc½L/$eY•.¸dCµYT•Ésn¶t­9­Òݬ-L)Z¤fÚ°°£B®W¡Ú=(·×5ø@ü5ªH|éï?³…Ô¡Ö6ýóF¬Àle9g®‚pTF¯ãOì½~=7ìö_5Õ½¶Ë›ï&â_5‘|ÈbØ|È×-¸r’áÉړúºdZdš6œö¶øíZÕ HÜòæn@î}i—š ^ê <×÷¦ÛÍŽv±Þ¦’2¬Ê—\2!Ú¬ªJ䃹·qÃÆZïü+áu%ªE©Íá÷Ôm®^e˘Ò?6G@…TæEtQ¸0á¼¾•µªøÂëKû%™Ó ¹Õ¥óLÖö²Ï:ÿÈWGÿ®èBŠî¥ð# üG¨x+þD}þ¼bÿÐEnÖ‚¿äGÐÿëÆ/ýVíqËâfË`¢Š*FQEQEQEQE7˜É {N3ŸçPÔþ¦/ÇùÐçÉýïÐQçÉýïÐTuÂj)âñ5Õìâ·Õ,ííî|ù‰lâ9RGŒï³ê žaLwþ|ŸÞý|ŸÞýp7Þ+µÑ,ç¾kÛË›Íî'T´X¥Âù!B€ŒCbI•„„˜ÎÄÿ–fƒ_jZ„Ò]kN½¸žÏ^´kWþÏšIŒi$2<¸FÜ)™wÐ`mù‰ËzwŸ'÷¿AGŸ'÷¿A\^¯¬ëV7—1A²[s«XÆ.VHöÛC#Û£ÂW–2ìÜŒùk"WÄk«Ía{¯\ÊŠ«mo©i~A‰K8ql ¾ÂÅ#ÎJ9>Z€z_Ÿ'÷¿AGŸ'÷¿A\ï„gÕ®4O7W}ò4­ä³«¬¦>ïCÍ»~1»zòN.¿ªkvºà{{›¯±Ç¨Ù[¢}• D’HUÖpù˜H|ÆÆÎ6´g®ã@çŸ'÷¿AGŸ'÷¿A^i¥êž7šÖú[ÄxÝ1s…ÙíØÈ¢Cn º+„Î Ÿ%cÁlüöëÅ·W–°ØÜj-bZP·7qÃ,±µRò+Æ¡—EÕÝå)*ã;€=Ï“ûß £Ï“ûß ¯8Óõ_kš_Úm¾ÇÑ[Hð42,%$i·~áöÈʪhùTÊž®XG¯èúUögqªM¨P?›seÁrßd°Ø©æoŠFwÚHL0ÌG€=Ï“ûß £Ï“ûß ®ZW×4­BÎîÿ¶âœe0Á3ŲIЗ Ñ®@‘Ç#&ÿ…¯n5/h·×ry—76M+à ÎÑ©'É=(kÏ“ûß ¬ÜÍy¢Aqq#I4…Ë3wùÚ´ë¿ò-ÚÀÿô6  Š(¢€ (¢€ (¢€ (¢€ (¢€ (¢€Üó7÷>µÔoþyãÆñÿÏ/üxÐü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVæøÿç—þ‡ÿ^1è"·kŽ_6[QR0¢Š(¢Š(¢Š(¢Š(©ýL_ó¨êGÿSãüè:䯵-FßÄÌÏyœ×n#b9¶[2A„¹oµFPNp’p+Úxúæþú×L·ÑÑu)ÚxÌw7/o¼K ˜dK!9³þ¯9Sò•ËŽ·û+NÙpŸ`µÙr¥'_%q*’ÌCqódrAîì{šÌÿ„3ÃÂXöiQÛ,RÆÖim‚O1¢bÌ›pX#Áöú`OJÔaÕô‹-NÝ]a¼‚;ˆÖ@u Á#8>µË?Žî"²²»}ÌRŠ+>8.’Hžh#ùÃ*ªIþ‘ ”À°À'´ªhzLÜK—e—2¬Ó²[ 2È­½]ˆ3ù<ƒÍfê¶«i¥[Ís`–ÓFÚÚa Øuòä•tlcË ¸RPýü…c^ãÆGâ—Ò Ò.®!†x­§ž8¦b®êŒÛ`!bÒ)1Úp»·µ+NÕíÖßS°µ½…[zÇs È¡°F@`FpO>æ‰4­:]N-NK W¿…vGtЩ•žã |ÍÀ=Ï­qw¾7ÕgðmÆ¡––W:$º‰{‘!UEMìãa5Yͼ›Ë< ­KÄ×ZvŸ6¶SêÞiI¬mî'ŸË'÷P3ð"sæ/<®íèlm-ü&Öþφ‘åFvåå^(ôNOèré‘i’hÚsØBÛãµkT1#sÈL`™¹¹õ  -'ź—ˆ¼Ð–±h7uÔ-qq²T3™Bü».Ì6ïÀÀ ’ÄU±â‹hµÇžß|¶º¤V0EçŒeX_6ÀUI™Kd9\¶ m.•§+ÙºØZ‡±R–Œ!\Û©H”ÀÇz“Û|­.É>ߟ¶m·AöŒç>g>w7\õ>´‚¾,ÔåÕ†‰š¢ùÂaöìAmÜæ=ÅJ\¯!2crã¢Òµu}"ËS·WXo Žâ5Á]CpHέšV§¤)eakl+¤K *‚5r‚àp : OÚÛÇooE J8ãPªŠp¨JÇð¯ü‹vŸð?ý «b±ü+ÿ"ݧüÿCjØ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ľ:ÿÈWGÿ®èBŠ>:ÿÈWGÿ®èBŠî¥ð# üG¨x+þD}þ¼bÿÐEnÖ‚¿äGÐÿëÆ/ýVíqËâfË`¢Š*FQEQEQE>4NNÎ)vGÿ=ñÓD?òÓýÃQЛ#ÿž¿øéªWú6©´myº_,ƒs€3×€qþER×5û}´æº\AwtmÞbN!T’olò/’pÄ€ T³ñ…„úTZ…ÔWV°Ë=ÄA¬Ì±¬R´eåm˜„aw3nÞr~Rhïü"ZüðÿÇäÿ?áÐç‡þ?'øÖv¡ã×OÕ'¶›í3ØErL[]¥€9x|»DŸ#¼¶ßœ¼ÖÓj–H÷Š÷(‚ÉCÜ»p‚7|Î~PBüÄg ' ¿áÐç‡þ?'øÑÿ–ƒÿ™¨Ë¿.åbYÝnÛ"bÃÌb (w9¯ˆÈÈ¿áÐç‡þ?'øÑÿ–ƒÿÇâoùù»ÿÀkoþ9@ŸÃÖ’x{PÑL“ýšûí^kÇžîï´ã2læ£Âúu»À–Áíì¡.RÂ-«n$PÀ˜àe•ð07Æ®mÅ¡û‰¿çæïÿ­¿øåcñ7üüÝÿà5·ÿ  µo [j÷É%ÕÔ sµ¼Š›n¡±îRT~òA”*ß9ç…Äþ Óµ é“Mt°™îî7#(m× 2¸åq€.v\眯ØüMÿ?7ø mÿÇ(û‰¿çæïÿ­¿øåE}àm&õoá[½†E$MÂY¥$¤ŠÊÙyä8`À|¥B•OáÏ Øøa\YK;ïˆD|ÀŠÍ/ Šª>iÜ` å¿cñ7üüÝÿà5·ÿ£ì~&ÿŸ›¿ü¶ÿã”6á};I¼{ËðÜM<ÓÜÈ›A¹óŸl˜0Rß)ûÊÁ`Óëº%·ˆ4ƱºwHËʪ8ÈõGVG̤‚0ÀKì~&ÿŸ›¿ü¶ÿã”}Äßóówÿ€Ößür€3ãøu¦%®köÛ£o`Îñ'‘l ³Èdb¬! $€ E6…]¸#5ÖOKo$i3Âî¥VX–BGÞyzƒXcñ7üüÝÿà5·ÿ£ì~&ÿŸ›¿ü¶ÿã”ZßÀ–¾ÔôX/.¢‡QSÒC¤`…Dc‚Am›ˆ#Ÿ•vߺðÕµí¾¥ÍÕÔ¯¨éɧ\JJ(¢_œa@|æ'ŒtÀØüMÿ?7ø mÿÇ(û‰¿çæïÿ­¿øåeÝx-µ=suì.š%žGß\eŠHÙ ¿ú¸˜‰˜´ŠÄ±ào;oÍàÈ.-5x®5}RYµkT´º¹wŒ¹Kð£fÄÊÈÊv¨ð–2ýÄßóówÿ€Ößür±ø›þ~nÿðÛÿŽPoøÃÅðG©^];Ç¥1ÀìàŽXo„ny%£Oû«·{NÓ¡Òí^ÞvGžk‚\‚wK#HÀ8Ëœ{c­e}Äßóówÿ€Ößür±ø›þ~nÿðÛÿŽPAXþ ÿ˜_ý„"þµ_ì~&ÿŸ›¿ü¶ÿã•izäó[5Û]Ï,Á<›uÉSê$úÐIEWó¯?èwÿ}ÃÿÅÑç^Ð&ïþû‡ÿ‹  U:óþ7÷Ü?ü]uçýnÿï¸øº±EWó¯?èwÿ}ÃÿÅÑç^Ð&ïþû‡ÿ‹  U:óþ7÷Ü?ü]uçýnÿï¸øº±EWó¯?èwÿ}ÃÿÅÓ^ææ(ÚI4Ë”E™šH@u$ù”ãŸä+£ÿ× ?ô!E7ã™c©èÅ£*ØÈ;‡Q]Ô¾a?ˆô¯ÿÈÿö?ûJºZæ¼ÿ ÿØÿí*ékŽ_6[QR0¢Šæµ«MZoé3irÁoåØ^$“ÜZ<ñÒ[¸WL1ÚH碷ÀKEy†çñ}´¾ÓLkkš¦ŠAD O4É‹vÛ >j€f•L¡OJÕµkÍT´Õì/dÑžÖâI"º´y<½¬ B6Û¢¾UœmVŸvÁ†#—îè®9®m>øWÚŠÍnÚtsÛ 5å|Fè%™B…v 9U*yÒ¸›Äi«j7I<íioªZÛÛY‹Q¶X$[q+³cs*ï‘R6•mÅ€Ú mÃøsTÖæñ=œ…ÍÔ¶÷zt÷$Ÿ²µ¬Ž¯ lÑ~óËÄ0ä«.yÍ_ñ••ÔÒè—°^j6ðÙ^4“µ„ 4Š­ˆ!ÙŽæUÀ‡bG”©¢¸ùõ-uµå £´öâ j¯nöÌ#3<³*°Y3à W&4¶Ë}cmã6дéâ¹:¢MëG‰]8ic&2I›*¯’Úû€`îŠá4—ñv¥.ŸΣ=¥¤Ñ];Ü%®f´0ÆX#T±›ºÁAПœ?XÕ¼Ieâ}2ÞÞ+©¢ÝmÇ—lßg˜;…–PØf8iЂ™*Ã@âŠà-¯H`U%Lf]’õ7úÓß^k^Ò{}nßO󡹚ل òåJœ2‚x9ä Å\(¿ð'ýu_üÿëQÿÒÐWUÿÀþµs_ÙמTŸ}†„±Í2|É<ØYEÁ –.¥ÚÀ1ó|©ˆy¹–½ÉºÓµ? Oª.¹<Ö—sJÐÅk=Ò[Û¹¤Çwuhú¥’ÜÚDf¸…®<1€ w\åWž96¹¤¦Ÿ%ûj–Keß2àÜ 7+–ÎC¡¡‡¨  ôVdÚÝ´WZDq£ÜCª³$P24@ˆÚQ“»$2£TÇ8ÈÌ–úª\kwÚ_ÙçŽ[H¡˜ÈûvJ’o®ž nà:w4%¦•§X\\ÜYØZÛMtÛî$†F™²N\–9'“ê}jÝA{}i¦Ú=ÝõÔ¶Ñã|ÓÈ',x?¡©ø—IÒ´³5ìFÖ²ÝÀ‘J…îc<Æ1Fÿ—ž8äs@ÔUíÍ'û[û'ûRËûKþ|þОwÝÝ÷3»îóÓ§5~"ÐåÓ%ÔãÖtç°…¶It·HbFã‚ùÀ?2ðOqë@tTpO Õ¼wò¤°Ê¡ã’6 ®¤dGÞ¤ Š( Š(  žf³Ð­`ž)E HÇL±#ô5©öÄþ䟕V¢€,ý±?¹'åGÛû’~UZгöÄþ䟕f_IzEÄw6wÃË{t‡ÌóäW¦1œçέQ@O øAðÕö­§èºÄ—7Hégö‹|‹4eÁU9É$“óvàx·¦éhÑé6HêUÖ ¬0AÚ85nŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+Å_ò-ÝÿÀ?ô5­ŠÇñWü‹wðý hË><ÈgJÿ®RèBŠ><ÈgJÿ®RèBŠî¥ð# üG£x'þ@>ÿ°1ÿÚU®4àúá¿’B[UrNâI?§ùäx'þ@>ÿ°1ÿÚU»=õ¥³„¸º‚'#!d)ǯ5çâ)B²•:ŠéîâÚ³E·e;Bç  sXZ'†4ík›¨ímZþæ{‰d¼[uI]e™¤Ø[©*9<íƒV ˜.P½¼ÑÊ€à´lgÓŠ£ˆ´;Lék:t·á™ ª]#Js¸l99ãœb¢”VÈ Û? ]®†Ú]þ¥É%ü—rÉojbb¯+Mµ v(ÂCàäòí`mivm§i–öM"H _-!X†Á«ò‚ídFžá¸BðJ’ fBÈÁ€e%XqÜAˆ"¤¦yà»Ë×ÖPêéok¨Áq‚ÞB/šÜÈÓ4då·‰3s¸`Ï›ÁN¨>«Oj×›I7_>âf£t}¥®²‘°d°,§­¢€9+ßXZhPG«@ÿÙ·óÞÌÒZ»™Ì¦\¨-)eÂÌã,\“´ž„{}*î_jÏy[\ÚÃn¶â܇O-/¼ƒ“,œmÃèwiá[„·iPLêΑ–™T€Ä¤Ë“Ûpõ¢Iá‰âI%Dy›djÌvÁlS…cØÚ€2|K YÛGÛÚÜZÎ.!•Z@ld ùn®ßuלg# àßü;[­çM·ÔÞ;ë1ozÒ[µÁw$¢D2»&YŽâçÚÈÃuv“O ºžT‰ *v 1 £žäîH%pþ¼ÕõS§Èš®‘çÝË([µ¹Å23DvùÞaiËãb’àdÍ´ð5ÂióíR–Xɽ^;$hj¡k£"6d“æW‡e ä×`'…®ÝeC2*»ÆnUbB’:€J¶}§Ò¤  š]¤Öe½¬÷Ou,kµ¦|å¿2NA¸³` ÌÇ,mÔWÖ–>OÚî ·óåXbód æHÝsÕŽäÔôQEQEQEQEQEQEQEQEQEQEQEQEV?Š¿ä[»ÿ€èk[â¯ùîÿàúЖ|xÿΕÿ\¤ÿÐ…|xÿΕÿ\¤ÿÐ…ÝKàFøFðOü€|;ÿ`cÿ´ªäúQ¾ñ)–X#{t³ ºP ïÞxïŒÿ“Tüÿ ÿØÿí*ékÍÄÑxJœ¶}´fñv³ VÑE )".6ÆP{ô÷®{Ã=þš.廾ºÙ-åä‰dÂ+Ü»«‚«¿%H8,q¸ð0èhªŒTb¢ºÇévºïü#pÛ›}FÒþ-FS——‹6ÈLŽÈe"G2 ‚l$±`0SUèthî!Ò`Žíg[‘»Í3L%f}Ç,`'%@ €@Ú˜Ú/ÑTœk«â !â½ASQŽØi×f+‰î6yxŒ”h„s²äsm地!îføÊ“Ì‹T{/6#ujºˆ77.Q#Ã(dÙ;[°PÑq‹»kwtPt Yo´m^k{Û»›h®`X¦ñ˜•æG·óˆ|2ª&ÙHó K€FëY^]ý¯Q½Žu¹‡ÎM>ÞÜÆÍ”J»þC+¯ ¿ fï ïQ@y‡µCÂsÙßÛ^¬ßÛÞD­*M(ŽDg@~Ó.>U;3(Îv¦ÐçZßEÔïõF–î}SN²ŽÂÝma‹PÞRey¾g<ï!‹pmÈÄ|Ý Ž¶ŠáüFú­ˆñ­ÜQê0Y}µÑº5ž8åÜc]å£8hù  ˜ØõÁm Zê¶÷~.’XÀK«¡;<à¿›*0àFÀǵp€moݦyèh kWÐ.uOé÷ms:é©aqÌ!!häÝ$'Ëet,UÕX6; Á\غŸŒäñ]̺Z½¬R¬Ñ¬ï7™n£Èqa¦`˜"$-ºw Ì2_¿¢€8 í3Äi&‘o«ÙCçÆÒZÞêh¸•B¾íŒ' £q„ÿÇÂä#|£‘).∎†ûFöX<»ä¤ÈX#”ºÞJ®ÕfapP@b\?EQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÖÅcø«þE»¿øþ†´åŸ?ä3¥×)?ô!E?ä3¥×)?ô!EwRø„þ#Ѽÿ ÿØÿí*—P†{ß­¢]ÞC³ó6ÛÈW'yýj/ÿÈÿö?ûJºUF€‡Rp?Sù×›‰§*”#.Vú­Ñ¼]¬Emd,m£‹ÍžV#s<òbO×§Ò¸ÖgÓ¼C¨ÉôçA>­ye%Á¢ûF‡vK“ÇX¡£-Ù;—#€00¬§ðþ•-¼vòÙ$Ç<×"9 e2J$ Á &“ƒ‘ótàb šŠæÜj?‰zE̶E.mma7‚ ǹº…Ö(Ú ÝI%áÛ‚Ùë7)6õ_ˆz6‹,ê =»IÚgh¢xá,ʲwWlìc±8ÆUˆS§gáM"Êù/£Žê[¤eu–æöiØYpdvà ¥ã§ÌO\T‰á­.)md‚)àklÄRÄ6†,¨ÁXI;Q²ª HªJy–ÞÞIÜ9HÔ»ш<*‚XûIí\õ—lµ -/--'žIn¤Ð\[JòÈÌ 2Jc@Íó:Ÿ—§+ž†xVâÞH¸I£Ý‘€#2Tû‚íY#š@·xŒwNìÊÿh’öf¸R ¶bþb€Æ‡ï6@ oMqu Ifmo¯'³º†x›‘Ç36ÐUàe<09È8äÏ'ˆ!µÔõ¨¯CÁk¦YÅw$ ÆÞigX’–FÒªAS÷ƒ HÞÒÛû7÷S¯öt¦k}—R®$9Üï†c¶Kî'{g;›/mM}NóP’–kصÂË3¼RD:)‰‰LrÝø›ûÇ SxèY^jCPÓn­a³‚Õ¼©„hâI^`wJdòvmmøÉ+’ä%u67i§Û^D1ÄK*êÜ0r¤©ëÔ= ¬„ðvœÑ%ìRÏåùÓǨÜ$Òìß·|÷¶<Æ“ÆÑÑWöVVú}¢ZÚDz$Î%‰$ä³Ë1$’Ä’I$’MOEPEPEPEPEPEPEPEPEPEPEPEPEPEPXþ*ÿ‘nïþÿ¡­lV?Š¿ä[»ÿ€èk@YñãþC:Wýr“ÿBQñãþC:Wýr“ÿBWu/Oâ=Á?òðïýþÒ®¡c,»·(Ç&¹ÿÈÿö?ûJ·oŸPû:&ž¶Û÷åÚà¶Ç@ùãߎ9|LÙlKÐÊò¬R¤†'òÜ©È €HýEdEâ[i.&Ýku„M,gR ·Ýa 'vä QÆçU\¯åwXÑlnl¡¹û[Dežá¦>Q;Fà=~†¹Ÿø2êúnîÞKY.®,îR*Ña¹žEŠi÷ñà Tcdd±*KH΋Qñމ©j·ÛâÓwýª;9Þ2œºœ°”rT}³€mÜêVÖ·ÖVRH‚âñbŒÊŠÄ*–f H,;A#p$c$s³x:âMW±]J–úÁ4ÈåAR+dÞ1«dįÊí_»„tõ 'Q¾ºÐ®>ßj§Oö‰ÇÙ‰ØÆÑ¿¼ýØÄŒîÁÛ×pšo‰tWVÔt»KØöÂS°‰P±Â¡,v‚á aªýÝõ¥„B[˨-ã;°ÓH|ª\ò}Y²“Ú¨[éºåÕì7ûm.å[ù ³J"X‡ÎOíE;BîÜ3»Z©â­ëY—B»Új?ji$dXöÁ0F(ßxy…œ‚¤nRkšL?bóuK$û~>ǺáÚ3Œy|üùܽ3ÔzÐuÍ$K,GT²CÍ*›„ÊFŒQ݆xUe*IàAé\¶±à+ÍOF:tZóÀ“-ÇÚÉB4“»<Œ©ÉÆ\€²G÷‹ôZG‡í4¨d_* e{û‹ÿ7É ÂI]Î{üÁËÝÔØq@íš÷Y´Õµ‹Û[««yâ“dVf8ŠÄ“ˆð¬îC‡¸gÝŸá\FhjMsI‡ì^n©dŸoÇØ÷\ ûFq/ŸŸ;—¦zZ¿\{ø.ñn£–×WKP'šg’(eI›Ì¸’m»–`ŒÌ!Dˆêã´†+]…QEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÖÅcø«þE»¿øþ†´åŸ?ä3¥×)?ô!E?ä3¥×)?ô!EwRø„þ#Ѽÿ ÿØÿí*ékšðOü€|;ÿ`cÿ´«¥®9|LÙlQEHŠ( Š( Š( Š( Š(  SËÞûºãŠ?sÿM?J?åÛþý*:“÷?ôÓô£÷?ôÓô®/Äþ3“Ã÷ÜÝä{M%/mJYÍ2™Iœ+ !÷IÉ+Õ¹ã‹v~:ѯ|LÚ2æçÍ’o6#¾HÃo_,9‘q±þfES·‚w.à§÷?ôÓô£÷?ôÓô®OA©xW^Ô4Fo´«SrÑNñܦЬÃ& JüÛc~F2F1»´  ?sÿM?J?sÿM?J宼mce6ë‹;ÔÓijÃý£µ ;áIQ´?™Ç“ ûœ•ã ‚kØ|BÒµHl žâôJ‘%œ[ÊòWq‡ILCåŠS†p~NŸ2îìsÿM?J?sÿM?Jã¦ø…¤ÛÊRk{ÔTˆÉ3”B!ei„ˆØl–AmpÇh ˆŽÒÅ”4‘xûH¸×¦Ñ­ƒÏx,Q¤sCºic ^0†Mê~GUß½†R@:ßÜÿÓOÒÜÿÓOÒ¸í/ÆrËá}RÔ4‹Ô»Õ<¸â†ÝüÙ.äÎØÎÖ¹um£,.]xËN±±Ô®¯aºµuš]Ïê¨ÃsJ‚1–Á}а;[ríf t¿¹ÿ¦Ÿ¥Gs=µµ¬·%)`¸ÎÏU=_þ@·ßõï'þ‚hkKµYÁpg›¾ÜçÆjj§¤ÈÇþ½ãÿÐE\ Š( Š( Š( Š( Š( ±üUÿ"ÝßüÿCZجÈ·wÿÿÐÖ€<³ãÇü†t¯úå'þ„(£ãÇü†t¯úå'þ„(®ê_0ŸÄz7‚äáßûý¥]-rÞi¢ð¶46í;.´(` ±ò°2xàZÓûv·ÿ@ÿÀèëŽ_6[ÔVOÛµ¿ú¯þGGÛµ¿ú¯þGR3ZŠÉûv·ÿ@ÿÀèèûv·ÿ@ÿÀèèZŠÉûv·ÿ@ÿÀèèûv·ÿ@ÿÀèèZŠÉûv·ÿ@ÿÀèèûv·ÿ@ÿÀèèZŠÉûv·ÿ@ÿÀèèûv·ÿ@ÿÀèèZŠÉûv·ÿ@ÿÀèèûv·ÿ@ÿÀèèkþ]¿àÒ£®~ùµÛèR/ìÙíÕ[qû>£–>çÿ?J¡ý›­ÿÏSÿñÿ…tz6Ÿ}öÿ´Ûïû}¨³¹ùØy‘ ø^ë_‘ƒÏ^#MMK‹¹D.Év®“Û¼ÎÖîåÿrO– ’Bä–lýãœ?ìÝoþxêŸø7ü(þÍÖÿ玩ÿƒxÿ€4áÑ¥ý´‰{,z„I É›Q¸‘Þ5,Bog,çl€@;ˆ9ÍmA ÛÛÇ)„S#³±c–bKrI=ë”þÍÖÿ玩ÿƒxÿÂìÝoþxêŸø7ü(i|myâOíKõÓ®P4Œ3§¢ÜH6ŒÇ,¹Ä‘„vv…L“ƒ»Oþ½8éÿbs{$b_9$’þwš7ÆÜ¤¥Ë§+‡ñãfëóÇTÿÁ¼áGön·ÿ÷N3òœP¹ÕuÈôËÃe{«Ïoº ÕÖ–ñÜ´‡Ìó*[¨ÄC´ æ\ä‚€‡çÉýïÐQçÉýïÐWœj¯Œ^]%,ažÝeµkÜ#-Ææ çì¶r±àFÜ‹s‡lí ˆý€"Ôon Ó.æŽM²G ²œ‚‘QiŽòé6rHÌîÐ#31É$¨É&›«ÿÈûþ½äÿÐMGülëÞ?ýPÊ(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû™w w{¤’U[Œ’¤Õ­¤ÈÇþ½ãÿÐEx÷ü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQìfñ=¶Šñ/ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð£ØÏ°sÄöÚ+Ä¿ázßÿÐÛþÿ7øQÿ Öÿþ€–ß÷ù¿Âc>ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûOï~‚>Oï~‚¸ KÁú…æŒ~‹oÚŒçOkCÊli`‘ñ± dÉÔÆCKð=õµ°º¼ž õ±ua(½iÙR(í’}¬FU¤J o ¡Ž8Å}£Ý]M²$ÆH]Ä’p@f$€I I¬Ãã-4[¤¢k§vfO³Çc3\)P ÝO1@ ‡%@ç÷—/×´éµ=+È·dG<1‰ í©(R@%CÛœg88ÁÉÔô½kT··žâÏN7HÎ6úÍ«D„/æ5ÜÀ•É]ŠS¼`¸¸ñn˜×q[Ç}æù»6ÏLðàS0S³\)`NôÀ;—7ïuDÓíêêm‘&2Bî$“€ªË1$ IMr¶ºˆì¯vŪ@ñÜ]Aw{}€’HRâ’?'c.×ò³¸:/Ævá¶µí:mOJò-ÙÑÏÌbBB»E*J PÅ6çÎ0@.iÚÔ:¥»Mk+±ÒXZ)#l†G”àƒ‚A¡­ùò{ôçšç„|E®ÛÃ-õå­Ë¬ó8Óåhš•ÂmÞÙÃ”Øø& Ø”üöÿịV‚Ex.¼¹mž=^îR×ÐGÆù>e“Ë}ÇzßÉòžww|ŸÞýAqª%¬Ö°Í6Ù.å0Â6çs„g#ÇÊŒyôúWœZü7Ôì´Hìmµ("Ý`°Ï_*3¯Ù—ʲ´lÑ]YN>Ôä£n`Öãø~CÓ’{:úêÎñî…•á­ö¼f32@¡îÊ@‹—^y;€¡ùò{ôyò{ôËiÞ‰u‹ýWTX./¦ºŠx'ˆºy[`…`$ù{š6Ü;“j±`02|+aw¿§.oM–—¥Í`±ÜØ› nƒËRÇ"i‰÷ ¿#ƒ³ÊwØiPMk¤Y[ÜEkÑAI¢•…(F!è=1@¦«§_Ü\ÛÙßÚÜÍjÛ.#†ev…²F•9ƒè}*y'†'‰$•æm‘«0Û°=NŽ`OjóCN×ìt8aŸO¹Òmm´¡söˆÔ\I%՚ò#"&Ϙ€áÆQ¾`4î|;¨ÞZÙ]Ok«´6Z‹Ï€Õ]¬ nc*eaŸÍ,à™ ’ Œ” ìÏ Ü%»J‚gVtŒ°Üʤ u \žÛ‡­I\ñMWþ-6ᬮ…«iÒExÑ]†¶I‹#&™I#lƒxŒ½sÆvó©¤x®KxâŽ]RÒçýu –¾YÄ¢âó[«;ã·¡T:ªètW¬i> ެ¬—WšÖ;ÂÖ¾]Þóä˜b'{›¨f'Í3c2Œåp#+Ôÿjj ­ØiÒ賘î-^iïa‘Z$]¿»ÉÃäàíñ€~m€ÔVMž¯ys6°’èw°-Œ» fhÿÓFÀÙæÀäã’Lw*Ï¢ßÜjš%õÖŸ><ñ{IÈ/=Ž?®¨ _¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ŽñßüÃÿí§þËE;ÿ˜ý´ÿÙh¤#µŸýs~Ê£©'ÿ\߇ò¯4ÓôË_øE³húŒ:ºYĺµÄvLâehÌžh%~Ø«–Ù¼²y€02ìg£Ñ^b–Q¥½»Þøu.tx–èClºdëo,ä@b±í‘íÇË:çiÞÿòÔô=(L4‹!qnöÓyùI9£m£*d9.Aãw|g½[¢¼ÇÃþÖti—Úxµ³Ô傯†ÛK1œ<°ùt»É•Ñwüß!PÒž7ezTëgÙ-çÕõG±>k=ý–ž“]ù<¸Ý'R§3Â5ÆÔƒ’àmçšf·â»bHnÄés Õ¤FÎEka¾ wºW”n+°;ºe—$à4¿q`°Ô¼yqopÒþæçͶIc’ÙäH÷«ˆÇ‘h‚·,§H}æôª+‹ñ“ªDš5Ãëz¤±Xß¼²\ZÙÅ$ëA"(±6öÛ~D,‡*JïÞîá¼u¥¶½H¦ÒæÞf-ä/*™ÕHV!d ¾aS±8ÉR@:Z+Î4Í[ÆOc©Í¨3Á$p ñý’iZ)˶¶ ǘ7päo™AßµcâwÒ¼'m®[ê#]-¶ï³4’H^@ªÛV(Ø(Ýš4$®mÊ\­¢³'×-müEi¡¼wFêê .ÖÝŒAP¨ ¾0Íü³‚ÊÓ5Ë]ZûS³·Žé$Ógó­Ú5f*(Hà ä~ë) tQEQEQEQEQEQEQEQEqÞ;ÿ˜ý´ÿÙh£Çóÿ¶Ÿû-„v³ÿ®oÃùTtËË(%ºw?qÆvÜʃ§¢°öu·­ÏþMÿÅÓjŠ«ýmësÿ“ñtg[zÜÿàdßü]Z¢ªÿg[zÜÿàdßü]ÙÖÞ·?ø7ÿ@G1<¯H3o‘•@.Ø “êpª2{;T•Wû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  TU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâèÕWû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  TU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâèÕWû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  TU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâè˜ñßüÃÿí§þËE'ŽT"éʹ‰Ë‡¹äÑHGm?úæü?•qÚV±®êrÏi$ÖVW͘°\ió©·`Êg t£vÓ$l ‡8±Ÿýs~ʲ4íMÒ®{H]_o–æyÈ;"V$Dœ/Ê€•xùFÌ_ kÚ¶¡ýƒý¢öOý«¥Ë¨Ÿ³Àñùxû>Ôù³þ¹òxÏËÀÁÏ[X³xSH–ßO€Gu iÐkSm{4 ‘€©dpX~í:“÷EkA ÛÛÇ)„S#³±c–bKrI=è‹Ó¼_¨ÛHZû-À™®ã€XÛ´MæAv–ª˜y#H˜$¨^䃸kÆî-aÒuu0βéëä‰b#fbÆAšò¹?¼pÛ_kàÝÒ¢ŽÚwYwe§»šVBÏæ3#;“Ë)²«g*øSH6éŽéYŸíÞÌ· XwLÌ`B Áb0‰ýÕÀ~"º¼ñlúZéW_a[;{”ºeTÛæy¼º³‡ì ÍÁƒn`Õvñæ¬wSYj1ÛÜ,rÙ¸‰d7q<‘Æ$Q™° ѬÈn@ÖéOqi7Ø‘ ª¢D‘’‘íC˜Ã"¬òØy\j¼'¢Âr¶®B´m½Äްì‘dU‰KD; v( €¿§_5ý»<–WVr£lx.UC)À<,¬ åXŽ à‚ºÌ×4;_XÇgy%Ôq¤ñ\mpжä`À¤d~†‚}ÖãÄVšãÉt.­`’ÝnDUÊ’Jgü¿Ë9*¥@4è¬Í3CµÒoµ;Ëy.žMJqq0šá¤U`¡p€œ(ÀþC@Q@Q@Q@Q@Q@Q@Q@Q@Q@wŽÿæÿm?öZ(ñßüÃÿí§þËE!¬ÿë›ðþUÉi>)½ÖÒèXXiÏ4j¬°¶¥óÀIÿWr¢2ÐÉß(2Ž õ³ÿ®oÃùV-†‚–Z€¼’þöòHâh-ÅÓ«y±RÊPωóH]¾QÏ-–2‡‡üOw«ÿd}¯M‚×ûRÂKø¼«£.Ø×ÈÀl¢üÇÏ9Æ@ÛÔ玖¹ïøD£ŠßGŽÇVÔl_J³60Ë’Ìñwù‘°ÏîäÞ·`¢·Ž7™ætP­,C9ï  ž¼=  (üP¶ï­É¬¥®Ÿc¦^Gh.~Ðθ•˜PƒF$['&¾­ã½+O³µ’;›U¸º­ã‹Q˜ÙÙS{w®øÆÝ¸Ê™#ìàÕ±áh ºƒÍ¨^Ì·×ð_²?–rBÑ• µÛˆ£S’N¨$“cþëOí?·ù“ù¿oû~7 ¾gپ͎Ÿwg>¹ïŽ(#ÓÖî+IÌð\¾ÅtxY’ ±I*ƒÈw( ['rã;—:Õ‹qá«kMîÍÕÒÃ,ñ]Of¥<©¦fÉ +¼åŰS°d¶v¨¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ŽñßüÃÿí§þËE;ÿ˜ý´ÿÙh¤#®¼žtºuKåQŒ:¼@?ÚpJƒíW?ô ¹ÿ¿ÿñʽ?úæü?•fG®i3}·ÊÕ,ŸìûfÛ„?gÆsæsòckuÇCéLd¿j¹ÿ eÏýü‡ÿŽQö«Ÿú\ÿßÈøåS—Å>‚ÒÞîm{KŽÚçw‘3ÞF]§ µ‰Ã`ðqÒ§MsI’îÖÑ5K&¹»ˆMo Ü!y£ è¹Ë.9ph_µ\ÿÐ2çþþCÿÇ(ûUÏý.ïä?ürŸq}iiŸ´ÝAØžcæÈ¦7¿?»—' ÈÏZ¡/Š|=¥½ÜÚö—µÎï"g¼Œ$»Nk†Áàã¥\ûUÏý.ïä?ürµ\ÿÐ2çþþCÿÇ*˜ñO‡ÜVƒ^ÒÍÌÛ<¨Eä{ßx6®rwc®F:Ôún¹¤ë>oö^©e}åcÌû-ÂK³9Æv“ŒàþF€%ûUÏý.ïä?ürµ\ÿÐ2çþþCÿÇ*-K\Òto+ûST²±ósåýªá"ߌgˆÎ2?1Vàž«xî-åIa•CÇ$l]HÈ Ž#½Cö«Ÿú\ÿßÈøåj¹ÿ eÏýü‡ÿŽUª‚êúÒÇÉû]Ôþ|« ^l<É¢.z±ÁÀšgÚ®èsÿ!ÿã”}ªçþ—?÷òþ9V¨  ¿j¹ÿ eÏýü‡ÿŽQö«Ÿú\ÿßÈøåZ¬É¼E¡ÛêcLŸYÓ¢¿,¨-^éRÍ£a9ÉÈÀÇ9gíW?ô ¹ÿ¿ÿñÊ>Õsÿ@ËŸûùÿ«UÕõ¥“ö»¨-üùV¼Ùy’7D\õcƒ€94ϵ\ÿÐ2çþþCÿÇ(ûUÏý.ïä?ür­Q@~Õsÿ@ËŸûùÿ£íW?ô ¹ÿ¿ÿñʵQÍ<6èyR$,¨Ø(,Ä*Ž{’@¹ P?j¹ÿ eÏýü‡ÿŽQö«Ÿú\ÿßÈøåE¦ëšN³æÿeê–WÞV<ϲÜ$»3œgi8ÎäjýUûUÏý.ïä?ürµ\ÿÐ2çþþCÿÇ*a<-pöë*‘UÞ0Ãr«‘ÔU°{í>•%UûUÏý.ïä?ürµ\ÿÐ2çþþCÿÇ*ÕWíW?ô ¹ÿ¿ÿñÊ>Õsÿ@ËŸûùÿ«TPã’JéÅ”©"BTHû¼q‘E/Žÿæÿm?öZ)ígÿ\߇ò®]7Tºÿ„‹þ%“Å¿Y´¿·ß$_é1Ãö}Á0ç ~ÎØß´|ë’>m·µO%®©sn–- ŠCæ—nHàñƒÜ©ÿ ßýCò?ÿcLfmÝ—‰fÖíõq§^ÚnûZ‘¥-šÜ„³ÄâgxÙ± ÈO Ÿw•sØêrëË5¶›u 7sÛÝ\G;ÛIjJˆÃ4 æU™V0DY7$mž_ ÿ ßýCò?ÿcGü'õ ÿÈÿýX¸Ñîµ õ BÑåÖ%X¤[xæUk=®’ác”.¬ŠÄ·Ë#¢î!6„t½^ëÃî“Û?ÚdÕ¬îGŸä­ÃÅÐ34Æ,F\ßP}ìŠOøNÿêÿ‘ÿû?á;ÿ¨oþGÿìhmmµ‹j—eÕÞÂîò9@Öfeûl¦->L-ìYX‚&ó†å ·'kq,||¸K_ðÿÔ7ÿ#ÿö4ÂwÿPßüÿØÐÛ蚟‹aÕ¤‚êîk›;h&jL"ŠHüÁ+HŸ*¸*ã`X±¼1"=Å«14ÉoQ˪Z\ÿ£®¡r×Ë ¸”\B^kugaaà”*€‡Q±±µt¿á;ÿ¨oþGÿìhÿ„ïþ¡¿ùÿ±  ;Ǹ𾒿Ùö:¦²ê4X>Ð$’$vUc¾C¹”rß3ÆURÜúÔ^"´ÓIº–Öx$•õeò¢e*œäçÓÓÅ0á;ÿ¨oþGÿìhÿ„ïþ¡¿ùÿ±  í3Sº¾¾Ôíî4›«(ìçC4Ì¥n—h;Óœdÿ.wnUÓ®;þ¿ú†ÿäþÆøNÿêÿ‘ÿû¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áSGoæÊ‘ŒÌgÞºO®ƒ ê—¾‹BžæâÖ¨µÙVóY)ýÒ£#?§1)F-+“zÜå|äÿŸ üü(ó“þ|,?ð?ð®Úm Ád –®ß I÷olÍ݆`þcÚªÁàËYÖÊÙ5•:¥æ–ºŒ6­lÀ0 ’»óÐóíÐT*Ôú’G'ç'üøXà,áGœŸóáaÿ€±ÿ…ug…tûû yõ¡m6²e[hM«>YÜôÝZh\²99?çÂÃÿcÿ <äÿŸ üü+¥Ô¼-gka¨\Xêé}&Ÿz¶w1}£(ÌÛF ëÏqדOÕ|%i¦Ùë ººÏw¤$&î·`¤#98<ô§íi$Ž_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ ìø øQç'üøXà,á]~‡à)õ­&Êõn3|®Ð¶g@þz88Lžœä•˜ G¡q”$ì‰i­Xß9?çÂÃÿcÿ <äÿŸ üü*O(Qå «!ùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…IiWréúpÀͲsÿŽÑå ¿gú*ñÝ¿™¤Ò)ùOÿ>gþ'ÿQ3˜Dtý?yé‹dÇòö5±å{U9"ÿ‰œ\ôjZv)ÿçÃLÿÀdÿâi®­3› 4…8¶Lÿè4¯§I{{tMõä"7U €>è>žôëh;KØZifòÙ”<§-€ú{Ô¦¯°ìGiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰©ã·2i¬¢V‡;¿x§y<Önyq¨ÞG²–0X}§ŒŒ»íCi;Xd²0VhßO°VÙ:|P~'xÆÔ›xõ§1Åò)x"vÀàeŠ’O¹95fò/ô¯øþf¸›Ÿøû›ýöþtªF---£¶µBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5lÂáßúäi?øªÅâ`ž«cENVŒdpkyw‰¨éP,F ¨“³©,œ¸2FçŽ:jô6áò}¬°ÂÚyÂwÍÆÔhwy‰»¡fØâ£py©âÓ|qiqs¤ó-¾ß68’åå]Ç÷cç?0e82:œ`-â);鸽œ»œž"Ö•§:yÓZàÂÞkBF1ØÏÐ|Ò[ëÚ­¶©c¨"Y™¬tõÓà ´Æo›%¾cÐí]ÔšG†ÚëDû&’“ÙêsÉnÒ›©‘áuŽGÁŒóœÄêÀ•*FÎ@ÖŸÁÞ··’wÓ\¤j]„o3±g…RK` =ª}­ÃäŸsÊ-u+Ëm"ÏN–ËJÔ"³Ýösld1dä… Ž ìr*„6Æ(‚¹êp0+×ìü7á Eä[+t¸ª;³ÁìäxíÀYgܙ۴ ‘_ñ¯?¹ÿ¹¿ßoç_QÂáßúäi?øªù“W!Ö¯âŒaâEQè¥V3Ñâã¹ô÷‚¿äGÐÿëÆ/ýVíax+þD}þ¼bÿÐEn× ¾&n¶ (¢¤aEPEPEPEPEPEPKÍ:Û« ‰ÃØÎn# F Þ<:bFéŽ@¬ð— ¬––“ÝZÙβEso–x^I$òH(J 3J£Ë*Øn¤€GSEd¿‡­$ðö¡¢™'û5÷Ú¼Ö 7=ÝßiÆ82dÙÍP¾ð6“z·Š ð­ÞÃ"’&á,Ò’REel¼ò0`>R¡J‚-ÛøŽõ4·òmfž[K{¢F%ž-þbmê yo†<ô –õ]Kû>(8¼û»©|‹XKmIµ›ælª‰Á8S€Ç @2lük§ÚhÖ¶ºìQiWRÝF¨°(‘ä/¸0à.%‘@@¸ ê ñ´¶òF“<.êUeŒ)d$}ḑ×G¨5ÏIã;A Ϭï¤M>¥¸…k8ÕÞ6ÈÉÞÁâ—! È$ìWéh†›¤Ûé>jZ<â 0|—º«ó¹Ál¶æÈ-’rAo¼ÌZýPEPEPEPEPEPEPEP_#ëŸòÔ¿ëê_ý××ò>¹ÿ!ýKþ¾¥ÿÐta÷fu¦|ë4Wv ‹afc€ÁÉ­?í}7þ‚Ÿ÷ùư´ù%Ö?ö _ýYÖ––Íg5¼D˜Ô’PsÅa?‰–¶:ïí}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð*n:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| .:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| »£éöRꤖ–î§vU£”ûQp¹bÐÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| .:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…ξ ˜.P½¼ÑÊ€à´lgÓŠù3\ÿþ¥ÿ_RÿèF¾´¶Š8l-(ÕB§jŒ žOë_%ëŸòÔ¿ëê_ý×NvgScèýþIuý‚WÿEÕK?øñ·ÿ®kü«SÂ$þÑá‘wG&Ÿ°Î2 k~K¸ìlÚI%ŠÞÚË36#E’zü+ üLÑlrTWG£ëÉ®iÂúÔN‘eˆ,ñyo˜ähÎTò9SÁÁõñLÔ|Km¦\,79Âù³º&嶈’’ŸáBF3ìÍ÷QÙfÁcŸ¢º|Km>¦lRGÉfŠ9Šb)eLï¡u‘ìÀdÇ ]/>Oï~‚‹Ž6Šì¼ù?½ú <ù?½ú ,8Ú+²óäþ÷è(óäþ÷è(°Xãh®‚oÛA©‹‘òb’`™Š)_#vèà{¨82FúƸtm8Þ<3Ü~ö(Vow’E@ÜU~óޤQ`±ÎQZ6ž7·¼Ó!½Kk£ç³ù0Âa¹y#Ly’¯’î .pyÎ@P 2«oA|.­ã¸·%†U‘ÊêFApAè°Xä(®ËÏ“ûß £Ï“ûß ¢Ác«Ú;¤Z¤RHʈ¡™™ŽNI5Òyò{ôyò{ôX,aÿÂU¢ÿÏïþBð¨á#Ò_PIÅâùqÛȬJ0ä¼x“Ðôô­|Km>¦lRGÉfŠ9Šb)eLï¡u‘ìÀdÇ Yõ`i¶ë$›ä’Fòá‚%I¤ Šp É ÌïøJ´_ùýÿÈOþƒö¨ou½FâÝ÷Äþ^ÖÁÂã¿Òº ð ÔlíQEQECRÐôgÊþÔÒ쯼¬ùj·IvgÆàqœÈUú(øZÑnÇÞFžÒÃq-Œh4°„0=U@Ž<¨àùiÐoÉô]WS·Ö¬õkÍ:âÎât{ˆuŽ5 vÊ®HpYyÆRIP ÍEák„šMDêž^³4®ÒÝ[Û…MŽ‘Fʱ¹l|°DÀ’ØuÏ*LgzÆÊßMÓí¬m#òí­¢XbL“µO'€:ÔôPEPEPÔµ{M*m:+·Ùöû¡i‰ ;€I#®Â£$1ÍA‰t™:ö I'ºšÒ®eHÞi"”ÄÁ?7Ì8Ç<Žq@Ûør54¸óÝ­až[»{R"ž]þcîêÀù…<#õp[èÚÍΘŸÛ•¬š­µä·6WVöÅR wªBß0òÝ”Œƒ†ÀmÀHt޹¤‰eˆê–BHby¥Sp™HÑŠ;°Ï ¬¥I<=(msIM>KöÕ,–Ê-¾eÁ¸An W-œ ‡B=CQ@2x2ÐÂðEu:EwA©nšò6w‘²p61yeÉ@$p;:ZÌ›[¶ŠëHŽ4{ˆuVd‚êFˆJ2wd†Tb ‚8ç¿<ðÚÛÉqq*E J^I$`ªŠI$ðèJ*1<-pöë*‘UÞ0Ãr«‘ÔU°{í>•%QEfjzK_\[ÝÛ]½ì ñ,èŠÿº®õÚÙùÇ ‹Ë¹Z4ÍGOÔô»}:æÖZYµ»Ù´LÒ–DdH[ õ÷ÎíÀ¦ÕÉ[ø!ÅÍÔ 8š+±³[ceŽ_1€%@ðÆÜ"¦wel í+MþÏŠw’_>îê_>ê`»D’mUùW'j…EP2Nd±ËôPEPEPEPEP_#ëŸòÔ¿ëê_ý××ò>¹ÿ!ýKþ¾¥ÿÐta÷fu¦üÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v±—ÄË[QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(3VÑ¡Ö%ÓÍÆÆ†Öw–HdŒ:Ì­± ñŒKžý1ŽkžO=½•í•¶«‹mB)m¯|øZYšyG2edâ@]÷ä…8êiEsRx6ÒO êÚN`êÞÍö¯³ÑÉpdñžYRM™È$ p*¼Þ t}AôíZ{V¼ÚH!ºù÷0-£í-pp”ƒ%e=mÉXøFúÂÓB‚=ZþÍ¿žöf’ÕÜÎe2åAiK.gbä¤ô ôZ­¢êEí“À— q‘42HѬ”¥” ç‘ÔUº(–𾙯©j—©¨©¹‚Þø˜Ë LÍJKbcTĈ\r¬HÉÜÝMPEPEPEPEPEPEA{{o§Ú=ÕÔ›"Ld€X’N¨³@ $$ÔzV£¯¤Yjvêë äÜF²+¨` Áõ  tVdÚ픘±v|†X¤˜.bŠWÆÈݺ`xê ‘†4ívËS¸hmÙÆWÍÝv­Ì@€dˆÿqŸuoºȩ̀_#ëŸòÔ¿ëê_ý××ò>¹ÿ!ýKþ¾¥ÿÐta÷fu¦üÿ">‡ÿ^1è"·k–Ðä—XÿØ%ô]d[i–rZÂíY‘I;\}k üLµ±èW ý“cÿßãSp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ÝÂdØÿÏü}¿Æì›ùáÿ·øÑp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ÝÂdØÿÏü}¿Æì›ùáÿ·øÑp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ÝÂdØÿÏü}¿Æì›ùáÿ·øÑp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ÝÂdØÿÏü}¿Æì›ùáÿ·øÑp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ÝÂdØÿÏü}¿Æì›ùáÿ·øÑp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ÝÂdØÿÏü}¿Æì›ùáÿ·øÑp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ÝÂdØÿÏü}¿Æì›ùáÿ·øÑp¹ÝÑ\'öMüðÿÇÛühþɱÿžøû ¥ê]Éhëc<\œl’xL¨9ç*Iã?Ä?¥s¶Ú'‰4¿ Xiv³§}ªÍ­âK‰,X)¶M¡”¯˜räÈ#9ÀÚNñcIðæ=ƒK=—˜ÂR ù®8À=]ÿ„cAÿ oþG“üiŒ†ãÃÏ©½Çžëk4ñ]ÜZ€1,ñlòßwUËL¨à˜Ó Þ$4ŸC¥\Dâw–;H ¥„lû4©)‘Ëœ¢ Ǩƒïog[oh7ùŸÙ{~yhý×eõï·4—zƒke=Çö^ï*6}¿hg8ë@Uò>¹ÿ!ýKþ¾¥ÿÐ}Y¥[ÛÁ¤Y›x–••3Ì2y$“øž˜¯”õÏùê_õõ/þ„k£»3¨} ÿÉ.±ÿ°Jÿ躩gÿ6ÿõÍ•ixN¹ø}¤[¹!%Ó£F+×â·¢¶´†$‰,íÂ"…\¦N¹äÖø™kc•¢º2ÿIÖ,VûNK;›WgD–8ÁV(ŸʞG¨È¢îÿI°¸¶‚é,â–å¶D­ùŽ@üYW'΋Ք°X種†;ý&]N]9ͯ"]ïŒd3ìH „Ž :€ë›žU·üùÛß¡E‚Ç%Eu¾U·üùÛß¡G•mÿ>vß÷èQ`±ÉQ]o•mÿ>vß÷èQå[Ï·ýúX,rTWC%þ“§œéf·’®ôˆÆ2G8ö…rRÈÈFÁ©ÞéšE‹^^[B°«"~îÔÈÅ‚( €±%˜ Þ‹ŽzŠÖÿ„ƒB]?íÓ¶°y¾Vo,d·bØÜNÙ6йbØÀ Ĉ×ò­¿çÎÛþý ,9*+­ò­¿çÎÛþý <«oùó¶ÿ¿B‹ŽJŠë|«oùó¶ÿ¿B*Ûþ|í¿ïТÁc’¢ºïô™u9täK6¼‰w¼B18ϱ 2:€èN®d½¸ÓôûGºº·¶H“"Ä’p@f$€I I¢Ác𢷤Õt8¾Å¹´ý·Øû3*†YÆÆÒYn„º å”þU·üùÛß¡E‚Ç%Eu¾U·üùÛß¡G•mÿ>vß÷èQ`±ÉQ]o•mÿ>vß÷èQå[Ï·ýúX,rTWC¨ßé:MºÏ~–pDͰ3Æ:à“ø‰èª¬Ç.yVßóçmÿ~… •¥§x›@Õ-ÚæÞÜ¥ªÁö“ss¦Ëo•€w $ER0sצO@kNÊãOÔ-êÖÞÙâ|à˜vAÁVeXAR@"‹ŽjŠë|«oùó¶ÿ¿B*Ûþ|í¿ïТÁc’¢ºß*Ûþ|í¿ïУʶÿŸ;oûô(°XÎÓ.`¶ÑÙî&Ž$7‘‚ŒísSké¿ô´ÿ¿Ëþ5bKk9•V[ GU$¨hAœgüª?ìí7þVø¿áLeK-FÆ5ó/-Ó|³:î•Få3>ç‘QꚦŸ&“z‰}jÎÐ8UY”’vž5û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü(Ó¿ä ¦ÿפ_ú¯“õÏùê_õõ/þ„k럔**¢¢"…UQ€è¯‘µÏùê_õõ/þ„k£»2¨}7à¯ùô?úñ‹ÿAûY—ººEººšU“ýïR¸ki ‚ 4e™ã‡™à¯ùô?úñ‹ÿA»XËâf‹c’°ƒÅ:G†5T‹NÒåÔ„·6q¥ë²HòÍ$»X´i»ÀüØä§QcUðõÞ«ö†2Aö­‚XjH¿—óal ·ïd_˜cæVÇÈQúZ*FsÖ¾š NÓ¡°´¼ŸP·4Í7›½\ôؾt„c“¹AÆÂdèh¢€ (¢€ ¡©iÚ¯•ö‰oSËÎß²ßMoœã¯–ë»§|ãœu5~ŠæŸÂî.Þ®â[=Õ½ìþk3Î%€DC’r­äÄIl·Êý|Àc/,õrÓY±Ôl,¢.¢}9’îU3¢dÚѶåá†vŸá` ÉÒÑ@~Ÿá}GNu¿²u•Ò´©‚n{KXe† €„ð‰pA.ëÁo0tºV‘¤Yi–ìí œÛÆÒXª(PNÀô«tPEPEAq{ok5¬3I¶K¹L0Œ¹Â3‘ÇO•óéô¢ÎöÞþšÚO25–HIÁÞïR´²³Õ´ûùgµ†9ÚHeLI‡m ÑÈÜ€pv±^±×KEqïà©–ÖîÚ+ÔdÕ {mMÙ!^I¥f„dí9¸•@bØ ‡'aY; ©s©ÚÙßYYÎî³^³¤‰Š³*— °Tí @$gÁ«tQEQE“ªé·sjš–, {o¶à\)hÌr”,p¤ÊcF8 2ü»ƒ­{]OF»ÑôkH%Ð-¬<™.æŸ÷êècBàäŸ^~îÐzŠá,| <*°¬vZtvÑ"Fö²É7ÚäŠX¤†Iƒá‚§“´&÷!$eW\zNšÈ^\Ý2ËùþÓ:ÄIŽ6òÒ0ªH€±¨ÉÆã“…(Ó¢€ (¢€ (¢€ (¢€ (¢€ ù\ÿþ¥ÿ_RÿèF¾¸¯‘õÏùê_õõ/þ„k£»3¨}7à¯ùô?úñ‹ÿA»X^ ÿ‘Cÿ¯¿ô[µŒ¾&ZØ(¢Š‘…Q@Q@Q@Q@Q@Q@¾ З]—IYUÞÒðÜJ™[D¨¥ä8wFF܃+–jg’$²¾–_´,7·O‰t÷{‰¥0…R%BBù4+†Æ úÅËàH¤ðö·Ží‹ïíÑ•øYÞRˆÇ¯–€”®ü°¾j‚ãÁ„6Z¥•”ÖRÙ]ùEm¦Bü³LÛ@häEÛ[ƬQò°ÂaJöê–RêréÉryïx‡P8ϱ 2:€èN®d½½·ÓíêêM‘&2@,I'TY‰ ’Hh’Ó¼=¯Yiþ·“ìS6›5ÅÁk¦"a2"G¶Ô˜qµya@ü½mô?hÓîaû<>dLžEÁÄräµÎÊz¡éUäִȾźú ·Øû3+nYÆÆÒYn„º å”ôËx+ÃÓh÷bçHÒ,nnYd–M6BVVÁÙå DQ€ª7u$’Å™ºš( Š( Š( Š( Š( Š( Š( Š( ¾G×?ä?©×Ô¿ú¯®+ä}sþCú—ý}Kÿ¡èÃîÌêMø+þD}þ¼bÿÐEn×/áçhþØ:1W])J²œ|¾¢³­Òê[h¤mSPË c‹ƒÜVø™kc¹¢¸¯&çþ‚šþ<›Ÿú j?øjn;Z+Šònè)¨ÿàA£É¹ÿ ¦£ÿ‹…ÎÖŠâ¼›Ÿú j?øhònè)¨ÿàA¢ásµ¢¸¯&çþ‚šþ<›Ÿú j?øh¸\íh®+ɹÿ ¦£ÿ&çþ‚šþ.;Z+Šònè)¨ÿàA£É¹ÿ ¦£ÿ‹…ÎÖŠâ¼›Ÿú j?øhònè)¨ÿàA¢ásµ¢¸¯&çþ‚šþµ§XMwjºVÎJÜð ô¢árÕ¯‡&ƒS€´èl-/'Ô-ÀÍ3MæïW=6/!äîPq°™#Ž×^Õ4û{½JÒÊÏVÓïåžÖçi!•1$j¶‚7G#rÁÚÅzÇZ?ðÃÿA}kÿGøTgE·)ö¾·¹£iûHƨ=¿Ú­1˜ïà©–ÖîÚ+ÔdÕ {mMÙ!^I¥f„dí9¸•@bØ ‡'aY; Ëÿ„~ú ë_ø?°ïbê3YÛêZ¶` ½¤¹êXg€§ùãŠ⼛Ÿú j?øhònè)¨ÿàA¥q\íh®+ɹÿ ¦£ÿ&çþ‚šþ.;Z+Šònè)¨ÿàA£É¹ÿ ¦£ÿ‹…ÎÖŠâ¼›Ÿú j?øhònè)¨ÿàA¢ásµ¢¸¯&çþ‚šþ<›Ÿú j?øh¸\íh®+ɹÿ ¦£ÿ&çþ‚šþ.;Z+Šònè)¨ÿàA£É¹ÿ ¦£ÿ‹…ÎÖŠâ¼›Ÿú j?øhònè)¨ÿàA¢ásµ¯‘õÏùê_õõ/þ„kë akaùÓL΂Fy¤.ÄŸ¯ojù?\ÿþ¥ÿ_RÿèFºpû³:‡Ñúü’ëû¯þ‹ª–ñãoÿ\×ùV…`ûWí*ßvß7MDÝŒã)ŒÖÄ:V Ä-™‚(]Í!ÉÀÆN+ üLÑls”WG ®“p…à…%@Ì…’bÀ2’¬8=AØ‚(’×I‰âI!Dy›djÓ]°[žNŽ`Oj›ŽrŠèÅ®’×n°¡™]ãʬHRFr*Ø=öŸJ“û;NÿŸOüˆßãE‚Ç1EtÿÙÚwüúäFÿ?³´ïùôÿÈþ4X,sWOý§ϧþDoñ£û;NÿŸOüˆßãE‚Ç1Etf×I[„·hPLêΑ™ŽæU 19 \žÛ‡­Gzš›h÷w [hñ¾iî "äàe‰ÀäøÑ`±ElZ]øbþÐÝÙÜÙ\[ V47ÓÌbMÀãq, ¿0õ«ÿÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜­ þBðÀ¿ôZÿÙÚwüúäFÿrYXÄÛ£¶dl¹e`FFxëE‚ĵU¿ä1ýzÍÿ¡ÅTG‡ü6×n¶HfEWxÅËîUbB’7dU°{í>”ét/YÛO4Ö«ºÆZg{§U>bX–Æ3Ï¥1šÕÈ]ÈÉ©ÿÛ/ýµäðÿ†âx’K$G™¶F­rà»`¶ÍɱÀì íV­ô=×w“a·v3ûç9üÍsôWOý§ϧþDoñ£û;NÿŸOüˆßãJ±ÌQ]?övÿ>Ÿù¿Æìí;þ}?ò# ÅÑÍk¤Û yáH² g˜¨,Ä*ŽORHw$ “û;NÿŸOüˆßãE‚Ç1EjiÚ—„õ{†·Ó/´ëÙ•w´v×ÂF 2B±8ÉûŠ¿®“uoż),2¨xäŽbÊêFAGz,9Ê+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,&‹þ<íë‚*ù#\ÿþ¥ÿ_RÿèF¾¹;v¢¢íTP g< ù\ÿþ¥ÿ_RÿèFºpû³:›Mø+þD}þ¼bÿÐE>ãJ¼Wº¸}gWº…–CýŸ·Œ0 áÂ#©ùO˜ eºÓ<ÿ">‡ÿ^1è"·k|LÑlqzú‡<©ð¥ìrYËsqkcAûÔ’i$DA¶6«(#Ê¥O®hÚ†¯,“Eoµµ µC3¨“J1s2à[%Ès¾¹ÇÏ[EHÎZÏB½‡^ŠGT åÅã߆ýåÒL, :á?vI·‡éSEQEU KO¹¾ò¾Ï¬^éÛ3»ì© y™Ç_27éŽØêsž1~Šä¥ðö ucûÏ´y·V·CT•”Mª­ÕïâO»µqq>@ÀI©Iâ bÀé™±¼­¦­så´r‡ˆ°eÈ+Àq´ð )ݳ©¢€8xt]U‚\ͧ½Ýš4ñ[é:¥Ð•ãŽXãMòHLˆe›»‘ìÈò[¥ZMa¤YYÜ]=ÜÖðG—2gt̪s’NIêzõ«tPEPETÔu];H·[NþÖÊm‹%ÌË–Á8ˆÀ<{‘/­$ŠÖTº£»ÇÙÙdM•.6âùAn;h³Ð¯a×¢‘ÕAyqx÷á¿yt“ ¸O݃’F-áÆzD4Ú–¿¦[_É¢ÝYÉa¨¼¦Ý:n»H÷ªCÎJÈ»¸ßá‚í’ºšŽ ặŽâÞT–T-î¡°ýþ°Åvy‘…_œ-¹²OsÈÆï˜®õç–>ÖœºTI{¥½ªC4zâMáŽHŠF›8XŒqË- ,ŠYä·A²¸µŠö{ˆþÏöÛ¦¹KLƒö`Ê ®G˹™ZFÛÆù–ûÍ­EQEQEQEQEò>¹ÿ!ýKþ¾¥ÿÐ}q_#ëŸòÔ¿ëê_ý×FvgPúoÁ_ò#èõãþ‚+v°¼ÿ">‡ÿ^1è"·k|Lµ°QE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€0|]äÚ< c§Ï{*ßÚLÑÂñ© é+»(è„z‘Û$dÛéÚÅŒ¾xì¯OüM/no¤TŠ ÚfU•L]•¥Œ¡ñå¾ÒxÝÚTrO OI*#ÌÛ#V` ¶ `zœ+ÀžÔÉÙXë2x·Qk˜uìÛ…’#,÷F=ªz¼«†ð‘L’ûßBËG×4Ï.‹m§] ­Ö^C¨»É#(Þ&B±åWjù±p_*0ûú€ßZ InÍÔÚþlÆA±6stJsÓ=(ÏìôoM¥_Oyq¨Ç}œFݪ+\¬·&"àHÙ"3!Ý•³ó—+‘¦úˆÍÞ¡öo¶Å©?Ú¼­B[ÐlŠ0³¨€–Ã.aÉòÓ”s¹²D„“ÃÄ’Jˆó6ÈÕ˜í‚Ø§ ǰ'µxZáíÖT3"«¼a†åV$)#¨«`÷Ú}(šðU†³eovÚ¬·JŽÊ"¶¹Ë2çn'$6Tcxa!FâOSEQEQEQEQEQEQEQEWÈúçü‡õ/úú—ÿB5õÅ|®ÈRÿ¯©ô#]}ÙCé¿È¡ÿ׌_ú­Úæ|7+ÁðÓNš6Û$zZ2œgG‘T¡¾Ö¥‚9?µq½CcìéÆEa?‰–¶;:+ûVµÿAoü–J>Õ­Ð[ÿ%’¦ás¯¢¹µk_ôÿÉd£íZ×ý¿òY(¸\ëè®CíZ×ý¿òY(ûVµÿAoü–J.:ú+ûVµÿAoü–J>Õ­Ð[ÿ%’‹…ξŠä>Õ­Ð[ÿ%’µk_ôÿÉd¢ás¯¢¹µk_ôÿÉd£íZ×ý¿òY(¸\ëè®CíZ×ý¿òY(ûVµÿAoü–J.:úå¼G¡^ê7—-n© ½³[8ævÃiΟÏNä“°ü¸;á‹·Ï?jÖ¿è-ÿ’ÉSÙjòò;í›óó}•0 þ”\.Z¾¸Ô5K½c@ŠÎ÷OŒØ~ãXR»<É/Èܸ±àçoÊ[$h€™u$ÓൊÞ[wþÅ‚E1Ïä$‰¸*nùã)¸-¡ÜPñAý—ªÿÐÉÿ’+þ4çêbe‹þ_”¸a^€€O_ö‡çLg7'„u4²{QäJ×v­m«üºA3<¡¡ÈÉT ®Ð‡6Ðp æ-+= öz)P$—~÷—I0`°0ë„ýØ9$bÞg¤Z¿Ùz¯ý Ÿù"¿ãY7sêV÷²ZÅ®´ÒDý.yßæ?ªŠä>Õ­Ð[ÿ%’µk_ôÿÉd¥q\ëè®CíZ×ý¿òY(ûVµÿAoü–J.:ú+ûVµÿAoü–J>Õ­Ð[ÿ%’‹…ξŠä>Õ­Ð[ÿ%’µk_ôÿÉd¢ás¯¢¹µk_ôÿÉd£íZ×ý¿òY(¸\ëè®CíZ×ý¿òY(ûVµÿAoü–J.:ú+ûVµÿAoü–J>Õ­Ð[ÿ%’‹…ξŠä>Õ­Ð[ÿ%’µk_ôÿÉd¢ás¯¯‘õÏùê_õõ/þ„kë §ŽÆst×ȡ˔ ŒöŸå_'ëŸòÔ¿ëê_ý×NvECèýþIuý‚WÿEÕK?øñ·ÿ®küªÿ† kŸ†úeº]1KtÉÖ¥¾ƒe ´Q4· ÈK  \v¬'ñ2–ÆÐÿbØ~çó_ð£ûÃû÷?šÿ…M‡cž¢ºì[ïÜþkþbØ~çó_ð¢Ácž¢ºì[ïÜþkþbØ~çó_ð¢Ácž¢ºì[ïÜþkþbØ~çó_ð¢Ácž¢ºì[ïÜþkþbØ~çó_ð¢Ácž¢ºì[ïÜþkþbØ~çó_ð¢Ácž¢ºì[ïÜþkþbØ~çó_ð¢Ácž­ þBðÀ¿ôZ?ضß¹ü×ü*H4ËKiD±Kr²B·ÊqFz{Ñ`±fª·ü† ÿ¯Y¿ô8ª¯ü#ðÿÐ_ZÿÀ‘þ/‡àRÌ5]\±]›ŒêH‚@8ã•=)ŒÔ®BëþFMOþÙè·ÿü?ôÖ¿ð$…xrÂdÜßË$˜ÜÒȬN:sŠÅ¢ºì[ïÜþkþbØ~çó_ð¥aX種‡ûÃû÷?šÿ…ضß¹ü×ü(°X種‡ûÃû÷?šÿ…ضß¹ü×ü(°X種‡ûÃû÷?šÿ…ضß¹ü×ü(°X種‡ûÃû÷?šÿ…ضß¹ü×ü(°X種‡ûÃû÷?šÿ…ضß¹ü×ü(°X種‡ûÃû÷?šÿ…ضß¹ü×ü(°X種‡ûÃû÷?šÿ…ضß¹ü×ü(°X¹üyÚÿ×þUòF¹ÿ!ýKþ¾¥ÿÐ}s„TŽ4ݵ Ý׊ù\ÿþ¥ÿ_RÿèFºpû³:›Mø+þD}þ¼bÿÐE>â-r7ºš}VÕlÈÁ-4Çk”\»XÈáœpÕØÆÞiž ÿ‘Cÿ¯¿ô[µŒ¾&h¶8kv~ðN§sqi«¬:t÷w ³Ù\ ^'¸•Ѓ*‚ä©’xÎ\ŽMXñŽ¡p.,âºs=šd8Vìwd¹2̧FÒŸx•%LfM’vTŒáçÓ¼@÷×ÙìöúÁk¢ú„§6ï,‚ÕÁ£Ž6åLsþ·2³û>ïÊ‘¢°½‹Ã¢XÞ›>džl,¢rXº—0›åÊ@“Ì̽Ý™ C{ z84…VGÞév1£¶NçXÊ+¶H'su:tQ@5õmÕtË«[i·ežæÙ§R¸<WBqÎ{9ã–Ö¬5é%ýóý®õ­Bi—q´1ZÞnreu.ÛWa’\IS½Ù'iEsZåõ¾·ˆ|' W¿mþËbζÇa«ª„f*ŒÜt,ägå}¼Ö›¤ù\}LÝ¢4°É¨,z?Øe¹]³ !Xv+¼HÆ wS"n”’‡Ò¨ }3ÄÕVtº’é eÑÜK¼ØOæJQ§`y" ³’àˆæ\±—éXÙjiâe‘ãœ\‹©Þòíîg³!þÏöܤÇÀ©II#Í̽mQEW%â{-NãP‘­£žIÕSI’#…³¼Ëî–OEÚS’mIS¼Ù'[E`ßk{w¬xJ3Á¬ÁaçCq5»ä #;Ê•8eÉàç2U‚ágÝùR4V±xtK»Óg̓ͅ”N@ËRæÀ1ó|¹Hy™—»¢€8 ôÏUYÒêK¦—Gq.óa?™)FäˆL*ÎK‚#™rÆ\K¥ce©§‰–GŽqr.§{˶?¹žÌ‡û‡ÿ^1è"·k|Lµ°QE# (¢€ (¢€ (¢€ ÌÔuý7J¸X.æu}¾c”…äXS$o•”pß3>Vçå8Ó¬Û Z~}GKOö»Xmd7R:ýŸËiX8USæçÎ?.äûƒæù² pjv·Þ¿Ú­7•&P÷m!ˆÃµ†Tœ ò*xfYк3'ÎŒ‡*Jž„`Œ‚ dÛXê1øËQÔ$ŠÔXOg¼l³±—tm#d¦À>sýÁýï—’›Âú¤Z‡¥>›§·sqöh$‘í„Ì‚7!¢'•÷Jò2¬ BèôVf§M¥hÐÚNÈ]ZG %!Vve‰ ä@ÁÂŽ äõ_j7ÃTŽÓ£šåo?âd]¾Ñt³G*¤€™¡‘0w¿&q´´Õ5;]L¸ÔoÒÖÝwÊéHU{ª ÀêN8'VëÔ¼%ršgˆ¬tdµŽONKhã–gQçŸ5ešFÚÅœ«Ç–9g)†#ƒTâ9 Ò¬›N°g…Œd´¹ã~"~\•›øÂG¹yþ­?ßÇüA×µí+GKo ÛC6©qI®¡‰m×ûûda¸ú I醩¢ëÚžµ6‚ukd³¿S0¹·Šé&Œ°‡RŒØ'ò9õ:ž)Ö|'áˆà¼ñX–äíYÍ›L ÷K*êÇCˆt}wÃ:°°»Ðm„±ÝI"EsöSùæ#r‚zíÈãï ä@%Q@Q@Q@Q@Q@|®ÈRÿ¯©ô#_\WÈúçü‡õ/úú—ÿB5чݙÔ>›ðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­ÚÆ_-lQEHŠ( Š( Š( Š¡«kz¢]_Ö'•!S ¼“ìp£¤òpHH«W¶ú…¢]Zɾ'Î H à«ʰ ‚¤ €EOEPE@÷¶ñêØ´˜¹š)&0yD(ç§DüýO@STÔít}2ãQ¾wK[uß+¤M!Uîv¨'©8àdžO$ËÄŒ™[bíF` r@ÂŒÉÀÎR’Š( Š‚ÎöÞþšÚO25–HIÁ¨·úsÍ „6¶*ÉVŠÊJí0ÀãŠÞ[Kk[ÅöñB ùh<ûWŸøÏž/²ñ-µ¿†ôËK‹ iw]¼ú„›Ž1¨/”?xŒî ïô¬½AQIXZ%ñÔu}Nã/µ£·Ú"¹å$®T•à“œ3žMnÐEPEPEPEP_#ëŸòÔ¿ëê_ý××ò>¹ÿ!ýKþ¾¥ÿÐta÷fu¦üÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v±—ÄË[QR0¢Š(¢Š(¢Š(Å:Ž£¥C™¬“%åµÃ ™Ú%Û«.Tc’P/NäöÁæ®|¨Ë†]:y®Vb“Jí»IšYæ•¥¶; weýÑ>BŒüý™â-:m_ö™nȳ^YÍoHHPÎ…A8ã'Ò¹ëÿ8»”Ø[ÙK¦Ÿ"GÓn¤o*òU¬1*û˜ù¾öÌЮz¥ÃÍÚMúZißÙ¬ñ¨¹Œ²Z¬“ còÎܰƒwN }+­Õm&¿Ò/líîžÒkˆ$Š;˜óºe 8Á œõ:Õº(‹“ÃǺöŸe¤èº\º©¶ŽÖÒwÊÊÒ±¨Ý‡è#ÉØbÙ§ªéšþ«á­A,´ï:Âv–åžá·F¯Féyya—ÝÎÌùk3•èh Ã^¾‹YmJX ·UÕ/ç3ââHšY•`*ÜyD²Ì`¤òd™Câ]&m^ÎÚ8ᵺHgÉexÅ`º]Œ»íneq•oš5àuTPœGà R-?ì²¶y3¬ÉÜÒI¿Nwžĩ±‰PœºœÂ¿;}á~ËÁZŽ«ÿiÚ^ÚÃ3Þ\Í"ìb»dk¦à‚ä™mw.Wþ=—æ;WÅæ¶ÞÖ"ðωt§ƒK1êV±ÅkleO&9A}Ò‘´jnŒ‚±1Œ°ÀÆÖ³á+jãSÔ%KT¿›IŠÞË÷ÎËkv¦fóAÚ9S"m.ñó`.H=…¨éŸÚúóZ‰¼™Ö+ˆ¤+¸,‘\$‰¹r2»‘rŒ€AänhºlÖ"öæí£7š…ÇÚ®"Lq·–‘„B@$cÇ' Q[I´oÕ“oÙü¤ýì“üª÷Úfôõ N3xƒ8ùGO­q:ÿ‹¾ø_Tm7Yhí.ÕCìm9Ø2ž…XFC£ õu»/1šu‘ñÇ/Ö¹SF¿Õõ K˽?Dš[Ìö(‘šÈÛªG±h|¦mà°H`v8 ’01Zu•¥XßA}}w|ÖæKŸ/ØAÿ Õ Š( Š( Š( Š( ¾G×?ä?©×Ô¿ú¯®+ä}sþCú—ý}Kÿ¡èÃîÌêMø+þD}þ¼bÿÐEnÖ‚¿äGÐÿëÆ/ýVíc/‰–¶ (¢¤aEPEPEPEP\ü:†·{ur–‹§ˆâ¹xš'¯ÜWAQY[Cb%ò£RÒÊÓ;7$³þ‡áXb#ZQJ‹IÝo®F­Ô£â+ûÂú®£•%Í•”Ó®å!Ñ Œç3øÖ-¯‰®­-¡›P3ßµÝ×Ù-aµÑg³“̼œ¬òT…Æîäà½5ýœÕ•Ü~eµÔoÉ’7#dr8'¥PµðÞi43)½šHeó¢7WóÜl}Ž™c¶>Y{äz n#3Qñö‘¥XÙÞ^І•$ó&…‰¶J ´¤*Ùˆ>qÆr¹“Fñ_Û®~Ëwi8î„>{\«ÙŒ©+gs$¥÷¡9lía퟼ÙÖ‚··Ž.R5¦GgbÇ,Ä–>ä’{Ðmž¼—ºƒA …é¶ódo¶)…䌲ºðÅ× Ž72ª’¸î]Ù‰â+Ûê:Íâ$×V-xŽm`ùH†i#Þ#y@ ¸®üœqZÐèl™Ô#…ÄÛšES3˜‘Û;"'b9Ëe•A;Û'ælÀžÒA»ÑwMavÎóÆ÷³39s—ùËîŽIàîlýãõ_Úi:…Ť¶—²ý–Õ/nfŠ0c†dÙ‰wË$¨Ë~Ul6 Ú_j j¶—±#ÝOeı…ŽIâ/¹Ç剨66àcpl¨dÞÓnµw¾»:}Ž 4ä}Û#i +¾ìÊæ Èù °ÝÙúG…4ý*æK½¾mÛÝ\\ïË*†–GmÛ2WÌ þ_™ÅF2>-EÒlîç±½’{Ëùìb¶ŠóHÚo‘€‘—þX•/»n~cµs¶;¯YÛØÜ]C¦ê7BÒ¸¾ŽkEF‘>ù1 £ä-÷b¤éØxkKÓb‚;x§+ot÷‘®¥”¬®¬®Ùv'‘#ätËŒœÖF½à[Mf²d¶RyÞb\Ù ‰"ižI °1HÅÉÉÞTÂŒÀmQ@Q@Q@Q@Q@Q@|®ÈRÿ¯©ô#_\WÈúçü‡õ/úú—ÿB5чݙÔ>›ðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­ÚÆ_-lQEHŠ( Š( Š( Š( Š( Š(  |´wI‚Fq¶“dó×ÿ4Mÿ,ÿÜI²?ùëÿŽš6Gÿ=ñÓ\’xºh5»»MNÊÖÖÆdz[µ¼-ó ´îudP‰åg'qà `š­¿Œ´8¢Wžæ{vyD+ ŤÑJÎÊÌ FÈîòÜ.ÌÊTe¸ ‹dó×ÿ4lþzÿ㦰dñf‹Dítåw³-¼Œ PJ“6÷ pL›pQÁÆÖÆÕ,Ío2M$ûcK1ØN5¼ésmÄa‚JÔ0ÁÁªú¿üo¿ëÞOýѤÈÇþ½ãÿÐE\¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¯‘õÏùê_õõ/þ„këŠù\ÿþ¥ÿ_RÿèFº0û³:‡Ó~ ÿ‘Cÿ¯¿ô[µ…à¯ùô?úñ‹ÿA»XËâe­‚Š(©QEQEQEQEQEQE$ßòÏýÁQÕ ûmNæà=¶¨¶± #Êÿ‰$Õoìíkþƒßù&Ÿã@¤ðMÕíü×÷—·°^Ë$Ïk+"Æ®ðù©DWâ, Ëyoš§·ð´ê6ú•Ö¡{{}«"Ï?–¤ªÇ**ˆ«´yòž™ËrHTßÙÚ×ý¿òM?Æìíkþƒßù&Ÿã@W?´+»è®æÍ‘e’IöðN%W™æ(|ÈÛj†•ÇÉ´y'޶±ÿ³µ¯úäšÙÚ×ý¿òM?Æ€.jÿò¾ÿ¯y?ôF‘ÿ [ú÷ÿAŸ6‘«Ï É®îŽE*Ãìˆ2ÁïZÖ}–Ê }Û¼¨Õ7cÀÆhj(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ù\ÿþ¥ÿ_RÿèF¾¸¯‘õÏùê_õõ/þ„k£»3¨v÷ø øTžP£ÊVB#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ ê<¦é7züšÔk+[ .YU˜°©$m ž3ÅiÞxFÏK´ÒüØ–à^x†h®D‡ÙÉáŒ{dspk)U„eÊÑj «œ'œŸóáaÿ€±ÿ…rÏ…‡þÇþÚx¦-C¿h Ñ´iÖ+¿(ó#Î˃ÃÇÕ;gÐàw©57H—RÐ4[ ;Iõ{[{—»û\Žm÷·Ì¡IÃpÉÇZ•ZÎÁÈûœ?œŸóáaÿ€±ÿ…rÏ…‡þÇþÙ_i–s[ë«¥øNF´ÒÚxQmH ‘\Äx+ŸAÓ§_Ù¿ç–?½ÇSG2½¬v¹ êw:k‹ëà³¼¶%ãšQX{È<‚TzŒ{m.ÏûÿÌÑSR1oaÅ´]µBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ_xCA½ðv•wu§ù³=œ,ÍçH¹%G£VÇü!~ÿ OþLÉÿÅVOõ[©ÊÇ‹ùp­ªF–áeS̰ úëýi¾W°¯jÿ„/Ãô ÿÉ™?øª?á ðÇýòfOþ*”q4ã¢LnœžçŠù^Â+ØWµÂáúÿäÌŸüUð…øcþ?ù3'ÿUõ¸v²gŠù^Â+ØWµÂáúÿäÌŸüUð…øcþ?ù3'ÿGÖáØ=“·Áì™â¾W°£Êöí_ð…øcþ?ù3'ÿGü!~ÿ OþLÉÿÅQõ¸vdÏò½…W°¯jÿ„/Ãô ÿÉ™?øª?á ðÇýòfOþ*­Ã°{&x¯•ì(ò½…{Wü!~ÿ OþLÉÿÅQÿ_†?èÿ“2ñT}nƒÙ3Å|¯aG•ì+Ú¿á ðÇýòfOþ*øBü1ÿ@Ÿü™“ÿŠ£ëpìÉž+å{ <¯a^Õÿ_†?èÿ“2ñTÂáúÿäÌŸüU[‡`öLñ_+ØQå{ ö¯øBü1ÿ@Ÿü™“ÿŠ£þ¿ Ð'ÿ&dÿâ¨úÜ;²gŠù^Â+ØWµÂáúÿäÌŸüUð…øcþ?ù3'ÿGÖáØ=“·Áì™â¾W°£Êöí_ð…øcþ?ù3'ÿGü!~ÿ OþLÉÿÅQõ¸vdÏò½…W°¯jÿ„/Ãô ÿÉ™?øª?á ðÇýòfOþ*­Ã°{&x¯•ì(ò½…{Wü!~ÿ OþLÉÿÅQÿ_†?èÿ“2ñT}nƒÙ3Å|¯aG•ì+Ú¿á ðÇýòfOþ*øBü1ÿ@Ÿü™“ÿŠ£ëpìÉž+å{ <¯a^Õÿ_†?èÿ“2ñTÂáúÿäÌŸüU[‡`öLñ_+ØQå{ ö¯øBü1ÿ@Ÿü™“ÿŠ£þ¿ Ð'ÿ&dÿâ¨úÜ;²gŠù^Â+ØWµÂáúÿäÌŸüUð…øcþ?ù3'ÿGÖáØ=“·Áì™â¾W°£Êöí_ð…øcþ?ù3'ÿGü!~ÿ OþLÉÿÅQõ¸vdÏ´½ºÓ¡¾KU„›ËY-$2©8GêFçŽ?•Lºæ¬º^¦î¶{m*é.à2#ܙ“œùϽz×ü!~ÿ OþLÉÿÅQÿ_†?èÿ“2ñU¯JNí BK©äZ®­y¬¼>—¢[Ë,¾l—¶Ì²¹÷bǯzeXÝÈÑDö±Û[´ †UŽIù³é¥{ü!~ÿ OþLÉÿÅQÿ_†?èÿ“2ñT•zK 8Iõ<®÷ÄúÕä±}&9/¡k{«¸íJÏ*0ÁÉÇ|S.uûû›kI´ ámmVÖç¶v• 6üg¿Nµêÿð…øcþ?ù3'ÿGü!~ÿ OþLÉÿÅRö´{–}Ï'·×õ‹}gNÕ#keŸO²K(€FÚñ®~øÏ9ÏlvéY®&¸»»»¸òüû«‰.$‚3±byÆM{Wü!~ÿ OþLÉÿÅQÿ_†?èÿ“2ñUJ½$îœ$úž+å{ <¯a^Õÿ_†?èÿ“2ñTÂáúÿäÌŸüU_ÖáØ^Éž+å{ <¯a^Õÿ_†?èÿ“2ñTÂáúÿäÌŸüU[‡`öLñ_+ØQå{ ö¯øBü1ÿ@Ÿü™“ÿŠ£þ¿ Ð'ÿ&dÿâ¨úÜ;²gŠù^Â+ØWµÂáúÿäÌŸüUð…øcþ?ù3'ÿGÖáØ=“·Áì™â¾W°£Êöí_ð…øcþ?ù3'ÿGü!~ÿ OþLÉÿÅQõ¸vdÏò½…W°¯jÿ„/Ãô ÿÉ™?øª?á ðÇýòfOþ*­Ã°{&x¯•ì(ò½…{Wü!~ÿ OþLÉÿÅQÿ_†?èÿ“2ñT}nƒÙ3Å|¯aG•ì+Ú¿á ðÇýòfOþ*øBü1ÿ@Ÿü™“ÿŠ£ëpìÉž+å{ <¯a^Õÿ_†?èÿ“2ñTÂáúÿäÌŸüU[‡`öLñ_+ØQå{ ö¯øBü1ÿ@Ÿü™“ÿŠ£þ¿ Ð'ÿ&dÿâ¨úÜ;²gŠù^Â+ØWµÂáúÿäÌŸüUð…øcþ?ù3'ÿGÖáØ=“·Áì™â¾W°£Êöí_ð…øcþ?ù3'ÿGü!~ÿ OþLÉÿÅQõ¸vdÏò½…W°¯jÿ„/Ãô ÿÉ™?øª?á ðÇýòfOþ*­Ã°{&x¯•ì(ò½…{Wü!~ÿ OþLÉÿÅQÿ_†?èÿ“2ñT}nƒÙ3Å|¯aG•ì+Ú¿á ðÇýòfOþ*øBü1ÿ@Ÿü™“ÿŠ£ëpìÉž+å{ <¯a^Õÿ_†?èÿ“2ñTÂáúÿäÌŸüU[‡`öLñ_+ØQå{ ö¯øBü1ÿ@Ÿü™“ÿŠ£þ¿ Ð'ÿ&dÿâ¨úÜ;²gŠù^Â+ØWµÂáúÿäÌŸüUð…øcþ?ù3'ÿGÖáØ=“S0Á!Xä~5%³G²³†ÎGîzãë^Çÿ_†?èÿ“2ñTÂáúÿäÌŸüU Ml‡ìäxȳӂíS:¨à$ Ã4·+ [Ç íNÁ0:ײÿÂáúÿäÌŸüUð…øcþ?ù3'ÿBÄS]ÙÈòûϲ©/Ü›¤ÐŠÜµÀ™—ip’+×ÿá ðÇýòfOþ*øBü1ÿ@Ÿü™“ÿŠ£ë0ìÎG…j«ÿë·«}Íé-Ðt8ô/-¶˜°½²²?Ÿ#Ì Ï-N>¿Vª*š¢\w;ÿȃ¤׌ú«Zæ¥ý j:§•ç}ŠÖ[+vÝû¶3ƒŒãÁª¾ÿ‘Hÿ¯?ôVµËí]QÓ±ŸµÚË<͙ܥ~öÖÛ×®ÓCÒ¸%ñ3¡lbÛø¸·‡u=js¤Ikf¤‰4Ûù/Sp!ÊC”*I Ø’ëj:œÖ®j¶É$:„ïnò™J´L"yT…ÚC#`yã¯j7V:ψ4Ëí'X¶µÓìîàhž}>üÍ.\I¨Ky#·<‹wš½›GšMRõdÓ%óQïßaBdù;«8ùvýóŒ`bF>MŸS:|s9›sF¬aqºçr$¤lwlª±#cd|­:ç´ÿéoˆ§Ö …>Ñ+I o )#œ»‰6y¹9n ÐÐMWQ‡HÒ/u;…v†Î .$XÀ,U±$ àzÕ­ÜØ[»ë¶Ihû•aR½ßžH'j(d.– !yÉÃm¿ªÚ.¡¤^Ù< p—IC$ÈHÚYA*q Eqpx}Qîÿá"µµy®9úÜEq)xÃ"µH˜’A¹•#ûªT¥“Åš,IµÓ”uÞ̶ò0A*LØ_Ü€UÁ2mÁG[^-Ð¥¸šíàiRC:4J¦"Áþf6Iƒœ*Lgcâ£ø#Mû"ÚA4ö–Ïj,îá¶ŽÒî Xíuá2d”“ÃûÃÏ ‚_h—¼øç“Ì–i%̤y«/Úr‡¶MŒ`ò2N(Ô,·ÔžÚÊ(­n¥ºŽx§‘™÷Ç"°Ù|ÍÎÈß¼hÃË|½mP×5/ìmQÕ<¯;ìV²Üy[¶ïØ¥±œgÎ dÅã}.]Bò瘭â•ÖÞV’Y$2ƒÄ{2y-¸H!Ã1¶5µËí]QÓ±ŸµÚË<͙ܥ~öÖÛ×®ÓCÒ¹«ß Üx›PžoiÖVêñB#{{Áu±â2í>T¶áVyA-»øp€òx—K–[X¡–y¤¸ÆYd1åŠ~ô*Ÿ+æVSæmÁGî¶+é+Óõ[™-7yWiuqm³ ÊZ)vïÀ_0ªyž^w9ÁÕKé— ¦EçqrUcm¹(ಕ5§7ˆlí®õxîÊ‹KµK«‡1É•FIfp‡”-È`@#’Ãö:lº{Ú¯—öYm£HãHÑ„;E ´`ü ™¸çŠ÷ÞƒP»Ö&ŸP½1ê¶`šòÂG C³váæHy$|çŽh¯nó%ÓÈ•U#·‘ä›p%Z$ ºT!\‡@ÊB1…$Fþ3Ð#•c’ÿc4BR^E,ÊC¸V97+`¨ŽBÀb(x»Â ®o¹†Ö «·ò-ÔÊ‘Æ"ó°À42«7ïÝpÊF#A¨,ü iu¥ÍoªXÁg#Z‹4[ ÁE]“¡” j$oµM‘°¯ @W,Ñm^égºtKe‘¤˜ÛÉå,‘RM»]Ô+å–”⦡ã}.ÓNûe·Ÿx¿j·€¬Vò’VY T%£#qW«•Ú¬Iªòü:Ð¥»Õ.<½­¨ÅõÔe’8Ù£‘pQ™OÈBÈ Qʺ•¬ð:éZ¦P[¡:]ofñá8ò­™åwxÏúÆ9 _µÐu ¸´©uK¹í®tÛ¦¸Aov·"á™J–‘¤…HÈyÔ 7ËŒ(P oí‹1«f9ž;“÷ –ò$r»¶¤…B;mÉÚ¤œ+qòœG êsjúWÚ®-’Úež{y"ŽS"†ŠWˆÅTJg ëY«à5|Yˆ„Óý®9ZP¦8NY£d Éåù¥pÇ \€@ZŽ4;-Vúêð<òÜ.D{ƒHÅØ Š£™Oâ=°Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@·ˆ|s§xrãT·¼’Ö9­4å½·Žk¥®Ø™G–€Œç1F~øã×ZMŸS:|s9›sF¬aqºçr$¤lwlª±#cd|­ŒŸèºõƨ¶vV³ÃªiËapój "ƒ/ÜQŒâcÉ>œqÌšOƒ4Ý?[}sìÐG}6ù^5ŠRÉÌŒ“„Ç$¸ù›b6€$µñmªhÐ_k,ešò{Š6iÃÍÊ»P„‹yLTm’HjÊößP´K«Y7ÄùÁ ©`yVT€A®fOJ–Úe¬:½ë­¶©6 ÷:$ÈÒG6vl@§÷²îÚÀ‚ •ùk¢Ó4èt»µ…Àg‘ä‚ÒHì]Üà–fc€à@‹?äã_úõ‹ÿ@¢ÈÆ¿õëþEuaþcSsoÂw_døu¤Iä\N~ÇÁv?(ì?­ZþÜúëø ÿפðüˆº/ýyAÿ ŠÞi‚±[ƒ¾kž_5[_Ûÿ@]cÿúôn?ýuüÿëÖçž?ºß÷Ù£ÏÝoûìÔŒÃþÜúëø ÿ×£ûqÿè ¬à/ÿ^·<ñýÖÿ¾Íxþëßf€0ÿ·þ€ºÇþÿõèþÜúëø ÿ×­Ï<u¿ï³TuMU¬’ÔGZâæ82Î~PÇ“ïÀ  ?Ûÿ@]cÿúôn?ýuüÿëÖóH.CTï4ß<u¿ï³@Ûÿ@]cÿúôn?ýuüÿëÖçž?ºß÷Ù£ÏÝoûìÐöãÿÐXÿÀ_þ½Ûÿ@]cÿúõ¹çî·ýöhóÇ÷[þû4‡ý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½nyãû­ÿ}š<ñýÖÿ¾Íaÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯[žxþëßf<u¿ï³@Ûÿ@]cÿúôn?ýuüÿëÖçž?ºß÷Ù£ÏÝoûìÐöãÿÐXÿÀ_þ½Ûÿ@]cÿúõ¹çî·ýöjŽ©ªµ’ZˆâË\\ÇYÏÊò}øGûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÞiÈbJƒæ›çî·ýöhûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÜóÇ÷[þû4yãû­ÿ}šÃþÜúëø ÿ×£ûqÿè ¬à/ÿ^·<ñýÖÿ¾Íxþëßf€0ÿ·þ€ºÇþÿõèþÜúëø ÿ×­k»áke=Ç”ÍåFÏ·Ì#8ÅEcw-Õ…µÃ¶X•ÈRp ñ@ßÛÿ@]cÿúôn?ýuüÿëÖǘÿßoÎ1ÿ¾ßcÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯[cÿ}¿:<Çþû~tý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½lyýöüèóûíùÐ?öãÿÐXÿÀ_þ½Ûÿ@]cÿúõ±æ?÷Ûó£Ìï·ç@ÿÛÿ@]cÿúôn?ýuüÿëÖǘÿßoÎ1ÿ¾ßcÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯[cÿ}¿:<Çþû~tý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½lyýöüèóûíùÐ?öãÿÐXÿÀ_þ½Ûÿ@]cÿúõ±æ?÷Ûó£Ìï·ç@ÿÛÿ@]cÿúôn?ýuüÿëÖǘÿßoÎ1ÿ¾ßcÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯[cÿ}¿:<Çþû~tý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½lyýöüèóûíùÐ?öãÿÐXÿÀ_þ½Ûÿ@]cÿúõ±æ?÷Ûó£Ìï·ç@ÿÛÿ@]cÿúôn?ýuüÿëÖǘÿßoÎ1ÿ¾ßcÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯[cÿ}¿:<Çþû~tý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½lyýöüèóûíùÐ?öãÿÐXÿÀ_þ½Ûÿ@]cÿúõ±æ?÷Ûó£Ìï·ç@ÿÛÿ@]cÿúôn?ýuüÿëÖǘÿßoÎ1ÿ¾ßcÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯[cÿ}¿:<Çþû~tý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½lyýöüéñ34 b>¦€1?·þ€ºÇþÿõèþÜúëø ÿ×­Ï<u¿ï³Gž?ºß÷Ù  ?íÇÿ .±ÿ€¿ýz?·þ€ºÇþÿõësÏÝoûìÑçî·ýöhûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÜóÇ÷[þû4yãû­ÿ}šÃþÜúëø ÿ×£ûqÿè ¬à/ÿ^·<ñýÖÿ¾Íxþëßf€0ÿ·þ€ºÇþÿõèþÜúëø ÿ×­Ï<u¿ï³Gž?ºß÷Ù  ?íÇÿ .±ÿ€¿ýz?·þ€ºÇþÿõësÏÝoûìÑçî·ýöhûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ»¾¶SÜyLÞTlû|Â3œQ§Ý5Εou(ùåEbˆ•ŠÉþÜúëø ÿ×£ûqÿè ¬à/ÿ^·<ñýÖÿ¾Íxþëßf€0ÿ·þ€ºÇþÿõèþÜúëø ÿ×­Ï<u¿ï³Gž?ºß÷Ù  ?íÇÿ .±ÿ€¿ýz?·þ€ºÇþÿõësÏÝoûìÑçî·ýöhûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÜóÇ÷[þû4yãû­ÿ}šÃþÜúëø ÿ×£ûqÿè ¬à/ÿ^·<ñýÖÿ¾ÍRÒµ&Ôd¾,›Þw…T99 $û’h‡öãÿÐXÿÀ_þ½Ûÿ@]cÿúõ¹çî·ýöhóÇ÷[þû4‡ý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½nyãû­ÿ}š<ñýÖÿ¾Íaÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯[žxþëßf<u¿ï³@Ûÿ@]cÿúôn?ýuüÿëÖçž?ºß÷Ù¨nï…­”÷S7•>ß0ŒàgÁx—ΗÃ>/»’ÒæÚ9­S`¸Œ¡8R ÏÝÍ}áoO3eŸO€ÉÂæ=Ä ô'󢺰ÿ 1©¹ÔøþD]þ¼àÿÐElÉþ±þ¦±¼ÿ".‹ÿ^pè"¶dÿXÿS\òø™ªØÊñ£6‘á[S·Ti¬ìæ¸d©dBÀq‘ëXV:ôö)M ïßW†v‰VêSxœ­Ùu>R*¦Ón0,Ù'²b𾃥ŜZ=’Y\mó­+ä9SÆ/¹»8ù±“µrNщ™mâ†ÔßB¸´D67ÚÝ¡–+…`â!>Æ! Œ!-Ã)o,3™4mcS›ÄzÝž¢,£´Šÿìöd\þðŸ³Å @žXÎT»“¸r0Bî­it=&ymå›K²’KiZhíИ¤fÞΤ•‹|ÄŽIæ¬}†ÓûCíÿeƒí¾W“ö,yž^s³w]¹ç3@Ö?ˆ?æÿa¿­lV?ˆ?æÿa¿­nMÿ,ÿÜI7ü³ÿpTtß¶œ’ë:–©uä™õ×OK5x™-L¼#…$+ïÈoœl’߯ú”Íooÿäâîâémã f†#º)d|ÐÆÇo’w‡ ÀÇ䮦=+N‹S—SŽÂÕ/æ]’],*%uã‚øÉ*ðOaéQÙhzN›Ec¥ÙZǦdX-ÑÈWapá¶’¹ëƒŠå§ø…$s,úÕÔЫ5äp$Ò•+4°•ˆÇ% “aˆ·‘–Û¯§øŽêðÜ\Üi‰k¥[Ïs—’]¯ËäÈêd*@2®w8Û´o­)t=&ymå›K²’KiZhíИ¤fÞΤ•‹|ÄŽIæ­Ã6èR’$,ÎU(,ij;’I'¹$Ð qãm^ïO–;=5-u+{Ë‘gi£F†yü±ƒ-º¶IVSò`ܰÛWõ?Iay¥¾”ú„ÑÀ³^ :p„»¡HÌq0g ‹‰ C r>m»¶žÐì-îmìôm:Ú¥Ùq6¨‹2àŒ8 0OÔúÔ’hzLßbót»'û>ǺÝÙñŒy||˜Ú½1ÐzP)½¸Ó|!­_ZIåÜÛXO4O€vºÆÄ u®jóÆZ¶—­ÝÛÞé¼x­#´´‰Þaæ7ÚŒŽZ(™ö‘ÆŽs…íç‚«y-î"Ia•JIŠ]HÁ#µAw¥iÚ‚L—¶·):¢J³B®$T%”6G H¡$Ð:Þ1ºHtÛ‰´Yím§ÏÚ§»YãX¹Vn!$(¾é„ ©S‘ó„4OjÜÇý¦`¸Õ/lmî¼ÅÜÍ“², ÄqÜNâË÷H;ÎÓøwC’âÒáôm9¦³TKiÕ @¨r2¡O@:v«‹chž^ÛXÊ•¦²Fݹǣï“Ôî>¦€'¬Ì/þÂZجÌ/þÂZÜ›þYÿ¸*:’oùgþà¨èƒTÕÓ^a%ËÈ“ÏqokòMŒÌ‚B±«¦gŽ@#;ÙÃ()(”Äzе9¼/¡¨,®5½F(<¨ÅÞÕpð4¾l¤G˜÷¥ÀUa8É^¦=+N‹S—SŽÂÕ/æ]’],*%uã‚øÉ*ðOaéQ¾‡¤Éiuhú]“[]Êf¸…­Ð¤Ò w\a› žxË?Ä&Y®ãZ§Ù½íæo‘M43—néhr¤… n1œÜVHðÖ’5»k(ËŠÞ8!hÇd1´k•‡šÃ# ï­@õùß×¼Ÿú £Hÿ-ý{Çÿ Š5ùß×¼Ÿú £Hÿ-ý{Çÿ Š¹EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPRAþ¹åQÔ®_ÇùP/‰/n,tpö²yrÍuml$–xâ, änÉd ‚8<ìþ0“Hs¦[µÖ·|“Í4ösDñˆÄEƒù01c™«,j…Hç#/ÚO7Vò[ÜD’Ã*”’92º‘‚<Gj¡'‡t9tÈ´É4m9ì!mñÚµª‘¹ä&0ÌÜÜúÐL~/šgY×Jx¬{k[ƒs!Žæ)§_+i>0ĸ#çÀ;Fì›O‰Ë6˜.gÒ9žäŠ(eiwû>Õ8MØÅå¿*¬sæ§jïí$Ò´éu8µ9,-^þÙÓB¦T^xŒó7÷>´+Nkt·k S @Ö©…v¬,hÀÆ«•èvJä¤ñN¿xtF±ÒRÞIµ-n"¼y`I@¶’EØd€>Î2[bÑí©-Zö^#ºÔõ[¨´ý1.tëYã‰ïRíx²EŠñ®0À 2Ù#åÁRäí_ØzOöOöOö]—öoüùý<Ÿ½»îcoÞç§^jÜpCÊñĈó6ùT퀹>§ £'°µsÚ/Œmõ­CO±Ž —3Ø=ÕÒ-öIPÄ;@ó”î2íQ¸WKY6 YjòKûÛÉ#‰ ·N­äFÅK(!C>v'Í!vùG<¶u¨§ Ô„ÓhÎEE.­¥C+Ä÷VªèÅX5Àê3Tu?iöštÓÚÉk<êÈÄà䓎€äã9ü*ì7þöŸ÷åÂì7þöŸ÷å€ _þ@·ßõï'þ‚jM#þEËúåþ€*=_þ@·ßõï'þ‚jM#þEËúåþ€(Ås^!MFïPŽËFÖïm/ž LpÇÃdþú]ñ³sÈT 7•ÀÀëÒÖf£áÝW¸[OFÓ¯fUز\Ú¤Œ$àã$ñîhïÆß`Škû­?þ%+-ÜËÛ§i-ÖV“1• ýž\䟓 díƒUñÍÞ‚Í¥¤@.bÛ4ËmxdAnb¸²³F¤É‹YÂ9_œdã©JÓ¢ÔåÔã°µKù—d—K ‰]xà¾2GʼØzTvZ“¦Ä‘XévV±Ç)™ t@²Ø\8m¤®zà†RþÕӅɋɑe– P6à²E#FûNWr#ÐsZ‹çºñ46̳ùW7÷:x…¬¤Xâò¸‘g+²Fo%² ð@ÁËöÁ º‚$‰ 3•E 1,ÇŽä’IîI4ű´O/m¬ åJÓGˆÀÙ#nÜãÑŽ÷ÉêwS@”º–©Ã-nøjsÿhXÿhyWf8·Ÿ"iBn]›9XÀ8Qß<×iY‘øwC‹L—LFÓ’Âfß%ªÚ ‰ÛŽJcü«É‡¥_‚mmã··‰"†% q¨UE8Ô%eøgþcõý7ô­JËðÏüÆ?ëúoé@•‹â ›¤—I±µº{S¨^w¸‰U¤DË•ÞrL@r§‚zµP^ØÚjVi}kÕ´˜ß ñ‡FÁÈÊž €9+ßO£Ü¦› ¼úì¶ñy—3ÛA#3/™"Q n†Qå8`Æ%Ü8Ú nÛÅw·7 ‹¤$qOyu§ÚÉ%ßúÙá3HvÆD-órÁ¸ØFíI¡é3}‹ÍÒìŸìûët?gÆ1åñòcjôÇAéVÆÑ<½¶°/•+M#d»sF;ß'©Ü}Mqv5¾¶ðf‹u¨[Au«ßEoåÃo#È\<- –EŽé¸E/Ž\g+zËźž£sö{_OæEkÌë<ÞCdš2¨®¡‹'rn˜ÇÀ;Ï¡é2Z]Z>—dÖ×r™®!kt)4„‚]×fÈ'žX·±´´ÇÙ­`‡lIò£ ˆÓ;á]ÍÐdã­OTõùß×¼Ÿú «•OWÿ-÷ý{Éÿ šàõoù|Oÿ`ÛoýE·ü‰¾'ÿ°m·þŠ¢º°ÿ 1©¹ÓxRKÄø{¢‹€ÎlàÁœ < š¤þ½–F’K]-݉ffšà’ORNkKÁ_ò#èõãþ‚+xNÉ®y|LÕlq¿ðŠÝÿÏ–“ÿgÿ?á»ÿŸ-'þþÏþ5ÙùoýÆü¨òßûùTŒã?á»ÿŸ-'þþÏþ4Â+wÿ>ZOýýŸük³òßûùQå¿÷ò 3þ[¿ùòÒïìÿãO‡ÃWÐMÑÚi+$lO™9Á#½v[ÿq¿*<·þã~TÊ^蚦£qçÝÁ¥Ë&Р™g°àUøEnÿçËIÿ¿³ÿv~[ÿq¿*<·þã~TÆÂ+wÿ>ZOýýŸühÿ„Vïþ|´Ÿûû?ø×gå¿÷ò£Ëî7å@gü"·óå¤ÿßÙÿÆøEnÿçËIÿ¿³ÿv~[ÿq¿*<·þã~TÆÂ+wÿ>ZOýýŸühÿ„Vïþ|´Ÿûû?ø×gå¿÷ò£Ëî7å@gü"·óå¤ÿßÙÿÆøEnÿçËIÿ¿³ÿv~[ÿq¿*<·þã~TÆÂ+wÿ>ZOýýŸühÿ„Vïþ|´Ÿûû?ø×gå¿÷ò£Ëî7å@gü"·óå¤ÿßÙÿÆŸ†¯ š9£´ÒVHØ2Ÿ2s‚Gzì<·þã~TyoýÆü¨”½Ñ5MFãÏ»ƒK–M¡A2Î0`ÀªÿðŠÝÿÏ–“ÿgÿìü·þã~TyoýÆü¨Œÿ„Vïþ|´Ÿûû?øÑÿ­ßüùi?÷öñ®ÏËî7åG–ÿÜoÊ€8ÏøEnÿçËIÿ¿³ÿðŠÝÿÏ–“ÿgÿìü·þã~TyoýÆü¨Œÿ„Vïþ|´Ÿûû?øÖ¬1x†c†5ÒV8Ô*ŒÊpÀ­ï-ÿ¸ß•[ÿq¿*ÅÿŠ—þ¡?ùø©êÿ‘+kËî7åG–ÿÜoÊ€1â¥ÿ¨OþD£þ*_ú„ÿäJÚòßûùQå¿÷ò  _ø©êÿ‘(ÿŠ—þ¡?ù¶¼·þã~TyoýÆü¨þ*_ú„ÿäJ?â¥ÿ¨OþD­¯-ÿ¸ß•[ÿq¿*ÅÿŠ—þ¡?ùø©êÿ‘+kËî7åG–ÿÜoÊ€1â¥ÿ¨OþD£þ*_ú„ÿäJÚòßûùQå¿÷ò  _ø©êÿ‘(ÿŠ—þ¡?ù¶¼·þã~TyoýÆü¨þ*_ú„ÿäJ?â¥ÿ¨OþD­¯-ÿ¸ß•[ÿq¿*ÅÿŠ—þ¡?ùø©êÿ‘+kËî7åG–ÿÜoÊ€1â¥ÿ¨OþD£þ*_ú„ÿäJÚòßûùQå¿÷ò  _ø©êÿ‘(ÿŠ—þ¡?ù¶¼·þã~TyoýÆü¨þ*_ú„ÿäJ?â¥ÿ¨OþD­¯-ÿ¸ß•[ÿq¿*ÅÿŠ—þ¡?ùø©êÿ‘+kËî7åG–ÿÜoÊ€1â¥ÿ¨OþD£þ*_ú„ÿäJÚòßûùQå¿÷ò  _ø©êÿ‘(ÿŠ—þ¡?ù¶¼·þã~TyoýÆü¨þ*_ú„ÿäJ?â¥ÿ¨OþD­¯-ÿ¸ß•[ÿq¿*ÅÿŠ—þ¡?ùø©êÿ‘+kËî7åG–ÿÜoÊ€1â¥ÿ¨OþD£þ*_ú„ÿäJÚòßûùQå¿÷ò  _ø©êÿ‘)x••—:XÜÊ™AçÐŽEmùoýÆü¨òßûùPÿ­ßüùi?÷öñ£þ[¿ùòÒïìÿã]Ÿ–ÿÜoÊ-ÿ¸ß•qŸðŠÝÿÏ–“ÿgÿ?á»ÿŸ-'þþÏþ5ÙùoýÆü¨òßûùPÿ­ßüùi?÷öñ£þ[¿ùòÒïìÿã]Ÿ–ÿÜoÊ-ÿ¸ß•qŸðŠÝÿÏ–“ÿgÿ?á»ÿŸ-'þþÏþ5ÙùoýÆü¨òßûùPÿ­ßüùi?÷öñ£þ[¿ùòÒïìÿã]Ÿ–ÿÜoÊ-ÿ¸ß•qŸðŠÝÿÏ–“ÿgÿ?á»ÿŸ-'þþÏþ5ÙùoýÆü¨òßûùPÿ­ßüùi?÷öñ«—:N±wi¤ñimòãó&``t<ñëïë]?–ÿÜoÊ-ÿ¸ß•qŸðŠÝÿÏ–“ÿgÿ?á»ÿŸ-'þþÏþ5ÙùoýÆü¨òßûùPÿ­ßüùi?÷öñ£þ[¿ùòÒïìÿã]Ÿ–ÿÜoÊ-ÿ¸ß•qŸðŠÝÿÏ–“ÿgÿ?á»ÿŸ-'þþÏþ5ÙùoýÆü¨òßûùPÿ­ßüùi?÷öñ£þ[¿ùòÒïìÿã]Ÿ–ÿÜoÊ-ÿ¸ß•qŸðŠÝÿÏ–“ÿgÿ¹“¬[XËe ZZ[ÍŸ1VI¾lã<ç=…tþ[ÿq¿*<·þã~TÆÂ+wÿ>ZOýýŸühÿ„Vïþ|´Ÿûû?ø×gå¿÷ò£Ëî7å@gü"·óå¤ÿßÙÿÆøEnÿçËIÿ¿³ÿv~[ÿq¿*<·þã~TÆÂ+wÿ>ZOýýŸühÿ„Vïþ|´Ÿûû?ø×gå¿÷ò£Ëî7å@gü"·óå¤ÿßÙÿÆøEnÿçËIÿ¿³ÿv~[ÿq¿*B8#Þ€8?é—V ñ,·_gmšª,ˆP‹·ø¹éZ+cÇßò!kõêÔWVáf57&ðWüˆúýxÅÿ Šè`ÿ\¿ò®{Á_ò#èõãþ‚+¡ƒýrþ?ʹåñ3U±vŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU)ÿ×7áüªíRŸýs~Ê€9È…­ÿ׫QG¿äBÖÿëÕ¨®¬?ÂÌjnMà¯ùô?úñ‹ÿAÐÁþ¹å\÷‚¿äGÐÿëÆ/ýWCúåü•sËâf«bíQR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªSÿ®oÃùUÚ¥?úæü?•s>ÿ‘ [ÿ¯V¢È…­ÿ׫Q]X…˜ÔÜ›Á_ò#èõãþ‚+¡ƒýrþ?ʹïÈ¡ÿ׌_ú®†õËøÿ*ç—ÄÍVÅÚ(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT§ÿ\߇ò«µJõÍø*æ<}ÿ"·ÿ^­E>ÿ‘ [ÿ¯V¢º°ÿ 1©¹7‚¿äGÐÿëÆ/ýWCúåü•sÞ ÿ‘Cÿ¯¿ô] ë—ñþUÏ/‰š­‹´QEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Oþ¹¿åWj”ÿë›ðþTÌxûþD-oþ½ZŠ<}ÿ"·ÿ^­EuaþcSroÈ¡ÿ׌_ú®†õËøÿ*ç¼ÿ">‡ÿ^1è"º?×/ãü«ž_5[h¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@RŸýs~Ê®Õ)ÿ×7áü¨˜ñ÷üˆZßýzµxûþD-oþ½ZŠêÃü,ƦäÞ ÿ‘Cÿ¯¿ô] ë—ñþUÏx+þD}þ¼bÿÐEt0®_ÇùW<¾&j¶.ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¥?úæü?•]ªSÿ®oÃùP1ãïùµ¿úõj(ñ÷üˆZßýzµÕ‡øYMɼÿ">‡ÿ^1è"º?×/ãü«žðWüˆúýxÅÿ Šè`ÿ\¿ò®y|LÕl]¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEJõÍø*»T§ÿ\߇ò cÇßò!kõêÔQãïùµ¿úõj+«ð³›“x+þD}þ¼bÿÐEt0®_ÇùW=à¯ùô?úñ‹ÿAÐÁþ¹å\òø™ªØ»ETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*”ÿë›ðþUv©Oþ¹¿å@Ç¿äBÖÿëÕ¨£Çßò!kõêÔWVáf57&ðWüˆúýxÅÿ Šè`ÿ\¿ò®{Á_ò#èõãþ‚+¡ƒýrþ?ʹåñ3U±vŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU)ÿ×7áüªíRŸýs~Ê€9È…­ÿ׫QG¿äBÖÿëÕ¨®¬?ÂÌjnMà¯ùô?úñ‹ÿAÐÁþ¹å\÷‚¿äGÐÿëÆ/ýWCúåü•sËâf«bíQR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªSÿ®oÃùUÚ¥?úæü?•s>ÿ‘ [ÿ¯V¢È…­ÿ׫Q]X…˜ÔÜ›Á_ò#èõãþ‚+¡ƒýrþ?ʹïÈ¡ÿ׌_ú®†õËøÿ*ç—ÄÍVÅÚ(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT§ÿ\߇ò«µJõÍø*æ<}ÿ"·ÿ^­E>ÿ‘ [ÿ¯V¢º°ÿ 1©¹7‚¿äGÐÿëÆ/ýWCúåü•sÞ ÿ‘Cÿ¯¿ô] ë—ñþUÏ/‰š­‹´QEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Oþ¹¿åWj”ÿë›ðþTÌxûþD-oþ½ZŠ<}ÿ"·ÿ^­EuaþcSroÈ¡ÿ׌_ú®†õËøÿ*ç¼ÿ">‡ÿ^1è"º?×/ãü«ž_5[h¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@RŸýs~Ê®Õ)ÿ×7áü¨˜ñ÷üˆZßýzµxûþD-oþ½ZŠêÃü,ƦäÞ ÿ‘Cÿ¯¿ô] ë—ñþUÏx+þD}þ¼bÿÐEt0®_ÇùW<¾&j¶.ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¥?úæü?•]ªSÿ®oÃùP1ãïùµ¿úõj(ñ÷üˆZßýzµÕ‡øYMɼÿ">‡ÿ^1è"º?×/ãü«žðWüˆúýxÅÿ Šè`ÿ\¿ò®y|LÕl]¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEJõÍø*»T§ÿ\߇ò cÇßò!kõêÔQãïùµ¿úõj+«ð³›“x+þD}þ¼bÿÐEt0®_ÇùW=à¯ùô?úñ‹ÿAÐÁþ¹å\òø™ªØ»ETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*”ÿë›ðþUv©Oþ¹¿å@Ç¿äBÖÿëÕ¨£Çßò!kõêÔWVáf57&ðWüˆúýxÅÿ Šè`ÿ\¿ò®{Á_ò#èõãþ‚+¡ƒýrþ?ʹåñ3U±vŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU)ÿ×7áüªíRŸýs~Ê€9È…­ÿ׫QG¿äBÖÿëÕ¨®¬?ÂÌjnMà¯ùô?úñ‹ÿAÐÁþ¹å\÷‚¿äGÐÿëÆ/ýWCúåü•sËâf«bíQR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªSÿ®oÃùUÚ¥?úæü?•s>ÿ‘ [ÿ¯V¢È…­ÿ׫Q]X…˜ÔÜ›Á_ò#èõãþ‚+¡ƒýrþ?ʹïÈ¡ÿ׌_ú®†õËøÿ*ç—ÄÍVÅÚ(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT§ÿ\߇ò«µJõÍø*æ<}ÿ"·ÿ^­E>ÿ‘ [ÿ¯V¢º°ÿ 1©¹7‚¿äGÐÿëÆ/ýWCúåü•sÞ ÿ‘Cÿ¯¿ô] ë—ñþUÏ/‰š­‹´QEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Oþ¹¿åWj”ÿë›ðþTÌxûþD-oþ½ZŠ<}ÿ"·ÿ^­EuaþcSroÈ¡ÿ׌_ú®†õËøÿ*ç¼ÿ">‡ÿ^1è"º?×/ãü«ž_5[h¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@RŸýs~Ê®Õ)ÿ×7áü¨˜ñ÷üˆZßýzµxûþD-oþ½ZŠêÃü,ƦäÞ ÿ‘Cÿ¯¿ô] ë—ñþUÏx+þD}þ¼bÿÐEt0®_ÇùW<¾&j¶.ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¥?úæü?•]ªSÿ®oÃùP1ãïùµ¿úõj(ñ÷üˆZßýzµÕ‡øYMɼÿ">‡ÿ^1è"º?×/ãü«žðWüˆúýxÅÿ Šè`ÿ\¿ò®y|LÕl]¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEJõÍø*»T§ÿ\߇ò cÇßò!kõêÔQãïùµ¿úõj+«ð³›“x+þD}þ¼bÿÐEt0®_ÇùW=à¯ùô?úñ‹ÿAÐÁþ¹å\òø™ªØ»ETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*”ÿë›ðþUv©Oþ¹¿å@Ç¿äBÖÿëÕ¨£Çßò!kõêÔWVáf57&ðWüˆúýxÅÿ Šè`ÿ\¿ò®{Á_ò#èõãþ‚+¡ƒýrþ?ʹåñ3U±vŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU)ÿ×7áüªíRŸýs~Ê€9È…­ÿ׫QG¿äBÖÿëÕ¨®¬?ÂÌjnMà¯ùô?úñ‹ÿAÐÁþ¹å\÷‚¿äGÐÿëÆ/ýWCúåü•sËâf«bíQR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ªSÿ®oÃùUÚ¥?úæü?•s>ÿ‘ [ÿ¯V¢È…­ÿ׫Q]X…˜ÔÜ›Á_ò#èõãþ‚+¡ƒýrþ?ʹïÈ¡ÿ׌_ú®†õËøÿ*ç—ÄÍVÅÚ(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT§ÿ\߇ò«µJõÍø*æ<}ÿ"·ÿ^­E>ÿ‘ [ÿ¯V¢º°ÿ 1©¹7‚¿äGÐÿëÆ/ýWCúåü•sÞ ÿ‘Cÿ¯¿ô] ë—ñþUÏ/‰š­‹´QEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ©Oþ¹¿åWj”ÿë›ðþTÌxûþD-oþ½ZŠ<}ÿ"·ÿ^­EuaþcSroÈ¡ÿ׌_ú®†õËøÿ*ç¼ÿ">‡ÿ^1è"º?×/ãü«ž_5[h¢Š‘…Q@‡â»–·Òaòo#·¸{Ûo%áak’³#´X€]ÑB’Î &©èzŽ£}ã-aom'±…tû'†ÒiÕÙs%Èf`„¢±*>ë6UP“Ÿ•@:Š(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ¥?úæü?•]ªSÿ®oÃùP1ãïùµ¿úõj(ñ÷üˆZßýzµÕ‡øYMɼÿ">‡ÿ^1è"º?×/ãü«žðWüˆúýxÅÿ Šè`ÿ\¿ò®y|LÕl]¢Š*FQEs~)‚­OÂö÷G4êr¤‘È¡•ÔÙ]<G­7IÓtkv·ÒôûKË´v°¬J[d…g û Ãñ{ÞG¨xY¬ ‚{¡ª¾Èç˜Äþ‡sœ°V#Œÿ ôã­\ðÖ±©kVóÜÞiÖ–ÖÛÀµšÚñ§[•Ç.»£B<)þ,>R¬À”Q\þ§âìÍb-!ì÷êÙþËA.ëjƒ&æÇîör[ åpW{€ ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢¹KKR³ñ֢Ѭ—Zlm›Ïmf‘7Kr ±¨8b Êæm$¨GÃÓ¼q}eáïYçϩß>‹gys4¢åóæ!î† ‰bcrwmí‚Üíôz+º×¼A7ˆtHô½6k{¥MvöºÃ[H®œ« “’ÍœmŸÄ~/þÀÔcµû,˜„ØšëÉ’ç$*Õ6Ÿ>o—”ÊòñŒüüuW!­øÊûJÔbÓaѾÓ|-#¹¹ ö™#ye ­ ¼„óòÊœcä,ãÄÚ¥ö¢¶Z^ƒ™Ÿm~çQ¹û7”%2-Ô#°y}#ïd©pQESÒu(uÇT·Y Ëxî#Y Ô0Œàúšã>#x­4ý;WÒ!Ö`Ò/#ÒžífyÖ9¦,$Ç'ïŒîaÊ‚¡Fç €ýÃuoż±Í¨9#`ÊêFApAæ¹ IÖoüS,–ö—sÙ›(5Éì IÍædBK!¡ÆSSó Ÿ¡]ÛêÓ/lÄâÖâÒ)a^@Œ€®ö$’Ø#$““ÜÖ…QEJõÍø*»T§ÿ\߇ò cÇßò!kõêÔQãïùµ¿úõj+«ð³›“x+þD}þ¼bÿÐEt0®_ÇùW=à¯ùô?úñ‹ÿAÐÁþ¹å\òø™ªØ»ETŒ(¢Šçü_á?é1i×·—Ö‘Ç)”Ie(ÎcxÙI*~R²0#¾}+?Lð-Ö‘æý›Ç+“ÍÆïµÜÁsŒgóam½{cÏ4'qbÀ\¶î®ŠÇºðÝ•ÿ‘%Ü×ÍuKÝAy%¬“ÓÌ0 Éb0 6É«–ºUÃOkmmâµÄ*ˆ£.QŽctý…\¢€+ØXÛéšuµ…œ~]­¬K )¸¨ <œ:Ñco©é×6‘ù–·Q43&â7#dr2 éV(  ½SA´Õïô«Ë‰nÒM2àÜB!¸xÕ˜¡\8 0ßÌ}Ö`Æ¥áý?T¸[‰þ×á-/f¶gPIŒN¥€%ˆ œnlc':”PpA ­¼VöñG  HãBª(ÀqŠ’Š(¢Š(ªSÿ®oÃùUÚ¥?úæü?•s>ÿ‘ [ÿ¯V¢È…­ÿ׫Q]X…˜ÔÜ›Á_ò#èõãþ‚+¡ƒýrþ?ʹïÈ¡ÿ׌_ú®†õËøÿ*ç—ÄÍVÅÚ(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT§ÿ\߇ò«µJõÍø*æ<}ÿ"·ÿ^­E>ÿ‘ [ÿ¯V¢º°ÿ 1©¹7‚¿äGÐÿëÆ/ýWCúåü•sÞ ÿ‘Cÿ¯¿ô[èÅ0ê=kž_5[誟iE£í/èµ#-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝSí/è´}¥ý€-ÑU>Òþ‹GÚ_ÑhÝRŸýs~Êö—ôZØ»=Ms^>ÿ‘ [ÿ¯V¢È…­ÿ׫Q]X…˜ÔÜ›Á_ò#èõãþ‚+v¹¯ ^Ûé¿4Ëë¹<»km1&•ðNÔXòN'€zV¶›¬Yê¾h¶3¬‘c|WòA"ƒœ6É[iÃØÁ*À9åñ3U±~ŠŽI–'‰92¶ÅÚŒÀä…“œ¤%HŠ‚ÆößRÓí¯­$ó-®bY¢|¹#‚:Óäžž$’TG™¶F¬ÀlÀõ8V8=¨J(ª‘ê–RêréÉryïx‡P8ϱ 2:€èN®@-ÑEQY7þ$Ó´Ý@ØÌ/d¹X–fK[ î6£ I ”n¾†­Á©ÚÜjwztnÿj´XÞTh™@WÝ´†# ÖRpTƒÈ  tQEQPXÞÛêZ}µõ¤žeµÌK4O‚7#AÁäpGZžŠŽIá‰âI%Dy›djÌvÁlS…cØÚ¤ Š©©e.§.œ—(ב.÷ˆuŒû!#¨„à:æÝQYšŽ¿¦éW Üί·Ìr¼‹ dò²‚"NærÊÜü§tQP^ÞÛéöuu&È“ $“€ª,Ä€I$ 4=•í¾¡h—V²o‰ó‚AR8*Àò¬ ©‚ T,üI§_ê el/d‘e’'Ø'¸óJl૽Ô`PµSLÔíu{¼³whY?yFÁ‘Š0*à0!”ŒÚ­ÐEåí½„+5Ìž\m,pƒ‚~yQ¬Ê?hz(¨ÄðµÃÛ¬¨fEWxà ʬHRGP VÁï´úP”QU4íRËV·iì.Rx•¶O\? °=YXdHº(¢€ *„zΟ/Ùö\gíRÙÅò7Í,~fõéÆ<©9<¼‘›ôQQÉ<1Š+žµðäÐjp …¥äú…¸ù¦i¼Ýêç¦Åó¤#Ê6'CEQErZ¶…ªÉâó¬Ù[ÁqÙ`‰Qõ{‹<^6š¶í<R}¨Ì£€‹y£I£X € D’£gÄIó| Þü=Ô®î­w^'Ùbi#‰c‘¬b7:4ૈÞ5 [|•ˆ WÑè >ÓÁKÄ3ɬ’ɨÞË|ÎYüëIŒå`ä}ÌÉøMÊÍÉäÐ_ÞÛx5t,4.&‰G—'”. .ÖžPÐÈŽï„ýÛFáHݼ°R½ýÇÏ ^ãÂ).‹¤j§OûÙÜùcA bb0ƒ…PYT„LƒaEÏZørh58 N†ÂÒò}BÜ|Ó4ÞnõsÓbùÒŽNå “¡¢Š+šñ‰©_êÜi¦%1ÅØ»š `IWdL¥ÊÙÉ´d‰:Z(€Öü®j:tº]¼ÚrÙ¬ú…ÄrHÏæH×Q\€ „×þ-ÃæùHÚÚÚ·‚l.t¡g§£Ú–¼µ¹”Çw4~g—*³»l´Œ»¾sóIÊ©^¦ŠŽVÞÞ8¹HÔ"™ˆ³Xû’Iï\·‡´-WGÖn¤–Þ¶¸ºº”Ì5{†ÂI+ȸ¶dòÕ¹PH#¹ÉÉ­¢€8K¯ ëz‡„ÿ³® ”S®©=ëAâHn#–Ic™ eùZ\ó‚bR6’ ÓŸáÍëÛ³A|‘ÝG§$ï#îd” ¦Æ’M¦Õû:aAU#Ñè 8½ø{©]_kÓÄ/{âÁpdEi ÊÊ‘Ja€3+Ý! 0tõ?ÛÝ-ìZÙ5“ýŽâ{€\Is ®ò¼„ƒóJ…#iæ#9 ŒÒŠáõ/ j·—š4ñZi½Š®Â4VØ|ªÇÀÜ 7Fð³ã˜Mºöz\Ñx÷SÔÛEÓ¢†k8cMJ9 ¸™mÈËŒÞsÑS–éCETÕtèu}"÷L¸gXo ’ÞFŒ€Á]J’2Î¥TÒ´Û¸u ½KQ–½¸Š+r-Ô¬b8‹•8bNæ2;œU~m¥ÛZŠ(¢Šá'ø~òD²ÛMž¤×÷÷}mñ¤ër¨ÉÓ÷ƒÎ‡wLùJ7‰T ømxÚjÛ´ðYIö£0XZ6Ž-æ&b‚%Jœg'Íò€=*ŠâäðÝÜ2øv#£éz„v:¥Ì¢i¥*lmÙ¤h„Coð©BôÀtí(¢€ (¢€9ísÓjw¾Lé:¥šé÷ÛÁ,°ƒ! 8߉d_›#æVþŽûë]OY»Ö4këH"Ð.l<˜îáŸ÷ìîdJà`N>öâzŠÉÒ´Û¸u ½KQ–½¸Š+r-Ô¬b8‹•8bNæ2;œU~m¥ÛZŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(œñ÷üˆZßýzµxûþD-oþ½ZŠêÃü,Ʀçˆë~/ñƒ¯êZF™ªÜ[ØXÝËom ˆãG*«“’pš£ÿ Åßô¹ü—ü(¢µQVØ–ØÂÅñwýn%ÿ ?ábø»þƒ·?’ÿ…Såas0ÿ…‹âïúÜþKþÂÅñwýn%ÿ (£–=ƒ™‡ü,_Ðvçò_ð£þ/‹¿è;sù/øQE±ìÌ?ábø»þƒ·?’ÿ…ð±|]ÿAÛŸÉŠ(å`æaÿ Åßô¹ü—ü(ÿ…‹âïúÜþKþQG,{3øX¾.ÿ íÏä¿áGü,_Ðvçò_ð¢Š9cØ9˜ÂÅñwýn%ÿ ?ábø»þƒ·?’ÿ…QËÁÌÃþ/‹¿è;sù/øQÿ Åßô¹ü—ü(¢ŽXöfð±|]ÿAÛŸÉÂøX¾.ÿ íÏä¿áErǰs0ÿ…‹âïúÜþKþÂÅñwýn%ÿ (£–=ƒ™‡ü,_Ðvçò_ð£þ/‹¿è;sù/øQE±ìÌ?ábø»þƒ·?’ÿ…ð±|]ÿAÛŸÉŠ(å`æaÿ Åßô¹ü—ü(ÿ…‹âïúÜþKþQG,{3øX¾.ÿ íÏä¿áGü,_Ðvçò_ð¢Š9cØ9˜ÂÅñwýn%ÿ ?ábø»þƒ·?’ÿ…QËÁÌÃþ/‹¿è;sù/øQÿ Åßô¹ü—ü(¢ŽXöfð±|]ÿAÛŸÉÂøX¾.ÿ íÏä¿áErǰs0ÿ…‹âïúÜþKþÂÅñwýn%ÿ (£–=ƒ™‡ü,_Ðvçò_ð£þ/‹¿è;sù/øQE±ìÌ?ábø»þƒ·?’ÿ…ð±|]ÿAÛŸÉŠ(å`æaÿ Åßô¹ü—ü(ÿ…‹âïúÜþKþQG,{3øX¾.ÿ íÏä¿áGü,_Ðvçò_ð¢Š9cØ9˜ÂÅñwýn%ÿ ?ábø»þƒ·?’ÿ…QËÁÌÃþ/‹¿è;sù/øQÿ Åßô¹ü—ü(¢ŽXöfð±|]ÿAÛŸÉÂøX¾.ÿ íÏä¿áErǰs0ÿ…‹âïúÜþKþÂÅñwýn%ÿ (£–=ƒ™‡ü,_Ðvçò_ð£þ/‹¿è;sù/øQE±ìÌ?ábø»þƒ·?’ÿ…ð±|]ÿAÛŸÉŠ(å`æaÿ Åßô¹ü—ü(ÿ…‹âïúÜþKþQG,{3øX¾.ÿ íÏä¿áGü,_Ðvçò_ð¢Š9cØ9˜ÂÅñwýn%ÿ ?ábø»þƒ·?’ÿ…QËÁÌÃþ/‹¿è;sù/øQÿ Åßô¹ü—ü(¢ŽXöfð±|]ÿAÛŸÉÂøX¾.ÿ íÏä¿áErǰs0ÿ…‹âïúÜþKþÂÅñwýn%ÿ (£–=ƒ™‡ü,_Ðvçò_ð£þ/‹¿è;sù/øQE±ìÌ?ábø»þƒ·?’ÿ…ð±|]ÿAÛŸÉŠ(å`æaÿ Åßô¹ü—ü(ÿ…‹âïúÜþKþQG,{3øX¾.ÿ íÏä¿áGü,_Ðvçò_ð¢Š9cØ9˜ÂÅñwýn%ÿ ?ábø»þƒ·?’ÿ…QËÁÌÃþ/‹¿è;sù/øQÿ Åßô¹ü—ü(¢ŽXöfð±|]ÿAÛŸÉÂøX¾.ÿ íÏä¿áErǰs0ÿ…‹âïúÜþKþÂÅñwýn%ÿ (£–=ƒ™‡ü,_Ðvçò_ð£þ/‹¿è;sù/øQE±ìÌ?ábø»þƒ·?’ÿ…ð±|]ÿAÛŸÉŠ(å`æaÿ Åßô¹ü—ü(ÿ…‹âïúÜþKþQG,{3øX¾.ÿ íÏä¿áGü,_Ðvçò_ð¢Š9cØ9˜ÂÅñwýn%ÿ ?ábø»þƒ·?’ÿ…QËÁÌÃþ/‹¿è;sù/øQÿ Åßô¹ü—ü(¢ŽXöfð±|]ÿAÛŸÉÂøX¾.ÿ íÏä¿áErǰs2îâíÄö›£êº¤÷:}õÜ6÷0±I8 2# ö9¢Š+ž³åk—CXk¹ÿÙnetgen-6.2.1905/doc/pictures/menufile.jpg0000644000175000017500000007152513504650527016724 0ustar kurtkurtÿØÿàJFIFa[ÿÛCÿÛCÿÀ†¿"ÿÄ ÿÄQ   67UWw…˜µ¶× %&g—¥§Øç'Õ$8V#(Xe")5:fEHIrtvy†ÇÿÄÿÄ'ð!2Qq‘±¡Ñá"1AaÿÚ ?Û!ùùu!uµ]]·…ƒÀzY½úº²ßûÙ·w¸¿K{wsÿos‹ó~—èðþnG£Å‚rŠ3«»pß`vüâýdyÑ7}ÉðP¾.ò.ý6p7ãàùøÏ‚¾§ñ±<Æo³úsv¯¿Ûï¢þÆ®ÕòLÿñqÿù¼ÏÿÊ4ÿwT÷ãïåtßíÚwT÷ãïåtßíÚÉûË™–_ ¯y‚s =£¢FòãÏ­Œ/âÁÎ0@ëQ¼…_†)Û,#\€ŸOÆ× iŸß¾F v ¯T0µâF —·‘/š¿2<”ÆãœÝ+Æ—KLžF Ñàå±rqx¾°žöaEÞš3•Lg!­ŽU££¶&++&â¡¡"Öð„†òÖ4JºZ:Z¸’¬­­¬¥F]4‰“$lÇÙÜÜá ¾îMFÇŒƒO¨ËD hêI… Æx…ï†É†ï Gµ£!¼ª.®êŽê®\[*›jÙR`XÀ“d9Ñ÷¶÷8²ïÌuã“YK'^9,ÝÞÍJ]¸CQ8¾†‰j¿hÚå®D ÈÝf5Ç„Gõ;ö ŠuqZl^™Uä¦q Ï÷œ–ì{ªñšu/|£[\Š¥hh÷’ÞC<¥—Ä)ˆ£#;&¤’[¸yQdºŽ<&¦ú9mæñ|j}º‘ú;­›éüQê·jlx%ñCÞÈyСěÐÅyƒŽƒ/)wƒ#1S-”Ý+bI!®ÍLÑèë«+XÅû×…±ï¨÷Æjvéø§ßlÝTîÕG—Ác‹{¢ûª{ñ÷òºoöícBP¶b§ FB òùÃÜ»F“c¢8›-·íšM‹Çi§¦•?`B2¦GºoïÚkö»åà3"Ús=V[Œ{<$!Š™Ü|‘a΋Élºæ¤}œ\ј1Hpey…¾Á½›YŠÖá½J ³»ƒ±ÛîOl\%}XõÀžéZ÷ÙdÌ+Èã ÂôßtÕä®± TÕ=øûù]7ûvÕ=øûù]7ûv³]•9—Äni5h >r€ÇE3¯p>J°9»0NX ™;kBݶ+Û¬$]«!-„)JÑÔÍÀ{ €‘‡9¿-µ28Ý¿ƒ2˜æf²Y6wè§'³jÆËòu&óWÙ\Ä^*›wÔ.}«ë¢**ªà7ÿ´‚K§’Šß-¡›D]³ŠÅÛK`5¹ÝSß¿•Ó·iÝSß¿•Ó·k$jeyÄ j̸f4ÂoÈ0—œˆ€ÍêŒt16Þ’fclŽ>ŒÞñ!Fx(Q¸Õ?b´KmAöKêCp=ÅØcó<{ròÊÃW­Ë¿ÙI¿É ‰çÆèjW`%yœ¬¦íÔ£rд¨Þ:A•a_‹/e |ŸCÉaÞñêªýÞ #5÷ƒ±°b}Õ=øûù]7ûvÕ=øûù]7ûv²³>ÍÅÚçò~1G3Fð>oáëžØ±®…C8`- /p9`® LÚO£OÚI¿·]H+7»$³$µ‰!ÚBêªôÍõClÛμ0 Î|4v<Â2c<7½™}͆uì¬bƳ<öܵ‰4=P¡\‰ú=”_CGE…s0ƒ­j¸6w;zµ—@M, RwT÷ãïåtßíÚwT÷ãïåtßíÚðe•˜²Ù|2Ç<î£ p NˆñŸÒõ@ýÇ3¨¡^PyÑT[Ò(Ä:¾ò<â—¦‘¿T?æ>S]½»&Ïß@zuO~>þWMþݨEîQC3\7ÂmN¨í€íÀEA›¡ê¶oMz ^Æ=áHQÈrQÓÐlz~«fÆÛÂDÝàÞâ­þd™†ÞÃe Iª¡!Ü?îb·A„&Új…ÅÆðá¼z]9òì#rÞ‚%ÐJÂfÔm»^+©1âElH«¥º}ÜþfŸ“ÖsÞÔ†FyçºÉþ²ãO‘¦ |±YOûWÝÇ·…éï/éRõT«×•QÞHýGëºrœ 6÷T÷ãïåtßíÚwT÷ãïåtßíÚ£œ7æÞxdÑbÓÂÌ…?UÉãμ(h‡ ×V´ ô™Uz­¯ŸnÉP__X2o6*wq§/²Î4mŠC *°¯†jH<Æ~`-çÖb$ZÜ) 0é¿<Œ3†o1ÆŒüâxÕVä8üv YŵºŸw‚7ªôG^¬aÙÏÎØ{W.¡¿=e Æî©ïÇßÊé¿Û´î©ïÇßÊé¿Ûµpþb¹âÇOòìÏÚ÷Õª£˜§3Î&ÌÃÞâæèm’¸È-ðêÝЧTªØ¬²¶ Þ7´)Yæfœ3ĉ dU„…ŠÑ#~­ ¾ß³*^`-í¬ø›‹<) Ü^XœV›[b`ãDq“‚1§Ùdy{lCn×ÅÛÿ ÝTP ÝÅ—Xâü“}´YºŠg爌Ìñ»ª{ñ÷òºoöíp·0œ‡u†¢«7Ø·âS/˜”VV£qï=5^Šb[Þ(°oê"ú©õÖTu¼RwêgÁ“.ÔŠ¹;Ûµsì!Êê}W2߀‘?ª/¹Çš›X^Ý“k Û²Ô¾ÿo¾‹û»U‡_Ë;hIåa°ò-ihæiš»™ÑTYÅœ ñ²ÖÑ¡ÔàÕ~D‰F¼¾‘³nNím-˜+j¡ìÆ«¬¯‡Ï¾ÿo¾‹û»UÐç ËÁ>Hö2zÞI‘Œ7ƒƒ9@…Èæâõ2H[?ÑL<<Äi©ÔF«A›ËNAü56E›3ãÕÞ̾†ê’{y~â æEÓåqbNŽÝåKxYÂIÇxcnìåKHb4¦dš« ÅT0Zjšâz…ƒHè ‰„½.¾8y-/øï¢«Ë2”·.œªsÙäû‚mûÀ‰«ëÒévæô~C,Vè'f}ý¹MÅáÅÅç`‹6Ö–[$'ÈÂf‡–QØ/å÷ÈÉ0Ù¨Øñi hmI0¡XÍ´ á²a»èíhÈG¯*¤K«º£º«—ʦڶT˜0$Ç™Fô}í½Î/¹ 8…ËË ²§7©¾æX ¤.1ÇÏʘmYåEÉ‹+—Ñ­Rî¹Û'sù=%K(…¹nlTºsÀŽï¼oðu·§©ÖK€ÄâÙ|¢\StâñV&¸ó[" ¡€2/Mæ×³­/-<®Ž® 1¹²±µ›ê•£8 >6á < «3*+¿bÞÒ°í%”îú›£•æd#¶Ç"ØõFV×"£:·Ú-c µÆ×%£gãÎ帙ÑåGVH'z¥¾ mâ(- Ü{*±ŠÊ¯,¹çcÊÚŒÎpTŒ¾²ò£…Ââá†..Ì3AÑ™¶ê¬o)¯rX@"óhüò¢ŒšÃzÆÙŸªŽ0aç ꮃ1ôQÚn€ãÜ…ÀMá j¦«f©lÝ#¢y+*ÙacǪ×5Aâö¼’4ë8ƒ[2.ï8¬¾ã7 ±•ÆÉ`·XëN£aµ1d³ zÉQç¸Êq}<˜¡iå4EUtu~iyi:wYSV×0!zÿ \U&ÖÌ}¾¦Ó@qèÎâ‘ ñ]RNŽ] ÎÔàlRkÃQ¹8ƒK>=”4™i‘ðmôˆÛ{v×…twF7Ð8¤U^ØÕË•z\¯0;àÕ'±êŽ%Y¢²z2öµˆZÆy@ô$®‰ Œ‰“´pÞF,hâŠÃBóbr³åð®Ý(‘ù%§á¥Eí¤H2¢÷Ö¾10ØPÙ ‘‘ €•±1YY5´ ±‘º-oHo-dD«¥£¥«‰*ÊÚÚÊThÐ#H™2FÌ}ÍÎ8õoË ”wØæT›òb|Oî'bˆå°Ú¤WÂýÒ[ ¦‹|þà˜æâÁ™ú uPt¤vál  ºéQ€ñººÏ,aâkµÓÌër¡‡º¬ Ç*VöÞçÜÐ 4Ó@5âxâ˜f9ÐÙlçmüdîd º„ª·¢{Î+ %•ú‚¢òÁ'R @‰Yû]Käþ«ÆÐyU†æä¾?oÓ@4ÓM™Ó^NâÌL^~š‡á ‡³½i˜‡‰—–¯‹Zqk‘¹¡XRo»#qÔá×P¯XAÉòªö›T̼Β±À¿é‹Ö&˜´Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µŽÌ“#Aã•W2ìžåçÌ!¾©Þù®Ïž[ÅQÏ_™5dSõpBÃâoˆœ6+ÅÝ×´ðW'‹ü§`T*k.j” KJ‰µ}þß}ö5v¸È‡ñ(µ±òW‹˜èLò‰x2MÎB’Z]6#lÔÆ !ŽÅ²’_³x%†`fÛnã†}Í-NÕTˆœÐøvh£3¼É³:¸Ú­oIºÓÂf\KäÙ0ŽöÂIËí%ŽÅ¤0*hW+¥€‚UH4×ÊÂ^_‰Üƒ…ckNÝ`’„$¿ã¬§$35“AêpóW)±U]˜LvYþ™_+$12D(°5ÞÞ¡‰ÍÌ10 ÀµE,–áZ¥âd#3b0'Ϧ⪺e2WìõÄ‹ú1Ššû #Ÿ#MbEÙ“E:¬d—¨o8‰”ÅgËá#Ey'ú;^"ÝáE Uç ÈÝ—°ÔªÉþ™ãÔs=2Kì×Mƒ}íÌmý‹Ô•|ZàaÜ42ÒëXƒp2òF6qf¯J»êöC‡ñÑxG}`5"„ÒЋEdÕùÄårCTÏ£le©ÖÛWŠ9ц´ƒ£l¼‹'lj¨ÙéÖ-WønŠŒÉ—:)ZøÖ·l"’²•Eä>¨|0º-ËŒ¸Ý‘9퉷GyÇH÷•PÏé^¡ò¿?éζ ¼ò?<ò:_8òÏ æ~OWã}—Äõ>ß 2%+˜ÂŸù¢põ•€§1Ô8èŽHän ¸Ö;Æ3ÙM‡¦” ˜ v BëMZ ÞÚTdÛ\Ïh½dÌÙÈ¡±ã&÷Hm_œ]3Ç–¬î`üÓUë<ÔVc¦'Qòõ&dz÷îv2ñUN€µ¬>gÎǰÀ2ÔÆXQ´XµK5¶IWÌ€#¼ÅVìH$«!¯Ó6âQ«…¸e‹˜èZ×-£¶+g$–—Ì"a»ài ûÁâKQ™d—TwKIr—vÕ6VR`XƒI%2>õöåÜ6Æ\nf2D\¬||H0ëÿ è6©²  ­’Ò—ÒÊ…úDæö‚y8ßM“ÏœGAäÖ¼žúl»Šï a'zGðÏ „lMȾl]ÀÊ–ž#ðrêÃÔ«ã—ØÀ Ce6í-0¤á:%l1ÊxfSåÍÌŽ þb( (WŠˆ@QžG»Fž!•O<µg;M'œ8²/¯êÿ&8Ðê& -65–´…¤Vû›Ó„÷í÷ÀoN÷+8dîT ²ç@­S2 J•,µÑƦ‘‰&±"ìÉ¢V2KÔ7œDÊb³åð‘‰"¼“Š}¯ îðŠ¢ÆÐ*óŠÐdnËŠØjUdÿLñê9ž™"¦äq21$jHBddV—–«-‘…edËá+âBd•ôù·‰ÒËZ‰v—JË«Ir¬­—ÖR¤‰XÏ“"dÊéÛ›œ@e%A”¹^œµf_×å ¼úñ­ù3¤¼ÔÈe·Êa³j¨³6ðÌĺ¤ÙfMO)x£ ˆeÆ4X‰ª¦† ‡D5/¼¹Xí<Ùø’f‡ù†b nò 3iÜãåg2<…Ê‘1ÈU…mÄÛ«º¥cÓ¢B, âœ"ò ­?¸FožRML1k˜Õû«)õÚ2ŒI§U‚EâJÊ”`¡XÊøJ„e%C>=­tzòª¢%¥*²–Ò$[*•õl¨ÂUÓãG™£fFÎÞçÃMc.7cŸQû>câAÖ>OÕÝšT¬:«§¼ÓÈ:¢h(üóÈüòëÉüÏÅygœZx/Qæýpe]ÒÚÝíþO(#s)Ó‹9³“Üi\¦3$3 3Ü婌ìúa}ªöµ»xaUä#ôEJ°:àÚJ¤ÅS 3!D¹'¿¢5Ûöö™^`ǵ_,@œŽwº›ù³ØßrÅݑיFêsú{ÃåÉlßë,‡]†×Œ-ýŒF%äÐ÷HÅ­í0©:ÿ¯,.æŠAÑX®2ãp/jº'݉ëžÈtª  {³}ÏñÊíW”PDíçpü\¾¹é'êß#ÏüÃ×î~—:áq#˜:·5ZmÊ2ÀLoV2C1u R¯ž)=TÂrÖ 5dÍÈŒùòW…BäñÃî@j‡†í§RRE;¶70°ÖA=³[/—\pÀíø@˜O^3oú­’mÒ”0(º¹‚Qá u!Á'€ó’Ëÿ Î/¦Ï±ð‘¼O©à›é¦€i¦š¦šhši ¯e¿";T_s5aÚ¯e¿";T_s56ð½»DÛÂöí Õ÷û}ô_ØÕÚ£’~qëú0Ì·ia®o3THïl _ŒõÀæ2ÜÕQ™¥-jëØ6´ÁV™IFß¼£¯¼©,±0Ž¶Ûª£ ßœJMÇE^:SÇGxÍ_·ßEý]¬Z,1…£øwùDr)Æ?÷‹sJÙ©ÇD •: ÆËG…ífHE˜ä5Çsíö(×Fk¶¸ÅQðgé„ðÑ~Ó“qQF´–LpÇÙ|Ý\\õñ¨&Ç!òëZ= 8¡€L/så7°jï*üÒŽÒ ï.¹­®µ…ëü5Œ’ö·£íÍõ¬¤g/NS“^kw}Ž€8]~¬6gn7–§9KËáfíÜÅeêÑLå´oÖG¶¼[ð·× w çVÙjzÎŒfn_" Swî5ÖxÊ' ß.ü›ä»Ií ížï¶WdŠc­…l«níùwõòÖ‚dü­H ŸO¥Qùd½ÔÅÇ$¯æúº[T¦ß ÓXÚËkM`ß"À²KÁYö <ë$æP—gä4TÀ)l5…ò âãu´‹5g…±VÆ 8NʼnØ×»@Ë'¶Ø¢ez8¾àF>«¬?“ …¶peúBPG4š6K~ÞDÉo¨xÔ5e€"÷*Ö%×[öC¢:yk\M6Ñ\ßA×Á ‘DB9á°SNÜŽLcŸhûÊeÑÝöw€ãŠ«öx¨‡ªœìÿ6è`ßÙZ;Ï#óÏ#´ý¡#òqZÏ úâò¿×ÇõÐŒÕË¥¶ã+/+´‡kÅ_Fõ 2ⶆÜÎg\0W>M\LJ!G#ÃÞÖʱñÄUÞª«bvüo/j<8Ú‘SÑã¥H¡8-Ö2áå[¤vå5v·×¸Û‚ÒîÆkNÁJÌ™{ÄQÁqД¾ÈOq™´ay$Ìææ¢Ôëzà®ëbd»ØçÙ²æCÇ\ ô:ó`#¶@ºÕWÒ›Yüâý°½¢¼\tý žƒ¹µð=cEQ.»z¾8c_”l¾¶yY–fú­h¬5flE°ßĦ!#&xl -¥RÀ5 •Íâò™Œ¶QeGD7m>TºËIÔðìþË<ÌÌ‘_bŸmëöûDóÃÉ™¡Ô"¶+<€¸í³»¬'“»ÆÉçøRÀî›COà§ìu„›ÞÄ3=Px°å»Ì£­²iß‘žy„9/åå Æê>ŽòÄ;GÆôç³æ>"|WPù„O8êîªõGWäG뮼âƒ]ÉîJû³]qÝÿûâ}ªí—Ÿw'¹>}¡»}Ò¿´ýqÔþWÒ}9úûϼ“þ°ðúhkÜšÀ1èØ2í„§Ì?+—{ÉìQ;‘i_X~óN¬ ªío*!¾ÙŒ¡"&ý+˜°åC˜uea¶¹«s¸*·;´žYÍ^ZpnÎ9ÎHå1òG+’4…&¯/`ææ8Se2bI…­K¼ÀvHqãÓuŽÀ…”åfò[JR‹]‘Ó:dþÒ»gm yZ­Z:i¦€i¦š¦šhši i¦€þ‰%Äõ.,ˆ¾*>Ô¸Þ#gsgÄDÞý/S+cÖpðúØû¿£Åê·¶ÿKosôx¿G‹Óù½:®že¿";T_s5aNwqŒ@êmH LhWÀsvNsâöÔ@[¼P¼víi ÀµžÁ¥…*£Š‹r¸2¿† ¾Ÿ5©-•#tÑ+b]uóà›·€ûvr"˱àh pXKƒzº™¼!'<2äC¯‘:Ó~ ]íÿFæäx{öv;Ѷx¸67'Kãà⑹6°½»DÚÂöí´Õ÷û}ô_ØÕÚóÝ}w9nÝc(’{rÓÓ±äÿžxÂ9ÌaG¿ëh*÷¿àHÅî¨,}W£sÔÉðR|$͹ez™±dÇÚòþ¼Ùù?}ýZ2ð¿UY5EVMQ9ÓPn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿J¬äk‘UœrNtÔ¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/Ò«9äUg#\“5ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ ôªÎF¹YÈ×$çMAºógäý÷õhÈÂý:ógäý÷õhÈÂý*³‘®EVr5É9ÓPn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿J¬äk‘UœrNtÔ¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/Ò«9äUg#\“5ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ ôªÎF¹YÈ×$çMAºógäý÷õhÈÂý:ógäý÷õhÈÂý*³‘®EVr5É9ÓPn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿J¬äk‘UœrNtÔ¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/Ò«9äUg#\“W2߀‘?ª/¹Çší^¼Ùù?}ýZ2ð¿\AÌzNäüz±âª#§ÛžÖ§Þ ¬X2ëÕlŒ±!qnÈ-ª¥¾‡·Ç"&ÿ‡ã™[±Ã+g‡‚T_Nô]ííÉ´ÿ‹Û´M§ü^Ý¢Öš¾ÿo¾‹û»^{¯Bjûý¾ú/ìjíVþæO¶/µÏúqÛ¯eŒÞ}á·¾þ®ë¾Çô§úï\c¦:Ÿ©ýè~Ðù/÷Ñmâá裷´×–[<ÒT-”5ã‰YJò5£L˜¶`‰W6 FâlÉ”B2º™o²_}G8‘^ü‹jªyp6vFHww$pðRÙqFøfÙ5Ë6HŠiiû}äª6kŠ2Mº®úX¨¿Hƒ^ßÀ'$êBx‡(<š®oœ_B—O]âl#oGàÛô׿Æl$°u$~ÑhŸ«)ËéÕ“å2˜ù²$­$|’+D¸È¸—k¾".9v—W—V’ÆÆ¸¸††Ê§ÕÏ*£ôúhçÈŸ߇í“ÿ»wÝíÇÿrlžÑõî½½¸ëî—ÿúÏWô_þµÒÿý“ ;{Mq8çšaù€á¼ÁåÏè•ô ••ÿ TIÛÙÖÞw¼sþì>˜œÓµ¤áæÃ>q@ÁÖý7çB5sëî*ª\I;s}ÓM4M4Ð 4×½³'²™›Ø‹ÛŽ¥öÛö¡ÿPz¿É»eìÚª¨fûÓé{^³ë?5òO|¢;ê<Ëõï­ð`vöši k–}¹ð—Èz«Ûzc¢;›Ô~Ðj_!í·r{5Ü8êï/èŽïÿ¥]Yâ<‡¹?°Þ?©ÿU뢆I†ÍFÇŒƒHhËD hêI… Æm _ “ ß@kFB=yU"]]ÕÕ\¸¶U6Õ²¤À±&<Èr7£ïmîq÷5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µšî[ín F$æl(ùKæÍ£C›Ng»—r†pO4ÚÃfjsYàÕ¢GCÆJ4Ð…•«ÊÝ‹Î-é#ǵÚÙôÕØÖÌ™¥¯¿Ûï¢þƮמêŠ2%‘x‰”Ð9‰b”$#L«7s™ŠÇ+ðïßÓçH¼ÍÆÃc˜ö=­ñ"ìŠÌG+Jâ®1!®ù#³¼ÎoÛçEZ Þ¼§4×Üa¶à8ª?$µÞ¬YßGgSÉgì—M–\ÐM²nš<ÚXeøœïÊñÞaœº—•¿î(‘7Ì;T§hT6–‡)ÁÆXÑž(œzW!Ùd.µ¸¡î!˜öÐÙ>dÐ&¦Ø·l™>àf»|qÝÿqï¶]ªé;îä÷'Ø·¥{}ÐÞ©úã©ÿg:OÊüûÏ¿Sø0ÿ‡ÕÂi 2“‹˜I‘cë aÁi¸ÓGW‰YeG˃6rRð¯é!©I1…–Ûˬjr ]·Føæ´ß,lÄþ8ûD‰ÉÈ d\Ý“ÏQ’ZÔqê2½3Œ¿“ÔÊ!Mæòª&5œs& Ý qê &±ëÚi€]X¸.µÇÆZ©©y¾oGÚÜÂþB@ÓËWûÜ{ƒ18ØeJÈWÛxÓ@e”ß ÑŠLåyÀŽ\ÓA‹‡ Ûü[mîcŽ=e£ó ÊŸÄD[fÙ—Š½qFFµycF؇vŸ¸sª¤ª„Æ8K’©ñ(ʾr,é…ù5„Y…ÔkÙ ê>af/0ðs¤ O¤É-AªIñäýˆ I¼´C´Ø¤”‚ žy0çÒäËÎbúN!1Í[i )’Ú0“†ù‘Ú§oB|Ús™0)`¾ž¶°IM€¬ª]¬(äÔRÕËVK«¥Ü­ ¶‹¸%¿§ŽŽ(ð8¶ö®ƒM4M4Ð 4Ó@WW2L¡l ¡8¡°[^oÔícN ãÙœ˜Ûô–©Ÿ_0Ôl…Œü¿›È\Ä"w5¸’ŸÔžy$g3dmÄŽª³'Èrê°°{j†Æ<ì„lÔ6(}¸Ã½ÁœC³Ì÷nR¤žz¶]Âi 1Ë›"Ÿör{‹‡g}³8æÂÍÉŽ´ÇËê~ß²gúÏg† ÓÏct¡ÄÞß«{0Xà/¤ôHCÏãé±ßÔØ1€¯6W'®_IblUH :–§ {ùÌÃôä*ùˆ_Ÿ7g³c$ÔCˇ×ÁH˜ürQ²{|ÂMBëzظ°2æÊMMi ªÎÔ|:Út2rJ ›/‡ŸØ žàÁd¦÷€¥êKÂÃUM´‘5ëO²rD½'ƒ`ÝÆw€ÁÒ5ÙGKÀGéµ­à$­a ïG¶®g­$“XZó®z ßŒu¶5î^ã—µë¨0àþ²ç"ðÍñ'—VHâÕS*†äJÅ·ŒØìÓˆ„~©yc½Jn©<ÊHŒcÊü²€â Ë Ü €;x?8pìè1~=“i˜ÊÐÙÇI¬qW%¯šÕL-°£'¼8£'¼©(OÖbFs¶C‰¨ªIÿN§‡¢‰‰†Â†ÈLŒˆhÄ„¨í‰ŠÊÉ­ PŒÐÀ‘kxBCyk"%]--\IVVÖÖR£@®DÉ’6cìînpÓÚ§sÅËËkq1ŸjÈì¾::n »šÄ@®sä¸n·Dz» £"i\I@ì´Ä—45€'Ìöj7)`\°¸8˜ôv„”Ø3wW(D“C±»è:øGcXÐãʹ›ËBeÕU³ÙÇH×e/àô€)ê˜=¸àL‡“»Qè¢Îù‘`êó°Üw9{({£³ŽöË-’'- šÕ9àã ¯ˆT4‡dgW–5ÁB`pl7 Ù › ÅclQ߆ƒæ‡Ù>ÂW"òŒè¼êŽÒìo€IŒ:6s¼: ¾e˜…–P‚´× ’Vzpx’ɰ¯eaè`† H'ئçWV0åyÇ0ORm†•/{ ^Ò eÀü4Ð`ç{µAÉÿ&RºZŒ=ÿ7—8ÝO°}U­|âkn“£´‡Y]]8 Ë3RŸöûš›é¯bOu[Ú{ýCU\öËÚK¬»-ï|æ×¬úÏÍ`|u_NúÿÚÏ"õ[Þ¬ #¨ži,œd†q+¢—’FlŠÔL&HÝy$(¶³§^ÛÝUļ‰WuOe&§~VÜýˆÕ³7cðÇŸsw‘9–ü‰üíQ}Î<Ôq)ËÊxÎ__gƒåÅFÅÈë 2 ª­´*Ho”ü Ä!ÊQMÊöUU3)å‘—•ÜjÍ»:<È–ªô+zÞêÝ`p)y]#æ[ð'óµE÷8óSo Û´M¼/nÑj _·ßEý]¯=ס5}þß}ö5v³\‚æÓ=N7•eyƒ=¦Ö«áç°òå±ñTJQ²b@/D k%UàÐC¥çTcQëI¶äÍ£h;IçØÖÕTКÚH‡bŠ4¦©ìV72EWé¼§\yÆSÇÁ’ãÕàÙ[™¶wÍZ* m*( jšuÅÏkvîd$ ·At,ÅU‹)†Õöi¾Ý9L_Ý$gÿȰu¢;0p•ᑦ+JzìtO6§ðPŒ‘Ÿ³ šYÇ©V2Kø¸iÎcÖÎÙYÝØˆJÈøá¶r¦üä iÓUÕ‘ÜÍÐxÜÉ2Z؇»ÛòÒÁÍ,¬&A¯c2…pé\Y}GR:q‘6ªï*üÒŽÒ嶸¡e7£&MÛó—QW•Hl ïîmÈ4{z©"2¡Ê|ª8*ÅüÀàÃDülŒªb¨Mš< y¢vÅŸþ ëp¨‡f]$3fÕK Ìà@(„ MÓU-Ë#>ÞÙªI˜ÔmÌp¼WÕãöad"PÊ¿ua°7QH©žNÏ‹Uí"ûŒ‹ªÊÔÔ¥v)#, Wðm‰îÚz6ëlE?²·BÛ ï#伄–H°ƒÔô$Ϩ+¹Ôs"ZRÞRÚD6&âŒB°]Z‰WÑ™¯¬­×-T%ë<  ÓM4M4Ð 4Ó@4ÓMÓM4UãÌ·à$Oçj‹îqæ¬;UãÌ·à$Oçj‹îqæ¦Þ·h›x^Ý¢Ô¾ÿo¾‹û»Y’÷"òGþ¶Hóû®žù?å»þ‰ø5øoÿé¿x¼­iµ«ïöû迱«µçº¢Œê{‘y#ÿ[$?ùŠý×O|‡ŸòÝÿDüü7ÿôß¼?ÞV¸‡q$sÖ‡›î"ñݤpi±Îó#g¼Ø<G›Ù_QÛ6Hƒ4ÌMN'éš “Ü D ÃÀ—ƒ¶0ö\V«&ÆýÀ\í„é )(9pä‰ Ÿ; ±tù!šŠAr‹Ë-ÇæÉ䂤Oo} ¦~;Ô/+¶*þq&,ˆ›ŠfUúóËÜõÁÜ. òï–±}MË “³ù:ù )£³Ç—)e÷.JÒk¹ó]¶‹gMA•I : ŠPItrÁ)bì[]ÖÜTÏß-Ü‘µ "?Ü­«iÓ@Vváë·¿·xb¬(FäŽa=36eLÞÆñ&Bl¬åJ&­™Å @= 0®Ž<ú«VŒ÷†Éˆñ^ç Œ È5‹Ë ~X}•<ÂòÅ~ÆV²ÚÍ>_¹ ƒ×3È\‘&Æ&ˇ‚™ Hº#Xù6=H@)aìï)ÚwóEdTSɽ4|)9-œÐ³Ì#ÅtÑØ-<—Ü|ºŽZÄÒXFNÒܠȱ›¥É“d!å×7qíhÏ ØFL«jymÛ’ÛÙU¼Fö!]Æõ>Z’8Š˜ÕAÊÉ8à Ś´XËÏ’†Mæã&¬Lv{èÎÚ&<^Ná£XNb)«ìoo ¤ì~ Ž&Øð\K¼Ó@fu3Éï)¨ý½Ë/ë°‡o2ï—Så ð®ÙßIŠÏ®¼« Èâ…ñpu,D§nדDVÞà‘¦¬’ „-æ”Iâ·†—âÅ„%Ë¡ÛBËä\e0¥Y¹WË#Š'ÎÄk²Þ9备ؔ»CSÎQmn„lǾ£Œ^%eee$ÊP ý‘½ø3"ÖÌ´Üß§thši i¦€i¦š¦šhši ¯e¿";T_s5aÚ¯e¿";T_s56ð½»DÛÂöí Õ÷û}ô_ØÕÚÉ3V,ÆO2jÆ4Ö:ÿšnc,–žÏ…œâJÖÁ)KáŽ_V{Ož é» ä^NW‚*§¡›KëàF’+úzÜjûý¾ú/ìjíR¢ 2×É2®R-1ÓlC)3 å˜VTmÜ-eŸ’’;gÓnL‚V Z»z1ú±Úxq§ï†ÀŸa?Ñee»Ã<صU´Qhsl$Y=ñFòË;F2,qSŠ8oÀÉŸ°I™‰#©þ‰aRÍŽ§± Vq ¸ŒöS÷IDSÔöÃð‚’*ˆ¾ˆ?§Dú,Ùbb]à–%aÞ}0ðƒ"²&¹Ì6UI3ÈÐÀó:–ˆH\_ÒÐ$äûjî2‹0€«›[ª¤>Íz‘¬»ß4?Ÿb˜ä¿4IéöÆG¯“ßy‘t ¬ uç¹dfpÚ¢zdóf…% ˆ`Ò“ƒ Z{HÚö+ÒÈw„…f½Œ6&3jk\¶,C_› { ‚PS†W™·h×ÀUÖ}*Hª^àØ÷ùzÄpD_ÁØ&„ð¡%G²!'dÂ=¾ÎéÌ’KQà‰ÊŠz½òcÑ)¾Kò»žàld{1’˜éAêÀ´¦{‰ÆXµç¹€ö`Ò_(‰Í.ö81ù§º°b¢ìˆ¸G™‹Ù#fÐM£)a5Ä OõE—.ðÄæm/²©p]Ó‹Å_.¡>]àh/ µ·ò ÀvÔ0¹wtïM­/-<®Ž®_\ŽØÚÍõGbm.^îôÀ9Ó”–RæžKg¤\—€¬³IgÖQ¢/X¦ÃÞw#y:Hb)%G|_G€°9€QŠaëÒ_’LÙŸÅTWŒæ4{‹tm ^aQZZÖÀLÊ[Öy/;#1ɪ¶ÈgÜ•’BG2=ŒÁ”l¾RÄܨ¥-ƒ©Ndš°­ŽÌ² C&·j0†óL¶Eõå™6Æâ[Šó êÙk._ŒÁýïoÂÜ,ÊœgSÔ¥™ÙÿxÚ]ã¥;$!®ñ6—ž»ÙÞº‹BÚ¼²)Ý|È?i„ˆq…¯Àvl=5 }±°®6‚­²vEpeÄ‹sWhæ¿/,ñf*B–<ºœ1ì}Î…B™§Ìí—NNà·Âé¿NÿMxKUèŽ(EU³U麨&3]7Àî|Œ æFç'•V.ä^;B‰š¸B:\™ÊkǨ«4Í ÉJ ÄÍ[ÜËý½™‚_Gc(|Ûľ&ª`,8KhXwNÄÛäàº$Ë6æFæŸ#²‹Y8dä Å d.̱¶\ò ³î0`Öµ[u¦-WèY®Ãì(,”")Õ”‚Wшî$E.¥è±¾Z=uëÍþØy?Guw“øF˜yy¤/ çR€´Ý4Ó@4ÓMÓM4M4Ð 4Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µçºô&¯¿Ûï¢þÆ®Ö;0X•8dóV¶cò›öî¼Î9k¢·{qËü¿§*¶¯ƒdì.<Ë+ª¶Ç”K—8›ÀÓL Úêÿ]s"òIê(ÖŽš Ç72ÜÄY¿ü½«– üÃú;Î^ÑäVïc)¶’I !°sd7 b´Þá*žzÓ¸Çè«ÆÈ®+Î$jÁ°#>âÛƒÊìy½å¨÷7rÁ€³ÇKlJÀ~f-=ip2àdYúJ°ä)\>bé»#š´¬i­ €D÷¦ñ ?é/ËÆáqc4õµ1#t #éªCÊcÙ"<çÎÁ]HKå\\½2Ëmù¼y©íÜ1_C¿iaŽöëËú…‡“ãÈs"^ãe•@Ãó=ˆ@O zÒxìUßó/ùºr)<·¯<ƒî ñûYå^kÌ€ÔÖšÌ0ÝÕèVZç"P5"¬Ž%ù093º(t3²sBH2½¡e› ѤGƒêŽ¢#iU”¼"ÜTìÖ¨#×O®ÖÈ†ÎØÇ k™VK¡RX‰8μ£¾/£äN‹Ìj­ÉÁ’™~Hßal‰-hJLm+´IÑÝZ[zH_ÇÖ ÕóÉFi¬)Ç$FØß,VÚk3»/NdMþj¢ðGá{Æ?$0<¢Ä\” |¨V¬’gm²í´42çUËØwÔ0åÙ Ýä|•M𚻇Ҿ“ä”Ò.íú™gÌŸ$^œªh–¨Ž—}eÙÃCÚî™´¯<¤ A-°¶×yqœßšº€îÜÍVq-Õ¿B}ÎÙ%¡ßµ!¤oô©e´8>.óMf㹽婲'—VäÒÏ8Q¹é‘w]é¡Dð2à¶ݤÌö‚Y¹èŒÀ#¶âVYÈ[´þubZ)³Z8îg›ñšÙãºçîóhËÆfW—.1㸠ÿ4Ûþ_g€A8Å”ewÁ)Hq 2ü»7h§ÏÆ‘¾›dO‚U÷*¨ETëi±#ØšF¯“²ÓãEzi¦€i¦š¦šhši ¯e¿";T_s5gm»5 ¥yJpn]c~¨kÖM´Ûµ´®·³¸àôú=0áVÓº$“s¿èôJ°ôǧ­›=]dÉ{ÐâÂ:Â%]s™³c€öø%mìNh LØÛm\Þ ™!';û|+,ãı®•ÃÁÇÃÃ" „HÓboz8ã˳¿·¹·Ã6ð½»&Þ·e­5}þß}ö5vª1sËc$Hý¼CfÞa&jòC"ÚyHÄ «Â±½¶Ã‚|…²Ç¥70Ý’_YG枪¦—|®~Ì(q÷7w%ZI²²Ÿnm_·ßEý]¯=ÕU‘×(¼na†då ³¿‰‡“ùN)—VY%Ó“I–JâÔzbŠ“Ü3–³oa J:[`4ål’ åºüõ†.2K!Lž-®!ÄNP×ìœï(Ìûw|e{škÇ&D°ÿ¤¶¾Å ƒ[B¾ã*E4[ Ѻ²Byþ<œ’]é:¾øðR„êb©?²ëVׯÆaztW¦€®¬ŽåƒÉI“*ÄÁÞ –éVå`Ê …j+˜ªá;ê;aÐ|ˆ°;iyiåtuw+³õÅòÕ½%0tn œÅ”¼·Š=[êc8>’ ËQìÁ Ù¼/ÃÚœXŒí‰P¤†RT,¸í =‘ມ(–”·”¶‘"ÔíÖ“F®¦–Ì»ÂÓ@qî>a*Ÿ[ÓW‘´âÇÈÆ™³¸¥]ls½9N6Økl„ú\C#{!ZYÞ2íbw27Y •¦öÁ "#eL |Â+ûŠ|E['2k-r°fìâs2» ÜúkÛ*A”^Ï û%ÀWA×WUÞUù¥¤‰EBDQãmx6wê|’'ΦÓ@p+Ï—BK ]®'É‘KN°½Û€¬]u£7bP†ëÒL’Ûs+‘èv¡V‘q-.¥lTÝÙ\[ l@Ûµ0"|ŽÉ[¾ [Éí%k? Öù ˜XìËÆü=‡‚””+dHPå…Ž•c|´Ãl®‘h„›ÊÖæ@â`—tŒ+HGU’¢’+'ÛNšˆn01a’)¬¦¬*wŒ3” ¼q—"¾UaÝôÀÁàãT$5ÊT]¾NÎ'é†pÄ#;BVÁS̲ñ¾±'¿°ãÞ[¸tZ—ÜÇóѳŒ´x¶_– 0Ñ¥J’wH´äeNQ¼`Ò²c%‹Œëo2±—aÄÂn­ LôïW0€£]4dJ¤/Ạ4u9>ò€¾Fc.&OÍ«w}ãMpÞlb+¤¶bã* Î@À¹­p UÚD´8«^UÀ,à#fŸ «X “`-¦Yqw¾€y\)ÕYÄ}­ù„6ÚȾ¯dc8ƒÛx Û”—•öåW5ƒQšûÔe·÷Ûæçë}¶æÚÁ‹wP§ îW ÜÄÅ•[ s˺„ jPs:/7ªƒ{Sç"äÅÕw•~iGi[s]ã ìxÚ«61½lIq÷·*’hФš#Û{^¼ø¨çë ”?Úv½yñQÏÖ(µ9ÓJ,¤KE”‰pA»^¼ø¨çë ”?Úv½yñQÏÖ(µ9ÓJ,¤KE”‰pA»^¼ø¨çë ”?Úv½yñQÏÖ(µâKŒçÂW2áE˜˜²Ôa‘ùO®2 Jpg{åS¯m¼˜\dºÒòÓÊèêì®l| ÿU]:ÆOª‰FößSiE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv¿TLÕ±I™âàe‚FÃUô¿sÀè‹(mÌ×qU½zׂõóä^u}y"ýC»¨*¶7¬j|\M®=î¾”YH—‹)àƒv½yñQÏÖ(´ízó⣟¬6Pþ7kõzÍ[ ® ˜!Œ6§TvÀô²† ÍÐõ[7¦½/a>=áHQÈrQÓÐlz~«fÆÛÂDÝàÞâ›éE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»\AÌzº²£êê"J‰ZŸƒo†yqdýî-ñ–$ÍÍé—ÇäSw?NOÖ×¢]¾öÔX›QâDÚØ±··è±W2߀‘?ª/¹Çš›Kø½»DÚ_ÅíÚ-A«ïöû迱«µwî-ÏÅѾj¯üz‰‡¼Í0]êÓy5ùŒbqõÐØE«A H7`®ò…g¶CÏ%æ$nn%Ó`z„…¤ £ˆ‹‰¼ù?¼aëá«ïöû迱«µQ‡üym4[îs¬a£»/a4ÃÌ:~æÝR„ØÙ¸Ø:>CRŸ×#Mo8x Œ8¯7I×V»%»ÇŒI%›7rF»·ÔQVYG›— ´’`O—ÛC"Ôâ¼—îsqKŽj”ž/‘-ãAõ©†T½s!†Á«½VÕÁŽ d“Æáƒ|‚³ŸZ~atÃ%¾¾¯›7£æ¬öÇmž‰Ëâ•eº7+ùK.ó߃l Vº  R©Àf>ðµa*Û¬ì‹Ç…û`ŽFqjEp/(£Œ|²Ê´äß-Ü̦J¹»“xæÜa§=FÈI þñ/Óª‹}š ¹µMÝEP"%æÄ™ÑÚ5¦A‘|ôº6ÅÜCRè÷sÑ8­Ä§Æ”„ÅååºÓškÇF9Q¶\„“ÖÌ%.õæâÎÆ9]óȼ–Œ9•8ÈA•ñ5HßH´Q¾±ú ªÀ(,Ï!ùÊQ3Ó˜3ÀÈiže¬nRÆ„adŠ^òþ$–¬'µØh@sÊcþU‚7w1ûƒbU{?8ilûÖ,8ü7Ð-v¢†ß¡0ô÷VŠfôŠ4U£km‡²òPÉ0ØøÚnyâZEkú@ñ‘ ±à…%öE©fåI5åá˜Ýl ˆö¶vÄU{;ó&|<¡ådžY”f,ÇÈTßU°ÃB VT‡‚ì6ªŒÏlŪ´¢3_^”'@o /(È ©·„Êç]PŪ5<®,C³ ›¾§í’Û¶ÝšíðGh:#¶]ªé:ÛvÛÈzW·Ý à:c¢:cös¤ü¯È|‡õ?€òÿø}–Qõ?±_¹:‘Ëtþ,ç®ÁÊt O-üíÆN>Ã9ÔvwŠc.‹š+}à†ÀC`ßzšÛ~ýrÊ·>RIx¿â5ܤ!t¶þ¦òæe—ÃkÞ`œÃDÏh葼¸óëc ø°sŒ:Ôo!A—Ç!ŠvË× 'ÓñµÂZg÷E„ ]¨+Õ -x‘‚åíÆdDKÁm8ãÊo—þ&²C[¨ÄO°Öá+…™ cMÔÚíˆaeõá1-2Ê¥¾Ç;£]yÕáYœéö!u´v»ýxÁéáŒcÝú™~â æEÓåqbNŽÝåKxYÂIÇxcnìåKHb4¦dš« ÅT0Zjšâz…ƒHè ‰„½.¾8y-/øï¢¨ ÜeþG9ñ%ÏùO†]¿o¯ýÅž‘.éáR¿)ê±Q›ÿÔÔdƒüxÁ%Õgë:Y¾ÆøØ^Â4I{…ÍUðöºÈ,ýÚÖÅà’gò|2#)7Ç…–gËlP¸ ÃíeÈ'+&$á£5ZWLYRų³núÚð7pI³FuKp¦xˆ,Iùedv“£.‘œ”kAì¢Û!¼1´€Ë€šÝUÈU,r¬ð¯snPÉ2Òq%a$*“-‹oA}5Mä(:‹•æ#I'/1êfþã$âQ,ÃÖ3KdÓ$Ï­•èVÖ´LLªØ4pj臩澻¢SŠˆ&ém`*†ÃjÀ¥üc¶QÖÔåëzjÀH=r‰ã %㺿.<2Qßc™Poɉñ?¸Š#–Ãj‘_ ÷Il2š-óû‚c›‹gè(AÕB=ÒiÛ…°0H2ë¥FÆêë>à†âEÜepšNŽ¡åux~YÄIÁxc,nåµH4Ùd…+§‘ÊT/šmjІ{H u„ÂÂ9-×¢Ô ê:sß™(Ž+s=Ía<¶£ƒWËï›K9‹·Ç5%ÀÛ9DäQ¯¶ÔìÃmˆu%ü4u‘Ù#Â… »Á¬úø°LXŒ¡ ]ºâ\xdV˜Èì|¿Møõ[;ï2; Ä{†Õ‹Ü9!PiµÑ—ŸÂ9ŒN)ãI×â6}<t6+Ê|J=Šùöq&öö€i¦š¦šhši i¦€j¼y–ü‰üíQ}Î<Õ‡j¼y–ü‰üíQ}Î<ÔÛÂöío Û´ZƒWßí÷ÑcWk“’Y˜ÈÎîvhˬ{ï>ǯìñP÷J¹ÖS×!¿µTt~yä~yWûB9ç¶~+õ=凨‘êzÅ«ïöû迱«µ†óvÀÛ>Fèi¢­_–Jjœ+2Ql’I<Áò’t[ZëáÚ=é«md†1 ×·Óê+vËCȪöw+w¨£kškàÎL‘_²EXõc”÷ ùLqùVœ½KhXeÇ|Õ½¿ *6´¾îñÁ?uw)¤8ó™QJꪹj\ Ñ17¤®²­ø ®æu‘`”ï6ËÜVçx|¡Äì?¹rÉ9 a3Âë:Œwž»xݰØÞkq®kfqÚ¯mqÞÄ·¥)ißÇ mMf<2±7"ù±w*ZxÁË«R¯Ž_c- ”xÛ´´Â“„è•°Ä)á™O—4s280 øEˆ $ @a^*!Fyín%zrƒ:9‰¢-œ–Ì,*ŽÓäNŽÉ—R»Øw¹â¹a“”¾“Zȃlj6%¢Òò²Òo•Õ¤õ ±±Ýµ©ܱ 1¢@4ŽÍ[3:»· †oÎ/ÖGYBWÑ,‘O Õ âï"Ÿ?¦Îü|?¹ðWÔþ6'˜ÀâvOÜÏpÛHÖCróy®¬Vn»šÁ«4³åé=P§³³2qÓVR=bÄ«ZQÖUͨ½·Ý8C½N6D(Mg³€´fÊÖ³¹‚+Ù<ÎãÄ88âaÇæ›ÌD(»"[ÅýF®\_c×ùĵ³&òŒøà~ð°&¤Û"oÆHÛ½_@<\É‘¦%}‹&ªÐb¹Å˜Œ4æ^…Yê°ÇË\×Qd¤ˆÛøvç ¯ Œ‘àmV³£ tÇSõ:MOvþÇ£Û«TÀÁ¤Z¬>°î›8¨ ØH»”ù §y#N¨Ù*†MÑiöî÷ H[ÛÐåG‘fÌKJ[Ê[H“¨‰†o`Ö V[ “TÔßÔÙVÅønÜŽLcŸhûÊeÑÝöw€ãŠ«öx¨‡ªœìÿ6è`ßÙZ;Ï#óÏ#´ý¡#òqZÏ úâò¿×ÇõÙÔ_äÛ%ÀƒäJ²ãW{›x»'® ˆ{Ø¿U©s僎ªu+6ž0”´F0àX0i§ÀsµÃ}kÞÔòÒÃnt%w6éËÒ êñÌü§ä~9cF“nìÞ’d¶/§îØ*÷! 2§fƒ¶ò|Â0Ûg Ul s‰ár%]y¡Üc ûp6K¯0ÉD-SúØ…´ÿ…€Ž6>EÑÑ]Æ.3M†te«Éà—¦ðÞÏ(퉅ë¤y©mTé0m¿ö8x²]yÎÉå—χô3ào!–|áYK$gèdõ;~¶žÿKôbùOù‹£ŠM_¿º`L?ÀPÉ pyT:³Oêf•BJŒÐü¦ÆE;a¦¹k„㢰… >O»E'Ú¶ 9kä«fâ=hîÓF [:ð¬h¤áD3}PW³carlÒ+šŽ*p5l²c†8ÖËæêâç¨×@68—ZÔyèaÅ a{Ÿ)½ƒWyWæ”vgyuÍmu¬/_á¬`Ä—µ½no¬²‹9/«îZØß“9bïÆLi.ä†5˜³²%í}L—ŽWÖ­‡ÇXû…Ù1siè°:ö|P_Úå-úþ¾ãj ÷¢#S"«˜«zªê8…^Jf&`ß~Noå´ïHÞeÈG2 ì©M]“ ;æ¯[A¯(#­ôìD‰ÝEåEa­9àUxͨ§s­øÁz›¼¾&Z:j—ù%›¶.”ù¶¦iºo¨ø¥ÌÇ-1m\Àwl›¶%©Ö[À³Fâúk«­ o8m ˆ'îÝ\ðîïDٰ٤ۨ£¥º ÓM4M4Ð 4Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µÉÞ̸Ýÿ—ćô×Á@üÈÿæÿ€|7þõýþëú믿Ûï¢þƮհ9̨Dý±oqS7Ÿ Ì8±\dc¹>®Wn­‡ÌÆ}^Ó˜ceî[°Ï;K/Åð¶,D@mª€hað1/çFV\Œ^QEŠû2ãwþ_ þÓ_ó#ÿ˜?þðßû×÷ùÿ¯ëpï–K$ù¼¤V7ÞO,ÂÈ<£ sÛ#„¨› q·ÖÌHÒ“,Y–%¥òhècïìH¹ª¸€A²hCµ¸WÁaeÃcêk.`(7H¯±¥qÂpGxÔÂ>` lNœP¶½Aœ@áý+Ûz¶YŤ»H79r¼® ‡óØÛļÚÞ£Ûííå‡ÈÄ“X‘vdÑN«%êÎ"e1YòøHÄ‘^IÅ>Ž×ˆ…wxEQchyÅh27eÅl5*²¦xõÏLSr?Üí’Û¹=åíðGwú#¶]Õé:äöÛϺ«·Ýsà:Ÿ¢:Ÿö¤üÓÈ|ûõÇ€óøMôЊ%’ØXÌñŽ2¾aµ:_¹ç”Bt5l~‡ªÞ¢ ëŠøï úBŽDŠa~¡cÓõ[ûÕÕ>&ïÏ•·pÿ²’ “ç1ÑÚ_YGf´­º’Z2I+ÆáO²µ†=ðÈfêÒ%KK«‹(Õ;¶àlO¶²™µ†Dù[›¾ ÝϺE¶ZÁÂÜpȼyKÇHÙI¿E»Ž”£uŠ}ö]’›v\â'ÎC¤£î^B/fM-n͆÷ ªÙÐ÷%ðm\pÔú¦"æ*c5Ö×ltÖáĉ8²Sµ@Ù«ò¥›%>硽9O°EÊ«¡xc…ÿUÕÓqŽN$Ù¾àŸ]NOqà$opíìu’ÙÆr¸n¯‚‹Â?.ê68 Àeï”ZÁ½©ó‘rh”vžWyW[s]ã ïø+Zè61½T¸‘÷¶þ‚1%l6° µN«,ÄWDÉKð”ѵ"ÚRè…aG&£r¬ð¯sr´*ØR-Lñhœpèä@ÅÅ·éõ=4:áþ%1 ̘¹Ž‡EíŠ:q–™YŠIhNHËž!j><yv3:ÐÊŽŠÑ|eORE*Êdð £ìH¦Ü…8&F$ILŒ“ªÂÒòÕe²0¬¬™|%|HL’¾Ÿ"Öñ:CykQ.ÒéYui.U•²úÊT‘+òdL™Q½#{ss‹ÔôÐ mŒ¸ÜÌ[¦˜øø`(þAÐj£e@ZØ'¥(eŠ‹ôˆ5íñ¾›Ÿ8rƒÉªáy= ÙtõÞ¾Nô~9ÅêÉlRfÇ&_°Õ}QÛËÑ:s5Ç\UlÑôE„ ‚_G=1GON®ê ­šëokƒg†o¦€„¬–Ë>®íÂø!Ü‹öiçD‰ÐŠu³$¯ÂuC»È @êC‚OÏË.|mõÇ‚‰æ3äømŸÐ›é¦€i¦š¦šhši ¯e¿";T_s5aÚ¯e¿";T_s56ð½»DÛÂöí Õ÷û}ô_ØÕÚŦb½‹ÃY^}:ø«’Æ_Ì]cˆ·mÇŽ<¿xqG_yYk‹¾Ðl@mªÅ¶ß 뮦[ð*è÷½¿”Þ"²E³ŠmÛ°é|† >¡¹\Y_nFcä4bv;§É¬I†£î—¤1vEl[:ž<~z'lFî óÑw´tÐðn¼ÒXýùDLŸ.%bHBÏ’üašÒ¶ëIl7`I78l­aA¼2·¥«—y.®–âÊ5NÄ­Éûð*l¦mGâVæÕge^Ëyׇ”AÌ%.ïPf°xÊ"Dà6ŠÕ¢ÍAã˜ÂÈyâõ®•E[a3[jÂ;ŠbßM†ôb% ? @l6¾²ê§shh 5äàª'g”—9¦ž5äê±Ú¨oÞrå!ÜWbþ#³ñ/Pç0Pþ›Xꑲ¶,kMˆ f´¹È‘‘b ¶èÆ–’‘ÑR?>Œj’Ì1.½V~PIuå~^rœ2Åb¾s›Dƒ?"gã…«íâylI>Ò6E¹­ëû&~GM•5ìo>¢ÂaÂAAfåæòôÐ.æ_ä>Õüǽ³ºã¯½–Rþà–÷'Ï»çàèzßÙ²ß÷þÔþܾνKúø…í·’yþ¼óZbÆ^óû7cç´wüÃvAQߟz¿ ýAÝxŸ±þ<óÞoì¯ý=ú£ÁëÛôÐ 4Ó@4ÓMÓM4M4Ð 4Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ,•Î[·XÊ$ƒÄÜ´ôìy?çž0ŽsQïúÚ ½ïø1@;ª UèÜõ2|”Ÿ 3nD^¦lY1ö¼¿¯6~OßVŒ‡ü/×½µ}þß}ö5v¼÷U%úÏYýÁºógäý÷õhÈÂý:ógäý÷õhÈÂýNtÒø¿uŠõñ~ëðn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿S4¾/Ýb½|_ºÅ|¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/ÔçM/‹÷X¯_î±_ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ õ9ÓKâýÖ+×Åû¬WÁºógäý÷õhÈÂý:ógäý÷õhÈÂýNtÒø¿uŠõñ~ëðn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿S4¾/Ýb½|_ºÅ|¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/ÔçM/‹÷X¯_î±_ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ õ9ÓKâýÖ+×Åû¬WÁºógäý÷õhÈÂý:ógäý÷õhÈÂýNtÒø¿uŠõñ~ëðn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿S4¾/Ýb½|_ºÅ|¯6~OßVŒ‡ü/×s“¹?ìxªˆéö絩÷£Ã+$ ºõ[#,H\[²‹j©o¡íñȉ¿áøæVìpÊÙáà•Ó½{g{rÆ5^<Ë~Dþv¨¾çjma{v¿é6°½»_ôµ¯¿Ûï¢þÆ®Öyx¹¸d[8“˜L\CÀz<‰ åèÓ°QXeÅ &E¶‰çÜRNXcÀÂE»i飩´.˜$¨Ê‚{Ž’—޵UZPׄX§ÐÓWßí÷ÑcWk üÀ« ?ØY)è…Ê¿>‘\Ìm2æÆP’Vlµ`m)r——^•j¢Y>€TE\õr™’ Ôì¹Ã`ÄP¯v[ÒQ¡ œÐÆê€Ár¦ëP#ï/RyBªÉC€4ãyV¶aZÑ ÔÙ¶‰Šv¥ƒùs ޵Uw6têÏH4k©·œqãïÍͲk–ka+ Ò õÈ: ªl×[u] ²¡~‘9½¿€0IÔƒ'Ðy5¤ß8¡….â»Ä×ÆÞ‘ÁKážØ5æô—+Ì…ò8ï"q´ã}ßl Ù%ÇÒl ¸yX‹:éo®( Þ0A ™»r"Ñ‹ÜX§Îˆj¥‡Öˆ_ZSñVrw3qK—O%ÙÞÇùO µGç ÊxªosǞื• <š5íxC»Í<ÅÆ]ÛˆÞn0MÖÔ=WAD|´ork…ª€ïI² 9FÔ(f¬.oZàuLu°8fËÕ‚ca!x@‚òDs‚ÁíëðÍý’‹iñ(÷x'q}šHIOòVâV £eÑŒ“Es°D©TòFÍwªcÇbÙ[ÆÞ£-‘}G°3m·qÅûzê§jªD¾;|;Ø£IQÚâM¯äß«ò—Ý÷ÎïæÐÏNWcÁ›LΤό΀Ì)¬¸¯´ïpB¿­AÞÐ[hC2ª-PmÉÊÌ”à'Ž“c¾kðÓf,V|¬¨ÃÜÂ*Ts15Íü>ÄìaSžä^$J8&¦ïq-at‰G‚èÞ[+C^B4 ›#%Õ]ý[áfÐäŸ1e²p3 Xê- Œ™^fVo%0ØxñpÛ¡”EÝ›Sš+f=1@Í1ÝßB^YSXˆAKãmx'WI(¤—W#gs°”O4–@Î2C8•ŽÑ ËÉ#6Ej&“$n¼’ ÛYƒÓ¯mîªâ^D«º§²“S¿+n~Ä jÙ›±øcÏ‹¹»”›\xÊ÷Ž(b¾AcsüWå‚0 ê°’&û'1CbaèñFbåæ1Ñ Díçpü]ÕÝ‹€ :dµµxól‡Î6N}M÷Ù@Ía~Ršß–WŠ+L££åél’#à­¸I¯_SêA­rŒd)‡®œ@ªñ¥"{Ÿ#vßÐ7xr̰¬rÒU”“]m~†ùï‰BX¾èÌ7ª±´EQ’X§ËCÈIéë­b¬)/!˜ÆÞi–Ⱦ µ&¨Ÿ|HfS·Ç³ÆE[¹½7Å\ªIfbH-ò†4£--£°²­¯#¾$\’_ ™LX3ᆑÕˆ4Ä*Êiö B·î$Ï Ÿ'ƒkwz>ôYR(3‹ÛNÂæåÅ,ViâÖ>59/Ø`Ðú º¯ÙÄBGF_H¸°VnAM\ñPPM£ÇeAE./FsnÐÏà²_¤IÍ”e× ÊîÀ“‹q$L±`ÓU_ª±Ñ ¢º¥n…O]X’.’ËñÃYÐBˆøâÒÑÒÄ'$è`>y4ðû#úÒA ñ†j}i¦š¦šhši i¦€i¦š¦šh«Ç™oÀHŸÎÕÜãÍXv«Ç™oÀHŸÎÕÜãÍM¼/nÑ6ð½»E¨5}þß}ö5v¼÷^„Õ÷û}ô_ØÕÚË·3lþsä_0œuÇÙØ §bóNÀð«'†]1²/-FÆ). l”GV.dX&ÅfÉœ©á 7’æš3jñz¹ß|°(£HúkO¹‰¢qðmw,7ïO+ütâÉ¢=Ÿ”¤ˆ€aÈ{M"f%Æ9®O#Ò+¥ö³Cx]Dõ¢kÒùô’†ìdpT\lV{z{-qÓ XM…rY§FÈ/IQ¦I˜»c0îæ×ä(6ã-0BÔêŽZ4eYlî²eŒîïÉSÒ‰H;˜t=¾³} ¶xB6åýNè¤{­ëèQøèölxåÅÛÞÔôÕ{zó@ö%÷Nýšñg±=ßÿbŽ¿0ö…öPí/Tw{ÚÿÎ{A×aþ°vsÙƒÆv3öO¬{íû®Þ6æÉËýuÒ<Ïß.–}‹4ªSXê¼¾+ÆR?"#.€zqiyiåtuwæ¥Á±+÷X‹a3fy°¨ú𸚔 ÓUe‘üÔ•Øÿ“X8‰¯8rfˆCi\èLˆ·›µTÁ€«ýƒp‹•€Ú]:ÒöŽëÿÓãôÞW,ø­U!’Ú°vÁËFìl~âO?¶ÔùäòÉ·f:Sª10²#<ÉgFí€ ­Þ †: ÕŠÙ®´5ȾBmš+}¤l¥éñ%à Ê‡x–þnàc¦¸†Ç˜æTc+0-œžV…NNY7H,WXFj¶M[™ad¾c¦dƒm:Î+ŒÈÇ¡N&^ÕßDª½¦*‘lNÒ æùWÌ‹\æn Œ’OAšmxå$KªªE Ú­¢Žª"f-  Ã!$bm~Ë¡wpV®Ü .1á-ôŒ0m¯Àíí5Ä8§Ìs ³fÖU69:âó`#a›šõxÕUÚ“­·LÈ—X uÍÐ`IlPŠV¥èA`ɉœM‘r‰õ–5°fvö€i¦š¦šhši i¦€j¼y–ü‰üíQ}Î<Õ‡j¼y–ü‰üíQ}Î<ÔÛÂöío Û´ZƒWßí÷ÑcWk.ÜÀ’Yãšãy)ŠïVèÿfÓ Â<Ö¤{.VÃhD“:Ôêw†ÉuáfMT4ÓEcŠÛ'z"¼K!`T™†Å¤âÙvê%«ïöû迱«µçº¢ŒÎóÂ~hŠÇÅűÆ]ãÍ·.« 4<.ßÌC Ièü¯!ò ’Œéɺ +ë#|›µÚƒg%stü‡sê0¬GbÛßlËi|6/.œ¾ Åü˜žPQ®r8«Gù3g•S^Hqìõ– šSŒÑœd@NàNS-.¯d€¤æK¡¡["³hÛÂ$SJ»€±Aý?i 3;šü·#ùˆ¨?Ká‘ÆVaµ7++n_H¥p_b‰˜·@ß“.ÆY…·…•ãE À£±V’ÒØœ1¿J«ÒbÅ7 %"cÝç³aNûÞv­xG‹>Ìw"‹#«SŽÜ[©{Ub<¾f1Å#Þô…êÑ3£À}‹R.€@P)µ.\ꎦÓ@gSµœ×½ÍßrÏÙQ!ÜîÈ{{d÷Ê›ØËÙ»°ý!Ü~—ókÞ÷ô÷ú5Ò€è>êÿ­}QÛôã^ M £„œç‘JŒLÆÓŒÃì÷ Á$evó…B«3Ø Zä %8 ¡A{ˆ0"×ÍMÃÁ'ž‘ømiªoX¢á„½Â{©­B;d¶îOy{|Ýþˆí—uzN‡¹=¶óîªí÷\ø§èާý£é?4ò>ýqà<Ãþ#@gQYÊß+ðÖ«‘þòî #&/9ûvѺ+©Œáªª¸ ³p0špÙ “xÛòå¤l;~!v9•žPg—ã‰ä»Å'ÃôòÍËé |–+„G®­ü ö6ÜwR‡@”ªq-ê=áHìj‚ª´µãR®IØÍ«{z€’ž¦¨ôlV‚úI}Ÿ´ÐeË~\y›’XËÎq¿R›éw×2Œ)€¢Ä‹ªÀÌ)m…¬QŠÒÆ;f1ÎÂV!ÃP2 …™9|2bKB¾ªL5šzYm:®ŠÅ™¸¤ç+æÖÁÉ.Ë„31ä““Ùf)z–i`¬³Ïq’ÓÏ;.Á¢òÖ¼ ‚°y?¢XYÙãaXÔ3çÃòÒK~—›pšh åeyÄ¥ÉBe[¿0›{@Àè0Í㙣¹¯B·~žNÞŃˆ„gÅ‚i 4(üITEÖ˹=ÉczhÍ€×Á6@w禚¦šhši i¦€i¦šªñæ[ð'óµE÷8óVªñæ[ð'óµE÷8óSo Û´M¼/nÑd®C/¹D?X£‘QúŸÂo²X´œ¨*ýŽ©¢BUDý^»†7…&²õðøcÉßðrw·«âùær|L„þ0·?µ½{ÛWßí÷ÑcWkÏu[ÉÞ…o'zoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankzâcÛvüôÅ}èà¸ÜkSñÎŒ)oy}K‹Ð2ÄÛ³܈DÊfç=¸Ò¤zxÇ!íGÞ‘Çkv_ »c¯e¿";T_s56°»òík ¿.Ñj _·ßEý]ªZ4ó7˜“Ÿ:û%•~Ƹó‰ŽöÖ(úª`9ÏòEr*·ëæ;罵Ͱ‹$€¼Ën×(ûPxÑ/™×Å »q*Ÿ:¿æ¯¿Ûï¢þÆ®Öy[<»³-o?=‡p¢¬€˜Ï«Æ§ˆ@•®þÅÖÆ&åñPÚò4œ„VäBb•ÆvØ£`Ž\²R¤P•¡Ðöj„×â6÷ Zz(û˜ãÍÓý öº ÿÄ7ºšCÊ-ƒìâ7þŒ{HõUçI›÷5•Öý莚êK¿ÛΪóÏ-ZùG€Ó˜_3‘Uúc™JɆïÇ–ÿ/Ïc>à»ÅQI‡¯‚ö­* ·íRÕšÖ`x‘‰³ÄN{ƒ,¥<îEøŸTØT@ۓΖܡ2Ö Œ†‹31ÒÏ4U<Úds@Ûrñ²ý*|¹aB1!›TZ褑W—"”õ¤Š´„V 4=å}t:øóYw…ÁŸ"yEæÖF†s‘Þ&6Åšf2ŸsÎzºˆ‘µ°¶öQµ¤œj&ys`µ´¼´òº:¸ââìê/Ovmk7-–HX„¼ ;çsíìåæKŸ8nQŽ•ŠŒ^¼BT†²éwV§‰Àd© Nåâç›+0RO܈“M‘`ÊŒmȶž63­É±¥ÉxIDHž‚phxB·WŠ1kEe`ÜÞ)6ÅqœðÙñ$P±hƒ/÷kë'wÒáš¶q†S1ÔL†¢ðÌzxñpYBp{峨­¼˜ f}¥§•ÞUÙSXøÛþ ÖºutŸU.$¼êr‚N¹ÞØÝÍ pÇ}œc›~óœ.lDwa}€­Š*³YÑ2¨e›<œ8#|žâuÈ9u4W8÷‘‹X×QØlÛlØ_šSÀj‘ é:23ƒi|룃3ÖIõ¯É‹ŽÇ?¼)a±Î%ñlìÎ,:( ¾ôÕWSQmOÚ££§®‚·é¦šªñæ[ð'óµE÷8óVªñæ[ð'óµE÷8óSo Û´M¼/nÑõ2K™EX›Ý¦!N¢Ÿy0ºÄ3zÚÈÒ= ‰ö‚±»Íýº¸£$;[8®ªì=[¼V»’&Õú!Ι²\ú¸~#î£~ã?©¿ãí4Ô;Vªïÿ_øˆv­Ußþ¿ñu÷ýMÿiî£~ã?©¿ãí4ÖyÚÏÒøg¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}®xÉ|Ìö‰© í¿GùYlŸ3ë õþ žú§Àø.–¤õ^·ÎüGŠñ{Ÿ¡á}W‡ãõÞ³i¦ŽÓw7Ðv›¹¾ÿÙnetgen-6.2.1905/doc/pictures/menu_solve.jpg0000644000175000017500000003104113504650527017261 0ustar kurtkurtÿØÿàJFIFÿáExifMM*ÿÛC  !"$"$ÿÛCÿÀòš"ÿÄÿÄF!1A"Q#aq26t‘³ð$3±4BSc¡¢ÁÑ%CRr&UbñáÿÄÿÄ1Q!ÿÚ ?êÍÛ¯‚Åä2ù+B„2ر)Œ¿—`³äð ž'V[kwQÜ"qŽšâËI’½ÌtÕ'UnzÊ™ú«…~:X£€IVÛĬ=­Ã±·>ߣ,QZÊc-Ò‰åvXÕ¥‰ÑKô‚zA#žÄý>ýc=á~åŒÁÖkVÊüfM²9+6§µ Ôµ Àd•ž>»˜Y„e^`GÎÁÓ‰’$+'‚ZñHÒ–žS®ÎªÁY„)MÀäªóÔÊ Sjn92{súƒÓŽËQþ{gKwc϶±qSodg™šÍ·ŽZÕå†Xšÿe'È<ÐÂ>Q‚4 /‰ðÂ:—+\š¾>iìgr¶3 $ŽæÖ:ѺÉSæSÌaæÚÑù߆nìÕÈ‘ðyÈ3xjŒe¯>ŽB¼vjËåó"u­ÃpGÊAî÷ãXŒ÷ˆŒ.dáí¶b{Ë^;/ »½È]P±‚' Ôb“€H'¤öÖÁý£gdí¨öûÑÀÕ«R8 ‰ñÐ÷Y#Ûœ K(Tån‚ŸâJ Ý{WrKâwö·FèGR¬±Ë¹îã Éö$=qÁ¤è|äí'#åaÓÃ52$ß‹›Ž¡ #êq¯~&ÇoŸ±ô=#ƒùêß~ærYø+Ê”Ö,¦C-œÍušk2Ån…ñZ_•BV¬õ4…”ª£@‘óÛ—eoÃ.á»’‡j«e©ãj WÄ JÓYvk¤BŦGÍÀ>€BÌW”™è#ÍVÃ=®/Z¯-˜bòÍM;sè8i¢É-Ûž“&ïrJ¡¦#³5füåÀÈé-Ê7* eùy©y‡0¾æ)VÚù+”v¶Spáã»QdÈ'X¥¶&«,n°¡v¬ˆ8‘ ^$pŽæÑÎO¼·Åê'„­¸°PcàÊSþ:;1$ê¶5 X)` ƒó|ƒ"Fø©ù㯿ÿ¡µ8ä8#ÔtßÓÔj­á\—r¸ù¯`vÞ F+6þ"Ć›„«v'—´QyZÌ $e´UÀbà„¯øi¹NGõ"ÁÈ0÷g–‹VhéÂnË-xâ«-I:(L+ÄVcШ¢uš…·þܵ7J¬7eÃnXÐ89üµ1ûs®ïý¬Ì~ÿ?óPÉã¡ò¶ªÑ†ÝÛÖa«V¸yfši$H¼–fcØ$žÚøKU^ì´’Ì-jÒY`$h傳/¨£Ï©FÇX_1·³^îÜ66bõìEÚÕ¢ë ×,º"òÇÉ rx~£}ç³ýµÎ»¿ö³1Øÿ§Ïíþñµ:anf²%Ûµ«T¥*ó^>–6X{4Ÿ0PHàðãŸÈA{¼÷fc°ÿNŸßýã}ÚŒ°@žNH1'“è9õü5óÛӑϯ÷þÖ|e­fï…»Ò*óY·6ôpC eäw0HUË@}u†ÜÛºÎS ÛéºñÕ’ê&RÚm»in´ÌZà>s’$n˜äéWf vtN¿žÀñØ€y?N¯O»¥A=€õàüÏùóë¨C|nϱ›[wÍÏz8îO\{0ÉF“0ª³Ã9š9%‰¤CðC™¸ uƒ$fÝ÷üTÛi‹1$4÷ǵ Å…§J!RôTÞ;‚æh™ZN|в7IhˆÜ%ÓÙŠ’_^??€çO~}GÞ3íë;—û#ޝGjÎ4¶FKoÓŽ5£oæšèë(,¿;!õí¨ÿÄ}™_Œ©¹•ÍõrÐcrp`¥1Ô¿4ð½ŠuFJ‰ùÂdþî€ã¨1Á>À€tÔ-á>&/²“äöíX²ræ²ÍZËl‹qZN»v\äÏ124$ÓÓʲ¯'‚h»víÛñþ½¾î4馚ši kÂ@³Rx׺wçÔ~ÄëÛÔM¾SÃv?CꯨÐöíïß‘ôü~šˆwÞ&yü(ñœÁÛËî+xéÍ:KQßvY> á‘”TH{´/×#ë6%Û÷`—1úÖß©v,ÌŸmFü•ä)ÀÝaa]A*á~ñ#°R<³šÛÇBn{wÓ±€#‘íî;úþåx³g1†«¸w$‹<ÍKr}¿j(¼Ø±¶’¬ŒÏ20`$aÏLÍÊôˆÙɵ󈹘Êbs°îœv{3DEY£Š\oÂ[‘ÌWé#¢(˜U1X:¡vo‰`žda'OëÈ{k7ífc÷ùÿ˜ÚžvÔ9h0"ÎÙŠÖIP‹Æ nO3À.0Ä0B, »ÿk3¿ÏüÆÐtmñ¤ûœûsÁïÇáÿSƾ:TAÁúvïî>¿wqÛŸ]k3Ú³GÂÝçv•™«Yƒ ~H%†B’G"ÀåYw äAííÆ£ 7NèØølœ²Öø)ÆF²Ó¿——*˜ä+;~{¥¯Õ Žˆ£D3$jëÙŒ¦HJp©×ÐsÈéõ=øñÏÝëÏ?~œñëíïì;ƒÇƒŸR>行—Ä­ÃðØÙ/Í·vý‰qÉn¼Wyœç™å™V*†¼ÏÐÆ8¡¬Wâá\€eÇæüZÝ•²û¾*¸Œw:99þÃÀ'®•c”Ãiø·ñ¬ð¿ ËeH… MÝùíÉ#ߎOcôü?‡cëÆ€©ù©çÜwûçžÿÿ#QýÏïu¥‘Æ›ø|mÜmŒ&^{uëÍ$0Ržë¬±9óPºB+³Ë91«Æd8O-©/lä£Ë`)d"¿õ–0¢ä0Ú¬ÜGõär[ŸÏ¿>¤zONúj¤REsO9UŠ(Ë»9áT}Iö½ý´À'•Èçž?ííøk÷r1ÝyràÞŸßýãjvÆféå­ØŽ…{oV@¶Ñ/“'ƒÐÜòÃG ÛPnë nŒ°ä.Íþ·ÿ¹Ðt<ýç““Û–‘íÈçòô翾¿± ;9$v#ž;ýÜ{sø~8_ó6¶æÆÜû†ŒpËoŒ·v™ FÏlëÔ¯#ƒÁ‰î9Ö½k'”Ú¶ Á¦y7f[#b8¨×ËKi+³EbVyå¯â•/³b­öi·¾ ·œöäý{ÄY?ÿFÙ›âvߨӝ#Ýt½ÔéíyǯsëÏHîx=øüÏÓXý³“3§“O$4ñƒ2DÌDR–HÏZ#õ#†BÁRT‚£# p=½·õý~Zi¦¦šhi¦ªv`ŠÍw¯:‰Ç §ýaÈ%OÕO‘îžuSMÄQÇt†(Ö8ã^#AÙPqèì8ôüµÎû¼/ö³1Ù¿Óçþck¢ý޹×wþÖf?Ÿù èˉä¬ôh¶͉²Vf{|×cq^¤¨8yU”îyT: 1XÈ–+M yÞÕvò|©¤uJ;|¬ÞdL8'­¹=Ûœ}훳¯SžÝ§ž•›¦üÐω£–Ë/vR¼'—<’ýµ ‡Û*–g/ygyqqÝvòf¬òK%Hä’x’/žŒ€ÒÆ‘ƒ†!“¯.|FǬ¦ÁgS-$‘ xÇŠ8¬ÜŽTÒUë‘V5d­eŠNÑÈ<¦ ªÌƒo£R­ PP£ZµkF°Ã1„HÑG ª£²¯°MVöçÛë­¯‰ØË—š¿¸®Y­غ•ê+ŠCâ,W”9 C:ÃZªÂB r¥ˆ·cÃ|’Ê;Ž;óÁ<m¿3ŸÙ­©ŸÜ+_â[BÍá˜c2ùQ»ôõO~ž>îyöÖ±WÅ=¹>o'I~1«Ò­Mãt¥aç±4íd4 XGæ3Æ*ž¾•% ȬÄü' Ù3›ošÉâ2¶laì|M3^ôÐ$ràž˜ÙCü¤¯Îég^8vÙÂÀ)©hä'É×sž‹S‰üé;óÉcfnåGQà‰TIÔÇË…9n˜WˆÐ±èQÉ×™=³ƒÉÏ~ÅêFIoÕ‚µ‰<çV+É$%HètydutépÀÜÅž/}m\šÕ©e|ÉmXVV‚Dóù†Y–DêQ× ÇÌ“c-‚±#f1:9z¯c7Ÿ Ïb«¥~Ò^)@är@xÙ{vn9Ž sqlNK ¹hÒ³g6à¡j”Ý6¦’¤-:°’UªeuõìʪÌÝe‰,ÇU“Ãý§9*Þ¸iH¥†ôñÏT'PHà•_®•d‘DqEJª ;jmíárÅܯšÓËTä†há5Íž‡X¦ŽHܰ·:Ÿ1\Á”+Fͼs¶îÞÌî±M-LeYîL°¨22FŒì’$ê}xÖ¾qO5º¹èfÛjƳÉ[/=t&Id²FGMkŽ® !rT/§ ÃÚðƒgXÆÍjò¤OŠ\rŠ©qݧHâc2ä,“òtrÊB Õ|߆œ¼W©ÜËfÛpÝx(¤‘êOm%ŽÅˆ›Ë2o‰°@wtS!áxT ±M¹0âÖ´7©Û|çSÐÛ‡íãXüÓ"Á¤^†òÊHé A÷FØ-ÖmÁ‡2ׯ-‹›‘†Ž£–I>nB#£« ¤z‚4ž á®f°ÐE«JÍšÖDѤ×lRuùYy†Õrd®ü7vUn¥êCÀrGžmÁµv„8S 88³fÑ­M>ƸžÄ³cáWäÍ¥y8Uì}‡»p{ÛmSÏà/Ãj½¨ÕÚ5–7–dW1J¨HI@qÔžÄêÏxîùöî[ŽM§žËœœ¦ ³Qz‚38ŽY#çN„0Ž’½?ª'¶‚Šì*±d¤¹w11Y³rT0h\°³ lÆL=eŸ9 #º}·eP.§ƒÛn ©{n-Ë¿nxìÈÉV”qƒÍHàZëúÒBäð¤ža‹£o]Ɇ\­'ÈSˆakÇbüÍnµð2®¸¸Ds UÁV=ø£’ÝÛvžØ·¸×/ŒŸN5•åŽì>·D’4Hë´‚T*]‚Ÿ1<0:çpx8˵×j`DbŠ“]|„Øë5üù¦•‹CQ q)°ýÙbDá€n%nÃážØÂï‹{¶hÛK8RªLSÌKK*Xò~$±-'f•”*^›G;ƒÆÝ‡Ìc©[šH¢†¼öR9$yKˆ•U%œÇ'H–(ÜsÁÕíFÙ;—û27 çü`»Å~ ð¹ëýCÕéú½ý;è2ÿ÷:iíÈ b4Ð4ÓMM4Ð4ÓMØëwífc÷ùÿ˜Úè¯c®uÝÿµ™ßçþch']û„;—jg¶ïÅ Ÿ¥(Ù¥çù}~WšŒ]<Ž 9çŽAôàŽN°–ü:Û=X±8l>*†#3ú]¨× ‰ ÓŠÒÂÂŽÕ¤ÃðOÙ/aÀ:Ûr¶«Q†ÕÛ¶!­Vº¼³M3„HÑy,ÌǰI>ÀŸc¬VÛܘÁñ Žk‰5~ƒ5{”g©:+óÐæ)‘¡ºX㤔p *Ü' Çî-¯=̾ڷ‡¹ÅÕÃå¥ÉÏ\ã¼ÃeåŽXäନ±±gbÅ_—`Çk,FÀ­“,6k‰*î\†~ËGL/Å=¤¶½ Cwe[J½GžD*;ÀØòY¼n;/ŠÅ[–dµ––Hitבãy#¤e2*”CÐŽÀ1A[ŽxÀ¹°våݱ‡ƒ >hä(P¯,lB°ˆC^V3!匓à;ò‰òŽˆÐòZë=ƒý)•Û·…‘ÂäçG•Ô&¬õú9äÿ«žüô‘ïγ?_ õ?Mk™íï·0y¶ÃäìÜŠÊWŽÔï:İV†FuY&™Ç sœ´Œ bx#sll¦o%¼d—pÕŠ–ãÛË„H—Í-`¢~™ZS7mJJô' ät’ÖY_ â÷´Æ[¼±d*1XÚEêT/ÇO_OKtsÔã$è[ËY:UrTñöf1X»Ö+F +"õ2㧯§©‚sÔU€B1y¦­-d©VÉRÆË1.—ò!Tfbî@*/*¥Û… è¤õ:ƒæg'GŒ—%’ŸáéšbŒV%$·à”òÌxUPYˆPH Ïc®uÝÿµ™ßçþck¢½b?÷kwífc÷ùÿ˜Ú€ÜtÎG‘Ljé?ÅC,=7+ 1e "$u§~ëÈê‚G¨Œ[an{x“B mÊQÜŠq·2yûy:–ÂÇ4oæÛ±‘CaGå:+ÔBi $·?øòwôcÏÝßX­¿ŸÁn*R]Àf±¹j±Èb’jV’tG¬ÈH†ƒõN¥WÚ[š”" ðáç‹™³¸’[’%«ÑÙ*ÖQŽµÒœùc¦¼c¥Cq-áÞNå¬ZÙáÅŸ·‡0«yôo܉£yÁ1èi-H>r ºÀò#-½ÚÊâêäicmd©AvÿY§ZYÕe³Ð½Oå©<¿JOð>‡W‡ÏQ ÇþãÇùè#ï¶5Í—K'ñ¾Myn:*Ô§-sQ)âUXjUU‘‹•v1³2ÇÌxSßÚÏï+û‰mõFqÔ«ÃŽkóÅVùŠ[m,"…x]l'õô°nQмrH§·<öãמÜ~:Äe7FÙÅfkar{‹G)o¤V§bìqÏ7S^„bº˜ä=4’øK“xî<«î)ª>B;ÿ —«,Kl5•‘cŽU–vŠ(éÛkÂÁS…Xþ³~åò;fzXü.ÖÛ(×a™ð¸¹úèÞXÒT>w›Y  ÆXßý5cå‰1˜$H·¦Î–æFœ[³%œdRÍ~ÈÄÏR8<ª”U$[€®«íÍÓ¶w!°6æãÃæ~)Ÿô}ØìyA¹éêè'Žz[Ž}xÜ©‡­€“nä°¶'µzSiô´–:<¦:y>aë‘ZW‘‹:žXÊZh#Ÿö¦äÛ»Ÿ!5šTå£vþFÃY]Ív@±Ø³$èƒEä#|ÈŒUÁýfäòTÈÝý}ûŽW×ðïùzw÷öhH½¿g»6.^Îбµqõ±¹,hº¶j·DRÍ#ʶ•¬Eh‡`CKó:ßí¢I–kf-lüÖÉKŠh£Þšt:ˆY«ô¢#¡z§Eˆƒ1G2´;‚Ûª×%¤-@lÅM$>`ëHܰG+êŠ?ö=-Ç¡ÒKU£»),D–¦¥ŠpDR¡WÔ¨.€‘Ø^}FƒJñfd²ô748Iéõn<4ØËKx°ò_áåH$Ž@¬Á9 ?hd@¯æ ³vÕ}½‹º›6•JW­„Öe•âi9!ìÊ9&i¸f,䬓UyGfLí‹ukM^6a†KNc®’8V™‚3•@X„FcÇ¢©>ƒ^Û³ZœI-»VåHUåp€Èî“îÎÊ {–Ô–ØÃUÛÛzž›ÊõêE塎}ÉàW’xD ˆ8TUP@û¿ö³1ûüÿÌmtWú§þºç]ßûY˜ýþæ6‚{ÞôËà3™*Cu.Õž»Wžw†9C©^†‘hÕ¹ º‚À@çQ€Äï‰à–ÕšŽÅ#bºÚŠ{4*gn@‰cì’zRE“IZEûXäžà§‡ÿðóêté èvôaþ]Á$¿·}àÅíߥ“ŸrØšz¡Ñ*pK°Ý$È=*`ÇÁ‹ ˆÏ3–ôUÃï]…kwx·’´ñckULcÉYÄ™¬Âÿx»Q³Ö¢´è 7XY “ìKŽüGvsÜz“ÿËO~{’;vïëéýsß»AÍ›ëo—üC;ggd¡ÈÚ»“–kàæ¬nÓlBQfhÂÎ U¼µf.ÿj‡Ï©KÁzXju²1c°¸ê6žXÌòSÙv° "ð|°R~L¬¬$$†==C€=L€0àzGaÏáè;s÷Ë_\wHävqõïÉãB~¾¾º #|ä7l™L)É=E$¾ñãRÁ§™Áš¯?ãXéó:¢âP#ôõ‚Öì}}¿/C÷ëÎ~^²ÀƒèÃõ}8ãx> {Ç_G»Ï'Ÿ¯'AæšnGÜïÓýÚ6º'ÛŽßã\ë»ÿk3¿ÏüÆÐO›Ãk/·óŠY9±V¯Už¼¢'®«º”¨ §©zº‡w£QOxæ,øi¾|@•ÿ³ë½j¸ëóMå%ˆài§ èð2Le´i,²×òã¡féÿÇr.AþíSœ‚¤qî=ÿþüs¯[ƒÈn“õÃü=þ‡s—Þu¢Ëøo#n\T•óY ª¼¿kTÞe©2¬Õù”uDeé\L®gˆ£ut3àwOŠ9ìJç嬸hG”ÿÈ|§øìzU†ÄݰD„˜&0EÀò£ír $nÅæRÁö%‰ïÛ·N߇×ï:ñ€SÜqÇ$àé÷zñߟϷ=ÃVÚ¹œü›“+·÷ Xö³R…\’5ä¢NöÈùÉó 5b|à0qöiÇÚ›³Ï<Üyüýõòêè'ýb=Hç‚~ÿQëÇsÛ_G×ÔŸ~O¿=ôi¦šši i¦š±×:îÿÚÌÇïóÿ1µÑ^Ç\ë»ÿk3¿ÏüÆÐO{ÆÕª;1z•œm[UêÏ$dœ¥TuF`faÜDåˆà…äý8Žñû¿)Æå«ä¥Ìd3Q ²TÅçáƒã%™GÈØÈçYP¬2¢ÄÒ!‚Vr”¬­?øÒû|ÇžåGŸqß·¯¯nÿž½ÌÙõ¶õ½ÔÁC†µ/›=ÇÄ•æqÃ:tô–åS¹‚‹Ç`4œ+P¡âÒYÁüZàæŠÝŠOú2´’º·£ºÔd¬:£ µUJ©È° "ä y·¼GŸ7¾&ÂEµ²#nÛ¢¹^ÑU’»H’´¬`ÄeâeVYäbZ0QK0MÀÁãiÓ¡ÃciÔ£+KJ õR(ëÈÁÃ4j£„,%¼$o^£¯ Áa+çìg¡Ãc`ÌZŒGc •#[ ò³€€¼ÇŽÇ s Äx“k5[N<™¡³bðŠQQ«-ùSÊ‘ÊUXBeå°ý%”˜­Z?îÒÃ\™)þ˜M¿Ž’þzÍɨâIìÄÑ¢F’E=”jS«ðÑBîŠÈB? "æ1xÌÖ.LfgO#FP<Ê–áY£~`p~`ñ_áigkí™ÿE‹;{'ènŸÑ†J‘€é ÒaùxˆŽ…㣎:G«ÆƒWÏnŒ–ÛÏoû¶g›#ÃmŠ™šøÙ<¸Ö7黿F’úа«=}\1b;|º³ñ~å«d²-¨˜ë9 mÌ·$¹ÓzëDa`#¯(‘óÏ¢ÀqÝ>÷[‚«žŸp×Ãc+æ-ÇäÏ~:¨¶eAÓ´ `<¸Ï‘ÙQ¡µöÍlØÚ;sV„õþzÐÒDŠH ;Ý@éd-,‡¤Ž9‘« Ãä7ÕËìÈbZW%bŽAè_YR+1Ö±#EóAö¨²A($œ2/ ‚Ñë¸üQµ„ÄßÏ6Ý‚LDO•«E× Vy­PŠÓʲGåtÇs…u‘Éå U,Bîv6¾Ø²¸£cnáçý ʼn*Fߤ$>WID§õzW鯩¶ÆÙ—'ÉË·°ò^È×5oÚzQ™-@T®T™ª(*Ç‚m–ÕÜWrY̆'-…ýv¤în+ÎÓ$^c(&¼£S"/n™žÛýPzzz‡<~>¿ñçTc©Q/>EkD·&‰b–Àˆ 5,È…ÏÌTb;ú±úW>¼ûžäŸS i¦šši i¦š±×:îÿÚÌÇïóÿ1µÑ^Ç\ë»ÿk3¿ÏüÆÐN%fmíݹ· ŠK˜¬m»Ð,ªÌ…âC*zIQÏ@}î|ô8õ?¸\¿rí“R•:aÖ% $…‘ш㕸w„àrÅTßn,eæ3%†ÉB,cïC5k1u²õÇ"•eêSÊž ޝ}kéáþÝd§$™ûϸ/K< ¡”4¼Åàb®ÊÆ6^¥fVåOrO¦0û‹Å­±€Ãcr™T–­KÒZ†:ÍXž«ÖÅa7™^b®H®&$©èêêNª³øçîì¹ðwó±Ï~x9‚o‡­iæ‘Òzê‡ÍTëš0ʽk{•ð×gäñߣìã­Ç]ª½k¦JÍf·f[ ŠÖ:šIù¥ÏT’Iv&ò=¶rÁ¸Î4þ’­fKU¤óå)^IUÖfŠ"þ\fO1™úTsÖÁ˜&ÏL¯|BÉæ±Xla+3õØرú>k¬EX‰>%±Ôá¥O*dë$ª08 æ_#^Î$ʨbéòo\zÿ)y#=dÆè=B³ÄOËÖW`“hàdÜ9\ìõ&³o-LQ¾–mÍ,+€xŒÀÎaæaÙø’wùØ›*~mJ‘äVNFÄ}3¿=rIÒãÏgê“©¥ê,$~®zߪ…ïvù¯½ÌlÒÇ~)ãš¿ÆÎ+'žŒ“¼P‡òá‘Ä’$j®|É <»u6ze]íÏ[9våŽÉc­ÕŽ+z’I^Râ)‚J‡h¥tÊ¥Z/#œ÷ð?†¬âÅÓ‡1c/ !/Y­ idën q4éç¤pÓJy ÏÍëÀ^ŸSÇ<{s¦ÏL¯4Ó8Óg¦SM8Ó6ze4Ó8Óg¦SØëwífc÷ùÿ˜Úè£ÀÈýN¹ßw#6ë˰ƒzb?ïMž™Xée’Å«Ï#Ë#LåÏQ$“êN¼à}šj^FNÐiÀú 4ÔÐiÀú 4Ð8A§è4Ó@à}œ ÓMôp>ƒM4ÐiÀú 4Ð8A§è4Ó@à}œ ÓM)IV=$ŽÃÓñÕ• ‰ ’ç’4Ñ_ÿÙnetgen-6.2.1905/doc/pictures/meshingoptions_6.jpg0000644000175000017500000007121413504650527020406 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W®xpu°ë<ŸüU'ü!~ÿŸÿ¿òñU>ÚaòO¹åÒø\œÜoû Ç&Ÿ&œ$m²(ŸŠå³»É'éIg¯j¶Z,ð¥™:+ÿäÿâ¨ui5k1¨É+ÿäÿ⩺ԚI­…É.çœê>*¹Ùek¢Û[ÂÐéXK{4¿B2FÛ°;‘žµ’×ןðÛh¾M”–öĘf’"f‡q‚°8çäõÏøBü5ÿ>+ÿäÿ⨠ðÙ8Ÿúï'ÿIU¤º1¸Éža/ˆõkGU¼ž:uÔŒ^}¤Ð³@|°œnÈ#õëU¯5cP¶Õ¡º’Ùÿµ<…›•$-”XÀ8ëšõ“௶}g“ÿФÿ„/Ã_óâ¿÷þOþ*kG°rϹåskW×€¼¸²Ó.-#´&…Ê…BHl†7'GÒªßÝê¾¥&¡¨ËLȱªD¸DEè<þy5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUR¯I;¤' >§ù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU[‡b}“+ÿäÿâ¨úÜ;²gù^ˆæGaòƒÎ>˜¯b ðÙ8Ÿúï'ÿQ\øWÂV{~Õ0oÎß6é×8댷½/­Ã°ý“<‚ëKѯg3ÜÛù’b¥Š ;'·³Œ¢°8P­ÔýkÔÿ°¼ýû/ü?ü]Ø^þý—þþ.§ëï{’G—"Û=§‘pÉ\‚¤ÚxemÓ1Rydtàšõ/ì/~ËÿÿGö‚?¿eÿÇÿ‹§õš}ƒÙÈòçhÍêJQ‚qÏñ©X¥ÃΣ¸ŸcdÐW¦ÿax#ûö_øøº½ÿG‡èÿ‘¤ÿâ¨úÌ;0ölò–pÛKºm߸í @Éêkœñ*í´‡ýÿé_@ÿÂáßúäi?øªóŒÒô}N–Â×Éw¸*ÇÌfÈÚ}I¦«Â^êBpkSÒ¼ÿ">‡ÿ^1è"¨x’þæ+Ä‚9Z5Û»(pO$uôâ¯ø+þD}þ¼bÿÐEcø£þB«ÿ\Çþ„ÕÃ=Ù¯C}tÚË W©†IÛlI%ÆÓ!ã…òy=EOöûÏùûŸþþã|A|šv§v ¶eíœP¢]ËE òdȬêJøÊî<7òYë÷Rj3ÛÝÈË,µ´°¿îåVS䪟; FPî¯*~c’Z@î¾ßyÿ?sÿßÃGÛï?çîûøkÔôíf?6+ ‹™mÏ•#—”™$oÞ 6áЯ>IÀdPÀê¦[#R’aöëûÑÚÅå˜äÙ¶]òFæÉU(¿1eoâߎ_Ûï?çîûøj+}b[È{]Iç…³¶H§,§üu‘âĘE"Y3°”‰ FcòÎÜ/pLâ% çæ#%¯è qŸ*ÝZÉm!ºž@’2Uågåb:6> ûÐÁâ-BÆêÊu•nnã…Œ¹b¡ŽžjmKR¼mBp.$EG(1ÿ:Ä›þB:Gý„!þu¡ÿ!¯úêÿÌÐCX•¶cRs½Ú5ÄçæuÎTsÉ[#¶¥KöûÏùûŸþþó·XÖxã´Ö-£ÔÆ£xR/P¬NâuFÙ“É-ÛƒŽx¾nÇa­¦‘:³_—’T a¹@s7%¶Ÿ”adR Ž0[,gj5Kƒ+D/¥2*†d€s‚FzÈÓ¾ßyÿ?sÿßÃ\kéz´‹st<øn“M‰-Ò;Žt2•ÞKHܹVfRX‚_«£¾·[½>æÝ¢YVXš3¹@à‚0Xd€}G"‰`ñ \ÚÉu°²ÛÅŸ2hîw"`däƒÍZû}çüýÏÿ qóZêÓhÚ¶!½7RÀ©lÒI W;Æìeâ*¾X$ ÏßÈ €eÖa»»º´xôýXFP<Ík|"+ƒŸ/h•W'ÍÏÎUÕý¾óþ~çÿ¿†ƒ­ßØE-ÊLÒ4q³•‹)ÀÏ­r–6ZÊøŽi®g[‡‘²2c’3ˆ›… É)ʘä–Û¿ÿu×ýräi¿¬ÞÜÙéòyž[Okïåe~f>žÕ“>ºme†+TÃ$í¶$’ãiñ‚y<Žž¢§›þAÚGýƒáþUÆø–î M@¯Ú`†{‹qYn È ¶É/Íå囘ù °ì´ÀèÏŠíDò@uøDÑîßÛåÚ lŒä`ŸL¿öûÏùûŸþþåõ+9õµ©mfŽ÷IHmq#~û¡ÏOyéÍkYÝMs¿ÎÓîm6ã{Fw}6;t÷ÇZ@[Ÿ]6²Ãƪa’vÛIq´ÈxáA<žGOQRǪ\J¥£¾•Ô1RVbFA ޽AqX\GªÝJºÛa¼µŽßfô¥ZB|ÍÇ;H}ÐǃÇLÕ´Óu+'Iá24¯{tÒE$øˆBÆVA2æ3»Æâ:p:¿·ÞÏÜÿ÷ðÓN©p%Xô¢FRʆc’2@ÏA‘ùŠáì4í~K˜á¹{Ø,¼ôg>~¯—0q“4­‚|¡Ã uP-ZWºDÑjv-Ýá·ŠHB›ÆB td.r2ƒi pÌF܇#†QöûÏùûŸþþ·a·)3HÑÆÌV,§>µÌÙC©/ˆî&’+“hû†ùäÂÆ6ªÊÊz?v‡–';µ¯ÿäuÿ\Ÿù@oßë7·6z|žg–ÓÚÇ;ùY_™‡O§µdÏ®›YaŠãU0É;m‰$¸ÚdÏ3ÎóÎ͘ÎìçÇ9®?F[ÝJcp³ÜÉi%ÕÐ7ï1µ¾ùQ «ÚÁ€?(áñ„‡MÔ-<s¦Ãkv·QÛ¬Q:^ï0P7¡/òG¤ Ž7 ƒ£v_o¼ÿŸ¹ÿïá¦RàÊÑ éLŠ¡™Ç à‘ž‡ò5ÊjÖzÝÕÔ×v <³C-8¼ 1Û´»·ù'‚ nywcYÕK[^µœ¶±„+piíÂ1¼$2 ü£*NG :·ÞÏÜÿ÷ðÑöûÏùûŸþþáVÃY:TžL”¼êóE=á›1ía²"'a¶’K¡n{|•~ÇHÔ¤˜}ºþôF¶±yf96m—|‡‘¹²UJ/ÌY[ø·ã€±uÕ`Âîlƒž\‘ùUèßyÿ?sÿßÃMT¸•KG}+¨b¤¬ÄŒ‚Az‚>â¹»(u%ñÄÒErmpß<˜P8ÆÕYYO@îÐã’ÄçtÛêgDŠ)m¯ÀŽòS,&ìyòÀK” “¨Ýràár8 \z¥ÄªZ;é]C%f$dëÔA÷ï·ÞÏÜÿ÷ðבâDKxüé"ËÊwÄÁü©yÈØ’ À«!ÁV‘y ÐéšuÌR=ÍÝÕÙ˜ÜNDm6äòŒŽQvôÆ ~ðé¿-onþÂ)nRf‘£˜,¬YN}k«ð«µö•·9Ý}x§{öE @Dô^3Žç“šá/ÿäuÿ\Ÿùî|ÿ"^—ÿ\ÛÿF544hÝkúeŽ¡ …Þ¯io{>ß*Þ[•I$Üp6©99 ަ­Ïv¶¶ò\\\¡‰KÉ$µQ@É$ž½y×ÄMFÕÆŸ,Ö°­òÌMq}o Æ× «2¼Ê)‰*§¶îâ`kÏãÜZÞÙÞ}™âpÖ÷qI#Rn6©£;Ä)’‡ç!‹;êcÿ}¿:<Çþû~uÂÛYø–Òê+Ï'Q’ÞÞxÞ{7¾Ieº“Ë%xز§–ZHPù`yLDhpžñ붺=ÄW÷ÞN­,Wmgh5‰íÝdiæ1ù ÿ¥±S ˆŽ mA…ó1@²çÍ£“çFY[Àõ¢°|/<Žš­©ba²ÔÚI%c Œ'“ÄsÛ½\ç…?ãçÄ_ö“ÿEÇ@yWÇ?ùiõôô^«^UñÏþ@_ý}ýÖ”¾4Lþ¸ðWüˆúýxÅÿ Š5]ê7‹žôx+þD}þ¼bÿÐEt3Ë?÷Dþ&5±ÇÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´TØ,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,q²x'P{»EÕ–Û{¨æÞ6J©ç/Zµsá+Ù®æ•nl»³ »gý+¨¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÔW> Ô&´š%º² èÊ3#c$»]•X,ròxJõí,b6{­íc…þvÁe㎕ü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿQ\ø'PšÒh–êÈ3£(ÌŒ‘þívTQ`±ËÉá+×´±ˆ\Ùî·µŽùÛ”sŽ:T_ð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüM^ ¿¶Ò®-^êȼ·Íp‘±´¨û½k­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹Ž6çÁ:„Ö“D·VAFdld÷k¡Ð4É´mËOžHžX†h‰*rÄñ=kFŠc (¢€ (¢€ ÍÐôy´é5Wšh¼¾{˜Â±ÈRˆ0r:ü¦´¨ ¼°¥ÊÛyÈgd2S“´3íÉÿ85åŸÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠUAîq@ EC¨ÞÁ§ˆIæ¸H,zŸÀÏñ õöŸ§Ç-„Yf”,³}™î|„Á;¼˜Èy2ÁW F7î<)  j+š‹\¾vðã‰l¤Šþêk[‘8$¬R¸e A‰„†ƒ$®r¹%ï¬l"º¸šÎ÷ìPý¡RéU O$ í$h7ï <©yeU;•ÈKEPµÕí/uK« wó$¶‰$wR |Ï,{Aï…Á¿nœ 3þ½8éÿbs{$b_9$’þwš7ÆÜ¤¥Ë§+‡ñÛÓµ];W·k2þÖöm%´Ë"†À8%IÁ{Š$Õtèµ8´É/íRþeß«L¢W^y œ‘ò· v>”Q<3£Ç Ñ-¦h’)Ì}Çc¼ŠÛ³Ÿ0<Žþfwî;³ >ÂLêéRÜng_>òi’6l‚QŠ¡Á#* pH¦j¾%Òt]Zâö¶[V»O.T&hÆÞcɲ]續ò)òx‹C‹L‹S“YÓ’ÂfÙÓ] ‰Ûžçü­À=¥iÑP5õ¢y›® _*U†LÈÉnÔ>Œw¦S¸zŠ¡ ø—Iñ$3Ë¥ÞÁqäJñÈ©*;.×d B“…m…”÷4­EPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( ŠP¬Ý?AAV^ ¨  =rÓYÕVæÚ?°%¬„mÜÏ¿‚2qŽßç­Xñ™6·áÝCJ‚å-žò·3xQ Qáü‘åç1œmÏÊW<拯 Mq©Ï"ß"X]^Aq€™LÐù[6I¸OÜGQÞÁw`ž«xî-åIa•CÇ$l]HÈ Ž#½xVá-ÚT:³¤e†æU 1©²äöÜ=h“‡À¬mÒÊóVyl"ÒgÑá†(6H$€Å‰9ðN6žUÁÝ~MY{‹mDk6§U…e‹|–$Ûˆ¤1’«09…LÉ~ÅBô4PZÎÞ YâÓcžÊåâ’y${a ¨/8 îwmùÖ•¤\iw7_ï±yfš+$,†W.ù;°ÌÁpwœíÖŸÚ`ûTmò¼ï³ùƒÌòóûzíÏéš|sÃ+ʑʎð¶ÉX€Ø>‡ §±½IEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( îoEœ’ùSÊĨT 1üõ¬­"{‹½[Rºš ¨£qÄ.©È÷ÉãÖ¶h PðÖ¯q©ê—q]],2ëv7If¦*h£û.ù +¼å¿†vy48¼Qiâ}BêöÊëìò4q"¼ÛÔÆ±.Œ; ^›”p¸¢€8áËÙüáu§ê+u£*%ŵÿ“+Âv2J¨N⬠pvnX©îà35¼mp‰ÅA‘#rê­Ž@b#=ð3è*J(ÏHñ\–ñꥥÏú:ê-|² ‰EÄ%æ·VvÆn B¨uW­ÐìîìQ¶™§kDºa3Îf(Å9v%ï ¿xç°ã­Eqwšg‰¦ñâÜ%Üñé¾lo‘‚ÑǪï×í ¥™„ƒq†BŠC –ôû=V4ŸûBFkv³‘m¡Žøy±)?êƒ.éˆØ›Ž6‘¸d›©¢€8 Ë?Üx7ÃöæÛW”0*^¬wI‘T)gtº…˜’ Œ¹wmÛ¼SUÿ„ËM¸k+¡jÚt‘^4Wa­’bÈÉ„fRHÛ Þ#ï\ñ½ 狦ëÚG‡¬d»Õ/QŸK_íYî®ÙÂίrçÉR†ti£(ýãe ZÞ–y¬uYo:Øßÿ¢ºj2_DcòbÏ—<€]þf{Ü;W[E`ÝÅxÞ:ÒîO좰¹†K ñ„G‘áeÞÔžŠ~òûã&K~huë[uÕ,üÝfÚkK†»Ø[ï‡Î1åßjü“6ÆaÀÚrTv”PžkZ7ŠQžÛO’ö].§òbNó²¡*ÆO´ÂåDŸiiOÞ_”€¥;Ë® Óí¡»¹ûUÌq*Ëqå„ó\ m.NNLÔôPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( ’êÞÎ×͸’Ô¾ÐÒ°8éÏÒ³tEõ!{+4eéã‹Ë.À>¹ëŸz·qimt\[Å6Üíó63×ú X- ¶B–ðÇ’±¨QŸ^(´Ö5˜îôǺÓF½©!š+™ežTAxDf*6 Í÷Ò„¾6—ZðW‹…ÍìË§Ø á½²¹Hq#‰<µ‰pÛã_ã·…+½êTP­j×6¾'Ñ5u‹X´9ìåë Ì·.^TŒ£€ò:nòÀV<>îÀéu[¹¬4‹ÛË{W»šÞ %ŽÚ<I0 É#^•nŠá"ñf­s{ka§^躧Ú.’©[ÆâÝwCpì˜Y2'’ŒFñ¸H£äÈzê4FmOJóîÑÏ=´†0B»E+ÄXIPÅ7c'ÆN2tè <ŽþùõeM?Pßâ'¿¾Š{;›—hâ·U¸û;I8Ž2V×÷Š °aÉÞwXÕ\82)ùŠrT+wtP¥kþ&Ö.D0Ûipyv^1•ËùÛäT)ÙQdX•Ã}™Æ%ÎE»mVÖø‚Ûíï)‹Nµ¹{E™¦d`fR Io“£ÊpK õ4P–ÚüLÔ'e·ó4¶oµE—¤)Š(äŠá‹2Ã<Àl0$¸IÏ–™]þ¨ÍªèÐÝΨšD!&UvU•'äp¡×“Ã[©¹qeou5¬ÓGºKILМ‘µÊ2Ç_•Øsëô©è¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPŠ©åï}ÝqÅR³¾ŽùuX'h2Ç–*O·'ôü(¾³kèR/µÜÛª¶ãöw Xûœgüý)šn›™ ‘Ç,²y’¥`X±<ãÚ€9»Éw©éúÙÜM6­ye+9–/*/´m)) þå2­ÀÇÉãÈ5/ ëÚ†ˆÐ-ö•jnZ)Þ;”Ú˜dÁ)_›cŒoÈÆHÆ7t/áý*[xíå²I!Žy®DrÊd”H$$‚M'#æéÀÅOøC´cim"^Ë¡CrfÔn$wK›ÙËùÛ âs@þ¹yiâý7H‹KžâÚêÖY¤ž3ØVH—?3ƒµC’Üw.Üá€×¾½·Ótû›ë¹<»khši_íE“Éà•Nï@Óoíí »…æKuòмÎY€³™°7+’p8«óÁ Õ¼–÷$°Ê¥$ŽE ®¤`‚Ú€9é|g´ÑÚ\é¤:„²¤ie²9$mé+#e+y.K ¤e¶¯Í[Zf£©b·P« ,ñ¼r9Š:2¬¬2 0j¥¯†´»I¡"žIá—ÍI®.¥ž@ÁÞìX¨Y$“€]ˆ9«övVö´6Ñùq´²LFIùävw<ú³1üx  üo¦ÛÝëí å´›Yn§Ä‡eŒÛb2yƒ¯ Ȫx!ˆe&Þ¡â[k M´Ñkus|V&ŠB1“Î!T³*‚ÞV;ˆ“ŠøkK’î[›ˆ§ºiwîŽîêYâÁ ¶7b‹•f_”•Šô$Utðn‡œËm8žmžeÏÚæóÉMû[Îß¿p:îݧnv€( •bIÕ%•"]D®ûD,Ê )`_˜äÇ•ægfFC)j‘|@ÐåצÒGi¢ic2’3Ébè"F3dl~JvðNåÝ~O 貤HÖ®c*ÜH¢u$±a¿| g$I»%ÜœîlΚ „WsEö¨ÒºÈ‘^L‘ç,Ê‚£““½@l’s’IÉÇšdž—Z¿ÙãŸìä-Õ³Ø&E”ăŸãuç«(nŠÆí/ôûkȆ#¸‰eQ½[†ŽT•=z‚G¡5˜<+¦-»Ä­¨‚ì¬ó NçÎm …S/™¼ ÜÄ&v‚Äã'5§eeo§Ú%­¬{"LàX’NK1<³I,I$’I$ÐôQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*A*r€zdÔuSP}PùI§­žÕ{\É$öüóíÈðÏ Ì^l¬±’@uèppqëÈ5“kâ:æßM¸bðC§>¦’OµV(TD[yÎÄËê8<úÛÑleÓtˆ-&di#Ý’„‘Ëßë\ÕûM*ÒÍt¹ ±»ƒK{ ®­­DorÄÂ|Ç*CË&Îwï×RPõψ¬bÓ¬õVû}•ÕÔVË=œ‰")’Abw ¨ríÉéÁÀž%Ò_ÄÓx{í°.¥I'’Ò gÜíUÎâÁSqà2žõƒ‚µ+}æÎ=n¹¸Õ ÔZy­¦˜+Ê*˜yËŸšÉ.x$8#z}"àëÿÚv·ÿgYbЍüìé; F' “#†Èl‚6ì#uiO<6¶ò\\J‘C—’I*¢’I<z |E¡­Š_6³§ 7Vt¸7I岫b8 3*“ذMI¬i¿Úºq¶ù2,±O•ÜH¤YpÈÊîA$d:Œ› ù>!‹]¾¹‚êøyîû-¶ ’D‚0Ñ‚ÌSÛ…<’w· |´ÒÕµÍ&x®%‡T²’;h–iÙ.ˆ£eޮĕJüÀžæMþÆÐ4í/Íó¾Åk¿›·nýŠ8ÉÆqœd×=€¡ƒJÑ,íîÒ#¤Ùˆcd·d˜Ko0•”7C%¾Ys–Þ~`y ¦ÊúÓR´K»¨.­¤ÎÉ :6py~š®§™%ýª_Ì»ãµi”JëÏ!3’>VäÇÒ«èúdÚp¼šêå.//gûDïF(÷Ò0K1lkÕ9<£7‡o$ñHÕbÔ’Úßr³Ãr«Ë…ïýï”äà.ã` AU`¬u]9mÒá¯íD/]$†eÚШ¤8(.[ Ü=j¼ž"ÐâÓ"ÔäÖtä°™¶Gt×H"vç€ùÁ?+pcé\òøãmŠ>³º-2Õm¬#û(rÁ,M!Ý—lÛ¨| >èŒä›ÿðŽêiw©©dº¿ïVYNŸû†I@Èv ‹æiø‡M¡6¤Õtèµ8´É/íRþeß«L¢W^y œ‘ò· v>•zæ“7Û|­RÉþÁŸ¶m¸Cö|g>g?&6·\t>•ÏCà Öa¹[×{h%’ÕŒ¨XQ6 ‰ʰb<ƒŒ ¡Ko_Ác{lÚ­©IÕÞ³ÀUƒTk†1•ÇÉå4aNÕÚÔÙ_ZjV‰wcuÕ´™Ù4FÁÁà §¬Í M¹Òtŵº¿{ÙÞÛÈP„wr;üÎÇ$à…Â:(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQŒœ )Èq"“ê((àd£~U “ÃÄ’Jˆó6ÈÕ˜í‚Ø§ ǰ'µbjzœú…Õ¥½½ž¤±­ìnîð²£ oåÐò;Rø“J¼Õ.4?±ÜOmö{öš[ˆ<½ñ'ÙæL"²œ³ªýÓ÷³Æ26¡ž„/©*d,ŒRU‡ÁØ‚)‘_ZOwqi Ô\ÛmóáIx· ®å®G#=kÎ5-ÆZ$Vú\WRÞC=ôÑ\$êä{‰6•VxcÁ•”|Ì (~¶;K©üe¬4ö7QØ\éÖöÉv³*di‹(þbœL0p9Vä|¤€nÁ<7VñÜ[Ê’Ã*‡ŽHØ2º‘AGz’¹¯i—z.—si7¬s<•2¬‰ò€I;¶·£x~ÚöÓA´‡Q¸yî‚’í"íe’¨~wÉPBä»·%‰9  :+Íuë/6§¬7w¶³ßÝ^À·_n+›­®ZÛdk–O-Bî 'Ì âS‡]-M|Q¨Vh´»«kyà´ŽÞz<Õ+$ÆF Ȝƨ)ƒ¸c Æ[ëH.íí&º‚;›ÞD/ .Ñ–Ú§–Àäã¥É$·•C¸áÔ!#9F;Û$IB;]tø&òÚ=&êÚò]Fæ_(Ü(”E%Ã̬†)ЇU ÊïÀ;Š+Î ³ñ‹EiíµnmÙË£Ü*BNÞXvK ùòÂn..8Ç Û÷íi–ÚÜ~5¼¸– ӧɽD—s€¡r6˜Õ'd<€òc;I,åÖÑEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢³üE­G¦Ù]-¼Ö¢ñ…F °Î9Ûô9ª>0¸»µÐR[ÅÏÛì‘”ÆuÔJU˜B°$ðzPõç~,Õtxõ‡¼’ÖÖðêˤŽ'·Š1imY%’ÝA%·c ’_ À3 =;Ä6ú—м5pnþÍ.« ÉrÚy»,2ZL&@,›æ Ý—€ÒŠä¼|ϧjºœwÑ]\±†;wG<÷Úd,ïµ]J4jvüƒà.x—\›I¸³…oôí2ÖG}CQBЫ)@±cz ì˜|Ý"nPÐÑ\=—‹5Ë÷×¶–q^YZÉi sqºæ;|©' m>s´înÇ¢ñ3¼~ºt»û.Ý…¥%”Þ7u£R¹S ÿV á  j+Ìdñ•Ö¤[ "†ÚIå_·\^-í¨Ú±‘O4°Cs–rÁ£•B•\®µÿŠuû;Ëqb–iì¡{W²–ä0™ãYÚ‘„Q•gu À’c£¨ âŠó[_ëÃDŽêëLåžÁn¢x£hÐöbòaß5x9uèîK¨oÝßÒ|Oâ=j]>ÚÝ4¸¾ÕÔ¢õÀ•"huŽ)~ô®…|ßáÝ‘÷wEpšGˆo®üMgu{®Ÿ«ivSZéí Èîî%.±0|BÈÎÁ8B›‚…Üv¼;ªM¬øŠÞMkN¿KKÁpZÆUíW`ù$9;Žwr;«süÐÑEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«éš|²4’XÛ;±,ÌÑ)$ž¤œUª)n¤‚ÎÑî%Ž3#Æpxü¨(¬}cX–ËÁ—úݼIçC§Éwre—pŒ¸$d{VSxâÞ;^V‚u±°µµ—ý"g!yd•7&5Ûò&î'Šëh®j/ÿh·‡/4¹ }?SºšÚ`é¹Ã$R·ÊêÛxxYIƒg*q‚gѵËÍK\Öì'Òç‚ ¯&+‚cÚÃʉ°på·0°ù@Û€pÙ½EPÕuTÒâƒý{™î%òmíàÛ¾WÚÎ@.Ê£ Žß3»ŽIâ·4å3e¨°µƒí7Œ±.ÛXÖIc»nÁ(и!wêÀ$u5™6¦Ï©BH\͹de8‰ÝqµÞ v;Œ.”‘±p~UÁâ-Fm#ö§n¨ÓYÙÍqÈ RÈ…€8 ã#Ö±SÆÈÚÝÍŠÙÏ,©ºÇbŠ«r.í ñ¶ç1ÁÜ«0dÈ[EqúÇ!µÐu ½>Êêk›K9g•LA–ÖE2"¬ 6Hóa‘ p  mÙøëF½ñ3hPË›Ÿ6H¼ØŽù# ½|°æEÆÇù™NÞ Ü»€:ZŽ8!‰åxâDy›|ŒªvÀ\ŸS…Q“ØÚ¨hzÖ­c%Åæ“u¦H³Ë†å”³*±ÆÒFÏ— t袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPYÚŽ“ý¥)ioïcB›<¨¤ ˜úcœóÖ´h  rév·3é7e³’ÜÛH¬ÄŒ®Ò ##¸ÅA} iºÄ—¿ÚcO:)ž)!}»Y({ ÊHrAÅiÑ@±øSH‰4äHî€Óç{›ôÙ²%rYÙŽüÈIfÎüðÌ: ¿ìm?û[ûOìÿé}s½¶îÛ·~Ìíó6ü›ñ»oËœqWè  šŽ™kª[¬7Hä#oGŠVŠHÛe]e8$dHèHª‹ám.íE§î¯-~Ép ŽL±æBwä±2ÈKgq,I$Öµõ•¾¥§ÜØÝÇæ[\ÄÐÊ™#r0 ŒŽGôªwÚ›¨ÜIqq ý¡Ö4ó¢™â‘BÛµ‚‡÷² ©‡ äVƒwàÍúÐZÜØoƒÊh<霤“™0ß¼`ÌÎòC±`Cjý®ge¨M{n'ŽI·oŒ\IäåŽæaíŠÄòX($’Iäæä²$1<²")f8èZÍÿ„“IÿŸ¿ü†ÿá@Ðô;_ØÉgg%Ô‘¼òÜspÓ6çbÄÄœdþ<“–$:Êÿ„“IÿŸ¿ü†ÿáGü$šOüýÿä7ÿ Õ¢²¿á$Òçïÿ!¿øUë[¸/`󭨼dà1R¹üÅOEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Ä¡¥ŒŠ£y¨u+ 8à_ô“&ç,N®xç祦•—,72¤ƒÏ¡ŠÎµÐ4Ë+”¸·¶Ù*gkyŒq‘ŽçÞ€(k:Åþâ}2ÖÖÆêþìî¤’ÞØÂr<\™Fvø‡º_ާ]?âî¶}²ÖÉo.¢Y Gq8@‹Ê^]†‘N!OÊ·0B× pÑ!™‘$*7*±€=@%W#¾ÑéTú——£iÍ5š¢[HÖ¨ZC”q• zÓµsÚ–¯¬XøwÇ3Û]y÷:d²›G˜"ù)öX¥ÀÚ˜m¥Ø¨`s€ ï]Nu5Í» ¥µŽò&Ù<6×e‰°ÅTä«+`¨ûèÁ%¦•§X\\ÜYØZÛMtÛî$†F™²N\–9'“ê}jK+M6Ñ-,m`µ¶;!‚0ˆ¹98QÀ䓸Ð-׉f·ÔçlQì-o °¸œÎD¢i¼­›#ÚC'ïãÉ.§ï` ÑøsÅ7×öqºÒþº•‡Û­GÚ­±|°ûÀ/2¡\‘’ÁË[RiZtºœZœ–¯ ìŽé¡S*/<Æ@ù›€{ŸZ’K#ɵ‚?³Äa‡d`yQ¹EÇEùWÇÊ=s>)½Õ£×ô«6MPG5­ÔÒ¦š-|ÂQ  I¸ùv1ºs’=*KÿW²Ó'¾‡t׊$2$Ò0Eß²%IÝ]!yPÝ)‚¸K†‰ Ȭ‰!Q¹Uˆ,ê*¹öJ©u¡é7Ú„7÷z]•Åì|«‰mÑäiÈÚÄd`’F:ç›ÆóC£GªÜih-ï ŽãOH®L’ʲ}èô=&¶ùZ]’}¿?lÛnƒíÎ|Î>|în¹ê}j ¯ è7šL:Tú=“iðJ³Ej!U6ì…IϨbA €\Ôÿäyÿ\ÿA5…k¯ßA5´HѪ[Ëedšy_Þ]¤È…®õ3!bÞ|ç9‹~þ7›O¹Š1—x™Tg© âŸf‹oŸ™k\Û[ù /€!wq E$wÚ=(ZŠ«öÆÿž?øõloùãÿPªÎ?ë$ÿ|ÔÿloùãÿU|’ÌÄc,N(h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQOGHÖI$*±-ÐÜÖLzÀ¼×Å¥¼¶ïl¶¦BbÁËï’=o¥iÑ\?Œ¯–¯½û¨‚Ö;é-&2l˜)K¹ä'àPF%5¿ˆõÍ.Æ[§5eÔu;{kd.×4Ms*|ü€1”# p6°oà þŠáÆ×vìKe­ØÇ*‰¯´˜NÆÝäBƒÌqæù‘£-ÏÚv‚A=Fƒ¨Íªé_l•Pžq FÙ!Y]bqÉÈhÂ6GvGPçâ­jÚùïÓLÔn„——ö‹xþÏ2Û­Á"Uc"ÈL,W’ïœ[޹ª_x~ytïiBÖòÎIu $òR#0óñ)P@w>aù T9ïè®JóÄqG{áuK&‹Pº’lÐdŽæâ(Zã ¶iÍi<·!ú…Jæ Ó´ñN«®G£ýŽîÕï¬Ð³Æ¡mÌfÒvÃyS̲+¿g˜Bd *äÑè®-¼PæïÃ"òêʹÕ.ì&Œ»Ffx„чA¼|¥ÑFÆ̨3¸HüM¯ ·b²¹Ž{ûë KH™£’Gƒí ŒÒ1Ú»¼…py;÷¸;J+‹Ò‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQE2X£ž&ŠhÖHÛï#Œƒßj(,m-œ½½¬9-aN=8«PEPEdZjZ¥õ²\ÛhÛâ|íoµ(Î:ê*o´kôÿÉ´  +;íßýÿòm(ûF·ÿ@?ü›JÑ¢³¾Ñ­ÿÐÿ&Ò´kôÿÉ´  *”êM:¥Ö˜-£ æá_ðÀv€ (ª÷óÛ\ÚÛ[Z}¦[ûWÌ ÷@=Oµ_¨ç‚«y-î"Ia•JIŠ]HÁ#µRûF·ÿ@?ü›J>Ñ­ÿÐÿ&Ò€¦èözWšm„í$¸ß-ÅÄ“ÈÀg ¾FfÚ2Ä.p 1“›õöoþ€ù6”}£[ÿ þM¥hÑYßhÖÿèÿ“iGÚ5¿úÿäÚP»É$óF"Œ” »o¶jZ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEWâ¿ͯxŸGUµÓ¥†;²ï¨éÆîböûFÝê=qéØQ@H`U%Lf]’úMciÖï¦ØEiÅ–0y*9$äþ¦­yÓÿÏ_ütPú*‡?üõÿÇEtÿó×ÿ~Š¡çOÿ=ñÑG?üõÿÇEKy÷âükÊ´/ Àö÷÷ÚjLï§[Ã.™§éò[¼ÌÆ<ý¨)v˜©c·…i²»mzs3¹ßv:qŠ(Î'0i~ V·Ôµ}5V·û3D–Ü!/òã·‘IHÛ©êÙ¾öãuZôwÓ^ZE¥ÍƒÛÝ-¬² ªJb;ðx ƒÐý nÕim<Ûû[±!V·´Ô°ùf€*ø^Úh./^[»--’!­ã”\þ{ä–8bP¸‡u‘Æwï~’¨yÓÿÏ_ütQçOÿ=ñÑ@èªtÿó×ÿyÓÿÏ_ütPú*‡?üõÿÇEtÿó×ÿ}ÁN¤Q´b–€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEJ(¥¹žñšúæ$Šq$K1壓Õz»Uì¾ö£ÿ_cÿDÇ@Øýïÿï˜øŠ>Äè'ÿ|ÃÿÄUÁ „ƒïU¥¸Ž+W¹ËI¡“0©²Ÿ”(%½€žÔϱú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆªš6¿¦ëöþ~3ºmY–…Š0ʸW”l088<Ó  ÿb?ô¿ÿ¾aÿâ(ûÿ ÿýóÿV* ‹Û{Y­ašM²]Êa„`ΜŽ:|¨ÇŸO¥'Øýïÿï˜øŠ>Äè'ÿ|ÃÿÄRÙÞÛßÂÓ[IæF²É 8#çÙsèÊÃðâ‹ëÛ}7O¹¾»“˶¶‰¦•ðNÔPI8žé@ ö#ÿA;ÿûæþ"±ú ßÿß0ÿñ$ó-½¼“¸r‘©v£;xU±ö“Ú¤  ÿb?ô¿ÿ¾aÿâ(ûÿ ÿýóÿV)@$€:š­ö#ÿA;ÿûæþ"±ú ßÿß0ÿñjD1&ù ¢ä ³É8ñ'ZâöÞÖkXf“l—r˜a's„g#ŽŸ*1çÓé@ ö#ÿA;ÿûæþ"±ú ßÿß0ÿñ¶w¶÷ð´ÖÒy‘¬²BNùãvGú2°ü8¢úößMÓîo®äòí­¢i¥|µN'€zP}ˆÿÐNÿþù‡ÿˆ£ìGþ‚wÿ÷Ì?üEI<Ëoo$î¤j]„hÎÄžA,}€$ö©(¿Øýïÿï˜øŠ>Äè'ÿ|ÃÿÄUŠ¡«ëzž÷׿u¶Lïx­ä›`’ÌI 9cÀõ  þÄè'ÿ|ÃÿÄQö#ÿA;ÿûæþ"–Êò+ûD¹…gXß8À𿣀çqïSбú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ¥±½·Ô´ûkëI<Ëk˜–hŸnFƒƒÈàŽµ=Wûÿ ÿýóÿGØýïÿï˜øŠ[‹Û{Y­ašM²]Êa„`ΜŽ:|¨ÇŸO¥O@.›+.F¥~Gû°ÿñ¿ÙsÐFÿò‡ÿˆ«þ¦/ÇùÔtö\ßô¿ü¡ÿâ(þË›þ‚7ÿ”?üEP›_Ó`ÔÆŸ$Î&ܱ³\ÄŽØÚ(ÎW Ì Þ¸2çN€#þË›þ‚7ÿ”?üEÙsÐFÿò‡ÿˆªš–±g¥yBäÎÒK‘[ÛÉ<Œ2Û#Vm£* c²‚y·ðÝ[Çqo*K ª9#`ÊêFApAèþË›þ‚7ÿ”?üE5ôçŠ6’MRõAffòu$ì©«Å_ò-ÝÿÀ?ô5  Zlâãíeg¸•a¸h?³9P2FÕÏ|ô*õdèêõ?û Mÿ²ÖµQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š*½—ÞÔëìè˜êÅR†æ eÔâhâCx 4ŒgÉN9 5¹õ ¢šÎÓLi£x fc:¯$À<œgÛúÔö±ÜÛhÆ‘#]Elª±É&Õ.¡`{€~†—û_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ #Nðô‰¢dYì"µµšgwY¢‚ ” IUÎö¸£#nÕ –ÜV¬x¿Áz†¥ikm¡ (#µŠAjeeG´‘ŽC#´2°QòíXÌE6ÝÙ×ÿké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4ÏYxgS·Öíä–öÓmoî/¡Œ/Ͼ_´ž;ý¨Ž§B?xBiøƒB]v]%eTk{KÃq(fely¢”#áÝAr@«ßÚúoý-?ïòÿÚúoý-?ïòÿp3ü6¼ií’)àŠÊ9gÇnÑÆl‘îe”<à“l›$Aò°b_˜ü¥mßø3U»¾ñ°Ç§[NÎæÙe’Q4æ) –òDÚpd‘T ª¸ÚS³þ×Óè!iÿ—ühþ×Óè!iÿ—üh—Ö<òé>!Ó´Ë{#m©XE PÜÈÛ~Ò]÷¬ZL4M¼å˜Æ2F©5Ÿ \ëWž¡*Z¥üÚLVö_¾v[[µ37šÑÊ™lw›rAé?µôßúZßåÿ?µôßúZßåÿâ!Ñ\üB³ºŠÓt–÷óÏq<ú[,â6Še¼ÜRXó"Få]€åµz*Iè Qþ×Óè!iÿ—ühþ×Óè!iÿ—üh3P:¦¥yj§Jh`Šñ&ót'h'ªƒè}MKâ uÙt••Q­í/ Ä¡™•±äJŠPŽC‡t`AmÈ9¯ké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4ÀÏðÚñ§¶H§‚+(åœG»G²G¹–Pð‚M²l‘ÈbÁ‰~cò•·àÍVîûÄRÃn5;;›e–IDÒ?˜¤.[ÈYgiÁ’EP6ªãiNÏû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ _Xðcˤø‡NÓ-ì¶¥a1Cs#mûHiwÜHv±i0Ñ6ó–cɤÖ|%s­\jz„©j—ói1[Ù~ùÙmnÔÌÞh;G*dM²Þ>lɤþ×Óè!iÿ—ühþ×Óè!iÿ—ühˆ‡Esñ Îê+MÒ[ßÏ=Äóél³ˆÚ)”fóqIc̈5•v–ÕØx‹N›WðÆ­¦[²,×–s[ÆÒ3¡PN8Éô©ÿµôßúZßåÿ?µôßúZßåÿåüWàëÍ_µ¼ŽëËD@xÒKR‹K x%"Br¦2 kó6Éeák¥ñn£¨\Úißa¼Y"˜HËq$ñ·ð’`Wà4²(`\m)Òké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4Ä/Ãë¿øGtý?컬eÜ—±Ÿ1ä²Â·G…ýî÷‰öõS>cbKŸj2Dð…Ó§ ³Cg,®Á´…3ÌÑËl6œG$Ch1ãÈ@+Ùÿké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4Æ_øT¼ÕLðÝÚÚ?Ÿw!Ô£y>Õ š)’2À`f5U2Ìv•£å[[Á^ŸÃ¶÷hÙÎË‹{y"0¨P~p#‚îÁ;I!ž¿Úúoý-?ïòÿÚúoý-?ïòÿh?ú˜¿çQÖF¡â8¡Çf-®¸%Ûí‘Æ<NOÿ«ð£ÿ EÇüøÚàÊ*$Ò5¸uˉ,.à‚Êòþ+Û‰· UŠ8Ú,ÆÁ•„Cç„èvá«øcÃz6¡ÓGe•jÖóOläÉ©ÈJq8*¸lcÉægùº–±ÿ EÇüøÚàÊ*?á(¸ÿŸOüE@õkGû^ÇVÓ"µ¸šÞ íš ™Ú+#DÛƒª9È0¼î'#<ö—ðýô«a²h%¾‚êÀÛ]’ÊÉ1ÛG(QÏ–Ò,RïPÄÆ·ü%óãiÿƒ(¨ÿ„¢ãþ|m?ðetµâ¯ùîÿàúÕ/øJ.?çÆÓÿQU=WY¸ÔôÙ¬þËi™ŸûF#ŒzgÚ€6ôõzŸý„¦ÿÙkZ±ü:ë%¾¢èÁ‘µвœ‚0¼ŠØ Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@W{IYŒ¶°ÊY·Ÿ60üà ŒôáW§¥X¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€0ÛÇåÁ P¦wmŒúà}>Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ôW¯íµ;›€öÚ¢ÚÄ(Œ[+þ$“T|ÿ">‡ÿ^1è"·jeñ1­Œìíkþƒßù&ŸãGövµÿAïü“Oñ­Š*Fcÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5º` àºîi<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú£Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿïª<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú¨f’%Š'ž?2bDhK`dþ@œÐOövµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5´Š]‚ާÖäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕC4Á,Q<ñù“#@r['òüæ€2³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€2¬t«¨56¾»Ô>Õ!‡ÉÉ ¸Çëùןüsÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMiKãDÏá;È¡ÿ׌_ú­ÚÂðWüˆúýxÅÿ ŠÝ©—ÄÆ¶ (¢¤aEPEPEP“ÿ®oÃùTu$ÿë›ðþUdÚx“L»”¨ŸÊVÚmä›äK¤,WFgŸhkb—ͬéÂÍÕ. ÒylªÁ†Î ʤö,S\^¡ðÉSDÓ­-nî®^-ì§Y¥iUÐ\[;ȉ3: H9òxGU)³Õã½µkзSËtÖa Ym¢UÞŠ&å_;ÉÚÛRúªG¯Ã¤5¼âI­d¹Ž—Ë!—ïnÜ<Ä=1ƒ×‚*Ä7Ö—G“uŸhˆÍÉócr뎫ó/#˜zŠÅ²ðÔÚv§¢Ii|Ÿ`Ò´æÓÖ `-,Š|¿˜Èsð{ÔmÌðÞƒyg¯ÚÜIk{mmaa-ŠGss±…f„¢A³“ˆ›ç‘VF ›³Œ(iXúüŒš'ý·ÿÐlV>£ÿ#&‰ÿmÿô@QEQEQEQEQEQEQEQEQEIúåü•GRAþ¹åQÐ kUMD¼Õ%·žâ+HŒÒGÝû–#sÀÉëÛŒœ ©Št´³–ãR4“ ÿfš=Bhã1ÊP8]ÁŠQ•†Ö<P@ŸÄ:dÚ߇u * ”¶{ÈÜÌñ+¬v†\œŽx8<ô91ø_Q‚ùµx5[Q¬JÒ¤’ɚݕÖ!b†S‹h¹.yßÇ#hñÕtå¾K¿µŽÌ‰nf_1™T;¹É!YXŽÁèh´Õtëû‹›{;û[™­[eÄp̮жHÀr§ ð}¥s¶>´Ótù­-®?Ö]XL&x“Ë´˜cv|–9à!Àõ“Âþ ÃwF¼{±e³2I9h¡ÊåHyY2vGÊ"—€êkQÿ‘“Dÿ¶ÿú­ŠÇÔädÑ?í¿þ€(bŠ( Š( Š( Š( ¼«ãŸü€4¿úú?ú ¯U¯*øçÿ /þ¾þ‚kJ_& Üx+þD}þ¼bÿÐEn׉Šw¾wðÚi¶÷K¥;Y ˲d¦í¼ã8Î2hÿ…ëÿ@KoûüßáTéI»¡)¤m¢¼Kþ­ÿý-¿ïó…ð½oÿè mÿ›ü){öxžÛEx—ü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQìgØ9â{mâ_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáG±Ÿ`ç‰í´W‰Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Æ}ƒž'­Þ>»%ÜjºrÀOÈ%.[øãü÷¨â¥ÿ¨OþD¯*ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒÃž'ªÿÅKÿPŸü‰GüT¿õ ÿÈ•å_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáG±˜sÄõ_ø©êÿ‘(ÿŠ—þ¡?ù¼«þ­ÿý-¿ïó…ð½oÿè mÿ›ü(ö3xž«ÿ/ýBò%Gޝ>¯ew|Ö";møÉܸïøW—Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…nøRÓMºñ­¦©›kpƾT«7 FïøÖœ¶Ó,t«mNÕ$Õ5lYÆ\°U†7 #mdÇѸ"³HEÙ¢”[ØãüäÿŸ üü(ó“þ|,?ð?ð®ÎÓÀ²jwÚœ‚G‚Ú=R[E½³M¬Fâ3ò õ$Õh<ÓO¶¨‘57Óî€"Š\Éœò»Tž‚’«H|’9_9?çÂÃÿcÿ <äÿŸ üü+¬ÿ„N-;P´[Ë…7ZM:(LG'ÌÈnp=zÒ?†tßø˜ÞÞêɧ[E­Ë¦F‹jò ŽF0IüaÖkH9$ržrÏ…‡þÇþyÉÿ>ø øWM/„á±›\mOSK[M"DŽIÖ!v|lAÏ9ôÍgkz'ö?ˆ¦ÑÖaq$B?œ.ÐÛÔÆ}ê”é·d'-Y•ç'üøXà,áGœŸóáaÿ€±ÿ…tú„ ³UŠU.5 &$–öØBʨ¤v¹á°Ï¦Õ¼i§¾µoo¬­Íî“ ÜOnmš?Ý ;²F@=j}­!òHä¼äÿŸ üü(ó“þ|,?ð?ð®ÏSÑt}g¶¶r;I¨EjòBð¶ÙUÛBÛþ\ôØ1õª’øfÍn/îoõôûOíy4ëP4›Ü1휪€:’ÄUi‡$Ž_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ êÛÁÖ–VÓˬk)cäêÙÇí(f(HÁîp8ïÚŸmàW›RÖ­$»cý–èŽ- 3K&á•*€Ž0yçó£ÚÒIœŸóáaÿ€±ÿ…rÏ…‡þÇþbêÙ ¾¸·FvÈSt‘ØãÕ[•>Æ£ò…j”Zº#R?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ ¤Eqa¦€Ã#6ÉŸýå?üøiŸø ŸüM^·‹ý.?€*—Êö©Ðf:±iŒCOÓ÷޹¶L/qRùOÿ>gþ'ÿSÇüLåãø¢ÕHô¹/Y›P¾÷®¡#1{Rm-Ò@Ñ.æÓôâ3ƒ‹dãÿ¥Ei\Xi 0ÈͲgÿA§ÅdaÝä+!]îrN$Ç?•Iq %]n>ÎcEq!è0:j.­{µ"òŸþ|4ÏüOþ&¡iš7;-m`š6e‚GF†VGF“s>§rÒLM¹‰F-†Al¾r:zT·QâyÏùû¢ˆµ%°4Ñü-_ÿÐkÿ%aÿâ(®6ŠÃ’=Šæ}ÎîÕ ÓíH>D}Ýñn73n~+Ô|)á÷Â:=ÍÅŽù¤³‰¼×;G`Õ®|áÁÖÀ¬òñTž& ê¶)S•òá[T-Âʧ™`ô#×úÓ|¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅRŽ&œtIƒ§'¹ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUWÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯e ðáé`Òy?øªC௠ƒƒ`ÿ®òñT}n‡ì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñT£Á>##OÈÿ®òñT}n‡ì™ã^W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xâ«#«¡ÚÊrê iê>"ÕõXëW¿dó¬ýž(Ñ„y », ’qœÀêð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUKÄS“»CT亞TºÖ¢b½Žæ×L¾†îñïZÞîx㕉ÉL0#®:šm¦¯ªiún­gh¶P¦¨˜$EV AÊü¼1ûW«ÿÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñUÚaòϹå—æ­w{¢\\f2¯Ù€FùØmù¤ç“ò/LTž¥wi%´¢ÔG.ªÚ«”FÍ`FÑÏÝç§_zõ¯øBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*Ÿ¶¥Ø9%ÜóËfûZ»×9#Õ7’Þ+1<{ÖpAž{t¬gSm{Äú†°–ò[E9A >7…U ÇœgŽ•ëCÁ^=,úO'ÿUfðçƒmåh§[X¤^¨÷Œ¤wèZ”kRŒ¹’cp“V<ÛSñ±©Û]ÛÈ,"ûj¢]ÝCÙîq€Íœv«^'ñMη¨ëi–Öö–ÞZKpÐm¹™@*͸¹ é]çö‚?¿eÿÇÿ‹£û Áß²ÿÀãÿÅÒö´o{,ûžrÚæ¢_Io³éìúYÈ¢o4ªª1 ‚¹öÞ–ßÄ´ä¼mОù¯ÄW0HfbNäù{“üëѰ¼ýû/ü?ü]Ø^þý—þþ.«ÛRì.I÷<Æ}SU»±6·RÃ7™©iË)B¥Û·qÛY:þ¢Ú½î«%Ž“5ÝÔË.d…ñU 6Á‡dEz‘ðO‡ÉÓð?뼟üU'ü!~ÿŸÿ¿òñT½µÁÉ>çŽÍ%åõíÍõüÂk«™<É úØÅ7ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUh±PJÉ ÙÈñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*ŸÖáØ^Éž7å{ <¯a^Ê<áÂ24üúï'ÿIÿ_†¿çÅïüŸüU[‡aû&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯e ðáé`Òy?øª_øB<;ÿ@ïü'ÿGÖáØ~Éž3å{ <¯a^ÍÿG‡èÿ‘¤ÿâ¨ÿ„#ÿôÿÈÒñT}nƒÙ3Ç¥‚ÆòÉ-ï#.ªT«uJŠ×KѬ§Û[ùr@`½›þÿÐ;ÿ#IÿÅQÿG‡èÿ‘¤ÿâª>±O{’G#F/^R# Ž{…!¶ÓË3n™KÄ+È£'¯×°Âáßúäi?øª?áðïý¿ò4ŸüU7‰¦ú³‘ä¶Éiä[†Ær×$’ivYÍmW »fÓ´©##¡¯^ÿ„#ÿôÿÈÒñTÂáßúäi?øª>³Áìäy# ¸IØfT+ìl€zЧv¡üù|¤gé^ÏÿG‡èÿ‘¤ÿ⪶¡à¿ǦÝ:éøe…È>tpÚ¡baØ^ÍŸ0ÑE¡Õ^ ÿ‘Cÿ¯¿ôT‡ÿ^1è"±üQÿ!Uÿ®cÿBjó§»::¿o¼ÿŸ¹ÿïá£í÷Ÿó÷?ýü5ÂøÎø[}©WRŽ)’ÈÉ-%«£|øtÚ11$´ôØ?¿D–zýÔšŒö÷r2Ëím,/û¹U”ù*§Î‘”;„kÊŸ˜ä–;¯·ÞÏÜÿ÷ðÑöûÏùûŸþþãõ=;YÍŠÂâæ[såHåå&I÷‚M¸t+Ï’pp:©–ÇHÔ¤˜}ºþôF¶±yf96m—|‡‘¹²UJ/ÌY[ø·ã„WöûÏùûŸþþŠßX–òž×Ryálí’)Ë)ÁÁÁEs"dx±&H–Lì%"Bјü³·ËÁÜ8‰H9ùˆÉkú\G§Ê·V²[Hn§$Œ„•yYÁùXލ>Ä€t0x‹P±º²…]e[›¸ác.X¨cƒƒŸçš›RÔ¯Pœ ‰QÊŒ@À?α&ÿŽ‘ÿah_ÿÈFëþº¿ó4U¼B‰<Ð6°«4dš3s†0æÈ#“ëM¶ñ47­¶Ó\ŽvÜ]†9 8=p¬~€úW-miˆÅšÞ[*¥Ô„Ã-ÌŠí»ýV?z%,܆ànp3òÕ£g}kŒ‹e$í©spñDèËs>Ò70òÑN3žiÕý¾óþ~çÿ¿†¯é~#¾{ùìËhâ±k€äŃ`sÓ½aÛÊóÀ²Io%»æ)J–^{í${ðj]+þF+ïûÉÿ¡Š@YmFõ˜±»›$ç‡ ~UI™¯#ó®=¬u_ìífÃì×î.–ôB¥­ü€dgd ƒædäxAÓ£²ÓŤ²Ï%Ì÷Wª£K6Àv®J®T`cÓ<õ醅׉õ=*Õ|‰UÚYn”)yû¹Õè¶vqi{ráCgfËHÇ«1îÇ×úWë¿ñíoÿ_ ü{4ŸëêhCD ©[¿—¶ö&óehcÄ ï‘wnAÏ,6>GQ´úŸÌï·ç^I,pGw:‰,¡×WYÔš;YµHÙ-ä”]¬Oån?1i pHç I»J 'Åøvíµs$³Æ#µVÔÅœÈ×Ìû*0“!ÊUŸsè¢íZáíÖà‘UÞ0ÿ2«‘ÔU°{í>”ç>lmŸ:0*Ê܆¨ õÀI ø‚d¾ÔíV÷ñèGeW˜]Æn y„±,FôÊ»¼d»dÚ»úá£Ô® ÓõKXä"+]Ií ä’‘ìVÏ ÐV{ê—²+ßJ­#m@f ±Á8òp úRŸõZ÷ý†ßÿE%s>#»Kì»Ù6˜à¼,ÀÍdƒ «Á‘”–g8Í! ê—²+ßJ­#m@f ±Á8òp úDº¥Ä1<²ßKh¥ÞbÔ“žs#PmZm"ûNŽybK‡[‘ ÔL±©B0ád*Ç%cq„àáë y{{scksö›‰~ÔÞÈ®Ã(E{r"‚cóó|­ütô)5Kˆ”4—Ò¢– L@É ש$îißo¼ÿŸ¹ÿïá®KQÑ.çK‹q-ÜöêÖ×(Zè«É*ÈÆP#i* ò bÛŒë/0YD$‰¢`¸òùŒmÍݱŒòyÏ'©@oi~#¾{ùìËhâ±k€äŃ`sÓ½gÍªÜÆ’O5ô‘Æ »¹”ª¨êO •ÿ#÷ý‚dÿÐÅgx‚6—Ãz¤jT3ÙÊ »(z“ÀçŠ`_³ñ j;þŬ-Ï—þEÎý¹éœ:ʬGª\J¥£¾•Ô1RVbFA ޽Aq\U¶¨u[³[]]Þ4r‰gˆ^Z‰å‹iC >ÂI+ÆFNqY·ñj:~ö÷[/™.~Üð9‘¥‘ƒFcP'fÜŸ&08ñ@ÏIû}çüýÏÿ o¼ÿŸ¹ÿïá®>+-qu›¹¥žäD<ÖSÒ$CŸ-<»U†W“ò‡,A%¯øvø-fŽö)çʤfsÇ<eÀàcçî~QŒ²ÔZø†þÊòÆu•no#…̹bªÇ?ã^^TÿòÑ¿ì#þ…^«M QLaEPEPEPUu?ù^×ÿÐMZªºŸü‚¯?ëƒÿè&„ÈTQEzG)õW‚¿äGÐÿëÆ/ýQ¬xrïQ¼YâžÙ`‘È=Iô÷£Á_ò#èõãþ‚+¡›þYÿ¸+ΟÄΕ±ÇÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´TØ,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,q²x'P{»EÕ–Û{¨æÞ6J©ç/Zµsá+Ù®æ•nl»³ »gý+¨¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑeàÛûmVâéKbÖà ;‹Ÿ»ÒºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xáu/jwÄ‘ÝØ’‡;¤nƒ?ìû×xç21¦›E1…Q@Q@Çü"—­¤>Ñh>Õ¨µÚeÏQW޹ýz‡þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E+ Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%eàÛûmVâéKbÖà ;‹Ÿ»ÒøCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,qÍà­@Þéó}ªËm½Üs¸ó%Täãåë]¯“ÿM#ÿ¾ª:)Œ“Éÿ¦‘ÿßTy?ôÒ?û꣢€$òé¤÷ÕOý4þú¨è  <ŸúiýõG“ÿM#ÿ¾ª:(O'þšGÿ}QäÿÓHÿ搜ŠK—†ÒÞK‰î"H£f-Ò«jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±CûFX*]8V*Y-dapy ƒÈ4¿oþx^ÿà¿üM?Nf]8`‘þ‘qÐÿÓV«>cÿ}¿:‘”þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó¬Ù|G§Ã3Å%ãF*ÃcðG^Ô7Ûãÿž¿ø/ÿGÛãÿž¿ø/ÿU¿á(Ó?çù¿ï‡ÿ ?á(Ó?çù¿ï‡ÿ ³öøÿç…ïþËÿÄÑöøÿç…ïþËÿÄÕoøJ4Ïùþoûáÿ¬ÙëÚƒ²ZÜ<…F[å`âEoþx^ÿà¿üMoþx^ÿà¿üM\óûíùÑæ?÷Ûó  oþx^ÿà¿üMoþx^ÿà¿üM\óûíùÑæ?÷Ûó  oþx^ÿà¿üMoþx^ÿà¿üM\óûíùÑæ?÷Ûó  oþx^ÿà¿üMoþx^ÿà¿üM\óûíùÑæ?÷Ûó  oþx^ÿà¿üMoþx^ÿà¿üM\óûíùÑæ?÷Ûó  oþx^ÿà¿üMoþx^ÿà¿üM\óûíùÑæ?÷Ûó  oþx^ÿà¿üMoþx^ÿà¿üM^Grê ¶ õ§´ÁX­ÁÇß4öøÿç…ïþËÿÄÑöøÿç…ïþËÿÄÖ‡ž?ºß÷Ù£ÏÝoûìÐÛãÿž¿ø/ÿGÛãÿž¿ø/ÿZxþëßf<u¿ï³@ÿoþx^ÿà¿üMoþx^ÿà¿üMhyãû­ÿ}š<ñýÖÿ¾Ígý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5¡çî·ýöhóÇ÷[þû4Ÿöøÿç…ïþËÿÄÑöøÿç…ïþËÿÄÖ‡ž?ºß÷Ù£ÏÝoûìÐÛãÿž¿ø/ÿGÛãÿž¿ø/ÿZxþëßf<u¿ï³@ÿoþx^ÿà¿üMoþx^ÿà¿üMhyãû­ÿ}š<ñýÖÿ¾Ígý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ4íSUk$µÅ–¸¹Ž ³Ÿ”1äûð*טÿßo΀)ý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5sÌï·çG˜ÿßo΀)ý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5sÌï·çG˜ÿßo΀)ý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5sÌï·çYZÜÒ†Ò”Há_Q„0ÜpFIÁü@?…Eâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶)éÿòõñqÿ£Z¬U}?þAÃþ¾.?ôkUŠ‘…Q@Q@r©ª\ZO5¤W°i°Íuy;ê51ØDA |À»žs²)1ƒó§UTtë_&¸îíb™%½k”WÃ†ê †‡èOI¼›QѬon-$³žâÞ9d¶“;¡fPJ€r ÇAÓ «•Wíÿ<ñê>ØßóÇÿ  UJëþ>GûŸÖŸöÆÿž?øõC$†Yw•Ûòã®h(¢Š(¢Š(¢Š(¢Š(¢Š(¢Štëê(“ýcýMÿ¬O¨¢Oõõ4KUžk]"öâÞ[X¦Š 9.ج(ÁIB9Séšãÿá*¼Ðâ’Úî=RóP–X–Køc2®õ•·³W2 ¸e;¾V{ºÌúZdºdz6œ–6ù-VÕNÜrS'å^Hì=(ž_êÓk:D¦Ê -6[ ©ïþg£ò¥‰L4[¶ª±eݳp|°M¢ºj3iÕµ;uFšÎÎkˆÖ@J–D,Áµaô­:K{Kw°µhlÙÚ6…JÀÈ0…0¥GB:v«tÉjZÍÇ…"I>·wq,iÄ<ØË,ŒKýž"ÞYX[n"'r¶I¤ÇW~MÌçÃóÇ‚ßÞ4ò˜™#2¸DdÌ|’ɸ `~cÀ= ~ÐâÓ%Ó#Ñ´ä°™·Éj¶¨"vã’˜Á?*òGaéV•§-»Û­…¨…à[WŒB»Z,dcfÂô­sQx¢÷N¼ñDúÊZ®›§O ·ò®33µŽo-P¢†%7¿-r9UÝQÛøßR™­íÿáœ]Ü]-¼aŒÐÄwE,€ïšØíòNàáX¸ü•Öý†ÓûCíÿeƒí¾W“ö,yž^s³w]¹ç3Uì´='M‰"±Òì­cŽS2,èd+°¸pÛI\õÁÅX²–âkD{«o³OÈx„À ã*êœdÁ rc®ëvçSÖ/Q›J±ŸPk5m|“2Jª°ĦA±ï>Ró¦»úŽ!·BD‘!fr¨¡Af%˜ñÜ’I=É&€9mSÄšž‰¯‰ì ƒRÓlîÛkÍèbo3dxxyR¦2¿wžN,k^)¸Òu Bô¿>ÛN°MBêàÜÛ2†U\Òb"Tp§œ²`nÒúZdºdz6œ–6ù-VÕNÜrS'å^Hì=*ÀÒ´å·{u°µ¼ jñˆWkB …ŒŒ`  Ø^ƒqõ  ]XÔæñ·g¨‹(í"¿û=™?¼'ìñH'–3•.äî$Œ»«¥¨>Ãiý¡öÿ²Áöß+ÉûG–<Ï/9Ù»®Ü󎙩èÄó ÿ°„_Ö¶+Äó ÿ°„_Ö¶(¢Š(¢Š(¬sýf‘ÿa(­kVN¹þ³Hÿ°”?Ö€â¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶9ß¶ê n"±Ž<$÷Ú[yß$ÊÝ !¯åŠoÛuÿîZàßÿ[:s2éÃô‹Ž‡þšµYóûíùÔŒç~Û¯ÿrÓÿ®ÿøŠ>Û¯ÿrÓÿ®ÿøŠè¼Çþû~tyýöüèûn¿ýËOü»ÿâ(ûn¿ýËOü»ÿâ+¢óûíùÑæ?÷Ûó wíºÿ÷-?ð ïÿˆ£íºÿ÷-?ð ïÿˆ®‹Ìï·çM–ãɉå’FŠYŽOu íºÿ÷-?ð ïÿˆ£íºÿ÷-?ð ïÿˆ«¿ð”iŸóüß÷Ãÿ…ð”iŸóüß÷Ãÿ…Rûn¿ýËOü»ÿâ(ûn¿ýËOü»ÿâ*ïü%güÿ7ýðÿáGü%güÿ7ýðÿá@¾Û¯ÿrÓÿ®ÿøŠ>Û¯ÿrÓÿ®ÿøŠÛµ¿KØ<ëy]ã'ˆeÏçSùýöüèûn¿ýËOü»ÿâ(ûn¿ýËOü»ÿâ+¢óûíùÑæ?÷Ûó wíºÿ÷-?ð ïÿˆ£íºÿ÷-?ð ïÿˆ®‹Ìï·çG˜ÿßo΀9ß¶ëÿÜ´ÿÀ+¿þ"¶ëÿÜ´ÿÀ+¿þ"º/1ÿ¾ßcÿ}¿:ç~Û¯ÿrÓÿ®ÿøŠ>Û¯ÿrÓÿ®ÿøŠè¼Çþû~tyýöüèûn¿ýËOü»ÿâ(ûn¿ýËOü»ÿâ+¢óûíùÑæ?÷Ûó t_kà‚Ó#þœ®ÿøŠÈ}âYI,mØ–fh/‰$õ$⻟1ÿ¾ßcÿ}¿:á?°¥ÿ }§þß…ØRÿÐ>Óÿï¿Â»¿1ÿ¾ßLÒ Ä•;Íy÷ö¿ô´ÿÀ{ïð£û _úÚà=÷øWçî·ýöhóÇ÷[þû4ÀaKÿ@ûOü¾ÿ ?°¥ÿ }§þß…wþxþëßf<u¿ï³@ö¿ô´ÿÀ{ïð£û _úÚà=÷øWçî·ýöhóÇ÷[þû4ÀaKÿ@ûOü¾ÿ ?°¥ÿ }§þß…wþxþëßf<u¿ï³@ö¿ô´ÿÀ{ïð£û _úÚà=÷øWçî·ýöhóÇ÷[þû4ÀaKÿ@ûOü¾ÿ ?°¥ÿ }§þß…wþxþëßf¡»¾¶SÜyLÞTlû|Â3œPqÑÍ¢ÉSökÓ‚GðÖ·ÛuÿîZàßÿ[v7rÝX[\;a¥‰\…'?˜ÿßo΀9ß¶ëÿÜ´ÿÀ+¿þ"¶ëÿÜ´ÿÀ+¿þ"º/1ÿ¾ßcÿ}¿:ç~Û¯ÿrÓÿ®ÿøŠ>Û¯ÿrÓÿ®ÿøŠè¼Çþû~tyýöüèûn¿ýËOü»ÿâ*)«ysdnÖ! ½ÊN|›;­ÇiéÊz]?˜ÿßoβµ¹¥ ¥(‘¾£a¸àŒ“ƒø€ ‹Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lSÓÿä?ëâãÿFµXªúüƒ‡ý|\èÖ«# (¢€ (¢€ «©ÿÈ&óþ¸?þ‚jÕW¿æÓîbŒeÞ&UêH8  ]~ú ­¢FRÞ[+$ÓÊþòí&D-p§¨ ™À#óç9Ì]ÅdÙ¢ÛÁgæZÄ×6ÖþBËÆà]ÀdQIöJ¹öÆÿž?øõZ¢ªý±¿çþ=GÛþxÿãÔÿY'ûæŠL’ÌÄc,N)h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©&ÿ–î Ž¤›þYÿ¸(:óÍKÄš§‡µbö[éïí-¯æl¥X‘V5ÓÍØÚʃn%†ÓÈ'æ¯C¬Äðî‡ÅÝÂhÚrÍx®—2-ª\åÜeƒ õï@nüA¨Øi“\]é Ád†Ï»'aFî$UVfTGPC®@ø‘ký™{u%‹Ç-½›L¹e2ÌŸjß( ö9fàŒªŸ–»ÛMJÑí/­`º¶“áž0èØ9SÁäøUxt=&Þ!‡K²Ž+|ù(–è,ºÈv€8ùÕ[ŽêP(ÞÜi¾Ö¯­$òîm¬'š'À;]cb:Ö ìºÕ|A¨¶¡­[ÞÛÚÉ4Ú dÏ åD*P«}Ó»'ƒ½Oa<Ý[ÉoqK ªRHäPÊêF ðA«6/ xz K‹Ht.;k¾|)gIvœ®å ƒÈÏJÌñŒ$ѵq§ÛiWï s?‘ÎÁT Ž'Ï–ü;F:|ßx­ø ­ÅêÞé®Û5ÈßÂFeˆÜàí!@,,î23Çîù;›gS&‡¤Íö/7K²°cì{­ÐýŸÇ—ÇɫӥX[DòöÚÀ¾T­4xŒ ’6íÎ=ï|ž§qõ4É[øßR™­íÿáœ]Ü]-¼aŒÐÄwE,€ïšØíòNàáX¸ü”jskºiH, Ó~ËzoþÑw°Fö÷Å+†òÎU>b¹+¸1-³h®–ËCÒtØ’+.ÊÖ8å3"ÁnˆB» € ´•Ï\T’iZt©Iajé ÿjZ!&Éo0qÃå˜îä“Þ€-Õ=_þ@·ßõï'þ‚jåSÕÿä }ÿ^òè&€ #þ@¶?õïþ‚*åSÒ?ä cÿ^ñÿè"®PEPEPY:çúÍ#þÂPÿZÖ¬sýf‘ÿa(­7Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥ldõhí’+1d€K3·ÚÉ;¤b0zz÷íŠfßÿGÿÈ¿áZÔTŒÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+Z°gÔui5{ËK%²òíös0|ËžÇëXׯN…7R«´WQ¤Û²,mñ÷ôü‹þmñ÷ôü‹þ§OH·MNÎb.}³Ïùí\;øÇU²·y¯ã%ómÃÙ „–÷E"¡9[D„y‘`n ò°°Ž—oˆÿ¿£ÿä_ð£oˆÿ¿£ÿä_ðªƒÅ±»‹XtF]L3¬ºzù"X‚Ù˜±FF&„ü®Oï6Òè×6æx%yÏo cZQ0·*꤃°}ª-Ä€FztȽ¾#þþÿ‘¾#þþÿ‘Ÿâa|?áÝCWxqgÍå b\Ààz¶0IàÍ]vúßC´¼»Íiïá¶Gdða$•SsÁ3«Çóœꯂ Poˆÿ¿£ÿä_ð£oˆÿ¿£ÿä_ð¢[û¸¼_g§feqa<øòϘ²G$K÷·`©ôÛW©ÎøIÿ³m¼Eu¬ÉƒL¿[xÚ$ò÷+Ç Æ¬]¶†Ý0RĪ÷;Fpoˆÿ¿£ÿä_ð£oˆÿ¿£ÿä_ð¬Ëéz•¼ocÕÔ¥¤ÁmåÌÑ,a ¹(å\,G³±ÞRC­áÝFm_ÃN§p¨³^YÃq"ÆPΈ$ã'Ö€·ÄßÑÿò/øV}î…©ê7}Úi2É´(&K€;A§xÎS Ýjš¶‘{k7íh»$/›¦Bª;±eùCqÉÎÀÜUû¿ËËi·¶²=ürÇÚ?ýý¸ÿÑÔü[¦éýž‘xvKw°Fþt?yØ¢,¿šrÀ ª3’@ EK_i×V6÷bÔaK¸{%š%VºÜѦÔ¸>dѦ_já)–ÿÂ'sÿ>Ú?ýý¸ÿ?á¹ÿŸmþþÜMsâ‹©lZ{k'²š×Vµ°»·¾Ev++BÓ…AÛ:°9=#¸’óÇZ5—‰—Bš\\ù±ÀÍæÄ6I ]‹å—6w§Ì¨Ê7rFÖÚWþ;ŸùöÑÿïíÇøÑÿÏüûhÿ÷öãükWBñ5Ÿˆ./¡µÐÙ°Wó$ˆ·%‡(®^3òŸ–EF1@Ú Cþ;ŸùöÑÿïíÇøÑÿÏüûhÿ÷öãük¯¢€9øDîçÛGÿ¿·ãGü"w?óí£ÿßÛñ®¾Šä?á¹ÿŸmþþÜð‰Üÿ϶ÿn?ƺú(fã´ôäz[tP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQET6ö°[Ý\ܬa¥¸*\¿?t`éÿש«&ç_†ÚúkAg{<íÞaˆ0ë:¾Ï•ûK[Ïa«ô6‹±cÔÖ^Ña9[W!Z6^âGXvH²*Ä¥ˆ"‰…;@kA#MHÐÉ aŸ.P¨â°¡ñ}´¶°Ý;QŽÎå — ¸YdHÑÁ JŒÈ‡ Ø' J°·uá­.îi§x§Žy¥ó^k{©`±DB7£ V8ò à”RFFhÑî+”Ó`I!Ùå„Qvä/cíÿ,¢?òÍ6¾Ohqi‘jrk:rXLÛ#ºk¤;sÀ|àŸ•¸±ô«}hžfë¨Ê•a“2²FÛµ£éÔ ë+}KO¹±»Ì¶¹‰¡•2Fä`AŽ éUõmÏ\´K[á;D’¤Ê!¸’½NTå稨böâ[[Gš9ï$\b nqÁvUã¯$tü+#Oñn›w¢A«^Ÿì›iâÃý£41—ˆìÄŸ+° ™rA€@ÈÈùt{9µ»}]Äÿm·‰¡…Ä7Þ0Ûp ýÕþèÄ á­-´¿u;hÊ&¸ßu+fA®™cå°Âà¦Ò6.1µqlêVÃWM,H†é k‚‚Tܨ(%3»“‚)ƒ€c‹\Òg–â(uK)$¶•aRá ŠFmŠŒùX·Êäž( |5¥ÜZ[Û\E<ñÁ¸)šêY•ŽYÙ‹I`e•8PAÀÅû+}7O¶±´Ë¶¶‰a‰2NÔP<žëTäñ‡™§&³§%„Ͳ;¦ºA·<Î ù[€{J#Öí¦Õíl!G•.ìÚö ¸ÙY†Îx‡8Á Áë@ o èïs%ÃZfG•fÿXûQÖE—(¹ÂfDWm o ÝSêÚ=ž¹h–·Âv‰%I”Cq$'zœ©Ê0<ÏPP*KMWN¿¸¹·³¿µ¹šÕ¶\G Êí dŒ8*rÐúU}OXuެ67W÷“«È–öÆ0ÞZ äÈʸÐc9ù†ËÏ iwÚ‚ÞÏþh–9ŠÇu,qÉ$eJ;ƬØm^X…QÐ Gsá›&Ó ´´D€ÚÙ›c"yȰ›£tc‡F"¶Nâ3†RsVìõ­2ÿOŠúÚú¶“ÊÚå¶ó SpC0‘0§æsU4ézýÝΑ:_=«HFҬʿŀa*X€AŠ¡aàm6 "k ¤@“Þ-ó¦šÆ%•Uv$o•ËVÁcóå¸à ¯ì{1«i ž;“÷Äw$r»wùü½ø½Ee^…:ôÝ:ªñ}›Nè|¬Báõ®"O%ÓÜ}®âÉ£žXžU‡NX¾Öxå&äÛ4‡Ë+¸*æHvüØ¥¨Žj_ ]Å®]k:v¥7³Êä ‹S,kÅnŒ»UЖͲÙaƒÁ-| “ÛCoª] ZÙÚÝÀ&F„@’03þ‹;xaüjS°¢€ ç´ß C`þy&K‡Ñ4粚 3—̇0ÀÏF}z(èsGâ-6þÒ{[{ 9-ÉmNv¹Cò°p*0ÓÀoQ·žŸáÜ÷Ú“\jZÏÛ 8S ÄRIæ/Ú!™ƒ‡•£„H~o»€wtP«hW–š­Æ«`ºŒ·S»ùšs[¬Ð«EÛq˜ÙÛ«á ±©ô_ j:sønIo­viZOö|Ð, ÆF"=̲n…1”é»Ômêh [Âþ ÃwF¼{±e³2I9h¡ÊåHyY2vGÊ"—€ÓÕt«»BÓQÓ¯ ¶½·ŠX¸·3FÑÈQ›åWC»1&ìcw ‡yú­Þ§ymb,‚[lÉŸvNåÏoÆ¥û7ˆýt¯ü‰@ô^k;x,lug‹MŽ{+—ŠHä‘í„* ¾@Rà(;¹Ý·ä:Ö5îšoRÛRO³ÈÓËmÛgd³HdfîÀv;Bì’㆖ßy¯ Öûãì᱌zšŠ]kFƒ[·Ñ¥¾DÔ®"i¡¶,7º/RçõÚØÎÓ€ á}E|¥h0ê¶«6žÖÇí/d̲,®ƒ`”IDÉÜsó` ŒX›ÂËq©Ü,È“_ê6w¯ „n na+9É…°{y‡ƒßbÎú;çºò‘Õ` ËX¨>ÜŸÓð«4Ëx_Á‘ønàH×v ƒì¶fI'-9\©+&NÈùDAòðÀMPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEVf¿=Õ¾3ÙJ‘\™•XîuRËæH@ß)r ñšÓ¨ç‚«y-î"Ia•JIŠ]HÁ#µrÚ7‰ 7gMÔ§Ÿt1\Íq5ÿ•¶Â!m”Åû¦ÊÜܤ¸ k7@ñíÖ£-ÅÄÖˆlÚ{ ¯Ú̶[¸-üµU —l¹›owqW°MIŽÒÖÑ4»%¶´”Mo Û Hdè¸Â¶I9òh‡CÒmæ‚ht»(å·Ï’én¢Ê,gi‘Uxì t€9­7Åš†¯¯ØÃomQ]hÓjVð5ÊŸ5Y¡]ñ7Í ^xg …·kâØm|?¡jZxìï´ãs%ÔŒ’E„M´ª ÜLk3d*Ýã`+hhzJý£n—d>Ñæùø·OÞù˜ó7qónÚ»³×hÎqRA¥iÖ¶1ØÛØZÅgŽÞ8UcF ¼ `ß6}yë@–ú®¡&¿¥Ú^Yý“íZ\·RD.O.UhC#a9Ûæ[-•û¦™¥xŠóR¸¿µ“MK;ÈUšÚÞâIQ¦Á î-\PˆÊ£pä‚¥µ¤Ò´éu8µ9,-^þÙÓB¦T^xŒó7÷>µ^Óú…½Í½ž§[Ct».#†Õf\‡a† àúŸZɱñíÖ‘áñcf—Wú–œ/ˆ¼¹ò”"¬[·:Frù™8ùË€ :mD ¸t—](Oi¸’us-ØÀ9 ΡòÀÊ—9Q»'‡t9tÈ´É4m9ì!mñÚµª‘¹ä&0ÌÜÜúÕÆ±´3u¬ æÊ³I˜Áß"íÚçÕ†ÄÁê6A@WWÁ}«,ÓÚÍ,¶ñ µ‰$¸™¼¶"8„™@ÄŒ–`T rv½z]ûGûí_øûù³»öî;7íù|Í›wíùwnÛòâ±"Ó4½[WÕíõk;ÈàuŽî%‘Caœ3ï]¶¦YÇga­¥¬yÙ ±¢ä’p£’Iüh²3¥Ô­p>U'œqÎ?*ó‹ß†êÛë7Z]“êO(˜Ü‹ÛÅpã¡RåÆ1Œ`c¯IBùŠG¨úW™ê_ð˜KãX¾ÁãÛh|76e—+lfƒ~érŸ6sò±èÝ’ðÓF°º°†ä^¼éîsåghÝQê iV?‡ç7#R”Ëæ†¾“kîݕƒéŒb¶(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*¼÷Ö–Îâ꜌…’@§¼ÕŠÆŸJ7Þ%2Ëon–awJ]ûÏ=ñŸòk*õ%N›œcÌ×E»Wf¤0\¡{y£•ÁhØ0ϧUõÍ&;»«GÕ,–æÒ#5Ä-páŒKºç*¸ äñȫ⭢ŠR4D\mŒ ÷éï^y®hÍÕ¶±§Øéó˜%ŠùãŽy-Þß|ш°&YYäçÈ¡åPHØMÁ¹E6¬#Ðè®.ÿHÖí®å†Þ]RûI>D³¢_¹¸r'ˆßzy7Ùœª´i…`£’¦¤ÚoŒÖÆæ iý¶Í­ã2ÝfK!ºàFKnÿX¢kmÎ ’ “–m›èþŠ©ªÇ{.‘{™2C~ðH¶ÒÈ2©)S±€pz¡®ÃHñ4Z[›¦Õ$¶7HfÓÒàÅrñ„pLs5ܤeÚGšƒ71ÞÀöó«ËE .ÊÍçSµ#¸*Túcª]«è?*ñýZ gGðä¶wwþ^­$W’[[Z[Yw¸Õá0¢­Üº?Ý»H_•|ÜWMo¦x­Óþü¯øV7ƒ-µkM>â-R ãýîèÚâwy 0ÓÏ…>g$·È¸Ët´Ð[!Kxc‰ ÉXÔ(ϯ-PEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQRB™Aõ>¶“júu¥œÖÒG1Ìb!ʹŽœÿ/­jQ\—®¿ØZmF kcæŽãR—NŽGùvŸ´Æ ìF~øfoùgYºV»¬Ã-õã³½€ÔlmÚAHºÌðZ&\$%]ì`ÌÌO¼@;ú+€¶ñ¾£$I1m:pË ×‘DŒHS<+$W'yùÄrJw<‡%q½/‡5©µØonšÙà·YÕ-ÖHʾß&6pü‘½di€èP©äÚ¢¸Eñ%õŸŒµ{<Çý©oV’ï3L’CnÉ<*¬[šV?îä3SOˆ·Oªê6Q YQ¤ŽVECiž8‹Î‹3¾eÞÁÄ$˜2vz=Ëx+T¹ÕŽ»5ÅÊ\ÔDqIÿ)[@CFŒIp#çÈgq©yâÝR/.‡œ!,h"‘âI'•YæBÓ+íL¿ ‚ba¸vv”W¾#þͶñœº}ÇöŒ¶:¢\ùßfWŽìw8Û9™Š–Ee$W´ñˆï—M[{[)>ÕçbdA0•¶ñ UbÕUáË í‘ å7e@=ŠóÍ?Çú¦©®ivði°EäVÒ‹i%ˆI$rÄ’<ˆÍ*¹TÜã †10Ü ;#ŸÄ'Õ<J‹XïõoͨZ ¥/ "Å•vYßÎq,Œ~ó©ôz+„Õük-†‰e=®±¢ÜÉ,®vG»pr’ÜF®£p ë+a†6œ¼-żs p’(u##FyV©ö Þ€$¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢ªj:®—n³];€í±(šY$l…D˜à€' &€-ÑT,5?T•⳸ó$H’WRŒ¥™Ð 0h¤R§•*A¯Ð2«£#¨e`U”Œ‚Pj¼ZuŒ‰!³·ŽEèÉ‚?*ÍQEA{{o§Ú=ÕÔ›"Ld€X’N¨³@ $$ÐôTW¶ú…¢]Zɾ'Î H à«ʰ ‚¤ €EO@Q@CûgOþÖþÌûGú_Llm»¶îÙ¿|Í¿>ÌîÛócÕú(¨,ïmïái­¤ó#Yd„œóÆìŽ9ôeaøqSÐEG<Ëoo$î¤j]„hÎÄžA,}€$ö©( ¯-mÜ$÷0ÄÄdp§3ûOOÿŸëoûü¿ãT¥_ð’Ë. -þËœew¸Û±~X“ÀgšÓ±µÑ58î­l­$…ò6áH ÊÊ@*À‚  ‚Øo-®_dÊøÎÔpÇ…XòßûùR-¥µ­â‹{x¡ |´ ž}«ÏügâßÙx–ÚßÃze¥Å…´»®Þ}BÍÇÔÊŸ¼FwÆÐw€zV^ ¨¤¬-øê:¾§q—ÚÑÛíF‘\Çò’W*JðIÎ Ï&·h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š+'Ä:tú–Ÿ[òÇ(‘VK‰-Û¡$Ñüñ7ÍÔ‘¹HÃ5¨ oß^C¨Ow<j¥­¾Ÿ,“;ý–u{†FÜFY£Æ«1aÚÍÁb }àk½Bkø˜Ù[ý«íbMU2×WÌ’*Ã"í»ÌL~ñòå\½Ýƒ¡éZ¾©©ê·I=ÌQ©!YÎÕÎß?Ër# p\ªÐñ/‡u [_Ó¯¬á²ÿDÚË=ÔŠþ[ÎDM ôÀ9ŽH™¸†Õ#­¢€8 oÁºæ£§K¥Ûͧ-šÏ¨\G$ŒþduÈ€¸@qâÜ>o”­­«x&ÂçJzz=©kË[™LwsGæyr«;±VËHË»ç?1`„œª•êh ƾÕu«{H´™-Aµ’Þk™˜H%xerxS•1°*Næ$‘ü#}%Þ cû¬÷j+­ÄïöÒ%± €¿,{Ô ÈæNÒ¥Ëx+Ã3øvÞïí"yÙqoo$F ÎpBØ'i$"sÀ?øbïYÔ$šì¦ómVÞî\‰4Érn [2êx1œÂŸ7B½mƒ£xtizæ·©4Ó³_Ýy±©»•Ô!Š%9F;CoFÁ…‚Ê$ñ.“6¯gmpÚÝ$3‰d²¼b°].Æ]Žv·²¸Ê·Íð:ª(Î#ð©ŸöY[N¼™ÖdŠîi$ß§;Ï4‚æ ÁØÈD¨N]Na_¾ð¿eà­GNÕÿ´í/ma™ï.f‘v1]²5ÓpArL¶»—+ÿËó«ŽâŠó[oëxgĺSÁ¥˜õ+Xâµ¶2§“ ¾éHŽÚ5 7FAX˜ÆX`ckYð•εq©ê¥ª_ͤÅoeûçeµ»S3y í©‘6Èxù°$ŠÀÔtÏí}y­DÞL‹kÄRÜH®Dܹ]ȹ‚F@ ò74]6k{svÑ›ÍBãíW &8ÛËHÂ! Æ€±Æã“…(-¤Z7êÉ·ìþHR~öIþU{í3zGúЧ¼Aœ|£§Ö¸Åß|/ª6›¬´v—j¡ö6œìOB¬#!‡Qz‚:ƒ]—˜Í:Èøã—ë\Æ©£_êú…¥åÞŸ¢M-Œæ{F”HÍ 2{˜Ê©Æ@À–™s§KuqŸdmÕ#‰Ø´>S6ðX¤0;I­:ÊÒ¬o ¾¾»¾ks%Ï—l  Žÿ…jÐEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQE"ªy{ßw\qT¬ï£¾{¯)V Ú ±åŠ“íÉý? /¬Úú‹íw6ê­¸ý–>çÿ?Jf›¦Å¦C$qË,žd†FiX,@Ï8ö OWñf¯¥bYÖmÓÛÚÜZL»¼¸ÝÑ–ã>\Å‚1.ÖUfÉÌmsâû`æ§j?nvAofÑ¢K:¸‘•Ææ €¬2œHQ†Â ‚Tî<'¢Ý=ÓOjî—+"É ¸“Ê`+#${¶£°g˨ w·?1Ì÷Ú›¨ÜIqq ý¡Ö4ó¢™â‘BÛµ‚‡÷² ©‡ äPkxçIŽÒúyñµ•«\KìYLáâ_› "›Y³ƒ— ‘Íix‹Q›HðÆ­©Ûª4Övs\F²T²!`8Èõ¨$ð–…*D’ièâ5Ùó;à’ÇyÎd$´™-’D²ƒ‘#†Ó¾²·Ô´û›¸üËk˜šS$nF‘Èàž”ÌØxžú8œ^ÚOzÒÊÙ˜4÷±{‰ »¼b+‡ãbG¿y`­»hù—úø‘'›EA:Çu5´…ãSåIHZ&!Æ4N7(u;þ%jÓÔtË]RÝaºG!zlœîÀÁ¦èÚ~‘æý†ßÊó0]›jŒíEÜNØ×'j.rpMdÜxßO‚YWì:£GªÞÜJÖ‚Ò+;‰6°Ûå1ÛÌ*­Î$¿ñ–§iSš¦„OwoµKn·Y™Ï-ŒnøçºçãJïFÓï¾ßö›}ÿoµw?;2!¿ Áãýkò0yëÀÅ ÏhóK-Õ‡˜Òy¼yÒO5%Ø¡°›Ã±m n$1Ë@lþ<…®¬a´²ºyžóìÓÛƒKþ®ã6¶ÐDÖï$í‰UÉñ+@ÓL+tﲳΒI5¸Y6ÈgB9"óÉÆw.íkÏ hW÷|úzy»–@Ñ»GµÁ”‡HÃ<­¸s¹·g "xkKŠ[YaŠxd·Æ©c2a‹þô«7æfcænÉw'ï6@+ÚxªÞîYöiÚ ·‚Yàk‘j] ³«*…%Û; iás¿ä«ñ¯‰4ù/-li)ˆ´A7 ÖˆpN}ºfÜZe¬3YÂ34®þ\¬­ºVgrÊK3‚1ž1Qéº=ž•æ›a;I.7Ëqq$ò0Âï‘™¶Œ± œÌ@ääýQ@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEP‘K°QÔúÔsI ÅÏ™1"4%°2 ?ÎiáÚ<º(fíRp Ç<â°£±ÕçÕì®ïšÄGm¿ù;—ÿ ³©ëN¸·µ†ÆêþòuyÞØÆËB¡œ™Wº g?0À eâM2úõìÖ"äKåG Ïù1Ìv#a¸IW €AÎEGâ= µÛx"Nt‹u»…Ž8m»”‡€Cc Ù Šx*{{´[×–k‹Ë—ºÌël Ú®ùÉ0±Ï2P ¨µÍ&yn"‡T²’KiVÕ.˜¤fبÀ•‹| Iâ­Ç<2¼©¨ï l‘U(Ø ƒèpÊp{{×&ž›ì¶–òêˆÉ¦@–úa[b¥$†E3|çÍ9·‹;|¼ý26íhöµÄmy=ä³Ê²I4Ç,ÛcH—'»l‰7í¸àF¾ ’]fçO¶Ñu„µ-ç»F€DŒÈœ4È "“…=ñšø—IƒZ-ìåÅq$ó,¨cƒÈ1‰FÏÊÃÍSƒÐœwÌ_ Í‹îuè$Ò ÜN’—ŸK2\Æ¢$‰‘&  „?Âq¸ðk6OKj°\ ¶¶Ÿ`¶6ÃA(Š9a’&ó!åC 6#f m@\°Kÿ O‡¿³þßý½¥ý‹Íò~ÑöÈü¿3Ù»8ÝŽq×­^yoàOPiõ)õ+ÛKù.¤xÍÛâ_)âIöI"]Û­Á\®Ò2 }ަߵ{Y#дï:ÕcHg{uyPF§ÎÀ¶T*€IÏ€-îi7;üRÊ]žVí—Û|ÜyYÁã~Fßïdc4\kšM¤ÆRÊW~R[„VHüü(ÊÇÐO¹èü V‰gov‘&ÌC%¸ $Â[y„¬¡º-òËœ¶óóÍx¤ÕßQÔug¹•çûKˆàX¾pÖl rp€Ùƒ“µðX‘¹€7a×´éµYôƸH¯"œÛ¤Rº«LÂ(åcÎX‘sÇöäɹ¤Ï-ÄPê–RIm*Ã:¥ÂŒÛò±o”ɇ §±½ax–Òñî,ïl ÔZâ%’/;N’ÜLŠå ]·Ë(J)';U!›ºw‡5»¹¼Qä]ý¾ÄÇme0ŽÐD"¶Šà¬y]©*€ù*J'$»¢¸ m3Å 0Š\B°É¨oƒ­üÉ<.ÆØy„FŒ‰p»H‰Oš€€ÉÒøre!½›[(.g]cË$aaŽ6Ù’v£H’:Œç Ãy¼E¡ÛêcLŸYÓ¢¿,¨-^éRÍ£a9ÉÈÀÇ9§\ö™£ßÁâmkP’úêYïHíBb™E´)¼¥Áܬ0}ÁÆ<ÊXøÍµ]Dù7PÙάòÆ·YDñ’;\9RbóÕX%¸ÉRB»=ŠóÍWKñ4º} ÓâÕ!²Ye&ÎkÓ5Òä&ÂÒ-ÄGh"cƒ<Ÿ}xè"êmômMÖ[ê2¼kš4‚Ù"™”ÇQe A$ãqÁ`jŠà-tOYiZ9[½FâëìpË©‰¯C3Ͷíå'Í´¸LŒ+äyŒIÝCé>+Õué.f7Z}›Îî± Dáa"ÉJ‘áÌkv2Ø•lírÝÇ<2¼©¨ï l‘U(Ø ƒèpÊp{{Ô•ç.‘âØõµ_Et——3ÙNó¥Üb+ºÝy‘)‹„t^1ó³,4/{…ºÔ¯b¹2Û,²D÷Ú#i&ˆ¼òP‹/ÉåD8€J¢¸¿hÚœ}µ¦&µu•ܨºßåŒCsÍÎâ3#™G·°€ÌÖñµÂ$sD˪¶9ˆŒ÷ÀÏ   (¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (§£¤k$’ˆX–èîh”VdzÀ¼×Å¥¼¶ïl¶¦BbÁËï’=o¥s^2¾6Z¼N÷î @ X老˜È²`@¥.äoŸ€UA”ÐqEpþ#×4»nžÔa—QÔíí­»\HÑ5Ì©óòÄ>PŒ)ÀÚÁ¿‚¤_]Û°q-–·cª&¾Òa;tS‘ 1Ç›æG Œ·?hEÚ €wtVfƒ¨Íªé_l•Pžq FÙ!Y]bqÉÈhÂ6GvGWá+ûkŸ^Gwª@÷«|‘B|A3ÌÛg6gäUƒŒg…À¡Ñ^qmâÖÓ| ·zeÚjºµÕ£^Mr· ošf¤y%@AAÒ/úÄ œ…bx‚ÞÝ®›MµhaÓ’öeA¿+‹§oŽFEGKUe¶´ëó>Ý®èôWœ^ø÷Z‚û^Ž\iÐ^IäJщ"XUŠJÀOæ29TãÊN%9¹¯ê¾![{»3ueisi.Ÿ{-Ä1HÑÅo%Ã+£êJ ˆ³Èv†MÀªuÝ‚š–³uik>•k¥ê0Ã$î 3°wtW«øþçûUáðòÚêVè±:˜ãy>Ð|«É]"e8b~̈Cf`C´PêkWîeµ ˜Qo ­ÜðÜÝÄbs„’o,–f@ . PN¢¼â÷ǺÔÚôpØÚãN‚òO"VŒI¬RV1‘ʧRq(!ȶֹ­ëz‰%Ýôú,R<¨"c @›²L`K$k+ ›Ìp,v\­¢¨h·ÿÚš%îw4Ñf캣s ¤ä‚!˜Mú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ d±GFÈKErV~8·Ž™uh'¶‚«Ø>Ö!>IòS´ —fò¢.X.Ì‚ÝòÕÁã 8n’×R´ºÓ.†ä»h±f9¤³#²„ż£®A^@èhªšv£©j÷+ª$ó[àº)6<ÆPãÛ+‡Õ|©ÙisM™‰bºÔ¢ó¥÷ –étÑà‡ÉbmÀ#¶×ÈPÑ–ô:+‹ºÖ¼A„5mfë)$±‰æT¸Ð®mwãfeÛ$¡Ž~\0àa¸=´ï®õË ¯[5Þ#Þ^=½Û‹7PÊ#’PciØq^KrÙí´€t4W5g­êOâf²¼[ÄÒÉvòZLŒUCt¸9ŠVePþZ€T3dæ6OëWš<:`²dG»¼û;»XËvU|™dÈŠ& Ç1Ç@Ií@ É]øÞ IÓî¼AÙšçÌ,þdpá±æyRH$ù”«ùj×;H-Œß´ñB_K:Úé:¤‰ ³Û‰D*I¢gS’îÇ8NB– ò€ ê+’´ñeä¿ ‰n´Ùàlå‘V7 û°ÆT_4f1’v³«¤uÆoßë—–ž/Ótˆ´¹î-®­ešIã1…d‰só8;T9-Á'ríÎ ê+OCk©ëQ^‡‚×L³ŠîI A¼ÒÎ ±$,¥T‚§ï©/Œà¶š;K#T‡P–T,¶G$½%dl£²o"EÉa´Œ¶Õù¨¥¢ªišŒ:¥ŠÝB®€³ÆñÈhäF(èpHʲ°È$pHÁ«tQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEÉ£imä‰e’"í/€ö$Sè  Û++Ö»ûUÝĦ?/3È }=©5MÕn{¸]Ÿo–á&xÖdÉ;%U Jœ·Êà™¸ùŽtè  Çðþ•-¼vòÙ$Ç<×"9 e2J$ Á &“ƒ‘ótàbá=ìï Ö¯r•™îî$žC€@]ò1m˜g3´‰‡`v¨ ,¬­ôûDµµdIœKIÉf'–bI%‰$’I$š¡uá÷Oû Ŧûc,óló|ó § ç‘4ŸMÜcÔPL~Ó£Óïl\ÞÏm{†tº¿ž|¡ ¹+Çîã· ©ïô{=JîÆêèNe±”Ínc¸’0¯Œd…`Œ˜‡Bs~ŠÌ‡@Ó`ÔΡ.&ÜÒ*™œÄŽÙÜé;Î[,ª ÞÙ?3fåÅ•½ÔÖ³Mé-%3BrF×(ÈO~Waϯҧ¢€2u izîÿ·Å9ó"0Ëä]K›?#ùl»×ælÈ›NoÙÙ[ØBÐÛGåÆÒÉ1'ç‘ÙÜóêÌÇñâ§¢€1[Âz+i—šwÙ]moG2-ÄŠ|±Ò%`ÙHÆH© 0 s=Þ¦ßÛÛAw Ì–ëå¡yœ³!2;g2#`nW$6àqZtPchkêwš„¼³^À-®Yâ’!ÑLLJc–è¿ÄßÞ9e¯†´»I¡"žIá—ÍI®.¥ž@ÁÞìX¨Y$“€]ˆ9­jÅÑ4†Ô´ˆ.æÔõ%’MÙ qÃÜ{P•½„- ´~\m,“’~yÏ>¬Ì*z«ÿÒÐWUÿÀþµMÁ§irÍq0Û¦ù&¹~FIfcÐcœô%Âh?4ßjÖz¬w6¨ïgö…À¼E\–QÔAùO;p¼²Ó¦{2Öi[t’BŽÇÉ Ò€,ÑEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEÏ_i)ªø§dÖí,Id ä€yÇ Öº+*ô½µ7O™ÆýS³^ŒiÙÜŽßO·Ómã·¶…b@709cÔ“Þ¼Ç_Ò§-â(í4¹î®çµ¾ +iòGrâ®nUŠ\FIDH@ʃ@1õ**ãX¨ÞöÅßÜxŽÂî[Io/e²>DÓê¶å‡xŸzCFÜ¡ã€`¬Ž«+cÃ-IµEcr±Y]O%Í›%„ÞB«$®9d]¸ÀÙnV ÷mª© ^þŠ #žn­ä·¸‰%†U)$r(eu#x ŽÕ牧^øoÂ’¿‡ô„²¸ŸVº[©-ívJ-„ó˜™BÅ!aþ­GîßçG̾Epuuëz„ú‹ºYÏ Å§Û«ùŒÒÄñ#‡…Y ˆ˜va«'X³Î–™©jÒøÖòÚo¶Íaóª£<0Å‚0~xwM¹Y¤Ü[p@§äëh  ›à­cì‚v¹6®"ŽQpÒ9c*Á•޲½ ¶šÝýÚK­>H¬ámIô°·^Rý©‰X¼³¹„­Ü‚³·”úUç—Ž'¹µŽêHíìÌ‘Æö¨ à¶™v†óCh®‹‚ïò#`¦šë÷ü,(ìÖÚ÷û.YZ)XXÇ™„ŠËQ¹Õq™ß‡ÁEn´¢€8M.}nãDÒí¬¥½µ’Mfî+»™ô±†Üý¡ÖB†4PÍû£¿n7·ÌæSÔh3^Í¥ÄÀ?Ú#žxwH›DI]È ²*¶@îÈ+NŠ+‡[RçJ­£žIЦ‘,M„²½ó%Ý,¾ŠTÇÉ ¤©ŒË²^âªxyšÏBµ‚x¤Y1#2ÄÐÐådKh÷Ö-ÝKl¤‚Ïo¦pqWþØŸÜ“ò¬Ëé H¸ŽæÑîâ˜yonùžbœ‚ ôÆ3œñùÐ)¼3“'­ßù[Ný÷cnÜsœŽ•¡b°¥…²Û¹xJ#cÕ—·jòíÀº†¯µký?EÖ$¹ºGK?´[äY£. ©ÎI$Ÿ˜ó·ûŽ7KFI²GR®° ea‚ÑÁ  tQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@(˜Üâ’•N×R{Ðn+EVšx×sˆÔg–bpGUÕSKŠôyîg¸—É··ƒnù_k9»*Œ*;|Ì>î9$JîÏYÔ/-Úãì o ÒÎlåðL‘ƒÁôgXÓ&ÔEœÖ·)oye?Ú yb2ǸÆñÊIdnŒ9Áäºöœ‰f/nO¸¼c6×®±Jò´¢©?1•È9&K}U.5»í/ìóÇ-¤PÌd}»%I7€W O7p;ƒšÅ¿ð¥íú\¬šº¨Ù‹IšÓ%â̇÷8p# M ¼Îg$1k¾›QÔõ¹.ï“쮜º{AeG™ó Oï¤þîúÀ¡ñ‡qfo ÖtémC2Òé*a¸d ,G` éRI®i0ý‹ÍÕ,“íøûë„hÎ1åóóçrôÏQëX§Â3^ë6š¶±{kuuoÓÿg¶ž!íª´Ñ¤ñïwly2Æ71–L—sónÚ›^Ó¡Õ`Óá%¼–qnñDêÍ ¤•Lƒ9PV6ÇñÛ‘&¥«ÚiSiÑ]¾Ï·Ý H˜HQÜIvÉ$Žk?´zõ…ÿÛÐÛé÷—7vðý•|ÌÜ ªÒg8ß&WhQ…Ã8eÖÕ´hu‰tóq±¡µå’#³+A,EâÖÌ-­áCo û:ÂfÁ¢–6BDÛ~R0¡‡!¸°þÔXx| ]és™åiíÚFŸ1¼{Cy€¨ #€[{p¥‹Å€/Câ-ãS:dÎ-øfCj—HÒ†\îÎFF8Á«v«§jöíq¦_ÚÞ­±¤¶™dPØ©#8#qX7~Ôu;íLê:­¬Ö7ðKi奓,Öð:íÙ†R ç ÌP– g…@¶ü7áÖÐþÓ5Í×Úïn6#Ͼàþí2Uq4Ò‘‚îx |Ý;ÐGÄ6šoö·íý—`·ólPwF|ÜÉå¿rÝp9õŸ5+kNîÂ)æ´XÚ`²£/¸…*å8ò!† ç5¯C¬ê:u䓼fÍ* ê%Š`=™\óòïÉ ±Í¡]Í­ê÷¯ue%µý‚Y­¬ÖEÂìÞAsæaÔ™dÊár6ŒŒ@/ÙkšN¥KcªY]G$¦h.ÃHy@Aå¶‚Øëš%×4˜%·ŠmRÊ9.eh`W¸@e‘[c"‚~f ò9ŠÁµð–¥mm 6¹æÞÛ]}¦Ù¦Ži¡FòÞ6ܲÌò6VFàJ!HæßGRø}}{¡¶–ž$œG'Ú¼×–7üù^BÛa–%fùðC†C´aW,¬·ÕRã[¾Òþχvd^× ðÜÚd:í¬W3^Kp÷1غþîYGŒ6å%™†ðÀ…~eùH T¸¢¸{}?Æq¼V—W 8–{Iî/#›hR‚ÛÌUŒa¹Ê…Á3ÇØÉ·_Æò^Åá–þθx/òÎ8äI<² \ĸݵ€U† Ê‘Áèh®®u໺ÔSLµ‘§†Úß\½fXcaÍ$¡d‘]%eŒÉ–IHø3FÖe°‚ÿZ¿Õã¹U´x"’äàk—zä´‚@ÁÁ å—kĸ¨æžt<©T ìbG=É Ü+ÎN—ã^î7ŠöÞÆæXÚ*õ€»„°ŠCpÎÊóùT‡#&vªßkÛh ÊÞê„¥¤ÈÖwj›ã ܳ¦èÙþС¹@P¡v€vóO ºžT‰ *v 1 £žäîH%púþ‘®ßk€ÅÔÐFÊt‘nÕ KXä…ž3?4‚Ey7n˜qå›~¶Öíõ Aµ/V °Ë%ôàÉ»'*Ï,|‚wX@ a8@¶Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÏñµ›et¶óZ‹Ä ‚Ã8çoÐæ€4(¬Ÿ;Çáë§K¿²íØZRY@MãpgPZ5+•2õ`—þã´}CT»ÕôëmõMîe¸¼’þ× Ö„ÜŸÓð®CWñf¯¥bYÖmÓÛÚÜZL»¼¸ÝÑ–ã>\Å‚1.ÖUfÉÌmâŠç‹íƒ˜¨ý¹Ù½›F‰,êâFW˜*°Êq!F* Pcoé1Ú_O ž6²µk‰b}Ë)œUfF…YX®õ*NIW.¢»-x¾ hrëÓi #´Ñ4±ƒIäˆ1t#²6?%;x'rîêh¬Ÿx‚×Äš|—–‰¶4”ÄGÚ ›ë Ž¿Ä8'>Ý3­@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPE(˜Üâ›pñZ*´ÓÆ»œF£<³€ ¢¨jºªiqAþ=Ì÷ù6öðmß+íg eQ…Go™‡ÝÇ$€jAâ9ïÑ}>à¬8Ž÷lE¤•åE‰r~gÌ/÷r`©`s@UZúͯ¡H¾×snªÛÙÜ)cîqŸóô¨_\Òc»º´}RÉnm"3\B×À»®r«‚Oж'…®ÝeC2*»ÆnUbB’:€J¶}§Ò€+éºlZd2G²ÉæHdf•bÄ ój£qá=éîš{Wt¹YHMÄžPóY#ݵƒ>]@c½¹ùŽoÜêVÖ·ÖVRH‚âñbŒÊŠÄ*–f H,;A#p$c$W›^Ó¡Õ`Óá%¼–qnñDêÍ ¤•Lƒ9PV6ÇñÛ_hn£q%ÅÄ/ö‡XÓΊgŠE_nÖB ÞÈ2¤ƒqPIá- T‰$ÓÑÄk³æv%Á%ŽóœÈIi2[$‰e"G <>"Ðî,ÍäÎ-¨fC:]# eBì7Œ„ˆì=* ¼Y¡Á«éúcêV¢mBqlÞzm‘w" ä—/òàÛ[(NúÊßRÓîlnãó-®bheL‘¹FG#‚zU;íMÔn$¸¸…þÐëyÑLñH¡ íÚÈACûÙT‚Cr*Ä•µÆ§waˆóZ,m0YQŠÜB•rœyÃóŒÈ¼Yc&‰q«ÉöÖQijÅ-ÉH’â7ÿVÈìÁóÀW*Ã#p\Œ€[›@Ón,ð¼Å`[uyfwtU!W'r¾à¬\Ä¢IU MÂ+‹¹¢ûTFé]dH¯&HÆó–e@ÁQÉÉÞ 6I9É$Ø»Õtë ‹k{Ëû[i®›e¼sL¨Ó6@ÂrÇ$p=G­W›^Ó¡Õ`Óá%¼–qnñDêÍ ¤•Lƒ9PV6ÇñÛ&›£Ùé^i¶´’ã|·O#œ.ù›h˹À,ÄNoÔwÖ– o. ·ŒîÃM Aò©sÉôUf>ÊOj¯&¹¤Ãö/7T²O·ãì{®}£8Ç—ÏÏËÓ=G­_¢¨lØ‹»ûv¹?³âIn§LB1ùÆíÉ…]Ù`Á<⦧âÍJ±kËJÔ—‰c#$éû¹™‚•lPw0êIǵEP“\Òaû›ªY'Ûñö=×>ÑœcËççÎå鞣֯ÐEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEªvº“Øæ°®ìõBòÝ®>À–ðÝ,àFÎ_ôÉ<A[”Pf»¥¶±¦5¢½® hï-Væ @þŒHÎa”†U9# á/€¡:¤-v†kí$é‰/ÙÇú2³LÌ#²#ÌÊ<ð± ÉÆGaErW~ û|SX]jñ)inçŽ(¡Û:Ép²¬™±R£íàl|™'vž‰¡M¦^^^Ýê{ut¨ŒÅJªª¼’`Xà<Ò3Â^J–mª('WÒ®õ GF¹·¼‚ôû£pé%¹Ë˜Ú<vü²?8nvžÄCáòjs,wŽ,c–õã-”LÚJ&ROñK•Àƒœ0í( >ÃÀ‘Åugwt——V÷‰rÎây¬qʱ®'šR¥^fpAëŽ3Í[O \[¼3YjžEÊK{™M¸|Eu?œáA8)T Çrðr‡8-Š49¤ñ¥w=­Å…õœvdÖ§;P¹ù˜¹ › #h௡ÝB?Cgðú_ iÒZÚ<öešém$b‚7”¢°Ë°’Çœg8Áêh KYð[kz„WwWÿëmc´Ô!Cqw©bB¬s.Üù’ŸÌÇ]ÒGàö^°¿ûz}>òæîÞ²¯™›!•ZLçäÊí 0¸`ç ½MÏx«FºÖeÐ…®Å6šÚšI#Y=°LŠ7ÞaA†ç ©…ðDße»·‹TEMN·ÔË[.¯$Ò1‡çQÍÄ¸Ýæ`l냻°¢€9­SÃz޾ϩ@–Ú¶–4åŒZ’ðàI‡-¿ ÌÒq´#™/<) ó\½´Éj”vÑ$#d-k3ËŒ¦YAQ·… œŽ†Šå¯¼1ª^ÞZ]m¤3F O<6òG,‡{6É• .âeIBó»~æÏSEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQ\Ýö·©Ç«ÝZZ¥§—Îe “•±úÐIEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂçUEr¿ÛZç÷4ïÉÿÆí­sûšwäÿãEÂâüDˆÜx'R¶_í’h%Ž(la’FšCìFòÔ°MØ$ðc´•7æñE„¤+A¨ÿÄÖv·ƒ6)V‰2PP|§¨éó}ÐÌØøŽæÙ'VÒ_8dƒŠ—Éñ/üôÑï©(›ŸNñß]ÿg³Û뮋êœÛ¼ ² TŒb8Û•1ÌOúÜ˯á«i ¸¼xmn¬ôÆXÄV×lZA8/ç?%Ž”îò»ŒïÞöÕ€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( ¹/YEuö'ƒÏ‰<ÅÙ>”ú•¾ã· Œ‡pv¿E@yuÏ[EpT ±–úýbº¶¨Ø©Ó™~ѽ^ H¦g˜å¤Øu+óFŋ޶‚šïü#jÖ­tn'Ó–KˆRÁVKyv˜Ð);Ç͹Y_schAò¦Šáôs®ßéž´†{­*Ò_íåtåãš?!U]6ÆrdÀÚT¨m£î²Áá˯I<×wÚsÙCyi=Ì‘ÄÆUv³· ‚&_–?0lgËù ƒ"wôPO‰§Ôí¼=u6‘™z»6€2U €ì£ke‚n m~@ù_îžJê]JçÁ¶W:Õ¬÷“ǬÚMjc²šYÒ4š6wuFÊÁVa‘‚¥GÌ[-ètPy}âŸøOÒòôÿ6?(29†X6©‘˜¬ ™óƒ4|ªeH?>M®§ãØtHÚh'žy¬]òÀªñŸôc!Â!Û ó®€BŒOÙÓÇw™éTP ¤¿‹µ)tø.uí-&ŠéÞá-s6 †2Á¤…ŒØýÖ „üàÒ±ÿ 5žµ¨Q$Ôô» öpZ§’²)•²î‰cóΖeðwtP%áKV½Ô5Ô>Û4\4SKlöñ§'…I ‰Æs7M€¸. ¶ëþFMOþÙè×Ö(ÐÞãWÔ.¥aŽSŒmÜ[ >Üÿ#øŒ—Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãJ±‰Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%·ýüÿä#þ4`Gÿ?ßùÿ ”VßöóýÿøÑýüÿä#þ4X,bQ[ØÿÏ÷þB?ãGöóýÿøÑ`±‰Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%·ýüÿä#þ4`Gÿ?ßùÿ ”VßöóýÿøÑýüÿä#þ4X,bQ[ØÿÏ÷þB?ãGöóýÿøÑ`±‰Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚ÅÍ;þA¿ð?ýÔõJm:ïìðAi«­²D?è¡Ë’sÜñÿëü þËÕèdÿÉÿc-iŸò°ÿ¯X¿ôT|Uÿ"ÝßüÿCZzé”qÇ^ XãŽ5UlÀPrOjŠë@¿½¶{{ï‰ñ¹~Ä£89ì}¨zõÍø*ŽŸ+”r)”QEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQESU’ö-"öM2šý ‘­¢á^P§bžGàuQVè KM×-ôËMRþóSžMÖ(äûuò•NKyÑãh</å ò»¼cDhÏj—­p&Óî\£Y¤Ú/Ù¾hﮉ|£‘ɳËà•^GÏî÷ÇÖO7Vò[ÜD’Ã*”’92º‘‚<Gj’€9+ÝMüL±¼“›“u:^Z0ýÌ`?Ùå^Û˜ˆù–/( ùX‹­¢Š+’±½ÔßÄËÉ9¹7S¥å£ÜÁfýžUí¹ˆIbò‚•ˆºÚ(ÖüWáûï¥ÜÚ=«ÞEx/þÊ’L¡¾Gœ`ƃnýÊA`£nðÁ_–Ô'•+·ñ$‘}€5½¾¯t¦íÒY‰·£tHAŽ/4—|Æ¥£&A^« Û¡H"H³9TP ³ÌxîI$žä“RPEP%}{©§‰š4’qr. K;E¹žÌ„ûD­Ûr“'$‚¥"7ž#Ölõ]VµÒµx>Ó§]@—¥.¤‡ÉTgW’0Z5(K…Ãd­Ž¶£Žby^8‘fß#*€]°'ÔáTdöv <ÓïdK5…µK££¬òƒ¬XÍ5ÇÚf „Fdi˜&æ‘6‚ÊÒBÿ¬1·y¥I{.‘e&§ C~ðF×1Fr©)Q½G'€r:Ÿ©«tP\÷‰nf‚âÍ&ºº³Ód2ÜÚ)ià§’œ8b\·ʈs¿cô4P-†½ ¾•¥k¶Þ!»³X«Œîyy<»œ…b3´‘Éjk›=SPÒõ-F >Ý£¶ u«Ýí‘£º_´³6çhÌb@”·Éµ«Ð̵Â\4HfEdI ʬA`P UÈï´zT”Íx&Pú]Ú%×ÛbŠè¬wÉs,Ñ] ˆKFd’BP€ì7FÇ‚H-PEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýV†£¬-­Â¶7÷Peà€²ƒéž3øV‚¿äGÐÿëÆ/ýVíyòø™Ò¶1ÿá ÿ¨F­ÿ€ßýz?á ÿ¨F­ÿ€ßýzØ¢¤f?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P/­jRêZDöé:šÉ&Ü· pÀö>Õ½©ÿÈ*óþ¸?þ‚jÕUÔÿäyÿ\ÿA4 >B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¼ù|Lé[QR0¢Š(¢Š(©bb±HAÁ⢩ýL¿‡ó Ï“ûß £Ï“ûß ¨ë–ñE¶©«é¶v–)yd`¸–tšêKhÖUh„MæFŒwÎTqÈÞ>dR:ß>Oï~‚>Oï~‚¼ÇÃúïŠï.#K¹/Zæ9lc6æÁV&ßon÷^s”d;¨>_Ìp ŸqmøGVÕu}"Þ}l]_YÜé>v “iÀFªlX‚ç #23_ØÉòèÐüù?½ú <ù?½ú àü?wªÙxwÂ[Z¼Ž4Ÿ"m>|[Ê&A ‰HЇV*þñWÈ®‹Â×·—„4[ë¹<Ë››&•ðçhÔ“Àäž”µçÉýïÐVG‡îf¼Ñ ¸¸‘¤šBå™»üíZuá_ùí?àúPÅQ@Q@Q@Q@Q@Q@Q@Q@KŠBHŸêeü?|ŸÞý|ŸÞýG\ítÛCéhï¨Ã ä¯.Ý5îÂD`‘NB£` \w áÈí<ù?½ú <ù?½ú óÍ*ãŃK³½“Qû|Kg¶6â[yâòâËq´âE&|1rcO•·|ñ­÷­|=c9iï/¯4µ¸¹W´}’Ex ŒDž\“1Vñü©ŒÆ@=Ï“ûß £Ï“ûß ®wÂ3ê×'›«¾ùVòYÕÖS÷¡‡æÝ¿Fݽy'z€3m.î.5ýV)efŽ{.T“ùŸééZU§ÈÉ­ÿÛýÖÅQEQEQEWSÿUçýpýÕª«©ÿÈ*óþ¸?þ‚h@|…EW¤rŸUx+þD}þ¼bÿÐEn×áŸøKð¾™§ßêÖö×–ÖÉ ðJJ¼n£ ¬B#«ÿ ÷…?è=eÿ+‚Qwz «ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå.YvÑÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]Gs}m§ØË=ÔËyUÉç'=šÀÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.‹ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáU?á>ð§ý¬¿ïåðŸxSþƒÖ_÷ò—,»Ñ<~#Ð"y^;„G™·ÈË퀹?/' £'°µx@µ·ŽÞÞá"†% qÀʨ `à;TðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÐšŽ«áM^Ýmõ5µ½…[zÇshdPØ# 2‘œϹ«Ÿð•h¿óûÿŸü*§ü'Þÿ õ—ýü£þï ÐzËþþQË.Át[ÿ„«EÿŸßü„ÿáG…ä[´ÿÿèmU?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü§Ë.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÔw7ÖÚ}Œ³ÝL±G•\žrsÐɬøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚è·ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþSþï ÐzËþþQÿ ÷…?è=eÿ)r˰]ÿá*Ñç÷ÿ!?øQÿ V‹ÿ?¿ù ÿªÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìE¿øJ´_ùýÿÈOþÂU¢ÿÏïþBðªŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»Ñ&‡u î·¬\[¾øŸÉÚØ#8R;ý+~¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèè®sþï ÐzËþþQÿ ÷…?è=eÿ)ò˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÕ]OþAWŸõÁÿôXßðŸxSþƒÖ_÷ò«ßøëÂÒé×1¦»dÎÑ:¨u$_`º>c¢¶áñ/ý Ú·þIÿÄÑ]üÈç³?ÿÙnetgen-6.2.1905/doc/pictures/menuview.jpg0000644000175000017500000005061213504650527016751 0ustar kurtkurtÿØÿàJFIFa[ÿÛCÿÛCÿÀ/ "ÿÄ ÿÄE   68…†µ·%&UV•Ö$¥Õ'(57"#w49EWvxÔÿÄÿÄ$ð1q±Q!aA‘¡ÁÿÚ ?Û#ûûpFâÂÅ–ô°búq±èo|Ï|2ßýÙ·w¸¾vöîçþ½Î/ðùß7‡ü8}œ<>Î7ʯ¿Ç¿Ò÷hµ~¾žû¯òaÚt35öe)m…ÉÉø’‚2ÌÍmlÜJàVÖVÀÀTã ±¢ (¸’‰,JTh F‘2d˜û;›œ*ÊÏ6,>ud^MM懭­í§¬ª*,ä.>ždfd=>8 kËÀÅ2Ë(hᢒâ$lY3ÈÏ“8ûÒ7¶öø˜ Pf"™+ͯ+Íç‹DîàåÑŒ/“9wÔNUÚ‡“oÅ8kQ³äàÓäcƒoí’+,q&tYÉ)ž¡„–ÊEx ·Nw ùU÷ø÷úXoöíU}þ=þ–ý»Y?¼¹™eòÝ{̘j›è0To.<úØÂþ,ãDN*·¨ÕóÊeOlØN¹MXnÀÌ›°™“¥@Û¥šöÆ2Wud*Ò´a¥®Ó&ì.Ku¿.Ú™l_ÀQò«ïñïô°ßíÚ<ªûü{ý,7ûv²G|Ç36ɲIŸ¢®O†ÚÄ—ÉÔ›Í_f¹‰^UVÙà7>ÑãL@…°Ÿ¿þ$’Ý9‘E•Tõm Ú"Ív‡g5«ÛU³˃3²úÇ̺žž¿îvê†Rò–­ùšmŠV'Wp(·›Jþ– U5Qn*mð²«kGUåRSnf{nÂfdD‚éÉZ9óŠ›á¥*¾ÿÿK þݨ±›2Ò™S\²¬RoR« ^mjŒÍÕÈEšH ùŽ\L ÊïD(¬ R$¡¥¬Qc)ŸD9…ödlîmðÐï6<Æ»éË%ò¶Ç[Þï\°ê¾]Y ˜ÓjZŒÅ’ý 29èÀUo|ˆºóŒ 2”€³‚È-mјÍV‘¿&û‡v¬rân׫»•›yÛ¬™vÜWË”cîß‘µ`Û­cVcO„¶=’Ém.är ô2¤ˆ!CR¶Æ$`´ýˆqö¦Ÿ#‡rVèm-fû2ê¶¼äšü µA´–eFµž%sËlËg G* …xà¨ÒÅšh\¸¤„–*L0$Ç™Fô}í½Î/sʯ¿Ç¿Ò÷j·ùeÿöÝåõÿô‡Aдïh$/*¾ÿÿK þݣʯ¿Ç¿Ò÷j=Ñ ¼ªûü{ý,7ûv*¾ÿÿK þݨ÷F‚Bò«ïñïô°ßíÚ<ªûü{ý,7ûv£Ý ʯ¿Ç¿Ò÷iiÌ+òÞNÆë<ò«´õó›P Œ`T10ÊAŽÀÖ|žàÙû#øe ŸÆ,¤Ý¨eGîÆ(*FæÙS!^Ì©¥/9þË6àŸÔUKµâ¥ÚñOµ«õô÷Ý“Ô{© Õúú{î¿É‡j=ÕWf× —m`ÔV8nã¯-D†Êáñ{¨•×SÏYh ÕNp_TRt¢â°½ÿ©:$½­™jÅeËÓ©ÏG® å:à:¯´öPÒ¾>3¼½lR? àWWñÜ‘)^H\=†edŠdÐ;¼D°{»Ã÷íVuÝÎ+–Ö=¼½VöFOÞo«î°ÚÐ+4nôT@alÔÓ£Ú¬Tzˆ·ZeÍŽ]eà¸@ìŒJƒ ‰‰!µg„¨Míøˆ/™+›)0eï §8Y8Î8Ä[6óR„qZ©¬—ZºZ¢Á´êÌâ+ Ié!ŠÂ¯`K=”/úï°Q¸ˆ9Xò©d_ô˜; ½H=¹òN8€àŒ*ÂU¶EVÖêê£%»Ê¬e¥¯< «na•èöHÓ‰ÄZÙlç&™e™mÕmyÉ5„jƒh1,Êk% [f[=9Pl+ÇH–,Ð3BåÅ$$°ÙR`&<Èr7£ïmîq{šfͬe¸ì›ݱëNã°íLYl§Æò°uÜex==™¢´é š…ƒÕ;¼ƒ `B÷þ˜sTH›[1öÊË ±–œ²këv¸­;rêñeO Ø{ÊÀ/б•ôezÓ¤j( §K8. îò247Üzb-RânïGÜ›ÎÙµ²³špÍ`¤.Xv§txÁ ë`v?cŠÙ:ëØjä'Ç8ßÚäG2ÑÛÐHöø­ý’%½$MÞ î.ß@äß-ÜÌ«&®·roÒ-Ëœ÷),'÷˜¡|ñQOFfˆ®ì$±íDˆ‡6$Έ‡hrL‹×[£lÛˆêÝ߆½Ë Ö`H6£9&<œ=fÀ=ÍÆ¦ùmŸÃˆ-¬…šÊÒqÊµÙÆŠD¡©‘VNE™²â”·²%55Œ €`Ç?Z4Ee\&S•µ}QW»r¼ªÒë„5î¢T¿BLGe\7V;8¡Â,¸0z‰’DJÍ÷¤Œér÷w¤nvú4h 4h 4h 4h )yÏöY´þ¢¨é´Ò—œÿe›GðOê*Ž¥ÚñzKµâô}­_¯§¾ëü˜v£ÝHV¯×ÓßuþL;QîªgS‘þMcu‚Œõ.Id!XeíwäüÎ`1-‹] zÉ‹sïäé…öÀìÆcÉýc¼iê÷‚ùábqUa=)b¹†öA„?ú+Òénáþ%d $+ç1Òío2ÈÖ»v’­,–Aëp§’+ z Ç%“E"ˆPÑ‚Q„ìJÛ±<±)›QødO•¹º¹Í{ͪßÌJ£q+!R(|]kä†["±O×e½ÏËf¡­O33Ÿíðw„¶›, еৠØÝiƒ[)ÕÊ6; Í”- ÍÝ^oüÉ®dT†1Ù¹Ëwí)¶r ­më5Ï ïy(5µ«~¾6ÓçäEVmL°bú¡Â,DwªùiKPõd6ȧ(V;œt¿;—q»#;sâ) Û³ºÇhù–¨C³ûW¸z__íÎös¡õΆ¬tÏKÔú8¿[ïú|OsÜxʶòO™||‘åþÈñ—•{L’|m×»«ÇÝóè;Ÿ²;Ÿ÷´ú§Aëß¶=Pÿ1 Å?¹odôÿ“m|æãiÌ(ÇVsu p\ó²:ؤ狯q‰mú2³+½°ëÙg(ØØ·n1fžm۱¶¯W7¡b¶8c´ôUÇ–·®iÞNQsR¬«dPÜöЧ ܹÙe¤ï9â´25‚¦W<¿öÐËã+ËiQ}È•CnL”ä|¶& “ÀÞªVÇÙÓðìeÆá •Åp')uå8ñͨÇUp“*»$YS'FØ5¼`@ÑÞca3±f³Ñ 2F<ý¹e'ooŸ ¸Ýæˆï‡ÊCâÿß>(Có?Õ^ÄÿÊ=½þ¤~æÿß>ªþïÚ?Éè)•ªM±ä^pd —˜™„h^-siæNVøïÇqlÈÇBÒÂ'Õ@šÁ&öPh±Ø¶'V ›ñ+ÚÄØçÀ4ñ%»Aúâk*Ú³îïWÉÿÙ¯’¦S½¬–¿IÝ wB¹=¾ØgÖž1è¢uò}6ÏÌíô4444”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz>Ö¯×ÓßuþL;Qî¤+Wëéïºÿ&¨÷UFB5á†ìƒøŽû<øB×óÏÖ¯ü1Øgü£õ÷ßê?\ú›ûÕü½û_Ñë,¸1ç)~rúƒx¶v>îþ,Úÿðø4[5ò­¨(]µ&~õ›ñ¦‡Žm8TîSÍåÿ·DIô¶:æ= L—4É®¯”C˜Á „èÖ|3~5±Ëþؤ¹Á_ í¸ôÀ7|[ÌX¸·BlÖ“ÜqÝÙØ%BĈ›whBŽr©Íj™F«¦€.«vÞÞÁ}¸êixmo×+|SsÅP>æ•Õ²ŠþxsÊÌÀa÷ uœš¾&Ff°¢ô•V&:ðwcÄÚ_¬=ýaÆ¿eìnõºušlhX®•œ\˪Û-¾"¼pà'Ã&SÛ¸ŠùÞÃ@êÖM1ÛýÐmG¡2²zô‰ýÉ 3ÐJ÷RúŠÐ¯w³ïñµÊeš½=Dòz„L' sJÌ+g1F­y"mK—»=½Ë"×­(n’7ª€8é$m×[ ßÛˆ½½‘l͇1Ú?Qš¸åI›Ø¬Å*³y’²* vMPKå?[ámcÖ‹µê‰¤¸œk¯‡¤(ö´b™V'” TZ!á¬ezïg²Öû„â±²¬p6¹£X®³1º…¦e»{Õ¯•5ÇëTêê%“Œ“Š6†j̤¨Zƒqº=¿Š´…Ä=™ÚÏÇè€LÕMQn$Î4»/ß••ÁZ¶ùRX鈡ž+Ú±èܱ֩Ê|‹žÒª0«Èg<º2°žtˆŠ õäv^ `pHc S œ D Ž«†„xѪ'äÄ«Dì¶æ§y;V]µE¾sØw*ì_Ä{?ñ‡y…Il{JǪVÚì;-m§b"­ äJʳÝ…]8…è¾~x5 —± 4hÑ 4hÑ 4hÑ 4¥ç?ÙfÑüúŠ£¦ÓJ^sý–mÁ?¨ª:—kÅé.׋Ñöµ~¾žû¯òaÚu!Z¿_O}×ù0íGºª4kÃff[J[arra¤ ¤ ³3[[1hVÖVÀÀTã ²" (¸’‰,JTh F‘2d˜û;›œ®^Ô‰ÒZmBÆMcuÆT0*‹ é PãA5x5qk¡¼;[s\°CY>RYDv²Hd[ ìï„æ:r¼™ûG"Hƒ¶¬ãg1jÚãLÍ+ÝÚHÆjó szëÃfËÛ0£c™hf ˆ ¾Î= 9Btã^ˆ¯Ñš Ë)gl,WF¡Ù5ÅÓ+‹NAÒ+Ëâ eQ>µÐæ¦Z–IB¦A ¯«†ˆÇ÷A¼<8¸Â šÌ⇥•dtx’ÅÎÙØrk¬ÊÙºå®2°* ÿ¯÷媓k¡µÖÉ=¨#SGw<‚?=ao¶Ö'Ác?ÖJBèàfÄ0GÓ“³#Œ&ý‹*+ΒȹÎT5ÅV]ªIY$×QX*VJØöHP•˜½8âisBâˆ,ÐrRDïÊÛŸ±°Ù›±øcÏ‹¹»)è 4h 4h 4h )yÏöY´þ¢¨é´Ò—œÿe›GðOê*Ž¥ÚñzKµâô}­_¯§¾ëü˜v£ÝHV¯×ÓßuþL;Q6e•·U¶×%àmª  Ë,µª3 €ym™lô Ž/0ƒ+X³@Í —(ia$¢É€F™æGÞ½¹·Å˜:ÆW;7+öù{X.ïg"¯ ªì™w«yªÑs̨d[9zØçêÛ[&T±ž0G·[¨Îž<تþç„“ÅYÜ«"žZ#©­.˜ÙŠN#-¾*PʧEÚ›EÝbJf²,ûY‘ÎØu€kkÓ •¸äôÞHãu û…·wÎqlÌŸA]ÝŸiB$¦L —Îü[ÈS®x‡UÕöÎSÜDßwñ9R\ÀlzÖŒŽ™ËUV¨¶Ç|2_q¶—ˆåñQ^NöR£±ÆöÝŸL_¥cÁŒÆÂ¡º“…‰¦åžVµÅõSµñJ]U]ßi!dc«·™‹Ûð,Á|v&m(Ùö@ vБ‘òåÄk`·…$¸—Y€õi•ÚÉ v›£A†¾S(L™ˆ<ž1¯í:ÊâÆ¬ú±2zýÌ"Ôüú¢§?Ž‹î-á.PK96>‹xæB¨2V˜Õ"©V’Àm£zaYº(Sµ’»|Öœy—ÔÖ:fë‚n#ÚnE=¿)ÑÈMýñØÄnäZŽ/Î6•¹»•8EZ_*§”m=颩ÕÖ€Ô[8`.¬ðøD‹aí;OØãŽ4Æ$Ó ¸ù‰¾?¨+þáíájké=ÖÔqØÿí÷cŒŒóý{;!¢´ÍMô¾·ÑBôÃãD‰±7è1—‹÷å‹P¦Wv®*e;WþSš¶"Î@ã\™eXpï#*ïin+.ôŽ‚‡ðóÿhêàòy5S‹ebs—9ÌU¯:˜5é3~q`õøçÿ"ÍŒQ/¢öǧ ª×V@ÝåkCn䑚ªOñíGˆ‡6Ø^G%È`sg²KHí‚fÃi†4®Âth)ï•ýz«"ÑÌ\¢‚»Ì[bÃɆ(–«Ï0Z–˜¡Ê·žªêqĬêªÎ¹§Î@ñ@7hÕ­šÜJ·‰[7¹ùÕµ“C[T‹„Ñ£@hÑ£@hÑ£@hÑ£@iKβͣø'õGM¦”¼çû,Ú?‚QTu.׋Ò]¯£íjý}=÷_äõêBµ~¾žû¯òaÚuUÄY¶:e9[X6íŽg·+Ê­!²Ç|aéÅKô$Äp3Ùš ôPJ)ÒÁ‹;§D¬ßqé‡A—/wf>ä 75q”¹ìEYeúƒ™ÜËcâœͰ6¼¨˜¡[·XŒúõ]¨ˆý:¼c ÃÓ¬y eúΓ “‘å Ø›ìÓ®jÕµ‚Í\!ùRÃ\Hl:‡Xw@¤#¹ˆ<‚ºzÙ C»ÎG‚½ÝcïŠ_ê=XŽÎìH›ÜYÔ®WWæ6[Õ¡çzç¹órr—;U5“'Êò³shµe’¦?ác7zðYÁñeÚγÔ®Ôå.Å9˜YP vâ0˜ƒAd&jã-WŠ3òËèXºQ"²±àÙý›`÷é—Å1õÁžÊ ªFÃÚî9o û=;yKl¨Ž©ïÁµJ²ÍP¹ÏÙ8ÿj8ã”÷ç/5…œ³¿ˆÇÊÅ\…²rçH=žėÜÂsoÐbÌÛmZ¡%ûlåW£ÞÕP‰*uÓtfËÛíü¡"ÓÏrAÊs…VN%4 Mf·-‘Jy›¡¦LYa”šÂÚ¡$àÛ‚‹HTkf[ÞŸFà6Bø¢’’ÌJ˜;‹9Ûrⵊ‘jXxkHYÖ%Ã"š¢ŠÛ<"5rÔLSƒÎáM8ëH[€âc®-¤›õµÆ™ÆDÅSc‰IH\:W5$زž“Ü¥ cÞ Òu0Ü{ŠQÀ8[s—®¦L‰TOwqc|*³"åk8£©ÎŒÓ'³H‹ÂAl;$ÒË©¬- ²p´444”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz>Ö¯×ÓßuþL;Qî¤+Wëéïºÿ&¨÷UFxlŧ[a8)dã©@ Ëš³!n##lñÐ$L†²½)É…IB1ÃÒ6vÅ ÖÖ²·³>\}ÃŒ!EðÊ%!¡sì%å”V#LÇ ‹¨mz†¬kØòŸ÷qÑÅ.‰ˆCQR[ܱÛ!ïQi–›à½âNÉÕÓ—o2¯WŒ;E‰Ð:T€ýkˆ±ë*ÚãL3\[µòE©^1ôîáC±ÔÀ¼&é`ÖUÙ S¥œ4Èï]ÑŒou.$}í´†Ùæ{Ô[ži¢[±Þ+£˜MH$äzí!¨Æ¿kg±SzI<^îgñíOIaì ¡ŠM PÅøÎ­WF50á¨ÿáÛäFxVعƒ²³ÎÝ­®ðUà´Š…Ù†ªÞN.üUó*¨•„fgð`ÞÎ? €øs†ßA’,ìXÒÊK…<Àw´j¥®ÞdKf1÷˜pjÆ-§ÙUŒø{rdMrŸ}VÐÞZ«ÝŠ}…ž¤Ê Õ¿Úz;mY¼ß2ùðŽ!¼Õ¶™µfEU5«¦îÊœÿ+™9êà qfå¶(Œ§ÈÆsœº«üÐÈËVš«ë`u²p•*cUˆÆÆód=Ñ5§†ØÃÒ4ùF«'`2†8+pkË2 ÂhÕY;sn ÁÙ*5UePå>K6XøB˜ e)øÍ=ýA±–6È-ˆç7AŽž× rÁ™ƒæ…¬Ô˰_NõõDØæéÖm„Ï4ªMßx³çÿ”þ©¤•´5{&o@›1}wqKžÊªª%Tÿ½µe÷Yé$U~AXâÇ-7F—LJÊJŸ5qÒ¬Ê BYÉu¥´a`{lÁw—ÙO lª£ZË­ÍÉ1öN)7<®Z@r–ÈO г ܱG1zFFFJ^sý–mÁ?¨ª:m4¥ç?ÙfÑüúŠ£©v¼^’íx½kWëéïºÿ&¨÷R«õô÷Ý“Ô{ª®"ÍòO¬ vG—û!³Å^MëÞ6òOAŸØÞAí_Þ~Èî~—ݹû{ úþûCÓꥰ——ƒ"eNÇHg>0áíè.ôÞrÖêµXm9ù->áÍ;z7[N>?ØØSJÕØ2@&³¾=¿ÆŒ¶Ï$ý™æ^Èòÿdbw•|e×¼m䟈ÌïŸwWï?dw?Tí>ãý½Ð}Xý¡ê5~z4NÁË£-r"~fdFP4ã¢ÎU^<³ž9lÓè´)»,Ž>„[u[$ØÓjYNDkxãmüx„ *êP*J|t $K^.„wÙÆ«9É[-mõ¼(M`á늅aË9;—}Ω‘‰–]ª·B2z±V.ba@8ÛAEËȹbÂíNdk‹PωºK†pÑì<;u¾Ÿ´h)¹xd”ØÉ[¤é €t‡'ºã— *áññÌ©k&«»Ç´ ~ ¼ÍP×8’kÅñ¥HìÎãˆye̬äøÃ™ÁˆŽøe!Vä}’)ØËÊU0´L!È —«ÆZyvŠ¿¶q–ò­²®À<ÌK¥6É©˜ÎxG´½íOîj0ЖIJ%wnÂÔÖé‰US%'Ž•eh䩎ˆ­ëÀæHkOĪÎ}CŽ‹ŒŒFʳœV"•.h¤@q •·1„–øÙïFú«ÜÅ”é »ŠaX½4444”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz>Ö¯×ÓßuþL;Qî¤+Wëéïºÿ&¨÷U\EšuÍZ¶°Y«„?*Xk‰ ‡Pëèäw1gWCïS»2¨wyÈðW» Ì}ñKýG«Ù݉{ƒŠ¥¡s›©Ù).[Ê:x3e9€œ=$úÛ5™½X­ãÕOC©eÎ{u†Ñ°kÀj  ñBá8†—â®·­èd1Vó¦ Ùÿ; ÕòĤMžÍ>b9)"ëJ4õ¦V³ÃjÏ$ö².½dRbq¬]yÃj¡Ð÷.ôpéufXdw±6ÍW/ d&MéêGA’T«¸ÆQ’ =ÝÌš§_©Þ¯,j¹püª(ð{¬9äÛûʰ*X7¶aÖñãÅ¡±÷,Š3œ² Cf²³& »# ±+(_OžÜ#· ˜ÀÎ\nÉwâÙÊ.ËJÇK!Nb»5…²EL áyÍÉQQ…ßm$l…£J  K–€b¾Ød­§³HXiUâdY*7‹Äæ„öNkx(kÉ!2 ¬žX6¶>[y뮘ɓºÚ’À:õÇös)K8â.Ü”æâµµŠÕ¸±.ÇSb˜0do1’nÖ.YÙ—_µËrÞLØ{•+1xi¡µ*Ó#Wb@M^E©‰X·k~Ùɱçƒ]Ú¶úÙ=•“‡zh¨ã¸ Ã]†1sDŸqXX‰wãyÌoàϬt}aéÎ;9nÞÙ±çª#@º«WX)Á H«N*¨eÖÌn[´*sÃ÷ÚfÓ÷”SØüåÉÌç¬9Aòù¶ìÒ©Ã=Ðñ‘j6Ig&o*ãÅlÚ÷ALSˆõpÙ°í‹}ýá zŒêÑ&¾ª_ýÀó¤Û ¬(Àâ0ÅrÎåål FåÝ‘™q²ì PÃÕĬ]¥¤Ò[8û?§Üõèñ– ûwÙ˜³%»i«VžÄìrÆÊ2¿[^[¯g2°VnvBÖ>!‘Í…Xã§/*þ†Ï•Grê9”R+LŒŽ(Ïkl«yhm¬•’$µöêh\C‘šº¼Ã¾újY¦î¬È0À¾A;tuWd© K8àÉÌÐVìƒYf¹–Ѷi·œSÁ¯i„îâèíµfó|cÒ‹=†6ÂS€ä­H¿ÙdQ³Ü±/WC²ÍdºrÑeT^®¦5¯mñ1 ¼Ñª{ØædÔ~edKާx‹‹©¸BÅžÄÜ2¹ê;E޶ÇY2’ræ¶¶Àd¶åW/bïaËO?T§I\»Pº§79¸EÚtU–FS ’yj•ÊmÃ0r!¬RËU,=¸òL½b^Ë^¬²@s´+t7·ƒ±,°§­ÄP_¸Õä³Fž9æ3˜'v`lŒ!Âc£T‡‹<DzDý£Ë­/*i €|ѱfUËALÇÝçÏiZ¢Éªêw ¦¹ppØÄx¢0$XõãJë~a/ÙõPç¼jŒcpƒ$×W+¼§°1ë”*DªâÀ¤^ˆW Ý/“Yisž‰päSŽüqN‹Ôô’ö ´ls6z"e2«±Œˆç#k°†´tk7·7¼µÉe¾LÜ5ugމüÉÁç0‹guû‚Ë`[¯1è~»Ø]c RX9e²X¼Të,™“Û pƒ¦=—w"dûä‰ôÎe2æ(u‹«¤å.p¿D«ãUd«wÜtÀâ¢æwEá_cø)Â/«SÒ)ìNNS¦Ã?‹sxjÛ€Þ8¤-Ò›5Ði‹F^]ÙY'SÚ'2>›9S·ÖùkÔjG‹Sw=@¿*uà¦+\€Y¤/o]eÖ ÞÙcŠª}­ßz"»çYò–ß­£F£F£F¥/9þË6àŸÔU6šRóŸì³hþ ýEQÔ»^/Iv¼^µ«õô÷Ý“Ô{© Õúú{î¿É‡j=ÕWf¤ù2¶°kŽîx¯ü€Ø“ß•‘þÔ²R{¬ ð]Ý_4zIý¶ð·ëúÊ™ÿC7£ž…¤“é½Ï±†˜I “ê¤ ‡»Þ)TÄ”ZiñS¦,{Ò°Ìn·l”¤qŠœ°Î¼M—¶bAÓíï,}ÜU±¡©Æ#™–8n32ÚRÛ ““5% e™šÚÙ‹@¶²¶‚§XN‘XPaEÄ”H±bR£@4‰“$lÇÙÜÜáñ<›[xÛ̾AHñdy7ʽØÆÞ6è=Õäùõý±Ù±ûÇÝS ôÛ¿§ÿ˜ÐT·3¼:mÎÌ‹åÝVJÆPlÔm-‘b²JòÊ'n I©l2PFys±F%VÌÝ×s’GÁ¦†µåÃ_á¯W F®’jqŽ:%úÎzáÎãÂ\Ĩ«€ÝÇaÚ˜³uÂ÷Q#®¹¼T­Ë*ằÙÂÁ‹ê‡ AƒÔL’*¿õ$gD‰µ½#nS®ï:JÞžpUMqU–Eh,̃k»IÖzòݬ·ÂåW0œ†´\œ ì•.´ÓöãÀq[âá8» ˆ¿o²V¥==ò×å+«lK²¯ç ¾ßÉ[RjÔÅ›òÂL²•pè«`ך>;ÇK] _T8SޱÜ*zÊsL"¤T ö,Z”G±x—‡+‘¦/ìã¦#ãòmÙ˜UAL$9t–¡2"¢ºC×yBc=n,Îo^@Œ¡¼ ¶Aè°dÈ€)’0EÑ á°ì 0ï¶è5ÄWmmq¦±ê+"Ô¯úo>W €^ô‚³èÍ 3Ê)ÒÎ $¡¿èŠŽœ:Oº—FÎØWM'Ê/¨™9“Š´R,°éÖÅ'” »Ã½›‡év@iq…\BA–á9/½ ²ÂDÜSÝÞ5Q•rÚth! ’ð:aUy6åßycxp°Y¬{ùû¾Ëq+ÆFDPD‰V¯+„…øœ0A'ÖU{[,ŠÁ¼5Ohá6&fýE–íçIcòÜ+æâ«)%g#,k·l*Ùlƒ$ØŠÃ^‚qȸQrÎKÁ(Âv%nO߀$”ͨüQàJÜÚíÖY–ÝVל“XA¶¨6ƒֲ̨Zå¶e³Ð#•¼pT‰bÍ4.\RBK •&ċ#z>öÞç{š4kˆ;fÖÊÎhuÃ5‚¹aÚÑã3­€D9ØýŽ+dë¯a«Ÿãh‘ËGoA#Ûâ·öH–ô‘7x7¸ƒ·Ñ£F€Ñ£F€Ò—œÿe›GðOê*Ž›M)yÏöY´þ¢¨ê]¯¤»^/GÚÕúú{î¿É‡j=Ô…jý}=÷_äõê«ÃfY[u[aMr^Ú Ú ²ËZ£0˜–Ù–Ï@(âó2±å‹4 йr†–J,˜`I‘d}èûÛ›|X£ïì‘ønÿ†ÛÍ¿õ{ñ½ð—Þ]%ó¿>ŠÃøŽø„î.xÇÿþéü:yw¬ü7Óߎ»‡öæ¶ñ¨CáÆ˜ø‘øºìßú†ð‡Ã{…«ÿ wç“{7´úçd}xý·Ü=µÝ_þ7®tò Îä®_Ú88{å°ãZÝ![ËÅŽRHtåP­v@«j¶Xqï ž ¶rËñ 6OlŠh´Yñ2·èÁÖB+û+Ϊ”Vo·/îp¸ß[^WÓ૾.ã^SáÅѹ"ÕOÂ+ 3nÜe{;êÉ 8‡ÀÇBŽìvÍ¥{)U·z8ĹUo<Ÿ;uqíâ èðlIùdIî“Ý#9Ö‹ÙE¶ÂqĤ .4·º©UÈŽ*[à´ˆ"÷6å,³VÓ™2Bå°[ØÞIÈ^WË ©j†ê£+ºo¥×™‘²º6ŒØv«£›Õl.®Ú¥VëéÖ£»Ë¦9!¬ÚâK®Á¹‹ZŠ”GÚƒrYB2e/Ôùíž76E¡cBm†sq¾ÉæÓ|[Êrêj犽ŸÈÒ’¬T&ÙÁUùB’ªÌ(×+òxhâ—!ä ™¶÷$®˜ –YpßL|Ÿú^°·Ò( yŸô«A½x«,hÇuð2QmNGˆ×ÕÚÍz­^W ñ8NS2¾·ìL‘d€ïsWˆ=†Dý1ÖXUŒ´å“_[µÅiÛ–W‹*xT†ÃÞV~…Œ¨ç 3+Ö$ëQ@e:YÁpgw‘‘¤l ¾ãÓj—wz>çVrãÃ*SáSÆTßm|yËá‡þaÚ¦|eñ%Ô|Óõä¯y÷ŸUŸÿ{¯·}ÿîŸB÷[>ì) '™^q/âƒuDÝi¤?ew‡ù/¤åôºusµ…™~&O O^7¼(D~ u’šgºI’í%ãu}»ÙcØ·/ËÇ&Žg3,C¿.ï<¬a¯Âd¡èk_×.gd*íÑwK#cíWBA¬x°r¾©§V˜pUP¸]p¤ÎÔí¼rS¿° KáÓ i¼h¤ñÑ”^VdY;÷(êLž9v¯oiöq°×làV2ËC~;Zsc€ÝTØÉHÏ uƒÊxi«•`Ò“£·¬B©9nÙøIlg­ßiÊ«ÌkM˜UTY7µïn¾Ù™ÀÂíìkÚ¶Š~Ï`1b–2 öAÒÚBH‚-Ê: |=²·`óéæÝ|¯%kÐx釡0>c˜˜Ùc£Ò[ô¬‰p§îÇÆê†òf0ŒáqìBe6›= Ý7´æ4ÙÕeg]/jŸå•åöD3FÐ9ƒñè’B3}N‘wõ>›œiêÖÛT$œ#yiQÆœÝÜžÞ²esÇ&$]Í?ÞxUŒ¹æ—gÙõ§üß®¿Ãeñ®¬ >üUÒœÂ½éªò߈‘,}†ëÀE׳ Éaœ@€)$=Ì­”‡89X¦X­®®^Ø(Hc×@Ù—bó’jáåÐ{Ò#nn ¨pÓ‰èQʃ\".\Y›Ì]ec¦\uµ}n×{޼µìt6œTG]Lx™\ÏI;YÁ}PH3ºq‘£ŠÂ÷þ˜Œ’ö·£íå—&¬tÈùµvî)™ìzócä—Zö>6°ÖCŠÕ} ™µmf§Œ×ÂaÁV9\vø>ÙÊc¢\*¡é FØ‚"Xîñü:ÆÔd¹rƒ )܇Ïü‹Çê’Îù7æèi{*çӓۮ݃XÚ®)¬ädÈÙ´Ô”°ÝŒÖYcÛL­Ô¥ [Û±óvá¯C]º„.ÜŽ¦1ÏÄ~erìï;]è8ãU~ï50÷UÏgõnÆMýÕs¡õΆS÷…£ªŒô¿¶÷ñýö`S2ï(2NÉÅ%”—ݧR3 }/dÝvâc _-­ªc䃂½Hñ{G2^ú|¤dhkl™.Ž,K-S7™¬Ž-ƒ²ï(ã¦CÛ¾í6dDß”Wa-=‘£ÜLAdÌÌJ6êaŽÏ³äƒPÉ nr"Muy7…&П_pJk€uìsQò®ÝÅõgeŒ#ç šË¹¯˜KV¾s ·TñåpMÜcާ\F|ÑI[µ³5xV1v%Y4]— z=Zû¼Å^©ïW«Ðkõ¤ðWà[•ÞÏ „¶&ä_6/ eM§ˆüº°ö•¾9}¬ Ú4zÝÚÚà…é–Ø±ÚxfËs291 øU˜ 4RP XG*ˆHQ¯'ݧ ÀÒ=›c¦S•µƒnØæ{r¼ªÒ,wÆœT¿BLG=™ ÏI¡Â,¹Óºpa¤JÍ÷˜tr÷vcî$)ü×°QÍÎCj¼(ÊŸ™ðÝ:߯ü¢“.ÿP(Q‘Þ3±îªm¼lë‘vVºKDŽç*Úœ {©œoYUtffduù;ì.NL'[Ûy/–fkkf-<ó#3!ìTã ²%”4pÑIr‰,JT™ägÉ‘2déÛ›œK¦*àMù–x³É…ÖîÊôˆ˜óŠ©w•ˆ´EAŒÒR\ÛÜëÊAJU'̼^o»o©v¬Þ˾‹XW‚¬GÜx7WVËËG5]…ÞRYLdg—<4åÞ> »ß±ÆÕýÞj^í[ž°é=ò›ûÔ \è}p_ï çXU'ê¿cœ!î${™¿XÚZÈ5¼~ÇNa{ŒÎÖš,{å?^¼2ÎAÀĵ²ÌFëö‚C¯Ü Š’ùeÑXé²¶˜tå¦ïFŠloÀ R "úƒ+‘®!#,²‚ËÅú\´´×cíü§å¼9]8D(ÊH²Ý`šV« ¨RG™©…Bò”Õº‰’¶Æ*ºa¬É¸-â½ÍÁ©E•"‰ž­sŽ9#ñqmûe=$+Ù÷LY”Æ8ä>*Ýù7PdÝÞ’Qn¤ª¢]“Ôšœ’OÛ–àm„fzö¯YÑ ~~&w£ûÑ3a *<¬I|a7‘Æ\n.™c×±ò)^\o¬Ûu P‡52Ô²J t•ƒc«Éº áà‰ÅÅã3› ”=,¨ ÄdOÜ–.öÅusåh矑W¤de "¼uH®Œ6ñÀÚ‡$¬œa+/æÁµNâÅ»!Ö­9_y°µXî[Ï"mG5“À½ŒÕSå}/aV2…ÂhÐB–>VÕž7WاÓtk6¾ö­•àW2ÁÑ`,2w"ÄJÙ ·a1ëgìtXÃäú Meem)my55x’‚1+*Š‹"`[Y[8 kËÀÅGˆ,(0¢âE$Hر <8qöcìííðñº·Ô•Å|¹A8MB’«,u¬jÌhY-ÖÊEÜŽA^†TQrÎKVÀ˜ÄŒ ¿?r>ÔÂP#ñnJÚAR¹±Ô%þKZ”Sã•y›>?‹Víª›W7VÖ£³Ù’jºâA,o¸ï³•sÅŠ Ói™V Ô½[ –aæD“0娘ƒ°ñeÆâé–=p[)•åÆñ:Í·PÈÕsS-K$¡PÇIX6:¼ Þœ\^39±š CÒÊ‚ FDýÉbàïlxppÿ†OTn.c òNTLÁÉA¤«H“IJcòܔڄlÍ…¹RJf*TE¢îmO­–åÉ› (½ýؼL^¡Lަ,ËžùÇÄ—.·oã'‹¼Þ£ÛÍC{'Ì곫_ÛåÁÀXdîEˆÉþèš?Ñý×¢?ÒˆnmÄãrMIMŸn•™NÕ’Êd1«7É)5ò–üûµl*ÜäÐëÖìÍÑR,bT ’T%ËpÔ d'‹h\½ø»…EFRXü·96†§jÊI@™É,Ä•**ùJ¶[ É6ÑSgM\³’Å…6Imø»“÷à vGxvö¥=FJ^sý–mÁ?¨ª:m4¥ç?ÙfÑüúŠ£©v¼^’íx½kWëéïºÿ&¨÷R«õô÷Ý“Ô{ª£X£‘øè¼%ߑ͑‘xŶ†E°¢°ò[±kÓf« &ÂX¶xòf×dzR™0øç'ɹwr½X£&Ñ4ëµ@‘»\4¬[«®hÐd»™Aø¯æ=ñßýð³Ký=7É={Î~Œ{ü"ø[ÿâŸã—á×¹~ýBøÛ¢uúRëšðï5œ‹uË[‰6Ü^8Û–­¿$JÁY³•D„<ÈÍ‘g¬²â—Õñå­š8jË–Hh‘5ÜY!Ï“”}èÃöøµÛ£A¬º1Ó,.Ÿ“ Z*q-¥aîgQ—ºÑ„ƒdQ£² Àʺȧ\}­‹{*ŽF¤sm¾¾Üß'?Û^³ =•ÅZ\U{#¢³Œªu:G/Kê‚«`hù4­ÏcÔòâVÕ[¼¡al<­dvmK­®ç.5¡’ Zu²‡ÞæõZÖru…S£7¢•8´¬©g!LgÞ^/òƒÉ>IÎέßN×Ò-\ý~ç¯y'à—¯{<%ánŸÿ"~|ñ‰ñ=׿å/^îù£ÚíòŸi‹ï#~Tá›u7½eÓ˜³ˆÖmg³9…ª¥%7ß,À„uápâ8Ø!›'”xzaÛ¸?n¼·-Uw-„èÐRû33#¯Éßarra8ÚÞÛÉ|³3[[1iç™™`ô‚§XN‘,¡£†ŠK”H±bR¤Ï#>L‰“$oHÞÜÜâ«+ºî©ó’NòÄÅ÷ wÖZäF:rÿ¬È&Ó{»ÖÜ jYÅù–…«—2«–ò” Y\”Ž=U¬»@]ÖHì†ãŨJ7BJÚíÑ Ã_=»”>ÖPg‚Zä_•HufX¸»i¨r‚éÊ …n©0Bõµ-|6½">@ª0¬Æ`fÚëÊþD 0ÂuÔÄÆí¶éì-ÄŒïVð1Ñ™o:ÛqwÜ6…Ž˜û’ø'U6*Ï»Üð¢ñ;yÙØ§yRª†Þë wÃÞÌúí»)ªbPཟT¸›ÍÜï) ,z¶Ñ Åÿ"뺮9Ì6­‘Q¤+ª‚âåd&¼#]Ð4u½Œ5 ÌÄ£ìZýùÞœ+ÃtYV! ÀÊ|{¨,ÒEœ2 3 9ʹ¿†LxCä²9´ 44”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz99&ÓØÜV›¯¡êž¤A§¦z¯EÔ{}7l·¡õ¾ž_¤õ~“Óú¯I+ÓûÏ{é÷¾g»âH_™$Ð+0,FõÁ„:oŸãzÁEáì+ÓL \QFÎ︕±±'kçû½ý­Þ.Ë4~£dGÿ¹þšÈ×5ŠìÒ(JCatîþÆýCZïlïlˆ!¹µ½µ¸˜owks‚?æÞ糃ƒÛíáãáöû8¸}¾ßg·ÙíÒï&º~/Ï×Ù~—y5Óñ~~¾Ëõ÷]O¶Ž®{í®QÀF|¸kb¶ì!O¥ GñÂL¬Ïh!ˆì•+jݾ"“JM‘®äÁ¢álŠ–j­Có;¹íð7-Õ‰¸$ñø¥D¼I)kE¸UW¬œì%:ånÀÊ‘qZÈXÉä„…€[M©çÏ]¿™OJŸVW‘?/˜±yÍÑ%ÀJ®âN‹"­®í÷±¥ìîG‘·óËFÜà÷›;Ü<œ?oƒs‡çpû>w³üxx½žßnMñ¥Û:y`áÀ< ®ðîÓ¶/,qÈ¿hšLÄŠuÙæ’Ï _¸ò²ÃßžÌ&ù§YÏÕ i‹ÌEÁ†>T41‡¬Ôƒ¬™2¼áÁ`ËÚ¯*¯bˆÍ nÈZÛ,t›Q"ŲD×jA á-’ÝÛ`vÙJ"ÕÄ4›ëïǼ–å£9“ÇG„˜~^Ç ÜÞööärk„&Xö9lƒ¤×”ãÄêÊÝ|#k¡ÂLªì‘eC%_XíOíGxqx4å6iÂÏD*t0é6唃³¿–\}Çë{«o“…qË¢òžÕ¯1ƒã¨6MÃIÆGÙsÑŽy h-Øé¿~ê–‘U¹—v~ÇžTSZªG5Ó¥ÙÕr“P)K3kŒPËË4]ûlæþQ[ÞMS+UUÏ•õ7˜…<ŽAâ}cƳ*k¼9 šù×Cs¡Œ†}õ±\þâÀIÖj¸_¦Ió­©ÄÌ-±ê-¤Œ™¯3+7©L6^|®-°2“yd«È"Ö8f…Ï`Þûâ! ÄT Î ëJðN% $±r6w!îqôeêþ(G$U½o˜³¶W’Øõsú°)ý×d¥ÏÓž¼ŸÜ"üè€ÓÖlš¯¥÷¨mÎô 󨞥¡²€‚5V5‹s m¼·Ê~Çlü3¹mP&<íbýÛ^쵄»-Bµb\J4)À¼&ÅÈhS Çë ‹y6À\­¤M_¿)‘Æ\‘™c¾IÇË¿tWò´§fÛ4ÕCáw2˜ 8¨`Ò/:â¸m‡q¤nK;z ª‰]âaA[N…,ã a©¤œšÆë2¶n¹kŒƒ¤, ‚¿ëýùj¤Úèmu²OjˆÔÑÝÏ ÏX[íµ‰ðXÏõ’º8± ôÃäìÈã]3Û<ðϬ<ìMY‘ @êfeA 6,+v2Ý·cWèàØW¬KïÂ÷î ~ŠÚ$°Ð†à>Ì91Ém“Kù‹H¹ŽÊýÌ/¯„¼RõgÊ ñûå¨%â*¶jÅG2ÚVCR’v‘k¤AdlƒRP#hHü0­…ÞÝàXíÎ-”áçµù^g6ánRb‚Euñj‘p¤îŠ3&dß)’ÜèõÞ'w¤7E·ŠÝÕzbFÎÙokD@¬"¥•dLdÇ©y#^wUÌZ¶Éþ_õ§0wi#kÇŽòî«Ûº˜…ÛWSU*'¬ÚŒÁ«€|]Òq|oï\ 7øc‚¹¨ËöG“;·®9tb=a~ÊA(oy ´F¸T·o;ÿ"2IÍ90¬™Òg†K%¶µŸÙÞÿ¬0ÄöYÛW`S[˜Xó¶„9µA1L7Æ\‘¨ðËåµpcåÞn ÂÛ¿2r£üPøÍs«µ\ö­¦µ‹ùð¯8±ëáñœÿ…×OÜõ«—‘ªtÖ1ûŒ³†ƒò¯™n%aòÞ/¹Z682Jsi¡×53Zƒ}i1omêÉ^+ôÁÆ'Å‘|Xè”,ŠÙ'ûMjS,¸iÓ=°fGb¹Æï,³-º­¯9&°ƒmPm%™Q­d´ËlËg G* …xà©Åšh\¸¤„–*L0$Ç™Fô}í½Î,—{1(ñlÚÓ]ª~P}yÌqדŒ2ÛËá•ÄæêúlŒk­£4”P8 Q§}á›haDж^‹0 iñ¶\}h¬–žymxáU“‰E X’k4…¹lŠSÈÀ2bË ¤ÖÕ 'ÈÞÜZB£[2Þôø’7°šÅ”÷4hÑ 4hÑ 4¥ç?ÙfÑüúŠ£¦ÓJ^sý–mÁ?¨ª:—kÅé.׋Ñë¹À,ÜÖ,¤(„†‰yÄ#lÌ€BÀcÌ…6Ž Èò¢J¹¹±&6þÞæÎþÎçÖï·Éîæ¿ævëD¿ÿN¼Œ£fž— àqµA54s ömïnÀÞžØRÔݨûñdnDÜ‘o‚NÞĨÛÜ{<\|;[û<~ÞÎ}A›7ÕÜEíb´q‹¡‡lÛ¶ö§ìÀ<61H{Sv£ïÊ·/n<­¾ ;{¤ìðopñðíoïp{8w8šçù“þšçù“þžyåË÷]P™^ãÞ{_6LÏsï~g½÷^£wsÝûÏw·ï>gø|ÿ™Áó¿Çæðÿ‡®6¿_»ªE?u«7H0Ï#¶¼2­€Û·°ÞØñäÌ4U°‡ü¹ägÉÞÚØDHã"Û—¸T®ñž( ¨étÉø¾•~ɤ>!¿“{móÃmO‡«ÞJ冀ò'Ö¯óßöØzªÑ^$71Ì2¡l–zªÔ¹;už¿ñ?•ŠB¯-VºÚŽó™î5Ê“âåNF?Pcç}ömH æ§”?œhÆ©>™`°ÃÕ®ij¼šæ¾¯•EÒ+]åëð)ÛÖ8$Ë%…ÏâÊ¿ö‘-ßVd¼Kc÷VÐJý–†¤ !½¼ÇÔ¶¶$ˆ £K¥ –¸é“Óì¡TM¦Á)QôlfÄÏ²ä· Ê¿p ˆPy Ue¤¡>;]Eq©m©íÅ¿d“•«›H¸3eG]~.¬Ÿ¥¯à3¢$xƒèêøºî>š{É>Iø–ð×DëËÛ‘Ûçúogõî½þk¹zì½'(¹@Í™ÕNodsmY‘*úZȳÏ@‰SÆ0¼Å¶Š³_œr#Z%âdYË#i58ô¶I,,··Œ6µÍ4Å꺬ÜÕNfÕƒQXö] ¹BÕ|º›3Uñ{³oÂù" 2=µ=e¢ËêÀ•JR¥)i‚çAìÐĈߓ_6=HåYj{»27=ºGšd]°‹HSÙ ¦Ë´jÍ«¢¯-JÆRfW¾ÝíÂk¦·DåÕ£‹R³‡vHUQ–A»&ôJƒ&þˆ7w ©.öðÃUb“e~Àr{:ßm³Ïˆ3÷¸(±ï}hª?or_ýý%´Oòµý ;ûó\Eœƒq¦®-ÚIŽÔ¯úwp¡Øõµ`ð˜w¤‚tOYWfm( §K8,i‘Þºÿ¢*: Þê\HûÛoo¹—4§·ÜËšW‹ÔvM[œÃZyä]#ð“Óp…+ 1ðÍ•_ÝNmeX¢ò̵ç;UE§¤-¤-»Ï™S×xå–s±Å#d6€§½ø„’~»Yd¥mÎ>k&âÕ§4l¾Yѱo~}DñY[ùJJÙ݉9vù¿©)€á(@‹½$ÐÝâ¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W®xpu°ë<ŸüU'ü!~ÿŸÿ¿òñU>ÚaòO¹åÒø\œÜoû Ç&Ÿ&œ$m²(ŸŠå³»É'éIg¯j¶Z,ð¥™:+ÿäÿâ¨ui5k1¨É+ÿäÿ⩺ԚI­…É.çœê>*¹Ùek¢Û[ÂÐéXK{4¿B2FÛ°;‘žµ’×ןðÛh¾M”–öĘf’"f‡q‚°8çäõÏøBü5ÿ>+ÿäÿ⨠ðÙ8Ÿúï'ÿIU¤º1¸Éža/ˆõkGU¼ž:uÔŒ^}¤Ð³@|°œnÈ#õëU¯5cP¶Õ¡º’Ùÿµ<…›•$-”XÀ8ëšõ;Ÿ øJÏoÚ † ùÛæÝ:çq–÷¨?°¼ýû/ü?ü]Ö`åŸsÍæÖ¯®5yqe¦\2ZGiM • „Ù nO ¥U¿»Ô5}JMCQ–6™‘cT‰pˆ‹ÐyüòkÔ¿°¼ýû/ü?ü]Ø^þý—þþ.©W¤Ò„ŸSÉü¯aG•ì+Ö?°¼ýû/ü?ü]Ø^þý—þþ.¯ëpì/dÏ'ò½…W°¯XþÂðG÷ì¿ð8ÿñtax#ûö_øøº>·Áì™äþW°£ÊöëØ^þý—þþ.®Ÿøp ?þ»ÉÿÅQõ¸vdÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ; Ù3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª>·Áì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡`öLñ¿+ØS¢QÈì>PyÇÓìCÁ^'Àÿ]äÿâ©O‚¼8:ØõžOþ*—ÖáØ~Éž5u¥è׳™îmüɱRÅ“ÛÙÆQX(Vê~µëÿð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUOÖ)Þö$"E¶{O"à63’>¹H-´ðÊÛ¦b¤0 ò0ÈéÁ5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU?¬ÓìÎG‘;FoRP¢ŒŽ{ÿH¢Å.u•À û$‚½gþ¿ ÏŠÿßù?øªwü!ÿ wþF“ÿŠ£ë0ìÃÙ³ÈvYÃm,Vé·~ã´)'©®sÄ«¶Ò÷ÿ¥}ÿG‡èÿ‘¤ÿâ«Î>0xKÑô]:[ _%Þà«1›#iõ&š¯ {© Á­OJðWüˆúýxÅÿ Š¡âKû˜¯åh×nì¡Á<‘×ÓŠ¿à¯ùô?úñ‹ÿAâù ¯ýsúW ÷f½ iõÓk,1\j¦'m±$—L‡ŽÉätõ?Ûï?çîûøkñòiÚØ2Øy—¶qB‰w,a+É“"³©(Cã+¸ðÜkÉg¯ÝI¨Ïow#,°NÖÒÂÿ»•YO’ª|ì)C¸F¼©ùŽIiºû}çüýÏÿ o¼ÿŸ¹ÿïá®?SÓµ˜üج..e·>TŽ^Rd‘¿x$Û‡B¼ù'‘@ª™ltJI‡Û¯ïDkk–c“fÙwÈy›%T¢üÅ•¿‹~8@uo¼ÿŸ¹ÿïᨭõ‰o Yíu'žÎÙ"œ²œqÔW2!ÖG‹a‰dÎÂR$-Ë;p ¼Á3ˆ”ƒŸ˜Œ–¿ %Äz|«uk%´†êyHÈIW•œ•ˆèØúƒìHCˆµ «(UÖU¹»Ž2劆889þy©µ-Jñµ À¸‘ Ä üëoùéö‡ùÖ…ÿü„n¿ë«ÿ3@ bVÙIÎ÷hן™×9QÏ$mlŽØ>•/Ûï?çîûøkÎÝcYãŽÓX¶SáHd½B±;‰ÕfO$´Cn9àù»†¶šDêÍ~^IP$†åÌXÜ–Ú~Q…‘H*8Ál±¨Õ. ­¾”ȪLrÎ èp#Nû}çüýÏÿ q¯¥êÒ-ÍÐóáºM6$·Hî8yÐÊWy,I#råY™Ib |n®ŽúÝnôû›v‰eYbhÌnå‚Áa’õŠB%ƒÄ)sk%ÔÂËo|É£¹Ü‰“’5kí÷Ÿó÷?ýü5ÇÍk«M£j؆ôÝK¥³I$1\ï±—ˆªù`@'? ‚—Y†îîêÑãÓõa@ó5­ðˆ®|½¢U\žw7µÊXÙk+â9¦¹žAnFÈÉŽHÎv n€W$D§(~c’[nÿþA×_õÉÿ‘¤ýþ³{sg§Éæym=¬s¿••ù˜tú{VLúéµ–®5S “¶Ø’K¦CÇ äò:zŠžoùiö‡ùWâ[¸-5¿i‚î-Äee¸€G"‚Ø$¿7—–ncä‚òÓ£>+µÉ×áG»|l—h%²3‘€}0jÿÛï?çîûøk—Ô¬çÔ"Ö¥´Uš;Ý%!¶tuÄûî‡=>uç§5­gu5Îÿ;O¹´ÛŒyíÝôØíÓßin}tÚË W©†IÛlI%ÆÓ!ã…òy=EK©q*–ŽúWPÅIY‰‚:õ}Å`^Aq«u*éÿm†òÖ;}›Ð"•i ó7í"A÷C3VÓMÔ¬'„ÈÒ½íÓI“â! Y@˘ÎìˆéÀêþßyÿ?sÿßÃM:¥À•b7Ò‰K*ŽHÉ=Gæ+‡°Óµù.c†åï`²óÑœùør¾\ÁÆLÒ¶ ò‡ 1Õ@ µi^éE©Ø^@·w†Þ)! o%ѹÈÊ ¤1Ã1rŽGÛï?çîûøh:Ýý„RܤÍ#G0YX²œ ú×3e¤¾#¸šH®M£îç“ Ú«+)èýÚrXœîÖ¿ÿu×ýräiÝøUÚûJ‡[œî¾¼S½û"† "z/ÇsÉÍiÝë6VÖ÷𕽴×M²Þ9§Ti› a9c’8£Ö²¼ÿ"^—ÿ\ÛÿF5s^7½µ²Ô5«9î좓[Ñ’Æ#5ìùæH$uo/÷Ô~Gãš(ô_1ÿ¾ßAý¥oýŸöÿ¶Åö/+ÎûGš<¿/ß»8ÛŽsÓÀøiu=nå¯êö}>{ûõ7‹¨î†K?2dH£U ¬ö0p ¼H#[hšÎŸðÎ÷C¶±ÔRþ 4‚ÞHõCæKr¨̉ŒƒË„V ¹r7èÀƒæ?÷Ûó¨ÅÚµÃÛ­À3"«¼aþeV$)#¨«`÷Ú}+‰ñ›â‹ûëGI’êÓtfwº ™‚ܶ͊oý“$ü¥U—qRÊtüA|M¯—±Õ$Ón,"2^(W•DÄCÍ 2¼`e $pHOæ?÷Ûó£Ìï·ç^fšO‰›@˜[ZëV—r]$·0]jFã1mp"·atmmŒÌdˆ·'¦"ÚW‡u¹®Gö®¯ª,QØA䘧lŸÌŽå&æ%;ÙÕñ—óvŽ|ØÚ9>t`U•¹ PAê+†RºƒOÕ-cˆ­u'´ƒ’JG±XOá¾y0 qª²²ž€Ý¡Ç%‰Îè!·ÔΉRÛ_ä¦XMØó倗(A'Qº<åÁÂ0äp@:¸õK‰T´wÒº†*JÌHÈ$ר ƒî)ßo¼ÿŸ¹ÿïá®=#Ĉ–ñùÒE—”ùR4ò1‘±$AVC‚¬8?"ò¡Ó4똤{›»«³1¸œˆÚmÉå¢íéŒ ýáÓ;~ZÞ:Ýý„RܤÍ#G0YX²œ úÕûýföæÏO“ÌòÚ{Xç++ó0éôö¬ ÿù]×'þF´&ÿv‘ÿ`ø•UŸÄ)mu¬úÂÅq.<¸d¹Úï“€NNOb]RâžYo¥Ž4RÎï1@êIϸ¯Ý倴y ŒÏ¦Ü[ù“\ÅC)@¬C8m£Ël¶N@ŠçNÖõª2\4Ð\ÛÜy,Œ)ÑÕ„H¤Ë´2Â5û§æ9%˜Îóí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¹(mõ˜&K.íâŠUimÚå]çm’«²’Bì%¢!NÀ6NÈÕÛSƒO™.®¼»çIÚÞÜjÂÁ̲òŠß’ `!ÆÝª07Ð#ÑWQ½V .æÈ9åÉ•uÖ.5›¹nV5h.ÞòÁh FrO<×]Ãïùj_ö—ÿAJÑ×W•|sÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMkKãBŸÂw ÿ‘Cÿ¯¿ôF±á˽FñgŠ{d]€bG õ'ÓÞÈ¡ÿ׌_ú®†oùgþà¨ŸÄÆ¶8ïøCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š›ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹Ž6Oêwc(º²ÛouÏûÆÉU<ãåëV®|%{5Üҭ͘Wva—làŸ¥uQ`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øšŠçÁ:„Ö“D·VAFdld÷k²¢‹Ž^O ^½¥ŒBæÏu½¬p¿ÎØ,£œqÒ¢ÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,3´ 2m@²Óç’'–!š"Jœ±ÜŒ‘Áhz(¨-ïm†7Ii(†a‚6¹Ep9ëòºž=~´=Q@#2¢3»U$œ)‚xZáíÖT3"«¼a†åV$)#¨«`÷Ú}*OþA7ŸõÁÿô@öžŸÿ?Öß÷ùÆí=?þ­¿ïòÿe[ê^³†ÂÖ÷OO"ÛÅç6“3DÒH(3ÊrÌwu8<×Gý‘¦Ð:Óþü/øP%Ôl]ÕòÝ™Ž©$þuoc‘ùSfÓ¬mü¹ ³·Š@Ü2DªG¸Ì|A×µí+GKo ÛC6©qI®¡‰m×ûûda¸ú Ié†êJ0*@÷Úãt]{SÖ¦ÐN­l–wêf6ñ]$Ñ–ðêQ›äàG#ž§² Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@s^!Ñ5+ýB;4Á¦!»sA$ *쉔¹Q»"96€C ‘!ÇKEp߃uÍGN—K·›N[5ŸP¸ŽIüÉê+pãŸ|ß)[[VðM…Δ,ôô{R×–·2˜îæÌòåVwb­–‘—wÎ~bÁ 9U+ÔÑ@?|%ªëVö‘i2Zƒk%¼×2: 0JðÊäð§*c`TÌH)#øFúK½@Çö+Yî>ÔW[‰ßí¤Jb~X÷¨‘†!L*¥;J(–ðW†gðí½ßÚ6Dó²âÞÞHŒ*œà„;°NÒHDç€~'ðÅÞ³¨I41ÙMæÚ­¼3ܹi’äÜ@¶d;Ôðc9…>n…zÚ(€Ð|)s.£5Õåª[¾£¨<¯*¹šxYÐ[20 Âw‰¸!IÇÈI2ïè3xoH]1­ôèaR4kD!®WkO'p+†Æ>ûgކŠä¼KáÝCV×ôëë8l¿Ñ6²Ïu"¿–Á³‘Bý0c’&naµHcø>hu]zm14뫬ŒÚ”Qu §göH¬-falŒC«NXD¿9@N|¥¹ù@;Š+ñ‡õÍRßTûÓ¢›WÒVÂãΕÙmÙD§äƒ c1\»v†ÃýÊ¡ÿ¢—7š¢YMu=ãI%¸`ѬÆì‡`³“-®GñìŸ1Ú¸ïè®[Á^ŸÃ¶÷hÙÎË‹{y"0¨P~p#‚îÁ;I!žøŸÃzΡ$ÐÇe7›j¶ðÏräI¦H “q ÙïSÁŒæùºëj Û}KO¶¾´“̶¹‰f‰ðFä`8<Žë\>ƒáK™u®¯,íRÝõAåyUÌÓÀò΂ّ¼MÁ N>BIïx?A›ÃzBéo§C ‘£Z! pÊ»Zy8;€¹\61÷Û<t5½í½Ô×PÃ&é-%Ì0F×(®=~WSǯֹŸøwPÕµý:úÎ/ôM¬³ÝH¯å°läDпL˜ä‰›€XmRþšW^›LM:Àêë#6¥D]BϦÅÛŽ<ÅoßË6äï…å¿ð‚êPi°ýši5A$–jêm<´¶¸Îÿ&Bù…„lJ0#`!ÇÈtæðfªfÒ(ôâöLÒ#Ë(‘-wLÒ,qÄð7É* Æð³PJmM Øž¸{u• Ȫïa¹U‰ Hê*Ø=öŸJ‡SÿMçýpýÖEž—4^=Ôõ6Ñt衚ÎÓRŽBn&`[r2ã·œôTåºG¯©ÿÈ&óþ¸?þ‚h+MÔ¼8ÿfÓŽŸ$÷ˆ°Å3G¤Í,k#ÆŽJ±”:’Kp8®û#Lÿ u§ýø_ð®BÛÂsÏ}e¨[ÚØÇæµ¥ÑÔ<ù~Ñ–‘DŒ‚¿¼H„lÊÑåVÙów”6coåɼRá’%R8=À®c⽯iZ:[xfÚµKˆð²Mu Kn¿ßÛ# ÇÐ`Œ‚OL7ayþ­?ßÌx§YðŸ†#‚óÄab[“µg6m0,Ý,¨pp8¨2ô]{SÖ¦ÐN­l–wêf6ñ]$Ñ–ðêQ›äàG#ž§²®oG×|3« ½ØKÔ’$W?e0‘~b7('®ÜŽ>ðÎAÒPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š* ëÛ}7O¹¾»“˶¶‰¦•ðNÔPI8žé@ÑX­â­14ËÍFUÔaµ³Pó¼úeÌeT÷ Ñ‚À`’@;G'¶¨¢Š(¢ {ÛxõlZL\Í“F˜<¢ sÓƒ"~~Ƨ ŠŽy–ÞÞIÜ9HÔ»ш<*‚XûIíRPEPE™Záà÷¢«’Q‚à’'å9äqœddJ* ‹Û{Y­ašM²]Êa„`ΜŽ:|¨ÇŸO¥{o¡ ‹I‹™¢’hÓ”BŽzpdOÏØÐõ^ý<Ý>æ=ꛢeÜçdIô©ðµÃÛ¬¨fEWxà ʬHRGP VÁï´úT:Ÿü‚o?ëƒÿè&€iªÚÚÙÁn/ì˜E¦ï0 àc=joíÛ_ùý²ÿ¿£üj–žtše„ñY}¾âÕ$Th”³|¹äã©ÚäËr2±~ú×DӬ人²´ŽÀ$[†$’ª¨³@ $$Ðm«ZÜ2F/- ,0Q’}:Öˆ´»ívÒm9ì´û2h„rGu¼—ÁÆ9=.Y¾}n·zu´Q´rùnÔÁ,MŒíde„‚ B b|A×µí+GKo ÛC6©qI®¡‰m×ûûda¸ú I醳k£ê‘ßiÒOŸ¥Š²Gª²…R»@Œ008­êãt]{SÖ¦ÐN­l–wêf6ñ]$Ñ–ðêQ›äàG#ž§² Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@fx‹N›WðÆ­¦[²,×–s[ÆÒ3¡PN8Éô­:(›DÖ§ðn·£-¥¬3^ÀðÂÓkW7ƒ2)F,òǹBŒ£ œýÜæ«ø“Áú—ˆu{é'HARÇɺÍÃò@ò[¹Þw 2ùG÷jI鳸¢€8ø@u¸¹¸´ÕÊk©ïI-Ãf7d8#œ™mr8ÿdùŽÕÄz_ÃÉbKE¾X¿ÏgÉä´b £áb‚,Í(Hd@ #å¯C¢€8øBfŠëN¾ŽÓH¸¼²k¨`7Q–[x^ãÌ“åÉ0ª…XÆÑó0 sØßFói÷1D»¤x™U|æ‡$ƒæ.Y?ÞŽ¢§¢€8¼©/€µÍ­t÷ÊDü‚4ró¢·Œ0¬£ÊÈ)÷ù-ø—ÃWzþ¡§\OáÏ^¬1+\}ªà‰ €äF$ò˜ÉÇÊ\ ¹_´¢€8½+Á×–^5¸Ön.¼ÈÚY¥I‘ãJ±H<æ4 € Ì3£.׈ô›ÝR'Ó®ÒÖòÒv–9]7- îÇBTJ\0ÅœÜ6¨ 8½ø{©^]ZË%âlf’IV9ZÉ丒gxH$%Çš2ù$ùJIäÞŸD½÷ˆïRÝ"µÔtèàYtû—,bO˜nP¡ñ&ÕbüykžËÔÑ@[¢ø8jZá¹66Qi)-»K:TºZͲ+µe0¹,ÿëâÜN”•ç¯øBfŠëN¾ŽÓH¸¼²k¨`7Q–[x^ãÌ“åÉ0ª…XÆÑó0 sÜQ@õž—4^=Ôõ6Ñt衚ÎÓRŽBn&`[r2ã·œôTåºG¯©ÿÈ&óþ¸?þ‚jÕW¿O7O¹z¦è™w9À’}("ËÃSO n#}ä¶šÈ ù¢hЇ¦Æòb'<®|Àc¹<ž/¹·×!†ÓM´‘.4ɾÒÇÌ„…ÞÍû¶àÛ•`‚¬«¹ç´Õmmlà·öL"Sw˜p1žµ7öí¯üþÙßÑþ4[H°ŸNÒŒW60ZÌ×ÛÊ¿–ñ¥ù@ òÊŠìØyÎT€¡âgÂ~Ž Ï…‰nN՜ٴÀ°t²¡ÁÀà t8ÖmZÖá’1yhIa€²Œ“éÖ³üE¥ßk¶“iÏe§Üi“D#’;­ä¿|ü¸Æ0AÈ AèOG×|3« ½ØKÔ’$W?e0‘~b7('®ÜŽ>ðÎAÒV ®ªG}§IÕ­OnB #G"íQ¹¢Ø@P# ½ˆò³¶€;J©ªjvº>™q¨ß;¥­ºï•Ò&ª÷;TÔœp2OVÒký"öÎÞéí&¸‚H£¹;¡fRŒr ÏQÓ­qv~ Ô¬¼â 6µŽóS­ã€N‹m*TÉû«h€|9ÏÈKlA¸€ýÃø“Áú—ˆu{é'HARÇɺÍÃò@ò[¹Þw 2ùG÷jIé²ø@u¸¹¸´ÕÊk©ïI-Ãf7d8#œ™mr8ÿdùŽÕÀP=í¼z„6-&.fŠI£LQ 9éÁ‘??c\—ðòX’Ño–/ÄóÙÅ2y-‚høX …K3J†RHùjßü!3Eu§_Gi¤\^Y5Ô0¨Ë-¼/qæ@Éòä˜UB¬chù˜P9î(¬ÏiÓjþÕ´ËvEšòÎkxÚBB†t* À'>•Çêõ†êÚÊödòÇ2Ú0TŽL=ÇîÙZ9P*G%º©(Ü[ ÂíR ‡EyÆ·à]jëAÓltû‹S5¤¦¸’1%¬Îwf9>ÌÇb¡kPƒîì¹qà½B÷Vפ"ÊÒ RÖâÕ®7-ÌÅd]£“ H9ÚÛL®  @ÚP»¢¸{Ÿ jšß‰!Ôõ¤Ó…®è<ËH&‘¾Hã»R…Н˜Ü! …K) »5ï˪Y5ŒÞVŸ K D%E{/˜É’J¶Å·Ê@ìíÄðµÃÛ¬¨fEWxà ʬHRGP VÁï´úT:Ÿü‚o?ëƒÿè&²,ô¹¢ñî§©¶‹§E ÖpÆš”rq3Û‘— ¼ç¢§-Ò=}OþA7ŸõÁÿô@Ö7¾,ln-á7M(ò}‰š5‘ÕJ£Êb»n\+0c½p>eÎÿöF™ÿ@ëOûð¿á\Ŧ›­Ýßi×–7zT)nm‘µbò€D,²É]ͱ „mÌ{JΛN±·òä‚ÎÞ)pÉ©àW1ñ^×´­-¼3m Ú¥ÄxY&º†%·_ï푆ãè0FA'¦°¼ÿVŸïŠæ›4B9#º.K÷Ï˸8Á €A¦Õi¥j+§<ɧCkb¬‘ÅhB©] Fq[ôQ@Q@Q@“¨kŸa×4­0YÏ'Û¥hÚãc‹K äýæ>S ƒ’FT6F¹â[AšãÏÑ즂;[»Ä1jæ MÛ™L!FY£R ™‚“@mƒá½~}sí>t6Qy[ }šæI|ÅláÆø£Ìg+®ål6½@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€!žîÚ×oÚ."‡vvùŽ?LÔ?Úúoý-?ïòÿbø¡MGJWPÊ|솨ýŽ×þ}¡ÿ¾+ŠçQý¯¦ÿÐBÓþÿ/øÑý¯¦ÿÐBÓþÿ/ø×/ö;_ùö‡þø}Ž×þ}¡ÿ¾ Gö¾›ÿA Oûü¿ãGö¾›ÿA Oûü¿ã\¿ØíçÚûàQö;_ùö‡þø\.uÚúoý-?ïòÿÚúoý-?ïòÿrÿcµÿŸhïGØíçÚûàQp¹Ôké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ5ËýŽ×þ}¡ÿ¾cµÿŸhïEÂçQý¯¦ÿÐBÓþÿ/øÑý¯¦ÿÐBÓþÿ/ø×/ö;_ùö‡þø§¡éö2^J$²¶‰âR3‘íEÂäZÅ­†¯}gt¾*šÈÙ·™ vÒ[mt.|ÈØ“¶FÎ:qžjÚÿb‰µ)›T¤¿À‘þÖ‘Œ¤2¨ù˜`ðÎäc5§ý¦ÿÐ*Ãÿ×ü*´ÓÚöxN•§íŽ8ܳ®rÅÁÿÐGëLfv˜ºfqqu6¼/ï'Tî.f„7–…Š ª®w9Æ~c’@iÿké¿ô´ÿ¿Ëþ5'öv›ÿ@«ü_ð®IÖ «ÛÝÖv¨±\4H±Âª¯ŸzêµôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¥q\ê?µôßúZßåÿ³ÑO’HÛ£#â+Žû¯üûCÿ| í¤D‰ü¸ÕQUQ€)ŒÅÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEÍGâ¿/\Ôì.í'ò-¯á´[¨ãýÜ~lP˜Ã’rÌÒJWähÚX(;ŒcÇÚGöþžCý²Õ¶,1Í ­3y«$°™5Ä»>÷8 ÛtÛÃ:;jÒj†Óý.YVi[Ì}²º*ª\ím»®AÚrÃ’k§ƒt4•œ[Ns…®æ)VÄJ_lXhЮÀ»v.1@xZ›Y—VÛ=°³¼É±•‘q°nH$3°Êü¤A äÔ¼ñÖeâeЦ—>lp3y± ’HbùeÄéó*2Ü‘µ¶ëiZ6Ÿ¢ÅÓä„—|kóLªÑ-˜JwNU¹#km‚ïÇèþ»Õtý2ôJt¹5%ºTNŠ«¹±¼¨]7gÌ{Æ oXøkKÓf¶–Ê)íþÏÄ‘Çu(•P"—MÛ]‚€70' ¼ü£ÃúTVö¶âÉ[6°Š9 u0@ÈA$0"4ë“ǹÈË+‰n­i¬ç³‘³˜'(]yÇ%—ž¼×𪠯'ö´–1X^Ï2¬Q"´pÈʬ†íç‡BYT¨ ’Fm½;LµÒíÚTp·»Ë+K$€2Îä³2IÀtUy´ 6}LjBæmË#(™ÄNë®ñ±Üap̤‹ƒò®*i(MoOKÛM'TXfµ6ÆXU>Ð0 U%°­’ÞT7U, °¡7‹/Mð¥Ý¦›> ºÆÓ'’±ÆØ6ï( ¯( Ĩ8,ÀaœíÏE™kk¤G¥[£ÅgÚ5ŽVVHÂí8;¾sß9ª‰á­.=×HH§[KL}ŸmÔ¢Xq6K»zðJðßt•éÅP¼ñÖeâeЦ—>lp3y± ’HbùeÄéó*2Ü‘µ¶Ï¤x¡5½=/m4QašÔ\ÛaTû@À%T–¶HyPÝT²‚ÂÜ›k}ݬ/lñ¨A¼Ï$Ø7D¤# (%ITň4Ë[]"=*Ý+8 Ѭr²²FhÁÜóžùÍdÛø K¤hÓÃeu¨^jVkv[$q1jr$*€dA·{˜cpˆí|q¦^Íþì–žl5ï“¶3¤mRîó‘p•<°PA6ךBi–z|qÝE ’˜íÚ+Ù’XÐõA*¸}œ/Ê[*ñòŒNžÒ¢·’Þ+$Ž'†äÇ*¢H„b28D1ð0>^œœ€gx—þBzWý¶ÿÐEU®¬Ã¹Šà¢™¢ ˆÎÝØÎ?/óšŸÏ“ûß ¥aXãh®ËÏ“ûß £Ï“ûß ¢Ác¢»/>Oï~‚>Oï~‚‹Ž6Šì¼ù?½ú <ù?½ú ,8Ú+²óäþ÷è(óäþ÷è(°XãkGH¹†ÒK™î$XâKv,ÍÛ‘]Ÿ'÷¿AGŸ'÷¿AE‚Æü%Z/üþÿä'ÿ †/é"òêàÞ(£…ØÙ$Iãî9éÈ®‹Ï“ûß £Ï“ûß ¦3þ­þòÿ…sör¤ó_MnŽK©N1yÞyò{ôyò{ôÆÑ]—Ÿ'÷¿AGŸ'÷¿AJ±Æ×e?úæü?•|ŸÞý1˜³dœšc1¿æsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚*õý¶§spÛT[X‚…‹eÄ’j‚¿äGÐÿëÆ/ýVíL¾&5±ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±EHÌìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?Æ·L@}Í'“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßTy?ôÒ?ûê€0ÿ³µ¯úäšÙÚ×ý¿òM?Æ·<ŸúiýõG“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßU ÒC±DóÇæLHÉl ŸÈóšÉþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ‘K°QÔúÓ¼Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú£Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿïª<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú¨f’%Š'ž?2bDhK`dþ@œÐOövµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[PUŽ•u¦××z‡Ú¤0ù y!07Øý:óÿŽòÒÿëèÿè&½V¼«ãŸü€4¿úú?ú ­)|h™ü'qà¯ùô?úñ‹ÿA»X^ ÿ‘Cÿ¯¿ô[µ2ø˜ÖÁETŒ(¢Š(¢Š(¢Š’õÍø*ޤŸýs~Ê£  ›Oi—r•ùJÛM¼“|‰t…‚ˆŸ¾¥Ø(Ç]ÈGÊèÌóâ- lRùµ8Yº³¥ÁºO-•X#ÙÁ™TžÅ€êk‹Ô>*hšu¥­ÝÕËÁ½”ë4­*º ‹gy&gD`c°) `à~Oê£Å6z¼w¶­zêynšÌ4 3­´J¢"ûÀ1DÜ«çp9;[aê_UHõøt†·œI5¬—1Ïòùd#"²ýíÛ‡˜‡¦0zðEX†úÒãÈòn “í¡Ù >lcn]qÕ~eäqóQX¶^›NÔôI-/“ìVœÚzÁ,¥‘O—óîcþïz¹žÐo,õû[‰-om­¬,%±Hînc–0¬Ð”H6rcQ|ò*ÈÁ“vq…í+Qÿ‘“Dÿ¶ÿú­ŠÇÔädÑ?í¿þ€(bŠ( Š( Š( Š( Š( Š( Š( Š( Š(  ÿ\¿ò¨êH?×/ãüª:¡­j©¡è—š¤¶óÜEišHàÛ¿bòÄn`8={q“U#ñN––rÜjS¦’aŸìÓG¨Mf9J ¸1BJ2°Úǃêø‡L›[ðî¡¥Ar–ÏyÛ™ž# EqµŽÐË“‚qÏž‡&? ê0_6¯«j5‰ZC4’Y3[²ºÂ¤,BPÊqm%Ï;øämÞ:®œ·Éb×ö¢ñÙ‘-ÌËæ3*‡`9$++Ø0= š®qsogks5«l¸Ž•ÚÉpTä¡ô®vÇÀ–šnŸ5¥µÇúË« „Ï2yv‚‘³ nÏ’Ç<d8²x_Á‘ønàH×v ƒì¶fI'-9\©+&NÈùDAòðÀMcê?ò2hŸößÿ@±XúüŒš'ý·ÿÐlQEQEQEQEW•|sÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMiKãDÏá;È¡ÿ׌_ú­Úñ#ñN÷Â.þM6Þét§k!9vC Œ”Ý·œgÆMð½oÿè mÿ›ü*)7t%4‘í´W‰Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…/c>ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œûñ¾!Ô ·²´°†Îâ`âïËt;ßt_ºÞˆQ™Sƒ´‡ïüù?½ú <ù?½ú à4Ÿ‡Éºö¤P\ZC×›dò+¯#A±U(£1âr¥·`Ÿ˜WÓü ¬&¹¥ßêZÚd‚+c-ÒÌžtoH¬ŠÏHÑ»£ıäJù^I`Góäþ÷è* Q-fµ†i¶Éw)†·;œ#9>Tcϧҹ-7ÁK¥x6; X­WVm9-.frΗ*†¸êVƒ€…r‡"ÓáýÒéP¦¡c¤_Kg¨½Õ­•ÁVƒÉxmåUüË…‹”g’Xz_Ÿ'÷¿AP^j‰a Ís7—K íÏÏ#ª àwfQøó\T¾ Ô®I•rK•$²°ccª&¥§Û_ZMæ[\ijDûq¹ÈàŽµ?Ÿ'÷¿A\w…ü"þþÇòü…ht³m¨2;3\Î<ŒIeP’…Ý÷C [@yò{ôyò{ô'Ÿ'÷¿AGŸ'÷¿AQÑ@yò{ôyò{ô'Ÿ'÷¿AGŸ'÷¿AQÑ@yò{ôyò{ôË­Q,üŸ>m­<« Js;žÀ“À$ú$àD“Þµ½¼“¹r‘©vÆ]ˆ<*‚XûIíYwztÇW¶Õ- È¿g–9‰ÚгÅ GÇ´+tFN/Ã=ÍŸ‰Í劷Ӯ –K9ìæ’fxJ ‰ÉapçË}ÒÆ çss½rèŸÚ°gý¿í}‹Êó¾Ñ½|¿/ß»¦Üsž˜© ½k‹xçBá$Pê$Œ£FyV©ö Þ°?áÿ‰OÙþ×þ™ö¯·y¾_î~Ñ»v|œíò÷s·9ÏÏ»ÌýåbÉàÝF}zmsε¶¼–òÞᣉ™¾UªÃÌÚ !bºEùy[†(fÚÚê‰yçynh%heR»Yv ŒŽ#Ô0# ‚yÏj—Ö±Ù%½Ô°‡.[Ëm¤ãäsÜÖ¦0ÕîuK¶A3¯ÙâŽv¬*Ä©s€]É$óÂn*½]ŸÇóÿ¶Ÿû-v³ÿ®oÃùVdzæ“7Û|­RÉþÁŸ¶m¸Cö|g>g?&6·\t>•§?úæü?•yÃx[TÔ4MGE6ÓÚÛ .[+_µÏ1Ú#H%„ 'ÏæÌ<ƒóŠô:+‹¸³Ôä´±S¥k_Ù±yÊÖPêø½.J’I|áòß ¢Vá£8ã ™¤A≵»¤¹ºº¸ºµ¼³îc» köÍt.D˜'Êà3d,G,À‡4ðÛ yåH² g` ³ª9îIäDsÃ+ʑʎð¶ÉX€Ø>‡ §±½dø«L›WÑÎv-yhïåÊca\FîC!UŽAÏsŠãõ/ øšÖâôiòÞÏi5ûLäN|ùØÛÛªÈJÏ2N6‡eq”ôªŽ ặŽâÞT–T^Õ#Ÿ’X+@çwÕv²GáíUÑt.Úíã:#E¼„ê±£‹ « ç(d*f-† Ò ặŽâÞT–T0ˆ¤¶m{=êpŒLD»AV8‰FÇ`ÛÀ=ZŠó‰õ_GáÛIæèM,ò0ÙÎÓ´@(c}‰‚Ûþ_!7.Âåm÷à]vßUÕµHRê¦Õ¬ñ`ÖêÞbI¬r»°Ýƒv dѱbã€ÜQ\?Úõ•OǦý©o?¶í„Üi„+Bæs • Wvw@wckQssâ8î¥ÓVëQ™ žA¶Ëh—·1ˆà`àL&ZYЍ ˆ‡÷Éî(¬Ÿ ^Üj^Ño®äó.nl šWÀ£RN’zWží=LÓî´‹ íuh­`µÕ¤{-¿j¼’æÕ2Åö-Ãô‘¼99;×xbë4Wž^Ŭ_A¦ßÉ­%–Ÿª;%ÒX'Ú¤­™|Æ€Â[p•Ú0cä;Šžo=ÝÃxëJ/mz‘M¥Í½Ì:[È^6U3ª¬BÈ|§bq’¤€t´Wž&¥âé-ãÒÞ›Ù>Î/–ëNýÕ”íq ²C…O6-q– øXÔï\îi5CÄ–ÍgÞ¢æ ÃW+bÆ[ˆ¼˜Ÿqxí¥Œò:àD»¶˜mÀý“ÿ ºëvDÖ·±^Þڽʫ@Y# ·r¼‹” 7c‚GN~dÜYøŠÎömb(¡½ ¤ËåOºÒA¼ìû±Œ¿ É<e,­EPÑuk}{D³ÕmRt‚î!*,ñ”p¨?Ìd A«ôQEQEQEQEQEWã¿ù‡ÿÛOý–»ã¼wÿ0ÿûiÿ²Ðk?úæü?•GL¼²‚[§wó÷gm̨:z+Pg[zÜÿàdßü]Z¢ªÿg[zÜÿàdßü]ÙÖÞ·?ø7ÿ@ª¦£¥iÚ½ºÛêv·°«oXîaY6È Î çÜÒÿg[zÜÿàdßü]ÙÖÞ·?ø7ÿ@ª9 †áOJ•º†”†SÏp@ ö ‡û:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  TU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâèÕWû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-QU³­½nð2oþ.ìëo[Ÿü ›ÿ‹  TU_ìëo[Ÿü ›ÿ‹£û:ÛÖçÿ&ÿâèÕWû:ÛÖçÿ&ÿâèþζõ¹ÿÀÉ¿øºµEUþζõ¹ÿÀÉ¿øº?³­½nð2oþ.€-Wã¿ù‡ÿÛOý–ºìëo[Ÿü ›ÿ‹®_Ç*tå\áD€e‰?ÃÜòh¶Ÿýs~ʸ _]é‘É7ˆ¥²xÛ=¬& ­ot–Àò2þñ¤S’T&I0ïçÿ\߇ò®v×Áº¤3E´î²îËOw4¬…ŸÌfFw&6.–R eVÎTCþ$Ôô85MàÚš¥µ•Ôrí›IcBâ¦í²« àt#9Å‹ÏhÖ^&] iqsæÇ7›Ù$v/–\HÙÞŸ2£(ÝÉû¯ é׺L:eÁ½’ÚVd&þ3z¶å&MûÛ ÈÉ8 c ÄÿØöcVþÓAK»ÊÅ)†UóMŽln™åe?+¸8 €?†ty%º‘­2×ÝûÇýÙ,´c?ºbá\²m%Ô1%€5~ÊÎ+ D¶…§hÓ83Îó?'<»’ǯsí@µ÷‹ïmu=BÉ4çq­geÀ1¥û>òçvCƒ>Ç;”€Ád*XüJÐ5»{gy¼åvI™bT¶ɈeÓ>w—€I8 åz4m>_´o·ÏÚ.¢¼—çošXü½×ŒyQð8;y'0Eá½:ÞÒâÖ{ íÌq_΂ §!bÃþéGM©´c  …ñ¡¸¹ÒÇNžî BÖêU†Ý¢–BñIÞ,†¸w$—êgqÚzkÛ}KO¶¾´“̶¹‰f‰ðFä`8<ŽëTìt 7N¸ŽâÞûB,‰çK3Ë#)»s9%Ïî£bHÀ«–6VúnŸmci—mmÃd¨ 2y<Ö€'¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(®;Çóÿ¶Ÿû-v5ÇxïþaÿöÓÿe ÖõÍø*ã´Ï¼ŽÃY±‚ÅOÚ|¦·¹kæÞu×ZÌîCÎ0ìgÿ\߇ò®8|?Ód²¸µ¿½½Ô_4¡ºŸ)¤˜Nä*ƪٕ°á‡Ê6’û¿DºtÖý¢6¿‚Îâ9÷ÛË›"&J2nÜ<Äm¬*r#6æ×ôØ51§É3‰·,lÂ1#¶6£ÊÄs•³w®̹Í ²‹ÃÑhö—sÙF—IvÓZ[ÛDòHŽK*ų‚©ÑA;$ó™&ð^‘?ŠGˆk­Ë#«Ûà iB«ït2)WFTd¶@ #Æž•w$WV±ÛO$,&µ™wâVn@]بù ÁHÝ×[NÔíuKvšÕÜ„mŽ’ÄÑI`28 §2=5“uàÝ:òÖúÒâk©,[Ve1C#H&g WL€>$Þ*RÊohZŸ‡´Å±²D ¸»ºÁ&F=ÊĈ¹À!GPK}žîêÐÚfæ+ûkXaó0óÇ(BfUÆv¨32?Ñß‘ƒ¶Å¯ˆlõ?:-1üë‘IÏÇpFI aãÉ\ºn2žw ¾m Êã^ƒXuµB¡W ò’ЬGª‰¦·ïA!JÔ°ð´vÈ€€Á°pp t2x‹C‹L‹S“YÓ’ÂfÙÓ] ‰Ûžçü­À=¥ëÚtÚ¬úc\$W‘NmÒ)]U¦ar±Œg,ȹãŽ{ryçð5ÂéðÇm¨Áé–Ino^%f +‹¡"®ØÐ.À”SWÇ„ý=Úó̹¼¿²¼’åà_1…¿“„b¸&<á}@:äh­ä‘!y²ÅPÎ@û£q'§$R+&ÏÅ:]ƃg¬]Κe½Üæ5¿š8ØDJ€Ç @zwãzƒ‚qZÓ‰šÞE·tŽb¤Fò!uVǨ ‘žÙõÏhþþÏÿ„yîî`»—D°–Ê'Û3»ÊÆY¶°HÊœwžƒŠÒ¸Ö¡ƒWM5m®§“j<Ï a–ÝdfXËŒî!™eCmÚKm^jŦ«§_Ü\ÛÙßÚÜÍjÛ.#†ev…²F•9ƒè}+ÃþÓ´;ëkæŽÖâò :ÖÉ. ª¬¡WF6IÕ•Hô@2GK†¦Òn,šk万M³k H l°“|Ö,ÁßÇÊ„{ŽF:(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ã¼wÿ0ÿûiÿ²×c\wŽÿæÿm?öZígÿ\߇ò¬ËMgO¾ûÙ®7ý¾ÔÞ[|Œ<Ȇ̷#õ©ÁÁç§sÿ®oÃùWš†ÓA£iÖöOkku“ö;¹#'I¾ÝÊ Ê@ü©ƒeHÌÌų‚èõ½í½Ô×PÃ&é-%Ì0F×(®=~WSǯּþ_ŸÚié¬Î³É;Ã5Ü>D ¡cìF"7gÊVVgÁ;Û:çÂ-}y©É%«ê²ê6—1\®õòâE·Y‚)Ýå—ʤw)Uf pÔÞÞÛéöuu&È“ $“€ª,Ä€I$ 5©Úê–í5«¹Û%‰¢’6À8dpN8 dzj¾½§M©é^E» š9์HHWh¥IB’*¦Üàã9ÁÆ5§h^$‹U—Z•täÕei#™ 1·Q$VªeŒ™À6Ã÷l’Ì7¡Ü¸ª–:®¢÷ilî^Îsm:¼L…d[0e Œ‚ šàÓÀúìWt—N¥ÁeÜFU$Tˆ¯š€˜F ƒ‰#> ýâý5–™¨¤¾&7–ZtÐê3™má7 Ë*ù ÉA Œÿ|Œ|ÀÇSµQ`]Þ3~Û-ÖH™Y›Ëi0TŒ©ÚŒpØÆ1׊·\;x2kŸ xfÓPÓt‹ëýU<‹†/ê"hˆÞc%AÊI‡æ@=Aªiú‹jÿcŽ[¦’çQ±¾¸XôæNñ4ÜM–Hã >[&ôኲ†ï袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+ŽñßüÃÿí§þË]qÞ;ÿ˜ý´ÿÙhµŸýs~ʳ"×4™å¸ŠRÊI-¥XgT¸Bb‘›b£~V-ò€y'ŠÓŸýs~ʼðhš½Ç…4½û%í®´Å±·þÑóa,DsÀ]àwɈ‹üáOʃcB€wôWžkZ7ŠQžÛO’ö].§òbNó²¡*ÆO´ÂåDŸiiOÞ_”€¥4áÓuØu˜~Ù&£}24^¡ ÒÛÛ•J$ƒqلLjÛýbé€P¬‚xn­ã¸·•%†U‘°eu# ‚8 Žõ£ªéÚEºÜjwö¶P³lY.fXÔ¶ À,@ÎãØ×;àÍ/[Òôý.ÛX;ü.(#0Hàe 7òp¸Vcç̹â[KǸ³½°ƒQkˆ–H¼í:Kq2+”%vÜ,¡(¤œîT †lt4W–^(´·KìÓç¼°œËgr"¶¶ºÍ JNìf9NÌ(çæ,v?…u‰>]ZK¨ê’ë—z1‚â9®’A$þXù~`Q{¡eÆàŘ³aÀie}i©Z%ÝÔVÒgdÐH 8<‚? ž¸ÿé¬ZDú`º½™ç2Ý]Fâ+‰nÕ,"–ÙXmÂçmo¼µô»?›«µxu/ÊÛ1¸†ù#¶DqùñÉm®åÄç"6ûè¦@â£3· nÒ ™Õ#,72©ˆH—'¶áë\ƒ4ÏZjë·s·î¶J¬ Gq) ù‘“q&Õo”G"Aò .ž³¡ÍªøŸL¹ó. ¶‚Îê9&¶¸10gx0‡$2¤ƒ=°*ÁXnÁ<7VñÜ[Ê’Ã*‡ŽHØ2º‘AGz&žt<©T ìbG=É Ü+ÎtøºÎ÷C†âyíí­­m1ñ‘‚Xœ …RÌë ÝäÉ€êCð6>=Ä·¶wÖòŨÄ&¼³™..çC2lºGfUóæ‹!1Ú±.U@FèôVN‡gw`Ú´Í;Z%Ðû žs3ùF(É˱,xeûÇ=‡­j(¢Š(¢Š(¢Š(¢Š(¢Š+ŽñßüÃÿí§þË]qÞ;ÿ˜ý´ÿÙhµŸýs~Ê£©'ÿ\߇ò¯-‡L?ðŒÙÛÙh÷Px†6ÓÆ¥vöRyÖæï!Êý¤‚²?˜¥€Îõß–ôê+Ï5­CÅÖ,ö–ï{-¤OÛÄ¿”yPºdGm*•Ý$땈Ý(,CéÃyâ¬Ã£5ÔwA U·±±ó,§Œ¢yÒ4¬¹BÌ2)Â!ØäáÀ; +ð/öÌFeªÚ½šC¤À±BŠY\…PÆV* H>Qå่i0|»~*MNÒk=cF´û]ô1\Zˆ˜n\J?ë¢Iγ“€7(KEpð&«¢ßZhöRj&&µµ²·6¡íç´ É,³ÂÈ£ÎÀÞ™1§Èw|嬗6Oâ—Ò¬n­ÈÖíî[.‚Xqn· eÄ„ˆçû™by,¤€wWú—‹uMzE±Q³°iÜF&µ?rE’ïË©Á[©›rme;LuŸ¬xÒû\ÒþÓmö8æŠÚG¡‘a(Ñ#M»÷¶@ÆUPÓGʦTõpC¢°|aiq} ¥½©ekû" ñu.| ä1ÏÇß7Šô{ÍL[½Ô‘Üj-,÷°[•fo²Û«çËÏš>áÇ–“vw€zuÅÇ©x†?X[]ùó'•ÝCem"[‰ 9$]CÙ¡À ±˜aÏí麇¬¯žy —F ,ol#[9#ªF8Ü«¾àä’P•Zí(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+ŽñßüÃÿí§þË]qÞ;ÿ˜ý´ÿÙhµŸýs~Ê£©'ÿ\߇ò¯%ð‡ˆ#‡ÂÉ~º•­Ö«ö;o3v¿=ñ]‘ežxpvð Ê9 V¢¼ÕÔMÊ¿¿ä('%ÀFÚ…À=*ŠãÏŒµ3¤%ÚxnëÎóÚH®Dc 2âÜÌAÝŒ˜•rŽ }Ý巊u'òRïGMFÚÚ+´™xYâ·òÄaAó™.æ,W ãi|m…‹âû›«/ë7–7Okukg-ÄR¢«È¥€Ã8Áã¡8Áæ²m5íVVó@ST¾·žA÷³ }ФVÎÅÚ8Èߺå@Ú990aErÚwŒV^YX Ò‹[Ç,·KÊóÇ XÈ*ÃÆïÎàªÄ(jšWе8´[‰õx,ší¯æ¶³Š+¼´‡í†ÜZíâRà1 î#'ií(®I|Y©Ë«  5Eó„ÃíØ‚3Û¸;Ì{Š”¹^Bd0Æ6åÇM ÚIä$£È¹š#(¶•×ÌmÝÂ’ÒÊ Œ‘Ï"€)éÚ›¥\4öº¾ß-Ìò,)vD¬H‰8_•*ñòŒiÔqÏ ¯*G*;ÂÛ$U`J6`ú2œÄôA<7VñÜ[Ê’Ã*‡ŽHØ2º‘AGz’Š( Š( Š( £Žby^8‘fß#*€]°'ÔáTdöv©(  ´ŠÐZÀ-¡ÙåB#a6¯A´¨#01Ò§¢Š(¢Š(¢Š+ŽñßüÃÿí§þË]qÞ;ÿ˜ý´ÿÙhµŸýs~ʨ+Nkt·k S @Ö©…v¬,hÀÆ«•èvJ¿?úæü?•yŒŸ5gÑôyÓNû,×–O,“Z<©æ<ö±þé÷H». 99EÎåu¤¾ðôö–ö“h:\–ÖÛ¼ˆ^Î2‘n9mªF'“޵}¬mÌÝky²¬Òf0wÈ»v¹õa±0z£ÐW-yªxŠÚêjs<·ÛŸ´h×²Í ùo0e*Y›Ÿ¼1Œu:O{«Câ­+M{‹'¶šÂiî Úº»IF§aóU&`pC´ŒœäkÞØÚjVi}kÕ´˜ß ñ‡FÁÈÊž ©ÉáÝ]2-2MN{[|v­j†$ny Œó7 w>µ›áíoR¿Ô$·Ô„Jb2F´š `@dW|¥ÊØ2G´à‰'Õõë/_Ó죰žî›[‰YmÐ4Ñ¡TêÀ&R ìJ’UC0Ó“JÓ¥ÔâÔä°µ{øWdwM ™Qyà>2ÌÜÜúÐÚVœÏxíaj^ùB]±…sp mN>`#<W%¤|JÒî†izè—÷Z™¼¹#UŽi£FT³ù¬˜œª²Ü·ÊÛlOãÛitûÛ›6W–L¯²W+,ë~æ7iQöîÂ:«gi €ÒÚiZvž¥•…­²@®‘,0ªÕÈf À$@ê@5º.™>·o¬ËcêVñ40Ü•ùѨóúnlcqÉ¥j©ªE?ú<öÓÛËäÜ[Ï·|Oµ\Q™NUѾV?{@ç¿á#ÕßÅ÷ºt$Ööב[ˆO›-E¼†ëw”…|Æm„e‚°4»oáíÕõ7ƒLµCª1{ïÝ‚. Nàx Œät%˜õbM/K²ÑtË};N¶Kk;uÙIÐæI9$žI$žMs²üCÑ ¾¾³•g3ÚJ±´p4Wù™!,'fiå`®sÂ’j>*¿µ—GX<=¨³ÝÞ=´öòVDÛȱ”#µNC2á\@M™&¦Éâ{m(Äê’ÙËr$(¥\£Æ¤ßFñSpà ¤>ñþ±¥^Ý\è·PIo=ÄqǺßyrȼ‹]ǃ·šèh®zßÅ]#Fž+­BóR³[´‚Ù#‰Œ{P³‘$T" »ØüÀ$Gkã2öoôh/d´ó`‰¯|°©#hzÇwœ‹€¤©å‚‚ éh®yüU ¥¾¯syot#°Ôb±òã€4Ÿ¼… #±pLÁ¸°q·pä-ÜZäê2êaeÓ×ÉÄFÌÅŒ‚214'årx8á¶€t4UM+Q‡WÒ,µ;uu†òî#Y Ô0ŒàúÕº(¢Š(¢Š(¢Š+ŽñßüÃÿí§þË]qÞ;ÿ˜ý´ÿÙhµŸýs~ʰn<'¢ÜØÙÙÉjâ(ÚÛ˸‘(Õ£p+Èhb9Î~^¼œëÞ5èº*VN0^vSÓÐ!þuíGþ}ì¿ð%ÿøÝV‹A°ŠÇìmö©áóã¹i¼šv#+© ì[‘N3ŽœÉ.g6·o«¸Ÿí¶ñ41°¸ FûÀÆaÎ亿ݗv£ÿ>ö_øÿünÚüûÙàKÿñº­§hn•pÓÚBêû|´3Ȱ¦AÙ±"$á~T|«ÇÊ1qì­äÔ!¾hós RCäðŽP°ÇNLiù{šfíGþ}ì¿ð%ÿøÝµù÷²ÿÀ—ÿãtNÇÃZ^›5´¶QOoöx–$Ž;©DlªºnÚì¹8UçåŽ/ iÍÕÆÕîïf¸d)"È»LŽÅFôB@Àm«œàV†íGþ}ì¿ð%ÿøÝµù÷²ÿÀ—ÿãtû{+{Y®¦†=²]Ê&˜äÎPz|¨£O­öVö³]M {d»”M1É;œ" <ôùQGŸZfíGþ}ì¿ð%ÿøÝµù÷²ÿÀ—ÿãt—ƒt8îRqm9höùH×s4p…‘% eö¢‡Š3µ@P1Ž+OQÓ-uKu†é„mèñJÑI`Œ«¡ §Œ‚2  »µù÷²ÿÀ—ÿãtnÔçÞËÿ_ÿÐeÐ4ÔÔìõáx¦²€Û[¬S:EGªˆ”„Ç Õ…º0&¦Çqw8ÉLvíìÉ,hz •\>Îå-•xùF'OéQ[Éo’G “ÃrcŒ•Q$B1¢ø/NNlîÔçÞËÿ_ÿÑ»QÿŸ{/ü þ7@ÓÃZ\rÞIåNÍyuäâK©\ced` ¸(œ.F0ªšß…¡ÔĆÓ‰š´O£b/!’O-c°²•p¨ª`0[ ’×ݨÿϽ—þ¿ÿ£v£ÿ>ö_øÿün€2ì|%§Ø]è÷1MzdÒl>Ák†ÑáF]·È;x$«¶ÅŸ‡lì¦Ö%ŠkÒÚ´¾lû®ä;ÀŸ»9Êp:ŒÀP·7j?óïeÿ/ÿÆèݨÿϽ—þ¿ÿ ´]&ßAÑ,ô«Wà´ˆD<…ÜêOò *ýUݨÿϽ—þ¿ÿ£v£ÿ>ö_øÿün€-QUwj?óïeÿ/ÿÆèݨÿϽ—þ¿ÿ  TU]ÚüûÙàKÿñº7j?óïeÿ/ÿÆèÕqÞ;ÿ˜ý´ÿÙk§Ý¨ÿϽ—þ¿ÿ®_Ç;¶éÛ†ę rùz*í§ÿ\߇òªš¥•ýÅÌ·),¶Í²U_á9#ñV\Ž7#¯U`/Ïþ¹¿å^hŸ5_ìýÖãY{”³³†Údib-“ÚHÂŽ5|m·p ÙÙÈäУÕC©Ú®®šS;‹Ç®QLMµ£V Ä>6’ .Fr7Œãõ^Ocsaa—ýšoþÑmdé¤)ä¢ü»à•ç1Q>fw˜6–›£ë–ºŸ‡f»k[”±Ò^Îòá®\Ë$Ïå` |Ã0ŽKw“Ž0ÀMæ6Ú&£va³·³Kètý&]>MnÁ ·ˆù–þPá„³ÆJãfàÍ%ÇÃÛÉ4KKk .Õmå™å³I£’+‡}‡Ïc%£ me "W²¨Ø@=*³4íMÕn IŸo˜…áxÖdÈâfJœ¯Ì„™yù†nXÚý‡O¶´óç¸ò"Xüë‡ß$›@»±ÆIîk‹>ñ¾!Ô ·²´°†Îâ`âïËt;ßt_ºÞˆQ™Sƒ´‡îè®ÛÀ÷VºeœrYéÚšFÓ4šUüËöHÙü½¯Ëp ¨¸gîäî-|¨Úß-÷ö¢Mx“Ú³\0a%ÂÆ¶ˆÎíɶ¥æÈ¹a¸l€w×¶únŸs}w'—mmM+ਠ’p9<Ò§¯8Ó~Î4ÍfÇS»I í›Zý œNç‘q*cc"²†RÒHAfù²Kx|·—škjz^‘iÔcLµ Ð)‘áeU”f9åTeÂ’»è°¢¸ SK¹‹Wþΰ}GÊ›Q±¼häµyDÞS@Ñ,¡pçkâBéÄ0Vï袊(¢Š(¢Š(¢Š(¢Š(¢Š(®;Çóÿ¶Ÿû-v5ÇxïþaÿöÓÿe ÖõÍø*© õ¥Ç‘äÝA'Ú"3C²@|ØÆÜºãªüËÈãæ¢­Ïþ¹¿å^[ƒüA§èÚ7ö|·K{ˆmgYn·ˆ[}«<1üë‚Á'ƒ  HŠ©´Óª8ç†W•#•ám’*°%°}NbzóÉôŸ/‡m!-«Í3O$žLlÀ˜PÛíË#œî`|çr Œ&Ý4Ñ5´ÔuULðÝͪZK¼7`ÁåyvÑÜ6>_3åYToERr@:ÛÛëM6Ñîï® µ¶æž@ˆ¹8cÀäøÔzv«§jöíq¦_ÚÞ­±¤¶™dPØ©#8#qYž1²¼¿ðãçÇ<—+uk2‹s“ÜFìSÌù7RFî2+&âÝÚXâ k÷^r5Õ´™ÉC Îa&31JílåIŠLPaðÝ[Çqo*K ª9#`ÊêFApAêJòhbÔ´ÏøGô©/q©Aý™³]Nh&Š5òDʶÈ<»˜ð%f—$\Ë*ÒÓ4ŸAc©¶¡u¨½Ë@#d·*~Ó1a™"gº!ù -ÉY>P¬«°Ñè¬_ ŨÁ Å§ Å23óei$eÎrÛ¤”ƒ’F<Çà‘‹µ@Q@Q@Q@Q@Q@Q@Q@Q@qÞ;ÿ˜ý´ÿÙk±®;Çóÿ¶Ÿû-v³ÿ®oÃùTu$ÿë›ðþUä¶zŠ4}Ã÷6¦êâæ˜DR[6€½žõ8F&@¢] «D£c°mà­EyÄú¯Š£ðí¤st&–y lçiÚ 1¾ÄÁíÿ/›—a ò¶ûð.»oªêÚ¤)uSjÖx°kuo1$ŠÖ9]ØnÈA»2hرqÀî(¬Ÿ[ý«Ã×Qm”ìfXbów(pHhò ‘t.›”rEsZÕö‘ös“:é-ö„X¬t÷f˜ù"¶îK[/©ÜU Ø0îè®/ÂgÅz” w«jÛ4_eÿF–ÅSÍÝmM¿€~ûHnÝ®;À Ñ´í[MÑõ½bí<íZYn£W´µxfe¸W}Í'˜ª¡ #O•D›°ÀÝç~µâK›5œš½•œsËÛmtæšæBŒk`vó‚ÂÊQœò÷PñŒž,´·’?"ä’^?-LŶE*¬¼ÕQö…Tá‡2wtQEQEQEQEQEQEQEQEÇxïþaÿöÓÿe®Æ¸ïÿÌ?þÚì´ÚÏþ¹¿åQÔ“ÿ®oÃùW’Áâ{Í+O°¿±º}Býìâ:ͬ×Î!»yí£ØÈ»ŒûË€#E©ù`PêÔWž^øƒV¹ƒM¾‡ZÒà±µÕõA›;ˆÍ³â`bFò°]‘Tä²·Ÿ]ˆøëJ°û\ æ—4ñ[I¾)ÃŒŒ£0ÎW~&åòߟ¼(¥¢¸OøÃVÔm¢þÔK+/´io{ãDé mŽ ÏóF>ÒüØçæÂW—Æooà_ êšÞ‹kujŠ©~ZT’P‹¸Ze(¨Cof.Ý.B°¡Ñ\"øËTZi0Geuù 24IöÈÞ5w¸ˆ´ûüµÜäŽ@|¢7ä/‰ãðõÓ¥ßÙvì-), &ñ¸3¨-•Ê™ú°Kÿ kQ\&‡âˆ¬~ΓÍÿ¹>ЫrnÞù$™|ƒVó}ÛæùHg.Ž«Âb§ðŸˆ|CâHðÇ¥ÇmÙ|Ô y<Ûh%}§$&Ó)#!·ð§f7ÒŠá4mGVƒGÖüA©¿•"Ku¬wOshçxÔ˜ÙcXÕ6ܬ”³ÈW–žŸñëQ³_2ûHÓQ'–5K ¯lì© ¬`$åC°™±‰›ýKqÉèôW¾4Ö%ñe¦–ºt¬¾NmädI%G]åC,‘ɵ78ÇÙ10Ê’BwtQEQEQEQEQEQEWã¿ù‡ÿÛOý–»ã¼wÿ0ÿûiÿ²Ðk?úæü?•T¼²·¿…a¹ÌeŽ`2GÏ«¡ãÑ•OáÍ[Ÿýs~ʸ j6núœóÜÉ{äyq·måó'†&–ÖH²ÞRùê@”o`É‚0ôÝÑ\‘ñÅ߈n4m#M‚öX¥ž/9¯BD¦$·gÞB±ÜÀ C È’ Õõ›ÿ®¥í•­µ­½Ä›ÖÝѼÓ&á.$/Ç—µL}1mÉ· mÅ·MkýŸ¿ÌÇö|Ñ´¢+ÓG ±w‰Wiiâ;£2¥ŽO˺MGÆ—šsÅdÚBKª³H$†Þin"EAº^@q4|4kßœl.ØQPXÝ}»O¶»ò'·óâY<›„Ù${€;]{0ÎìkÏׯWú.•¤k:„ï}«§%ô¶îa…m™¥µLDØP –?¼c÷,>b@=Šâï|I¯=þ›igad—iª=•ì/xÞSŸ²4êO$±]¥X¶Õ!“n%«hjÍ7‰ôûX%°»Ó¦ºŠx¦VY ¼#8ÛÓ)Vƒ¹²¿tÐÕÉxWÆßð‘Íéÿe–k_´ “yª>Hd#;Wø. ç|ÁÀPÏÔÁ<7VñÜ[Ê’Ã*‡ŽHØ2º‘AGz’Šä¯µ-FßÄÌÏy´nŠ( Š( Š( Š( Š( ¸ïÿÌ?þÚìµÖê7¶Z{"Í7–ò6ÔM¥‹Ÿ`?þ±\—Žÿæÿm?öZígÿ\߇ò¬Èô=&¶ùZ]’}¿?lÛnƒíÎ|Î>|în¹ê}jåäwmtæ+¨8µ¹b8õÞ?•Aå_ÿÏí·þ7ÿ ¶Ò´ë'W´°µÕv+E © „\ ˜Ž1DQØTâVáî$:ª´¾UÿüþÛà#ñÊ<«ÿùý¶ÿÀFÿ㔇JÓšÝ-ÚÂÔÂ5ªFa]« 01€„*åz£Ò/K²ÑtË};N¶Kk;uÙIÐæI9$žI$žM/•ÿ?¶ßøßür*ÿþm¿ð¿øå$šV.§§%…«ß»#ºhTÊ‹Ïñ>fàçÖ†Ò´æ{Çk R÷ÊíŒ+›…hqó 9àâ—Ê¿ÿŸÛoüoþ9G•ÿ?¶ßøßür€3äðž‡)¶FÓm~Ço¶éd O³•’HäbcÆ3º%#ܓצÕUò¯ÿçöÛÿÿŽQå_ÿÏí·þ7ÿ  TU_*ÿþm¿ð¿øåUÿüþÛà#ñʵEUò¯ÿçöÛÿÿŽQå_ÿÏí·þ7ÿ  TU_*ÿþm¿ð¿øåUÿüþÛà#ñʵEUò¯ÿçöÛÿÿŽQå_ÿÏí·þ7ÿ  TU_*ÿþm¿ð¿øåUÿüþÛà#ñÊtvPG{=æÌÜÍ÷ä=qØ@¾ry®[Çóÿ¶Ÿû-tþUÿüþÛà#ñÊåür.œƒ6$É €OËÛ'vÓÿ®oÃùW5§xÛCÔÒÅà»EK­9õ2Ï"(U[ÌÃ|¤#Ó1¸ÏË],ÿë›ðþUÃËðòÞM'M²[Ï*K+¶3E¦•Ù’V*Á†>È€€Á°pp t2x‹C‹L‹S“YÓ’ÂfÙÓ] ‰Ûžçü­À=¥ëÚtÚ¬úc\$W‘NmÒ)]U¦ar±Œg,ȹãŽ{ryçð5ÂéðÇm¨Áé–Ino^%f +‹¡"®ØÐ.À”SWÇ„ý=Úó̹¼¿²¼’åà_1…¿“„b¸&<á}@6µF.Õ.'Wdyá·'t²,jy#Œ¸Ï¶zÕI|K¤Úµ÷Û¯`±ŽÎém[¹R$i I( IçåqïÁãŒÕ½WN‡WÒ/tˆu†ò -ähÈ Ô©# ŒàúV,~»³[;?R‚=Bµy’ÜZ™"´J&—‡R¿:¿9ÂäÇæϪ¤zü:C[Î$šÖK˜çù|²‘Y~öíÃÌCÓ=x"‰õÍ&ÖÒ;»RÊi"ó’i.Q£Êá‰Á\º ôù—ÔVm—†¦Óµ=KKäû•§6ž°KidSåüÆ@Àû˜ÿƒûÞ£nbxà>–²k;­´¸¢·µ„Zˆ£žÞUÜÛ²Òn›…9*à†énõÍ&ÂÐ]Þj–VöÆV„M5Â"yŠH)¸œnX×å>•~¸CðØ[¤_ÙÚ¼ðI#‰œÊ¸‹È·ˆ«e‰™¿Ñ‘³¸/ÌFÓÁ¥•¾›§ÛXÚGåÛ[D°Ä™'j( žOu  袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+ŽñßüÃÿí§þË]qÞ;ÿ˜ý´ÿÙhµŸýs~ʲ4íMÕn IŸo˜…áxÖdÈâfJœ¯Ì„™yù†uçÿ\߇ò¯1Õ|#¬L²>@þÌŠ×N¶–Ù呿CujLΪ¢Ú°!\ýãó¹ ‡q{ok5¬3I¶K¹L0Œ¹Â3‘ÇO•óéô§™•n{«8!®å±€~a€NO8Î8‰| çØÛÉ6‘¢É%µû]A¥?6±FÐùM ¹åRß¾8øÇñÖÑÒuøL´Ý]¡Ó"Ó¤´»¹VhåvfGSk|€Æp ñæ7§ÌÐÔpL·ñÎÂH¡ÔHŒŒåX§Ø€Gzâ<;àk½Ú(ɲºˆéokqfÙHd“ËB”\¹%r ä³f;Ïê7ž ðþ‹u£è7ÒØÀ¶×-q;dFªÈab…ö®ã€Tç ýAy{oa Ís'—K àŸžGTAÇ«2Çšâ×ÁâËMQÚ {hü—Dµ’5k1j>Ï6åÌE”çl‘‚$q³®î³ZÓµôKÍܳ)‰%f–2ÅËÜê8—9n‡gw`Ú´Í;Z%Ðû žs3ùF(É˱,xeûÇ=‡  rjºtZœZd—ö©2ïŽÕ¦Q+¯<„ÎHù[;Jžyáµ·’ââTŠ”¼’HÁU ’Ià;×'}¤êO©ê‘Ø»Ã}«Yê+x$AIÙ÷#‚Û÷Ÿ³¶6©2ä›o;¢èº÷ˆü ä\Oz?´t²Ü]ê éq;¢6üȪ»Äƒjî݆ó¹bêU_Z'™ºêò¥XdÌ€l‘¶íCèÇz`u;‡¨ªzM˜±ÉeuhŠÄGåÙ¹Ÿo\»î~r[;|»yurot+Ù¼R5Oì{™à¾»RÜ™¡Vý K-™|¸óŒáÀ:Yç†ÖÞK‹‰R(bRòI#TP2I'€ïDÃuoż©,2¨xäƒ+©Áw®OÃöºíÁžòßQwŽÍÅð–ñe[묡W¶S!'ðDC÷‰•ãäF¶×ô½ÃtÙÚKM-¬.lZæ5oÜ„•Èb¦1å?+¹ÀaXÒŠóDñ°´º¸»ºóQ¬Öhe½ó7šHØ,W}»wvfVÃŒ4ü¦xšÓP¸—]»¿u²U`Z;‰IÌŒ›‰6¨Ã|¢8A”m@;J(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ã¼wÿ0ÿûiÿ²×c\wŽÿæÿm?öZígÿ\߇ò¨êIÿ×7áü«Ëllõ,ZM¥ÔÖðÜ_®˜Ð\®nbW3ßÜ… ¬fPUv¹é%zuÀE©ø ÃzÑÔtøÕq¦Ø‹‰D¦$…È a¤¸MáOú”÷d¼ðj^(këA{ÔìÖ ØÁjÍâeŒÜ;͵¶ºq´y«Ÿ.?•·|àÅæ©§kÚæ’²j—7«¬Åp²\Ù£A:ŠÈ® *y›‘¼Ç Ä.ÖÇÀ®ÓCmA[Q´¿–yÖÖèGos©g-…à¶fò¬ÔAç(ŸcS¶ç1–·ñ»"Îoø³À·ï=ìÓê ´¥íbvDòV&#k,ªdÞw6Þ?Ô“´z•™¡\5Ƙ¥¤Ôf ÅVãP·X%˜uݰ*’£(¤íÎ!Žþ—zþ){(í´ËûË]J{Žè丽n‚Ì`‚H’R3‚P°¢¸½÷SºóSZŽöêÙ¬$mVÚçOÄpOòþæ#xÈ3 ¹Ÿ7ÍóÇáûýGKðï…Xê-jšOÙ®-–Í„¿kQ Æ¥Xƒå˜om±ô%€*h¸¢¼ãGÔ¼pÂÒêî;§ˆµšO¶¨˜-˜“å žéØôVGÊ+iø2ûÅ7º…Á×Ëbýô2#*rF`Lcç‰&è˜n¥€;J+šñÔm𮡤ÿgOy%ý¬°Á²5}¿º ×gÍ‚€«·%—Œæk޳¥xŸL±Ò,n“M­­ÌÛ“nbg Î6@ÁB!?zhðS; ãxqEp–Ú—ˆÛN•̺£ÞùQ›ø¤Ó‚¥“™J-›hóv¡˜¨}ÞZrr”&Ÿ[}nÂíåÖ†ŸW®¤šXk¯)¾ÊÀ´^XÚÆU‘îI(¹ÛŒÊ=*Šä­.õ6ñV‚u+iÒy´i>Ö‘Ùï‚Þà´M´NíÎÙS!bq’¤ásÆ2ê÷vÖ^Å’ÆQ®¬ÚQmþ— â•—ËyKm’^"AÌéTVN†Ú‚¶£i,ó­­ÐŽÞæxÕxÌQ¾ãµUNÝr “IÖ Š( Š( ¸ïÿÌ?þÚìµØ×ã¿ù‡ÿÛOý–€5µ鶺Œöå.¢mŒÈƒÉøª¿ð›é¿óÂïþø_þ*Š)?á7Óç…ßýð¿üUð›é¿óÂïþø_þ*Š(ÿ„ßMÿž÷ÂÿñTÂo¦ÿÏ ¿ûáøª( þ}7þx]ÿß ÿÅS ñ†ko½½ÄPÄ¡#Ž8‘U lj( ÿÂo¦ÿÏ ¿ûáøª?á7Óç…ßýð¿üUPÿ ¾›ÿ<.ÿï…ÿâ¨ÿ„ßMÿž÷ÂÿñTQ@ü&úoüð»ÿ¾ÿŠ£þ}7þx]ÿß ÿÅQEð›é¿óÂïþø_þ*øMôßùáwÿ|/ÿEÂo¦ÿÏ ¿ûáøª?á7Óç…ßýð¿üUPÿ ¾›ÿ<.ÿï…ÿâ¨ÿ„ßMÿž÷ÂÿñTQ@ü&úoüð»ÿ¾ÿŠ£þ}7þx]ÿß ÿÅQEð›é¿óÂïþø_þ*øMôßùáwÿ|/ÿEÂo¦ÿÏ ¿ûáøª?á7Óç…ßýð¿üUPÿ ¾›ÿ<.ÿï…ÿâ«ĺݶ³ö_³¤«åoÝæ3œtÁ>”Q@ÿÙnetgen-6.2.1905/doc/pictures/menu_special.jpg0000644000175000017500000001264313504650527017560 0ustar kurtkurtÿØÿàJFIFÿáExifMM*ÿÛC  !"$"$ÿÛCÿÀ6Ë"ÿÄÿÄO !1"AQa#Uq¡¤âð$26Bt‘±³3SerÁÑáñ45CEFRcds„’“¢ÂãÿÄÿÄ1ÿÚ ?õ´ÒH&p²8øÈÐo··>^çüvK—åÍä½O.WŽåªzËZ®…Þ·™ç•1ÈêB˜fßÅí6º4ÆÓ>¼ù?Î?Ûþþ˜O,¥,$ÕÇe[̶³ÑùX³ lÓ-– ÒòÉÒc–Étp{QÓÕñð˜r-v9¿—«œW¨æ|d#1Ó÷,É~5õÝE@0ìþeÓø;ßPúñ3sw/A‘¿Ÿ™ñ‘^ÇWkW«5øÄµa É"o©¥”õ0LûŽ(òøg•%œ_4C vÕ©g¯VÄVßÏ»5¥ã²‘H#2¢Ïɳ#"FN52ž ÁzN`†Lì­G#I¨Ç+\‘¨Ùº³,“tz¡]€gV:a¶-ÔÌeñ•0‰r·¹’‹U‡+&gŠôDCeäT(ä° P1‘Á;TVmvâÇK!êp]¥ymU±ËðÌ9Q€*ÊÃ`©Gb8¯ó(c/à†?^¦&h}­,”,~Žq=hʯI1$ƒ} W³8R[|={µq°Ã‘È ÀKK`@°)%‰Ò"ï¥úTÌFَ؇Üyª2 yjÎ,X’¬%m!óf¯Ìë:ùRmFÈèmë¤ëCœðvù~,ñÍÒƒ4“¤¤È@ÐÌ!ó ²ÈŒÈGD2I­íU[¨)V ¡äÊ´ùÊlè»4•<É­UÇ:"µ©‚,Ó(ö Â2AÖ-XMÒ¼|7‡–’žþ_•|G3Zæhñf5‘æõ.¥å“¤¤ÖšE}yh4N߀î\ñ•*s6—çæJ+k5LÜ Þº.‰¼I_‹lÒ™±šþ~âf©?“Ó•€ùö$«¬¯Ç4}~dkõtò¤êQÝzzé:àg¹MçÊQÉrîF, ªÑ[®Î”ÖQåZ–9gt]…[âV°uÛ9xäêíÇ“Ã̇ÝzrÕæ©)c(eoe*V‚„^rÍn+BFy©\¤–Ù£Ôj¡v²,¤‡Píesèv}ÿgì>|)+xQš\9Q±ÎÏk™ñpâ͉k\²+D¦pç÷ÍÉdbRÀ¢EU!N‰ßSN´´¡KÓE5¡¬ï F8ݵܪ’ÅFû€YˆíÜëd9\»Î8œå¹¨ÕȬyd´Œ¶#z+Úz¯/– o,˾{Ç·pÜßËÙ¨!±†æ|fJì5X¤©~9UæT24jT¸@\¨îoÛ¿6ð†Pdñ™è“Èå2o l|pX[7£³~d:$YW­úÕOX@"ù=o,9šï2c_™ ’¹«4X–JH‘Gn0<»’·¬÷(ÿÛán°µËÍü»ˆëÉÍ´š[ Z8Û!g™¤’5ŒwÖ^P/¹hÝ}ÔŽ1^ç,Enb§Ë둲v.­)+×J²=i¬'œ»ê@ñÀý=»ìk¶È£Ðð‚:ø®i¯c>o_Ïaíb†Fj(¶![®Ø‘ÉB í®/R(EcžÀ…]·ðÊÉæzãžÚË_£Í¯rŒÕ'UpJ?•2, Òà7OI(àUµ÷ÏØOÝ/)çùwÔú_º”lÒôuùFTdëéØê×Võ±ùGœ®7žòÇ–³K—+ÝÂä=],jd&’)ú«ØÌ–L*SbÇPQhí‘'àä­óå(Ù­‡’m]µZkPÇÒtÑDcWn­t£$o«¶ôu¸Îíû}'·´p¢«á~R½Ì6zÍ.QËs+^«vª0Ž/W6á·!œ¼}0õ/y¤ÔÊGS2ù§g/ËLM<Œ¸ÛwiMZÑlÉUÝ ‰WL§jH#âǸߟ1’¥ˆÆË‘ÈOåW¤™˜…DUPYÝ™•UfeU8ãZç®V­Œ§‘›({~aR ‘šºfy”/T ²<¡V& 9RuÅo íä16ën•«Í‘ÅØLN%%,¤œ›áægÎc/dâ\ÎG$rå”Ûš½‰l êËÒ"d°J²§ššò‹;`Áøk›–9žÆ`jPÅó5üœ”1öåjíRtºRQmC[XÚ":4mì1€k’$‘Ø­—û;ñ'±Ñì}ÆþŸ_êïû9¿óù–?¯+ÜúòÏ xàžŸ\ݱ,/PÍRr’,CX~MÀ!¯Î¸_Ý/&g9wÔŠuqóÓ3ù~g—æÆÉ×Ó±²:‰÷—€é\°•)ÍjU™£†6‘–Zg t¨€³“£¥PKÀÛŒäèÅš«ˆ’}^µZkUã OTp´BF¢«£4c¹$kz:Yó‡üÕŸå^v.ø,Ž[˜qQckÁ;°­¬Ö%ÙÄ;- µÐ„G¶5c”i ÇØæîKµšæ~^çÁr´Ùú4Þ´¾½ ÉVG’VÄrybIZŽN„üa3Ÿ2#½…ד¥–ªö±ó‰¡ŽÄÕYºYu$´2®›¸éteß±÷6þ@ööÙÖø\òï‡saó8ìÔ V<’óNöBÒÍ#I5 u⬬Àç¯#B­þ'ø›½âG/Xæ]`©ŽÈÃVè³c‘r•2IåIŠfÿ ´‰0ÜoñBƒKÙÔ;’å(Å™©ˆ’}^µZ[uã ~(â1 «EWFhýôOPÖôu8œµY-PœM v&ªÍÒË©a•¡‘4Ýö7CÒHØÑ+ü0·^Ï-æ“Ê׳8ÈíÀ‚ôáÇ$Ö–Ä ÖâŸIŠ(ǓԮÄ<é37…y¦òâòqb3–ò¹™meàšV)ÜŒ1FN˜–zÒ˜ƒ*y‘»ƒ×ñ06o˜þ’öð~ÞÜ%ycÁË0Å‹18é¦d[¹Œ¯j/Hð-;P‚±Ö§UÝì*È®„IaYˆø £ˆÇEŽÆÁéêB[Ê„;2Æ Ò»'¥ô¨4ªU@6þG;óoñ¯1üþïD|wæßã^cùüÿÞ7%z+n­­Ý½j µk«Í<ÓH"vYÙeP=ÉíùøøKUd»%$³ZI "#–̻ڂQÀ'[éo¡ã‹âÆ6îkÞkÃã`óïÞÄÝ­V.µ^¹ž&D]’%˜ ’5³Ü{ð¶çLñ¾o+o ŸÌæaµ_ÓØx"µa"lzñzg§Òæ¯!o6-©qÖãq´˜´Ýµ”ÆUÈÓÆÙÈT†õñ!§ZI•e³å¯TžZÔÝ#¹Ðíóã5ÛUiSžíËPW«Y “Í+„HK1>Àv~Zár¸Þk­SÄ»Èç§Çe%·‘³¨!jPµ[0Ç‹%‡whýDjY^fa±fb:êü×ɾ'ÚÄslÞ½[îÅA6SÌÔS¦LFÅ @Ei§íyzÁæ:Ñ`Ç}¾¿·ôoKY\e\•,e¬•(/ßó=Y,"ËgËOå©;~•Ñ:Þü¼.sÜ»Î2sÖ§g˜ó\ºÆ›±Ç—òï^…Ñ?“)–?'Oè%( AVEEOeZÛ\€Ö°Ù;眷nܾªzšpVIÚIA’Xã³ ¹C!o*SÔçF@dAfµ‰¬C^ÄSKVA„F¡rŠá\{©ètm2Ÿ˜ã/Ì{÷Ö¶ý¿'ôð²£Ê×°\çÎaÂç24órÉhM0Ê‘¬MV(š£iÆ­¡=/¤Tˆ¯LëÐ#ãwÁln^•l„¹¼?4ãoZ•d1eóc# @õfõ36” ¼ŽÈX*•ék+‹¨-›Y:P U…«FYÕ=<'«R¾Ï‡˓LtCwìxÜ=½ûoÛ}¿·òð§ñS²üÍmR9$7¹B v>*×Åt½a}sy/PÐ %sÔzGrETl40ž$ÇÏÙ¬•Ìž])jä±5ÒÜ.V‚žá†9,f<6»‰ÈSÌZÈÛÂÚ¥B(ò‘WJÄÍhV­4«7›Uê"u5†WV-$NÞ Ý9§ÎsfG;óoñ¯1üþïDݵïû{qç~n'÷W—Ò±ýý?ËþѸ±*ÿsÅ„6¥òðlñ=ì€XoùC {ößôñˆx³þ@ßmnHÿÛ×È|¾\f`>ûG°8¡Û½Íêòýÿ!üGßcÛx ýž³Û¾÷üýþÏêààà x³¯ù€žÚ;»½ý}Ð~ÿ?ôñ?}žãx:Ö¿~÷ú~·úø88ø³þ@×mvºGÿ_ÍÄwÿGÁùw¶o§ø?oaïÁÁÀHñgë'~û¹ïöƒ¸û>ŸNâÉ:?pþgÖŸíèöùh€ƒâÉ'þ!#ÿ;ý_Èù|¿ÓÄýÏì}=iúÿ™ùø88ûìoîÏóÍw{'Ôoú~Íø°4Bòùÿßüþß~üŸ~CuÜÿÃÌïü_Ôžã\}€}ù`ö ÛÞÁÁø;ü¿.ààà ø²H;ÀØþUÝïòüŸåôîx“âÀ,OÜs½ú¿þ}öâÒÿSƒï°?~—úœ÷؈?KýN¾ÀüAú_êpppß`~ ý/õ8>ûñé©ÁÁÀHñg^ØÓùÿáð¹ËXL†VåöŒÆlØ’^£Ò‰zûx88±+ÿÙnetgen-6.2.1905/doc/pictures/viewingoptions_3.jpg0000644000175000017500000005154613504650527020427 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ0¡"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…nøRÓMºñ­¦©›kpƾT«7 FïøÖœ¶Ó,t«mNÕ$Õ5lYÆ\°U†7 #mdÇѸ"³HEÙ¢”[ØãüäÿŸ üü(ó“þ|,?ð?ð®ÎÓÀ²jwÚœ‚G‚Ú=R[E½³M¬Fâ3ò õ$Õh<ÓO¶¨‘57Óî€"Š\Éœò»Tž‚’«H|’9_9?çÂÃÿcÿ <äÿŸ üü+¬ÿ„N-;P´[Ë…7ZM:(LG'ÌÈnp=zÒ?†tßø˜ÞÞêɧ[E­Ë¦F‹jò ŽF0IüaÖkH9$ržrÏ…‡þÇþyÉÿ>ø øWM/„á±›\mOSK[M"DŽIÖ!v|lAÏ9ôÍgkz'ö?ˆ¦ÑÖaq$B?œ.ÐÛÔÆ}ê”é·d'-Y•ç'üøXà,áGœŸóáaÿ€±ÿ…tú„ ³UŠU.5 &$–öØBʨ¤v¹á°Ï¦Õ¼i§¾µoo¬­Íî“ ÜOnmš?Ý ;²F@=j}­!òHä¼äÿŸ üü(ó“þ|,?ð?ð®ÏSÑt}g¶¶r;I¨EjòBð¶ÙUÛBÛþ\ôØ1õª’øfÍn/îoõôûOíy4ëP4›Ü1휪€:’ÄUi‡$Ž_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ êÛÁÖ–VÓˬk)cäêÙÇí(f(HÁîp8ïÚŸmàW›RÖ­$»cý–èŽ- 3K&á•*€Ž0yçó£ÚÒIœŸóáaÿ€±ÿ…rÏ…‡þÇþbêÙ ¾¸·FvÈSt‘ØãÕ[•>Æ£ò…j”Zº#R?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ ¤Eqa¦€Ã#6ÉŸýå?üøiŸø ŸüM^·‹ý.?€*—Êö©Ðf:±iŒCOÓ÷޹¶L/qRùOÿ>gþ'ÿSÇüLåãø¢ÕHô¹/Y›P¾÷®¡#1{Rm-Ò@Ñ.æÓôâ3ƒ‹dãÿ¥Ei\Xi 0ÈͲgÿA§ÅdaÝä+!]îrN$Ç?•Iq %]n>ÎcEq!è0:j.­{µ"òŸþ|4ÏüOþ&¡iš7;-m`š6e‚GF†VGF“s>§rÒLM¹‰F-†Al¾r:zT·QâyÏùû¢ˆµ%°4Ñü-_ÿÐkÿ%aÿâ(®6ŠÃ’=Šæ}ÎîÕ ÓíH>D}Ýñn73n~+Ô|)á÷Â:=ÍÅŽù¤³‰¼×;G`Õ®|áÁÖÀ¬òñTž& ê¶)S•òá[T-Âʧ™`ô#×úÓ|¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅRŽ&œtIƒ§'¹ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUWÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯e ðáé`Òy?øªC௠ƒƒ`ÿ®òñT}n‡ì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñT£Á>##OÈÿ®òñT}n‡ì™ã^W°£ÊöëØ^þý—þþ.ì/~ËÿÿGÖáØ=“<¡U‘ÕÐíe9u´õjú¿‰,u«ß²yÖ~ÏhÂ<†Ý–‰É8Îà ôOì/~ËÿÿGö‚?¿eÿÇÿ‹©xŠrwhjœ—SÍ—ZÔLW±ÜÚé—ÐÝÞ=ë[ÝÀÏr±9)†uÇSM´ÕõM?MÕ¬íÊÕˆªÄ ù@—†#¿jô¿ì/~ËÿÿGö‚?¿eÿÇÿ‹¨öÔ{$ûžqq®j×wº%ÅÁ¶a£*ý˜o†ßšNy?"ôÅAq©êWv’[J-Drê­ª¹D`|ÖmýÞzu÷¯NþÂðG÷ì¿ð8ÿñtax#ûö_øøº~Ú—`äŸsˆ±ñ&oµ«½q#’=Q£y-â³ǹíg€AÉç·JÉÖu6×¼O¨k o%´S”£ãxUP œp Æxé^©má_ ^nû,ϳ¼«§lg¦pÞÕ)ðW†ÁÁ°ÿ×y?øªQ­J2æIÂMXòÝOÄƧmwo °‹íª‰wu g¸UÆ6qØt­xŸÅ7:Þ£¬E¦[[ÚX_yi-ÃA¶ædU«6â6䃥zGü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿKÚѽì³îykkš‰}%¾Ï§³éf?"v‰¼Ò¨r¨Ä6 çØz[jÐ’ði·B{æ¿\À]!™‰;“æuîOó¯Qÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿ⪽µ.Âä—sÉgÕ5[»ku,3yš—öœ²”!Ú]»p0p±øÕ“¯ê-«Þê²Xé3]ÝL²æH_•P£i pA$W©øp ?þ»ÉÿÅRÂá¯ùñ_ûÿ'ÿKÛQì“îxìÒ^_^Üß_Ì&º¹“Ì‘€ÀÏ €S|¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅV‹¬½œò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ©ýn…ì™ã~W°£Êöì£Á>##OÈÿ®òñTŸð…økþ|WþÿÉÿÅQõ¸v²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}n…ì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡`öLñ¿+ØQå{ öQ௖ý'“ÿŠ¥ÿ„#ÿôÿÈÒñT}n‡ì™ã>W°£Êöìßð„xwþßùOþ*øB<;ÿ@ïü'ÿGÖáØ=“ßyÿ?sÿßÃ\/Œï…·Ú•u(â™,Œ‘B×òZº7χM£@OMƒûôIg¯ÝI¨Ïow#,°NÖÒÂÿ»•YO’ª|ì)C¸F¼©ùŽIiºû}çüýÏÿ o¼ÿŸ¹ÿïá®?SÓµ˜üج..e·>TŽ^Rd‘¿x$Û‡B¼ù'‘@ª™ltJI‡Û¯ïDkk–c“fÙwÈy›%T¢üÅ•¿‹~8@uo¼ÿŸ¹ÿïᨭõ‰o Yíu'žÎÙ"œ²œqÔW2!ÖG‹a‰dÎÂR$-Ë;p ¼Á3ˆ”ƒŸ˜Œ–¿ %Äz|«uk%´†êyHÈIW•œ•ˆèØúƒìHCˆµ «(UÖU¹»Ž2劆889þy©µ-Jñµ À¸‘ Ä üëoùéö‡ùÖ…ÿü„n¿ë«ÿ3@[Ä(“Ík ³@†I£78hÓîaœ‚9>´ÛoCzÛm5ÈçmÁqØc’ ƒ× Çè¥rÖ×ö‘xŒY­å²ª]HL2ÜÀè®Û¿Õc÷¢RÍÈnç?-Z6wÖ°XȶRNÐj—7N¼·3í#sÿ-ã9æ˜_Ûï?çîûøjņ±wªk¶¾¹ô9bg•“"I†;Kg¡À$w¬«y^xI-ä·cœÅ)RËÏ}¤~ Máïù(¶?õí'þ‚ôéÈ|¨Ö8þDPUx @è+>?hÒé’êqë–a l’énÐÄÇó€~eàžãÖ®O<6¶ò\\J‘C—’I*¢’I<zóU‹T´±{"ê÷OÖo5ÓíïíežH%7YvÊS´¦w2ýÖÆ~]Ì£¶ºñnƒcäý¯Ä:m¿ŸÍ›z‰æFÝrySƒ‚85n=fÊ]N]2=JÝïá]òZ¬êeEã’™È2òGqë\-­—‰luÕÔ¦Ó¯Wε‹Î‡F[8â‘ÅÅÄ…eYܲ±YT±ÎYŸ x5ìZ͆­<–:TóAo-ÍÜvóÍnmÝÝd``|yÉ+»ó¿äPò€H ®ïY²ÓÒg½Ô­í’G•¦PF®J©lž €ORª—^-Ðl|Ÿµø‡M·óâY¢óoQ<ÈÛ£®O*ppG²µ= xìã¼Eº½ÕÖušK»FŠ9ÔìtJK˜ö#(λ¶ZNX·Òõ&‡ÃO=²,–ÚŒ×7;v+*<7*¬á~S!2&ýœf#忀5O‹tw-¡ñš.aßæÂoSzl¾åÎFФœôÁÏJ·§k6Z½»\iš•½ì*ÛKiÖE €pJ’3‚8÷À¶“âìoi?aÕäË©­²´–BÐ^W &ËnæÈŽ@#´Ó4q§\\]M}uy:¤oqr# å¡b¨j«€]ÎqŸ˜ä¼S3ÙI¥ßÁòÝ5ô6­'v‰Û §Ôwèy‡©jW¨NĈ¨åF `ç[3ÿ=+þÂÖŸú0W9ÿ!¯úêÿÌÒbdCX•¶cRs½Ú5ÄçæuÎTsÉ[#¶¥KöûÏùûŸþþó·XÖxã´Ö-£ÔÆ£xR/P¬NâuFÙ“É-ÛƒŽx¾nÇa­¦‘:³_—’T a¹@s7%¶Ÿ”adR Ž0[ ¨Õ. ­¾”ȪLrÎ èp#O]FõX0»› ç—$~UÆ>—«H·7Cφé4Ø’Ý#¸áçC)]ä±$Ë•fe%ˆ%ñººªB5àñõþ‡u+ùq¼w­l¦0F(9äž}ë9õKˆÙï¥V‘¶ 3Xàœy8ý¨t¯ùo¿ì-'þ€+Äwiaý—{&Ó…˜£Œa•x22‚rÌ砅õKˆÙï¥V‘¶ 3Xàœy8ý¢]RâžYo¥Ž4RÎï1@êIϹ‘¨6­6‘}§G<±%íȆê&XÔ¡p²c’Œ1¸€Bppõ„¼½½¹±µ¹ûMÄ¿jGodWa”"½¹A1€ùù¾Vþ:`zš¥ÄJKéQK¦ dëÔ’÷4ï·ÞÏÜÿ÷ð×%¨è—s¥Å¸–î{ukk”-tUä•dc(´• …ùP1mÆFõ—˜,¢DÑ0\y|ƶæîØÆy<ç“Ô 7´¿ß=üöå´qXµÀrâÁ°9éÇÞ³æÕncI'šúHãP]ÜÊUTu'Ð ƒJÿ‘ŠûþÁ2èb³¼AKá½R5*ìåP]‚Œ”=IàsÅ0/Ùø…5ÿbÖçËÆÿ"ç~ÜôÎåV#Õ.%RÑßJê©+1# G^ ‚¸®*ÛT:­¿Ù­®®ï9D³Ä/-DòÅ´Œ!ÆÐa$•ã#'8¬Ûøµ?H{{‹­—Ì— ?nxÈÒÈÁ£1¨³nO“ ø g¤ý¾óþ~çÿ¿†·ÞÏÜÿ÷ð×–¸ºÍÜÒÏr"k)‡i!Ï–Š]ªÃ+ɉyC– ’×ü; ü³G{‰óå Ò39ãž ²àp1ó÷?(ÆYê-|CeycºÊ·7‘Âæ\±UcƒƒŸñ¯@¯*ù èßöƒÿB¯U¦†‚Š(¦0¢Š(¢Š(¢Š(ªºŸü‚¯?ëƒÿè&­U]OþAWŸõÁÿôBä*(¢½#”ú«Á_ò#èõãþ‚(Ö<9w¨Þ,ñOl‹° Hä¤ú{Ñà¯ùô?úñ‹ÿAÐÍÿ,ÿÜçOâgJØã¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ*l9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,8Ù<¨=ÝŒ¢êËm½Ôs?ï%Tó—­Z¹ð•ì×sJ·6a]Ù†]³‚~•ÔQE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÓ<aâ«}V[›6‚(]Qع$0àmÇqÞºÚ)Øv (¢€ (¢€ (¢€ (¢€2µí&}b (à’$0^ÁrÆV F€yô¬ËŸ ^Íw4«sfݘeÛ8'é]EÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´R°¬r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,rV^ ¿¶Ò®-^êȼ·Íp‘±´¨û½hÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%eàÛûmVâéKbÖà ;‹Ÿ»ÒøCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,qÍà­@Þéó}ªËm½Üs¸ó%Täãåë]¯“ÿM#ÿ¾ª:)Œ“Éÿ¦‘ÿßTy?ôÒ?û꣢€$òé¤÷ÕOý4þú¨è  <ŸúiýõG“ÿM#ÿ¾ª:(O'þšGÿ}QäÿÓHÿ搜ŠK—†ÒÞK‰î"H£f-Ò«jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±CûFX*]8V*Y-dapy ƒÈ4¿oþx^ÿà¿üM?Nf]8`‘þ‘qÐÿÓV«>cÿ}¿:‘”þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øš¹æ?÷Ûó£Ìï·ç@þßüð½ÿÀ9øš>ßüð½ÿÀ9øššòê[{‰Ñ‰hãg“Œš¥l|Guk Â>œT¡Œ™Áæ€'û|óÂ÷ÿåÿâhû|óÂ÷ÿåÿâi¾O‰¿ç¦™ÿ}IBz)c72Øù%°Þ_˜[ðÍ;íñÿÏ ßü—ÿ‰£íñÿÏ ßü—ÿ‰©µ]VÃCÒæÔu;Ãoi~d²³p£ù’OI MDúͳM§¥´¯:_x¦IBwnuÎF1ëœú€'Ûãÿž¿ø/ÿGÛãÿž¿ø/ÿZrHÊícöÍ3ÏÝoûìÐÛãÿž¿ø/ÿGÛãÿž¿ø/ÿZxþëßf<u¿ï³@ÿoþx^ÿà¿üMoþx^ÿà¿üMhyãû­ÿ}š<ñýÖÿ¾Ígý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5¡çî·ýöhóÇ÷[þû4Ÿöøÿç…ïþËÿÄÑöøÿç…ïþËÿÄÖ‡ž?ºß÷Ù£ÏÝoûìÐÛãÿž¿ø/ÿGÛãÿž¿ø/ÿZxþëßf<u¿ï³@ÿoþx^ÿà¿üMoþx^ÿà¿üMhyãû­ÿ}š<ñýÖÿ¾Ígý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5¡çî·ýöhóÇ÷[þû4Ÿöøÿç…ïþËÿÄÑöøÿç…ïþËÿÄÖ‡ž?ºß÷Ù£ÏÝoûìÐÛãÿž¿ø/ÿGÛãÿž¿ø/ÿZxþëßf<u¿ï³@ÿoþx^ÿà¿üMoþx^ÿà¿üMhyãû­ÿ}š<ñýÖÿ¾Ígý¾?ùá{ÿ€rÿñ4}¾?ùá{ÿ€rÿñ5¡çî·ýökšÕuYn5ˆl”âƒP´S‡'ÌÝ–çÛ…ãÛ?@ üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÇ;{{q§éÚ]Ôrm¶»Ãt€Ò$²¼H}%’&<ŽõèhiÚæ¡=·†.e>dÍÔÒ+‡Td‰ãšh“aª†Ã) £—ç¡¶‚­íî"Ia–k”’92º™\Aà‚;RÝéZuýŵÅå…­ÌÖ­¾ÞI¡Wh[ å S9ƒÒ¤g;©xÊ}.m`]i~TV6³O•äFºhоÕo+Êù•Y†Ù€*`¶5OEe¨jVñÁqwg³,~k–’IL‡ËÙnû‚E¿Xr@µkZèzMŽ¡5ý¦—eo{>ï6â+tI$Ürw09 ž¦£ÐÖÅìWFÓ…›ª£Û‹TòÙU‹¨+Œ™€ìXž¦€1`ñ ƪÞ¾¶yíb»¿¸³»´hƤSç;Ð8Äq÷Ì ð4ãÔo_ÄZÅ‚BŒm¬íç¶VŸ !s0ù±ä;£ÁåÆÈ3¯‡t5K4]N bÅíZ¦-ØÄÇÇÊIäc‘š‘ô=&K»«·Òìšæî# ÄÍn…挀 ;c,¸`ñÀ  ¼W©ãQ¸Ó,V=³Œ$»NWr†Áäg¥Nš“¥­¢ivKmi(šÞ·@È !Ñq…l’r9äÐm׈MÔüB×±?ØôÍ:åH®]œ[ UJ¾b#Øü§uS¸ñf§i¨Á¤Ï¢@ú¤ÒÆ«½öè‚Iì¬]£SÁ¶}À)ÂFãò×E•§E©Ë©Çaj—ó.É.–ºñÁ|d•x'°ô¨ì´='M‰"±Òì­cŽS2,èd+°¸pÛI\õÁÅ>¥ý«§ ““"Ë, mÁdŠFöœ ®ä8$F  ÁÔ¼e>—6°.´¿*+Y§€Êò#]4h_j·•å|ʬÃlŒÀ •0^¦!·BD‘!fr¨¡Af%˜ñÜ’I=É&¨'‡t8î.îFÓ–kÅt¹‘mP4êç.ã,õ¯z·ñ¼×wO‡KOí6ŸìñF÷$BX…rÒ,kIñ„9Y;w0Aüo7Ùnî"ÒÑ“Lî50×%J*I4l!ùšso.7yy:díénô­;PI’öÂÖå'TIVhUÄŠ„²†ÈäIô$šŽMI›ì^n—dÿ`ÇØ÷[¡û>1/“W¦:Jäõkv–~5yžÊÝl|ôÓ¥¤-¢Lª#1€Ünä’WWu^¸ñv¡o¨Á¦6…ÿ ‰cCöµÂÇ$s²4·¶pê»À*d?)è§Ò´ë«‰..,-ešX ¬’I ³<$äÆI(Oðô©ÆÒKµ»{Xåq¶c.0 7^’øzšã§ø…$s,úÕÔЫ5äp$Ò•+4°•ˆÇ% “aˆ·‘–Û®ž$¹õÞŸ6–ñ$jÿfÜÎ$ºu‚!d’Ê€ù‚á‚éK¡é3Ëo,Ú]”’[JÓ@Ïn„Å#6öu$|¬[æ$rO5xwCŽâîá4m9f¼WK™ÕN®ráÎ2ÁPz÷  Û rMkAÔþÓl–—QDû­Çœ!SµÈš(›†í í8$‚­.ûTOèÖ2Ié“hòËH¹wxͰÞÌz­u =2IÜJúV¤h7Öúe…­”-ŽÑÛB±©m¸É ÎçØTš‡ü;q†§q¤irj+ ..¤¶ŒÌUväg#<`PGUï?Õ§ûâ¥ó¢ÿž‰ÿ} ‚êDhÐ+©;‡C@Œ|&Þ0û<–·6Vÿ4i5Äé—Æ P}sŒœc$T>ð|úØÃÖú}£JésM&Òãa8ç’OSS|A“^: ø†3T†?1mæòvܯ÷s ;Or\­MMN9´m[Ä)¬ßæi.d‹bÆ­å𪨜2rOÀí§ÿ\߇ò¨êIÿ×7áüª:óxÇW‹AþÔÔN£w‹;V–+ÈáVyî bmÔ±„—}Å•›åAeu­8üe«]ëzU¬:_‘=ÔWqý–íÞÞ)dì,K)P â<–ÏWxì•§5º[µ…©… kTŒÂ»V4`cUÊô;G¥W>ÐÚÅ,[FÓš+"[›TòÕYƒ° ŒYUˆîT¢€1m¼wiw¥­ú[ùqËegn“JåûBA 8çæUœ’£9òÏ>šzmåÖ¥.¿k+½´–׆Ú9"‘dئYsâ@pÁðÙä®_›JÓ®/äö²ÝT¼*Î\:ÄgÀ`;ZŽ=I‡í¾V—dŸoÏÛ6Û ûFsŸ3Ÿ;›®zŸZç¬|Wu†zÀáÐãœ,Ű3„ägˆôßkW¹Ò'·Á,ÖWöâFY#VUóË ¡?¼F<Õ<äã·¦Ò´ë‹Áy=…¬·AUï ³…W£qÀpÄÖ«§‡t8î.îFÓ–kÅt¹‘mP4êç.ã,õ¯zÅ·×5ø@ü5ªH|éï?³…Ô¡Ö6ýóF¬Àle9g®‚pTWîµ}Z?C¥Ûi–W>×’o·:ÉXæGO(¨ËUòÄ`+•·'‡t9tÈ´É4m9ì!mñÚµª‘¹ä&0ÌÜÜúÑ7‡t;LjsèÚt·á•ÅÓÚ£Jq´ï#99ã€9=[Çw¦kÑéö¨—i×7¶€ËåK[A4ª±Ã£(C"·BÀNö¡¬ÞÛiVò¼V«tºµ­äv·›ü$¨ h¾bD‘’¥Tís†i:Vº“c¨Mi¥Ù[Þϻ͸ŠÝI7ÌNH穨äðî‡.™™&§=„-¾;VµC7<„Æù›;ŸZ£uâY­õ9ã[{ [È,.'3‘(šo+fÈöÉûøòK©ûØt~ñMƵýœn´¿°®¥aöëQö+l_,>ð ̨Wäd°CòÖÔšV.§§%…«ß»#ºhTÊ‹Ïñ>fàçÖ¤†ÆÒßÈòm`ìñaÙTgnQqÑ~UàqòA@šæ¼ÚMÄ0Ej“»A5ܦ[……RŠ fßûÅÀb«×.¸çžÒüu:éþp}³í–¶KyuÈZ;‰Â,^RòèÄ4ŠpÙ ~PÝ¥Õ¥÷“ö»X.<‰Vh¼ØÃùr/G\ôa“‚9Mü;¡Éqipú6œÓYª%´j… T9@‡P§ ;P‹âmEtKûhiÑÜÇ=ÚÚÆ—lÍ7—pñÚ" €Æ(ÁUvmËòî!N·†µóâ ;™$´{[‹YͼÑ2ÈmŠà1ñµ×ï"óœd`›í¥iÌ÷ŽÖ¥ï”%ÛW7 Ð$ãæ0sÁÅv•§iío¦XZÙBͽ£¶…cRØ$(8Ÿa@ë»ÿ‘¦Oû Yè ]}rò4Éÿa+/ý¨_Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥ldõhí’+1d€K3·ÚÉ;¤b0zz÷íŠfßÿGÿÈ¿áZÔTŒÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+ZŠÉÛâ?ïèÿùü(Ûâ?ïèÿùü+Z«ßNÖÚ}ÍÂ^(™Ô7L€O4žÑx…Ñ‘ÛFea‚”‚?*_/Ä_ÞÑ¿)›¥O­ße”éénè%mªåöã8ã?皈o¯´ý>9l"Ë4¡e›ìÏsä& ÝäÆCÉ– ¸R1¿qáMcF½:ñæ¦î¶ù¡´Öây~"þöùKþy~"þöùKþ…Ž›…½ƒí6Öö]Íqe ‰|ÉÒWHAM¢%Ì\ȧz€ûIï|mcaÕÄÖw¿b‡í —J¨Ry Wi#A¿xaåKË*©ØpÜ®v4Úf­q)–koÉ!Æ]â“Û©‘iš´‰!¶ðür/FH¤~ V®¯i{ª]X[¿™%´I#ºSæycÚ?x4.íù⦫âk=#W°Ó'Ì׬«"‰FX(ǘê\äò±‡aÆ@Ü»€(\øsP¼¹’ââ-&I¤9fin9ýjøDîçÛGÿ¿·ãW¯üe§iÚAÔæ†é¡ÝÛíERÛ­ÖfsËc[¾9î¹Ç8¯«øÀØhÒ]®™¨Á+O}¢ÊG &p‹.Øòp9>[|€¤)uÈ?ð‰Üÿ϶ÿn?ÆøDîçÛGÿ¿·ãSj3¶ðî™§\k»Ý+3JŽ…UÇÏåLë.J°&5We9_˜àµ¶ñ]¤kž[KØôÛo8>£å†‡t;¼Á…&A´£Œ²Jà¹wgÂ'sÿ>Ú?ýý¸ÿ?á¹ÿŸmþþÜ$4YôË»ÄW&Õ£Y"[‹g vÖ2¬¦cžE9c,º›´¿Óí¯"Žâ%•Fõn9RTõê „Ð/ÿÏüûhÿ÷öãühÿ„Nçþ}´ûûqþ5×Ñ@‡ü"w?óí£ÿßÛñ£þ;ŸùöÑÿïíÇø×_Erð‰Üÿ϶ÿn?ÆøDîçÛGÿ¿·ã]}ÈÂ'sÿ>Ú?ýý¸ÿ?á¹ÿŸmþþÜuôP!ÿÏüûhÿ÷öãühÿ„Nçþ}´ûûqþ5×Ñ@‡ü"w?óí£ÿßÛñ£þ;ŸùöÑÿïíÇø×_Erð‰Üÿ϶ÿn?ÆøDîçÛGÿ¿·ã]}ÈÂ'sÿ>Ú?ýý¸ÿ?á¹ÿŸmþþÜuôP!ÿÏüûhÿ÷öãüjŧ†ï`¹¶8Óa†;˜ç“Éy‹6Âxù³Øšéè  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¨®`[›YmÜ’¡F+×cŠ–Š!Û@Ã""\@j¦£¦Zê–ë Ò9ÛÑâ•¢’6ÁWBN d:*ÝbÛxŽ;÷Óu‡ ËÚyÇ]جÿwM[E–£Õ’/†tu´»µŸº¼µû%À292Ç™ Üs’ÄË!-ı$“AðÎŽ×rÜIiæù»÷A,Žðà‡a &5f Ù` ï’w6mêzŒ:]‹]L®à2F‘Æi$vˆ2@Ë3(É ò@É¬ÏøK,måŽ=R)ô–1K+›ò‘¤A%åÃ9óãÁRGPH`Eh"þ›£iúGšl­ü¶—c³³³c=Y‰'’ÌyåØå™‰QÐl5[…–óíR»¼™!‘rN%`ŽH!ÈàäqV$Õtèµ8´É/íRþeß«L¢W^y œ‘ò· v>•$7Ö—G“uŸhˆÍÉócr뎫ó/#˜zŠÈ¼ðf4²ÝXy'›Ç TóQ’]Š ¼;ÚâC°kÞY[ß°ÜÇæF²Ç0#çÕÐñèʧðæ£Ôu];H·[NþÖÊm‹%ÌË–Á8ˆÀ<{¯¨ëÚv—2[ÏptíÈêeÛ,Ë ¾ÒAÙ½ÆOש‫økK×wý¾)Ï™†_"êX<ØùùËeÞ¿3`6@ÜØêr èíw-Ä–žo›¿tÈï.v’cV`Í– Þù'seéâ-K‹»tÖtæšÍ]îc[¤-¡Ã—Ê…=IéÞ‰fìcg™¿oû9ÆyÆjý••¾Ÿh–¶±ì‰3€IbI9,ÄòÌI$±$’I$“SÑ@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPU4;Ò´ëh$vycqQòä’N?:·EeV…:ܾÑ_•¦¼šÙ6¶*j–m¨i—‰"Fe]¹’•wWCÃ#•†A œpFàÈtÝNÊþI-]íàG‚( i|¡˜SsyC6@'sJç#8®¦ŠÔG¦ø"m:Î×O]QÁÎk…6ÄK$ÖÉ ¡Gß„CöxÉR¬~ödm·áÿÿaÝÛÊÚ”÷QÚZ›KXÜcËŒˆ—OðÛÄxo2¶>p©ÒÑ@÷‰|3&»qgwm¨=ժɰi‚²HP°>L±6sãæÇ\©8"„Þ„=¼Wio¦Áyi}»[‰]d·F H͆8‚ð7d“¸©({ (Î"ð]þ¥4v·Q°²±³6ÖÉ4ðºDâh$Œ@Ðí•£g™ HFÜbÄi¿®O†;mF¯L²KsxÂðÉ+0E\] vÆ€©v¢œ í( ࢷŽ7™ætP­,C9ï  ž¼=©(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1üUÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ ŠÐÔu…µ¸XVÆþઠ¼P}3Æ ÏðWüˆúýxÅÿ ŠÝ¯>_:VÆ?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[TŒÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠÇÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëbŠåõ­J]KHžÒ'SY$Û‚öäÇÚ·µ?ù^×ÿÐMZªºŸü‚¯?ëƒÿè&„ÈTQEzG)õW‚¿äGÐÿëÆ/ýVíax+þD}þ¼bÿÐEnן/‰+`¢Š*FQEQE,LV)8]zŸ'÷¿AGŸ'÷¿A\‡îõ[/øR kW‘Æ“äM§Ï‹yDÈ!Q# aêÅCÞ! ùÑxZöãRð†‹}w'™ssaÒ¾Üí’p8“Ò€6¼ù?½ú ÈðýÌך$4“H\³7«N±ü+ÿ"ݧüÿCjØ¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(©bb±HAÁ⢩ýL¿‡ó Ï“ûß £Ï“ûß ¨ëñ½®›q¨xqõ-õa¼•åÛ¦½ØHŒ)ÈTl!‹Žäü9§Ÿ'÷¿AGŸ'÷¿A^y¥\x¢Ðivw²j?o‰lâ6ÆÜKo<^\BâYn6œH¤Ïæ.Liò¶ïž5¾ñµ¯‡¬g-=åõæ–·*ö‚/²H¯`¡Qˆ“Ë’f*ÂB^?•1˜È£ùò{ôyò{ôÎøF}ZãDóuwß#JÞK:ºÊcà~ð40üÛ·ã¨Û·¯$ïPm¥ÝÅÆ¿ªÅ,¬ÑÂ!¯eÊ’3ý=+J±ôïù5¿ûaÿ Ø Š( Š( Š( ªêò ¼ÿ®ÿ šµUu?ù^×ÿÐM¨¢ŠôŽSê¯È¡ÿ׌_ú­Úáü3âÿé~Ó4ûýZÞÚòÚÙ!ž IWÔa•èAbµá>ð§ý¬¿ïåpJ.ïC¡5c£¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü¥Ë.ú::+œÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¨îo­´ûgº™b*¹<äç “XðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»Ñoþ­þòÿ…ð•h¿óûÿŸü*§ü'Þÿ õ—ýü£þï ÐzËþþRå—`º'ÄzO+Çpˆó6ù``]°'åäáTdöv¢è¶ñÛÛÜ$PÄ¡#Ž8U \jƒþï ÐzËþþQÿ ÷…?è=eÿ(å—`ºQÕ|)«Û­¾¦¶·°«oXîm ŠdR3‚y÷5sþ­þòÿ…Tÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.‹ð•h¿óûÿŸü(ð¯ü‹vŸð?ý ª§ü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”ùeØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèè®sþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::+œÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèè®sþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::ŽæúÛO±–{©–(ò«“ÎNz95ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]ÿá*Ñç÷ÿ!?øQÿ V‹ÿ?¿ù ÿªÂ}áOúYßÊ?á>ð§ý¬¿ïå.Yv ¢ßü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øUOøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚è·ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþSþï ÐzËþþQÿ ÷…?è=eÿ(å—`º$ÐÖõ‹‹wßù;[g G¥o×9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå>Yv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèè®sþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::«©ÿÈ*óþ¸?þ‚kþï ÐzËþþU{ÿxZ]:æ4×l™Ú'UN¤ƒB‹ìGÌtVÏü">%ÿ¡{VÿÀ)?øš+¿™ögÿÙnetgen-6.2.1905/doc/pictures/viewingoptions_6.jpg0000644000175000017500000005313713504650527020430 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ0¡"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…nøRÓMºñ­¦©›kpƾT«7 FïøÖœ¶Ó,t«mNÕ$Õ5lYÆ\°U†7 #mdÇѸ"³HEÙ¢”[ØãüäÿŸ üü(ó“þ|,?ð?ð®ÎÓÀ²jwÚœ‚G‚Ú=R[E½³M¬Fâ3ò õ$Õh<ÓO¶¨‘57Óî€"Š\Éœò»Tž‚’«H|’9_9?çÂÃÿcÿ <äÿŸ üü+¬ÿ„N-;P´[Ë…7ZM:(LG'ÌÈnp=zÒ?†tßø˜ÞÞêɧ[E­Ë¦F‹jò ŽF0IüaÖkH9$ržrÏ…‡þÇþyÉÿ>ø øWM/„á±›\mOSK[M"DŽIÖ!v|lAÏ9ôÍgkz'ö?ˆ¦ÑÖaq$B?œ.ÐÛÔÆ}ê”é·d'-Y•ç'üøXà,áGœŸóáaÿ€±ÿ…tú„ ³UŠU.5 &$–öØBʨ¤v¹á°Ï¦Õ¼i§¾µoo¬­Íî“ ÜOnmš?Ý ;²F@=j}­!òHä¼äÿŸ üü(ó“þ|,?ð?ð®ÏSÑt}g¶¶r;I¨EjòBð¶ÙUÛBÛþ\ôØ1õª’øfÍn/îoõôûOíy4ëP4›Ü1휪€:’ÄUi‡$Ž_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ êÛÁÖ–VÓˬk)cäêÙÇí(f(HÁîp8ïÚŸmàW›RÖ­$»cý–èŽ- 3K&á•*€Ž0yçó£ÚÒIœŸóáaÿ€±ÿ…rÏ…‡þÇþbêÙ ¾¸·FvÈSt‘ØãÕ[•>Æ£ò…j”Zº#R?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ ¤Eqa¦€Ã#6ÉŸýå?üøiŸø ŸüM^·‹ý.?€*—Êö©Ðf:±iŒCOÓ÷޹¶L/qRùOÿ>gþ'ÿSÇüLåãø¢ÕHô¹/Y›P¾÷®¡#1{Rm-Ò@Ñ.æÓôâ3ƒ‹dãÿ¥Ei\Xi 0ÈͲgÿA§ÅdaÝä+!]îrN$Ç?•Iq %]n>ÎcEq!è0:j.­{µ"òŸþ|4ÏüOþ&¡iš7;-m`š6e‚GF†VGF“s>§rÒLM¹‰F-†Al¾r:zT·QâyÏùû¢ˆµ%°4Ñü-_ÿÐkÿ%aÿâ(®6ŠÃ’=Šæ}ÎîÕ ÓíH>D}Ýñn73n~+Ô|)á÷Â:=ÍÅŽù¤³‰¼×;G`Õ®|áÁÖÀ¬òñTž& ê¶)S•òá[T-Âʧ™`ô#×úÓ|¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅRŽ&œtIƒ§'¹ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUWÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯e ðáé`Òy?øªC௠ƒƒ`ÿ®òñT}n‡ì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñT£Á>##OÈÿ®òñT}n‡ì™ã^W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xâ«#«¡ÚÊrê iê>"ÕõXëW¿dó¬ýž(Ñ„y », ’qœÀêð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUKÄS“»CT亞TºÖ¢b½Žæ×L¾†îñïZÞîx㕉ÉL0#®:šm¦¯ªiún­gh¶P¦¨˜$EV AÊü¼1ûW«ÿÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñUÚaòϹå—æ­w{¢\\f2¯Ù€FùØmù¤ç“ò/LTž¥wi%´¢ÔG.ªÚ«”FÍ`FÑÏÝç§_zõ¯øBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*Ÿ¶¥Ø9%ÜóËfûZ»×9#Õ7’Þ+1<{ÖpAž{t¬gSm{Äú†°–ò[E9A >7…U ÇœgŽ•ëCÁ^=,úO'ÿH|á°pl?õÞOþ*”kRŒ¹’cp“V<·Sñ±©Û]ÛÈ,"ûj¢]ÝCÙîq€Íœv«^'ñMη¨ëi–Öö–ÞZKpÐm¹™@*͸¹ é^‘ÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅRö´o{,ûžZÚæ¢_Io³éìúYÈ¢o4ªª1 ‚¹öÞ–ßÄ´ä¼mОù¯ÄW0HfbNäù{“üëÔá ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯mK°¹%ÜòYõMVîÄÚÝK Þf¥ý§,¥v—nÜ Çl~5dëú‹j÷º¬–:L×wS,¹’ÄeT(ÚCIêGÁ>'OÀÿ®òñTŸð…økþ|WþÿÉÿÅRöÔ{$ûž;4——×·7×ó ®®dó$`03è`ß+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU¢ÅA+$/g#Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª[‡a{&xß•ì(ò½…{(ðO‡ÈÓò?뼟üURþÂðG÷ì¿ð8ÿñt}n‡ì™äþW°£ÊöëØ^þý—þþ.ì/~ËÿÿGÖáØ=“<ŸÊöy^½cû Áß²ÿÀãÿÅÑý…àïÙàqÿâèúÜ;²g“ù^Â+ØW¯ÛxWÂW›¾Ë3ìÆï*éÛéœ7µOÿG‡èÿ‘¤ÿâ¨úÜ;²gŒù^Â+ØW³Âáßúäi?øª?áðïý¿ò4ŸüU[‡`öLñé`±¼²K{È˪•*ÝGÒ¢µÒôk)ÄöÖþ\€¯fÿ„#ÿôÿÈÒñTÂáßúäi?øª¬SÞÃä‘äыה†ÃãžßáHm´òÌÛ¦Rı ò(ÉëÀ5ìð„xwþßùOþ*øB<;ÿ@ïü'ÿMâi¾ìäy­²Zyᱜ€AõÉ$š]–s[EÂnÙ´í*HÈèk׿áðïý¿ò4ŸüUð„xwþßùOþ*¬Ã°{9HÂÅîv• û ¢©Ý¨>E)úW³ÿÂáßúäi?øª­¨x/Ãñé·Nº~ar'\ö¨X˜v³gÌ4QEhAõW‚¿äGÐÿëÆ/ýU_ÜÅxG+F»we 䎾œUÿÈ¡ÿ׌_ú¬ÈUë˜ÿК¼éîÎŽ†oÛï?çîûøhû}çüýÏÿ p¾3¾ßjUÔ£Šd²2E _Éjèß>6ŒLIm=6ïÑ%ž¿u&£=½ÜŒ²Á;[K þîUe>J©ó°¤eáò§æ9%¤ëí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¸ýONÖcób°¸¹–ÜùR9yI’Fýà“n óäœEªe±Ò5)&n¿½­¬^YŽM›eß!änl•R‹óVþ-øáÕý¾óþ~çÿ¿†¢·Ö%¼gµÔžx[;dŠrÊpppAÇQ\ȇY,I„R%“; H´f?,íÀ2ðwÎ"R~b2Zþ€—éò­Õ¬–Ò©ä #!%^Vp~V#£cê±  "Ô,n¬¡WYVæî8XË–*ààçùæ¦Ôµ+ÆÔ'âDTr€#0ó¬I¿ä#¤ØBçZÿòºÿ®¯üÍUo¢O4 ¬*Í&ŒÜá£L¹†räúÓm¼M ëm´×#·ÄWaŽH$\+ >•Ë[_ÚEâ1f·–Ê©u!0Ës¢»nÿUÞ‰K7!¸œ üµhÙßZÁc"ÙI;Aª\Üõœú¥ÄlŠ÷Ò«HÛPˆ,pN<œ~€Ô:Wü‹·ßö“ÿ@‰â;´°þ˽“iŽ ÂÌ ÑÆH0ʼA9aÆsŒÐBú¥ÄlŠ÷Ò«HÛPˆ,pN<œ~€Ñ.©q O,·ÒÇ)gw˜€ u$ç\ÈÔV›H¾Ó£žX’áÖäCu,jPŒ8Y ±ÉFÜ@¡88zÂ^^ÞÜØÚÜý¦â_µ#Æ·²+„0Ê^Ü€ˆ ˜À|üß+0= MRâ% %ô¨¥‚‚Ó2HuêI{šwÛï?çîûøk’ÔtK¹ÒâÜKw=ºµµÊº*òJ²1”ÚJ„Âü¨‚6ã#zËÌQ "h˜.<¾cÛswlc<žsÉêPöÅÞ©®Úø~åÿÐ剞VL‰$ í-ž‡`‘Þ»É'ŠÆÍ¤’T·µ‚2ÌÅ‚$h£“èèy§‡¿ä¢Øÿ×´Ÿú ×iãZãÁ:üP<šuÂ)‘ÕYˆ =Éw¦†‹ºn¿¦k>oö^¯i}åcÌû-Ê˳9Æv“ŒàþF­Ãv·^ *d,¸RU‡ÁØ‚+άuöñŸØ¬µ GRxgÝ@º•ŠÝÏÆ]±5¬Š,†&%Š22ÙÚquh5Ã’ÙÝßùz´‘^Imn5imdiÞâwW„Š·r>èÿvBí!~UóqLg±ùýöüèóûíù×o¦x­``ùœ’ß"ã,7‰¦k9ô«è~[–¿‚Õ¤îÑHøe>£¸ÏCÈ­úçB¢Š+Ò9Oª¼ÿ">‡ÿ^1è"c×zâÏöȻĎAêO§½ ÿ‘Cÿ¯¿ô] ßòÏýÁ^tþ&t­Ž;þÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢¦Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác“Á:ƒÝØÊ.¬¶ÛÝG3þñ²UO8ùzÕ«Ÿ ^Íw4«sfݘeÛ8'é]EX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&‹/ßÛj·OudR[·HÙÜXýÞ•ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç'‚u»±”]Ym·ºŽgýãdªžqòõ«W>½šîiVæÌ+»0˶pOÒºŠ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°X䬼m¥\Z½Õ‘yošà#ciP1÷zÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKLð}ý‡Š­õYnlÚ¡teGbä÷Çzëh¢˜ÂŠ( Š(  ½sJ›VŽÅ ’$6÷Ð\¹•ˆQÁ `}+cÉÿ¦‘ÿßU'“ÿM#ÿ¾¨òé¤÷ÕGEIäÿÓHÿïª<ŸúiýõQÑ@y?ôÒ?ûê'þšGÿ}TtPžOý4þú£Éÿ¦‘ÿßU—/ ¥¼—ÜD‘F2Ì[¥VÔÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPE‹¨jŠk cb¶¿ñïç8oïØý+:µaF¥Gd·cI·dmQPÚ-âÛ!¾h Ì7bBØrrÏÖ¸Ý_Åš¾–5‰dKXM´Ookqi2îòãwF[ŒùsÄ»YU›'1¶n2RJKf#¸¢¹ãâû`æ§j?nvAofÑ¢K:¸‘•Ææ €¬2œHQ†Â ‚TÛÇ:Lv—ÓÈ'¬­ZâXŸ`rÊgüØiÚÍœ|¹ŽiÒÑYž"ÔfÒ<1«jvê5œ×¬€•,ˆX‚2=k&ÇÄ7‘Yù÷¬ú„·‹kKk}&[ ^@Œì1q&Ø¥²J”Œ“@MÅÁãô=Ýôšeí×Ù>Ó=ÂÛF±˜-Òy£ftmÅal¨ÉNBän/ˆºôÚBÈí4M,`ÆRFy" ]HÆlÉ@Þ Ü»€:š+'ÃÞ µñ&Ÿ%å¢m%1öˆ&äzÃ#¯ñ Ï·LëPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQET+iê |P<Æ!ÝÈ ’xSú}jjŶñw†1o¦ê2 –´óŽ»±QQÂÖ¬ôר/#qܹ€aÜxOEº{¦žÕÝ.VE’q'”<ÀVFH÷mG`Ï—Pïn~c›úž£—b×S+¸ ‘¤q€ZI‚" 2ÌÊ2H<2k3þËycTŠ}%ŒRÊæü¤iF‰ypÅ|øðT‘ÔV•´@[¾Ð4ÝFâK‹ˆ_í±§ÏŠ¾Ý¬„?½eH$9 â “ÂZ©I§£ˆ×gÌìK‚Kç9’Òd¶IÊDŽüš®§™%ýª_Ì»ãµi”JëÏ!3’>VäÇÒ¤†úÒãÈòn “í¡Ù >lcn]qÕ~eäqóQ@õ•¾¥§ÜØÝÇæ[\ÄÐÊ™#r0 ŒŽGô¬Áá]0[¼,ÚŒ™]^]Nåä€#1»HZ3†`J‘H9Tš®¸tÝBÒÆ.÷P¹¹ŠY•-LCjFP1&GAÖEéžôû_è×c©šþ¹µ¤ ,±0,!Ãcž¥ajÿ´íBÆ=2Ú: 0,©äK`³4cv¶rA…ÉcÔ2©…H;© ØEqw4_jˆÝ+¬‰äÉÞr̨*99;ÔÉ'9$™-õ›µ¹€Gmt-O= ™NÑ·†8mÎka³ÛM ßøzÂ-6iµ{/³j2¼p\ ˜ü¯‘X³- ®ÜŒüÌ£½_Ót{=+Í6Âv’\o–ââIä`3…ß#3mb8˜ÉÍú©&«§E©Å¦Ij—ó.øíZeºóÈL䕹±ô«tQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQJ› 'è(*¦‡`šVmŽÏ,`î*>\’IÇçW ²õ}ES“UÓ¢ÔâÓ$¿µKù—|v­2‰]yä&rGÊÜØúVUhS­ËíùZkÉ­˜Ók`Õ,ÛPÓ.-DŒÊ»s$+*0†F+ ‚A8 àŒÁ麕ü’Z»Ú-ÀŽ-P@ÒùC0¦æò†"l€Næ•ÎFq],Ãuoż©,2¨xäƒ+©Áw©+Q~›à‰´ë;]=uD{k9®Û,“[$*…~Ùã%J±ûØa‘¶ß‡ü#ý‡wo+jSÝGijm-cq.2"\u?Ãoà¼ÊØù§KT4ÝsIÖ|ßì½RÊûÊÇ™ö[„—fsŒí'ÁüTÕ¼1§k𽿧kky ¬Ķ×6ë*–‘¢;Æî2:äw‚ëÃS\jsÈ·È–W_Ü@`&S4>VÍ’nS÷äc÷°FFÝÙ§†ÝÏ*D…•;˜…QÏrHw$ ’€9iü#5úk0j¶·º–£o{äýŒáV#cl¹ E'’Ç¢Åφ¦kË›ë[äŠñµ¨@e€¼q·ÙVØ«(e.6î<2à‘Ôì3Ãp…à•%@Ì…‘ƒÊJ°ã¸ ‚;EI@ÐðÍòø†-Eu‘&Ï5c‰Ò[‚¨´›d³60[ÉÈ\*UXtµ_Z'™ºêò¥XdÌ€l‘¶íCèÇz`u;‡¨©è¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Å_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&¨ø«þE»¿øþ†µ{SÿUçýpýзä*(¢½#”ú«Á_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î óåñ3¥lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*;›Ñcg$¾Tò±* BÌýjJ(HžâïVÔ®¦‚ê(ÜD± „*@²}òxõ¬»í7Q&f³³Ÿì×P\L] ’ÎMy9e Ø#ÊnHØž_m皇|G¥x{H´¶šõ›û.4Ôck±ñ½¿î¢ä,må}¡“nNÖg݇«vÖ¾(±¸†òÒÞéìÕ¥HôûËÁ,ÑÄÆÝŽö2ïû«„ÈÛLу…ݳ¸¢€(hv·v:i?Ú/`µŠ;‰·—ó$U›qää‚ry5Éé¾Õ4ÿiÛ®ïgÕ­¬ ¶04‘!‚,Än ‰ã ó2ǵY˜BëËWwEpóÙë±h*mìµvtÕ­çµµ:‚›ˆ­”ÆeYdi± lM….üHƒŒ|–î4­lêÚŽ¡ÍéaªZ›8>Ô+m¶ÝnÌàä ¸|àÈ·[Ep–Z§£húΟiiª’Y¤K”Ô|Ó.ùÙÑbY%pŽDº'$eY˜‡^‡Â±j0h1C©ÂñLŒÁ|ÙZIsœ¶é% ä‘1øägbíQ@>¡á­VmOT¼¶wT¸ÖìnpÉ4}”—·Èêc“ž¬7ÈVK= X²ðTM-öµq­KawQ‹¤‘š\.q¹ÕWo̤££0$î/µÇiEbøV-F (u8^)‘˜/›+I#.s–Ý$¤’1æ?Œì]ª( Š( Š( Š( Š( Š( Š( Š( Š(  È·wÿÿÐÖ¯jò ¼ÿ®ÿ š£â¯ùîÿàúÕíOþAWŸõÁÿôBܨ¢ŠôŽSê¯È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸+Ï—ÄΕ±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¨5]VßM´™-EÀ€È‘ÊÃ,pqÆrrEOU¦Ó¬®%2Ígo$‡w‰I=º‘@$šæ ¼étð]Id\\Goç4nS;Ä`|ävÏJáluKÉo4Ë}ñ$/¨ª]^]FÌæÖ䑿°λÚ…â" —,=1cEDP¨£ ª0ôêà.|o¨Å–m: ­–`Ê»Vš)扢¶ÁG&8ýéz |úV^+»ºÖíô–´Ûr/î#¹ýÙm×ísØKbÄŒbâ2?Ö-u´P=âÛ…‚0]]½ž™%æËû…  “)\ʤÁ”D2É!y̛݃ký_ÄA¡êwSZç[µµäúœñù¦¹Q®Û¡„\y‡¨¹f Z½ŠŽxVâÞH¸I£Ý‘€#2Tû‚í\%¥ñð烵 I/.žåµ›d–þâK˜Ñcº•:dD.™;rYˆ¿¢€<âÏǺΡ¥_jvðiÂ×MÓôû²í9IncdMŽUC‹|†Üá3Þƒ‘sUñv»¦kWØ<Õ2Ü¢X.Ÿ>ù8&’2—@˜Ù¤òìU%w‘ÉS]ÝfC i°jgPŽniLÎbGlîtˆˆç-–UïlŸ™²Çé~2×õD´ŽÚ=._µ_‹D¼ÝŒ~âil†y¾dòѹq¼>Ü'ߩħöÖ‘s¨ÚÙØ*ßYÜ!¶‘Öâx®R=±'úÉlcL;.3B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š(  BÆ#VmÙlôªuòjV)w2G!mªÇ'ˆçò¦ßéí~cÍõåºÆ o @sÜñ“þ}éú}ŒZmŒv³´qçÈ'’Oo­q¯ãVÊÝæ¿Ž—Í·dl.XÜEŠ„ä]mæE¸'ÊÂ@ÐñlnâÖ'Q—S ë.ž¾H– ‚6f,d‘‰¡?+“ûÁÇ ¶x¼'¢Âr¶®B´m½Äްì‘dU‰KD; v( €’ëÃZ]ÜÓNñOóKæ¼Ö÷RÁ!bˆ„oF ¬qåAÁ(¤ŒŒÐH^6ÇÛþYDåšm·©é–º½‹YÞ#´,Èÿ»•£`ÈÁÔ†BÊAí@¶¾"žÚÒÛíÂ}BæçÌ™ÓL’Õã‚2ªîÑJåÎÖeàe›pÚɪšWŽ…Ö‘¥ÝM¦ÝLg[8îî-„byî"‡9¾ŒåCrH k inMÕÂ#3fâöiYƒ6grZ6Ú¹Œ’•5™qà[Iu 9Y +³ýœ={¨¬‘Çp["<¨Èebw?Ì7  <=ã­ÄÚ„–z|»¤ã>lOæÆ°ŽÍÞ_–@ótá±>¯âì}Oµž?ô ín&¸¸ Ÿ#ËhT;ñïNノ †"þ›£Ùéh²¤rc5Ä`g 3Fqµc‹eo&¡ óG›˜b’ß'„r…†:rcOËÜÐ3á¿ÿmØÙÓoZs·Û&‚ÜE$ÐÇ*ã,X©ó@à1\eö®éè^&³ñÅô6±º6 þd‘ä°åËÆ~SòȨæ2ôOÐíšßN·òbm™]ìßr4‰~ñ=4†z’j=;A°Ó.âµI1]‚K»É®YHS+1PH\Œí\çtQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­Œ» ,̲ØZK#ÜO¹ä…XœJî*Çöv›ÿ@«ü_ð£Oÿpÿ¯‹ýÕb¤eìí7þVø¿áGöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«Ȭv2]\Ât¹5Jk»‡Ž›ÊýÌe7¶âBäÝrUw:€tßÙÚoý¬?ðÂìí7þVø¿áUì4jzuµý·™kuM ïnF©Á9u«ðŠhŸóåÿ‘_ühþÎÓèaÿ€ëþgi¿ô °ÿÀuÿ ?áÑ?çËÿ"¿øÒE¤Øé—$Ú[ˆË''qc×Üš_ìí7þVø¿áGöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«P ¦é¬ÀeØrqÿëþ!Ò´H:}†Gý:­KúÄúŠ$ÿXÿS@ÿeéóáaÿ€«Gö^‘ÿ>ø ´Ë믰é÷7~D÷DM'“n›ä“h'j¯v8ÀÍ`é¾/·¸Óå»»k&eFúMÑÔg ’Š™ÅBp¤6OÍ´¡þËÒ?çÂÃÿVì½#þ|,?ðkøÂÀëšn WS%üJ³Gk3Ù$Hö0 òYƒn#Ë*¸V¶«¨Ã¤iºÂ»Cg—,`*ŠX’p=hì½#þ|,?ðhþËÒ?çÂÃÿV²F·sanï®Ù%£îU„YJ÷~y ¨¢5¸ X€„ç' ¶7ñž€’¬M‰ Bf_&LÅfBò ¿»UderØFnF@6¿²ôùð°ÿÀU£û/HÿŸ üZŰñUÞ£­ZKö«¥JË%ÄðÈ‘XÑÙŒŒ¡Ï9UÞ>R ã-(•繞ݞQ Ãqi4R³²³(²;¼· ó2•n(kû/HÿŸ üZ?²ôùð°ÿÀU¦Y^Ûê‰uk&øŸ8$ ƒ‚¬*À‚  ‚Ëiþ;†ëW¸´¸M:(`žæ Z€’ku…œgŒ¢ˆ£"?½¸àºâÈë?²ôùð°ÿÀU£û/HÿŸ üZŹñf‰¨ê(ga‹Ì’+›Yáu;YÆd’εºí8±âmLÔ åß—r±,î‚7m‘1aæ1…Œ;œáWÄddKû/HÿŸ üZ?²ôùð°ÿÀU¬+ÄpjºÎ­¦%µÔrióù;ÞÞUIHØåƒ™0$ ©¶¨ä’DdÓ쉖U…m–cÇøþ'öv›ÿ@«ü_ð¬ÿÌ/þÂZØ  ÿÙÚoý¬?ðÂìí7þVø¿áV(  ÿÙÚoý¬?ðÂìí7þVø¿áV(  ÿÙÚoý¬?ð³õH,­M‚ŦiãϼŠ?fRv“Î8öÇã[“®¬Ò?ì%õ ø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­Šzüƒ‡ý|\èÖ«”šØì‘Æöä™î û<Âþùºž”ŸÛÿ@]cÿúõ#5¨¬ŸíÇÿ .±ÿ€¿ýz?·þ€ºÇþÿõèZŠÉþÜúëø ÿ×£ûqÿè ¬à/ÿ^€5« ËK´¾Ží®$¸¶™/¦òç·vŽO-¶‡@í· eVYÿ·þ€ºÇþÿõèþÜúëø ÿ×  ØÊÖÞ+{uŽ"@‘ÇmTP0`8ÅIö¸?¿úç¿·þ€ºÇþÿõèþÜúëø ÿ× ‡ípô5ZiIÁC‘·­cÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯@ÔVOöãÿÐXÿÀ_þ½Ûÿ@]cÿúô­Edÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯@ÔVOöãÿÐXÿÀ_þ½Ûÿ@]cÿúô­Edÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯@ÔVOöãÿÐXÿÀ_þ½Ûÿ@]cÿúô­Edÿn?ýuüÿëÑý¸ÿôÖ?ðÿ¯@ÿ¬O¨¢Oõõ5ºë«ý‰¬psÿ¿ýzÇ’û\’WpÚ²bv®’¸Ã-šêg…n-äË„‘J1Ù1Ã)O¸ ŽÕÍ_xÃU·j——W÷LѲÝ\Ç2D~_”@óeûÈOÎNrl?k×禱ÿ‚”ÿâ¨û^»ÿ=5ü§ÿ@?ð‰ØÇiaok,ö_c‰àf$nTʤ*…]ìŠÅ+>R¹5¯}eo©i÷67qù–×142¦HÜŒ##‘Á=+—û^»ÿ=5ü§ÿGÚõßùé¬à¥?øªµà»]_O6Ú¶£{¨H%Ycšé`(¨`1—äžÆY ;‡?*m‘<¥Å¦_XE¾(otåÓ¥¤qƒÍ%ÕU«“3“ŒãÞÚõßùé¬à¥?øª>×®ÿÏMcÿ)ÿÅP­×†,¯.¯žynµú°º³YvÅ+4b"ç|ù`.7mà6ÝÃuTÒ<¥hÍlöÿë`ºûH‘-­à.|§ˆ+£@T \Ž3“×U_µë¿óÓXÿÁJñT}¯]ÿžšÇþ SÿŠ ¾³#Ь—F¼ÒdWšÎñ®ZevÁa;»ºåp@ÌŒ9çšÃû^»ÿ=5ü§ÿGÚõßùé¬à¥?øª½?„£»Ó5KK½[QžmJµžñ¼‘/’7b00€~òNvîùÏ<.'ºðÕµí¾¥ÍÕÔ¯¨éɧ\JJ(¢_œa@|æ'ŒtÀ•ö½wþzkø)Oþ*µë¿óÓXÿÁJñT¹‹ Z̺Œw7Iç7›%²ÈO.Á˜xÜNÅUÚNÎmÜ7Vrk×禱ÿ‚”ÿâ¨û^»ÿ=5ü§ÿ@þ ÿ˜_ý„"þµ±\k6§<ÖÍvšÄñÁ2Ìû1W%O¨o­nn?ýuüÿëе“ý¸ÿôÖ?ðÿ¯GöãÿÐXÿÀ_þ½kQY?Ûÿ@]cÿúôn?ýuüÿëеdëŸë4û CýhþÜúëø ÿת—wsêWZdqéZ”^]ìR³ÍnUBƒÏ?YñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€*ZjºuýÅͽý­ÌÖ­²â8fWh[$aÀ9Sx>‡Ò­×˜ê:ö›¤,Vq]X¥»ZYZ´óÀL®­Ñc¶•¹„¨!ŒÊY€*~qSê:OŠä³ˆY®¢–y,^ìÉw”Œ.ùê2Ãx¸?뛉m8X£Õ 7\ÒuŸ7û/T²¾ò±æ}–á%Ùœã;IÆp#\ô:n»³Û$Ôo¦FƒËÔ!º[{a¢ Dn »0˜ñ¬@0 TÓ|)ªiþÓ·]ÞÏ«[XAl`i"CYˆÜAÆæej³1 …!×– Þiá·@óÊ‘!e@ÎÁAf!Tsܒɤ®{=v-M½–®Îšµ¼ö¶§PSq²˜Ì«,6$ ‰°¥ß‰q’ÝÆ•­[QÔ"¹½,5KSgÚ€…m¶Û­ÁÙœ7œ¹c–êaž„/©*d,ŒRU‡ÁØ‚(3· nÒ ™Õ#,72©ˆH—'¶áë\ׄ´kkë&µºòZyæûT÷ï2HgxÄhÌÄ®C±KyÂÇŠtíVqm{ ²G©Â³[¬ŽG˱‘œ0# *Á!ã;c`3¬»ðÝ[Çqo*K ª9#`ÊêFApAèžxmm丸•"†%/$’0UE$’xõÄ/‡õë?ZCc<öú%·’–¦2Ï6ñÆ¡¢pnb®7d :ùeï[ë>d·¶z¤—1ÚŸµ´·é$w·5¼läF¤‡ÀýÈÔ?òÌ©‚xn­ã¸·•%†U‘°eu# ‚8 Žõ%yÄúGŠƒ|1gmou³³÷¶‘J¦UTTpÑÜ adÿ–‡ï®PžSNÄpMqu6§{wwýšÀ|á/Ët¹“Êo͉ÎÖÎÒ2€–í(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ÏÖîf³Ò'žÙ"íÃ`e€ïZ•âOù\ÿÀ?ô!@ Ž;‰uI´ÈüO^B›Þ!h¹Œ÷Á 2 :€ë“R†ÿJ·Yî5›·Fp€Zé-pÙÁ<¬aˆuÆ:zŠ–×ÃSAª[–¸Œéöw·°ù¦iüÝêç¦Åó¥#È<²d"o_x~q{§é¶÷íq4gŽúUY-òʤL‹º'Á ¸)g Ÿ éRÓSî uQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@G<\Äb™ÆH%OCƒ‘úŠ’ŠnÅô£búS¨ ì_J6/¥:Š`QEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEhj:ÂÚÜ,+cpU^ (>™ã?…gø+þD}þ¼bÿÐEnן/‰+cþú„jßø ÿ×£þú„jßø ÿ×­Š*FcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úõ±ErúÖ¥.¥¤Oi“©¬’mÁ{r cí[ÚŸü‚¯?ëƒÿè&­U]OþAWŸõÁÿôBä*(¢½#”ú«Á_ò#èõãþ‚+v°¼ÿ">‡ÿ^1è"·kÏ—ÄΕ°QE# (¢€ (¢€ –&+„**‘?ÔËø:<ù?½ú <ù?½ú ޹o[j—ú¾›gib—–F ‰gI®¤¶eVˆDÞdhÇxÜåGãæE ­óäþ÷è(óäþ÷è+Ì|?®ø®òâ4»’õ®c–Æ3nlbmööïuç8FA#ºƒåüÇÉ÷ß„umWWÒ-çÖÅÕõΓçj 6œaŠ¦Åˆ >p’3#0ùmŒŸ.€=Ï“ûß £Ï“ûß ®Ã÷z­—‡|)µ«ÈãIò&Óçż¢d¨‘„€0ub¡ï…|Šè¼-{q©xCE¾»“̹¹°‚i_nvI8Ié@^|ŸÞýdx~ækÍ ‹‰I¤.Y›¿ÎÕ§Xþÿ‘nÓþÿ¡µlQEQEQEQEQEQEQEQET±1X¤ àñQT‰þ¦_ÃùÐçÉýïÐQçÉýïÐTuÇøÞ×M¸Ô<8ú–ŽúŒ0ÞJòíÓ^ì$F ä*6ÅÇrþ€ÓÏ“ûß £Ï“ûß ¯<Ò®­q¢yº»ï‘¥o%]e1ð?x~mÛñˆÔmÛ×’w¨6Òîâã_Õb–Vháˆ×²åI?™þž•¥XúwüŒšßý°ÿÐ lPEPEPEPUu?ù^×ÿÐMZªºŸü‚¯?ëƒÿè&„ÈTQEzG)õW‚¿äGÐÿëÆ/ýVípþñ‡ô¿ éš}þ­omymlϤ«Æê0ÊÀô ‚1Z¿ðŸxSþƒÖ_÷ò¸%w¡Ðš±ÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþRå—aÝÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÔw7ÖÚ}Œ³ÝL±G•\žrsÐɬøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚è·ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþSþï ÐzËþþQÿ ÷…?è=eÿ)r˰]Çâ='•ã¸Dy›|Œ°0.Ø “òòpª2{;Qˆô [xííî(bP‘Ç ªŠ.µAÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰] ¨ê¾ÕíÖßS[[ØU·¬w6†E ‚2)Á<ûš¹ÿ V‹ÿ?¿ù ÿªÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìE¿øJ´_ùýÿÈOþxWþE»Oøþ†ÕSþï ÐzËþþQÿ ÷…?è=eÿ(å—`º::+œÿ„ûŸô²ÿ¿”Â}áOúYßÊ|²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]Gs}m§ØË=ÔËyUÉç'=šÀÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.‹ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáU?á>ð§ý¬¿ïåðŸxSþƒÖ_÷ò—,»Ñoþ­þòÿ…ð•h¿óûÿŸü*§ü'Þÿ õ—ýü£þï ÐzËþþQË.Át[ÿ„«EÿŸßü„ÿáGü%Z/üþÿä'ÿ ©ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]hwPÞëzÅÅ»ï‰ü­‚3…#¿Ò·ëœÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.ŽŽŠç?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŸ,»ÑÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]UÔÿäyÿ\ÿA5ÿ ÷…?è=eÿ*½ÿ޼-.sk¶Líª'RA¡Eö £æ:+gþÿн«àŸüMßÌŽ{3ÿÙnetgen-6.2.1905/doc/pictures/viewingoptions_1.jpg0000644000175000017500000004444113504650527020421 0ustar kurtkurtÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ0¡"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…nøRÓMºñ­¦©›kpƾT«7 FïøÖœ¶Ó,t«mNÕ$Õ5lYÆ\°U†7 #mdÇѸ"³HEÙ¢”[ØãüäÿŸ üü(ó“þ|,?ð?ð®ÎÓÀ²jwÚœ‚G‚Ú=R[E½³M¬Fâ3ò õ$Õh<ÓO¶¨‘57Óî€"Š\Éœò»Tž‚’«H|’9_9?çÂÃÿcÿ <äÿŸ üü+¬ÿ„N-;P´[Ë…7ZM:(LG'ÌÈnp=zÒ?†tßø˜ÞÞêɧ[E­Ë¦F‹jò ŽF0IüaÖkH9$ržrÏ…‡þÇþyÉÿ>ø øWM/„á±›\mOSK[M"DŽIÖ!v|lAÏ9ôÍgkz'ö?ˆ¦ÑÖaq$B?œ.ÐÛÔÆ}ê”é·d'-Y•ç'üøXà,áGœŸóáaÿ€±ÿ…tú„ ³UŠU.5 &$–öØBʨ¤v¹á°Ï¦Õ¼i§¾µoo¬­Íî“ ÜOnmš?Ý ;²F@=j}­!òHä¼äÿŸ üü(ó“þ|,?ð?ð®ÏSÑt}g¶¶r;I¨EjòBð¶ÙUÛBÛþ\ôØ1õª’øfÍn/îoõôûOíy4ëP4›Ü1휪€:’ÄUi‡$Ž_ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ êÛÁÖ–VÓˬk)cäêÙÇí(f(HÁîp8ïÚŸmàW›RÖ­$»cý–èŽ- 3K&á•*€Ž0yçó£ÚÒIœŸóáaÿ€±ÿ…rÏ…‡þÇþbêÙ ¾¸·FvÈSt‘ØãÕ[•>Æ£ò…j”Zº#R?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ #ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…P¢ÈüäÿŸ üü(ó“þ|,?ð?ð©<¡G”(²?9?çÂÃÿcÿ <äÿŸ üü*O(Qå ,€ÎOùð°ÿÀXÿÂ9?çÂÃÿcÿ “ÊyB‹ ¤Eqa¦€Ã#6ÉŸýå?üøiŸø ŸüM^·‹ý.?€*—Êö©Ðf:±iŒCOÓ÷޹¶L/qRùOÿ>gþ'ÿSÇüLåãø¢ÕHô¹/Y›P¾÷®¡#1{Rm-Ò@Ñ.æÓôâ3ƒ‹dãÿ¥Ei\Xi 0ÈͲgÿA§ÅdaÝä+!]îrN$Ç?•Iq %]n>ÎcEq!è0:j.­{µ"òŸþ|4ÏüOþ&¡iš7;-m`š6e‚GF†VGF“s>§rÒLM¹‰F-†Al¾r:zT·QâyÏùû¢ˆµ%°4Ñü-_ÿÐkÿ%aÿâ(®6ŠÃ’=Šæ}ÎîÕ ÓíH>D}Ýñn73n~+Ô|)á÷Â:=ÍÅŽù¤³‰¼×;G`Õ£sá_ YíûTÁ¿;|Û§\ã®2Þôž& ê¶)S•"òá[T-Âʧ™`ô#×úÓ|¯a^±ý…àïÙàqÿâèþÂðG÷ì¿ð8ÿñt£‰§`éÉîy?•ì(ò½…zÇö‚?¿eÿÇÿ‹£û Áß²ÿÀãÿÅÕ}nƒÙ3Éü¯aG•ì+Ö?°¼ýû/ü?ü]Ø^þý—þþ.­Ã°{&y?•ì(ò½…zý·…|%y»ì°C>Ìnò®±ž™Ã{T§Á^Àÿ]äÿâ¨úÜ;²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}n…ì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅRøpŒ?#þ»ÉÿÅQõ¸v²gy^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}n…ì™ãЬޮ‡k)È#¨5§¨ø‹WÕüIc­^ý“ΰ öx£Fä6ì°,NIÆpGW¨Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU/NNí S’êyRëZ‰Šö;›]2ú»Ç½k{¸ãŽV'%0Àޏêi¶š¾©§éºµ¢ÙBš "`‘X(òðÄwí^¯ÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅT{j=‡Ë>ç–\kšµÝî‰qpm˜hÊ¿fça·æ“žOȽ1P\jz•ݤ–Ò‹Qº«j®Q5G?wž}ëÖ¿á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª~Ú—`ä—sÏ,|I›íjï\HäThÞKx¬Äñî@;YÁ`ryíÒ²uMµïêÂ[Émå(øÞT('qž:W­xpô°é<ŸüU!ðW†ÁÁ°ÿ×y?øªQ­J2æIÂMXòÝOÄƧmwo °‹íª‰wu g¸UÆ6qØt­xŸÅ7:Þ£¬E¦[[ÚX_yi-ÃA¶ædU«6â6䃥zGü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿKÚѽì³îykkš‰}%¾Ï§³éf?"v‰¼Ò¨r¨Ä6 çØz[jÐ’ði·B{æ¿\À]!™‰;“æuîOó¯Qÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿ⪽µ.Âä—sÉgÕ5[»ku,3yš—öœ²”!Ú]»p0p±øÕ“¯ê-«Þê²Xé3]ÝL²æH_•P£i pA$W©øp ?þ»ÉÿÅRÂá¯ùñ_ûÿ'ÿKÛQì“îxìÒ^_^Üß_Ì&º¹“Ì‘€ÀÏ €S|¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅV‹¬½œò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ©ýn…ì™ã~W°£Êöì£Á>##OÈÿ®òñTŸð…økþ|WþÿÉÿÅQõ¸v²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}n…ì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡`öLñ¿+ØQå{ öQ௖ý'“ÿŠ¥ÿ„#ÿôÿÈÒñT}n‡ì™ã>W°£Êöìßð„xwþßùOþ*øB<;ÿ@ïü'ÿGÖáØ=“•Ë[_ÚEâ1f·–Ê©u!0Ës¢»nÿUÞ‰K7!¸œ üµhÙßZÁc"ÙI;Aª\Üõœú¥ÄlŠ÷Ò«HÛPˆ,pN<œ~€Ô:Wü‹·ßö“ÿ@‰â;´°þ˽“iŽ ÂÌ ÑÆH0ʼA9aÆsŒÐBú¥ÄlŠ÷Ò«HÛPˆ,pN<œ~€Ñ.©q O,·ÒÇ)gw˜€ u$ç\ÈÔV›H¾Ó£žX’áÖäCu,jPŒ8Y ±ÉFÜ@¡88zÂ^^ÞÜØÚÜý¦â_µ#Æ·²+„0Ê^Ü€ˆ ˜À|üß+0= MRâ% %ô¨¥‚‚Ó2HuêI{šwÛï?çîûøk’ÔtK¹ÒâÜKw=ºµµÊº*òJ²1”ÚJ„Âü¨‚6ã#zËÌQ "h˜.<¾cÛswlc<žsÉêPÚ_ˆïžþ{òÚ8¬Zà9q`ØœôÇãïYój·1¤“Í}$q¨.îe*ª:“èA¥ÈÅ}ÿ`™?ô1YÞ ¥ðÞ©• ör¨.ÁFJ¤ð¹â˜ìüBšŽÿ±k såã‘s¿nzgއò«ê—©hï¥u T•˜‘H#¯PAÜWmªVßìÖ×Ww¢Yâ–¢ybÚFÀãh°’Jñ‘“œVmüZŽŸ¤=½ÅÖËæK‡†·<did`Ñ˜Ô Ù·'ÉŒüP3Ò~ßyÿ?sÿßÃGÛï?çîûøkŠË\]fîig¹5”ô‰çËE.Õa•äļ¡ËIkþ†þ Y£½ŠDùò†iœñÏYp8ùûŸ”c,„u¾!¿²¼±]e[›Èás.Xª±ÁÁÏø× W•?ü…toûÁÿ¡WªÓCAESQEQEQEU]OþAWŸõÁÿôVª®§ÿ «Ïúàÿú ¡òQ^‘Ê}Uà¯ùô?úñ‹ÿA¯ilö–Â9 ’ÒK'Ëèò3Ñ…dx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEekÚLúÄQÁ$H`½‚匬@*Œ óéY—>½šîiVæÌ+»0˶pOÒºŠ(’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¥aXä¿á ¿ÿŸ«/ûøßüM^ ¿¶Õn.žêȤ¶-n‘³¸°9û½+­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹Ž6Oêwc(º²ÛouÏûÆÉU<ãåëV®|%{5Üҭ͘Wva—làŸ¥uQ`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉYx6þÛJ¸µ{«"òß5À"FÆÒ cîõ£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E •—ƒoíµ[‹§º²)-‹[€$lî,~ïJ?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±Ç7‚µ{§Íö«-¶÷qÎãÌl•S“—­v¾Oý4þú¨è¦2O'þšGÿ}QäÿÓHÿïªŽŠ“Éÿ¦‘ÿßTy?ôÒ?û꣢€$òé¤÷ÕOý4þú¨è  <ŸúiýõG“ÿM#ÿ¾ª:(.^Ky.'¸‰"Œe˜·J­©ÿÈ*óþ¸?þ‚jŠ¿ä[»ÿ€èkWµ?ù^×ÿÐM p>B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà¯>_:VÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š+Ÿ‡PÖïn®RÑtñW/óCäàõàûŠÊµzt#ÍQÙmócI½Ž‚ŠÌñýÆ‹á}WQ‹Ê’æÊÊi×rŒè…†FsŒŽ™ükž¾ñÃÃâhl¬ ûe£J†34˜½WUÉbKDŽÄœ|ÃQ¥‚¾$IæÑDN±ßÝMm!xÔùRD’‰ˆq† ÊNÂ?‰Z ³ñL¿mñ'ö–Ÿ=¦Ÿ¤JÙ¼; ùk r…vrÇ{0ÂãnÃdPKE`øoźoŠ>Ò¶Gl¶Û ±ùÐÍ…lí;¡wNv·²1È‚s|]âMS@ÕíÔÚµ¬–sÜ´RZHìÍGò™UÂÂŒ$ǘëµ6å²aEsWÞ:Ñ´ÍrçJ¿—È’šV“ÍŠL…ˆÊß»G2Œ c–@8'+˜ï¼`4ùtÓ¨Ú> מEÃêmªÆ`™Õ–Dv%â ‚Ùä ÊHSEsZ‡ŒàÓí'¸þÈÕ'[kS{rˆ‘£Á_k²Èê~a£,1†URXŒFÄ0]§…Îÿ’€:+ßÅ0I¨Ûé·Z}í•ôò¬kþ[­®®J;.ÓäJ:ç+ȃUÇšrMv‚ËQt²W–êU‰vCM4O!;º£.ATá‚€u4W5'ŠüÍsL°´´ŸÈ¹¿šÑ®¤÷ryQLdAʲÉ_œ ÃqPÀn-QEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@VMο µôÖ‚Îöy!Û¼Ã`22;ÔÊq‚擲Z¢²¶†ÄKåF¥¥•¦vnIf9ü;– hF†HK ùr€}@'…¥xÂÏQ›Ê¸´ºÓšD‹í­´s\)Ga‘#"àãqa·w8%ÉZJàm_ÙÁ©ØÝY]Çæ[]FñL™#r0!†G#‚zU|1¢[ê1êúl\ÇåíhA@<¸ä>QÂJê8è@þÃäñ‡™§&³§%„Ͳ;¦ºA·<Î ù[€{J¸×Ö‰ænº|©V3 $m»Pú1Þ˜Náê*€ þÒä–ÎO*uk;©o ÝJ€K#3;Éwá²0Ì1‚E>éWWÒ^\Y$²J¥dI hß+°±Œ…Ê|›ñ»o˼UOQ‡K±k©•ÜHÒ8À-$ŽÁHfe$žH5Sþ+}?íz»c(—É+©H‘añ¸ÛŠ6WŸ•qÔ-éÚl]»Ao%Ó£6ònn¥¸làFb3޾¦ªj^Òõ}B+Ûè§–Xâ0…R¬m ²4jÁ[p`CȭɪéÑjqi’_Ú¥ü˾;V™D®¼ò9#ån@ì}*8µÍ&x®%‡T²’;h–iÙ.ˆ£eޮĕJüÀžæ€*Ká={ïµÍjòÒ?÷}άŽ|‚Þ^X;äíä»É&¤µðÖ—i43¤SÉ<2ù©5ÅÔ³È# Ý‹ $˜Rp ±'5x§K”HÑÎŒ‚ò(Üͬï,qȦ2X%“µ°¾u]9o’ůíEã³"[™—ÌfUÀ.rHVV#°`zçußÚkØ(²]=bxD76Bw·V'&ÙË `à}å]‘íP¢‹K²ŠÆk¶Fµ¥yb“çW2³<™ œ‚]¸éÎ:U ÿhz~™ªß6¥k2iJMÜpNŒñ°ÈFxrAP2x©äñ‡™§&³§%„Ͳ;¦ºA·<Î ù[€{J€xSHïŽéÝ™_í^Ì× T6Ì_ÌP8À`0ïýæÉoá- ÖÆòÆßOHmo ki¢ÙTÄÍ#•”fi>î1»€1µXºo‰mµŽskukg:¤–—wW*åB!‰RÅÓ áXîà/†tuÕ£Õ§ú\R´Ñ7˜ûbwVW(¹Ú»·±l¸áŽHkVdž"ÐâÓ"ÔäÖtä°™¶Gt×H"vç€ùÁ?+pcéV$Õtèµ8´É/íRþeß«L¢W^y œ‘ò· v>”nŠ©iªé×÷6öwö·3Z¶Ëˆá™]¡l‘‡åNAàúJ·@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPTmtÕS¿¼šBEÉj èqÉ>ùü½ø½Ee^…:ôÝ:ªñ}›Nè|¬Báõ®|?šî¯©ZÝ¢ÎòªGbQe¼Žêduip& £¦9 ]Å5ÝcFw`¨£,Ìpõ5¨Œ=Ãóê‘§ßgÈÒù³(™¶… Æ"rÀ(çÆ:©Â•ÉÓþý‚+(¯;[AöWš!Ñ,,7\maÆA 4Ã'x)Ô¦©§Èê‰}jÎÇ «2’O æGUÓ´‹u¸Ôïíl¡fز\̱©l€XœDZ õ7ûWN6Â_&E–)âr»‚É‹"n]È2Œ€GQ›&‰¬½Å¶¢5›SªÂ²Å¾KmÄRÉUŒH‡&Fä¿b¡w`ž«xî-åIa•CÇ$l]HÈ Ž#½I@•§‚~Á6º‡üJV[IäŠXwNÒ[¬K$ )ûÈÛbßÁ¶–¾ÓthL >"¥·÷‘É¥Šƒ¯$JΡo\àŽ–ª]êºu…ŵ½åý­´×M²Þ9¦Ti› a9c’8£Ö€9¯øC/bÓ/`·Õ­Ræ÷V‹U–VÓþ@éå1PŠëÁ’ rI8$Íó›óxRn5;…™kýFÎõäÁmÌ%c'9#0¶o0ð{ô5•õ¦¥h—v7P][I“A tl0àòü(’OÏ6¡.¥­Ïw͉݅_Þyf(Y²òÚÆÒ?.ÚÚ%†$É;Q@dòx­s?ð‡\M¡Á¡^jPO¤Úýš8-Íùâ†XÜ,ıÞÅc •¿3§€½m‹¨èsI©ÅªiSÚÙߢÉ5©•%Y<½Å•] ÜÆnà0xÆe‡ƒgÓ5²Õ<‹H¡ˆEH²Ì±Æ¨ „Kä» 0çn ª°ëh {Þ¼Ñn'yõ$–P±ÚÛÇ,pÇÏRIdà,{A ·¡¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇñWü‹wðý jö§ÿ «Ïúàÿú ª>*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA4-Àù Š(¯Hå>ªðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¼ù|Lé[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ ©ª#I¤Þ¢)gh*¨É'iàUº(Ž£Áck’[Ú¥ÊÀ²ªï ·‘ø÷¬ÿEy6XéóÞÊ·ö“4p¼jBE:JÇ.Ê:!ž¤vÉÔV|©¨j–ÖÉkÙ+Á˜ßθ+¿ï‘"hU·G9Ýæ`oÄ~Ôït=n;}kQº{«;˜á°u¶X‹c [ÝÜø™lK&ßu=¼šr!ûU¤q‡Ûq!ÜsìL|Š?~Ÿ1ãw[EQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜçËâgJØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEâ¯ùîÿàúÕíOþAWŸõÁÿôT|Uÿ"ÝßüÿCZ½©ÿÈ*óþ¸?þ‚h[òQ^‘Ê}Uà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷yòø™Ò¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcø«þE»¿øþ†µ{SÿUçýpýÕÈ·wÿÿÐÖ¯jò ¼ÿ®ÿ šà|…EW¤rŸUx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁ^|¾&t­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@þ*ÿ‘nïþÿ¡­^Ôÿäyÿ\ÿA5GÅ_ò-ÝÿÀ?ô5«ÚŸü‚¯?ëƒÿè&…¸!QEé§Õ^ ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpWŸ/‰+b:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?Š¿ä[»ÿ€èkWµ?ù^×ÿÐMQñWü‹wðý jö§ÿ «Ïúàÿú ¡nÈTQEzG)õW‚¿äGÐÿëÆ/ýV†£¬-­Â¶7÷Peà€²ƒéž3øV‚¿äGÐÿëÆ/ýVíyòø™Ò¶1ÿá ÿ¨F­ÿ€ßýz?á ÿ¨F­ÿ€ßýzØ¢¤f?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P?ü$õÕ¿ðÿ¯Gü$õÕ¿ðÿ¯[P/­jRêZDöé:šÉ&Ü· pÀö>Õ½©ÿÈ*óþ¸?þ‚jÕUÔÿäyÿ\ÿA4 >B¢Š+Ò9Oª¼ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¼ù|Lé[QR0¢Š(¢Š(©bb±HAÁ⢩ýL¿‡ó Ï“ûß £Ï“ûß ¨ë–ñE¶©«é¶v–)yd`¸–tšêKhÖUh„MæFŒwÎTqÈÞ>dR:ß>Oï~‚>Oï~‚¼ÇÃúïŠï.#K¹/Zæ9lc6æÁV&ßon÷^s”d;¨>_Ìp ŸqmøGVÕu}"Þ}l]_YÜé>v “iÀFªlX‚ç #23_ØÉòèÐüù?½ú <ù?½ú àü?wªÙxwÂ[Z¼Ž4Ÿ"m>|[Ê&A ‰HЇV*þñWÈ®‹Â×·—„4[ë¹<Ë››&•ðçhÔ“Àäž”µçÉýïÐVG‡îf¼Ñ ¸¸‘¤šBå™»üíZuá_ùí?àúPÅQ@Q@Q@Q@Q@Q@Q@Q@KŠBHŸêeü?|ŸÞý|ŸÞýG\ítÛCéhï¨Ã ä¯.Ý5îÂD`‘NB£` \w áÈí<ù?½ú <ù?½ú óÍ*ãŃK³½“Qû|Kg¶6â[yâòâËq´âE&|1rcO•·|ñ­÷­|=c9iï/¯4µ¸¹W´}’Ex ŒDž\“1Vñü©ŒÆ@=Ï“ûß £Ï“ûß ®wÂ3ê×'›«¾ùVòYÕÖS÷¡‡æÝ¿Fݽy'z€3m.î.5ýV)efŽ{.T“ùŸééZU§ÈÉ­ÿÛýÖÅQEQEQEWSÿUçýpýÕª«©ÿÈ*óþ¸?þ‚h@|…EW¤rŸUx+þD}þ¼bÿÐEn×áŸøKð¾™§ßêÖö×–ÖÉ ðJJ¼n£ ¬B#«ÿ ÷…?è=eÿ+‚Qwz «ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå.YvÑÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]Gs}m§ØË=ÔËyUÉç'=šÀÿ„ûŸô²ÿ¿”Â}áOúYßÊ9eØ.‹ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáU?á>ð§ý¬¿ïåðŸxSþƒÖ_÷ò—,»Ñ<~#Ð"y^;„G™·ÈË퀹?/' £'°µx@µ·ŽÞÞá"†% qÀʨ `à;TðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÐšŽ«áM^Ýmõ5µ½…[zÇshdPØ# 2‘œϹ«Ÿð•h¿óûÿŸü*§ü'Þÿ õ—ýü£þï ÐzËþþQË.Át[ÿ„«EÿŸßü„ÿáG…ä[´ÿÿèmU?á>ð§ý¬¿ïåðŸxSþƒÖ_÷òŽYv ££¢¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü§Ë.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÑ\çü'Þÿ õ—ýü£þï ÐzËþþQË.ÁtttW9ÿ ÷…?è=eÿ(ÿ„ûŸô²ÿ¿”r˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÔw7ÖÚ}Œ³ÝL±G•\žrsÐɬøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚è·ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþSþï ÐzËþþQÿ ÷…?è=eÿ)r˰]ÿá*Ñç÷ÿ!?øQÿ V‹ÿ?¿ù ÿªÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìE¿øJ´_ùýÿÈOþÂU¢ÿÏïþBðªŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»Ñ&‡u î·¬\[¾øŸÉÚØ#8R;ý+~¹ÏøO¼)ÿAë/ûùGü'Þÿ õ—ýü£–]‚èèè®sþï ÐzËþþQÿ ÷…?è=eÿ)ò˰]ÎÂ}áOúYßÊ?á>ð§ý¬¿ïå²ìGGEsŸðŸxSþƒÖ_÷òøO¼)ÿAë/ûùG,»ÑÑÕ]OþAWŸõÁÿôXßðŸxSþƒÖ_÷ò«ßøëÂÒé×1¦»dÎÑ:¨u$_`º>c¢¶áñ/ý Ú·þIÿÄÑ]üÈç³?ÿÙnetgen-6.2.1905/doc/ng4.tex0000644000175000017500000010742113504650527013765 0ustar kurtkurt% % Requires latex and latex2html packages % % Generate pdf-file with % pdflatex ng4.tex % % Generate html docu with % latex2html ng4.tex % \documentclass[12pt]{book} \usepackage{a4, epsf, graphicx} \usepackage{html} \title{NETGEN - 4.X} \author{Joachim Sch\"oberl} \unitlength=1cm \begin{document} \maketitle \tableofcontents \chapter{Getting Started} WARNING: DOCUMENTATION IS NOT UP TO DATE \section{What is NETGEN} NETGEN is an automatic mesh generation tool for two and three dimensions. Netgen is open source under the conditions of the LGPL. It comes as stand alone programme with graphical user interface, or as C++ library to be linked into an other application. Netgen is available for Unix/Linux and Windows 98/NT. Netgen generates triangular or quadrilateral meshes in 2D, and tetrahedral meshes in 3D. The input for 2D is described by spline curves, and the input for 3D problems is either defined by constructive solid geometries (CSG), see Chapter \ref{chap_csg}, or by the standard STL file format. NETGEN contains modules for mesh optimization and hierarchical mesh refinement. Curved elements are supported of arbitrary order. \section{The history of NETGEN} % The NETGEN project was started 1994 in the master's programme of Joachim Sch\"oberl, under supervision of Prof. Ulrich Langer, at the Department of Computational Mathematics and Optimization, University Linz, Austria. Its further development was supported by the Austrian science Fund ``Fonds zur F\"orderung der wissenschaftlichen Forschung'' (http://www.fwf.ac.at) under projects P 10643-TEC and SFB 1306. Starting from 2002, the development continued within the Start project ``hp-FEM'' (http://www.hpfem.jku.at) granted by the FWF. In 2006, the Netgen development moved together with J.~Sch\"oberl to RWTH Aachen University, Germany (http://www.mathcces.rwth-aachen.de/netgen). \section{How to receive NETGEN} % The latest NETGEN source code release is available from sourceforge \begin{center} http://sourceforge.net/projects/netgen-mesher \end{center} There are file releases, as well as a public SVN repository containing the latest sources. The latest NETGEN Windows executable is available from \begin{center} http://www.mathcces.rwth-aachen.de/netgen \end{center} \section{Installing NETGEN} THIS SECTION NEEDS UPDATE INFORMATION AVAILABLE AT http://netgen-mesher.wiki.sourceforge.net/ \subsection{Installing NETGEN for Unix/Linux} To install NETGEN on Unix/Linux you will download the source code and compile it yourself. You need the following libraries: \begin{itemize} \item The 3D visualization library {\bf OpenGL}. It comes with most systems with hardware graphics. The free software version mesagl is available from \htmladdnormallink{http://www.mesa3d.org}{http://www.mesa3d.org/}. \item The graphical toolkit {\bf TclTk} developed by John Ousterhout (available from \htmladdnormallink{http://www.scriptics.com/}{http://www.scriptics.com/}) and its extension {\bf Tix} available from \htmladdnormallink{http://www.sourceforge.com}{http://www.sourceforge.com/}) by Iam Lan. Netgen has been tested with version TclTk 8.0 - TclTk 8.4 and Tix 4.6. - Tix 8.2 \end{itemize} You can also download these packages from the Netgen site. To install NETGEN please move into the directory ng4. You set the Unix-variable MACHINE according to your machine/operating system, e.g. \begin{quote} \tt setenv MACHINE LINUX \end{quote} % (in bash shell you type {\tt export MACHINE=LINUX}). The Makefile includes the makefile-include \begin{quote} \tt libsrc/makefile.mach.\$(MACHINE) %$ \end{quote} Please create/modify the according file, (e.g. copy makefile.mach.LINUX to makefile.mach.SUN). Then you enter {\bf \tt make} to build the executable. \medskip To make NETGEN globally available you just copy the binary ``ng'' to the global bin - directory. In difference to earlier versions, it needs no additional files. \subsection{Installing NETGEN for Windows} NETGEN is available now for Windows in binary form. You download the zip - archive {\tt ng4win.zip}. After unpacking it with winzip, you can start the executable ``ng4.exe''. \subsection{Adding IGES/STEP file support via OpenCascade} \label{subsec_occ} NETGEN is capable of importing IGES and STEP geometry files. If you want to use this functionality you have the add the OpenCascade library to your NETGEN distribution. OpenCascade is an open source 3D solid modeller library by OpenCASCADE S.A. You can obtain it from \htmladdnormallink{http://www.opencascade.org}{http://www.opencascade.org/} (Linux and Windows). To compile NETGEN with OpenCascade for Windows just choose the project settings ``Release (OCC)'' and adjust the proper search paths. For Linux adjust the directory search paths OCC\_DIR, OCCINC\_DIR and OCCLIB\_DIR in the Makefile and in libsrc/makefile.inc. Then add -DOCCGEOMETRY to the CPLUSPLUSFLAGS2 in libsrc/makefile.mach.\$(MACHINE). If you use OpenCascade version 5.2 also add -DOCC52 and -DHAVE\_IOSTREAM to the CPLUSPLUSFLAGS2. \subsection{Testing Netgen} Please start Netgen by entering ``ng'' or clicking the ``ng.exe'' icon. A white window with menu items should appear. Please load a geometry file by selecting "File {\tt ->} Load Geometry", choose e.g. tutorials/cube.geo. Then press the button "Generate Mesh". By keeping pressed the left, middle or right button of your mouse you can rotate, move or zoom the object. With ``File {\tt->} Export Mesh'' you can save the mesh file. \chapter{Constructive Solid Geometry (CSG)} \label{chap_csg} % The CSG input format is a useful geometry format for small and medium size geometries. One defines the geometry by writing an ASCII file in a text editor. The geometry is defined by the Eulerian operations (union, intersection and complement) from primitives. A complete list of available primitives is given in Section~\ref{sec_primitives}. The following input describes a cube: \begin{quote} \begin{verbatim} # A cube algebraic3d solid cube = orthobrick (0, 0, 0; 1, 1, 1); tlo cube; \end{verbatim} \end{quote} Lines starting with $\#$ are comment lines. Every CSG file must contain the keyword {\tt algebraic3d} before any non-comment line. The keyword {\tt solid} defines a named solid, here the solid {\it cube} is defined. A solid is defined by the Eulerian operations applied to primitives. Here, the solid is just the primitve defined by {\tt orthobrick}. This is a brick parallel to the axis, specified by the minimal $x$, $y$, and $z$ coordinates, and the maximal $x$, $y$, and $z$ coordinates. The present definition gives the cube $[0,1]^3$. Finally, the definition {\tt tlo cube} declares the solid {\it cube} as a top-level-object, what is necessary for meshing. Please start netgen with the geometry file above by entering \begin{quote} ng cube.geo \end{quote} Instead, you can also load the geometry from the file menu. You will see a blue cube, which you can rotate by keeping the left mouse button pressed. Pressing the big {\bf generate mesh} button will result in a (very coarse) mesh of that cube. Instead of using the primitive {\tt orthobrick}, one can also specify a cube by intersecting six halfspaces (called planes). Each primitive {\tt plane} is given by an arbitrary point in the plane, and a outward vector, not necessarily a unit vector. The six halfspaces are intersected by the keyword {\tt and}. The following input gives an equivalent result: \begin{quote} \begin{verbatim} # A cube algebraic3d solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); tlo cube; \end{verbatim} \end{quote} To drill a hole though the cube, we will intersect the cube and the complement of a cylinder. A cylinder is defined by two points on the central axis, and the radius. Please note, a cylinder is understood as an infinitely long cylinder (although the visualization may suggest a finite cylinder): \begin{quote} \begin{verbatim} # cube with hole algebraic3d solid cubehole = orthobrick (0, 0, 0; 1, 1, 1) and not cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.1); tlo cubehole; \end{verbatim} \end{quote} Like {\tt and} denotes the intersection, {\tt or} denotes the union: \begin{quote} \begin{verbatim} solid cubeball = orthobrick (0, 0, 0; 1, 1, 1) or sphere (0, 0, 0; 0.5) -maxh=0.2; \end{verbatim} \end{quote} The flag {\tt -maxh=0.2} assigns the maximal mesh size of $0.2$ to the solid. The current version, NG4.1, uses the mesh size assigned to the main solid of the top-level-object for the domain. Future version will contain more possibilities to define mesh-sizes for parts of a domain. It is possible to define geometries with several sub-domains, simply by declaring several tlos: \begin{quote} \begin{verbatim} algebraic3d solid cube = orthobrick (0, 0, 0; 1, 1, 1); solid cyl = cylinder (0.5, 0.5, 0; 0.5, 0.5, 1; 0.1); solid dom1 = cube and not cyl; solid dom2 = cube and cyl; tlo dom1 -col=[0,0,1] -transparent; tlo dom2 -col=[1,0,0]; \end{verbatim} \end{quote} This example show also solid trees involving previously defined named solids. Top-level-objects can be assigned a color specified by the amount of red, green and blue (RGB) values. The flag {\tt -transparent} makes the solid appear transparent. It is possible to specify bounday condition numbers for individual surfaces of a solid. The flag {\tt -bc} assigns the bc to all surfaces of that solid-tree. If several flags are given the one closest to the leaves of the tree dominates. The following file defines a cube, with $bc=1$ at the bottom, $bc=2$ at the top, and $bc=3$ for all other surfaces: \begin{quote} \begin{verbatim} algebraic3d solid bottom = plane (0, 0, 0; 0, 0, -1) -bc=1; solid top = plane (1, 1, 1; 0, 0, 1) -bc=2; solid cube = bottm and top and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0) -bc=3; tlo cube; \end{verbatim} \end{quote} \section{Curves} For the construction of some of the primitives in the following section it is necessary to define 2D or 3D curves, which are given in terms of straight lines and of quadratic rational spline patches. A line is given by the two endpoints, a spline patch by three d'Boor points. The patch is an elliptic arc from point 1 to point 3, such that the lines 1--2 and 2--3 are tangents. A 2D curve is defined as \begin{quote} \samepage \tt \begin{tabbing} aaa\=aaa\=aaa\=aaa\=aaa\=aaa\= \kill curve2d $name$ = ($np$;\\ \>\> $x_1$, $y_1$;\\ \>\> \ldots\\ \>\> $x_{np}$, $y_{np}$;\\ \>\> $ns$;\\ \>\> [ 2 | 3 ], $p_{1,1}$, $p_{1,2}$ [, $p_{1,3}$];\\ \>\> \ldots\\ \>\> [ 2 | 3 ], $p_{ns,1}$, $p_{ns,2}$ [, $p_{ns,3}$]); \end{tabbing} \end{quote} The number of points is given by $np$, the number of segments by $ns$. Each point is given by its coordinates, each segment by the number of points (2 for line segments, 3 for spline patches) and the pointnumbers. The 3D curves are given analogously by \begin{quote} \samepage \tt \begin{tabbing} aaa\=aaa\=aaa\=aaa\=aaa\=aaa\= \kill curve3d $name$ = ($np$;\\ \>\> $x_1$, $y_1$, $z_1$;\\ \>\> \ldots\\ \>\> $x_{np}$, $y_{np}$, $z_{np}$;\\ \>\> $ns$;\\ \>\> [ 2 | 3 ], $p_{1,1}$, $p_{1,2}$ [, $p_{1,3}$];\\ \>\> \ldots\\ \>\> [ 2 | 3 ], $p_{ns,1}$, $p_{ns,2}$ [, $p_{ns,3}$]); \end{tabbing} \end{quote} \section{Available Primitives} \label{sec_primitives} Netgen %4.1 supports the following primitives: \begin{enumerate} \item A halfspace, i.e., a plane and everything on one side of it, given by an arbitrary point~$p = (p_x, p_y, p_z)$ in the plane and an outside normal vector~$n = (n_x, n_y, n_z)$, not necessarily a unit vector: \begin{quote} \tt plane ( $p_x$, $p_y$, $p_z$ ; $n_x$, $n_y$, $n_z$ ) \end{quote} \item A cylinder of infinite length, given by two points~$a=(a_x, a_y,a_z)$ and $b=(b_x, b_y, b_z)$ on the central axis and the radius $r$: \begin{quote} \tt cylinder ( $a_x$, $a_y$, $a_z$ ; $b_x$, $b_y$, $b_z$ ; $r$ ) \end{quote} \item A sphere, given by the center~ $c=(c_x,c_y,c_z)$ and the radius~$r$: \begin{quote} \tt sphere ( $c_x$, $c_y$, $c_z$ ; $r$ ) \end{quote} \item An elliptic cylinder, given by the point $c=(c_x, c_y, c_z)$ on the main axis, and the vectors $v$ and $w$ of the long and short axis of the ellipse, respectively: \begin{quote} \tt ellipticcylinder ($c_x$, $c_y$, $c_z$ ; $v_x$, $v_y$, $v_z$ ; $w_x$, $w_y$, $w_z$) \end{quote} \item An ellipsoid, given by the center $c=(c_x, c_y, c_z)$, and the vectors $u$, $v$ and $w$ of the main axis of the ellipsoid: \begin{quote} \tt ellipsoid ($c_x$, $c_y$, $c_z$ ; $u_x$, $u_y$, $u_z$; $v_x$, $v_y$, $v_z$ ; $w_x$, $w_y$, $w_z$) \end{quote} \item A cone is given by two points on the central axis and the two corresponding radii. It is not possible to mesh the top of the cone yet, it must be cut off. \begin{quote} \tt cone ( $a_x$, $a_y$, $a_z$ ; $r_a$; $b_x$, $b_y$, $b_z$ ; $r_b$ ) \end{quote} \item A orthobrick is a brick parallel to the coordinate axis. It is specified by two opposite corner points $a = (a_x, a_y, a_z)$ and $b = (b_x, b_y, b_z)$: \begin{quote} \tt orthobrick ( $a_x$, $a_y$, $a_z$ ; $b_x$, $b_y$, $b_z$ ) \end{quote} \item A polyhedron is defined by a set of triangles forming a closed polyhedron. First, a set of points is defined, then the triangles are given by point indices. The triangles must be oriented counter-clockwise when looking onto the object. The following polyhedron describes a tetrahedron: \begin{quote} \begin{verbatim} algebraic3d solid poly = polyhedron (0,0,0; 1,0,0; 0,1,0; 0,0,1 ;; 1,3,2 ; 1,4,3; 1,2,4 ; 2,3,4 ); tlo poly; \end{verbatim} \end{quote} \item A body of extrusion is defined by its profile (which has to be a closed, \textit{clockwise} oriented 2D curve), by a path (a 3D curve) and a vector $d$. It is constructed as follows. Take a point $p$ on the path and denote the (unit-) tangent of the path in this point by $t$. If we cut the body by the plane given by $p$ and $t$ as normal vector, the cut is the profile. The profile is oriented by the (local) y-direction $\bar{y} := d - (d \cdot t) t$ and the (local) x-direction $\bar{x} := t \times \bar{y}$. The syntax is: \begin{quote} \tt extrusion ( ; ; $d_x$, $d_y$, $d_z$ ) \end{quote} The following points have to be noticed: \begin{itemize} \item If the path is not closed, then also the body is NOT closed. In this case e.g.\ planes or orthobricks have to be used to construct a closed body. \item The path has to be smooth, i.e.\ the tangents at the end- resp.\ startpoint of two consecutive spline or line patches have to have the same directions. \end{itemize} \item A body of revolution is given by two points, defining the axis of revolution, and the 2D curve which is rotated: \begin{quote} \tt revolution ( $p_{1,x}$, $p_{1,y}$, $p_{1,z}$; $p_{2,x}$, $p_{2,y}$, $p_{2,z}$; ) \end{quote} The first point defines the origin of the local 2D coordinate system of the curve. It is assumed, that the curve lies above the (local) x-axis, and that it is described \textit{clockwise}. If the curve is not closed, then the start point and the end point have to lie on the x-axis, and the tangents at those points have to be orthogonal to the x-axis. \end{enumerate} \section{Surface Identification} In Netgen it is possible to construct prismatic meshes between two surfaces, where these surfaces have to be specified explicitly in the .geo file with the command \begin{quote} \tt identify closesurfaces ; \end{quote} (this feature originally was intended for close surface, which is the reason for the command name). \paragraph{Optional parameters:} (selection) \begin{itemize} \item \texttt{-tlo=}\\ the prisms are only constructed between two faces of a tlo. \item \texttt{-direction=[,,]}\\ This parameter has to be used if \textbf{skew prisms} should be built. In this case netgen ``needs help'' by the user, it needs to know the direction of identification. \textit{Example:} We start with a cylinder with the axis given by the points $(-1,0,4)$ and $(4,10,1)$. This cylinder is cut by the planes \texttt{p1} and \texttt{p2} (which are not necessarily normal to the axis and not necessarily parallel) and we want to build prisms between these planes. Then the command would, e.g., look like \begin{quote} \tt identify closesurfaces p1 p2 -direction=[5,10,-3] \end{quote} \end{itemize} \section{Known problems and work-arounds} \subsection{Interfaces} A airdomain with two connected interior parts may be described by \begin{quote} \begin{verbatim} algebraic3d solid cube = orthobrick (0, 0, 0; 1, 1, 1); solid part1 = orthobrick (0.2, 0.2, 0.2; 0.5, 0.8, 0.8); solid part2 = orthobrick (0.5, 0.2, 0.2; 0.8, 0.8, 0.8); solid air = cube and not part1 and not part2; tlo air; tlo part1; tlo part2; \end{verbatim} \end{quote} The problem is, that a domain is an open domain. Thus, the domain {\it air} is not only the outer part, but also the interface between {\it part1} and {\it part2}. The result is unspecified. To fix this problem, one can define the {\it air}-domain by cutting out one big brick: \begin{quote} \begin{verbatim} solid air = cube and not othrobrick (0.2, 0.2, 0.2; 0.8, 0.8, 0.8); \end{verbatim} \end{quote} \subsection{Degenerated edges} Degenerated edges are found sometimes, but some still cause troubles. A sphere on top of a cylinder my be described by: \begin{quote} \begin{verbatim} solid cyl = cylinder (0, 0, 0; 1, 0, 0; 0.5) and plane (0, 0, 0; -1, 0, 0) and plane (1, 0, 0; 1, 0, 0); solid main = cyl or sphere (1, 0, 0; 0.5); tlo main; \end{verbatim} \end{quote} The edge is a degenerated one. A work-around is to split the domain (artificially) into two non-degenerated parts: \begin{quote} \begin{verbatim} solid cyl = cylinder (0, 0, 0; 1, 0, 0; 0.5) and plane (0, 0, 0; -1, 0, 0) and plane (1, 0, 0; 1, 0, 0); solid hemisphere = sphere (1, 0, 0; 0.5) and not plane (1, 0, 0; -1, 0, 0); tlo cyl; tlo hemisphere; \end{verbatim} \end{quote} \chapter{Other Geometry Formats} \section{Using IGES/STEP Geometries} % IGES and STEP are standard exchange formats for CAD files. Contrary to the STL format, IGES and STEP deliver an exact representation of the geometry and do not approximate it. In order to use IGES/STEP geometries you have to install NETGEN with the OpenCascade Geometry Kernel as described in \ref{subsec_occ}. Most solid modellers can export IGES or STEP files. However, often these files are not as exact as a mesher needs them to be. So is meshing fails, try repairing the model via {\bf IGES/STEP Topology Explorer/Doctor}. \section{Using STL Geometries} % STL is a standardized file format to describe (approximate) geometies by triangulated surfaces. It is useful to describe complicated parts which are modeled with some CAD programmes. Also, some users have written their own (C) programmes to define STL geometries, where was not so easy to use the CSG format. The syntac of STL files is as follos \begin{quote} (not available yet. please figure out the syntax from the examples) \end{quote} We found that many STL geometries have some difficulties. Some of them can be corrected (removed) by the {\bf STL - Doctor}. Please see the corresponding manual pages (not available yet). \section{2D Spline Geometry} % The extension for 2D spline geometry is ``.in2d''. The boundary is given in terms of straight lines and of quadratic rational spline patches. A line is given by the two endpoints, a spline patch by 3 d'Boor points. The patch is an elliptic arc from point 1 to point 3, such that the lines 1-2 and 2-3 are tangents. It is possible to use different subdomains with this format. This file format also supports a priori mesh grading. To the spline point i one adds a local refinement factor {\tt rp}$_i$ . Close to this point the mesh-size $h(x)$ is {\tt h}$_{Glob}$ / {\tt rp}$_i$ . The global parameter {\tt grading} describes how fast the mesh-size decreases. The gradient of the local mesh-size function $h(x)$ is bounded by $| \nabla_x h(x)| \leq \mbox{grading}^{-1}$ Also a refinement by a factor {\tt rs}$_i$ > 1 along the whole segment i is possible. The file looks like: % \begin{quote} \samepage \tt splinecurves2d \\ grading \\ np \\ x$_1$ y$_1$ rp$_1$ \\ ... \\ x$_{np}$ y$_{np}$ rp$_{np}$ \\ ns \\ dil$_1$ dir$_1$ [ 2 | 3 ] pi$_{1,1}$ pi$_{1,2}$ [ pi$_{1,3}$ ] rs$_1$ \\ ... \\ dil$_{nl}$ dir$_{nl}$ [ 2 | 3 ] pi$_{nl,1}$ pi$_{nl,2}$ [ pi$_{nl,3}$ ] rs$_{nl}$ \\ \end{quote} % {\tt np} is the number of points, {\tt ns} the number of spline segments. Every segment starts with the domain numbers at the left and at the right sides of the segment. Domain number 0 is reserved for the exterior. Then the number of points and two or three point indices follow. Finally, the refinement factor along the line follows. \chapter{Mesh and Solution Formats} You can export meshes to a couple of file formats. Some are self-defined, some other are standard formats. The self-defined are the followings: \section{Mesh Size File} By means of a mesh size file you can provide a local mesh size density. The file extension must be {\it .msz}. If you want to use the mesh size file, you specify it in the ``Meshing Options'', doalog box, page ``Mesh Size''. The syntay is: \begin{verbatim} np x1 y1 z1 h1 x2 y2 z2 h2 .... xnp ynp znp hnp nl xs1 ys1 zs1 xe1 ye1 ze1 h1 xs2 ys2 zs2 xe2 ye2 ze2 h2 .... xsnl ysnl zsnl xenl yenl zenl hnl \end{verbatim} You specify {\tt np} points, given by the $(x_i,y_i,z_i)$-coordinates, where the mesh size will be reduced at least to $h_i$. You specify also {\tt nl} line-segments by the start-point and end-point coordinates. The mesh-size along the whole line will be reduced to the given $h_i$. \section{Neutral Format} The neutral volume mesh format contains the following sections: \begin{enumerate} \item nodes \\ After the number of nodes there follows a list of $x$, $y$, and $z$-coordinates of the mesh-nodes. \item volume elements \\ After the number of volume elements there follows the list of tetrahedra. Each element is specified by the sub-domain number, and 4 node indices. The node indices start with 1. \item surface elements \\ After the number of surface elements there follows the list of triangles. Each element is specified by the boundary condition number, and 3 node indices. The node indices start with 1. \end{enumerate} \section{Fepp Format 2D} The Fepp 2D format contains the following sections: \begin{enumerate} \item boundary segmetns \\ After the number of boundary segments there follows a list of segments. Each segment is specified by the spline - patch number, and the two node indices. Counting starts with 1 \item domain elements \\ After the number of domain elements there follows the list of elements. Each element is specified by the sub-domain number, the number of nodes (3 or 4) and the node indices. Counting starts with 1 \item nodes \\ After the number of nodes there follows a list of $x$ and $y$ -coordinates of the mesh-nodes. \item geometric information \\ After the number of spline patches there follows a list of spline specifications. Each spline patch is given by the 6 coefficients of the describing quadratic polynomial equation $$ c_1 x^2 + c_2 y^2 + c_3 xy + c_4 x + c_5 y + c_6 = 0 $$ \end{enumerate} \section{Surface triangulaton file} One can export to and import from a surface mesh file. It´s structure is as follows: \begin{enumerate} \item {\tt surfacemesh} \\ starts with that keyword \item number of points \\ point coordinates $(x,y,z)$. \item number of surface triangles, \\ surface triangles oriented counter-clock wise when looking at the object, index starts from 1. \end{enumerate} \section{Solution File Format} The Netgen software includes also a simple visualizer for finite element gridfunctions. It supports scalar fields (e.g. temperature), and vector valued fields (flow velocities, mechanical deformations). The solution field is imported by the menu item File $->$ Import Solution. It is important to load the corresponding mesh in advance. The format of the solution file is as follows. It consists of an arbitrary number of blocks of this structure: \begin{enumerate} \item {\tt solution} {\it function-name} flags {\tt solution} is the keyword, {\it function-name} is a string to refer to that functions. The supported flags are \begin{enumerate} \item -size=s \\ number of entries (default: number of mesh-points) \item -components=c \\ number of components (default: 1). Mechanical deformations have 3 components. \item -type=[nodal,element,surfaceelement] \\ the grid-funciton has nodal values, or one value per volume element, or one value per surface element (default: nodal) \end{enumerate} \item block of $size \times components$ values \end{enumerate} Please try out to import the solution file 'tutorials/cube.sol' fitting to the mesh 'tutorials/cube.vol'. \chapter{Netgen operations} You can use netgen in interactive mode using its menus, or, you can run netgen in batch-mode using command line arguments. \section{Command line arguments} Command line arguments are specified as {\it -flag=value}. \begin{itemize} \item -help \newline Prints the available command line arguments \item -geofile=filename \newline Specifies geometry file. Is equivalent to {\it filename}, i.e., you can scip {\it -geofile=}. \item -meshfile=filename \newline Mesh file will be stored in file {\it filename}. \item -batchmode \newline Exit after mesh generation. Otherwise, the GUI will be started \item -V \newline Verbose mode. Prints some additional information \item -verycoarse, -coarse, -moderate, -fine, -veryfine \newline Mesh size control \end{itemize} \chapter{Using the Graphical User Interface} The Netgen main window looks like: \begin{center} \includegraphics[width=12cm]{pictures/screenshot} \end{center} It consists of the menuline and the button line at the top, the status line at the bottom, and the large drawing window. The menu items will be explained in \ref{sec_menuitems}. The button line provides shot-cuts for common opteration: \begin{itemize} \item Quit \newline Terminate Netgen \item Generate mesh \newline Performe mesh generation \item Stop Meshing \newline Stop mesh generation \item Geometry/Edges/Mesh/Solution \newline Switch between operation modes of visualization. \item Zoom all \newline Zooms such that the whole visualization scene fits into the window. \item Center \newline Center rotation and scaling at marked point, available only in mesh - visuailzation mode. \item Rotate/Move/Zoom Left mouse drag rotates/moves/zooms object. \end{itemize} The status line shows information, namely \begin{itemize} \item Points \newline Number of points in the mesh \item Elements \newline Number of volume elements (3D) in the mesh \item Surf Elements \newline Number of surface elements (3D) or inner elements (2d) in the mesh. \item Mem \newline Used memory in the large memory arena \item Meshing Job, percentage Douriing mesh generation, the current job as well as the progress is displayed on the right side of the statu line. \end{itemize} The drawing window displays the geometry or the mesh. The view can be changed with the mouse: \begin{itemize} \item drag with left button pressed rotates the object, \item drag with middle button pressed moves the object, \item drag with right button pressed zooms the object. \end{itemize} The view can also be changed with the keyboard: \begin{itemize} \item cursor keys rotate the object \item shift + cursor keys move the object \item control + cursor keys zoom the object \end{itemize} When in Mesh - visualization scene, double clicking on triangles mark the surface. The point cursor is set. \section{The Netgen menu items} \label{sec_menuitems} \subsection{The menu item {\em File}} \includegraphics[height=7.8cm]{pictures/menufile} \subsection{The menu item {\em Geometry}} \includegraphics[height=2.7cm]{pictures/menugeometry} \subsection{The menu item {\em Mesh}} \includegraphics[height=9.8cm]{pictures/menumesh} \subsection{The menu item {\em View}} \includegraphics[height=6.0cm]{pictures/menuview} \subsection{The menu item {\em Refinement}} \includegraphics[width=3.2cm]{pictures/menurefinement} \section{Meshing Options} \includegraphics[width=10cm]{pictures/meshingoptions_1} \includegraphics[width=10cm]{pictures/meshingoptions_2} \includegraphics[width=10cm]{pictures/meshingoptions_3} \includegraphics[width=10cm]{pictures/meshingoptions_4} \includegraphics[width=10cm]{pictures/meshingoptions_5} \includegraphics[width=10cm]{pictures/meshingoptions_6} \section{Visualization Options} % \chapter{The Algorithms of Netgen} % % Netgen follows a top down strategy. It starts from computing the % corner points (CSG only). Then, the edges are defined and meshed into % segments (CSG and STL). Next, the faces are meshed by an advancing front % surface mesh generator. After meshing, the faces meshes are optimized. % Finally, the individual sub-domains are filled with tets. Therefore, % a fast Delaunay algorithm generates most of the elements (about 98 percent). % But often it fails for mesh the whole domain, then the slower back-tracking % rule-base algorithm takes over. Finally, the volume is optimized by the % usual node - movement, element swapping and splitting algorithms. \chapter{Programming Interfaces} % \section{The nginterface} By means of the nginterface one's own simulation code can be included into the netgen environment. This is particular useful for FEM (FVM,BEM) code developers, since they may profit from the netgen preprocessing and postprocessing possibilities. Please download the example Netgen-add-on module {\it demoapp} and follow the instructions therein \section{The nglib} \subsection{Introduction} The NETGEN mesh generation library {\it nglib} is available in C++ source code and can be compiled for Unix/Linux as well as Win95/98/NT and linked to one library file. The interface to the application programme is by the C language header file {\it nglib.h}. The functionality of nglib is volume mesh generation by a domain given by a surface triangulation, and surface mesh generation from a domain described by an STL file (standard file format for geometries defined by triangle approximation). It can do mesh optimization as well as mesh refinement. It can generate 4 node tetrahedra and 10 node tetrahedrons (with quadratic shape functions). The local mesh size can be defined automatically by geometric features and/or by user specification. \subsection{The Header File} The interface file contains the following type definitions and function calls. All Netgen types and functions start with {\tt Ng}. Types and functions have capital initial letters, constants are in capital letters. \subsection{Types and Constants} \begin{verbatim} /// Data type for NETGEN mesh typedef void * Ng_Mesh; /// Data type for NETGEN STL geomty typedef void * Ng_STL_Geometry; // max number of nodes per element #define NG_VOLUME_ELEMENT_MAXPOINTS 10 // implemented element types: enum Ng_Volume_Element_Type { NG_TET = 1, NG_PYRAMID = 2, NG_PRISM = 3, NG_TET10 = 4 }; // max number of nodes per surface element #define NG_SURFACE_ELEMENT_MAXPOINTS 6 // implemented element types: enum Ng_Surface_Element_Type { NG_TRIG = 1, NG_QUAD = 2, NG_TRIG6 = 3 }; struct Ng_Meshing_Parameters { double maxh; double fineness; // 0 .. coarse, 1 .. fine int secondorder; }; enum Ng_Result { NG_OK = 0, NG_SURFACE_INPUT_ERROR = 1, NG_VOLUME_FAILURE = 2, NG_STL_INPUT_ERROR = 3, NG_SURFACE_FAILURE = 4 }; \end{verbatim} {\tt Ng\_Mesh} is a data type representing a Netgen mesh. {\tt Ng\_STL\_Geometry} represents an STL geometry. One can operate on these data structures by the functions defined below. Netgen can (now and/or in future) work with various element types defined by generic constants. Several parameters can be specified in the {\tt Ng\_Meshing\_Parameters} structure for volume and/or surface mesh generation. The result of Netgen functions is of type {\tt Ng\_Result}. \subsection{Initialization} Please call these functions before using netgen functions and after using netgen functions, respectively: \begin{verbatim} // initialize, deconstruct Netgen library: void Ng_Init (); void Ng_Exit (); \end{verbatim} \subsection{Mesh access} Netgen meshes can be processed by the means of the following functions. A mesh contains nodes, surface elements and volume elements. Counting starts from 1. \begin{verbatim} // Generates new mesh structure Ng_Mesh * Ng_NewMesh (); void Ng_DeleteMesh (Ng_Mesh * mesh); // feeds points, surface elements and volume elements to the mesh void Ng_AddPoint (Ng_Mesh * mesh, double * x); void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et, int * pi); void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et, int * pi); // ask for number of points, surface and volume elements int Ng_GetNP (Ng_Mesh * mesh); int Ng_GetNSE (Ng_Mesh * mesh); int Ng_GetNE (Ng_Mesh * mesh); // return point coordinates void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x); // return surface and volume element in pi Ng_Surface_Element_Type Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi); Ng_Volume_Element_Type Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi); \end{verbatim} \subsubsection{Mesh Generation} The user can specify the mesh size function by the global parameter maximal mesh size, and can additionally restrict the mesh size in points or cubes. The function {\tt Ng\_GenerateVolumeMesh} generates the volume mesh starting from the surface. \begin{verbatim} // Defines MeshSize Functions void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h); void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h); void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h); // generates volume mesh from surface mesh Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); \end{verbatim} \subsection{STL Geometry} A STL geometry can be read from a STL file (ASCII or binary), or can be assembled by providing triangle by triangle. Either, the user can specify the edges of the geometry, or netgen can define edges by {\tt Ng\_STL\_MakeEdges} by using an angle criterium. \begin{verbatim} // loads geometry from STL file Ng_STL_Geometry * Ng_STL_LoadGeometry (char * filename, int binary = 0); // generate new STL Geometry Ng_STL_Geometry * Ng_STL_NewGeometry (); // fills STL Geometry // positive orientation // normal vector may be null-pointer void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, double * p1, double * p2, double * p3, double * nv); // add (optional) edges: void Ng_STL_AddEdge (Ng_STL_Geometry * geom, double * p1, double * p2); // after adding triangles (and edges) initialize Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom); // automatically generates edges: void Ng_STL_MakeEdges (Ng_STL_Geometry * geom); // generates mesh, empty mesh be already created. Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); \end{verbatim} \subsection{Programming Example} The File {\it ngcore.cc}, see Appendix A, is a simple application using the netgen volume mesh generator. First, the surface mesh is read from a file containing point coordinates and surface triangles (see e.g. file {\it cube.surf}). The volume mesh generate is called, and the volume mesh is written to the standard output, see file {\it cube.vol}. \end{document} netgen-6.2.1905/doc/ng4.pdf0000644000175000017500000177011413504650527013744 0ustar kurtkurt%PDF-1.4 %ÐÔÅØ 5 0 obj << /S /GoTo /D (chapter.1) >> endobj 8 0 obj (Getting Started) endobj 9 0 obj << /S /GoTo /D (section.1.1) >> endobj 12 0 obj (What is NETGEN) endobj 13 0 obj << /S /GoTo /D (section.1.2) >> endobj 16 0 obj (The history of NETGEN) endobj 17 0 obj << /S /GoTo /D (section.1.3) >> endobj 20 0 obj (How to receive NETGEN) endobj 21 0 obj << /S /GoTo /D (section.1.4) >> endobj 24 0 obj (Installing NETGEN) endobj 25 0 obj << /S /GoTo /D (subsection.1.4.1) >> endobj 28 0 obj (Installing NETGEN for Unix/Linux) endobj 29 0 obj << /S /GoTo /D (subsection.1.4.2) >> endobj 32 0 obj (Installing NETGEN for Windows) endobj 33 0 obj << /S /GoTo /D (subsection.1.4.3) >> endobj 36 0 obj (Adding IGES/STEP file support via OpenCascade) endobj 37 0 obj << /S /GoTo /D (subsection.1.4.4) >> endobj 40 0 obj (Testing Netgen) endobj 41 0 obj << /S /GoTo /D (chapter.2) >> endobj 44 0 obj (Constructive Solid Geometry \(CSG\)) endobj 45 0 obj << /S /GoTo /D (section.2.1) >> endobj 48 0 obj (Curves) endobj 49 0 obj << /S /GoTo /D (section.2.2) >> endobj 52 0 obj (Available Primitives) endobj 53 0 obj << /S /GoTo /D (section.2.3) >> endobj 56 0 obj (Surface Identification) endobj 57 0 obj << /S /GoTo /D (section.2.4) >> endobj 60 0 obj (Known problems and work-arounds) endobj 61 0 obj << /S /GoTo /D (subsection.2.4.1) >> endobj 64 0 obj (Interfaces) endobj 65 0 obj << /S /GoTo /D (subsection.2.4.2) >> endobj 68 0 obj (Degenerated edges) endobj 69 0 obj << /S /GoTo /D (chapter.3) >> endobj 72 0 obj (Other Geometry Formats) endobj 73 0 obj << /S /GoTo /D (section.3.1) >> endobj 76 0 obj (Using IGES/STEP Geometries) endobj 77 0 obj << /S /GoTo /D (section.3.2) >> endobj 80 0 obj (Using STL Geometries) endobj 81 0 obj << /S /GoTo /D (section.3.3) >> endobj 84 0 obj (2D Spline Geometry) endobj 85 0 obj << /S /GoTo /D (chapter.4) >> endobj 88 0 obj (Mesh and Solution Formats) endobj 89 0 obj << /S /GoTo /D (section.4.1) >> endobj 92 0 obj (Mesh Size File) endobj 93 0 obj << /S /GoTo /D (section.4.2) >> endobj 96 0 obj (Neutral Format) endobj 97 0 obj << /S /GoTo /D (section.4.3) >> endobj 100 0 obj (Fepp Format 2D) endobj 101 0 obj << /S /GoTo /D (section.4.4) >> endobj 104 0 obj (Surface triangulaton file) endobj 105 0 obj << /S /GoTo /D (section.4.5) >> endobj 108 0 obj (Solution File Format) endobj 109 0 obj << /S /GoTo /D (chapter.5) >> endobj 112 0 obj (Netgen operations) endobj 113 0 obj << /S /GoTo /D (section.5.1) >> endobj 116 0 obj (Command line arguments) endobj 117 0 obj << /S /GoTo /D (chapter.6) >> endobj 120 0 obj (Using the Graphical User Interface) endobj 121 0 obj << /S /GoTo /D (section.6.1) >> endobj 124 0 obj (The Netgen menu items) endobj 125 0 obj << /S /GoTo /D (subsection.6.1.1) >> endobj 128 0 obj (The menu item File) endobj 129 0 obj << /S /GoTo /D (subsection.6.1.2) >> endobj 132 0 obj (The menu item Geometry) endobj 133 0 obj << /S /GoTo /D (subsection.6.1.3) >> endobj 136 0 obj (The menu item Mesh) endobj 137 0 obj << /S /GoTo /D (subsection.6.1.4) >> endobj 140 0 obj (The menu item View) endobj 141 0 obj << /S /GoTo /D (subsection.6.1.5) >> endobj 144 0 obj (The menu item Refinement) endobj 145 0 obj << /S /GoTo /D (section.6.2) >> endobj 148 0 obj (Meshing Options) endobj 149 0 obj << /S /GoTo /D (section.6.3) >> endobj 152 0 obj (Visualization Options) endobj 153 0 obj << /S /GoTo /D (chapter.7) >> endobj 156 0 obj (Programming Interfaces) endobj 157 0 obj << /S /GoTo /D (section.7.1) >> endobj 160 0 obj (The nginterface) endobj 161 0 obj << /S /GoTo /D (section.7.2) >> endobj 164 0 obj (The nglib) endobj 165 0 obj << /S /GoTo /D (subsection.7.2.1) >> endobj 168 0 obj (Introduction) endobj 169 0 obj << /S /GoTo /D (subsection.7.2.2) >> endobj 172 0 obj (The Header File) endobj 173 0 obj << /S /GoTo /D (subsection.7.2.3) >> endobj 176 0 obj (Types and Constants) endobj 177 0 obj << /S /GoTo /D (subsection.7.2.4) >> endobj 180 0 obj (Initialization) endobj 181 0 obj << /S /GoTo /D (subsection.7.2.5) >> endobj 184 0 obj (Mesh access) endobj 185 0 obj << /S /GoTo /D (subsection.7.2.6) >> endobj 188 0 obj (STL Geometry) endobj 189 0 obj << /S /GoTo /D (subsection.7.2.7) >> endobj 192 0 obj (Programming Example) endobj 193 0 obj << /S /GoTo /D [194 0 R /Fit ] >> endobj 196 0 obj << /Length 154 /Filter /FlateDecode >> stream xÚ-Ì» 1…á~ŸbÊÌ8™LÒ QXpSb±ÞPPö|u³ÄêpŠïß”n½µ˜0öPÀ|ñY Üआ\vyÐÆ+ÓFð¨Ï¥¯:‚txÑÖbLÆ»±M÷ÓxÕÕóõ©–ƒ:´ûÕ’HMmê»Ï稜$q%ýûqn¢q·jËdi1].ݽ-£ endstream endobj 194 0 obj << /Type /Page /Contents 196 0 R /Resources 195 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 197 0 obj << /D [194 0 R /XYZ 86.4 708.045 null] >> endobj 198 0 obj << /D [194 0 R /XYZ 86.4 688.245 null] >> endobj 195 0 obj << /Font << /F16 199 0 R /F17 200 0 R >> /ProcSet [ /PDF /Text ] >> endobj 204 0 obj << /Length 55 /Filter /FlateDecode >> stream xÚs áÒw34W04Ô³455RIS040гP07°Ð301UIQˆÖ0ÒŒ ñâr áêg ø endstream endobj 203 0 obj << /Type /Page /Contents 204 0 R /Resources 202 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 205 0 obj << /D [203 0 R /XYZ 100.8 708.045 null] >> endobj 202 0 obj << /Font << /F17 200 0 R >> /ProcSet [ /PDF /Text ] >> endobj 237 0 obj << /Length 983 /Filter /FlateDecode >> stream xÚÝXMsÛ6½ûWðH >©#+nS'3b&‡¦D„%L$ÒC‚Nš__€)Ëa]µ™‰Íœ@Š"´o±ï½]ýRœ_"!œ2Î`TÜDœ¦8"‚¤‚æQQF€‹ºŠsŒ² ¦ÿ,~íß‚0„ ÷V%”¥ˆ`ÿ Œ‘Q°TÆèj'9#`edcT'“Œâ·ìþ6¥„ˆ($…‚…½R»Ì2Þo¥±{! tëV®Årq'œå ’esZ ¥!.ǘQÀ\l•‡¼Õ­©›¿üM}sŒ :_¨y€úªŽ-¤Ï¡©ýÚ¨µÒwîAÈÃq2Èt2¯ªÖÈÝÎsä>8FæZÏ1¢©@øØ=•!Ê?²KÂMÝø‹w•þrþZWîô»/ö³œ?Éaõd<9ê÷º*}%[‘¢ýˆ¤³Š<‘¿(Ë1ê«åbu¾*o}¼2ˆw\mw{ëªÔñ_¾ÓÒ?zã¨êB¶kYÚFEEDEQáUsTkõ¯ÌÆÚLÂa>ŸŠgS†˜` “ç‘ÍYг`‹ÈÛ¢5ÔÖ4ÝÚXa³Æª‚?Ö;]úË¥ª÷Êôboï>d$»X-íâØƒsL€8Õ<Ñhž]ãeÔV%Éñÿ‚‹…˜•AF„SÜ@£Á¾¸‹ RïäGÏÞ6z¯Ýá Þ§Kp2?Øhö`¶«®¹‘ë@û«Rõ"k´ƒµ4Ú¶| Áp~°ñ4ìÁp«¼4WømSÛSß·þNV¥¿ø÷ø)‘MÝU¥ÓqˆŸÓ”¥¢#KíPõçjCæÏ—ÝæhÈ/•µ ÕÈ~®pÔUå¦glŸu•’·Œ0|åÞ2Þ˜­j¦Ìá2Ø–ê^Ú¹,e@vª;ä£;¼kG~ЄŸÓ.­ö«ùÓ×OádË“²~Ъxí‹c©bh蔬?C‹{ï çèe{kÛSutt¶Rš¡qO÷UCßï«°'ÉïªÝzVx%÷MUçÝì[²p›8On¥ðH–ð;.Ûúkè.õ.ö­¦?Wÿ$¦ºx<íZu¦‘;ŸK×ÐÛA‚½û«†RøS&a¬ˆ}7ÊÍN}-¸»¾Ì|V7A3œè'R²éTà©ÆÒ*­¬6ÝNšº:ž69Ï»;y,ÀäÅU¿æèÀƒ¾Xþ]'ÿ4¸áÉÚK¼ö“»“Ùºç°}™—«¶±L”Ÿª¶ä0¸ÖûýØ™ÌM6›nÆ×ñaþcòóŸÏÃ'´AŽSmDÊ9Z<ûèlQœý æ—Òò endstream endobj 236 0 obj << /Type /Page /Contents 237 0 R /Resources 235 0 R /MediaBox [0 0 612 792] /Parent 201 0 R /Annots [ 206 0 R 207 0 R 208 0 R 209 0 R 210 0 R 211 0 R 212 0 R 213 0 R 214 0 R 215 0 R 216 0 R 217 0 R 218 0 R 219 0 R 220 0 R 221 0 R 222 0 R 223 0 R 224 0 R 225 0 R 226 0 R 227 0 R 228 0 R 229 0 R 230 0 R 231 0 R 232 0 R 233 0 R ] >> endobj 206 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [85.403 525.388 198.113 538.007] /Subtype /Link /A << /S /GoTo /D (chapter.1) >> >> endobj 207 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 512.516 227.606 522.81] /Subtype /Link /A << /S /GoTo /D (section.1.1) >> >> endobj 208 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 494.994 259.802 507.614] /Subtype /Link /A << /S /GoTo /D (section.1.2) >> >> endobj 209 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 482.122 262.334 492.284] /Subtype /Link /A << /S /GoTo /D (section.1.3) >> >> endobj 210 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 464.6 234.76 477.22] /Subtype /Link /A << /S /GoTo /D (section.1.4) >> >> endobj 211 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [129.886 448.739 353.992 462.687] /Subtype /Link /A << /S /GoTo /D (subsection.1.4.1) >> >> endobj 212 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [129.886 434.207 340.89 446.826] /Subtype /Link /A << /S /GoTo /D (subsection.1.4.2) >> >> endobj 213 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [129.886 418.345 429.829 432.293] /Subtype /Link /A << /S /GoTo /D (subsection.1.4.3) >> >> endobj 214 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [129.886 403.813 246.788 416.299] /Subtype /Link /A << /S /GoTo /D (subsection.1.4.4) >> >> endobj 215 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [85.403 375.745 319.579 389.693] /Subtype /Link /A << /S /GoTo /D (chapter.2) >> >> endobj 216 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 363.537 167.062 373.699] /Subtype /Link /A << /S /GoTo /D (section.2.1) >> >> endobj 217 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 348.34 235.503 358.635] /Subtype /Link /A << /S /GoTo /D (section.2.2) >> >> endobj 218 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 333.143 240.805 343.438] /Subtype /Link /A << /S /GoTo /D (section.2.3) >> >> endobj 219 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 315.621 313.773 328.241] /Subtype /Link /A << /S /GoTo /D (section.2.4) >> >> endobj 220 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [129.886 302.749 218.499 313.044] /Subtype /Link /A << /S /GoTo /D (subsection.2.4.1) >> >> endobj 221 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [129.886 285.228 264.187 297.847] /Subtype /Link /A << /S /GoTo /D (subsection.2.4.2) >> >> endobj 222 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [85.403 257.824 254.788 270.443] /Subtype /Link /A << /S /GoTo /D (chapter.3) >> >> endobj 223 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 241.963 290.673 255.911] /Subtype /Link /A << /S /GoTo /D (section.3.1) >> >> endobj 224 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 227.43 248.33 239.917] /Subtype /Link /A << /S /GoTo /D (section.3.2) >> >> endobj 225 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 212.233 236.173 224.853] /Subtype /Link /A << /S /GoTo /D (section.3.3) >> >> endobj 226 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [85.403 187.154 267.959 197.449] /Subtype /Link /A << /S /GoTo /D (chapter.4) >> >> endobj 227 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 171.957 206.238 182.252] /Subtype /Link /A << /S /GoTo /D (section.4.1) >> >> endobj 228 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 156.76 211.701 167.055] /Subtype /Link /A << /S /GoTo /D (section.4.2) >> >> endobj 229 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 139.239 216.578 151.725] /Subtype /Link /A << /S /GoTo /D (section.4.3) >> >> endobj 230 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 124.042 255.117 136.661] /Subtype /Link /A << /S /GoTo /D (section.4.4) >> >> endobj 231 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 111.17 238.529 121.464] /Subtype /Link /A << /S /GoTo /D (section.4.5) >> >> endobj 232 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [85.403 81.441 212.861 94.061] /Subtype /Link /A << /S /GoTo /D (chapter.5) >> >> endobj 233 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [102.962 66.244 263.636 78.864] /Subtype /Link /A << /S /GoTo /D (section.5.1) >> >> endobj 238 0 obj << /D [236 0 R /XYZ 86.4 708.045 null] >> endobj 240 0 obj << /D [236 0 R /XYZ 86.4 556.113 null] >> endobj 235 0 obj << /Font << /F22 239 0 R /F17 200 0 R >> /ProcSet [ /PDF /Text ] >> endobj 261 0 obj << /Length 673 /Filter /FlateDecode >> stream xÚÝ—KoÚ@…÷ù^ŽžÌû±m´UK¢ÆÉ&íÂ… XƒŒQ›þú^{l `”ª¢ÂtÅXlŸïž¹÷ø]|uݧ: [)Y?”lM &Bñ8xB"ü¼î3²» Ž-åñ{nn‡qoß×[ÙîÖ¨Ùqе¬ïªÂÈ…Vi6 #®%*¦Î/y²œ¦£dæ/V.÷«YÈ)*\þœŒ`/‚Ĥ螥´ìÁB¨ú‘˜ÂŸ¡(®Åºbâ2¿žÃ‚i´öWiáæ+xGJ#IHG(0L— ¦°eü@t%›2Rä•ëµ#U;J-ÖL5eî§3×F›qÌÕÆ Ý„8&¦ñ‡Ü¢b§B5p¡$h1wEþÒ†LÌÌù‰…ˆmÀ‚ Q‡â§óÙ­¦m@8ÃÒvÕCÞ<¦f$æô°¹`q*F©ûñŸ2’§bô¥<_î+¡"spƒâ™õp)õVO§ò„ø©4n—EºÈ`®º=‰Þ&àå“}ݼÖý˜®ÖÉ,ý•”Š÷Ôs¥/N/­q¨‰&0­©¤‚öiè._Lòd>ßd¢W‰0Pk¤@ü#>Œ<Ù$­NÛ&F)qBc kÏÇ[¶ùKoÎÕ‚YúN”ùמê¶LH6™Æ *òE)ÆëQ}øì…¶yÜ­áî½KÆÕ÷ø¢Š·ð•¢.Öór+vØ ¾/˪¼e )E'ÙØ+¾æZ$¾¬Ê;ënªTÇJ*66N ¨jº3?˜¡—:)¹>¦·‰OUŠ®J˜Œ`2”µ³ç”û·îxC®ªåÞCmãOÞ¼WUEFÛ ª©9&R×"ïrP¹@lïg2_–]ItH«o³Uš»êÅW¿¹µP endstream endobj 260 0 obj << /Type /Page /Contents 261 0 R /Resources 259 0 R /MediaBox [0 0 612 792] /Parent 201 0 R /Annots [ 234 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R 247 0 R 248 0 R 249 0 R 250 0 R 251 0 R 252 0 R 253 0 R 254 0 R 255 0 R 256 0 R 257 0 R 258 0 R ] >> endobj 234 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [99.803 672.969 326.236 685.589] /Subtype /Link /A << /S /GoTo /D (chapter.6) >> >> endobj 241 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [117.362 658.523 269.252 671.143] /Subtype /Link /A << /S /GoTo /D (section.6.1) >> >> endobj 242 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 646.402 285.593 656.697] /Subtype /Link /A << /S /GoTo /D (subsection.6.1.1) >> >> endobj 243 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 629.632 315.251 642.251] /Subtype /Link /A << /S /GoTo /D (subsection.6.1.2) >> >> endobj 244 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 617.511 292.627 627.805] /Subtype /Link /A << /S /GoTo /D (subsection.6.1.3) >> >> endobj 245 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 603.065 291.432 613.359] /Subtype /Link /A << /S /GoTo /D (subsection.6.1.4) >> >> endobj 246 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 586.294 323.252 598.914] /Subtype /Link /A << /S /GoTo /D (subsection.6.1.5) >> >> endobj 247 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [117.362 571.848 233.224 584.468] /Subtype /Link /A << /S /GoTo /D (section.6.2) >> >> endobj 248 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [117.362 557.403 257.286 570.022] /Subtype /Link /A << /S /GoTo /D (section.6.3) >> >> endobj 249 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [99.803 531.251 261.383 543.87] /Subtype /Link /A << /S /GoTo /D (chapter.7) >> >> endobj 250 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [117.362 516.805 226.269 529.424] /Subtype /Link /A << /S /GoTo /D (section.7.1) >> >> endobj 251 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [117.362 502.359 195.704 514.978] /Subtype /Link /A << /S /GoTo /D (section.7.2) >> >> endobj 252 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 490.238 247.791 500.533] /Subtype /Link /A << /S /GoTo /D (subsection.7.2.1) >> >> endobj 253 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 475.792 267.137 486.087] /Subtype /Link /A << /S /GoTo /D (subsection.7.2.2) >> >> endobj 254 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 459.022 292.538 471.641] /Subtype /Link /A << /S /GoTo /D (subsection.7.2.3) >> >> endobj 255 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 446.9 249.092 457.195] /Subtype /Link /A << /S /GoTo /D (subsection.7.2.4) >> >> endobj 256 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 432.455 245.385 442.749] /Subtype /Link /A << /S /GoTo /D (subsection.7.2.5) >> >> endobj 257 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 415.684 260.392 428.171] /Subtype /Link /A << /S /GoTo /D (subsection.7.2.6) >> >> endobj 258 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [144.286 401.238 302.094 413.858] /Subtype /Link /A << /S /GoTo /D (subsection.7.2.7) >> >> endobj 262 0 obj << /D [260 0 R /XYZ 100.8 708.045 null] >> endobj 259 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F22 239 0 R /F32 264 0 R >> /ProcSet [ /PDF /Text ] >> endobj 268 0 obj << /Length 1510 /Filter /FlateDecode >> stream xÚWKsÛ8 ¾÷WxzYyËzZRo©cg“IL­L›=0m±•%-IÕM/û× ('Íhgz1AA<>ПòwóuL‚ÈMÒÄŸä»Iºp£Iœ…nNòrò—³¬X§¹œÎÂ$vüéßùõÄ›ÌâÀM“€4.¹Ö¢Ù“ÆV3©y‰zóµŸL|ßÍâ8@ÓøYâ†ñ‚>{˜ú^æœÙ\m.?ÂÇAâ\Ü.ï?¯6ù4 œsüɯn7$ºÚâºp6·9÷w$Èoi1… }´¢Óáb~â~ §§n’%tºïúÓ™ï±óP1M¾ Eëf•_®6ÿs…0pc/"#Vqf úVÖØµ×íÔwL‹‚8®*¢ö¼á­ÕÍxßִݵÒò§Aêñbí`¼´’JrNd)¼Q`K¹CvüÈ"æ ×p؇Ƞ¸¶9o`«¶—'ºoJL6’º2¼Ð)ð"M)ÐáÁÂŽDV'pn.ïn\"¯4­E 7&’ÙUisêۆ9ÜÉv/Ùá€×ó}ç(tEÔ¼¬«DÁjâôÊ&P¢Á(AîXÁÏ9­•áá¸.?|@Âsjñ$™|&.Æ×' mjÑ|Cƒ¼üÅ<8`µ!Ë#®·Ia]Wƒ£2Kø¯9,)"Zþ>c‡‰š=՜ئÐÐ}#~ÌoÈþ‡5NAŒœÑ”-JŽŠ$Y:ßä. áÀÙ˜—äEœÙ2W´Ép´¬Ù÷5“´7NÄ©óOÏJ îA€1ö(Âj¦ÏR ágDƒ Ñ\KVñrä³ ?q/¼@ÿã…“›ÚB4]51¢°/¸°2EkÉU!…MbI¼'ŒÌ3Ñ ÒÑp2Rôò»É®BwopwaËùõ‘‹áÈ#(¤é ~q>&ç©Ã|‡‹¡píÑó£Æx•ú/^]@CiÙZCC?ÖÂ*ï94d…[»^ì-·—°øgV™s€¹J3øË¡Ô×#q7½ÉdI—Ýæ7D ï5?…ð ëZ`?Ñ–„ À9 ¤¥N ÕÕ×\½ %A!Rm§ÅAü´`ˆLƈ{•€Ú“sB€tÀT ¤2€¡q½ g9äº$5^Ÿ4q˜äD¨¾#\lÍ^fpŽ”ž„@# @I÷·ÆL`ÇŒ©fœ.•Pº5†`cìÿÖȱFfÞËì*r:‹#ç+/4qÌÐ0Àeg²ÙøY…]‹«L˜‚úCŒžp¶ÆSX¯[f“pKÓ–„ÿN#¬>Û²¶¸0L—(Àh[áw¡(ùQHs¤w²Ýa½Ä¹¯¥ £$º„ârMLj\ .x—RL¼Áè²=tý($jS£ßùÌÀœÜŠ„@ܾªVÛ€ÏT`R 3¯ŸI ûçòy¯XMß,`èñí‡LÌíHpB)x¡PÙNטÎÔ©p E‘9r$­‚™sÍþ=Ê<ƒw†¥u÷q>?‚KÇ£»;î\V¸L#’t`WÒîuC(²tGß[Dáh ä«%¨ Ó‰íú~è- {™· ÷­yí¢`'ÛQç!æÆ}!¯äÕáAa3hj22o*ÚÙÁÎí‘øÚ‹d Éx€dj¯Û¾G¦­êfëÕç÷¤ý6€½ª‡vüà~ýÖ¿Ät¡Ýí3ª$kC¡ðtþúa=úм2éŒ1 ˆD¨Fßoxû€2E%})j IdF†y Y´F–n÷œzwôDêÚ%[[ª$(Æ4{…6ÃǤôÅüÑxÈÿóúÜ¢zgþV¼´³ÏX™gô?ãÓ㯱1Až nú*¸UQpåÊ£®fl°Ž=ç–|Þ˜@`È)†¸AN`X»iš’O1ŠÞ­òwÿ šp endstream endobj 267 0 obj << /Type /Page /Contents 268 0 R /Resources 266 0 R /MediaBox [0 0 612 792] /Parent 201 0 R /Annots [ 265 0 R ] >> endobj 265 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [437.475 301.34 445.321 315.288] /Subtype /Link /A << /S /GoTo /D (chapter.2) >> >> endobj 269 0 obj << /D [267 0 R /XYZ 86.4 708.045 null] >> endobj 6 0 obj << /D [267 0 R /XYZ 86.4 688.245 null] >> endobj 10 0 obj << /D [267 0 R /XYZ 86.4 449.482 null] >> endobj 14 0 obj << /D [267 0 R /XYZ 86.4 240.289 null] >> endobj 266 0 obj << /Font << /F22 239 0 R /F17 200 0 R >> /ProcSet [ /PDF /Text ] >> endobj 275 0 obj << /Length 1779 /Filter /FlateDecode >> stream xÚ•WÝsÛ6 ï_áÛíA¾›hQßêÝÒÆMÜK^£të­{eÚf#K>IŽãýõR¶Z%ë^,A?ÀoÒW“w<qÎ’ pGéjćţȉ™ã£t9úË Ç§ï'ï\ç\ÎåóâpäÌÛë‹éôÓØöÜÐâllG¡k]MÓt6¿"æ]:޹uñi»V:½Ô:ݘËuÚF©íqúzμ±Í¹X×ÕØãÖôEÕVô­E.äãØs-AŒ9H[Óôj:§;úïsà–¹±Vžn™Wd­hZ¤#kN§¿©öu®er¸¶—‚ÄjQˆ¬Ñ{²¡o6†Çqà[™,²E¡·Wuµ=W¸ªêµ@ûFqÀBÇ«\–D.YµA%m»{=™œ‰³1·JÑNv5ØÖ7‘·Í8kQÚ[ØÍFÔJ©büü¾Vxk æ¸Xiˆ¯÷ Më÷4¿á++kˆ}@cDQ蓊Á;Õr·_2'úîóÜ(Ú)GUl«úH̼*Õ«2YÊrM¼v£¯ÖÞW¦CBA_Ÿù~H¦“¦$†þ3ŽÈrY¡(ñ$ò}{ŠæÆÏo8ãIül¼‡Ûfí‘£Åõ¡ÝØY–£ÄF”l)tÄ Ž!ï#Èÿ„…qdòß×ù?+›6+ å>•é?å׳;]…Ó·éìvnü3½Ôüû—háUçnÖŠfów(vûéI*U.á wë³ú½˜Ý\¼¹™š ”#zƒ®%7™¬U)ËòA²óLÇ4?9ÈgžªwuÉáQ¼Ÿñ—]¤hPMÄ})Ÿ&7²D4Ù?=ç?—ñP‡ ÅG`ñ'‘%éZõHC~«o§Új ((iŽëŒ,‹*[‡*ƒ;HŸá.³riø[[…ÊéGi'»¤Ö•pDσÆF+gß ¬/ÇhÊ•B,IRe®¸UUd!ùËK.ꬖ¢y­Ã“ôšGÄ|Q'`~ì‘1€0Ñ‹Œ=núÕo[Þ%}e³Ï ùOÖJt,²èîã)/ΔÐ%×h»üØŠòêfèêÀa®aFÚg-}Á©¢!ò Á@%¢k¥`ͱiÅö\Fá–ëp8ßáÒ&«— @â<²Öu¶ÛȰ̆^ÑËqcU M5ÕªUnǨu×ò2ÀÎl]è…ß~û«€P|«ß°íåK8 _ª•dÞ’A-²¡8Û:x¶ë±¶þo ]?6~ȰüÄjÑ: !M‹ÙÙIXtR”éÃÐ}^ É—±¥ ¿õ$Ìs¼~1Ve¡è÷Õ¦$+n÷ÚzSí[ÚùêŽqipj(zîOðf ]!yÑ­MŽ'ä®ÅàC–M@9'`¤ŠÆ0¶ qÄS+JêG¸0q7î]ƒòà»þôÎŒ« ´­(0æ˜J€ŠdÉ –lšâPª\ûSÇ9s|Ñöιª ÚÏtQµ„Š03VdÁP¿o¯gó©vhžWõ²k>ʸ³nF«-¹s#K11E^CÛ S‘†ëßôÔÇ ¢ya¯XLϦ:x”(=}0M›ðÀº™Íïÿ*9»§¦k€#K*·¾·ÙÐF5©_D …ýGý’!c9xÒ =SÚâiWÕmÏÎߟ5‘d;^ X׌®MuçGúCö  ¯û{€ØTæÅ~)4@Ñ ‚]¨'ªCîz‘êǽ˜k?ë~h÷MO@¿XÁ@Su¾a¿¢7é‘`íÔÀÒËÐ ?êüßÊk&[=YÉÕ‘øêYHœ¥.éuD@?Ú ÉNBvýP°ïf’“Q@èŽj›ž;xw?×AÂd†ö©¡)UZSñÒ¿¿Ò%ñ÷MÄÑŸƒí"fA×\[c‹½,–ß¡Òé3ƒÏœ¦ž°ÄÌ "ÁÀkžF«’€^Õ°êH«…ìÓKañm¯Æ°$$¿Ç–>Kæ±eVkæWîùåú-Q$ŸÅ%2“‚£&"lúœ ž†]²Vš=ˆ›ÿ¯K5´§­è+²ºµ8kgêo6ânK[8‚7šÔG³åRâøk ¢Ô Á¯¦é«‚˜| endstream endobj 274 0 obj << /Type /Page /Contents 275 0 R /Resources 273 0 R /MediaBox [0 0 612 792] /Parent 201 0 R /Annots [ 270 0 R 271 0 R 272 0 R ] >> endobj 270 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[0 1 1] /Rect [129.068 342.393 253.713 356.341] /Subtype/Link/A<> >> endobj 271 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[0 1 1] /Rect [129.068 304.018 268.086 317.965] /Subtype/Link/A<> >> endobj 272 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[0 1 1] /Rect [456.148 304.018 604.53 317.965] /Subtype/Link/A<> >> endobj 276 0 obj << /D [274 0 R /XYZ 100.8 708.045 null] >> endobj 18 0 obj << /D [274 0 R /XYZ 100.8 688.245 null] >> endobj 22 0 obj << /D [274 0 R /XYZ 100.8 531.439 null] >> endobj 26 0 obj << /D [274 0 R /XYZ 100.8 452.309 null] >> endobj 273 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F22 239 0 R /F29 277 0 R /F36 278 0 R >> /ProcSet [ /PDF /Text ] >> endobj 282 0 obj << /Length 1737 /Filter /FlateDecode >> stream xÚ­ËrÛ6ðî¯àxz€f"˜Aì¡3²,;êø‘Zj;™$š„%&©Tç뻋e«–ÓvÒƒ­ÝÅû~ðt~tr.}Ož„¡ôæ÷^¬¹ò"?æ¾ ½yî½c‚+>FZ°é`(Øõl>ˆ%]^N¯/Ã@jv=™_L®濞œ‹èékÊW`Ðl Ù"q€ÿQºúPzmZô‡ÆÙºÐ’Ýoª¬+ê*-!îpÿv!FdéŠþºEé Giž÷/º#ô'æ.øœ ¦ä޵,î*d¯÷ä4„W–…«fÍò¢íšânƒÛTñDÄÃ0ÙO¨r¹S!·Q»0Ù|¼î¹mA‹ÌKpÖÓÊ"'pU[îÜ”¥-àÚ„çwÎy?ÊÍÆ£³‰Ëý§š:Ãf|q•‰Â")ž€PMPßuiá`[—ð{ßÔ+‚–è¼®[ÿ|r²ÝnùΠŒÌæu³ Æ÷~è_6?6_‰D™À“^lâ€W®v2 4¤:ĵ^­ ›íšš6lEêZ‡V‡BTÛhpÂ#Ûh‘ðqÓvQ#$¯×­»H€u'aÈ>š¬{Ù½­é°êZJì3·¦4©­xÝr3½Çhù1­c=ÍI„]ûŽP®³¨¡“Öô=›ðuÚ-Û—xnw• ˜ IlC¢¤Ü DØ Dž¼hÐDì\Dqc”ˆ¬V"ÝŒÇ(ùh2?ú|$ Š`ú{y X鈫XxÙêèÝßËá Iìm-ëÊ lsö½Ò›ývtŠ Ä~ t° ß’±ëÇgÓÛW¤ ÈŸ^PA©ˆk_ý/*(ÈQ!ô3œ!z6­xl{Þý.§§Ïõ䉒ðvÀ}·?¢Ÿ`É ÁÖPò8ÐOô“оí$%r€«ô“öýÀB•§ˆìæh6m“¬7r¼ð–áE•A ’„Í—Æ1Û®Œ·‡g`òÅäæj2¿ÅÌ{KÎ }{MÓvä$r©ÀøÍåï3ü;¿¡~3Iv‚ßC*Љ¯RªþVØÕ‘ñëéõ„Œ½Œs  8Ÿ´ÿçM$ˆ•›GM £€!î”A ¾lk"ÑxÀ:"”ŽjK‡g¯Gá'ìɺI 4äºT\(õcu“hBâC‘B¢9OofóÛÉ芔²þ°Ö—n] „Ï\ÛóÆ~\"ŒË¿Ýš”Ûšæhü¦í—nÓ- yþyïy³kŸº_ø°-ºû–ÜOB„ í$¦!I® W‹cBhߎXV¶£}rl}îøínH„"ûÞèA¶]6PåÃ,êç[ãlB¦i·! .¬Zbi—õ¦Ì‰œ®]ò¥ ~(¯zàiY§=]…íV·gÒn- "tUl]p “)sôø¼(îÿ@.áCÊmõÃ_EMh=ËeM_!*N»ãWˆ'Ïg,2¾À]SÃÔÛtuS@5d›;òÝ©m7d¦Œ!»Ã};×iqðªþãG ‹[g«ˆÇ¦2MÚ¹£+Ó.ñå(b§D£¶hÖä Ø7Mþ·WKsEƒ6©­,ò¼t‡6Å€»)KÚ4˜^šwü}º™jXÿÜî¬7oD즖5u¶ rï/Ì!©üßœ³W„º­¤‚áÛ׎‹ ®F˜§x†%ðR6@â~¢¿Ÿ ÞkÏèÉ×Ý— U– •ߣ²· ~ÿ;àq/‹án¿Ta~ó¾Ÿþé$Í endstream endobj 281 0 obj << /Type /Page /Contents 282 0 R /Resources 280 0 R /MediaBox [0 0 612 792] /Parent 284 0 R /Annots [ 279 0 R ] >> endobj 279 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[0 1 1] /Rect [230.044 506.635 379.727 520.582] /Subtype/Link/A<> >> endobj 283 0 obj << /D [281 0 R /XYZ 86.4 708.045 null] >> endobj 30 0 obj << /D [281 0 R /XYZ 86.4 688.245 null] >> endobj 34 0 obj << /D [281 0 R /XYZ 86.4 606.178 null] >> endobj 38 0 obj << /D [281 0 R /XYZ 86.4 392.77 null] >> endobj 280 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F22 239 0 R /F36 278 0 R >> /ProcSet [ /PDF /Text ] >> endobj 287 0 obj << /Length 113 /Filter /FlateDecode >> stream xÚMÌ1Â0 @Ñ=§ðhum‡$f,*ÞâþG@¨ ë×Ó?Dgm ÊûR â*ÂMœeW ÞðD§W\ÇÙäß™fÎ^A6s> endobj 288 0 obj << /D [286 0 R /XYZ 100.8 708.045 null] >> endobj 285 0 obj << /Font << /F17 200 0 R /F20 263 0 R >> /ProcSet [ /PDF /Text ] >> endobj 292 0 obj << /Length 1796 /Filter /FlateDecode >> stream xÚ¥XKoÜ6¾çW,‹ð2"EêÑ ‡ÔpÒÀ¾I´–ëe¬•zÄv~}g8¤¤]Ëh‹žHÉÑÌpßè·›WoÞ ±’eyÆW7»Už2¹REÊ’<_ÝlW_¢Ë½>ö¦]o’LEbýíæU¼Ú¨˜Å\úMÝõíPööÇ:á‘¡£×Me·4ý`šƒéÛ§pY,ì¿Æ*¾¼þÇí7ïy¶âœJ ”?¥˜’¾Ù#÷"‰à NddëãÐm×´Ý{rG4MËaÍ#  p<Ú Qï‚\Ϯ܈ÝAW•gUoió`¶v8ø}ûÓµ¸dR¦$¨gmMÇÖ™¨èÏ%i´5_ÁrµAEõ{OŸ «Û5ìùùCk{[ßÑB×tïÝõåÇõ&‰ŽL+C{¶ögièÍcO xß´Ì Ì3¦Tá¤NƒÔd^•Ì…•3&ŒAô--AÆ<òGúpój¨Lk”°jŽNFÓêÞ‚—Ÿ|¨a}ë4FqøXgJW欀Òzb…çI8å‘>+ë8âohœ’fî“fRD¿‡ºÙ4\ûÃù 3L­çû} lʧSÄ•‚([d7é–ò Û‚w¿W^H>o,=åLñ"}1–à‹(œHȰ8j ªzOË£n¡Ø›ŠVh7:OÆK¶z{‹–•@»"ó[[[À$¬8Ñ,‰å<@b©èb‰K ‰,xZfÁ“tb ˆP\Ïym’\1qæ>?—˜ò˜‰Iô²qö€ø¶µîMç »ðˆI©à­*:€_°WP õ?­<òÿd çâû°4u|Ù ò%3` P•‚@0sR'nùP·¸PP¢â,9ƒ•3Ø‘ðªñ_I}‰—ô·-²QŸÅº¯/Ç'àß< f-²Ø5ã±\IŸ¡SÉplÈ}›Ù1ŒE[ïÁ2Uõ´Î…3¾Œ'ÎM𠩈„©”éÎëü¢: è“M£¬ rŸÛnVoN“}ØŒgÿ*×CíͦCE* VˆâyEBHÞ7•¡·¬6 <€Íï€ /Ñ=ì]'‚0σ¹Ú”¦ë4õ™oP€~0Ý€ÊËòsetça¤ƒ5Ä 6ýñ”ð“kï[ˆ;¬SSC’Íú –äl ÁdïvgM‹P›E9Ù€fÀ²£û2h<¼û/´ÐgíÊ·Tð!”aÀJ×qHˆåªkˆT5zK3Ò 6gm }³0?0j DmôÜ<ŽþZç|ü܃u]!Ì:ã¯jZßVÃ"^Ut54ÆÚ“EhøTΔ6…”jÛôšÚ9æ÷®@›#5@ðµVF•Ùõ4;4ƒ{vàw;ô}ãYBê:Â2>ã*¼Ð9ÍÇ­½ó‰à$<’‚¥ct€/!¾ð½?:åRœä9K²1ûŽb9t§‰M{Õ/´´™ë¥ÿ, ý£ï}\ÐÌuu®Ó15¹›GMÆežÆw6„³±ããÐQS |Þ ÂlC³¹˜»˜p9V¦1³*·‘éÚÍùNÈÑq6¡‘Ý“ßóg§ª€Ë cAXI¨\â .Û³®w¾•0µ4Ùëj×ué2h&Ü#”ˆ˜¶´>VºϽÇ´¯ÀÛ¯´Z{pÞ›/™+‰K'¨OŒ—:¨Wq~‚±ý¼ Ïf°9ÃJï_nª$;ýUàÞ««›W‡Ûê endstream endobj 291 0 obj << /Type /Page /Contents 292 0 R /Resources 290 0 R /MediaBox [0 0 612 792] /Parent 284 0 R /Annots [ 289 0 R ] >> endobj 289 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [126.374 401.959 143.325 412.121] /Subtype /Link /A << /S /GoTo /D (section.2.2) >> >> endobj 293 0 obj << /D [291 0 R /XYZ 86.4 708.045 null] >> endobj 42 0 obj << /D [291 0 R /XYZ 86.4 688.245 null] >> endobj 290 0 obj << /Font << /F22 239 0 R /F17 200 0 R /F36 278 0 R /F32 264 0 R /F26 294 0 R /F24 295 0 R >> /ProcSet [ /PDF /Text ] >> endobj 298 0 obj << /Length 1510 /Filter /FlateDecode >> stream xÚµWÝ“Ó6ç¯ÈL_œ™³‘dËÜð@¯…¡À@Ú™܃ûÇJýÁþúîj¥ÄÎùàZÊ‹-ïJû¥Ýß®^ùÍ“@Ê¿·ÇŽP¯éöKæ­ Úûª¬óðЗ,Âr5 ¤D([:˜j<ü\¢ì=­;>åˆ0†+@×$<ÂÊبÊÚö¹l1`R: à±@:MÇÕ¹“[¼˜üß@Œñ¶úÒ ®åeIƒÂô|H}c<"¡úí¦¼ÀhG)—Œ±²îlJi 'H7“³H Ó_üue0véz2-}ž2øãÜN£¥BüAief楑¶¹ÒîPMÑܧõÒˆ¤þ¿UŸ7Y ¦ï= .;mæ·(J°²¥ZOE eqèb}P1¥!fAÂ‰Ò¶åºÆ{AÓÊ-¢­ù(Ú ®R˜y¿Ø Ø%ðíþ6ÆÙ‘Až¥‡<{4eFÉÝaÕë‘)]7þŸd‰‰‚©«É :ÜŠ-¬Uß4‡6űýhZ“Áз¸÷êYp»î[ãrlSÖË8v^ÂÊF'·[õéœDðoÅœ¢ÔÄ¥ ŽÝ8…ÞùUAÿ•¯¡}à ýuv”ÞÐÂVIèåz jpš#ï)Ž}×7–IrŒ£HnlÖJSDŒHØjwÊ6^ðoYVeWRe†èã„Å®¥Sõb¤| RKE|xÚÐz§šÎ¹$ð¯Œ>(ÞL!Ù¸®žãoHJc¾b£@’iÂð>š#’Ì[z[tq¹Ô«pÕÚ ›¹·Â¸{°vé“98EˆÔ2J`À¨´§Ãnn!…«J5Ã*ÈüO¡—#•ê*ÝÞÝwå¸ÒïÛD£Ck˜¿™†½Á ü5Ì;Ÿš¤†J÷c¨Åæ JÇýsÐ wÒ?‡]ó¸‘zë„·}‡«ãc;†ÿ}ƒ6ß̾‡Hq‘CIÐÓLŒÚúÐ4¥«ÇïÙ;ãWøa~­[(¢î&íJC)¤°+sæÁåâÁ?Ð’x¹ endstream endobj 297 0 obj << /Type /Page /Contents 298 0 R /Resources 296 0 R /MediaBox [0 0 612 792] /Parent 284 0 R >> endobj 299 0 obj << /D [297 0 R /XYZ 100.8 708.045 null] >> endobj 296 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F36 278 0 R /F26 294 0 R >> /ProcSet [ /PDF /Text ] >> endobj 302 0 obj << /Length 1956 /Filter /FlateDecode >> stream xÚµYKsÛ6¾çWèVjÆDˆõäg'=¦n/I4EIl)R%)§žôÇw 0$Å®\D`±Ø7€Ћ«'O߈hÅ9Ë´««í*™Z%QÊ"¥WW›Õû@0ÎÖaóàåïïÖÑP^÷-µú¶®6Ä2tei§V 2ßàO[ßTÍŽÈÇ®¼©ÚS_ßRS~ˆ¸jJ+ ÉÔ´b{fìŒV!WL©Ø¸NEÐú4òË:l¯×¡VÁŸe1€~Ä"o°‘0‚®=:zÉÁËÊÔ­ˆÁå}i¶–d,áŸ}ëHdLĶ™„eNÄ®¼îòªã~+R–fœ†í&¦¹ ®M\±­ÑHükÜS°F±‡;rtAmúª º\ôíxÈiÓF,çgüÒWkíhHn¤3Ò­@÷L1· ¸UÀ/ç ñ éÏ‚Q±6ŠÅ]Š¡šË™ÓpÛFÓnh JÒšÉ8YäÉ1Ñ0õÿ,tEÆn­òE:¾®ï>FÚE~aùc ?'Ûo÷XE’’º˜J¤m€mÍÌ)@äôÒ®V±‚Kp­p}„n¨œxDP;°[/OÝÍZrÜ`=ë—@Ni—λ)e±A¢§ô›ƒ«¨;t#“Dž2‡rJ§ÃÑßU8´op‡ÆmÙ«fÁ4ßÃI$@=PgUÁœX«ž¾M [Fè] y‡€A :vÀ{·ëU¼"ª З¶_`¬Ìa„$@±Oûª@žÆ]Ñ„éÙôª±ÚÊîÐSÖš= §j·7‰øëŠÎ4e&l}žü}Ê7]>TæðW6ÛÆ`…À ÑÈ1ÈR:Ó,xNLueë;÷Ô~¥Gè‹m{LÀîEW<œˆP6‹âù&J*£3T9s<^ŒÆ¡«ª#D§z@YRoóÓ‹–TtDX(D×wòã°œÁÐ5¡~Y×Õ‘‚‡Ô® ò¶Ã3I„<["—`à4JPki„ÏAyAgZý±Ã`ÂA9 ¹ÌC“4H%ñYRƒê çåÍ®¤û‡½'MꈵŸÛé¯hUqX•Õ7¹‡½÷V—D€7p³aIœ’x”W /R€;lCàÕÎ'T*–©lÜ–é)SzXÍÑk¥`i,Ï¥OL˜¤L'bž¦,'\±Y–Dc¸!K2ioÎ>•)W.?X¬w²[: ñM ÎžJ.Ƙϖũè|Oü¾«oÅ;ä5a:ïº\ºž,\Oï¥-Ífúü Và\¼HpÓŸ)‰Y¹À4"Φ¿§Òt:ÿK=I½^¯c¸V'£è£7ái¢} ŸÅF1!Õ² §b ºzÔóØ •wgƒ…7-KS5µøýÅÝ;ÂŽñy.ÆbjñGWM:fA˜ga.‹ïUeÉ7#Ðô>A¨úr}å÷òñ;Ý£MJ~`¥<Þ¨{ÖûKÊ…ŒY ’é\MÜ#¬y=æÏX8 é1(ˆéemŽEl±œ/: >6ÉåѺ¸ØÏŽÖ z&#øÂGKSûFW"z›+¶ï³Œ&%gLRéô³éϘ·+Çcxð:hð 4|à€.^ܳ÷$h06"Ró¬=XžÂAÑ =;] øÄQ‡ñp¦óÖ`Gœ5eâ†\Þ +û\gÍ—F"B$AÌ{&ÒÎA쉽£LÒS¨yù¶× N® î%:þD-\]šå{nõ ÒtZÞhÇ—ö÷v–aö’ˆfäu»³ÿ áKý> endobj 303 0 obj << /D [301 0 R /XYZ 86.4 708.045 null] >> endobj 46 0 obj << /D [301 0 R /XYZ 86.4 382.692 null] >> endobj 300 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F36 278 0 R /F26 294 0 R /F22 239 0 R /F24 295 0 R /F27 304 0 R >> /ProcSet [ /PDF /Text ] >> endobj 307 0 obj << /Length 2200 /Filter /FlateDecode >> stream xÚí[ßoÛ8~ï_áGˆ¹âojûÐíe÷z¸Û.¶¹md[M„s$C’Ó&¸?þ8$%K åÈŽ\ìbó$™¢f¨™á÷ÍôW¯¾û ËÆ(âœÌ®>Ïp"5“¡B!㳫õìC€ÉüÓÕß¿û‰„펊 ²Yhû¼ùÛë_¯.›/(Aó…$xóî—÷W¿Í‰ þõæêí¿/íÓ÷ïþñö¯ööçËwÿ¼Ô=þc[>†<|óþg}ÁV)m¥ NPÄf Š‘änx«]q—еc§;‹Á¢cß&>¡”i™QÝë‡ù‚cnâ‰b|/rëˆ R‚Ö}þâ³ qIf ÌcÂöüêz²™D‘ 1tHpè†dD;|*’”ÌZ½.¼ƒ'ˆî}vïQÇ‘výyÔ=xÕ1zŠ:cS Ú:aψ!ßXB׋wM-ý¦f‡Ü!E³V·#l-ý¶ž\߃W_cìãô D0A8¤]ãgåÀ|àÚMaÇw®±óú;÷\Xð?û‹Ú_Ÿ¼_-$×¢·ÞS’ûB¬c†åýÛ£­Ë›O˜lNãIQÍ<ЇPR¶Q’òáy©³#‘ž¼žµ1cãPRx -öóUã(PDGÈIô1‚ !ò B‡Q9—>¡€mdopÃ|ÚÉ(4¸Ýb¾AtD|_¤-½5pÙÉTå©Ã„|2UyLD”g½ìx•ØéP@‚aëkZº;È`;‹xîJrÁ“ÍÄ)|Ãâ¨I?üÜGLÒ#¿=.â¿né84ÏÎÄãÔ=²éqڦ㿣æËó9NÝTü7NÛtÆ,¼’`™½¸a¬Ç¢´Å¢Poo’"qi鵫p]‘\—p領´ó_׃‰¿fÐ|îíW¾q)MíG ª'®—É…ôEÃj6ÕéEÃH‘Ç"ñ1誄&°è™à…f]¾=6\C+纊—'ùìùh0NÝTh0NÛ0ðÉЀ>‰Xaê¶Ž?YÌÃ0H6›t[¥+û«¦Ò È…I;}&:?«ázš˜„›Ö¢‘ô/Lõ'‰ˆ˜"Àø¹óLãÛ8uŽ…,͹ÑåÕÀ ‘Hôƒjtq GU^x!†ÃvT“¿ÝùÓð¨qâ@2O’¢a²/Þò‰ ¾¯ˆL׿£M^/Ò:€Ôœv“nõdŸœ>zÑ„zYS_‘”6tõ;ÜÜûQFˆ)ÑGõ¼—|bík¹ß×ú@¤ü]Bä± ÓWŸàÑyŒ9NÝTƧm:c~ñèÓØ,ΙCêΙã>îa`˃Á>Ö¥cY¿DåmÖj(ÊÓ5€QÈÚy8Jƒ·¦8$%-RïÆ7c.ËÔ6ÒϪÜ>ºMÊ×b©M'ßÚKz¸~Bœå éÞ¤Õ…SèßBë®tZ—¶ît¯î\ØyübŠÆò¦UzèŒ4ƒ$„´·Hï-N¶ 12}ë=‹„¤wÆ øºèe‹åÛo±Ð§|×=g¶ÐG$w¤AÂÑÉÞyAÙB\Eà0âM¾,Ò`Ü¡Zì…U;{±O¥}J‚m¬‘s“lì/+s5ˆ©ˆšS …†Ç¸J¬P²º©„ƒ”0L„7ju¥=ÿ¬R8O‘¬öñU÷ÄÄêæõ)ËÒÈ€ýã¼ÈÌ¡ "q„w©L"ްˆâ¤Bö¨}ßq…ì3ÏWÈÓEu¾Â­—úÎWàöŸs–þ•]òždð?øY r¢ÁMñûêòêÕÿÉñX2 endstream endobj 306 0 obj << /Type /Page /Contents 307 0 R /Resources 305 0 R /MediaBox [0 0 612 792] /Parent 284 0 R >> endobj 308 0 obj << /D [306 0 R /XYZ 100.8 708.045 null] >> endobj 50 0 obj << /D [306 0 R /XYZ 100.8 552.36 null] >> endobj 309 0 obj << /D [306 0 R /XYZ 100.8 500.694 null] >> endobj 310 0 obj << /D [306 0 R /XYZ 100.8 421.077 null] >> endobj 311 0 obj << /D [306 0 R /XYZ 100.8 356.925 null] >> endobj 312 0 obj << /D [306 0 R /XYZ 100.8 307.219 null] >> endobj 313 0 obj << /D [306 0 R /XYZ 100.8 243.067 null] >> endobj 314 0 obj << /D [306 0 R /XYZ 100.8 166.019 null] >> endobj 315 0 obj << /D [306 0 R /XYZ 100.8 100.318 null] >> endobj 305 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F36 278 0 R /F26 294 0 R /F24 295 0 R /F27 304 0 R /F22 239 0 R >> /ProcSet [ /PDF /Text ] >> endobj 318 0 obj << /Length 2237 /Filter /FlateDecode >> stream xÚÍ]oÛÈñ=¿B îí'w÷ äp àâ®-Zá^š>Ð"c±‘Iƒ¤ÏÖýúÎì,)RYÛ  E€p5;;3;ß³þiû懒¯„`¹1rµý´rÓ+ËãÚ¬¶åê_‰d’­S›‰äÝZp—üÿçÉ»ë_ÞýôËûuªd–üý׿^o¯{ÿÏõ¿·ùჰs’*w,ËõŠ=¡Ies¤TiÅ2›ÁB0kï¶öíMWï>¯S#tò‘N§åâ´ÍYnÍÈ¡(veÌbdLÀ…R +ÂzЉa˜ÌÌj†µ‰±’)®¿ŽÝ1ÆNÃoÄM/¸ýã&8Ë‘ô íêu~7~(¶ý>ʼŒÝ·RæeÜ.T&8§ˆù*e°Ri™¶Ž°•Î9¸>Oî×°›´‡ã¾*»¶A Hêž¾eõ‘ ÝT%áÞ¬õH[}új ½ö†®.šÛC(|j»»º¹%œpfwh{")ÎÙ3¼ÇJ€*ŒUh¦Çlð¡îúaØYŽt¤Éˆ·4ÆóÆo V7(çÐ°î »\‹d¼Ò±<öUCH° ‹“øø³èü¶þ‰Žø£&F®Ž¸ºd fuƒìê]ÕÓx¸LF—Ù"; ™±Ó*OîìC?Ðæ¿NÀl»º¢{á=JîÚ‚U] Zõø;|~¬ûŠh>úK"v@h?{ƒx¢tº Âe,"o ¢ü§Ú è=ÊÐ þÔ€.Üü‘Ì  /] RuYõ»®Wê ± ­¡º‚p߯<^HÌg^\n«›®¨wªŒ Ü·‡º¤Ô}‚àÊ$?Ò{¯D/‚0½ó ü»¢3bZ›„oÄGAà«+rU£ Ý’»Ø¨ h#A½Q ØÈ&p€HÀ×S¡D9]’a0 ép…Ãñ*øš3+ÄRcù)޹Àk½=Ê#”#üVOk 䇾F!ƒ¿³„€?Ç0ð(CÀ¹ïZD:TÄuû¸¯½[î c_TïyžÎèéð£ e‰K•\¤Ày~:G÷7äù¥È›V øN>AœÈŸñë’ÝCG¡Ž¦Ø`–’§Ä§|òÁÏ}1ìé^0ÕÏô]ÐÇšrqþwŒˆ§¶‹U ™ÃÕl>J[Æ.”1î¦û q­J®¢öò>¤Œ`F™3UµMÖÝÑÕ5ˆÔÓ÷˶RÃU²];HõŸ½¬—>gI/VðrÁ$ôUAÀûØ –qí&›4DÛ'cÏ„t¬GíÁ¢«‰¤ª3T4ÂCSéX Áù¹`JêåÝH·c…Zâ¨vÀ—*,î¾ç‹?êfÜõeÄoS܈¤ž“ ÓƒLÈICLšIhf¦Yr{ ÊÇõîa8“–"§õBaY\r<¿Ö¡hÂòTË(Ï8Ãæ×yžyá>†e\¾hÖ.,¦¾±)£.™àæE­`òš}TZ‘4ÐP\Ë„®ácH$XÓ DÒ`ÕádØ‘§4½ýbƒÐA9æ G¹!'í¬ .Bc'μÌStä–c].” ~L˺É}‚U+Ì¢ÚF²rR÷1®nm&ïyûãsF³ö,È|©m'§„ó‘s Xáç³ +>i†‹¯a&bd 㙽-S5ê¬\•ÓcâhÐD0&ÀØÁ¦*Ïì‰ûÅ¡oψœWq„9“üõo[9¨Y™àÉu æ“È´+zO›'»e´ò-@Ok(™áºüÔ6QÃö¤a€x »ÙHŠ?hŠŸmO%ýÄ^ÑMó~DÊÓ½ý¸,f®4ØZ:–Ot—Ù‹¼+£`å§\x©á{ºT&“þ.LÉÃ-—A/ͰQðö ºHè8ÆF2+† ˜M™~W:  ß]²Ài(º!©eéöó÷Ò1BÖ¤6¥Içņz²ûûCÝ„µ75Žÿâu±ÃÚ¯4g!¥ƒEã;û@¥Ç”:—>f*Šáí#Õ3™^F$i•¹:÷€Q6ǽ®òüÛÕZ„ùÞ pæï2ùi Å­ÁO2AS8Sk°Z™óq²õ}ým à Z<ìâ"ùüºçt⬤¹SÔø^âÇLL#"ýœMÈT »óÃN1Lyìõ: ¢Mšºüé:ôñ0.ò¿aÎ.ß’EôÙRª©Œ\EËôWÂ}eAúVã)Hÿÿþˆ $¾úü2ä3™×Mf¿‹†äÿ›É^×Ð¥&ÛQÚe·ij3aãùÇz+ǧšy0Sù2«îðaX÷e}„ñe®§Ÿ”o†×Ûº! ¯!óÍÓTC>9|j`WÖM1úc?TwsJô¼)SróÏRrþ,Eo`}ÿpG­‘†jº/Â> 6@£'¶C]'ÇB1oPæ'cßRÌâãô7ìýkO¬×Ã2/°Ëس¤…6_OÓ«’P¹tgã“øjF­NžÉYÓiG»Y°H=Óly)a‡šOÌšÏñ3–º:3s'ÿ „‘†æªyÃ^“ ³Xÿ§…ˆjÁœXFszñã|¬´s+q&ñ|4.âP›±±šú.¢óVÛ2Ë×É€7uµô–É©ÉAôSÈCG|Ûú(>Lx‘[ ãàBB{¾y¿}ó_K-x] endstream endobj 317 0 obj << /Type /Page /Contents 318 0 R /Resources 316 0 R /MediaBox [0 0 612 792] /Parent 323 0 R >> endobj 319 0 obj << /D [317 0 R /XYZ 86.4 708.045 null] >> endobj 320 0 obj << /D [317 0 R /XYZ 86.4 666.431 null] >> endobj 321 0 obj << /D [317 0 R /XYZ 86.4 525.487 null] >> endobj 322 0 obj << /D [317 0 R /XYZ 86.4 238.674 null] >> endobj 316 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F36 278 0 R /F26 294 0 R /F27 304 0 R /F32 264 0 R /F29 277 0 R /F24 295 0 R >> /ProcSet [ /PDF /Text ] >> endobj 326 0 obj << /Length 1547 /Filter /FlateDecode >> stream xÚÙnÛFð=_!ô‰¤ w¹¼êH]§u¸ˆÕE’Š\[[S¤@R±Ý¯ïÌÎ’:Nò hfwvî‹?,^¼|-㉔" C5Y\O¤ï‹dû‰ðu8Y“wžÔÓ‹_^¾Vþ>a¢„òõÄ'š³Ÿ_ý±8;*ò”˜ÎãHyg—o®o§*öþ<[\üuN·W—¿]üHàOç—¿ŸE"½èä½úgW?ÁŸd¡j"c¡d¨Q蜥Î)âõS"˜Î¥T¡wµm®³Ü«8ô. SMéuö½/užu¶®ˆç¡Åþd®"‘FÌí¢šÎUxoLwc¬<ÛÑ™mé±W·­]–†Hºš®òºj»f›ó‹McÛu6E-r:Y›ve˜ÏÒñ1ºènªÏ–Þâß’ií ÐPyw+Ó´Õ—Zh‘ú07äËþ b±·ÊPÀGdÉ÷¨2Þ°ümErç5PÜDeî7¥ÍmgÊ¢´³Y¢7¦î£(uÉ ïl·¢{&ŒÀGëuVŒ Ú†J…Š´‹ˆŸ(2ÉB ;{ bC©½¼¬[³3-”¡w̨<%’W§GcŸ‘$¯[Yç,å]›¬Û6†º±7¶ÊJ2\Q¤2¦/ i†ÿ ~_78m”<Þ<êt›áaq„¼Àè07æÊ®R^c²¶®1ÅÛ‘Ð÷nu>®²µÁ*»2:Hù *Hèáåk#+©n6Yo;Ó´ßyO‘ÐIÔ>ú­5¥É‘Å^Ù¦—2>Àq…,‰ÇrÀ$èùÏ»²>9Fk(¶õ5ż«7”æ#fiIX½üT9}¢Î yÊ•(IÖða]õi>t_»¢M¨B]ѺޏöÊõÆ£Œ‹¦¬ÅžBã¿ÁO…m('ïŽïOgÇðûïôÃç<ÁoáÒ^KzBWŸc§Àÿ¡S ²mÑ#Ùë±$“1Ä<¥½ÅflîàI,{§(C/³ÚU½-‹éË­-;˜3Q¹–íÔDC°0 E†"MÓGõ‘a)j­¼Š{;Âïe +cŠ–Ð•)7߸Äp>ì²°º™‘ 8ˆÛðÚ9 þo«šøáã!F„Ö×ceŒíÎ5“½¹Å¹<®bå»NæÞßgëMiF‹6ŒE §þ=Mú1„ÔvYÓ!¨¸S#”Ñ_þPÚªÀl8¼vö8º{Ì„n,M–ŠÐ%"¨yjrÇäH±fÀž2VZ„a°k<¾?f*ôö4é‰úntP7¡HvlF'D(”VÿÛy„=…vÌ—žëÐ*ö•zŒ·Ž„ÔêË”£ûÑWp¡i…cG˜º… ï²1·öù¶£ƒ>ÔxèB‡›2«L;Ú´’Tè`pÌFŽÎ˜P„ƒbOm Jøé`ßF=Ëý½·.ùpuš>Ê>ž©WÕÚx›5–fÞ4kp›˜€Ò"•ö#%åºpÍãÏ1ÛàzØÀzaJÊ’ƒw4aú·mw“Q1±ûk ôÆ‚ÁÃ"u°mòà⸵‘ò€(dY·dà)Í:hи•bO7b6ÖÓÊšjÿ–†aioݶ;×6û¯Ý!ܤÃ÷§a8“þl|ýž€9áËdÖB"Äý÷„æï‰_¡Ãк«x3jjØ÷Ý®…€»i€Kâí> endobj 327 0 obj << /D [325 0 R /XYZ 100.8 708.045 null] >> endobj 54 0 obj << /D [325 0 R /XYZ 100.8 688.245 null] >> endobj 328 0 obj << /D [325 0 R /XYZ 100.8 546.823 null] >> endobj 58 0 obj << /D [325 0 R /XYZ 100.8 298.555 null] >> endobj 62 0 obj << /D [325 0 R /XYZ 100.8 263.427 null] >> endobj 324 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F22 239 0 R /F36 278 0 R /F29 277 0 R /F32 264 0 R /F26 294 0 R >> /ProcSet [ /PDF /Text ] >> endobj 331 0 obj << /Length 973 /Filter /FlateDecode >> stream xÚíUKoÜ6¾ûWèÈ"F¤H=jôàÀÉ¡iíÂÙ"‡¶­D{kÅ…D!ÝŸ>ä•-Ç@/½ôÄáp8o¾!?l/ÞâIÄ-¥äÑö>*2*¢<)h"d´m¢? §‚nâ ôdÔàÄc5Ì2/ÈnÃÈ„õg©ºQ?»yC¹pñ¾ª½jç0xð +Vjµ8žå4e!íã [ífB¥˜M«¾Yõ—R.Ÿ»ãkîxF™œÃîÈ‚l¡PWUA5N]€Oäà7]ÂgAf)™úÑ7¼nÿJ˜P xiÞ F´3ƒPä€[¸é¹†(³ ,é•;©-—@hÞ j„|­êP,Þb¤^fÁ(ž nwØ¡“<Óöntpð’Ñ"ü‘?Ê ä®}p#ºÚ}=þäÓÌi–”gœ¤t>Fݵ €Ï„ÍI~vK=í”?é§B>[6{À¢=ÂÑðð•IBù;g$Òeг®˜í ¸È.]¶œ#H©Èl¶qH74CUx²8„d\’kõ z5TF58&’¨æAkÐ'àŒS–yâ,/ra/BóG·«å„{=õÞbÔeÚƒ²ïìwvýJ)MÛuNYWÓè}˜AOÀ±ÑRR+ë¸Wƒ¥æ¶|\K >bØR}ï•[êS×ö}#àðˆÃç‘wfë¡õª& ñ¿a]2“Àl¨°Ý= ]ö}gaÎ/ $öÞ‚ >“K$fÒ» ƒ©·CÅ/bÍ’åèüÀ9[qn)þâ`¦n¯p õ%‚~<‚žV÷ZnbäSØgÜ1vF¨"^®ÍB¼èuqöûrxtí$X ßH\+·4ç3ƒ x|ÓíÊ)¾á_£‡Ç¸ÜÜœ{1Ú­ã±kW…˜á%DK‡þãu[uÝéEÃëï>=íÇÅt9ñŠ^÷q³œóÌ~©ãÿð À^Ú'Š{9W=…~ÕÌú×~#¬áM/" ³ZÀk£TŸœîÇ6{ü> endobj 332 0 obj << /D [330 0 R /XYZ 86.4 708.045 null] >> endobj 66 0 obj << /D [330 0 R /XYZ 86.4 590.155 null] >> endobj 329 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F32 264 0 R /F36 278 0 R /F22 239 0 R >> /ProcSet [ /PDF /Text ] >> endobj 335 0 obj << /Length 135 /Filter /FlateDecode >> stream xÚM;Â0D{ŸbK»ˆ³»ÄJ0N‚â âþG È ÕŒæ=i¶¢ÚžÙµs òB´F‹yÃC“7/9´=ã¿Ù2v€ÕIûÍEòlš{ÍÖ4Á³NÓ¹Èl8èk’ñ–+-ÓqÜÕ:äé”#’¾×å‰S– ß©Ê¢¾Êr%L endstream endobj 334 0 obj << /Type /Page /Contents 335 0 R /Resources 333 0 R /MediaBox [0 0 612 792] /Parent 323 0 R >> endobj 336 0 obj << /D [334 0 R /XYZ 100.8 708.045 null] >> endobj 333 0 obj << /Font << /F17 200 0 R /F20 263 0 R >> /ProcSet [ /PDF /Text ] >> endobj 340 0 obj << /Length 1510 /Filter /FlateDecode >> stream xÚ•WKsÛ6¾çWhz)4Ñ¾Ž‰ã¸é#ÉŒÕé¡é&!‰3$¡‚”-÷×w )9òtz‹Å¾÷ô~ýæê£R ¥£¼Èåb½YY¤i ¿R/ÖõâOq½3ûÑúå*ÉS‘,ÿZÿ¼ˆ+]Fe‘³Ä—q7íßZ×ÙÑ?ñêã²ÔÂùÎŒž#[2”L5Ú5™ŒJ°š$’Ë•”*¿M¿eŸnoî®îÖ7_Ïô76(”ùB‚Š4UA¡Ê¢,8ŽGá”΄ék$r!Ë[f £é—RÔÆ{¬–*;.H¤6! : æ^¿ûÀœo±Ô­¢%ä%×®G £7”Ø€DM ”:Ò:cOïÖ¿ÂI™0jÆ·°NÒ‚–ŠC@©Ú¶ÍÃR“ „¾öhª‘y»÷v°ìD܆¿ãŽcDz;ÕœÁD‰Úñ·w#àë~ïª?6!˻͈©H¥øÔ3ÃùšZÈ1h8 Aø´Ä p;—˜¶ŸP¹;ðbg0àdÙguümz¨kÛ¢ˆŸoÖ·7Ÿ™~l d¢°@¤âË~¹B}ýµ*S[Þ>édXýb}oƒ:3ð·¶Cå›{>\3¯éY§Œt”Dgž¥ìÙonÀÌ¥±\ÛPÏ•¢ƒœ@\`[жµ~`‰ +Š„=²Î‡³So—‚z8!@Í͘Ʃø‰ŠóH}ÂyóoQ.ƒmÏJ TùôÅ& ™‘y(>” ‰3cÀóê×ð§³ãž´¶»`³ v„ÌÄ=%Ábë@aï·f5 °Ø˜¦0 ÎS‘€ Ín2œçr«Œsãôà:™ÁiÆ’\G2)@Ë3–œÀК€mf…kÝ–ð.7Ç}ë¼õWÈwHTçN©7K'åÑ%p\%q•qP+£XN©¾‡HBÿ Ž|H'œ^øb±´&8D,lþ¡–† n¦™fLKÎÇ€•|‹Ó8àBpX’åy¾y¼Aöež˜ßM¿ºT½í¡%q"à¤h8¿15z–åâB^¬) ü¾l-Ÿ@_‘÷ÂWdU®Û·M5kß?»¦B÷v¼¤þGbn!8tÁÛ2ZÂŒwÓ%"§ëB ÈÌÖÜéøÒÈ ñ®ÜÛPH B „@¾@>à<úf c{7žùaà¥èyÕ¸žòOÆW—€ =ê°**Õ”0•bq±ü½e.5 3FƒË*+ SÖ¡G4pTX 18þZ3wpBS‚lÝ@8Yuhqˆqøà¹ »9g¤ÞÙÏ„« ‡ûìéþúÝ‘”/F΀zU¢—‡ Ì4™ÀÖžLÔÏÏ*`4S¬nĦWõ<â'-“)ybT'…`øÆæ¦÷5²óá»m¸OúÀ_øûÒ‘DÉ_` ð:o¶;LëÈ;èfPÃm &鿦öð|®xéé% 5{µ¿Ÿ£é½ùEÀz)Þá[dÊp¶áAßórêq ÏUt—ßsfؾ¯Ã†Q„FZÑ•Ž¡^ò…—³þÚ«þñ½ oM.EYFð× ŒŠ¢àðdŽ{onÖoþdaµã endstream endobj 339 0 obj << /Type /Page /Contents 340 0 R /Resources 338 0 R /MediaBox [0 0 612 792] /Parent 323 0 R /Annots [ 337 0 R ] >> endobj 337 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [468.489 411.186 494.544 423.805] /Subtype /Link /A << /S /GoTo /D (subsection.1.4.3) >> >> endobj 341 0 obj << /D [339 0 R /XYZ 86.4 708.045 null] >> endobj 70 0 obj << /D [339 0 R /XYZ 86.4 688.245 null] >> endobj 74 0 obj << /D [339 0 R /XYZ 86.4 501.756 null] >> endobj 78 0 obj << /D [339 0 R /XYZ 86.4 349.262 null] >> endobj 82 0 obj << /D [339 0 R /XYZ 86.4 144.375 null] >> endobj 338 0 obj << /Font << /F22 239 0 R /F17 200 0 R >> /ProcSet [ /PDF /Text ] >> endobj 344 0 obj << /Length 1582 /Filter /FlateDecode >> stream xÚ½X_Û6 ï§È£¨Uý³-oÀ€®»k7 èÐåehûà‹•‹ZÇl§½+öáG‰rbû”»;ì%‘)Ф¨)Š¿.Ÿ½¸bÙ‚1’' _,× F)Q‹Œ*Be²X–‹SŸ–¼¸ât˜PÂEº ÈôêÍË?——ï/bÁÓH‹8Kyônùf ½¾|÷örùþBñèoKÉ¢« øy÷þíKK[þ…:¦ÆÄƒ’X0’%ÞžÝE +S[}º)£åFƒ\Pº+ú•ÙØO™ÉEߺªÌ®7+OmWH^·ÍG#ñ*ê‘Æð¯o¼Š‰8'žÃÆ¢n?ÖÞoŠ×ôhŸˆ*SëÎî\3I¤L½Ÿc޾*ê]Äcá)­ÆA_Ô7ú°q+„e$Iò©¤ß{äv{^oo×™ëjÔàÔ¾ó„Ò|¤LèV6Än햖Ͷ0u‡Äo¦ßàâ~cO»ó–-2’g”9N•`Ér|&$°B©ÅˆËzƒñèUÕ¸³«û fýâ†xd`Ý= A lÖÅqg¾koØÌú”°ÁöMȦ”d"8>Ò„†ÄHbžé6,&=r€†g%iB”̦‡eº £‘BÍl¸¶¬c/¿†Cÿ5×!“¸ NeÄþ"¨—ÉŸæ|ŒfÇ«ŸïdšD7Usmq(Ór_[lu¯Ã œä Ûåc'¤R*’ 10–º[µîPѦ±¨ù†ëðÌÅTêadgŒðÐx’ŧgæ‹$«VvÙ\pŸÍaÂYyŒ* 4küï–I0&ù»ð©¢õ¾^õ¦©CŒ’œæbYƒeñƒXvƺh„to³¯K] ÜyeùäZ\•Ìœù¹ L®Äd·!ûÂÓ Êþ÷°žor"æ3À)WÀËe0(ùxF` :ò†PDd°W&Õ œ{“œ¨CeÃB7L%‹x$ë%Þb‰»$ìßýKÁR¯mYq7a|àžH9ÜòGºÿ”GÄôˆëÔμ-U>sC _|Û4•Æðà;1‹_}³Ô æº"[ŠÄG60 Õ€eô!Ü|ñåDe¾X©ú§SxîÀéKê·üjß~Õ/CÕÕó©zª[nƒÀ` CWË :fÇ5´Âpòlw'„ñ3…ɱ°Ãu"OÀà!q—á ¡¤†6 ñN!$ä˜Û÷%› ­Þ…¡K(ŒF|wO*íô*ÎÃm”ÑÜ{a` –奩BîVDƒd¬é1(ˆA^û¤ò>ÀÉ’ˆÛ?ýƒ_¿>á×Î4fîcÒ8q©„Ø!ý.?&ê3m8¼S%gÄ ©©ƒvAžI!Ï<­£ÄyŽòxHü÷ìʇ $ʪ`9û<ä“9Ú³èôÉ¥®‚;QŒ“Õî÷¦ç Ëû¸g'à~Ôh ýÐYÙû‰ÇQ=ÉËA½¼|¶^~žÞl{ Þ3ÕŸQÆhv£žsÌsA >‰EFhʦ¹{V{DZØvµFžù牮o³ßÚúÁ¿YZäp`˜õž‡ßJ”dòfêîqC¼Yääž6 ;´$¬1C ¥°“•J]~uµO{ç¹GE¶*R Õ?›•b}áZ&‚²¡A#´‰RßÀAbÀ>¿Ðõª(–±¨ÒëÞO¹žÔg$º57›¡zgJíŹýŽYG[ &Ÿß+?áE%"ŠóØÆPewºE•8³n<§ïfˆHßöž¨¶…d}LÝ빞1…qn »~êÐôê­_ECÏc‹3Ûf² -üï7­Ö8œÊ³4™º4+÷ȆuSUøÎ¶Vg*º2uQUw¶ÍõXì²xlX ø²pã¡À§Ù°J¹^dÈü£fì2>»\>ûžêM endstream endobj 343 0 obj << /Type /Page /Contents 344 0 R /Resources 342 0 R /MediaBox [0 0 612 792] /Parent 323 0 R >> endobj 345 0 obj << /D [343 0 R /XYZ 100.8 708.045 null] >> endobj 342 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F36 278 0 R /F27 304 0 R /F26 294 0 R /F29 277 0 R /F30 346 0 R /F24 295 0 R >> /ProcSet [ /PDF /Text ] >> endobj 349 0 obj << /Length 1151 /Filter /FlateDecode >> stream xÚ¥VKÛ6¾ï¯r’#R|Hí-Eh¶‡ø4=h-Ú K†%Ç_ß!gDÙ^ݶ¾˜š‡ß|ä̧åÓÇ!"!™É –ë(×LFªÐL(-«èÏø§m¹ìa‘dFÅrñ×ò×(•2. ´øÍö[T—m…‹Ï]sê®Å¯—E!ãî°+‡Þù|á&âœJ ·§ '™Î8†û²ÈEÜk¯JC±=ï‰0f@Ívµ=*‡ÿKrêŽûÆ¢¨[£ìkÊå‚Ç^ ŸkL‡-¥%¤»#óò@½mÖIe[k«gæ tv„—LJ)wÃÖ#$4€DûÐ(aËC…‚iK™©x¹µèp¿ÑCa´ZwMÓ-@rªÛMÿ¥ㆠîJåa”‚¥)Á(_$œ uSŸÏõÕRIêÆ~§B³B òéæÒØeë°–QI8!ƇãÃÊÇc —·/((°  Ýüy¾Õ•½ ¨c8f"r°kð{÷&ºŽ+ÛöõàÜ/‹œÇÒB¤ ¦Íg eσsõÄÔ.yØéØøõê F°dâ–"gV)Fa»þ:žÌp¬€[JÇ¿¬1ú„‚ÖñÉ}®Ä¨F kÈÆ’`K t€áu¬4‘û½‡Ï®êõ%5íP·‘„‹”åP`Fa²h_y&a€fHÁ?öC 5îÚþÃ3Jª®lº š#f¾’çgíË ±wŒ…rG¾Ìç¬Uªð˜œø:]ˆ âRb}½¬)Ÿé[À“1pV ŒÓîç v—AI_p‘Å×Q²å³bt£Ã(ÙŠ9¿Ù@PÂSQÄ—°º†Õv>ݶ¹“R‘Î}8EŽdg´6hí?œ²ÇìÃ9ƒìlƒÖ­ý0ôp&ÂaZ^§åÙNÓòJË,¨šï¿Xi®Þtƒ—ÁÐe˜á–,åáZc)ãsÍò4ØPª‘¢½ï E¼©¿¹—͏íëÈ\£éb÷(©”ží»à‰f*-Æ Îdc"à “ú¦¬™Û„3SdhUÏEÊX—éÆêG@ο> endobj 350 0 obj << /D [348 0 R /XYZ 86.4 708.045 null] >> endobj 86 0 obj << /D [348 0 R /XYZ 86.4 688.245 null] >> endobj 90 0 obj << /D [348 0 R /XYZ 86.4 454.955 null] >> endobj 94 0 obj << /D [348 0 R /XYZ 86.4 116.46 null] >> endobj 347 0 obj << /Font << /F22 239 0 R /F17 200 0 R /F32 264 0 R /F36 278 0 R /F26 294 0 R /F27 304 0 R >> /ProcSet [ /PDF /Text ] >> endobj 354 0 obj << /Length 1553 /Filter /FlateDecode >> stream xÚµXMsÛ6½çWèHM+_ÉÎôà&ö$&îÄê©é–(›S‰tH*‰ó뻋]Ф[öLzÀÅbw÷°Xè·å‹—*™)%²8Ö³åf¦¤é,‘©6ž-׳¿#-çÿ,y¡åDÑ8a¬›IRzõæìÏåù‡ùÂhY1_$NGïίÞäìýkì$ÑÕå-ß^¾'ñÅD—ÞÍS-¯ÈÏ4 …ÒZH“ÍF‰$æ˜x°™Œªz¾ë¢Å¹3ea^ s¬°›W=ÛtEƒîtÔÝØQQ…~÷;ü½özz®¢ uG¦ûÉMAÝ ªm·5ÎÿÂÃ95Û²íÈG½ámsãåèX )ã~Û¾†–섃kü²’%³^ã>lC™d°™(¯ÖÁ2‘*Óë~ Y‹E–¨^c±¢©›uYå]¿?´^€IÆÂ¥ÉÞyíŠöv1l­ 9=nÚˆX¦L;†øó\§Q½Ýï bP±-v°ý…ǰ;{š±w¤K{êqO£^£ÞÂÄ|£3ô”¢'/éi“6õ˜4F#ÌyÃBÑ5ùm±nrZ²œ{ž¯ÐÐ-(»ìàÖG‚$2j«ò£T¶XÓè5jÞ“…Âv½X×»¼¬è;@y¤E*=-ü\Ëš=:$-«u¹ê‘: {ÙÃ:ž-Ï¡±¶Ë›Žº_Êî–4Ô#ÈF¾Ý7@:_?€qvmí…¶: ;j :¨€ž¼Žv¿=jØcžzÌQÀNcŽ"² Óš2¯n¶¸w +“äÀNN × A®S†"†PÇuìS^èOæ¾Zç ­`f xte]‘$L ,õT@Ú¬ø \RÑÿÇHLz¦¡Ul}ê‡Ì¤] )%Ö19¬€Ø”Ò1\™Š»;¤)ÕÍ.ïè[¿%2ˆX;¡Óø(â‹yªØ|é×Ônz{âª&æÁjIrÈiC(«^e±ÂýnéyjdâIždéô;BŒ&ß슮:Éq«b ;Á+ ØóÑž)ôeû:$8”0ÙqÊ„ì8–“œ¨>6Þ›Á3s*ÁY;V'Op6%8=$8Ë ö6î¶eUpA¢»¼{y åYæ9ª°50ëñóÙŸ‡«9äÄ…5qô 6Õ¯e€IÞ~ÇòÓ—Ý+ NÚÏÌx6指?ç;6Ä”ñ°í¯ìƒô:ä<6Õ°±ß Öyb.ŒLƒ>Å=Q'ç´.€ôÀ­†zŽ/;$6mzü`8©4_Ú¨0­.–ñQÆÒÆuCxY)Å´ëÝ%Ó¬èžÁ!L,s\íI™g—ÅxÕÐí‘dá‚þFK¸4H©&æ™ ÏC(È©ák‘Œ„ªO ÁûhAœ‰ìPí>TÄj¡ µ>VÃ%’¸GŠØñBqKü.ëÔ‰8;Ú»§±–¹ÁVCVoÊU)Òí‚·ò©“í˜´Ø çyGU¶}^´Î`BĺÁŸ6\"[jxxšßA“ Ÿé Q}¨H°°ðGs:+¿4¤·ƒÂb8òV©ÁôG9?Ë–Ú›ò3J‹Š>ûS}¾òTä¨a$ Å­ÊQSœ“Æs®Uy‡,ó§}zG¹ˆòO½½¯ê]™o9%‚eï¸ó0“ÂfΓ@ÇŠ·‚-¼Û²D*zQIƒhCA`¹ ™³"1P Z_¶ð½hfxŒx:DÿD˜<ŽÔ~ y„.<Ýûcò´Ðõ“B¿†ŽÏÔ§„ž=1tõ¼ÐÍÓv=˜PTì©#pHö9D8Nqfø_à‡? À; (…qóÃraW2žô+ß4’Á§…‘J8pCo‹¬ÏÖ–ßWýƒŸôŽÛoó_P(Á¬·-žðÀ¸Ä4§<òŠ:ÅWN+ø BAWSKo/è”»#M¥ éP3> endobj 355 0 obj << /D [353 0 R /XYZ 100.8 708.045 null] >> endobj 356 0 obj << /D [353 0 R /XYZ 100.8 688.245 null] >> endobj 357 0 obj << /D [353 0 R /XYZ 100.8 642.867 null] >> endobj 358 0 obj << /D [353 0 R /XYZ 100.8 576.021 null] >> endobj 98 0 obj << /D [353 0 R /XYZ 100.8 496.155 null] >> endobj 359 0 obj << /D [353 0 R /XYZ 100.8 440.808 null] >> endobj 360 0 obj << /D [353 0 R /XYZ 100.8 373.961 null] >> endobj 361 0 obj << /D [353 0 R /XYZ 100.8 306.451 null] >> endobj 362 0 obj << /D [353 0 R /XYZ 100.8 257.04 null] >> endobj 102 0 obj << /D [353 0 R /XYZ 100.8 151.598 null] >> endobj 363 0 obj << /D [353 0 R /XYZ 100.8 100.664 null] >> endobj 352 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F26 294 0 R /F22 239 0 R /F24 295 0 R /F36 278 0 R >> /ProcSet [ /PDF /Text ] >> endobj 366 0 obj << /Length 1474 /Filter /FlateDecode >> stream xÚWYÛ6~ϯð[d`ň—Ž)ÐY`‹Eã>%}àÊôZ,-$*›Í¯ï ‡º-š‹‡s|sø÷ó×"ÙqÎ ­ÅîpÚå)S»,ÉY¢ôîpÜ}ŒÓlg)>¼ó÷áæý»},E]ß¼y«4ºÞÃöý_oÛç":ìÿ9üñâšgK©²ÈYZ¨]B"G¦],sÅdžÁ‚³L‡÷¼¦Š$jö"† ʾÝÇðk;z¸=ѳ÷žÚV ²¸Þ‹ä ÞÌw1|•JIàšî–-»cÕg{’ü)Ñ ©/Ò¥úEÆD^ŒÚýeó4‹áRùM}Û2[L¨|¼Ò9#ùâLz Ð3Éé\þ¬áýÐLiiãºÊ4wµí¯žtÀį$'þ=ð QÚ®²ä{$ x‡GC uqY“·J$|&–‡ª÷“èá ·=-°µŸ«æŽ(Æ…GAÞ9(ЂQZGÿZ •Ž´NÖ WÍÑ~ ¶:Ó¹žS×^ˆJ~„0‰‡Øp­ÐÝ1ú;¯Ê‚RNð…q¡£m=¸ªee¦£ëª¶aµ/8áÊnÄT)„? ó€fÈDEכּCÃe¢£¾=9ôÍFÎt–¨USÖÃÑc øMÝ·a.U—û:ûRõƒ©«o>Òpvj;:ø”pÕT.°ÙÚ^ìcà»vÕñ44e¼åH4·GX\oðŽÌ ÷!#ȱH*Mm:Zã‹¶>öãN'–ÝÎ^î":‹ˆ¾BÆ"2Í‘n|AõléÚnÜC°M=ØãSò¢[r߆ $oD`å*D:ŸGëy6Mú#MFG{ò‘D»)ßbàûÊ7Å GKßΞ|EIY*" ‘2ÝZ®!?Õ^©Cýñ­Û߬‚ç¨ÀøÁƒ|K9ÒyvV%ˆPL#Db°®Ñ¤÷Ð2@Î+~DÂrÎ× ¤õÃ0‘N ýf€ð<¾eÔ µ{IÚ?!#—˜þñw™W48ˆ©”xd³-· [ph/Á;õ©æúW%™6 ø_Ó ÛxÓ ÊÌâ@vcÇ9Ñó|ge!"ú…> endobj 367 0 obj << /D [365 0 R /XYZ 86.4 708.045 null] >> endobj 368 0 obj << /D [365 0 R /XYZ 86.4 688.245 null] >> endobj 369 0 obj << /D [365 0 R /XYZ 86.4 653.874 null] >> endobj 106 0 obj << /D [365 0 R /XYZ 86.4 590.528 null] >> endobj 370 0 obj << /D [365 0 R /XYZ 86.4 447.681 null] >> endobj 371 0 obj << /D [365 0 R /XYZ 86.4 384.584 null] >> endobj 372 0 obj << /D [365 0 R /XYZ 86.4 350.047 null] >> endobj 373 0 obj << /D [365 0 R /XYZ 86.4 302.392 null] >> endobj 374 0 obj << /D [365 0 R /XYZ 86.4 250.919 null] >> endobj 364 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F26 294 0 R /F22 239 0 R /F29 277 0 R /F36 278 0 R /F32 264 0 R >> /ProcSet [ /PDF /Text ] >> endobj 377 0 obj << /Length 127 /Filter /FlateDecode >> stream xÚUÍ;Â0EÑÞ«˜Ò.âŒÇ_J¶" Ї Ñ!ö¿ˆ\Ñ=]éYŒÕD0F¼'àD bÒè<ðž’H½ø:V¿Ðm]ìÑiÊw.›,é´b 9—6uÉËyQ¶õöà˺t®êGë6g•HrÛDañÝ¥!Í endstream endobj 376 0 obj << /Type /Page /Contents 377 0 R /Resources 375 0 R /MediaBox [0 0 612 792] /Parent 351 0 R >> endobj 378 0 obj << /D [376 0 R /XYZ 100.8 708.045 null] >> endobj 375 0 obj << /Font << /F17 200 0 R /F20 263 0 R >> /ProcSet [ /PDF /Text ] >> endobj 381 0 obj << /Length 766 /Filter /FlateDecode >> stream xÚ­UKoœ0¾çWp4Rp°±1ri”T©Ô‡Ôm¤ªíÁa]K<¶À¦ÝþúŽCvW$i¢ž°‡y}ß<üfqrvÅyÀU™bÁâ.ÈR*™§Tfy°XßÈÅZozÓ†Q¢$‘áÅ» "‘ÓŒ%¨ñÁô+S£B³/#¦Õ½mêΩŸ]10Fs)¹ ÖRPž+´þfœ4[0K$)´ó“²í JêÑ9m2øòŒ@Rºèí}ÈñÊUFp[šÑ‰­WÞ¤ïPV3PÙv§îž’¦Šìœóc’´[Ûçáá3A…`ÈŠ§äV÷…ó±ŽöÓ€c *šªÒõ奭½†nW[ŸXßQ$ êÂåL OZ’Ó<SRFŒqI.&À¾÷§Ñ#Ô¢¬ <¥<ó .þ!±QdK·PšÂ~™0ÞVûh ߯YJ•”uˆ…Ô«ó{]nÍ\vRÑ$KGõ‘‘|_%â|Æ PŒ8CUp¬æÂ1KØmÊÍA-Süñ©µ`ûõH„“Þ‡RmK}‹ÈKü7[TõÀ]6•àO ä/°2c½4çø©ueæšóóa‘Š€ueúv‡7ô@ÃX$×^ÅüÜZÄ[úú;90ÒÌÕ—å9åi2¦w˜Ó1Á!¿ ŒXK õÇ£ÌM¢Ëc˜Dwè »™ ÃQˆ=bB“‘œÙð°|ùto%YN¯*MeºõÓµñÍö±iPÛæ—-}_ù.óÓÖ7m‹u‰×qéx˹’HIåÃȽ¤$Ì[ ;Ÿ¿nÞ¦Ýø°g¹üm{?nwøä€j5±û׿+®Wa9„ñlÙΜMëÛ/×ϩۨ|v(_†òfÔ{ßLëâCWw>Éåxñt0 ~,—¶·Pú¦ÖåXü»¦­&þ÷^Á×´Ýn'^£ÃÛ”;…jØè¢žTF7(}ºù;ûÇŒ¯#n˶)¦bg áí‹GKž¸Ÿ'—‹“¿¤ú2é endstream endobj 380 0 obj << /Type /Page /Contents 381 0 R /Resources 379 0 R /MediaBox [0 0 612 792] /Parent 351 0 R >> endobj 382 0 obj << /D [380 0 R /XYZ 86.4 708.045 null] >> endobj 110 0 obj << /D [380 0 R /XYZ 86.4 688.245 null] >> endobj 114 0 obj << /D [380 0 R /XYZ 86.4 457.693 null] >> endobj 379 0 obj << /Font << /F22 239 0 R /F17 200 0 R /F32 264 0 R /F29 277 0 R >> /ProcSet [ /PDF /Text ] >> endobj 385 0 obj << /Length 114 /Filter /FlateDecode >> stream xÚUÌ=ƒ0 @á=§ð˜ ÛÅ$ŒP™þ Qo¨[Õû¡BL]Ÿ>½ÉC;sfTü L„2¤NÁ?°GéÒÛŸí,ôŬ t¢ë}\ݶÔ\¤Š©É½Äj~³z¶eµmL…£?–ú:ŽÁ<ü7( endstream endobj 384 0 obj << /Type /Page /Contents 385 0 R /Resources 383 0 R /MediaBox [0 0 612 792] /Parent 351 0 R >> endobj 386 0 obj << /D [384 0 R /XYZ 100.8 708.045 null] >> endobj 383 0 obj << /Font << /F17 200 0 R /F20 263 0 R >> /ProcSet [ /PDF /Text ] >> endobj 391 0 obj << /Length 524 /Filter /FlateDecode >> stream xÚmSMs›0½ó+t„™"#!$‘cš¤“:“rJ{ Ûš€ä‚\÷çWÒBlw<Ø·»oW»÷M²y¢Q†…5[$9f¨ª9.$EMÞÒ¯ûöàԔ奨Ržýj¾£åUKJñ:k³¿Û+¾Mía¯»võuö–PZc)%„>›¬$©O¿m;›'"!¸®*ø„R Ë‚¾‰ù)O(·S&È"[mÀzÒ¦·™7@l–{Í~Ì‹®?‚WÝ…RÉc“_ @Jpåû!œcQ3ÔÉï¤ÀUÍXD\ˆÑU Š©”"Z˜g÷æy$èÁ&/þ[ äk…ü¢Ä}˜ÿu¿qþ¤ô#bõ2"ç¹—"í¬™õìB'%Oí¬0poý4|kÇA®ÖôàZ0"}?:g /pî¿Tξ©>GήuÇä5’_E.KfŒów¾¯9ú|´.€•SIÒ¡v‹ØOm|º¸LÁp~MœåŒðúÁ³6 ÉtVhœA;éaÔW`VƒßÕƒ/lLøsLð-ö93;÷¥(‡)rû£{µl×¼·.ïŽnQ·vdg}Ô8®Yl8§Öikî`ãi}¹D`V2&×+›Ÿ·®Ã‹² +Q/Gínö’…þ§Q›Ö-äãùxV&â‰(â½_&­Ö#ùØ ˆ endstream endobj 390 0 obj << /Type /Page /Contents 391 0 R /Resources 389 0 R /MediaBox [0 0 612 792] /Parent 393 0 R /Annots [ 388 0 R ] >> endobj 387 0 obj << /Type /XObject /Subtype /Image /Width 771 /Height 591 /BitsPerComponent 8 /Length 36363 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFa[ÿÛCÿÛCÿÀO"ÿÄ  ÿÄ[   V•Ô6U—¥µÕWv…˜Ö&™$'78w¶ %HXh†·Ææ#(5"GJfx‡ˆ§4EFTst‰£¹ÊØÿÄÿÄ+a‘ÑðQq¡!1AÒ±Áá"rÂñÿÚ ?ûdŸÏåÌ’çf¶·nŠ…/@ú €Ù­ûL؉F¯ýª„ZºÛ_µ­«©·ÿ—©µüŸµû;?ɳɳ³É â¬÷×Þëfùpµ}=~ü/àÍÆ8fÖUäa™¼Ýx‹Ž4„W¶kî°nZ²ynîwg:ª)f°näNyQ=+xzÁé‘ã¬äºßAÒÜ‘}V+@ðÅYﯽÖÍòáÅYﯽÖÍòã#/Ûß%ñj7Љm Ï^%÷Ö}Q¸ðäøá™)YFßë IΚÊÞ°ŠCm|tG‘n®‘ç« ΙEh”è5vÛf‰XÔ JêÿË1³!…ÞšS̵w„W t?:m×ÍñJ!®!–Lšgjn³¬š¥Œ³WÕ6m‡k]òõrg]gZ²/µÒÚšW>£…³1Çßœtq¸«=õ÷ºÙ¾\8«=õ÷ºÙ¾\Tê#©ŒŸ†:Ï)–ö1Ç' Ê^…Æ=*ƒÌàVL×mšc_XõÄýŽ-a׈ú½eÑ9Ô^>ýÈÔâÌû¤ƒUñÅwo¡qV{ëïu³|¸qV{ëïu³|¸ÍüûÌžÅÄVlÁ\qªß·.úƒqòÞþq‚ç¸eZ °Þ%-‹ÊãÿFŒ"—K·†l‘¶+­ºý@­ñ±Áí³So–PîÜïLVÅN+£8 `Ó69KM¬ë‹j/(4朥ў¾CäÉ4î™ ®å«ÚâpˆkÒv†Ø „×a\:j“Ç–WõKÜ®hçÅYﯽÖÍòáÅYﯽÖÍòã7éþqÌ2¾¬˜ÅUUÜ›Å'°8±Â—Eµå«­¯?lG-¾Ï—,Æ ÁPdâ¸rê¨zà¬æyû,(œåIºLa¥Íá'¹ÏÌAžd[Æ(ÄîÆ7{É•òÚì1ÌRFÞç5+$:KlÖЫE|q-Q`ÚuKú0ïgÕ°Y¼ŠÂ¯P+pQ02ìGä\­A œUžúûÝlß.UžúûÝlß.22YÏ͵_d¶Ì2yŽ<¢ž´í*FÑÔq€ÛzH –ÅC’ÊäY#¯$i­¹òL× ›¥¥ôµV}DÉ Óxm­fKáÒV6¾§õŽa—8óÆOÜ~7öeê>Z¼gí#½[›Ùó³Žãv†ã[ÿ<áG ·óu~úƒqÿx@Ò*Ï}}î¶o—*Ï}}î¶o—s‘\ó8õQÃ1šyUFçóñ›ÍXU5Bżã3:*TÕÁšÏK<®6èù†ÝwÁÕé4kEñ^Wƒ\÷+S¶³ífØòÆÎàã³7¸9êù²ñýúOº²[†Sˆg ÷¢½—SwûU’ÍÆºÛnÚôºçZªßB:2¹·Ñ0jp¥ùÕ‚jndâDÅq â¬÷×Þëfùpâ¬÷×ÞëfùqE䫌±jÛm×Û/ ×™•8¥«Œmîm€«ˆó<‡aÖ“SÌÝRŽ*¡ò!½ìiõ—uŒñ¶.ÕýŽ(\ȯke>Õ¦¡qV{ëïu³|¸qV{ëïu³|¸ç¦/ó<ó²FùÃ0²[|Ý/5e[kÐÏ“&üšmmqA ¯`Ñ´s(ž™®ÇšÉ#5ci³É ºk`<3 W9€[ºM› ^”ñqV{ëïu³|¸qV{ëïu³|¸ùåæù祯rcï ¶È%,u-h“>¥8«1øôrõlX‘¹=^óDÂÔU‡»ž_eä\‘=€¯’M¦ÛÝÐjh²»<´GRFã¯O{7zM·Ьtå\Ë!XâTÄJÓv£%k¤Ñ+†ÂŒÝ¬/jŸ)Ù ëIy2Úl»i>»WÎUÂikt2‹cF£©&Ù <â¬÷×Þëfùpâ¬÷×Þëfùqƒ¹sÎß^ÖU>']øû8««K/œÆªÁü–|»˜g5Úú6¯ZÁÓ½´gQI»…O/£í:Ý<=#ƮȑmnŒ¥Þ$çzeuÕ¿XÉš¸Ë˜|QO–^÷¾R3zâà…?Ãl ¾É¬æiúNÆÛ4Ú°¶"°{9ôªÛžšR8¹ÆSµ.~ŒË£È—(|ˆIÛÚBôqV{ëïu³|¸qV{ëïu³|¸ç¦us¡eÕ“‚8ÊÝ•æHD޼ªîú?´Ë4™µùÞf³§Uq;àSs\– Æ¢ïNù/ˆ*‰oü‰º¤Õ¡$×xéjô›© Wâ¬÷×Þëfùpâ¬÷×ÞëfùqŽ/λ™5ÍÇŠx·&¤,[6g¶kãÌ…ë{¡ØK¯äv<úÁŠ8×sMÄ“‹Q£Q.1ËÇeu,áÖ1:Ðz^#.Òí/yÏkI âÏ‘öåY7µò‘òâWŒøcKe¬ý´¾§˜Øº5õ õX¾åRæ:ú OµiÉŸë­ÜvIɨ§mÙ+žªîWÅYﯽÖÍòáÅYﯽÖÍòã0ãÜèx-@¡Ö)¬rf´˜{&ÏeNQ蕌ô6+B¤ŽÐÙ•†¡cl9J}È”½…ò)&©µ56nF#+³­~‘ѹb]©Yf®2ÜvM}QW^ñØv¦,ÄóVÜÛ£¯q–pü‚3²úÙö*ÖÆ×ÖŽˆPîkË“u€‹éúKŒU"M-eaz8«=õ÷ºÙ¾\8«=õ÷ºÙ¾\sÓ:¹Ù2êÉÁoû÷+*&HDŽÃªøY»ÌÖ;kó¼1fü]UÅpí×-Ñ™,AñGGc—¹*nè2&ï¢uÐC®§¥¤ÒP…Hj¿g¾¾÷[7ˇg¾¾÷[7ËŒUš9kCób> ß3=¼buV]2f×zNeÑm?$©¢ò9Â9 æ·™_YÖñVNZáï(;¶ƒÜe|¢Zžu­¤¡­=F©²À¸_XæqŸ€Üdýøãf^¼áå«ÁŽÒ;«¾]Ÿ;Gn7gž7õGó>qG7«÷¨7ã÷x â¬÷×Þëfùpâ¬÷×Þëfùqòí]óÁ_7U°øñ}ÇJ6eçi€ópµWY ‹Ù¸’ذãoº;;:qKQ¶!ȹ҈ìÏU gÐдý¢®+¡“ö]·H¢›E¤Üñ\ÛP¹$†),Éæ8ë¤7"ݱBv©Þm¡×7³Bõ º‘[2e¯ÙˆVÌnÊ$ú‘K"tù¬&È+ëUÖ2}k©lµ‘@×>*Ï}}î¶o—*Ï}}î¶o—¿psŽa• dÉê«RäÝÙ=Â~+:"¯-Y]mGqÍûn9Rvƒ¹aÐgúƒ7éÓIC/§0?ÚaZÙ*SÑ£Í ü;+©ÛbΤ,ì…c†Yt³å@Ém±¼D¬m4Æë¢Ã©\Ì&2½v´A†¬R¢[ g—ÜnÚ5=_$ž@"Ö„Î$žDžƒO8«=õ÷ºÙ¾\8«=õ÷ºÙ¾\f3§”•Ç‘ Ù ÆÙTP pù5¼ï:‰XÕŒ’²bL“ЦC­[Ù0è–îÇrÆälŠihüAÙÒ½ÃI†¬Q.ÙÖlÓ:sžá~§¿.y]¸ùˆbÛå}ÈFyý-|À-Š•}±­ЬKèibÅy!c°væL{Pé6u¯‘hò¼)jvTž1&Õh <â¬÷×Þëfùpâ¬÷×ÞëfùqŽ<5VÙ‹#¨,8YØuH8ÞŠi‚)j²¿LâªXtÞ rØK¦µdë¾t„Ï­aΊòB³g±iˆem;ˆÜ²Y:zÆBÅ#u´ø_”Ì9™Õ^A±C'ÿ!yÌFm ²bDý+ŦÎ-qû¿®8¹lÞÆ –ʶ¶žô%kbï z2äˆBôqV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞀:g¾¾÷[7ˇg¾¾÷[7ËŽzè\UžúûÝlß.UžúûÝlß.9è¡qV{ëïu³|¸qV{ëïu³|¸ç …ÅYﯽÖÍòáÅYﯽÖÍò㞙ՒyudÓœàÚX§d„.¯3+¶OÞ_[_•LØ»^nBNoê>ʦ)vøòš:c«/¸Xë4ðjŽÓ·-蜷!SÂkºÁÊ _ʬU] ˜h®nK·¤˜½É||â¾eÚx¦i:s€Ëf”’8Ýž½Á½Û±!ªe#ke|»çOÌ“¸ôÖ¡¢P5D –üŽLÿsÉôëhòæÍËèÝ{Í÷Íå,1±Q¼Üyõ¯š9DZ;‡:Æò _NfvÅM^±ýÆÝ¯ ´çï÷Ìžg¥j¡¯j+„¶c^Ûs(ìkcéøòËõqæoØßþ”×Ö9ýaÕ_ØËí“ÓŸþ^Z¿úŒB-îl¬âv ò!DfÞ¹Ã'ùEs®røJÝ‘QÚbgyã*”ÉXYÔ×\:Q©Á‰Ãÿ]¨vBé!“Wö ©æBÒŸNpŠ!‘}h€>n,noÛan:PRj Ÿ)9%QÏAVsŒX˜÷&Ë­„È»¶ {] –ÙR>ܰÜꆜ‹²X6™çîÕŽ¾JÈëÔ JêÝo[Ó”gRïaF/“Æ÷nN½#gïs+\}/M`ëVý=E{šÓ*¥˜¾ÃIM"™ƒdÕ•¥s1ÈéZ«vÒg§ãrÔ$JDÚùC2u’Ä”&|~ˆhɵiGßI4P ruiÖM¶Ù¨±5‹|¤ó+lSu Û`Êò—œKnûÊÇ æÈÀ$±›ëÉ$8GVKtœªÕ±èm#vJ¿>_’÷ˆ¶›L.Æc|¾aËëäíJ¥ï»u(ÎYVs_ç[Œ¼ÇëdØÝ8œÉð~q¬Y9DS9qÇëñš–™TjyX^0;z¿Œ-ÝHÂdïï‘xõõu˜)|Ö®ÚÉ#+êöùµ¹ªæjè>o$ØéŠý–dú|RÃüÀ¢+<•j³SWœÞYКÏU’h¦7™£“ßSŠO,GnÔ]…Ö-u^_’)+”J½ºã -/Jî5n XXßae ¡|ÆßËÙ!XSˆnR¹Ty¬×Íljðhœ6yЬ*{t®Ÿ/‡M‹;!aº¸ô®ØjA4Ò§+Õš Ume—=^8ÜùmÍ—’ØùÞ [ö÷F#¼1X§[n¥ÿUMŸÿÏógÈÜa@ŒFÞœÿÎoHºWBèHºK‚”‰5õ4‹ö7îž<ݹ/ƒx×VU•Dó"êÜÈŠcd~§¡¤“Jöô®X«)dñ&­c¶ªÊrˈ šÊ#K¤S–%ûlR:¶›?¤U¦×Hh®nK¶šw–•߃—…+çi}Ïú7%Óó€Ëkœt«#r­· ñÛã3.WINEÔN,0ˆöƒÅè‚Ó{›I¡ò›nL@˜¥ó§àË/ÕÇ™¿cúS_Xçõ‡Uc/¶ONùyýjÿê0¹9¸ó6WÍ—ÏWŒßO·òÛ6ÕÈì|ˆñªKÄ bIãLÙ–e×ëg)£N›¯åÎ{½6zÊ“uOBVǠཱ"ß© Åþb!Æï¬¯œgbèåÅœ¢¥rç²ÌcSžj…pÊ–ÉÇ-8Å?bBs.§cº"vƒpU±É-„jÛ©ûñúë‰Æ!©‰>Û­ìViàNTåoŸ~e@WŒvœCœ!šNM†ò¸Í³MêÆï8Ý‚ ëfÈcÏŠìl¬l­i5\š]¦ £¨&h6“¬„(‘§V—S[êØó›<Ù¹}‹ÿÊG1§Oš¬|Úغë!ÛÐZëñ>6ÆùjFSé¤xqt…>m:Fu!±•[l.6ñ$wiU¯!oˆr;JÚ¼<ˆæú¿/>nžqøÝUÍí8 ²‹*û!PÏps„©Ë;žüu¢æõ„¾Tã'ŸÚ¶œÊ¼…B*4Ч0ŠåEÑÉ3´¢±·UqWjèA¡Ë>¦€O˜)‘yŸÙG`Cclm•EÛÌOvà¤RÓ“J™FÛò.ɺdÏlq¹ }©SÕ–‘$mé,‰ÚTÛvdÐA¦¡5KßötÙµo×7Vç¯0—j«Öªàô⛤)ºkZ*®s?+á]Kƒ>ÈßÔ@Ô>BúònÇ-QgÎg½.¶Ù„ʤΑ)Ä–QUW—x>|9ÕY1¢[ÎKÍB«(&{ËFÓLy±&¿ ÙIqã\qhÝ»R0Di9 ºn?ØLov¼ Á+´^)@Ã$‰ê98¨hÛiÙ[£ôø¿šâ”_æ=svÉ0…É'áÝ3ÌN«qòýÆ^VSV,îü–öÑl­©¹{ºº¯¥Øzû1DO¶,V ~²g¬«ÝeXÞ]%ˆí6Ds}_—Ÿ7O8ünªæöœPYE•}‰¨g¸9ÂTåÏ~:ÑszÂ_*q“Ïí[Ne^B¡ES˜ENò¢èä™ÚQXÎÛŒª¸«µt ÐåŸS@’éÚ<š±yÇ¿Ê$Æoøð&ª)­îê}ÞÞ®@Ø!;ÇÔhùÔ}yÔ}gÔýtñÕ+¡u£‡Ðt½iÃe[E¦sË3_B#–©ºüOž1DØZ&v>ãµk1B·òPÞ;ä¿tÔ(f‹ï çßj×Öniè‰5vôv¦à|Ä߿׵ÕýíXÿã/ßëÚêþö¬ñ‹È<ï;éòËæÛ:Ä™Ì^y•s“ƞҶا‰CÙ¹:©·U½š>ųnÚL­£U¹ƺ5N+¶ôµ<:;¼¨psW ú¾™¾Þ3ÛÛÄ å¥´µðgïï ¯üÜW³zG2ÚÒ9–Їý_LßoííâòÑõ}3}¼g··ˆËOÂdzkjrócÛ¶ "«¯#]¼3ËXÆ1u»ª&ž¹”I—µ±µõ£ã£k3wN]¡Ó]\P·&úUjÓèê{q™4nkL¡²9lBZÆÓ&ŠJã.È£rhÛòî¬róãR…moLoMjÒ¹4»6ªRÅ”ë¨ÖO­§©´¤s- ¤s-¡åý_LßoííâòÑõ}3}¼g··ˆËORC&Ä'u•ÈXã-jß#1”®Rd ¨É&²F˜l6÷pj×Ùû«¼=iÔǹ/ïG×FõÔýgÑzÏ©Ý:Óõz¿¡íâ‘̶‚‘̶„?êúfûxÏoo/–«é›íã=½¼@¾ZL¤s- ¤s-¡ú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–“)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤ÀðݤѶñ–§É +¤ÕñDfÚìì¹|¶H’7!™*FQ¬Q¢¡ùñ4B%+•¨ijÓV¿F7¾j'ÙkerT™Hæ[AHæ[CËú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–ž¤šM…Fä3)”…Ž%‰1»I¥r¹3²Üf6ÂC«ä†Bøê¡#[++ZENNÎÎJ“ n@™BÅŠ4Sèêjlû‚‘̶‚‘̶„?êúfûxÏoo/–«é›íã=½¼@¾ZL ¦M~_&jc±½:BŸÆfM­.ÈWĤŠãqé’Xô™5Ê_Ä%±IZv—]4‹õ£rhóæš}¦·¦ÕJTŽe´Že´<¿«é›íã=½¼@¾Z®ĘZÜŸ2+9Ù™Y,uxxuÈJé¹­©­¹>¢Ç''ˆtR!@…&޲¥‹ki'LŸKS__ScKckk’~T¼çþË6û“ÿb"b"+OoÕ6‚b"+OoÕ6‡tjÀø³Ú F»ÿ=•!Uô¿A¯Ç8Fíý¶¢}_û% :ZÛ?³­¥©±ÿ—§³ü¿³û[?˳˳µËè}_LßoííâòÓ¹Hý­ÿߌèôR9–ÐR9–Їý_LßoííâòÑõ}3}¼g··ˆËHäú󤪙%w ´n*²¶—ÛÏ›Qšš)>°bPé%¡$Ù^ÆÕµ®ØäNíΓWÍ—I4m·i¦4•Í"ù >Tý!ÙšŽ¦)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤À G2Ú G2Úÿ«é›íã=½¼@¾Z>¯¦o·Œööñùiê'“FÕÉ¡©d,jeì,qé3äQ;² i#,nZ¾LÕ»1é¨Útnc“:B¦M±çe‰tP=/‰I‘¶¨R¡…×M!ÚMa_j|±²ºM_Fa­®ÎÈ—Ëd‰#r’¨ôeÅ*ŸD"R¹Z†–­5kôcq™ æ¢}–¶W%I”Že´Že´<¿«é›íã=½¼@¾Z>¯¦o·Œööñùi0‘̶‚‘̶„?êúfûxÏoo/–«é›íã=½¼@¾Zz‘™4nkL¡²9lBZÆÓ&ŠJã.È£rhÛòî¬róãR…moLoMjÒ¹4»6ªRÅ”ë¨ÖO­§©´ŒÉ£sXÜze ±ËbÖ6™4RWv@ý“Fß'ucÇŸ”+kzczkV•É¥ÙµR”(§XF²}m=M¥#™m#™m/êúfûxÏoo/–«é›íã=½¼@¾ZL¤s- ¤s-¡ú¾™¾Þ3ÛÛÄ å§6K‹4âôÉ×7e&sº7­ÐÑVͪóˆ:5¸£Q§³¬•sk›{”(èmì(F½tŠÓêi¨M­«£©±·µïß¿ÔMÕýÒØÿàç‘AQ4¯÷K\ƒ™…"±äaÚ4)ˆ§#Ñ£ÇìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡ ìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡ ìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡ ìTÿ¬¶{{dþœ“ªŸõ–Ïol‘¿Ó‡r‘̶‚‘̶‡"C†PG=-­vÛ÷œ-ÃCcS—GoY ¨Ì¯KgWggcokKkSB-©±³©³±©§·Ë±ËËɵɳ·±µËÉü›\œ¼¿Ù؆)ößÎ/í)·ô™gи¸6UÛZí«Ö7ëíϹtvõª×I«µ¥µØÛÚÒÚÔÐÛÓÛÚÓÚÛÓÓÛåØåååÙåÚØØÚåäþ]žN^N7cßlTä1æÇ·n†š®¼ŽuvðÏ,{ÅÖî¨XšzæQ&xkckëGÇFÖfC¦º¸¡nMôªÕ§ÑÔR9–ÐR9–Ђv!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“'uÅöÅqìzŠèiµ+ÉXîôò¸±‘Î!½P깉۩¥—‡F7N«|krfqè+µú«ræå?D­"9¾÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤Çb§Û8¿´¦ßÒgrÞé_yä>4åæF÷JûÏ!ñ§/2)Ëh)ËhpÞÄ1O¶þqiM¿¤ÏçÔÂØ6Š´TßüàèÕ:(ØHߤ¾ÚaAÒÔmêihòiém¬Œèiòÿ&¦¾ŽÎ¦×.ß&Æ—Òìrêmllírrë{¥}çøÓ—™+!Í‹ä~|x{ägrÆF¦ŽGw5®\M{Q×§}¦ÖÞEšúÝÓ³³«¦Ò4¿DŸ•ÅÍÁo.ŸIZ§WQHŠz|þ"¿õ‚‘ôùüEë—õ}3}¼g··ˆËGÕôÍöñžÞÞ _-:Œ»Ò¹?Þ¯‰) Ri4n̦R8”B$Æí&•ÊäÎÈcq˜Û ¯’ 㪄l¬l­i9;;9*L¹e (ÑO£©©²¤s- ¤s-¡åý_LßoííâòÑõ}3}¼g··ˆËN\g>Üs6jâ¢ÌLYµ,9Xîô¸È:–q3}ꆥϮÝMŒË:­­ÉåÇ ¡×èMMËœTýDŠ5´í0¤s- ¤s-¡ú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–“)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤ÀðÓÉ£jäŽÐÔ²52ö8ô™ò(Ù´‘–7-_&jŠH]˜ôÔm:71É!S&Øó²Äº(—ĤÈÛT)PÂ릑Hæ[AHæ[CËú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–Ÿ‡kn¾Ý^ Â7Ÿ~8e»›ØÃ×ÜIá·x}Ôý?¬7ã„Ò®éô~¾á·ïÏ@Ýó¡7Že´Že´9|‡ Q=*$y#œìû‹ùš¶_ð …Îs§+kRM–Ý¥NköÚÝu¡ÑP£I­±ÉËSOezú2«é›íã=½¼@¾ZW»ƒûSaßÿðé°¾Ö¯§¯ß…ü¸DGOiýDþ£B":{Oê'õ8oÕôÍöñžÞÞ _-WÓ7ÛÆ{{x|´˜±Úó¤˜mˆÍ ùqUŒ·”ÕDšL;X1&ëb[I£!RªC®–;èËߘÓ'‰JõÔ;53«A££êê(ÙØerÚL¤s- ¤s-¡#ú¾™¾Þ3ÛÛÄ å£êúfûxÏoo/–“)Ëh)ËhCþ¯¦o·Œööñùhú¾™¾Þ3ÛÛÄ å¤À G2Ú G2Úÿ«é›íã=½¼@¾Z>¯¦o·Œööñùi09-ûýDÝ_Ý-þyŽe´Že´<†¼N©ß¶Qí°dÖwÈ4\´6µªÝ‘GÔn¨õt:V‚æ•­, : P“ù¥^߬¡"”œ»*“ëj'ÚÙÔåv!Š}·ó‹ûJmý&Np»ÐlwþéaŸðÕ9þ¬{튜†<ØöíÐÓUבήÞåc#ƒÃºÝÕ O\Ê$Ï lm}høèÚÌÝÓ—ht×W-ɾ•Z´ú:ˆˆ¤M:~¶‚")NŸ­¡ìCûoçö”ÛúLv!Š}·ó‹ûJmý&ºk2)œŒÞ>Ï™SXÞÛÔûÝÁ«Æ+gî®ðõ§PoäÊ:¯:ë©úÏ¢õŸSºt/§êõCÛ÷ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“;–÷JûÏ!ñ§/27ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“;–÷JûÏ!ñ§/27ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&;Å>ÛùÅý¥6þ“;–÷JûÏ!ñ§/27ºWÞy9y‘Hæ[AHæ[C†ö!Š}·ó‹ûJmý&~zØMO¥«¯¯zs‰èhhiíëkkkY­zzZ:Z{<»zšºº›qM===ž]½½½¾^MžN]­®^NNN^S»ot¯¼òró%NË)”¿i>¶mJ¤›M¯ySJ·¼·í>9ò¡w@ÉÑçAšNU_@½&ƒ»S[®ŠeZzº:nM¨lllªFŸWMHŽŸ¨ÄˆøéúˆüC!®m¼T‹Zöi$'&§<¬2צ— |žù®Ÿ$/¨ꦑ¹®nÓǹ.ÏÓ¿é¹r¦[¯"\±Õ"wUúmëV¨lF8•ûý{]_ÞÕþ1y5í§:r²Æ½´çNV__V¯þ ýýá5ÿ€›ŠöXKWÿ~þðšÿÀMÅ{7nΩksS—8lšc8®8—'ÇÜ!Ï0Ê=Ȇ‚f²gcX·¬g34hÇiÛÌ20ë8uŒC0Î3}KÐ5TV4-ÊQZF2 Z¢yOݸE”3Œ,qcÓ¶vEóJ½ØªbЄPhe®Mgg|ï‡Ø,2¸ÞËÅm‘nØâÙå9)lŠYu<’J×dHá{ŠËËäúÓrã1~nâ»6Óäðž¸áõ•Ê«;ž±ÞN«Ó–pªï¬Ÿ!öý[¾ìÈ'<>›F÷Þ+°¢#,ëˆÂõí ybœÄÕ=»F¹RlnÕEøÆÚÕtÃ^&/,ç¶ÍeË9m‰Š§9·G¬‹ztVö_“ê—md\âI€I¦V‹óým_¹F‚¬eµÑa6^mi¦âÆáˆ>sI£q© " )@Ó$Èu‹:®´d)ùd±·eOŽq Ú §v××Õ_[I"Í3ºÑDBw¡Ë$Úœs[WÒØU-l¬’Þv¼Û0³Ù¥UˆÑI6 Œ¯‡göV±È¤Ìz•5;Wº(|µ99fSäòG) mºIµ´–®VÑÙŠlöø¦â´7ZT½ª¼|pž>cÔš3˜Û7%…aX2LR¶ÝX÷!ŸØÓëK;œ>V3µÚ{,îÒ¹ºõÐfH…Lø¡Ö¨„C¡L]¾K×µ|’Ä“ÁŸTZO›2i\bo9_^§’k/|y|ªÇY"êÒ±|œI$² …žíZDâKíiËÄêÉQ*—©Ô{å¦pÜÿLßïË"äó¹7¿Ó7ûòÈŸù<Ÿ1Ú0Ÿ1Ú0îEÏXÌnÂÑÄŠ¦Ô1ʱÆÒÌ(Dg##³” ë×èÛ=OtØTz~µÉ>Ò&æ96h±v2ÎÒ­rŒåâ!G»'•3ÚN)mú!=e[\pÇšâݯ¡¥y#êíáØñ6Ä1÷ªP¾´õÌ^LÑÓªßÛ^[ºr~„êÜ…Å7Ñ+HŸ[NªÞ«t3[ UYøÃHIão±àxÓ’oIŸ+ œŸ ¯Ù퇬ãOòcósË¥û ï;%=ÞÿJäD"_cä*¼ÀH~7Aa–½lënЯ8š¦˜È d·n<‹J Né7dKE®ëe@æïÖ á E3`NÚ—La؊Ы p%¯%·=Xøð÷_ݶí³r^—lgEú /®œáèn+¦ÀŸYz•f¤n}2×MN,”©©Û¥²'+ ¶’ÀÖä“ìøtÿ7P¶LbÕªé½Ý“×üXáKZÛÕ•ÖÔwß¶$vßgÊjc9¨1ó~œ95S½pV ý¦®qTÝ0ìæÎ¬)+Zy›µ擽m|«âûw¢we:çFÕPÈd}úYƒ¶&TÁlÚ’Anf°ã3†•t:¸Ý¬‚m-²«kÖјɫªúƒchƒ@bÐŽo«œòé~Ã{ÎÉOw¿Ò¹—Øù †Ã¯0ÐXe¯[:Û´+Î&©¦2G™-Û"Ò‚SºMÙÑkºÙP9»õƒ8CQLض¥ØHö8ÓH®8ÂX!½1‰=GÙñ³xeJ¸»tÄËž­|Rá+èU.ˆþû+’tž¶ëõO'@Øô‹ˆSüÜxeBÙ1‹V«¦÷vO_ñc…-kl;VW[QÜs~Ø‘Û}Ÿ)©Œåþ ÇÍúpäÕNõÁX4ö˜V¹ÅSthó›:°Î¦»³.syauÙ(Ë›¾aÙÉØ+iµ’Më˾Ä+tŒÞ·E}!ŒZ9Ôý&O~Klçí9†uW×9å©y¯± iî÷Ú±¯œZͧBøy€xe¡‡tæBË1VÇQ¼o9ÝΫwÇ ò‹÷ˆz(u#ö«_ ±ýÒ¬ZÝ"Wp¹Ç 2K>C€°xUˆùQNÞ³ ÂÛ¯í8öÊõkë« §›?ÞàSUôO‘Ôó¦8Ô½µ•ÞMXHÜù Ö¬m#µoa·½A%2&g§õqá—øóÁ¿ßŽ7öšê>!Ú¼í#º»›Ú³ŽüöyãT<â¿ ·óz¿~úÿ~?xKO,®!“‡êÊM(fëGÊrp¾Ç®u‹ª-Ü™ºVÖ D¹ç£7.H‘ßéëËRyêçÔîZ]{ÖÚ(tßÙœ›ƒ óË"䙂×ô/°ùTm×x —7ÎoCãÒÕúëà– ÈZ'ˆJ&íˆàËælk2Öž¿]äÖ•VæåšFð‘Ú·žF$TnZ±ê¿û™qóžL²5ñ=Þî“'­qBÀëÊóctÖf’Œ¦rNÄfË)FJä}”NœRÒ»V®8ã·UµTp6Ö¬yuaëÉØ’ì$‡i‰\W#¡/ðÞŸËn¼íÙ¼2¤¼@ÞJb_ÏQ>&pŠtÚ‚¿ˆÄrUÆú7TõúO “¯sz[Ä.n<2¾¬™=«jS{Å'°8OÅf´V«­¯?mÈêNÐtÔ:rÁPdâ¸ré'eãTyû,(›"ªzLa¥± UœÕ¸2Ž™Ùw,–O”ð|n¯w5þ59ÆÊŸï,wƒVÚMQTòɶiUVNÚ|ð—î…”¢Â‘Ýi0ñÒ8ƒÛ ÏÙt:Ún´¥LüBéY“U¶Ÿ=NQY%ÂŽÌ{MæÏUrÓÕüîqºÔœÚ˜+fOáw›¼¿elÝL"À„E«¸g%%¡¦u›«ìÒxû3µºt:)ÔÛ ñê×™¼Î&qÉÆª¹gWq%»¯8 CpusRÞ×h¨ ‘¥o޹†4²WRÞ1À'íWGãulï+ÈãeÞCŽ4Ä®+‘ЗøoOŒe·^vƒlÞR^ o%1 Çǯ稟8E:mA_Äb?¹*ã}ªzý'ÐI×¹½-ÞT¼çþË6û“ÿb%´*^sÿe›GýÉÿˆ±O´öŸÂO´öŸÂûHý­ÿߌèôèR?@«÷Ãã:=*³:KH¯‰\‡gRP\tʘÞE>CX3[åúQ¶[µJøÆ>×°Í=ž»Yú¹–±ëP)¢Ž :ȸ]o~–äÆÐËjÖ´hÆu³¦1Ѩ´rg2±>iÄ©Šk˜Ÿò'q~Åg©ÞkÞZõ†§ç q£*[]Ãf ûy.c¯¶á¨¦Šõ£"šrí9—M›¤–¤Æ¿Ñ…EâÛCcáV2ÚÓ7™ü¶´ú <Ç«´mU©•X5dS;RóD_(c5œª#ÊxCLaÜA®‘lö|1ºñ)‡#bÐŒLem/>Û¶%c£ÂøÊ­j±¹®-V(£4àÑ¥q žUImFä1ªvҦ⎬ÕEËVC˜%Òôuµ}mÃf±*·Z_,r®Z"Î’gÅ«Ã,¯©öna6o ©W÷n˜™cã/óÕ¯Š\%}  °%ÑßerN“ÖÝ~¯éäè‘=ó}\|ç—KöÞvJ{½þ•ȈD¾ÇÈT6y€ün‚Ã-zÙÖÝ¡^q5M1<ÉnÜy”ÒnÈ–‹]ÖÊÍ߬ŠfÀµ/o£® £‚dÕ#Ye|Ÿ)ã’ËˉLh%Õ>!ÌpBwdÁë÷k[ Å76Ñe9ôzLO¶>«Îµî/Ó¼r¯lØœÒ"ç}j£–A-5?ÍdžT-“µjºowdõÿ8RֶõeuµÇ7퉷Ùòš˜Î_ê |ß§MTï\ƒ@ÿi…kœU7FŒ;9³«œW_UDÍšq ŽN4•ÄúLJq)5ÝyϪ¬Z—FöxEO¬‰5+Cõ41ÙprÜšºA$«aýG^Hß#+Ã,°%fMSÔ¯2“ÆIoåA“t…mFL1ñΞ¯Øá&¤|ßó\ƒ§&•$Ù“gFßlœE[ñÏbkrÙóûnj:ÙS|*G7¶Ã!1¦'»åÆKÖÔÝaYå‡ef6ng¾m ¹‰EUŽîíÕ·åêÔ±ígdñ™D]xÑHh$ªã[rª: ‰)Y»0fú‚Ê¡ØÛ'6vÂG±Æ˜ŠEqÆÁ èŒIê>Ï›Ã*UÃýÛ¦&XøËüõkâ— _B¨, tG÷Ù\“¤õ·_«úy:ǤJiŠ'ªxU Ý^£¤),qkýá•>tZc÷ûƒPßÞ7ǧÜî'ÎxT}4ªCן½OXÏÕá™Ô-Ó—Ù±$¤#¹ÇÍhy³°Ÿ0$°Ø +œFí ‚Ìu÷ÎF›U¢á(—¥ÇJÝ>=/jÙ¬êi]OpKÐYÏš›Y'tޯܒ߬±æwáÝ»c¼ï‡jbÎ>XóÉW54uìÎqRÄdÒ‡ž©bBÖÆ×ÖŽ‹—us3ksR/§èÍÈR$ÒÑO§Ar›ªb®IL*ÅjeQ o^q:ÇyÜy}JÉclëáú•Í}qJéW+¯6ð÷]®;°ŽÁÄl…† @ô½»–ÕªäžÒšµ$Óe¦»9ãv>cæñïi ¢šÞî§Ýíêá„ ‚¼}AÖG×GÖ}O×OYÒºZ8}KÖVýþ¢n¯î–Çÿ<Š ú‰¥ºZãüÌ/ßê&êþélðsÈ ¿¨šWû¥®?ÁÌÄùŽÓù„ùŽÓù‡Z@ ÿ5?ûÂÿ–ÌÃÖŒÆææ:®¶lyÕÒ–ÃØ,›ܤ­(4×Ǥ–½©wCsbCV¬PŸECóâh„K â–K²MG…õTnycJ¢×’4¶.žæ§ÿx_òÙS®\q¦/ÍÜWfÃz|ž×>²¢²UgsÖ;ÉÕzrÎ]õ“ä>ß«wѽ™ç‡ÓhÞûÅvDeq^½¡HcÝíqß•ÌòÁñ¦ÇÜðžÂ9¯¢ú¶Í e©Éþ%5dæWÛØ‡U¾¬ˆÝU¾׎w}$“F~¢ ­b»hÃ%:®ŒÚSÎJÖ ™£ÛUgs–×tþO"“¿Zp$ókOê,G»²öµÂ‰]ÛZI2à ¡øÁx®z†á¾¦µém‰TNä§”Ì"5r÷9lÑÖ :m±¢-5‹o×/6îêC/8Œs„-ŒdÜ"ÈTî:Ò''[5~ë4Åg<™{Ú™<®ïE'°$ÒõÙìð¦ü™ê³Ld6K¬ž)vd"æãÃ-Û ê§šoˆŒ­ê^Ñ—‡jÝ–M±ºŒ-‘È.óܶôæmoíðͽ¹EOÐg(¸Ný¡·*®7^N¥SưRFÓÌÚE’”SNUñMñ¢qÍ,£.+šª•ÌàÌ9·œNX­mVV|~šn¤+Ëj¤’¡ÉׯbTÕ’ªÔFSØ:‘È|ùŸÜÕ¶ò¦¸’[jœ²UòňbÞ}aŽ´1ËjêmºIzFòù~jYŠ•Áᵕ›^c¸#Çtç Æ„•õÛ;•뵑éߜڴ.ôqZ½A:JÇ^>::Z'tY™ý³rZÖÄòÂÆù$]D8ËîKBÀ˜Zò:©þºŠ,‡BfJ ÍZ)Þtã|­r¹b'¾¦íŽ4Ãæÿu¤7¥q>ï¨ò:sûÃ*ÐëËž‰à— ¦_Íß4z³u{9Ó_»Ìý_|ÜïÞ67á•uàcÝ}qóžZ—šûžï}«ùŬÚqt/‡˜׆ZwNd,³luÆó Üà·|qª(¿x‡¢‡R0ïjµð±‹Ý*Å­Ò%~Ï’•Í{EA+ÌÉ´ôöòC§œN”˜>Oªüh•ëE ÐÏ;þtý]¡ŒRµÒvûNÏ—ÕQË/jE5ÔŸW°»a­]–¥UFéË1úm¦?WqŸ<ýøãi®£â«ÁŽÒ;«¹½ û8ïÏgž7õGóÎ+ð»7«÷ï¯÷ã÷„êm¸¡D³ØI¬æØ«âI#u¦ºîcmز,ýªö+l=A­ÚîW:…Tz“-º¢ù?`¾mÇ ?V% eÑ´§3W BÄÑ“Yi¥¨ȯ‹Úª¯n¼Lv¶&Ù‚šÓ©jìºß"Õ†µ…0©óZrü×UdþÕA1ÕWÌ@`ŽdÂë§obfÖ±`Ø >¼§ÍTõ[k£xkIHWãå“`gÄO%,ÖÊC’ Ç BÁ®q…¹'éζÉÈ7*ÉuÓmKd ¬1Їv#R –¾Ž×Ü“§é\V}f½Ë,(û{þpšïê$×ðÖI´ÞÎX¾ ‡¸ÈW«rpTÚŸc]:ÆÔ¨Sië"Úéjº+Y¤ÐÔÚ“EbçGEèÛÛ-qR‘6¥yú°sÿ¼ÿû6÷裹züSOì'¯Å4þÃ…Uù1 ÈIõžÝZGÐ6×Õò›3îš¹2§IS¤¥4‘[òÅšD­Z­hõZ‘³6¶ì4l(ÚPÕÛ]ÕÁ#³j&¿¶ŽNýáÆ/ðb¢É•³¿¶ŽNýáÆ/ðb¡Ó¼þ$éÞ¶’ïJäÿx^¾$¤w¥r¼/_Rr{6¸†\uµƒQXìÛÇ^Z‰eqÞWõ1¸|2ÜÝìëÍ÷ôüɼ;˽_ýe×oüüœYµÄ2ã­¬ŠÇfÞ:òÔ„K+‰ä{¬]Z:ö8a_”3u³æ·Æ¾´ct\‡¬Yœ›Q}?In\‘^–Š0ǯôðÿõ¼ÿúÝ›xqÎ4Æþq7s~8ßÚ;®÷†Uýsön싾][×Qýž£íÞè«ÿÚΣßÞS·RîíM‡üAÿæÂûZ¾ž¿~ðfâ„ÜÚ›ÿøƒÿ‡M…öµ}=~ü/àÍÄyïú„yïú‡=2[é_°ù¬6äÔ¬Ý «®îpíI¾“<)†PHRiÊóut:éëGöë+N²¼£òä²M^™xÆ™%jÝ ŠhÖIêËOZJ{&À>磔I­:š!nlÀiÆ K )'„bËѦH¢qe¿Mõ,îrÚÚ´½µ%oÖœ)­Û"ùµ¡Ø»hfk…›a³[ 2Ö²¢2JaDðjßÚª,š±¥Íò4ñ¦ÕöÆÖ»2Š5Kù!QK!§L­Œ*Æ[ËŒ íZÓ{ØïèFÄå…+™X+k 2}ØØkœ?Ö ò¦êóVïŽ$ƒÁšb9ž2žü‡0Á¡1è­’ÎÇŽ7¶xpl Åjõé+xøèéhZtÑdNgöÍÉk[Ë äyuã/¹- akÈXê§úê(²u™*ƒ5h§xmÓòµÊ刞ÂÅ×7è<1š/&³gã_XôëÇA[5Ìä}5ÕsŠn¹CQWÕ]y¡Õ §bnÝèÒµ5¡ÖvëGÍG'—åûýDÝ_Ý-þy:ÑÉoßê&êþélðsÈ ½Çî–ÿ S”wœ±D‘&1±*†´±¿KÓf7 ˆ£šB¾%z’hó‰âÆ£L†VÕšºFXÜ]6R£v¶Ãe«ÙPk(rG~P›M©]âÂïA±ßû¥†ÃTç`×ËQ…fxÍ׬msŠÊÇB‡¬]Zþ‚gNY1;v¸yé,Ë›•êî凋Èz»YF£S¿UõKêF5®-ªä{Ghü${Ghü1ê󱬚^ÉÈ\À¸êZB±ËÚCšË-äøå®dO×}mpVÕ‹ôÏ´6-«™Ê½Çû9ç…6sv?¢ŽÓê+ÚņÃwØRªòØ»ä6u‚Ç‹|C:2⣠ò§­|ßœd4bÜæ{ÍÛòLûGc½q3‹Ûؤš™iŸ'¨®ë¶¨Â:C$c®)(¯&ÑYõ£\5EôW×YÙ'wÚ¶nÄÚ‘©ì™"I]cš:$«-zGi,›KYê6çSÞKë§+f !†¯Ö׈IØæê*x›¶”‰Ó[e*†¤ZÉßdHÝ«¥5ÍdžTNñîM7×›ÕH3ã+Ÿl;W#:.71õ§BÇÈçh9ÍŸ¹Ô†¿\+늢#Ôp9еõûŸQ²õ}U!Ê.`Ç-è¶,ãæPfõ›aűfkhÉ)ÌWæûLÛ¥V¢é¥m<–¹rEv%­/¼Ý+uÈe°9ÄÂO_Â%by|Âÿȉ\ÎÀ¨f“=üš•¿¦2YÊO“tƒ¬ŸKmFÝ/‘nÖ•\™©k¬eI4aåÙo¹ÀœVÆàØõxùµ®jÇŠ1¶)"¶nI¤ncI; —µ#§n¶9•€þ×õd%®7m©këí-“¥Jß‘Ôm”îj´õ¬`þ·8Ãeۢǒ:¹/£Wc¦ž´¶e”p^oX<‘§("ÒØ’=Za. ÝÓue±“ÎÝ^`¶ìRRñ[/¬aúl×t—n^öÛµ­%=ÇL ÅlS’mÌ©jññ¶_§VD¨Æy\úÙ¹.Ù$>’‚¯Xë§k·Ë¾À±+J±±Ño+–Õ}_ªDœ cXæÐµDu‡Q¶á!––cáQ`Ië§ç$ _"KöZž9[VX®éÓ:l%O¬½·Ql}í¯§´ªÖÕkuG¤å®¡±ÑÆ×4Ž)£O3·<ÁÛžaWåYùŽÏŠ ±]‰Ža:²à°­}W%6J4ñ¸ô…óAì“M3» GUé’rõ{R§M„îŽhÞ¥vnjZÎáååú4ÿíiMÿÌe´*^Xÿ£OþÖ”ßüÆI­=zža&´õëù†߿׵ÕýíXÿã/ßëÚêþö¬ñ‹È0`ÞŒÁɉû¬‰î¹§#÷û )Ç+£½Æ›-ªX¡ Y­ƒe².®Y' Ù`@¿Mߦ½é0¹lI§k[yÑŽém«“Ò^(å7{²Óò1]~¶5 Ó×Þ|ÚölÞž¾óæ×´ëfKñG)»Ý–Ÿ‘Šëõ°âŽSw»-?#×ëcZ0Þu›_¾¶L7f×ï­™/ŦïvZ~F+¯ÖÊ9MÞì´üŒW_­h çYµûëc çYµûëfKñG)»Ý–Ÿ‘Šëõ±?¦.õ/^\QÖzã)^,mî_ Ö±œ±q6šv'YÆœoAñÏN–ÇØmq_¥¦Ìà­«giÉ*GGzËZÛ5Ùt¤ 7Ÿ6¯Ï§´ëc çÍ«óéí:Ù’üQÊn÷e§äbºýl8£”ÝîËOÈÅuúØÖ€0Þu›_¾¶0Þu›_¾¶d¿r›½Ùiù®¿[(å7{²Óò1]~¶5  7f×ï­Œ7f×ï­™/ŦïvZ~F+¯ÖÊ9MÞì´üŒW_­h çYµûëc çYµûëfKñG)»Ý–Ÿ‘Šëõ°âŽSw»-?#×ëcZÃyÖm~úØÃyÖm~úÙ’üQÊn÷e§äbºýl8£”ÝîËOÈÅuúØÖ€0Þu›_¾¶0Þu›_¾¶d¿r›½Ùiù®¿[(å7{²Óò1]~¶5  7f×ï­Œ7f×ï­™/ŦïvZ~F+¯ÖÊ9MÞì´üŒW_­h çYµûëc çYµûëfKñG)»Ý–Ÿ‘Šëõ±;ß¶TUÒ5zËG¨Ë×Aë6ÎÄжî“ÕÎ)‘=i°8hý ‚Š?›«ÒúO¢ú-_ÛÐÛÔÓÛÙP0Þu›_¾¶0Þu›_¾¶P;&®yÒX[Ms ÊZ‘–&çM^Žž'²Î$.n»Kµ–,q‘O4R!@…&Š$­­Í: 6Tm:¬qusÒZÚ…“‰ñG)»Ý–Ÿ‘Šëõ±­RzϘé{N¶)=gÌt½§[2_Š9MÞì´üŒW_­‡r›½Ùiù®¿[Ðγk÷ÖÆγk÷ÖÌ—âŽSw»-?#×ëaŦïvZ~F+¯ÖÆ´†ó¬Úýõ±†ó¬Úýõ³%ø£”ÝîËOÈÅuúØqG)»Ý–Ÿ‘Šëõ±­a¼ë6¿}la¼ë6¿}lÉ~(å7{²Óò1]~¶QÊn÷e§äbºýlk@o:ͯß[o:ͯß[2_Š9MÞì´üŒW_­‡r›½Ùiù®¿[Ðγk÷ÖÆγk÷ÖÌ—âŽSw»-?#×ëaŦïvZ~F+¯ÖÆ´†ó¬Úýõ±†ó¬Úýõ³ _æ™%(bzŒ¾É2Ñs$‰¥É‰áaøn˜ÔîY½Á/IG%‹uŸzXîû:6žÐ·­_Dé}¤t^–«£ý'ÑtoØúM«ÂE>g”¯ÏÍ'[ùžR¿?4l©}¬Ù§-=ÿÔcµû4å§±¿úŒ¶€´ž¾;u²ÒzøíýÖÊ—ÚÇýšrÓØßýF;Xÿ³NZ{ÿ¨Ëh'¯ŽßÝlRzøíýÖÊ—ÚÇýšrÓØßýF;Xÿ³NZ{ÿ¨Ëh'¯ŽßÝlRzøíýÖÊ—ÚÇýšrÓØßýF;Xÿ³NZ{ÿ¨Ëh'¯ŽßÝlRzøíýÖÊ#h_ÎvlU¢³YçýtÌ× W&×Ú«ë¦ø³£Óž»v‹Z^Gwe.Ž›hì¬åHØÞ­½½J‡eo Ý!cÔià¿Å Ö€J_Ÿë·”¥ùþ»yd¿ñhÅ Ö€0ß§Œ?_&ôñ‡ëå’ÿÅ ƒZÃ~ž0ý|˜oÓÆ¯–KÿüZ h úxÃõòa¿O~¾Y/üZñh5  7éã×Ɇý2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#Àƪ½aüSã.%9.5UèâŸq¡b]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@—zW'ûÂõñ%%ç(Ļҹ?Þ¯‰)<\j«Ð&Å>2âS’ãU^0þ)ñ—:F%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„²ÝqWÛöËÇDò 9µWOÑ÷\…ÑJV툪ȭý4ÈX,9½™v“®³º‰k¾5ΔIR®cnnFÜíÖkuyR¹á#®¸®JPT~EÁ[ä 0›úŸ­.¸s\±+rSlVÔ…²Î£ÍòT,äÚR'yJÖøòÜÇMNŠWÛJõ²Ø®ï<·Ê¬¾ÛiÇL`ºá8ñpWسµ—eÎa`óƒ^ìbŽ7e*¨¦TìQ0œªs柔奓ŽÐ×Å3¬êH¯[¹Zí¤Ù3g¥bÕüN¢û/âÆ4ãFôïÇgz›¢÷ש7g|8I]G Ó»o ÝýàÝþ¶êN¾{ê®—Ð:ÝËè:f°wðŒK½+“ýázø’’ó”b]é\Ÿï ×Ä”.5UèâŸq)Éqª¯@˜øËˆÃíÎÅÿ·ýsÿñeͦ_ó k¬‰bþQs“3[Uv_ÿJ[ÚUì‚­ÀœáÈ$ õvàuc¬úÅcÐ8óf×ëzYO"nmšr^¸jxŒ¸&roIÿaµ­ßþ²Ìuû9Ïÿá;ΛÿøÜ þ À´³†—¸ µÔ2Î~Ñ:‘ug\*Þolú£§iìV‡†÷Úû¨­+ókür‹ý,ͱAÏ´ô¹£Ùõ#¹9ÓèW{ ±o@ÁŽÔÿÒníiû“¾Üâ/a>~÷p»±Þ÷½Ý ø£ÿz~1užûÝ/°Àü“e‡eþG9êè–oiwmÙ˜¬á®êÑ0l—~þ`‚>©ÎcÐ)+*5ýÀG*é]u»ˆúDµ¹Ù…>ps í9½QþP=¥PÇlMõhñ: Ùg¬¤rô¹“D©æ…Ä8&Ý;©CªÈ¶àèVj{Q‹ìc‚™‘Û3vÈ¢©$m”÷{Gór'›ï¹…JÙ/ÜŸªÜtäêlR˜‰Î?EVEv(ʧU±åÂcù»|ײw­y¡Uç9‚»7#nnjtÉibì/y¬Y؃èù4²*²TóI%ª›G#ñ©d†™å»^TÅš8ËáÒW˜ö’§v¸ü±Þ:k<®I Üúã –!kR©LqãI€Ä¶¡‰Uæ¶fPN+üÿžq^€Ã&Ê›lŒá|‚O²³òµLÖ­²£TŞnjµE¶Ë>Ç-¶¶üÖ]QâãÄúÜš*}Øë|±–lWü°²$úùÙnÆæÖö@W´üNÀ©åy³ùÁªÌ`Çýzv —ÞÌֹÊþgƒ®$Eä‹´4³Ÿ$q//ðö9‘HòR#f§ñ« ®kl>óC›‘<ß}Ì,‚VÉ~äýVã§ ¯S`tz”ÄNqûú*²+±FU:­.oÍÜkæ¼m(˽kÍ ¨×9ÌÙ¹ssS¦KKa{ÍbÎÅ`2›ÉW–®y ƒ`Ÿfþ­­EÈ$³.mÚº h]ñzÏbiæÑÅy´q뵱ö<§Î²ìyòž·ÛïŠ Ú†͢‘ª–Sbdv…¨¼qû’þ¦±ñºésXQøkRà«è×Iç[_mÆyrܲ¤Pêæ½‰³ ÐXîû }wY¶­N‹rè«L–u'×f„ĤòŽÀ`8ŸKì›ЄдIGÜòÿ›GWetEíÚ:‰®rǬ˩Ӧ"akC"Õü§#j™ÍÏ’Çf.˜êRzP‰E’Ë`Gñ.™«ã¡¿Å@´³»é¹Ûí;”XKaYÄé¤R€ÈK"“¤:;SµÚ!늲YBã¯QA^X,ù§lŠÿpj),ZÞ›îýe(Êܤ¼¶¬áÙqPás¤zàSk]Tý©uÅ$¬Ôå„óM7Ej7¸c…¾Yo·±kÂc’Jfˆv“%Vç´ÜǯËc:Ãå7>0[ÙÁ–öÔJWnä^(ͪ€ª1–qÕ,Yk!¨y²³‡!§yâ–Æ¤àM’¦úÿ ñ¢œ˜Ôµ­~–¥AÆ["Ò|Qjdt¡¶Ï«kfÌCz£i<†ßb]é\Ÿï ×Ä”—œ£ïJäÿx^¾$¤ðqª¯@˜øË‰NKUzÃø§Æ\@è@Ÿâv,Zöœ*ô´±¦€²®Ú×w8uqOéºêciÀw:F²aÜ«Eq–ÅwVZâá)Žuº£‘¯XöÙÑ\ÕkªÛïàF%Þ•Éþð½|IIyÊ1.ô®O÷…ëâJ@ªô ‡ñOŒ¸”ä¸ÕW L?Š|eÄ„Q‰w¥r¼/_R^rŒK½+“ýázø’#À­­dQô¦T‹ŸY‘ªÒë¥L­Íu¶ì¿Scé4uµö56?oOocSgö¶y?kckgk“ùvv¹9yjóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó#{¢çxÓo™(ÀóïtS¼ñïmó%5”ki(“Hµô5tõô5ß]õ´u´vöu4µ´µméêéjlríljiêlmrmìmìròìíìòòmlòòòròrž ²Î‹åg’8Ã\Ns»°UA`Re6~žuÖ(E7Úɬg˜zÅ^Dw£,ªkb1£ô1‹bÕyꪇ玅Ö*©ojèìrÌlç_¤§’)|ÎÓ϶·\ú”bFÙt½XY~Ȧ$Å;Ö^Ý®‡^¬Çð“" S|a[Oc¤– ŒRK2„nšÚÚo´Î¨Îiµ\’|z@ÀŠï ¤ý·¬ìX»¨ÛJ¦†ožÌ·y zè×ó‡Ý)³äaŽùc­rtP²»eªtÕèª%›±`Μb^_Î{¶th—(ö0æLo*jɃ‹òé}o^Æ#wŒ¶-SòÜŽc:×oeEmi»D&ê ÷Ú:Š’·Vó•GqN«NX¼æLb ²ÇNqåŸØ£9–bUÞùÙH4Üh)ªÉn76oŒ ŽI¼Y·ý|é`å;|"=H%œ^ÕôV'³mV<‘×Þ¤ Ô:Í rÉ=ރݻìë]3mÔw|5\îiKµ§¥j¬ª9œ!¬¬WÔîÎ,zS‰äáÁuZ¾ã5­®eu?±ë W^%ŒÊ%!ÛÁVrzÕ²`Šqúº¨”Bì<’»×SQéÝ~°a•ÖïÐw¦D»HÞkhÌæ¬|Ÿu» ångCi@z•Öj†p¥Ñõ$MDVÆVÉ©ÈêÝQ|°ñ¶ïCMHguÄUú¾†X»ÁAÑyÓ#f­¤Ó›MòÕ wÓlÅu¥>ë§XRéÂgF$’Äðx Z` {É¼ŠŽÅ³jyQ[|æ½+Èæ,ãU^G·£`üG™Ø¶Ö_Ælçž¶ËJ6×|ê:¢©CÕÐç&¦¨ÿXô—4:ªä)ÔmÂ3–äN 9¡KròæÆ]œάµ±ï) %O&_?ÓöI ¶šuØíTØXâ5EËb#Œ£¨á¨M£n-.NMSYZf§Ý³9ìnÏ|·±‡0±ÍÒ»ÃÙ®r´CnÊÞ½l’ZTMjƒae‘§U¶ç‘KN½PëjœSü®¬³â«ì¸.£Üa[‹›“8iˆ3©ÿœž¶Šo¶ôQOáœ!%ñcõý^ÂÏÃü>_½Ý/fÝc;Mº…¼?žtLr}èàŠw&]ô8k·»o= xó“ÖÔdÎîc_De=‡^bç {R_Õ…^ÂýPÐ|Hji˜joÃÔî7iÙ|4«$‘KšæìõX\Ü-«¥Lr WCWª­©h¨3ªãç'­©wëý#½”ó>'Î!Ñ<›¸+꽆E[SL3JÚ¡¶Y«öõçm“{„[šoöj BiY53 Y.²«è¬殓Øþg>å¨,,Ùcµ±ÂÓÁ1Ë"á=S2cÕ¤•èÚRÛ6 ‰ÈêŸe.ŽC¼?ìZw¯‘È]k¹Lš)YRQZž[Ó¼'µTî?d¶³†˜‚¬Ç2aùÉ…Ñ|»²ž²“µN)¨ž¥}#ˆÖÓ7åŒ7]’ÏY4Y­rÊB×¶ê(D Ácü²å@’ÍÔ²jJÚñ`Í«æ¨Äе_<›äÕËÙϲ ÷s|xHZ÷.èõÆïoW oómÜëþ«|ê>¼ê>¬ëŽ¥xêΕÓz­Ãè:&°vðRæÆÉ>HÂñó æ”…³ÅšBë¹b2êj”žP[À)æ<Â_ã’6 ¶CdŽþoçiW6w†Çªûqø|è‰k\ã~+ƒÝà§¹¡:»`0jõ¡Ö|b¼Zicwý‹¤e¹lU4“¥{cmjÍézb¤üÿ-´õ­tÕL.6ã­WÞQ*ûF`ãgY4¼æ´…Ì%å•uîý[@ÔÚ²\—„f¾)LçÉUc½á\¢­nwë&õÉ|o'¶¤õ¼gˆE‘8¬ÓÇeU¸~aеXQYŒg>…%–Ù!¢ §·ŽmTøü÷e±Íc–›ºŠ¥ä2MÀƒkO—¸ Í\‹c-\ž!/];™>1Nëç§YŒf9p’kÆÕ3é×6 ½Ã’#¥Ä*‰¿¯Lé”UÒŠ—"ñr´£qÒ®·T¦Øhú‚Ó’]“l‚¯6PÛOUÕ©‘’ý4)êfù-šš’VkÒI!w/%úäé{¦#’ Óbß&á¨ó2wó¾ö$á%ß_ÂjêW}¹º`ѳÎ!㩯.èÙ7Ž–Mœý×Öu“ehõþ¤£]‡üÛÔM õ"Åβ½~*Ùù(Žß•Zvýi@áîHcLQšÞ7/»m{Úú½³åOŒÕÐØzy%§rúþ”†´ÆZÛbuƒ4µBuLí5ÌmÂH»`4ÄÕ­ÎO[FØn•vÅ”ôÌ⃜c N{OË*ö½’½‡/l˜ýOIÙµ–Å;¸aT!înå'`^‚Ÿ›N,”Õƒد”ÎG£Omœ ºI³“Qù\ºFm:ÕLbÕî¼oí‹Á|·`³ù”*ИD,‡ËÁE±Uê3ébãæBèÔÈ,xƒ®LkQmn[K4ý:¾²zÛ‰;±ÀŒ§áj~Åý¬¸^ÃÙë´/_pów>‹~øí¹vÿ»¸ÀÎ9þéq#«ÿÏÁ'9=l¦TÀƒZˆÊt‹ÆS˰½Ç"Õì;tÄS!cw<ÚƒfŽ?ê!­³”Â, :(ňÝÑzÊIF"•YšúydBlä<"¿ YQ|â3É\ºQhâUÞÁaÈ2Ÿ qÆ‘®#kq»iÖï~ª-ìžnֆėjå;ì298§©\o”>Þ²zyTVÒyœZM£¯–:Gø+3­Â‡dù>ŒAï2.»’L­7Š¢E˜Âckµªuí•<¾áE6ŸÍ+ù´ê¨r«$L¦h³=‹VXV\oBذbü[–Š{„‹tÊ›vIIÓûRÈj5rù-§tœQL™2÷(ÜrI’YWã»æBÂÔäÂé-c¯]-³§h;lž¾t‚:¢ŽuPù§/e„PvuÛµvܸå|¿U“ù}iVP×cm—QV²Úb6ã¾e¹G][L­ûíÓaòéÏêgf 2 µ‡J Q U š…Âά«ÊÉž8e63·(KÖxó$¤2Ra»ZíHÀZ¢÷~ Ö[ùK‚øê¿Ù„QÜz“I.­·i½q ‡PkíK¢Bë$w¨â©h¨3«8r²gPÈ©Z¢œKÒg»¿[²¾Mv¥-UUgg;cÓ“sÚ1ÙwòN2ˆ³MJÌö’™ú_䥋 ±ÑN(41Y;ë'­¸“»Ê~v§ì_ÚË…ì=ž»Bõ÷7sè·ïŽÛ‘Çoû·ñ»ü ãŸî—:¿üüŠƒ:´¹ÉëeNª[›¨Œ§uH®ïº±núÝW°ëµ[™GHLíH»å\híNôßõë97±ÐßÒFhÆ!¡(nŒ‰ªì8e‰†ØªŸ$ãw´ N1´Ò'˜±ß²‡xº Û©ì,m¶"Ô…§HÙ’–gרÚKM%–õ,cŠhÃÝfpkCjÊ೩ A‘úF,eÚ¯$z·´OXÒž{ov6àG 'œgþßWgûIqËr=7þŸ·C²ß¢¿Ð~ôu¿ôÞX»òλvnÚk¨gê²/²êËæìr²íÚÖ[sÆÛ£t4· ‹ Èkhm¿B:m¾L]2Eý4ã^ÌÛAA_¹0êÁdŠ&Éd ¸@®˜­nÉ.ÊfY2BÆ’_´ò“•©Œ¦^Û‘É1· ­ w|œÇ˜]\Ÿ"Lv¥\ªtÓr“Ì×ÁPH“ÃÖN§Jõ%ïV, é&¨¤YkI_)W1éÄ+ltÊ:‰ñµB•û2ErK¶ËÃù”QsJ=6ÝV½v6ö¼~™hHT¬x@½"÷8Γkk²u®ª™aQ]¶&Ž;Xڵñ«"ٮƈ}ЦZÉ^Ùq·jžß ,ˆ3ŒÞÛ&’Wšõ¥é/‘B'  VJÉÌn6‰ú òÀæçªŠá2Ê­Ä\‘Õ±`÷Ö÷H"°Ý9ŧù“dÂ*×)ã¤2[jsyX¸ V×yœ²4ÐùjN1èT³Iü½úN0¸ººX¼‘Ø»ZF(ÓdŽqVb-“¥y¦ë‡g¸B‡ÌáÇU79?jµH÷C›þýÅ7.k©$Vïôö©yC¼ÈbK Fò⣣>'CqÑPK Äkµ³±ëg¸Ó€¹mÆv8­E…d\ª[©±#u5i¯*Ì›ØzyÆ+®™´Ôµ °e¸öŠ«·Ð"Ab#WËm”ñ¸å—bðæ·±z®¢(­§XBú‚ ¼ùYÔÌ- gZºÉ-èä¿(Ê®<ÛäpRùP?Ø”n¬Î|Ý™ÊZ«ÚUõŽo_(‡1ÝàYÉêªÉ©Çë¢O|°ñ¶ï]rÇ –<©ú¾†X»ÁAÞ˜ìíy²c0kMòÕ wÓ”ý¹á [>ë§XR:–¶$’ň£j«&§ l[u¤È8Bêò¦iÔÌ ïœ_ÝËFk6G&VúǶ™ÙVÞ3ªÓÄ[&qJó²W /p„ï™ÝÄ~*qr~ÒjŽo7ýŠm¼G×MV­£è,:®Bò»vPËþб™Å?I|Pº:Ýí»Pwk$·5Å"ØégV™\øËnªj»%º¨dˆi,vÆÙ–2N«6ÚúDÀ®¬´êŠ-ñf®BjL¤«àrK+Eµ×møÜf……~€e‹X‰ock­é:ª*|YÆ6Î1o•f-Ô–-£ac,iª·™í2ä]çÓØ©±õ¢ wܘòö’Ù „ÒlPÍ[…ªg6,Òm¾òÔ‘K½“T×hÌnÈ<|Þ=Îãµ!kÓ[ÝÔûú¼O¿Âw¨:ѯ:¯:Ï©ú韬ú/BëFÿ§éz=¼Hkšç$g# È<ƒ…Ò7 © ®šˆÄi«®y~ïÇg˜ó6‘ÈßæØóÛ‡¸}›™[ÙÛløâ ¢Õ®}ÇH’qw€ˆ^lWã³T-Û§ˆ¤ž8ä–É¡Ö<]KÌ2ó†&†LÙÔRï2ömI=1×òw¸¬™ºêŠG¬X¬= …õe¥[!€H³ª}‚ù#e&ÊëÑ;†,ÓùE}v—B Q˜Üò}P´Y<Ý—ãýñX+½n͎ýxʯj3–ÍšiŠú «š#p¸ó§«^·Èe›Éi&å­ÃcZ–ͳ«ŽÇKóš‘Dn]Ìì¹’4o³ÆÁÉËE¥òÇ’Öµ3äÚ!+Út€ÈPV5‚ )#îÍW"Œ¡kòÞVeÞŒÔRF\µ»o•K˜õ"N:båDÆÚJý©"I%%eæÊV¹Ù£n“^ƒƒ^@Ãt#ÊQ¼/^­{d›Iɵ¥:&¥OV,MðŒÚ§.ü³”TU,Ú•æBÝñ –<ëcåeµLÌØº£qºvŽ<Ãã8Yy1íþÃåäúÜð†y¯ÓZŸè©kmV‘FƧ+Êœ»ruŸ$Õhã£D¾äÇNnÖ†:æÅÓ–ÝT’Ë· ²‚ùÊY]gk¥Ô‰W“,t²]'ðÚ±\­3|µÖ$²m rª›T7µE¤:ÒǸY( v;*tæêÄ}äÊ|µbð,Aˆ¿ é5¶(d3|O\·fOPñVpý»:*Š*Ý6ÿ§¡lyœÉ7ÍöCíólE²d¦º Ü#KŒüâØ1—Q~–äý§Ð+ldú»÷ñ‘ÿècZýpíÙ&ÇÝÖîµa_×pž¹’°u“îíè¨ëîn+&¿Éò¾Í<ÖShÂüÞ³r‹µýƒM¿I35mfO%—ïÐD7zk¾¿·å{‹YdiͶ¥U‰È{?¯“³îÚ›OÙÉìÓÁ®»„o?Ö-Úë§õ“÷PðÛëkíçÔ+vºÃ~8Aû¹Õ½WÔд㵫`°(O·tÎ+ï#g1•qe¤¥C_¯¹¸¬šÿ$WÊû4óYM£ ózÍÊ.×ö 6ý$ÌÔUµ™<–_¼;AÜdMé®úþß•î-e‘ý§6Øb•Tn'!ìþ¾NÏ»jvðPœE²c}™zsÜ#WƒâÙÏ—RŽˆäý©Óël›úÄ7 ‘ƒé£Z*pÓÚÚ¸Þæ×ªaAÔ“n¦’¿õkòup+v_®Ü¦Z®s§$ÈÓ_8î†7ª¥µ¥ƒe²¨²l†Û¡3š]Uè¬$„pw'¨ÞƒóÂû„Ë.Ê™#Õ½ººìóÛ{¶Oø§<ã?öøúÄøqÙ·»‘é¿ô½ý©=þœ7_­ÿ¡©Î«µÚ³ê¬°ã¤þ×­ó“Ù­,«.˜¯\i+æö¨çu4çjÉAP_rM‹NZcu\ÁbAù+=ˆ”šs`OŸ£S¨Û&;šß tÅjŠIIÓû19’æ5rù-§—d­4eJ÷(ÜrI’YhdCä<üêÚÂé-c¯]-PV™Ã”b¾t‚:ž`² Pù©e±`ÿÙ endstream endobj 388 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [477.594 122.082 494.544 134.701] /Subtype /Link /A << /S /GoTo /D (section.6.1) >> >> endobj 392 0 obj << /D [390 0 R /XYZ 86.4 708.045 null] >> endobj 118 0 obj << /D [390 0 R /XYZ 86.4 688.245 null] >> endobj 389 0 obj << /Font << /F22 239 0 R /F17 200 0 R /F29 277 0 R >> /XObject << /Im1 387 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 396 0 obj << /Length 1109 /Filter /FlateDecode >> stream xÚ½VMsã6 ½çWø(M#Y”õåÞÒ¬ó±³Édbç²m´ÅÈÚJb†”ãñþú‚iËZ¥iZÏ^™À‡‡G€¿-ÎÆW$âOã8-žG$ül”™Dñh‘~wÂÄýsñy|]Ã4õ³ˆŒ´¹¼¹xXÌ]o&Nâ»^š„ÎÓüöþ—73õ‘:×7·—_pýinnï]8 —8³Ç+—™sᆙs93‡O»‡{IàGA:ò&ÄOcƒó€¤hÜK‰øÙĽf ´exhÍäZ¹À®G"?Š´zp*Ï\Ô]KýU`„’7ƒÈð4/Œü0˜~ؼå/xÀU6Å®ƒ‘Å“îñs'†tÍxÍZ±Ïò‚ɱÂ5žójcsÿݶlWŠ9ÃÔÒõ­ZÚjFYƒ;* Í0ò¨ó¨U°œ99“Æìÿ¿–rC«ò»¶öOšãW®‘ðAPQUCÉí %ZÊÍJéÓ¡]Ó±¶k£˜íšW w?„6)˜+¨ÚÔ¨5I—¢ªå60¸™0Û²É9’IœÓÒpÉðT&†rïìz“,vomYâÐ&ǹ‚"pµæk*þÒµÏq+ÏM–ç®hW,¹1¸•]jÞÀ—7Õ½Js–‘=|y¸ñZzCˆï²: ŽX¾œ–·GÅßqLÁÆ_QÅ(©Äùž[‹a#M)s%¤þÐtÂŒà÷ªÙ’ãï=Áq¸Nqä|c«Vç A§A ¨'~FZXùIˆ¹1®P»ºFíµ¦Zœ¦éWZ3 }ˆ£À'¡=íé^jë-‡Šu¿©Õ¦i¢{÷Óž^w¤{ÙÒ}#?Yag«ÙŬ…²6è˜ –™RÀ“Oð—ü¬„æaºéÿJMBº2jbÝH¦‘çź•Mc# ;…yŸŒôÐJ§½·w¬JýIê6¥¬¹ØYð½Ö^QQìë·–8Ö” ÖÐ÷’ÅÇ€NSç3_ªk„úV@¯+5Lª )«O|#ʽvÌpÚ}¸è ÌGí¬6B˜(èôM5õA%ZàøîMFó§ÝÁ Á¤½«æ^Ê—J7úÝ~(…ô‹-Êbm èŽUæìX‚íQ‹3÷^WTƒ&ÁVÓ£:3 (%®´Ö·0Ï!ü¥”}´"õ’$8÷Z2wEüXbå ÖÔãé±ñE›Â2¯ªu¿;¨IòëÎ b4‰Ž³ÿWBfŠãó`nìG×rÓ¶v”¾¨Ú"85»@z|õŠÓWç'½ºC@ë2Ï+öPõ{³¯=B*ZTx† OßÜ qkDNý0‰Þx   U­BµD+Ééfµ%µòK”_âàƒn‡®œŠü})~€2èF’‹£“L¹ð¡ô6§l¼Ðv­ø1伉««¬U]¼Gw6[œý —ëg endstream endobj 395 0 obj << /Type /Page /Contents 396 0 R /Resources 394 0 R /MediaBox [0 0 612 792] /Parent 393 0 R >> endobj 397 0 obj << /D [395 0 R /XYZ 100.8 708.045 null] >> endobj 394 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F29 277 0 R >> /ProcSet [ /PDF /Text ] >> endobj 403 0 obj << /Length 516 /Filter /FlateDecode >> stream xÚ­SMÓ0½çWøh ìúÛÎuEº,R+!‚8‡nÖÛ†æ’i÷×ãd5h÷Àå0ã™É{óÆã›<Ùl%GB°Ô‰òGä-ÓÈqϸ6(@_±e‚ê¬ÀùûŒP%Þgùm¶}‹wÙþ3Dïòl÷‰|Ï?l¶Â­1Uê™M5â(Ét]D•LÚhsfæþÆ…{ 1º^‰°hù‡®­ §7`ŠK×·4w&ÒãðÔÃé¹%4š¶†Âá ÞÞj4þŠa¤E49›2†i¯îË)4„j%p9Û]èOàÑÑHü»ì/‡ª|&†²m Ú¡ o£o~h/÷U€ŸŠª,Fç²9B¤‡®<4Ç*ôp¬ÝyNÄŽ¡AÇŒI£ÕLk ö—îñP6–œƒ8‹FÍ·el 暯S²¸ìÁöa`ó%I)¤0zœ;GÔùñ––Í qBrápïÃp§3úutb«8•C¨û+¦fJ[9cjÉ4O¯ëöö% )·FV2ï—­Ø–Õ4£$Ë“qUâšÃvK­˜T uò+áÌ ×m̯ý))t¼~§äQñQ'ô’ÞÜÕ½k“ñ[ðéD@W 7ÓûKðT#grýÄäÿÐ|ˆIãZ‡¡{zU»M™±æ_¤KÏ´ Vp˼˜çÒÕ"ýnx endstream endobj 402 0 obj << /Type /Page /Contents 403 0 R /Resources 401 0 R /MediaBox [0 0 612 792] /Parent 393 0 R >> endobj 398 0 obj << /Type /XObject /Subtype /Image /Width 191 /Height 390 /BitsPerComponent 8 /Length 29525 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFa[ÿÛCÿÛCÿÀ†¿"ÿÄ ÿÄQ   67UWw…˜µ¶× %&g—¥§Øç'Õ$8V#(Xe")5:fEHIrtvy†ÇÿÄÿÄ'ð!2Qq‘±¡Ñá"1AaÿÚ ?Û!ùùu!uµ]]·…ƒÀzY½úº²ßûÙ·w¸¿K{wsÿos‹ó~—èðþnG£Å‚rŠ3«»pß`vüâýdyÑ7}ÉðP¾.ò.ý6p7ãàùøÏ‚¾§ñ±<Æo³úsv¯¿Ûï¢þÆ®ÕòLÿñqÿù¼ÏÿÊ4ÿwT÷ãïåtßíÚwT÷ãïåtßíÚÉûË™–_ ¯y‚s =£¢FòãÏ­Œ/âÁÎ0@ëQ¼…_†)Û,#\€ŸOÆ× iŸß¾F v ¯T0µâF —·‘/š¿2<”ÆãœÝ+Æ—KLžF Ñàå±rqx¾°žöaEÞš3•Lg!­ŽU££¶&++&â¡¡"Öð„†òÖ4JºZ:Z¸’¬­­¬¥F]4‰“$lÇÙÜÜá ¾îMFÇŒƒO¨ËD hêI… Æx…ï†É†ï Gµ£!¼ª.®êŽê®\[*›jÙR`XÀ“d9Ñ÷¶÷8²ïÌuã“YK'^9,ÝÞÍJ]¸CQ8¾†‰j¿hÚå®D ÈÝf5Ç„Gõ;ö ŠuqZl^™Uä¦q Ï÷œ–ì{ªñšu/|£[\Š¥hh÷’ÞC<¥—Ä)ˆ£#;&¤’[¸yQdºŽ<&¦ú9mæñ|j}º‘ú;­›éüQê·jlx%ñCÞÈyСěÐÅyƒŽƒ/)wƒ#1S-”Ý+bI!®ÍLÑèë«+XÅû×…±ï¨÷Æjvéø§ßlÝTîÕG—Ác‹{¢ûª{ñ÷òºoöícBP¶b§ FB òùÃÜ»F“c¢8›-·íšM‹Çi§¦•?`B2¦GºoïÚkö»åà3"Ús=V[Œ{<$!Š™Ü|‘a΋Élºæ¤}œ\ј1Hpey…¾Á½›YŠÖá½J ³»ƒ±ÛîOl\%}XõÀžéZ÷ÙdÌ+Èã ÂôßtÕä®± TÕ=øûù]7ûvÕ=øûù]7ûv³]•9—Äni5h >r€ÇE3¯p>J°9»0NX ™;kBݶ+Û¬$]«!-„)JÑÔÍÀ{ €‘‡9¿-µ28Ý¿ƒ2˜æf²Y6wè§'³jÆËòu&óWÙ\Ä^*›wÔ.}«ë¢**ªà7ÿ´‚K§’Šß-¡›D]³ŠÅÛK`5¹ÝSß¿•Ó·iÝSß¿•Ó·k$jeyÄ j̸f4ÂoÈ0—œˆ€ÍêŒt16Þ’fclŽ>ŒÞñ!Fx(Q¸Õ?b´KmAöKêCp=ÅØcó<{ròÊÃW­Ë¿ÙI¿É ‰çÆèjW`%yœ¬¦íÔ£rд¨Þ:A•a_‹/e |ŸCÉaÞñêªýÞ #5÷ƒ±°b}Õ=øûù]7ûvÕ=øûù]7ûv²³>ÍÅÚçò~1G3Fð>oáëžØ±®…C8`- /p9`® LÚO£OÚI¿·]H+7»$³$µ‰!ÚBêªôÍõClÛμ0 Î|4v<Â2c<7½™}͆uì¬bƳ<öܵ‰4=P¡\‰ú=”_CGE…s0ƒ­j¸6w;zµ—@M, RwT÷ãïåtßíÚwT÷ãïåtßíÚðe•˜²Ù|2Ç<î£ p NˆñŸÒõ@ýÇ3¨¡^PyÑT[Ò(Ä:¾ò<â—¦‘¿T?æ>S]½»&Ïß@zuO~>þWMþݨEîQC3\7ÂmN¨í€íÀEA›¡ê¶oMz ^Æ=áHQÈrQÓÐlz~«fÆÛÂDÝàÞâ­þd™†ÞÃe Iª¡!Ü?îb·A„&Új…ÅÆðá¼z]9òì#rÞ‚%ÐJÂfÔm»^+©1âElH«¥º}ÜþfŸ“ÖsÞÔ†FyçºÉþ²ãO‘¦ |±YOûWÝÇ·…éï/éRõT«×•QÞHýGëºrœ 6÷T÷ãïåtßíÚwT÷ãïåtßíÚ£œ7æÞxdÑbÓÂÌ…?UÉãμ(h‡ ×V´ ô™Uz­¯ŸnÉP__X2o6*wq§/²Î4mŠC *°¯†jH<Æ~`-çÖb$ZÜ) 0é¿<Œ3†o1ÆŒüâxÕVä8üv YŵºŸw‚7ªôG^¬aÙÏÎØ{W.¡¿=e Æî©ïÇßÊé¿Û´î©ïÇßÊé¿Ûµpþb¹âÇOòìÏÚ÷Õª£˜§3Î&ÌÃÞâæèm’¸È-ðêÝЧTªØ¬²¶ Þ7´)Yæfœ3ĉ dU„…ŠÑ#~­ ¾ß³*^`-í¬ø›‹<) Ü^XœV›[b`ãDq“‚1§Ùdy{lCn×ÅÛÿ ÝTP ÝÅ—Xâü“}´YºŠg爌Ìñ»ª{ñ÷òºoöíp·0œ‡u†¢«7Ø·âS/˜”VV£qï=5^Šb[Þ(°oê"ú©õÖTu¼RwêgÁ“.ÔŠ¹;Ûµsì!Êê}W2߀‘?ª/¹Çš›X^Ý“k Û²Ô¾ÿo¾‹û»U‡_Ë;hIåa°ò-ihæiš»™ÑTYÅœ ñ²ÖÑ¡ÔàÕ~D‰F¼¾‘³nNím-˜+j¡ìÆ«¬¯‡Ï¾ÿo¾‹û»UÐç ËÁ>Hö2zÞI‘Œ7ƒƒ9@…Èæâõ2H[?ÑL<<Äi©ÔF«A›ËNAü56E›3ãÕÞ̾†ê’{y~â æEÓåqbNŽÝåKxYÂIÇxcnìåKHb4¦dš« ÅT0Zjšâz…ƒHè ‰„½.¾8y-/øï¢«Ë2”·.œªsÙäû‚mûÀ‰«ëÒévæô~C,Vè'f}ý¹MÅáÅÅç`‹6Ö–[$'ÈÂf‡–QØ/å÷ÈÉ0Ù¨Øñi hmI0¡XÍ´ á²a»èíhÈG¯*¤K«º£º«—ʦڶT˜0$Ç™Fô}í½Î/¹ 8…ËË ²§7©¾æX ¤.1ÇÏʘmYåEÉ‹+—Ñ­Rî¹Û'sù=%K(…¹nlTºsÀŽï¼oðu·§©ÖK€ÄâÙ|¢\StâñV&¸ó[" ¡€2/Mæ×³­/-<®Ž® 1¹²±µ›ê•£8 >6á < «3*+¿bÞÒ°í%”îú›£•æd#¶Ç"ØõFV×"£:·Ú-c µÆ×%£gãÎ帙ÑåGVH'z¥¾ mâ(- Ü{*±ŠÊ¯,¹çcÊÚŒÎpTŒ¾²ò£…Ââá†..Ì3AÑ™¶ê¬o)¯rX@"óhüò¢ŒšÃzÆÙŸªŽ0aç ꮃ1ôQÚn€ãÜ…ÀMá j¦«f©lÝ#¢y+*ÙacǪ×5Aâö¼’4ë8ƒ[2.ï8¬¾ã7 ±•ÆÉ`·XëN£aµ1d³ zÉQç¸Êq}<˜¡iå4EUtu~iyi:wYSV×0!zÿ \U&ÖÌ}¾¦Ó@qèÎâ‘ ñ]RNŽ] ÎÔàlRkÃQ¹8ƒK>=”4™i‘ðmôˆÛ{v×…twF7Ð8¤U^ØÕË•z\¯0;àÕ'±êŽ%Y¢²z2öµˆZÆy@ô$®‰ Œ‰“´pÞF,hâŠÃBóbr³åð®Ý(‘ù%§á¥Eí¤H2¢÷Ö¾10ØPÙ ‘‘ €•±1YY5´ ±‘º-oHo-dD«¥£¥«‰*ÊÚÚÊThÐ#H™2FÌ}ÍÎ8õoË ”wØæT›òb|Oî'bˆå°Ú¤WÂýÒ[ ¦‹|þà˜æâÁ™ú uPt¤vál  ºéQ€ñººÏ,aâkµÓÌër¡‡º¬ Ç*VöÞçÜÐ 4Ó@5âxâ˜f9ÐÙlçmüdîd º„ª·¢{Î+ %•ú‚¢òÁ'R @‰Yû]Käþ«ÆÐyU†æä¾?oÓ@4ÓM™Ó^NâÌL^~š‡á ‡³½i˜‡‰—–¯‹Zqk‘¹¡XRo»#qÔá×P¯XAÉòªö›T̼Β±À¿é‹Ö&˜´Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µŽÌ“#Aã•W2ìžåçÌ!¾©Þù®Ïž[ÅQÏ_™5dSõpBÃâoˆœ6+ÅÝ×´ðW'‹ü§`T*k.j” KJ‰µ}þß}ö5v¸È‡ñ(µ±òW‹˜èLò‰x2MÎB’Z]6#lÔÆ !ŽÅ²’_³x%†`fÛnã†}Í-NÕTˆœÐøvh£3¼É³:¸Ú­oIºÓÂf\KäÙ0ŽöÂIËí%ŽÅ¤0*hW+¥€‚UH4×ÊÂ^_‰Üƒ…ckNÝ`’„$¿ã¬§$35“AêpóW)±U]˜LvYþ™_+$12D(°5ÞÞ¡‰ÍÌ10 ÀµE,–áZ¥âd#3b0'Ϧ⪺e2WìõÄ‹ú1Ššû #Ÿ#MbEÙ“E:¬d—¨o8‰”ÅgËá#Ey'ú;^"ÝáE Uç ÈÝ—°ÔªÉþ™ãÔs=2Kì×Mƒ}íÌmý‹Ô•|ZàaÜ42ÒëXƒp2òF6qf¯J»êöC‡ñÑxG}`5"„ÒЋEdÕùÄårCTÏ£le©ÖÛWŠ9ц´ƒ£l¼‹'lj¨ÙéÖ-WønŠŒÉ—:)ZøÖ·l"’²•Eä>¨|0º-ËŒ¸Ý‘9퉷GyÇH÷•PÏé^¡ò¿?éζ ¼ò?<ò:_8òÏ æ~OWã}—Äõ>ß 2%+˜ÂŸù¢põ•€§1Ô8èŽHän ¸Ö;Æ3ÙM‡¦” ˜ v BëMZ ÞÚTdÛ\Ïh½dÌÙÈ¡±ã&÷Hm_œ]3Ç–¬î`üÓUë<ÔVc¦'Qòõ&dz÷îv2ñUN€µ¬>gÎǰÀ2ÔÆXQ´XµK5¶IWÌ€#¼ÅVìH$«!¯Ó6âQ«…¸e‹˜èZ×-£¶+g$–—Ì"a»ài ûÁâKQ™d—TwKIr—vÕ6VR`XƒI%2>õöåÜ6Æ\nf2D\¬||H0ëÿ è6©²  ­’Ò—ÒÊ…úDæö‚y8ßM“ÏœGAäÖ¼žúl»Šï a'zGðÏ „lMȾl]ÀÊ–ž#ðrêÃÔ«ã—ØÀ Ce6í-0¤á:%l1ÊxfSåÍÌŽ þb( (WŠˆ@QžG»Fž!•O<µg;M'œ8²/¯êÿ&8Ðê& -65–´…¤Vû›Ó„÷í÷ÀoN÷+8dîT ²ç@­S2 J•,µÑƦ‘‰&±"ìÉ¢V2KÔ7œDÊb³åð‘‰"¼“Š}¯ îðŠ¢ÆÐ*óŠÐdnËŠØjUdÿLñê9ž™"¦äq21$jHBddV—–«-‘…edËá+âBd•ôù·‰ÒËZ‰v—JË«Ir¬­—ÖR¤‰XÏ“"dÊéÛ›œ@e%A”¹^œµf_×å ¼úñ­ù3¤¼ÔÈe·Êa³j¨³6ðÌĺ¤ÙfMO)x£ ˆeÆ4X‰ª¦† ‡D5/¼¹Xí<Ùø’f‡ù†b nò 3iÜãåg2<…Ê‘1ÈU…mÄÛ«º¥cÓ¢B, âœ"ò ­?¸FožRML1k˜Õû«)õÚ2ŒI§U‚EâJÊ”`¡XÊøJ„e%C>=­tzòª¢%¥*²–Ò$[*•õl¨ÂUÓãG™£fFÎÞçÃMc.7cŸQû>câAÖ>OÕÝšT¬:«§¼ÓÈ:¢h(üóÈüòëÉüÏÅygœZx/Qæýpe]ÒÚÝíþO(#s)Ó‹9³“Üi\¦3$3 3Ü婌ìúa}ªöµ»xaUä#ôEJ°:àÚJ¤ÅS 3!D¹'¿¢5Ûöö™^`ǵ_,@œŽwº›ù³ØßrÅݑיFêsú{ÃåÉlßë,‡]†×Œ-ýŒF%äÐ÷HÅ­í0©:ÿ¯,.æŠAÑX®2ãp/jº'݉ëžÈtª  {³}ÏñÊíW”PDíçpü\¾¹é'êß#ÏüÃ×î~—:áq#˜:·5ZmÊ2ÀLoV2C1u R¯ž)=TÂrÖ 5dÍÈŒùòW…BäñÃî@j‡†í§RRE;¶70°ÖA=³[/—\pÀíø@˜O^3oú­’mÒ”0(º¹‚Qá u!Á'€ó’Ëÿ Î/¦Ï±ð‘¼O©à›é¦€i¦š¦šhši ¯e¿";T_s5aÚ¯e¿";T_s56ð½»DÛÂöí Õ÷û}ô_ØÕÚ£’~qëú0Ì·ia®o3THïl _ŒõÀæ2ÜÕQ™¥-jëØ6´ÁV™IFß¼£¯¼©,±0Ž¶Ûª£ ßœJMÇE^:SÇGxÍ_·ßEý]¬Z,1…£øwùDr)Æ?÷‹sJÙ©ÇD •: ÆËG…ífHE˜ä5Çsíö(×Fk¶¸ÅQðgé„ðÑ~Ó“qQF´–LpÇÙ|Ý\\õñ¨&Ç!òëZ= 8¡€L/så7°jï*üÒŽÒ ï.¹­®µ…ëü5Œ’ö·£íÍõ¬¤g/NS“^kw}Ž€8]~¬6gn7–§9KËáfíÜÅeêÑLå´oÖG¶¼[ð·× w çVÙjzÎŒfn_" Swî5ÖxÊ' ß.ü›ä»Ií ížï¶WdŠc­…l«níùwõòÖ‚dü­H ŸO¥Qùd½ÔÅÇ$¯æúº[T¦ß ÓXÚËkM`ß"À²KÁYö <ë$æP—gä4TÀ)l5…ò âãu´‹5g…±VÆ 8NʼnØ×»@Ë'¶Ø¢ez8¾àF>«¬?“ …¶peúBPG4š6K~ÞDÉo¨xÔ5e€"÷*Ö%×[öC¢:yk\M6Ñ\ßA×Á ‘DB9á°SNÜŽLcŸhûÊeÑÝöw€ãŠ«öx¨‡ªœìÿ6è`ßÙZ;Ï#óÏ#´ý¡#òqZÏ úâò¿×ÇõÐŒÕË¥¶ã+/+´‡kÅ_Fõ 2ⶆÜÎg\0W>M\LJ!G#ÃÞÖʱñÄUÞª«bvüo/j<8Ú‘SÑã¥H¡8-Ö2áå[¤vå5v·×¸Û‚ÒîÆkNÁJÌ™{ÄQÁqД¾ÈOq™´ay$Ìææ¢Ôëzà®ëbd»ØçÙ²æCÇ\ ô:ó`#¶@ºÕWÒ›Yüâý°½¢¼\tý žƒ¹µð=cEQ.»z¾8c_”l¾¶yY–fú­h¬5flE°ßĦ!#&xl -¥RÀ5 •Íâò™Œ¶QeGD7m>TºËIÔðìþË<ÌÌ‘_bŸmëöûDóÃÉ™¡Ô"¶+<€¸í³»¬'“»ÆÉçøRÀî›COà§ìu„›ÞÄ3=Px°å»Ì£­²iß‘žy„9/åå Æê>ŽòÄ;GÆôç³æ>"|WPù„O8êîªõGWäG뮼âƒ]ÉîJû³]qÝÿûâ}ªí—Ÿw'¹>}¡»}Ò¿´ýqÔþWÒ}9úûϼ“þ°ðúhkÜšÀ1èØ2í„§Ì?+—{ÉìQ;‘i_X~óN¬ ªío*!¾ÙŒ¡"&ý+˜°åC˜uea¶¹«s¸*·;´žYÍ^ZpnÎ9ÎHå1òG+’4…&¯/`ææ8Se2bI…­K¼ÀvHqãÓuŽÀ…”åfò[JR‹]‘Ó:dþÒ»gm yZ­Z:i¦€i¦š¦šhši i¦€þ‰%Äõ.,ˆ¾*>Ô¸Þ#gsgÄDÞý/S+cÖpðúØû¿£Åê·¶ÿKosôx¿G‹Óù½:®že¿";T_s5aNwqŒ@êmH LhWÀsvNsâöÔ@[¼P¼víi ÀµžÁ¥…*£Š‹r¸2¿† ¾Ÿ5©-•#tÑ+b]uóà›·€ûvr"˱àh pXKƒzº™¼!'<2äC¯‘:Ó~ ]íÿFæäx{öv;Ѷx¸67'Kãà⑹6°½»DÚÂöí´Õ÷û}ô_ØÕÚóÝ}w9nÝc(’{rÓÓ±äÿžxÂ9ÌaG¿ëh*÷¿àHÅî¨,}W£sÔÉðR|$͹ez™±dÇÚòþ¼Ùù?}ýZ2ð¿UY5EVMQ9ÓPn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿J¬äk‘UœrNtÔ¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/Ò«9äUg#\“5ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ ôªÎF¹YÈ×$çMAºógäý÷õhÈÂý:ógäý÷õhÈÂý*³‘®EVr5É9ÓPn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿J¬äk‘UœrNtÔ¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/Ò«9äUg#\“5ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ ôªÎF¹YÈ×$çMAºógäý÷õhÈÂý:ógäý÷õhÈÂý*³‘®EVr5É9ÓPn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿J¬äk‘UœrNtÔ¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/Ò«9äUg#\“W2߀‘?ª/¹Çší^¼Ùù?}ýZ2ð¿\AÌzNäüz±âª#§ÛžÖ§Þ ¬X2ëÕlŒ±!qnÈ-ª¥¾‡·Ç"&ÿ‡ã™[±Ã+g‡‚T_Nô]ííÉ´ÿ‹Û´M§ü^Ý¢Öš¾ÿo¾‹û»^{¯Bjûý¾ú/ìjíVþæO¶/µÏúqÛ¯eŒÞ}á·¾þ®ë¾Çô§úï\c¦:Ÿ©ýè~Ðù/÷Ñmâá裷´×–[<ÒT-”5ã‰YJò5£L˜¶`‰W6 FâlÉ”B2º™o²_}G8‘^ü‹jªyp6vFHww$pðRÙqFøfÙ5Ë6HŠiiû}äª6kŠ2Mº®úX¨¿Hƒ^ßÀ'$êBx‡(<š®oœ_B—O]âl#oGàÛô׿Æl$°u$~ÑhŸ«)ËéÕ“å2˜ù²$­$|’+D¸È¸—k¾".9v—W—V’ÆÆ¸¸††Ê§ÕÏ*£ôúhçÈŸ߇í“ÿ»wÝíÇÿrlžÑõî½½¸ëî—ÿúÏWô_þµÒÿý“ ;{Mq8çšaù€á¼ÁåÏè•ô ••ÿ TIÛÙÖÞw¼sþì>˜œÓµ¤áæÃ>q@ÁÖý7çB5sëî*ª\I;s}ÓM4M4Ð 4×½³'²™›Ø‹ÛŽ¥öÛö¡ÿPz¿É»eìÚª¨fûÓé{^³ë?5òO|¢;ê<Ëõï­ð`vöši k–}¹ð—Èz«Ûzc¢;›Ô~Ðj_!í·r{5Ü8êï/èŽïÿ¥]Yâ<‡¹?°Þ?©ÿU뢆I†ÍFÇŒƒHhËD hêI… Æm _ “ ß@kFB=yU"]]ÕÕ\¸¶U6Õ²¤À±&<Èr7£ïmîq÷5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µšî[ín F$æl(ùKæÍ£C›Ng»—r†pO4ÚÃfjsYàÕ¢GCÆJ4Ð…•«ÊÝ‹Î-é#ǵÚÙôÕØÖÌ™¥¯¿Ûï¢þƮמêŠ2%‘x‰”Ð9‰b”$#L«7s™ŠÇ+ðïßÓçH¼ÍÆÃc˜ö=­ñ"ìŠÌG+Jâ®1!®ù#³¼ÎoÛçEZ Þ¼§4×Üa¶à8ª?$µÞ¬YßGgSÉgì—M–\ÐM²nš<ÚXeøœïÊñÞaœº—•¿î(‘7Ì;T§hT6–‡)ÁÆXÑž(œzW!Ùd.µ¸¡î!˜öÐÙ>dÐ&¦Ø·l™>àf»|qÝÿqï¶]ªé;îä÷'Ø·¥{}ÐÞ©úã©ÿg:OÊüûÏ¿Sø0ÿ‡ÕÂi 2“‹˜I‘cë aÁi¸ÓGW‰YeG˃6rRð¯é!©I1…–Ûˬjr ]·Føæ´ß,lÄþ8ûD‰ÉÈ d\Ý“ÏQ’ZÔqê2½3Œ¿“ÔÊ!Mæòª&5œs& Ý qê &±ëÚi€]X¸.µÇÆZ©©y¾oGÚÜÂþB@ÓËWûÜ{ƒ18ØeJÈWÛxÓ@e”ß ÑŠLåyÀŽ\ÓA‹‡ Ûü[mîcŽ=e£ó ÊŸÄD[fÙ—Š½qFFµycF؇vŸ¸sª¤ª„Æ8K’©ñ(ʾr,é…ù5„Y…ÔkÙ ê>af/0ðs¤ O¤É-AªIñäýˆ I¼´C´Ø¤”‚ žy0çÒäËÎbúN!1Í[i )’Ú0“†ù‘Ú§oB|Ús™0)`¾ž¶°IM€¬ª]¬(äÔRÕËVK«¥Ü­ ¶‹¸%¿§ŽŽ(ð8¶ö®ƒM4M4Ð 4Ó@WW2L¡l ¡8¡°[^oÔícN ãÙœ˜Ûô–©Ÿ_0Ôl…Œü¿›È\Ä"w5¸’ŸÔžy$g3dmÄŽª³'Èrê°°{j†Æ<ì„lÔ6(}¸Ã½ÁœC³Ì÷nR¤žz¶]Âi 1Ë›"Ÿör{‹‡g}³8æÂÍÉŽ´ÇËê~ß²gúÏg† ÓÏct¡ÄÞß«{0Xà/¤ôHCÏãé±ßÔØ1€¯6W'®_IblUH :–§ {ùÌÃôä*ùˆ_Ÿ7g³c$ÔCˇ×ÁH˜ürQ²{|ÂMBëzظ°2æÊMMi ªÎÔ|:Út2rJ ›/‡ŸØ žàÁd¦÷€¥êKÂÃUM´‘5ëO²rD½'ƒ`ÝÆw€ÁÒ5ÙGKÀGéµ­à$­a ïG¶®g­$“XZó®z ßŒu¶5î^ã—µë¨0àþ²ç"ðÍñ'—VHâÕS*†äJÅ·ŒØìÓˆ„~©yc½Jn©<ÊHŒcÊü²€â Ë Ü €;x?8pìè1~=“i˜ÊÐÙÇI¬qW%¯šÕL-°£'¼8£'¼©(OÖbFs¶C‰¨ªIÿN§‡¢‰‰†Â†ÈLŒˆhÄ„¨í‰ŠÊÉ­ PŒÐÀ‘kxBCyk"%]--\IVVÖÖR£@®DÉ’6cìînpÓÚ§sÅËËkq1ŸjÈì¾::n »šÄ@®sä¸n·Dz» £"i\I@ì´Ä—45€'Ìöj7)`\°¸8˜ôv„”Ø3wW(D“C±»è:øGcXÐãʹ›ËBeÕU³ÙÇH×e/àô€)ê˜=¸àL‡“»Qè¢Îù‘`êó°Üw9{({£³ŽöË-’'- šÕ9àã ¯ˆT4‡dgW–5ÁB`pl7 Ù › ÅclQ߆ƒæ‡Ù>ÂW"òŒè¼êŽÒìo€IŒ:6s¼: ¾e˜…–P‚´× ’Vzpx’ɰ¯eaè`† H'ئçWV0åyÇ0ORm†•/{ ^Ò eÀü4Ð`ç{µAÉÿ&RºZŒ=ÿ7—8ÝO°}U­|âkn“£´‡Y]]8 Ë3RŸöûš›é¯bOu[Ú{ýCU\öËÚK¬»-ï|æ×¬úÏÍ`|u_NúÿÚÏ"õ[Þ¬ #¨ži,œd†q+¢—’FlŠÔL&HÝy$(¶³§^ÛÝUļ‰WuOe&§~VÜýˆÕ³7cðÇŸsw‘9–ü‰üíQ}Î<Ôq)ËÊxÎ__gƒåÅFÅÈë 2 ª­´*Ho”ü Ä!ÊQMÊöUU3)å‘—•ÜjÍ»:<È–ªô+zÞêÝ`p)y]#æ[ð'óµE÷8óSo Û´M¼/nÑj _·ßEý]¯=ס5}þß}ö5v³\‚æÓ=N7•eyƒ=¦Ö«áç°òå±ñTJQ²b@/D k%UàÐC¥çTcQëI¶äÍ£h;IçØÖÕTКÚH‡bŠ4¦©ìV72EWé¼§\yÆSÇÁ’ãÕàÙ[™¶wÍZ* m*( jšuÅÏkvîd$ ·At,ÅU‹)†Õöi¾Ý9L_Ý$gÿȰu¢;0p•ᑦ+JzìtO6§ðPŒ‘Ÿ³ šYÇ©V2Kø¸iÎcÖÎÙYÝØˆJÈøá¶r¦üä iÓUÕ‘ÜÍÐxÜÉ2Z؇»ÛòÒÁÍ,¬&A¯c2…pé\Y}GR:q‘6ªï*üÒŽÒ嶸¡e7£&MÛó—QW•Hl ïîmÈ4{z©"2¡Ê|ª8*ÅüÀàÃDülŒªb¨Mš< y¢vÅŸþ ëp¨‡f]$3fÕK Ìà@(„ MÓU-Ë#>ÞÙªI˜ÔmÌp¼WÕãöad"PÊ¿ua°7QH©žNÏ‹Uí"ûŒ‹ªÊÔÔ¥v)#, Wðm‰îÚz6ëlE?²·BÛ ï#伄–H°ƒÔô$Ϩ+¹Ôs"ZRÞRÚD6&âŒB°]Z‰WÑ™¯¬­×-T%ë<  ÓM4M4Ð 4Ó@4ÓMÓM4UãÌ·à$Oçj‹îqæ¬;UãÌ·à$Oçj‹îqæ¦Þ·h›x^Ý¢Ô¾ÿo¾‹û»Y’÷"òGþ¶Hóû®žù?å»þ‰ø5øoÿé¿x¼­iµ«ïöû迱«µçº¢Œê{‘y#ÿ[$?ùŠý×O|‡ŸòÝÿDüü7ÿôß¼?ÞV¸‡q$sÖ‡›î"ñݤpi±Îó#g¼Ø<G›Ù_QÛ6Hƒ4ÌMN'éš “Ü D ÃÀ—ƒ¶0ö\V«&ÆýÀ\í„é )(9pä‰ Ÿ; ±tù!šŠAr‹Ë-ÇæÉ䂤Oo} ¦~;Ô/+¶*þq&,ˆ›ŠfUúóËÜõÁÜ. òï–±}MË “³ù:ù )£³Ç—)e÷.JÒk¹ó]¶‹gMA•I : ŠPItrÁ)bì[]ÖÜTÏß-Ü‘µ "?Ü­«iÓ@Vváë·¿·xb¬(FäŽa=36eLÞÆñ&Bl¬åJ&­™Å @= 0®Ž<ú«VŒ÷†Éˆñ^ç Œ È5‹Ë ~X}•<ÂòÅ~ÆV²ÚÍ>_¹ ƒ×3È\‘&Æ&ˇ‚™ Hº#Xù6=H@)aìï)ÚwóEdTSɽ4|)9-œÐ³Ì#ÅtÑØ-<—Ü|ºŽZÄÒXFNÒܠȱ›¥É“d!å×7qíhÏ ØFL«jymÛ’ÛÙU¼Fö!]Æõ>Z’8Š˜ÕAÊÉ8à Ś´XËÏ’†Mæã&¬Lv{èÎÚ&<^Ná£XNb)«ìoo ¤ì~ Ž&Øð\K¼Ó@fu3Éï)¨ý½Ë/ë°‡o2ï—Så ð®ÙßIŠÏ®¼« Èâ…ñpu,D§nדDVÞà‘¦¬’ „-æ”Iâ·†—âÅ„%Ë¡ÛBËä\e0¥Y¹WË#Š'ÎÄk²Þ9备ؔ»CSÎQmn„lǾ£Œ^%eee$ÊP ý‘½ø3"ÖÌ´Üß§thši i¦€i¦š¦šhši ¯e¿";T_s5aÚ¯e¿";T_s56ð½»DÛÂöí Õ÷û}ô_ØÕÚÉ3V,ÆO2jÆ4Ö:ÿšnc,–žÏ…œâJÖÁ)KáŽ_V{Ož é» ä^NW‚*§¡›KëàF’+úzÜjûý¾ú/ìjíR¢ 2×É2®R-1ÓlC)3 å˜VTmÜ-eŸ’’;gÓnL‚V Z»z1ú±Úxq§ï†ÀŸa?Ñee»Ã<صU´Qhsl$Y=ñFòË;F2,qSŠ8oÀÉŸ°I™‰#©þ‰aRÍŽ§± Vq ¸ŒöS÷IDSÔöÃð‚’*ˆ¾ˆ?§Dú,Ùbb]à–%aÞ}0ðƒ"²&¹Ì6UI3ÈÐÀó:–ˆH\_ÒÐ$äûjî2‹0€«›[ª¤>Íz‘¬»ß4?Ÿb˜ä¿4IéöÆG¯“ßy‘t ¬ uç¹dfpÚ¢zdóf…% ˆ`Ò“ƒ Z{HÚö+ÒÈw„…f½Œ6&3jk\¶,C_› { ‚PS†W™·h×ÀUÖ}*Hª^àØ÷ùzÄpD_ÁØ&„ð¡%G²!'dÂ=¾ÎéÌ’KQà‰ÊŠz½òcÑ)¾Kò»žàld{1’˜éAêÀ´¦{‰ÆXµç¹€ö`Ò_(‰Í.ö81ù§º°b¢ìˆ¸G™‹Ù#fÐM£)a5Ä OõE—.ðÄæm/²©p]Ó‹Å_.¡>]àh/ µ·ò ÀvÔ0¹wtïM­/-<®Ž®_\ŽØÚÍõGbm.^îôÀ9Ó”–RæžKg¤\—€¬³IgÖQ¢/X¦ÃÞw#y:Hb)%G|_G€°9€QŠaëÒ_’LÙŸÅTWŒæ4{‹tm ^aQZZÖÀLÊ[Öy/;#1ɪ¶ÈgÜ•’BG2=ŒÁ”l¾RÄܨ¥-ƒ©Ndš°­ŽÌ² C&·j0†óL¶Eõå™6Æâ[Šó êÙk._ŒÁýïoÂÜ,ÊœgSÔ¥™ÙÿxÚ]ã¥;$!®ñ6—ž»ÙÞº‹BÚ¼²)Ý|È?i„ˆq…¯Àvl=5 }±°®6‚­²vEpeÄ‹sWhæ¿/,ñf*B–<ºœ1ì}Î…B™§Ìí—NNà·Âé¿NÿMxKUèŽ(EU³U麨&3]7Àî|Œ æFç'•V.ä^;B‰š¸B:\™ÊkǨ«4Í ÉJ ÄÍ[ÜËý½™‚_Gc(|Ûľ&ª`,8KhXwNÄÛäàº$Ë6æFæŸ#²‹Y8dä Å d.̱¶\ò ³î0`Öµ[u¦-WèY®Ãì(,”")Õ”‚Wшî$E.¥è±¾Z=uëÍþØy?Guw“øF˜yy¤/ çR€´Ý4Ó@4ÓMÓM4M4Ð 4Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µçºô&¯¿Ûï¢þÆ®Ö;0X•8dóV¶cò›öî¼Î9k¢·{qËü¿§*¶¯ƒdì.<Ë+ª¶Ç”K—8›ÀÓL Úêÿ]s"òIê(ÖŽš Ç72ÜÄY¿ü½«– üÃú;Î^ÑäVïc)¶’I !°sd7 b´Þá*žzÓ¸Çè«ÆÈ®+Î$jÁ°#>âÛƒÊìy½å¨÷7rÁ€³ÇKlJÀ~f-=ip2àdYúJ°ä)\>bé»#š´¬i­ €D÷¦ñ ?é/ËÆáqc4õµ1#t #éªCÊcÙ"<çÎÁ]HKå\\½2Ëmù¼y©íÜ1_C¿iaŽöëËú…‡“ãÈs"^ãe•@Ãó=ˆ@O zÒxìUßó/ùºr)<·¯<ƒî ñûYå^kÌ€ÔÖšÌ0ÝÕèVZç"P5"¬Ž%ù093º(t3²sBH2½¡e› ѤGƒêŽ¢#iU”¼"ÜTìÖ¨#×O®ÖÈ†ÎØÇ k™VK¡RX‰8μ£¾/£äN‹Ìj­ÉÁ’™~Hßal‰-hJLm+´IÑÝZ[zH_ÇÖ ÕóÉFi¬)Ç$FØß,VÚk3»/NdMþj¢ðGá{Æ?$0<¢Ä\” |¨V¬’gm²í´42çUËØwÔ0åÙ Ýä|•M𚻇Ҿ“ä”Ò.íú™gÌŸ$^œªh–¨Ž—}eÙÃCÚî™´¯<¤ A-°¶×yqœßšº€îÜÍVq-Õ¿B}ÎÙ%¡ßµ!¤oô©e´8>.óMf㹽婲'—VäÒÏ8Q¹é‘w]é¡Dð2à¶ݤÌö‚Y¹èŒÀ#¶âVYÈ[´þubZ)³Z8îg›ñšÙãºçîóhËÆfW—.1㸠ÿ4Ûþ_g€A8Å”ewÁ)Hq 2ü»7h§ÏÆ‘¾›dO‚U÷*¨ETëi±#ØšF¯“²ÓãEzi¦€i¦š¦šhši ¯e¿";T_s5gm»5 ¥yJpn]c~¨kÖM´Ûµ´®·³¸àôú=0áVÓº$“s¿èôJ°ôǧ­›=]dÉ{ÐâÂ:Â%]s™³c€öø%mìNh LØÛm\Þ ™!';û|+,ãı®•ÃÁÇÃÃ" „HÓboz8ã˳¿·¹·Ã6ð½»&Þ·e­5}þß}ö5vª1sËc$Hý¼CfÞa&jòC"ÚyHÄ «Â±½¶Ã‚|…²Ç¥70Ý’_YG枪¦—|®~Ì(q÷7w%ZI²²Ÿnm_·ßEý]¯=ÕU‘×(¼na†då ³¿‰‡“ùN)—VY%Ó“I–JâÔzbŠ“Ü3–³oa J:[`4ål’ åºüõ†.2K!Lž-®!ÄNP×ìœï(Ìûw|e{škÇ&D°ÿ¤¶¾Å ƒ[B¾ã*E4[ Ѻ²Byþ<œ’]é:¾øðR„êb©?²ëVׯÆaztW¦€®¬ŽåƒÉI“*ÄÁÞ –éVå`Ê …j+˜ªá;ê;aÐ|ˆ°;iyiåtuw+³õÅòÕ½%0tn œÅ”¼·Š=[êc8>’ ËQìÁ Ù¼/ÃÚœXŒí‰P¤†RT,¸í =‘ມ(–”·”¶‘"ÔíÖ“F®¦–Ì»ÂÓ@qî>a*Ÿ[ÓW‘´âÇÈÆ™³¸¥]ls½9N6Økl„ú\C#{!ZYÞ2íbw27Y •¦öÁ "#eL |Â+ûŠ|E['2k-r°fìâs2» ÜúkÛ*A”^Ï û%ÀWA×WUÞUù¥¤‰EBDQãmx6wê|’'ΦÓ@p+Ï—BK ]®'É‘KN°½Û€¬]u£7bP†ëÒL’Ûs+‘èv¡V‘q-.¥lTÝÙ\[ l@Ûµ0"|ŽÉ[¾ [Éí%k? Öù ˜XìËÆü=‡‚””+dHPå…Ž•c|´Ãl®‘h„›ÊÖæ@â`—tŒ+HGU’¢’+'ÛNšˆn01a’)¬¦¬*wŒ3” ¼q—"¾UaÝôÀÁàãT$5ÊT]¾NÎ'é†pÄ#;BVÁS̲ñ¾±'¿°ãÞ[¸tZ—ÜÇóѳŒ´x¶_– 0Ñ¥J’wH´äeNQ¼`Ò²c%‹Œëo2±—aÄÂn­ LôïW0€£]4dJ¤/Ạ4u9>ò€¾Fc.&OÍ«w}ãMpÞlb+¤¶bã* Î@À¹­p UÚD´8«^UÀ,à#fŸ «X “`-¦Yqw¾€y\)ÕYÄ}­ù„6ÚȾ¯dc8ƒÛx Û”—•öåW5ƒQšûÔe·÷Ûæçë}¶æÚÁ‹wP§ îW ÜÄÅ•[ s˺„ jPs:/7ªƒ{Sç"äÅÕw•~iGi[s]ã ìxÚ«61½lIq÷·*’hФš#Û{^¼ø¨çë ”?Úv½yñQÏÖ(µ9ÓJ,¤KE”‰pA»^¼ø¨çë ”?Úv½yñQÏÖ(µ9ÓJ,¤KE”‰pA»^¼ø¨çë ”?Úv½yñQÏÖ(µâKŒçÂW2áE˜˜²Ôa‘ùO®2 Jpg{åS¯m¼˜\dºÒòÓÊèêì®l| ÿU]:ÆOª‰FößSiE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv¿TLÕ±I™âàe‚FÃUô¿sÀè‹(mÌ×qU½zׂõóä^u}y"ýC»¨*¶7¬j|\M®=î¾”YH—‹)àƒv½yñQÏÖ(´ízó⣟¬6Pþ7kõzÍ[ ® ˜!Œ6§TvÀô²† ÍÐõ[7¦½/a>=áHQÈrQÓÐlz~«fÆÛÂDÝàÞâ›éE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»Nׯ>*9úÃeãv§:iE”‰p(²‘.7kןýa²‡ñ»\AÌzº²£êê"J‰ZŸƒo†yqdýî-ñ–$ÍÍé—ÇäSw?NOÖ×¢]¾öÔX›QâDÚØ±··è±W2߀‘?ª/¹Çš›Kø½»DÚ_ÅíÚ-A«ïöû迱«µwî-ÏÅѾj¯üz‰‡¼Í0]êÓy5ùŒbqõÐØE«A H7`®ò…g¶CÏ%æ$nn%Ó`z„…¤ £ˆ‹‰¼ù?¼aëá«ïöû迱«µQ‡üym4[îs¬a£»/a4ÃÌ:~æÝR„ØÙ¸Ø:>CRŸ×#Mo8x Œ8¯7I×V»%»ÇŒI%›7rF»·ÔQVYG›— ´’`O—ÛC"Ôâ¼—îsqKŽj”ž/‘-ãAõ©†T½s!†Á«½VÕÁŽ d“Æáƒ|‚³ŸZ~atÃ%¾¾¯›7£æ¬öÇmž‰Ëâ•eº7+ùK.ó߃l Vº  R©Àf>ðµa*Û¬ì‹Ç…û`ŽFqjEp/(£Œ|²Ê´äß-Ü̦J¹»“xæÜa§=FÈI þñ/Óª‹}š ¹µMÝEP"%æÄ™ÑÚ5¦A‘|ôº6ÅÜCRè÷sÑ8­Ä§Æ”„ÅååºÓškÇF9Q¶\„“ÖÌ%.õæâÎÆ9]óȼ–Œ9•8ÈA•ñ5HßH´Q¾±ú ªÀ(,Ï!ùÊQ3Ó˜3ÀÈiže¬nRÆ„adŠ^òþ$–¬'µØh@sÊcþU‚7w1ûƒbU{?8ilûÖ,8ü7Ð-v¢†ß¡0ô÷VŠfôŠ4U£km‡²òPÉ0ØøÚnyâZEkú@ñ‘ ±à…%öE©fåI5åá˜Ýl ˆö¶vÄU{;ó&|<¡ådžY”f,ÇÈTßU°ÃB VT‡‚ì6ªŒÏlŪ´¢3_^”'@o /(È ©·„Êç]PŪ5<®,C³ ›¾§í’Û¶ÝšíðGh:#¶]ªé:ÛvÛÈzW·Ý à:c¢:cös¤ü¯È|‡õ?€òÿø}–Qõ?±_¹:‘Ëtþ,ç®ÁÊt O-üíÆN>Ã9ÔvwŠc.‹š+}à†ÀC`ßzšÛ~ýrÊ·>RIx¿â5ܤ!t¶þ¦òæe—ÃkÞ`œÃDÏh葼¸óëc ø°sŒ:Ôo!A—Ç!ŠvË× 'ÓñµÂZg÷E„ ]¨+Õ -x‘‚åíÆdDKÁm8ãÊo—þ&²C[¨ÄO°Öá+…™ cMÔÚíˆaeõá1-2Ê¥¾Ç;£]yÕáYœéö!u´v»ýxÁéáŒcÝú™~â æEÓåqbNŽÝåKxYÂIÇxcnìåKHb4¦dš« ÅT0Zjšâz…ƒHè ‰„½.¾8y-/øï¢¨ ÜeþG9ñ%ÏùO†]¿o¯ýÅž‘.éáR¿)ê±Q›ÿÔÔdƒüxÁ%Õgë:Y¾ÆøØ^Â4I{…ÍUðöºÈ,ýÚÖÅà’gò|2#)7Ç…–gËlP¸ ÃíeÈ'+&$á£5ZWLYRų³núÚð7pI³FuKp¦xˆ,Iùedv“£.‘œ”kAì¢Û!¼1´€Ë€šÝUÈU,r¬ð¯snPÉ2Òq%a$*“-‹oA}5Mä(:‹•æ#I'/1êfþã$âQ,ÃÖ3KdÓ$Ï­•èVÖ´LLªØ4pj臩澻¢SŠˆ&ém`*†ÃjÀ¥üc¶QÖÔåëzjÀH=r‰ã %㺿.<2Qßc™Poɉñ?¸Š#–Ãj‘_ ÷Il2š-óû‚c›‹gè(AÕB=ÒiÛ…°0H2ë¥FÆêë>à†âEÜepšNŽ¡åux~YÄIÁxc,nåµH4Ùd…+§‘ÊT/šmjІ{H u„ÂÂ9-×¢Ô ê:sß™(Ž+s=Ía<¶£ƒWËï›K9‹·Ç5%ÀÛ9DäQ¯¶ÔìÃmˆu%ü4u‘Ù#Â… »Á¬úø°LXŒ¡ ]ºâ\xdV˜Èì|¿Møõ[;ï2; Ä{†Õ‹Ü9!PiµÑ—ŸÂ9ŒN)ãI×â6}<t6+Ê|J=Šùöq&öö€i¦š¦šhši i¦€j¼y–ü‰üíQ}Î<Õ‡j¼y–ü‰üíQ}Î<ÔÛÂöío Û´ZƒWßí÷ÑcWk“’Y˜ÈÎîvhˬ{ï>ǯìñP÷J¹ÖS×!¿µTt~yä~yWûB9ç¶~+õ=凨‘êzÅ«ïöû迱«µ†óvÀÛ>Fèi¢­_–Jjœ+2Ql’I<Áò’t[ZëáÚ=é«md†1 ×·Óê+vËCȪöw+w¨£kškàÎL‘_²EXõc”÷ ùLqùVœ½KhXeÇ|Õ½¿ *6´¾îñÁ?uw)¤8ó™QJꪹj\ Ñ17¤®²­ø ®æu‘`”ï6ËÜVçx|¡Äì?¹rÉ9 a3Âë:Œwž»xݰØÞkq®kfqÚ¯mqÞÄ·¥)ißÇ mMf<2±7"ù±w*ZxÁË«R¯Ž_c- ”xÛ´´Â“„è•°Ä)á™O—4s280 øEˆ $ @a^*!Fyín%zrƒ:9‰¢-œ–Ì,*ŽÓäNŽÉ—R»Øw¹â¹a“”¾“Zȃlj6%¢Òò²Òo•Õ¤õ ±±Ýµ©ܱ 1¢@4ŽÍ[3:»· †oÎ/ÖGYBWÑ,‘O Õ âï"Ÿ?¦Îü|?¹ðWÔþ6'˜ÀâvOÜÏpÛHÖCróy®¬Vn»šÁ«4³åé=P§³³2qÓVR=bÄ«ZQÖUͨ½·Ý8C½N6D(Mg³€´fÊÖ³¹‚+Ù<ÎãÄ88âaÇæ›ÌD(»"[ÅýF®\_c×ùĵ³&òŒøà~ð°&¤Û"oÆHÛ½_@<\É‘¦%}‹&ªÐb¹Å˜Œ4æ^…Yê°ÇË\×Qd¤ˆÛøvç ¯ Œ‘àmV³£ tÇSõ:MOvþÇ£Û«TÀÁ¤Z¬>°î›8¨ ØH»”ù §y#N¨Ù*†MÑiöî÷ H[ÛÐåG‘fÌKJ[Ê[H“¨‰†o`Ö V[ “TÔßÔÙVÅønÜŽLcŸhûÊeÑÝöw€ãŠ«öx¨‡ªœìÿ6è`ßÙZ;Ï#óÏ#´ý¡#òqZÏ úâò¿×ÇõÙÔ_äÛ%ÀƒäJ²ãW{›x»'® ˆ{Ø¿U©s僎ªu+6ž0”´F0àX0i§ÀsµÃ}kÞÔòÒÃnt%w6éËÒ êñÌü§ä~9cF“nìÞ’d¶/§îØ*÷! 2§fƒ¶ò|Â0Ûg Ul s‰ár%]y¡Üc ûp6K¯0ÉD-SúØ…´ÿ…€Ž6>EÑÑ]Æ.3M†te«Éà—¦ðÞÏ(퉅ë¤y©mTé0m¿ö8x²]yÎÉå—χô3ào!–|áYK$gèdõ;~¶žÿKôbùOù‹£ŠM_¿º`L?ÀPÉ pyT:³Oêf•BJŒÐü¦ÆE;a¦¹k„㢰… >O»E'Ú¶ 9kä«fâ=hîÓF [:ð¬h¤áD3}PW³carlÒ+šŽ*p5l²c†8ÖËæêâç¨×@68—ZÔyèaÅ a{Ÿ)½ƒWyWæ”vgyuÍmu¬/_á¬`Ä—µ½no¬²‹9/«îZØß“9bïÆLi.ä†5˜³²%í}L—ŽWÖ­‡ÇXû…Ù1siè°:ö|P_Úå-úþ¾ãj ÷¢#S"«˜«zªê8…^Jf&`ß~Noå´ïHÞeÈG2 ì©M]“ ;æ¯[A¯(#­ôìD‰ÝEåEa­9àUxͨ§s­øÁz›¼¾&Z:j—ù%›¶.”ù¶¦iºo¨ø¥ÌÇ-1m\Àwl›¶%©Ö[À³Fâúk«­ o8m ˆ'îÝ\ðîïDٰ٤ۨ£¥º ÓM4M4Ð 4Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ-A«ïöû迱«µÉÞ̸Ýÿ—ćô×Á@üÈÿæÿ€|7þõýþëú믿Ûï¢þƮհ9̨Dý±oqS7Ÿ Ì8±\dc¹>®Wn­‡ÌÆ}^Ó˜ceî[°Ï;K/Åð¶,D@mª€hað1/çFV\Œ^QEŠû2ãwþ_ þÓ_ó#ÿ˜?þðßû×÷ùÿ¯ëpï–K$ù¼¤V7ÞO,ÂÈ<£ sÛ#„¨› q·ÖÌHÒ“,Y–%¥òhècïìH¹ª¸€A²hCµ¸WÁaeÃcêk.`(7H¯±¥qÂpGxÔÂ>` lNœP¶½Aœ@áý+Ûz¶YŤ»H79r¼® ‡óØÛļÚÞ£Ûííå‡ÈÄ“X‘vdÑN«%êÎ"e1YòøHÄ‘^IÅ>Ž×ˆ…wxEQchyÅh27eÅl5*²¦xõÏLSr?Üí’Û¹=åíðGwú#¶]Õé:äöÛϺ«·Ýsà:Ÿ¢:Ÿö¤üÓÈ|ûõÇ€óøMôЊ%’ØXÌñŽ2¾aµ:_¹ç”Bt5l~‡ªÞ¢ ëŠøï úBŽDŠa~¡cÓõ[ûÕÕ>&ïÏ•·pÿ²’ “ç1ÑÚ_YGf´­º’Z2I+ÆáO²µ†=ðÈfêÒ%KK«‹(Õ;¶àlO¶²™µ†Dù[›¾ ÝϺE¶ZÁÂÜpȼyKÇHÙI¿E»Ž”£uŠ}ö]’›v\â'ÎC¤£î^B/fM-n͆÷ ªÙÐ÷%ðm\pÔú¦"æ*c5Ö×ltÖáĉ8²Sµ@Ù«ò¥›%>硽9O°EÊ«¡xc…ÿUÕÓqŽN$Ù¾àŸ]NOqà$opíìu’ÙÆr¸n¯‚‹Â?.ê68 Àeï”ZÁ½©ó‘rh”vžWyW[s]ã ïø+Zè61½T¸‘÷¶þ‚1%l6° µN«,ÄWDÉKð”ѵ"ÚRè…aG&£r¬ð¯sr´*ØR-Lñhœpèä@ÅÅ·éõ=4:áþ%1 ̘¹Ž‡EíŠ:q–™YŠIhNHËž!j><yv3:ÐÊŽŠÑ|eORE*Êdð £ìH¦Ü…8&F$ILŒ“ªÂÒòÕe²0¬¬™|%|HL’¾Ÿ"Öñ:CykQ.ÒéYui.U•²úÊT‘+òdL™Q½#{ss‹ÔôÐ mŒ¸ÜÌ[¦˜øø`(þAÐj£e@ZØ'¥(eŠ‹ôˆ5íñ¾›Ÿ8rƒÉªáy= ÙtõÞ¾Nô~9ÅêÉlRfÇ&_°Õ}QÛËÑ:s5Ç\UlÑôE„ ‚_G=1GON®ê ­šëokƒg†o¦€„¬–Ë>®íÂø!Ü‹öiçD‰ÐŠu³$¯ÂuC»È @êC‚OÏË.|mõÇ‚‰æ3äømŸÐ›é¦€i¦š¦šhši ¯e¿";T_s5aÚ¯e¿";T_s56ð½»DÛÂöí Õ÷û}ô_ØÕÚŦb½‹ÃY^}:ø«’Æ_Ì]cˆ·mÇŽ<¿xqG_yYk‹¾Ðl@mªÅ¶ß 뮦[ð*è÷½¿”Þ"²E³ŠmÛ°é|† >¡¹\Y_nFcä4bv;§É¬I†£î—¤1vEl[:ž<~z'lFî óÑw´tÐðn¼ÒXýùDLŸ.%bHBÏ’üašÒ¶ëIl7`I78l­aA¼2·¥«—y.®–âÊ5NÄ­Éûð*l¦mGâVæÕge^Ëyׇ”AÌ%.ïPf°xÊ"Dà6ŠÕ¢ÍAã˜ÂÈyâõ®•E[a3[jÂ;ŠbßM†ôb% ? @l6¾²ê§shh 5äàª'g”—9¦ž5äê±Ú¨oÞrå!ÜWbþ#³ñ/Pç0Pþ›Xꑲ¶,kMˆ f´¹È‘‘b ¶èÆ–’‘ÑR?>Œj’Ì1.½V~PIuå~^rœ2Åb¾s›Dƒ?"gã…«íâylI>Ò6E¹­ëû&~GM•5ìo>¢ÂaÂAAfåæòôÐ.æ_ä>Õüǽ³ºã¯½–Rþà–÷'Ï»çàèzßÙ²ß÷þÔþܾνKúø…í·’yþ¼óZbÆ^óû7cç´wüÃvAQߟz¿ ýAÝxŸ±þ<óÞoì¯ý=ú£ÁëÛôÐ 4Ó@4ÓMÓM4M4Ð 4Ó@5^<Ë~Dþv¨¾çjõ^<Ë~Dþv¨¾çjmá{v‰·…íÚ,•Î[·XÊ$ƒÄÜ´ôìy?çž0ŽsQïúÚ ½ïø1@;ª UèÜõ2|”Ÿ 3nD^¦lY1ö¼¿¯6~OßVŒ‡ü/×½µ}þß}ö5v¼÷U%úÏYýÁºógäý÷õhÈÂý:ógäý÷õhÈÂýNtÒø¿uŠõñ~ëðn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿S4¾/Ýb½|_ºÅ|¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/ÔçM/‹÷X¯_î±_ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ õ9ÓKâýÖ+×Åû¬WÁºógäý÷õhÈÂý:ógäý÷õhÈÂýNtÒø¿uŠõñ~ëðn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿S4¾/Ýb½|_ºÅ|¯6~OßVŒ‡ü/Ó¯6~OßVŒ‡ü/ÔçM/‹÷X¯_î±_ëÍŸ“÷ßÕ£!ÿ ôëÍŸ“÷ßÕ£!ÿ õ9ÓKâýÖ+×Åû¬WÁºógäý÷õhÈÂý:ógäý÷õhÈÂýNtÒø¿uŠõñ~ëðn¼Ùù?}ýZ2ð¿N¼Ùù?}ýZ2ð¿S4¾/Ýb½|_ºÅ|¯6~OßVŒ‡ü/×s“¹?ìxªˆéö絩÷£Ã+$ ºõ[#,H\[²‹j©o¡íñȉ¿áøæVìpÊÙáà•Ó½{g{rÆ5^<Ë~Dþv¨¾çjma{v¿é6°½»_ôµ¯¿Ûï¢þÆ®Öyx¹¸d[8“˜L\CÀz<‰ åèÓ°QXeÅ &E¶‰çÜRNXcÀÂE»i飩´.˜$¨Ê‚{Ž’—޵UZPׄX§ÐÓWßí÷ÑcWk üÀ« ?ØY)è…Ê¿>‘\Ìm2æÆP’Vlµ`m)r——^•j¢Y>€TE\õr™’ Ôì¹Ã`ÄP¯v[ÒQ¡ œÐÆê€Ár¦ëP#ï/RyBªÉC€4ãyV¶aZÑ ÔÙ¶‰Šv¥ƒùs ޵Uw6têÏH4k©·œqãïÍͲk–ka+ Ò õÈ: ªl×[u] ²¡~‘9½¿€0IÔƒ'Ðy5¤ß8¡….â»Ä×ÆÞ‘ÁKážØ5æô—+Ì…ò8ï"q´ã}ßl Ù%ÇÒl ¸yX‹:éo®( Þ0A ™»r"Ñ‹ÜX§Îˆj¥‡Öˆ_ZSñVrw3qK—O%ÙÞÇùO µGç ÊxªosǞื• <š5íxC»Í<ÅÆ]ÛˆÞn0MÖÔ=WAD|´ork…ª€ïI² 9FÔ(f¬.oZàuLu°8fËÕ‚ca!x@‚òDs‚ÁíëðÍý’‹iñ(÷x'q}šHIOòVâV £eÑŒ“Es°D©TòFÍwªcÇbÙ[ÆÞ£-‘}G°3m·qÅûzê§jªD¾;|;Ø£IQÚâM¯äß«ò—Ý÷ÎïæÐÏNWcÁ›LΤό΀Ì)¬¸¯´ïpB¿­AÞÐ[hC2ª-PmÉÊÌ”à'Ž“c¾kðÓf,V|¬¨ÃÜÂ*Ts15Íü>ÄìaSžä^$J8&¦ïq-at‰G‚èÞ[+C^B4 ›#%Õ]ý[áfÐäŸ1e²p3 Xê- Œ™^fVo%0ØxñpÛ¡”EÝ›Sš+f=1@Í1ÝßB^YSXˆAKãmx'WI(¤—W#gs°”O4–@Î2C8•ŽÑ ËÉ#6Ej&“$n¼’ ÛYƒÓ¯mîªâ^D«º§²“S¿+n~Ä jÙ›±øcÏ‹¹»”›\xÊ÷Ž(b¾AcsüWå‚0 ê°’&û'1CbaèñFbåæ1Ñ Díçpü]ÕÝ‹€ :dµµxól‡Î6N}M÷Ù@Ía~Ršß–WŠ+L££åél’#à­¸I¯_SêA­rŒd)‡®œ@ªñ¥"{Ÿ#vßÐ7xr̰¬rÒU”“]m~†ùï‰BX¾èÌ7ª±´EQ’X§ËCÈIéë­b¬)/!˜ÆÞi–Ⱦ µ&¨Ÿ|HfS·Ç³ÆE[¹½7Å\ªIfbH-ò†4£--£°²­¯#¾$\’_ ™LX3ᆑÕˆ4Ä*Êiö B·î$Ï Ÿ'ƒkwz>ôYR(3‹ÛNÂæåÅ,ViâÖ>59/Ø`Ðú º¯ÙÄBGF_H¸°VnAM\ñPPM£ÇeAE./FsnÐÏà²_¤IÍ”e× ÊîÀ“‹q$L±`ÓU_ª±Ñ ¢º¥n…O]X’.’ËñÃYÐBˆøâÒÑÒÄ'$è`>y4ðû#úÒA ñ†j}i¦š¦šhši i¦€i¦š¦šh«Ç™oÀHŸÎÕÜãÍXv«Ç™oÀHŸÎÕÜãÍM¼/nÑ6ð½»E¨5}þß}ö5v¼÷^„Õ÷û}ô_ØÕÚË·3lþsä_0œuÇÙØ §bóNÀð«'†]1²/-FÆ). l”GV.dX&ÅfÉœ©á 7’æš3jñz¹ß|°(£HúkO¹‰¢qðmw,7ïO+ütâÉ¢=Ÿ”¤ˆ€aÈ{M"f%Æ9®O#Ò+¥ö³Cx]Dõ¢kÒùô’†ìdpT\lV{z{-qÓ XM…rY§FÈ/IQ¦I˜»c0îæ×ä(6ã-0BÔêŽZ4eYlî²eŒîïÉSÒ‰H;˜t=¾³} ¶xB6åýNè¤{­ëèQøèölxåÅÛÞÔôÕ{zó@ö%÷Nýšñg±=ßÿbŽ¿0ö…öPí/Tw{ÚÿÎ{A×aþ°vsÙƒÆv3öO¬{íû®Þ6æÉËýuÒ<Ïß.–}‹4ªSXê¼¾+ÆR?"#.€zqiyiåtuwæ¥Á±+÷X‹a3fy°¨ú𸚔 ÓUe‘üÔ•Øÿ“X8‰¯8rfˆCi\èLˆ·›µTÁ€«ýƒp‹•€Ú]:ÒöŽëÿÓãôÞW,ø­U!’Ú°vÁËFìl~âO?¶ÔùäòÉ·f:Sª10²#<ÉgFí€ ­Þ †: ÕŠÙ®´5ȾBmš+}¤l¥éñ%à Ê‡x–þnàc¦¸†Ç˜æTc+0-œžV…NNY7H,WXFj¶M[™ad¾c¦dƒm:Î+ŒÈÇ¡N&^ÕßDª½¦*‘lNÒ æùWÌ‹\æn Œ’OAšmxå$KªªE Ú­¢Žª"f-  Ã!$bm~Ë¡wpV®Ü .1á-ôŒ0m¯Àíí5Ä8§Ìs ³fÖU69:âó`#a›šõxÕUÚ“­·LÈ—X uÍÐ`IlPŠV¥èA`ɉœM‘r‰õ–5°fvö€i¦š¦šhši i¦€j¼y–ü‰üíQ}Î<Õ‡j¼y–ü‰üíQ}Î<ÔÛÂöío Û´ZƒWßí÷ÑcWk.ÜÀ’Yãšãy)ŠïVèÿfÓ Â<Ö¤{.VÃhD“:Ôêw†ÉuáfMT4ÓEcŠÛ'z"¼K!`T™†Å¤âÙvê%«ïöû迱«µçº¢ŒÎóÂ~hŠÇÅűÆ]ãÍ·.« 4<.ßÌC Ièü¯!ò ’Œéɺ +ë#|›µÚƒg%stü‡sê0¬GbÛßlËi|6/.œ¾ Åü˜žPQ®r8«Gù3g•S^Hqìõ– šSŒÑœd@NàNS-.¯d€¤æK¡¡["³hÛÂ$SJ»€±Aý?i 3;šü·#ùˆ¨?Ká‘ÆVaµ7++n_H¥p_b‰˜·@ß“.ÆY…·…•ãE À£±V’ÒØœ1¿J«ÒbÅ7 %"cÝç³aNûÞv­xG‹>Ìw"‹#«SŽÜ[©{Ub<¾f1Å#Þô…êÑ3£À}‹R.€@P)µ.\ꎦÓ@gSµœ×½ÍßrÏÙQ!ÜîÈ{{d÷Ê›ØËÙ»°ý!Ü~—ókÞ÷ô÷ú5Ò€è>êÿ­}QÛôã^ M £„œç‘JŒLÆÓŒÃì÷ Á$evó…B«3Ø Zä %8 ¡A{ˆ0"×ÍMÃÁ'ž‘ømiªoX¢á„½Â{©­B;d¶îOy{|Ýþˆí—uzN‡¹=¶óîªí÷\ø§èާý£é?4ò>ýqà<Ãþ#@gQYÊß+ðÖ«‘þòî #&/9ûvѺ+©Œáªª¸ ³p0špÙ “xÛòå¤l;~!v9•žPg—ã‰ä»Å'ÃôòÍËé |–+„G®­ü ö6ÜwR‡@”ªq-ê=áHìj‚ª´µãR®IØÍ«{z€’ž¦¨ôlV‚úI}Ÿ´ÐeË~\y›’XËÎq¿R›éw×2Œ)€¢Ä‹ªÀÌ)m…¬QŠÒÆ;f1ÎÂV!ÃP2 …™9|2bKB¾ªL5šzYm:®ŠÅ™¸¤ç+æÖÁÉ.Ë„31ä““Ùf)z–i`¬³Ïq’ÓÏ;.Á¢òÖ¼ ‚°y?¢XYÙãaXÔ3çÃòÒK~—›pšh åeyÄ¥ÉBe[¿0›{@Àè0Í㙣¹¯B·~žNÞŃˆ„gÅ‚i 4(üITEÖ˹=ÉczhÍ€×Á6@w禚¦šhši i¦€i¦šªñæ[ð'óµE÷8óVªñæ[ð'óµE÷8óSo Û´M¼/nÑd®C/¹D?X£‘QúŸÂo²X´œ¨*ýŽ©¢BUDý^»†7…&²õðøcÉßðrw·«âùær|L„þ0·?µ½{ÛWßí÷ÑcWkÏu[ÉÞ…o'zoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankz~g'ÄÈOã sû[ÔçM7~¾JéFï×É])üÎO‰ŸÆçö·§ær|L„þ0·?µ½NtÓwëä®”ný|•ÒoÌäø™ üankzâcÛvüôÅ}èà¸ÜkSñÎŒ)oy}K‹Ð2ÄÛ³܈DÊfç=¸Ò¤zxÇ!íGÞ‘Çkv_ »c¯e¿";T_s56°»òík ¿.Ñj _·ßEý]ªZ4ó7˜“Ÿ:û%•~Ƹó‰ŽöÖ(úª`9ÏòEr*·ëæ;罵Ͱ‹$€¼Ën×(ûPxÑ/™×Å »q*Ÿ:¿æ¯¿Ûï¢þÆ®Öy[<»³-o?=‡p¢¬€˜Ï«Æ§ˆ@•®þÅÖÆ&åñPÚò4œ„VäBb•ÆvØ£`Ž\²R¤P•¡Ðöj„×â6÷ Zz(û˜ãÍÓý öº ÿÄ7ºšCÊ-ƒìâ7þŒ{HõUçI›÷5•Öý莚êK¿ÛΪóÏ-ZùG€Ó˜_3‘Uúc™JɆïÇ–ÿ/Ïc>à»ÅQI‡¯‚ö­* ·íRÕšÖ`x‘‰³ÄN{ƒ,¥<îEøŸTØT@ۓΖܡ2Ö Œ†‹31ÒÏ4U<Úds@Ûrñ²ý*|¹aB1!›TZ褑W—"”õ¤Š´„V 4=å}t:øóYw…ÁŸ"yEæÖF†s‘Þ&6Åšf2ŸsÎzºˆ‘µ°¶öQµ¤œj&ys`µ´¼´òº:¸ââìê/Ovmk7-–HX„¼ ;çsíìåæKŸ8nQŽ•ŠŒ^¼BT†²éwV§‰Àd© Nåâç›+0RO܈“M‘`ÊŒmȶž63­É±¥ÉxIDHž‚phxB·WŠ1kEe`ÜÞ)6ÅqœðÙñ$P±hƒ/÷kë'wÒáš¶q†S1ÔL†¢ðÌzxñpYBp{峨­¼˜ f}¥§•ÞUÙSXøÛþ ÖºutŸU.$¼êr‚N¹ÞØÝÍ pÇ}œc›~óœ.lDwa}€­Š*³YÑ2¨e›<œ8#|žâuÈ9u4W8÷‘‹X×QØlÛlØ_šSÀj‘ é:23ƒi|룃3ÖIõ¯É‹ŽÇ?¼)a±Î%ñlìÎ,:( ¾ôÕWSQmOÚ££§®‚·é¦šªñæ[ð'óµE÷8óVªñæ[ð'óµE÷8óSo Û´M¼/nÑõ2K™EX›Ý¦!N¢Ÿy0ºÄ3zÚÈÒ= ‰ö‚±»Íýº¸£$;[8®ªì=[¼V»’&Õú!Ι²\ú¸~#î£~ã?©¿ãí4Ô;Vªïÿ_øˆv­Ußþ¿ñu÷ýMÿiî£~ã?©¿ãí4ÖyÚÏÒøg¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}§ºûŒþ¦ÿ´ÓO;Yú_¬ý/ƒÝFýÆSÇÚ{¨ß¸ÏêoøûM4󵟥ðyÚÏÒø=ÔoÜgõ7ü}®xÉ|Ìö‰© í¿GùYlŸ3ë õþ žú§Àø.–¤õ^·ÎüGŠñ{Ÿ¡á}W‡ãõÞ³i¦ŽÓw7Ðv›¹¾ÿÙ endstream endobj 399 0 obj << /Type /XObject /Subtype /Image /Width 173 /Height 135 /BitsPerComponent 8 /Length 11009 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFa[ÿÛCÿÛCÿÀ‡­"ÿÄ ÿÄ?  67VWw…•˜Ö×%U¥µ¶Õ &'"#$(9ÿÄÿÄ!ðQq‘2±a¡ÿÚ ?Û#ûûpFâÂÅ–ò°bùa±äo£Û …#wþìˆ[»Ü_êÞÝÜãÿ¯s‹ü¿Õþžòáðááð„ö?3Ìb§Ì×îpâÍWa®tîáC±îú1ÌWèž²®ÌtYÁ}PA¦Gyè;tQ$c{X’ãïnJkWãéï²ÿ“ÖAïÜ[Ÿ‹«|Õoüz‰‡¼Í0^õ´ï+_˜Æ'?[CȺ±å‡{&»ÊÏm†?\¨[ÜXîn*êØ^aP¡Ä¢âo_/ç,&05ñê«ïïïáa¿·iê«ïïïáa¿·k2^7ýÏvNòøå¡o|Uï+*‡=S­ÆêqW&ìŸ`‰åzJ Æ¹h6cŒõ…¾ÛXŸ™ÙþK¥ŽÔ|ð E™<{)g¯‡žÛ’ŠKk"*|—9.òYå-bçk†Ô8ÐëII6üh9.Í‘ªÔz;nï7Æ42º¨qâ·5‘g”¸˜ZˆðKA¼¢}U}ýýü,7öí=U}ýýü,7öíeÙ ,3Ç2r×é ó'AâÐ ÿ‘=?l»©Ô%sgl¨ä]‰eÃàȱhñ)B†—˜Uu<ö½N=½X,U]¥nù¯,[“®R[¡Ëkr>ò– ®ô øK‘•à»+°gÖÖÛýYš@H{œBÇf•û4pQÄ­ø2-Ʋ¼´ˆjøÐ'E»ÌV‡ÇæH)·Î`ã¥$ÞLfaª–í³MÖÌ„æÏ$* nEB”–Y@¦Æ-±rüñ$¡íHâ‘VÞ×ܹs¾«Ç>Ü÷ƒÊ B‰ï±Ú>²ØuUaÝ]½Òúÿnw´à}s¡õÀ½c¦y®™ÖùßaÔ"{j䌸Ý{`£=µ’XùHYù{{]ù?˜ »b¨Ca²e\û:a¸½]p$±€ßôãöu=apPÜ+©Ê«Ç¢¬XÐѰ˜á>Cî\˜L·+(1$¹[d®ŽÉ¬tÀUJºˆÆ\…ÝwÔöq©[ÛÊÊl¥r:½;ãh¨‹¾ëÁkov­g= £5¡ßÀhj¸Ê(w`k¢·Ò-Jñ¨öóåpa!á0ïH+8nŒÐ³ÂPN–pY Ä|Œíÿ$TtáÒ}”¸’6vü®¢æ+Cä $äÚ0qÒíoK1%JŠÙ¦ì–Aëp§1†p4Ò¦ŠD¡ ãd–ß‹·bya°÷dpÈŸow! U÷˦v‡þâ”+?JÊæõDz…â˜DÝNUÎW×óa§) ³€±ØxVÜTbb#PîÁDãÚS#ÓÝÂ>Æ ñË™§.L{ƒËÇSbX¾ó;8‘’ÓTdK&¢QÐ϶ʻ>±I Ç¤7¾ìqáÐÇ]N©…5”ºL‚ aÅ0ÄÍ}™J[arr~¤ ¤ ³3[[7¸µ•°0$8ÂÂp¬h‚ƒ .$¢E‹•è¤L™#f>Îæç–SYßUägqû¾e!{vwGîïF¬:ªÏí^áê¸û&q·×:®Ôü¯Sèå<—·éòý*s]Y[´ós“E!+ÀÙ°¹û"ò Ý® üL º‹"Ò¨i{˜vžÞ×>Oy•4¥ûU»•&*Á ê¶tÊæ¥§nª±v” ü·–ôºâŒ¿ùö5:˜«µ]ÕÛ"ONðM¾ª¾þþþûvžª¾þþþûv²í‡¹…̵B’qÌL†N´íìJÊZax2޳𡑧-S”¸­)Ôo†$ðø2+c¥»ZÝž }ùT0ÙjÓÖ‡u^ÙýAm¿¸ÅlÎËå»Û•°»þájßñÒÙºöÓãU‰Õ >y¯ëy:( DYSl›%‰VM­,µêP’íÌaÂÂãd¯ Ûñ-¨qÙUü`iGÕWßßßÂÃnÓÕWßßßÂÃnÖ-0ë8¹šdpNaÚ3s¡æMïÞÇj”êõW ì˜O0XRc‘Rš±&ï°)©nGW'S u³z‰Mœq5o¡µlnâ¬æ‘wõÈütïvs{öúöw1ˆmøóîk™];Óýœ»“#T;¿v}gIR‘ñ\-˜L”íNZß±NPR³"NšóITY ƒ§´33Ù¯¢ü¥¬U_ ý»OU_ ý»T‹Yóhó Êü^!Žné ¸»^á ¶Mf¢òKCyu ó(á˜Y¨pí¸·€ÁXñBËA±,óí‹<ä°ôȉVBvÑåy®ó@zª¯¿¿¿…†þݪpæ5“™ØKYX¸_“‚F¯#òHì<ÑS,¬CçJ)%OŒ4³ø‹âö¡lß›_³—¸/féBœsm7T{Ì·åÙOê”õ‹æ§/õö ËÆ}}ƒ@–¯ÇÓßeÿ&ªŒäëËjѶîw¬am¾Â´Ó®ë ? õ¶*§°­„=“ OÔ0WñÔk©Îg#›¬õÑ]–ÝçËKfɹ®éësµ~>žû/ù0íVEóCÀìS°¸*;§!AµöÁ¶³¬PT¬k¶ÂO[EF‡h4°Ø‰t‚uˆÉZZMð±8KXV F€q´d‰ OEÆa` çÊÚr¦[R`íÑuñÉì)R¤qMdYžZÓQĹWŒjMñž²?q…gÀçŠÙùà–J™8¢²äÁ|=ëÊÛ—ÆJ²Q­wN)Uå1¼%:z,xÕÖÑ•§Ž$±[MK&º õV-Há¶½VØÚkÐ 3 µ[{T3&Þhx™Sã¥ÔK!AšDËsÖq·…JÆ´ÞnI{Ü7×”*jÍ9¶×’p ýèiŽ"e%Dža\¹GöhRìÎâŠÏÌAÈå»É®®»ñ ÆC‡W².-Š Æ‘d£'¬À"Hü‹]6í\¯[ÐÁŠŽ“n[3(1Ë|Ô…xâ(”× 8 Gq[žQlºš¼8î´ÇM¬JGea¶nKx t‰aoZ#*ÈþE€ÛH0-ûÜ;‹3'ìK6®·J"éQˆD-ÂõÎÈhŸí3S|¯òP¼°øÑ"lCÔq\¶­aB˜EÉàfÛì+MÆ‘¯ q Ûbª{ ØCپƊƒ|š@FºœáàfOá´±b•ÙmÞ|®ã)ï‘a%mŸV=›[S‰†l{vÁHªëÅÎÜ/–;`tÀ]\¬BzËC4ñ`ÅõC…†ç§lyÒ¤`Žíe˳¸»¹:òÚÈG—«"ÈÆ{-ö˜=ÕëZ}fýmÑp-xl-›ft‹Uv®Ö쳄ì¸B ³<<Èa‘uP™2Òä),ñ íï®W˜’³ëR¶ž=á)PU‡èÊè•`ÛcP³Öé&e¹©¥éÞ ”;m YÄ YP}|gpŠE¶ÇPaêÙÏÜ¢¹Ža–F¹­×Éåì7”…›6µCµ+ËVs·kfñM§@X4ª½ôZœºR%Ek3%²ª‚ÞH û¤KÏD-é3{@GEœDÅõ,t^ÄaT%Y/VA‰^H3'u¯dÀ n;L9 \£ŽÚsy¾6Û±ff¾´ÈyçŠC±ÂÄZåÊ1½qÿ”ß/ü^s¯,JR‚í·ŠÌlÕLÇm;ªÇ+ZŠž*ã]]E™c¸v’C¯öÑÆ„0<0\Ú6_˜x[Ta)œ2RƒEa¶’?õa#ŽÇȰ`Æns¦Ó;0­‰ Ëâ —‰Çp}q feqÒº«h¨;Ò`–ÿ£‡‹¸¬¬tËŽ¶¯­ÚàÏq×–¢BކÃÓŠˆë©`3+™é'`‹8/ª)wN24qX^ß˃^Öô}°8|ƒÆº+«buGT©xSÎïvó°HÅ:1Y M,÷B‰oòÚ8Žð8È IsZê’ä¯/sÌxGJS•æcäóÅkLzÂQ²¬b£‰?¶Ø×,÷ I™n¥M›N·Ì¹_d5U‚Ô(úÙQ:¾`Ü"¥_­ˆ0 Bà·W˜¬“ëMqO—a1YGq²›ìs›é”'l;VÔ*±[m9±Xòkä26ëËܺé Õ†Öuñ¡Myp sœ½–†ˆÎ:ÜǬÄSyk²( LzÞÚzžäøÇO@OF+a5[%kj‰u­ŒêÝV²Ý^ U´È„:ôƒ$˜$å­oHˆlÂÓ@B³—Ržêž™S}µîIë—»ü‡j™ôËÞK¨úÓñä¯y÷ŸUŸòƒÝ}»íÿÚ} Ùlû>"o)¾_óiŒ| ýéÕæ(¼±ñÇx§u-Y4ã›Q7£†Rnåë]Ô/ª9”î™c½Aݸx2‰O#á-7tŠé ! Þ[¸;:¶ÇÊ‹sÒ#ט³Ö¶iá›ÌA»\Sxk6R¹¢Â Â9b$]`̓hvQ&ô̇êSdÝàŸåÈÜ‘ÅêuÎ_Ǧ¬¨¨Ñ.ì±’²àÆÄn"^Ku´Üt£jü}=ö_òaÚ‰×.2ãvFvç¼>R·guŽÑõ–¨C³ûW¸z__íÎös¡õΆ¬tÏ+Ôú8¿;íú|OcE÷–[œµ2 ®0ÕY—î«Ì—~_Î幑t =È ·äw2*Y&8¬2*{Ô…°‘l]ûÂ$8k,³',JÏãY¬ìvA/µfÜîEä.>zJKqÒÞµé€xÞ ƒ™fF Z-ç­$œ¼ ñiðÙna‰xª4Úu2‰lz×iöS ˆÜê%8‰ÅfêÙÛqºÌ­”i«)  ¯úaÕNÕB]l“Ú€eª«öŠ1ÐÖûmb|åÀ\.Žl°ã¼°ù;ÑøûŠâ²­©ÄÀÕÅE_$UuâçQíä:áL :`.®VqÒÝ]f°bú¡Â„Œ‘ò0v<éR3ˆÉö²åÈÞ܉ò?˜ÅN,xøYe`-Û‰Y+˜XyŠÂ¨*ÇxÛÍu"»¾ãúÐ;­H]Ts…ËÇÎuKN8m²Pö%v}ŒióÕö}OŸ7ì¼eÆ7Ç_û¸»UóÃ;8 ‘ý®˜SX6À±ë¿;.ãHܰÎÖÓ«!êï Ø wN^Òæñvb'ñ( Ë5 1Ð-–êr;3•ˆ&’­<¶²D°—­È¬,ͰÖvOž9×RT³£–*B\ý› eyÓnG Q¤£H½AœÎ¬ÚÚÝÉ®K(xé`¤7åoTù‰:¸lÄç'ã×öœ™r cŒŸ±%!jW‚!ì‘^àhŽ7#E+N¤ÇÝP(8MYÊ»ñ®æu‘h•w»eî+s¼~¨q;Ìܲ^S,$Ë2ÞW¬Äc¼ìlöÛÎöÂE°‘½kq×£fq•¯Jã¹ÜV•R0‡¾ <ëFšÆ\nÇ>ã÷|ÇÊB‰ïÝÞUu‡uv÷TèÇÙ õÎ‡× t~§æºgX)佇P—í¡îò¤±bØÉ+äàJ²ß¼¯,ÂÈ<£M¹ËQÊ@­Š]núÙ‰U0³bÌ"Úß$ûÍ{ Š0§ƒeчkq<_\$@¤7AJUFh‰²ÈlZuÍ®“Ž•c >Oݪ“ÊÛœµòVÙ1jîÕ£]œqZÓKÅD²xC^Î=­¥É'H ®@$ìqõ5k’ɾrÖÆü™Ë¿1¥»’ÖbÎÈt›Øö=Y7ŽW­—×l}Æì˜2SÀƒ×»å@|®RŸ¯Ç˜Ú‡Â{Â%©‘C¬ZÜPàq4ŽÍFRN¬Œ.NTíXÚÞÛV£ÚÙ«å#̌ԑéò œ§XN,¡ª°ÑIr‰¯‰J’¤F|™&Þ‘½¹¹Åðݱ—¬ÊÙFš±ñò°* ÿ vTíT!µÖÉ=¨Zª¿h£=ao¶Ö'Î\Ñ…ÂèàfË;Ë“½Œ ÎÕy)˜™‚{ü9¼͵wÒ'2å#™öF‰¦³Ð¹¦Uõ´{Cð߈‘=T¯ uø”=dª§©Å,ü`;Mœ‘_3*ü4–Œ‹qåñ˜”qÎi‡(NX¹f‡‘u•iV£µ‡yÕÀ®ÑAÏÅ› z`ª¢î™oõÐMô¸;ö8•û·7œÖœÕ®+mn²žEF˜œÂ¹Pó\¦k‹mã51usÑ"|¹2zÕªYÑïV¬<㜗¬‹µýµÓ—Â-Çã".ã“M–¡V(-´Â̳ŒPV‰‚¤¼ ,ø‰‹L., vé¬CæGÿ2ùñû»ÿòóÖü7÷íüõþ¬÷â÷qꟵý÷†ö²?õ»º»ËÐ?ü^õÔÂKfÞu°¹›¹ra´ÛpÍ·”³{1vºœµ°{y››!äi¥kv#%Ûf³Ö>KC%|­%I#lIV™”7²Wxfç¶×ˆ]¹LcŸ¤~²¹vw®×z8Õ_íæ¦ê¹ìþ­ØÉ¿íPg:\èe?Ü,}Tg•ý°p·í±µ…Š´I|Ëë~’ÉÚ±ˆþçø|,*ÎùÅÜmÄ{>’F]yZI°¢µrºÔݰܫK0 ²¸’"g‹a[Uìòöõt© ¨%¾Yƒ¸¸ðklä·—2©0dJZÉч7îû|㬶3xin5fHöQëÅB¡ÇO0š’yfeSüP#Ö)$„ø‹Y@$ v¢]½õsß4פwzw¡>—ʯh=½L\ž§ªÌjÿžz´¿Pý<ò¹hþËÚMR¡‡ý¡íüÇ·ëù²V:¯øž#ã»Â8=ŠC’ÎʺU|†çUžP ö©…žÅyõ†È%fÊá!~…ákf¡°¬®FP­¢6/= qÑñå=WQb;îóaDÏþ—‹·âF=|%Ëûò"ŒÆìJ*.¥ 9¢rD ¢éˆõêUy*¶‘ŸµÂ9anièpÙÖr$[´SfJHÑÓYÔä Ø‡>Np!Óµ• :•AxÇOMrç䈾Á9øÏ¯°hÕøú{ì¿äõçºú÷;nØË)’}¸SÇc£ÿœõŠ:æp¿í@ ÞÿÁcTC4²ðÜö2|)>Rf܈2½ŒØ²cíy~lý߆Œ‡ý/ÕZóZós¦¸nüÙú?¾ÿ ú_§~lý߆Œ‡ý/Òãu˜ì\n³Κá»ógèþûü4d?é~ù³ô}þ2ô¿KÖc±qºÌvw:k†ïÍŸ£ûïðÑÿ¥úwæÏÑý÷øhÈÒý.7YŽÅÆë1ÙâY«ˆµ¶wc-—Švé·…ÊòÔìÞá3\!ÎcØ ¶8žŒE™i¼0q@lR>ytµ¿;b7”—»tiM®¿6~ï¿ÃFCþ—éß›?G÷ßá£!ÿKô¸Ýf;¬Çgs¦¸nüÙú?¾ÿ ú_§~lý߆Œ‡ý/Òãu˜ì\n³Κá»ógèþûü4d?é~ù³ô}þ2ô¿KÖc±qºÌvw:k†ïÍŸ£ûïðÑÿ¥úwæÏÑý÷øhÈÒý.7YŽÅÆë1ÙÜ鮿6~ï¿ÃFCþ—éß›?G÷ßá£!ÿKô¸Ýf;¬Çgs¦¸nüÙú?¾ÿ ú_§~lý߆Œ‡ý/Òãu˜ì\n³Ψ÷™o˲ŸÕ(/ëÍ\O~lý߆Œ‡ý/Õ=s3ÙÝ}¬loínloìU!vw¶w¸8¶÷vwvÜßx76·vøü8xö÷6øø|x8ø8ü<8¸8¼žû/ù0íyî½ Õøú{ì¿äõž^.ng2s ‹ˆx"@rô´ÈTN Ä2à"&EÛLŠóÌzXcÂÅ#n”ñ$¢³tÄ©-N@'Üañª†´Zð›*u(½5Oy;Ì{$hX˜ò' Ò W™©wã6>TBíì“|¤¯Äk'%Ó8ØÆŒÈŠj6$Y êïOÎaUz„³jÙÇ IDp»ÒæNÛëŒØ²Jgxl·hÔ„{HæK ¥qxµû,F ®x3QTáþtØ×r-ó†.t²²ç&FW/tw2€X®šñ š¹}Üñ» ò·;ÇКB×¹{G¬v÷uz`†}Û·:ÿK9ÐúçCéc¢˜éžkÎô²ÃÊoVp®jvÂ5OŠY5”†µÄ¬³LÎ|Óy!³qÀÇù½[îÕä²ä=Kã0º’¬”-ì‡uÛªíÖjÚ{"ÔuB1·gº¥ï˜è4×–?^t•RÉ]¦Ú7Y[7ÛÇ8–jeGëI9’Ðdáž Wõv ˆ¸âާ8J3-ⵜÿ ì áøÇó mÈ[·%Ëp\¯›Š¬¤” œŒ²5®Ý°T«e² “`+ z Ç"áEË9,XS£ Ø•¹?~’S6£ñG+shSÓP‡™n%)gL~^ív85›Ê]X³cE$ÂßZF’Èêì%56‚0“äfýì‹mŽxÊÍY¶—Å<õzhK0©Òø˽)ÄÞt‘ëaš†qU†¯$ qÙœ©6 ‘aIn^Êô˜¬,ÕÔ2ûÍàAÉŽÚ©¿±Pñ ol³/níÈâà47ŠH§¦¼@6Mcsœá{ é¶G‹²†×C(æFɧ;n×ÐUàŸß9-â«\I›N<ÃÈâŠ"Í\I±··}¿@4ÓMÓM4M4Ð 4Ó@5G¼Ë~]”þ©AX¾jðµG¼Ë~]”þ©AX¾jsñŸ_`œügר4 jü}=ö_òaÚÈ?0!/û %Eš£Hr–HìYu0d^@­íÛó “ÞÒ,íú®²d 9 &Qù;D£ÄÙ…toÍíŽ3AöçÞÆšæ1½ì‰å™rªdûLÑK/r¥e†œ¶+»`û$º®ÄQ½›²­xÇÙᆲ&zlIí3D’]ŽLY¡fÒýšÞÌÞT8wʆ«Æ|§a¼ÒKYå-»jãÅ£@ÖØ†™C™ÇY6£Œ‚Y »LƒÈW§îU¨)V“%[À‡ylŒË"Èx-úšÓ@f<1îØ…‘|ؽ@ÅkO.89Šáí+CòûgA«öoºIµ<' +-Ob64ñCˆÀáäsšbp´±OW¤§À¯NZðŸdÞH[IûlŒÇ»bƒ»p¢òÎLV´ù­Ñµ×,äì;s®j*¿g7Ùó¤kj[}’SªK«‰zGC·”§‚“pàÈv1=xjÍŸkŒÂVÉí?i 3áQÓÖÅÍm>B´ëêtç%ú« A¥ •Ù»ÖñþØMÈtW6ºzĺ· m€€’ª&É3Ãiج¶nø S–Å8Ur^ã¦"e˜»qJm iªæîs1³²¿13IJq€õ=»D˜dbdµÚ–s7Ëx2_§32´³iú’EoãÇ>ÏiÞ¨˜U2u6³I«`ð×nš‰ùLaúÚ•±Ìvù¹1pÍå/›No³R=™I@ lI¤vU#aª¬V•˜ÍûÕclsÏ; (˜âR=²i¯j‰|Lpï^Æšhši i¦€i¦š¦šh¨÷™o˲ŸÕ(/ëÍ^¨÷™o˲ŸÕ(/ëÍN~3ë쟌úû-_§¾ËþL;YvâæmŸ×>Eó Ç\}€µ=ý‹Ö™_¬žYºcd^Z­¬0ÊBÄôFæ¢Ñ6Øè‹$¬ê§…59Þ†CF¶ŽWµÎú½ó`j&Õøú{ì¿äõ—n`T–xæºÞJb½áÊÃ/øäí6Ì#Í`—µs[-Д•jp{Ãe¸ãfM´é¦µÊ´•ÆŸR$RÈX\Ób„âPQ]Ù»h¢Eæ¦\ó ÇaX<ê'Ýf¹÷ÑÊ|GÅ3”EIضëž59ädéOÒŒÞ5Þ\×i§¦®ëŒ#Çl,Ö ¦aR ðGbÛòF{}q•y"/™¸n_ÖéAàÇ.¢9tÃfWcåVT¥“»•sª!-3^W@I«ÍÁ¼$FÎ.Æx£œIÌq™D#8_–fžä[­%Ê"®M$s#Ûñ>°ÐÈ e™€"ã#5{êMK¶­ìÃÂüñ,¡£†ŠKŠÊYpk#ÃÉç$xCðe‘±2ݬ²R¶ç5“qjÓÈ6_,èØ·¿>¢xÆ€¬ƒ-ü¥%lîÄœ»|ßÔ”Àp” EÞ’hnñ ž)æ†Á‡·/hÇ,W0-ÖL~Ĭ£¾S`ƒ&ßIc¥Ûnª f>jÙJÚ´fr†¢AJK, X»£ 0&~ü ÉPÉ@‘Å·+j¡syÅešKÌåE¬¹¿­Œ§ó­Â·N¬îF}žõÑJ7¦D 6 C ÓJAw`0ª4Û[ÊUNßi¹EØ®R[H¼ häß/,«J^¦^+û~çÅœ”®){‚¡ÛsÚsk®Ÿƒd@³ì ‚u’$€â1ìù¢†Š7špŒ]X1…Y5NfÖÛ¶=iÛ•åWÈ30©ñ‡¼«òý &‘í¥fŠÓ¤‚j(p§K.tîò 47ØyaÍRåîìÇÜ·¿¹°Æa¹ùjÒ˜BÊØ˜©²YŽ„¿/šÙU1T—ˆàBëÊàÍ9,ëÄÛoÀ ˲JÚ_+ˆ€VÌ1d:Ø3NŸJùˆ/™cTîÀeï §Ôø–ø¸Ä[6óR„Ne¶kd«FzäZ¢Á´êËìúµ݊¯`K!!Áh/ûˆª'À^\y›Jùÿõ6›í¯rO…[Þ{þCªŒúeï%Þ^‹|_y+Þ}çÕ`|Ÿw_nû÷gBö[ÞÏîQ¼³rùn½å÷Ëɱ*7—}oæ‡qð=§[ÈTjùåÎØ©«Ô¬€cŽ×I´ßÏß,év|W­Ø5íC¥ ÚŸc^ÜnK«\iûM4Ð 4Ó@4ÓMÓM4M4Ð 4Ó@5G¼Ë~]”þ©AX¾jðµG¼Ë~]”þ©AX¾jsñŸ_`œügר,o!ù„ÑI·]ŠŸ¸2Ä=1HÿÁR@€ðâq~$QàÅâ:Ê –÷I5xùÚ'æµ÷wçÍ4ÔkËñ¼¯/Åþð>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍ>Ú'æµ÷wçÍ4Ó^Jß×’·Å>Ú'æµ÷wçÍW6^^*wõ’Å8{уQƬïì3Døg™Jnîím ,f?N(æbðmîqÊÛÞñÞÛßáâØáàáÛÜÝi¬œ¦bŒœ¦bÿÙ endstream endobj 404 0 obj << /D [402 0 R /XYZ 86.4 708.045 null] >> endobj 122 0 obj << /D [402 0 R /XYZ 86.4 553.908 null] >> endobj 126 0 obj << /D [402 0 R /XYZ 86.4 506.491 null] >> endobj 130 0 obj << /D [402 0 R /XYZ 86.4 194.393 null] >> endobj 401 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F29 277 0 R /F22 239 0 R /F37 405 0 R >> /XObject << /Im2 398 0 R /Im3 399 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 410 0 obj << /Length 306 /Filter /FlateDecode >> stream xÚ­‘=OÃ0†÷ü öà«ÏggLKÚAUZ—1AP;„ñ÷I⤠#òr_~_?¾yÌfKô rç4‹/ •‚À¼  ¬cñ™=pÄc¼ž-µšzÁ"Sif±.¶±Ü i4q!=i~ØW›U*ÅuÙž¯vÅv]-Š›T?ìÇKÕFHäQ /wK*ðBèÀå`®Z0–zs9¸KƒàÝðNÓŠ v<ëVÖ;Þԯ ÿJÙé³n’žñS=$ !Œ0·õDZ›Êʘu„-÷ð/†8"öÔdo_¢¾¡‘úÄ‚\!ŽYÕXvõ–ݵgÔ•IXN”çÝV~ó¦!M98o.´ö?hïOõ÷ß´¹3¬Ê-¸ç¸o"hž÷mrð†Ì„ÚÔ?Â3‡Ô endstream endobj 409 0 obj << /Type /Page /Contents 410 0 R /Resources 408 0 R /MediaBox [0 0 612 792] /Parent 393 0 R >> endobj 400 0 obj << /Type /XObject /Subtype /Image /Width 291 /Height 489 /BitsPerComponent 8 /Length 48322 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFa[ÿÛCÿÛCÿÀé#"ÿÄ  ÿÄT W67—Õ %Vw…”•˜µ¶Ôר&(U¥$'#8Ffg"9EGH§)DXe5:r†ˆ·¸ÿÄÿÄ!ðQ‘!qA1añÿÚ ?»!ùùu!uµ]]·•ƒÈ{ !Y½÷žÚ²ßûY·w¸¾û{wsÿos‹þ}÷¼?ðáðááðåç.wªñϧ=àò ‰ëXéò°ÕKªéïKõþœëiÔ~¹è~¹Kë™æ½3Ö*üï°õžÛwµ~~ß~kýÍ]ª»almÐöç2ßeã–:d|QgÓ=/N5”žA}>» 7ÖÊä5t¿„ÛŠáp¬hcÓ&®”Ü})aÁ”ãpw)ÎÉ ©v·IÂÍ£/»“Q±ã Óê2ÑÚ:’aB±ž!{á²a»èíhÈG¯*£K«º£º«—ʦڶT˜0$Ç™Fô}í½Î/sº§¿ëßítßgj‹.`„éŽM"Š8Ä¥vœs*6,Eb•†70\ã†*bn¥Ës.ˆcF Ùä"Ê €q¾˜¬­]'¥ÐWÓÃ'è­¼‡æ±…Éß슩±¶’§¥lG°7K›.G¥!¥…¢{ª{þ½þ×MövÕ=ÿ^ÿk¦û;TìùJù€ b‡@Þ´û¨úçéòLܾJ4¨;Ž¡¨™Õ6$«à&<ùº ï/ݼ»–yG¾®±ÂQÁºYsc‹w·2s›:=‹•-É7Ü<ïx¦·1oãSPÍ‹ƒ­¸Å÷ ÙY!} ëPÿˆÉÖÂ$…E&¨ ,qÂ!« ™Gä!jNêžÿ¯µÓ}§uO׿Úé¾ÎÕVóW"ó[he 63½ÞøÊ$.¬¨Ìc»dár¿Öc ²lã­žùC‘%ÄkÊ䀟30ƒþçôËâZìÉÝé ~5+ Þ/Áç£[M»‡ë;\Põ>>ˆîÞÜåMŽוï%u2gªÒœxx´¶{$“Ê×~Â6@°!0yy%AÇ_ÈF“QP^íO¶a[AாàßÜ¡³ D›e5ŸH÷¾¿îÅÈ­®:Ù’Wæú]|#ë¼0:à“ÈNô:o;}qä¥út >[{ï3~êžÿ¯µÓ}ªhs3È}ì»Í>UìÓ"òß’™õʶ=lhëÖÀ˜ÛQÛš¼e¹ÚÚøÊPà¥ÕâOAPDCÃÕàV¡p3 šA0äû B}’Ë®jY•íË„Õ!ÁŠÎûZ¢¾›†ãØ +„«u Ç7~`¨–9o2ž~ò­ËêC„w [9’½.œj¿bB«d-IÝSßõïöºo³µ„å6gWvá¾ÀíùÅúÈó¢n ú%’)å:¡|]è\3úlàoÏÁõñ;Ÿ%}OçbzŒÞggïë’m“À1ߘ°ˆö];xé‘9½@™ÄZÕÎ*¥\Xdn¡·—i`ÚnÖ°h3%Q”ír+ñ¨ã·—u; àö¨#š´}ÅŽ’îã(£;mÓ—ØŠÜæs[²Œ¯yìdeµÒ.Ý*r6ø€däF¯FY†ÄvÅô4rc–‚o HQo-‰`Sµ`ܘZ1ׄ(P¼÷uO׿Úé¾ÎÓº§¿ëßítßgk^é Ø]Õ=ÿ^ÿk¦û;Nêžÿ¯µÓ}­{¦ƒawT÷ý{ý®›ìí;ª{þ½þ×Mövµîš …ÝSßõïöºo³´î©ïú÷û]7ÙÚ׺h6uO׿Úé¾ÎÓº§¿ëßítßgk^é Ø]Õ=ÿ^ÿk¦û;Nêžÿ¯µÓ}­{¦ƒawT÷ý{ý®›ìí;ª{þ½þ×Mövµîš …ÝSßõïöºo³´î©ïú÷û]7ÙÚÔ$ÖÓèFÈo*†o m)hí­«CFd Ä$-Ÿ]DÈc#ÒŒˆD„#^_HÙÛª©VV27³>\}ËÂZ¾VQ¡ ÍAžd°Ì§›sÇËñ“þY›U`ÜÓ_l¯Q+þì§s óB¢´ð£¶´)²Þº]á}Úž`,±'»*EUÄ Ð°×uO׿Úé¾ÎÓº§¿ëßítßgj®È°ÏY)ɧm­“´m5§5ec£"XjøÈEÈ–ð>4½Çª"Ê^)åóU›qݪ;-æM©Ãby&:Á+ÙjAiš­öû ù€·ž4X€ñáHfB‚Ÿªäñç^4Ck«ZúLª½V׊Ϸd¨/Ž/¬7›;¸Ó—Ùg6Ń *°¯†jH<ÝSßõïöºo³´î©ïú÷û]7ÙÚƒœgæÞ}f!E­ÂÛõÈÃ8fóhÏÎ'Ua>CÇjœ[[©ñçx#z¡ODuᵌ;9âÂ;ÏjåÔ7çǬ¢CÖg3LŽ¡äçNQ›ž…a̛߾ŽUAˆ å讲aÁ! b%4bK½€0(xš–ez9906¶/´ÙǦøËUŒKî©ïú÷û]7ÙÚwT÷ý{ý®›ìíUÛù¨ä'+Ì Ë·¦Ñ¿œ7„Wé¶âåÁºs˜3Ã2’«xëñþ£-Yc-;¾»‚®5¦%äßävnÂÁf¹‰"'ìc[PÍàƒR·X‰SŒs8a„R$Xòj¥™®­lãxnÈ¢¹Þ©ÝÿúgWlÞVŠ™Æª—1ððãd„x!ï!rË'wž­Ý¸ïæå4:Ö!euPÁé•}Pí̺*¨°hì*)b{*Úè¼2wãÀÛ“e3ÂE¥žôËI³fHkŸ¿NίÊÓøÆçMa™Üßù 3;›ÿ!k†¯ÏÛï͹«µyÊó²±…ÀÜtãÕ“_rŒ´fáœZÆI0ŒΡ«ÊG˜†‰Ù#.ŽÍi ÁwÃRÀ²%^ >ðJ²<*+êû)Hö2zÞI‘Œ7ƒƒ9@…Èæâõ2H[?˜xyˆÓS¨Vƒ7–$œ2ƒøjl‹6gÆ9«¼™9} Õ$ Û³s>W˜t½N+­qêŽCÚf„Ú赌¤$I°nÙe*ƒµYˆiÚúŽqÝîá,@BJ jYô>cu±× {™Àfâ î~&Ù$èÄd`Ý,{vǯ jà- 9Fö…’$UD#Û«>¼>«ÛÜ”LLˆbIfI6ØË~ÛľæÚònïy¤IƒC\JÂÒòÕeKÌPPe‚%|HL’¾ŸªÄ=GUo.ÒéYui.-mK¶,‘+òcÇo½#{oo‹iè8ß•æ2Tî„Þ=Q”­2"É2Õ£GlZÆßŸg‘eûÕÛ„1’¿õµå´zͺy֗œ#v"Û[Ce$µVÞåw.<2« \ÆMûZ5^SÁͱ™Ö,6­¹¦W×ZÜÜÇy±ØöÇ3Xn3Éw³¶gJn”C´ªØ¦¢²….Œpzº¯·µ¤2;#“’˜2È<ƒ2íúÓÝ\]ÓÅE~“ÕeTa4€hÉ çùòrJZÏÁ”³|¯ó³|µ|iröHdß-Ü̦J¹»“xæÜa§=†ÈI þñ/¿ª‹}š ¹µMÝEP"%æÄ™ÑÚ5¦A‘}tº6ÅÜCRè÷`þ\xd j½¡Mû[ÌcàY'.ImS[ZuµqS=|[bfs-®¨aО"„Û[Ç(1¡’„¤+ÁÊIÐ:šÇ N-˜-Ö=ÏN/aŒsÂNµ·ô ÀzäÅ>“EÒòÓÒèêçNôêjÛY¾ÃËWA—/wf>ádÇ q­—ÍÕÅÏQ¯lp2Nµ¨õÐÊÂ÷>“{®ò¯Õ(í ÎôëšÚëX^ßËXÁ‰/kz>Øqâ'•æc;cÁÔǪ03¸—a¾Ŭk eÙ#§drD…D¦%1¹T&¯ hFC,­•!AÓö×´°W0dDÛñâè³¼qL3èlƒ6 õ¶þ2wG²ÝBU[Ñ=ç†ÊüQy`“© D¬ÿRßú?²ó´•a¹¹/wëH{Ç&=ä}ÑzËüÃvCÞ;·Ýˆùñø§º—ª¿ø—¡úGüþƒHWrÝÁÚ0ÅÂìgÂÔ™O5@@÷ˆ€ê¨òjªÖæÚ—½:î×=×$QÑñZ¯èÃ+EÀjEaƒ†Qøqù^`tL‹¶Ê¸¸õGÏ|ÓyÞNŽZÆÙ^Ý;D© ¨…VÈݳm‹Lg€ÔÊôyƒ1q¼[JrZLÇ­·ŒÀ¾µ&—Ñgy˜Y¹ÐØøleèü›îdzxªË­»0+ Ù•ø~¢ŽxÀßMŒO‰gþ.º õkä¨=VÃor'ïÐp,~W˜"í²®.=QÆsß4Çžw“£–±¶W·NÑ*Bj!G²7lÇ…bÓà52½`Ì\oÒœ–“1ëmã0/­I¥û„<¸ðÈ­1‘Øù~›óê ¶wÞdvAˆ÷ «¸rB Ók£/_„sœSΓ¯Älúx&èlV7¤ù(”{óìâMíí4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@׆M’XÙ PÛj:ù4vÑÅ/ ‡§–Ò’o@‘·GlB)TLhMG]iÅe°õi”û¨2+a“PÈ“·kÜÓA[Œ]äîäæŠ9ŒZ¹ÃÜiÆ•cŠ êÿܹRè€Él:+°‰«W`O!àE¦'c¥Y#‰ˆÍQ(ë-öCI-Éh줜G8‚D¸²>šhâg.<2J{ªvÉ7Ó^äò÷aÿ¨m[žÙ{Ézz~pÚõŸYú¬ÿ¤«éßoþô/e³ìû{MÇqLbJ`71ð7·êÿPôˆP•úOU•^_þ6¼$'ŸçÉÉ.¬ÿ ÝMò¾wÉBòÕñ¢DØÝúi ¬K÷éÙÕùZcÿÜé£÷éÙÕùZcÿÜé©Ó­pÕùû}ù¯÷5v©Ù’dhÛÈñà€ÏÞn•äé“0%¥£ÆÖ׫%±I˜™|FÃUõGl/DèmÌ×qU³DkÐe$^u}xôÅ=:»¨*¶6k­¼ÜM® ž¥’¡l>hÓªÊW‘­q“'=JøJ¹°Z7dz4Qâf,:’ûê8ÑÄ…6#ÔÚÜK³²2=µ·‡‚–·†0TJë*߀ÊîgY™Nól½Ånw‡ÊNÃû—,“Æc1¼.³¨ÇyØÙí·Û €æ·à¶gªö×ìKqZR†ñls0Ÿtsÿ¹—2?ÿ¿ÿª‘Úè¼;儒ņÆI>o)÷“Ë0²(Ã\öÈá*&Â\mõ³4¤ÀËe‰i|š:ûÅ{.j®àlšínÕðXYpØ÷Ód¶q†\®«à†¢ðÓº„ Ž'Bp{é°oj}d\𥧥ÞUÖÜ×yè;þJÖº Œoe.$}í°¨Žb“\` g“®á Ot¿¨óp™á¿2ÛøÉ8°;ÒÖž_„%»£ò$ZxÑ´-ܹFxíƒÖ"lcYëÜ‹¥" LÊâÇ·id”üÄ`L£InýÍ¡Һ”k›Î _=¦ìVÛä%’rä‘ëxŸZ,÷ ¸¬¿h°‚½g›oØ Ç€Y2öä·ë%±_[uBø “¹L_¡¸îÚWyñ·¨À“Õa»€yåï|ý n¶.ö08:’çÎê³ì?Ħ°Úì5£‹˜èÉPÑñ ©…’KCµxß :®!åÝÍXUXÈÝoHÔZÈ0¨áøÇòõ06ã…u9Š–d]8627­ùQºmœ³®m|NÄNat˜(Ø~0·¼wì,ùB..ädª²˜@mß³¡ÙHF»«:«1f¤ =Êš¬ææÖ°§zå:èMÙ÷:‹V“õOAõïÃCÔ?æ4Iåù—y@àŸ÷4VL‡ÛL¢C¶›@ó¯nIÄ(h1²AE†íU\˜5lëÀz±ª‰U¤Çï‰$’mÎ2³¶ž_qqy?HbÛ;()p‘.kLÍ|Â0k¾y˜âƒ`pýÝpl§:Dµ_/à«¡Rõá )ÕfW”Ukë-àæA–ñ Û‚‰çå€sù7s¨N¬’ÉPŽ]ÝµÈ OŸ’4xÊþ¡#.ÇIÁ8ú`³b+²~¼®_lå÷¤n²n”4O> 3„Ã9ךּK¯q‹:y§­µ×€àŽ_¹¸È÷›pk„ÜäŽ9Ú4lb®­qx–’_H-iïF·xÁ½ßœZNHXÄ;&··;g1 ÂÖË#næ-—Ì~‘8_÷ LÛ Ù´(É êº½"ÁósúlàoÏú1ež›è÷Ч×y¹>[Ûqæú§¶'cŠc*³kSïàÞá¬o>å—}t&Y U ÿ›mPlúüA{Ê?\ô?\ã'õ^9}É£ lú9x\7«1`˜·–×!K\³!¼&埧”#9Éd¶Ÿt§pÛ= åÖ=ó8$I¿ÙÇA&½ø¤Z“=Î_¡Þ¥[ѹãÄ¢®_ÅÙ ®j:›ÉÖÀ®w>*ÑO–müsà`ä@Ž6+èlû7Cj*0l âý¼vž=8j îÙ¬VI[¦‹$·¥LáFÙ°•‹~çH™z[¹Ïj›!¼&FÄæbùÇË"c›©ñ±Ð)?ޏø=c6D–Í’b„Pf¤»s†î„n–¦ŽlxœuÞWgÃÄ|ŽLrÁsóGMg!—»ÿrs{&3í4Õ;*¡L>“ aUU ªæâŽ¿»îõ¨Q4Tµw%\EWÐéÖ› ŸN#‘FyŽ9˜ËdÀnAãá—p ¡éîž*õn”*¼ ¿ümF6OÈÝV~¥…æ¼—…ækäÄ—¾ÈìŽLbJ`Ë ò Ë·êÿOuqwOúOU•Q„Ð~ £$'ŸçÉÉ)k?RÍò¾wÎÍòÕñ¥ËئÖDŒï'ð±K’ùF<ÓÇeFO}ÓööpY Ô¶y™ÇBŽ¥TÍãú0ØõŒµÛNÚЀ֟qE}w’Ð@Œ¶EüØ»p=̽Yw3—Oèú·Óþ2èCù‡þ!õoÿ'­ßª²ÌÙªØæšÑàå .!/‹îu;ØR² \-¥´dfùÜ…éBøxªˆqYbpÓÝŽj&y&¾B…©BAŸWzR¼/„Mo„rÐôzþ\>æ=q×Þë.—»Ô»“ëÝóòwÝïuÞŸûz~_x®šûÏó Ûo[ôïò¥èz héªbZ]zËÃîw²Ø6ºðw#¯¹´†£,Û5¦ç;$›‰&žGd°ë;‡Ä“Š®¹XMVÂrú¶¾ –ÜòÖíÌ:ˆ×GLóî¦/ŽLs §²S[QæCù·ÌÄ;À-š=™iŽaø•²`­1¯¶G³ “ ‚:pV œZëQÎSÏÇ eÛP™–¹»T´ár]4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Ö½×®ç-Û¬eAânZxìz?ügŒ#œÆ{þÖ‚¯{þDŒPê‚ÇÙxn{>BÊO”™·" ¯c6,˜ûZ¿¯6~¾ÿfŒ‡þ—êŒÛöfß°ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬ç\èúÇÉîÉëR܃ȼv/VÞ_ÛS!M†à@#€P74jìe”®i„µ‘­ ? ®è$«/ÉI)á\¯ÈEdM ðºÚ]y³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ¹Û p•OÊr5b°¦y ñ¦rîh´]Ç;Ì&ÃU°ÂÞàHttIá–®]人QúmÝÚaúM› šM›»½›RûRR[ÎÂÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ëIe"­²ÛÝ׸÷gžì™N¢Ë >‰²¡­õfJc¨:^»×F‰<øDþ¤ëõ´Þ}+ÙDôâZ¯g½íú›X7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬çM`Ýy³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ³5ƒuæÏÃ÷ßìÑÿÒý:ógáûïöhÈé~™Û1Ó1»f:ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬çM`Ýy³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ³5ƒuæÏÃ÷ßìÑÿÒý:ógáûïöhÈé~™Û1Ó1»f:ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/Ó¯6~¾ÿfŒ‡þ—é˜Ý³3¶c¬çM`Ýy³ðý÷û4d?ô¿N¼Ùø~ûýš2ú_¦cvÌtÌnÙŽ³5ƒuæÏÃ÷ßìÑÿÒý:ógáûïöhÈé~™Û1Ó1»f:ÎtÖ ×›?ß³FCÿKôëÍŸ‡ï¿Ù£!ÿ¥úf7lÇLÆí˜ë9ÓX7^lü?}þÍý/×¥POãu?jº8S‚æîÜ­ï„h·@,}¨q7æÈÝžBROC[·Ã>ï³ã°²Ã¿½ì¢ìxîJߨÙÜf7lÇLÆí˜ê¶ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚ׺ØM_Ÿ·ßšÿsWjByšeFb©°6¦¨Â¬Âqb³œ#&î,2…H1°z~—CMÆŠàC[ÎBnµLü„$-¸¨±²°¿–;»}B„Ði®=Ï|J-Åô¾`Þ=UŠTkÖŒnÀ4­ÆÎZÀŒHAOck)awy0ÆH†ËLJE Xù˜UQ5¼ú@à Î=î1Û-ÍœŸžaYSË·ÃFhÚbÂ(ò,˜QØ2ź626‹MÐ8¨ÈG UU³hÙµdcTÛV—ŽÀ®Åú‚8òöâp‡}i®t¯Ì J¶$g†Õe:Y—¤¨ÍIœâ•îÕ¤ÒEÚÚS…ŸG›rÐŒÓsn´ÖØ®-Liûœï$@‘Å÷ãθ§ÍS rÓee`Ëœ!V¼öϦx±T æhÿW`.»Ý]^Ä$£Zw.ðnD¥¯P‘lu•UNýOµ—/ŽÀH®šÂ Õ³Œ2™Ž¢`„5„~£ÓÇ‹‚Ê€ËßHµEmèÅ3í(í=.ò®ÊšÇÈÎßòVµÓ«¤û)q$líñ s Í–Nr( ˆô 2œëJ½~Ô«©Ã(@Ü­¼)GKÜ[ÀF<ß×YZˆô™¹ºÞˆAE"`H®šŒìnæn§Èœ‹æBž‹ Œ)iË’ðxåòLi½L7>Æ‘—ºäCN\ oF/S™ ÛL'&(U Ò¶Úß-ù½„“XÜÌ[9W`(þ¿×P–¸ZØ'¥(buqÍüñ¾›ŸŽÿÖm!z= Ø—>Z¾NÌŽ0Ýúj3³™êK°9ãˆkµfd$¯FlªO)£v† e <ÁéÌ€ÚæmXýàý[6œ¶MNý$éûð7+vwcÀwÏk·€^i&±#5\âV2KÔ7œ#-‘@‘‰"¼“Š}åWóŒvÞÆÐ*óŠÐd’·†¤–-dÿã×ü#ùŠ™ûqÃi馚ši i¦šši i¦šši i¦šši i¦šši i¦šši ¬K÷éÙÕùZcÿÜé£÷éÙÕùZcÿÜé©Ó­pÕùû}ù¯÷5vªí„Ζ~Àæœ933  òmsiËæ®9+DZ¥ì> æk.Öer2vùgÃŽ+eeµÅe•Ñ30ɇºö¢ØÖ-AI ¢Z¿?o¿5þæ®Ö½Õ ö™‚95„ko¹ôá—O”ûÑ1[ß&›&Ù8tž_½\øâgšô1 #AÛVï䕨Búòô؀Ǡ]±ª§Š‰XÞ×V0Í•ÃSú-ˆ“Óïo¹Ô­F¡3]’£æŽBU¹’áÃs[ ˜Å„‚°¸ùjž9h±¼8$%,föe $mȤÕ0Ôäôp,ý¦‚¢\˜1<´8“A²aGÌÄW"yÞg¥M z$Ê I÷ådÔîýÀ ÷ͦ;¦p#¤“¸ÁÆ%Õã˜í¨¤‡HAǼ¾äéËÉ7ÅŠÙ…T×åÉÌÄ ÆûŠ©W‡¶ ÒRd6YÙ^]ãiÇý^CÞÕŸ©‹©ŒÇA˜XèK²Å¢›Àæ€ õ cuÍ4Êá8 ©S¿È)3 wÖa=Ÿä™´½Y6%[ÃCEÅp(zÚÑp¬?´ Ü»e«¬/ Ù÷;àTbþ! ‰Ívá #“ÝÊAࣤ;ì‘lŸ¢_oPWnœ%A©¨„øçq_T+„ë«àG©Ù‰7šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šh+ýúvu~V˜ÿÆ7:hýúvu~V˜ÿÆ7:jtë\5~~ß~kýÍ]ªò¤ó™ŽIÀÏ#ômN”GÃ|úÈ [ Ʋ›P<åø ƒ$ *$|œ™’s-3€BYÔc7W¸ý|½„ƒS8›nBâËtnÃM_Ÿ·ßšÿsWjµØ¸!Ì? s [àíá£/'y˜äþCã»dÝÃŽ5X¿F½yˆ24/‰9³F%OCnÆ$^ƒ¥mHéá×VJ$½“°öÁ#2̃çm«Â#»{}²iôeãaä’-ª«mõcÅ÷" ¼ÏpšI²(ܼ-´º£w®¥R¥Ÿ2ÆßP1Ê~íkž>-™p¬|2Âð.Dy;›ƒ8ÕxÕ$¼]¨ÍMÕ\I36¹×ùÌãÖBá]7†Î1íŽ*–PWÓ@lήd˜µNÖK…ö>S#Ç}ì ºUÝО;_.¾þδê?OØÏñà^Q\¹¸ÄI‹Á/ƒ—ÀÛ̻Ž)šVœÀKMPÆÙóì+èí±›*Œˆêéo•gWÔ‡cƪL ¡ JÆù5ûœŸml=¤8ùhóåO‡X£±Žôe¬¾^ô"ýñʺÅ1&S‰P¼2h”–r¢7ã[!+G0AÈ´·c›«µÓá6$n+Iªï@Yù‘ÉŒŸ µÛbíK%›d=’íª0£­Á>ßSrîEÀF©Ú<0ñróä5ò-®Þµ7É‚LªlO Þ¥Ûrº„Ì*º›F¬J´ˆ 5²ß¢Ù㮟)r_tW ®3³ï•CŸ!sàVÝckéØ5] ùX„|ˆ¬¾®÷!²Ø6B~ bR7è;Ï_·Nÿ-›b=ºé>åõfý쨞!ØIîfBKLÄ,æ&z¬[5ò‘YjãªÇàGiü  Ü!7Om˺­;A·Sž#—ïã9‘ì׫²O >;´Â’,ó‡np fç+2›yXxÏz<´&$bFÜžQ>HÚY 4ÜW¨‹F‹coQ–Ⱦáß²¶ŸNcøozè슮=Ï -íY”(ìšQó æ?މ{oRÂ\(+ÇÊfRý*f/k‹ik6¼f­´‚@‚CxÔìzž u&kŠ«ºæ@•‡Ø[„Öqæ6ò¯È¼SarÛð£kˆ`1ù4Ó³¤$Ê i×b5#ÃåwÕÇf´|'dÖ µ$4csì QG0+sèÕ¡Ø|Ç9žüŸY_Ëmpm"<å±Ã°%ÞxGµåo—7 QDµ.«(·? ¦7iD¹rß—A$ôåµMÅM‹x{6cüÏ}βG—n)®#„·ó)ÔÁ'”Äû^µÐ˜ÜNyP¸(.஢?'8'''ƒ?r:NuЋ’,6`Èðù’`£ 33—¼­±»Éâ$¬æf¢É¦ÉP5 "äo,1NXFpõa\©v—W—V’íaÔÉ£ 4A>4{"ºÝšøÈâœæJ埉œŒ«£`äpw3[6 ¦“¡„ñÆÜôdÊýÏ$‡»Ç‹ÉÌõÈþ5õ~Ùyˆâõ¼°[Ö‹\’ŠTÐ|£˜eÞ~Ãw“üqÞÿv_\íãW³ò=+Ö^ïžñÝ îóÞÿHÿ“íGtzóª¿Àž×áíxqù¡àt¼‹¶ÅH¹ G%ÏBÓF^AŽ$ÆÞ^Ò»Ki ¯E¶Ï-°î$msL›€(ʈy}1²[tr$L¸­¨’À¡µ‰h®\ŽÐ|Óym;ðrñà¿+æÓ{Ÿèܗ̵sŽŠÁ²®; ËlS2ñ´)ȵ¥M@öÅÂÒNìØ˜<¥¶˜¢/8ÚfعœQy‹bÎ:aÂò>oP6ò¸¹ÍÒü2̤hD¸Ï£Ö]D£¼Êr 15ø8í˜bNî5ÛT½„rjÖ‘,9túã ¦‚çl‰ŒI•b™°ÑV$m<Ì^XJ©•@"ÏñÙŸMZ¡#}lñ*o2"²·!±/+ÒØ öU¨¬õj†LÊØÕY\œ¸ó4¯–_:¼| Mùöþ[sMjäv>÷ U¸ ‚Gþ4›R™züӘÞta~]gÓÆ×CeQ½'ÉK£Ø°ŸYm¦´ 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Ö½ÖÂjüý¾ü×ûš»UååcÌM±‘9k̯_»÷–ö‰ ÂɈØÊq ?fŒný¥eÒ­Ë”U6b‹š ·˜í ¡5nCdPnDÏ(‘c2, úXÿ«Í¡Bv4ÕgqS¿Q™ó’ɼ‰²8¢ÂlM÷J¿Æ`•¯°3±[8ê˜4†Âñ-«6·¾¸*¶ˆFÔºz¦uÆñu +2íÙ½æéËõ¶lœº‚]èâ|íg¼*hØl ¡“ ¿T4—^‘´L2šª~ïX_F öMX)}\†§o†8c‘É MÓPÌ+™“ž‹•¶_är%O”øVúJ{³K÷¡@ŠÒÚîP»Y‰o/~-êÛÄ©—š 5# 5ñ¼³d§ áZ4We›#Þw¾P¼ÄTebŠ»"Óp5eàv©ô¨Þ^Àp"I.!QÀl-w8n®­"QÄ´º«¿hÔ­âä—sA‰ª˜ öÈ¢ü;ëMBûÏ:ØXýÍÄ¿2$¼³Ä¤—%öu•«EA¦’X0–ÙoIxHv#]–ñÏ-$>Ä¥Úžr‹kt#f=õbñ+++)&R€gìïÁ™¶e¦æýofÁ60± ʤ—ôåR´³t¢¸8ˆVwÁ Ú7–0Þ'ćהá›]^ØñÙ$‘.Íu›Z¿?o¿5þæ®ÕyI9dÕãöò¤½ÛŸYO˜-`¥"öÊùOšëݤ~LbÝ|ãï_Ú6"6̬o…Uà+½…¶°hîÏ«¯½¡B:±_œ `*<|ôÈa¶™"¡mGËퟌxÏÆs³ÃeO’£f5ø×ǧu‚ÎRÞ8Á ‘Œ,‹° ™s½\If[uÂmI†EG¹ÜÙ¤¹Ž±¢¤¨Ü…ü»hÕD×pÝé'ÒN!·P—®Šƒ¼¶ÖëKHTk»JÃ-œ¶˜¤™:$B_[!ƒ"¶Ôf³ÜprN[6j¹žÇköÙyÌ(# B‚W ºê¬f÷ ¬ XD¦‰ÀE»Fpcx83.Ä&¦]éa•ó‚G¯ëeͯ.¥ì ÌsÍÈI'{˜Åá3ÈÚŒ>¥LëÅd0ÚJxP•%_6Ê€Š3>;ñª__nXîŽXuÂ7>þèÂ{8+ \m„=ç§1—³·’þs>ëhñÄíay‹ÔáíüBÎe†HîO9ic­Á¸u+­j(^Ó\Ç4³]8D-Ä鯿Àµª·[Ÿ¶ 7m Jj?Lée`›Ë¯1ìî£(2ÉFEÂßm@>I\B_ÙmB…:µ¦*_qJð2Ší®%(u‰¼2Ë ª]žµ¸„ƒ‘Ló¬tæ¶=Êš9.c7˜»pÙr‚ãÚÑ{[?®Å 8LvPC¬íÈóÚnÒøL·q|&XðÙË t€tW‚ª}y,˜û›ø‘| ýÇÿè‡ÜÛ´}!ÿ¯íî?_uGÿÛ=!ÑþõÕü'AǹFnØÈÞhÉŽ\㮆ž?#E°öç7òÁ.I² ÂÈx±IW4(ë©Úè::ñy÷†æêfy#¼‘gŰ-ǻғŽ\ùkXÔDÄiå’5cË8ûš&?Pº6g0”Pì¶u9þ7Ø»ïŒÚî3›ù$„3›$ÄäŠPa¡°CŽ8sŠläW(ð‚{Ú˜Êôƒ¶ór©GrF{V6x½m©Ë CÈŠÒù2¿Üß/o+<¸õöà Ý;uy¼´93³i XìšWÕMÄ8ÑÉm!½— ´g"“Žü|+EÀVoc Û…°ë`^á,ÛVCB¯1Ó­Ï+Š~>Y³ ^6Ç3 ¶£ính:,o™wPžr‹ 쯔ùTR §/©÷Ìv'·˜Ü}9äºc¹þ±Ö=#ëmyéþëþ—7Íú,]Xœæñ²ušj<5a¨•%ï;̧Zf Ÿ#©2Leã›sâ=˜êÅuð"ñŠ HGsGRõyÏ¥-§’u‚DK±Ï9K9Ö Zìvîq÷º'- ‡z©fU•E+f‚‡iH)ÆÎ¡Gy\pGµ[MrU:q5 °`*âº00s;U¬àÕ˜»Èå…‹MŒQ2£Ï ÆÓÚn+|RMŸãˆ6ÜD–Kl±adZø¼äÔ,½ŒÓ6ŽV)dⵕ^$»$¸™¶Œ$,Œ",CË“,]¤ê~@ûel‹s<ŸÔ|ß$E˜g—%¢ vy"y‘(6§,«l•N¢÷%lxttkB»XÑ;Ñ÷Jê†XÜ¡†ë¢ùoógÊûLe墛 ðƒ…æs;Ùøã³˜ÔLøu¦un}Ö–•"y‹ ¸Ü)GKÜ[ÀNh¹Á­]Uó³x.Çj¢Ó©±c“o»GÉUþcz×äÊ÷äÿåNw·ß?¨õBû¶Ý¶õïüûÖSÿ {û ìà ^^ܠߪ#}”ùePÔàð9¥ ÷ꦎû„÷$ÐL¢b„l½ó9g ·U½£!Ý,‰b¡š*œ]Ž£¨˜wwÔO0”ÜWÌŸz·>j„ˆ®<‚ƒ]õ˜ãJïêÿ5Ý—8ج[|ƒ í­˜¸é8c í¨z†\²AVo«zøMæý| »{}½®YÂD ®0b‚1"QkÔl10ˆ¶.2þ°3>ë×áÄɧùÇë™qÝE'‡^z÷fºOP{-šj8›Qéàõ6¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šh+ýúvu~V˜ÿÆ7:hýúvu~V˜ÿÆ7:jtë\5~~ß~kýÍ]­{­„Õùû}ù¯÷5vªí‹˜ ‰æ°öæ@öÎñ[ÇÔ„N}dþ¡”Ĭ†bQêu’À WpF­XíxU‹4ÛµvÑ Y'1änïBgŒ ²•Pô{œt(YMVw)P6¸½Ì&?âݯŸèo•L}E'" ØUKPÂD¨õ•m©Ñ¸ü ΂1ð"ÿpuB°–T7jR½QÝ9¼üæíåœÊaÌPõ†:­!W”T\á~ISÂ¥«½Æ˜®µ«™ÔEö?ÑN¨}5< žÄàá4Ý1ýY™ÁVÜúëH[¶›*= ³š€Ï•?)„ñC¨XøÕÓyDÕæ-òqbU“5RïÆTÃ~Õ—3Ï!²Å‚¢lpÛ¾•i b{ó¤S[2ÌíÊ‚çŒ×Šî’YIZòÇ4v¦bãw.£|âJ„Xº’Üï1çf $“²¨r(0p ‚Ä¢œŒ<Ý«aÕœZK´·KÅ\XíZ‘²Af’SØÅ 8ኚÓ\CË· Ù9gŠ ¬œcÙ¤7ûíê¬`1t<ÛârÚâgȺ”ôòöê_pÝëÏ)8yØEL(°¡ªdÅ!®^×ôvõéu3S—×»¹Ÿ1÷®oa¿Ê‰¹dpXå»Ì4Q·æ‚ aê® ¡ƒƒk§®ý°…]司ØÍÂ`¶¾†¥*±-&ÉZ»´Ýhz@D.¦¡ïs.Öß6±ó—ãÅÛNOjŒËÈnÙ¦Hµ-f¶¨b匫ك‘,záy»Ô³nå]Dg,òÒ}ŒÊ½­ÍáÝŽNs{ÏìƒSòŽÜS,ð÷uåÌ‚™rHlNHZœ<“÷ˆâ«­¨ì†ˆÙ%õ”|1êxo‡§ÕO`oBâ&Rp^x …Ÿ´ÕD—‡ù¦ÍÎty]•eø C‘ØWŽ˜%5€ÜpP¢qð弆½›*·Ïf\:^@j;3=AR‰pÜ,Òg—Ç¢’Џ1²•ØT<íJ•knj%Ïå×t~NŸu¹â×A(ç>_8}ìèkë„˱ó(oޙɾ’gqqÄ¿`Úß‘u*Úæ!°zÊo¥UÂ= é¨'}fÿ3ÀìËÈœÏIaéc--F£¶D•ca»Sm$m=ÊÆŒž2xÊØÛkÀ¼I_Íc”H¯µ¨k‰Qˆ‡“Âê|Êl—~0²¥~ùTÞV&o9#2S Fòm’ 6Èʦ¥“ö%‡u‰£±ËÒƒÛhFfí ‹Çá‡`Vc¦ªÊ¢z™¢~èÓ?ö¬‰*±ç!N0_Žà”U ÚÅ~à©CwŠh¤Ù‰XušìKu#²è2I ›äz Y½½U]m~WæÑœþpéŸ]ÓP.9=æ!æ-ŠžÕYÕ ð÷2f*¶öw™”«è•ü]ño¡[­ú+ØÑšq†Ã‚õðJ +èâT@ „é¨ Á~d9ßþ¡"ÿûÇFO˨o/UÆ¢8瑸L¶“S}þÄgäÝë5xÖêø„Â6Á9 MD¿â¡‡~CdºrM€¿,Ss ÈŒ«Â^g)Ì¢½Å‘÷PW+'“1•ŽÁ*ì¸ÆÜ‘Çó2Å+/{„8¹W”Cób8Â7—«{»öúÔÂŽ©vy{3ˆi‚|·m]¦´Õn00²Õ3qÉ7Ú!ØéoŽ9»€°#©¦€Ïeð;Ud˜Ó‹àǼVÌB".°Cê3àM±».á €yᥬ+Àßc t¼öÈúši i¦šši i¦šši i¦šši i¦š Ä¿~_•¦?ñΚ?~_•¦?ñΚ:× _Ÿ·ßšÿsWj#Ü®í7±ÖJ­ßù…ˆÎvõèóЫžÛÁÐð!¬6SÁ2ÂØ#MH÷ŠOxÊ’`qÂ@‚B#úËnàC'£—6¯ÏÛï͹«µÉÎ\šÆìséÏx<ƒH"zÇÖ:G¼­p5‡Ut÷¥úÿNuµý®z®RúǦy¯LõŠ¿;ì=B'¶¡C–Byd ÀÌð`ú¤ÁßhO>óV+ëcc[VÙž_ÕKŽüc¿ˆJGmIÌÎ ÉíHXœs†oª¡™‘ÚñG¦ðà«­Õfüšñ|éNèVL>ȱ٠ìú$æOTÑeÓ‡6y@K½]á¹~—$£ ‰WKGKWʘnùÕÅ.É Ü[%‘hÏ4”Ùê*¨n%d»L£²&CVÆ`‰oÏvÒÁ2¸!QCÚ·âÉ£©³­+²¶ Ûºn ä©Urö%nm=“rîS±qЇœM‹tÚ]4ퟹÆkïKȵSÛrîEðSa^9J6!WŠq «’`kêH“¨ç]U˜°ãjÊŽR(8Kd€ û{)Ù‰lÞZó–ãl8#2œî7â–‡l0'…À`\'iÐ"­yV"»à £“¶* 1ÃÞ-ç¯ÝÞÊn°ƒfjÙgÒ=Ç`„/û€q@²ëbÊN¶d•ù¾—_úìøHpIä'z7¾¸òRý:Ÿ-½÷¤1/VØdÃ\(®Î7ׇös´x šÊ‡t1+ÝKX÷¶Ê4P¸Èеá ?yÃer$ ¿Jµ#$±“mc.ÞFö¸„Ã’Ú  ÍýeS‘™¼¶Pe;¿ý‘8¶°ÆA¶ 節iZ•D{!›õájòÎ`ñ–í QtiÔpcðT×­”±&XBáš¶q†S1ÔL†¢ðÔzxñpYBp{鳨­½ f}¥§¥ÞUÙSXùÛþJÖºutŸe.$°â§,„ ø•ȰÃ~5œ%Rq‚5N/0£'ƒq—zNìˆ(b‘êÑÙý67çîøÂ¬Ó“lk[*²ÐóZC…ʈ™{ƒ ¹Eãv9üŸýlï´ù8}êû!ÕD€sº«ÞÿÖ{•Ý_HZÑúç¡ú來é†ôÏg×ú›ï7=´‹.«ge3DÁj/ýG§”'—¾‘k:ŠÛÑŠgÚQÚz]å]•5‘¿ä­k§WIöRâHÙÛ^³VÂÆ`k‚f@ã ©Õ°½,¡¨3cô=VÍé¯A‹ØOx_Òr#Ü”tôŸªßÙ±¶ò‘7x7¸ƒ[œ¨q}å?˜<ÆEƒNæ?2J<{©uÕF,§¨€?†ø(ÔÊ-ʱh–”·”¶‘* ¬£œY0†ïI)`ųß“p)iƒ¨ù5âúâ@RŸd^RÐeš°Ug”U™^˧qÏzO]’[ªÚ¥GÂêc­5(ÙÚñon´5 #ØÝk‹T²6%§MKUòqÇIxé“8êàsfOGÊÊ0A–+‡$òí˜í¥QÝÙš&€Éøª*ÇhÔ¬²–p½Nøu¤ ¢Ò«ØÌ(æÂ# Äì<^ÅÏvj¢˜“²+)òR㤜H.ÊïqmihW¡•a#4ÔÃàëÁÏkºMù©uhNË%²guh\Ý6;¼à©—WÔÚh#¨Û–B ðÏ9Ï­ŒõdùíîËbÁ¶aF µRâTHè6:„Xv¨œ0à0ž¨y‰Á8šðæªa˜åWŠoŽ;A›'ÉoŠÉëŸH8é“«ä·ì×YÌí·º‡¯zǤz§–îÿ\zøW¬û«ç=þcËu?ø]¼Í[3:»· †oÎ/ÖGYBWÑ,‘O)Õ âïBŸ?¦Îüü_¹òWÔþv'¨Àæv~ýDÍ[™ž.X!l5_K÷<ˆ²†ÜÍq×[ס]x/_>Eà‡WÑÇ‘r/Ô0kº‚«czƧÍÄÚãÞá!Å>[Á˜¨)w(3yÎ!±Žà£-üŒµ…T¦WmÚ‘[nÅYÇHÑ&=ão×ãQ7¬¸®ÛË Á@àÒüƒd{sUƒò{IÀvn0²0²0íÙ‡§X))í‘#¦À.:2‰M †Å ëVCQȯ,‹Î·ï 8*šwc[#‚¢‚Ò©A+¦ ÙKN°†;5lœ ¹c·X! µàç§u 㲄2‹Õí`ÑTúÉA4úº:¿T¼´­¦®óÓ¶<í­ŒèÞÖ\¸û;Ç”œºT%¼º ¡”´÷-9d+ ÔHm‰7b\p FÏ’BÈk‰ÍÝ­ ™ב„«l«d†Ê²I¿:dªÙ•{›ñ»ëM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Õk¹m#OÌ©çÑʄ걓–µ9ôßKÈÜn¯„¬ØCxYÄ›Zc…tKúeculn5Þ´n³ƒ$Á¸l¼L‰0*x7áYE«óöûó_îjíFEò¼Àì¬ap78õGd×Ü£-¸g–±’L#³ hjò‘æ!¢@ÅvHË£³ZBð]ðÔ°,‰`WƒO¼¬ €Šú¾Ê…—Ê¤ÒØ+˜·"ÄÖ„#ás«¥¸YSа(U÷ÖÁ™N¾³´ž6p6o=¦8&9wVD¶H²c@§½MƒÍMZi”¯˜¶(t ëOº¡Î~Ÿ$ÍËád£Jƒ¹Øê‰SbJ¾cÏ‘‹¢òýØû˱9g”{êáñ[%¥‘'68¬€x‚»Ÿ‰¶@‰:17FËÅݱëø HQ½¡F¤‰Qöêϯªö÷%2ᘒY’M¶2ß¶ñ/¹¶¼›ƒ›ò¼ÀæJÐ;Ǫ2•¦@äY&Z´hí‹XÛóìò,¿z»p‘¦2WàcÂ^¶¼¶Y·O"ÒøB“„nÀ„[b«hl¤–ªØ#8Û.¹šcî(„½i;sÙUÍ6ƒ±iÞØ­@2W8ÝS%ÛªòQÀµÆòYxòÃw¯*"ˆð ËZϾ ¿&¦$¨q¶ËçNf2rùS¸"4Ùn«9„dr3žÆF_Ï_V‡c‰kB~ê|²¢yŽÂz´F´í 8†ê, xq ø$®­(wwÀŸ :•“m"¹kT© QZÉ"°!ÇeÀÌz˜¤ö’qëÅ܆!+ÍkMryÄwb0B3SI^÷ñÛË#{™‡+5qMC_+ZksîNAT5e¡Û|Á[KÆòíKtÁáZcU5p’l¥8‰o’8äMï ;z#íl’ÇÆ9÷s³A½ßgyöG5Ä%D=TçgúO\™Н/=×=¯ü<9èⵞWð=·‘í‡xâ˜f9ÐÙlëmüdîd º„ª·¢{Î+ %•ø¢òÁ'R @‰Yþ.¥¿ôeçh=*Ãsr_Bý-+ÙDížI’ñ£Å:´,íÌ™5ÉðTBÀ¼‘¶s^[/)k6SÌ8¤KðZ2W=•†J»­Î\ÝXYžüÉlç²f嵤{ïºir’WUX㚢íNÆ%£;$Üñ‡IhżCÚo%궬‚w¦’S›Å’? …“x3É×–ÐY ñXž0ÑŽÚä]NW‚E¨>mÁ\½ª'DzÛ*Y†ìðˆ-¨í¤V m•­ÁhÇÖÐʪ£ÛÚµ*Ò¦Óù8ðËàßÿ[ß(çÒWþù¿>|ÿöóè«ÿ#h œ›™–nPã¡]Qíá«.—îƒí¹PÖ·AÑ2,·k®äð­2§ĨÙ}gm_RXV±OìÒKax-JIÃ)‰o9w[f劣9Æo(Kèr-¯Rµ7†Þlâþöõ-ℙѷŒ„7HØ8œWᤑ×Õ¢Tü["UÒºzL‰;ÅdÃ~W˜ÉSºxõFR´È‹$ËV±k~}žE—ïWn4ÆJü xKÖ×–Ñë6éäCZ_RpØ‹lUm ”’Õ[tZSÀj‘ é:23ƒi|룃3ÖIõ¯É‹ŽÇ?¼)a±Î%ñlìÎ,:( ¾ñª®¦¢ÚŸµGGO]+Ë3!÷±4ù¨0¬‹ÊŒJuç×5(öQ¤/[ƒj·nq‰dDËj›àÙDb”·ŽÌe:~‘XW–š@ÃÁ˜BäÄsëâˆpqê‹'3 –ßt)–·¤?y™6á¦Û÷_S->¿jùYFÿ‹zÏsĬå7Ëþ©ÛÆhè/4 {v§eµ[rÓu™™Õ"cAJ Înß1ì›ð•àc5‹€:“ºðÀʨ¶5cÔUõä$Q­C®œ¾_szeaÃ!(òPo€´ 'ÅÄ•SÏNÅyBL¯@d‡ØK´ºV]ZK&"£ŠÖ¸d0‡öb3˜Ä÷âçLVÄÐkH{¸¦=ä}îº7üÃvCÝǸ=BUô1×ÍèÞ“õΈùñøo¨zkª¿øo®zGü†·~¦šhi¦¦šhi¦¦šhi¦¦šhi¦‚±/ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚŒ:þf8›|HÏ ™‘l»DËLÕ"Δ¢ÁÜàp ‰6sø+Mg+ñØ´BMå è»’v«o&ìï@Ÿ[kzM]|É2xÕùû}ù¯÷5vªíÊ g-n‰9²JC;qÑl!·Îƒ;£ÙQ·qq–í$–IÃ=w¹2Ú Xn`cõ]}ý^í<8ÃÛá¶sâOeeºM6=´ZªZ, Íc†'Ìëç§а‚Æ9á§ZÛú`= òb‹ŸI¢ƒiyiétus§zu5m¬ßaå« Ë—»³ssóKI…*”q- °ö§?+eQ˜… ÆÄ©ñëa»LŒ‡(D¨ödIÛܶ£+¼¥1¡Ã"Öðrº®$©›0Ìôô‘ÞÂçF¢ÈŒiãJçpÇ Öà. øð7‘{.€i¶lÓö%D¹‘øò–Žýå@!…Ü4òxíÔôp7‹ ·ñÄSrÉ aÉ2ž:&É’ÓŒ˜÷C.íµpóI„$ ÄØÞ©ñª:6(KKW.ò]],1"mÙQ÷¶MW»ÖËS-›åýõàÕˆ]d˜lÔlxÈ4†Œ´@¶Ž¤˜P¬fÚðÙ0Ýôö´d#וR%ÕÝQÝUË‹eSm[*L ċ#z>öÞçgWs¥åÃ<1pÏî8P7 ®oÌ_Ë5 Î}­Í/ 6ËÜù6 ä,ɸ/lm`U Æ(°!Y^7y*¹Éþ‘z;˳êL/ md°rIg¡£µ;qæ’Y’…å4Õ|"‡<¥r-O› ¼ãÌ'¦3/Ë<ÝñÊ36Ôm=I¶ÀAµS lvQ /Ôô{îp„•Í¾àŽøØ¬zøRš6ý˜÷}r· É P¨cåÑqÅÞCdÙÁžQ°@Ë/Ï,¨qó¼ó#^‰ãªÈ]›dÝN§Ù¦ž¢»Ð¬Ö ui­Fä ïðÝÜâ¹mcÙÉÒÝ‘“Ô{ÅêÊ=Ò´˜ méQ3 eM:;T‰ÄZ^V2æÔÛŒœ[Ð’S’ VYÔÄZ3Ãk"£$Ãf£cÆA¤4e¢´u$Â…c6Ð/†É†ï Gµ£!¼ª‘.®êŽê®\[*›jÙR`XÀ“d9Ñ÷¶÷8«áÈÿ&±¹‚„ê\’È4‚Ã/Q.üŸ™Ì#a®<ÉŠçßÉÛv‹€ØŽÿc¹þ±Ö)åï焈ÄT†úPÂæÝ ? yâÞ ye~,cEfDao,r~VFY,|:µÂnáÔÃð¥¬dÍŠ+» #1vúGÂARÀªòt¦™ \²¬¬ 骗*òS13ûîsx-§zFó.B9odmJjìß0ÅzÚ …yAõoŽÄHÔ^TVÓžWŒÚŠw:ÑŸŒ©»É âa\g)r½aƒ¯TÕ†P»í€œý yf³39ŽSéùŽ˜hD7\Vعȫz}ª0sŠëÂ>Êçó>®Òµy%‹œ+lR]Z«€8,VÓæ9†IOz¾æ¹:kÜ“±¾óßôñ«sÛ/y/Nì·Íðk^³ë?Uô}Õ};íÿÅž…ì·½žï0ÉD-SúØ…´þV8ØùGEw¸Í6Ñ–¬Hw'€"^7†ô~¸GlL/] {ÕKj ïHƒmÿ±ÃÅK÷õå®.PýÔE¦1äþÒñtqÊš¸]ãïfvçµ´dïRž.;ï²E¾Ã—Ú¹våh?"BShgB*)Ûã«›«Ê»ÙS;Ò¨IQštØÈ§l4×-pœtV¡§ÁÉ÷h¤ûVÁ§-|•lÜG­ÚhÁ«g^Õœ(†oª öqìl.MšB¥s@±ÅN¶Y1ÃkeóuqsÔkÆ @› ‡Ó­j=t0â†0½Ï¤ÞÁ«¼«õJ;H3½:涺Ö·òÖ0bKÚÞ·›ê¬¢ÎFKêû–¶7äÎX»ñ“K¹!f,ì‡ {_cÓ%ã•õ«añÖ>ávL\ÚxX{¾(/ír–ý_qµ†ûÂ#S"«˜«zªê8˜B¯%30o¾ç7òÚw¤o2ä#™öFÔ¦®ÉÐó W­ ÈW”VøìD‰ÝEåEa­9àUxͨ§s­øÁz›¼¾& h骉”dY/ŒÄG^sL¼Bqã':-äRdÝ"E°ÞÇE˜ÁL¤ ¼Ó˜D^ Ó%dVÀ¥fÕ/Y~ÄCq_¸Ä—d8=0œœ^SÝXèæ­"®È±c´fad:³É7¨ÞP&ÎD.ê/íÔàyYEL^åVG.\¥³0½…[?zô7„ôÌXú`KNši i¦šši i¦šši i¦š Ä¿~_•¦?ñΚ?~_•¦?ñΚ:× _Ÿ·ßšÿsWj>ɹy` ©! ‘– áéiymå±1YY63%¯‰ ‰/§Èµ¼!!¼µ —iuyui.U•µµ”©3ìgÉ‘2déÛ›œ]‚ño)ÅÚEDÌõàíÜDó´÷¦£U°üÈíDÈÞj¾ÂÎ<¸þb$‰[×gƒÚÆßÙßÛûí­Þ.-MßÔOÆ¥/Ö8wÛ:£6ý…·ì>ìDbI½>ŽÕ²V4-hφF옋á#YãÃma¾ ÖˆõÂZ‹94l‘.!CꘑàñqQ‘G±«ññ‹ Ê1$HFǵ±c'ÚË—#{syy`Q ñn áè‘x•åI0¡XÎ3%¨II(gǵ£!¼ª ‰iKyKi-•Mµl¨Óë§Æ2™;{œ;£¿¨ŸJ_¬pï¶tïê'ãR—ë;í3¶c¦cvÌu÷>F$šÄ‹³&ŠuXÉ/PÞq)ŠÏ—ÂF$ŠòN)ôv¼D+»Â*‹@«Î+A‘».+a©U“ügQÌñ‘æ*`nG#MbEÙ“E:¬d—¨o8‰”ÅgËá#Ey'ú;^"ÝáE Uç ÈÝ—°ÔªÉþ3ǨæxÈó07#ü;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ^P®2ãp/jº'݉ëžÈtª  {³}ÏóÊíW¤PDíçpüܾ¹éGêß5#×ýCÛî}÷¹^ŒIT³Ãj“ªÊÁmá©3œR½|%mºHÉÁTÅ!gÑÆ¨Û«>¼>«ÛÛ­5¶+‹m<¦ß;Éãððíø|;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ^U2ãpµQåÎ>$(Úë&}5 ¢©Ž¶ Þ\/+«è#Ä/^H.&C³cB>¿¼/S%ï,#Üc }¥}Îñg¦:#¶]9îø¥ôÛw'¼½¾ô~‘ôþˆîÿýUé?/è=Éÿù§ü)­™ßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΙÛ1Ó1»f:åþ`x\IžKÕúÕ¹FŽ2Z`&y@´¯žZI‘‹ÕéÈ‘Ýzr¥“\Ï´IÑÝZno˜ SÝœîOÙÝ£»¡§ª(:ï­j^þ¢~5)~±Ã¾ÙÓ¿¨ŸJ_¬pï¶tÌnÙŽ™Û1ÖÝÃüJÈH&Oœ\ÇGi}eašÒ¶êIhÉ$¯…>ÊÖôÃ!›«H”q-.®,£TìJÛ±>ÚÊfÔ~ånnç ÔbK Fà†¾SªÇh…eäbjÑFêøI’7^I •T24fUUq/"UÝ\Vƶ؋·?bµ”=©1çÊÛÝøwõñ©KõŽöÎýDüjRýc‡}³¦cvÌtÌnÙŽ²;Õ’Ø¤Ì ŽL¾#aªú£¶—¢t6ækޏªÙ¢5è2‹/:¾Ž¼>«ÛÛ­5¶+‹m<¦ß;Éãððíø|;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇXwâVàÙ¨næ.c¦àƒ&`2ÅãI-8†Ï†ÒP+ê“Æ´|C>5e4j*ºšªÕ…MäYð`VWÃSm½¼à™’5$!22N« KËU–Ȳ²eð•ñ!2Jú|‹[Äé å­D»K¥eÕ¤¹VVËë)RD¬gÉ‘2eFôíÍÎ/‡Q?”¿XáßléßÔOÆ¥/Ö8wÛ:f7lÇLÆí˜ëÊ6Æ\nf-„SL||H0 ÿ@è5Q²  ­lÒ”2ÅEúDö‚xÀßMŒOœ9AèÕp½†lºzï-_'z?qz²[™±É—Ál5_TvÀòôN†ÜÍq×[4F½QaEà‡WÑÇLQÓÓ«º‚«cfºÛÍÄÚàÙáÇ;ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ^UŽ2ãu¸cqm‰ EãŒâs5ºb¨šÔdÚZÓ^Ù0Xâòh7hÎ,o®gA´¾—kEMc"~亸;ÛÂád¶NS.Kà…ZðsÔzx p'BEêö³¯m½\f]_ª^ZY\Øù;vÖÆuŒŸk.\íÌs¿¨ŸJ_¬pï¶tïê'ãR—ë;í3¶c¦cvÌu¶´Ö¥ïê'ãR—ë;í;ú‰øÔ¥úÇûgLÆí˜é˜Ý³m­5©{ú‰øÔ¥úÇûgNþ¢~5)~±Ã¾ÙÓ1»f:f7lÇ[kMj^þ¢~5)~±Ã¾ÙÓ¿¨ŸJ_¬pï¶tÌnÙŽ™Û1ÖÚÓZ—¿¨ŸJ_¬pï¶tïê'ãR—ë;í3¶c¦cvÌu¶´Ö¥ïê'ãR—ë;í;ú‰øÔ¥úÇûgLÆí˜é˜Ý³m­5©{ú‰øÔ¥úÇûg^½yNQkˆež¼"»íü•=¨Õ½¬Ï-zdŸ+__g"\/>ü­ÿe³Çì£looî}îÖ× 1»f:f7lÇUÌ~ý;:¿+Lã4~ý;:¿+Lã5:u´YDD n¢A½¹‡kÓ½”h–scÇÛûú˜œ~Ïggƒoƒï÷8ø÷8¾÷‡Ãï¸ø¸¸¼ãÅÅããã‚õq_ã9ë«/æuµ~~ß~kýÍ]¨ßxóÆìzÊüXÃf97oå·Yt³º‹B#Ópü:_¹^ºiHOAÞr}¹Ë„‡£ ’w“Sn!]ì, oÂ…ÿêâ¿Ær×V_ÌéÕÅŒä?®¬¿™Ö=¦ƒ!êâ¿Ær×V_ÌéÕÅŒä?®¬¿™×62élœÉ¬JÅ2jC‰Ì<ÊïÏl.h«heQ{¼/ëXæ½yc`KWyWê”v‘â‹ôðéGµàÞØ¶ôHœ<·:›Aõq_ã9ë«/ætêâ¿Ær×V_ÌëÓAõq_ã9ë«/ætêâ¿Ær×V_Ìê92O˜ŠŸ xÅT®È¼É¦ ¹½j/ÆD” r²ÛÕô7A᱕Òõ0¬ª`Rm‡”´*÷…çÞÑ[^WA•(†ÔÄ\´ Ì5µÙðºñÞœ¼ 8²\1Ó™±µQ¹Öfp¨FŒàÓØÈ±‰µÔkÀ6 õåíTáSZ>-éÑo6îi*C±ú¸¯ñœ‡õÕ—ó:uq_ã9ë«/æui Èz¸¯ñœ‡õÕ—ó:uq_ã9ë«/æui Èz¸¯ñœ‡õÕ—ó:uq_ã9ë«/æuÍà™˜f9ß8øeëmüdíw{Äzxª·¢{Î+0Ùkø~ÞŽÁ'R @—gþº¿ôeä¯ý*Ãsn'ïÐd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù:¸¯ñœ‡õÕ—ó:Ç´Ðd=\WøÎCúêËù|÷Š ¤mnìo‘^ïìoíñìïlï[ØnmomnpøðnmníñÈâàÜÛÜàâñàãàãðñáãáññáâðñðññð×…¦‚±/ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚ¦… >tó(DóEÊ”8õh†e4éªpW™ØüsB§åÂϾ´Ä2d˜T<‹ìrÐd ÅAhqš”–«|‘ËünBöÂåÚ ™ /ÄõƒaÈpZ1ÃqÒØw7…<œ±à¯Ø¼·½~š 5á€ôÎÏÜëc†DH¼5´¥£ç·ˆ™´1&$ˆÂ\§#„?Øà¶€ÀVÞ ¦.()äÈ$ –!ÁC–¯†ƒsƒ©Ö¡;,Ùë ÎÉw…øË÷?4m÷Fn^1 yJwÐØ°Ýöß,1E;µ¡&އwZgÁ…Ê`^oñ(žl¢²ý‹]«vëq; Á±6{வ„ÓvµòU§Ýw½í){vØ'Ÿn XX'Æùz¹ZUÂV.êë&m«×QhöÆÖû$„uA±)¨'ìSà {1‡±õËÚŽhc<Œt]äÓ¥YR<™Å<"&Oа¬+29h[#!˜Ãmg"¥¦Éâ¶.Ì¢câ6\Ai4‹[ eX¤#5U|ùòbDì–æ›OòuXíT7ï1¬‡q]‹øŽÏļACœÂIlxÚÇT•°Ù`“Zl@K5¥ÎDŒ‹m°—F4´”ŽŠ‘ûùôcT“±¦‚º„í Î_\Òy‰åIÁÆ=(9–„a%v:eí­º…pÑ],ØHi‹ƒÆ‘jè­@¿wư…dã‚H\¡®Wï5®j+üxÆ,"Ë"2Éù¼¥3mó†~<¬9ú(h­ÚŽŒh“¾sËSat ÚFe>;'W¨.ì¤;‚¥j̾ÜkZ˜¯êw©íîÛ5×xÓAQ"eæòï–) TVG^d® si¶3ÎÌvG6i%§.;²‰y’œÅñJó& Ýî†Á´™va‡†DƒÖbWÍjÝ‹»jg-¬ÞtÌýÙ|øýÝÿ÷^w¿ ýÄz{èc¯;þ¬÷â÷qõOÂý÷†öž‡Ñ廪ºË°ò½k«¼i ¡§0ĺõXI÷A&@U×”øUyÊpËŠø Îl  ü‰ŸŽ¯·ˆUå±$ûHÙæ´O¯ì™ù6T×±¼ú‹ „L; ›—›¿?…D™|Óù«2 'hñ<¼’–± ´KñÛ’¹A ”±?(ü´‰Œ0Òµõäìš½—Lx2›=$b\\±îê*i$+𤵗\ÓAOg±¸ÌºPã.J„´Î0†©§ŠöÛ‰xÛ¥\5Eœ¾ò^>P:–¤0D¤K/aÇ¿ wº"XQ†¹ÈêŶ-3á¡’ à3Sß‚¾9¿ãø‘Å^Qc’C ²o$‹¶N ›&nP«Ç!œ±W ÐdŸiJéØÜFUn°;WW0r©mD­QÆÝ´—EmrÎeâµVi Ë1ЙÄïL°=qý²€0PÌÈ3r4È÷ ‹R’+ó1ø C¤µ&ª…Æ%ms$ü¼dŒ8ó•Â}ðÞAs 8à¼âeó1iì>¨6É«ÆéI±f±LZÕ/KW2o(P;Õ†–×õUÆ;ÓÙ™II½rL´ëà  ££©©B627C=UðõTx•t´tµq"ÖÔÔÖźhðáÇÙ³··Ãîhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦‚±/ß§gWåiücs¦ß§gWåiücs¦§NµÃWçí÷æ¿ÜÕÚŠŒæ ›,œäQAèe9Ö>”zý©WS†Qß ¸=[x$RŽ—¸·€Œx=¿®²,µèÿ3su½‚ŠDÉWjüý¾ü×ûš»TÐG¢sO[ܘýˆ·†ï">f<ÑQPJ’Üu­t–Tl£K1=åÀ’•ŸyŽ‹ÌµR€C+½ƒ<°J™$åÈV}ˆŸ‰!? yÜÍÔù‘|ÈSÑaQ…-9r^¾I7©†ïçØÒ2÷\’iË„ã­èÑåês![bi„äÃe*¤VÛ@â…¿7°‚rk™‹bç*ã Ò ÿ×úñª×+[ô¥ B¢Ž®9¢¿ž07Ócà‘ßúͤ/G¡›âÇËWÉÙ‘ÇOfG+—⛹ñbª1pg‰!Éš‰Ê>ï )1|n» »°LwW.­’çèH6íõÄÀw©•tàŸýef€¢|×Pú€ÔÃ`¾Àªó¥k}sØÀ¸¸„<ºYVü¶tŽW*û7½Þ~K*Õ”®"‰çÇÓ?½¡)TUõÙÎ@ë˜þ¨Gd&GiÒ¿6®. z¿GÈÖq“‹)›æ|¦r…j¾Êwvbƒ½èBíN1Äò½½“Q šSˆ|޹Çü¢e’,ïv†ÔËòšëɵdÎuZüŠ ª6ø<‰ÛØKÌYm˜«l¹rû …Òƒ2öƒî¯vèK–Çkd}¡W¼G\ú0ÀÀÀA8Á?Qû?T!¡¥¡ƒëom_'ÌGêa|šÆã€ËÖ8VA¤ ׂÁÌÒcÁv¸`âÚ=©å† éEMüº:€‹Å[>›x²Âtz«UÁåwþb;5ÕIÃL‹ÞÂÌœ‹M‡­05BëîƒÉs)‘‚¶ƒÄŒ^ð.ímÒ«e†ú7 hö¸+é&.Ì®ÒÌYê®:ÕaA…ýP=uÞnfLºÅoiÑ^rÌ1I§ç¥››ËâK¶+Dþ:t–ñ®7£‡¼†iíè ¶{&53¤n2̼F7Bä¡95Ìűs•qiëýxÕ k•­‚zR†!QGWÑ_Ï鱉ðHïýfÒ£Ð͉qcå«äìÈã÷O4–@Î2C8•ŽÑ ËÉ#6Ej&“$n¼’ ÛYƒÓ¯mîªâ^D«º§²“S¿+n~Ä jÙ›±øcÏ‹¹»_ eF>1»š‹UŸœá^>ö·ßZ·Š£‘"ľBב‰{¬&†h1ËÔN1§Ö¨ã™u4µ³ˆñqà*™÷ûâJrþŠäÅLö‚[švlDåà’bmæ5Õãkm½…+ Ê j–ÆÎú ʹY†¬ê˨ðâ®`’X ƒZ¿Œ½½¸ðcx(Êmû5B à4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Ö½ÖÂjüý¾ü×ûš»Ps˃™ï¾.HóÅ6ôô(L&š‚|QçV§z¶9®•™+p‹/ Nþm"yœ-–ˆ³šeðéÉøÛ&ŒÉ–¸ÛÛÇHëJ:ÒCÁ²‘*­ëÓbXTû=õ ˜æo-² «räíøÆ)z/¼E[xÕI²TýWCXF Ôé¦ð0Kƒ¹•÷ÑÔþDov/·øÅWPOU>Èvöš„<Ãç®åÓ”Ù…‚æ –:û»ïK p.ÛÁ~UfêN’‚uvÒe§ºÃV27ŒTç•üPC<¯ñ»Ò8”Wõû]ô…ÏÌAÉÖÃ)vQ›5Ôôt…¼Tf#æì˜0É”`8?VÚVUÛŒÞÑ´•3¶£fë²h$»ô `["ì-5yë̽Žñx\i‹8¢•o¤Ú—¹…™"-ŵá˜Õ•Ì ”ªã„]Ї^Tœ Ħ¦#/’ÇtÓUK¡e Ń»Pgàèè´Ža;TŠp]¾kÊÌqy1ó kT3ËY*|ˆ$9ÞÞ””1­§á>/TѰcÅ £Ú€æµ§Ÿ[¼¼VeÄÀaVH„þÇÆO†U»ƒz²Œpà=š!:¸„¨Ì ’kÁrÁ\1À/˜kƒù|;Û0KJï¼*¬nh·gîÑÞ\WNÂ1“ ±—;£#!xî8ßc¸ o̘ K0ÎG™ãã¹6g¶ Žd~Ê]Õ´Jë2iPo‰‹ˆaAx^Oamƒ´ùŽa’SÞ¯¹®Nš÷$ìo¼÷ý½¦¸…?Ìs ŸL‘…R­ÉÔDììv¦Òjñª(¶xö2û€q·îøå1 PdBØxîȺì©ÉçÞг*æF*lî"vö¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šhi¦¦šh+ýúvu~V˜ÿÆ7:hýúvu~V˜ÿÆ7:jtë\5~~ß~kýÍ]ªŸƒ`72TÔü³|ã]û#Œy˜ó&´WU°Ô Yˆ9ø6˜£~Xnx;øâ^#žI”VGð/¬6Ä HתzÞÈX†àøhRÞØ _Ÿ·ßšÿsWk^ê… —9¹8dÖâ‡.=$CüØ;!Ê9q†dÌv"ÿnÕÏU€ÊàÊ“Šk™û±ºPâooöE+¬N…V¡—æwpgíN ñ²!¤íå¾ÚÝãv~\rœö <“JS"2‡™YžA2rîÕV±*\‡ý†@Ѧ{SxE~‹Lx‡ñ ʯ„…‹Í«±~%@Ðôùé ©sGù¤»9tóMJ^‡;ìbd!Æ"”aÎ-d¾Z¬ò1έµ7R°rš‹c$.í(íw•{Ô(“ÆÖÑ ªÆi@« âÞ{a=Ü\ÿ-Ÿ½×Fÿ—Ÿ’ËÝǸ=B+ôÏïiÜÞé?\ë˜ÿ†ú‡¦ºWÿ†úç«ÿÈjStÐE–t]fo&½|/Ëá!Ì?˜ N»Y_š*…4ù"}¼X¶ëhM@H$°€'¡ ”ßB.fïyð uó2%¼9Zfšo—Æ4Õ)–tf¬´?6•ç30|—\{Љ*ë;ÍÚÌ']dK#~È@–ðA Y³~ØÈ•©%Û^ðw…ŠIÃQfÔµ¶š —ežsÉ Î|ä0q¥IóËäº ;δ­Å©-V9Úñ0ëŠ/< ê†*£H<¦²¶Þ Ú3ð½Q1݃”lB¹„Ëqs³9šr•È0ß[Pc'¿—{˺„V·¢{΀ Zþ·¼€NIÔ„ð%Ö„ioýÙyÛÿJ¯ÜÛ—Ç)ºh*]‹XiÍz¿8°w ó $pļÅ~X:þ½LÞª}Ðå¸ëTPm،ƃsæ0¤#†Ö/iWÌ“  ¹£H{ëÀÛñÞå±ùŇžï˜m‹I¼]ÄC‡‰å0R íÝó2©‹Þûq”ž9D§ßa¢Ýþ2ß±oK‰îƒ ­‡Ÿt[Ga7Ó禂°<¢¹r;qˆ“‚2_/;‡7™wS4­9€–š$¡³çØWÑÛc6$UÕÒÞ;*ί©ÇT(˜B@•ò2k÷9>ÚØzÏÚi i¦šši i¦šši i¦šši i¦šši i¦šši i¦š Ä¿~_•¦?ñΚ?~_•¦?ñΚ:× _Ÿ·ßšÿsWjV<Íæ$çξÉe_¹®<âc½µ†Ê>„Fª˜sü‘\Š­úùŽùïmsl"É o2۵ >Ô4EKæuñBîÜJ§Ö§ù«óöûó_îjíAÍV"æÖ"¹òðÛnñdéA˜goýä†IÙ6–½ÊòÑP*‹Öõ;( iÚNòm“Ó3“—pżˆexÄ6¿ˆ£rÎ… V—ç)K+Šó<ò[Èg™‰¿*Æœ\JZ¯dä-Ù%ùr°6ìÒùÎZ¬Þ_ÆÛ™Ã_Gtà¾9⵪OØðK¦‡¼Íîq3Ô•*+È95Šm5Ò¡ÓŽù#F7^I3ÎÔT4†Îq÷]<‚¥cHB~Ôä{~Î>ž`'yU.ÈPi­$¹‚á³' 1C—ÈJåŽêËÖç?DžG;٢˅³ƒ+Ü3¶ôL¨IA_oÂ#y%è‰`ò–]l=êy÷ã´u„7röøû ÛÊÛ“8éÍ>S-˜¬Ë^e÷ˆ›y`¼e¥˜è¤Ûº=Ìp_l•ߎ 2Ëï ÆÅ¶!»œ[´"Ý”îÙ#6àðU†ï,æp¶Ì¶NÛg"ÕàŠ^RÍ,Ü8ÂÂ/O¬ÙT¿‰G,Úò o‡R,šdB\Tc)8²üCvõ%dL1Ó¿ qjŸw>nت®±¬ÆÜÞ —s‹4Ù·OE:Sk/8ƒåï;â÷Í€B¦ñeh¸¹”wr-1¨fL¸ŒÐŸ Æ8q忆ùåÑ–¹Yÿ+)ÇJ‹GÇ%÷÷/ˆ££×l½˜îÖӀрÁ"mE”‚U`(y3sohtµ€IIloUkª²`Cz³ä‹ÉÇd‡ÿË©òEüä<ÿ¼ã·Ñ¯Ð‡þdùùÿ¦º§ÙÏ)%yÞ.<‘*wä*ÅÊÈ1–¸¼¸M Å*˜L\¢ {Ó>_NDÁ½!ÆØEþÌ{aÕHˆd`ÈS‰¶ˆä³¼!MmóŸFl÷*®÷2œtá”é $¦ܪǢ¾ìe{ÏÕäW#­UÆE›cÏÂ΢ŸzáßñÊ Oçj &Æ8¶‚+½Ëùis N+›¸ÆÏÅ‘ÇR¯’–¹ Í‹oCDüs‚3àTì©í"ZU¯*Êç,¬ÈkldÍdì Æ:SË Ý½¹áµyIdÏ/Œqú·Tñð“"Òy ” k>z§ÈéãmYñLž•i‹x÷h/F{hÑ·3¹€ n6a½cz¸¬QˆoÓÙS„Ðâ^]-³ 1†PHpxœw³±ÅƸcÖÐÂ3Y¹Ôv±ëŒngœ/ý”K;ÚâÙá¨¬ê«Ø;<7›w‘néªkÞçÌÌܣȼåLdG0;ÎWŒ»6™=O+èÍ\dCBÀæÒI¸I¶LW•le“zA ሇHp³#Ébï%XÌJˆÔ#̲Kl^O¦£ jr1²´î¡m šg&ÑU˜J¾ž§°ÞHŒ‚Ê :Cy§ÒÔ~-}µr‚Æ÷ ª¥ÕuXœ;›èéÉÜHæÉcyo‹$í pâVL4äp1^GûnÜuÇC8ø®‚…Ó ÀªE£¦‡$Þ-Ç6yƒvÞájïx¤êÊyÈäd˜wÒË.¿ÌŠû´Ÿæ÷Ü„O.š¤k*ßòÝóòhæ‘}pTKÜï¤ïTž'ZFóÈJ¸%ê1W®=Ï/î”ørÙIæ¬|ç£Ë dZýv–§e6%ÏÄ=ë(FÃ7€KãòkNÃ[Jï2ø‰†âlËá"h¬„+H©|=þ\9#Ù‰Šoì->HZ/|º‡yh›QeÉä£1å²øž)BéÔ-¼¨®¨£jD¼Ø¥µ5\[q¤èJ*ƒm襴¢'4†ò‹ÉsùzØÙ!iòpü£½ïéRCÉÝUïÕ=µíW«­hýsÐýr'\õwCzg³‘èM÷›~ØžfY áÌÜñ(:Sæòçp­!‹ÆÁ8~F¹Ïo² UnUEò½ Ürd7¼êܶŽõ]@¤R±¶ß1«JZ+{%… $Bco~f(5CÁ§om…± âà*ÄHSÓìÅðZŒ¶q«îƒmד­/Vibé UùFö@Ú_ø.H@¯èJrDê… vé¨ÎFf”ù¹jÀK[j<´—Ë9}šVY¬3z7J6퟾˨K̶T†ÒÙˆTѲdqn6joEÖp ]G£¥—Wµ÷sˆA¹ã0šª~\†Jl¼f2ùŒQçL€tØöGQO$Ãë¸U•2Y@btl)\6DÄ3åÏ] ð[Lm’C¨! éªÀ¤²Ï4ïssšs§ Óמ6˜)Ž˜–V¼Ä!n`<`ªt¹#u JrF*Á¶ºˆ‹Ä¦¸FLæB¼< g ·—•uˆ˜úº«JžÂ[óÂAÊ[gãË^—×e'šâ“Š6^&•YC±Æª®K³ã‚'%ÞœMaíÚ* )ˆÂEÃж«eÜ1ühøŠ¬Bo4Ô/™óP{cÆ å–Jæ·.¶ž4—ãMЄqo\éX:œð;ªõäq·¸Txƒt·”¬¸›Ñ;Ã6äŠõí¸Aü“‰¢~;¿ù æû *T‘i›eø©x xs¸9ŽŒQ·h4ÒáKe»“lKiox?h:d ˜¹jîŽ.Íi1‰¶°‡‚LtÔ!ð[²s§šN^ã™3½Þ¢ÅÞ^Á¹·90Œe_'mrÏ‘«6YüfQ£ÑE¸º}  ÝGñH1$Š˜™Š2-­ámTÙÞrÍg2?.5·7Öäã:þK³Œ-ÜU3KEVì“ôÆbP®h–¬U…߯œ&=¥¥Éc¼Ž 9SÖúê}Å@?ü¾ÎÀY‹MBFó.sŒ-¹ƒ&¶R¾í¹¨‹ÂÜÔ@Ó—1ÅX”$øÝµC2¯Í,Œ< Š<ïGœF½6Ç2вP2vHå8©”š+µrŒi–Y¿-®@2;Œâ­‡•i Ž8ó¨ì“\˜lÕUá*•Ü\§Bû³Ñ–^^^[«CIªÃ1ü«ÇÄ„xý™ÓÐ)‚ÅzjºˆÞy®|ƒ¡Áé|¾}‘?0^þÑãý=þWŠ×Pø•c#&†­ÆBlGG>Àm 6 žPsËdVÕÏ~É\*¨±ÆÀbÉxå:–œÌ!¼ùÄž[ ^/ªÛ´w’%Ïmg2qû—O2ì”Àl÷w´¬ÝøçÁ)›5÷×9_ËøÀÜl=¼§»ãÈ÷ ;«ÖÉì«´CþË`Haí;°ÇI¾ujÀ „é¨'Ì~rD˜Ts(ÓJã¥KÊ‹Yy”{P[š“×Ê{q±fà:ý+ŽŒ‚,_ê÷¶E³ãŒ\C\\¨P+÷ ðUÒpxͳ¯Î,9°°«†'á•ãæý×Ë8+™2ßtÅî ŽÞÛ6-㧨UŸìYÕŒÞXÕð§§&¾?¸Ø)$©Tqœ>@Bh4×:bVR)óW™@—y-hÚ£™mG¶MK¼>IQ>–îÔP¬d†«srL}›Á"úá{iöCvê$X‹‘ ˪¼°è½M4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4Öl 5¢ÂÒ„¹v¡ÑM²Û“‡ƒsÙoÇ߉µÁÇ¿³Å·ÇÅ"? Ž=ÍÝž-íß¼áàÛßÚññÿŽs4j¬ºÄ&!•Ñt udTÒIaÕîlÖÉØŸr-±?zú‡osbⳋð¬û\|s6|®ü­ÝýЬK÷éÙÕùZcÿÜé£÷éÙÕùZcÿÜé©Ó­pÕùû}ù¯÷5v u­Ë;/˜“òyu[Í)§Y‰YfÓ¹-a&ŽÎ6ÀR’7z.ñÇD›õ€m:­b¬8«%™TŶò_dhˆ7ƒv BÁ³;JŒ¨¾žŽð˜{n©o?€obØR¨š¥œ3*|7’¼òh­Q™™iy–qù„«ƒY2E269âlc%Ϥ¢ž´/ܣܬ²[­Øû&¬ h'›‚¤jkØÓA æ|«ÞÙˆ9eY­ÌQ§’Åù-F´dW%– pdĹŽëAy m"XÝÕåÓ.^ô—A6ñ5A#A{PØ@=)g‡}bòŸ&–E6ÊnáËåžé\PQÄHUІ21¹}"4ÔWW€)FºˆÄ.±.¼sZ²KM¸¨',×›¡+ÀI„ÓAx±É·Ý£äªÿ1½kòe{òò‡§;ÛïŸÔ?ú¡}ÛnÛz÷þ}ë)ÿ…½¿ýŽïÁÞ_n|La>åÿ­¨1“ÞO½â>ïâµ¾ô}ç*-6Zþ·4-'IvHœ¶]ŸøFêÿ¹>ËÉ_úU~æÜHÒ›¦ƒˆrã_ŽÓ-޼Ã{™g@uÏ OaAHïÛ°¿ȺêÁN:J¨Ö paÏTÛ(/ÈC¦Ø¯M:bV-©ð«˜¾‰yh¥£™SG¸Mu¼@Io>êîÔ¬¬˜†×sn4}ëÂÒûëâ‹hôõô£uóíäW Ī£¯è½4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMT›_òÚj[I3‹¦Šq_Á㓵mG_s&ÝÅ ˆ’áoA%Ú¨Û¶3oã½»±C½[{*ºî-nõ–·\×ïDƒÅÇeeÅá$”®Ó†ÄÀÒÛŠLÙÒoLH÷vøl/íåØYÙMãß—¹ã±r|ŠØÐ`û(›yÞš Ä¿~_•¦?ñΚ?~_•¦?ñΚ:Ñ®qËFQ$îSpÃÑÿáP1)3·GÙPUìÿÈð£Loø}¿Žß™“çÈìã3zGŒ_) Æ4º¿ w¾1¾ÿNÇíŸ[í«óöûó_îjíkÝQ¶ý•ûoÙ`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lút÷Æ7ßéØñý³ë9ÓL}ìßË™1÷³.eƒt÷Æ7ßéØñý³éÐ;ßß§cÇöϬçM1÷³.dÇÞÍü¹– Ð;ßß§cÇöϧ@ï|c}þÛ>³4ÇÞÍü¹“{7òæX7@ï|c}þÛ>½ñ÷úv<lúÎtÓ{7òæL}ìßË™`ݽñ÷úv<lúôª¼*§íOÇpíìmÊðð¦#ž—𥕻½b?ÿd@­÷Ü9»S¶ö«È+8··£mmoïqÅãߨÝÉôÓ{7òæL}ìßË™V%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖ¸jüý¾ü×ûš»Uå““ÑYÓÍYlçb+1ÅÑŸ\ÍYë;SSÁ°yáŒF6U^do†ÝøÕ_í¢5äº;à°âeÌÙÆ–yªŠy—Å{Öøjüý¾ü×ûš»PáoÊ ÎõYE»¾ìaù›Ì¬ð1ÞˆÒ˜}’ç¡Üo­¨/Vua6 b‚àñ*\{»}=lÎ6²aŸph n… êb×1æ=UsûæNj"rß+åXó^ï_É’"–„’掄˜ÐùÙ¼Œ!}x*MZV¶%²Â$»‹k „ðÈHÖ¬fòƯ†à*âÛb‡z|°bÒñÍ©£ßJÜ׸þÃDD ê±Ð˜O¢AÂz>Å)l¡ÜŒ³3Æã5œnêV>;ŽÃÙí9ŸØÇàœ=‚ªW¡+jk€{‹á›P®§6<ºd·¹eó’ÄWõ G†Ca Æ@3`§ëo¨“ U¶A¿ÔlÔa`À™¡)Yºüâ0D.:FÂúԔꆄª»‚È=š]QãbLKy‹»hY|ôCa‹+7*ùdc¢º†ß“H[Ç<´û˜›ˆ-ÝÝ£}˜÷Ôq‹Ä«kkcÅŸ²7¿:«)–››¶™×(¼nfã.Nc‘ù³¼²ó2Ž9-“—$€r²i£|À:^@œWâµá^„." S¯— !xúÙ~¿à±­¤¼¼¼!±=ùH ÞÎ|—to7²Q/1Ò‘™>špF[9*¨wÂéìÄÈï+Žèö¨«©üEÉ(.èi- Wwȃ`#¨Û›¦mqôŒuÀN,Æó<ƒ(9º\ ¶¦ú;&›´( ¢e@ê@‚O!€nä¨Rø'ªåµlYLß즙™ºƒœHǵfN~'Rôv<žÉyÉ'Ô§ƒ–¢ h†f;!øäÌ<3à)ˆÇ8 ^q/¬I[ÂË…]žÑ5Z¼â~’ö?o|‘xÝøìïÿÝeòEüäÿ»wã·Ñ¯Óþdù‡ÿ¦º÷yPâý õå­ƒLÖ®—–uO* ÒbÊxƒe¸¿]><É–2ƒE„‹ã4ï£ìîU[ ŒÓìÀ—#rŒZ–Ó†-”`çNY\Àòó,!ÔdçŸP2°…_“õY#‰yG‹Ë`g9%õT# c‰tþ#bŒd/ü ‡Í‚] á±R*;ùtcå5óøìÅfó\ …¼¿ÆðžM0îLfÈlAYD—Zä+šH2½{DItO±\( ¶³¼â‘m~¹í!¡È‚ôXUX¿$ZUî Êï­M4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4ÐV%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖ¸jüý¾ü×ûš»\œåɬnÇ>œ÷ƒÈ4‚'¬}c¤{Ê×XuWOz_¯ôç[_Ñúç¡úå/¬zgšôÏX«ó¾ÃÔ"{n±jüý¾ü×ûš»UÊ劲[7rk1æE¯‚ òˆƒ7›âwŽ'CÄg'ã¯×”ØÌr¸³±"A¨¼¨™½\CÆ/·#j… Þ–Þ1÷D*ìjhPŸ=5M¤>Cä^5b s†lŠ5¢4³î‘Êp£Jí—´ŽU9&1 Omká Þ\Ê…~íVOkîïHg 6á1®÷ªDÝÜuž”Îko‡±®s¨Â—bñ•iËý§‚´¯M¡e€Q&@©ò¹ŒÁ V»‚G¶Ä ^$¤M‰³¼ÉIì¨7™³ÃgO«Úa2‚ÝÝÍ[w'³]ÁîÿDw7µ]YCÜžÛz÷J÷¡¼ÿSôGSÿ‡:³Òý׿ùÿPÿ—ÖoªÎåuߌ™ß•cÃÍ~à&>çS%2 AøÇIbÎãóu¢)‘§–Ò®X EÿòÕ1ë”1êa(l¤ÒA&&¿8“pSk˳‹™¥UuwŽnz,¾>A”ÜàÈoFñ±³kºÉ c‹Ô§D¶I„‹(ǯ/ìw­é1Ýñšôš 'ƒ׌Xà`ám.æ­»“Ù®à„w¢;›Ú®¬¡îOm½{¥{ƒÐÞ©ú#©ÿÃYé~ƒëßüÿ¨Ëë7ÕgU™2yyÞ•.>h„bäF§Üê%óô\+ñº ÍM}}‘¢FŒ-Êg>C«w”IT{—‘,WìKò¥µVüãn*èŒ8qOàé àæ<7ŠÜ™®u;ïœÄ¹‹b¦9b˜ ?‰•yš´Å’ >"& Íôò?wÝùiºMf²­c‚$Š«±;H-ée’˜ƒama †jÙÆLÇQ0B‹Â?QéãÅÁe Àeï¤Z΢¶ôb™ö”vž—yWeMcägoù+ZéÕÒ}”¸’6vøó—u¶nX©Ú0óœfò„¾‡"Úõ(ÛSymæÁ®/ïoRÞ(IxÈCtˆÓ‰Áu~I}Z%OŲ%]+§¤È“¼VM]GñÛË#{™‡+5qMC_+ZksîNAT5e¡Û|Á[KÆòíKtÁáZcU5p’l¥8‰o’8äMï ;z#Â݈jÙÆLÇQ0B‹Â?QéãÅÁe Àeï¤Z΢¶ôb™ö”vž—yWeMcägoù+ZéÕÒ}”¸’6v׬հ±˜à™‚8ÃjuGlïK(j ØýU³zkÐböãÞô…ˆ÷%=ǧê·ölm¼¤MÞ î('¥¥{(¸·É#^4x§V幓&¹> ˆX’6ÎkËeãÅ-fÊy‡‰~ FJç²°ÉWu§Œ³J|ÐjcµÍ¥‘.ÿ–„IžùS÷3`dF^Ò£æß¬hf|ùã{$‹ÔߺòØ{Æ×‡ŠÒºŒšÐ*Q=Hõ”Û¹âð.#Ì&*‘U¸Ij¶ÓUeMóÌÒ¾Y|•2ýÉçÛùmÍ5UŽ9]ÛÅT^à& ù,tè£ yÑ…øgP„Ò•FôŸ;óbÂ}œ¹º°³=ù’ÙÏdÌËj1H÷ßtÒå$®ª±Ç5!DÚŒ6KF6vI¹ã’Ñ‹x‡´Þ2KÕmYïM$§7Šÿ$~ -ݺj©$Ü̳r‡Bêo Yt¿tmʆµ¸2†‰‘e¸û]w ¶€õi•8–%FÈ»è;jú’µˆÊf’\{ ÁjRNLHÓy˺Û7,TíyÎ3yB_C‘mz”m©¼„6ó`×÷·©o$μd!ºFÄiÄ຿ $޾­§âÙ®•ÓÒdIÞ+&úÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4ÓAX—ïÓ³«ò´Çþ1¹ÓGïÓ³«ò´Çþ1¹ÓS§Zá«óöûó_îjíFû×—di™#˜›òì3‚e“(ñVÃj LÛ«bú¡*+õó¨¡ rµ¼t„J£¦Œ&Õœ_CSUOµ]QIvdÉWçí÷æ¿ÜÕڈƇ8N^ òG°Á“ÖòLŒa¼Èr.G7©’BÙþÃÃÌFšDj´¼±$á”ÃSdY³>1Í]à,ÈñËèn© P¡«9‹r± Ëd âÚˆ ³Ç”®o(^m…tkTðe²ž3R3˜-qZžàôsƒnæYKƒáp&4«[+›©&t–ü{s·û ¿ñ:3ñGq'Gzv^–8FÌo N‰G,¾RvIûDÐŽù®ZÓÞ¿UoNÒ¼7œÂž8! P–—Œ4WÆŸ©†I†ÍFÇŒƒHhËD hêI… Æm _ “ ß@kFB=yU"]]ÕÕ\¸¶U6Õ²¤À±&<Èr7£ïmîq{š!ÞådžR-J/d&ý½áÆ,žay­Îó «»j_MC;Ö;mÁ\½ª'DzÛ*Y†ìðˆ-¨í¤V m•­ÁhÇÖÐʪ£ÛÚµ*Ò¦Óù8ðËàßÿ[ß(çÒWþù¿>|ÿöóè«ÿ#kwãŽG&2Ù0xøeܨzD»§Š…=[¥ ¯oÿQ“ÀòãwUŸ„éay¯%çayšù1%ï±Ç#“l˜ È<|2îÔ="]ÓÅBž­Ò…W7ÿ€ ¨ÆÉàyq»ªÏÂt°¼×’ó°¼Í|˜’÷à ù^`s%NèHãÕJÓ r,“-Z4vŬmùöy_½]¸HÓ+ð1á/[^[G¬Û§‘ i|!IÂ7`B-±U´6RKUmÑhqLce¨D7¤èÈÎ ¥ó¬HJŽ ÏY'Ö¼w&,;þð¥†Ç8 —ų³8°è ‚ûƪºš‹j~Õ=tÞG&nt6>z#&û£Ùž*²ënÌ Ã6e~¨£ž07ÓcâYÿ‹®¨=cÚù*U°Û܉Á»ô 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4 4Ó@ÓM4‰~ý;:¿+Lã4~ý;:¿+Lã5:u®¿?o¿5þæ®Õ;2LŽU\˲{—Ÿ0„:ú§{æ»>ylgDchl¼ÒE¡ôœGCM…ؘ· :|F£‡‘Æg¸wÄ,;]%>öQ4 KÈ tÃoHc¦]å´]¹[5öÓ*ÍÜÁæbÎÅ ÄÀëc‹…:‰NHD6×Ã/3âH‚¼Ã5¢É>ÛÈñà€ÏÞn•äé“0%¥£ÆÓ@(Ä’¤‘ˆd®N«ÅíëÎfÉX øH8‘ IÃ>òׄ…‰x;Q]hkyÃhLIeÃlK*΄òÉž<Å´ýÉ ”bJ…°Lù£N«)^F´qÆLœõ+á*æÁhÜM‘èÑG‰˜°ê6Kï¨ãGØSkq.ÎÈÈöÖÜ~ ZÞÁF·8"¸•oÝLjpqÄÃÍ5ø"]‘-âþ£W.3#x/Î%¬ ™7”gÇ÷…5&Ù~2@ÞÝêúâæLˆ…1+ìl…ñl!ùá2±Ã%²-ʘjòΠÊò!Óe‹‘íM’“sÊ–°¸¨êjÔTe5~$¥ëuuxŠÃdÂmpØhòü9L º–’¬eÆã®êõ¶>$ {íÐÝïê¥@y;aåûkÝ_W —Ü>ÞyH ÕÞ±Ò^V? z°ÛûÜã¶Knä÷—·ÁßèŽÙwW¤è{“Ûo^ê®ßuÏê~ˆêñIú§ ú÷á!êó^|“ «ùúâvDÑЪX ÒKá¼ÃëhÆãæžóìbS6¹w[.Dî‹LáJ Äo&—ZÅn„ªþLPß=ÉFo­çÇ:"°|€Â’}“ÆÉ¢Î’ô ø²nߥ§‘ËŸM`hïV¨ÉF)Ù´œ–IŽž´SÙ“ÀÞÛ³d¶q†\®«à†¢ðÓº„ Ž'Bp{é°oj}d\𥧥ÞUÖÜ×yè;þJÖº Œoe.$}í½ ÓÄÕ±Nº°ÑEBKÆ¢AК‚¸^PÔ.;Ì0[MlGL¸Ý£‘åï ì‹,iàÌ¡ê ]ùÛ’m"K²‘cÂ…îFMÓG”²ðC,]ù^;Ì3—Sߘ=ëÚù‡j”í †®¬ÞF¬´3ÅUÉŽ&”2©ï‡{ˆf³º¸O™4$.Y½÷44‹Ú~Wˆ™T¦–,²š3ÒcÐkgÉ|Q¾¤ÉáùÊlˆÎäA5Fc DÖ‹eàhT‘ ‘‚’A™³`Jná:KR@ åp²œ¾X¦l¶@TÂJÒGÉ"´K€w…ˆÄáà—iuyui,—‡„”ª}\ò«Ï Éò'ÏŸ7¢ÂVKeŸWvá|¿îÅû4ó¢DèE:Ù’Wå:¡‚]èP u!Á'ƒëå—>vúãÉDõò|¶ÏÞDs"ñ)ÛÌ3– […§{#ž L9»†&KºC‚ü‘ú[¼1ÌÖ ¸ëh!%-*Ò'Œ½èËñWDôÂ'Œ‹gd_mtY?¾ž#ý•ø±ËÓ'ø•I.VFLø%ÓîÐÉm¹ÐÐüÓ d=vÈÕA_»n<íxäÕúÈ2(ج;혌瘙‚žž˜R¶}/VKb“0692ø †«êŽØ^‰ÐÛ™®:â«fˆ× Ê, H¼êú8ñéŠ:zuwPUll×[y¸›\<>u’ȸ!¯”ê±Ú!Yyš´Qº¾d×’BeU † •EÕ\KÈ•wW±­¶"íÏØmejG yò¶÷B°(óó(òî]ßY9Uén¦(G5›‰$ªªªÑ›#Àl~™ÞàØ‰º‹ÊFWž…V}Õ~¾ MJiESHcæs²JùeòûüÄ8$Èfg8UªÉç÷ù}pç`- ?Ýf¾lĺI¹XD †©ÄÌ<ý aSdÿªÀà¨$ ó· ½Y-ŠLÀØäËà‚6¯ª;`yz'Cnf¸ëŠ­š#^ƒ(°"ðC«èãǦ(ééÕÝAU±³]mæâmplðê¸ø‰Q -Œ¢âæ:F/¾i<ï 㤖›$—NÑ)äÖ¢Ž+kͱžK˜Í¡©•ód­âÚYå¤Ó+mãH¾µÜ–.,geDöM”l×Ì! º~irجÛw\E€®Å÷(Ù(¡ÅÚªÞÕ\KÈ•wT2•³Ká˜ÓãÙ Ñ–;ЪKîY‡¾ã722EŠ ?xÓˆá?tÆY‚=TÍÈãÅô,2™=—ÚfjÿŠò~Þ±,|õA#TQmÁ>‹Ö®àtl›hû²ãwÿ§Ä‡Ó¼×Ñ@ýäýAÿüé¿ÿUþ~ûþ–8ËÖáŒuŶ>$-Ž3‰ÌÖ芠hcQ“ikM{dÁc‹É Ý£88±¼¹œXMÒú]­5Œ‰û’êàïlò¸§v‹©ßᯠˆVd  ~a=©Aà¬ò(·+'ã²÷xjö³Ú¯&@‹\Ŧš¿¹&­·ÜkE°9„7d)tºú½ªš 1Ö¸Y-“”Ë…ø!V¼õž\ Ѓ†Qz½¬ëÛoFWGWê—––W6>Fǵ±c'ÚË—#{s7Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4Ð4ÓMM4ÐV%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖ¸jüý¾ü×ûš»PrÀç2¡÷ż ÅLÞ|+0DâÅq‘Žäú¹]º¶3ö{LJa–C¹nÃ<í,¿7ÂØ±¶ª¡‡ÀÄ¿Yr2uy8Í_Ÿ·ßšÿsWj–™ˆñÁÕãŸ6XXîÊ~[¼×Ã÷Ë (Å©=0Çåð­·ŠT‚Óvª[KÆðC¾&Ñ´$Óš‘†K¾ôÙ£µ%dª÷Ï(P¶’ÉŽã[/›«‹ž£^5Øàd>kQ롇0 …î}&ö ]å_ªQÚAé×5µÖ°½¿–±ƒ^Öô}¼ßTÚÏpâG.Z½nrÀŽ©ÏC÷),æë!oGq?yz'‘tŒ³;x<5…ä£gk\é¤ ¸Ä÷l*AÑ ˜Ý”–9ÅC G› Œ‚©­Ä •ì•û˜,»Ÿ¹$›fî{Ó˜;%ÁtV:ûnÚ¶m¬ÆØ9¬¶]ôZÓôËjÁ‘²IÁ»2i—<ä¾½ãÞÞôú‡ý ÷YìO¹ß» ÿÒ_^éÿrú£Õú º9¤b‚srŸ+#Ûœ5˜j/jeÀdȦtNz†ýpFM\Ð’´£$黯XÌ«’-ñYµ\s·Ç¯.åÄñƒ¹"º Æ@+iî\?t"*¶ÈaŽbÆ»#qê’ñ† À°îû,ðh…./ÆM\%·‰›Œ^²¸¡jU ¨¨‰êÆöÃS°…K¯q‹î‚ÙKDmuà8#—”µ͸5ÂnrGœíÊèJê×÷‰i%ô‚Öžð„iÛwŒÝùŤ䅌C²k{s¶sœ%7(óiOФ‰…±ãM¢òÉ Ë‘ì~C%Á·ŠØMyâSÃöäW\^OTÑ®h ›“6YkѺ`j²Bi\3¶8¹›J|ª$s­‡Gjç–7ÞSd Ð ¼(ÂTO-ža´"ÆâŽyZ Ú@<ì ™LËa ܃Z q[Eྃ±Ç9FC9Ǧ3ßò—[¸ s„·Žª±’Keî=¶"e({P&Mvêv„ÊÆdƒšð!ÍÅü½ÃŸ>©€,KjgˆrD†a»y¶g:B=åÖ*¨¹ä®Ѻ­I*W¹Ø–Zíc‘ã1®åN胅X³ |¾;9§¿‰³¶sáYÒÐ B六µ¤1Ç#“l˜ È<|2îÔ="]ÓÅBž­Ò…W7ÿ€ ¨ÆÉàyq»ªÏÂt°¼×’ó°¼Í|˜’÷êËË/³6+š,)ÿª€d|ºŠÖ\îi¦uQÂþö†¡CÛŒy_d•s›Õí*ßUn04ð6Îû&2×p‹†ÀÚÂh‚pvûëîl„Ôá¼*–Ô`ù4-xËˉ[JÝáÁÈÖGd-hZÙÜeÆ5Y"Ù¦¶áÛÜÞV•ÞNa)Á‹Ámo……ÀS ÂSq‡8YEŽ—¹/U½x›¼k ¹ÅÛ‚KÖ<’%nîj˜£ÙG´‚­Kx;WQ¶kgRW}}@5Ýäz¨ö\;{Y¾%d˜Þ`㢳%Ã@ÚkaõÂaAG@¼æß Ý­U Ué5_ ­]tSP‹jÛë8€Ä#dpäy{m½¾ Àç¦;¿Y‰<ºñÒ)ÅZƒî€N˜ô,šfôšZ¬[3W“îs'¹‚­¿:Þ°lwaA½ å]ÀV‘ª5 '®D‰A7¯ „5©óÕqŒ©Ì¯ÆµzÓtç&%_.£õÂxÊÅn˜¢Ì@xw#'£ŸÄ¯×,å]-±'Ý׸ô‡~óyN¢ÄP>‰­¡²ô–KŸ¨:^ì»×IFü€D›ëöTÞ¿}ÚÄôá«_i½ì8ó“Šñz»ÇG4UGQ䪠£0²ÌñnŽ9Aã¢Ófîî£lÁ9Š…†L»Üt eÁ7˜` 2$SÙÝßVÒ]Ü_ÓÚ͇·Ï3ï2˜¢W”aW‹<Ñç@™&xaO s“VÂo °ZD'ÛÒ–`²+hÇD E o-­G) Ulñ1)väXÍI¶÷„‚ݺjŠ‘€uÜÊå_ÇÆRâ„•í{x·Éù5µ„¾`¨¢< ssh17W‹|!sDaŒ„â½Hˆ”q~r°ˆ=:à2wÇo û½|¨ ß” ÞŸåTùE |ž¨ïŸ¯|=`¾íHôùR÷YèþûÔúïøß¶ÞóoÿZ=OAmrÊŸ.–Î<šË\S¤8‚ÃÃ^Ãw>æö¶†(eï¼:þÉŽÐv5ä¶—–ž—GW")GPŽ‹ù+^=ŠŸ[‰ÅÇ;n¬¹AÜžäçg«uÇ˵ò‹.~J?cëÝÉ÷%õïÉv[ÓÿèOºÏb}ñ=ç½{þ’ú÷P{ìÕׇ˜8­/˜?“&øõ䜥¡V`¸Ï/R±j—&ó —-KqÄJÕ4<‡¼UÇâã®È²gRRÈ ¦®VË.èI±2ž<”FnD v÷·üÈû¸ößô!ÞÞüôùnùùУî«}7ÿã.ô?˜âVÿòzÝú«/®¿¹‘u3Ä á©”CŸrË뮂ȢH;%Žü¨|zƒ |k»2%ˆ°ãÛ ”$cïɾ±lµÙÝ݉KÁÅxÄîW^Ueœ…²At q}ΦL¯,Whs{T7™ˆ à>7NZðºLK ÀÊ|{P3l­Œ2 1 =⸿Œ†LxUòI//ôÓUÅ´ºõ–_s0ËSW^åfº†rD–!¹Í„÷`Ø­ ƒÌ_ ’K(ä´`¥ä\;53ö7 ‡ªcÖ‚%”CaíÐ4ÓMM4Ð4ÓMM4ÐV%ûôìêü­1ÿŒntÑûôìêü­1ÿŒntÔéÖux·”âí"Š"fzðvî¢yÚ{ÓQª‹X~dv¢do5_ag\1FÄ­k³ÁícoìïíýöÖï¦ïê'ãR—ë;í@&UÿÞ‡$/nÿØdZКÓüŸêÜßîŸäÿVæÿlíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöεc̃r$âC=ÀkªÆ ˆ®Èe ¿„I^6É· ¼œ=2×zê®%äJ»©[õ2l©í lOÛ»2¶|~È»µÜÓO9Õ¹±íç:·6=ØAŒ¸ü’N¡ƒ^à6b %bùD)dLÐ_Í$°[ TÑÎ!™U½KW.ò]],]ûi5´õ07çîH݇[?Ü]­§ßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöÎýDüjRýc‡}³ªÄé§œêÜØöó[›ìíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöÎýDüjRýc‡}³ªÄé§œêÜØöó[›ìíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±îÎÝýDüjRýc‡}³§Q?”¿Xáßlê±:iç:·6=¼çVæÇ»;wõñ©KõŽöÎýDüjRýc‡}³ªÄé§œêÜØöó[›ìíßÔOÆ¥/Ö8wÛ:wõñ©KõŽöΫ¦žs«scÛÎunl{³·Q?”¿XáßléßÔOÆ¥/Ö8wÛ:¬NšyέÍo9Õ¹±ïg»l [9Û¶•sbYVY3Ϭ+¬käìÌaa]´ˆsaLǹTIQ÷6÷ãIØÜÜÙßÙÜàÝÚãâàâáâñkXi¬Ù¿ÿÙ endstream endobj 406 0 obj << /Type /XObject /Subtype /Image /Width 160 /Height 303 /BitsPerComponent 8 /Length 20874 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFa[ÿÛCÿÛCÿÀ/ "ÿÄ ÿÄE   68…†µ·%&UV•Ö$¥Õ'(57"#w49EWvxÔÿÄÿÄ$ð1q±Q!aA‘¡ÁÿÚ ?Û#ûûpFâÂÅ–ô°búq±èo|Ï|2ßýÙ·w¸¾vöîçþ½Î/ðùß7‡ü8}œ<>Î7ʯ¿Ç¿Ò÷hµ~¾žû¯òaÚt35öe)m…ÉÉø’‚2ÌÍmlÜJàVÖVÀÀTã ±¢ (¸’‰,JTh F‘2d˜û;›œ*ÊÏ6,>ud^MM懭­í§¬ª*,ä.>ždfd=>8 kËÀÅ2Ë(hᢒâ$lY3ÈÏ“8ûÒ7¶öø˜ Pf"™+ͯ+Íç‹DîàåÑŒ/“9wÔNUÚ‡“oÅ8kQ³äàÓäcƒoí’+,q&tYÉ)ž¡„–ÊEx ·Nw ùU÷ø÷úXoöíU}þ=þ–ý»Y?¼¹™eòÝ{̘j›è0To.<úØÂþ,ãDN*·¨ÕóÊeOlØN¹MXnÀÌ›°™“¥@Û¥šöÆ2Wud*Ò´a¥®Ó&ì.Ku¿.Ú™l_ÀQò«ïñïô°ßíÚ<ªûü{ý,7ûv²G|Ç36ɲIŸ¢®O†ÚÄ—ÉÔ›Í_f¹‰^UVÙà7>ÑãL@…°Ÿ¿þ$’Ý9‘E•Tõm Ú"Ív‡g5«ÛU³˃3²úÇ̺žž¿îvê†Rò–­ùšmŠV'Wp(·›Jþ– U5Qn*mð²«kGUåRSnf{nÂfdD‚éÉZ9óŠ›á¥*¾ÿÿK þݨ±›2Ò™S\²¬RoR« ^mjŒÍÕÈEšH ùŽ\L ÊïD(¬ R$¡¥¬Qc)ŸD9…ödlîmðÐï6<Æ»éË%ò¶Ç[Þï\°ê¾]Y ˜ÓjZŒÅ’ý 29èÀUo|ˆºóŒ 2”€³‚È-mјÍV‘¿&û‡v¬rân׫»•›yÛ¬™vÜWË”cîß‘µ`Û­cVcO„¶=’Ém.är ô2¤ˆ!CR¶Æ$`´ýˆqö¦Ÿ#‡rVèm-fû2ê¶¼äšü µA´–eFµž%sËlËg G* …xà¨ÒÅšh\¸¤„–*L0$Ç™Fô}í½Î/sʯ¿Ç¿Ò÷j·ùeÿöÝåõÿô‡Aдïh$/*¾ÿÿK þݣʯ¿Ç¿Ò÷j=Ñ ¼ªûü{ý,7ûv*¾ÿÿK þݨ÷F‚Bò«ïñïô°ßíÚ<ªûü{ý,7ûv£Ý ʯ¿Ç¿Ò÷iiÌ+òÞNÆë<ò«´õó›P Œ`T10ÊAŽÀÖ|žàÙû#øe ŸÆ,¤Ý¨eGîÆ(*FæÙS!^Ì©¥/9þË6àŸÔUKµâ¥ÚñOµ«õô÷Ý“Ô{© Õúú{î¿É‡j=ÕWf× —m`ÔV8nã¯-D†Êáñ{¨•×SÏYh ÕNp_TRt¢â°½ÿ©:$½­™jÅeËÓ©ÏG® å:à:¯´öPÒ¾>3¼½lR? àWWñÜ‘)^H\=†edŠdÐ;¼D°{»Ã÷íVuÝÎ+–Ö=¼½VöFOÞo«î°ÚÐ+4nôT@alÔÓ£Ú¬Tzˆ·ZeÍŽ]eà¸@ìŒJƒ ‰‰!µg„¨Míøˆ/™+›)0eï §8Y8Î8Ä[6óR„qZ©¬—ZºZ¢Á´êÌâ+ Ié!ŠÂ¯`K=”/úï°Q¸ˆ9Xò©d_ô˜; ½H=¹òN8€àŒ*ÂU¶EVÖêê£%»Ê¬e¥¯< «na•èöHÓ‰ÄZÙlç&™e™mÕmyÉ5„jƒh1,Êk% [f[=9Pl+ÇH–,Ð3BåÅ$$°ÙR`&<Èr7£ïmîq{šfͬe¸ì›ݱëNã°íLYl§Æò°uÜex==™¢´é š…ƒÕ;¼ƒ `B÷þ˜sTH›[1öÊË ±–œ²këv¸­;rêñeO Ø{ÊÀ/б•ôezÓ¤j( §K8. îò247Üzb-RânïGÜ›ÎÙµ²³špÍ`¤.Xv§txÁ ë`v?cŠÙ:ëØjä'Ç8ßÚäG2ÑÛÐHöø­ý’%½$MÞ î.ß@äß-ÜÌ«&®·roÒ-Ëœ÷),'÷˜¡|ñQOFfˆ®ì$±íDˆ‡6$Έ‡hrL‹×[£lÛˆêÝ߆½Ë Ö`H6£9&<œ=fÀ=ÍÆ¦ùmŸÃˆ-¬…šÊÒqÊµÙÆŠD¡©‘VNE™²â”·²%55Œ €`Ç?Z4Ee\&S•µ}QW»r¼ªÒë„5î¢T¿BLGe\7V;8¡Â,¸0z‰’DJÍ÷¤Œér÷w¤nvú4h 4h 4h 4h )yÏöY´þ¢¨é´Ò—œÿe›GðOê*Ž¥ÚñzKµâô}­_¯§¾ëü˜v£ÝHV¯×ÓßuþL;QîªgS‘þMcu‚Œõ.Id!XeíwäüÎ`1-‹] zÉ‹sïäé…öÀìÆcÉýc¼iê÷‚ùábqUa=)b¹†öA„?ú+Òénáþ%d $+ç1Òío2ÈÖ»v’­,–Aëp§’+ z Ç%“E"ˆPÑ‚Q„ìJÛ±<±)›QødO•¹º¹Í{ͪßÌJ£q+!R(|]kä†["±O×e½ÏËf¡­O33Ÿíðw„¶›, еৠØÝiƒ[)ÕÊ6; Í”- ÍÝ^oüÉ®dT†1Ù¹Ëwí)¶r ­më5Ï ïy(5µ«~¾6ÓçäEVmL°bú¡Â,DwªùiKPõd6ȧ(V;œt¿;—q»#;sâ) Û³ºÇhù–¨C³ûW¸z__íÎös¡õΆ¬tÏKÔú8¿[ïú|OsÜxʶòO™||‘åþÈñ—•{L’|m×»«ÇÝóè;Ÿ²;Ÿ÷´ú§Aëß¶=Pÿ1 Å?¹odôÿ“m|æãiÌ(ÇVsu p\ó²:ؤ狯q‰mú2³+½°ëÙg(ØØ·n1fžm۱¶¯W7¡b¶8c´ôUÇ–·®iÞNQsR¬«dPÜöЧ ܹÙe¤ï9â´25‚¦W<¿öÐËã+ËiQ}È•CnL”ä|¶& “ÀÞªVÇÙÓðìeÆá •Åp')uå8ñͨÇUp“*»$YS'FØ5¼`@ÑÞca3±f³Ñ 2F<ý¹e'ooŸ ¸Ýæˆï‡ÊCâÿß>(Có?Õ^ÄÿÊ=½þ¤~æÿß>ªþïÚ?Éè)•ªM±ä^pd —˜™„h^-siæNVøïÇqlÈÇBÒÂ'Õ@šÁ&öPh±Ø¶'V ›ñ+ÚÄØçÀ4ñ%»Aúâk*Ú³îïWÉÿÙ¯’¦S½¬–¿IÝ wB¹=¾ØgÖž1è¢uò}6ÏÌíô4444”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz>Ö¯×ÓßuþL;Qî¤+Wëéïºÿ&¨÷UFB5á†ìƒøŽû<øB×óÏÖ¯ü1Øgü£õ÷ßê?\ú›ûÕü½û_Ñë,¸1ç)~rúƒx¶v>îþ,Úÿðø4[5ò­¨(]µ&~õ›ñ¦‡Žm8TîSÍåÿ·DIô¶:æ= L—4É®¯”C˜Á „èÖ|3~5±Ëþؤ¹Á_ í¸ôÀ7|[ÌX¸·BlÖ“ÜqÝÙØ%BĈ›whBŽr©Íj™F«¦€.«vÞÞÁ}¸êixmo×+|SsÅP>æ•Õ²ŠþxsÊÌÀa÷ uœš¾&Ff°¢ô•V&:ðwcÄÚ_¬=ýaÆ¿eìnõºušlhX®•œ\˪Û-¾"¼pà'Ã&SÛ¸ŠùÞÃ@êÖM1ÛýÐmG¡2²zô‰ýÉ 3ÐJ÷RúŠÐ¯w³ïñµÊeš½=Dòz„L' sJÌ+g1F­y"mK—»=½Ë"×­(n’7ª€8é$m×[ ßÛˆ½½‘l͇1Ú?Qš¸åI›Ø¬Å*³y’²* vMPKå?[ámcÖ‹µê‰¤¸œk¯‡¤(ö´b™V'” TZ!á¬ezïg²Öû„â±²¬p6¹£X®³1º…¦e»{Õ¯•5ÇëTêê%“Œ“Š6†j̤¨Zƒqº=¿Š´…Ä=™ÚÏÇè€LÕMQn$Î4»/ß••ÁZ¶ùRX鈡ž+Ú±èܱ֩Ê|‹žÒª0«Èg<º2°žtˆŠ õäv^ `pHc S œ D Ž«†„xѪ'äÄ«Dì¶æ§y;V]µE¾sØw*ì_Ä{?ñ‡y…Il{JǪVÚì;-m§b"­ äJʳÝ…]8…è¾~x5 —± 4hÑ 4hÑ 4hÑ 4¥ç?ÙfÑüúŠ£¦ÓJ^sý–mÁ?¨ª:—kÅé.׋Ñöµ~¾žû¯òaÚu!Z¿_O}×ù0íGºª4kÃff[J[arra¤ ¤ ³3[[1hVÖVÀÀTã ²" (¸’‰,JTh F‘2d˜û;›œ®^Ô‰ÒZmBÆMcuÆT0*‹ é PãA5x5qk¡¼;[s\°CY>RYDv²Hd[ ìï„æ:r¼™ûG"Hƒ¶¬ãg1jÚãLÍ+ÝÚHÆjó szëÃfËÛ0£c™hf ˆ ¾Î= 9Btã^ˆ¯Ñš Ë)gl,WF¡Ù5ÅÓ+‹NAÒ+Ëâ eQ>µÐæ¦Z–IB¦A ¯«†ˆÇ÷A¼<8¸Â šÌ⇥•dtx’ÅÎÙØrk¬ÊÙºå®2°* ÿ¯÷媓k¡µÖÉ=¨#SGw<‚?=ao¶Ö'Ác?ÖJBèàfÄ0GÓ“³#Œ&ý‹*+ΒȹÎT5ÅV]ªIY$×QX*VJØöHP•˜½8âisBâˆ,ÐrRDïÊÛŸ±°Ù›±øcÏ‹¹»)è 4h 4h 4h )yÏöY´þ¢¨é´Ò—œÿe›GðOê*Ž¥ÚñzKµâô}­_¯§¾ëü˜v£ÝHV¯×ÓßuþL;Q6e•·U¶×%àmª  Ë,µª3 €ym™lô Ž/0ƒ+X³@Í —(ia$¢É€F™æGÞ½¹·Å˜:ÆW;7+öù{X.ïg"¯ ªì™w«yªÑs̨d[9zØçêÛ[&T±ž0G·[¨Îž<تþç„“ÅYÜ«"žZ#©­.˜ÙŠN#-¾*PʧEÚ›EÝbJf²,ûY‘ÎØu€kkÓ •¸äôÞHãu û…·wÎqlÌŸA]ÝŸiB$¦L —Îü[ÈS®x‡UÕöÎSÜDßwñ9R\ÀlzÖŒŽ™ËUV¨¶Ç|2_q¶—ˆåñQ^NöR£±ÆöÝŸL_¥cÁŒÆÂ¡º“…‰¦åžVµÅõSµñJ]U]ßi!dc«·™‹Ûð,Á|v&m(Ùö@ vБ‘òåÄk`·…$¸—Y€õi•ÚÉ v›£A†¾S(L™ˆ<ž1¯í:ÊâÆ¬ú±2zýÌ"Ôüú¢§?Ž‹î-á.PK96>‹xæB¨2V˜Õ"©V’Àm£zaYº(Sµ’»|Öœy—ÔÖ:fë‚n#ÚnE=¿)ÑÈMýñØÄnäZŽ/Î6•¹»•8EZ_*§”m=颩ÕÖ€Ô[8`.¬ðøD‹aí;OØãŽ4Æ$Ó ¸ù‰¾?¨+þáíájké=ÖÔqØÿí÷cŒŒóý{;!¢´ÍMô¾·ÑBôÃãD‰±7è1—‹÷å‹P¦Wv®*e;WþSš¶"Î@ã\™eXpï#*ïin+.ôŽ‚‡ðóÿhêàòy5S‹ebs—9ÌU¯:˜5é3~q`õøçÿ"ÍŒQ/¢öǧ ª×V@ÝåkCn䑚ªOñíGˆ‡6Ø^G%È`sg²KHí‚fÃi†4®Âth)ï•ýz«"ÑÌ\¢‚»Ì[bÃɆ(–«Ï0Z–˜¡Ê·žªêqĬêªÎ¹§Î@ñ@7hÕ­šÜJ·‰[7¹ùÕµ“C[T‹„Ñ£@hÑ£@hÑ£@hÑ£@iKβͣø'õGM¦”¼çû,Ú?‚QTu.׋Ò]¯£íjý}=÷_äõêBµ~¾žû¯òaÚuUÄY¶:e9[X6íŽg·+Ê­!²Ç|aéÅKô$Äp3Ùš ôPJ)ÒÁ‹;§D¬ßqé‡A—/wf>ä 75q”¹ìEYeúƒ™ÜËcâœͰ6¼¨˜¡[·XŒúõ]¨ˆý:¼c ÃÓ¬y eúΓ “‘å Ø›ìÓ®jÕµ‚Í\!ùRÃ\Hl:‡Xw@¤#¹ˆ<‚ºzÙ C»ÎG‚½ÝcïŠ_ê=XŽÎìH›ÜYÔ®WWæ6[Õ¡çzç¹órr—;U5“'Êò³shµe’¦?ác7zðYÁñeÚγÔ®Ôå.Å9˜YP vâ0˜ƒAd&jã-WŠ3òËèXºQ"²±àÙý›`÷é—Å1õÁžÊ ªFÃÚî9o û=;yKl¨Ž©ïÁµJ²ÍP¹ÏÙ8ÿj8ã”÷ç/5…œ³¿ˆÇÊÅ\…²rçH=žėÜÂsoÐbÌÛmZ¡%ûlåW£ÞÕP‰*uÓtfËÛíü¡"ÓÏrAÊs…VN%4 Mf·-‘Jy›¡¦LYa”šÂÚ¡$àÛ‚‹HTkf[ÞŸFà6Bø¢’’ÌJ˜;‹9Ûrⵊ‘jXxkHYÖ%Ã"š¢ŠÛ<"5rÔLSƒÎáM8ëH[€âc®-¤›õµÆ™ÆDÅSc‰IH\:W5$زž“Ü¥ cÞ Òu0Ü{ŠQÀ8[s—®¦L‰TOwqc|*³"åk8£©ÎŒÓ'³H‹ÂAl;$ÒË©¬- ²p´444”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz>Ö¯×ÓßuþL;Qî¤+Wëéïºÿ&¨÷UFxlŧ[a8)dã©@ Ëš³!n##lñÐ$L†²½)É…IB1ÃÒ6vÅ ÖÖ²·³>\}ÃŒ!EðÊ%!¡sì%å”V#LÇ ‹¨mz†¬kØòŸ÷qÑÅ.‰ˆCQR[ܱÛ!ïQi–›à½âNÉÕÓ—o2¯WŒ;E‰Ð:T€ýkˆ±ë*ÚãL3\[µòE©^1ôîáC±ÔÀ¼&é`ÖUÙ S¥œ4Èï]ÑŒou.$}í´†Ùæ{Ô[ži¢[±Þ+£˜MH$äzí!¨Æ¿kg±SzI<^îgñíOIaì ¡ŠM PÅøÎ­WF50á¨ÿáÛäFxVعƒ²³ÎÝ­®ðUà´Š…Ù†ªÞN.üUó*¨•„fgð`ÞÎ? €øs†ßA’,ìXÒÊK…<Àw´j¥®ÞdKf1÷˜pjÆ-§ÙUŒø{rdMrŸ}VÐÞZ«ÝŠ}…ž¤Ê Õ¿Úz;mY¼ß2ùðŽ!¼Õ¶™µfEU5«¦îÊœÿ+™9êà qfå¶(Œ§ÈÆsœº«üÐÈËVš«ë`u²p•*cUˆÆÆód=Ñ5§†ØÃÒ4ùF«'`2†8+pkË2 ÂhÕY;sn ÁÙ*5UePå>K6XøB˜ e)øÍ=ýA±–6È-ˆç7AŽž× rÁ™ƒæ…¬Ô˰_NõõDØæéÖm„Ï4ªMßx³çÿ”þ©¤•´5{&o@›1}wqKžÊªª%Tÿ½µe÷Yé$U~AXâÇ-7F—LJÊJŸ5qÒ¬Ê BYÉu¥´a`{lÁw—ÙO lª£ZË­ÍÉ1öN)7<®Z@r–ÈO г ܱG1zFFFJ^sý–mÁ?¨ª:m4¥ç?ÙfÑüúŠ£©v¼^’íx½kWëéïºÿ&¨÷R«õô÷Ý“Ô{ª®"ÍòO¬ vG—û!³Å^MëÞ6òOAŸØÞAí_Þ~Èî~—ݹû{ úþûCÓꥰ——ƒ"eNÇHg>0áíè.ôÞrÖêµXm9ù->áÍ;z7[N>?ØØSJÕØ2@&³¾=¿ÆŒ¶Ï$ý™æ^Èòÿdbw•|e×¼m䟈ÌïŸwWï?dw?Tí>ãý½Ð}Xý¡ê5~z4NÁË£-r"~fdFP4ã¢ÎU^<³ž9lÓè´)»,Ž>„[u[$ØÓjYNDkxãmüx„ *êP*J|t $K^.„wÙÆ«9É[-mõ¼(M`á늅aË9;—}Ω‘‰–]ª·B2z±V.ba@8ÛAEËȹbÂíNdk‹PωºK†pÑì<;u¾Ÿ´h)¹xd”ØÉ[¤é €t‡'ºã— *áññÌ©k&«»Ç´ ~ ¼ÍP×8’kÅñ¥HìÎãˆye̬äøÃ™ÁˆŽøe!Vä}’)ØËÊU0´L!È —«ÆZyvŠ¿¶q–ò­²®À<ÌK¥6É©˜ÎxG´½íOîj0ЖIJ%wnÂÔÖé‰US%'Ž•eh䩎ˆ­ëÀæHkOĪÎ}CŽ‹ŒŒFʳœV"•.h¤@q •·1„–øÙïFú«ÜÅ”é »ŠaX½4444”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz>Ö¯×ÓßuþL;Qî¤+Wëéïºÿ&¨÷U\EšuÍZ¶°Y«„?*Xk‰ ‡Pëèäw1gWCïS»2¨wyÈðW» Ì}ñKýG«Ù݉{ƒŠ¥¡s›©Ù).[Ê:x3e9€œ=$úÛ5™½X­ãÕOC©eÎ{u†Ñ°kÀj  ñBá8†—â®·­èd1Vó¦ Ùÿ; ÕòĤMžÍ>b9)"ëJ4õ¦V³ÃjÏ$ö².½dRbq¬]yÃj¡Ð÷.ôpéufXdw±6ÍW/ d&MéêGA’T«¸ÆQ’ =ÝÌš§_©Þ¯,j¹püª(ð{¬9äÛûʰ*X7¶aÖñãÅ¡±÷,Š3œ² Cf²³& »# ±+(_OžÜ#· ˜ÀÎ\nÉwâÙÊ.ËJÇK!Nb»5…²EL áyÍÉQQ…ßm$l…£J  K–€b¾Ød­§³HXiUâdY*7‹Äæ„öNkx(kÉ!2 ¬žX6¶>[y뮘ɓºÚ’À:õÇös)K8â.Ü”æâµµŠÕ¸±.ÇSb˜0do1’nÖ.YÙ—_µËrÞLØ{•+1xi¡µ*Ó#Wb@M^E©‰X·k~Ùɱçƒ]Ú¶úÙ=•“‡zh¨ã¸ Ã]†1sDŸqXX‰wãyÌoàϬt}aéÎ;9nÞÙ±çª#@º«WX)Á H«N*¨eÖÌn[´*sÃ÷ÚfÓ÷”SØüåÉÌç¬9Aòù¶ìÒ©Ã=Ðñ‘j6Ig&o*ãÅlÚ÷ALSˆõpÙ°í‹}ýá zŒêÑ&¾ª_ýÀó¤Û ¬(Àâ0ÅrÎåål FåÝ‘™q²ì PÃÕĬ]¥¤Ò[8û?§Üõèñ– ûwÙ˜³%»i«VžÄìrÆÊ2¿[^[¯g2°VnvBÖ>!‘Í…Xã§/*þ†Ï•Grê9”R+LŒŽ(Ïkl«yhm¬•’$µöêh\C‘šº¼Ã¾újY¦î¬È0À¾A;tuWd© K8àÉÌÐVìƒYf¹–Ѷi·œSÁ¯i„îâèíµfó|cÒ‹=†6ÂS€ä­H¿ÙdQ³Ü±/WC²ÍdºrÑeT^®¦5¯mñ1 ¼Ñª{ØædÔ~edKާx‹‹©¸BÅžÄÜ2¹ê;E޶ÇY2’ræ¶¶Àd¶åW/bïaËO?T§I\»Pº§79¸EÚtU–FS ’yj•ÊmÃ0r!¬RËU,=¸òL½b^Ë^¬²@s´+t7·ƒ±,°§­ÄP_¸Õä³Fž9æ3˜'v`lŒ!Âc£T‡‹<DzDý£Ë­/*i €|ѱfUËALÇÝçÏiZ¢Éªêw ¦¹ppØÄx¢0$XõãJë~a/ÙõPç¼jŒcpƒ$×W+¼§°1ë”*DªâÀ¤^ˆW Ý/“Yisž‰päSŽüqN‹Ôô’ö ´ls6z"e2«±Œˆç#k°†´tk7·7¼µÉe¾LÜ5ugމüÉÁç0‹guû‚Ë`[¯1è~»Ø]c RX9e²X¼Të,™“Û pƒ¦=—w"dûä‰ôÎe2æ(u‹«¤å.p¿D«ãUd«wÜtÀâ¢æwEá_cø)Â/«SÒ)ìNNS¦Ã?‹sxjÛ€Þ8¤-Ò›5Ði‹F^]ÙY'SÚ'2>›9S·ÖùkÔjG‹Sw=@¿*uà¦+\€Y¤/o]eÖ ÞÙcŠª}­ßz"»çYò–ß­£F£F£F¥/9þË6àŸÔU6šRóŸì³hþ ýEQÔ»^/Iv¼^µ«õô÷Ý“Ô{© Õúú{î¿É‡j=ÕWf¤ù2¶°kŽîx¯ü€Ø“ß•‘þÔ²R{¬ ð]Ý_4zIý¶ð·ëúÊ™ÿC7£ž…¤“é½Ï±†˜I “ê¤ ‡»Þ)TÄ”ZiñS¦,{Ò°Ìn·l”¤qŠœ°Î¼M—¶bAÓíï,}ÜU±¡©Æ#™–8n32ÚRÛ ““5% e™šÚÙ‹@¶²¶‚§XN‘XPaEÄ”H±bR£@4‰“$lÇÙÜÜáñ<›[xÛ̾AHñdy7ʽØÆÞ6è=Õäùõý±Ù±ûÇÝS ôÛ¿§ÿ˜ÐT·3¼:mÎÌ‹åÝVJÆPlÔm-‘b²JòÊ'n I©l2PFys±F%VÌÝ×s’GÁ¦†µåÃ_á¯W F®’jqŽ:%úÎzáÎãÂ\Ĩ«€ÝÇaÚ˜³uÂ÷Q#®¹¼T­Ë*ằÙÂÁ‹ê‡ AƒÔL’*¿õ$gD‰µ½#nS®ï:JÞžpUMqU–Eh,̃k»IÖzòݬ·ÂåW0œ†´\œ ì•.´ÓöãÀq[âá8» ˆ¿o²V¥==ò×å+«lK²¯ç ¾ßÉ[RjÔÅ›òÂL²•pè«`ך>;ÇK] _T8SޱÜ*zÊsL"¤T ö,Z”G±x—‡+‘¦/ìã¦#ãòmÙ˜UAL$9t–¡2"¢ºC×yBc=n,Îo^@Œ¡¼ ¶Aè°dÈ€)’0EÑ á°ì 0ï¶è5ÄWmmq¦±ê+"Ô¯úo>W €^ô‚³èÍ 3Ê)ÒÎ $¡¿èŠŽœ:Oº—FÎØWM'Ê/¨™9“Š´R,°éÖÅ'” »Ã½›‡év@iq…\BA–á9/½ ²ÂDÜSÝÞ5Q•rÚth! ’ð:aUy6åßycxp°Y¬{ùû¾Ëq+ÆFDPD‰V¯+„…øœ0A'ÖU{[,ŠÁ¼5Ohá6&fýE–íçIcòÜ+æâ«)%g#,k·l*Ùlƒ$ØŠÃ^‚qȸQrÎKÁ(Âv%nO߀$”ͨüQàJÜÚíÖY–ÝVל“XA¶¨6ƒֲ̨Zå¶e³Ð#•¼pT‰bÍ4.\RBK •&ċ#z>öÞç{š4kˆ;fÖÊÎhuÃ5‚¹aÚÑã3­€D9ØýŽ+dë¯a«Ÿãh‘ËGoA#Ûâ·öH–ô‘7x7¸ƒ·Ñ£F€Ñ£F€Ò—œÿe›GðOê*Ž›M)yÏöY´þ¢¨ê]¯¤»^/GÚÕúú{î¿É‡j=Ô…jý}=÷_äõê«ÃfY[u[aMr^Ú Ú ²ËZ£0˜–Ù–Ï@(âó2±å‹4 йr†–J,˜`I‘d}èûÛ›|X£ïì‘ønÿ†ÛÍ¿õ{ñ½ð—Þ]%ó¿>ŠÃøŽø„î.xÇÿþéü:yw¬ü7Óߎ»‡öæ¶ñ¨CáÆ˜ø‘øºìßú†ð‡Ã{…«ÿ wç“{7´úçd}xý·Ü=µÝ_þ7®tò Îä®_Ú88{å°ãZÝ![ËÅŽRHtåP­v@«j¶Xqï ž ¶rËñ 6OlŠh´Yñ2·èÁÖB+û+Ϊ”Vo·/îp¸ß[^WÓ૾.ã^SáÅѹ"ÕOÂ+ 3nÜe{;êÉ 8‡ÀÇBŽìvÍ¥{)U·z8ĹUo<Ÿ;uqíâ èðlIùdIî“Ý#9Ö‹ÙE¶ÂqĤ .4·º©UÈŽ*[à´ˆ"÷6å,³VÓ™2Bå°[ØÞIÈ^WË ©j†ê£+ºo¥×™‘²º6ŒØv«£›Õl.®Ú¥VëéÖ£»Ë¦9!¬ÚâK®Á¹‹ZŠ”GÚƒrYB2e/Ôùíž76E¡cBm†sq¾ÉæÓ|[Êrêj犽ŸÈÒ’¬T&ÙÁUùB’ªÌ(×+òxhâ—!ä ™¶÷$®˜ –YpßL|Ÿú^°·Ò( yŸô«A½x«,hÇuð2QmNGˆ×ÕÚÍz­^W ñ8NS2¾·ìL‘d€ïsWˆ=†Dý1ÖXUŒ´å“_[µÅiÛ–W‹*xT†ÃÞV~…Œ¨ç 3+Ö$ëQ@e:YÁpgw‘‘¤l ¾ãÓj—wz>çVrãÃ*SáSÆTßm|yËá‡þaÚ¦|eñ%Ô|Óõä¯y÷ŸUŸÿ{¯·}ÿîŸB÷[>ì) '™^q/âƒuDÝi¤?ew‡ù/¤åôºusµ…™~&O O^7¼(D~ u’šgºI’í%ãu}»ÙcØ·/ËÇ&Žg3,C¿.ï<¬a¯Âd¡èk_×.gd*íÑwK#cíWBA¬x°r¾©§V˜pUP¸]p¤ÎÔí¼rS¿° KáÓ i¼h¤ñÑ”^VdY;÷(êLž9v¯oiöq°×làV2ËC~;Zsc€ÝTØÉHÏ uƒÊxi«•`Ò“£·¬B©9nÙøIlg­ßiÊ«ÌkM˜UTY7µïn¾Ù™ÀÂíìkÚ¶Š~Ï`1b–2 öAÒÚBH‚-Ê: |=²·`óéæÝ|¯%kÐx釡0>c˜˜Ùc£Ò[ô¬‰p§îÇÆê†òf0ŒáqìBe6›= Ý7´æ4ÙÕeg]/jŸå•åöD3FÐ9ƒñè’B3}N‘wõ>›œiêÖÛT$œ#yiQÆœÝÜžÞ²esÇ&$]Í?ÞxUŒ¹æ—gÙõ§üß®¿Ãeñ®¬ >üUÒœÂ½éªò߈‘,}†ëÀE׳ Éaœ@€)$=Ì­”‡89X¦X­®®^Ø(Hc×@Ù—bó’jáåÐ{Ò#nn ¨pÓ‰èQʃ\".\Y›Ì]ec¦\uµ}n×{޼µìt6œTG]Lx™\ÏI;YÁ}PH3ºq‘£ŠÂ÷þ˜Œ’ö·£íå—&¬tÈùµvî)™ìzócä—Zö>6°ÖCŠÕ} ™µmf§Œ×ÂaÁV9\vø>ÙÊc¢\*¡é FØ‚"Xîñü:ÆÔd¹rƒ )܇Ïü‹Çê’Îù7æèi{*çӓۮ݃XÚ®)¬ädÈÙ´Ô”°ÝŒÖYcÛL­Ô¥ [Û±óvá¯C]º„.ÜŽ¦1ÏÄ~erìï;]è8ãU~ï50÷UÏgõnÆMýÕs¡õΆS÷…£ªŒô¿¶÷ñýö`S2ï(2NÉÅ%”—ݧR3 }/dÝvâc _-­ªc䃂½Hñ{G2^ú|¤dhkl™.Ž,K-S7™¬Ž-ƒ²ï(ã¦CÛ¾í6dDß”Wa-=‘£ÜLAdÌÌJ6êaŽÏ³äƒPÉ nr"Muy7…&П_pJk€uìsQò®ÝÅõgeŒ#ç šË¹¯˜KV¾s ·TñåpMÜcާ\F|ÑI[µ³5xV1v%Y4]— z=Zû¼Å^©ïW«Ðkõ¤ðWà[•ÞÏ „¶&ä_6/ eM§ˆüº°ö•¾9}¬ Ú4zÝÚÚà…é–Ø±ÚxfËs291 øU˜ 4RP XG*ˆHQ¯'ݧ ÀÒ=›c¦S•µƒnØæ{r¼ªÒ,wÆœT¿BLG=™ ÏI¡Â,¹Óºpa¤JÍ÷˜tr÷vcî$)ü×°QÍÎCj¼(ÊŸ™ðÝ:߯ü¢“.ÿP(Q‘Þ3±îªm¼lë‘vVºKDŽç*Úœ {©œoYUtffduù;ì.NL'[Ûy/–fkkf-<ó#3!ìTã ²%”4pÑIr‰,JT™ägÉ‘2déÛ›œK¦*àMù–x³É…ÖîÊôˆ˜óŠ©w•ˆ´EAŒÒR\ÛÜëÊAJU'̼^o»o©v¬Þ˾‹XW‚¬GÜx7WVËËG5]…ÞRYLdg—<4åÞ> »ß±ÆÕýÞj^í[ž°é=ò›ûÔ \è}p_ï çXU'ê¿cœ!î${™¿XÚZÈ5¼~ÇNa{ŒÎÖš,{å?^¼2ÎAÀĵ²ÌFëö‚C¯Ü Š’ùeÑXé²¶˜tå¦ïFŠloÀ R "úƒ+‘®!#,²‚ËÅú\´´×cíü§å¼9]8D(ÊH²Ý`šV« ¨RG™©…Bò”Õº‰’¶Æ*ºa¬É¸-â½ÍÁ©E•"‰ž­sŽ9#ñqmûe=$+Ù÷LY”Æ8ä>*Ýù7PdÝÞ’Qn¤ª¢]“Ôšœ’OÛ–àm„fzö¯YÑ ~~&w£ûÑ3a *<¬I|a7‘Æ\n.™c×±ò)^\o¬Ûu P‡52Ô²J t•ƒc«Éº áà‰ÅÅã3› ”=,¨ ÄdOÜ–.öÅusåh矑W¤de "¼uH®Œ6ñÀÚ‡$¬œa+/æÁµNâÅ»!Ö­9_y°µXî[Ï"mG5“À½ŒÕSå}/aV2…ÂhÐB–>VÕž7WاÓtk6¾ö­•àW2ÁÑ`,2w"ÄJÙ ·a1ëgìtXÃäú Meem)my55x’‚1+*Š‹"`[Y[8 kËÀÅGˆ,(0¢âE$Hر <8qöcìííðñº·Ô•Å|¹A8MB’«,u¬jÌhY-ÖÊEÜŽA^†TQrÎKVÀ˜ÄŒ ¿?r>ÔÂP#ñnJÚAR¹±Ô%þKZ”Sã•y›>?‹Víª›W7VÖ£³Ù’jºâA,o¸ï³•sÅŠ Ói™V Ô½[ –aæD“0娘ƒ°ñeÆâé–=p[)•åÆñ:Í·PÈÕsS-K$¡PÇIX6:¼ Þœ\^39±š CÒÊ‚ FDýÉbàïlxppÿ†OTn.c òNTLÁÉA¤«H“IJcòܔڄlÍ…¹RJf*TE¢îmO­–åÉ› (½ýؼL^¡Lަ,ËžùÇÄ—.·oã'‹¼Þ£ÛÍC{'Ì곫_ÛåÁÀXdîEˆÉþèš?Ñý×¢?ÒˆnmÄãrMIMŸn•™NÕ’Êd1«7É)5ò–üûµl*ÜäÐëÖìÍÑR,bT ’T%ËpÔ d'‹h\½ø»…EFRXü·96†§jÊI@™É,Ä•**ùJ¶[ É6ÑSgM\³’Å…6Imø»“÷à vGxvö¥=FJ^sý–mÁ?¨ª:m4¥ç?ÙfÑüúŠ£©v¼^’íx½kWëéïºÿ&¨÷R«õô÷Ý“Ô{ª£X£‘øè¼%ߑ͑‘xŶ†E°¢°ò[±kÓf« &ÂX¶xòf×dzR™0øç'ɹwr½X£&Ñ4ëµ@‘»\4¬[«®hÐd»™Aø¯æ=ñßýð³Ký=7É={Î~Œ{ü"ø[ÿâŸã—á×¹~ýBøÛ¢uúRëšðï5œ‹uË[‰6Ü^8Û–­¿$JÁY³•D„<ÈÍ‘g¬²â—Õñå­š8jË–Hh‘5ÜY!Ï“”}èÃöøµÛ£A¬º1Ó,.Ÿ“ Z*q-¥aîgQ—ºÑ„ƒdQ£² Àʺȧ\}­‹{*ŽF¤sm¾¾Üß'?Û^³ =•ÅZ\U{#¢³Œªu:G/Kê‚«`hù4­ÏcÔòâVÕ[¼¡al<­dvmK­®ç.5¡’ Zu²‡ÞæõZÖru…S£7¢•8´¬©g!LgÞ^/òƒÉ>IÎέßN×Ò-\ý~ç¯y'à—¯{<%ánŸÿ"~|ñ‰ñ=׿å/^îù£ÚíòŸi‹ï#~Tá›u7½eÓ˜³ˆÖmg³9…ª¥%7ß,À„uápâ8Ø!›'”xzaÛ¸?n¼·-Uw-„èÐRû33#¯Éßarra8ÚÞÛÉ|³3[[1iç™™`ô‚§XN‘,¡£†ŠK”H±bR¤Ï#>L‰“$oHÞÜÜâ«+ºî©ó’NòÄÅ÷ wÖZäF:rÿ¬È&Ó{»ÖÜ jYÅù–…«—2«–ò” Y\”Ž=U¬»@]ÖHì†ãŨJ7BJÚíÑ Ã_=»”>ÖPg‚Zä_•HufX¸»i¨r‚éÊ …n©0Bõµ-|6½">@ª0¬Æ`fÚëÊþD 0ÂuÔÄÆí¶éì-ÄŒïVð1Ñ™o:ÛqwÜ6…Ž˜û’ø'U6*Ï»Üð¢ñ;yÙØ§yRª†Þë wÃÞÌúí»)ªbPཟT¸›ÍÜï) ,z¶Ñ Åÿ"뺮9Ì6­‘Q¤+ª‚âåd&¼#]Ð4u½Œ5 ÌÄ£ìZýùÞœ+ÃtYV! ÀÊ|{¨,ÒEœ2 3 9ʹ¿†LxCä²9´ 44”¼çû,Ú?‚QTtÚiKβͣø'õGRíx½%Úñz99&ÓØÜV›¯¡êž¤A§¦z¯EÔ{}7l·¡õ¾ž_¤õ~“Óú¯I+ÓûÏ{é÷¾g»âH_™$Ð+0,FõÁ„:oŸãzÁEáì+ÓL \QFÎ︕±±'kçû½ý­Þ.Ë4~£dGÿ¹þšÈ×5ŠìÒ(JCatîþÆýCZïlïlˆ!¹µ½µ¸˜owks‚?æÞ糃ƒÛíáãáöû8¸}¾ßg·ÙíÒï&º~/Ï×Ù~—y5Óñ~~¾Ëõ÷]O¶Ž®{í®QÀF|¸kb¶ì!O¥ GñÂL¬Ïh!ˆì•+jݾ"“JM‘®äÁ¢álŠ–j­Có;¹íð7-Õ‰¸$ñø¥D¼I)kE¸UW¬œì%:ånÀÊ‘qZÈXÉä„…€[M©çÏ]¿™OJŸVW‘?/˜±yÍÑ%ÀJ®âN‹"­®í÷±¥ìîG‘·óËFÜà÷›;Ü<œ?oƒs‡çpû>w³üxx½žßnMñ¥Û:y`áÀ< ®ðîÓ¶/,qÈ¿hšLÄŠuÙæ’Ï _¸ò²ÃßžÌ&ù§YÏÕ i‹ÌEÁ†>T41‡¬Ôƒ¬™2¼áÁ`ËÚ¯*¯bˆÍ nÈZÛ,t›Q"ŲD×jA á-’ÝÛ`vÙJ"ÕÄ4›ëïǼ–å£9“ÇG„˜~^Ç ÜÞööärk„&Xö9lƒ¤×”ãÄêÊÝ|#k¡ÂLªì‘eC%_XíOíGxqx4å6iÂÏD*t0é6唃³¿–\}Çë{«o“…qË¢òžÕ¯1ƒã¨6MÃIÆGÙsÑŽy h-Øé¿~ê–‘U¹—v~ÇžTSZªG5Ó¥ÙÕr“P)K3kŒPËË4]ûlæþQ[ÞMS+UUÏ•õ7˜…<ŽAâ}cƳ*k¼9 šù×Cs¡Œ†}õ±\þâÀIÖj¸_¦Ió­©ÄÌ-±ê-¤Œ™¯3+7©L6^|®-°2“yd«È"Ö8f…Ï`Þûâ! ÄT Î ëJðN% $±r6w!îqôeêþ(G$U½o˜³¶W’Øõsú°)ý×d¥ÏÓž¼ŸÜ"üè€ÓÖlš¯¥÷¨mÎô 󨞥¡²€‚5V5‹s m¼·Ê~Çlü3¹mP&<íbýÛ^쵄»-Bµb\J4)À¼&ÅÈhS Çë ‹y6À\­¤M_¿)‘Æ\‘™c¾IÇË¿tWò´§fÛ4ÕCáw2˜ 8¨`Ò/:â¸m‡q¤nK;z ª‰]âaA[N…,ã a©¤œšÆë2¶n¹kŒƒ¤, ‚¿ëýùj¤Úèmu²OjˆÔÑÝÏ ÏX[íµ‰ðXÏõ’º8± ôÃäìÈã]3Û<ðϬ<ìMY‘ @êfeA 6,+v2Ý·cWèàØW¬KïÂ÷î ~ŠÚ$°Ð†à>Ì91Ém“Kù‹H¹ŽÊýÌ/¯„¼RõgÊ ñûå¨%â*¶jÅG2ÚVCR’v‘k¤AdlƒRP#hHü0­…ÞÝàXíÎ-”áçµù^g6ánRb‚Euñj‘p¤îŠ3&dß)’ÜèõÞ'w¤7E·ŠÝÕzbFÎÙokD@¬"¥•dLdÇ©y#^wUÌZ¶Éþ_õ§0wi#kÇŽòî«Ûº˜…ÛWSU*'¬ÚŒÁ«€|]Òq|oï\ 7øc‚¹¨ËöG“;·®9tb=a~ÊA(oy ´F¸T·o;ÿ"2IÍ90¬™Òg†K%¶µŸÙÞÿ¬0ÄöYÛW`S[˜Xó¶„9µA1L7Æ\‘¨ðËåµpcåÞn ÂÛ¿2r£üPøÍs«µ\ö­¦µ‹ùð¯8±ëáñœÿ…×OÜõ«—‘ªtÖ1ûŒ³†ƒò¯™n%aòÞ/¹Z682Jsi¡×53Zƒ}i1omêÉ^+ôÁÆ'Å‘|Xè”,ŠÙ'ûMjS,¸iÓ=°fGb¹Æï,³-º­¯9&°ƒmPm%™Q­d´ËlËg G* …xà©Åšh\¸¤„–*L0$Ç™Fô}í½Î,—{1(ñlÚÓ]ª~P}yÌqדŒ2ÛËá•ÄæêúlŒk­£4”P8 Q§}á›haDж^‹0 iñ¶\}h¬–žymxáU“‰E X’k4…¹lŠSÈÀ2bË ¤ÖÕ 'ÈÞÜZB£[2Þôø’7°šÅ”÷4hÑ 4hÑ 4¥ç?ÙfÑüúŠ£¦ÓJ^sý–mÁ?¨ª:—kÅé.׋Ñë¹À,ÜÖ,¤(„†‰yÄ#lÌ€BÀcÌ…6Ž Èò¢J¹¹±&6þÞæÎþÎçÖï·Éîæ¿ævëD¿ÿN¼Œ£fž— àqµA54s ömïnÀÞžØRÔݨûñdnDÜ‘o‚NÞĨÛÜ{<\|;[û<~ÞÎ}A›7ÕÜEíb´q‹¡‡lÛ¶ö§ìÀ<61H{Sv£ïÊ·/n<­¾ ;{¤ìðopñðíoïp{8w8šçù“þšçù“þžyåË÷]P™^ãÞ{_6LÏsï~g½÷^£wsÝûÏw·ï>gø|ÿ™Áó¿Çæðÿ‡®6¿_»ªE?u«7H0Ï#¶¼2­€Û·°ÞØñäÌ4U°‡ü¹ägÉÞÚØDHã"Û—¸T®ñž( ¨étÉø¾•~ɤ>!¿“{móÃmO‡«ÞJ冀ò'Ö¯óßöØzªÑ^$71Ì2¡l–zªÔ¹;už¿ñ?•ŠB¯-VºÚŽó™î5Ê“âåNF?Pcç}ömH æ§”?œhÆ©>™`°ÃÕ®ij¼šæ¾¯•EÒ+]åëð)ÛÖ8$Ë%…ÏâÊ¿ö‘-ßVd¼Kc÷VÐJý–†¤ !½¼ÇÔ¶¶$ˆ £K¥ –¸é“Óì¡TM¦Á)QôlfÄÏ²ä· Ê¿p ˆPy Ue¤¡>;]Eq©m©íÅ¿d“•«›H¸3eG]~.¬Ÿ¥¯à3¢$xƒèêøºî>š{É>Iø–ð×DëËÛ‘Ûçúogõî½þk¹zì½'(¹@Í™ÕNodsmY‘*úZȳÏ@‰SÆ0¼Å¶Š³_œr#Z%âdYË#i58ô¶I,,··Œ6µÍ4Å꺬ÜÕNfÕƒQXö] ¹BÕ|º›3Uñ{³oÂù" 2=µ=e¢ËêÀ•JR¥)i‚çAìÐĈߓ_6=HåYj{»27=ºGšd]°‹HSÙ ¦Ë´jÍ«¢¯-JÆRfW¾ÝíÂk¦·DåÕ£‹R³‡vHUQ–A»&ôJƒ&þˆ7w ©.öðÃUb“e~Àr{:ßm³Ïˆ3÷¸(±ï}hª?or_ýý%´Oòµý ;ûó\Eœƒq¦®-ÚIŽÔ¯úwp¡Øõµ`ð˜w¤‚tOYWfm( §K8,i‘Þºÿ¢*: Þê\HûÛoo¹—4§·ÜËšW‹ÔvM[œÃZyä]#ð“Óp…+ 1ðÍ•_ÝNmeX¢ò̵ç;UE§¤-¤-»Ï™S×xå–s±Å#d6€§½ø„’~»Yd¥mÎ>k&âÕ§4l¾Yѱo~}DñY[ùJJÙ݉9vù¿©)€á(@‹½$ÐÝâ> endobj 134 0 obj << /D [409 0 R /XYZ 100.8 688.245 null] >> endobj 138 0 obj << /D [409 0 R /XYZ 100.8 297.938 null] >> endobj 408 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F22 239 0 R /F37 405 0 R >> /XObject << /Im4 400 0 R /Im5 406 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 417 0 obj << /Length 288 /Filter /FlateDecode >> stream xÚm1SÃ0 …÷ü Î`Õ’-;^{´PîÚõLh†¤p-ÿc7m΋m=½§OóXÍ–¤"fñC4¬ðºmYÄwñ,ÔÊ;”ëÅînU+”›ÛZrrûWÛÍ®~÷³%ú© ¸`….&ŠˆH c]©Q¥ ‚çK §$–qߦ(ϲo‡Ú ü)¯îÔöÅÐø©!:‚¦CŸj²}Ñh‡6õŸþ:ªE¬0 taeN¬xë«ïJƒ·ŒœËÓ{."¥ •^bЈcq¶ê¸9TéŒæ*»««ý-Û^–}&_·Ç}7|Þíש; Ç\v<8dÏ×{.Z“¿{3܃ÿFÿrå endstream endobj 416 0 obj << /Type /Page /Contents 417 0 R /Resources 415 0 R /MediaBox [0 0 612 792] /Parent 393 0 R >> endobj 407 0 obj << /Type /XObject /Subtype /Image /Width 164 /Height 158 /BitsPerComponent 8 /Length 13794 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFa[ÿÛCÿÛCÿÀž¤"ÿÄ  ÿÄF   68Wg†˜§ç%&7U…¥µ·Õ×$'5#Vf"(4:EHÿÄÿÄ"Qð1q‘¡±Ñ!áÿÚ ?vG÷öàÅ…‹-ê°bú‡¼`õ™¿#߆B‘—ÿ,ˆYss~Vl¹9ÿùòs§å~O/úrú9y}-›«Ÿ%20¦¹uÓÕ&õ#…–ZÕ¶_@²,²Ÿ QÅæeYb p)H’†–J,iã§Æ‘d|20äÇËp­_§¿uÿ&Â>Dz,úîŽT«ŠwV^*„[©Ësãñf>wRÇcEth–…F¡ÖÞ ³RnÆoTŽØ¹ûyˆGÃégà¼Õ}ý½ü,7öî"Ëwrõùn •ó°e$ Läe‘­vëus[-d›‘XkÐN9f .YÉb˜%N Y'ç€$”ÌQù£À•“×5låßQÕ^ççUu5†ï^m¬—œy†ŸEÕ;^䙯eX3Wƒ–í“[Þ®×^5•¯¥°óAX°Õy+Ëd¾\±Ýb¹"wq·|}ÍùÍèf9WíVP}EÄÛ)¨±èb q§Õ5ÎYœ¬Øe.¯X€9ŽlÅQ4UÝ \…°03åÉD¯kó§¢y, 6 q´Pî4ÀÖ=Eo¤Z•ãˆöóåpa!á0·ƒ4,ò”SÂÎ $¨ÎÏêEGN'ޥđ‡oæ«ïíïáa¿·p–š ¶[pßL{Ÿú^°·Ò( {Ÿð«A½y«-h×uð2QmNGˆ×ÕÚÍz­^W ñ9NS2¾·èL‘d€ïsWˆ< ˆ-ýÇÂWÔ[T;í§æ¥ô¹×Óà™3|VU*sØõ‰ÒE–¾B±çÈÕÕ ½¿,|ÕÚœ·ÀyêåõR09Z92¶Dlsâ~j¾þÞþûwš¯¿·¿…†þÝÆaôî-»„j{Fó¬œÞbíq4iWy6ka×Wóf r¡fº1ë# ª6%§ÑôÖHõðÕ üØT‡Jíé2$ækfÅû“¨ææªtËëW°`.OP·õ'ªm«®:øÝååU+ËúanÿÖ”©¾5JÃ_©,X Ã;…Ø+#TŸõÙg3€2\ sÍWßÛßÂÃnãˆö¢‡æO“^o¤y¿ÙfùUã dùmãÝ«æc~OsöGsþŽwg…ø~gõÿÿoÂÉl®Íu?wõâ^§7ÈÄ~œ”†µÞt˜:ùJØ…r-«,[ÒY'€}e"ÀíGæ}ı9„s)\3&9¬£¡¼Ô·=XÙMˆ´vl­´a†RE~Bç÷%ÆöѼ½qPÔ8Üñ9µ¹úZÜkÀÖ«ú-o¤ÇÉ,œF±ÿ4PÑFç7¬ÈoÆf ¾*-ÈOعÎT6ÀU—j€Ã’VI5ÔMÕÍ’¶=’¥f/N8›˜Ð¸‡" 4”‘9åcŸ‚a³2Çå>.L²Ÿš¯¿·¿…†þÝŸê]·µ6ßMŽš”6Êœ×iú/Õ›Úϳ*êná°fh€2™§¨(­I+EÚ²¥d`ÊÂ{8#öÅ¢ŒŒ²ƒ–ÀLošép¶øk]J÷‹w…tJæ¢m4;gê‘ÔÑ# F»¦sÖ$ÌëËoŠë.óÖÙàzƒ:Ûò¿¦Äð EOhf¼‰n·<Õ}ý½ü,7öî5_o ý»„ÐÚM÷êK¬ú°ÌÁ¶ÀßãôÄÒC0F5Τ îy¾Vëw~Wáú +U–éBÖ“z*±.K!D´ýÝT¨$´ªZÓÓ¢ñÙ©ûqÔkKv.îö‘ö7ö)œ©t­kú½Í®Äk¿;½˜:rÝT%m"Du¹…«€ÜáJ¹­Šc" ¶Ç±=LAn7š¯¿·¿…†þÝÁæ«ïíïáa¿·qðp…æ«ïíïáa¿·pyªûû{øXoíÜG¼!yªûû{øXoíÜj¾þÞþûwïbþðm>ÈBÙP!¯ 5\䢦7I‚<µ@ì²g€¥$,Ró”6C.R¤±K)Ïš(ïLÏ6$CˆyþTÖÔŸéÒmÍýy¾ÿÄ[s^o¿Å°ËÖ¯ÇÓߺÿ“â™W:•®•JÝúš›VÆ¡´–§tl£4Ãoëv……vÀ‚*Õ" ø«0¾Pn¢ÇEY lXÞˆ‰á­Å6f96Õøú{÷_òaÜde¡Ö§…>É{,9^§$ÈÖ‹‹;ÀƒBìu¹^Ó,³ý——¬KN§¨kE“„Y9e'ò‰$Ù†|g‘gfGŽÞÐH,ví½0´ê§×Ja®£8YCQŽCaÖs×MóؤçŒÍÉœLtä}ò /<@| ÖqؼËap¦Wq… ‡¶AĹÜ&h ×sõ4’%& FFƒ²×µwñÇp+H*Þ%KRDQñ‹~8ü/ILÌÖ\7Bl“K9g-éo2XäÛL²Ì¶ê¶¼äšÂ µA´–eFµ’Ð-³-ž¨6イKh¡râ’Xl©0À“d9£æÇ“›Üà CVtãÓ*SÙSË*o¶½‰<òöaÿíS>Y{Ix?J÷Ÿyø¬ÿÖuöï¿þ‰ø½a÷¿ ߥæ‡Y5=ÑH=ëÐ6šÓ`v-“mme›llóÉì[~aÙ-5–¿C+}lp´q˜ÃȇZP ʶA…[¬Km,¢‹_®„(q¦50ª"›Ú`ØÞ,ÖùÄXZžßl—â¼æ\lÇ8ÓaØï ù°áœØôÐÀ{Ò(p`X§â 8è4öÐèëÓjåd½šì=a\¦Ë\lºb~¶ÔÖÛžTçú ²c&§¿PR´ðÈ’ÇŽu¤” rÂ3÷Ee .嵡¸é‚&ÇSeÏ|ëâK—ÛúÉåwê=¼Ô7²|çU˜íZþ.Ã'r,@–OôDÑÿ÷¯R?áD2c‰ÎKJµ”¹íºf#ZzÁÍîHZ®6²wyX¼ÔLP­ÔK¡½[V(ˆþ^1™^ñâ:Y~¹âÓ§I9),?ÁǦ_3ÿü¬;Wäeó7ñçïõ«ÿ¾xî/=ÕÖ]ssK¬,û/þ_±Ó2-\&Ø…øÔ+œÍeh DR*¶¿-" úñל‹ç"Wf ’½8y±ˆ{Ì\ݾ¾l¥µÕ°Ëw\m¤‹Ž¼)êX{…$Übž Vh¬Ý®Ü'ýqGx ŒãènCA9­x¤HÌ …ËÉêþ€! S§™]5 +FX”ߊWšê‘&²¥ñ°íT·4ZØ¥]–•d¯ Ú‰+–™‡Š³/*]ަqÌ (TQÞ—è rÅŽ“S)©ZèZÂÖkG%X c~›ƒ{YÖ\‹3 §­ÔKvJ0ÊѹyyP¨TI`墴$IŲРAéTŽG/¿úl_…%±ÔÆÆy¹äÓ—xùw¿k«ú<Ô½Ú·=aá=ò›úT ŽxŽ ý!\ñ…R~µùœáx‘ï BŸN=2ºýªüͦû—ÛoÈßiïùÕ æo³o‡y-ñ}äWfvg…@ý_v§q{ÇégŽûîo|›Ñ5Ƙ¬î{ç`ÒS|ßÙ¿+¼ïnî¢]íä¬Ě×ós“Öûmb|±Ÿ¢!@xǾúéÿ!¾I¿ƒ€8888ààààãÞ•5£õ'út£ÁÁ¼ÿ*kGêOôéGƒˆ<Þ¯²7«ìeëWãéïÝɇp›&ÇA뮥Û=ÓϨ ! x«¾ù¿=67ˆDg=e¿6h’cL'Úá ‡Ìo¨¼[Õîã¡à×_+ý§°U# Ѝ*B€NÕøú{÷_òaÜS&?Ô¦Ûb=ò׫šèÍyD8²Íça¤«CVÄfD¬"c&°Ç±I,ÉoÂqJ8xKc1Ë<¢q ‘t>\7.,îØÝ[ií¬¨ôA‡¡?´ uC:îUÁÓÍR/cæ â.|ЏÉnœÕ Ò¹Éù –¢³X¯k{=¯8ÊÞ8¶ÌæýŒ·¬+"íÒ\Ün£Ç5\LôÎNÙã[Áª·ê6¯-í–éÃmK®ÝA%ì«ÈäGZ³•šMº¹TÖËéœó XK¯Ìᤇ‡^BX`û—Yu»c;sÚ_) Û³¼c´|åªìþÕî ñþÜï`<Ç< /ŒxgªøŸƒ‹õßðøžóî[´e%°+pSošv¬»TŒÌ5Rݯ”¬•±ì  †7!…Ä9Y£cÁü ‡ŠG,yò±åì»’þؽ8×K›ym:·N\ºKÜ€{™Q3ÏÐÆM¯Ø¸#/µ¼NqÉG"è:–`—¸2uÁ{œ8Jþ|á­WúóÅ^ª)juªöSq7÷¹Íä¾m«¾‘9·)H3lhšhÛ=çše_[A‘W´1¯ ôà‰ÍJð@ÇPï‰CÖJªyœRÏÖ´ÙÉó2«?[´e%°+pSošv¬»TŒÌ5Rݯ”¬•±ì  †7!…Ä9Y£cÁü ‡ŠG,yò±å÷ÖU³KšŽÍ_$1Øu_ty`øuL w:ã¾aëØm H8¡ÝàãÇ ÑÛÓ‡w¬Gõ¸˜¹0ò€¥«;Kµõ†ŽÞ´Ñ ¡»ÊWˆ}zfÙ›c´Ã5~k¦ƒ”b[×lØ¢áñGxq‘puýg‹(6¼“bÁ•RXº«‘:ït‹NL¯ú¤õÙL@µž.u…×ÖǶÊÞnpŠã¬îžvjàÍžÂLÛ9ÿ&ò§Ao6mÍPR÷%™À!'vÑ”•»=4U;V P»N:³\êƒëå(Kvë%“UŠÃgƒŒ#·ãÂñãêY®)ií01òC9"|~^\~‚»£)*†yµ5;VUå ¬²®ëå$©ì+uJß*m\¼rbÐ’ ­”9yUDÏÉ"rß/(5Øã…ú=x¨&eºû¯OPuå„Û^ü×M=7¡ðÜË@0Èw]RߢìJ}8K,‚<é@ù¯%“.æ «Fܧ«›¹1&ºMÊ=ì­æÈ?]=Ò6Ûi ÄqK\Mì^ƒ„¡íx°g¡­åذ&éÝÚp­ùRK‚)å‚QÉOÑa\`ÇÆ °0 Å21·<ünÑ”–À­ÁM¾iÚ²íPr30ÕKv¾R²VDzB€HT6 Ü„äAfŒ Œ[\sð@,J)±çÊÇ”a£)&Úž= ×NÕŒÔl@k+1i†ùHÕOm+0™)«Ñë¢B$¨a¥ <ë"q‡å€0Q9EG‰Î:61e’mo½´PŒn&á1kŽønöí³;-f\XTío+U‚“½§uUíZ,UKzëVl–°PXŠv ‹a5áÄÖJ3©‡$ÆV!Öw[&¸èµª*Ù³†«K/Ý?£Þ6 ³eç×sï=t–’¨ÒM¢ÉÝ:Üd¦úø­e®ÒØÊ§C|ësYNAÂMlÑuÃ)cÖUµÆ˜f¸·kä‹R¼cðîáC±ÔÀ¼&ð‚°N‰ñ•vh”ð³‚Æ™ëÐsú‘QÐHÆ÷©q#æÇÑÖ]n.™c×µò)^\o¬Ûu P‡52Ô²J t•ƒc«É”ÃÁ‹‹Æg63A(zYPAˆÈŸ’X¸9°³¶áýĪh=\¬ o‡­³µ{¢ºÎ‚‚ɪÛ\ϱŽzÿAØq›ÈÉÔ Šè·PG³Ûï9|ì 2•aÆ"+ ÷µ²k¤f-q¤½œé„ÚkÍ˾öìîáÿ•v9ûÌû«¸ZŽ5~™<øH?ð?íÅïÍq|1T80ÿùü?Ö3µ—[„&WÀ|¤×”ãÄ6¢CT!ÂLªì‘eL`× ñ€bŽð8ã ˜-‹0EžˆTé’1çã–RvlóppppÁÁÁÀ Ǽÿ*kGêOôéGƒƒyþTÖÔŸéÒy½_doWØËÖ¯ÇÓߺÿ“ã0Óú‹ÒN´–ö_"•­8ê=í=ž¨®q¤)bdfdÔõ(®V,êÂgybÍ4.^< RZÌ%Ï#?—ŸÁ«‘ý²¹´òÕøú{÷_òaÜ%¥mT>5é/ºHy³W}f°·»Ýa¼fšI­ÓëkÁêX÷qK_, ~u“…TÿaÚ©>¬I ý¶ÏÏ9ŽmËŒFnRÞÀ²S¢“i]‹¡véí}¹J—;5q$=nÉž"0:U†ÅÐh\M‹ˆ,ÔV²ÕÀÜe `RÇ ä6‰ñùqòå¸\'¶²ùÏí#¯žÎ?(oþj£ÈoŠ¿®~üåwÇ¿ÐñËôWÿPþhõÎ"Í/fÕhCú¦ÑŒ'#m)ê³iÙº¡ª-ra°mª–¸ßBˆ0í ;2G/9‹Y¼w@n2Í‘sYaQ›bC‰"5"zÇ,¶Ò­º­·»YkM¬¨‚<.W–§yvðkhpûÀj® xÈå–Vðqý`â)C½Eˆ¾ŠÏ<ŸT—–DݾÇlu1©4ÖÁì——õÛÝÜÝÛÍM~Ým@Ò@~`IÈÏ?×ÙÙŒüØoªúï®Íõañ¥ËÀ”z—Kר=<=ÎöÛ&Ž8»±Çº´¦Ñ„í‘®ï8Y2RVžÇl²íNÆåô²s V3 J‹è_ KöÛtÌ1Œ^—L÷æGë=YY-tÆ¥\µÅ|ñn{õÔ=º|ªªu3Ï·=[W F•ZSèÀ Iî·ˆ^`Acçd¢¸Ê ™Ìeƒá˜cÍo©ú“ÖÏW=?¯–¥´ú™oìbG=ƒ®ê;'Wç J¬îÏPŸ¨^î„'Š­ak;:²ºUÖJ—u&B’§˜ƒXœº+ÂêmÆÇSO®~—Ö¹{@ym»ÚÏ¿w-ªˆ¼Ôz˜¡iŠ¥VÝj«|¼‡CÊ ¾ßðó«•u@ô,3W+Pì¼·ˆ®H9]4gT XXzÈíuFªpîük÷S¯ËÚFÉ"ÈdÀ¶‡lX58% òÕÍÎQµÇ1ÆÓ†ˆaf±'a+zÌvÒÙB¦®úÂÆÝVÔæÍjV©³xaîWŸ>X4 ¤À^ÏøÛ׿ep_Š)*¿o.´zé^LØ x$N^IÙ-7 G§ë:­¨@g*xäm¥=VoBÏP¦¶‘7&ÖÚ©k‹i[•zø9jGåç#±k7“­ÖIôIIY¬°¨Íµ<ÃãR'µÏ$³¡Rª“Û¦în: Cxj#D×¶»Z×µí¶¶ôö–Ù³äuÙÉ(ì Ñ[ت—Z©šé®U–üËôy*³MØ _*ð¹ÁÂÜ{› P¢Bè.¯nd5S™¶9¶¬¿©¯¥¬‹<ô•©3ˆ2½ælY1ñEýù‡æþûû4l?ø¿‹ÎïT^wz£Ýf^€Ú¶Â¨VAȂٖ^%)e™‘)’4P$ ™!yÉ4°õ#˜cÉÉK2¡À¬€gòÇ* °â‘"ÌÃUL$d½‹¢v‚ÐÙíÂÚ‹/XªÆ:¢‚DZvEzUn¹€ÜÒ¨ÐíÈ*«©*yö›:†r í¶-œAÝ‘ÚÈd]%°²)¡œT¿ù‡æþûû4l?ø¿ƒ¿0üßßf‡ÿðš­Û[‰ªÝµ¹ÜðqÃwæ›ûïìѰÿâþüÃó}ýš6ü_Âj·mn&«vÖçsÁÇ ß˜~o￳FÃÿ‹ø;óÍý÷öhØñ ªÝµ¸š­Û[Ï7~aù¿¾þÍþ/àïÌ?7÷ßÙ£aÿÅü&«vÖâj·mnw<pÝù‡æþûû4l?ø¿ƒ¿0üßßf‡ÿðš­Û[‰ªÝµ¹ÜðqÃwæ›ûïìѰÿâþüÃó}ýš6ü_Âj·mn&«vÖçsÁÇ ß˜~o￳FÃÿ‹ø;óÍý÷öhØñ ªÝµ¸š­Û[Ï7~aù¿¾þÍþ/àïÌ?7÷ßÙ£aÿÅü&«vÖâj·mnw<pÝù‡æþûû4l?ø¿¬{‰O„::áŽA q¡`ÈC^/‘01æ•›“.y¥ WÆ ‰ËÏ“—šI3"À‡‡ÑÏ"dœñäËÊš­Û[‰ªÝµ¹‚;Ïò¦´~¤ÿN”x87ŸåMhýIþ(ðq›ÕöAæõ}Œ½jü}=û¯ù0î#Þ$+WãéïÝɇp¼¥ú±mŸ¨-÷Sh½YbU=6/ch[)mÑ0‰l:ÀÖ|ÁÉ>ÙK)³u(Ò$@q r»È>ÜædæÂ…yvAük°Ù®\ÝŽ*ÈÐÖïfêCk,{Q#_ê €H­]ÌìÂSúÖCÇc«¨“"u§¶;ã¶=zTИŒÿÓÎ:Yã³Nâ¬mGTJÚ•¹ô«\©¬´…Ïoï?‰Ÿª§9lˆš˜U”eØåŽªx³Ëó韘]}®1*ó`n¯KÐíÐHŽ8Ø›ÁÅÖíû¬- t¦.›ý¯]5¡¾äx3®¹6ú‰º–ä-ÐÛ9l†«ÜK8:"Ö+Ï,Ÿè“©0€Çyd/“è±~ÓZÝäÇ´w´!ìóóóæº“»õ£ãý‘ñßô7þóãWè÷ý¿û>›ø8„lÖ·L®,q;H¯.7ˆ5•Dø:×Cš™jY% ™6¾®#Ê áà‰ÅÆÐTÖg=,¨##£ÀÉ,\ì8<4íÀÔ«‘6¿Ú=tzo¶˜f«®ÚÑ’Ë[]žÞ)…FiÅ‚)_>0Yv)('¤7Û#…£8ábø8„=¦µ»Îgh:CÚæÍt?9þ*÷ßê»ÇûßâGé—ýÅ_Òú÷œxr7R¢2 M•´zé¼õ¦ÃFT‘vÖ˜Y ]ªSÖE5Ó¢Aäfå(FÓY(êš5†¾‡3hYí«0É ð¬rÀ±|PZ©n¥\û}°B©cƒ‰ykñÅU™CM7Ö˜ [l†“˜œœ—¨èc_ 7¾œ£ãªœ{‰È¦}hÈ>P±òòD™*?nïÚ è ®õe’ß“Ocn+ÝÙÚIn"ß5ÒJ–˜bn²l B0ÄÔiùù†@—y(ùyaHÒh 1àãùz¯ÉªEná×.¶‹Mž+zÂþÔ—Ù*\»]Íîekƒ‘ƒþàÆF¼ÅH1Äx;:ˆ¹šª Ø~Ç› <¦…zy´UÛfµº³²Ti«`é þß°<°ê§k] RÉvî³ÒÕUûEéø ìÈÏrà7ÆB–w¬š? †‰ÜŸ:÷7|uËŽÚö$ö^ÿ{¿Æ|Íö’ª‹Ù¿û\Wfvg…x'ÆV¾â÷ÿüÅï^¡’ÅÔW%°+sœ¨kЬ»T’²I®¢°T¬•±ì  +1zqÄÒæ…Ä9Y ä¤‰Ï+ü ™–?,yñreSàâWÙ­nxs;\%l ßa«Ÿ½½Î Ú6„Ü%z’Õ…«&˧-Ͷ)˜åa!­.>Ç•§£N­+ Œ³¢¥¬˜’6Y„À±ƒ³ƒ€ÏÜ›]?4þí…ÜÑ ¸urÓˆ/_Žuhf¹FÙT“n“!¦FG* †Î†Ð³Ë¶8Y¼bÃ]@Y«YóÙ8—#)Hƒåcâôÿbëm_º%Uš¹±jËzý6Õa^é ˜-š” rЧªÔÛÒÏ2…’ L‚kðêøa“[ëNl#ù‰–´Vpš%×88K­Í)×AêàÚ¾‚Ýëyç÷EužÏìvË¢“1¹Ø ‡£7¢Þ7Ëe#^W þVê˧ƒz$ã{TUQXÂ̜Ɣ7Ø®>ŸÝ± 9EÕËN3yïuÚ½yœkI6ád5©JSÙŠª\EŽcYå(G]J:¹^°fJÍZžÚÍ0ixÒÉ-Éx8D¨­Omͺw•G²USœƒºìê¯biª‚’æÒÃÐ s‘~@Ø«fP$È I@uëzµ}…d“ÈꆑYÔÌ×”GáêQfÁèÅ’×Ó/¯äiÛÃ&ÃYal«6Œü|Åš£Ht–Hà²ê-`ؽ[ÇlKÜ2Ox‘gg¡ªë&@ܪe“ˆ”x˜a@Ê7žflæƒãŸ»žÛ…«[_~èï[½º‘«×z‡Ô1ã§Þ:'Qs+C°ïÏE1¬ TpÕË)¡j¯0Øq}áøÆco”e¨-T\”3£XK³Äôú àðúÒW›¹l[Gµî·Ô}‹ ¡~UšŽ×J8ê®±PÆ*}‘@aÍg[å÷‡bŠ*¼§Zu÷:itaª‘ßÔY æWHNYžg“g¹/*M못k´í¾è®6º%ÚuñM¿«:\×f»rË×xBÚm%­ËX8øº¥"1ÃÊOÓÉM|  /²8sWWo:H¹Ì™Mõ¥vì†Åî=÷¦”í§ÓÞ˜°zKÒ¤eûv¾mÓB›§ˆ$“4Ý—¬QÎÉÈO«F@,k×”/:¤ñ$‘õ¦u_®M7‘øðÙ–VÝVØS\—¶¨6ƒ,²Ö¨Ì&å¶e³Ð$ 8¼Â ¬ybÍ4.\¡¥„’‹&dC™4|Ù1óžÚëm7¨¹Ø¡3ê §¬—>¶ë¦äÒ÷Ãõ«[°l$Ýqw Ø:»´Äz3­ì¨©ãaÍ -Uð³¬Au 1‚æ—#<9ƒ­±5¬ŒÍk0Ò·ë€^=çùSZ?R§J<Ïò¦´~¤ÿN”x8ƒÍêû óz¾Æ^µ~>žý×ü˜wQÓ¿n¬¶öçó"@OfN¢Û5¨¨}’4ðß­©ŽÉísmÞ:ÊÉëïû’w’ àe{ÔOZïy½ÿUí_§¿uÿ&ÂòèªöÙiS'PpnZ±v€½êc¶IX¹TVFç[/SÚÓÔa¥ËÐÛúµ¼9ÉñÕe’’¤|ÃàŽfLE=$¹sE›÷óPPö,>¨¶]€Ä^FŽ )ò­óƒq–¶æÚâËSVζŒÉUE}iÚÀYËÖkÓºí…a@ˆ>BzÑ®FßI_àê9¦T-’ÏUZ—'n³×þSù¬RyjµÖÔwžg¹×*Oh;•9ýA¯ôCÑŠ@_:žPÿ( ÑR}Y`°Ãñ~òé›·Ì•ïPNžJh@ÎѽG7ëèso;Úp¥½zF°^S-‹f½u×ùæ9-wkMý °—XEEË:½· [CÛ\,j'5‰kŸ‡ê÷£ÝSöæØÜš±¸9uë×VPõu¦&ëK£ª}rŸGacZ•Õ‹«Q®­ì5§°ÖZî@É.ÖZûJÝo™¦¨7ž×T¨Z-VÂõêeDèEOlz >ƒåØášéd\u5i%ϲ`fž'4DJÄÝ»‚«;ž±«/&Tª¸k†Ë[-´2œ¶¸áÊ`aL‚½Ïk«'à”öóðD7þ¯k®ÜðÓÞ[y“ìÓç/‚x?r÷?dw?û ïðö½Ëâ8ΉÔ}ÍŠùÕBÁ¤µãÍQý^t…5W·Ú­ªª«jÔ›ž¡Öæ*[Ê«Wr¼¬X^a,<–žŒóQ¶3ªà¹ÖãÖOÒªÞÓÂn÷³Ïð&{"öoÿPß—³—Ý«úçöKò˳{³Ç;#ãÇæNáî^Õÿö^9áïøÃÕ¾¬”•½ÒÂ'R[ È0Bëº°Ñ ˆT]"¤2zõÛ_DÆ)¾°UzÇ'IË%¿˜G>¿¥<=Amq[²ê>b|ðŠ9FÇÇ¢ÝZT­ÓÛiàÔï-·9y¯%TñRݶ›#¼újƴÚ‘[Ò•ä+Âç( V¿B~ÂfôG.¶±<œ^s%r1® Ï]5˧†æ¢IÓªÑ>ÔÕÓÉ:6Cpƒs¾USë­¯éíAÖÕÇ-ž:BÛ-•"ì°ém-q*Î Ö› (­\¿† mUÅq'Ak¤5gKýâ«u—¡üÖmnxygÑ÷í³”E3· ºý~LÛ šRÓåax¡ÛÕúÄÞÔXùÅuëéT«„“‹õ©lѬCI`0{oT=L©õÒê%° Í"m¹Èk:ÛÊ€¥cZo7 $¼Ü3¯(TÕšsm¯$àù¡¦8‰”•z5„L=råÙ¡K³*ÍÛÕ¾½R½ºX橞*ÇÍ>ßp{hm’ÓŒ塿NjZ°Z7W'ÔKëD#Íi¶Úç¹j’TäúÙÆØ=afƒP®¦ ´²zf„, *dUÒÍ®jî˜GÏÖg,®|k:µÔŽz6ÚôïÃ~r7I{u vVˆ.õ9˜[›&k6°e¶ÀÔæì¼Hê÷ Pú‡Fé×Ql¶@›7j±ù¥aê"FüDÛë75€lª?• u:DüäDµ"À»_>7%À°|EÍxëc³TBž‹Œ øZztû({nûR¤{4÷Ç–]óáþ=æO®z¿—ÞUv·›ýñáÿ¥ý§Ø^=å·ü§ê[þ•qÃÛGÊ&jãæ´\”† v§QjÏI-(7õy²"Åž"U¼5“F ®‘¡XtæÓã– dø»®[ Ÿë¤Ø€ØÔÈ” «ZK±h:éÔ.+–†ƒÚvû­ẚÿUeÛ@šÏad¯X ×ó*­‰¤v3J–Ó]("TÌ"I9Rï8ѹž†Ì5ŽAh/Ü@íêJÏ®šDŸnd´î2”W]Š»i0_×=Hù±u?OŠøÛ®0röËÏÌ¡dÚbd$ØL-võlÀÌ–L"×1¢$°œMôâ%„•W9:ZtÛ}ˆÏfMDZz³µšÎ¶in•F!eÛL<{IÖˆ×hƒ%2¶–$ÉXÐý$cHn }ƺo¶«mc':m-aœ$ß’¬R¼Ãª?T×%$ÈáI=O˜)Zâ®ÁÝõývRË« ”…éÍ`×ñYT‡Ïž2ð¤1ÆK5¯qöQ‡m˜ÔN­Û^¡zénë"3ƒ]“ªoz­¦” žÃX¦êW¥Œ²öjh;¬˜›aO ÑaÔœ®CPGÒ ðf¶•:Aê “K­\omx×˪ªÒ ]fØ S~lÑW¯sÁ"EkJÓ‚lKj¼­éTC\µ¤òú ÔÞZ¹ºe©*úÝ©2 ‡( óààààƒƒƒ€^=çùSZ?R§J<Ïò¦´~¤ÿN”x8ƒÍêû óz¾Æ^µ~>žý×ü˜wï«ñô÷î¿äø^^–=Dí‰Û^¥z£~ç8\¥!¸[1Y^$'á¶~‰©l°µ»uD$š¥rBiÍvÑMa$ÐîÅg´@ص™ øZÿ‹Í¹sv88T”.©]AöÁo®c–œ¬e)CƒÔò>êãu€ÌÌ‘ê{:×¥–üO[iD­, åÏL-ÆÚŠr¾²F¼fôÏ6˜°­b‹‰iÒÓôõÙ[Û`v.¤ôWLAì²"…XꟿZw¶ôa¬›§JÞÊaüIίª*ŠøÐk¶»*å\úՖì+Î~WU°·Üö@,úðàãú„í&Ê)oM-&¦eÚuz&Ú¾KY×MNZXR`U5Îbq–P½;‘ñ@ :öAX–•ñ!†™Èy°j…¹ïÐã_æ÷(¶º¡|UÅoé5ÖÓѺܹH8]¬Û-QÓè1=osÓ’*1VX“Í ì{½€ç4©è5=…Üшò'-–ÚÃ[†a88Ìå.©´‘„m‹`°*‹×ë/YõÒfÚ¹kUôФ°MZ邽ç‹iÖ«0ì#Ê  óHŒN¶?Ðö<Ý[p ›Z]"«VL£cO®“ºðëvCˆŒÖÝÞ`–gVCnØpPiÔ1%eê‡2eŽÐÿy‘Ìßp,ƒPHªNVE+ƒ2žÌ«LµÙ«‰ÚÍ ø¯,tçÂàmçÑšÝd±5)†ùÓè í†÷­t-nêàÖhÓ×Vì¶FzÒC•%†1*ø  nE',à-€ÂDñ HÄX’ÔŒ%B_ ÛmÍ»ÜõwRŸWÜ•'€ÿwN}úÕÊ«UœÊÖÍ♚'{1E¤Tí6„°›OÃ_ÛÀ¹Š&‰i[¾E.È!I3€Ó\e“—WMnGÖ]ÕÚÂÉ7|ŠóDv«QmÐÖÐò¹±Ù*i\7\“eD]#9ËQzTLÌJ²Š†g<…¨ÒãÁ‚D°ú®ÖÊ5qê*F­nöÂ]TƒÆ¿¤¸À i.i‘ý£+ù ƒq[4ÅŠ­^W ñ9Gp?t2Ö>®T¯9%¸ŒéНíŠjo÷Ñ#c¶sôÈnÞlS“ÁV{­âÊðd™«Ôbí0”2Õ°€ö|‰\󲨥– ²z…ºÏMfÊ ÔXì(C\p͸Y­›`NI¼$5ò½Å_£ûkq{߇ORõ.¬cI¥ÄiÎ;-’Îd¶+ŸJ=Ÿ.û².5%’œÕbQB6+mT*Ï=F}¾c ŠjBÁÒv×qð£}}æþp|(ßAŸy¿‡Ü1Ã^ƒ5áøJ{'¨¶MÇÔ¦–Ö,›Hƒ^i¯¶O™áŽ’=Ìï´=* ¸Jì1ÃÖŠ)ágÈ”ÑÜ,Jþ¤+Ÿq>7/›ž:yKô„d—ÑwI툳o’ Þ9{:—çžÚ¶“6ͲlUnXtg…Ä¢ŒÀÇæPŒî½$j”óP0²ÌD‘Ž1'…è3ï7ðûƒáFú ûÍü>áŽðüá¯Â`éѶ»?s6#huÑgj¯™Ï6iôZÝ–G_B-º­’liµ,§ "5˜ãmüx„ *êÐ*J|t $K^.„s³‹>½‘ÿÖÔ‡ÿާÁñ‘óå#ÿ­¿V¿©ýÉñóè׋‡ð£}}æþp|(ßAŸy¿‡Ü1Ã^ƒ5áøZj2…¶*}§u|U”¾¼«M=¯¨Q·È 6"ÚE°›K¯aÙKÊÎP—c½Zo H±à°³À…qÈC9'JÁƒ3¢èOPݯ²t0·R!æ¢ï ÷öwZ"X§vFç¿+ƒÓ䂜“åe^W”Í!dDÅ]3^éékÌ\*HRyA´«Á¦,_Âô÷›ø}Áð£}}æþpÇ x~ pׇá;Ҝ螩z“VYš{šÞÍÂϺ(N¯ü÷HK`#ŸYØvFÞuq•AtÙ«þ”ë@1Éòð¡ n°ÏzÂcÖÝiÖÍE²iΠKv±˜ÚDêór½¼° ‘éN`½ž)SµÃ¯~ ´,¿8R<¥~ÞbhõÑ\™³–ðI|¼rEŸ 7ÐgÞoá÷Âô÷›ø}Ã5áø1Ã^„§ÒoQléÿAjºm!ŽÃªüÓî5Á#ÅÓ&wÅÕcØâ|‹2ÒÉ® ¼lR>¼º;ÞŠà‚7­ÄÅtœ²×î‡wu«š•A´^) ~ªù®=DWn WauB~Þ7íÒJmnH}1àü}ó]Ù˜N¤@™é¦6Ûc1á8[¶ÔV›¯×Âô÷›ø}Áð£}}æþpÇ x~ pׇáAmî‹»"÷AìBˆ–½Y9a±õ¼zê«Q$ÛÃ_(;¶`ÚOb"FTp_Š(Ã-è2Èà&£Š“æ(“›•.ñ7Ùz;cÓ†¹t{G°ß®ùϲ5ޏ¾ÑÒ•¶& ØW¬y+݈r݃TJt|sÑk€J1)†@I¯Ä&Ñî|(ßAŸy¿‡Ü 7ÐgÞoá÷ pׇàÇ x~‚·è×°Uþºj…6)ú¬.Šë@›ÔTmI–˸+Ý|ÕõcmY¡ë%#c9%ó7Ù'Ç'» †´jˆ;#Ë›ÔÓœøJze7¸i–¶j-“Nuê[µŒÆÒ'W›•ìmå€`DJsìñJ®{ðq¡`Åø¡Â‘å+öóG®ŠäÍœ·‚Kå䃒,øQ¾ƒ>ó¸>o Ï¼ßÃîá¯ÁŽðü5£ƒŒ—øQ¾ƒ>ó¸>o Ï¼ßÃîá¯ÁŽðü*^óü©­©?Ó¥"[ÎÒó¦Óh²ü ¶»—Á?2øŸŒú—ƒ.ˆÿeáâ½gÖ|+Öÿû óïþñÿ—Þ½û!ÄžoVIæõgÿÙ endstream endobj 412 0 obj << /Type /XObject /Subtype /Image /Width 430 /Height 573 /BitsPerComponent 8 /Length 29622 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5lx}ºi¤ý&“ÿЬ& ê¶4TåcƼ¸VÕ#Kp²©æ@Ø}Çõþ´ß+ØW´  Ð1¿ïìŸüUð‚hô oûû'ÿJ8šqÑ&7NOsÅü¯aG•ì+Ú?áÐ?èß÷öOþ*øA4ú7ýý“ÿŠªúÜ; Ù3Åü¯aG•ì+Ú?áÐ?èß÷öOþ*øA4ú7ýý“ÿŠ£ëpìÉž/å{ <¯a^Î| áõ릑õšOþ*˜|á°pl?õÞOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ^Éž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸vdÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ;²gù^¬½ýÿöÝ'ÚâtMŒ0ò¢³!v>÷Íž1ÆÇjõÃ௶}g“ÿФÿ„/Ã_óâ¿÷þOþ*§ÛQì>I÷<º_ë“›ÿaXäÓäÓ’¶Eãq\¶wp9$ý),õíVÂëEž³'GŠX­ƒ£Þ`ÃoÃsíŒW©Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT½­¬³îy-¦§¨ÚG Æ¢Ô®ŠÒ=¾Q²ììïç‘‘Ûµ øšÛL‚c¬D×%õÔ(¬–P’’c,à¡ê9Ïèð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU­&­f5#ÇÕÍίy«6Ó\]½Ô`cËn^}G£â]núÚîÜ.›joWeÕÕµ¶ÉçSÔ3g÷Àêð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU7Z“I5°¹%ÜóGÅW;,­t[kxZ"+ ofƒ÷èFCÛvÇr3Ö²Zúóþûmɲ’ÞØ“ ÒDLÐî °V㜃^¹ÿ_†¿çÅïüŸüUÁ^'Àÿ]äÿâ©*´—F73Ì%ñ­q¨ê·“çNº‘‹Ï´šh–SÙ`½jµæ³¬jÚ´7R[?ö§³b2¢$…²‹}s^²|áÁÖÀ¬òñTŸð…økþ|WþÿÉÿÅQíhöY÷<®mjúãP—ZeÃ%¤v‘¤Ð¹P¨I À†äòúU[û½CWÔ¤Ô5ci™5H—ˆ½ŸÏ&½{þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠªUé't„á'Ôñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*¯ëpìO²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}nƒÙ3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ¥> ðà:~ýw“ÿŠ£ëpì?dÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ; Ù3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª>·Áì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡`öLñ¿+ØS¢QÈì>PyÇÓìCÁ^'Àÿ]äÿâ©O‚¼8:ØõžOþ*—ÖáØ~Éž5u¥è׳™îmüɱRÅ“ÛÙÆQX(Vê~µëÿð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUOÖ)Þö$"E¶{O"à63’>¹H-´ðÊÛ¦b¤0 ò0ÈéÁ5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU?¬ÓìÎG‘;FoRP¢ŒŽ{ÿH¢Å.u•À û$‚½gþ¿ ÏŠÿßù?øªwü!ÿ wþF“ÿŠ£ë0ìÃÙ³ÈvYÃm,Vé·~ã´)'©®sÄ«¶Ò÷ÿ¥}ÿG‡èÿ‘¤ÿâ«Î>0xKÑô]:[ _%Þà«1›#iõ&š¯ {© Á­OJðWüˆúýxÅÿ ŠèÝŠ**œ œw5Îx+þD}þ¼bÿÐEt3Ë?÷qKâfËb•Þ³eaqmoy©[ÛMtÛ-ãšuF™²–9#ê=jߘÿßoμûÅú¬z6¹¨)¸Ò<íSN·¶Ž=Fâ’mÆhÞDc q”Þ~VùNj“i¾.¿›Z»³Ôgxî-nžÊ{is Â:7ÙÒ6ûFÔaº#¼BœÆ~s¸³ÈÏLóûíùÑæ?÷Ûó® \Ñ|MÚ-ô›»Ùì›ìòÊd¸-4î|ñ(B%ˆ§?fmªñ ¶ŽY}+úÜ×#ûWWÕ(ì òLSˆ¶OæNÇr‡“sFìêøËù„;o1ÿ¾ßAe©[êV‰wc{Õ´™Ù4‡FÁÁÃÈ#ð®Am¼L>!Gt ž=-åe„åá1˜!§8bâ2BÀ„ì2_[Â1^C£Î—Ú|öRµýÜËÏ’Îò©Ê3Žç¨=°H†¯©Ïc¨Œ#ù÷I oàò9ëÅr:–¥xÚ„à\HŠŽPbþuÑxý^›ÿ_ñZä¯ÿä#uÿ]_ùšLLˆk¶ÌjNw»F¸œüιʎy#kdvÁô©~ßyÿ?sÿßÃ^vëÏvšÅ´z˜Ôo C%ê‰ÜN¨Û2y%¢pqÏ—ÍØì5´Ò'VkòòJ 7(îbÆä¶ÓòŒ,ŠAQÆ dµ¥Á•¢Ò™C2 Ž@9Á#=äißo¼ÿŸ¹ÿïá®5ô½ZE¹º|7I¦Ä–éÇ:Jï%‰$n\«3),A/ÕÑß[­ÞŸsnÑ,«,MÜ pA,2@>£‘HD°x….mdºƒXYmâÏ™4w;‘02rAÀÀæ­}¾óþ~çÿ¿†¸ù­ui´m[Þ›©`T¶i$†+ãv2ñ_,çïä@2ë0ÝÝÝZfã¤H>ècÁã¦jÚiº•“¤ð™W½ºi"’|D!c+ ÀÈsÝ‚ãq8_Ûï?çîûøi§T¸¬FúQ#)eC1É g ÈüÅpöv¿%Ìpܽì^z3Ÿ?W˘8ÉšVÁ>Pá†:¨­+Ý"hµ; ÈîðÛÅ$!Mã!º29A´†8f#nC‘èû}çüýÏÿ [¿°Š[”™¤hãf +SŸZæl¡Ô—ÄwIÉ´}Ã|òa@ãUee=»CŽKÚ×ÿòºÿ®Oü 7ïõ›Û›=>O3Ëiícü¬¯ÌçÓÚ²g×M¬°Åqª˜d¶Ä’\m28PO'‘ÓÔTóÈ;Hÿ°|?ʸ¯ÜÁmu¨ÛËql©iËl†K˜ãòˆ2îÛûÁʆ?+qÓ,×í÷Ÿó÷?ýü5öÄ¿eûWö“ýŸg™çyçfÌgvsŒcœ×£-î¥1¸Yîd´’êèw˜Úß|Ѝ€Uƒm`À”pøÂæêž ¹Óaµ»[¨íÖ(/N÷˜(Зù#ÈRG†ÁÑ€;/·ÞÏÜÿ÷ðÓF©peh…ô¦EPÌ‚cpHÏCƒùå5k=nêêk»ž Y¡ŽœÞ˜íÚ ]ÛüŒ“ÁŒH7<»±¬ê¥­¯ZÎ[X¸4ƒváÞ ~Q•'#‚PÛï?çîûøhû}çüýÏÿ p«a¬*O& J Þuy¢žð͘ö°Ù‚0ÛI%з=¾J¿c¤jRL>Ýz#[X¼³›6˾CÈÜÙ*¥æ,­ü[ñÀXºê°aw6AÏ.Hüªô#¾¿Ðî¥.7Žõ­”ÆÂ…<“ϽdQ¥È»}ÿai?ô@¹Ö%³§ºÔžW¤–rª2p2IÇSO‹T¸š$–+édÔ2:LH`zsȬÜG†5y#V¸àŒI*FÙH.@õ=zÖ¨L××Û¯ô»ÉRÉ>ËhP]0ᶱт ÚsÎì vo¼ÿŸ¹ÿïá¦Çª\J¥£¾•Ô1RVbFA ޽Aq\Ý”:’øŽâi"¹6¸ožL(cj¬¬§ ÷hqÉbsºmõ3¢E¶×àGy)–v<ù`%ÊIÔn9ppŒ9®=RâU-ô®¡Š’³2 uê ûŠwÛï?çîûøk€Hñ"%¼~t‘eå;â`þT<ŒdlI`Uà«ȼ†ètÍ:æ)æîêìÌn'"6›ryFG(»zcH?xtÎß–€7Ž·a·)3HÑÆÌV,§>µ~ÿY½¹³Óäó<¶žÖ9ßÊÊüÌ:}=«ÿþA×_õÉÿ‘­ ¿ä¤Ø>å@gñ []Gk>°±\K..v»äà`““ÅX—T¸†'–[éc³»Ì@P:’sÀ®+Å·q. -H#3é·þd×1FÊP+ÎhòÛ$í“"¹Óµ½@jŒ— 46÷K#Štua)2í ‡p~éùŽIf3¼û}çüýÏÿ o¼ÿŸ¹ÿïá®J}f ’ãË»x¢•Z[v¹WyÛdªì¤» hˆS° „„S€r5vÔàÓæK«¯.ùÒv··„°°s,…<¢£÷äƒq·jŒ ôôUÔoUƒ ¹²yrGå]G…5‹fÆî[•Z ·|°@Ú‘œ“Ï5ÇWCðûþAZ—ý„eÿÐR„4uÕå_ÿä¥ÿ×ÑÿÐMz­yWÇ?ùiõôôZÒøÐ§ðÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š(  ¦.¢-'<›”™Œ„ŒœÇ^kçÂW³]Í*ÜÙ…wfvÎ úWQEr_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]m¬+—ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰¨®|¨Mi4KudÑ”fFÆHÿv»*(°Xåäð•ëÚXÄ.l÷[ÚÇ üí‚Ê9Ç*/øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&¢¹ðN¡5¤Ñ-ÕgFQ™#ýÚ쨢Ác—“ÂW¯ic¹³Ýok/ó¶ (çt¨¿á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš,¼m¥\Z½Õ‘yošà#ciP1÷z×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E mÏ‚u ­&‰n¬ƒ:2ŒÈØÉîÕ©<%zö–1 ›=Öö±Âÿ;`²ŽqÇJê(¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¢Ác’ÿ„6ÿþ~¬¿ïãñ5«ámçD²»†æ{gi®Þu1¹ ) raê(z(¨ãž^TŽTw…¶HªÀ”lÁô8e8=ˆ=èJ(¢€ (¢€ * «ëK'íwP[ùò¬1y²ó$nˆ¹êÇrjz(¢ KëI"µ•. hîñövYeK‡ø¾P[ŽÀšžŠ( ”+7@OÐRT±’!ƒƒÅ3Ëî7åG–ÿÜoÊ1ÿ¾ßcÿ}¿:<·þã~TyoýÆü¨óûíùÑæ?÷Ûó Ëî7åG–ÿÜoÊ1ÿ¾ßcÿ}¿:<·þã~TyoýÆü¨óûíùÑæ?÷Ûó Ëî7åG–ÿÜoÊ1ÿ¾ßcÿ}¿:<·þã~TyoýÆü¨óûíùÑæ?÷Ûó Ëî7åG–ÿÜoÊ1ÿ¾ß(2°È.~™ òßûùQå¿÷ò§~ûþš~´…¥^¥ÇÔšiVQ’¤}E%d´²?ŒØ¢Øž2 ŸÐ~U­@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ ó|â ?FÑ¿³åº[ØtCk:Ëu¼BÛíYáç\ 8 `•DUM¾EyÄúOŠö–Õæ™§’O&6`L( íöå‘Îw0>sŒ9FnšhšÚj:Žª¦xnæÕ-%ŽÞ°`ò¼»hî/™ò¬ª7Œ€¢©9=¥“âgxü=téwö]» JK( ¼n ê F¥r¦Aþ¬ÿÃ\_†tíKZÔdw¿½ËpYëS\E.c´Øá±#(uœåqµƒ®pHoJ¢€8}bÏÅ â}2Kº–Þ¶ŽK‘0Û,[ÇœÒ'œˆ©~ü%XàµÑÅ{eåÚ¢ýšú_2høèÇù .ÕÆÑÑ'ú™çQÔwW‹ee$†æ$¨Áv?‡øÐ‰mon.,Ú;}FîÁVA5¶yöiŒ¤§–ûüÈò€ Aúº§\Ïìÿÿk@Ó}¶K‘-³%â^²Å¬~|rF ‘ˆŸ äŸõ‰Êc ¹ÿ ýB5oüÿëÑÿ ýB5oüÿëÐtßO«Ýª}¶ÊÚâXÞI"¹ …Ü,LFIäʈ¼þ<¨ƒ ÈUÖñ&©Á§ÛZhòkWQ‰]Ê‹­þXÀá¤70LÜî#20ù˜Ä{w?á ÿ¨F­ÿ€ßýz?á ÿ¨F­ÿ€ßýzçåÓ|WqãHn¥¸{{2Ñ86ìe†(Â/™4a‹009ÔîÅcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±EcÿÂAÿP[ÿ¿úôÂAÿP[ÿ¿úô±P^Þ]Û[ ³²k©þ`%XÂŒzšÎÿ„ƒþ¡·þõèÿ„ƒþ¡·þõèßÚºïýÛÿR)u 5û»ûv€L#XÑ¥`(9sŸÆ›ÿ ýB5oüÿëÑÿ ýB5oüÿëÐÿ3ŸýÃÿö¥lVŒÒÞø™®þÅwo³òóŸs7Ú ¶òâgóîc‹Î2>QÔò8GZž¥9h$cáéµ? iw—•®¥4°+Iwj…#‘»àAƒÀä•~èÞOõ2þ΀;þ™Çÿ|ÑçÓ8ÿïšä¼Q~º¾›¥ÙÁ¨Ê—\\¿ös“‰¢s+*ì\‘ÎâPºœÆZ棧Eª\C§-šÏ§ÛÉjþdu±$Ø@qŸâÜ>_”Ìè~wý3þù£Îÿ¦qÿß5Ài^5M__Õ4‹ÙàKµ¸œÎ®¶Ò[FŒªD›gwFęˈYJ—9 ?‡¼Cwÿ¯…îÄsêv×:XYæ·S<­v0¨X.OœŸ Fæ^àÇÿLãÿ¾hó¿éœ÷ÍyÆ™ã{½CQЭÛ]ðô^ÚÚÜÝZKYcócR#F3üÒ;•vªAlü¡ïø3ź§ˆõ ˆîìàŠ(âß"+Ä$³‘ˆdU™Ü·ßå’" g+“…î<ïúgýóGÿLãÿ¾kŽñ}í½¦¡b5;¹í´Ÿ²ÜÈÆ+Ógæ\)‹ÊÍŸ1S6°Ÿ»‘›mã-]üIa¤¥“„‘mÇ•¨aº™5w˜ƒ*SsîT…Áh˜;=Îÿ¦qÿß4yßôÎ?ûæ¼á?ÕÂß/P°^|CÖ ±…¥ÓàÓå2•š[›!&&XXK4 I‰ÊýüŸ%ˆLÓ¼ïúgýóGÿLãÿ¾k‡µÕuh|j‡Uº‚Æ Û O+LhžW2“/˜‘:¾Ödb¥Ü! ghŒš^µâ{¯ Xë“[iÒ¥Ô×-¬r³Å4fBI˜ÚGT¨P%Îh´ó¿éœ÷Íwý3þù¬ëSkRêÆKg·ŽÖðA ËI f¤ ÊI “!88 `Z—𥖕l’^J‰½Ê¨e,Oð9ÿõЯ;þ™Çÿ|ÑçÓ8ÿïšÇÿ„¿EÿŸ˜ÿïËÿ…&™¬_Q¿òYÖ‹jÎAÜNyëÇá@½üÏâ5±Â,ÐÌB¯%·×Ø?¥^¬ùœÿîÿµ+b€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEAoeok5ÔÐǶK¹DÓ“¹Â*ÏO•qéõ©è¢€#‚mmã··‰"†% q¨UE8Õ+M“I4‰k·,ìúšJGµ¶»…–ê–5!‚²†äg€*ké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ5'öFÿ@ø?ïÊ…Ù7ýàÿ¿)þö¾›ÿA Oûü¿ãT5%Ð5_(Ü߯²E’Ûß´(8Êï•¶œ)+œªHàcOû#Fÿ |÷å?Âìþðß”ÿ ¯¡£ÚÛÇoowc1(HãŽDUEµIý¯¦ÿÐBÓþÿ/øÔŸÙ7ýàÿ¿)þdhßôƒþü§øPÚúoý-?ïòÿÚúoý-?ïòÿIý‘£Ð>ûòŸáGöFÿ@ø?ïÊ…Gý¯¦ÿÐBÓþÿ/øÑý¯¦ÿÐBÓþÿ/øÔŸÙ7ýàÿ¿)þdhßôƒþü§øPÚúoý-?ïòÿW½ºÑu Gµº½´xŸà)†RU†@ ‚*çöFÿ@ø?ïÊ…Ù7ýàÿ¿)þCN“CÒíÚ[ëp·»ËwæÉ#` ³»c€I8€ ·ý¯¦ÿÐBÓþÿ/øÔŸÙ7ýàÿ¿)þdhßôƒþü§øPÚúoý-?ïòÿÚúoý-?ïòÿIý‘£Ð>ûòŸáGöFÿ@ø?ïÊ…eAsÏŒ Ûͨ,0Z6 3ætâ·k>?ìë]dYZX¤Ss+H¨«òî<óøÃB€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEfišŒ×º†µo" KÅ·Œ¨9*`†LžzæF鎬ŸøO´yªY°´ië#¼i42TpŒ~I–eÉ—ËÀ$œrºmá½8êÒjjoc¹–UšAüñÆîªª F®ü¨ är9ªéàí9ZH’ö&1PE¨Ü †2ÊÅ"À‰sp›FœP M%·‡îôÍ&{Ø5;©au†{yŽV°›fâcÏ FÃ`W[Y?ðiÙÿcò§ÛæùÞwÚ¥óüÌmßçnó7mù3»;~_»ÅiA6¶ñÛÛÄ‘C„Ž8Ô*¢€jâ'ñ~³e¢k—ÐÛ[ n’Á­%àtÆW|Œæ5ÏÍ$ez æ(Ú¿l´K)5;Iínn÷”´žâÚ7 „%ÚQñ/É;ºpØ¿káÓÎÚoŽXšò<±¤M÷£DrV8Î( ) £(ÄgšA·H„wHêÌÿhŽöe¸bÀº`þc „Oî®*ZøãL½›ý Ù-<Ø"kß'l*gHÚ¤1Ýç"à)*y` ‚zäh­ä‘!y²ÅPÎ@û£q'§$R+ ië®_jÓ¯=ÍÒ\–U":ƒ¶M­u,ÒÄ®'jxVâÞH¸I£Ý‘€#2Tû‚í@4[ûSD³¾ºÓçÓ§ž ïi9â'±ÇõÁõä 4ÿS/áüë3EÒmôÏJµyÞ H„HÓÈ]Ȥÿ!€:´ÓýL¿‡ó  ZûQþ×±ÒtÉmm渂{–žæ™BÆÑ.ЊèrLÀçwHÁÎFfãÛMVÚÚfÓ¯aWû*O.ÐÐÁ%Äq¦Yä@ … «y˜o”‚Äzf7ùh¡¢³$ñ‡™§&³§%„Ͳ;¦ºA·<Î ù[€{J±&«§E©Å¦Ij—ó.øíZeºóÈL䕹±ô  tUõÍ&o¶ùZ¥“ýƒ?lÛp‡ìøÎ|Î~Lmn¸è}*øJ|=ýŸöÿíí/ì^o“ö¶Gåù˜ÎÍÙÆìsޏ  j*¤š®§™%ýª_Ì»ãµi”JëÏ!3’>VäÇÒ§žxmm丸•"†%/$’0UE$’xô%Gqh÷ÖÝKl¤‚Ïo¦pqPiz¥–µ¦[ê:uÊ\ÙÜ.øåN„0AÈ ò ò*ú©—ðþtÿÏýFõ/ü ÿëQÿÏýFõ/ü ÿëU™5bÕí´ÆWó® –á´,m°<ç9•qÇcø‡R¶ºibD7M\¦å@ÁA)Ø$œùH$[þŸúê_øÿÖ£þŸúê_øÿÖ¬äñðö§­C¨A-¶æyëѳü®È¸±ûŸ&HÝ‘ëWî|Ecg¨Ú·Ûì®®¢¶YìäIL’øeC§nHÏNÿÏýFõ/ü ÿëQÿÏýFõ/ü ÿëU™5]:-N-2KûT¿™wÇjÓ(•מBg$|­È¥[  ¿øFê7©à_ÿZøFê7©à_ÿZµ(  ¿øFê7©à_ÿZøFê7©à_ÿZµ(  ¿øFê7©à_ÿZøFê7©à_ÿZµ(  ¿øFê7©à_ÿZøFê7©à_ÿZµ)ëeݹ@Î94‘ÿÏýFõ/ü ÿëQÿÏýFõ/ü ÿëVÇ“ÿM#ÿ¾ª:q%ºL,aKªœíÎqŸÈÿ“@¶šU®«nþÑžæñà ,Òï"=Þœsý}ëV±ÿæsÿ¸þÔ­Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQE‹«xcN×5{ÍNÖÖòX'‰m®mÖU-#DwÜdtþ#Èï%§‡í-õ^öX žMFê+†-ÊùQƨ ç;Z2àñ‚Üzj(–ŸÂ3_¦³¡{kqk©j6÷¾OØÎb1f6Ëá’Rp9,pA ,\øjf¼¹¾µ¾H¯Q„X Ç}•mв†RãnãÃ. @ ô4PpFÑ[ÇÌó:(V–@¡œ÷ŽÐO^€W/ÃËy46Éo<©,¬ØÍF6šTkfIX«û"ÁÀeÀ5ÚQ@[øátøc¶Ô`ŠôË$·7Œ/ ’³PÅБWlh —`J)ÀÀ«ãÃ7ËâµÖ6D›<ÕŽ'In  RÒmBÌØÁo'!p©UaÒÑ@%Ç‚/’úãSŸRŸTt‰–CºJΊQ"´’¥>¥{i%Ô»|KåÉ$K»u¸#k•ÚFAo»ètP-oá,u›Yôûä²Ó­–8ÖÖ˜;ª @™ŒnHP»š"Û@‚ªÃ¥œLÖò-»¤s"7‘ ª¶8%AŒöÈϨ©(  ÏYÞéÞÓìµ-d¼‚ŽF´‡Ê‹ c ½€ £®Ÿêeü?GQ]=ÚÚ:Ù,v#rBß§'ô  ­[IÔnµ{OL¿µµšÚ íÙnmuu‘¢l²!‡sÔÐtFOiº¬·ö¥-lä¶š´`ei 32·˜v Ę6á“C¿â¥ÿ¨OþD£þ*_ú„ÿäJ¬<.Ïcªésj.t«å¹Q q*Ȇá™äfsÄm˜ 8`çމ¬êZ2ZɬÚý°^CtÒ›b'WTHÄ€,ŠIgcËc¨[?ñRÿÔ'ÿ"Qÿ/ýBò%g\x2;¾ª×ŽÖ³OÔÖ$à£TÀ$«Š6ÃFÇ óŒêkþ*_ú„ÿäJ?â¥ÿ¨OþD  Š+þ*_ú„ÿäJ?â¥ÿ¨OþD  Š+þ*_ú„ÿäJ?â¥ÿ¨OþD  Š+þ*_ú„ÿäJ?â¥ÿ¨OþD  Š­}äð$Vw‹jCnfòD„ñÀäàú¿ñRÿÔ'ÿ"Qÿ/ýBò%ÙÚ×ý¿òM?ƦÓ4ɬ®nî./>Ó-ÆÍÍåÆÐGcïúT?ñRÿÔ'ÿ"Qÿ/ýBò%ó9ÿÜ?ÿjVÅcØØê_ÛM~ÖŸñïäoïßñ­Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEV.¡¨j)¬-ŠÚÿÇ¿œLῼGcô­ª…m ]A¯Š˜Ä!¹rOêO­e]T•6©;K£{ Zú…¢Þ-²æ€ÌÃv (‡''üýk•мG«êzä°Ðìc”’Š¥—'¢0®Éܹ€R‹K²ŠÆk¶Fµ¥yb“çW2³<™ œ‚]¸éÎ:UÁ5͸ŽjÏâ>‘|-­î§¹yÖÝm­ž†,ÑÈèKE# ÉqË ¸¶¯ÍVõ麥•Χ ö±ÜïÞ'’ž„Ê<¤Æå|ã+˺ݟ…4‹+侎;©n‘•Ö[›Ù§`UdEÁ‘Û€&—ŽŸ1=qRjþÒõÝÿoŠsæDa—Ⱥ–6>~GòÙw¯ÌØ 76:œÐ¥ýÜž*Õ4ÙŒ m­µÄ#*ãÌi•ƒÄ71dÞÇ8Íd'Œ“KðÂj:ëÀg7÷+äm%xæ• ²mL¬E¾gí€I è´{8u»]ÿm¸‰a‘Ä… /Ý2Û2O}æþñÍH|)¤A¦>8î„>{\«ÙŒ©+gs$¥÷¡9lía퟼٩‰ÿ´[ך\>Ÿ©ÝMm0tÜá’)[åum¼<,¤Á³•8Á;Z®£‘¤^êw í œ\H±€Xª)bHÀõª÷ …Óé7Ú™ôÖlßl˜ØÛ–Ã~ðã —ÎC0?xæåõ•¾¥§ÜØÝÇæ[\ÄÐÊ™#r0 ŒŽGô fãâii,· <2Ç*ÃäLÑFYÉ‘HÞÎ#h'S—1d2’/i$@A©¶È˜Í *°“Ë 3Ȥ0 ˆ¼Î€ôd-§qáæYekO*Yvæ[yRFܬ„bf—,¸-æ0$ƒŠ.¼7§^ù"äÞËQ,>S_Ïåȃ´‰¿l¹ÎðÛ‡4CFñ_Û®~Ëwi/³ì·ÇÙ‹ço–Y<Ííלù²px¸XxkKÓb‚;x§+ot÷‘®¥”¬®¬®Ùv'‘#ätËŒœÐe׎¬íìn.¡Óu¡iÜ_Gˆ5¢£HŒ|І†Qòû‡±RzYäh­ä‘!y²ÅPÎ@û£q'§$R+–×¼ i¬Ãö@,–ÊO;ÌK›!q$M3³É$)¹9;À*˜Q‚­ .ÏÆz„¾ðÎ¥>‘:KªJ‘É "»KºÕå W;Tº¨B02[hù…ø¼kiqrÖöún©<±D%¸X  ä/™,N ó2<. ¦âÝP8Éí|3£ÙM Öö›d†_6"dvòðŽW'åVIÆ>EÜpOc£iúmÍÅÅ¥¿—-Æ|ÖÞÇvd’^çžiÞÇ@ɳñÖ{âfС—7>l+y±òFzùaÌ‹ó2*¼¹wW°ø…¥j‘:ÙA=Åè•"K8&·•ä,®ã’˜‡Ë§ àü>eÝ´šš—rˆ]’í]'·y­Ü9ËþäŸ,9$…É,ÙûÇ5ÁÚ2yͲõå—ËÌòj72lß·dŒåÓýdƒå#!Ø‚hdžõg×4s|é³7W1*˜Ú3²9äw+|Á¶¨È8ç<•­U4Í.ËG±[:Ù-­QÒ(øU.ÅÛ°Ë À«tQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(î‹fI%.âY°õ5JçR´´Ò¥Õ&›m”P‡—i8Œ.âØÆzsŒf«kê׋%½ ²[g‡Ê&V}ç#ð0:ûÿJ±¤±èñYùí«n"ó¢Á(Ûq¹w2:Œ‚=ET‹_-..u[iôXíö—mEãTÚÇ |ÅvNOÝ‘Æ@ܹžMsI‡ì^n©dŸoÇØ÷\ ûFq/ŸŸ;—¦zZåÃâlÊÇ{kep“¤ð¦™k%²2¤ˆXÇ¡÷²ÊÀ²È¹Û<) n/=œ- ôGuj-µ=³\ùÃ|®Ìždµ™§”Ÿ3Í®AÁܼúæ“ÝÕ£ê–Ksišâ¸@ðÆ%Ýs•\rxäPúæ“¥ÕÛê–Kmi)†âf¸@ȳ…l0yäW=©x"mFÎëOmQÁÚòkuÄË×)2¹w߇Aö‰Pª~îXàî·yá=Ú´Z–›sœ¶Ñ[Çi¶Ý ^RÜ'*¬¹R—,pT‘ÅmiÚŒ:¥«Ü@®¨“ÍnC€è¤hØðOClt¨ß\Òc»º´}RÉnm"3\B×À»®r«‚OŠƒÃZxoC‹KŠo:8¥™Õü¥‡•¤j€£±ÀŽè1u/M¨ÙÝiíª"X;^Mn¢Ø™cšå&W.ûðè>Ñ! OÝËÀ ëšLv—WoªY-µ¤¦‰šáC vβ@Áç‘PCâ]&E‡Î½‚ÒI‚+™R7šH¥10@OÍó1Ï#œTz‡‡¡”Xͦ [ËClÿf UŽHÂ2©RP,Òm† ÏLƒÍEð¾"ŠÝu'{VW‚ê%…f§–P`–5ºœ«/L*Œ‚ÚCªé׆ΠûYn‚³˜eg ®QŽÐs€à©=ˆ#­I{}i¦Ú=ÝõÔ¶Ñã|ÓÈ',x?¡¤x~ÓJ†Eò –W¿¸¿ó|¬$•Üç¿Ìü½ÝH‡‰tâ ;hã»{[‹YÅÄ2«HmŒ„-ÑñµÛîºóŒäd æÖí¢ºÒ#âU™ º‘¢FÒŒÙ!•‚ Ž9ÆFd}sIŽîêÑõK%¹´ˆÍq \ xcî¹Ê®9‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQE(œ“JQ€ÉR¸¡$X›Ì|íPIÀ$ôì&¹ã¨\êZæšVÏP†L'ŸUÉBëQøÐ¦£ªéÚEºÜjwö¶P³lY.fXÔ¶ À,@ÎãØÕºçµØõ+]sNÖ4ý1õ! ZÉoÉ,6ð\… ,OÆrIQЖ^wGÓ¼M§h~—3̆]2_µ ƒÃoÛ$±„|H˜äb…Ts“»(@=£ŽxeyR9QÞÙ"«Q°Ðá”àö ÷¯î¸|¸Ln5.|_¬Á¥\̺r5ÆQýÙT[–•cÜ›˜-PI1Éû·…‹(b@qEpšO‰üG­K§Û[¦—Ú¢º”^¸£¤M±Å3¯Þ•Я›ü;²>á¶šŽ©gãÓ¥¨ZÁkugj!±X¤”É.e[pÜT•g/îÜ Ä°¢¨k7Wv:L÷vP}¢X6ÈЄ.ÒF¬ ŠŠ:ÈP0QжÜñ\Õß‹.Ç—0½Òô­6êY®£¨FZ&Ž?-UOïKJÆYƒàÆ€àä•í(®>×Z[x{í=æ¡¢M4º\·-”}вƒ oÎ7m…nË™'o¦·ÑíìÍ’êW6±}¸<ékr×°´d2ùònŒ¶á„Î3È¡Ñ^kyñX‚Æ—OƒO”ÊVinBl„˜`™aa,Ð&'+÷ò|–!0HOC±–â}>Úk»o²ÜÉ´¶þ`)È®áÃ`äduÅOEpžñu爿´SV† ;íZK¦[ˆá’ÀÿÏ9 NÎþvXJ˜ÏÊ ÂÐÿ„ÖóNð/„îmç‚o¶X)¸Ôn^9Jˆ‘Œ“¦Fbçï–ýÛ|§’ •Ep‰ã y5fŽïK‚+eº¶·–0š‘mF”¬Ûï ‘ Û’…‡õûë{‰cÓlŒ‹-´fe ¬’ÜG“.Éd}Øwùš8ʘÎPçhôª+€Õµq'µó5]:Å4ÍY­¯¯^ÙÖÝÕ¬üÄg_8lLÊ©†s—ØÀºo¿ŒþKM-gµ³*!QZë.›†ô2¬±A+ä¸ ó3(-°°¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPHÊ®ŒŽ¡•VR2=A¥©SËÞûºãŠ¥c¢Hlíã‘z2D Ä ³U¬ï£¾{¯)V Ú ±åŠ“íÉý? û׮ôÍo^kÇô3KŽüG Ï;¼ÜÅöœy ”gxämÉéh¬|Wi%ÜvÓZ^ÚÈòƃí„ÂJ$ò¤n~Ev+a÷•R£p¬Ûÿ‰ZœaûCº$ŠÒ–y"LB$tY”3ƒ*6Æeòƒ±\|ÊaE`Úx¡/¥mtRD†YíÄ¢ $Ñ3©Ia×aÜ'!KùDžÖ.µÿ iúå‹ÚMqr2±]¯¹·¦Öb’p†ã‘@TV.«âk=#W°Ó'Ì׬«"‰FX(ǘê\äò±‡aÆ@Ü» ¿ñ–§iSš¦„OwoµKn·Y™Ï-Œnøçºçà¡¢¹m_ÆÃF’ítÍF Zx ƒíR8a3„YvÇ“ÉòØ£ä!K®MCÆvÞÓ4ëwb¥fiQÒª¸ùü©eÉVƪì§+óêh¬ñ]¤kž[KØôÛo8>£å†‡t;¼Á…&A´£Œ²Jà¹wñn›â´­‘Û-¶Ã,~t3a[;Nè]Ó­ÆìŒr ê+šñŽ´o êÙêíÄ'ù±'•$ú´Ÿu¾X÷ËÓ•Ìï®=Ž·®Ç¨Ëiº}„Ë"DÛãFóƒîäîÇ“‘€:ã©Þ¢¸¸¾'hR[4Á'>\¡&X¥‚)<¹d23E#.аJJ‚_åû¼®d¿ø• i¦ºw‰ÙYçI$‰Ü,d3ƒ!ƒy‡äã;—paEsÐx¾Úæá¢‹NÔOïî-"vg¸„ɺ$%†I;8N0X6TS°ñ¡_Øø‡VÓ§¶iâ„• #—EmêÍ&ÄŒäãÌe=Þ*[EAcv—ú}µäCÜD²¨Þ­ÃG*Jž½A#Кž€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEZúͯ¡H¾×snªÛÙÜ)cîqŸóô«4P=7M‹L†Hã–Y<É ŒÒ°,XžqíUn|5¥ÝÝê77O$š¯Øîº—cÅ‚6„ݵz·*˜çæ9Ö¢€(]hÚ}ì·2Ü[î’æ(⑃°;cfxÊ~VVv`Ë‚xô 5®-'޶{UHâ“< ±Qc :/8V ÍÉΕ½„- ´~\m,“’~yÏ>¬Ì*¾›£iúG›ö+ÌÀ9vmª3µq;c\¨¸UÉÀ5~ŠÌÔt Váe¼ûT€.Æ…o&Hd\“‡‰X#ƒ’`r89UKÏhóK-Õ‡˜Òy¼yÒO5%Ø¡°›Ã±m n$1ËFõ啽ü+ Ì~dk,s’>xÝ]Œªj†¯á­/]ßöø§>dF|‹©`ócçä-—züÍ€Ùsc©Îµ’|3£µÜ·Zy¾nýÐK#¼¸!ØBIYƒ6X('{äÍ›zv›—nÐ[Étèͼ››©n8†‘˜ÇL㯩«tP ­ÎïP†úA:\Å·Ä‘o rªá p­771Ìm i¯©ÞjBòÍ{¶¸YfwŠH‡E11)Ž[¢ÿxçNŠÉ_ ifŽÞh§»Š9ZU[Û©n~f¢`|Æl©Ga´ñóŒóBøkKŽæ;ˆbž RV”´RÇæ3HÒûXy‹½Ü…l½€(šÙïüH- ÝÔ O3I·-¿Ö®Â4ŸôÕð#ÿ­@G£iñ}Ÿe¾>Ïu-ä_;|²Éæon¼çÍ“ƒÀÝÀ¨<)¤%»Á wVèì­›{Ù¢e XÕ‘ÁX×sb0B.NV®˜¶€ »»€Àqq.à9ì:W)âÿ‹ðwˆm4{ÁçM#ÿ¥WwÙ##†p9$œ£¹?Ý ÕÙY[éö‰kkÈ“8–$“’ÌO,Ä’KI$’I5=fiú¯öž§z"’-#ŽáÁWWRÛƒ¹ÈÇlb´è¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEP/Œ šëÁ:ý½¼O,Òé× q©fv1°É$ö®>}?No‡^(µ·Ñ`k™­YDv^žÇÍr¤Bn»+ó¸— ½O¥Q@?‰5O¶¯bº"J‘ÓZÖ‘«ÞI«‘l·Ö&;[XÙ§"å[ÁO”MYgÊ Âц翢€*j²^Ť^ɦB“_¤5´R+ÊìSÈàœ£ê+ŠëÄwW¶¶ºv¡ª6Ÿ-Ò$—÷ú`Žeƒ"ì1Æ‚¶å\¦7¾ q”®îŠóÏ/ˆÆ‰©i‘Ë{y¿K’;²Ø >Øíæ,‹68FXü² ˜÷;6Õ~"Þêž7Úð ¼"u*ªÞCEþµ¤cå¦gêã`?*z=Éx5 /ÁZì÷Þ ½ÿV\ÙY¯nØ;¼°¿òϦ7Ê7/F^šÅ·éöÍæÏ.bSæ\GåÈü]v®Ö=ÆÑƒØt©è c_–(¯om:}F?°"›HUØË™Ôa‚Æ>~p²›†Ö)ÔðU´º4Ëoæ*5Ã1„i’éðÄv¨Û rˆq¸òAvsžHį‰ÉÌ?cò÷ÆâùÇä+_í‰ýÉ?*dùûbc®ÑŒýkO4’»¾·¨†f$âä(ÏÐ.j™D—Hàæú×—øËÁ~ñw‰-µk­XYb—&ÞØ¨½Œ´7 ƒÓæá¶ät¨w§iöº}íÚE{-ÕË3y²o+×nNlþ­*ÀðôAoõŠÂ[+R°$<>XUU+€:08Õ¿@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ +Æÿ°QÒæò¯ì¦d‚&•ö%ÔLÄ*‚Ç ¤ðJÍñ¿y>‘Ú$Z¼DÎUåRÄË…ÎÒm+wG·å ¸8Vì(®?ÃRø£W-©Ý>ž­ÙlZÈ*0khZe%¾r´pAV ¸¸F šß‹’eò]\Ks§Ir?ãÙíŸ[†’ÔÄ­!EŽY|Åv?'Èç*@=:ŠÁðŒúµÆ‰æêï¾F•¼–uu”ÇÀýàhaù·oÆ#Q·o^Içµ#U—SÖ."–ém_Ätße[pDªŸc̱ƒ»â^T+‡ïè¯5°Ô Ó`¶ºÕ´g‡Je¿ó D¶Ûâk‚Ñ$ˆË›’cݰ*-w!¸©Ø®—ðòØG>¯¢BÚÛù+a§7š"{ç(†&L¢+ÁøF;Ñë Ôõ½J9/¯aH<­‹»G̼ñÏ¥lW/ÓêZ‡î¤¸ÓÒâÔm¢RÏ=¿• *rà9™.ªË†Ý±€7¿áOú ê¿øÿÖ£þ¤ÿ ®«ÿýjŸÃÐß[èǨ™<ðòYdó8‹±‰²w:ÆQY²Ù Í÷Ž¥bÂ4ŸôÕð#ÿ­Bi as‚úú|‚6Í6åúãŠÛª·Ÿ~/Æ€8ÿ|JѼmâ¼í7s²•µ„ â,á¤9à3Œýâ1Ð1[úwˆíõÝBÙôÙàŸMžÄÜG$K÷É}¼ç‘ŒŽ9‘Å˽î®äõ{èÙÎvGpWØ* M*×NÕ·hÏsxðiw‘áÏN9þ¾ô«EPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( ªZiZu…ÅÍÅ…­´×M¾âHaTi›$åÈc’y>§Ö­Ñ@Q@Q@T´Ò´ë ‹›‹; [i®›}ĨÓ6IË2Ç$ò}O­[¢€ (¢€ (¢€ ¥¦‡¶ÖuI¤‰ü¹LA¸^]¢€,ý±?¹'åGÛû’~UZгöÄþ䟕C4ÂgMªÃÎE2ŠóïˆþÑ|kuÝiÚª]ZȪ·Ö–Ù/~xòzޏ8àò2 ¯áë+k=R4í&ãOÓ­¬<ˆã’"€ùëÎIÉ$“’rMuTPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Š½m©ÜܶÕÖ ¡DbÙ_ñ$š£à¯ùô?úñ‹ÿA»S/‰lcÿgk_ôÿÉ4ÿ?³µ¯úäšlQR3û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­ÓÐsIäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕC4Á,Q<ñù“#@r['òüæ€2³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­¤Rìu>´ï'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾¨òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûê'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾ª¤† b‰ç̘‘’Ø?ç4“ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅ•c¥]A©µõÞ¡ö© >HHL Àö?_μÿãŸü€4¿úú?ú ¯U¯*øçÿ /þ¾þ‚kJ_& Üx+þD}þ¼bÿÐEnÖ‚¿äGÐÿëÆ/ýVíL¾&5°QE# (¢€ (¢€ (¢€$Ÿýs~Ê£©'ÿ\߇ò¨è&ÓÄšeÜ¥DþR¶Óo$ß"]!`â'ï©v 1×ròº3<ø‹C[¾mgNn¬épn“ËeVÄ6p@fU'±`:šâõ†Jš&ikwurðAoe:Í+J®‚âÙÞDI™ÑXì AÈ8ß“Â:¨ñMž¯í«^…ºž[¦³ Ìëm¨ˆ¾ð Q7*ùÜNÖØ@:—ÕR=~!­çMk%Ìsü¾YȬ¿{váæ!錼V!¾´¸ò<›¨$ûDFhvH›Û—\u_™y|ÃÔV-—†¦Óµ=KKäû•§6ž°KidSåüÆ@Àû˜ÿƒûÞ£ng†ôË=~ÖâK[Ûkk lR;›˜åŒ+4% œ˜ÔDß<в0dÝœa@;JÇÔädÑ?í¿þ€+b±õù4Oûoÿ  Ø¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(H?×/ãüª:’õËøÿ*Ž€(kZªhz%æ©-¼÷ZDf’86ïØ¼±˜O^ÜdàUHüS¥¥œ·”餘gû4ÑêGŽRÂî P’Œ¬6±àú‚þ!Ó&Öü;¨iP\¥³Þ@öægˆÈ\mc´2äàœsÁÁç¡ÉÂúŒÍ«ÁªÚbVÍ$–LÖì®°© ”2œ[EÉsÎþ9@7Ž«§-òXµý¨¼vdKs2ùŒÊ¡ØÎI ÊÄv CE¦«§_Ü\ÛÙßÚÜÍjÛ.#†ev…²F•9ƒè}+±ð%¦›§Íimqþ²êÂa3Ä ž] €$lóä±Ï¬žðd~¸5ã݈ û-™’IËEW*CÊÉ“²>Q|¼0SXúüŒš'ý·ÿÐlV>£ÿ#&‰ÿmÿô@QEQEQEQEå_ÿä¥ÿ×ÑÿÐMz­yWÇ?ùiõôôZRøÑ3øNãÁ_ò#èõãþ‚+v¼HüS½ð‹¿†ÓM·º])ÚÈN]È#%7mçÆq“Gü/[ÿú[ßæÿ §JMÝ M${mâ_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáKØÏ°sÄöÚ+Ä¿ázßÿÐÛþÿ7øQÿ Öÿþ€–ß÷ù¿Âc>ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÕâ¥ÿ¨OþD£þ*_ú„ÿäJò¯ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð£ØÌ9âz¯üT¿õ ÿÈ”ÅKÿPŸü‰^Uÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{‡> endobj 142 0 obj << /D [416 0 R /XYZ 86.4 688.245 null] >> endobj 146 0 obj << /D [416 0 R /XYZ 86.4 505.627 null] >> endobj 415 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F22 239 0 R /F37 405 0 R >> /XObject << /Im6 407 0 R /Im7 412 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 422 0 obj << /Length 185 /Filter /FlateDecode >> stream xÚM޹ƒ0D{Å–vÙõMIˆ9¢%`ª(U¢t(Êÿ7áÚfôfV3§ÈÒŠÉÜZñ„(=8ô…ø†×(žñ’V Aç¤7¸eʦ¸ÅЋD«ŒgR$.S|Ú®ÞPlÂ"¯ûâÖ´eqÝø8ìOm'âQ}%=/„ò¼ K9 ‘-]ó‚yƒ—Úæ  ¥E‚×Ä~ efseÖÈQ¯¦Ñ+ëôÓvòpþ²û|)½7 endstream endobj 421 0 obj << /Type /Page /Contents 422 0 R /Resources 420 0 R /MediaBox [0 0 612 792] /Parent 393 0 R >> endobj 413 0 obj << /Type /XObject /Subtype /Image /Width 430 /Height 573 /BitsPerComponent 8 /Length 41901 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·Áì™äþW°«/ý—¤0%༦å”HhÃÀǶ}ëÓÿ°¼ýû/ü?ü]>x6âUе–Fè‰xÌO~ª^&œ´h9#Í ÖõkEÒÖHc](ÌйRÎæS—ß“†'°ëP}ºOµÅ:èš+aåEfB>ì}ï›+ÿäÿâ©{Z;X9gÜò[MOQ´AE©]¤{|£eÙØ1ßÏ##¶+kAñ5¶™ÇX‰®Kê-¨,QY,¡$'$ÆYÁCÔsž+Ð?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øªZMZÌj2G«›^óV m¦¸»{¨À<ǖܼúŽ+FÿĺÝõµÝ¸]6Ôޮ˫«km“Χ¨fÎ9ï€+Ô?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øªnµ&’karK¹ç:Š®vYZè¶Öð´:DVÞÍïÐŒ†¶ìŽäg­dµõçü#öÚ/“e%½±&¤ˆ™¡ÜA`¬9Ç9½sþ¿ ÏŠÿßù?øª‚¼6N€'þ»ÉÿÅRUi.Œn2g˜Kâ=ZãQÕo'‡Nu#Ÿi4,Ð,§²À=zÕkÍgXÔ-µhn¤¶íO!fÄeDI e0úæ½dø+í€Yäÿâ©?á ð×üø¯ýÿ“ÿŠ£ÚÑì³îy\ÚÕõÆ /.,´Ë†KHí#I¡r¡P’! Éäôª·÷z†¯©I¨j2ÆÓ2,j‘.z?žMz÷ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿT«ÒNé ÂO©ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU_ÖáØŸdÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ;²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿJ|áÀ2tüúï'ÿGÖáØ~Éž5å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅQõ¸v²gù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñT}nƒÙ3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª>·Áì™ã~W°§D¢9‘Ø| ó¦+؇‚¼6N€'þ»ÉÿÅRŸxpu°ë<ŸüU/­Ã°ý“ID‹löžEÀlg$}r"[iá•·LÅH`äa‘Ó‚k׿á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øªY§Ø=œ"vŒÞ¤ 1E'÷ÿ‘EŠ\<ê1+€ö6HzÏü!~ÿŸÿ¿òñTïøB<;ÿ@ïü'ÿGÖaÙ‡³g쳆ÚX­ÓnýÇhROS\ç‰Wm¤?ïÿJúþÿÐ;ÿ#IÿÅWœ|`ðþ—£èºt¶¾K½ÁV>c6FÓêM5^÷RƒZž•à¯ùô?úñ‹ÿACÄ—÷1^$ÊÑ®ÝÙC‚y#¯§Á_ò#èõãþ‚+Åò_úæ?ô&®îÍzÓë¦ÖXb¸ÕL2NÛbI.6™('“Èéê*·ÞÏÜÿ÷ð×â äÓµ;°e°ó/lâ…îXÂ(W“&EgRP‡ÆWqá¸8×’Ï_º“QžÞîFY`­¥…ÿw*²Ÿ%TùØR2‡pySó’ÒuöûÏùûŸþþ>ßyÿ?sÿßÃ\~§§k1ù±X\\Ën|©¼¤É#~ðI·…yòN"€U2Øé”“·_ÞˆÖÖ/,Ç&Ͳïò76J©Eù‹+üp€êþßyÿ?sÿßÃQ[ëÞ@³ÚêO<-²E9e888 㨮dC¬$Â)É„¤HZ3–vàx;‚g)?1-@KˆôùVêÖKi Ôò‘’¯+8?+ѱõØ ‹¯êzUªù«´²Ý(,S ò9ör=«ÑlìâÓ 6öå†,ÎÍ–‘Vcݯô¯!×ãÚßþ¾ùöi?Ö?ÔÓCD ©[¿—¶ö&óehcÄ ï‘wnAÏ,6>GQ´úŸÌï·ç^I,pGw:‰,¡×WYÔš;YµHÙ-ä”]¬Oån?1i pHç I»J 'Åøvíµs$³Æ#µVÔÅœÈ×Ìû*0“!ÊUŸsè¢íZáíÖà‘UÞ0ÿ2«‘ÔU°{í>•'˜ÿßoμúMÄ%ö ¿j·¿D‚;(â¼À’î3pSÌ%‰b7¦UÝã%Ø&ÐÕÚj¶‹¨i¶O\%ÄDÐÉ#F²R6–PJƒœdGQ@ µ×ôËí>kûM^ÒâÊ ÞmÄW*ñÇ´dî`p0'=_óûíù×saâ øƒm¶¨×ÓÚ¤VRM5´ÆP\ŒÉnÊ‚%,¬mÜÊ €gñ-®¡¨êt‘hþ!–K—°ÕVLˆv „MÇ'süÜ )$†@ÛÌï·çYÚìkq¢ÝrÆ(ÚXÛ$u«)ê5ÍiZg‰“Æ·W×s‹!,ϸÐÍ$Eà…e a’c#qÜKõ¿üo¿ëÞOýÐ>³}u¥iR¼ÅdžÎ)ähþRY—ž½«6}tÚË W©†IÛlI%ÆÓ!ã…òy=E=ä ¡ÿØ2ßÿA®GÄ·pZj~Ó3Ü[ˆÊËqŽE°&I~o/,ÜÇɇe¤IÑŸÚ‰ä€ëð‰£Ý¾?¶ Ë´ÙÈÀ>˜5í÷Ÿó÷?ýü5ËêVsêkRÚ*Íî’Û::âFý÷CžŸ:óÓšÖ³ºšç§ÜÚmÆ<öŒîúlvé€·>ºme†+TÃ$í¶$’ãiñ‚y<Žž¢¥T¸•KG}+¨b¤¬ÄŒ‚Az‚>â°/ ¸Uº•tÿ¶Ãyk¾ÍèJ´„ù›Žv‘ û¡Ž™«i¦êVN“Âdi^ö養Iñ…Œ¬ƒ eÌgv Ätàuo¼ÿŸ¹ÿïá¦RàJ±éDŒ¥• Ç$ džƒ#óÃØiÚü—1Ãr÷°YyèÎ|ü9_.`ã&i[ùC†ê Z´¯t‰¢Ôì/ [»Ão…7Œ„èÈ\äeÒᘹG £í÷Ÿó÷?ýü4nþÂ)nRf‘£˜,¬YN}k™²‡R_ÜM$W&Ñ÷ óÉ…ŒmU•”ô~í9,Nwk_ÿÈ:ëþ¹?ò4€ß¿Öonlôù<Ï-§µŽwò²¿3ŸOjÉŸ]6²Ãƪa’vÛIq´ÈxáA<žGOQSÍÿ í#þÁðÿ*â¼KsµÖ£o-Ų6¥§-².cÊ Ê7¸voï*ü­ÇL°;_·ÞÏÜÿ÷ðÔ_Ûý—í_ÚOö}žgç›1ÙÎ1Žs\~Œ·º”Æág¹’ÒK« nÞck}ò*¢AV µƒ~QÃ㛨Zx2çM†Öín£·X¢t½;Þ` oB_ä!HnFì¾ßyÿ?sÿßÃM¥Á•¢Ò™C2 Ž@9Á#=äk”Õ¬õ»«©®ìx1f†8Zp?xc·h%woò2O2A ÜòîÆ³ª–¶½k9mcVàÒ Û„cx(HdùFTœŽ @t?o¼ÿŸ¹ÿïá£í÷Ÿó÷?ýü5­†²t©<˜5('yÕæŠ{Ã6cÚÃdDNÃm$—BÜöù*ýŽ‘©I0ûuýèmbòÌrlÛ.ù#sdª”_˜²·ñoÇbê7ªÁ…ÜÙ<¹#ò«ÐxŽúÿCº•ü¸Þ;Ö¶S# òO>õ‘F•ÿ"í÷ý…¤ÿÐ>çX–ΞëRx!\n’YʨÉÀÉ'M>-Râh’X¯¥’7PÈé1!èAÏ"°á¾y0 qª²²ž€Ý¡Ç%‰Îè!·ÔΉRÛ_ä¦XMØó倗(A'Qº<åÁÂ0äp@:¸õK‰T´wÒº†*JÌHÈ$ר ƒî)ßo¼ÿŸ¹ÿïá®=#Ĉ–ñùÒE—”ùR4ò1‘±$AVC‚¬8?"ò¡Ó4똤{›»«³1¸œˆÚmÉå¢íéŒ ýáÓ;~ZÞ:Ýý„RܤÍ#G0YX²œ úÕûýföæÏO“ÌòÚ{Xç++ó0éôö¬ ÿù]×'þF´&ÿv‘ÿ`ø•UŸÄ)mu¬úÂÅq.<¸d¹Úï“€NNOb]RâžYo¥Ž4RÎï1@êIϸ¯Ý倴y ŒÏ¦Ü[ù“\ÅC)@¬C8m£Ël¶N@ŠçNÖõª2\4Ð\ÛÜy,Œ)ÑÕ„H¤Ë´2Â5û§æ9%˜Îóí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¹(mõ˜&K.íâŠUimÚå]çm’«²’Bì%¢!NÀ6NÈÕÛSƒO™.®¼»çIÚÞÜjÂÁ̲òŠß’ `!ÆÝª07Ð#ÑWQ½V .æÈ9åÉ•uÖ.5›¹nV5h.ÞòÁh FrO<×]Ãïùj_ö—ÿAJÑ×W•|sÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMkKãBŸÂw ÿ‘Cÿ¯¿ôF±á˽FñgŠ{d]€bG õ'ÓÞÈ¡ÿ׌_ú®†oùgþà¨ŸÄÆ¶8ïøCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š›ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽRð§y IÝ€)(sºFè3þϽwŽs#êi´SQEQEQET¶íuaqn…CË"–<AÔôP(<|4ý6ßí6{í¬âϘØ,£—¥7þÛÿùú²ÿ¿ÿÄ×[E+ Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,9y<%zö–1 ›=Öö±Âÿ;`²ŽqÇJ‹þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰¢ËÁ·öÚUÅ«ÝY–ù®66•w­u´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÆÜø'PšÒh–êÈ3£(ÌŒ‘þíZ“ÂW¯ic¹³Ýok/ó¶ (çt®¢Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿZ¾Ð.tK+¸ng¶všíçS’ g sÅlQLc^XRåm¼ä3²)ÉÚöäÿœòÏŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQP=í¼z„6-&.fŠI£LQ 9éÁ‘??cSÐE-żs p’(u##FyV©ö Þ€$¢ŠŽ9á•åHåGx[dЬ FÀlC†SƒØƒÞ€Ic†3$²,h:³øÔÚzüÿ[ßåÿ©âOù\ÿÀ?ô!W`_]j—šdö^Y$os¤Ä$ݳw…'qƒÐŒ€7ûOOÿŸëoûü¿ãGöžŸÿ?Öß÷ùÆ¡Žï³isjQ%„–‘>ÆxíÃÇB¨bû ï…w\É,¾‹ì%—M+ƒjË2Ê0À¤²(n…9eßÚzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð¨çÒôø¡2Gclޤe…A=Ž(ÁŒ…$}((àd£~UâÝkPÑ<=æé‘^jRe`†[˜áLÿy‹²åG ää2Hå4ø‡RÑ´Û_AœWÐ,ÜR%ÒdüÛcc´ä ‚Îë…ô*(¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEÅÝx2î_]ëp]A²ßÃ:€fEªÌ +”Eà €ÌiEyå·‚õ¸õJæQ¥˜¯"‘_cÖIšXÝ')(á“˺WpHE$½v.6›oqì’Èó´†äæ\d <œ`8.Ë„]¡ºtPuà˹|Mw­ÁuRË ê!š5ªw00H®PA 209šg€5+ N9¦K«‰àá¾Ô‘-á, K>Ûl—ùs‰ àïubC1oG¢€8}3ÀìÇJY·Ó¦²²‚î?±Æ«åæY!e ©qÈÛ˜ÔSå,»Î¾“á"ÏL—R½ÔgÔíàg‘5KŸ*IQÙ¼+W'+ódärk¡¢€8¿ø_PÓ?¶ ÅŽ–Ñ_DA¶iVo=¾l &û:9_™2 ™·g ƒ¾¥çƒõÏøEºÑôél`[k–¸²#U ˆd0±BûWqÀ* s‡^þŠáÁâËMQÚ {hü—Dµ’5k1j>Ï6åÌE”çl‘‚$q³®í¯ésXk>"¸“EÓ¬îðIö²{¥Ø>yÓÜìÜô4PW‰?äsÿÿÐ…Q“ÃZ•æ³®Ãqa¦Ûhº½‘±‘­/ÏUÝpÆP†»ÜÜdÜœ¶kSYnt©¡i£…X®dà(Ü*Ïöí¯üþÙßÑþ4•'†µ)ï×]¸¸´mjÝâ0Gd·u‰'@9e..f9ØJ I°™+¿æ[[ËX¯£dÕíäµÕã …yf•ž“´î¸™B±lC–òÊÉ»ý»kÿ?¶_÷ôÛ¶¿óûeÿGøÐ½CwÿÏø:ÎþݵÿŸÛ/ûú?Æ›&³i"kÛ<IGøÐ/_ø{BÒ×Vñl¤Ff6­6Ì“ŒíRTdõR˼ëé>ò,ôÉu+ÝF}NÞyT¹ò¤•Am›Â°%rr¿6NG&€:Ž –âÞ9Ð8I:‰‘€#<«Tûï\‡ü/¨iŸÛâÇKh¯¢ Û4«7žß6“}¯ÌÀ™ÌÛ³AßRóÁúçƒ|?¢Ýhú ô¶0-µË\NÙª…Ä2X¡}«¸à…9èEp‹à‹Æñe¦¨í½´~K¢Zɵ˜Ž5gˆ›ræ"Ês¶HÁ8Ù×wKâkµxzê-³²ŒË ^nå A’2€åÓrŽH  j+Í|3à˜®õ//ôû#¤ù·;Q`öqK¾;EÚ¹8PÐIÃõ`®*F–±á-VëÄúeýŒ–« ›[*Ï$€\,(àÈ…Ú•Ë.ñŸ9‚§æ.ؽí¼z„6-&.fŠI£LQ 9éÁ‘??cO‚e¸·ŽtE¢Dd`Ï*À>Ä;פø2ûOÔÄöú]Äi¥Ïc,fGÿ‰„®b>|ÙR¡¤òÎÿ•˜q–“€³éÞ ym<5o®ÛÙ\E¥irYO‘¤ŠWÌ©Pql0á¶ã%CÒ£ŽxeyR9QÞÙ"«Q°Ðá”àö ÷¯1ŸÃwÃPÑíî£ûv­ ºsËus§=Ã(Âeho7Š?ÝÈÅf2qûÅ®Çú\Öψ®$Ñt뻼G=¬…žévžA´çw»7Æà!Ô´m6×ÄG§ô #Áw‰t™?6ØØí9 €3‚:ázß_ø{BÒ×Vñl¤Ff6­6Ì“ŒíRTdõ‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQYšž¿¦è÷ð_Lé-»ĩ ɸ)P~è8$º(Y™Td)ƒÄÚ;]Åoß›æìÛIœM¹cf¹‰±µP6#œ®˜½p>eɦk–ºµö§goÒI¦Î-æ3[´jÌT6P‘†?ÈýÖR@4袊(¢Š(¢Š(¢Š(¢Š(¢Š§ªY¶¡§Kj޹_˜ö?Ê´>Ó7¤­GEIö™½#ýhûLÞ‘þµ'Úfôõ¦É4²!F ƒéš@ 8&—Ëî7å@Ú¼w÷vâÖÚ mž6I’ð3 Á] cëž¹éë‰eáëë;=3N‚ .×N°™$Ž+}à€§ž¹É9$“É'$×Yå¿÷ò£Ëî7å@ ¢å¿÷ò£Ëî7å@ ¢å¿÷ò£Ëî7å@ ¢å¿÷ò¤ ƒ‚0}è(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQE«izUÞ£g{©JíÕ–$yB)>l2†õ$<ž¸ê9¬ xOOÔlobº¶’KH¡Œyëm!‘¢cG.È]XCò2Œ®qÉÏG{ Sø‡HŠhÒHÛÎʺ‚Éèkcû#Lÿ u§ýø_ð "×ü׾´fšâxn$“6ЗxæYah–Q’ሶ•ÜÙݳ}*Êêþâ=B÷Ó‹‰L¸ #Hð=±õÏ$Ö×öF™ÿ@ëOûð¿áGöF™ÿ@ëOûð¿á@Ö‘£^xšr}ax6ùH>λtJÎ ’I]ø;ˆ ©*C¦XˆµµÅ7q6¯(•äŠxà;U?tBqò*®NHÚ!²Ç¬þÈÓ?èiÿ~ü(þÈÓ?èiÿ~ü(„¼ðŸ‡õ>ÎÖ÷ZK†²Ü¶ÒË“yQ°PcXÌ>X_‘H;7 `0Šê`½Ò­mã··¹²Š”$qÇ"ª¢€jÒþÈÓ?èiÿ~ü(þÈÓ?èiÿ~ü( Ði–:tövº²GçK<Âa4eãydy \‚¼3œdƒ9ï˜Ú6—ÿ¶Ÿ '‰'Ž…¢e·2‘NP®ª'hÉ99ì?²4ÏúZß…ÿ ?²4ÏúZß…ÿ ãæðÿ†'ñHñÜY5Öå‘ÕÒÞ@Ò*…WÞèdR®:Œ¨8ÉlßÓ 67ÚÅlj ìw“‰a†i# j»@ؘÁÆGòãvæn‡û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ?´ôÿùþ¶ÿ¿Ëþ5{û#Lÿ u§ýø_ð£û#Lÿ u§ýø_ð  ?Úzüÿ[ßåÿ–«{ÞDñK·®Ç ʬÿdiŸô´ÿ¿ þ·†Úi#‚âLƒ¶5 3A@Aþ¹åMóûíùÓ ÿ\¿ò¨è+ÝJßM´{»ëØ­m£Æù§”".NXœHZ•¾¥h—v7±][I“A(tl08<‚? Êñ}µÕïƒu›;Wººº³–Þ(‘•IgR åˆ äóÐdñ\ö›áÝbëVYoæÕ-¬n>Ñ-ÏúZE<϶Õ"óŒ(aåIƒ>UPÇ,á€;ß1ÿ¾ßcÿ}¿:ãgÓuÕ×”¬šŒî³Û˜/Ò¥º[(ŒL’¬¡¤|O‚"l »~JXxÀi‘Ãvn‹YéÆÐ5­Â´—R!wÒ.Nb‹n„s.Ò²Úè>cÿ}¿:<Çþû~uæ×šg‹åÐtÈ£ŽéR˜Mw‡$©Øý±H÷£hq‚‡ohýÆ+ˆ4ûhnî~ÕsJ²Üya<×ÛG ““Ó4gÌï·çXÞw—ÃöÒHÌîÆFfc’IvÉ&µë¿ò-ÚÀÿô6  Š(¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢©Ã5ýÊ4‘[ÚÄŽŠd¹e'kÎ6OZ“—üð°ÿÀ¶ÿãu#,QUñ©Ï ü oþ7F5/ùáaÿmÿÆèÅ_—üð°ÿÀ¶ÿãtcRÿžøßün€ ¸ŽOíÝ2uš8D¥È2 ÔÖÇÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùQöÄþ䟕gcRÿžøßünŒj_óÂÃÿÛÿÐÛû’~T}±?¹'åYØÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãt£öÄþ䟕lOîIùVv5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝhý±?¹'åGÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùQöÄþ䟕gcRÿžøßünŒj_óÂÃÿÛÿÐÛû’~T}±?¹'åYØÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãt£öÄþ䟕lOîIùVv5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝhý±?¹'åGÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùQöÄþ䟕gcRÿžøßünŒj_óÂÃÿÛÿÐÛû’~T}±?¹'åYØÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãt£öÄþ䟕lOîIùVv5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝhý±?¹'åGÛû’~UKþxXà[ñº1©Ï ü oþ7@?lOîIùUf2gpj¾5/ùáaÿmÿÆèÆ¥ÿ<,?ð-¿øÝZI&ó;Tp =;ɬ_øH?ê«à7ÿ^´1©Ï ü oþ7F5/ùáaÿmÿÆè?þú„jßø ÿ×£þú„jßø ÿ×­ j_óÂÃÿÛÿÑKþxXà[ñºÏÿ„ƒþ¡·þõèÿ„ƒþ¡·þõëC—üð°ÿÀ¶ÿãtcRÿžøßün€3ÿá ÿ¨F­ÿ€ßýz?á ÿ¨F­ÿ€ßýzÐÆ¥ÿ<,?ð-¿øÝÔ¿ç…‡þ·ÿ  ÿøH?ê«à7ÿ^Ÿá¨eƒÃö±ÍÇ"ïʺGÎ{»KþxXà[ñº1©Ï ü oþ7@(ªøÔ¿ç…‡þ·ÿ£—üð°ÿÀ¶ÿãtbНKþxXà[ñº1©Ï ü oþ7@(ªøÔ¿ç…‡þ·ÿ¦Á<Ïu,‹PÑ*—ÎÎT¶qœ ïžœs@æsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶)éÿòõñqÿ£Z¬U}?þAÃþ¾.?ôkUŠ‘…Q@Q@fjúí–Šm饻ž8"Ž%Üļ‹ã耺åpYAÓ¬_é:ޱkoockh‘ÏÙíb͉"‰)Ï\ƒÆ(j¹ï øº9Ú}Ô Žà´Ó[±UŒ2G+:–S¸nQÀ5oìú÷öÝ„§P²:jZºÞB¶Ì¯,ÿ.ÖBXí^¼ãwd©¢xe´›È%{‹V†Î m¬âµ²[p©#£¹)*ÎLjrŠƒ%¾^F:(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ +&ÿÄšv›¨…ì—+ÌÉka=ÆÔbÁI1£’×ÐÕ¸5;[NïNßíV‹Ê( û¶ÄaÚÃ*N ynŠ( Š* Û}KO¶¾´“̶¹‰f‰ðFä`8<Žë@ÑEQEQEQEQPXÞÛêZ}µõ¤žeµÌK4O‚7#AÁäpGZž€ (¢€ (¨./mífµ†i6Éw)†‚w8Fr8éò£}>”=3,è]€“çFC•%OŒŽB0FA¤ ²tßù5Ï­¿þ€kZ²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[óÈ©{ÿoŸú×'m¦YÉk ´9fE$î=qõ®²où/íóÿCzçìÿãÆßþ¹¯ò¨`È?²lç‡þ>ßãGöMüðÿÇÛüjí„RþɱÿžøûÙ6?óÃÿoñ«´Piz›s¨Å¶Û‘³‘½‡b}koþþ¿ùOñªº'ü…àÿè&´¿µôßúZßåÿhh¤|= ‹Ä·þËûÑ<›¾Ñ'J uÿoô©áÐèÿ‘äÿ_íÔÒE¼·hãµ—{ T…ËÅŒœñSÿké¿ô´ÿ¿Ëþ4Ær·Ú~™ý­si‚Ä–á9ó]‹–îxíúþdØÿÏü}¿Æ¬K4SøƒR’HÛÊÃ#Éê*ZB)dØÿÏü}¿Æì›ùáÿ·øÕÚ)¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ­_éQi>Î¥¢Œº$á²0pO½W­mþ?&ÿ® üÅ1™Z¶…ªÉâó¬Ù[ÁqÙ`‰Qõ{‹<r³ry4Á7¶Þ ] #ˉ¢QåÉå ‚‹µ§”42#»á?vѸR7o,¯EPÑm.,4K;K£› B2 @¨ pà`d*ƒŒ…PvŽOð†©toåIL–kÍH¦ ž`º $“¢G´ã÷yuœe‚ü™&CèôPži%‰-ù`XüO=œS'’ш&…ŠT³4 8e!‘$–»Ë++}>Ñ-mcòà;#€œí\ôQœOEp÷^ ¹½}V "Ó£7«v­«‚íw"L,N€()us¸Ä+…S´¡sá-S[ñ$:ž´špµÝ™iÒ7ÉwjP±Uó„$ ©e —î( [Qð‚ÈVßN‘-¬.`ûü ¹·Û „LýÐMUÛµfÈ?»EªøGR¸ñ×ö´ë§=„­"Ý­qBÈ"tòw0¦wÌÊvghùU{Š(‡Òü#¨èºV™oem¤#é3¬‘Gh…ë$¥•ÂŽÂ@Ø ø)í»*hÞ)ws¯}–ñäVòÚ‘Hn®fósò8¦Ö²à79nâŠâô¯^YxÖãY¸ºó#if•&GŒI(rvÅ ò7˜Ð630ÌhBŒ»^ З]—II•ÖÖðÏq³1<‰cÛÇÞȹSÁ]Àäª(„ñ‚õ JÒÖÛBPGk‚ÔÊÊi#†Ghe`£åÚ±˜Šl»²x|#}‹,õ3ö/.Þþ{™nw¿Ÿt’G2¢¸ÆßÝyŠ‹’ÿ(;L|£v”P¦xoV°Ñ4øÒÓK†çMÕ./mí!¸qG/œoòM¢sŒ!Ë7|´‚õ¿?O•†—5͵Ô÷&éØV’æIX$…Êà2“²XØýÒÿ*0ô:(¬7þF sëoÿ Ö¬7þF sëoÿ oüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÆu¼ s¢Inä„–[”b½peqÅYŠÚÒ’$³·Šr™8ç“Qéÿòõñqÿ£Z¬TŒO*Ûþ|í¿ïУʶÿŸ;oûô)kßÄpÏ©¥¿ëk4òÚ[Ý1,ñoóoUË|1à˜ß ØdÙò­¿çÎÛþý <«oùó¶ÿ¿B°¼SâðíµŒ‘[Á<—w_fQ4̓åÈãQÙ˜ù{UB’Å€F¿}SI‚òT$“vä†FuB‚¤²#Ã)PT‚â€/yVø#ìvØ ©ýÐä‚?*ƒû;Mÿ U‡þ¯øUŠ(¿öv›ÿ@«ü_ð£û;Mÿ U‡þ¯øUŠ((í,¢Ï—§Ù¦zí…FjO*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô(ò­¿çÎÛþý Z(<«oùó¶ÿ¿B*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô(ò­¿çÎÛþý Z(<«oùó¶ÿ¿B*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô(ò­¿çÎÛþý Z(<«oùó¶ÿ¿B*Ûþ|í¿ïÐ¥¢€ʶÿŸ;oûô)È"&;xc$`”@)( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ²tßù5Ï­¿þ€kZ²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[lcÒË»Ežä³1ÀÍnM7û_Mÿ …§ýþ_ñªóÈ©{ÿoŸú×3iilÖp3[ÄII%ƒšå¾Çkÿ>Ðÿßµ¼=il·ò:ÛÄab¬d4\.I}â -uy4Ë]QÔ&Šî$kfUÙÕAó$BNcn€ö«vúª\kwÚ_ÙçŽ[H¡˜ÈûvJ’o®ž nà:w5‹¬xNkÿ®¹o&‘ç$Åö†–nšäpñ°‘ dÿÇG5b÷ÃSj:ž·%Ýò}ƒUÓ—Oh"€¬±¨ó>a!b ýôŸÁýßC¹Œ½ˆ´;«xî-õ:XeœZÇ$wHÊó‘ à¹ÃÖ¤“\Òaû›ªY'Ûñö=×>ÑœcËççÎå鞣ֹoøWQÝZ´z†¢òÍ+:ÍÎVI$@“8Îè˜r^˜¯ðîÚâïPWÓËcuö§Ž!,Áà’à8‘—2˜zK(ºæ$‚Z;¿ _Ûß]k3Þês´ [L†i!hÖh÷Ʋ–G%&ÚD¬p7Ü"•|E¡²Yºë:qKæ)hÂé1pÀí">~b <œVyå§Ã¹î­ã–þúp×>j_ÛË,€Í ÜM0Vû<±§™¶w 韺1Þ‡@Q@Q@Q@Q@dé¿ò0kŸ[ýÖµdé¿ò0kŸ[ýÐæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶1æÿ‘R÷þß?ô7®~Ïþ±ÿ€Ÿýz?á#¸ÿ >±ÿ€Ÿýzc)ÚxI·´U’ñAi%p1àÊägŽ9ÁçšQñ.‘>™w w{¤’U[Œ’¤Õ¡ÿ ÇýõüÿëÑÿ ÇýõüÿëÐ;gÿ6ÿõÍ•M[Ÿð‘ÜÐXÿÀOþ½ð‘ÜÐXÿÀOþ½+ ƹÿ ÇýõüÿëÑÿ ÇýõüÿëÑ`±‡EnÂGqÿ@}cÿ?úôÂGqÿ@}cÿ?úôX,aÑ[Ÿð‘ÜÐXÿÀOþ½ð‘ÜÐXÿÀOþ½ tVçü$wôÖ?ðÿ¯Gü$wôÖ?ðÿ¯E‚ƹÿ ÇýõüÿëÑÿ ÇýõüÿëÑ`±‡EnÂGqÿ@}cÿ?úôÂGqÿ@}cÿ?úôX,aÑ[Ÿð‘ÜÐXÿÀOþ½ð‘ÜÐXÿÀOþ½ tVçü$wôÖ?ðÿ¯Gü$wôÖ?ðÿ¯E‚Ækhñù7ýpoæ*oøHî?è¬à'ÿ^øŠr:>±ƒÿNŸýz,4謟íÇÿ .±ÿ€¿ýz?·þ€ºÇþÿõéŒÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¢²·þ€ºÇþÿõèþÜúëø ÿ×  j+'ûqÿè ¬à/ÿ^íÇÿ .±ÿ€¿ýzÖ¬7þF sëoÿ ?·þ€ºÇþÿõéº7.¥«]ÉismÆ‚â2„áX?æsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶2ìl,$³2Ëai,q>ç’bq+¸«ÙÚoý¬?ðÂ?þAÃþ¾.?ôkUŠ‘•ÿ³´ßúXà:ÿ…ÙÚoý¬?ð¬Q@ÿ³´ßúXà:ÿ…ÙÚoý¬?ð¬WâvÛIñ_‡–ïÄV¶6æv3Y¼Éä0OûÉ 9)½P/A»9Üvíê?³´ßúXà:ÿ…ÙÚoý¬?ð³oõèYõ]+G¸µ¹ñ ¥™¸ŽÅœgqË Èà¹ä`2“À˜<5s4÷‰ ÕÕæ˜«ŠæíJÈg%üää)„¸FgA›gû;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øQý¦ÿÐ*Ãÿ×ü*Å_û;Mÿ U‡þ¯øU-?ÉþÚÕ"ŠÎÖ·ªaT8e,rG'œ{p+V²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[±Oö]k»¼©.ŸnqœH玞(¼‘×Gʰ´ŽŸ•iMÿ"¥ïý¾èo\ýŸüxÛÿ×5þUhÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Í moT»Ç‡½€ÜGÚÔqøŠµö­{þ…ïüŽ£Ð?ãòoúàßÌVÅ1˜áõ•¸{…ðÊ UAwæU$¨' lÛ­Iö­{þ…ïüŽ­Eÿ![¿úáþ…-Z ~}{Q¶™¢—FQ"ýåˆqßœ*?øIo¿è ÿ“Kþü~j_õû/ó©é\W-ÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Ë_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\µÿ -÷ý¿òiÂøIo¿è ÿ“KþVŠ.-ÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Ë_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\µÿ -÷ý¿òi­iúÅýýÚÃý”±®7n<ϲۤ[ñœghÆOæh'Rñ5Ö§Ä ­”ú·šRk{‰çòÀ‰ýÔ üˆœÆ y‹Ï+º¥‡Ž›Qî%×JÚ@n$D„ÜÇ G¶0H3¨|°r¥ÎTnÉáÝ]2-2MN{[|v­j†$ny Œó7 w>µb-+N‚ßìðØZÇèßËHT.ä à eB&m‹Ž‚€9¦ñ¼ÐèÑê·Z {È#¸ÓÒ+“$²¬ ’0›”æhóå‰qóNÐû^Ö'Ö´ù'¸Óç²–9Ll’G"«ðäó¯ÍŒ”^C3Ç¡é0ý·ÊÒì“íùûfÛthÎsæqóçsuÏSëV,¬m4ÛD´±µ‚ÖÚ<ì†Â"ääáG’Oã@ÑEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkc"Di<1vˆ¥ØUQ’O˜ü ©iáëµ³^[tq†RüƒŽœ V¶Ÿÿ áÿ_ú5ªÅHÌì Ÿùïmÿ}Ÿð£ûçþ{Ûßgü+bŠVŒûM2òÇÏ’)-Vˆ¢…É#“ÇOóïQù>%ÿžš/ýõ%jQLfJZxdšmúA–@‹òm »ÏLuùý{S¼ŸÿÏMþú’µ( ~××èg’{‹?2išSå»`gê*ÇöÏü÷¶ÿ¾ÏøVŬ+ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅX,cÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?á[Q`±ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…lQE‚Æ?öÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þ±E ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅX,cÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?á[Q`±ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…lQE‚Æ?öÏü÷¶ÿ¾ÏøUÍ3L–Æid’XX4E@F$ç#ÛÚ®QNðQEQEQEQEQEQEQEQEQEQEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|LkbžŸÿ áÿ_ú5ªÅg¬ímáë‹„¼Otê¦DŽy¬í6÷Ĥ&XF–Š[÷ž`ëÓ¦jFS¾²ÔßÄÍ"G9¹7P=ÚŸÜÁf}¢&í¹ˆ“‚ bñO•˜®O¬iZÕ¾µc>•u}:Awo5‰e“…}Ȭ1 Pw`eŽÐTɺï“â_ùé¢ÿßRSU%ÿžš/ýõ%ekX,Þ[ir¨$oŒHTッހ:š+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ4mkŸÜÓ¿'ÿ.:ª+•þÚ×?¹§~Oþ5wK½Öo¯rý"U.åË`võÿ>Ô»EIed{Ö<úÚM«éÖ–s[IÆC1ˆ†?*ä:sü¾´©Er^6¸ÿaiµ-­˜;J]:9åÚ~Ó$0±ûᙿåA »ñW‡î$¹Ö“í:\·rÁqy,$ÉZ„ó!F«í¹B…$œƒ@¥ËxÄZv¯áÝ5›[ÝMtèæ5ºY& ±C—-Ç’{žkkR—V‹Êþ˲²¹Î|ϵ^<zcb|÷ôÆ\ð~ŠŽ3[Æ×‘ÌT7.ªØä 3ß>‚¹mT·72Žfö+ö`÷7tµÞ"KùXÄ‚_—*Öà­¢¸}Ä:¦«¦xV&]8CI{™î'2\ž/!H~ç;¤e!œy,J•jšõMS\ÒíàÓ`Š+È­¥ÒK’Hå‰$yšUr©¹Æ ba¸vzñ·}É»›È¶7›/šbؘ9mà‚¸;ëšóÏøMo4ïøNæÞx&ûe‚›Få㑨ˆÉ<*df.~ùoÝ·Êy*éTW‰µã5Ä÷vVV¶Ö·övRÚîi&ßp–ùÁ <·œÀ6ð1„Æã“©x‹ÅÖš¦›û5ôº5ÝÊA™q¶òÆcTr—Û;~ñ”IÆà¬éTWš¶©©ëšÈåd¶!Ò0äJ@m™`~r¥S¡ê_Û:ªy^OÛmb¸ò·nÙ½Cc8Æqœ ¿EPEPEPY:oüŒçÖßÿ@5­Y:oüŒçÖßÿ@4ßùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Œy¿äT½ÿ·Ïý ê/ È.Oúçò5`Äóønê×t’5Ú¨Î2LŽ%ž‘=ž•öh5†wXÃH Þhä ‘Ÿ©íÛÒFiU[?õ×ÿõõÿ´£ª¿Ùz¯ý Ÿù"¿ãHºF¤ŠÁ<@ªÏ!‘ßìC,vªú〣 õ  Zá4ŸùCÿÿÐtÿÙz¯ý Ÿù"¿ãQZxb;[T‡ûCvÜóä‘ß>´˜™•Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%·ýüÿä#þ4`Gÿ?ßùÿ ”VßöóýÿøÑýüÿä#þ4X,bQ[ØÿÏ÷þB?ãGöóýÿøÑ`±‰Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%·ýüÿä#þ4`Gÿ?ßùÿ ”VßöóýÿøÑýüÿä#þ4X,bQ[ØÿÏ÷þB?ãGöóýÿøÑ`±‰Emÿ`Gÿ?ßùÿØÿÏ÷þB?ãE‚Æ%khñù7ýpoæ*_ìÿçûÿ!ñ«VtvÉ ¹ó FS^==ý¨Ã*º2:†VYHÈ õ«Å§XÁ(’;xä^Œ‘(#ñ¬ÑLaEPEPEPEPEPYšv¦éW =¤.¯·Ë@ó<‹ d‘+"Nå@ʼ|£tPEPEPEPEPY:oüŒçÖßÿ@5­Y:oüŒçÖßÿ@4ßùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Šzüƒ‡ý|\èÖ«_Oÿpÿ¯‹ýÕb¤aEPqÏ ¯*G*;ÂÛ$U`J6`ú2œÄôM<6èyR$,¨Ø(,Ä*Ž{’@¹ W'áXo4™uÕÔm-çŸí &·v”ˆ!B¤‰˜™ÑÛså›$ÓåMC^Óôfm,Ö²Ç6~ê4ÁT;ù@e9]Þ\¯ÆìÆÀmSJ´šÃH²³¸º{¹­àŽ).dÎé™Tç$œ’3ÔõëV袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬7þF sëoÿ Ö¬7þF sëoÿ oüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÆQ•àðÝÔѶÙ#k¶SŒà‰Šça¾Ö¥‚9?µq½CcìéÆEoÍÿ"¥ïý¾èo\ýŸüxÛÿ×5þUKö­kþ‚ßù,•«ic¬\ÙÇpÞ ò÷çåû‡—]>ÿ ‹_øþ„h@Š_Ùz¯ý Ÿù"¿ãL‹OÔæ†9cñ.RE§ì+È# õ­z«¦ÈÃþ½bÿÐ1™·Öú†Ÿe-Ôþ$o.1’ÁI=€÷5™ö­kþ‚ßù,•¯â¯ùîÿàúÖM&&'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²Qö­kþ‚ßù,”´P}«Zÿ ·þK%jÖ¿è-ÿ’ÉKE'Úµ¯ú ä²UýûRêû«4Q©vEìvÎ8ëþzÕÖÐ?ãòoúàßÌPÔn‘?™#*"‚ÌÌp’M`7ˆ£Ôµ½6ÞÊñžd3(B¹Â¹Èïþq[´SÉxÚÊ+¯°É<|Iæ.Éô§Ô­÷¸-d8“ƒµú(2Ë®`ƒÃ–“ø«Ãú•߇ Žåt¹^áåApñ\+Zùaç —‘@p®NNŽõÚQ@_†5Æ´ðV“a—ª>¥kamA6Ÿq‰0‘œÈÑíÚ¬Ùb7¡˜ŠÅZ%¬>QfúµÍέiutc°i÷2É‘„jbQ“ü£³1-ÜQ@=Õ¹ÅóË6„÷×òê05ÑIÛÚ¢RuBª¬ÄÄÌ›Ánðžð¶‘mƒ´ºW‘¨ q)·ðÔÖòíR†D™ÜâåIz!EF=fŠâô·&žº^ŸaýŸòÈë{“ÛCJ# ÑÛÉŸ&BÎUQ¾RQåÃgkT“EƒKñMœV:cÌ!khíĶR³Ã ª!òoU¶Åª³Ÿær$‰F{ú(Ìu_ ÙYéž'k/ZÄ_V²yz_šØ}œÐ’=Ë!e^¤7|ОƒW¼Ñâ±Òtˆá† Óp×^–c){m¤A#)T`6ãŽá}:Š‚Æ×ì:}µ§Ÿ=Ç‘Çç\>ù$ÚÜíÝŽ2OsTôè5È®µ=GN¹‡n-¬ ‘Éf™ÁÏî9ã:(žñ-Õí½ÅšÇq¨ÚX2Èf¹Ó¬þÓ0”òÓg—&ƒ)'gTQ¸g M7ŸhW76­ìš4ñ]\%“W/ ª4‹½îLBïlg©Ü u´P«âAc<6£ö±–¼YtÆÛiuº0"¶Ù2!Ý0߉ÂìF;†C×¼Ö_™»nyÛœã<â¼ÿKÕJÇ‚ÙùýŠó[ À÷oþøè/­àHÿ ƹӵŸh‘kGÒþÛm$‘ÚÉ|©bùã]ΫÆQÎC+«.C*ï!6´ :m+F†ÒvBêÒ8HÉ) ³³,HH"¼p½Pè¶óÅæ.¯­½Ó›‘ÕX©íê %Îmmk-ÃêÚÙH»¹ÀãŠÙ¢¸xÖy¢IWRÔ•]C7$lãš“sÿAMGÿ +ŠçkEq^MÏý5ü4y7?ôÔð Ñp¹ÚÑ\W“sÿAMGÿ MÏý5ü4\.v´WäÜÿÐSQÿÀƒG“sÿAMGÿ  ­Åy7?ôÔð ÑäÜÿÐSQÿÀƒEÂçkEq^MÏý5ü4y7?ôÔð Ñp¹ÚÑ\W“sÿAMGÿ MÏý5ü4\.v´WäÜÿÐSQÿÀƒG“sÿAMGÿ  ­Åy7?ôÔð ÑäÜÿÐSQÿÀƒEÂçkEq^MÏý5ü5¥¡Ù¼·å¦Ô/äXÈîÒF1ŸQÏJ.:@ 8&”£’¤qBH±7˜ùÚ “€IéØMsÇP¹ÔµÍ4­ž¡ ™O>"«’„×£ñ¦3SQÕtí"Ýn5;û[(Y¶,—3,j[à gñìj¼Þ"Ðíõ1¦O¬éÑ_–T¯t‹)fÆÑ°œää`cœŠ£â[KǸ³½°ƒQkˆ–H¼í:Kq2+”%vÜ,¡(¤œîT †lz]ì:¾<ÖÖ±%¦“=´âÓå†9Y­ˆXÔó³÷oŽ8 3Ú€7`ž«xî-åIa•CÇ$l]HÈ Ž#½I\׃QµÐ4½"ÿD½²’ÊÂ(^yd£gEU!vHÍÏ$dn•­©i÷7ÞWÙõ‹Ý;fw}•!o38ëæFý1ÛNsÆ/ÑQÁEoo3Ìè¡ZY†rÞ;@=xz\%…Š-AŒ:Šæ{{…7wAf”G:»Æ¡n$‹.Ôà@™*6í?»ïê o­ »·´šêînwy¼€<»F[jž[“Ž•Ç[i> Õ¼I4ú©Ôl4©Zwðj8ùLv‚%%å;’v;Ù[/~ßןð™\ßÝßÝ\ØýŽÍ&Kr“KL~`# ±I~g8àP¦Šó„±ñ›jº‰òn¡³Yån²‰ã% v¸r¤Å窰Kq’¤…!vIªé~&—O´|Z¤6K,¤ÙÍzfº\„ØZE¸ˆíLpg“ï¯@‡EAcÄ}´7w?j¹Ž%Yn<°žk€m£…ÉÉÀéšâítߥ—ú­Q/¢ò$½’]D4wÒ$ѼŸgMÇbº¬Àä®$PËõ`ÝÃÛi> Õ¼I4ú©Ôl4©Zwðj8ùLv‚%%å;’v;Ù[/¦úf¶š´vÉ}<ºlÒÁs=Ô“24K†B€¡dd„• ‚ã;w  †yáµ·’ââTŠ”¼’HÁU ’Ià;Ô•æ³h)Ö%ñŸwöÖZ…Ê÷nb—ÊÚÞ|åó&qA—†NB®ì ­ÚKasi¥^ýš8®-ŕ֤$—s´L’Ììì6©IGÊÒ0W\’ªÖÑ\_„ô m [{PÕî²ùQ›ÀéòÛ@³nû¤YÝœrÉ´¶âx3Lñ5¦¡q.»w;~ëdªÀ´w’™7mQ†ùDp‚$(Ú€v”QE“¦ÿÈÁ®}mÿôZÕ“¦ÿÈÁ®}mÿô@ ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØÇ›þEKßû|ÿÐÞ¹û?øñ·ÿ®kü«¦Šµh3[îÛæÉt›±œfG§Ã¥iÐÁBÙ˜"…ÜÒœ dâ è¿ò úîôWj­Æ•¦][¬Z3D®\'œànÆ3ÁçëëUáÐèÿ‘äÿc-ißñçÿmçÿÑÏMÕÿä }ÿ^òè&¡o ènª­`Ä Ú ÜIòŒ“Ï©'ñ¦ÿÂ1 ÿÐ7ÿ#Éþ4ÏÙÿÇ¿ýs_åSWJšf›*-ž@y­Óó§gißóéÿ‘üiXV9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9Š+§þÎÓ¿çÓÿ"7øÑý§ϧþDoñ¢Ác˜¢ºìí;þ}?ò#ÙÚwüúäFÿ,9ŠÖÐ?ãòoúàßÌVövÿ>Ÿù¿Æ¥‚ÞÖÕ™ ·ØÌ¥IÞO ¢Š)Œ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š+'Mÿ‘ƒ\úÛÿ赫'Mÿ‘ƒ\úÛÿè€ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±OOÿpÿ¯‹ýÕb«éÿòõñqÿ£Z¬TŒ+2vÊ}LØ£>K4QÌWK*g|hÝ ¨f&9éÖ-¿‡!ƒSK=ÚÖå»·µ b)åßæ>øSÀ2?Q°F&¿¯Ááëky¦¶žãÏ•£U‰ãM»cy™¤tUP±±$š·¥ßSL·¾Xw¢;ÆçièwF̤‚cÁŠº&·{¤Æš½þ—q©[_µÕ´ÇN (fòòŒÛ·*¶C+)¹°Åõ´}7û+NÆ_:F–Yåp»CI,#í8]Îp $ OR~Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( ŠURÍ€2h‘L[|«¸íPXrqœ^?…%CRÖ,ô¯(\™ÚIs²+{y'‘€Æ[djÍ´eAl`PO#5?á+Ò§o§¤—RÍr¢H)¤ŠD;~u•P¡A½2Û°7 ‘@TT7¶ú–Ÿm}i'™msÍàÈÀpyÖ§ Š( Š‚ÞöÞêk¨a“t–’ˆf#k”Wž¿+©ã×ëSÐEPERÇSµÔ^í-ËÙÎm§W‰¬€+cæ# ¤A@袊(¢Š(¢Š(¢Š+'Mÿ‘ƒ\úÛÿ赫'Mÿ‘ƒ\úÛÿè€ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±7üŠ—¿öùÿ¡½rvÚeœ–°»C–dRNã×Zë&ÿ‘R÷þß?ô7®~ÏþkŽ0cWáÐèÿ‘äÿv™s¶ŽÏq4q!¸ 4Œghãš›û_Mÿ …§ýþ_ñ¦2•·‡´ˆ|Ï콿<‰´H~ë²ú÷ÛšK½Aµ²žãû/w•>ß´H3œu©ìµl×̼·MòÌëºU”Ìø#žEGªjš|šMê%õ«;@áUfRIÚxÐ1›e41Êm•K¨mªí‘œ šöMüðÿÇÛüj{?øñ·ÿ®küªj’J_Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ£û&Çþxãíþ5vŠ¥ý“cÿßãWh  _Ù6?óÃÿoñ­_éQi>Î¥¢Œº$á²0pO½W­mþ?&ÿ® üÅ1›+'”L›Yö‚v®2xè3Åsêºî·§Ü\i¿fŠßÌÜÞz¾w.;}?Zߢ˜Ìi7ZÙ¤´·‚i"Þ§uôöRØû³B mùFPŒ1Úr6dƒI½M_H½¹»K§³Ó¦µ¸˜¦ÆšWh𣀔Čñ{mQ@÷„í5Í/HÓôNÓNHl¬ã·Yí¯V‘‘UrQ¢PŸ¼qÀç­ijZE¶«å}¢[Ôòó·ì·Ó[ç8ëåºîéß8çM_¢€#‚··Ž.R5¦GgbÇ,Ä–>ä’{מiu++[åšñ%™Ö4$È5²+¿Ú@­—P—iˆIÙ;½ŠóŸ ɦC+_ÛZÉ Åä“ÅlšdÚ¥¤Ã*A|¦TpÜ0›Õš€uK{ÝòömŸfµ´VX„Ö­(­ Ÿ%ØÆÌ»l¨‘ÆÓ’_Ò¨  Õ¥Åþ‰yij`ófˆÆè AŒŒ•`3’¬ÓÅè?®"»‡ûv++>´ùvB@ñ([mR‹Q•Ý ¯·`™[²ÃÐè -ŸÃwÃPÑíî£ûv­ ºsËus§=Ã(Âeho7Š?ÝÈÅf2qûÅ®ŠïúÍýŸŠ-ím†¥yųE9rè‰4rj‡XpxbFX 7aE`øGB—Ãú'ÙflHò´†$th¡ÎØöE…8Ü@Aó3s“½EQEQEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkc:Þ¹Ñ$·rBK-Ê1^¸2¸â¬Åmi IYÛ„E ¹Lœsɨôÿùúø¸ÿÑ­V*FG%µœÊ«-…£ª’T4 €N3È~Uöv›ÿ@«ü_ð«Pìí7þVø¿áGöv›ÿ@«ü_ð«PV UP«ejD8¥ò­¿çÎÛþý ZÉ×uÏìU³Åœ÷-su  ÂD²J‘—fvß÷èQå[Ï·ýú´PyVßóçmÿ~…U·üùÛß¡KE'•mÿ>vß÷èQå[Ï·ýú´PyVßóçmÿ~…U·üùÛß¡KE'•mÿ>vß÷èQå[Ï·ýú´PyVßóçmÿ~…U·üùÛß¡KE'•mÿ>vß÷èQå[Ï·ýú´PyVßóçmÿ~…9QäÇo dŒˆÅ%QEQEQEQEQEQEQEQEQEQEQEVN›ÿ#¹õ·ÿÐ kVN›ÿ#¹õ·ÿÐ 7þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb“¬zYw`¨³Ü–f8y­É¦ÿké¿ô´ÿ¿Ëþ5^où/íóÿCzæm--šÎkx‰1©$ çŠ€:ïí}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ük#^‡N×a‚âF²Ž)RlZËÎèêèO˜÷Yãç9¨ô}>Ê]R’ÒÝÔîÊ´`ƒòŸjßþÎÓèaÿ€ëþÆb~çûnÂûþÖh-­^ mHv\¹Û‰a¸=1ÛFàÅ…¾“e¨ É<@×’GAn.®co"6*YA3çb|Òo”sËgTÚiâþ8?²´ý­ ÈOÙ×9V@?ô#úTßÙÚoý¬?ð€#þ×Óè!iÿ—ühþ×Óè!iÿ—ükœ¿Ky5«»aeiVáàUÎW$ž9ÿë}j/±ÚÿÏ´?÷À¥q\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ®_ìv¿óíýð(û¯üûCÿ| .:í}7þ‚Ÿ÷ùÆí}7þ‚Ÿ÷ùƹ±ÚÿÏ´?÷À£ìv¿óíýð(¸\ê?µôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¢ás¨þ×Óè!iÿ—ühþ×Óè!iÿ—ük—û¯üûCÿ| >Çkÿ>Ðÿß‹…Σû_Mÿ …§ýþ_ñ¥MSO‘ÕúÕŽVe$ŸAÍrßcµÿŸhïZÞ´¶[ùmâ°±V2Àš.:Rìu>µÒC±DóÇæLHÉl ŸÈóšxv.Š€;TœqÆO8¬(ìuyõ{+»æ±ÛoÀ€¾NåǘË:ž°4ë‹{Xln¯ï'W‘-íŒa¼´*É‘•p  Æsó "£x˜ÿmÚi±èš£ý®/>+‚±"ycË̯"È»Lª ” ×â¤ñ„Úí¼§:FÅŒ:‚ÝÂÇ6ÝÊCŽ@!±†lƒD–úÙµ .çí“Íö l³pwÉ6ó ÞïÝ¿sÏ–ÏäÞ•¨Ã«éZººÃyw¬€ ê‚Fp}jÝ`økHÕ´=>ÓN»Ôì®ì­-RÞ!‹Ã'È‚Ìe`x (äöéWõ-IÖ|¯íM.ÊûÊÏ—ö«t—fqœnÀü…_ªkšLòÜE©e$–Ò¬3ª\!1HͱQ€?+ù@<“Å[‚mmã··‰"†% q¨UE8ÕÉÚø.ò+[ˆeÕÐ!he·‚ÞV¤ŠE–?ÝÉ4˜@P ‘˜ÆÒG÷Jt7Zæ“cç}¯T²·òÖùמ_ÜûÙ<­¯÷×ûÃ1ÜkPÁ«¦š¶×Sɵg†0Ën²3,eÆwÌŒ2¡¶í%¶¯5“¦x=­|Iý¹~—×[§nµTòÞXíã%9;@ìS¶L$Öí<%¤ÙxšMn $—ì°ÛÂÕ òÄŠJ°é”uL qŒ~=sI›í¾V©dÿ`ÏÛ6Ü!û>3Ÿ3Ÿ“[®:JŽOhqi‘jrk:rXLÛ#ºk¤;sÀ|àŸ•¸±ô®hø ò]Uïîuç¸uSö1%r² á™YÃLS PËÄ'p¸±¨ø.óQx¯[WHµUi “[Ã-¼N®#R6Ã2HN!–‘»ñ; ¡¹¤ÝZIwoªYMm^sÍÂ2,ya¼°8 ”qžŸ+z±ceo¦éöÖ6‘ùvÖÑ,1&IÚŠ'“Àk‹_†vñéööë©Î$ŠÕ"2+™PY„qµƒ*ÿ¡&T6ïœá×ÐQ'ˆ´8´Èµ959,&m‘Ý5Ò¹à>pOÊÜØúQ½§MªÏ¦5ÂEyæÝ"•ÕZfG+ÆrÀ,‹ž8ç·'ž\.Ÿ vÚŒ^™d–æñ…á’V`Џº*íRì E8|xA?Óݯ<Ë›Ëû+É.^ó[ù8F+€racÀÔ¡žxmm丸•"†%/$’0UE$’xõ¦«§j Ù_ÚܤêïC2¸‘P…b¸<€HŽ„Qëoö®œm„¾L‹,SÄåw’)DÜ22»d Ž£'þ­@ÝǨZµFóRyá±UC‚ Û±"@ í 6T®ÕP huÍ&âh!‡T²’[Œù(—Z\"Èv€yù[ŽÌB*Ä7Ö—G“uŸhˆÍÉócr뎫ó/#˜zŠÁðǃm<=c,˜/d“컥kp¤ýž£Lòs†ˆ¸þén=M½Ãé“N³¼ÈÃi¶ÖåÌiè2ÁxÀÙK“$jŠ( ²tßù5Ï­¿þ€kZ²tßù5Ï­¿þ€h¿ó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[óÈ©{ÿoŸú×?gÿ6ÿõÍ•u6‘$úCC"îŽI®U†qepjêHÑF±Çµ@UUP  >Šì¼ù?½ú <ù?½ú ,8Ú+²óäþ÷è(óäþ÷è(°XæôwHµH¤‘•C33œ’jÇü%Z/üþÿä'ÿ Üóäþ÷è(óäþ÷è)Œçá#Ò_PIÅâùqÛȬJ0ä¼x“Ðôô©¿á*Ñç÷ÿ!?øVçŸ'÷¿AGŸ'÷¿A@/Ú¡½Öõ‹wßù{[g ŽÿJ±]—Ÿ'÷¿AGŸ'÷¿AJ±ÆÑ]—Ÿ'÷¿AGŸ'÷¿AE‚ÇEv^|ŸÞý|ŸÞý mÙyò{ôyò{ôX,q´WeçÉýïÐQçÉýïÐQ`±ÆÑ]—Ÿ'÷¿AGŸ'÷¿AE‚ÇEv^|ŸÞý|ŸÞý mkhñù7ýpoæ+sÏ“ûß  Í!àûQ`±QLaEPEPEPEPEPEPEPEPEPEPY:oüŒçÖßÿ@5­Y:oüŒçÖßÿ@4ßùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Šzüƒ‡ý|\èÖ«_Oÿpÿ¯‹ýÕb¤aEPEP£>¡&¼¶V—ßfì¾iýÒ¾Nâ;þ•lZÛÏokÜÝ5̬7(¯`="Ž;¦ºTQ; Œ¾2v‚N=¹?ËÒ¥gg9c“XFUYÍÎñkHÛgÞû»ŽêÇö§.¼ÐÜêWPÃw=Å­¼%´–¤¨ªÄFeY•c%Œ¡“rH¸å1_G¾Õâ})®u›«Áw­ÞXȳŠ"ì.6F§$Å'ÕxÀ$¶=+N‹S—SŽÂÕ/æ]’],*%uã‚øÉ*ðOaéQÝèzMý ´¼Òì®-„­0†kttó’_iÜK1'¯Ì}kqë2Nò]LÚ>…¨Åf_¶;Û˜ˆÃ`J_|¹ädqrÊÆÓM´KKX-m£ÎÈ`Œ".NNp9$þ5=rÞ8ÔïôÛ],Ø>¢ ׌“.›2\V-ó9'šÍƒÄÌ÷ =Ž­¶‘çÜ[-Ô·ª²„È$-~æC•v8•vÜ[¯ßjñ3G úN©¥ØÄu‰ÈÆÙ `\B„äÄÀü˜Áá³½„zV§.§…ª_Ì»$ºXTJëÇñ’>UàžÃÒªEáoAiqiƒ¥Çms·Ï…,ã .Ó•Ü a°yé@õ]~âËP¸·¶²‚hì­RòöIîÄ"c 2¥Y¿u&w²(ù~nI[úæ¥ý j:§•ç}ŠÖ[+vÝû¶3ƒŒãÁ¢MI›ì^n—dÿ`ÇØ÷[¡û>1/“W¦:J·<Ý[ÉoqK ªRHäPÊêF ðA¨‹—â$‡û%ÚüN-Ò(ÚIQ›3«’cŸ­'Æ#9Y;w0Km㤇M¸›EžÖÚ|ýª{µž5€+•fâB€ î˜B •98NŠïJÓµ™/l-nRuD•f…\H¨K(lŽ@$BIªïáÝK‹K‡Ñ´æšÍQ-¤kT-¡Ê8Ê…=éÚ€1tOjÜÇý¦`¸Õ/lmî¼ÅÜÍ“², ÄqÜNâË÷H;ÎÖ»©\é:c]ZØ=ì‚ì]ä(?ÄB#¹¾Tc’2å…ű´O/m¬ åJÓGˆÀÙ#nÜãÑŽ÷ÉêwSQê:V«Û­¾§ak{ ¶õŽæ‘C`Œ€ÀŒàž}ÍdziåðÛÄ©äêÉ ÁŠcû¹ \ÆUã @hÜùl¬ ÷–«Ýø£Q°¾ÔÍΕjúf™·W6׬ò"ªïT(Ñ*ùŒ¸;Cü ‚OÌ›¶¤Ðô™¾ÅæévOö }uº³ãòøù1µzc ô¨áðî‡o©N NŠü³9ºKTYK6wàg'''<äÐO ë÷ZßÚRïJžÊH6Íë³Â™¢‰‹ § .eääSÄž®¾'Òôm6+¨Òx%¹k˜’\£Æ :Èà˜Ç™— ‡9M÷±½§iZv‘nÖúe…­”,ÛÚ;hV5-€2B€3€9ö9‚¸K†‰ Ȭ‰!Q¹Uˆ,ê*¹öJäõ/ͧYÝj ¥£Ø#^CnÂä‰dšÙ&g›0ˆ~Ï ÝÊŒ½›w¨\ù¿oÓ~ÅÑ¢Äë.å9á±÷dù€Ü¼®Üà}I’îêíô»&¹»ˆÃq3[¡y£ ŽØË.¡[€¬Ëh³–qòä‚`Pxù|ÁÉÇ= Ö‡¤ßjßÝévW°mò®%·G’=§#k‘‚Ièh›CÒn&ži´»)%¸Çœïn…¥Â4cq#Ÿ‘™yìÄt&€0uÝ\²ÐÞoìYàžk«h"0O ¬‰4¡2w•Q(Î1ó fO™×~ÖjÞ,¹ðÆ™j×=ô‘À×£cùðÄ9RË IòYãFdb¤.võ“A ž$•+…u ) §žà€Aì@5SRÐôgÊþÔÒ쯼¬ùj·IvgÆàqœÈP,þ0kK{½JâÁ‘]F²¥Òý¡ÞÜIæ)‚Œ&Lmv8ÚJ¸­¿ ë÷ZßÚRïJžÊH6Íë³Â™¢‰‹ § .eää§•§E©Ë©Çaj—ó.É.–ºñÁ|d•x'°ô£NÒ´í"Ý­ôË [(Y·´vЬj[d…gsì('\ñ,ÚMÅêÃb—é¶k|ï9–dÇ”¡X;â8bƒîóÉÅ;/Ü_ݼ0é°7÷Zd,× –¹„HÃzª‘²EœŸ˜>B¸sÑ]éZuýŵÅå…­ÌÖ­¾ÞI¡Wh[ å S9ƒÒ«éÚ¥Ì÷[£];LMË¢™vË3Lɸvosôêy jÏÄÚ©ø]&¯v-_U‹IKæX.Àv¢ÝæœÄB9Û! ±—+Œ‘œ[ñ¿áÕ¥µ“Oó †Õ.U› ÊÏ#»qÄv²wrÅ€K.óèzL–—V¥Ù5µÜ¦kˆZÝ M! —uƲÉçR +N[w·[ Q À¶¯…v´*XÈÆ Í…è7Z¡£zþ"Ö,cmgo=²´øI ™‡Íˆ÷!Ý.0€AÌ‹Åz‘Ñ.52É•cÓÄ7“L/»³ X7•Àb £n ÍÂaÎóèzL—wWo¥Ù5ÍÜF‰šÝ ÍvÆYpÁãPEáoAiqiƒ¥Çms·Ï…,ã .Ó•Ü a°yé@í¿Œ5íWI¸†ÞÖÛJ’ÎòKÑwpИš ãŽGù¢ÎæÚfàÇpB¢µî¼@Ún§â½‰þǦiÐß(ŠErè|âØRªUó.À€§å;«I4=&;K[DÒì–ÚÒQ5¼+n!C¢ã Ù$äsÉ©#Ò´èµ9u8ì-RþeÙ%Ò¢W^8/Œ‘ò¯ö”ÎÜx³S´Ô`ÒgÑ }RicUŽÞûtA$ŽvV.Ñ©àÛ>àáH#qùk{GÔ¿µtárbòdYe‚T ¸,‘HѾӕ܇€HÁ t–‡¤é±$V:]•¬qÊfE‚Ý,…vi+ž¸8«pÁ º‚$‰ 3•E 1,ÇŽä’IîI4%Q@Q@dé¿ò0kŸ[ýÖµdé¿ò0kŸ[ýÐæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶)éÿòõñqÿ£Z¬U}?þAÃþ¾.?ôkUŠ‘…Q@Q@Q@Q@Q@Q@Q@Q@Nòº p6ŽÕI7ü³ÿpPçÉýïÐQçÉýïÐTuÅé0[Ùê—RÍ¡Þϯ¥Õܯu¹C$ä1)¸b©"ùf%ïm§fBùd qçÉýïÐQçÉýïÐW”Ëy¬ë> ñu†¯c{{°c2ØÊòI;‰Uf‡;Yb`Dgil–þïK¬êZ™Ô"{YuK{gµŽ[%¶Ó¼ß´NKnŽp똔Þh~ûåÆ @ÇÏ“ûß £Ï“ûß ¬A5ׂuû{xžY¥Ó®8ãRÌìc`’Ií\–±ÿ ^™«ê3[+Î P5ü1Ÿ1¡V»mÛV˜£V Œ6ìFäô¿>Oï~‚>Oï~‚¼ò]SÆvúd‰öW¸¹ºÓ€´–ø†oßíwÝ䵚°eE‚ª£ã¥ñ„]x'_··‰åš]:á#Ž5,ÎÆ69$žÔ½çÉýïÐQçÉýïÐW-¢ÚjÐø¿V›T– 2ÂÍ#žÞÑàŒí’ä•Ã;å†àO=xîzZÍ{ˉ‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶)éÿòõñqÿ£Z¬VtºO#_ÞÄäp-䃽ËsÁ'®:öíš‹û?è+¬à_ÿcR3ZŠÉþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±  j+'û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€5¨¬Ÿìÿ ®±ÿýØ ÿA]cÿÿûÖ¢²°þ‚ºÇþÿö4`'ýuü ÿìhZŠÉþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±  j+'û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€5¨¬Ÿìÿ ®±ÿýØ ÿA]cÿÿûÖ¢²°þ‚ºÇþÿö4`'ýuü ÿìhZ©j:î™ap\Ý*J#RT+63ë€qU¿°þ‚ºÇþÿö4`'ýuü ÿìh¿ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáNþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ± ÿÂU¢ÿÏïþBð£þ­þòÿ…;û?è+¬à_ÿcGöÐWXÿÀ¿þÆ€ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþïìÿ ®±ÿýØ ÿA]cÿÿûoü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øS¿°þ‚ºÇþÿö4`'ýuü ÿìh¿ð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáNþÀOú ëøÿØÑý€ŸôÖ?ð/ÿ±  v:…®¥âÖšÒ_25±ÚNÒ9óî=ÅtU“ý€ŸôÖ?ð/ÿ±£û?è+¬à_ÿc@ÔVOöÐWXÿÀ¿þÆìÿ ®±ÿýkQY?Ø ÿA]cÿÿû?°þ‚ºÇþÿö4­Edÿ`'ýuü ÿìhþÀOú ëøÿØÐµ“ý€ŸôÖ?ð/ÿ±£û?è+¬à_ÿc@ÔVOöÐWXÿÀ¿þÆìÿ ®±ÿýkQY?Ø ÿA]cÿÿû?°þ‚ºÇþÿö4­Edÿ`'ýuü ÿìhþÀOú ëøÿØÐµ“ý€ŸôÖ?ð/ÿ±£û?è+¬à_ÿc@Õ“¦ÿÈÁ®}mÿôGöÐWXÿÀ¿þƬéú\:k\ ÿ‘Cÿ¯¿ô[µ2ø˜ÖÆ?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅ#1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÝ0p]÷4žOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}T3I ÅÏ™1"4%°2 ?Îh'û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÚE.ÁGSëNòé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûê'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾¨òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûꡚH`–(žxüɉ 9-“ùþs@?ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@V:UÔ›_]êjÃää„ÀÜcõüëÏþ9ÿÈKÿ¯£ÿ šõZò¯ŽòÒÿëèÿè&´¥ñ¢gðÇ‚¿äGÐÿëÆ/ýVíax+þD}þ¼bÿÐEnÔËâc[QR0¢Š(¢Š(¢Š(Iÿ×7áüª:’õÍø*Ž€2m_Ìd ?¹ø?½ê6æxoA¼³×ín$µ½¶¶°°–Å#¹¹ŽX³BQ ÙÉDMóÈ«#MÙÆ´¬}GþFMþÛÿè¶+Qÿ‘“Dÿ¶ÿú  Š(¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€$ƒýrþ?Ê£© ÿ\¿ò¨è†µª¦‡¢^j’ÛÏq¤Fi#ƒný‹Ë¹€àdõíÆNTÅ:ZYËq©NšI†³M¡4q˜å(.àÅ (ÊÃk¨ Oâ2moú†•Ê[=änfxŒÆÖ;C.N Ç<z˜ü/¨Á|Ú¼­¨Ö%i ÒIdÍnÊë ± C)Å´\—<ïã‘´xêºrß%‹_Ú‹ÇfD·3/˜Ìª€\䬬G`Àô4ZjºuýÅͽý­ÌÖ­²â8fWh[$aÀ9Sx>‡Ò¹ÛZiº|Ö–×ë.¬&<@ÉåÚFÌ1»>KðàzÉáGá»#^=Ø‚²Ù™$œ´Pår¤<¬™;#åËÀu5¨ÿÈÉ¢ÛýVÅcê?ò2hŸößÿ@±EPEPEPEP^UñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5¥/?„î<ÿ">‡ÿ^1è"·kÄÅ;ß»øm4Û{¥Ò¬„åÙ ‚2SvÞqœg4Âõ¿ÿ %·ýþoðªt¤ÝДÒG¶Ñ^%ÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ½ŒûÁÏÖï]’îFµ]9`'ä—-|qþ{Ô?ñRÿÔ'ÿ"W•Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÕâ¥ÿ¨OþD£þ*_ú„ÿäJò¯ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð£ØÌ9âz¯üT¿õ ÿÈ”ÅKÿPŸü‰^Uÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{‡> endobj 420 0 obj << /Font << /F17 200 0 R /F20 263 0 R >> /XObject << /Im8 413 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 427 0 obj << /Length 154 /Filter /FlateDecode >> stream xÚM»Â0 E÷|…Çd¨kÇy4+¢…"Ñ‚š­b±Uˆÿ_EHÕ]¬ã£{wYÕ%`Æä½…ü„& ƒH ’ó0ë€Mës;{S±¦ôxÉý8Læ–OuÇqÛ#©ÁЯDø+©6+.¨,“90¡'†û¢ÞŠ0ødݪlïõédÅà£üaÝ/ ö/u-ù§7+ endstream endobj 426 0 obj << /Type /Page /Contents 427 0 R /Resources 425 0 R /MediaBox [0 0 612 792] /Parent 429 0 R >> endobj 414 0 obj << /Type /XObject /Subtype /Image /Width 430 /Height 573 /BitsPerComponent 8 /Length 30684 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W«\øWÂV{~Õ0oÎß6é×8댷½Aý…àïÙàqÿâê}µÃäŸsÎ¥ñ¹9¸ßöŽM>M9 HÛdQ>7Ëgw’OÒ’Ï^Õl.´YáK2tx¥ŠØ:1Ýæ 6ü7>ØÅz7ö‚?¿eÿÇÿ‹£û Áß²ÿÀãÿÅÒö´v°rO¹æ6šž£iƒ‹Rº+HöùF˳°c¿žFGlVÖƒâkm2 ޱ\—Ô[PX¢²YBHNIŒ³‚‡¨çç•Í­_\jòâËL¸d´ŽÒ4š* !²ÜžAJ«w¨jú”š†£,m3"Æ©á óùäׯÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñUJ½$îœ$úž7å{ <¯a^Éÿ_†¿çÅïüŸüUð…økþ|WþÿÉÿÅUýn‰öLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñT§Á>'OÀÿ®òñT}n‡ì™ã^W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡a{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“³ÉÿÅRúÜ;Ù3Æ®´½ös=Í¿™!!êX ±³²{{8Ê+… ÝOÖ½þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ©úÅ;ÞÃä‘äH¶Ïiä\Ær@× ‚)¶ž[tÌT†žF8&½{þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿЧõš}ƒÙÈò'hÍêJQ‚qÏñ©X¥ÃΣ¸ŸcdÐW¬ÿÂá¯ùñ_ûÿ'ÿNÿ„#ÿôÿÈÒñT}f˜{6yË8m¥ŠÝ6ïÜv… dõ5Îx•vÚCþÿô¯ áðïý¿ò4ŸüUyÇÆéz>‹§Kakä»Ücæ3dm>¤ÓUá/u!85©é^ ÿ‘Cÿ¯¿ôT‡ÿ^1è"±üQÿ!Uÿ®cÿBjážìס>ºme†+TÃ$í¶$’ãiñ‚y<Žž¢§û}çüýÏÿ q¾ ¾M;S»[2öÎ(Q.åŒ"…y2dVu%|ewƒ€ y,õû©5íîäe– ÚÚX_÷r«)òUO…#(wו?1É- w_o¼ÿŸ¹ÿïá£í÷Ÿó÷?ýü5Çêzv³›…Å̶çÊ‘ËÊL’7ï›pèWŸ$à2(àuS-Ž‘©I0ûuýèmbòÌrlÛ.ù#sdª”_˜²·ñoǯí÷Ÿó÷?ýü5¾±-ä =®¤óÂÙÛ$S–Sƒƒ‚:ŠæD:ÈñbL"‘,™ØJD…£1ùgn—ƒ¸&qsó’×ô¸O•n­d¶ÝO I *ò³ƒò±P}‰è`ñ¡cue ºÊ·7qÂÆ\±PÇ?Ï56¥©^6¡8"£”€bMÿ!#þÂÿ:пÿ×ýuæh!¬JÛ1©9Þíâsó:ç*9ä­‘ÛÒ¥û}çüýÏÿ yÛ¬k£‘HD°x….mdºƒXYmâÏ™4w;‘02rAÀÀæ­}¾óþ~çÿ¿†¸ù­ui´m[Þ›©`T¶i$†+ãv2ñ_,çïä@2ë0ÝÝÝZê¹Ào— j~‰­érÅwlg’y5K÷šÞk°° gk‰"F@Ý!…‹íiâ>èÚ;o1ÿ¾ßFnÕnÝ®™Õ#/ó2©ˆH—'¶áë^o¤hÞ.šö+kÙ5KM/íQ¼‡í[d)ä܉ãs;í,mÇ0~e À½mj~¹·×4JÕuDÚA5²«jORÒFñ™à5Êçì6nYÈì¼Çþû~u®Æ·-Ñ—,b¥²AGPJ²ž ƒX:e¶·o.%‚ôéòoQ%Üà(\¦5IÙ <˜ÎÒK9`Cô:¿üo¿ëÞOýÐ>³}u¥iR¼ÅdžÎ)ähþRY—ž½«6}tÚË W©†IÛlI%ÆÓ!ã…òy=E=ä ¡ÿØ2ßÿA®;Ä·0[]j6òÜ[#jZrÛ!’æ8ü¢ £{‡`vþðr¡ÊÜtÊ$í~ßyÿ?sÿßÃQlKö_µi?ÙöyžwžvlÆwg8Æ9Íqú2ÞêS…žæKI.®¸y­÷ȪˆX6Ö ùGŒ |:n¡iàË6[µºŽÝb‰Òôïy‚½ ’<… dq¸l²û}çüýÏÿ 4j—Vˆ_JdU È&9çŒô8?‘®SV³Ö»°iàÅšáiÀýàYŽÝ •Ý¿ÈÉ<ɃsË»ΪZÚõ¬åµŒ![€H7nà¡!gåRr8%Ðý¾óþ~çÿ¿†·ÞÏÜÿ÷ð× ¶ÉÒ¤ò`Ô çWš)ï Ùk ‘8# ´’] sÛä«ö:F¥$Ãí×÷¢5µ‹Ë1ɳl»ä<Í’ªQ~bÊßÅ¿u‹¨Þ«sdòäʯAâ;ëýêWòãxïZÙL`Œ(PsÉ<ûÖEWü‹·ßö“ÿ@ûb[8{­Ià…qºIg*£'$œu4øµK‰¢Ib¾–HÝC#¤Ä†¡<ŠÀñ]ÄpxcPG’5kˆÄ’¤a”€2äS× =j„Íq­}ºÿK¼‘Õ,“ì±Áv…ÐókHÝ §<îÀÀaöûÏùûŸþþlz¥ÄªZ;é]C%f$dëÔA÷ÍÙC©/ˆî&’+“hû†ùäÂÆ6ªÊÊz?v‡–'; †ßS:$QKm~w’™a7cÏ–\ YFèó—ÑÁêãÕ.%RÑßJê©+1# G^ ‚¸§}¾óþ~çÿ¿†¸ô"[ÇçI^S¾&åHÓÈÆFÄ‘Y °àü‹Èn‡LÓ®b‘înî®ÌÆâr#i·'”dr‹·¦0Tƒ÷‡LíùhxëwöKr“4lÁebÊp3ëWïõ›Û›=>O3Ëiícü¬¯ÌçÓÚ°/ÿäuÿ\ŸùЛþAÚGýƒáþTV¥µÔv³ë ĸòá’çk¾N99›qoæMsa ¥± á¶-²@>Ù9+;[Ô¨ÉpÓAsoqä²0h§GV"“.ÐpÈw×ä–c;Ï·ÞÏÜÿ÷ðÑöûÏùûŸþþä¡·Ö`™.<»·Š)U¥·k•w¶J®ÊI °–ˆ…;ØHE8#WmN >dººòï'k{q¨K 2ÈSÊ*?~H1€‡v¨Àß@E]FõX0»› ç—$~UÔxSX¸Ölnå¹XÕ »xË  )É<ó\ut?¿ä©ØF_ý(CG]^UñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5­/  Üx+þD}þ¼bÿÐELJ.õÅž)í‘v‰ƒÔŸOz<ÿ">‡ÿ^1è"º¿åŸû‚¢Øã¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ*l9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,8Ù<¨=ÝŒ¢êËm½Ôs?ï%Tó—­Z¹ð•ì×sJ·6a]Ù†]³‚~•ÔQE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,3´ 2m@²Óç’'–!š"Jœ±ð`Ì„uÜØ#šÖÄš&£g¦è;Å«/˜“ȬË=Ô’»JgÙo&ÔÉV80¶¶ÈßÑ\Öž±Gñ\hìç‹Ï°´ß?Ù#–Di·~ónÖ`²D:“Ž?„ãJšæËÂC§[j:mšê×k1‡MužÞÙ¥šHÚ(^2H%¡^°¬Ü¤¨Epjþ0ŠÆåb²ºžK›6K ¼…VI\,rÈ»p²Ü¬ îÛUR@½/Œ šëÁ:ý½¼O,Òé× q©fv1°É$ö  ª+Ï,Óô·þË´ûû¤÷ZW†e²• Øå E"¹•¼ÀªHVÂÈNïVL·þ)Òü#2›Û[›h¯¯^+HíUâ‘®n|ñÌÎDD)å'rß) Y¢¸K}KŇÄÚŠÏû‹H>ÐÛÚY£(o)ãT€oþ튉Ø\S€šÞ ¾Ôï4û©­ëH’ü“]&ÍÀò€`¸ÆrcÇÌ0Ç -ÂxÉÕÝ"’ Éap¤ÙˆÙ@Séh¬VÉÖ]:9þÛ©²éË?—n¬žrÉ#gvôBÅŸkcä.›ÔQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢±|Q ”úA[ý-/â •X}µa}¬Cù˜qòsóvaÇÙ躮‡kmmcS ù'`£ÑX¾+žkÉ$R¼)çۭĨÅLp4È&mÔ2ä¸ ¨²1‘ƒ'ˆ-të{htŸZǦLҲ꺴sn¬¢?ܤ¬èd,]Ø1‘°c‘GÝÂwW% ëž!×n&˜ÙÙY[[ËKk8“Ïýå¼2º–à+Fe=TïÆÒ#Æã’¾6×­ü=c¨ÝYÙM.£¥­üQÛ+lÀŽÎ]ÀeÄþaÆ!Rä~ðzÂi>'ñµ.Ÿmnš\_jŠêQzàJŽ‘4:ÇοzWB¾oðîÈû‡·€ÌÖñµÂ$sD˪¶9ˆŒ÷ÀÏ   (¯-±ñŽ¿¾™t,g3jö°Ü•Ô%Œ@ò=Ŭ_¹òÙš8ö\†\ü¨Ø,d/½qâ-v¸´"2Îé­ç¿ƒLžé¼¨¥Eñ¹uȘňW?|ÚQ\>¯®¡â/ Ïq|‘^jž{‰l–á‚3“©X‹œðq’¹!x“Áž-Õ‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEpþ*׿ӼO½Â9³†î­ãKÓl×rïpñ 5Ä€,{aCæç&:êu-ÏUòÈd‹;%·¸’ ewÆÊÛN•Î U$p1n!µ·ŽÞÞ$Š”$qÆ¡U à;W-c{©¿‰–7’srn§KËF¹‚Ìû<«Ûs ’Åå+u´QEQEQEU KG³Õ|£r'Y"ÎÉmî$‚E]ñ²¶Ó…%s‚UI _¢€#‚mmã··‰"†% q¨UE8Õ%PEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHÌ]S]–ÃP[Hl~ÐÆ!.|И#¸öª¿ð’ßÐÿ&—ü*kþFtÿ¯!ÿ¡šŽ‹_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\µÿ -÷ý¿òiÂøIo¿è ÿ“KþVŠ.-ÂK}ÿ@oüš_ð£þ[ïúäÒÿ…U¢‹…Ë_ð’ßÐÿ&—ü(ÿ„–ûþ€ßù4¿áUh¢ár×ü$·ßôÿÉ¥ÿ ?á%¾ÿ 7þM/øUZ(¸\ÖƒQÖ®aYbÐ7#t?lAíéR}«^ÿ¡{ÿ'c«ºwü‚-àú©éŒËûV½ÿB÷þNÇM{Ýr(ÚI4DPY™¯£Ô“W4ÏùØ׬_úª>*ÿ‘nïþÿ¡­Sÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E+Šå¯øIo¿è ÿ“KþÂK}ÿ@oüš_ðª´Qp¹kþ[ïúäÒÿ…ð’ßÐÿ&—ü*­\.Zÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E –¿á%¾ÿ 7þM/øQÿ -÷ý¿òiªÑEÂ坸Io¿è ÿ“KþÂK}ÿ@oüš_ðª´Qp¹kþ[ïúäÒÿ…ð’ßÐÿ&—ü*­\.Zÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E –¿á%¾ÿ 7þM/øQÿ -÷ý¿òiªÑEÂ坸Io¿è ÿ“KþÂK}ÿ@oüš_ðª´Qp¹kþ[ïúäÒÿ…ð’ßÐÿ&—ü*­\.Zÿ„–ûþ€ßù4¿áGü$·ßôÿÉ¥ÿ «E –¿á%¾ÿ 7þM/øQÿ -÷ý¿òiªÑEÂ坸Io¿è ÿ“Kþ¹e-Äö‘Ísn¶í ܱ‰7ü½‰8Ì×[üyÚÿ×þT BÑEÆcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒÂ½Òîo¼GæÆb[@¦G8·ž©ÇùäT¿Ø?óÞÛþû?á[P?öÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þg®ÞͯE²žòâÍìþòÕ! Vv=pÿ»' \CŒu—©¥aXÇþÀ¹ÿžöß÷Ùÿ ?°.ç½·ýö¶(¢Ácûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ ¥y>©/‰–-6öy–c[ˆ(…¬¥„®xÒ•,TFp3õ w<~×ouËe¸d^Ùµä¢á´ç©ä?rIÞ>lðËÛ䌰XÑþÀ¹ÿžöß÷Ùÿ ?°.ç½·ýö¶(¢Ácûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ ³¬ê/¥i3ÞÅg=܉´,0£;1f ¶ŒåˆV @8Áãô¯ê7úU²Üj)fæ}CÎÔ®¬ZÇÙå%"É·Ær~bÁa”d8.…‚ÇOýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…]Ò®æ¿Ò,¯.-^Òkˆ#–Ki3ºe¡È œt:Uº,(Ém«Aimobúv# ½§w䓞ŸçŽaò|Kÿ=4_ûêJÔ®K^ñ¶:ûZ{ •…¬z…ÜÖ£æ"ÒóÆ5U3#î1±²ÆkÇiâ †_HÅF7¼„ªrô¨5 3Ä•Œ–“M¤,rc%@x ÷ÕNÏ]½›^Š7d)=åÅ›ØýåªB¬ìzáÿvN@¸‡ë/S@ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅP×/_MÐ5褂9-­e™^à1J© ¸_˜¯ãœt¥aX­ýsÿ=í¿ï³þ`\ÿÏ{oûìÿ…s–úγ ÛiW7°4òÛÇöE-ÍŪÊ&ùÿr<’¬Ñ,qç$Hçpa±[¨Ð5µ]¹Õ³Hã$ʮʲ $üŽ:òxaËu%‚Ä_Ø?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVÅX,cÿ`\ÿÏ{oûìÿ…Ø?óÞÛþû?áXñkºÍ®â¯šÕ®-5 MŠ|›H¤ŠÝ™˜ð]#ó]Ù‰]ÁIù ×õ3i¯¨Ak¼· ýµlðËÛä©¢Ácûçþ{Ûßgü(þÀ¹ÿžöß÷Ùÿ Ø®j=[S¶×ü@·©çÛYØAumieù-p༌"^8£8,Å‚Åßì Ÿùïmÿ}Ÿð£ûçþ{Ûßgü+˜ÒüWªj&úÚiÞI5híÁ²’±ŠKepš‹½üÌÆ –•¦ÖXÏY j3jº47sªf‘ÆI•]•e@Iù(uäðÖêKˆ¿°.ç½·ýöÂì Ÿùïmÿ}Ÿð­ŠÁñî§§xCT½Òd‚+›{Yfóe¼°‘³eW£6@$œØÚÅ‚Äߨ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVV½â9luö´&ö+ Xõ ¹­!GÌE¤ æ3Œ,j"$ªfGÜ6ccfK=vömz(ݤ÷—o`÷–©b³±ë‡ýÙ9bâc¬¥‚ÆöÏü÷¶ÿ¾ÏøQýsÿ=í¿ï³þ±E ÿØ?óÞÛþû?áGöÏü÷¶ÿ¾ÏøVUÖ³«Xê)77QÅc¥Çyh¬ŽÑÅ“r7HTolùJÄ(à| 75}gY†í´«›‹ØymãûF¢–æâÕe|ÿ¹IVh–8ó’$s¸0جX,tØ?óÞÛþû?á[!<¸`Œ²±H•IS‘+/@ÔfÕthnçTÍ"Œ“*»*Ê€“ò8PëÉá‡-ÔéÓQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(1+p÷  U@£s*’TÔ€Y°;n>µ%PEPdÞÐî51©Ï£iÒ߆WOj(eÆÓ¼Œä``çŒ ¿Äò¼q"<;FU»`.O©Â¨ÉìíRQ@Q@AöO'Éû,W›çlòÆß3™¿Þßóg®yëSÑ@Q@T»Ò´ëû‹k‹Ë [™­[}¼“B®Ð¶AÊ2§ r=¥[¢€#B·p± ™ÕQä 72©%A=H›¶ãëRQ\ÔwW—Zæ§+ëc¶Óïá³KvŽ3 Áâ…þbFÿ0´ÅWkŸ+r¥¢¸} ÆW§Ãºlú½ª%ÍÖ’·–ò¼Üܺˆ•ƒ¬hv’dبßu[d°ñÅö©wŸg¡gP>x•gàŠ#²L‘ 6•¸^|¼îÁS¼t¶º“c§Íai¥Ù[ÙO»Í·ŠÝ97 Ê@稫õË[뚯ü&W6×PZÛiBÎÎL\]–)%i” *ÎΪ›|Ì| ©%ˆ­?êÏ¢hrÞÄ›äóa…vÒm2J±†Ø¿3ã~vŒÆÍkQ\>™ãFîûûÏN{û”iÑno7Yec[wÝ*4{”‘påC–PBª¿È?ÄX^ãNû=­ªCzÖb8ï/D7R-Á!XHŠ$Á;‡Ì’áÉétïèzEÃ\iš6e3.Æ’ÚÕ#b¹¨aW ´ŠÐZÀ-¡ÙåB#a6¯A´¨#01Ò¹–ñ Æmâk‹·žùlõHíícòÆáæÇnQ?v™*cÈV|vcÁ×ðö±>µ§É=ÆŸ=”±Êcd’9_€w'˜ˆå~ld¢ò € Ö¢²^öâ_.æ}žmEÈàvY™ ‚z,xFm¼æHùQþÞÛU/©­Ýú¦b-Þ0#ùpCr g #@ 5-IÖ|¯íM.ÊûÊÏ—ö«t—fqœnÀü…@<-ááwØÐt±sÏ*agôØM­Œ¡@鎔ýQ›UÑ¡»P;4ˆ0BLªì«*OÈáC¯'†·S§@Ç1<¯H3o‘•@.Ø “êpª2{;T”Q@fCáÝßS:œ6ùfst–¨²–lî;ÀÎNNNyÉ­:(±´’+¨žÖŽï?hVŒ6T!Þ?‹åyì©è¢€ ©¨éZv¯n¶ú…­ì*ÛÖ;˜VE ‚23‚y÷5nŠÌ_èj–hº6œÅ‹Ú(µL[±;‰”’ÈÇ#5|A Ü=ÂÄ‚gUG(Üʤ•õ lÛ­IEQEfCáÝßS:œ6ùfst–¨²–lî;ÀÎNNNyÉ©-t=&ÇOšÂÓK²·²Ÿw›oº$rn;” €ÏQWè Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@W¨jšì7.ˆ\ÚÂöºJ\éáv……˜Ü€Îï€Iò‘Žp«Óœ`Šæ¼1q¨BþÇU¹½–å"†áåà}‘Hd “H™·/Σ µŽMt´QEQEQEQEUI4­:]N-NK W¿…vGtЩ•žã |ÍÀ=Ï­[¢€*+Nkt·k S @Ö©…v¬,hÀÆ«•èvJŽÃCÒt¬givVxݳۤxÝ·wÝ®ÄÏ®Õô~Š‚[Iîíîæµ‚K›mÞDÏ/á†ÚÇ•Èàã­>h!¸@“Ä’ ep®¡€e!”óÜ=ˆ¤¢€ KHîÚí-`[–Îé„`9ÈPrÝyÆ?à è+2_ [IqÛ«¨¬"h¤le¾èŠ˜Èw Rˆv£*åy-»jŠ¡‡¤Ãöß+K²O·çí›mÐ}£9Ï™ÇÏÍ×=O­X²±´ÓmÒÆÖ [hó²#‹““…I?OEG$Êñ<‘#¼-¾6e£`®G¡Ã0ÈìHïDðCuo%½ÄI,2©I#‘C+© ƒÁv©( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘™Z޽o¦Ý­´–÷2ÈÑùŸ¹@Üd_j­ÿ ]·ýõûò?Æ©ë_ò3§ýyý Ôt®+šð•ÛÐ?Qÿ¿#ühÿ„®ÛþúýùãYôQp¹±ý¸ÿôÖ?ðÿ¯Yã[êgSƒÁ“Å~YœÝ&–‹)fÎã¼s“““žrk¯™ØLÀ1ëT¯f•"ˆ¬®¤Ü@§ GU~ â˜ÌM:{-"Ý­ôÏ _YBͽ£¶ÓÖ5-€2Bàgsì*ÓøƒÊBòi²(êÍm€?ZÚóûíù×9âid7ú\fGØL¬Ww…8üOç@ÿ„®ÛþúýùãGü%vßôÔïÈÿÏ¢•ÅsCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÑÿ ]·ýõûò?Ƴè¢ásCþ»oúê?÷äð•ÛÐ?Qÿ¿#ük>Š.4?á+¶ÿ ~£ÿ~GøÖµÑ¼¶YþÏ4 üªÌ 1¸ñ\Íu±ǯýpOå@ ESÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR3Ô,®oÿøúÿØšüûÿãëþ4Ë_Í>§hX]ÞO§ÛOš&‡ÍÞÎ:lo&@1ÈÚ¤çyô4X,R½¹Öä¢ßDi¡ #]"î÷Ç8ª’>¹pbI4&DY£‘™nãc…pÇOZØ¢˜Ì¿µkßô/äìuBöÇ[Õ/¬ä“Iû:A¿'í(ùÜÓÒ¨jº¥¿ˆ ´·û,Ñ»F œpHòùLpÓ<À„„œ…e;ü¢·6ÐüG6§qeç@‘êY¶¡c°’Ë1‚²çø–6ùr>f_ààþÄÔçßÿ_ñ£ûQÿŸü}Æ·¨¥aXÁþÄÔçßÿ_ñ£ûQÿŸü}Ưë:½¦ƒ¤Ï©_>È!Ú Èf`ª2Ä(Ë0bÎI&¹­ÆWzõ•´VK›R–[Âþ]Á{tŽÞ`›w¸³¬á¶‡/ƒ€ŒX,kbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ãZzV£¯¤Yjvêë äÜF²+¨` Áõ«tX,`ÿbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ã[ÕÍk>)‹O×âÒþÓ¯—wwRÍËû–f^±FÆ-+‘å2ÊX,Oý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿ2×ÄsO©Àw“éöä扡ów³Ž›É r6©9ÞD}  ?Øšüûÿãëþ4bj?óïÿ¯øÖõTÕoNÒ/o’4•í ’eŽI–%bªN · >ñàu4X,fbj?óïÿ¯øÑý‰¨ÿÏ¿þ>¿ãY6^*Ô¦›û9¼‰on%Ž+k‰,f³TfI‹Á+ ªÀÄ0 9;]¬Ã¥Ñõ/í]8\˜¼™Y`•n $R4o´àew!Á 0H`±CûQÿŸü}ÆìMGþ}ÿñõÿÞ¢‹ŒìMGþ}ÿñõÿ?±5ù÷ÿÇ×üj¥¿Š/Ež±=Mk¨Ãcml%ç3$_šã ÓÅCÆüeˆüG¨Ï|Ú$Z¶±H&’BÉnëÂä®2À¸¸ˆ`ça.rû°X·ý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿiéZŒ:¾‘e©Û«¬7GqÈ`®¡€8$gÖ­Ñ`±ƒý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿIâ-Z÷IŠÉìíTšòÞ ¥•ð±$“ÇÀ³Ÿ3ŽÃ“ÀVƒPÕuKAioöY£vŒ8à‘åò˜á¦y 9 ÊwùD+nl)`°ÿìMGþ}ÿñõÿ?±5ù÷ÿÇ×üišˆæÔî,¼è8uK6Ô,vYa0V\ñ¿Æß.GÌËüß¡¢ÁcûQÿŸü}ÆìMGþ}ÿñõÿÞ®yÑ.n-à’P%}± Df,ÝÈùq…ä’Ê2ÊX,Gý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿA¬ø¦-?_‹KûL¾\QÝÝK4/îY™xFÅ´®vG”Èmÿ,–¾#š}NÐ °»¼ŸO· Ÿ4M›½œtØÞL€c‘µIÎò#,ý‰¨ÿÏ¿þ>¿ãGö&£ÿ>ÿøúÿoQE‚Æö&£ÿ>ÿøúÿØšüûÿãëþ5ž"Ô ÔÀ¨ êB 9¸·EQE’ÞÓŽ­&¦¦ö;™eY¤_Ïnꪠ´jáÊŠG sš·i¥ÙX\\Ïkl‘KrÛåeþ#’–fÀãs»uf&ÝQEVd¾Ò§±ûÖI%·Ÿ%ÎÇ$þñÙ™ÎIλ‚:vR6’+NŠ(¢Š+3QÐ4ÝVág»…ÙöùngfL“²UR©Ë|®ù›˜çN¸½?ÆhºEΦ=¶µkÕ²[DUí·Ëo£–r$æårÀ'Ü'iÜêcÒì¢ÔåÔRÙòUØòޤqŸ`HTõ!„\[®[Vñlöš½­†“uz´ZÆä'”~Ëö°¼Š2C/'Œ#Ž»s%玴k/.…4¸¹óc›Íˆl’@»Ë.$lïO™Q”nä­´¥¨ç‚«y-î"Ia•JIŠ]HÁ#µdè>$‡Äð\Á§ê6ö×-Ä\ÂeR@Á%H,Íܔޠµµö£ý¯c¤é’ÚÛÍq÷-=Ì 2…¢]¡Ðä™Îî6‘ƒœ€ "ðÖ—¥Å·•<«q·Ì’âêY¥ùNS;]­–\µ‰a‚sZPA ­¼vöñ$PÄ¡#Ž5 ¨ `Ú¹«OLš­õ–¥`ñ‹{È-Z{pZZX¡(¬í‚äË)PQxK&9~!èÐ__Yʳ™í%XÚ8+‡|Ì– ³ 4‰ò°W9áI¶Šåµ_ÚË£¬ÔYîïÚ{y+"mäXʉڧ!™p® ®¦€1l|)¤X=ÛGÔ¢ñJ\¥Ýì× 0!TîI”ª«’3ŽœTòxJ›L‹N–É$µ‰·ª9,Kî,Äå‹n`䓼;†ÈfÏ/cñ;LVi$‚â+ˆ’â´÷óç·F–(‚LŠr$ÌÈØ\ÿ€J“hx¶7qk“¨Ë©†u—O_$KA32ÈÄП•Éýàã†ÚÐÑ\õ‡ˆ&Ôµ}­Â 3TÒ^þ4’"&FV‡`ÅpVn˜à¯SšÃÞ:ѼM¨Ig§ËºAž3æÄþl`€[ìÑýåùdß7NZƃa®¤)ö¢°tX/&€n0'ËeÉT‚s‚21PEá]2 ï¶DÚŠLZ7}ºÈYQK¯™µÎÔPK»æ§Ö5¬…µª¡¼¿ŸìÐ4 ˜ão-ä,ÀH  n8PK %—SݼQ[@ÚkDÆiŒ˜u~ÀËŽs–$¦À$’ÓK²°¸¹žÖÙ"–å·ÊËüG$þ,ÍÆçvêÌMºÌ±Ôf“W¿ÒîU ÖËÂI!ZZ@€‚rØ à0Æâ«§@dÁá½:Û[“WŒÞý¶O¾Í;#› c.ShÞÄ.0¹à Ö¢€(K£ióE}–ù[éViÈvÈªŠ®¤«`®*Áæ­Á6¶ñÛÛÄ‘C„Ž8Ô*¢€j’Š*†¯£Ùëº{Øß‰ÚÙó½"¸’à‚ ±F©åOÒ¯Ñ@²xSH™"Icº”F¾[y—³1™2[dľfL³adÜf`oÇ¥ÙE©Ë¨¥²-䫱åHã>À¨ êB 9¸·EQEbÿÂ)¤NãPxåLs¬×³Iˆw|9Bƒ{ávàn8¤‹ÃZ\V—ÞTò­Æß2K‹©f—å9LHì]v¶YpFÖ%† ÍkQ@Á6¶ñÛÛÄ‘C„Ž8Ô*¢€j’Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPX±øOE‰%EµrŽ»ZâF(!€‡-û ¡=¸(„cjãjŠÅÂz,6rÚÃjñ$³ý©¤ŽâE—ÎØÈ$ ¼9Q†`rÙlçsfx4 6Öú;»X^ÙãP‚+yž(H °n‰HF!@PJ’¨þ:¡«½ÜZ{ÍiecåfIg½€ËÆ' H˜ìrNŽàÅ•¾›§ÛXÚGåÛ[D°Ä™'j( žOuªú–gªùFäN²E’ÛÜIŠ2»ãem§ J窒8æ¢ñ^­o¤µÍý¤[ªj å¼-öwiv"!-¶P‘±`Ì@e ½;JÌOéQ[Éo’G “ÃrcŒ•Q$B1¢ø/NNjGàÝ;”œ[NZ=¾R5ÜÍ!dIBÇ}¨¡âŒíP cŠÞ¢€*j:e®©n°Ý#½)Z)#l•t!”à‘FA#¡"§‚mmã··‰"†% q¨UE8Õ%’|3£˜tèM§îôè’Qæ?îÑ'Qל4s÷}Îjk~‡SN&iþÑÂÊU¢¨!€Ál‚H#¡¢€1l<-¦éÏ¥Kºy´»1co#\¸PȤ#µI%zªÿtbÞ›£Ùéh²¤rc5Ä`g 3Fqµc‹ôP¶Vú…£ÚÝG¾'Æ@%H ä2‘ʰ À‚EOE­•½ŸäGµ§•¦•‰,Îç¹'“Àz`ôQ@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE#(_kZ~›0†îãË‘—pñ’;cU¿á*Ñç÷ÿ!?øVnµÿ#:×ÿÐÍGJâ¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü(ÿ„«EÿŸßü„ÿáY4Qp¹­ÿ V‹ÿ?¿ù ÿÂøJ´_ùýÿÈOþ“E šßð•h¿óûÿŸü*½æ»áÛøV›Ÿ25–9€Ù ùãut<̪j÷‡˜¬Wd“úÖ·Ÿ'÷¿ALg/w«xbþâÚ{©Ym›|LÑ?Êr§#*­ƒÆäFêªEÏøJ´_ùýÿÈOþ«my<’݆|ˆçؼ–‡›Χóäþ÷è(þ­þòÿ…ð•h¿óûÿŸü+ÊækËU¸¸‘¤šBÅ™»òjÅ+Šæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð£þ­þòÿ…dÑEÂæ·ü%Z/üþÿä'ÿ ?á*Ñç÷ÿ!?øVM\.kÂU¢ÿÏïþBð­;È/íÄöÌÏ$(W8ôÈ®bºØ¿ãÎ×þ¸'ò ¢Š)ŒÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©Ìj±I7ŠUbÝ…8U$ãy¥ûçüúOÿ~ÍtÊ;:Œ; ¤ à~§ó§yýöüéXV9°^Ϥÿ÷ìÑö ÏùôŸþýš½oâuŸSK*Uµšym-î‹q,ñoóoUË|1à˜ß ØdÚóûíùÑ`±Ëý‚óþ}'ÿ¿f°^Ϥÿ÷ì×Qæ?÷Ûó£Ìï·çE‚Ç/ö ÏùôŸþýš>Áyÿ>“ÿß³VµÝéÚÝ­›ÚÄ`¸•a7ƒí3·sÅSº4Þ ’ÊT+¤ZM'ÄëªÜD‚)bŽîwa#6~Ó* àr‡.‡içk¡ûÛÕ Š?`¼ÿŸIÿïÙ£ìŸóé?ýû5ÔyýöüèóûíùÑ`±Ëý‚óþ}'ÿ¿f°^Ϥÿ÷ì×C{¨Å§Ú=ÕÔì‘&2FX’N¨³@ $$Ö §Œ./l­Ú.äêKt‰,vó¤bùٻYÀÎÐÎ¥‚Ã>Áyÿ>“ÿß³GØ/?çÒûök¡±ÔbÔ´ûkëIÚKk˜–hŸ‘¹#‚:Ôþcÿ}¿:,9°^Ϥÿ÷ìÑö ÏùôŸþýšê<Çþû~u‹©x•lu{m1$·ó¤h¼ÖººòVFe@™É#“jÎÆË/˸°XuƒÍ¦Ù]É-Û–(8¡ffëÐQý¸ÿôÖ?ðÿ¯M·ñ:Ï©¥¿•*ÚÍ<¶–÷E¸–x·ù‰·ªå¾ðLoÐl2myýöüéŒÂƒU’´HtT™§.Zœ¨¢äöä©è{T¿Ûÿ@]cÿúõ±æ?÷Ûó¨/¯žÇO¹»òîn<ˆšO&ÝwÉ&ÐNÕ^ìq€;šäôÍ6ú=:%{+…aœ†‰ê}ªßØ/?çÒûöj;=ôOqZ\ݼ© ©ÓïþÑm4Œ®Û Ûk*ÆÎãi!J‘¸°ZètÍUuKº„Ê€³ÆñÉÃG"1GC‚FU•†A ã‚F + ÆØ/?çÒûöhûçüúOÿ~Íucÿ}¿:<Çþû~tX,rÿ`¼ÿŸIÿïÙ£ìŸóé?ýû5=¯Œk=Rêk;ÈÎò;H¢~%¤HŒ)ÆÂÆe1ÈÝ· ñd®âÆ+fÖ#gYì’`Älì²6YbÙГ" ‡(X,Aö ÏùôŸþýš>Áyÿ>“ÿß³] Ž£¥§Û_ZNÒ[\ijDüÈÀpyÖ§óûíùÑ`±Ëý‚óþ}'ÿ¿f°^Ϥÿ÷ìÖ–»âÑVÏ·7-su § É*F]˜ñÁaG-Ø`3-}GÄwzv·kfö±.%XcÍàûLÄíÜñBî7‚䲕 çi,*ý‚óþ}'ÿ¿f°^Ϥÿ÷ìÕí'ÄëªÜD‚)bŽîwa#6~Ó* àr‡.‡içk¡ûÛÕ6¼Çþû~tX,rÿ`¼ÿŸIÿïÙ£ìŸóé?ýû5ÔyýöüëßÄë.¯«Y϶–ÚlÎ×W-å««4ªÌä"˜[æ8Ï$|¸f,(ý‚óþ}'ÿ¿f°^Ϥÿ÷ìÓíüd÷It‘X\¥Ð¿6p\?–Ó±g ü~év31~îó²¶´ÍUuKº„Ê€³ÆñÉÃG"1GC‚FU•†A ã‚F  _`¼ÿŸIÿïÙ£ìŸóé?ýû5Ôyýöüë'ľ èz˜µ¹¼h"y1qªXînˆ )$Ÿ ˆRX,fý‚óþ}'ÿ¿f°^Ϥÿ÷ìÕíKÄ«c«Ûi‰%¿#EæµÕת²3*È&I¤›Pv6Y~]Å¿‰Ö}M-ü©VÖiå´·º-ijſÌM½T-ðÇ‚c~ƒa°X£ö ÏùôŸþýš>Áyÿ>“ÿß³]G˜ÿßoÎ1ÿ¾ß ¿Ø/?çÒûöhûçüúOÿ~ÍZ)s¨kvãN¿eÒíRàm\Éu“("8úža Ää|¸f£aㇾ‰ãŽ+K›·•!µ:}ÿÚ-¦‘•Ûa›bíeXÙÜm$)R7 E‚ÄŸ`¼ÿŸIÿïÙ®•¥­²°!„*#qUôÍUuKº„Ê€³ÆñÉÃG"1GC‚FU•†A ã‚F Z$±É$ýiŒJ(¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEfC¡YA©›äWÈf–8Kf(¥|ï‘ v“îÄ`É!m:( Š(  Sáù^ŸU‡ZÔa3´f[uX6TËF\'Þ8 0]ÈÁbj};B²Ó.kus…ò GmËm ˜â„ŒãÙWî¢*éÑ@Q@^ØÚjVi}kÕ´˜ß ñ‡FÁÈÊž ±m|£XX‹[žËÍ0–ЈdV˦ää#jÔBdV Cko½¼I1(HãBª(Àv©(¢€ ÁÕü'c¬êy,³Ã$Ö¦ÊèDý"Ü’LLYK*Í’…IÏ_•q½EfC¡YA©›äWÈf–8Kf(¥|ï‘ v“îÄ`É!m:(  ¾²·Ô´û›¸üËk˜šS$nF‘Èàž•=‚ž€ùÓ\ê·Zƒù{/äòÖhvoÙ³b* y’uS¸;+nS¶µì¬­ôûDµµdIœKIÉf'–bI%‰$’I$šžŠ(¢Šç¬ü%~nõmGPŽý„³Gqä¨ó@EY¢]DI‚Á759ðÅ‘·Eón–è3<—Ñ˲âRÀ 7:ㆠ£B¦Í†4+µEGÚÛÇooE J8ãPªŠpªJ(  {C:ì0BuKÛ(â•&Ũ‹çtut'ÌFû¬€ñŒóœÕx|74³ê)â PÉ/•ç#%¹YDjRL[•OÌÅT¨ܨ]Æ·¨  Í;B²Ó.kus…ò GmËm ˜â„ŒãÙWî¢*éÑE‚¾S­Ýê7­íÔwqyÙO»@ñ3ldƒmkÿOñ[ÔP=màÀ^>Ñ,d¹.V[XÒ6·‘c¦<.qÁÈ>d€‚®AÚ²²·ÓíÖÖ=‘&p ,I'%˜žY‰$–$’I$’jz(¬Í{Gþ‘>˜÷×VÜ+G3[÷‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAzþÛS¹¸mª-¬ABˆÅ²¿âI5GÁ_ò#èõãþ‚+v¦_ØÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢¤f?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[¦  >æ“Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿïª<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú£Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿ惘i!‚X¢yãó&$F€ä¶OäùÍdÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[H¥Ø(ê}iÞOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}T3I ÅÏ™1"4%°2 ?Îh'û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(*ÇJºƒSkë½CíR|<˜ì~¿yÿÇ?ùiõôô^«^UñÏþ@_ý}ýÖ”¾4Lþ¸ðWüˆúýxÅÿ ŠÝ¬/È¡ÿ׌_ú­Ú™|Lk`¢Š*FQEQEQEI?úæü?•GROþ¹¿åQÐM§‰4˹J‰ü¥m¦ÞI¾DºBÁÄOßRìc®ä#åtfyñ†¶)|ÚΜ,ÝYÒàÝ'–ʬˆlà€ÌªObÀu5Åê •4M:ÒÖîêåà‚ÞÊušV•]ų¼ˆ“3¢°1؃0p¿'„uQâ›=^;ÛV½ u<·Mf™ÖÚ%Q}à¢nUó¸­°€u/ª¤zü:C[Î$šÖK˜çù|²‘Y~öíÃÌCÓ=x"¬C}iqäy7PIöˆŒÐì61·.¸ê¿2ò8ù‡¨¬[/ M§jz$–—Éö +Nm=`–ÒȧËùŒ€÷1ÿ÷½FÜÏ è7–zý­Ä–·¶ÖÖؤw71ËVhJ$91¨‰¾yd`É»8€v•¨ÿÈÉ¢ÛýVÅcê?ò2hŸößÿ@±EPEPEPEPEPEPEPEPEP®_ÇùTu$ë—ñþUPÖµTÐôKÍR[yî"´ˆÍ$pmß±yb70 ž½¸ÉÀª‘ø§KK9n5)ÓI0Ïöi£Ô&Ž3¥…Ü¡%XmcÁõ üC¦M­øwPÒ ¹Kg¼íÌÏ"¸ÚÇheÉÁ8烃ÏC“…õ/›WƒUµÄ­!šI,™­Ù]aR!(e8¶‹’çür6€oWN[ä±kûQxìÈ–æeó•C° œ’•ˆì†‹MWN¿¸¹·³¿µ¹šÕ¶\G Êí dŒ8*rÐúW;càKM7OšÒÚãýeÕ„Âgˆ<»AHÙ†7gÉcž2YÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû¯ew|Ö";møÉܸïøW—Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛkʾ9ÿÈKÿ¯£ÿ šÇÿ…ëÿ@KoûüßáI­qñ–ñ4IÖ-(ZF×bdS6ìM¸%q÷óœöª9Aó=„äš²?ÿÙ endstream endobj 428 0 obj << /D [426 0 R /XYZ 86.4 708.045 null] >> endobj 425 0 obj << /Font << /F20 263 0 R /F17 200 0 R >> /XObject << /Im9 414 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 433 0 obj << /Length 186 /Filter /FlateDecode >> stream xÚM޹ƒ0D{Å–vÙõMIˆ9¢%`ª(U¢t(Êÿ7áÚfôfV3§ÈÒŠÉÜZñ„(=8ô…ø†×J<ã%­ƒÎIopË”Mq‹¡‰VϤH\¦ø8´]½¡Ø„E8^÷Å­iËâºñqØŸÚN$Ä£ úJz^åy–r"[ºæó/µÍAJ‹¯‰ýÊÌæÊ¬‘£^M£W Öé¦íDç/»Ï÷c7í endstream endobj 432 0 obj << /Type /Page /Contents 433 0 R /Resources 431 0 R /MediaBox [0 0 612 792] /Parent 429 0 R >> endobj 419 0 obj << /Type /XObject /Subtype /Image /Width 430 /Height 573 /BitsPerComponent 8 /Length 23179 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W®xpu°ë<ŸüU'ü!~ÿŸÿ¿òñU>ÚaòO¹åÒø\œÜoû Ç&Ÿ&œ$m²(ŸŠå³»É'éIg¯j¶Z,ð¥™:+ÿäÿâ¨ui5k1¨É+ÿäÿ⩺ԚI­…É.çœê>*¹Ùek¢Û[ÂÐéXK{4¿B2FÛ°;‘žµ’×ןðÛh¾M”–öĘf’"f‡q‚°8çäõÏøBü5ÿ>+ÿäÿ⨠ðÙ8Ÿúï'ÿIU¤º1¸Éža/ˆõkGU¼ž:uÔŒ^}¤Ð³@|°œnÈ#õëU¯5cP¶Õ¡º’Ùÿµ<…›•$-”XÀ8ëšõ;Ÿ øJÏoÚ † ùÛæÝ:çq–÷¨?°¼ýû/ü?ü]Ö`åŸsÍæÖ¯®5yqe¦\2ZGiM • „Ù nO ¥U¿»Ô5}JMCQ–6™‘cT‰pˆ‹ÐyüòkÔ¿°¼ýû/ü?ü]Ø^þý—þþ.©W¤Ò„ŸSÉü¯aG•ì+Ö?°¼ýû/ü?ü]Ø^þý—þþ.¯ëpì/dÏ'ò½…W°¯XþÂðG÷ì¿ð8ÿñtax#ûö_øøº>·Áì™äþW°£ÊöëØ^þý—þþ.®Ÿøp ?þ»ÉÿÅQõ¸vdÏò½…W°¯dÿ„/Ã_óâ¿÷þOþ*øBü5ÿ>+ÿäÿâ¨úÜ; Ù3Æü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª>·Áì™ã~W°£ÊöìŸð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU[‡`öLñ¿+ØS¢QÈì>PyÇÓìCÁ^'Àÿ]äÿâ©O‚¼8:ØõžOþ*—ÖáØ~Éž5u¥è׳™îmüɱRÅ“ÛÙÆQX(Vê~µëÿð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUOÖ)Þö$"E¶{O"à63’>¹H-´ðÊÛ¦b¤0 ò0ÈéÁ5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüU?¬ÓìÎG‘;FoRP¢ŒŽ{ÿH¢Å.u•À û$‚½gþ¿ ÏŠÿßù?øªwü!ÿ wþF“ÿŠ£ë0ìÃÙ³ÈvYÃm,Vé·~ã´)'©®sÄ«¶Ò÷ÿ¥}ÿG‡èÿ‘¤ÿâ«Î>0xKÑô]:[ _%Þà«1›#iõ&š¯ {© Á­OJðWüˆúýxÅÿ Š¡âKû˜¯åh×nì¡Á<‘×ÓŠ¿à¯ùô?úñ‹ÿAâù ¯ýsúW ÷f½ iõÓk,1\j¦'m±$—L‡ŽÉätõ?Ûï?çîûøkñòiÚØ2Øy—¶qB‰w,a+É“"³©(Cã+¸ðÜkÉg¯ÝI¨Ïow#,°NÖÒÂÿ»•YO’ª|ì)C¸F¼©ùŽIiºû}çüýÏÿ o¼ÿŸ¹ÿïá®?SÓµ˜üج..e·>TŽ^Rd‘¿x$Û‡B¼ù'‘@ª™ltJI‡Û¯ïDkk–c“fÙwÈy›%T¢üÅ•¿‹~8@uo¼ÿŸ¹ÿïᨭõ‰o Yíu'žÎÙ"œ²œqÔW2!ÖG‹a‰dÎÂR$-Ë;p ¼Á3ˆ”ƒŸ˜Œ–¿ %Äz|«uk%´†êyHÈIW•œ•ˆèØúƒìHCˆµ «(UÖU¹»Ž2劆889þy©µ-Jñµ À¸‘ Ä üëoùéö‡ùÖ…ÿü„n¿ë«ÿ3@ bVÙIÎ÷hן™×9QÏ$mlŽØ>•/Ûï?çîûøkÎÝcYãŽÓX¶SáHd½B±;‰ÕfO$´Cn9àù»†¶šDêÍ~^IP$†åÌXÜ–Ú~Q…‘H*8Ál±¨Õ. ­¾”ȪLrÎ èp#Nû}çüýÏÿ q¯¥êÒ-ÍÐóáºM6$·Hî8yÐÊWy,I#råY™Ib |n®ŽúÝnôû›v‰eYbhÌnå‚Áa’õŠB%ƒÄ)sk%ÔÂËo|É£¹Ü‰“’5kí÷Ÿó÷?ýü5ÇÍk«M£j؆ôÝK¥³I$1\ï±—ˆªù`@'? ‚—Y†îîêÑãÓõa@ó5­ðˆ®|½¢U\žw7µÊXÙk+â9¦¹žAnFÈÉŽHÎv n€W$D§(~c’[nÿþA×_õÉÿ‘¤ýþ³{sg§Éæym=¬s¿••ù˜tú{VLúéµ–®5S “¶Ø’K¦CÇ äò:zŠžoùiö‡ùWâ[¸-5¿i‚î-Äee¸€G"‚Ø$¿7—–ncä‚òÓ£>+µÉ×áG»|l—h%²3‘€}0jÿÛï?çîûøk—Ô¬çÔ"Ö¥´Uš;Ý%!¶tuÄûî‡=>uç§5­gu5Îÿ;O¹´ÛŒyíÝôØíÓßin}tÚË W©†IÛlI%ÆÓ!ã…òy=EK©q*–ŽúWPÅIY‰‚:õ}Å`^Aq«u*éÿm†òÖ;}›Ð"•i ó7í"A÷C3VÓMÔ¬'„ÈÒ½íÓI“â! Y@˘ÎìˆéÀêþßyÿ?sÿßÃM:¥À•b7Ò‰K*ŽHÉ=Gæ+‡°Óµù.c†åï`²óÑœùør¾\ÁÆLÒ¶ ò‡ 1Õ@ µi^éE©Ø^@·w†Þ)! o%ѹÈÊ ¤1Ã1rŽGÛï?çîûøh:Ýý„RܤÍ#G0YX²œ ú×3e¤¾#¸šH®M£îç“ Ú«+)èýÚrXœîÖ¿ÿu×ýräiÝøUÚûJ‡[œî¾¼S½û"† "z/ÇsÉÍiÝë6VÖ÷𕽴×M²Þ9§Ti› a9c’8£Ö²¼ÿ"^—ÿ\ÛÿF5s^7½µ²Ô5«9î좓[Ñ’Æ#5ìùæH$uo/÷Ô~Gãš(ô_1ÿ¾ßAý¥oýŸöÿ¶Åö/+ÎûGš<¿/ß»8ÛŽsÓÀøiu=nå¯êö}>{ûõ7‹¨î†K?2dH£U ¬ö0p ¼H#[hšÎŸðÎ÷C¶±ÔRþ 4‚ÞHõCæKr¨̉ŒƒË„V ¹r7èÀƒæ?÷Ûó¨ÅÚµÃÛ­À3"«¼aþeV$)#¨«`÷Ú}+‰ñ›â‹ûëGI’êÓtfwº ™‚ܶ͊oý“$ü¥U—qRÊtüA|M¯—±Õ$Ón,"2^(W•DÄCÍ 2¼`e $pHOæ?÷Ûó£Ìï·ç^fšO‰›@˜[ZëV—r]$·0]jFã1mp"·atmmŒÌdˆ·'¦"ÚW‡u¹®Gö®¯ª,QØA䘧lŸÌŽå&æ%;ÙÕñ—óvŽ|ØÚ9>t`U•¹ PAê+†RºƒOÕ-cˆ­u'´ƒ’JG±XOá¾y0 qª²²ž€Ý¡Ç%‰Îè!·ÔΉRÛ_ä¦XMØó倗(A'Qº<åÁÂ0äp@:¸õK‰T´wÒº†*JÌHÈ$ר ƒî)ßo¼ÿŸ¹ÿïá®=#Ĉ–ñùÒE—”ùR4ò1‘±$AVC‚¬8?"ò¡Ó4똤{›»«³1¸œˆÚmÉå¢íéŒ ýáÓ;~ZÞ:Ýý„RܤÍ#G0YX²œ úÕûýföæÏO“ÌòÚ{Xç++ó0éôö¬ ÿù]×'þF´&ÿv‘ÿ`ø•UŸÄ)mu¬úÂÅq.<¸d¹Úï“€NNOb]RâžYo¥Ž4RÎï1@êIϸ¯Ý倴y ŒÏ¦Ü[ù“\ÅC)@¬C8m£Ël¶N@ŠçNÖõª2\4Ð\ÛÜy,Œ)ÑÕ„H¤Ë´2Â5û§æ9%˜Îóí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¹(mõ˜&K.íâŠUimÚå]çm’«²’Bì%¢!NÀ6NÈÕÛSƒO™.®¼»çIÚÞÜjÂÁ̲òŠß’ `!ÆÝª07Ð#ÑWQ½V .æÈ9åÉ•uÖ.5›¹nV5h.ÞòÁh FrO<×]Ãïùj_ö—ÿAJÑ×W•|sÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMkKãBŸÂw ÿ‘Cÿ¯¿ôF±á˽FñgŠ{d]€bG õ'ÓÞÈ¡ÿ׌_ú®†oùgþà¨ŸÄÆ¶8ïøCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š›ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹Ž6Oêwc(º²ÛouÏûÆÉU<ãåëV®|%{5Üҭ͘Wva—làŸ¥uQ`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´Q`±ÉÂÿ?V_÷ñ¿øšŠçÁ:„Ö“D·VAFdld÷k²¢‹Ž^O ^½¥ŒBæÏu½¬p¿ÎØ,£œqÒ¢ÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,3´ 2m@²Óç’'–!š"Jœ±ÜŒ‘Áhz(¨-ïm†7Ii(†a‚6¹Ep9ëòºž=~´=Q@#2¢3»U$œ)‚xZáíÖT3"«¼a†åV$)#¨«`÷Ú}*OþA7ŸõÁÿô@öžŸÿ?Öß÷ùÆí=?þ­¿ïòÿe[ê^³†ÂÖ÷OO"ÛÅç6“3DÒH(3ÊrÌwu8<×Gý‘¦Ð:Óþü/øP%Ôl]ÕòÝ™Ž©$þuoc‘ùSfÓ¬mü¹ ³·Š@Ü2DªG¸Ì|A×µí+GKo ÛC6©qI®¡‰m×ûûda¸ú Ié†êJ0*@÷Úãt]{SÖ¦ÐN­l–wêf6ñ]$Ñ–ðêQ›äàG#ž§² Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@s^!Ñ5+ýB;4Á¦!»sA$ *쉔¹Q»"96€C ‘!ÇKEp߃uÍGN—K·›N[5ŸP¸ŽIüÉê+pãŸ|ß)[[VðM…Δ,ôô{R×–·2˜îæÌòåVwb­–‘—wÎ~bÁ 9U+ÔÑ@?|%ªëVö‘i2Zƒk%¼×2: 0JðÊäð§*c`TÌH)#øFúK½@Çö+Yî>ÔW[‰ßí¤Jb~X÷¨‘†!L*¥;J(–ðW†gðí½ßÚ6Dó²âÞÞHŒ*œà„;°NÒHDç€~'ðÅÞ³¨I41ÙMæÚ­¼3ܹi’äÜ@¶d;Ôðc9…>n…zÚ(€Ð|)s.£5Õåª[¾£¨<¯*¹šxYÐ[20 Âw‰¸!IÇÈI2ïè3xoH]1­ôèaR4kD!®WkO'p+†Æ>ûgކŠä¼KáÝCV×ôëë8l¿Ñ6²Ïu"¿–Á³‘Bý0c’&naµHcø>hu]zm14뫬ŒÚ”Qu §göH¬-falŒC«NXD¿9@N|¥¹ù@;Š+ñ‡õÍRßTûÓ¢›WÒVÂãΕÙmÙD§äƒ c1\»v†ÃýÊ¡ÿ¢—7š¢YMu=ãI%¸`ѬÆì‡`³“-®GñìŸ1Ú¸ïè®[Á^ŸÃ¶÷hÙÎË‹{y"0¨P~p#‚îÁ;I!žøŸÃzΡ$ÐÇe7›j¶ðÏräI¦H “q ÙïSÁŒæùºëj Û}KO¶¾´“̶¹‰f‰ðFä`8<Žë\>ƒáK™u®¯,íRÝõAåyUÌÓÀò΂ّ¼MÁ N>BIïx?A›ÃzBéo§C ‘£Z! pÊ»Zy8;€¹\61÷Û<t5½í½Ô×PÃ&é-%Ì0F×(®=~WSǯֹŸøwPÕµý:úÎ/ôM¬³ÝH¯å°läDпL˜ä‰›€XmRþšW^›LM:Àêë#6¥D]BϦÅÛŽ<ÅoßË6äï…å¿ð‚êPi°ýši5A$–jêm<´¶¸Îÿ&Bù…„lJ0#`!ÇÈtæðfªfÒ(ôâöLÒ#Ë(‘-wLÒ,qÄð7É* Æð³PJmM Øž¸{u• Ȫïa¹U‰ Hê*Ø=öŸJ‡SÿMçýpýÖEž—4^=Ôõ6Ñt衚ÎÓRŽBn&`[r2ã·œôTåºG¯©ÿÈ&óþ¸?þ‚h+MÔ¼8ÿfÓŽŸ$÷ˆ°Å3G¤Í,k#ÆŽJ±”:’Kp8®û#Lÿ u§ýø_ð®BÛÂsÏ}e¨[ÚØÇæµ¥ÑÔ<ù~Ñ–‘DŒ‚¿¼H„lÊÑåVÙów”6coåɼRá’%R8=À®c⽯iZ:[xfÚµKˆð²Mu Kn¿ßÛ# ÇÐ`Œ‚OL7ayþ­?ßÌx§YðŸ†#‚óÄab[“µg6m0,Ý,¨pp8¨2ô]{SÖ¦ÐN­l–wêf6ñ]$Ñ–ðêQ›äàG#ž§²®oG×|3« ½ØKÔ’$W?e0‘~b7('®ÜŽ>ðÎAÒPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š* ëÛ}7O¹¾»“˶¶‰¦•ðNÔPI8žé@ÑX­â­14ËÍFUÔaµ³Pó¼úeÌeT÷ Ñ‚À`’@;G'¶¨¢Š(¢ {ÛxõlZL\Í“F˜<¢ sÓƒ"~~Ƨ ŠŽy–ÞÞIÜ9HÔ»ш<*‚XûIíRPEPE™Záà÷¢«’Q‚à’'å9äqœddJ* ‹Û{Y­ašM²]Êa„`ΜŽ:|¨ÇŸO¥{o¡ ‹I‹™¢’hÓ”BŽzpdOÏØÐõ^ý<Ý>æ=ꛢeÜçdIô©ðµÃÛ¬¨fEWxà ʬHRGP VÁï´úT:Ÿü‚o?ëƒÿè&€iªÚÚÙÁn/ì˜E¦ï0 àc=joíÛ_ùý²ÿ¿£üj–žtše„ñY}¾âÕ$Th”³|¹äã©ÚäËr2±~ú×DӬ人²´ŽÀ$[†$’ª¨³@ $$Ðm«ZÜ2F/- ,0Q’}:Öˆ´»ívÒm9ì´û2h„rGu¼—ÁÆ9=.Y¾}n·zu´Q´rùnÔÁ,MŒíde„‚ B b|A×µí+GKo ÛC6©qI®¡‰m×ûûda¸ú I醳k£ê‘ßiÒOŸ¥Š²Gª²…R»@Œ008­êãt]{SÖ¦ÐN­l–wêf6ñ]$Ñ–ðêQ›äàG#ž§² Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@fx‹N›WðÆ­¦[²,×–s[ÆÒ3¡PN8Éô­:(›DÖ§ðn·£-¥¬3^ÀðÂÓkW7ƒ2)F,òǹBŒ£ œýÜæ«ø“Áú—ˆu{é'HARÇɺÍÃò@ò[¹Þw 2ùG÷jI鳸¢€8ø@u¸¹¸´ÕÊk©ïI-Ãf7d8#œ™mr8ÿdùŽÕÄz_ÃÉbKE¾X¿ÏgÉä´b £áb‚,Í(Hd@ #å¯C¢€8øBfŠëN¾ŽÓH¸¼²k¨`7Q–[x^ãÌ“åÉ0ª…XÆÑó0 sØßFói÷1D»¤x™U|æ‡$ƒæ.Y?ÞŽ¢§¢€8¼©/€µÍ­t÷ÊDü‚4ró¢·Œ0¬£ÊÈ)÷ù-ø—ÃWzþ¡§\OáÏ^¬1+\}ªà‰ €äF$ò˜ÉÇÊ\ ¹_´¢€8½+Á×–^5¸Ön.¼ÈÚY¥I‘ãJ±H<æ4 € Ì3£.׈ô›ÝR'Ó®ÒÖòÒv–9]7- îÇBTJ\0ÅœÜ6¨ 8½ø{©^]ZË%âlf’IV9ZÉ丒gxH$%Çš2ù$ùJIäÞŸD½÷ˆïRÝ"µÔtèàYtû—,bO˜nP¡ñ&ÕbüykžËÔÑ@[¢ø8jZá¹66Qi)-»K:TºZͲ+µe0¹,ÿëâÜN”•ç¯øBfŠëN¾ŽÓH¸¼²k¨`7Q–[x^ãÌ“åÉ0ª…XÆÑó0 sÜQ@õž—4^=Ôõ6Ñt衚ÎÓRŽBn&`[r2ã·œôTåºG¯©ÿÈ&óþ¸?þ‚jÕW¿O7O¹z¦è™w9À’}("ËÃSO n#}ä¶šÈ ù¢hЇ¦Æòb'<®|Àc¹<ž/¹·×!†ÓM´‘.4ɾÒÇÌ„…ÞÍû¶àÛ•`‚¬«¹ç´Õmmlà·öL"Sw˜p1žµ7öí¯üþÙßÑþ4[H°ŸNÒŒW60ZÌ×ÛÊ¿–ñ¥ù@ òÊŠìØyÎT€¡âgÂ~Ž Ï…‰nN՜ٴÀ°t²¡ÁÀà t8ÖmZÖá’1yhIa€²Œ“éÖ³üE¥ßk¶“iÏe§Üi“D#’;­ä¿|ü¸Æ0AÈ AèOG×|3« ½ØKÔ’$W?e0‘~b7('®ÜŽ>ðÎAÒV ®ªG}§IÕ­OnB #G"íQ¹¢Ø@P# ½ˆò³¶€;J©ªjvº>™q¨ß;¥­ºï•Ò&ª÷;TÔœp2OVÒký"öÎÞéí&¸‚H£¹;¡fRŒr ÏQÓ­qv~ Ô¬¼â 6µŽóS­ã€N‹m*TÉû«h€|9ÏÈKlA¸€ýÃø“Áú—ˆu{é'HARÇɺÍÃò@ò[¹Þw 2ùG÷jIé²ø@u¸¹¸´ÕÊk©ïI-Ãf7d8#œ™mr8ÿdùŽÕÀP=í¼z„6-&.fŠI£LQ 9éÁ‘??c\—ðòX’Ño–/ÄóÙÅ2y-‚høX …K3J†RHùjßü!3Eu§_Gi¤\^Y5Ô0¨Ë-¼/qæ@Éòä˜UB¬chù˜P9î(¬ÏiÓjþÕ´ËvEšòÎkxÚBB†t* À'>•Çêõ†êÚÊödòÇ2Ú0TŽL=ÇîÙZ9P*G%º©(Ü[ ÂíR ‡EyÆ·à]jëAÓltû‹S5¤¦¸’1%¬Îwf9>ÌÇb¡kPƒîì¹qà½B÷Vפ"ÊÒ RÖâÕ®7-ÌÅd]£“ H9ÚÛL®  @ÚP»¢¸{Ÿ jšß‰!Ôõ¤Ó…®è<ËH&‘¾Hã»R…Н˜Ü! …K) »5ï˪Y5ŒÞVŸ K D%E{/˜É’J¶Å·Ê@ìíÄðµÃÛ¬¨fEWxà ʬHRGP VÁï´úT:Ÿü‚o?ëƒÿè&²,ô¹¢ñî§©¶‹§E ÖpÆš”rq3Û‘— ¼ç¢§-Ò=}OþA7ŸõÁÿô@Ö7¾,ln-á7M(ò}‰š5‘ÕJ£Êb»n\+0c½p>eÎÿöF™ÿ@ëOûð¿á\Ŧ›­Ýßi×–7zT)nm‘µbò€D,²É]ͱ „mÌ{JΛN±·òä‚ÎÞ)pÉ©àW1ñ^×´­-¼3m Ú¥ÄxY&º†%·_ï푆ãè0FA'¦°¼ÿVŸïŠæ›4B9#º.K÷Ï˸8Á €A¦Õi¥j+§<ɧCkb¬‘ÅhB©] Fq[ôQ@Q@Q@“¨kŸa×4­0YÏ'Û¥hÚãc‹K äýæ>S ƒ’FT6F¹â[AšãÏÑ즂;[»Ä1jæ MÛ™L!FY£R ™‚“@mƒá½~}sí>t6Qy[ }šæI|ÅláÆø£Ìg+®ål6½@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€!žîÚ×oÚ."‡vvùŽ?LÔ?Úúoý-?ïòÿbø¡MGJWPÊ|솨ýŽ×þ}¡ÿ¾+ŠçQý¯¦ÿÐBÓþÿ/øÑý¯¦ÿÐBÓþÿ/ø×/ö;_ùö‡þø}Ž×þ}¡ÿ¾ Gö¾›ÿA Oûü¿ãGö¾›ÿA Oûü¿ã\¿ØíçÚûàQö;_ùö‡þø\.uÚúoý-?ïòÿÚúoý-?ïòÿrÿcµÿŸhïGØíçÚûàQp¹Ôké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ5ËýŽ×þ}¡ÿ¾cµÿŸhïEÂçQý¯¦ÿÐBÓþÿ/øÑý¯¦ÿÐBÓþÿ/ø×/ö;_ùö‡þø§¡éö2^J$²¶‰âR3‘íEÂäZÅ­†¯}gt¾*šÈÙ·™ vÒ[mt.|ÈØ“¶FÎ:qžjÚÿb‰µ)›T¤¿À‘þÖ‘Œ¤2¨ù˜`ðÎäc5§ý¦ÿÐ*Ãÿ×ü*´ÓÚöxN•§íŽ8ܳ®rÅÁÿÐGëLfv˜ºfqqu6¼/ï'Tî.f„7–…Š ª®w9Æ~c’@iÿké¿ô´ÿ¿Ëþ5'öv›ÿ@«ü_ð®IÖ «ÛÝÖv¨±\4H±Âª¯ŸzêµôßúZßåÿ?µôßúZßåÿåþÇkÿ>Ðÿß±ÚÿÏ´?÷À¥q\ê?µôßúZßåÿ³ÑO’HÛ£#â+Žû¯üûCÿ| í¤D‰ü¸ÕQUQ€)ŒÅÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEÍGâ¿/\Ôì.í'ò-¯á´[¨ãýÜ~lP˜Ã’rÌÒJWähÚX(;ŒcÇÚGöþžCý²Õ¶,1Í ­3y«$°™5Ä»>÷8 ÛtÛÃ:;jÒj†Óý.YVi[Ì}²º*ª\ím»®AÚrÃ’k§ƒt4•œ[Ns…®æ)VÄJ_lXhЮÀ»v.1@xZ›Y—VÛ=°³¼É±•‘q°nH$3°Êü¤A äÔ¼ñÖeâeЦ—>lp3y± ’HbùeÄéó*2Ü‘µ¶ëiZ6Ÿ¢ÅÓä„—|kóLªÑ-˜JwNU¹#km‚ïÇèþ»Õtý2ôJt¹5%ºTNŠ«¹±¼¨]7gÌ{Æ oXøkKÓf¶–Ê)íþÏÄ‘Çu(•P"—MÛ]‚€70' ¼ü£ÃúTVö¶âÉ[6°Š9 u0@ÈA$0"4ë“ǹÈË+‰n­i¬ç³‘³˜'(]yÇ%—ž¼×𪠯'ö´–1X^Ï2¬Q"´pÈʬ†íç‡BYT¨ ’Fm½;LµÒíÚTp·»Ë+K$€2Îä³2IÀtUy´ 6}LjBæmË#(™ÄNë®ñ±Üap̤‹ƒò®*i(MoOKÛM'TXfµ6ÆXU>Ð0 U%°­’ÞT7U, °¡7‹/Mð¥Ý¦›> ºÆÓ'’±ÆØ6ï( ¯( Ĩ8,ÀaœíÏE™kk¤G¥[£ÅgÚ5ŽVVHÂí8;¾sß9ª‰á­.=×HH§[KL}ŸmÔ¢Xq6K»zðJðßt•éÅP¼ñÖeâeЦ—>lp3y± ’HbùeÄéó*2Ü‘µ¶Ï¤x¡5½=/m4QašÔ\ÛaTû@À%T–¶HyPÝT²‚ÂÜ›k}ݬ/lñ¨A¼Ï$Ø7D¤# (%ITň4Ë[]"=*Ý+8 Ѭr²²FhÁÜóžùÍdÛø K¤hÓÃeu¨^jVkv[$q1jr$*€dA·{˜cpˆí|q¦^Íþì–žl5ï“¶3¤mRîó‘p•<°PA6ךBi–z|qÝE ’˜íÚ+Ù’XÐõA*¸}œ/Ê[*ñòŒNžÒ¢·’Þ+$Ž'†äÇ*¢H„b28D1ð0>^œœ€gx—þBzWý¶ÿÐEU®¬Ã¹Šà¢™¢ ˆÎÝØÎ?/óšŸÏ“ûß ¥aXãh®ËÏ“ûß £Ï“ûß ¢Ác¢»/>Oï~‚>Oï~‚‹Ž6Šì¼ù?½ú <ù?½ú ,8Ú+²óäþ÷è(óäþ÷è(°XãkGH¹†ÒK™î$XâKv,ÍÛ‘]Ÿ'÷¿AGŸ'÷¿AE‚Æü%Z/üþÿä'ÿ †/é"òêàÞ(£…ØÙ$Iãî9éÈ®‹Ï“ûß £Ï“ûß ¦3þ­þòÿ…sör¤ó_MnŽK©N1yÞyò{ôyò{ôÆÑ]—Ÿ'÷¿AGŸ'÷¿AJ±Æ×e?úæü?•|ŸÞý1˜³dœšc1¿æsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚*õý¶§spÛT[X‚…‹eÄ’j‚¿äGÐÿëÆ/ýVíL¾&5±ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±EHÌìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?Æ·L@}Í'“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßTy?ôÒ?ûê€0ÿ³µ¯úäšÙÚ×ý¿òM?Æ·<ŸúiýõG“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßU ÒC±DóÇæLHÉl ŸÈóšÉþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ‘K°QÔúÓ¼Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú£Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿïª<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú¨f’%Š'ž?2bDhK`dþ@œÐOövµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[PUŽ•u¦××z‡Ú¤0ù y!07Øý:óÿŽòÒÿëèÿè&½V¼«ãŸü€4¿úú?ú ­)|h™ü'qà¯ùô?úñ‹ÿA»X^ ÿ‘Cÿ¯¿ô[µ2ø˜ÖÁETŒ(¢Š(¢Š(¢Š’õÍø*ޤŸýs~Ê£  ›Oi—r•ùJÛM¼“|‰t…‚ˆŸ¾¥Ø(Ç]ÈGÊèÌóâ- lRùµ8Yº³¥ÁºO-•X#ÙÁ™TžÅ€êk‹Ô>*hšu¥­ÝÕËÁ½”ë4­*º ‹gy&gD`c°) `à~Oê£Å6z¼w¶­zêynšÌ4 3­´J¢"ûÀ1DÜ«çp9;[aê_UHõøt†·œI5¬—1Ïòùd#"²ýíÛ‡˜‡¦0zðEX†úÒãÈòn “í¡Ù >lcn]qÕ~eäqóQX¶^›NÔôI-/“ìVœÚzÁ,¥‘O—óîcþïz¹žÐo,õû[‰-om­¬,%±Hînc–0¬Ð”H6rcQ|ò*ÈÁ“vq…í+Qÿ‘“Dÿ¶ÿú­ŠÇÔädÑ?í¿þ€(bŠ( Š( Š( Š( Š( Š( Š( Š( Š(  ÿ\¿ò¨êH?×/ãüª:¡­j©¡è—š¤¶óÜEišHàÛ¿bòÄn`8={q“U#ñN––rÜjS¦’aŸìÓG¨Mf9J ¸1BJ2°Úǃêø‡L›[ðî¡¥Ar–ÏyÛ™ž# EqµŽÐË“‚qÏž‡&? ê0_6¯«j5‰ZC4’Y3[²ºÂ¤,BPÊqm%Ï;øämÞ:®œ·Éb×ö¢ñÙ‘-ÌËæ3*‡`9$++Ø0= š®qsogks5«l¸Ž•ÚÉpTä¡ô®vÇÀ–šnŸ5¥µÇúË« „Ï2yv‚‘³ nÏ’Ç<d8²x_Á‘ønàH×v ƒì¶fI'-9\©+&NÈùDAòðÀMcê?ò2hŸößÿ@±XúüŒš'ý·ÿÐlQEQEQEQEW•|sÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMiKãDÏá;È¡ÿ׌_ú­Úñ#ñN÷Â.þM6Þét§k!9vC Œ”Ý·œgÆMð½oÿè mÿ›ü*)7t%4‘í´W‰Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…/c>ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû> endobj 431 0 obj << /Font << /F17 200 0 R /F20 263 0 R >> /XObject << /Im10 419 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 437 0 obj << /Length 154 /Filter /FlateDecode >> stream xÚM»Â0 E÷|…Çd¨kÇy4+¢…"Ñ‚š­b±Uˆÿ_EHÕ]¬ã£{wYÕ%`Æä½…ü„& ƒH ’ó0ë€Mës;{S±¦ôxÉý8Læ–OuÇqÛ#©ÁЯDä+©6+.¨,“90¡'†û¢ÞŠ0ødݪlïõédÅà£üaÝ/̰©kÉÒí+E endstream endobj 436 0 obj << /Type /Page /Contents 437 0 R /Resources 435 0 R /MediaBox [0 0 612 792] /Parent 429 0 R >> endobj 424 0 obj << /Type /XObject /Subtype /Image /Width 430 /Height 573 /BitsPerComponent 8 /Length 20811 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W®xpu°ë<ŸüU'ü!~ÿŸÿ¿òñU>ÚaòO¹åÒø\œÜoû Ç&Ÿ&œ$m²(ŸŠå³»É'éIg¯j¶Z,ð¥™:+ÿäÿâ¨ui5k1¨É+ÿäÿ⩺ԚI­…É.çœê>*¹Ùek¢Û[ÂÐéXK{4¿B2FÛ°;‘žµ’×ןðÛh¾M”–öĘf’"f‡q‚°8çäõÏøBü5ÿ>+ÿäÿ⨠ðÙ8Ÿúï'ÿIU¤º1¸Éža/ˆõkGU¼ž:uÔŒ^}¤Ð³@|°œnÈ#õëU¯5cP¶Õ¡º’Ùÿµ<…›•$-”XÀ8ëšõ“௶}g“ÿФÿ„/Ã_óâ¿÷þOþ*kG°rϹåskW×€¼¸²Ó.-#´&…Ê…BHl†7'GÒªßÝê¾¥&¡¨ËLȱªD¸DEè<þy5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUR¯I;¤' >§ù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU[‡b}“·Áì™äþW°§D¢9‘Ø| ó¦+Öaðçƒn%X [Ydnˆ—ŒÄ÷è­xpu°ë<ŸüU/­Ã°{&xÕÖ—£^Îg¹·ó$ Ä=K6vOogE`p¡[©úׯÿÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU?X§{Ø|’<‰Ùí<‹€ØÎHúäE ¶ÓÃ+n™ŠÀ3ÈÃ#§ׯÂá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñTþ³O°{9Dí½I@bŠ0N9ïþ5"‹¸yÔbW3ìl: õŸøBü5ÿ>+ÿäÿâ©ßð„xwþßùOþ*¬Ã³fÏ!Ùg ´±[¦ÝûŽÐ¤ ž¦¹Ï®ÛHßþ•ôü!ÿ wþF“ÿН8øÁáý/GÑtél-|—{‚¬|Æl§Ôšj¼%î¤'µ=+Á_ò#èõãþ‚*‡‰/îb¼H#•£]»²‡òG_N*ÿ‚¿äGÐÿëÆ/ýV?Š?ä*¿õÌèM\3Ýšô1§×M¬°Åqª˜d¶Ä’\m28PO'‘ÓÔTÿo¼ÿŸ¹ÿïá®7Äɧjw`Ëaæ^ÙÅ %ܱ„P¯&LŠÎ¤¡Œ®ãÃpp¯%ž¿u&£=½ÜŒ²Á;[K þîUe>J©ó°¤eáò§æ9%¤ëí÷Ÿó÷?ýü4}¾óþ~çÿ¿†¸ýONÖcób°¸¹–ÜùR9yI’Fýà“n óäœEªe±Ò5)&n¿½­¬^YŽM›eß!änl•R‹óVþ-øáÕý¾óþ~çÿ¿†¢·Ö%¼gµÔžx[;dŠrÊpppAÇQ\ȇY,I„R%“; H´f?,íÀ2ðwÎ"R~b2Zþ€—éò­Õ¬–Ò©ä #!%^Vp~V#£cê±  "Ô,n¬¡WYVæî8XË–*ààçùæ¦Ôµ+ÆÔ'âDTr€#0ó¬I¿ä#¤ØBçZÿòºÿ®¯üÍD5‰[f5';Ý£\N~g\åG<‘µ²;`úT¿o¼ÿŸ¹ÿïá¯;ugŽ;MbÚ=Lj7…!’õ Äî'Tm™<’Ñ ¸8ç€KæìvÚi«5ùy%@”w1cr[iùFE ¨ã²Æv£T¸2´BúS"¨fA1È8$g¡Áü;í÷Ÿó÷?ýü5ƾ—«H·7Cφé4Ø’Ý#¸áçC)]ä±$Ë•fe%ˆ%ñºº;ëu»ÓîmÚ%•e‰£1»”#†HÔr)–¥Í¬—Pk -¼Yó&Žçr&NH8Õ¯·ÞÏÜÿ÷ð×5®­6«bÓu, –Í$Ås¼nÆ^"«å‚Aœýü‚]f»»«GOÕ„eÌÖ·Â"¸9òö‰UryÜÜñÀ<åX_Ûï?çîûøh:Ýý„RܤÍ#G0YX²œ ú×)ce¬¯ˆæšæy¸y#&9#9Ø€y¸R\‘œ¡ùŽIm»ÿù]×'þF÷úÍíÍžŸ'™å´ö±ÎþVWæaÓéíY3ë¦ÖXb¸ÕL2NÛbI.6™('“Èéê*y¿ä¤Ø>å\o‰nà´Ô ý¦g¸·•–⊠`L’üÞ^Y¹’ ËLŒø®ÔO$_„Míñý°n] –ÈÎF9ôÁ«ÿo¼ÿŸ¹ÿïá®_R³ŸP‹Z–ÑVhït”†ÙÑ×7ïºôùמœÖµÔ×;üí>æÓn1ç´gwÓc·O|u¤¹õÓk,1\j¦'m±$—L‡ŽÉätõ,z¥ÄªZ;é]C%f$dëÔA÷yÄz­Ô«§ý¶ËXíöo@ŠU¤'ÌÜs´‰Ý x ^Akà]^)e‚9/-d´€Mq!¤‘ ºFUã’yÎà•“p÷ž'þÔÕôNy#K‹ìZj˜Öý|æÛ'–åK.èRLln €UŒï|Çþû~u7kp…ภfBÈû€e%XqÜAˆ"¹M2Û[Æ·—Áztù7¨’îp.FÓ¤ì‡Lgi%œ°!êZÙë­áh-ç²ÕÔC¨ÎÓÛA~×=«4­¤Âl‚¥áÎdSˆØd‚vÐݭ‚àJ™ #aÇpAv Š“Ìï·ç^W‡|mvp©à̳±–ù½ÔÎfp³@²)W‰€(ãåaå¦J·c¡h×°M-ö¡¨›“ytV¹ßÙÚi i³•ÆÒŒß.à£eik±­Æ‹teË£iclQÔ¬§¨ ×%>³}u¥iR¼ÅdžÎ)ähþRY—ž½«°Õÿä }ÿ^òè&¸ÿ.‡ÿ`Ëý“!ŸÄ)mu¬úÂÅq.<¸d¹Úï“€NNOb]RâžYo¥Ž4RÎï1@êIϸ¯Ý倴y ŒÏ¦Ü[ù“\ÅC)@¬C8m£Ël¶N@ŠçNÖõª2\4Ð\ÛÜy,Œ)ÑÕ„H¤Ë´2Â5û§æ9%€;Ï·ÞÏÜÿ÷ðÑöûÏùûŸþþä¡·Ö`™.<»·Š)U¥·k•w¶J®ÊI °–ˆ…;ØHE8#WmN >dººòï'k{q¨K 2ÈSÊ*?~H1€‡v¨Àß@E]FõX0»› ç—$~UÔxSX¸Ölnå¹XÕ »xË  )É<ó\ut?¿ä©ØF_ý(CG]^UñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5­/  Üx+þD}þ¼bÿÐELJ.õÅž)í‘v‰ƒÔŸOz<ÿ">‡ÿ^1è"º¿åŸû‚¢Øã¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ*l9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,8Ù<¨=ÝŒ¢êËm½Ôs?ï%Tó—­Z¹ð•ì×sJ·6a]Ù†]³‚~•ÔQE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâhÿ„6ÿþ~¬¿ïãñ5ÖÑE‚Ç%ÿmÿüýY߯ÿâj+ŸêZMÝYte‘±’?ݮʊ,9y<%zö–1 ›=Öö±Âÿ;`²ŽqÇJ‹þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰£þÛÿùú²ÿ¿ÿÄ×[E —ü!·ÿóõeÿÿ‰¨®|¨Mi4KudÑ”fFÆHÿv»*(°Xåäð•ëÚXÄ.l÷[ÚÇ üí‚Ê9Ç*/øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&­øWÃw~mM®§¶“ís+ …ÉÀºäQ]Ç`¢Š(¢Š(¢Š( Ûvº°¸·B¡å‰‘K Žk›¾~›oö›=öÖq@çÌlQ‚GËÒºº(’ÿ„6ÿþ~¬¿ïãñ4Âÿ?V_÷ñ¿øšëh¥aXä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMjø[@¹Ñ,®á¹žÙÚk·LnH BœÏ±E1yaK•¶óÎÈd§'h gÛ“þpkË>9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:+3[¿¹°··6«–k…„y íÓè*]8jޝ%ûY„j¬²O©$ÿŸÃœzqª©7ï=Rò*Î×/Q\Ö¹â½7þO&8û/FKøw©;¤?hÈlW÷+Ó“ÏLIÿ ž–ºž©g6øF™—»Ç‰ÇÊfÇ9Æ He'Q ƒá¿é¾(ûJÙ²Ûl2ÇçC6³´î…Ý9ÚÜnÈÇ  ·£4¾'¿ÓSÉ·³¶¸Fî-#ά8Æ"\qÜþtW=7Œ´ëWšK¨n °§oÙTÅ$‡iP*±“*"—’€‡åw>­–“w¥^Øý—ah®¤·r³mHeòºç‚àŒ>eܽEsQxŸûE¼9y¥ÉéúÔÖÓMÎ"•¾WVÛÃÂÊHÜ9SŒ¥â-Fm#ö§n¨ÓYÙÍqÈ RÈ…€8 ã#Ö€4è®.ëân¡zº•”öpE°‚;ƒ2I,†}ãsÈ# ²†*ÛKBÖâñö‘9ÒDä›l‰ŒÐ¢« <²<€JC‹ÌèFBÀMËi¾1YŒ‰}gu//-cž+vhähd—ª‚]ßʈ¶UJ’ ƒ»å£þ8.¼ªkö0;%’É•ImîHÚ¡‹~îm¤rWz±ã¨ÈSEbë^ “F¸·ˆhºè¸eŽ7µh>iŸ+ȬH± `($œŠ–~:ѯ|LÚ2æçÍ’o6#¾HÃo_,9‘q±þfES·‚w.à–Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­Š—6ݵ¹™w%*ç‚ÀgóÏáV™ò›B*Œç媖¥™r˲y’ÕbPX±dzSl5~_7"uyã ôäÿŸjÅû>u{s~%jE¨èn«p³ÝÂìû|· 3Ƴ&IÙ*©Tå¾W|ÍÇÌrÃá­.K¹nn"žé¥ßº;»©gˆo6ØÝŠ.U™~P>V+БF£âM7û[ÎŽvþ˰[ù¶(;£>näòß¹n¸ŽzâÜz®.§.™ý«ß»äµY”Ê‹Ç%3>eäŽãÖ´iÚl]»Ao%Ó£6ònn¥¸làFb3޾¦ª_øoNÔµ}1½Žå¢XYíoç·ÜŠX¨"7Pp]ºúš·§jºv¯n×eý­ì*ÛKi–E €pJ’3‚8÷™­x¦ PKk>öH¬—’]Eå˜âŠ2¢F`\9Û½I ¤x‚ƒá®å¸’ÓÍówî‚YàÁÂLj̲ÁA;ß$îlÆ<)¤ wˆÇtî̯ö‰/fk…*f/æ(œ`0wþófüz®.§.™ý«ß»äµY”Ê‹Ç%3>eäŽãÖªYøŠÆ} µ{¶þͶŽY!—íÒ"yN’´D3+÷Ô‚s‘@ÇáM"$Ó‘#ºOîmÿÓfÈ•Égf;ó!%›;óÃ0èH:wÖVú–Ÿscw™msC*dÈÀ‚29Ò£®œÖïp·ö¦nžA2íXX²œ![ Ðí>”Cªé׆ΠûYn‚³˜eg ®QŽÐs€à©=ˆ#­W¾Ð4ÝFâK‹ˆ_í±§ÏŠ¾Ý¬„?½eH$9 â™uá½:÷É&öXâ‰aòšþ.D¤MûeÎpw†Ü89©ìµÍ'R‰%±Õ,®£’S 4ᤠ¼  òÛAluÀÍ[†xn¼¤¨²0`IVwGb   i¯oKªG<×1˜ætd–Q ‘ƒ'Γ¿¸Æ o i¦^iòGu,7ª#¸iofydAÑ ¬åörß(l|ÍÇÌsµEbÝøWL½¸¶¸™µ5´fŠHµ;˜ØGH%d‰*¹'$í'­ÚèövZ„×¶âxä›vøÅÄžNXîfnجO%‚‚I$žNoÑ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[º¿k1¿bCr³9ÆI ñ#üñZ?»H|¸÷}ìüÕ^{˜-=ÄÑÄ„à4ŒgÓšdÖ—.RÞê \ •Ž@ǼV…9TUZ÷–‰ùwkÚ熦ծ/Zä·‡R³[ äx ŒÐƒ&<¦ ¡IËwŽiËàÙîîõAqªyZ~¡ñ=­šIË( ’WwÌX²F„¿$ಷEwªéÖÖ÷—ö¶Ó]6Ëxæ™Q¦l„åŽHàzZžá¸BðJ’ fBÈÁ€e%XqÜAˆ"µ‹á¿¶‡ö™®n¾×{q±}÷÷i’«‰¦”ŒsÁæéÞ ñ†.õíA]u(-ìžÂ{ á6¥ähæ)æ}à+b5 •`I œ–£Â×n²¡™]ã 7*±!I@%[¾Óé@ÖàÈìXÁÀéh |¨éo>¢o.µÂÐyMg#,öûÊY>×,ªä‰ÙJ±U Y‡ÍŒô¾Ó&Ò|?¬èèæ{‰ÂI)‘Ñd™äUv$îp9nAäõ:vWÖš•¢]ØÝAum&vMѰppÃÈ#ð©è¢ŠŽá¸BðJ’ fBÈÁ€e%XqÜAˆ"€$¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkc\²’ùl!H„ƒíˆÒ÷BÙ'=¿ýU¥ocmcnËVñ³°-å(qœ~?>Šæ–¬«6î•·Ó_"¯¥ŽkRµ¼‡_¾¸GþÔ¶Ôl!³1™#XУL[ÎÞså‘0ûªç¾^²SÃþ#²´’].êxu ‹ýGýtàÁ2—…¼¾TþôÂå¶³üÄ·*;º+qya¤xš--ÍÓj’[¤3iépb¹xÂ8&9šîR2í #ÍAˆ›˜‡°š?ˆÖúæê1Ó<;â]ÈYeùcÁQÎþ‹Bѯ`š[íBÿQ7&òè¬/s¾/³´ÒÓg+¥¾8]ÁFÊèh ;]tø&òÚ=&êÚò]Fæ_(Ü(”E%Ã̬†)ЇU Êïðm ñ„÷SYNúÛ¡Ó£òoV5¶™®.„J»ÛzÑ72Bp7,§•õj(„ðÒkw:Ë]´—¯ê—ë$òÞ…­–Y‘aXº¬‚@ŒÓò.<Ìb0û 3]»Ò4«;«Ø$ZµË\™/•¦k6YÌjd9#ç‰:ïd´=wP”ø¡µ{-*{Yõ'[áÌzm»ê³ZLq,¢ˆÆÚähü±ŽàUs̤׫QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lax¦ò,c†i¡3^G4,U°A㊻§iFÆ7–K«ÙŽÐ.%,{ëíõ«eT²±²©Ç àŒÀ‘øÓ‹3 'êkšT¤ë*ŠnÉmÑù•},yßu¬õø– Z{}Kûî[KX¯Ý<Û•h¾Î<ÁdbÆ@©ß‚m¸Ö>'»¹ñ2Ø4–M¾ê{y4äCö«Hã¶âC¸æ7ؘù~ý>cÆî¶ŠÜG%ñê+? G+ß}’O·Ú¤lu³ºe­"…òÌ„ðpl|¼fÛêËð\—Z«Ç-Æ£s,—lx|¹Â–ýúd@VŸ(Ü®þŠáçñ–£õÚà ­ìÑ5Òc@¬/"X–B’¹ II h÷cý|x-Æè$ñ5ì·šA¶¾µ×Pj!Y´Oݬ ÚÜ“o”ÆJ”W?¼Ï+•)~þŠá./µsYЭa𶏵¸º–KKÉmÚ#–$ÆÓ.Ñ+²@ÛvôM¡kjÃWY|{¬é-yk#Ãgk4pÇ#yˆ “xe.FGÈÛ‚©Äˆp¦º(ίk'Áÿ\Á­»‹FÔ ´ÔY¤VY¤07vâHò° ùƒ(ä7=³¯[Ûkòõ/²jWNª ÄÊ2áYwm\`LˆF\ô´P‰µá¶ãìVW1Ï}aii4rHð}¡‘šF;Ww‘°®'~á÷¿ ë×ú¦¯©XÞH’¥´ó$ƒKžÅ³#J)3@òÆqÉ«¥žn­ä·¸‰%†U)$r(eu#x ŽÕSMÑìô¯4Û ÚIq¾[‹‰'‘€Î|ŒÍ´eˆ\àb' 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØÈÖïîl-íͪÄešáah;FAôú —N£«É~ÖaÚ«l“êI?çðæ{›HnÚÜÌ»„‰•sÁ`3ùçð«LùM¡FsòŒW4£[Û)&¹-ªë~š•¥ŽzöÿV›_ŸNÒÍ’}’Ö©ÔnßhóUXyXòO͵þøù~\5 ?[Ç Ìº´ÛA ÕìkŸ$ù)ÚK³yQ,fAîùkkQÐ4ÝVág»…ÙöùngfL“²UR©Ë|®ù›˜äéRÛÇo-’I sÍr#–S$¢A! œÂi897N7‹añ JÕ"u²‚{‹Ñ*D–pMo+ÈY]Æ%1–)NÁù:|˺Eñ”)®Oa`yüÌïÜwg Ÿ\Ô¿±´ GTò¼ï±ZËqånÛ¿b–Æpqœc85‹}¬kš ºlwëk¨‹ËÏ!M…³¤˜&}غ4ùËíÃ6àw–x!º·’Þâ$–T¤‘È¡•ÔŒAà‚;Vm¯†´»I¡"žIá—ÍI®.¥ž@ÁÞìX¨Y$“€]ˆ9  ÍGÇÚF•cgyx(nT“Ìšh&Ù(*Ò«db ùÇÊæÝ§ŠúYÖ×IÕ$HežÜJ!P’M:˜Ô–v9Âr°o”ž Ðï¡–m§Xæó|áÜÐùÂGgu}Ž7®é…l½°MkÙÙ[ØBÐÛGåÆÒÉ1'ç‘ÙÜóêÌÇñâ€3<'¬]kþÓõ;Ë´šâäeb»_r+oM¬Ä!$à1 Ç"²|]âMS@ÕíÔÚµ¬–sÜ´RZHìÍGò™UÂÂŒ$ǘëµ6å²C¦èÚ~‘æý†ßÊó0]›jŒíEÜNØ×'j.rpMA©xkKÕõ¯o¢žYcˆÂ]J±´d‚ÈÑ«el Á  ¡{ãk®®&³½û?hTºUB“É»I ûÃ*^YUNÆås>©â»M+VM1­/n.äò„iomí"ÎTrF?ãÝÁ'eI n+`øgGk¹n$´ó|Ýû –GxpC°„“³l°PN÷É;›1ÙøOE±¾Kèm\Þ++›‰n$’GeYK31.BÍ"å³Á¢®2uCk êz}•Ô×6–rÏ*˜ƒ-¬ŠdEY@l‘æÃ"à6$.ϪøûHѵ[Ý>ì8šÖ 'ÄsBí&ÈŒÅDbO1NÀÇ.ª¼uåsnóÁšü2Ãsa¾)¼ß5<éËæ;Hw€ß6GeÎv%vš/<¡ßÍ,—6ÓºÉæî„]̰æDd‘„AÂe‘òÀ–'99  !ñ$2]Z[˧ê6Ïw?“¸„(pc’@ýxDß)éÆå\Š·£êöšîœ/ì_̶ieCùr4e”‚ART{‚*=wKmcLkE{\ ÑÞZ­Ìü/ ‘œ0Ã) ªrFA“GÓ²´áleó¤iežW ´4’ÈÒ>Ñ“…Üç’@À$õ 袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐE^¿¶ÔînÛj‹kP¢1l¯ø’MQðWüˆúýxÅÿ ŠÝ©—ÄÆ¶1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(©ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖ逃‚蹤òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûê'þšGÿ}PövµÿAïü“Oñ£û;Zÿ ÷þI§øÖç“ÿM#ÿ¾¨òé¤÷Õaÿgk_ôÿÉ4ÿ?³µ¯úäšny?ôÒ?ûꡚH`–(žxüɉ 9-“ùþs@?ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÒ)v :ŸZw“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßTy?ôÒ?ûê€0ÿ³µ¯úäšÙÚ×ý¿òM?Æ·<ŸúiýõG“ÿM#ÿ¾¨û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓüksÉÿ¦‘ÿßU ÒC±DóÇæLHÉl ŸÈóšÉþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€1ÿ³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÊ±Ò® ÔÚúïPûT†$$&à{¯ç^ñÏþ@_ý}ýתו|sÿ—ÿ_GÿA5¥/?„î<ÿ">‡ÿ^1è"·k Á_ò#èõãþ‚+v¦_Ø(¢Š‘…Q@Q@Q@Oþ¹¿åQÔ“ÿ®oÃùTt“iâM2îR¢)[i·’o‘.°@ñ÷Ô»ë¹ù]ž|E¡­Š_6³§ 7Vt¸7I岫b8 3*“ذMqz‡Ã%MN´µ»º¹x ·²f•¥WAqlï"$Ìè€, v ä oÉáTx¦ÏWŽöÕ¯BÝO-ÓY†fu¶‰TD_x(›•|î'kl Kê©¿Öó‰&µ’æ9þ_,„dV_½»póôÆ^«ßZ\yMÔ}¢#4;$ÍŒmË®:¯Ì¼Ž>aê+ËÃSiÚž‰%¥ò}ƒJÓ›OX%€´²)òþc `ýÌÁýïQ·3Ãz åž¿kq%­íµµ…„¶)ÍÌrÆš‰ÎLj"ožEY2nÎ0 ¥cê?ò2hŸößÿ@±XúüŒš'ý·ÿÐlQEQEQEQEQEQEQEQEQE$ë—ñþUIúåü•G@5­U4=óT–Þ{ˆ­"3Iwì^XÌ'¯n2p*¤~)ÒÒÎ[JtÒL3ýšhõ £ŒÇ)@áw(IFVXð}Aé“k~Ô4¨.RÙï {s3Äd®6±ÚrpN9ààóÐäÇá}F æÕàÕmF±+Hf’K&kvWXT…ˆJN-¢ä¹ç ÇUÓ–ù,ZþÔ^;2%¹™|ÆePìç$…eb;¡¢ÓUÓ¯î.mìïínfµm—Ã2»BÙ#ÊœƒÁô>•ÎØøÓMÓæ´¶¸ÿYua0™âO.Ð@6aÙòXç€ ‡ÖO ø2? Ü ñîÄ}–ÌÉ$墇+•!ådÉÙ(ˆ>^©¬}GþFMþÛÿè¶+Qÿ‘“Dÿ¶ÿú  Š(¢€ (¢€ (¢€ (¢€ ò¯ŽòÒÿëèÿè&½V¼«ãŸü€4¿úú?ú ­)|h™ü'qà¯ùô?úñ‹ÿA»^$~)ÞøEßÃi¦ÛÝ.”íd'.Èd’›¶óŒã8É£þ­ÿý-¿ïó…S¥&’=¶Šñ/ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð¥ìgØ9â{mâ_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáG±Ÿ`ç‰í´W‰Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Æ}ƒž'¶Ñ^%ÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{öxž·xúì—r5ªéË? ”¹l{ãóÞ¡ÿŠ—þ¡?ù¼«þ­ÿý-¿ïó…ð½oÿè mÿ›ü(ö3xž«ÿ/ýBò%ñRÿÔ'ÿ"W•Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÕâ¥ÿ¨OþD£þ*_ú„ÿäJò¯ø^·ÿô¶ÿ¿ÍþÂõ¿ÿ %·ýþoð£ØÌ9âz¯üT¿õ ÿÈ•v:¼ú½•ÝóXˆí·à@_'rã¿á^]ÿ Öÿþ€–ß÷ù¿Âø^·ÿô¶ÿ¿Íþ{‡ÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû> endobj 435 0 obj << /Font << /F20 263 0 R /F17 200 0 R >> /XObject << /Im11 424 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 441 0 obj << /Length 246 /Filter /FlateDecode >> stream xÚMPËNÃ0¼û+öhâx×ÏÓ4A¨”Ôå‚8T ¤H”‚ ¾'QDäËhv<;³›Èò= ÊÂZ‚ø¨” àUÊXˆ¯ðĵÏñ6oH­…ÞË`Ô¬©Úrë^dšwRdÞ?ºÝv¦b[Àóm_îÛ®*ïfþxX>u;‘!yÝ7UॠÀ«z\ÎêÈÆ])Aʤ¶hTÒ*„—3ûbJ:[™$k< žh°^/dÞ‘àæÂÒ[œ³Å:[yoÆzIhÍÿÈ' s'uŠdùãpý9½¿§ïáò‘ªyËï?G|]ŠüË™Rƒ endstream endobj 440 0 obj << /Type /Page /Contents 441 0 R /Resources 439 0 R /MediaBox [0 0 612 792] /Parent 429 0 R >> endobj 430 0 obj << /Type /XObject /Subtype /Image /Width 430 /Height 573 /BitsPerComponent 8 /Length 29324 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream ÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ=®"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?æç¿šòO¶^EÝÍÂ,²Í<(îÌÊR8 €Ÿq Ú¤&Ÿ§7ÆËozp8#Ò¡†0Ö¶Çþ˜Gÿ  ¯vÒE¶8ÜàÛOE>¾ßçÖ½Y¾H¦–‡,uv'3(\ÿgØc Ǭ}*<äÿŸ üü)!Q"îÜ vÿõÿ‡¥Kå ¸Ù«’ôv#ó“þ|,?ð?ð£ÎOùð°ÿÀXÿ¤ò…Pª²œŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå ì´ éú·‚o$òÀÖ$ºh,¤.FçXÄ1¼…a’;ÔÎQ‚»CŠmÙOœŸóáaÿ€±ÿ…rÏ…‡þÇþè¿‚¬¥—ÃzvŽ\]5Äw—E™hpã=˜0{Uð ¿ÚzUªÝ´qê>hVº·0Ȇ>H(IÎG#ž}«5Z“)ÂGç'üøXà,áGœŸóáaÿ€±ÿ…vº†4Ø5VÖõç+=ÒÉyi$R}¼î“Æ:n‘á[ñ'‡âKȵ Z eŠGЊr âmL9$qžrÏ…‡þÇþyÉÿ>ø øWM£øVÆÿMÐî.µµ´ŸYi’ÞjÏ–GÛÀã98ê:ÒXøR -¼íCSK?3R:d °™L³ƒÓ^>Ôý­ ä‘ÍyÉÿ>ø øQç'üøXà,á[úÍâó¡yùÙ{öV”.:6 ·SNÐuCÄ5–“5”ºTsošä¹™â8`èxŸJr©ô‹gç'üøXà,áGœŸóáaÿ€±ÿ…u°x6ÒàY[Ǭ¯ö•î–ºŒlÀ2NÒùÀèyöè*®«a¡ÛxAÔ¡šQ}z%8±•`'v.O |ÞÔ½­>ƒä‘ÎyÉÿ>ø øQç'üøXà,á]†·á{+]w_–âê-?IÒͺ³ÅÈKHŠ@T,OSÏ?ýhåðmµšjÓêÄvö–ÛÌ'[vq,sàrF1ƒÏ æ…V“WIŸœŸóáaÿ€±ÿ…rÏ…‡þÇþ×Gàq7ˆeÓ"ÔVH–Åoã•!%åºm9-íšçõKôýR[4iÛË“=»@ã#¡Fä~ ÕFtäì„ã%«(ùÉÿ>ø øQç'üøXà,áRyB(UÙGç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øQç'üøXà,áRyB(Qd~rÏ…‡þÇþyÉÿ>ø øTžP£ÊYœŸóáaÿ€±ÿ…rÏ…‡þÇþ'”(ò…@Gç'üøXà,áGœŸóáaÿ€±ÿ…Iå <¡EùÉÿ>ø øR‰C:ªéúy,p?Ñcÿ ”)öñ¥Eõ?ÈÑdå?üøiŸø ŸüM5Õ£Fsa¦£'ÉŸýµ|¯jŠâ/ôYxþüªtiWréúpÀͲsÿŽÓü§ÿŸ 3ÿ“ÿ‰¥–6þÈÂ;ÆZ@»ÐàŒÉŽ?:ŠM.K6ŠeÔ/¤ýê)I$H,Ïõ-¤öB3˜Dtý?yé‹dÇòö5/”ÿóá¦à2ñ5<‘ÄÎ.?‡ú5RÕ®gÓ.VHI¸2©Í±É+÷ÆOZri+Øl‘Õ£Fsa¦£'ÉŸý¡ÿ„‹SðôŸmÑäŠÆwS˜`L2õåH#9qž¾µvÞ&:K;\} ÈŒæAÐätÕƒ¯.ÛHÿßþ†“IÇ`WLܵBtûRÏ‘_÷E<[ÌÅF[ƒßŠõ xGC½ðŽsqc¾i,âgo5ÆNÑØ5kŸxpu°ë<ŸüU`ñ0OU±¢§+9å¶©[…•O2À+èF?¯õ¦ù^½“þ¿ ÏŠÿßù?øª?á ð×üø¯ýÿ“ÿŠ¥M8è“NOsÆü¯aG•ì+Ù?á ð×üø¯ýÿ“ÿŠ£þ¿ ÏŠÿßù?øª¯­Ã°½“·ÂöLñ¿+ØQå{ öOøBü5ÿ>+ÿäÿâ¨ÿ„/Ã_óâ¿÷þOþ*­Ã°{&xß•ì(ò½…{'ü!~ÿŸÿ¿òñTÂá¯ùñ_ûÿ'ÿGÖáØ=“×ë¢h¬a‡•™û±÷¾lñŽ0F;W®xpu°ë<ŸüU'ü!~ÿŸÿ¿òñU>ÚaòO¹åÒø\œÜoû Ç&Ÿ&œ$m²(ŸŠå³»É'éIg¯j¶Z,ð¥™:+ÿäÿâ¨ui5k1¨É+ÿäÿ⩺ԚI­…É.çœê>*¹Ùek¢Û[ÂÐéXK{4¿B2FÛ°;‘žµ’×ןðÛh¾M”–öĘf’"f‡q‚°8çäõÏøBü5ÿ>+ÿäÿ⨠ðÙ8Ÿúï'ÿIU¤º1¸Éža/ˆõkGU¼ž:uÔŒ^}¤Ð³@|°œnÈ#õëU¯5cP¶Õ¡º’Ùÿµ<…›•$-”XÀ8ëšõ“௶}g“ÿФÿ„/Ã_óâ¿÷þOþ*kG°rϹåskW×€¼¸²Ó.-#´&…Ê…BHl†7'GÒªßÝê¾¥&¡¨ËLȱªD¸DEè<þy5ëßð…økþ|WþÿÉÿÅQÿ_†¿çÅïüŸüUR¯I;¤' >§ù^Â+ØW²Âá¯ùñ_ûÿ'ÿGü!~ÿŸÿ¿òñU[‡b}“+ÿäÿâ¨úÜ;²gù^ˆæGaòƒÎ>˜¯b ðÙ8Ÿúï'ÿQ\øWÂV{~Õ0oÎß6é×8댷½/­Ã°ý“<‚ëKѯg3ÜÛù’b¥Š ;'·³Œ¢°8P­ÔýkÔÿ°¼ýû/ü?ü]Ø^þý—þþ.§ëï{’G—"Û=§‘pÉ\‚¤ÚxemÓ1Rydtàšõ/ì/~ËÿÿGö‚?¿eÿÇÿ‹§õš}ƒÙÈòçhÍêJQ‚qÏñ©X¥ÃΣ¸ŸcdÐW¦ÿax#ûö_øøº½ÿG‡èÿ‘¤ÿâ¨úÌ;0ölò–pÛKºm߸í @Éêkœñ*í´‡ýÿé_@ÿÂáßúäi?øªóŒÒô}N–Â×Éw¸*ÇÌfÈÚ}I¦«Â^êBpkSÒ¼ÿ">‡ÿ^1è"¨x’þæ+Ä‚9Z5Û»(pO$uôâ¯ø+þD}þ¼bÿÐEcø£þB«ÿ\Çþ„ÕÃ=Ù¯C}tÚË W©†IÛlI%ÆÓ!ã…òy=EOöûÏùûŸþþã|A|šv§v ¶eíœP¢]ËE òdȬêJøÊî<7òYë÷Rj3ÛÝÈË,µ´°¿îåVS䪟; FPî¯*~c’Z@î¾ßyÿ?sÿßÃGÛï?çîûøkÔôíf?6+ ‹™mÏ•#—”™$oÞ 6áЯ>IÀdPÀê¦[#R’aöëûÑÚÅå˜äÙ¶]òFæÉU(¿1eoâߎ_Ûï?çîûøj+}b[È{]Iç…³¶H§,§üu‘âĘE"Y3°”‰ FcòÎÜ/pLâ% çæ#%¯è qŸ*ÝZÉm!ºž@’2Uågåb:6> ûÐÁâ-BÆêÊu•nnã…Œ¹b¡ŽžjmKR¼mBp.$EG(1ÿ:Ä›þB:Gý„!þu¡ÿ!¯úêÿÌÐCX•¶cRs½Ú5ÄçæuÎTsÉ[#¶¥KöûÏùûŸþþó·XÖxã´Ö-£ÔÆ£xR/P¬NâuFÙ“É-ÛƒŽx¾nÇa­¦‘:³_—’T a¹@s7%¶Ÿ”adR Ž0[,gj5Kƒ+D/¥2*†d€s‚FzÈÓ¾ßyÿ?sÿßÃ\kéz´‹st<øn“M‰-Ò;Žt2•ÞKHܹVfRX‚_«£¾·[½>æÝ¢YVXš3¹@à‚0Xd€}G"‰`ñ \ÚÉu°²ÛÅŸ2hîw"`däƒÍZû}çüýÏÿ qóZêÓhÚ¶!½7RÀ©lÒI W;Æìeâ*¾X$ ÏßÈ €eÖa»»º´xôýXFP<Ík|"+ƒŸ/h•W'ÍÏÎUÕý¾óþ~çÿ¿†ƒ­ßØE-ÊLÒ4q³•‹)ÀÏ­r–6ZÊøŽi®g[‡‘²2c’3ˆ›… É)ʘä–Û¿ÿu×ýräi¿¬ÞÜÙéòyž[Okïåe~f>žÕ“>ºme†+TÃ$í¶$’ãiñ‚y<Žž¢§›þAÚGýƒáþUÆø–î M@¯Ú`†{‹qYn È ¶É/Íå囘ù °ì´ÀèÏŠíDò@uøDÑîßÛåÚ lŒä`ŸL¿öûÏùûŸþþåõ+9õµ©mfŽ÷IHmq#~û¡ÏOyéÍkYÝMs¿ÎÓîm6ã{Fw}6;t÷ÇZ@[Ÿ]6²Ãƪa’vÛIq´ÈxáA<žGOQRǪ\J¥£¾•Ô1RVbFA ޽AqX\GªÝJºÛa¼µŽßfô¥ZB|ÍÇ;H}ÐǃÇLÕ´Óu+'Iá24¯{tÒE$øˆBÆVA2æ3»Æâ:p:¿·ÞÏÜÿ÷ðÓN©p%Xô¢FRʆc’2@ÏA‘ùŠáì4í~K˜á¹{Ø,¼ôg>~¯—0q“4­‚|¡Ã uP-ZWºDÑjv-Ýá·ŠHB›ÆB td.r2ƒi pÌF܇#†QöûÏùûŸþþ·a·)3HÑÆÌV,§>µÌÙC©/ˆî&’+“hû†ùäÂÆ6ªÊÊz?v‡–';µ¯ÿäuÿ\Ÿù@oßë7·6z|žg–ÓÚÇ;ùY_™‡O§µdÏ®›YaŠãU0É;m‰$¸ÚdÏ3ÎóÎ͘ÎìçÇ9®?F[ÝJcp³ÜÉi%ÕÐ7ï1µ¾ùQ «ÚÁ€?(áñ„‡MÔ-<s¦Ãkv·QÛ¬Q:^ï0P7¡/òG¤ Ž7 ƒ£v_o¼ÿŸ¹ÿïá¦RàÊÑ éLŠ¡™Ç à‘ž‡ò5ÊjÖzÝÕÔ×v <³C-8¼ 1Û´»·ù'‚ nywcYÕK[^µœ¶±„+piíÂ1¼$2 ü£*NG :·ÞÏÜÿ÷ðÑöûÏùûŸþþáVÃY:TžL”¼êóE=á›1ía²"'a¶’K¡n{|•~ÇHÔ¤˜}ºþôF¶±yf96m—|‡‘¹²UJ/ÌY[ø·ã€±uÕ`Âîlƒž\‘ùUèßyÿ?sÿßÃMT¸•KG}+¨b¤¬ÄŒ‚Az‚>â¹»(u%ñÄÒErmpß<˜P8ÆÕYYO@îÐã’ÄçtÛêgDŠ)m¯ÀŽòS,&ìyòÀK” “¨Ýràár8 \z¥ÄªZ;é]C%f$dëÔA÷ï·ÞÏÜÿ÷ðבâDKxüé"ËÊwÄÁü©yÈØ’ À«!ÁV‘y ÐéšuÌR=ÍÝÕÙ˜ÜNDm6äòŒŽQvôÆ ~ðé¿-onþÂ)nRf‘£˜,¬YN}k«ð«µö•·9Ý}x§{öE @Dô^3Žç“šá/ÿäuÿ\Ÿùî|ÿ"^—ÿ\ÛÿF544hÝkúeŽ¡ …Þ¯io{>ß*Þ[•I$Üp6©99 ަ­Ïv¶¶ò\\\¡‰KÉ$µQ@É$ž½y×ÄMFÕÆŸ,Ö°­òÌMq}o Æ× «2¼Ê)‰*§¶îâ`kÏãÜZÞÙÞ}™âpÖ÷qI#Rn6©£;Ä)’‡ç!‹;êcÿ}¿:<Çþû~uÂÛYø–Òê+Ï'Q’ÞÞxÞ{7¾Ieº“Ë%xز§–ZHPù`yLDhpžñ붺=ÄW÷ÞN­,Wmgh5‰íÝdiæ1ù ÿ¥±S ˆŽ mA…ó1@²çÍ£“çFY[Àõ¢°|/<Žš­©ba²ÔÚI%c Œ'“ÄsÛ½\ç…?ãçÄ_ö“ÿEÇ@yWÇ?ùiõôô^«^UñÏþ@_ý}ýÖ”¾4Lþ¸ðWüˆúýxÅÿ Š5]ê7‹žôx+þD}þ¼bÿÐEt3Ë?÷Dþ&5±ÇÂÿ?V_÷ñ¿øš?á ¿ÿŸ«/ûøßüMu´TØ,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,r_ð†ßÿÏÕ—ýüoþ&øCoÿçêËþþ7ÿ]mX,q²x'P{»EÕ–Û{¨æÞ6J©ç/Zµsá+Ù®æ•nl»³ »gý+¨¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÔW> Ô&´š%º² èÊ3#c$»]•X,ròxJõí,b6{­íc…þvÁe㎕ü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿGü!·ÿóõeÿÿ‰®¶Š,9/øCoÿçêËþþ7ÿQ\ø'PšÒh–êÈ3£(ÌŒ‘þívTQ`±ËÉá+×´±ˆ\Ùî·µŽùÛ”sŽ:T_ð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüMð†ßÿÏÕ—ýüoþ&ºÚ(°Xä¿á ¿ÿŸ«/ûøßüM^ ¿¶Ò®-^êȼ·Íp‘±´¨û½k­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹ŽKþÛÿùú²ÿ¿ÿÄÑÿmÿüýY߯ÿâk­¢‹Ž6çÁ:„Ö“D·VAFdld÷k¡Ð4É´mËOžHžX†h‰*rÄñ=kFŠc (¢€ (¢€ ÍÐôy´é5Wšh¼¾{˜Â±ÈRˆ0r:ü¦´¨ ¼°¥ÊÛyÈgd2S“´3íÉÿ85åŸÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠUAîq@ EC¨ÞÁ§ˆIæ¸H,zŸÀÏñ õöŸ§Ç-„Yf”,³}™î|„Á;¼˜Èy2ÁW F7î<)  j+š‹\¾vðã‰l¤Šþêk[‘8$¬R¸e A‰„†ƒ$®r¹%ï¬l"º¸šÎ÷ìPý¡RéU O$ í$h7ï <©yeU;•ÈKEPµÕí/uK« wó$¶‰$wR |Ï,{Aï…Á¿nœ 3þ½8éÿbs{$b_9$’þwš7ÆÜ¤¥Ë§+‡ñÛÓµ];W·k2þÖöm%´Ë"†À8%IÁ{Š$Õtèµ8´É/íRþeß«L¢W^y œ‘ò· v>”Q<3£Ç Ñ-¦h’)Ì}Çc¼ŠÛ³Ÿ0<Žþfwî;³ >ÂLêéRÜng_>òi’6l‚QŠ¡Á#* pH¦j¾%Òt]Zâö¶[V»O.T&hÆÞcɲ]續ò)òx‹C‹L‹S“YÓ’ÂfÙÓ] ‰Ûžçü­À=¥iÑP5õ¢y›® _*U†LÈÉnÔ>Œw¦S¸zŠ¡ ø—Iñ$3Ë¥ÞÁqäJñÈ©*;.×d B“…m…”÷4­EPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( ŠP¬Ý?AAV^ ¨  =rÓYÕVæÚ?°%¬„mÜÏ¿‚2qŽßç­Xñ™6·áÝCJ‚å-žò·3xQ Qáü‘åç1œmÏÊW<拯 Mq©Ï"ß"X]^Aq€™LÐù[6I¸OÜGQÞÁw`ž«xî-åIa•CÇ$l]HÈ Ž#½xVá-ÚT:³¤e†æU 1©²äöÜ=h“‡À¬mÒÊóVyl"ÒgÑá†(6H$€Å‰9ðN6žUÁÝ~MY{‹mDk6§U…e‹|–$Ûˆ¤1’«09…LÉ~ÅBô4PZÎÞ YâÓcžÊåâ’y${a ¨/8 îwmùÖ•¤\iw7_ï±yfš+$,†W.ù;°ÌÁpwœíÖŸÚ`ûTmò¼ï³ùƒÌòóûzíÏéš|sÃ+ʑʎð¶ÉX€Ø>‡ §±½IEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( îoEœ’ùSÊĨT 1üõ¬­"{‹½[Rºš ¨£qÄ.©È÷ÉãÖ¶h PðÖ¯q©ê—q]],2ëv7If¦*h£û.ù +¼å¿†vy48¼Qiâ}BêöÊëìò4q"¼ÛÔÆ±.Œ; ^›”p¸¢€8áËÙüáu§ê+u£*%ŵÿ“+Âv2J¨N⬠pvnX©îà35¼mp‰ÅA‘#rê­Ž@b#=ð3è*J(ÏHñ\–ñꥥÏú:ê-|² ‰EÄ%æ·VvÆn B¨uW­ÐìîìQ¶™§kDºa3Îf(Å9v%ï ¿xç°ã­Eqwšg‰¦ñâÜ%Üñé¾lo‘‚ÑǪï×í ¥™„ƒq†BŠC –ôû=V4ŸûBFkv³‘m¡Žøy±)?êƒ.éˆØ›Ž6‘¸d›©¢€8 Ë?Üx7ÃöæÛW”0*^¬wI‘T)gtº…˜’ Œ¹wmÛ¼SUÿ„ËM¸k+¡jÚt‘^4Wa­’bÈÉ„fRHÛ Þ#ï\ñ½ 狦ëÚG‡¬d»Õ/QŸK_íYî®ÙÂίrçÉR†ti£(ýãe ZÞ–y¬uYo:Øßÿ¢ºj2_DcòbÏ—<€]þf{Ü;W[E`ÝÅxÞ:ÒîO좰¹†K ñ„G‘áeÞÔžŠ~òûã&K~huë[uÕ,üÝfÚkK†»Ø[ï‡Î1åßjü“6ÆaÀÚrTv”PžkZ7ŠQžÛO’ö].§òbNó²¡*ÆO´ÂåDŸiiOÞ_”€¥;Ë® Óí¡»¹ûUÌq*Ëqå„ó\ m.NNLÔôPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( ’êÞÎ×͸’Ô¾ÐÒ°8éÏÒ³tEõ!{+4eéã‹Ë.À>¹ëŸz·qimt\[Å6Üíó63×ú X- ¶B–ðÇ’±¨QŸ^(´Ö5˜îôǺÓF½©!š+™ežTAxDf*6 Í÷Ò„¾6—ZðW‹…ÍìË§Ø á½²¹Hq#‰<µ‰pÛã_ã·…+½êTP­j×6¾'Ñ5u‹X´9ìåë Ì·.^TŒ£€ò:nòÀV<>îÀéu[¹¬4‹ÛË{W»šÞ %ŽÚ<I0 É#^•nŠá"ñf­s{ka§^躧Ú.’©[ÆâÝwCpì˜Y2'’ŒFñ¸H£äÈzê4FmOJóîÑÏ=´†0B»E+ÄXIPÅ7c'ÆN2tè <ŽþùõeM?Pßâ'¿¾Š{;›—hâ·U¸û;I8Ž2V×÷Š °aÉÞwXÕ\82)ùŠrT+wtP¥kþ&Ö.D0Ûipyv^1•ËùÛäT)ÙQdX•Ã}™Æ%ÎE»mVÖø‚Ûíï)‹Nµ¹{E™¦d`fR Io“£ÊpK õ4P–ÚüLÔ'e·ó4¶oµE—¤)Š(äŠá‹2Ã<Àl0$¸IÏ–™]þ¨ÍªèÐÝΨšD!&UvU•'äp¡×“Ã[©¹qeou5¬ÓGºKILМ‘µÊ2Ç_•Øsëô©è¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPŠ©åï}ÝqÅR³¾ŽùuX'h2Ç–*O·'ôü(¾³kèR/µÜÛª¶ãöw Xûœgüý)šn›™ ‘Ç,²y’¥`X±<ãÚ€9»Éw©éúÙÜM6­ye+9–/*/´m)) þå2­ÀÇÉãÈ5/ ëÚ†ˆÐ-ö•jnZ)Þ;”Ú˜dÁ)_›cŒoÈÆHÆ7t/áý*[xíå²I!Žy®DrÊd”H$$‚M'#æéÀÅOøC´cim"^Ë¡CrfÔn$wK›ÙËùÛ âs@þ¹yiâý7H‹KžâÚêÖY¤ž3ØVH—?3ƒµC’Üw.Üá€×¾½·Ótû›ë¹<»khši_íE“Éà•Nï@Óoíí »…æKuòмÎY€³™°7+’p8«óÁ Õ¼–÷$°Ê¥$ŽE ®¤`‚Ú€9é|g´ÑÚ\é¤:„²¤ie²9$mé+#e+y.K ¤e¶¯Í[Zf£©b·P« ,ñ¼r9Š:2¬¬2 0j¥¯†´»I¡"žIá—ÍI®.¥ž@ÁÞìX¨Y$“€]ˆ9«övVö´6Ñùq´²LFIùävw<ú³1üx  üo¦ÛÝëí å´›Yn§Ä‡eŒÛb2yƒ¯ Ȫx!ˆe&Þ¡â[k M´Ñkus|V&ŠB1“Î!T³*‚ÞV;ˆ“ŠøkK’î[›ˆ§ºiwîŽîêYâÁ ¶7b‹•f_”•Šô$Utðn‡œËm8žmžeÏÚæóÉMû[Îß¿p:îݧnv€( •bIÕ%•"]D®ûD,Ê )`_˜äÇ•ægfFC)j‘|@ÐåצÒGi¢ic2’3Ébè"F3dl~JvðNåÝ~O 貤HÖ®c*ÜH¢u$±a¿| g$I»%ÜœîlΚ „WsEö¨ÒºÈ‘^L‘ç,Ê‚£““½@l’s’IÉÇšdž—Z¿ÙãŸìä-Õ³Ø&E”ăŸãuç«(nŠÆí/ôûkȆ#¸‰eQ½[†ŽT•=z‚G¡5˜<+¦-»Ä­¨‚ì¬ó NçÎm …S/™¼ ÜÄ&v‚Äã'5§eeo§Ú%­¬{"LàX’NK1<³I,I$’I$ÐôQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š*A*r€zdÔuSP}PùI§­žÕ{\É$öüóíÈðÏ Ì^l¬±’@uèppqëÈ5“kâ:æßM¸bðC§>¦’OµV(TD[yÎÄËê8<úÛÑleÓtˆ-&di#Ý’„‘Ëßë\ÕûM*ÒÍt¹ ±»ƒK{ ®­­DorÄÂ|Ç*CË&Îwï×RPõψ¬bÓ¬õVû}•ÕÔVË=œ‰")’Abw ¨ríÉéÁÀž%Ò_ÄÓx{í°.¥I'’Ò gÜíUÎâÁSqà2žõƒ‚µ+}æÎ=n¹¸Õ ÔZy­¦˜+Ê*˜yËŸšÉ.x$8#z}"àëÿÚv·ÿgYbЍüìé; F' “#†Èl‚6ì#uiO<6¶ò\\J‘C—’I*¢’I<z |E¡­Š_6³§ 7Vt¸7I岫b8 3*“ذMI¬i¿Úºq¶ù2,±O•ÜH¤YpÈÊîA$d:Œ› ù>!‹]¾¹‚êøyîû-¶ ’D‚0Ñ‚ÌSÛ…<’w· |´ÒÕµÍ&x®%‡T²’;h–iÙ.ˆ£eޮĕJüÀžæMþÆÐ4í/Íó¾Åk¿›·nýŠ8ÉÆqœd×=€¡ƒJÑ,íîÒ#¤Ùˆcd·d˜Ko0•”7C%¾Ys–Þ~`y ¦ÊúÓR´K»¨.­¤ÎÉ :6py~š®§™%ýª_Ì»ãµi”JëÏ!3’>VäÇÒ«èúdÚp¼šêå.//gûDïF(÷Ò0K1lkÕ9<£7‡o$ñHÕbÔ’Úßr³Ãr«Ë…ïýï”äà.ã` AU`¬u]9mÒá¯íD/]$†eÚШ¤8(.[ Ü=j¼ž"ÐâÓ"ÔäÖtä°™¶Gt×H"vç€ùÁ?+pcé\òøãmŠ>³º-2Õm¬#û(rÁ,M!Ý—lÛ¨| >èŒä›ÿðŽêiw©©dº¿ïVYNŸû†I@Èv ‹æiø‡M¡6¤Õtèµ8´É/íRþeß«L¢W^y œ‘ò· v>•zæ“7Û|­RÉþÁŸ¶m¸Cö|g>g?&6·\t>•ÏCà Öa¹[×{h%’ÕŒ¨XQ6 ‰ʰb<ƒŒ ¡Ko_Ác{lÚ­©IÕÞ³ÀUƒTk†1•ÇÉå4aNÕÚÔÙ_ZjV‰wcuÕ´™Ù4FÁÁà §¬Í M¹Òtŵº¿{ÙÞÛÈP„wr;üÎÇ$à…Â:(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQŒœ )Èq"“ê((àd£~U “ÃÄ’Jˆó6ÈÕ˜í‚Ø§ ǰ'µbjzœú…Õ¥½½ž¤±­ìnîð²£ oåÐò;Rø“J¼Õ.4?±ÜOmö{öš[ˆ<½ñ'ÙæL"²œ³ªýÓ÷³Æ26¡ž„/©*d,ŒRU‡ÁØ‚)‘_ZOwqi Ô\ÛmóáIx· ®å®G#=kÎ5-ÆZ$Vú\WRÞC=ôÑ\$êä{‰6•VxcÁ•”|Ì (~¶;K©üe¬4ö7QØ\éÖöÉv³*di‹(þbœL0p9Vä|¤€nÁ<7VñÜ[Ê’Ã*‡ŽHØ2º‘AGz’¹¯i—z.—si7¬s<•2¬‰ò€I;¶·£x~ÚöÓA´‡Q¸yî‚’í"íe’¨~wÉPBä»·%‰9  :+Íuë/6§¬7w¶³ßÝ^À·_n+›­®ZÛdk–O-Bî 'Ì âS‡]-M|Q¨Vh´»«kyà´ŽÞz<Õ+$ÆF Ȝƨ)ƒ¸c Æ[ëH.íí&º‚;›ÞD/ .Ñ–Ú§–Àäã¥É$·•C¸áÔ!#9F;Û$IB;]tø&òÚ=&êÚò]Fæ_(Ü(”E%Ã̬†)ЇU ÊïÀ;Š+Î ³ñ‹EiíµnmÙË£Ü*BNÞXvK ùòÂn..8Ç Û÷íi–ÚÜ~5¼¸– ӧɽD—s€¡r6˜Õ'd<€òc;I,åÖÑEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢³üE­G¦Ù]-¼Ö¢ñ…F °Î9Ûô9ª>0¸»µÐR[ÅÏÛì‘”ÆuÔJU˜B°$ðzPõç~,Õtxõ‡¼’ÖÖðêˤŽ'·Š1imY%’ÝA%·c ’_ À3 =;Ä6ú—м5pnþÍ.« ÉrÚy»,2ZL&@,›æ Ý—€ÒŠä¼|ϧjºœwÑ]\±†;wG<÷Úd,ïµ]J4jvüƒà.x—\›I¸³…oôí2ÖG}CQBЫ)@±cz ì˜|Ý"nPÐÑ\=—‹5Ë÷×¶–q^YZÉi sqºæ;|©' m>s´înÇ¢ñ3¼~ºt»û.Ý…¥%”Þ7u£R¹S ÿV á  j+Ìdñ•Ö¤[ "†ÚIå_·\^-í¨Ú±‘O4°Cs–rÁ£•B•\®µÿŠuû;Ëqb–iì¡{W²–ä0™ãYÚ‘„Q•gu À’c£¨ âŠó[_ëÃDŽêëLåžÁn¢x£hÐöbòaß5x9uèîK¨oÝßÒ|Oâ=j]>ÚÝ4¸¾ÕÔ¢õÀ•"huŽ)~ô®…|ßáÝ‘÷wEpšGˆo®üMgu{®Ÿ«ivSZéí Èîî%.±0|BÈÎÁ8B›‚…Üv¼;ªM¬øŠÞMkN¿KKÁpZÆUíW`ù$9;Žwr;«süÐÑEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(«éš|²4’XÛ;±,ÌÑ)$ž¤œUª)n¤‚ÎÑî%Ž3#Æpxü¨(¬}cX–ËÁ—úݼIçC§Éwre—pŒ¸$d{VSxâÞ;^V‚u±°µµ—ý"g!yd•7&5Ûò&î'Šëh®j/ÿh·‡/4¹ }?SºšÚ`é¹Ã$R·ÊêÛxxYIƒg*q‚gѵËÍK\Öì'Òç‚ ¯&+‚cÚÃʉ°på·0°ù@Û€pÙ½EPÕuTÒâƒý{™î%òmíàÛ¾WÚÎ@.Ê£ Žß3»ŽIâ·4å3e¨°µƒí7Œ±.ÛXÖIc»nÁ(и!wêÀ$u5™6¦Ï©BH\͹de8‰ÝqµÞ v;Œ.”‘±p~UÁâ-Fm#ö§n¨ÓYÙÍqÈ RÈ…€8 ã#Ö±SÆÈÚÝÍŠÙÏ,©ºÇbŠ«r.í ñ¶ç1ÁÜ«0dÈ[EqúÇ!µÐu ½>Êêk›K9g•LA–ÖE2"¬ 6Hóa‘ p  mÙøëF½ñ3hPË›Ÿ6H¼ØŽù# ½|°æEÆÇù™NÞ Ü»€:ZŽ8!‰åxâDy›|ŒªvÀ\ŸS…Q“ØÚ¨hzÖ­c%Åæ“u¦H³Ë†å”³*±ÆÒFÏ— t袊(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPYÚŽ“ý¥)ioïcB›<¨¤ ˜úcœóÖ´h  rév·3é7e³’ÜÛH¬ÄŒ®Ò ##¸ÅA} iºÄ—¿ÚcO:)ž)!}»Y({ ÊHrAÅiÑ@±øSH‰4äHî€Óç{›ôÙ²%rYÙŽüÈIfÎüðÌ: ¿ìm?û[ûOìÿé}s½¶îÛ·~Ìíó6ü›ñ»oËœqWè  šŽ™kª[¬7Hä#oGŠVŠHÛe]e8$dHèHª‹ám.íE§î¯-~Ép ŽL±æBwä±2ÈKgq,I$Öµõ•¾¥§ÜØÝÇæ[\ÄÐÊ™#r0 ŒŽGôªwÚ›¨ÜIqq ý¡Ö4ó¢™â‘BÛµ‚‡÷² ©‡ äVƒwàÍúÐZÜØoƒÊh<霤“™0ß¼`ÌÎòC±`Cjý®ge¨M{n'ŽI·oŒ\IäåŽæaíŠÄòX($’Iäæä²$1<²")f8èZÍÿ„“IÿŸ¿ü†ÿá@Ðô;_ØÉgg%Ô‘¼òÜspÓ6çbÄÄœdþ<“–$:Êÿ„“IÿŸ¿ü†ÿáGü$šOüýÿä7ÿ Õ¢²¿á$Òçïÿ!¿øUë[¸/`󭨼dà1R¹üÅOEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Ä¡¥ŒŠ£y¨u+ 8à_ô“&ç,N®xç祦•—,72¤ƒÏ¡ŠÎµÐ4Ë+”¸·¶Ù*gkyŒq‘ŽçÞ€(k:Åþâ}2ÖÖÆêþìî¤’ÞØÂr<\™Fvø‡º_ާ]?âî¶}²ÖÉo.¢Y Gq8@‹Ê^]†‘N!OÊ·0B× pÑ!™‘$*7*±€=@%W#¾ÑéTú——£iÍ5š¢[HÖ¨ZC”q• zÓµsÚ–¯¬XøwÇ3Û]y÷:d²›G˜"ù)öX¥ÀÚ˜m¥Ø¨`s€ ï]Nu5Í» ¥µŽò&Ù<6×e‰°ÅTä«+`¨ûèÁ%¦•§X\\ÜYØZÛMtÛî$†F™²N\–9'“ê}jK+M6Ñ-,m`µ¶;!‚0ˆ¹98QÀ䓸Ð-׉f·ÔçlQì-o °¸œÎD¢i¼­›#ÚC'ïãÉ.§ï` ÑøsÅ7×öqºÒþº•‡Û­GÚ­±|°ûÀ/2¡\‘’ÁË[RiZtºœZœ–¯ ìŽé¡S*/<Æ@ù›€{ŸZ’K#ɵ‚?³Äa‡d`yQ¹EÇEùWÇÊ=s>)½Õ£×ô«6MPG5­ÔÒ¦š-|ÂQ  I¸ùv1ºs’=*KÿW²Ó'¾‡t׊$2$Ò0Eß²%IÝ]!yPÝ)‚¸K†‰ Ȭ‰!Q¹Uˆ,ê*¹öJ©u¡é7Ú„7÷z]•Åì|«‰mÑäiÈÚÄd`’F:ç›ÆóC£GªÜih-ï ŽãOH®L’ʲ}èô=&¶ùZ]’}¿?lÛnƒíÎ|Î>|în¹ê}j ¯ è7šL:Tú=“iðJ³Ej!U6ì…IϨbA €\Ôÿäyÿ\ÿA5…k¯ßA5´HѪ[Ëedšy_Þ]¤È…®õ3!bÞ|ç9‹~þ7›O¹Š1—x™Tg© âŸf‹oŸ™k\Û[ù /€!wq E$wÚ=(ZŠ«öÆÿž?øõloùãÿPªÎ?ë$ÿ|ÔÿloùãÿU|’ÌÄc,N(h¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQOGHÖI$*±-ÐÜÖLzÀ¼×Å¥¼¶ïl¶¦BbÁËï’=o¥iÑ\?Œ¯–¯½û¨‚Ö;é-&2l˜)K¹ä'àPF%5¿ˆõÍ.Æ[§5eÔu;{kd.×4Ms*|ü€1”# p6°oà þŠáÆ×vìKe­ØÇ*‰¯´˜NÆÝäBƒÌqæù‘£-ÏÚv‚A=Fƒ¨Íªé_l•Pžq FÙ!Y]bqÉÈhÂ6GvGPçâ­jÚùïÓLÔn„——ö‹xþÏ2Û­Á"Uc"ÈL,W’ïœ[޹ª_x~ytïiBÖòÎIu $òR#0óñ)P@w>aù T9ïè®JóÄqG{áuK&‹Pº’lÐdŽæâ(Zã ¶iÍi<·!ú…Jæ Ó´ñN«®G£ýŽîÕï¬Ð³Æ¡mÌfÒvÃyS̲+¿g˜Bd *äÑè®-¼PæïÃ"òêʹÕ.ì&Œ»Ffx„чA¼|¥ÑFÆ̨3¸HüM¯ ·b²¹Ž{ûë KH™£’Gƒí ŒÒ1Ú»¼…py;÷¸;J+‹Ò‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQE2X£ž&ŠhÖHÛï#Œƒßj(,m-œ½½¬9-aN=8«PEPEdZjZ¥õ²\ÛhÛâ|íoµ(Î:ê*o´kôÿÉ´  +;íßýÿòm(ûF·ÿ@?ü›JÑ¢³¾Ñ­ÿÐÿ&Ò´kôÿÉ´  *”êM:¥Ö˜-£ æá_ðÀv€ (ª÷óÛ\ÚÛ[Z}¦[ûWÌ ÷@=Oµ_¨ç‚«y-î"Ia•JIŠ]HÁ#µRûF·ÿ@?ü›J>Ñ­ÿÐÿ&Ò€¦èözWšm„í$¸ß-ÅÄ“ÈÀg ¾FfÚ2Ä.p 1“›õöoþ€ù6”}£[ÿ þM¥hÑYßhÖÿèÿ“iGÚ5¿úÿäÚP»É$óF"Œ” »o¶jZ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEWâ¿ͯxŸGUµÓ¥†;²ï¨éÆîböûFÝê=qéØQ@H`U%Lf]’úMciÖï¦ØEiÅ–0y*9$äþ¦­yÓÿÏ_ütPú*‡?üõÿÇEtÿó×ÿ~Š¡çOÿ=ñÑG?üõÿÇEKy÷âükÊ´/ Àö÷÷ÚjLï§[Ã.™§éò[¼ÌÆ<ý¨)v˜©c·…i²»mzs3¹ßv:qŠ(Î'0i~ V·Ôµ}5V·û3D–Ü!/òã·‘IHÛ©êÙ¾öãuZôwÓ^ZE¥ÍƒÛÝ-¬² ªJb;ðx ƒÐý nÕim<Ûû[±!V·´Ô°ùf€*ø^Úh./^[»--’!­ã”\þ{ä–8bP¸‡u‘Æwï~’¨yÓÿÏ_ütQçOÿ=ñÑ@èªtÿó×ÿyÓÿÏ_ütPú*‡?üõÿÇEtÿó×ÿ}ÁN¤Q´b–€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEJ(¥¹žñšúæ$Šq$K1壓Õz»Uì¾ö£ÿ_cÿDÇ@Øýïÿï˜øŠ>Äè'ÿ|ÃÿÄUÁ „ƒïU¥¸Ž+W¹ËI¡“0©²Ÿ”(%½€žÔϱú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆªš6¿¦ëöþ~3ºmY–…Š0ʸW”l088<Ó  ÿb?ô¿ÿ¾aÿâ(ûÿ ÿýóÿV* ‹Û{Y­ašM²]Êa„`ΜŽ:|¨ÇŸO¥'Øýïÿï˜øŠ>Äè'ÿ|ÃÿÄRÙÞÛßÂÓ[IæF²É 8#çÙsèÊÃðâ‹ëÛ}7O¹¾»“˶¶‰¦•ðNÔPI8žé@ ö#ÿA;ÿûæþ"±ú ßÿß0ÿñ$ó-½¼“¸r‘©v£;xU±ö“Ú¤  ÿb?ô¿ÿ¾aÿâ(ûÿ ÿýóÿV)@$€:š­ö#ÿA;ÿûæþ"±ú ßÿß0ÿñjD1&ù ¢ä ³É8ñ'ZâöÞÖkXf“l—r˜a's„g#ŽŸ*1çÓé@ ö#ÿA;ÿûæþ"±ú ßÿß0ÿñ¶w¶÷ð´ÖÒy‘¬²BNùãvGú2°ü8¢úößMÓîo®äòí­¢i¥|µN'€zP}ˆÿÐNÿþù‡ÿˆ£ìGþ‚wÿ÷Ì?üEI<Ëoo$î¤j]„hÎÄžA,}€$ö©(¿Øýïÿï˜øŠ>Äè'ÿ|ÃÿÄUŠ¡«ëzž÷׿u¶Lïx­ä›`’ÌI 9cÀõ  þÄè'ÿ|ÃÿÄQö#ÿA;ÿûæþ"–Êò+ûD¹…gXß8À𿣀çqïSбú ßÿß0ÿñ}ˆÿÐNÿþù‡ÿˆ¥±½·Ô´ûkëI<Ëk˜–hŸnFƒƒÈàŽµ=Wûÿ ÿýóÿGØýïÿï˜øŠ[‹Û{Y­ašM²]Êa„`ΜŽ:|¨ÇŸO¥O@.›+.F¥~Gû°ÿñ¿ÙsÐFÿò‡ÿˆ«þ¦/ÇùÔtö\ßô¿ü¡ÿâ(þË›þ‚7ÿ”?üEP›_Ó`ÔÆŸ$Î&ܱ³\ÄŽØÚ(ÎW Ì Þ¸2çN€#þË›þ‚7ÿ”?üEÙsÐFÿò‡ÿˆªš–±g¥yBäÎÒK‘[ÛÉ<Œ2Û#Vm£* c²‚y·ðÝ[Çqo*K ª9#`ÊêFApAèþË›þ‚7ÿ”?üE5ôçŠ6’MRõAffòu$ì©«Å_ò-ÝÿÀ?ô5  Zlâãíeg¸•a¸h?³9P2FÕÏ|ô*õdèêõ?û Mÿ²ÖµQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š*½—ÞÔëìè˜êÅR†æ eÔâhâCx 4ŒgÉN9 5¹õ ¢šÎÓLi£x fc:¯$À<œgÛúÔö±ÜÛhÆ‘#]Elª±É&Õ.¡`{€~†—û_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ #Nðô‰¢dYì"µµšgwY¢‚ ” IUÎö¸£#nÕ –ÜV¬x¿Áz†¥ikm¡ (#µŠAjeeG´‘ŽC#´2°QòíXÌE6ÝÙ×ÿké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4ÏYxgS·Öíä–öÓmoî/¡Œ/Ͼ_´ž;ý¨Ž§B?xBiøƒB]v]%eTk{KÃq(fely¢”#áÝAr@«ßÚúoý-?ïòÿÚúoý-?ïòÿp3ü6¼ií’)àŠÊ9gÇnÑÆl‘îe”<à“l›$Aò°b_˜ü¥mßø3U»¾ñ°Ç§[NÎæÙe’Q4æ) –òDÚpd‘T ª¸ÚS³þ×Óè!iÿ—ühþ×Óè!iÿ—üh—Ö<òé>!Ó´Ë{#m©XE PÜÈÛ~Ò]÷¬ZL4M¼å˜Æ2F©5Ÿ \ëWž¡*Z¥üÚLVö_¾v[[µ37šÑÊ™lw›rAé?µôßúZßåÿ?µôßúZßåÿâ!Ñ\üB³ºŠÓt–÷óÏq<ú[,â6Še¼ÜRXó"Få]€åµz*Iè Qþ×Óè!iÿ—ühþ×Óè!iÿ—üh3P:¦¥yj§Jh`Šñ&ót'h'ªƒè}MKâ uÙt••Q­í/ Ä¡™•±äJŠPŽC‡t`AmÈ9¯ké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4ÀÏðÚñ§¶H§‚+(åœG»G²G¹–Pð‚M²l‘ÈbÁ‰~cò•·àÍVîûÄRÃn5;;›e–IDÒ?˜¤.[ÈYgiÁ’EP6ªãiNÏû_Mÿ …§ýþ_ñ£û_Mÿ …§ýþ_ñ _Xðcˤø‡NÓ-ì¶¥a1Cs#mûHiwÜHv±i0Ñ6ó–cɤÖ|%s­\jz„©j—ói1[Ù~ùÙmnÔÌÞh;G*dM²Þ>lɤþ×Óè!iÿ—ühþ×Óè!iÿ—ühˆ‡Esñ Îê+MÒ[ßÏ=Äóél³ˆÚ)”fóqIc̈5•v–ÕØx‹N›WðÆ­¦[²,×–s[ÆÒ3¡PN8Éô©ÿµôßúZßåÿ?µôßúZßåÿåüWàëÍ_µ¼ŽëËD@xÒKR‹K x%"Br¦2 kó6Éeák¥ñn£¨\Úißa¼Y"˜HËq$ñ·ð’`Wà4²(`\m)Òké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4Ä/Ãë¿øGtý?컬eÜ—±Ÿ1ä²Â·G…ýî÷‰öõS>cbKŸj2Dð…Ó§ ³Cg,®Á´…3ÌÑËl6œG$Ch1ãÈ@+Ùÿké¿ô´ÿ¿Ëþ4ké¿ô´ÿ¿Ëþ4Æ_øT¼ÕLðÝÚÚ?Ÿw!Ô£y>Õ š)’2À`f5U2Ìv•£å[[Á^ŸÃ¶÷hÙÎË‹{y"0¨P~p#‚îÁ;I!ž¿Úúoý-?ïòÿÚúoý-?ïòÿh?ú˜¿çQÖF¡â8¡Çf-®¸%Ûí‘Æ<NOÿ«ð£ÿ EÇüøÚàÊ*$Ò5¸uˉ,.à‚Êòþ+Û‰· UŠ8Ú,ÆÁ•„Cç„èvá«øcÃz6¡ÓGe•jÖóOläÉ©ÈJq8*¸lcÉægùº–±ÿ EÇüøÚàÊ*?á(¸ÿŸOüE@õkGû^ÇVÓ"µ¸šÞ íš ™Ú+#DÛƒª9È0¼î'#<ö—ðýô«a²h%¾‚êÀÛ]’ÊÉ1ÛG(QÏ–Ò,RïPÄÆ·ü%óãiÿƒ(¨ÿ„¢ãþ|m?ðetµâ¯ùîÿàúÕ/øJ.?çÆÓÿQU=WY¸ÔôÙ¬þËi™ŸûF#ŒzgÚ€6ôõzŸý„¦ÿÙkZ±ü:ë%¾¢èÁ‘µвœ‚0¼ŠØ Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@W{IYŒ¶°ÊY·Ÿ60üà ŒôáW§¥X¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€*ÿfißô²ÿÀtÿ ?³4ïúYà:…Z¢€0ÛÇåÁ P¦wmŒúà}>Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ô] ßòÏýÁ\÷‚¿äGÐÿëÆ/ýWC7ü³ÿpTËâc[ÑE# (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€ (¢€1ÿæsÿ¸þÔ® ãŸü€4¿úú?ú ®÷þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šÒ—ƉžÌî<ÿ">‡ÿ^1è"º¿åŸû‚¹ïÈ¡ÿ׌_ú®†oùgþà©—ÄÆ¶#¢Š*FQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcÿÌçÿpÿý©\Ç?ùiõôô]ïüÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5¥/=™Üx+þD}þ¼bÿÐEt3Ë?÷sÞ ÿ‘Cÿ¯¿ô] ßòÏýÁS/‰lGETŒ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢ŠÇÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&»ßùœÿîÿµ+‚øçÿ /þ¾þ‚kJ_&{3¸ðWüˆúýxÅÿ Šèfÿ–î ç¼ÿ">‡ÿ^1è"º¿åŸû‚¦_ØŽŠ(©QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMw¿ó9ÿÜ?ÿjWñÏþ@_ý}ýÖ”¾4Lögqà¯ùô?úñ‹ÿAÐÍÿ,ÿÜÏx+þD}þ¼bÿÐEt3Ë?÷L¾&5±QR0¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(þg?û‡ÿíJà¾9ÿÈKÿ¯£ÿ šïæsÿ¸þÔ® ãŸü€4¿úú?ú ­)|h™ìÎãÁ_ò#èõãþ‚+¡›þYÿ¸+žðWüˆúýxÅÿ Šèfÿ–î ™|Lkb:(¢¤aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP?üÎ÷ÿÚ•Á|sÿ—ÿ_GÿA5ÞÿÌçÿpÿý©\Ç?ùiõôôZRøÑ3ÙÇ‚¿äGÐÿëÆ/ýWC7ü³ÿpW=à¯ùô?úñ‹ÿAÐÍÿ,ÿÜ2ø˜ÖÄtQEHŠ( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š( Š(  ùœÿîÿµ+‚øçÿ /þ¾þ‚k½ÿ™ÏþáÿûR¸/ŽòÒÿëèÿè&´¥ñ¢g³;È¡ÿ׌_ú®†oùgþà®{Á_ò#èõãþ‚+¡›þYÿ¸*eñ1­ˆè¢Š‘…Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ÿó9ÿÜ?ÿjWñÏþ@_ý}ý×{ÿ3ŸýÃÿö¥p_ÿä¥ÿ×ÑÿÐMiKãDÏfw ÿ‘Cÿ¯¿ôW¯íµ;›€öÚ¢ÚÄ(Œ[+þ$“T|ÿ">‡ÿ^1è"·jeñ1­Œìíkþƒßù&ŸãGövµÿAïü“Oñ­Š*Fcÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5º` àºîi<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú£Éÿ¦‘ÿßT‡ý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5¹äÿÓHÿïª<Ÿúiýõ@ÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[žOý4þú¨f’%Š'ž?2bDhK`dþ@œÐOövµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5±Ecÿgk_ôÿÉ4ÿ?³µ¯úäšlQ@ÿÙÚ×ý¿òM?Æìíkþƒßù&Ÿã[P?övµÿAïü“Oñ£û;Zÿ ÷þI§øÖÅý­Ð{ÿ$ÓühþÎÖ¿è=ÿ’iþ5´Š]‚ާÖäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕOý4þú  ?ìíkþƒßù&ŸãGövµÿAïü“Oñ­Ï'þšGÿ}QäÿÓHÿïªÃþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿÜòé¤÷ÕC4Á,Q<ñù“#@r['òüæ€2³µ¯úäšÙÚ×ý¿òM?ƶ(  ìíkþƒßù&ŸãGövµÿAïü“Oñ­Š(û;Zÿ ÷þI§øÑý­Ð{ÿ$ÓükbŠÇþÎÖ¿è=ÿ’iþ4gk_ôÿÉ4ÿØ¢€2¬t«¨56¾»Ô>Õ!‡ÉÉ ¸Çëùןüsÿ—ÿ_GÿA5êµå_ÿä¥ÿ×ÑÿÐMiKãDÏá;È¡ÿ׌_ú­ÚÂðWüˆúýxÅÿ ŠÝ©—ÄÆ¶ (¢¤aEPEPEP“ÿ®oÃùTu$ÿë›ðþUdÚx“L»”¨ŸÊVÚmä›äK¤,WFgŸhkb—ͬéÂÍÕ. ÒylªÁ†Î ʤö,S\^¡ðÉSDÓ­-nî®^-ì§Y¥iUÐ\[;ȉ3: H9òxGU)³Õã½µkзSËtÖa Ym¢UÞŠ&å_;ÉÚÛRúªG¯Ã¤5¼âI­d¹Ž—Ë!—ïnÜ<Ä=1ƒ×‚*Ä7Ö—G“uŸhˆÍÉócr뎫ó/#˜zŠÅ²ðÔÚv§¢Ii|Ÿ`Ò´æÓÖ `-,Š|¿˜Èsð{ÔmÌðÞƒyg¯ÚÜIk{mmaa-ŠGss±…f„¢A³“ˆ›ç‘VF ›³Œ(iXúüŒš'ý·ÿÐlV>£ÿ#&‰ÿmÿô@QEQEQEQEQEQEQEQEQEIúåü•GRAþ¹åQÐ kUMD¼Õ%·žâ+HŒÒGÝû–#sÀÉëÛŒœ ©Št´³–ãR4“ ÿfš=Bhã1ÊP8]ÁŠQ•†Ö<P@ŸÄ:dÚ߇u * ”¶{ÈÜÌñ+¬v†\œŽx8<ô91ø_Q‚ùµx5[Q¬JÒ¤’ɚݕÖ!b†S‹h¹.yßÇ#hñÕtå¾K¿µŽÌ‰nf_1™T;¹É!YXŽÁèh´Õtëû‹›{;û[™­[eÄp̮жHÀr§ ð}¥s¶>´Ótù­-®?Ö]XL&x“Ë´˜cv|–9à!Àõ“Âþ ÃwF¼{±e³2I9h¡ÊåHyY2vGÊ"—€êkQÿ‘“Dÿ¶ÿú­ŠÇÔädÑ?í¿þ€(bŠ( Š( Š( Š( ¼«ãŸü€4¿úú?ú ¯U¯*øçÿ /þ¾þ‚kJ_& Üx+þD}þ¼bÿÐEn׉Šw¾wðÚi¶÷K¥;Y ˲d¦í¼ã8Î2hÿ…ëÿ@KoûüßáTéI»¡)¤m¢¼Kþ­ÿý-¿ïó…ð½oÿè mÿ›ü){öxžÛEx—ü/[ÿú[ßæÿ ?ázßÿÐÛþÿ7øQìgØ9â{mâ_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáG±Ÿ`ç‰í´W‰Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…Æ}ƒž'­Þ>»%ÜjºrÀOÈ%.[øãü÷¨â¥ÿ¨OþD¯*ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒÃž'ªÿÅKÿPŸü‰GüT¿õ ÿÈ•å_ð½oÿè mÿ›ü(ÿ…ëÿ@KoûüßáG±˜sÄõ_ø©êÿ‘(ÿŠ—þ¡?ù¼«þ­ÿý-¿ïó…ð½oÿè mÿ›ü(ö3xž«ÿ/ýBò%Gޝ>¯ew|Ö";møÉܸïøW—Âõ¿ÿ %·ýþoð£þ­ÿý-¿ïó…ÆaÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =ŒûÁÏÛh¯ÿ…ëÿ@KoûüßáGü/[ÿú[ßæÿ =Œû> endobj 150 0 obj << /D [440 0 R /XYZ 100.8 292.486 null] >> endobj 439 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F22 239 0 R >> /XObject << /Im12 430 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 445 0 obj << /Length 1409 /Filter /FlateDecode >> stream xÚ•VK“Û6 ¾çWøVysEêAéØdvÛt’ÎÔmM\‹¶9¥$W”²»ùõÒ–³ÊL{"‚ |x¼Ý¾º¹b%r&+ÉWÛýª*Y¾*ê’ ‘­¶Íê¯äÝQF=¬7™,¹þ{ûË*]mŠ”qY“įCTÛšî@Rï»uƸ´W;íðІK&x‘ã3 ¡ŒgiŒ¯7œ‹"Ù5éèf®…”p¹âœÕE!‚!Y*‚oŸáf–%­VCR$ýžX£× „×*ª³VÏì;ýƒ $>v´q¦] ™LV¦ïHã®_o@¤Ña«‚ì°ešng§F7$ƒ/Êdì/¦òœåyIÆwzЧAÃÿ  Çªàšêš àÏz7~+¶`o”uæÁX3í˜,Eíe+ÎŽ­V JÓ¤éÑ íUC²5…ð<©ödƒÜ½7|£šfã!¬6øs²µ™˜£VHÁd]¡þÑFƒ|‘&êtZÂx.Y%Ê(L.€7ö½µdáÅ8ü@¬b¼Ê®`:7ÓQìaS¢ü ˜Ë©™CjÖ<¦¦x™šÖ<\®æ,ˢYÊ øA¼zÎëP0`°6dÌ÷’Z°:ÆÄ?šç"¹¿Ýþt{Ot«Ý‘(ð½Bzâ Ôð¼èw EÁ£+gŸ¸6@Ôðù"Šaž¡b…Îþ¼.ŠD«l°Ê„wß½~M„ë§ac­ä‡èˆ<õQ¹ŠUd¡˜á‹I勉@-íÉXdBNgÉïyºÍ¨¼LOÄVŽÖGL@mí5÷OÓÕÅM]ÝÜoÃA*‚jkº|懽¯X`”ǥ̊®†* Lp«¡JÉ´1n¨|±Öæ¼òJñh<àÞš„ ñQä¾bø†Õ8b? ¶çoî¿£½UÝaR‡kKCw9jÕøÀ'C—ðQ”¬€Ž6‡;.$ËX.ó(HådI×y¨'b†ÝŒCЦÎã]A @¶ïN< Pô¤/ë<¤Aøz;µA!OæˆÇ“‡™BEKӷʄメj¾(í-ŸUÂslÝB&²’Ö s© BÕEI˜ÅÃ+I²©¹•¸§’”¢%Úèiívƒ 4è†ú+Ýþ~Û~ÀÚWźHÝÖ©¡yyºïdC«Æ¸ˆ8è¾ÕðMíhßh¼Õé âì4 É¤P"x_†ŸLë‹]•-YûßÌd$6¿†Èf¶V¨¦5_Îó†¤Ì…ÃY>ÃŽ¸—Ë2‚É- ~`(«—φÀhÚå´tç¡fÁò<£Žº0rPý)ô²LxJŒî2? ÛËÃOðŠï7Èĸ<šñH7þTƒèØÑÖÁ„+îcº8ò¦OsŸKxhÉÖ²K©: Ô™/X! `û¿#ë<£áfcܪiDú€jûo„Š4„v#g¯Õ8 šœRâ…OÎïÁD6,ùÕ…IjgÐ9û^W-Y-.MõEGþ9V8 ïŒÕÿµ±f’[¤‘uΉí‡ÎÑ7ÆÀãåˆòðï§ó< âÁ×& EM5„`‡×À÷0¡m ™&?Z»ä·û0*æevý–#ž×ŒÄF´…²0ŒDz$R (¯ZZ±²”±´ß–üÈËÒYùßT9DârôÃ1•eâìÔÉŒÐÁY) “ÀRU½’xöêvûê+1[›y endstream endobj 444 0 obj << /Type /Page /Contents 445 0 R /Resources 443 0 R /MediaBox [0 0 612 792] /Parent 429 0 R >> endobj 446 0 obj << /D [444 0 R /XYZ 86.4 708.045 null] >> endobj 154 0 obj << /D [444 0 R /XYZ 86.4 688.245 null] >> endobj 158 0 obj << /D [444 0 R /XYZ 86.4 501.373 null] >> endobj 162 0 obj << /D [444 0 R /XYZ 86.4 364.377 null] >> endobj 166 0 obj << /D [444 0 R /XYZ 86.4 326.529 null] >> endobj 170 0 obj << /D [444 0 R /XYZ 86.4 122.897 null] >> endobj 443 0 obj << /Font << /F22 239 0 R /F17 200 0 R /F32 264 0 R /F36 278 0 R >> /ProcSet [ /PDF /Text ] >> endobj 449 0 obj << /Length 1139 /Filter /FlateDecode >> stream xÚ­VmoÛ6þî_!`_¤!¦IQ¯+úÁMÏ[üRY)6´… X´#Ì–«ŸóÒòÙ=ò­þ¿ëN'Ï øîfüD½F ß!žÃºPXNÇ€'PkØÜ' «º<®ëiù(dù6^&e—ÞžpE"ðRÞ@Zowê˜û"ùåñ9G8ß·‘ÏE.ªê•!}뤅J8Bðw]$e%T3œÃ5Koôïñ”¡l¶^‰u‘ƒ§´(SQ¶19?ƒ²øÖû*v´ EuÜÕß«¹øýLK ¯ô¢p/<óÉ…jst:_ÞDq†‹°£»è;ÎãÛt5ž^ß„A_Š<µ‘ïêsŽø³FŠaŸ' ÿÚÜò\BMÞDÌ6Û3nåÚ ˆÀCï 1¨åešïAUu´õ~ðáÕRX„ûžvßìÜkœ8¾´Úi«Á»ÁÙ¦tK(ƒÊLA€²lUdúöµ¦O¸éµJ&˵å?iSæ¸7[6²¦ÃGàb)¥¨¶p3Î,AsQoEŽSPïH_©79'Ô±[ç}Q±…°¹/ 44™×‰Š¬ÍO}-‹™/â“»„Á-:÷Ùñ>5lN|@P1‰¸O‰Éýn>FT³<M~›ŽC ãOvãÍc:¼>µõ…,ryÝJØ2©ÕR¡Vê;p‚CL9—ñX å÷¶IŽ“AßÙóuAï'»@OOÅGʬ\¤ø{‹îw…º—Ï–OS64Låà#µiŽÛpËQQâ8S›6GI¶2ü¿—û‹ò/õ—Õw8úlØtÁYq¬Ú,øþúÏ endstream endobj 448 0 obj << /Type /Page /Contents 449 0 R /Resources 447 0 R /MediaBox [0 0 612 792] /Parent 429 0 R >> endobj 450 0 obj << /D [448 0 R /XYZ 100.8 708.045 null] >> endobj 174 0 obj << /D [448 0 R /XYZ 100.8 656.404 null] >> endobj 447 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F22 239 0 R /F36 278 0 R >> /ProcSet [ /PDF /Text ] >> endobj 453 0 obj << /Length 1201 /Filter /FlateDecode >> stream xÚµVKs£F¾ëWpD[fÌ 0@rZ'^gSk•«rÙÝray© Pù‘_ŸîéŒ%;ÙT‚ž~~ýugËÙéáZœ³8„µ\Y‘d¾ºsýÀZfÖg;d‚ÍPr{ùËùÜñDh/.>}<›]þzú‡Ck/Ž˜Œ}Ë%S/D%ËéÄŽÇY¿ªPkUÎÁ];w|ß…?ÙO›¹ª!Y¦¾¸ÜŸs»TInÑ≞ïT©ê<¥—´*›6!‡ fJûZÝ£SU')m’:Y«VÕÆ Æ­†Š^š ½¥¹£ p-‡ûÌ÷%eŽ)ét¼ÈÎÑÞƒßâÉ! AÌbux,îPgv¾œý5ã ä-*`#¥È}+]Ï>u­ Î .䬭¹¶<À­ ëzöÛì {7Æ¥Ç\x”’³|阗ªù–—…+Yxß%²à. ÀÇ(òÕë ªH T2M[oÓv[+BsUÕï=¶³*¶ks”ÙiwÖlëU’šƒ5”Idã±Ë¢XŽ[¦™’´yU2Ôì%ô ¸,íZ5Û¢%^W+’-T ô¼Ú–)Ú5ôš7cÕVÓÑðeŠ"ô€ó(àŠ‡–ôCìÿ¥^¸F±ö…†:èïTãÔÀJà'ï’c¤"„Øy¾Ô*X.óàÏg®Œw;ÁŸ;œ‹ÀþXæmžùßÞ© 0>B0.M/® •4ˆ~Àü>ù8@p9œ˜ÑN˜ómƒ„Ö¥‚Ý`šµo [ÈE²îû`¬-'&¼÷sÒ“¤[ m®9©Š§¦ÚÍó\ØtÂe± ÉÛééÜ x€»‚Û,uB²Lé½…ìGßs‹ü¶Nj ´Ÿâ}•gÆâî{@&_ÜÀ…ÿñ¨Íùã¤Í³öwí÷?0ýÇ(…wšª¦9ÄHW£¹\Üö"4Û…ý6Æ—M]éWtŽk—ð® g\½ÆURO8ž£³UUøE…½{Ð ÐҮϸ¸´ßïršÂZ¥¯—$ïÖAI©eŠ˜ÒR‚H©¢÷î–‹àR" ‘l‡» ßbc¶ÔOÕ–ÄYP‚+®nMðU]­É'g¹(XäFc.^(}©ÂNDðQRª↮^‹v[y  Ð¥Ñôíwd²…z؉_ÏÆŸ¡úV]ö¡Ñr*&7ò("Øöb\Ü ‹S™)lSåeÛœ›þÒÀB¼mèH7Å÷¦)(ªv[‘TÓªKgT[0QÛû,»ÂŽWf’̪íma"¼#Ñãë`„P×Tá9%þê˜pl,oŒéÍòiӡОèаÃwÅ8¾2“ê&ßåêLZì§ü‡ü_dL†‡Æ°à-ùM+>¦UÒ­þ4ï=6Ûõ­ªÉnÃŒ3ó34Äql›©÷ù.@çîæBµ‹«7Éw×çß×ß[Ýùó¼Áe „‰áÎ…ÍS%iUÕY^ê½ul —· ^¯ ]}iû =ºƒjýeÒW0`ÁáMÓ*PáøÅðÂö׉]D@<_ þ>"ýDôˆv{‡È@dàÎÏ/Œèt=ä³Eð?äˆßÞÿhwå? endstream endobj 452 0 obj << /Type /Page /Contents 453 0 R /Resources 451 0 R /MediaBox [0 0 612 792] /Parent 455 0 R >> endobj 454 0 obj << /D [452 0 R /XYZ 86.4 708.045 null] >> endobj 178 0 obj << /D [452 0 R /XYZ 86.4 628.606 null] >> endobj 182 0 obj << /D [452 0 R /XYZ 86.4 508.065 null] >> endobj 451 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F36 278 0 R /F22 239 0 R >> /ProcSet [ /PDF /Text ] >> endobj 458 0 obj << /Length 1363 /Filter /FlateDecode >> stream xÚ­WÉrã6½ë+x¤¦,˜X¸%•ƒ=±§ÆŽc©r™™rQ"$³ÂE!)yœ¯O7”D[ÞsØÝè ¯¡ãÉàð”‡ç,ö}áLæ÷<9¡1OùÎ$u¾º2~Ÿü~x*¼ž¡¯˜:Ù|þíèjrr=I¸!ŽÂ@¸W×Cºœ]]\œ_ž‘òüìN‡Ü‹Ý#T>[÷b×ýÈúIÎBßfr¡›[ðúî™.u´YUÒæ~ž3‚ñ ¤m“[=).ÝU£kZÍ’Êm–Ãd¡gÙüžTmg]˜h¸j²­l¾*g&ªÙ<ŠÈ½§u{;䮦õ"¯¦IN;–IºíɬdirÅ” (MŠ'ãØÄ;@ûÐMÊ”d&c\$iša Ižß“¤ÖM[g³–¾Lþ¸èû£UfœD.V¹|ÂOÛ²ªm¨ÕÔ¨uøÒ4p7a{›f˜#ÁItð¸\ Íàd2øgÀAHrxà1îGN |¦$wfÅàëwÏIA ‘déÜÓ‘,ˆq[µýh<,R±ñ%¤  #ú¯*_Ú`gV8÷÷ü.Ó…Ý„- |ÛÌ p׈U㈶¹ iÚN¾n³rA‚y]ÛÝØ·#¨UõÏ»YÕód¦Ù¾öqÁ¤'Æ> „$ûÃÃáÈç¾û«žg¥†˜ }cecsÂ>`ïÔJ³bë*KiÓåâæKÈé\œYà¢Å7Ï÷ÀŠîzþDr¬ü€$iµšæšÄ·`Ï~OÐ+€aû®˜ŸH´< Ï­J} ãêLJ’)²rO>vïîÿ‹Í‹ï½C'\B¶š(Y[4¢¯Âæè[ðáªY!,aÛ´÷õ» ›UÞ’+øÜsq^Û«†»psÕ_Ó7^nj%ÎWLªÀr¾E½„ô¤E}È †#Î…ïŽ'_:ú¯Àu}ÿ ò? íV7w[˜æ,¦4ȦÖIJbj'®’~¾y\嚄ؘ£ñçsããœdH¦Æ1p,w“úË6]Ý£è{H6i] ùX0)ŸãØ ÍØõ²®ðk¥†PhNÊ…Éíq§Z`þžd@P5š¨{`d‡$¬(=X44.º!‰žL‹%.ž"†úçôküâbÓøH¸SzÜôAÄ‹Ò-@œ,M\\¤»\Z;ÎmQ{ˆS1¡znðÈH2³ Æ1ãqð¡Á#£€EðLQÝ8¶CŒ<Šª¼€yÿ_¢*/Ñz‘ü­OL‹ö\ )e3ä:L`+W ÇL)„,ŒÂþ‘šg¼Û,¤$ìœÕY‹ó§ÎVÅ›§W^%©e„íU´Ì>-y™kf¤Y®Ÿ`-°¹9Ûq±¡«û‘úz¼§³Û¤î6F(©,iÛY¤ðâ&]n¿È{LÓâIš&A©ïz©w½£ªK}÷¸¨Ç™Û®oZû\"ݾeÕÀcêYÛzª:Óe»yy?µ¯¬ê‚ ¶ÎÚÊö¼HlÖÓ®?«<-+C’øH~i`Áºp”¦“ Íí̦'»‡X;0Þ¹/YÇýûF5ßãµ7çA-žyȧ_åz{X£M.ûÎ úÛ®–ôæÇͤ:4—ŸÞÐ3ä‡7÷KÄ@XümýÊéÏP¯_»uw>•dR†êž›KèÿëàXC±^à޼ÙÖ`þQ;P§›mƒ² ›äø2~Õ³{q{à÷¬ÇLze†U§Ûi—‰ÌÝgù!YµUaø!›Ñ¸-kØ—¢A÷êcÝòþ«vs8¢þ{›)Ñ endstream endobj 457 0 obj << /Type /Page /Contents 458 0 R /Resources 456 0 R /MediaBox [0 0 612 792] /Parent 455 0 R >> endobj 459 0 obj << /D [457 0 R /XYZ 100.8 708.045 null] >> endobj 460 0 obj << /D [457 0 R /XYZ 100.8 668.569 null] >> endobj 186 0 obj << /D [457 0 R /XYZ 100.8 479.331 null] >> endobj 456 0 obj << /Font << /F17 200 0 R /F20 263 0 R /F22 239 0 R /F36 278 0 R >> /ProcSet [ /PDF /Text ] >> endobj 463 0 obj << /Length 697 /Filter /FlateDecode >> stream xÚuTMoœ0½çWp„*8þƒzJ¤$m•VQí©"‚Ä ¼iúï;ãí¦Ù^°ÇófÞx晋êäìJòHVf™Œª§¨È™Ž /×YT5ÑØ0É’Ôä"®>]&©’&þv}óù"ùY}9»æ0Z•ËKq U%T~J•ÑŒ&JuÎ$„=;KÒLdqë7ÙDÄÞÍt²qóó)mÝ[ÿû¯ƒvWÛ~r¶YÜ5ìCž†aQ*$S\Áª™Ö9Ñ~k¾»y×{Jæ]uópŠðîn7=ÙÚ}ÝÝóŒÒlÜ8?-|(E ‡§P*ÅŒY ³=ášNSÈzC áïªCp7´·v²@æ¦ùmèJ©ÏRF­tN}–Ð_n ÏJ³ÏÖqš$Bfñí4¶uùa°&‹/_ífÛ»c£…ʤd"7”¦z†–ëŒÇWÝŠWòŸq&Í^ C[''ü:Œú ”, ä% Æ® Ï.‰ø|»MR šî•øÏOÉÕÍd[Zæ.\$¸ìvÛÃĺÚúnèl7‡K#Ô¯Wœõ‘VJx™x;—¨Ç~·Aü^z/Z?NøR¸„¦L³ÇÂT±¤ÐLbB#QÈKxNµÅK'OÓ€ –¼÷\è~ ¯Ñ=`=Þv^åP=‹Ô¨WcG84 ‡SÓ 6<1<µCC›}hø©;´ýŠCù‡a áX˰šr­ìˆ d®à͉užõî‘€> endobj 464 0 obj << /D [462 0 R /XYZ 86.4 708.045 null] >> endobj 190 0 obj << /D [462 0 R /XYZ 86.4 599.121 null] >> endobj 461 0 obj << /Font << /F20 263 0 R /F17 200 0 R /F36 278 0 R /F22 239 0 R /F32 264 0 R >> /ProcSet [ /PDF /Text ] >> endobj 465 0 obj [674.4 703.9 1044.7 1059.4 355.6 385 591.1 591.1 591.1 591.1 591.1 948.9 532.2 665 826.7 826.7 591.1 1022.8 1140.5 885.5 296.7 386.1 620.6 944.4 868.5 944.4 885.5 355.6 473.3 473.3 591.1 885.5 355.6 414.4 355.6 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 355.6 355.6 386.1 885.5 591.1 591.1 885.5 865.5 816.7 826.7 875.5 756.7 727.2 895.3 896.1 471.7 610.5 895 697.8 1072.8 896.1 855 787.2 855 859.4 650 796.1 880.8 865.5 1160 865.5 865.5 708.9 356.1 620.6 356.1 591.1 355.6 355.6 591.1 532.2 532.2 591.1 532.2 400 532.2 591.1 355.6 355.6 532.2 296.7 944.4 650 591.1 591.1 532.2 501.7 486.9 385 620.5 532.2 767.8 560.6 561.7] endobj 466 0 obj [826.4] endobj 467 0 obj [295.1 826.4 531.3 826.4 531.3 559.7 795.8 801.4 757.3 871.7 778.7 672.4 827.9 872.8 460.7 580.4 896 722.6 1020.4 843.3 806.2 673.6 835.7 800.2 646.2 618.6 718.8 618.8 1002.4 873.9 615.8 720 413.2 413.2 413.2 1062.5 1062.5 434 564.4 454.5 460.2 546.7 492.9 510.4 505.6 612.3 361.7 429.7 553.2 317.1 939.8 644.7 513.5 534.8 474.4 479.5 491.3 383.7 615.2 517.4 762.5 598.1 525.2 494.2] endobj 468 0 obj [531.3 531.3 531.3 531.3 531.3 531.3] endobj 469 0 obj [272 272 761.6 489.6 761.6 489.6 516.9 734 743.9 700.5 813 724.8 633.8 772.4 811.3 431.9 541.2 833 666.2 947.3 784.1 748.3 631.1 775.5 745.3 602.2 573.9 665 570.8 924.4 812.6 568.1 670.2 380.8 380.8 380.8 979.2 979.2 410.9 514 416.3 421.4 508.8 453.8 482.6 468.9 563.7 334 405.1 509.3 291.7 856.5 584.5 470.7 491.4 434.1 441.3 461.2 353.6 557.3 473.4 699.9 556.4 477.4 454.9] endobj 470 0 obj [514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6] endobj 471 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 761.9 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8 500 500 611.1 500 277.8 833.3 750 833.3] endobj 472 0 obj [550 575 862.5 875 300 325 500 500 500 500 500 814.8 450 525 700 700 500 863.4 963.4 750 250 300 500 800 755.2 800 750 300 400 400 500 750 300 350 300 500 500 500 500 500 500 500 500 500 500 500 300 300 300 750 500 500 750 726.9 688.4 700 738.4 663.4 638.4 756.7 726.9 376.9 513.4 751.9 613.4 876.9 726.9 750 663.4 750 713.4 550 700 726.9 726.9 976.9 726.9 726.9 600 300 500 300 500 300 300 500 450 450 500 450 300 450 500 300 300 450 250 800 550 500 500 450 412.5 400 325 525 450 650 450 475 400] endobj 473 0 obj [380.8 380.8 489.6 761.6 272 326.4 272 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 272 761.6 462.4 462.4 761.6 734 693.4 707.2 747.8 666.2 639 768.3 734 353.2 503 761.2 611.8 897.2 734 761.6 666.2 761.6 720.6 544 707.2 734 734 1006 734 734] endobj 474 0 obj [625 625 937.5 937.5 312.5 343.7 562.5 562.5 562.5 562.5 562.5 849.5 500 574.1 812.5 875 562.5 1018.5 1143.5 875 312.5 342.6 581 937.5 562.5 937.5 875 312.5 437.5 437.5 562.5 875 312.5 375 312.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 312.5 312.5 342.6 875 531.2 531.2 875 849.5 799.8 812.5 862.3 738.4 707.2 884.3 879.6 419 581 880.8 675.9 1067.1 879.6 844.9 768.5 844.9 839.1 625 782.4 864.6 849.5 1162 849.5 849.5 687.5 312.5 581 312.5 562.5 312.5 312.5 546.9 625 500 625 513.3 343.7 562.5 625 312.5 343.7 593.7 312.5 937.5 625 562.5 625 593.7 459.5 443.8 437.5 625 593.7 812.5 593.7 593.7 500] endobj 475 0 obj [571.2 544 544 816 816 272 299.2 489.6 489.6 489.6 489.6 489.6 734 435.2 489.6 707.2 761.6 489.6 883.8 992.6 761.6 272 272 489.6 816 489.6 816 761.6 272 380.8 380.8 489.6 761.6 272 326.4 272 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 272 761.6 462.4 462.4 761.6 734 693.4 707.2 747.8 666.2 639 768.3 734 353.2 503 761.2 611.8 897.2 734 761.6 666.2 761.6 720.6 544 707.2 734 734 1006 734 734 598.4 272 489.6 272 489.6 272 272 489.6 544 435.2 544 435.2 299.2 489.6 544 272 299.2 516.8 272 816 544 489.6 544 516.8 380.8 386.2 380.8 544 516.8 707.2 516.8 516.8 435.2 489.6 979.2 489.6 489.6 489.6] endobj 476 0 obj [301.9 249.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 249.6 249.6 249.6 719.8 432.5 432.5 719.8 693.3 654.3 667.6 706.6 628.2 602.1 726.3 693.3 327.6 471.5 719.4 576 850 693.3 719.8 628.2 719.8 680.5 510.9 667.6 693.3 693.3 954.5 693.3] endobj 477 0 obj << /Length1 1615 /Length2 9459 /Length3 0 /Length 10363 /Filter /FlateDecode >> stream xÚ­—eTʲ¶‘àÁ݇àî.ƒ»» îîîîÁƒK‚o\‚Ü-hp ü›}Î=;¹çþýÖü™§ººÞ·ª{z­¡"SVc5w4I9:¸1²2±òÄÄ´YÙ¬L,ˆTTâ. 7kG 7€•—— ên `c°rñ±sðqr Rļ]¬-­Ü´ât'qDíA.Öf&7+=¸†™‰@ÍÑÌäæÍµ³¨þ½Ã  r¹x€Ì™YYæÖfnS¥µ"óߎd,Üÿ›»;ýgÉäâ 6 ›¤€-š;:ØyÌAˆÌŠŽ`-ØÉÿSÿ]\ÊÝÎNÑÄþïòÿšÒÿY7±·¶óþŸ G{'w7 @ÁÑäâðß©Z ›s´û?22n&vÖf¢–v Ë¿CÖ®RÖ^ sek73+€…‰+è_qƒù[í_˜Ê’J2ŠôÿsžÿZT6±vpS÷vú§ìßÙÿbÖß žŽ‹µ@…‰……œþüç›Á‰I:˜9š[;€/'ÀÄÅÅÄ|3ÀÄ ðeX;˜ƒ¼ /°cf&G7ðx$þ GÄ¿“‹À,úwèßÄ `ÿM<f‰ßÄ `–ü‡¸YÌR¿‰Üëob0Kÿ&v³ÌoëÉý&.³üo«+ü&°ºâo«+ýC<`uåßVPûMfõßÖÓøM`=ÍßÖÓú‡À·“Ùä7ÕMXÝì⯙9Úoÿ"¬,`Cæ x ?<‹ßø7Yÿ®Æþ7züNçü{ÝÑÝåýàË?Ü¡Õ?ÈîÐÊÛÉ ô§pÌú·fû‚ýÛýàæì#+¸•ߥ8Á[¬þhüF0;þVovü_Ë`÷N¿—ÁÅœL\@v ·ßQÖÿ‰þûuø' >'ðûàøÇ$YÁ½þ1 Vpc®¿ÍýM ?:ç§»‚9ÿ”Ûwµ3qµú£Xå·&'ØŠ›• èñƒ-»y:þ±\ÃýOÏãÀó³ïöúÁå½ÿ@ðp|þ…ÿ÷ÅsôòeßF6°)VVv^ð…Åÿ%𹻀§æö¯Çüîü‡-¬Á¯ä2C\Yt4ã³Él‰¨ ,™®‚ù)fÙš¤ø¥w® )t9Ò®|LÎùÃægíÇêL”˜RÏgBטN?•I©‹`礬…×ミvBíëï}'òûÐÔ¿ZæžrB*ÍnŽW¦é”å_~=)R¦•P?„['ƒèÓóhêË ãâ֖ʱӈ ÿLÍN¦Š–å\Źቖ–ònã[h€M$|ýÚ•c§;Æc |aê«´ù¤¦ñ½Üy†7ò®îcÒÄ=FcAEÌ®{¡B¶NBí³©Þ:i«žÝu\î<Í ƒ›~v]·ÓjÝ|A©îƒ<>G0Z–Ù:¦£«”L¢1©ž:ð[ëFq§•±®âÉDÉ"‘•ð­9ʇÿl»i%¡£õž‚•丹6—ŽòM–].|%q1\ò¥¶)0›Ä5©å‡TY}”E/¹2åÂ~£ÌfóòéxúŠXè"— Ui’³„&Ú¥À®1‚$zŒmï—*ÉT4Eð»û5Nø a)@þÚ—+ø®å¦F&A’‹ða›´^ƒævw™%ÌRNˆšÎQšP_ÀR[+&ú‘Õ¢dhIäKu#Í7±÷¬öZ‘‚…ò—kTŸ8ÝJ7™” ÄaÕ¿r® Q{ö¥y(Öj…ÿ,¸‚…Bý¸µo¼”»T\á’ÝÉZ`±ŒFØ®¹ +^”›:’@°çü‘éUÛârqÕpÈ—€r®j>Èm~”;Òˆ¬]Sûh'eöƒ%ÜÀRà(¦5Ñ(äc`1uµÖ¥¯¿¢ß.Ê\ë 2 çV|ÅÊ#‡4ÖKÅîz°@è<½P=pÞ¨ÔŒ`&ïˆk['5øé/o .u}Œ9î”D¾µÚw’™Ù„N$!äñИÏ~ŸÍ:½k6ªczÄÚx´…ˆa²Õàì­°âGZFU}ùܦü/¼bÐÕH%0¶PM˜…VO&÷jfy8úŪıÚ/²öº]Ö/‰Õd¬U›5¶y7òq£ò>÷Ù‰þ…#/àô˜£.q|tTˆý¥ ©Io<¶d¿œ· |tœ5|Wxމë ¡$©Ü6F†½eZ7Þ¹ßñ(Vû”†hÖ¹d‰¤eŠbfê<î_ÌþÅç¨r:}‰O8fÃwÈP0ÂZãÂ1©£:l6Åìx|óé†^;R³DLšÔAÖÌ„37¸Œ#ߤyÇиLÖ¼†Ûï>.º®Q7v¡ 3å‹Ó±N5Í,©¶km}G öË“¾3¸÷ÌïêϾd~È&_×x¯)W?Tj:£Ÿ~›`ÿ•“ ŸÀß?òug;$ÑKd1šoqÔ•rWKôVÙÕöDa…\÷Ø¥·ÂÞºÁ©}ÆîÛ.ÎxÆôÄfCiWI=,n­zûבYÎx{ÌZsŽ¢VŸb5ƒ„\,Æõ?§“ü2§ €Ðªµl· P´n?Ù›ªjè%î­< 9¨¿åµù#΋7ÑFèÚ»ƒÙÂêÍ•»{)\ÁMf¥°oÍêøî”ú¬þÊKŸHЭ}·dËÏÏûN£P0Ú@ÀÑìˆ!Tm¥¸ƒä—eò”¯a8£M¶6Tµp\¿Ù¥·ÒÆ•PÏÓ`™CÌ0|{ÍSQGÉ”VUo3RnÎ@ä-•b µLW’i›Kq-Ÿ9 ‡eì ú•q+§¹R°…»Jú˽fuq›¦ê¿PÓ~/£ýz–AÇ•e™ùë°O€yíÁš‚½JKd{»È4¦.IPy0ƹ°)Š«5÷ Ç;3rðâí¹…1[n­µXAªîÈYðNo+pŠèdƒcÒ?Pꡜ15 ÙÓ½(õ^h}9=þhׄõ„7g‚£WÛJ ‰ôyçuI„þÒb…sÔçØ4åÀýŽxbÜUkÑ;MËR›xøx²VKEFYüü1\,Ž}Ðjv*cß+·o²ók2zþÅÂÊÃlÞ3–œÅ^yÎ}’=ì‚$!Y`ö.‡ž»†Yn…š”ï4Æ8ÙÈÆ;øÚÚ¿aö² Åµd:I&É®\xèOz˜s»ßpøx̲÷?¹¡²àï¹èž“”ny tü5Sn’*­ˆt…Ð㌓fн¿„âÃ*‚¡ÁŸŸwur7Ĥnò²1ìAå]ú:µŠŒ¥­åQµfy÷“~(b4lÒd{ÓèB8Mr<% ò†|®Ëê¨LÏÞ/ˆ Î*·´qšf³ÏŽO^µè&ŒÂªQÚ_ŸÖ6R¤iûÆÆwôÆÜóè÷æxˆ d.(k“"W›’DßR¯¤rG^†Î0ìè/—*Óv×LÞ|ï‘GGçùýîø;ñµbŸ!!•;e„άšª…ØÙîuk°¹ ÍGKÈ<‚v”cS— õ§‡D}Dü›ºÁÓÄä›ùŒóò•‘Ûhê¬E}›Êaëk ‚5+„Húoåð¼EÖ]ȯ$B Rž5̡؂ü4.Ò‘ºå0r f–ÕUz¼<…ôàXÕs(¿eM²/8“ïÙ#ü¤iZýë@[ŒÖM ¼+N ®š²"S…}ºwæE‡±ÍZ½O8O¼‰Ü_`q™ç†fz‹ŽÌ-cÝÕ·dgt¯Oém# šU>¹s®¥w9̟Ŷϲ8OcRé±îmM†¨[2£Ry»3‹Þenb•áÐEåwJXÁkÑVzse¸LÑ3âD†_óÛ Ù‡vúm=1ß“+àXož³›õš›Éö&eé…ŠE§„e® [±µíZ­0Qºcûp¬-epÚtJ«´´•Ɣ߈£F pÃIÕÚœg2Uì ´Ã×29 ³òWhðm@åÊj]‚½4ó˜Èeu›3n×Ï(Ø-oa„F”xôH…Žcí¡MMÆ9k{öŒÎ}…mâúù×*ËP䊵çH“\¾"$Ýb4z}è21SéåãKÙî}Oë”í;Ã6‚ *¤$š oœvF`ú:±´.¢ñ“dvãÉÞTÃ’¿¢Ú â·ò^Sš°‘öZÈëèA¿>ëk@{Sùèsâé1#ôÆØŒêÊ“3ÒŠÎÑ; Ý…Ü™]”5¯_+uµ¢ÞQÌ6oÞ8שìû ºè\4Ù©í’%jˆ[s¼ìjD³pSB˜ÎÕý¨6­HŒ}gæãŽ'8èÖ™ \oKO©Ï$"k4ì®x1±‰;Já~\†Æu¯ÝÉ¢Òøºf{AJ+µÒ1ïOå?h>¾L *ÚŠ¶|šóTôZü¡påÄš°Û„é:& õžopÕÛxžƒxYáÙK²FÃG½ ‡—1<5¶$ÌRU- ›%JRN™f: 2€ÝI³œæZ¿Øqk{«UæmÜ”½M6ÃLòÓ‰øš¸ö¬Õñ®€ßú¢T2Òw(©ÉÈË™= ,»ë–iC?Gãòî(ÐHΆރ†ñw½ÑE3¨R=ýRgìPª6ƨõ™ÁìƒJr”lÏrœ×­ÉGÿR´ŒK*6ÆÓN*Ù›mürñbL´Ã¬¤ ƽ<Ñô¢±H)è"Y§‚C¿ßp Ø£ß®Ñj)¾Q<ÜŸŒÊl*åh‰îr?Å[üûv5Ì™ŸÒIÖÆ…ÐÈF¸Æ~Úä"V¡z”¾O]ÂzxþXøý°4V:­ÿ @1t°°wüDòÈn ÂÎ ¸Å’VÀ0nEFšJ&Ãn9ìhòW#ÿkȯ)åë˜,ËeûqàN¥`"†ìÜéœÝR䔾pµñ6‡× ¿ÝûÊäQ'«N¬Îþ ’A;¶W[“zM´ô¨Æþ–HµížçopQâÁÕ«9­ŸâÛä"™ò‘Ê1ïªö‰‘ñy?ÖúÇ­sÙ(ÀÈ•x×a8O)}‡ŠµiœòH“ vv6øìôzš5~ð.£ý4˜2Ò94,f¾ü²1}‰…ƒÏ½ÔI5c&dQ]Uk´i>ý²ÈûLñT_Ô2¬ÍáÓ%yú§úNŽšÃG¸…&"<‰®oÜ‚aÓ–Ÿ,³RQz`|yPåv3¢u¤èlÇ øt'I$®´jª-ËdY–7Ôœ(0{[x ‚çRmÄÞíÎî…]¾SaÞÖMš‰°¥/3‰Ùo!ÿKê%iÌæÐ§Gå[Q§·Nòª°W¡áGÇ–þWÛÚ s'8S(ZgËhYÊ÷PØy¶U”®nú‰”Ä«5‹´1AE¼•¼QBxo\·’’Luú í™>äXO‚W»_§GQJ:€¦†ð>,íOÏöŒ#A(¶î·+åH‘Þèb¥^KýöÛЇ õÉâ«whDy‡Ø3ŸŸ:ƒ¿êçýrº|ñëØ¦QÞ ‘,¯r…:ë¸êÊ,ÄÜÈëLmø®$š3¦r•öÚ‚n<¾iµ‹ÓTñ}É^†V¢½…ð_2_"Ú‹pZƒÃÏá *i#wÖ ô¾cxG¨ðå,üFPÄ/¬é|þKyÞBõ¥SÎÀ²Ú?ŒóªåÎAzÞ°¦ê”î% ëJ õöÚlßh‡˜ ¯Ã©nš™1òEb®j°a‘«ÙóŠS€øÈjªÊ¼;¸%ôжÍ/§[îZy­VÕ¾˜6ß)²´_„àŽ?qf]Ĭ;RO¿ß—31ü’í_œ×±y‡bå ÷ØÝÒñ Óm òLA¢*Üë_}ü‚´¬* #]8Ñ’N·LÙÈä* žïW¤8édñ/±U QHå59¨ë¬xñ¡·¥ú:Û“zŸƒ¹êbìæ] î½Å©*ÝL¸¬¶ïû/õ?'-VêlÚqœ¹‚OèaÏc÷ äb(zS‡]<–Åôm‘¹Þ8ú(JíßÛR‘[‹)ùº|Šéä7#n¡.7õõyôvý³Ÿ±O](±ªC±ƒÇ}'!Œ"1iúçû*:€?]¹§ŠÐ"=d!ñ{Ãçé’cõÛ~þLòp ~…L‚ò°K%VsxÈG’̵éíáç‰TnqÖZš+¬Õó,"í%ÏBé-¨ðÌÛd‹ÞìÙìF•WR 1¬c¯Øæø™¼4è]sɲ%ûË«¸‡W¹ÔßÞ9T¿CiÅ©ÒÎEJÂÓÓL£fùFŠ8žehXùZ<Ù ÷gš$^vs ]±¢±Ôß’¡%17i-ärƒßÝÕy<ÚÔÔŸ$zNÉk0Õ›Ø8,Hjèæ ÄìÓ¬ìLš°‹å Sûx†Y@^#üöâåqp¨üKTNãé¶zUã…ò:ùî¾5½Aaêýú Ô™ÿÓ‰û¥ mÃÓ2¿·µ–º‡Enj²ò¹ð$¨½¨‰†tHöðÈJ3#DÚ†Ù³]/pR„È ¸ä4žÛX}]”çsÖÑêm9發öˆ"ˆÕ¿Ú_~îßï|P-}ö±t£FÐíÙ“øÈ¦¶ä?ƒƒˆÇÁ„T4ïA?}§3™yAf#Kžre»â¸b®ñî´ÈŸãѯâßEf*MQmãZìÛã½Eך÷TíÝç£ zç…#Œòh5»GoÓÜà$ÆôŸ³í+W±†HFE¦*ý©¶ü `]gR“«©¦Ù Q#Ö,¨ïg—] ˜¿3¶u#T%~§SG­Êô€¨õ>¶%1ñÊ.ƒp“a"ʺ[™ˆTŽŸÀãÏ]Axÿ6å˘Ù"Že¥ˆ”\ý¦,q‰Ìr½F åâ*ûšH3ÒDŒÞà€b˜ÊœœJª‡ÁBØŠö«8Adöïa™ýMM™õrXåë’†¥ª»úè”!ufOYŸòL3ûÏPíìƒUüµ° l0Gß¹à­sÓU2âçØ00© {³ Vôh·†£>r|RaÃåv¶Û×øËGû õb©ÅôqýÝ÷#F?6*žSbÂEY¨…x šæÍÏ5PDE•Ò¯=@_Xé¸C«²Z¡À vW]ëàCEŒÎÄ0.¬WÈ'3æÂ>ö¿6ŒîçÛé˯¿°M=±""¢ &%Ù£8†ö\-ZM»j$%‡–PŸÓc’Åëh“Ñ:FQXÁ&/•­f92aæ5S§\©b¿õ9‘w Ll¶ÝóôMý”9^yï dþª(¾YÕÒpEoÂú+†¸’µ°tÒ ·Ïyåû„¹7O1vT„%'^Žë‡ÓaPˆ£É‰Q)ã²àõr†PõѶñÃÞv€×yÑ ¦bË Ý=¡‰CÈIb£‹ Œ2Á)f7”KÛè÷ﳨ#¢Ï.­ 6Nñ_ ®¡!76ýÙzÖäo\ÆÎK¦/ì®÷÷bÎÒæçÅÉQ*Ch÷驨ÌÉjBf«ÆÃ¡ª.¼?âˆx1•$ý…ò,™‰åՉ߳C^À½G5|×–«GiÊW3îŠT§[½q$ÖUfæ,nѾñ]ýéõ¡h”„$ ~á´û0Gþãôs”iT-+´é†èƒRž§úƒ`­·p=5YeÞ÷³7õ1!T¿C%H‡¹¶š TâÆX]Óº‚* a¡“êZÇ}h¬7òÂSy‡ìТÌlü“ß¹ÿÌ Û(ó˜2iñÛpÎõ‡}ïÛÔİýWsXS玦”ô“4‚Pç±–‰qÁ´@ӒĘÇÜ­. ‹TÔºw·l œuºF*CÜs4?(ñýÄËg0©uw„&6^{ºÖ5‹É]E/#É×4p™+U7‚ŸËü}‘RäuÜ L¦ŸÁ0¾©;h« #ÉpIK\NÁ ¹-Ôà2(3Nm]os<(]@¬È[ÙvP‘¹ÌÊ“«¼=žóú(:uÔáe¡î'¬Îs*5–¶ã¸ÒMÜ-ˆýªÖ:EOà„"Oõ‚žÚ;>.Ûö˜ee!ÇÚpˆb}=íc¨¹¯è%1¾˜¬à’Ú×Ë1ž$4ÿµ× ø5dp=P³\{¹ùG´ËWúiß Ï ÚÔb™ÕAAV ¹x'èT7K2$7éÉàÂáwó§¾Ò§ÀjÿFV­‡C™ š=3ãdŒPC»T/ÄÎ2]Ï@#©4ÓˆE»>ÓèÃôWÆjQfÜŠ‹Ì¸bå8¶Ï_¡ëÞj­:R‰â¨œåUðÃâçºOîÏ‚ý5Oèö“ˆ¦÷׉2$Ç.¥Ü~¬m:ªúVʺÄjÓT1Añˆ÷ìóŒbbîÜ-àáÌž_o&­r£6’ðf3aëâõîCV‹-¢å";æ“W6£NKyH~žæ÷LàKÕHM™ŸÍß÷ÇSW",åQx~ØåýÁÉØ”<éûÉQÓ’Ffh·@ vqëZ …3|Ä껑1¸2cQÆaîMÏ¢æ¬Ëjyè•L„öwç¹óâÃ2ýêTWC>?~˜ôÂg¨’ä{c˜+"/ í‡÷%Ô;:ɰ÷<+!D†“Õ>ƒv³pà]¤Y ‡#[á4öÖÓêA—2ƒ±UA:†Ïï&¦/ˆùáó1¿d_Ý¿×!zav€VÐL¿lÜH0>’Æ«±¤Ó˃£ÿµ%8¿þVYݳ] ½[ööþó½þAúM_Hí/Ám4ºí䔺mÆÆqnQÊàºl™®8FbéìÅ 5'=Ë’tiíïDUÜmX a0„âzÛê"¡Ï¡p8èÀCñ8GŽJ*ÒxD~Jµ%MÁŒô9Ë· \ÿ²–#Áb|U§G"Óq´q‘§õ†|&5ýQ8÷xŒŸd»7„9vÚ$ju/m)• !‹ŽØ3ÝSw¸v“¶‹Áö*íè ómÇÕš$E\{ŸÁô.ªOE'àçÀå˜çìQ„‹Äiògú$Üíà{ ¬„æŠä®u[6¡\ÜÂ’ÒÔ‡ðVj|W¥ «ÚlH>Þ°8æ-<åÉÁy :CI‘Îù1&¦æ˜0B·,¨ÞÂûìÆc³|Ëw“j~ÖtÖ&muþªšl§Î_*íç>"Ú¹LkpD^´Ë^JUO#5JNx ž>V•DͽܜfèPÇÈ›ññ¢j®¨·TR þ}7._ÝM™/‹ß›‡W .Ò²)fXâÆ~†,©Í`ùžç‰¯ˆ¯ŠMh%Ï´6„öTŒåBÎHç”ôúê+húÊça‹YÂÜÕº‹3>“X‘>ûp ¥©,Ì«? x¼á4±¢˜u„;†F`šŒCêCkaFÉÁ®Šäĉð|^¼Jå¢"Ô£-¸Å°#=(Îz.®Ê)KÏ$8_]ÆD쀺FSRSÇÇNJ©[Ê¿+s‰þxè¿õB³îôäÕ©¨Ç§òj¥0õZkZ>2Ž-AîÀtèZ×l:Ñß²x¢#ÃÔœ³ Må4ÊÙ¦c~Ao1«e ƺÛ6N³Ú6­ŠnµF®œæ©áP¯Æá1 SÆQ uè>¡+º[¨½te|j¥,Ú Ñ[œÿ,S x{0¹dÝà–&Ó‘¹÷ê·¢Ð=°€ƒ¹Ýÿù™ó+â2Q¾ÎÆ3dNä>šN·óò†<ÑÎü»tÕ“ItÛQ­«kX4‰Ð'\YÑðê_V+?ìrjí‚^TŸY>3d6Ë ŠÙù¬ë»õà#Ôµä+(E='@È­¨ ÌžaÏ/ï5JdUvt½"¢¥mÎ8W±ûs£ó‹³å°*²4 yxnF´îÊ~:F•‹½¾+<¹B»C“\Ü@{IP01²ôÑšßÄÄÐ;Ç‚e`Pí„O–zº*îÑõ}X xÁâ!l£7j`ƒ¨W d\@@ °É,èë¼m¬Iœè ^$ÑÀÞ›5?È7¥“GUÒrDírÊ[À%$¾EÁŒL~(¤‰ÈÛîÜï‘Ççrg xû)ÃwñHgFÅ ÉcsD’ï 9Z„r`ã`¾ Uòœ6M’èMáìJÁ¬IUFÉR~w~`ÕN…òËü0v1AÔÆ²¨’µv•x ð© e‚á+.Æ·Si“äz˜;½¢Ï3s賟NËjL}⊄!`0ÓŒ3×ÝàDba]È}O2êh­»gÌ«jçýœ/ÁTw½-Lÿ ¸Ù,1±v9?\ñYº›Óí½/âqH î¼Èò5ãkTõå2!±T Ì¢‹rþ.v…‰öK£¯¤ °|õ]4;޼O„7þ³ A02°”¯~¹¤^â8ÄžY”³O×®ÇVv U¿ïCÒáVq‚|¾¿Óé»ïÎ"ÏãêŽy·˜ ùæog0 £ãO”:ß}²—Vˆ¶Ài%{Ÿ£ë]´ÿ©h“"4¼<à΢êxa™ä… Q–·AÛ‡jœ[g+â÷ÞÒå#–ÙèDö÷:Ëg[ºè¡º ÙÄ;ï·¦vacÊ{AeŸû¶È”wòt7Z‘ô¡W-HO)D–Þ«Ññ|“yµ*Æí±"S­&û;W€;Ÿ7:˜ù?Vx-ÒfO8I´éŸC¥lši Uæ6 åÞIó{º·Uâ>bG:…wôŠ'+×8é½DÀ¯ú€¥©y­þ$]ëfDø6 1;S(½mïã$è¡O‹›r­¥:tºÃØè˜vköY*üШ5äYAX?ÿö¶­2*×™Z`äáôq’zz©Ø÷cTóÀK}×B/44!xÔ±fjlx'·Ë?IZ6CÔ "ªB26ãg¶˜SŸ¿  ›[J×N&}žÙä‰ÁŠY[ËC2çÂÔuaB5 ã 901®¼ÜγaIÚêC²(}y]j³õb§üôÈ+£1Ø^}T‚hº|Jøƒ?'æG3vÕz7ŠªUclT Q…"M-Y®°›š#¬Ú¹¤ë³©Ì@µÊ~ü6ÃÞ)û'xÇé)à±üŠñ¿nŸ2¹nrÙE@%˜îŠ&?r ·~E6wœémÁÜu¬¼üŒÉ.-°KM“Ð?¢ù"ÛéÑŸ›K#å$­±EvzéÊ ñ‘ò?Oˆ¢yw¬_y‚Å|éù”õÝQé ±gÐ@ªr7œW͉´ÑuèÂp‚k°\‡”¨ÄzO´/‚Êkƒ~geÌ9«è5ÿ®3œ ™•ÛÒÁ«?³J$/6žƒûëj”«–3ž ýšŠSuƒ{“nŒ‹²È]˜öÛst93·—& jõ©Å:âo†1’&¨ÑÍÊ5×hÃ4Ÿ«&z2e7VQ¢ø? ÉjŸ0ëÒÀè|™F€h†í9¶Š/ÄÄrrÊTñ*å»x† }W£h ÑuID—)“F—11.¡o›Òh3aùÅsCXxÇ|2ç¢ìªòÝÜDsÿÖSO ºsãRÆÝÇv’Z7d L 3åþoÌ%A„¶÷Æxë›´<ÄõßýÕ–H™Šä[æ,[°P'Jy_™S¾R± U»éõªjD¢q38aÝjAjÈ$H’‘Rðc¤Ü!àm”&5Pó‘¯ä<þUÅ %ÌRµ·(ÀÀyǨÌ,Ð#ÓJa:¤#†« ºHrz³†hBPû¸u=L8²û´«žÿP{»,Έšè<…åxÔ²*ù9¦‚iLŠ—2~#/°õrV*&x×_Ëê»9ùdqe õäã…ÌwqN §(%P¡èÓCʳ4ᆾxÌ—=[£ç›wLzs•Iö08KÿºJz²í}è¤Ñ6ñtþ²€ø°,0K²”&Â>”õ]7^ß„Ð)+Aš©Z ÎúpX(Áåä CÔ¶g5ôºSø}x/jîçkA{ã¼¥=Ú¦z¿ 2¾åÊÞá¬ë[C_sv ^³ƒE ¾’SUÀ›…×gèõý¯šïî­}•C]"¹ÂôC)Àϼ[úÄ2a[w1ÕŠwŽÍ3¶ƒ.KŠu# UÔÈ]²§ ëèKIÂ.šÔÈ›º²vXé$¢L{9\§¾àÂÂex"ÛûÂ&8˜4Z¬Äžqñã´ M–NXx7F`R6ëé•ÝmM,ÍCM†áùµƒNáN" 6£T³\a®Û¬™aQe[ËívíÇ\8µþFÐWž¶#Š-«W*ŒÃˆœ!U¹b OÜ(ªüŒ¤ÙëÝêޙ䒺znáÈåÎ4ÔAGšÐ–ɺ#¢ ÓðÉ[jyS¤¬]â:†ÒÚÂT„Ïßѧ7“Ͳ2‚yF¯ 8”÷4‚2†ÄûȈ..‘àl[ÅIŽ¿óìÅ)FÑí•ÀÑÄÂj âO#Cø¿ü¨àNhuh_<ìcLä¨`fòß ‘­·K@×Ñ…lü?53B endstream endobj 478 0 obj << /Type /FontDescriptor /FontName /GPEOIN+CMBX12 /Flags 4 /FontBBox [-53 -251 1139 750] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 109 /XHeight 444 /CharSet (/A/C/D/E/F/G/H/I/K/L/M/N/O/P/S/T/U/V/W/a/b/c/colon/d/e/f/fi/five/four/g/h/hyphen/i/k/l/m/n/nine/o/one/p/parenleft/parenright/period/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z) /FontFile 477 0 R >> endobj 479 0 obj << /Length1 999 /Length2 4728 /Length3 0 /Length 5371 /Filter /FlateDecode >> stream xÚ­“e\TkׯARB:%6Ý ))H7R‚HÈÀ 0Ä C (né’’)¥%$¤D”Î)y9ç¼Ïs|ŸçëûÛ_ö­ë^ëÚkÝ›‡ÃÈTD‚°‡j"à(qQqy@Í@õ¡™Ž¸ .*FÂㆄ‚Q0\Œ‚Êârr — . ˆËÈKÝ‘—¼j4æäŒøÕþÉ*îP$Ì  À(g¨ûu °`Šp€AQhQ@ÅÍ 0ùó„'`õ„"½¡Qqqs@öP'œô§'¸#ù; ñòøWÊŠô¼6ð_›®-Bp74:’€ ×½ ×Nþ?LýgqM/77C°ûŸåÿwNÿ¥»ÃÜÐÿ«A¸{x¡ HÀ"áÿ)µ€þmOáö_tP`7˜ƒ ÜÉ ˆˆK‰ŠIý‡yjÂ|¡#ÊÁp»yBÿŠCáÿôq=½¿\€Ì Õ4L„þ½Ø¿ÒF`e†ö€bÿèÿbñøzLH˜/`%&*&&~-¼~þõfóí4à îHHßÀH$Mr}…®Ið`pÔ€ú^{‰Â¨ë#ÀõdžŽ$ÉŸ{•@š†þ&q¤õÉ ƒ“¬2ù‡î\ß¿IüÚú^Ka¿e¥óo( €~ÏÊ ·ßP¹ÿƒ×sÁÃëFˆßðº2ò7¼®ìù^›Dý†×•}~3y] ýþ÷UU¾þ"r€ˆ„ôõ8%d¤i©gÿGèà…DBᨿ~‘ëkð/v„]ß(Ôê@2A8(„¸¤5†•h¼+'ðdÉ( j­ÏPÝœS ž@6šAÙ¨B©\`”©ÛzU ˆ£ôS£ÊÓ>SPèU9­@~¦)ѮæµíþÜ]î/#צٗ=š„vg¸°óÞíÕúëâ2LÛQøe_0—‡®Ã Ӥ鮕T›Üý¨ùù„g[ZˆWˆé¢~ëL,ͯi¦®o㮳ärѹ8zÏÝ¥~Ä; |#TÜ@RDÁü¢_ìAzLþ¥I}9)‡÷ê6W lJ7~§Îü)IÔ.„aqQ]m_ÑToITúH·ŽXB±©ÆbÑT‚u ²[–lj¼–Ô¶¼¤{ü¡ËYŸ90wɽ†;„Xº…žÇ’T`ùä·²:·+rÅz‡Ðã¢n¯Âä½Sc%ƒçk+êÓHö6)ë¯õÁaûÙ0ðVŒ–‹Ñ §Âì"žá¢[ÁïÇb„dDô-uúL%€›MàÍÁaÅvé‘ÛŽ‡­±ÝÎ|#ªà<‰ãOáɲZ ï!>ÈŒOfGi_äÃÉ’ŒœœzùO±Ò²hnfa‰vº2ìóˆ„ÜlbB#1aü„߯ í:p›%¯+mP—ŸRÝ2«êQï[§òFiª%¯Ìnjê{\áâ1¶,GËx÷ó@?@鞊&+ÚmVpM»Z]ë²¢[îÞÙLB$ +WœÔäž`!ÖGÕ.÷~À.冖ÆëÒD+'Ë‹¨‘¶«M³2سT›œ?Ï(xÁÜ÷wÐ"ƒ œ’‰]©³½ÍJyʱ›x/ûå¿ûô‡ÐY­šÂ5ì2˜Ø)¾<'ÿâ›Yzx!°k¯™GO¾èC¢^¶½éw=2b¬x7Å­'2 |°{òUF|2ÕÌ Ã‹sOÖ«8€v|¡ÎþýQ™òbªùˆx FkU#½øe–^i®KŽuíó‡ 3{mo¯®_xéb/^;s¼ónûªtwñÑBïÝŒæó91¥8µ¯g+É÷8 ¢2ä¹-Dìc|¬•%ië:kIÆv×ýHP5§Úâî7ƒ6³sZrcŒË¤¼h%«Ÿ¦ÕÔ@¸Í ÜUûÈ‘MòäqÎPi;½üû-8˜ï*¡i¡®¯qÚv¹^Ž´M@ß_CÌ{AvžÁ† × †1}ÀêPq<°*6®èÃy‡ï¤~Hé|‹ûÇšÒe>^ßÖëuå3‹Ÿ‰«Gå©dÔ6£)-rFy 7ƒ¿_<.á iniÚÐ å …ç¢Í¤bƒe—qÙNÏÇJ¡ÔSY-rÇÀT¥à¦ÔÛÚxfJDÀÎi£èS»4T†@%ùÇ ·‰ÈŠW5¬=ï?Íåb%߬!®Ni@­CdŸ'ÆbŒ©n©ëP˜wÜñ'™1 W?(ßbŠ,ï٘î©à–™äâ}žïÿQÃQ4(ˆZãHÅÜP€E©ºƒÊh™„-9êöºÍ81'Í®— l¼?²º/PÌEUdzè,2œ¸-€{ž´—¡»ƒÿòÖÌ8ÞqÂØ¨¬hsàDø£še¿×É/w]O’Ãt0=ôüHŠžö=‡­Y¶Èï°šç§"Ùè^Åæœã?C¸¶2g}•j:7ç¢-ÍöãQæáJgv·iìôD‡êrÓ­YÝh ÷¸2•WÉ3Ì0±HÍ…5ž÷‹®°Nºƒg7c›$µ¦L©¯¢ D+Þ|Ÿ³§-̯›eû£)V÷â_(l~ÙDSàÔw2±`1¼qÈ7ûíu>òÇOrùö¹Æ‚_ 0÷¯áÜ6ô¾kÚgá‹ wêÈž‹®¸Kxï ·6çEµÒÛÖ®\¾F[C§¥êñ@!rÑíK–{ߘZؽè ük8¾<Ô}®ö| é-•_w)ÖÊD¼7Õ˜qqhˆ(Åâ,×ô5¿ Û&b—aƒü–N»‰{`.gÍ·NWqHWT™ÝÁôíÃ]TdaOk¸Rÿf¿VŒ{?Æ6è§ßüdþ† ­õú³43×$lAöjÆ‘ÚÒL•« i`³r-–WÒEò,Ic»¸ló׉0SÑ¢G`–¿igoçâì×çc>ÐO ¤·zDOåÅ‹Zìs…ØILw=•2sLªX·‹8=µ¦ÖkÇ?xýͲïĤÂüµ\‹?èŸÇz”CŠXöŠgÇ@-ó Y¥ÿìí®ŸMyÏß"žùùÓ’Mwø÷æ¦õxÎ,g ²€;ÐzÁ½R½´/ÆÔ+=æ‘W9œûì%ÓCm¼·§‚ŸfÓ*Õj®E¬tÞ(RRØÚ”`îˆè#"ä Z—äC  üW°¯%˜¬X®Ìo&ÙÞK}'»nã5rÛÆoMí’þuUåj~üŽpãe¥ ¢7_?·2Çx³I-NÏÓLTÌìÃgü¯±§Ô¼¼µF¾REÄÐp&ª¬â!éFÍí”}&ÿªÚâ»YÝ_”D^£8X€·ßЬÅlÞÍâ–8¼2pä{²¯¯äâšÐb<ø™ÞN/ß/Ì¥™ÿünWÉ/5.Øà3tFÓÃ3èèÞΙÇ+Ÿ4šZk8«Ö÷Q›Ë–Ë»ÆPögc ,äxWŸÀVS¡Kns.o4ÓêÌmÜS鹨Sˇ×Zùä!]×·"¶Ñ64‘4®1 êã£Êé£qü'&aç–ÊÅœÔç¾Cñzõ¾  /°eV͵j‡¾È±ÒÅAšchƒé̇>™â°/"ƒ²8ÊŸuFófd ü‚Œö–§xÅE}åOmt&6è.ž'óé7s’Lô°é¾ZøEƺÜ=Zäèk.§ê«véiY¿Ä†q§“¯øœU¼3;©êrB$KÄ­GÔ}H?hÙ(.·“§7=cô—Ì9ºrHŽLÃw@^xÍ&÷Óü±ñ±òªcLш?økW¯©rŸ*­¢Ò,ò›1 N9-£Äm¢“:RbPZ’h§±+‚é¨Ô)–d¢y–ò²W²½S4œv§ãKŽ'õ%ØIžÏ‘}§yû’Þ%ª¡<‘òºî£¨Y´‚r#"ÝfMmÔô^0’N¨ôq]¤;Ï…ã¹}ï7ß “3r µngàªÆ€sjèž\ìêjtMZ]…2Th[åœÅhßpùùâÓ©}¦ïfà/ŦÒPБœM®És³ÞªK¯ª pŸÌ[ˆêÇ}þVØ7iw«ß檈cuåY|>=Å.ƒ6do-¾úŽè3ü3)¹(¿ÞÇž†%dVÔåŠ n™ß`€U¨“ß)Õ^·£7£€ûEgãÞî¥>ÛÀ÷•‡ŠLó«Ï¡R¾µN÷C׈oa)_d0­r9½ñ!ˆiÎ v±w6+dãûêÅrïuV2XXŠçÉi-ž™RøôL:¢†9¤ô‡Ž—¹·‰„>&’´P’ŒÒUÚö…\ŽàÊp~6w˜7ëÿ2AÍ30P>'ˆ»¿ƒÝ4íK^ªO w±¨š÷Ú;%¡å\Sͽ8¤@++½–ó{ʰýb+™¬1×ü˜;aZã};#Lv­{µeÕp+¡'„œ|§ßN"G/+ÿ‘vXVùJìCgkì×'tž™ÅÖ7%„Œ“°ÌDŠ<ý-îÆô‹Õ ã#¼júªt«fI†žË<£•H¿²·è[Ïú†·½¹Ä^œØ†þšq‹Ya&ÁJ yÒaXJt:T‹ÇI½£Gæ©à*L¿y‘ûáW }¯å Aµ%A8“-ftó‚9uÕµ¶U>  ]:´µ¸Ípæ*Ù2ò—÷ÞŒà\z÷+§Z©FWŸãáUµ*‰¨õïçQ¼8v3,,u´"{aƒy“`…˜E/¤ïE;˜ö°nw÷ÁÇÁ”2:º”iJ5e¤y OÊ«†>ŒˆEä+‡eo¹ê¦ìšÑø§µ†¦±bGxï‚Cgüµi­ÛêrÞË0@õsœb%?1Bß}¥=£}7ëGÐóD8¶h¸O^193‰QÛL)´}ìJ$Ø#_¶£VÓúš¹Ëqœ¶¼ f2ëÐæºDi}ª½OÀôÒ쮬è)`Á¹Û:HŠ6®h° M;™@¥p™:B~–Ã늼X¤l5˜©e¾V_¶Np¼Œ½ýËr»í‰†¿t³Á mr"êEªÀf†ˆG8æ;êÖ*¢+¥ˆ»^\ÜÒÄQzVEçQ¢is§ŸHìÜÍ g¥®¦`¼.öâÉ‹¿Î®ëæéNI&eª’¿æã§$p ûPTŠ¿L5¦/£`ѽJôE`¬N6]Ïóþ¸UOœˆÚf¯fSÑ#اÐï¥~Ãð˜m_¤Ö7ý1òbR&ƒ´ÄËM|áO«,ò¦KëìsÉ3½§ù5Jœ~Lm·k"ZàÆã½ž‘Ìžm=jlèºÆÜN“ã#Uŧ¤¯B™gôÐ'¢Š–û©²XÞ°:x¤ÖÍéüݰ’þ÷c­Ó¡‹ØÞ r¯àŸj5VÍ~=¨/jsbOºq%¬ô\hJV·&Xaj0Üû=<™x‹Uý\nKvR\=¿ þò@ïdc+NVÜÕ[u5©aÀnš·0xã(}œØ4ML4D&ì¦ChãNZcSl¨4Êî-gÄâr¦ìå p™<¿¼ë´Ñ¦X=O4'Å~–«iwêÒ¿çkýyÇš'€€päã ëv ÁÆà®¤‘@Œ µ½tÕ½,œÜ,¼³;‹°›©ôåÛ>ecEõ”EóûÏûH)µTuñ¸4sË3©UÜì`*1]ixq0.sdš”?%Î7]\?É"½e¯Ã VÀhÈ` ¡A¼Œ{j‡¶ÃaåMû€<>°®ÏKá9}˜­±R-¬ˆ9”Èa‰ŽW®H›4^¤µV®¿Ö‚jáwÊÌã„G) jÀ%8 ƒn0=¨ã^hÚ' ¬}@I(Niüø¾Q ¦÷ÙôþÀX~trÛøöb 8ð(¯q?® Э˜Üg½ÁØSÙ•l ë ÝOÔ ¬†ÏÒÈÆnñȧBÄ™ƒ[M¶Ú~dÚÍ h`¦£I”p8©Âê²¥…Xßw] ¦óáÄôG/´À  „lÍ ]ÏÛò˜rjBQ™žbVF‰&·/¶ÛPª=÷3ÂÔNqhÔs&Û>ËÁåöï³Iïö“Dî1Êq’+¹r‡Tø'>rM*ÈÎ5»²: Å ~z˜5˜ÐoÀtä䇸%w×…;Ä1IŠ=+E{ˆ:º”5ÉŒyÊ ßŠxÀèf¥w‡€À¿•àU-nñ¥1•âýFúŽÜ¤[N|P§6uÚ}-~Ù(bJèbe´³Œƒ'øIô¬ðªáÌ7Áf7H¯ýh[l=ªKÁ¤1©u‘( Ü)Åvë§Ž+¸ižNžYÞˆT¹ì±v{ÙG~{„Q™¸i¼“ä}û°îYMU†ãëDsŠ}ú³3KÆY«½œðúãÃÅ7ê}Æc¸Ô7e È—ðÕG»ƒ2Ùž£$Ùˆ¸µé‚}ŽõnÉÞM¬B0rv–ý”e3“=·i¦l:m_sˆ½I»P ÐÔÙæ]1T-ÁÅÀ SÍ‘æ\ëíÚ윧¯JØ ?®-–éc^RYsßXj J¢È;’×{…8ØE]Hd7(ç’Dÿð­Ï1k7> endobj 481 0 obj << /Length1 1088 /Length2 6133 /Length3 0 /Length 6820 /Filter /FlateDecode >> stream xÚ­“eXTm·€énA@‰A$f†‘înéš¡a`èIénF‘înéîééäð¾ßùÎëùÎßsí?û~žµ×º¯µÖfbP×─À, ²0'7N0X ¥¢¢æ<¼ƒ@xLLRp¨¹›-ÌIÚÜ * ñÝÜ 0Ÿ€0@ æì ·µ¶q°J±ý$p„Âm-Í*æn6PLJ–æ-˜¥-ÔÍ› áàÐüë W€&Ô ÷€B¸ðÀ`ÄÖÒ `µ¶uÂþå¤àdüëâîüï+(ÜõA Àú·&àAsrð@ Vx@UØC5èƒËÿ‡Ö&—uwpP5wü+ýßú?÷掶ÞÿstvwƒÂ*0îôŸ¡zÐÉ©@!¶îŽÿy«àfî`k)ádíp‚y¹@¼ÿ:·u•µõ‚BÔmÝ,mVæ®Ð¿Ï¡Nÿ4yèßß@eU]MÙÿ=Ú¿/ÕÍmÜ´½¡Ð?Ñ3ø~hÜÖ `âÀϿߌÿ£˜Œ“% bëd àæã˜ÃáæÞx ‡TÜ||_0ÀÖ õ@½Œ\N0·‡OñXÁàxÍõa4@ó¿ŽþE‚ Å?$ZþñýE0GÇ¢6„ü`ú?ÈÏ ZÿµÄcø'„´ùù@Û?ð¡„ã?~Hïô>¤‡ýùÿ±{0w~X1Ø>à‡bÔ?sýù@·?ð¡îàC>?ðÁÌóä~0óú̼ÿÀ3Ÿ¿ñÿî…¤$ÌË—“àäæ{˜ˆ› Àòÿ_–îp8ÔÉíïïa»þÍV¶ …zA-ñæg`–"!vIµo 2ȱBL6Wš”/!C­¡Õ)"\ûË"dSðºQm(Ý i(©mIâ¡R bÅ·J]+á×ë« #í%$gËIÕÂ>²Ü72AëËêé vÌÛ™§ßt®{q´Àx¾âÑŠY¦¼È¥> Ç(˜¹;EØ¿^ÇO†0n%âg5)'@uwW¢oä`HØüç>J£ÔóG¿ç©;¾MØ/¦Ed© Ïäÿ4”+K8b-è6_\Jîò;×TG¥¥Þãwª½£&!(´ Û˜žŠv}ÉíÈë‹X’Šé_‘F ­¿¥È JžbŠêöŠ]ê~ã.‰£Öšiý’¢ƒâ%]Ä…éÎÏéY?|ÒµbÚ¡â"Û¸ãâ°¦7§DÅ™Ñ øìg~,/‘@ÒÏ_%aÕ¹¿€ª6–Fq‹ÁzºoÊB\ÛÕ½–¦6‰˜r϶Êd;xGõÙivO3ŸæT~ŽçÓØt{Œ(QIš~ò3?¥ZêÝÚ]œ0·ð]^£&ïg’jg#< ˆÏ¯Ó-á 6nÂyk-Ë´Ít wNò{Ë£$ß‚Œšj€PÇ«z[-1W"ôïÏî}+¿ÎûóÜyV´ ±›Up\ÝFw7·ŸâY‹^¿~·é÷]Ÿû5H—@0IÛw8ÀØ1TZ§BXÅ5(¨Ë駃AO<ßRHÅD& ͳÞê÷O¸§`%1Eé È ½5ÎÙiïþå«›ìÛçãèÿº¸ 9ptü{¶OÀ§¿&%ç<êU¥i°%½ªÉb!yš»Íèø›Ã6IAðô Ï€äÚ&ÔÓó÷Ë,i ?9´/1æ¦ÔRaS,H¸Z›ñƧ‘ŽMœåñŠqŸÇÙš Ô.­ý~èj/82çJÊ8³RG7±?çV<-ÅEŒ«ÕËñbYlCØ yÉFq=ÓºyíôÂ]µ¦†šfÍ 2ÖòŠŠk6ßPÆç½Rwù-¬…e³4ͤ±Ã—·E_[43*§¹xp‰³‘åýn hÂF§=i£¨²ˆàòïm ƒòñü!qRó”}€³Ï0“IÏÄΠ¾ñhÉ—Pͨã®à¥½­£˜Ö¢/ùZ¾#/?£ êÏ¢’›ðJó¡T‡¾D±‰•ÒKÙq†Ó,)¯ØèŽ||sëüAQxBëDjò(Òô©wþpíæFrcO Û‚®² âk²ÕqΛúíêúXÔŒ5nÃ+¿‡ï-§)¾'ÿ¾oÝfĤ˜¡.å…«7³NÑ!£iN4Å_×…ä3ÑÌ9´_ÏjéÆI¢Ž”öwÇ¡<‰ ÷àï§)ˆ²Ó]£zl{F޹°\JñJR ØnÂÞÖ—ÞªXyÉêP ­’ðC¯wêàöד–@YÏË…˜ÃËÞÆàh-îëž3L&†©3ž×èðv:Oë;ïÈhSùi°ÂÙù9e ΈåÆâ‘7…í»Âj5q¾úDMVòø9åÚ—T{`»Í=ý’cöœ2âï>Ñ(ãKßwf¶<ƒSí좧+ê}ÄI$rñ3×}ß“ûœÏ ?ËX½¤¤ûôáЗk¿e%ÌiÑcQ®nY5{l5 ˜´¨8*x_œQwÈÒ“ÎeŽu°â˜§!Ä(©Y:JYó²TŽfn‡<Âj²­+cU^¢\­.)e©5çå]Ñÿj~ù¦Þ%—‹ÙxDÁ™^‚xu²ËZF ˜üO³ólSÔU9Ú<^3H‚J?Q›ñ[Z™z©'ê* Ô‘KíƒÈvO1K ab {ÁY:wþ胎»2Ù'csly†DÓP¡úÑöºŸ&içªÆ6”[í¥‚Á~ÊÊzOEhÐ7Ãצ’{éÎ}(¦ýpu%¨?ó@3ª3Û‚Y­,½§ÓÄõzKvòE]:u2q]ܽ¯ùäͽ8n%zy=‹è˜/ûÝ5DÄܙЋ ÈŸ=“ÏÑöÑŸsG½ÞöÈŽÓ®.Z.äÝ®o\ØI¦|OÙ·†áë–a<ª¯ 1Á÷{–÷^N˜!­T÷êiÁ´+¡ä)ÒA½AL}îùwí¹[ ÊÁhÒôÎ>½U•‹6¦óċӑz®Ç}ñkã'hA¼©A¼˜ÞV ±Ø~» Âh¦R©ûEÒÀæ¿3?jâ(ÆWÛCàîîRÒ´€DÈ †;x—BÚ¾C@X[*5æËðAõ–"Ó68Mº&ç†6æ‰XÃjá=ý)×öN© Y}Lßý¿ v ÷‘“´ŠDµà[ü@=P1Ò!§w«´|hZníêfÄçý-wsAÕyX¦8QúN‘•ŒeM½ÌÒ&òÞìýq"¡–{K£A@ÒWýìg°Š0õX½– Õ×ßTÆ,ÓJ=b™b”K[—X ©<‰¬ÃðÏeíMÉÜnÉâE.U¥’â6lèD:R¯´ ~šjN~( ò±\ ›­2©^9)6ê6õEO|.žïˆA Ü Àx“;ÓìYòp€Í8†[ÓC=¶Yß;[lÁºi\?¤ç«Ì||4K£ë”mAqÀ(Üã-ªCׯ·š²3ÑFÐÂ,vÅÜl+uÌ|!×Vz­ïÞ¾Àk»eD¡>šO%[†5N=h¿˜úM¥êŒ×Æ:‚ÿè}¿ÌªÝ–.›ý’*[ññ$!jŒŒÍú®ùøÅG4õDq6“Jû ®ÜÉÒÞs»éŒìCªqÓÏ Ÿì`ˆÓmâr½œ÷¥ÓÖ†m2¬p‚†ìwž…˜eQ.µ¯Üåh0!)Šx+?V4i‰ò›¤€óÓÉQ‘õ¼‚ÊâJm~£ÒÂ}–'`çÀùëßô-ûh×Ffœ›!XKuty¿>Ž Þà<Ç…Æâ…w÷g¾bš¯ÖsG¬ò³Â %¶tlAY@mÛ§äÁ5¾V«í-Q[«üB»–Y"†óFLTm:' Ãå½yò6Ë$æä!Ÿcÿ–ÏED_O¢§Éa‹ÔÒ4 Žç£Ïé¹RC“êR':É®ú[4S¿ú×$Ü­»—#ÚÉ>Ôðå¨hÆâNgòàf‘+½€,ٲ˨Í|u$@ õ¼: ;Ò_¼éïÖjl±·š ôÝH0â `ƒËõ½ßŠFæ^%¤eã‡ñ+ ?ÿºä3}$$˜Ï²ZYP2kåS¤W^XûüÛÔ"4#„ÃHÔï{¶E‹ïYó‚Xz›óˆ,ldï²h´Á(âv©çiKÎþjn‡‡˜RC'æ(ä}9)á3ãê>‰>vcH‚D|üùùþ’óR%Ugjž6]|§àØç_òEg/öþ5Bí-»2ÛYW°íªQ¿›µÄP3´yD¿P°2­#ž .Pg:Ì!P8ãü…±==”úúbY¨§ž Yo¼±s£ˆÎS7OH·‚zfùšn™ìåœêÙ®Z}–¾„)‚ÔœZvDóúõØ9p.™Bž9kË•iô6“è%$õëgåפø¡œMn‚3 fÇ”ÅE«¹Odá}Š(µ:_¶ß–ÛëU[EðEr³=ŽÃÿTëŸÈ­P¿ÌóÁ$6SêÊï=Ú(çõT*^‡&õ¤ÓK^C¼ÜvQB#ó÷’aÐG92oŒâÓ´ø¨¯n o)ïécÜ᪵Neº›e²Gd?)ø¸îD¡µpçÌeM럇s=+»tÅ^KU<Μ[ ïù’>ˆÀÜ=KDø{6‚1—®ÅÊ3XLdÛ÷ÛfcZ$ˆ,$£Ï­ÀÞbH†Ò~\;„N¯*]øù²'4Óå1ÏœxÚ’ŸŒHS´Bï}?ñºÚÝ9õ±´záMããï»ó –¾w®¸L6Q­Ç‰9„Ô$’wâ›ã}Cl^ÁÊŠ˜¾³°‰Âüé“w„GŽ6W F­iê‰] wˆƒ²º’–ªû³€_KJ‘5ØÜ%K7ìzK#+fé¸T^Hïw×-âôÛƒ‹×'·œMë6]Û¢%_ô84F*gXµ©°fJª-½“mRº³k0ÃÞ¬£„ý‚‡ÿ<‘nl9×Ú¡û‡Y£ªÇôÊ©õW&ÍKÈæw®g ýBãdù»ûóC³¯~âÓö3.vú^èáãqˆ¥€’y­µü(§:ñÕÝÛqis”4uÝ5h"Ô%^-'YÍ5É»˜®0å‚LY{Œ*òþ0õj6•÷ _PÏw‘|³*àÀoé¹õ•éu?`=mÞä–Ù…Ùs]‰ÚmӦϭîi«á²è R.ëL6Àa ÎÝ|pzÍ‹d2p¬î¥zeϬª0'%rÍà9º\T•­vXðmÝ}J´N¶~“ÉøE+âmnûè ¯¥‘©Þ;|6•)»6UÃZÕcœA1ô„ðc2#ï7!¦Ì»>Ø‚íí?¾§³ª±šv(©æ`Ö½kCÛ¿úREÞ©I—EÙ3ë±X²œ IÏüb+Î’õÍØ¶¢½†˜°G,öØÞègTþ Ë-e; endstream endobj 482 0 obj << /Type /FontDescriptor /FontName /ELNVRF+CMMI12 /Flags 4 /FontBBox [-30 -250 1026 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 65 /XHeight 431 /CharSet (/a/b/c/comma/d/e/greater/h/i/m/n/o/p/period/r/s/t/u/v/w/x/y/z) /FontFile 481 0 R >> endobj 483 0 obj << /Length1 926 /Length2 3510 /Length3 0 /Length 4126 /Filter /FlateDecode >> stream xÚ­–i<”×Ç£±–ì"䲕-fc¯,BÙRÃ\Ø1ö%Éž¥,É^ÖÙnB¸É…’k©È6d )þS÷s?õôû|®7×÷œß9ç÷9çzqI‹›[ÐE“œAC‘r¦ÓôÍÌŒÕú+Ê.-­OQ,‰h€¢€šLCœõÆpeª¦©ª¬©ªÂ. è“<üÉXW7 £/ûC¤è@2ÖEÌP7@ïá‚ÂV$,HñWtñxÀòG…` zd­Èƒh¬ p]±Dv¥–Œ‰ öOííñoÊ${ÑM2?mÊt“hï A »Ò9}H÷òÿaëÏæ†Þxü9áGû‹ú¯4Š€Åûÿ€Dðð¦€dÀŒ„ÉÄ?¥và?ÞÌ@4Ö›ðgÖ˜‚Âc]t‰®x8SQ„ªüÇzbý@´9–ââ`Px/ðg$¢ÿtB_ßOJgl -ŒÌåÿ9ìÏœ9 K¤Xû{€ô—ø'Ã~1}Ed¬àU„Bat!ýù÷íÒ³Î]Hh,Ñ€«"™Œòg‡Ò[ÁUU@€%¢A?ô£VR$’(ô€¾˜`C"³ÿ¸ª PBþý$ú™”P¿HPrþ_RÕ”\H¯< ª (aCºÿ aP@‰øÒ'‘~C8 äñÒ[yýB8½Öï7¤×úÿ†ôÚ€Ÿøß{×Ó#ùž€«'àªÐS¡€š*4øÿ]¼ÉdHùùiÓ¯÷/c°ôƒƒ èÂN!¹h…»§ÕE–„œÉ,e’õI/ïo‰¨M×R\˜Ôâ&×XƒGW¹#¸Ý±e\·—LÊ•ÐÕ·BuºAÝVJo¸»9ødïeX±,»,8:1öävµs²cf©b<êå—G%7¦|Z˜šÎÁÔò„–b!%¯G¾¯…à®>{K=p-ùñ6û¥Ü&ÓTÐöÓÔ;¯‹HR>‰ZØsØ1cƒw—*Ô>ñ7Α®q#×lÿÈýäÃÔe™’NÔØøŽ  KsQ¡9±î;¿Ž&×ÁRgž÷¯¨7½®ÆÃ *!ãú·z§ #}ãÏ>tgX:±Ó/ibÓ ­ðêX‰ûóQ]À/Q¢j0—/-e†0ô@A^«k·3Û™¤ôª"˺{3Ñù ɸ¦ýãŒÜŽí8-ÊÀž§D¯íìŒàЮ0wÉ@n©x1î#Sÿ2ÔbZfS ä:]ž^¬»Šì e™‰ ŸlM/½ä]üòù‹y×õ Ô§ÇÔÙQuۉêJ¶ +Êû§N›»|›Ük„Ã"_{*J"EÞ¾ÎL~$~.óËé6÷)öïÈŽäD5Uï®§·>¢'¥fÂ&;Lìæc·ÎÙ Û²ÀÍß(˜˜÷5@¤ÃQ×Ö†}¹´¬jzgÆôFjø¿f³„¯¼$3ë7op;×Âû>drªjf2…;3:uçˆò_Dì©«úV«xÕ Ëâ$\u>¤qÓ²eÑapÀÆ}yqݺ1¨©Ø*°k¡ ©¬ƒÐÍŽ¢nä4•ùÔÆ³Ê©Ê8ÓQ“¢3ÂD3^¯Ôæ²úUÏÇ"x#êÔQ{R…_¢-Û¤¶Ñp€+[uðÃåšAÏå}õGr#9 ˜2<õ®ý]oRvʵÉUƒ¬ ©`Ú~ï ¯ÐÐeÊ}Þî^D­6GÉ©ÐÛêfžyéH£üîžG­o‰V/?ž¢K-\À‹Mãï43^V…IºÝ?^!·õ± Ö®Wª’ÖÛhr;ìpä“þÚˆÓ¹t—;¢&‚ç¼>»qþâÛ7» CÓFoØ`šcû8ƒ Üê·b¾õ´°Ù*…(ï›d[9¬ÉT{·š»Á/ÔO ¹>g¹ÅÊØ<þ&Sg?™Ecž–ëþ¾Q¹&k?ø¥üpz0s¶cëd+nŽ6žŒÉ¨ðº4ˆÛy·x!Æðr:ã=ÙàŠ…*|®3AEfœÔæ³Ij“ï¸sW9ÚWäóÕö1Ü6´høX×™J#¢8&ó÷¬*Û#ïçžpK ®Dâ7‡Ô$*$³&3Kw*8h2Ôšø=#(”ÖöZêÈ*s±OaqÚÊHÑTpcf¬¶QA+H í2ÞU+^†Õå<»R kÿÙE&úÑ(R_v´wQg÷€!?äû«}òfÎVèë•^þ‡¾%‡ V̸WWŽ÷ûN©!ù‹¿†®K4D5äaFôª©ÚM­"8ÁÒÒ× üw_ÄŠc€|LªcÏÆŠºÚþPJ9Æé‹‰¾ŸtofÝ­äj@­–G½u+¤ñàK¡y«ìf¹¯ŸÇBÌ.’‹mG`«ÎÛHNô°÷K>÷Þ³µ5OeØÚÒ…±œšŠ;i) Ô4Ò™øWá‘ì‘©FùÓ…œ,Û‡¾æ ôÍûÞ=Qëâå±1«¤¬lOŒI…ä§Ýº bU e'¬Œf9dŠŒ“¢VüMÛS-Ò<ôx&#,.³¹Ç™}JÅǼt³v$âd‡ˆÿHÙ2Q3bpr˜sC¤ÔÅ›‡D½œ Èf\•\‚š”®}]‡È¦‘:IK¯½#®ùÊTNŽŽŽg ß© lU}—Ø›³ä‡"\¶RôÍi´ÛiúÜhßÒD!Gf¶wÓIÉù~§•›™dZ7Î=ÓØ°r©wâ êÑZ¯ÔˆoZÃÝ5û™SHÝCGöÍþY§Û[hi¶a›ŒÄ7‰›F}ÓÊÈDÎʶ¤¤¹i:Ê02•GÀÒ1Õír ïw5)4îë!±›Ƚò¹Ë÷ò­¸LC˜ð7’o2—Öì9œZªØðŒ ¤ŒÕÉÝF¤ÎVæ ïÉ µðŽ–qé7¦ã‘²ã—Æ“QnþÌc‡àΟú¾^fá·hÀ»‡z?ô~7®<ötM’mŸŒDÔÜ;ö²Š’Åý ·kåª&xëkDÆ##ß]94E: "ƒYû£ ZXB”JrŸÃÿ ÏqÛÐÒ³eÓ–ŧf1wLúµüZyh9„—.xkOô/HMÐx²˜PÝ{2ÁgßC*&3ÿÊgA; %=)UnZ|ûl8kCótå—êë³ûhÔÇu©®©œ TwÅxÑ'"arV‘êXosãÊÈ”ä-_õCˆEv#ç¯õI°¢OJ)üÉRžïÐX›X•­Áš½jŠ©´õMe±±ÏšHYÛâRÿ\˜A…º.väIÁ$Õ´¶ /ÂsÊ)È?[¢¤?ÕlÜd×û ?ËÖÕÇfm×€ikOËàLü Ä7àƒx,ž-/qÉè}ìq;N9-#o­`±9ùÌñ*(gjí%ø¦äó… 'æíE…~Ì$˜rJ¸!?§ïN·YÉà Ð)ˤ©ÙéLj× eñÉŽ=½ÿ!ñ™U?…œz1H2Ç8íôfÛƒoɵ1H¾ŠŒ“ M²ªvf;ÿÜGgÑÒB>]sÕmX»ùÁ#þJ—ºØº ±ö„Rèbef}›ÓøˆoJù¬èl§:P_Z²\ÇxªÍ*ÐtuFöã®Èén”«›£[ÏÍéžGX+ƒ§÷Ñh§³dø7<à9™©òRfz~ ëÀqDKDfG½‰2¿vOÊu«™òéxÉ ˆÄ6xÚ…„€˜ç‹l¡zÒÊa>zÝ:"| rÞÇY?ǧy"Ìk¯˜ïðùBúsë[gSò>Îgˆ”›X5øàÇi~³ ]­}7½î¬>?Kí{ØàSUÉÍ ÿh.«a8ëËöœ.n.Dùø éûœ´iý'oy=°¿°çý&LÍ`z\ó•.ºg[4—¸ÌJU§bŽY_Ÿ/Ö-~ªP-ürD16áyöë×U½­ËÓÆ9sì<\º9)•óíÈæÉnôj®Á‰P&}%ÕݤokMaž«Ój¢†Ùa"vY«ª\„>!Ì¿Ïô÷6S¡ËÂWFËaÎà¶}|Ũ½Ñ "»Pó•3>1º´ƒƒíŸ¯dW¨0wuµúý –›òäíñ1AŸØÃ”â£ø†Ì69ˆ¼Ò£qV·|¥Ÿ8&eŽ|2Ž¥ Ø}Àä5¥.V–rOh¶ûÙ-äÈËßC( ÌBëñßì­÷’ Ç;r–V¬ÃN¶¿ÌÚ<ÂAð$Ä×ë¼Ôk"3ß›—éÃË¿9j-¿Vexc r-c”…ÒÒŽÊœ6¨åÊ@­Í±>C—"Ø6'îx(Œ"=H ¢Ë9îY•¡‹;$Y/ù ž§jQªÝÔü®D5ݬ'N9O«¶.Âa eU*Áꤔ& ÙÉ 4Ì"· õË}…ï•^À¡’僯-E‘0£|>\°møù‰¾[ˆṳ́æxó|ò‚Zù°K¯~é«8 ùc½ÆD³Â€²S¯jÄùCSÙsZ“ ûŠ9ûÔµæ—U¤ÊÄÁ—¦ýQq>ŒDãÞN3Ùj¶ÞбÔeqϲ2Xu°–ÙÑs"1>_áç 16xM¾)þ^˜‘0çæHïž­6¯{Fó²qÆ’PbáD&¯ͼ·/€;ˆ?TêØöãÉ•ÿ=û²d™OkŒ";ŠZ¡i2ýõ— S²4uŽ€nžL®ŠÑb’¾Çya#{™xT‘SÅH“ÍãåxéI{…äœàÞÇš#¹RòÌ^Cú™íMö%rt––saÎÊÞ¾f=êè-k-¬Ò.{vxó‚°êÂyl„¡YE0ƒEŒµ!zóvBB(Ë Þ·˜ü¸õwá…ù:7KŠÚ.ˆúÀÇ›WE2+23˜.Ÿ0Iã£Æµ‡¢×ËzfÎ)ï»Ï‘UÇ2#ßpdÔ‰é|Ö×x"ÚÕuUkòº±ÈTž€¨§}?uËßKgÕ ÒxÄ,ðmfÂ^óg!*‡âùiØ«jNaQØqfÑ;uþlwcý_`Á†mðØÀ—<‘AvëV¨´iÍI=[òEçv§¨Å>Z\²«—¨¡§ùŠtÌÆ‰¹¸÷& UÅ“ri‡ Ÿ‰Ü^á%Fõ#¾Óº‰„.Icí32ÜJw¬%ê"Ð&’kŠ É•%ªfɆÛWEµ¬»"ß×î™ðOh•³½Ñg,Œl\QA~Ú#w²£o½-dåíé²5ñ¥êðì·L—OlÁÃÓžPZ˜Üä©$uWzÿÒ֬ЋS5—äJbË|„ZÆÛb\ÛöÝèˆÉÈͺû_¬òè endstream endobj 484 0 obj << /Type /FontDescriptor /FontName /EUFQHP+CMMI8 /Flags 4 /FontBBox [-24 -250 1110 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 78 /XHeight 431 /CharSet (/G/a/b/comma/i/l/n/o/p/s/x/y/z) /FontFile 483 0 R >> endobj 485 0 obj << /Length1 2126 /Length2 14540 /Length3 0 /Length 15688 /Filter /FlateDecode >> stream xÚ­·UX\ݲ¶‚wí@pwKpwwow÷àînAƒ†àîîœànÁÝþ~×Ú{‘µ¿Óÿ꓾kÔ¨zFU9¯IþQA™^ÐØÖ$fkãDÏÌÀÌ–Ubf030!“ ;€ ÌmmD @<fnnf€ ³)€… ÀÌÁÃÊÅÃÄŽ@¶µsw075sP SÿãÄ ´9˜ m²†Nf kp  ¡@ÙhrrgZY”þÙáP9‚\@Æ ÌÌcs ÀdjnƒÀø I[ç¿ÍÆÎvÿ»ärp‹PERÀmm¬ÜÆ F9[p.XÉÿ¢þop1g++9CëÂÿS¤ÿgÙÐÚÜÊýl­íœ@Y[cƒÍÿuUý[›,ÈØÜÙúÿ®J:Z™mL­@¦›ÌÅÌÝ@Æ æN@3€‰¡•#è_vñÿ®Û¿$0Jk)©‹ˆÓþ»ŸÿZS04·qRq·ûOÔœÿÅÌo ®Žƒ¹@›‰‰‰ìþýï?Ýÿ“KÔhklnv€¡ƒƒ¡;x2ÀÄðd˜ÛƒÜ 7°`F['ð¸&Þ[„ÚÉÁ`üÇôoâ0 ½'€Qø¸Œ"oÄ `ýq2ÅÞˆÀ(þF,F‰7b0J¾€QêÀZ¤ß¬EæÀZd߬EîÀZäÿC\`- oÖ¢øF`-JoÖ¢üF`-*oÖ¢úF`-joÖ¢þF`-oÖ¢ùâkÑz#ð>Ã7ï3z#°N#C %ÈÉ dâôfgýýßWé? àDÀÿ;8ÐÖ |!ÿ×ÂÆöÅÚú-!3Xñ²€å›ƒ@ŽæŽÿ±²‚Ojlkeeèð×>°6Ð[*°迤0³€E‚o¡£ÙÛ|ü³ÇÞ|¹ß€‹oò†`“¿í4ÿ+&˜ßõtySÁüá-8û?î¶Î‹;˜þ…àøoêØÀÝ5s·3Ùüå¶ý•Ÿ |L‹¿\,Ë¿\ï¿n†õ,ÆÚèðW7˜™ÁµCvp4s›·ã°‚“Û8[ýóT5ý{¸J¶o²ÁilÿÚÅüO•ìÞ–Á9ì @6ÿ5AlÌÿcýïùaŸÏü0¶}›6pÉ쬜ÿŠ¶Ø¿õœÍÞäøÏÛÈØÖõM&÷¿l@ÆFVÿ•›•ímá¿Ó³rÿÏÊ›™ÿ™ƒ¿ºÈ ®Ë›öäòWרÁîŽà'åŽ.¬£Õ߃ÈÌ >è[vp5œÌ@Í3¸jN®¶mÇpþ Á­vù ÁÂ]ÿSðn·¿Þý/ÆãM8’Èáß©þß7†­›'=¸dô,`•Üàç ';“÷ùÀtú×Ë|áþ—MÌÁ/)È DXœ³òZ¤Ô—øˆæO–ÂÐ@ ™6ÄÊÕtþjC Xˆƒ´*–¶§Y­Öxø‘޼ ³KâúDàÞê¥8&vêg›:û²ëb°›îÑD q‘.ë¾cGzp„ÒR?suÌ)?½:R’¨ù½ïÛYÿQ®•ˆÊÞûß!º´]j»2985ÄÒ­TC‚ª)X?*¡¦Ú—„²…¬¸¢&Æ¿[™ð±k¤]>·muFȇËIxѹ:˜ÐÆÎœåеŸ7›³¶23Œˆ” e#‰ÌÎhj~zø™ÉÈ?ÉZO›j3ó%3ÁC´‘,~vxß«ö›ƒÿï™ ‘W†êÝ¢oŽ¿ñä4»yK-· tj+6urÇÍ~?Yë¼öós¦,©ç%åá­¯y›´Ü%×…¬% 3{ë"-ÂŤJ¢Û’­¬3ÝV»®¤ÁèD e–g¦a…÷n(Œ=Ñ™œÄÕŽÂÓ”¾Ü0ÏeÕúŲT¢0 TÄ%Ãúêp˜¯æbÔíí4ûé³oÊíWéÕ$Ký ï­ùšf8•T"±µàÅìOŸT`ý1D[05Æ;WÃN¡g€@NXµ…óBu®šs<ùBÅô%7 %ÈMÿ*Ö,1sÔýâ®\}ö6£©oBïD7U½)Ù;#ylÂqvNÿVë¡ÅÄQ·yÓXÓ0˜=åèNá"•5éV{„L3‡úþOÞJ^yhŸÏÄ©´ý6&[Ñov³b™!2û¢0(|T|6;…çÂãÛX~Ói "$/q©Xå`›ÌÐ]=s–æ"ŽàÃJÈ„°;Y¬TøÞTb¦“D†j´Ê×­€«M—Ö æúÖJ7ad øNo&ÃúËùå)H]™‰€âøsV™ïºféT ij\f®‰&Ç‘îLÖgŒ—[ãÏÕP½B>ߪ …–\²çæ%ïR:ÂF¸óRFåï¡Qæ°úYT"¿9Ïýx?Ò°Š;Õ6Ÿ*ŠÈ²4sïz¶ä U;ldjëeæ!PBXßæw˜ý’±H¥ùZ¡#s½­a!(׋ý„Èn_:ü1¶nKj ˜?%Ç­V¨³BC7hÜ.ƒ…/Fƒ…d×ÃHž¨QŸÔ¹ÈÇP^ý)E6áó ˼¯—d]¶õéíöžFæZ®™õ6ÄBêÇ>x…ù•£¾ ˆÑJ.ÎH<ä£êüy²æñàXú{`8ý`ø4*‡î3Ò­ˆw`5“´AˆcŽô.Y›˜C,zˆ|®VEÂ8<³ÈÆO?»-6Nb!R™1*F+Õ×Ô1“¹¯©95\ßg¶¿¸rO¯pq7—Œ¶éZÚO~¿Ð4,à ێ…§á,8böStAkHx:NÙ=ÒCЗҶ+ŠåèÏcíAGÊšDo ‘"w¯QLqoŸ”ܪ]Žf¼íÉe87Xýv*o{ëÅúÝÒ¯y©½!&ÂÐl§ê?Žp.î£4—{¿ôý¹CfÕ{9ä†0ŒÌúæ­_çxFÄ@Òjé/ßÕüCXVÃê›æ÷”Ëð¢»ÆøÀmJ éVÆ3äÝ€‹ÞÝ;“» *Ç,‘F:b:‘¤¾3^ÅüàçµU‡Å`Œ5£ËýÛ¯»¨WKÒ¶–&h‚X®¢OgI鹡 wú?Ó»}øâ¥üœIMt†Ù5:P™Ø IgïÝq‘ý 9V×NéPK~Í0íøáb¢“@æéo;YëK¦» #Jóm.# N®¯Ž±m캵Ö%O(®«Î ú¨©À󻫪•ô„{‹Q5g2 #ây8ÉòþÖEPÒN ŒÜE°#ÏbÍa%ˆH•ÇgzUÑó¢â¸w¨±±5„/UìúsK#ÒuœÁkJÐõ®Gê¾×˜9ÏÿüW8¢4“3e;D%fA–L UbŒz{3×»j.™ãïŒ,vCæè²—ç§ô42­ÛxQpí¸‡‚¥TÚce»¿>m¿ËdüpI‰‚4ÝÛ$ƒ…سIYpÔ—;(€þ;—qìËâî§úu! á•nð8“'4™½=…éùv€ø¨cË{ÿ°ùøo®Vjù$+8âõe8÷–”9X-–Q.UOÇAÌ„ï»+Òü8Œ ëÞ7!ÛN"¢!Ñ-ܯýÊÝÝMÈŽaO ψokŒ?ô×ÑYLêB,m¯‘†ªÝ½¼®0~È Úˆ+ÈÎ8 œ•^ÙàGE8!å]?ä/ûå(»ÀòOE?þbëËZhù~϶àˆ±¦¼~÷Å·¶4[Ä¥A)ÒÕÕîêÁ‡Á?ô»²€‡pDQ&hÈ•Ôb€üLä»4÷ÕÒ˜_žg’Ü ]ÛTA¡cÝ2À¡v|ÝtPHÖ;«G¶„F¬€ãém‰¹pðEH’ƒ§6Û“?%æ“e~ ÜPS¤ÂëÕÉíQý`ÖµïOýã™–FI*ºòêš:_ÓçVJ@s‹W-Ž^Ó1ë>qæ‹}=Öe:èyÚš‚Éú÷¾w6³¬Öi6PhîU6%ág9þWøPX´ú\ýaß%‰ ºp¾Ý«ø«ÃªCóc²Ú¦kõj6ÈÛ¯Y¦¹”£Àå*Ã£ß ã…Wß»è•c>þÑËÍÔã­ñÏ=ý!¯â–~üHW‹™Ÿ2ç¶n¶ Òe€ñø³y–û[謷`¿bçfKÓÛ÷ÙMŠä<±"TЏJBù%~²°TMr|ß ‚pp¿„£©¦Oi´ƒìÐ'hU™b²b¢olý僂Í0ƒ‰þ¨¼=¥Mnj-Ä¡m‚\úí%dù×Þo2t#|Ç"a/ž¶­éuT·×½”–Ðlªƒ˜ÍÀ¾¦Ú,0ïî, "²±–hÒN™ v|¢ì:?„™-Ú ÙL¼Ä…h@p@Ô7Cø|õÕS´8_„~p¿Wy"´åW§XS­ï·×ÝÙ£4ÅN¢‘ä'ßá>g‰Àðœb»~ £`™˜Gÿ&°!ǘ߽Zë*‹‹´¡laô…ù%+&Ñõ®Ý©oÍDÿ:%$Ñ÷9Ä(Tÿ° ¨nÊ…+&×õÝyu‡ ûzÄX?wÏëê€Ò•гónçÕT5>bº\P´5» ‘4ú5× í4‘d?Íf{ªÏÂXØDƒG×sß¡TȬ½ Çã‹Ï„>ÒÃP”îSòm+TRÃ{¾þ¯Ë/§<ò‘ÓÞ*Új3”*-5âW¯Í-Ú`/WnÅœ{®5m­1wµË,Jœ–œ”{‰»pßfíÂÊ—¡ôOŸìÅüI[?PíFýZ«ÑòûxaÐ*ÀäV^—]eÎFƒÈ4J2Q€JÝã[•„Õ²m œÒÑ/j÷pªû|ÝDˆÏâɯþgÃþg캛) K‹ãÞ <«ûØŠ²r±m÷~â ¾]ÑÈ…. ¬ž£'iÙ“[¥{žRÝÞ'7αãLëÁé¬8ãùŲÏYònŸar^w·’¸â2làS‡AškÅì'Ô‡¢à÷%d¹ŽÔ¢«YtD± ɉš‰Wéô0pP>ÁBž°«Äö)¢‡É«8OEËŸpsºìÔŽ½ØâÓ»œ¤7̾Դο}šPé„5»L}èŽCÀgM½œ¹)Q„õê0òQÊvôÕEy^³ Wx½÷dˆ1M§o]ðìQ"ŠÒNBá®tÚâxâ0!é>Vh-Èáô¶ÛeVž_‹ø×ÌQ(j»¼rxï±G,šÁ~%̾=âú¹{²(áÖ‚KÍ\²Þ+ì+$S†Dãï³¾àî&s»™ôÊ&„hEí ÈSùæ•é¦Òúw·f¶©øÑ¢Ò_ÂŽ’A¿li^<á¶Ê$w 2Èb8Éýê„Åòhð‡ÃyˆKì—ó°©ÝžT V؇ޙÕæ-©—{ >}ºb¸=éi³¥oTëyÑ´¢ÈÊQýè̽LîloiØtj/„p ÒB§©Ï$òõ§·+ Ylˆ™*Xqä¾ûC­— í€4eÂ7Sþ%+)Ì )Mð“çÎeFœSë‘YxnEõíH,BõQ^È 6é\ÒìÄ#t&èŸÖuùclI Côå?&÷^yùOA’ ~…Ò布•ܺÏ~=„ÃÔûŠÖ‘4[UéJßGiÇíÁþ3yø=G-žoœ©žówþÚOd‹.Ì0_êIl˜—×â\ÚeÛŠòe Ôú+/Oó”:%]áyÑW»‘¦¨‡=GAØN¥÷ER˜„>ûÔþúÚ¾.›Èn†92 (–;Ê¿£Sø6‹<´–¯ÁÀtˆ4‡Âötî¸F5¨Ò B­Æ¥À&Tk·×DæÁª:šXO|öë±}÷Sn6FÊZ·ÜM•¹ŠËÎX}*_/Yä––‰ø‰‚´}~†ŠßÐvžPd)EZœdqÒyìÛ ¤`…e+ýÔ†ï 99ƒöaˆ¯ ÓŠ‰…ꥊz{¡E*~OË+ÿá1n˲ELèäÛ$usÞd ï#þ#€h"HÜXN-@vGjS?R2Øê˜ÁêB6zѵœúzÉ­ëENwõ£o ÜÂaðYBä'ïg÷DÖIÌ /Ÿ,[KŸ£Å ü Ønž60{>-ü¨¼2öa‰ìþš£ªwK–¿õš³Ã²ºpGÄ qW·2¼6}z'×ϲ#Œþn%J(<A n ±O™Ë}õ< Ü!ÚŽ6: žÉYÏ\wíÞ-‰Ù[ÜÑya'gÎ3ŠÎÄÁ>ù÷I˜²[z3ƯpG€ÇKLyrùàÆ GMË_™óŽbLjpîÃÄ °õ\U’Ïöî:û,L—ÒÂH°¼x’–v.zºN–)pJþçåñ”ļ.á™Å!ZÌl¨rÿ ÙŽ ^E@j Iý›¶@éŒN«ßJŸ>̇o‰- ËøÂ§÷ÙÙƒ˜½Oî #lÝ:lÒ»wètÆ’ï"2áøM–BÆ+n»zTE z¿g¬=À²k}KŽö4¦iîÊŸúøu÷½ÞG˜Ñç±RÜ¡^½¹%%ïÇý§lAõE Áªú=4Ízågj]ê,Lmõ¤¶BcýÜ+çˆÞæ¬'EÕÊ£2“Kê¥\xcp³€1Z„¯^w'®8ÂÖ8©›²<øÔˆ!'<”qãYhÞÇHSËžK 9G+Oòñ*L±e™ ãàL™‰ŠO¬HyÑVq⌛üÜ<“|gh¸ï•ÀÌOg>½jm.“ÈÄ&¡ý¾·Í+ر!-+|µ¸ÐDk\k’gìòœe®àRÞI/˜I–¬Ž$3¨ýé¨éÀ¢¼Øªdj#,] kb’ç†ûÒ&ü²Íªc,¡ä1oMÒ ÔíÇ¿CšÉÜŸ-Øvß³nÀ­©B³"|ÉH Ò­’/YÕì(6Æ‘J™xOj;P¿];ðÞ.U2œ¸é þ*š{•Y—[CÞ&jØ–,ޠβ–K‘+ˬÌEˆ„öóë Ùªq(õ/ÛT)Y<²‰zÁFXáÉ4ÁÀfA •4óh¯s sTݾ—ûs‡qذÈ|—¿$“u$öIÎ!®Z•…Ëk;ñE.ϛڽ¡9ž^fõÜgñ•Șʴˆ1ÖãK/£D2ÏÞ×åÝ0“a1Á…uœNfÒw6ðÞÜ“ïF‹Ì´äÆ¥‚"@A×°‹žÛ¼ÀóD.Ú'ÖfâºèE„Gú"¸ŽL:¤ÕØ“ö!ùˆ‚©âÌ“SWŠu5ŸO9+–ÿbßåpBùNá7}S©YÅÃR=“.m}ãâ%h ÁÖk’’\»áü v÷j¹šôËJ$ÿ{6Á,Œ}œk}Þ‡O[•üçÂÃ'ý¢‡}ÔãVÐr2ìŸâÌDˆDZªdgwÑI"NßQÃ1«oB¼jü,LñΫó•i(»ùÞÏþtqÍb•²Õ-/Y&¬g›¥Ë~z‡ü5 Ž©±‚´‘ì£~³3°§8äFˆ‹Gy-ç[›÷Ë‘ÇúÃÍ=•³lÜÒìtð„K‹nâzë4>¼¹a¤¯÷¨ÁǧÚî%ìú>º íå;˜ÅˆP§ôïwÞ¿ûø»1:ý3á±eƒF:s¤)?ÝlÒ¡lãÐÙRÚ $ü’S­OF|êg{1d_2ä4.¶I³®âˆ¨ÎÅ!Ÿ b@Îcåܾ2_ÅL¡*‡$Óݘ¢W¤ëÇõ¢ØKOF¢ù =„×φ¬÷x{ùË»UxB?/Ý7.ÓðëŽJUm÷á{%BôI}øÈ/™ò$ÞÎ’9«…nwcÿ¦åªÚÏ”"yS #©sʤHÄt@;’£1®^äØörô‘ÈΡì@%}NNÀÅçñ¬»­Ýc·U5*èÅt¡°|òn”(n’Ñ„[zí,J•W‰uÚ–K_µ~Y¬ª9We—šíŽòŠ}ña KŠUOˆ R–›‚‘M¯Ë Y~©ÊyÚxט}!©JÒ\zÕE¸pv^åj¹rÆ©kî…é{OOöHÞŸ++²“˦œTyE°¿’¥!?›™Œ-´ä½ÇŠ.6’¦ØÚî$€0Dñ/ÍY–L^R漈TåñÖÞŽG}ðeî2¡w§J?W<µ>”îs€X\½pñ-jßçó—%˜ý}¸‚°,+¸eüè$<Éü2â*Áç÷ÝöE}WRºIè󙊶 $ˆ/ùð&Ùá~¿Æš™úÕ¢Ø6w´éìBþË‚yò¢µ1$uØœv ƒ©³M¥›”•Ê[búñŒCo@ztª02zÊžz¾*ÓÉPho*\”XN¨ƒÆ¦Éµ†ÅyÎsk@)Wv»P´ÿLI!¦aWõz×Í87ü4ÁÞc@T¬é˜ý€|`Š.h|­ï`²·‰wâÃíšãÃë·ny…æ{Öš yØ‘{•˜@YÚJ¡ þ$ÚXaîð?ض»Ì³9Gvá'Zæ(¿#:~š*å2ëC–|ÜËÀ*,âù¤Ý2@’>ÊËûNkÞF! ÈÐ~û.¹#Œ’J2,Hgy¡Tü&qd§f@n¥æ *~Ôu¯¥;kßg£ªÊ(L}*Xå¸ Dþýý–F-ôMÙµÒö¢!‰ìywÅH˜Ò¯U ô$¾ƒñ zN>ÎÕìcÃøƒI‚²™úR ý?²!Ÿ_tÎuÖzPƒº¾¬ôéæøƒ¸¾òîÞÓvÛŒ¨gãÈÙ“øŒª£8qŸ;µÕFMêƒå—±Y¢q‚¦âÇòÎr¥Úëàh {Ns¶Â^Y ]ąݤ)Yp¸ç #"zU«e‡¨>rèëa%ª™6¤FŠÔ±’0oÊpÚ×*/ Ô‰£,” ù‚”g8›m·ËËP¶§Ÿi”q·öàš¹Í%Qu_„‰tV¦•¢®õõ´pZ1ð.ckÍ!ø©“Çø¨xxË­’(MMâ?]S`q¥bbý¾.AÇ2˽r¢‰ <èETmÇGâX30-àÏâ·æh6úé+3—Së NÄQûG*Úu !>=<3©O‰»~þQâøÀ¸AŇþRl ׯhÑ’E?|Ù}«Ý„¦Ä“ðúŽH¬$±åxüi¯®Í¹婿ú²ªÆäû…â¸"í®ó½tiÎ…ç|©åÁî®A*$kZ¦%On „/&¯´Æf¦Œ­×Ð#*<¢—ðË5!Ù”î=åË;b¢$Y¢ëŒ/çèþ˜:B:®„ã”Ùº†ß×¾q rîØ;»W­ Lõzè~ÖKÙ2†”ŽÐÚ“¦¹B43мÿai-Ó%\†¢Eÿ˜Öz§vL bp“|ÕУMwL´([ÿ½™5NïEÆvšýåt’m,~3ù1?MI 9ƒ–U-‹+<·DйÉÓ+•lON‚îˆù&~åx §Íu)e'a‡y·=<ÁÖ)[‚Îàò6árÈøn³Žf·­OöÑjÿY\ÉçFpÊO¬ÁÃÌ!lh}ËmáçìBWçGGõ\äœq‹¤Ù2¯'÷N-ÜUóföñO¿¼­b²·‚Ð’;¾,Ë©w‚T¯_ÂÎGe¡`ßãåÞõUÁ§¶¾ÚÈ63:7*ߊû“áh”H½ú³N¯C%8‚–¡?xèã8m?¼¹Ú@ÿ@çï˜1We'G¤ëòXî[ŽAÚiDRV?LV?ÒèoÈ™¦ý”ñâObx!§Öª“D¥X¶ú ƒX’{ùizz['0HB~|ÊöTÅ«Ë{dC*¥Åmÿ„9æ–… äÆö]µñ9žÞ;7jøã¸1ІéÇ‹K>Ÿö½WGê©—o5x*.h°p“Ÿ&Rˆ± ;›SÑXRQ&iP°Uú؃‹xH· dË|Dê{Ä És Çâ¸Pø`°ò õ%Ãcš¥±â mÎyÓqaÃYÅ[B bÌõ-?˜­Ê3´D%¹ÎÛ\¦>.ÜÍ\iÔ<ÇQ/k‰q2Ï’·%<­9¹8¤ ¬rÌç}7¨û¾¥]¤¼º¹xl%™ÅåŸadcuý Üö튥iE³…µaReü$nœE1k³¬‡cñ©ñâšÛŽÝÞ}ôvüÜ-ͳsà_6!s·üÛJ`4¹i+,VV¹žÞ‚}.¸Ø'—“¿žX9+IŒÃ³t÷¤êàû1Œ_ýÑ ãI7q}¦°~ãûRF¶™â Ô¦"‡oþ¬~¼ 17 ^Y¢l¹b¨`S‹…Í‚u‘éñ[p\UªÓ†³/NÜ[Ap­9nC¦ï U¦.ß/P¦š¬¼Çæ¾ÚÜ<1´W0Ì^kVö™€Ø¥N±eø$Ðlzeo÷ö4æô>ÖtÍzó¢uX3Q\ŸçÜÿDMƒ÷>ÁšUÞ•÷·!$³~a¼H°QHvšøùІÓÒbãÚäœ5Á+»µi(1f=!™écRÃdWléî CØ‹÷ÙèZeü—›çyáÝø«Ìßß©è/F׊U‡¯ŽRRà9† ‚¶äŠU¥¨`+.±™|ç9‘GõE9[•=-?äÉCïúÑR„M³:·ØtäwAþø)LŠÈÀØí‹KhÔÐ凨»K–ÀaJ#ƒŠ¹•ë´&AlV‚j£67€üšwoϲiÁH}láò$31Ò’Ò2fh0°ÝÙ'–½ŸÈwd-ûú¸IÉž™[G†f̾NžÍa[evß•À.2²2ÓFðiÍÅãi¤h/5‰tÀdýÖ¶«ŽGàƒØ`Ù|bíOš/ÔŸ„ÓÃ,ÿxvQïÄ™¸õAÕíÉÆÕêÍ»ó§Ô«ŒKX†õû$W,òc|*qat¾É”QµÑ糊‰JЋÌúZJêø«ˆúÛäò5}.7%Âä»!§ßh_ Ÿ-=î´WÏß9a™iŸ³$œ’µ›Ý|5¦Œ¢òÐèo  bÿíáÉ×ýéÕöÔ{Hvz_%)ˆ&&ʤRÐ0dƽ¨g¸€OOáTä\éñ(ÙßêÝA¨SSðaíxÂÊ”È;ª}!œG:¢!']Ê´RTžêaµVäº(¨€0:N#Í~çM kÍ¢FÃ¥PÐCfÖŽ4¨ÎÉ\;„G‰Èß=ðó 3ñþ(æÒ͵{ÉÉe“¥ÇC­ÎÛ̹Ù(Âu|ç_ Ð’F˜Lþã¢¿:o‡þ C©EUùy<÷ó–ùù-N&+Ð¥‚ìÓ>&¯\fÐ/‰v±¦NÛAê8‘6²C‰ó¶6ˆ{¥@’Ÿ×ÊöF¬älT!‡z”dôQÌÉc?)Ëò¥ÁÄJHžVo4S‘'“ü‰{'®`žŒéx¶Ía®Ï Á‹°GÀV@}Þö~ùƒ¦ü¶K¼]»ÃW¼CI¹ÝM§QåØEC_Bvd:úŸêd¨îAÎøìÛ/RmæþµY 0xJš½q·ŸB Ä!?÷]ZjE£Ø™³{Oú5í–¥¢ÊP*a…„~›ÿ%=)ÅL£S2˜×í=b’0@ƒÊÅi6 ¹n<ë¬õž'Ðï10Ar·jãAžùY±ýðF¥ñÎpR…Õ—,ÃýJä÷¨7ÓB¿Æ?3GnÍ|a䄯ëت¹Ü å«Iâác>çL+aÊPž :ËY$rº…?,§X­8@Ø.üøYuH½Žã‰³÷¡ß†ºù´TG×ÝñsQ…€âyS1mð‰äÅÙ:±ÕÓKàôˆÝûw¢pT ÂNlžÄíî{eÔÈߣ<0h6rª{ãã¶Ÿ_gmE{ócz+%Ó6ÕgÓ‹‰˜ÛX×¶Ñùíš:~“èÊ·ìÁ4 Êÿ¦3®ÓçŽižîµ"׉¸ž.ô’!Æâ‹c²Ænî¤ù0–•,Ò°Œyf˼[\‹Ñ¯n'g7}ÞÎJZ,õjÙ#ŠŽÀÓ&Ý·7!Oï™i‡‰¬rAËyÏ>È‘ÁŽ!|c†q!¢]oQ:²Ó' D‹Ë±ÈÌM Ç@“ ¤„ fã¤J]Àön²DqÌÝøÓ´;Gæ7óW„[¯û tÚ5L÷×ÄãÄ2]3…kšDï„%ýžèaó‚Ëá|ÐäGµ³¨|õKÅyž•öÇŒË'¹À/0”PäµäÛ''ûøÏ&©g¥QZºÜ¨{1q±KÍ„j\­rI¥[»¢å§= juË?cyÍEw\¤ôì<, ]š·Š'ÉÌ|¤6R×ÃÐ.¥fŸ¾î%õ§†[íyoR–u«Ë îþ“´S­?Ï»áEì3å:ðf0î D'Þ)Õ}ÈXõ0ʼ‹ñº|-M) $e’^4…[7¿œ$Ý÷ÃΚœÊ-Í­3ÄB….©Q®"¶6©MÓ›Ðdc¨iºIPÏó¦ä˜ìkËg¡”Û:ÊŒkaUEïÂNÞÖ呿VÛ‰u`ŸÄI†Ê—B@¶-ç=Œ‚œ·\*œè±foEÖœXŸD}×VóäsWDÙ#úT¹ƒð|æäý=éq$œÂ÷ˆwh7ò¦pÂEσ¿ëåL7hÞcA{Á4ë¡¡¢%ÞùñÓÿAþ¡}-\K—Ë߇ ¾:M–œ>AZÖÀˆ×S¯HI‚}Ò%åÝ€$Ášüð#A‡ÀT‡x¼Yµ{˜ ³[¥±ÓÂ|ÈÓÑ,êL¿<¼m‹ÁmLQBõa+ÎÆCYÿ\ì~0lYK¶¶Á£0DQ>W@梜Çì•Æ·Â ;µøÁnß5ÂCñãtjìš[x¥0¨^—­JV‡á9¯ËÕÂCad»Ío©çª0(ÏAùù,Cõh„Ÿ°`Ýåg\§ ö…¶I cW÷ŠiÉ‚¦~*.¿`ˆ(2’ œÕõ@LFz>†òüx¼â£¬è;Þ©hÝhP<6ÍŠHׯ‡û/ᓤ¼~b¤TY5û+{Ñ‚9²’ ‚T†à ºV5?&ôÝTUæ}B£>ÝñÔa—=HŸâ¢:@ EL¼ºøÓ¦Õ'±÷õÁö[Ú„›²[cµcÌL¾ül_àDy’ÓÂ÷BŽè[Uº®ë¸LF®'øAú%ÇpÍ“"Ã"'ÎWEsÁ3Y‰úÉšÏɓ܊€Îd< ¹$.V¿öŸB#ßGЦ/¾-VTÉp0âV1~¤‹_`¸‡}ux­\àpÃKÓÑžgaSPI¥ÚÜ×5góÝRÕ(œ¯^5º°å’² `…Å‘.çdòöô‡gbñ^BqaßvzÌB üv­b¬9TNÇC24-×Ýþ‚§2YK“Ÿ›‘@:»{L_ß Μä^êFîlcx‘—ID³W/+KZ„=ÏžÿídfÃ…·óãhæ$•L*nQy<®óÇó0Џ0‡N¡ÓÏçýçœaYÌb‘ËSÒÂ!ïF÷/þ»ÈŒNP颠É1Šǀy¯EĦ®z÷Èâb i+~U>êRZÓäÏŠy+:Ë3„}ÁTp^xä}›ïRÇ«a °èuQqÛ]–/)0Õ‰NLÓåŸñÿhR»~1úù~Vî ³§þ²`ÖÜ”x 11ÅJ˜Ë4Â(fͺê)çÌ„·ÿU~]'J÷; +¡t+_`-ãx&Óeà ýôŒÜÖ+†X n¢4† Ü·¿ªýM™Žˆ³+Ö ‡ô“6oR“uøA%¬Ô·Šu©?KwdD±’Εö](Û×T]dÃËæU +ïÆù|œÖÜOÐ]S½—|•I~m•¾âΪ |NNÚ®"»¨CÜ8z*Ôׂíª' ÆPÓ了 waE1ÒHŒk¡ö©Z{ç±|Éä¬HªH hñ’tΓïß^n^Ð êRƒ}ÿDö·ÚALD%›z8TôVp5ßS©Ày1WøƒÝÏk8Ö諆†*Èt€mËëÝ×!ÓsÍŒQÐ;ÁŸ×¬°?¾Q¤Ú>OnTHÖù)ÙŸ`ŠV.´û·½¿FÜG³®ÚQ‚ “äî!š؆ñp$=GJ™ü ¦² ]TË¢ðПpŒ6ެò¥ûx•_n‘„ë¡´ ¯V{³õ• È0N’ ¹Õð6‹§ž7Ö%ƒwÔ É~ï‰ Ç3©Scÿ»¾ ¯{CýÎ~,6Í®:D®¿\„ ;‘ý}ÉÝþw4Õä†÷Ð œ¡€zá²rËHÊ©Oþìù¼ø‘ñQ¾Pò^¹Ý«i‰“˜ðåìì.vÌ‹ŸX;CÅÎ{»5îŠtÇÆ%+y÷ñbNlÎeçÆ#t<]ª_ìûã{[+$LêíIbñ¢Å´!9¯E;вú6oæxážêó^ìLÍPªs“?µò»É´ ा(!—pîí£®“$kéYzoÃç°¶F|j‰ý²Ønb3…€CÁY·Ȥîýe³¹~¯öÇbƒ§wAã$¬Ú"U\;eMÁä€L¹0ë0?s(]¨÷¶DOŠçà›8.Ó3FÓŠeåLgö…P¼¸8‰Al*ÜÀ¦ \Ìú† ‚å(/í¦‹%E§‹W„ö áÒÜFˆSÒ]`c³LKzB†3÷·ÈïÎ!LÓhY—AøªÛUÂ=ÏäR‡(ÎÖìžVä ÙüfÉý´þøhµ/¨Dð¶*ô¾¦gôú{æ]õ?Pâ·²ÒJ‡Û§˜¤ P2Ý#wù° ޤ'fñ?RM|¥csóHV›ùÎLüK+p¨ mý¦®#ÅõãMô‚qà™Ìãš —Ò9ÐËTz+¯„‘¤´0Í÷uw» -ï:¾a-‘AÉ]ÃôG–RhØÔúê4ڼòÞGc•]QªœØ{ØÔ· iÛ q„î1U¢BöÜ ”Y2R© Âê‚@üº¹ÑûÛ y„ç­«‘Cºº€ù@%‹}tÃÂ_Úþ3ŠFk›€ q˜é׈ H/W˜ Õ¬sÊÌuª]?æBªˆ_6ü!,•}ää€ì«¤1H£•‘ô&kLÓÞ|Äí0‡B«ßž £‡´»YLgG÷ÛéÄŘ“\ü´‘¬Mš>ÙjñÝ·EÓP$ã›—.O±YIªéÅZ×y²;Q|5ï¨@9Z_l+IµKtOý.ûvz”T7ž‰ $ìV¡‘]vj°xú¾œ­»CÅ”ˆÈ©üÎøL+b?æÊžw‚pk¹ÃÊìrÔEKT¿ ¡¾kðiO µÇ`P§k(GJ¸'¦Å_ sÀIêòê1¼ih;ÍW tAÄTÉ=MÛŠ&fU$ì/UR·Œ õû«ê\u ì<Ã×Sì}æ*òÖs~M£ÓÃB-–¥ÉZ–nÔ:tjî™×Îî£GÆJ-‹pýlŠ' Í¡$7mâ¾/†ŠùžƒŸ„÷>ܽ,Ö<®¢WªVÎÜBº½Š“Ž)þûtYŽì•#zt,ÖO4LSš”²"A'é¶RnA×|%—ƒ@)·mð\B<±]Ùr¾(Úœ{ q 4 CçåÒ½?´}™ÇÜõ˜Ð¨ú(-% Ó”Î"J‘Ä'‰”1Íᢛ¹J¨«šË K‰Ð@jò¸ŽKù¤š> Œ=s– ùú¼¹¥~»X‡ºÚŠäê¾M©ñø.!覞•tœ`H]uL¾)“u“¨ˆhòÕ×è¿òδ'*fi{;)TÍfÊ÷ä顲‡3¦p¥PµçæF@}ȸꔑõqºâ÷ëäU\Þ»Æ-ÛkªÄtólš`O‚gú}¬\$²¨Mnrÿûçù7M–̈UIþ;ꮽ"ýå@ݬ?þ‡7Òdù:¶Šùc’(©½l¹Ä‚ÂKS¶ã¸©ôSö½Ð›¢|¸Ÿçóó4üÁµ¥ûþ70í—“æí :ÎÒ©¸y{5û/ŽÛ9eÈV² ŽæõûÎèð¶¬RFSŸ^>çzÈ9f™,øUQr8n½JÕ” Ë9Å ®u{¢½*£xJd·ž—•ÔCDØÁú°ta4¤º©Zß¿ÝYœk¡`ç&·…õxÛSÿ4P}^@|b}1˜äxjõõî#D)œáÁÎõ ÌaJî“ò9H[7x9™ÉßßD³Â~Z04Ž´Â§!²ñ7ÙÍ<§tñýš[â`ê];O<Ð ólqÆð¬ÀñèKFÓûtFk‡4h1“RGÛO’»ÀF¯o®PuOµ…ݸ82¡Lgqø!4¢ ߬/:]þCOõöãg"ÒŒµ-¯&‘ ÷3a?÷‡YÁ¡ 1­O¯_tpÃt~†ÃìÂ].C´x(dGI©•ü^…åqŒÚ+5kÎr0°= é±f-8ˆ÷äÒã¸xÕy¬ÄDÂ7©‡7Ù%}óñ~ìÄw>’•sÞCé~‹žm~úå~ã×BùTñîSêa¿>™]ÜE:Ú·–ÙE蹓m̧›ŸUØh)âìEKž8¾ù~Zš¡NÍc¦p× 'Xݱ™cíxÔÅåQYo©VÖ×t¥.¶)¿ü9:›ÒtR_)²‘‰*ñë/qïÑûÝÑÉì[¤(u›}<*žW$€ù …¹m‰³¸þ€lwéÚ‰ÚO$ù¾»8 ÀE.¡8’H>Fl×AÚ»ËXÆÍ+Kå¥ÛŽ™Râ:sÇ8ƒ0ä×1ÓO*~?ºŒ Ü€s6Ù²À¶ÊÑvÝL3 Àw^»ÊéCÚÂÈC•Ö.ü<Ö…Ú´aÁŠ?+ˆlU Bì˜jµ&.òw"lþ}ªñ¸ endstream endobj 486 0 obj << /Type /FontDescriptor /FontName /KZRWDG+CMR12 /Flags 4 /FontBBox [-34 -251 988 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 65 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/a/b/bracketleft/bracketright/c/colon/comma/d/dieresis/dollar/e/eight/endash/equal/f/ff/ffi/fi/five/fl/four/g/h/hyphen/i/j/k/l/m/macron/n/nine/numbersign/o/one/p/parenleft/parenright/period/plus/q/questiondown/quotedblleft/quotedblright/quoteright/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 485 0 R >> endobj 487 0 obj << /Length1 846 /Length2 2055 /Length3 0 /Length 2636 /Filter /FlateDecode >> stream xÚ­Ry8Ôm¥M;!¦øÙ'Ř±ÌЋÐXbe-5f~Æ cFdÏdOd-{Tï (•}_BYÊ’ÒúZÙc쾡¯º¾Þ¿ëùç9ç>ÏýœëÜ·”˜©¹œbêRÈ49„’V3Û—ìÎ S }i_ümï;‚ýCyJŽöOS*è¼KÙ<™qk¸í2³ ü…ã\=[Ór È‡ä„ìö$©œ#E¶÷½‰¼+Èh5Ø"¥õ-p'ù=ºÀgeáž”—þáñ†°FAÓÌdü/ü‰«eÆŸVœ·{ÎÒõ¡>‹å˜Mhº÷iæ½ùð^özb#cÏÛ¡wqâ#‡×í¤v¡É¼9-Ë‹ëÎ!ƒgÛï^ñÊ*L»÷õIYÄø\ö'?Uôy3~½úܼèb.:¹,ú;¦à”/S2ÿ…z†}Ì_%ÞÙvÚX>!9ÕbbÀGµ¨Ò=%Â葹!¡Oý|·ïþ÷Ïèâxê+&„ÄL—ˆ´¡µ<tmö*”„L5Ÿvô¸³ü#£®?§ð¾•ñ×OºJf¯2pVu©·ê H¥D¹—[„ˆ>òÝÝRõ } w{~Â4âÄÈSçÑ‚Tú¡—‰YuòÇ¿á„å‡n ¤øJÍ¿ N+q·÷Øn_ø§Œ¥dñõ³[mz¤t“öO¼êÚ“÷pv둊ýwP)¼åš'ìPüBw4˜½8Ú¸Ôí¡3øoîLŸÁCÕá Þœ`³”ÜÓåysCÃ6‹HI×Åä£è¶/Ò‘Õ´§…µ±Ÿ.ø!{)ØN‰—Ó»e/©0/²dkD=ÔöoA#Ûœ–íÃî$]Òa‰a¯3kêY|bݪ—ÜY°Õô!ß5¿Ø%¡ßÂ4šš:Inà÷ñƒS í´²Ø¼jÀhÑ}e꛿¥ã¹,µ%q‚WWd®l 0Úªú:E D..C ÅŠ6£ .O#ÍS‹/Þ7×Cæ³Ç£ ³ZñgLW'Xé]¯jÿ^¸G:>Ÿ™ÎëËš 7eî§@‚Np×`.Äœ¨ËÉE^ûò(GäN®ÛH˜\EávY ˰זkå—}æÉ2uþCDâNjϙ-\¢œbS_ÇSʽ«oú±ææy¯pŸáúìÒ:ZZñNÔR‘lÛrvW¨û(ÒzÀ~JmÇsO Ú{õÔTPæÔÀ˜tÆ~툂;³Ί·Ÿ—Š<ÞéÏh|xD´LèeH¬Ÿ"ëe®ž÷d´9NínäöSv‹W !m ¨µÝÆåFÍÔAá4kV²ÞÖï1ÃÆ Ç;c««sja Aë ìâ«O¢Bñî ÷S:‡NÒÆ:Ö_ ªiJVÜ ô¼ë—üU!wœ–b%´düMäºö¡„o&Ç{´œü Ï]kšR›”ü„ë¤7)†"T'çtйòµ2íÊ:±Øá…ZÑk“ƒÓùþFG°_—ׂu‘ô‹jOÇZ×ùæ¾GçÛ…'°ÏS¯6j,iöÎõöx´Xn=ëG’ÚŠ)šhæX™¾daŸ3œd°WSöÐÂB„Çú›Ìf©Ú{$Èé£`‡ò*É•§ÎáÜÀÍy†¬( ‚£òQÙhêÈÙ¢'3³ïõJŸŸ<}l&®Êw O9MœÝÿvέí0 yXÁ]Û°>¾)/¯W~/tˆµ«+4ó0ýµÎ•ºÀ4t¬E ®@àlV¨“HS¹h çÞ¦w‹OÜ\ 3²B­ë8bŒ…Ž‹ÞK¹›÷fßHˆ€^Xm«œ>2 è¾EáM÷]«½³jÛ-¥#±væ›–ÜÇŸ•ìÝ_r…µ zgáêBQ·Y2QNÍêPýÌJ5ž:{—¬ˆIçò#æÇz/”F|¾äBóZ§ÂÂ{×+Ï7Vû&æjö§¯Fe-ÒtUf^F"’ãÔf?]_•¸þÎŽy¾0ä $¢tÕ1ì“#t‹Mta‹¸AbʳD#1è:AÑñäÚêwH–ýÉmîA¢ß¦ÅØ{ó–ewÉ9®oÏœd0[ý¾¯²‚‰ê¾cãùå´ôrÔÝsÂÞÛŽM=3¨áYZÓºA{Qô¥›r­a25®³{~Š#û¹¹çµ‚í´ÈØlöµ€9‰‚•چ ݆ÕÊûhàŒ‰j;ÍìÕ[«RðÄ3‘`¿ÌóXKþëx`*×øãé1kW>›Õön±¶7aÓ†&#{8#Ä;e”„ÐŽ;aç²ïÐÞÖkÕì#{d0л¨úŒa#œÛÉ-…Ós3Ê©’Upô„3ÊE 7ÐÛ·(¹/Àp§ÒzóhûA`$C'¡*9¤‹êÔ™9hS»¨nè?²`)ãböoCëÎLe+½Z6 ÙùU±Eè?w›F‹8Ôõ^ÕdÇ5Í-ÒRú„ó:ÓžeM=ÃÉíu&8st3ZM#â^nKÒ<åX’o‰› ¯æ]슎%ÊU¿Ã /8*oÔÍ2m†ZúÉ>ï;½5™·(™õ(‹zÛp,u–ORŸ¬=^]!Û*5yÅbÊÈúúÄöžZýÒ¹jc;ϲ¶]æìzœvPSú:ㆄ-+rf8_x,^¦?ö®ì¯ÜÐ(Ÿ’NâÒAîô÷•!G¯k" ¶Ãˆ®NÇ(ÊÖjÍ£ª÷b ó`LG÷¢¨M…›m9ÿ—z% endstream endobj 488 0 obj << /Type /FontDescriptor /FontName /WECPER+CMR17 /Flags 4 /FontBBox [-33 -250 945 749] /Ascent 694 /CapHeight 683 /Descent -195 /ItalicAngle 0 /StemV 53 /XHeight 430 /CharSet (/E/G/N/T/X/four/hyphen/period) /FontFile 487 0 R >> endobj 489 0 obj << /Length1 819 /Length2 1937 /Length3 0 /Length 2503 /Filter /FlateDecode >> stream xÚ­Ry<”kæ ‡œ‰‘WRÙg¬¡h,Ê6)#GŒ™wxÇxG³X²œN”LÃϾ…kBRÖû.J¤S‡Ô!ÑÈé4–ÎÐwÎw¾Î¿ßïùç¹®ûzîçú]÷­®êrTK¦û‚8:ÌÒÁèbÌkGü>£‹F¨«[3@" ¢Ã6Dh`LM1–í裌±™©™¡@XӃŸ? Øk­±.2° "aÀ‘Èò=HDp”N‚@V˜.€¥Ñüú &€™ #$ë"0€ ‘X€/èÁ½u?ö0…˜|¥Éì ¿JÁ ƒ)0ì˜ÔÉt˜A Bω.ø 8ù˜ú¶9ŽM£9×Û 2úW•ÑÂþS§±Y p¤“Aü­ÔüjÍ$CìÀo«ö," "aa? ¿R…‚dˆEò(DÜàA˜ü­ Alôì xW{­in”\ˆÌr ú»éºvcþ‹Ù0 PÀ­‹FcBÁùëæõÍW¶0‰N†`Á:Dƒ†ì…á‚É`(† üêéÂt–à ˆ$ Ðˆõaz(\g¿ú‚ÎfüMšztøC@)0÷7Æz,øZÀ„Ð7ð¿s±²¢‡†ë:ú!m‚LŒÐ‘ÿ#$± fm¬œ Ý¿0ÌCAâÙ:É<†šV{¾8ʶp DLSØÊïN¢SuËãFÉèÑ$aÚµ®Ã§4_Tø¥™[¥§Å¦UBV¶39 ®½¸ùŸO%¦¬MûLgž¾»ÀËt {´óSôì–úÚá‡^t§xµæ,´Í^qÙkãöfósU¡ûžÁ5÷³bŒM¸LÚ±ØsU» Tñ2é§Š/ÆN„ȤpE'ú££¨±âuZãè l$¿P|®ûJˆöÔÎzeFt¹Ÿ'hw}FºýN¹ÄB%·}þI??âÞþúi‰EqԽǩ ƒÍýäàXìÜ ÂSz¹Ù0ây“®ÈÓã©§Qµ[Ç·<ò.(Äè~»º*J)•ˆ |yÿh“péI|ˆbåé8§ZÞ#stÇ6E݇Oôº+*ú¤JÊM¹¤pNÎÈNl™¸àø%E•©Þ}>ú–C´ÌE/tpTAB¨?†—9x`W}šœ¦}Õý3SC„Îá˪î¡:‰¾T´daÆwÕ­<Þ„°µ¹TPFKdã¯þ_æ\¡†vU „rßQ¿xßÀöÂE¼œvƽT‹ÏÞœAåºÊÇ®ªù©­'Fsk±Œd¯ý@aúâû÷å\S©¬}ó–ï­´Ä ‚‘²öÛZsé‡ùåÆó9ë¢Ø@øÖ”æª>ÄàZOË|ùÃ-Û„$ˆ3[‹´‚øI;Úë ±fkÇf¿c.–‹M®ëÑHxõ¼é²êÞ--òcÔ˜¹w.EÊ$ß-Y·ÕIânÌJQi¤î•³ v›ØTFµÌ$*m>-–”‡¶Žéö¾nÇs.Ï’#r\RÊ‚¿g;¯õ¾¢w]~¼wåOž‡Yßdm’JöËš•“ßsͧ‹Ïô0 زÇNlû!gl,@(…ê­W³È’_u/^»c0˜’n¨=ûÄaë¢F'¡£FìèR¨UŸÆÕÍ—ýñÔ iâYá˜Ûo?ŸŸ{,9çáDe.“,|L sBsÞZM(ŸˆÃ…‘Kü&å—íßÍè[.—åÜtSîyÄ£÷”òôãTÙ#F(-Õ”Û*“mž²Èv–Á°ä‰Èç˜Ô%‡h÷=Þe=î¸ÃÕl{3ÚT‘ß±Ç1Lðò—®O@>J•ÜôóæL~\¾Ž{ÁÍ_äêTºF ˆ‘o“*qËœn‘#¯+kƒå]o^Ðïr‰PÓΤ’m+/\´rJ¬Ž¾£t­Ñ-…ÒâQv~þ—/¶béêPTtnæçmo‚î§ÕÏíXÅ*¸ÛnLøµCÁ1eûkWPQNS6YZÚÍJ³_ðÈ…}šmƒÃY‘Ï iÍ¢½o-yгÆZX÷ć“ÒcG2‘Ÿ¬!„¥ò]RÌÁ”ÐÍC Uy%†S/±™‡tdÙÒŽBTèT7+ÁAÉÓߺç•U-Ô÷²Šài!÷³ †]pPéaw ópÒ*÷1‹<ÙŒ§,ß’pµt怒ÁÅ#w¿Ü?^d³UXÚE¸Áü—ß—*+?ØõãöSzÃî*¯¼üð;o@Ib~ø{ïaqÃÝ©¤ƒ¦‹Šêvù‹'Þ$Sùv1¹3Ë{E«†Æ¹kè $¥;ÈÓš·‡‡QRÚ3aaYÜ=ˆMAïg©"Õ¸ñ+fJÕ©:nø¯Ä«#ç"Ê2zæËä5àåóì{jRFœÃÏ endstream endobj 490 0 obj << /Type /FontDescriptor /FontName /IMXRQI+CMR8 /Flags 4 /FontBBox [-36 -250 1070 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 76 /XHeight 431 /CharSet (/five/four/one/six/three/two) /FontFile 489 0 R >> endobj 491 0 obj << /Length1 1238 /Length2 6680 /Length3 0 /Length 7438 /Filter /FlateDecode >> stream xÚ­”eXÚ¶µñâ^\‚;$¸»w)‚$×/.Ї"Å]ŠS(îZ¼´¸-Enö>çlîwîßïÉŸ¼cÍ5ÇÈZs…‰NK—KÆf V„A=¸@Ü Q€œº®ˆâb21ɹ­< 0¨¼•Xd<í¼@HP”(ÊÂdÈÁ\}Ý öV9¶¿Š„2.`7ˆ nåáv÷°±rèÂl `_n€Œ³3@ç¯î°;ØÍ lË l!6k°=ŠÉóW"¨ ô/ÙÖÓõ?K^`7wx(+<$ÑuöØ‚í0y4`p/0<ÉÿPÿÝ\ÑÓÙYÃÊå¯öŸÒÿY·r8ûþ»æâêév¨ÃlÁnÐÿ.5ÿ+œ:Øâéòß«*VΨ½3À%ÂÍ/ø/â®ñÛjAà$ð P[°ìOÌà …yÀ·à°ƒ¹aþu©‚™¿¤‘ €Gö‰„À£ôD¼å'⃟ÊÁÝUŸî®öDpwõ'‚»k<Ü]ó†»k=ÜOç‰à~ºOÄàÑ{"¸»þÁÝ žînøDp?ãHÞÓâ~à–v0O·~xg_W0ôI‚·€AŸöðÃC»Z¹¡Î`;'ôoõ_¯çžÍþ~`¶Ožp w°×ÿr€ÿ8wøÔüÃð^nàÿ•îéá û›ÿïÈÊÊÂ|ü¹àSÄÅ ß yá÷ ü m<Ýàá<þþO€þØ*`°Øsif#æ˜ÖQöZ¡p²•Í*ãcØhgxC†÷Ášá¬[ó„˜æA8#¤ÿý‘j%­Ày“LÀ ¿.Oø"Á 1[~¦î³›Ss¤¡Ü/½x.¢~.Ñ~wmæ8Yf¸\÷êD­VÛ E£”-Ìߟ¿vz3¶±„•n˰óÓ,·]-l°»ž8r{¨+„-‘šf^=,‘÷®N;}ÃɉÉUGž/=}©TzÂZ6`µò-½?àRÿÏTÜøµðIËž“ªÕRO¦ÅV]ÎMN/Ö5É6.}Å;hÛò§û%étöoïÉ»Ö"nz¸aP£yz—‘·kw|cƒq¸"ã²çc"DÏŒò—í »6îÇ‘„S!–6 n貆v™Ð‹xÍ>ŽŽ¾á€ÞA+³Oƒ¯vr¿µIÏUê:/Í>Ôwé‡û§p\3Zƶŕ ¼+rkI¡›m{n­<{q]ž¸¬qÜP?ç§Æƒ'Óü’ùQ=WIî“&M~ŒÿçhŽÑý_ÓíÈÁ€—ä‰,ëgFDÆ2cHèÌi Ÿœ¥F–$ÁÒÖÉ¥´ó ß&ôÂÚ¤­šË»ç<»QÞên·¤›¾—Õ"ÂzhÊÜÝU‡wÔg$öµåïž-9­|©J%ß¶íËĨ+f_ý-ð€¿ÿÑXÛìœ9rrï%µÐ8ÃÞ… ‚›%zL…‡íb~—ÿÉÑCÿw7˜}¬9Ôª:ÇÄÌ¥ÅaG˜L×(êªߪ(ÓY0›9hÄ+S_z®„‘mùXƒý2²‡«Z¨~ùÀ®-…-½’lÕf]ôùO?EŸšèþÝÜôf;C¿ü¬=Eê‹äÙˆªÁ]¢„CDò#ªMìŸÛ´:MêºkëÑJù‹¡}ö!'½ÜòAÑò‚¡K†È^ZŠñ÷<å^¿0ß#§¯/(Ç%gò·òHz§.£oÛo-¸ è&Öm6aãøî½x‰^zàš¨fIØpzéé,½Œß[TF䢹SÓ ¤ÿFu>‹Ô /ÀV€ºà@{¸)ZüZŠåÍ'ý_ê?ÊCªb&^Ê¿ÐÚДx¦^îQÑN5ßç´õÿ6—DBxh4jT« È áÔ_hê…6¼vœ¤Ô齋åòrã|ŽzAð,øÊpeûvi‰D¬Ë†³ê­¶ôh6ȉ¼táSb-¿ óÉØÁ»®Ž¬ÀÆ ð"œÍºSÿ02ÙŽj—ç•+TfÕá­õ)!çQï;xÄãàá+¶] ¿fÚ0ºæ îÃóùè”Nsûm‘~Q}ù„³Aì—ªÚg“"Nª½’´-ªy&öî¶¢H©M­û±…å<{^²½£,upyÇêB½^¯têÐËÊÝf=ŠÞ<º÷ÁöZ4ï §f0ÔÒ•ÔZ 9…«Õaš–Í¿ƒÎ{2(òósH°¤ ßCݺúá9íB.î­°Ú³¯>Kǯ#Å‘u'IZC0¬Ó¶k ´fÙjÁŽû,ßq3»%hPÙÄ×®õxæš1š¿‘úÑu¯ýòu;”âš2æ=·W‹)´GQö*Þ*Ô™%ª¬µµ,†«X“WÀ¶fœ ä²@+dÝ*›J­=ïñ8{Eܾ¹Õ¡tœ«6q{ ;4¤ s¸{~(;ÜJ¿ÌJxÍ`d»§{ˆ˜‘’¤J<¡'P/Îú¨.Áh¹üÂU^¿P»sg•>‘äìm·Yï Qá~–¾ðÔÑ/ hÀ¼M1 rÈÒŽHÂ+ÈH³@M$?ÏÇjŒ’vþÝXXc󖉱¾ê÷B¬zäêO î¢—@áO¬AaÚ{Žj07#‡ÏãÇk1À&è)cÇ;”M3lz"vɺêsýNÊcÑv£‘wè‹/ˆÉVm±?Úò_"Ät{XzÐL¼ŸZ®cT«j¼FÓl)_Ó8¼v1ÚenŒ¤é{›{¢iPq& A#l†\6Û´±Ps¨´ Û V¡]_Ž|1"œýÚrøV8md³®úÍ’›’¬ذr!’ÓîáZæ—Ú)oCyÿ`K³1#¡ž'¾¦5*rb¦R)vD@T)±ÈÉ9Xpø8Qî’±FÔ㌻>ÕÐ|Dr×ÀuÀ!MG‹ÿ]× ™ÀXC¾¶±‘nnÌFÝ&ox¸ r)íõtÒKÏ6¡&–}HOœ:†ÌP Tå5¾Þ´P˜ ë‹Ô-ŸíêºG éA7ôä4Jð¾*Á“§‹X¯m¦òí8Q¨‡±n(;>LÕSCc·öÍvi°DôvÁ‘‹³‡œ‹¾Üwã¿ÉOÍ“·ãPêFwO÷³°%AÉç6Q©uÑ_oç¼S°E‘YÔ@ŸäP³ØS!bÎÛQ®!­«>f‰'mLmz»QšÓ»…ÅÈïb£G HCJd®éFƒŠq—#ÌyÑlz|cÙMw~>¢pMjæç_äsÞ£/‡ ƒiïM™j¦¬­3®<´MÉ™Þ3|JË’+ s£”õ¿4Ž!OZ >0ÒÇIÚ«¸ï¡«M-²:vs^,!ðsCgŸŸì“¥"]*‰îbøˆ†ãªqþ bàg Ë+le¥± Á±OTm³J¨ƒF|%úÚ¶UÐÌltÈz|õüu¶Û–üA]ºÅRWóæ5žS|NºÎÉħ–¾giC(LT>ÇßÏ=ú÷×Ï“>ývÞ#BèŽøüöøeVcì¾y5cŸxR‘×9¤ã#6]m’÷pܤúêõíõÿh®ußøš"§S7aIéÏœt¯Ñáým.I’Û7äwæ –¹G‚?ã<1M(ê¹?ߤT±ž$¶x¥½å¦6©(*ï*Ù²ç:>6#5dæ®"åò¶SÒ¿^tÉ4·´}Z>Ü£vm§Çôh œ8$£ÆJMÙÕ˜Ë/WÅOf/¦ÿzÄÞ!dp™ù󈦫ü!ô1«òÙSÀ«ƒ¥(8Î’üC&”1«t‘êѱäVR*ñ­W0òéß1´â×ÊJ•#KýÌLO æIûi!>³éûÚ“ä  ¥Ñ>Õ‹Ñ ·c 9y>Œ›dv'‡@WÙg“¡´Eå?ÂéRJ á7" >a˜›‚ƒe•%8¢0Y÷c7â>ƒ9ÁNnn£ÛªÛ~tÐ-“àlÚ:Ô΂Z*EÝÍЊœ‡ßD8-É+Þcº"ÚMÄ œ–®ÕdïTŸä.PVÛÚ¨¬%AæN,Ts”½m¾Œºs“—Ëæ{è t!ÉöþZ;àåí¡e‹¯È˜îL0¯3†*écQ7ÐÛP|Óû+“ oC?#‰ÿ’gNÄH,á4`7¿Օ鞉È?R?pdfZ0®þkZºo ¾àuʹɩé—Üɱ蜄u  ò[Þ”‚[ÀKu²Ò¹³wqûÊo7ñ6æÑ7¬@±ŸªGý¦£x gea4 ~¾õ—Áùffl¡ÊäN.ŒóÎé1,>;qW×Ù·òó•/ä¹¶îN0cæŸMRuŽÞï+ oÌ‘âxiÃAÜYîS¦ËÖ¥ûéï@ù£Ì¿ìùû¹N·ë’®8Öp‰¢ìKFÑúÖ‹É?t|J 쥬EYuÀô*B2ºõ‚S~ƒtIyÎ…“í·œ×é¼Öá]H¡ÔW% zr¬ËQ?Ä]òŽJß”‚ŒÑ5^¯œ¡à{0É‘%ßÖ®¼Ñ½ö£GHªß4:ãøîfÒFSÕ®=ÃÉ(ÙdÖÆ“Ð3hÀ𸱩¡ÙFñR$-=õ—†_š!Äçìö.kå}(‰yJ&ZñÃ*ãÚ"ãN݈}Û;òÞ_2çÂî:9Ì~6†8†áQÊ*ª¬›ÕcSU¨3Kô÷9zÒêƒjt,ƒÉÓZu ©Ý[£~“l»ûfitÛ½‘“RÄúl©¾¥bMI;`3©Œ:˜Gçß-äÞK—¿L<¨wèËõ´py_´ÓÜÃò6ØÉ®»s`λ ÿ¹Æû{Ah&Œ¶g¶Ý¼j¬ƒ˜Œ ;–K}ÚY­k¬ý`ÏPx'ôÃHŽDì×Û1åµç/Ìeúq|íVI1¹©#Çq’ÍitïÞ¿ «y5ÃΔˆXÃÏ4lþÜ›ÝcÛ½Èãû#ÉLO=3Ÿ55Ð 3|ЧP«l·Ö‘¢ñLv6úÝçO¡œU§,…Q}&¥ÉoZ4Í /aÞ\ÆXRT!ÓõŒÕtÜ÷Tàh`è96íiû÷Ì:½~A.5+ÛË*aî ,ùy‹³ÁÌUqg{ ÒÞì€S(¤^ÙØõhPêÄlc­‰üï#õo}ÝßhÝß÷2J@@L!¾þ,ID­ü6?³‰4'â)Qš¨#>Û)Ñv¨S`—BÓŠZ÷-Ëž)ó¼%¡k"•õi!1§ñÐÓ°‚ñÄ_ ¤RHµ 8Û mž"ª9~ÝÛŸ°OÚ­ÝŒ›9Kå³Sou&SFnppªRQZÑO÷¹ÈV7Hçið´ቿ‰§Úg}^Êy1wîÜß &œÿ‚È|8×2+a£&•;™QxåÞÕE¯R|ËCÖZCÑYû¶ÿ‹ù¢!¶û{™ë5<ö~ °Y ®ø3s@qfPæÜ®båÚù×Óõ=cƒ>ç°‰ØÖ™Žh~Ïpö DÓÝöÚkµSõY3²Qo˜N4ñ¦÷P;º¶üL2Æ3Ô|ûÙ¬ìE7Ù Š“ƒ‹]XZZ¾@­òUæñøŸÞYuâPŸÅmEÁ‘}–ŠÆÕWä!×éQ\hî |ʉ­X5+ÚiìLÎçv³b¸TG£½[ß Ž a3;”m?HÑËSµ5csÿP`òßDhoK¶Ÿ9Bð3î‘¶Òp‹µÙ˜=OêŽ>ÏæZÊÚùT¡£<|ìÍIKšâ´îHûæfv[ú{VÊZ 9sv½Ëq߉âDKçm8j=sãRØìJŸ0Ûár¼ª_®õ Ç×îO´@uûG[$ -J5œÔɼÐüJ sÀϺ¤êS\êw}.aöž !¥D©'¯nˆ»™ ùL߇;Ä;H _ú¸xÖI&ƒ|o쇃Ev…0½c„^övä+z¶ˆŒÄ>J@qP±_†>ν†6ۀƎç#a¤kðª Air™G­»…¤È…íO…(à­sŽn…ZÊrþ9²ò]QïDµÆ¦Ú3ÓGŠÆ#)} (Ûb|Ø©Ò|ÇŸËgž©þPÉðWNÁ”Þâ^Hš7¿þD#¦\ ߎôÁoܼ™EÁ™ô?†¶–”Ä7УfE A-{¯ ‘Ë•À˜ë2W”ÙW8䦵–~Ïb¹Ã$¿P ÔÔ ç ϱU ãW×ñ’Àð l†cÜ®9Íø|9þ)ªZ®xD £ãŸ ÑAh¾¯F €KØqþåÁ²´„'‚ŸüSãy8±¸²¡YîÀ+m·²Nó[ØÄcŒ$iÛU/ºÅÛz{ÎP†í0Z8&ßÙ™/‡tܵ­-qêT´[c ZYåT•šŠ¶:“Uÿ c¬Óhº4ŠÃúÆŠQ ïûïÈ´7E ~ßPîtœ5ŒˆÞ0ô!—ÐhËcÚA»HíSí|Î(«ŽTòîxª†^޽Ù':·eˆÁý1`”ÊnIÉ;ÍÁ"~H™õ>3$m%˜yç;e|ú‡Aì±iVÞQl"3¹õ€"¢ð–W_+†ÒõW<¦ï ÊtrM•¾ðOoK;ˆÛ½kDÊ…Ûµú$Î7¨ÿœ]]êŠÍ&¿fx«u3gÜO¡µõüNŠ ]'~™)<±Nš,S5f¨ÂøçEÈ{´B­ïïß[w”díL4j•oü7ÅZV¢HU=Ä«"µXÎBd?ÿhŸü(¨VÙ((åìÐåŠào$C³hHKí¿þxÙ¹|‘À %ŠŒ›ŒÊû#ä1¤pÖåUAûLñºê÷åA¼Â…·ä ù‚<áÍžª­ë ÊÙÕƒe´TC>qF¼ãÊMÿb BºakÛ÷Ç0‘—My¦†Ï4yоkŽMó°sƒbŒ±ÊIÌËY…|.@ÇèݢMÅ¡@ÍEÂjx•K4)“‰q¡;à’€î!šhÛ‹ ’,÷â;Åâb÷Îo ¦¢G×$ù>Áôô&úÏ ŠÊüâ™–L¼nRjåb˜LûãÓm’ƒot Áá çyïc1«hŠCM_÷/ h|ÁÄôˆ¾W~æOYˆS¯V.ÌÇúØa`h©ýý9I#¥âžáèEˆ[? kfXˆ ½N27jؤ/SCYý–èùåÞ¸iù¢Ñø³r®/Mk+$åñ{—¦c?—'u ³ð½p µ0ý}~”ÉS&A)Ä;Û™À|Î=BÍrGóËTç¢ÏðU €yHb$ ¤µ\rï¹r¾ùAëÐ^yZ¨Â?(œ³ìT3ª5ð'JjÎåQÏž÷Ðùï“hp¾ËcÃvðޏ™;7kê_£³ÑN1j óbìÖ¶Öòéµïÿäª3ÉfçѲ±Ía]°2p‰4„ÔÓH°ÚÙh›Þ‹aPÚ7¸°‹¬ˆ?95wÌ— ‰G$" Âñ Iý ýH›ÚzÚ) ÆÍoË•½•+j%yvu{>Ú[ íúʾ$P9/{·&7Ó¤J/—¨_»¿.[VShÊK½±ÿm_}ÝÛÑíKc Ûõq=®‚ò+eïlå ñBkytÅ#+ƒíö»±÷ƒ—ãšÔóhÊnâU޽.¡ný¯®ï¨8ú¦„¶}$×=Ãp­6Û“ä?ÂÚî¿$\j=/Yxí£–ZtÞeÓic›³×I Ï®:öŸÿvMf#V¼êvŽi`þ…½‡ý §ý endstream endobj 492 0 obj << /Type /FontDescriptor /FontName /IUQWOF+CMSL12 /Flags 4 /FontBBox [-56 -251 1102 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -9 /StemV 72 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/R/S/T/U/V/W/Y/five/four/hyphen/one/parenleft/parenright/period/seven/six/three/two) /FontFile 491 0 R >> endobj 493 0 obj << /Length1 871 /Length2 1214 /Length3 0 /Length 1815 /Filter /FlateDecode >> stream xÚ­RiXSgÅÊ¢•ÅV½¨”’䂊Ò‚Q ,…J ¹7ÉÅp²hRd…ŠHDË&n0€Ã"›È2 ”Í0ű ˆZud "ö‚µ>CÿÎsÿÜ÷œó½ßùÎûZ˜û2l] ~(Lã£b[:T/ÆA €D2΂*„™b„º1ŰîØ.:dŠ“ÙÉ‚³¨|Lˆp¸bÀŠj½(¢.á°a1QÀ‹)æÂáX“0ø,ˈ€ ø-ž~°…!"a‰P˜ƒ 8Ò¢#w”Í(ïaH"ø@……"Ì`…™´0‹åÉfãHÞ|ì.sòÿ0µ¼9MÂãy3ÃÛ/¥ôžŽðd(øá‰^|¢Ë¥ð{s^0„H—³îb&a¹  ؂ۉd{‡÷"¢!RòEÄ,.ÀfòDð£Ðr+X|KFHÔ º·[ Ís]"}™*ö— `€üQ½Tƒk,%!"‚ÉD2Ä„Ø÷áïвËv£,>„ ÀÎÁ` …LÛ ¬r"AA!X ÀRÌ1‰ˆòÅØ‹& `ó…¸Å±‚dG€Ê.¢ï¬Æ²†ÅBvd€ÄƒE"8B‚ íŠá*}”a€„'F˜µ?»ÛÊ å1?BI€-bÁ(6#Zbþš «+_ik·°Ýሽ Å!ê„,‰PˆuYZRlj6‚͆¥0 §à³v&„ýpãÔ•èÝ…ÝW5H«ßt”>Qj5¨Ž>‡@Q ‡ ûÌ9⢧ù#U§[Gz =X;Ï+R½SB¦ JªäyÅÒc‰÷Ù yÖš˧î-Ù¹'GLœ…£9ßmùL9µ%¦Cç4áTØðúÁ€¶þ§~Ÿn6¦(/k ¯Ø@ ?îÝ4YóC»3ëE×ÝÝ— ¢É-{Ø_h‡N1Up‡ØG{zlö»4÷MŒ3„æt}Rƒ¥¿™%mN´xu›Q,–G›DÞh~Nz–š?}Üg5®Ñ̵u¸»%¡}„”»§ÁŒnÚ1jÏ}kÜa㵞C~`ÿÉõñj£»aöW”‰ï&´Œ/FÏ3ä*2ÍÜ~û6âRóëý„Ô(¢çìƒ/‹êZ´êð Á—}JjÚ›W{wjÊí¼$Uª¬jîég$ÂØóíÝ{ŠFcÃÕtŒÎßwHKõaÒ4S›Ç$· œ­RÊæ\ÚÜçG=ãüª¿ÚU™}øù©rK½h°pPY¹ªâíwýÍíò;EyÞ„0Å •QFCæ/é@€Ì™”f˜¥¯¢ÎUÝ=V?‘âé–ËÖœ½4÷. òPï¬=Þg7vÿéé2Oãaê‚fjR§ÊG zž‰;ôøëh_òL\ÜëR¢ºÁÕ|äY[tݤD¹¦—kõŠHüþÇKÉ;U÷èÿq?öý,Të“éÔÙ…¿tË)»MÝþuÁÿ–÷VÉF‹¶­:9­©Ê u& ü'ët‡ô»&‘M5“2Ü4¨Sêêhôv÷ û¨¢@ó8½+^‘k?µx›={Åf×ÝåpÅŠ˜#5k#?oùõ–®=Üãoª•m©W·gMv¿‹ÓKG.'º¦îjÂU™Î&æmí÷Í”q|öž/mÃÕåÓÝ/¯P ¹ ±™Þ®a¥/;›a¤šš3CIÕçïn,t¤çmYyOöO†æ·5™^—óêð]ª_|3ôî‰ìášR0`òŒŠ64<1á¬-MñØØ¤óæssõ’´^Ób|¿¡µª 3мêYhu˜k­Zœå3”úFHá)Ÿò¬3£7ONª~q›`gØ’ÿ“ö¨úZw­/êÒR­ L®Äg4¸WÖYæž™(gpƒýi–éÒ•OXÍ÷ƒìG/vöb_°*~ÏŠ›úç¨üîˆwy”„ Ûü f“³ñ-:&Ý_±Ê7x¼î˜aªŸÌþ;½aößß<;f²ÎÚ¹ã§{>û^4ïLÎ.Û]"=Ü”ð˜P^’CxCÙ£Vuad~k éD nùúÖÖÇœëJº+/Ù¶þÎ5Ú|Ѧ/"äÉýÐÙ€¸‡ÊÚøüƒxÛ~ê9+JnâíäÝ Gµ¿i­*=2Êy›~w›ãZ ÆdœŸ4CnL(=U•G§mÞ ù¹é«îxù³DÁ1gœÙôxaÛx°³ó|–éCµÍC&Æ®Zk†Æ¢’*iNw ?¯˜ò'ËW¦ÓGÓW$²Í£Üæ7Ü<à_sÚvJ´Q¯PeØ<ÞT®[‘ޤ·ÍlÑïü×CQ³~{Íþ°mmä+®]­1úGžG•Û¯õÄkñ3yêU!†¿©[r¨ endstream endobj 494 0 obj << /Type /FontDescriptor /FontName /CZLNDW+CMSY10 /Flags 4 /FontBBox [-29 -960 1116 775] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 85 /XHeight 431 /CharSet (/bar/bullet/lessequal/minus/multiply/nabla/periodcentered) /FontFile 493 0 R >> endobj 495 0 obj << /Length1 745 /Length2 580 /Length3 0 /Length 1092 /Filter /FlateDecode >> stream xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž´P0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22²2*RpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥rg^Z¾‚9D8¥´&U–ZT t”‚Бš @'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<(0¤s3s*¡ òs JKR‹|óSR‹òЕ†§BÜæ›š’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l ‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;z`‡è‡ø:»8ùjCb,˜™WRYª`€P æ"øÀ0*ʬPˆ6Ð300*B+Í.×¼äü”̼t#S3…Ä¢¢ÄJ. QF¦¦ Õ† ™y)© ©@ëëåå—µ(C¦V!-¿ˆ © ú¹™y¥Å Q.L_89åWTë(èZ 44´0U07·¬EQ˜\ZT”šWN'À°€ñÓ2á—šZ‘šÌuóZ~²uKÖômm+ë\_XŪÏùóÄÚ—7ÙD쨛™Rl:/P1½dÉ«…¶öϾ(á•l=U¸h‹d¯_OÜ—EÂk¶v-X1¡Át¿Þ`ñÊæ®i¼ÿ´Õ_y. ›1§õ‘´Õþ¢Ç³:•un~Q®?Á3/å…SÔâ}ßï]ãÒ š¤¥$e~sû]F1ñʻϯþ‘Välžt·Vtl_]ׂhWÎ×V¼M\­|e¦ÂïsWgE²)šÜð: Àؾì¬|Ã×»7/)­ÙxÈXmyjVrŒ—ŠÌY£Ó˜±íXeö]¤ü«g¢àƒÐãžLë?=É;ãæ¤ÏÜpa²†G“ªòï[âbgüõtN]ýXüg_ÞÝ%kUc®>=ð#IÄÒþt|ŒÂí­yflÎ(zØXœìåöò’öu‰)O®DÝýñLÌ·¥ŒÜa!k¸Üš`»5y£…Ã.Ñïz÷4ˆ&wìúaSki‡¦Ï°Ë—²L¾ #~Ó™{¼«:Ï-ŽÿïиïÀÔå:æ8«]Ø”mbªñ©«nßTéìÈç5ï¯ü¿sc%WØí †„¶YÏÜþ¤K5ÛLZ23ñÕÿIŒÓ‚²c™Oz ñFì¬Óük3Óç,ôº¤žuaá¹&­ÝëzC :;Ö\<C endstream endobj 496 0 obj << /Type /FontDescriptor /FontName /TMCDBM+CMSY8 /Flags 4 /FontBBox [-30 -955 1185 779] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 89 /XHeight 431 /CharSet (/minus) /FontFile 495 0 R >> endobj 497 0 obj << /Length1 1307 /Length2 8313 /Length3 0 /Length 9095 /Filter /FlateDecode >> stream xÚ­”UXœË¶h±àîhÜiw—ÆÝµÆÝÝÝÁƒkÐà$8 <¸BÜkí³÷ÊÝçõ~ýÒ£æ¬Y£fUýtTjšl–ÎæPYg'6;H ¥¬%â€Ø9Péè¤Ü [g'iˆT$<­ ~'HƒW‡ • åìâëfkmã`”bú+‰ áu³µ€8”!6PÇ—€¦³…-Ô× áàÐøk†;@êuó‚Z²£‚@K[ €9ÔÚÖ ø—‘¼“•3€ï_Öž.ÿyAÝÜ_¤Œ/’L€EKg'_€%Ô ¨âü²ôÅäÿ‡Ô—õtpP8þUþï.ýŸ8ÄÑÖÁ÷3œ]<= negK¨›Ó§êBÿ%§ µ´õtü屮ÄÁÖBÂÉÚ `q³spÿkÜÖ]ÖÖj©fëaa°‚8¸Cÿ‡:Yþ·ÉK÷þöÊ*ËèÊȳüï±þTƒØ:yhùº@ÿdÿÍ ø¥In¶>CvÐKâËïßÿŒÿk1' gK['k'/âæñEåx)ÅÉÃðl,¡>¨Ï‹1ÝÉÙãe à¥3+g7Ô¿N•W”ùkèoâãxqþ‡@ Ü?Ä*ÿ‡ø9@ˆÔù½7òñ€æÿÐËzÿ!ž—˜…³ÃËuú÷ˆãEÁò|q€þyÿ"WÏ—›óO‹ˆÕ?øÙþƒ\/øgò [ÿÜ Í›ç…|]l Ú¼ŒýQŽãegöà‹þŸÕ_öæø‚^vòG©—'tþg±—\g'èás—Â/ uyy1δôbëö¾¨¹ÿ/3<þiìËÚÞ΄_Ì=ÿÀs¯?ðÅÆû&¾Ìöù_Ì}ÿÀS¿¿ñÿ^{IIg6.^'è¯pøx8ÿŸD O77¨“Çß–—Çóo¶²}yoP¨ÔuiÞÙB(Â.³5ê}LÉ·ªWLîäÙcÝ‘ÍÙBìûkB¸³nm“ZPŠ3œH;ÛjìŒCÅZ ¥Ï:I«DÀ¿&0rgŸ©(GéØbßÈîkÁ`?–c^ìÎå¦KËñ2Íå¯îWõJ{ ¾b’Ã8„÷ óçAöÁãëKhY–4[¨ÆJéPÝ)£wrÎ%ÎKe_‰Œr.ñž–HúW§í¿cd Ä(ÃÏWžÊÕ§3¾€¬|Ïúp©¡¾²ÕƒÔ¸+jÕv¸°~ÔfàÓ•ÊÐÓÃb·7àÇõ4{ GêÙ°ñ‘kÍ ˆuo}0ë¡ð‹¿ž©þzƦƙn¬=lÅß]J’Úe„'O­ÆÁ0Ój /„ÑV±Rö1„fæ]p]hÙ\»ua¹C\áÊW!‚ŒJUÞ;_˜6ë®±uDT0Œ°ïã˜ë‚X0ª•çžà4©NóxҵɡÈnoQüþõÇ©n75°ÛœÓ "óÁÍ¡Õæ«‘+‡þ2ÉUÿúùOì²\ç/¶9»ák QmLÌýFs®Š÷øÇ˜§ (ÝŸT¹ ŒE³é«û?-¬à1B)¤üï…e—ýÍ©2ÌxÎg\”k›!ýÉ®„аâù+@Ú4h I*µ˜wšˆL$FuxÛøôϵ?É{-Sj|ù(qûä˜cê\>¹9ÝœœæK¸žq8UòÉ:„…RAÓ"TÈã˜7úiv¹i ߥÔEï’ÊbÊ ssê&@Pa‡¦XøÑ7êAµK Mnïò­…Ö:Þ¢Ùƒ´Ý3’ôå2Øw@FmSÌÔ.ÏêèOš{u/ßmG"«ã´õzÔ¿µÛ.\@x Î ¾ñâ×?“WAú¸ÝÙç‚kX«šqq¢Æ[qWqZîÌÛÄÉbAz‹`€xtÐ]Û/ 8êÈ\‰³Ã%P$ Ž¢Ÿ1ÚnʤÅMÜõ¡*ü¤3uP«‹Wü\ ÿ¤lë0´M>üÚùsü»:©7òKÑ™¹•N­9ØzHÕ’VLÀËûã“Ðàɹ-lÖåwP};è,!ìà*« ñôoZ"Ñz¹.÷/fC<„l9žËú*ÄM'ñ{ðŠ¿î‘êÏÜ/H$½ž÷!ÉÓ ×"–Š…tÌsìåec sèŸóÊÂv_bW­:P•>A4@‰%ëDæû~«õ‚…)B.Öd–™”ä)œÃÃîôECòøãcÅî ôû¿u;ÉêW¥µûŸª¥>?ç^n·rÚMõ®†È¢dÐÕaÕ's}xö¨P~#ߣ¦GÆ"¯Îðþݰ)Íù·û¢õï*3ÒG¡$ÃÎAàæÑ¶ö‚àB2·,÷3ï¸Ñ†ÌU†ƒËÙô¬7WAz]¸i2 ” ”š&ÅÑbÂ_€SÝCµz,Fw0CïÙ°½Õ¾µˆŒÎXÚGO)‘¹IÔ±2PôœUn8"B·¢|Ô¶eús¤2 ኤ:Ͳȧì7½¸ÕÓpÏú0 0FÆM;87n\îƒ=‹h 6î?H²ozÏØÓ,ÝCFDKcÞ8ï5LÓÆd´<çJ‘r„â© ”â¤gAó£ºP'Õ( ¢K„s‚¯ŽÃH_c…° 1÷Ú$.7ß mq-'#''³TR[„Ãæk¹ë‚ÓÙ[¬Jƒ×«N¶6›QŸ÷ýFËcZ~²VëÓ¬¥Ö^@¢ßC‰Bcó}è8)-:àUÚìÌV§:}‡ð;gmVpÛ>©Z[ÓÀbÊ{ºæŠL)W^JcC‰XÎ4¤{F;sr”&ÅHïD*}^ÿÎ[+b:QY$ü‚ ±“V˜¢£¦>ªíØ.üÒŠe)é9–2b5ža½U®ó1VÑXw_Õn•Ÿ·×ÐR:jZUn?5–ª6ŒGÚ{ DYÛøË'¿¡² Ìm½iF]iLÛ {õζ¿$èƒ%Ü핇RˆLŸFéв·6™¹|‰qÁŸžu½R8̉ÅKÎëz«C1¨c‰?÷xnã¡hpDq èªäŠy¶›‘¥òÉX®w×.j4ÝQ©ÙH'=±Šÿxm‚An¨R™½4‡-ùë· û…’讆ó^}n±ÏçT‰Œi ¹±ÿP(<ô³4mL&Ieùá8O†«á5ëlÊ¢­9öŒ=ªyZ«Ü— >EæÄ«“sqÇR6Ë«¿'OûÑ¿5ð%*ö»Oc [Lñ¶ÌÄe’˜IÅýÓ·xvßý*RÇ- `݃¯Vß}†/ü=ºSm0uP k)i«Ù‘G=)TAà*ô^¡cÄ~Â7I1=`þr´Eþfb¹mz–øn[íöÕà­¼<ÍC¥ÈÜ*×ÖúÉl¿W…‘vî]é7ƒ[¸¥ªµŽÄ›»¯[î£b¸&ÑÖŸB¬ÛsSoBuì?(›ËžÜ©ÉeœÌç`l…¿ƒ ¥/N÷g®¡KÁ4ÎZÈ.Ik¶àkÏc]²ãóü óèÚßl%ˆý±oön"Žñhîd®ÿí ÙYá—î×I¥ÜÀU_ë­Ëû|])™<’*[&z-OÁçyß踟ؘ!¨"ËíÒ .µkD”êÎÉà½nÉì©Oïyó6Ò“Á¡& Ìhøå\›X ÞR¥“…;ân­7×°-0 ‡|ÕV" é+&dvž¿c}Ó½ÑX/>‹Ñý(¢ªQÔžÅ˜Ê rÉ9Ÿ»P{[ì:ª^®—éÕUm_yO¹|KQ¥"ööͦ¨j±%ÎÇUøìv0—ð¬9_tˆ1S}·®üøhý$òv!ŽÚ=ç` }ñqhõŠÙýÆØEyÔggã‡[¿§£Ò9fxZ-¿‹1-¿¸®C>e»áÏSÜr´7[,aýü%?ä¤õ€úÑ‹9Ϊ×ìþŠðN°“ilåg‚Ò—¨t™´KÐÜaÄTVÆfwí¼£®[ß@Câ)¹RÍ‚³ò~§lPâ× ñpÍÕ¼ÏäçŒ1x—­‡qn¶*Æ-0ØŠ»D!.Ã*.ð|˜Ùxåþ~¢û(¼ô]*UdÆC4aö5]²«BM°”K°$ð§à—1ªÜÈr  _)Šq}3•ŒÉ ,¯Õ—í²ÊÍhkTþhü—v„!ÆÑ÷Õ”×q®3ú’ãrÉñØVèEªFv“±~£Ü-d[eU"ýÉ>atW]¦¸Õ¼¼­Dííqì,EÔ\6¸k&ßÌËZJ7„± ã-îÓïø C=‡ó ǯ31Bªóï30#Ù;rUY©ÃÞ-IjßÄÍ‹?Îï¥U®+Af$L‚14Ÿý»ØP ½ü…Ø8ñ ö:Â($OÖs [e}«·2¯´,f¯“þ¶K?K: Éa-ùeÏ`}•{ÐC´Â’ÉM#ókÍ Â—D¤ÕI¢]Z°­·¯À(Bqd¾-ºý€Göê{éË8!á–ÃkÕ'H¥®u[ƒêZ„‘(ƒÏÕ< ‰tÀïÞF°Œ`:.qì½ÿÒQôf”˜ §t€‹ ¹i+¶¹Oí7›Ô2‹ˆ–ÊbÎð½‹>7›åª–PÉ65§IKgß-HÒJ5¦ßLÁWj¸½ƒÈézGžÕ€C) ýšë3I¾ª_¬ìŠ=]k]A°œí¸D­K×Å}'Žç­%ƲæzŸ…H!£O^SfeYšóÇÃ:ØêÅZßÚ¸tVì=:ߞᇉ¨ Ø.j&×J~ 6¡ZröÝ”T‹×®W5ÿ=øýÄÝó ã4¾ä»2îK‚ûØÝ±AÖ³5Ó%âOꟋÚÐãv™‚ìÍg|-탪ηM:äé4à ä£´Ñ”[ïnèåòŒœ“ÄÖˆxO‰œÙtf¼x¢ˆ£ÑÞ¬v…Þ³A— ‰0F´¨rÌXVP·—7‰“1prûëÜ?k×wþ&­ß[L‚(í!y}ëµÑs!MS†õ‡•ùÑòާCÈZ­ž±Ù#e¬zTˆT„ƒ¶Ô~ô>Nyxë(ÑQÅßÚQH|#9˜y­ä¶A¶ú'm„V ±««°F5óà˜½0)§åcÌ-RxOÉ•>I•/ßí€“ÕÆŸ-°B°Òkò¼•~Á­>Epûø²©’ê)Ï-ÞÞg&ª”@¸÷3…³Î–›¥6YCúGšØÌ#ÙeiÄgN£a   Ø`šÂç}>}Òé»/¼Š•¹œ4æ¥=ùéü&‘`|ÒÍn§-Ð kˆHÈB!IBÄ—UÀ‚ýžz¬*“í/«JŸšòSïU«?SŽ"ñZå«WãɈ¾¸4HØÖp¸ÞË¡—-S“)Æ5ø”ÅUÌ~áckfvO1«¼F_Tk³``¼)å5Âà“×+•høàV`8GŽ]eÓõœäb¤1¥IVª«ÑÑ\+N÷5‰)Æ&2†ç[“Œƒ1G}êI9^es實ǷvÖÆ¨®;}ýåZ8¡ÿEÈaT«ÁP˜)ÓÆð2%7n;>V‹ÜÛ@-.²˜¿FÆÓ»»ª1&q!ñ°Bä•¥LܶmÚ‰:·*‹x(~ñíÏô$óóß?:Ðié–†Æ:YåIC„íµsob ä¢ e½RDÒ ‰ÓNUîÆÅ,XÈ`³˜2ß Š-é8"¾ QÛ÷û™ê[ÿìAiÛsj½.è0ût¶xõFi?P…~@Xù›±2xdÏSõ±±\øÕ„¸¯úxa9­om¿ó¾5‡ d"¬&oº.s‚&¸M¹Ë<Çgbéû«Yæ(×@ùí"G¡‹¸”+K¡ª98ôë od¶}€›Àç†Yî(“‹Äù¡¢Qqüñæ™x½MÛ~Áo|”nŒC%¢— «­’üܲĆGD¶43”¹¸tw¯tú¨1ò›,ì•aÁ¾ÆþŽ\$ Á„¬›KÿyK¥Ô´pœßºÇ°K;/%¸ÚœŸ;wîê#îÙ|IÍX„âž\™ˆuÏÄ))#aÿÝý-9 /ý35q®”¡el×n õÍ(ꙟ™Æ‡~ýéjÙrÇôo‚*t^;°§„UÖ•ùñt â#¤¦pê?ß°k?¨¼÷ë˜qWWƒtTóØÎÝ–ú7‚2÷*„+uÕ~“Áo*{#ùN†¶®(4¼íøòOñ¾ZÓÑ¿¥YH:•¹7ËÀY˜ä›º¦”(ßeEÊUͰ&b=Ysn?´ ääQ;;å•­‹QEf÷-ù`ÆÖr–ûË=•â°1’\„©à4fuÀ¤8û›2$ûBñáµ ×}ÏQ‘ÛÁ˜µy•ÖÉ=Û}SdGä  ${»ße†ƒµ˜ŸÆí|^b;ýmVzC€ ص^zâ^4œÌØÅ¦:Iä¯í!÷†.ž„–Ù¼P};c™. ;„·Xï*˜)y}ÔÄ¿¸xg¦UÓÇ­L¼¯Fø($ŠV¶¯k Ï–¿èaÝ:®á »ž0<Ëœ5ݾjÕF10˜Ñ¥kÇ(Òkïçê ‰j”¾à¸þÁ‰!°‡LBî…Ó1SIÿñ:Þn¥þÒ/†“Š-½¶Ã·²gqìõçà¦~¶’Ô¥Ým{€u-°Ã# öžêï-õ }#ô=Îï=ަÛ~³‚}|q±ñ¢£‰êD{7é+$á²DªAõ—×5‰¹‘X|Œx9ùƒF^{þuÈä‡ÊffÞÎê[wòÖ¶Ìœu¦Î–\i7ç÷8sÒã*î¢bÕn•Æ4 Ï÷cž¹_u­eÈC¸ oCpÅiT*O]ÀÃT[HüµA†³¢j1é´“Ó0RÒ"¹A"‰¦|8LB$G$‰¦xL«ø?N§ÿ¤O‘›ê™9(¼[ü vVÁg2ÄÀB&¡â<¤åh Ibónæ~“_j22¢Ù?¶?ôë•Å©½›—Oùd¬40Êöœºbãd’±]7ªh#¤Td@0Pžö•¢Wá™Ò&7çbGò-Ð'%êçã«#c@o£<ëÛRÐø/rбw•òà7꜓O©ÛÙ¨¨…³¢»_>–jI“ í•xOÒ5ÉwákæèX« b à4Èá­^VµqNÖ-ŸÄmòt”A]fÿ*=×lÄãEË¿(Zm\ƒÊ)àÌ*`ûƒ¼0°Ø‘£K&ÙV }À)Tð—W¹~"XÁàk®?ØNkÁÎv{jhŒOìð•t̉+[f9„ïmîG–-É™6Ò¥î3 sò‰hÒÐŽ7O`Ü4–™UÛ±õGôËö- `±'×nšønN/ÚÊÝBÅâ+yàú™lšÌ4ÓÅÄÛ*õ\o‡!Ñq”î…f07BÕ“‚ðO×ENt̤æú9õüí1ªn ÄWf¸Ë¨+ìX <Ûf±üÝà„_MŽ+¯µéd+Û)É7Ï+é ¯ó˜Nü*;ÆÙŠÚÎ+ã ÌK½:l“0®amÕ·;¿½fÂs½ ÷Úº+Û\ãê¹Ïè¾0jS!he.‚M…ƬšUR`~†!Ø’GÌækõ$ŒÎ,mÖèµÎ›‚¬ÞEZ›©ƒK)T¬R‚‚­%n¤ÎÕFNáî Tâe§0aA?´à5Š^YOŠ¡´¨õæ"]šÄØÝ’M ×NÎ+ëßõùtC¨?,Õmv'VÛyééÏmê'È'´.ψζ ~|™šKÑ”µÓ2†{>hs*¯lCï1ÝQ­(‡Ëð$ºÙz>„á$ U|d¶´o0cŸRò€(+ý‡¢.ÄÌhös0¿E{)=%ßlrÃkécªªÆnW£²Qoœ#'Š~0¼ÄNµž,²¦n‘6ï¹ÿä¯ó;¯Rú`ŽQ£•™îŠ!Ëð¢dÊ f)⊗ƒ„Bg9Œ?BåüÕ³®0’ªLóDèQ»Ž°v$õû²9¡]iŸÔ9é¸ÒiǺ0hâÃÚ|~ã!¿;ݤsÎÆ?-ha„©€Ppá1ôGbùYS‡XWëé”vSf§häÖ(&𣙹‚¿ñ˜CU™Õ©·ò\9¯Ôr2”ºC¯5êºp]vä=Ž`›ð¥8|kè<®§S?ô>Tc#b9ÇCã­)@ ï'ƒÞ¤£­uÍxg¹7c'˜“vÎðÕ&šyHokNM^ùô}Ë’øFbpNIÒQÏs²×˜Ói¾ùu,𬞳[^‡:D@ພ ¬ž§ÛžkÝKv'ÆûI¡LvNéëf~B¼·†õÓ…U<Ÿa ‰Ó[—m.Äô+’FÂy 3•§Xt!±NWØà$¡ÐD’€$öªæ®EE@_¾"qXùèy‚ó –‘wþ}³Kö…VP!5ŠùL%×2ë¾Ä '•èvµö¬@ê¡À¦ô©ÉÈö§"iù›*}Ìu"âµD.ôÒà#1èL˜8û9¶ å€Óp©Í쀫,õ°-۾ܞ4E t”%é‰ìòxY×÷ ƒ,1„ÚÛðú¡þÈãf»‡l\Ö ý ŽçH$¸c.rñ1L$‰\í´²ß ˜Ø“©¬2 :!¢‹SÈÈ®×Íl ò_PNaƒó" Å'¢á¯>F|ÝT4 d ÔÛ 9EÌq8‚1b<CQ²2W”’Æ´);´yòÊ‘ðÇÅéÕ7$C3Ïüka¤µY3ÊÝ™¬¢¨‹¼»Ðù>|ÿ˜~*™g·•¹ú\· ý…̧{æ–»Ú‰ƒãâJÄÁ¾U…¶Š¯ReŠbP~ÁcºS"ůž ^s}Þ5º5¹7ÕÞ;ÏCVÝ Lmâ7p; žä§öÁ_nâ þŸ‘㿘u£?ogJƒ}vŸõ°ËhQñ?͚ǫŒó„ç/"“ð)H u®¨"& û¿oé±Ü¤ß˜\ìnUÒÁU¿ºóÇGK´Öš‰æ8t@>Z³I£Çx='È]fæÊNþ­˜×(æ ½•[¬éú×¦Ïø£rX *³"‹MË@1_JwHxkùgF³œ"a¨×ª,ʤtžCM@ –\ï=æÁÇZ—‡6ûκ3"ÆÈnBÛœ5¯_ÕÇ_Øûèw³ðˆüùÜ ØL ðÒðÕQºˆ'çÂô—*c®¥ éé2ц=Y¾âÙíL…a%À°¨ïãw…ä/X ñT}óê&Cm¤÷&ÇŠAåÆBÙÅ"·cs™[é5_«óæäNÌÅåMu‘öðH‰ÚWIv+Ã8šÒÀ0% ‘Î&;eM…‹Û׬0%·K­.Ž?ímrù–l*­±ðCöËGÛ?€¤äøƒ¸¨ƒË=ô+_#–/­v)W#nÄ(ì +!«O÷?vFµ²sÏ5n=w $®lôwÞØq«4äÚá(“ýLÅócV5áz âìIYù¥ƒpeœfÓÔ_°Ioµ Ó¯à¬ñ`é*mÉ!ñ/±E,‰éë«éAFø”¯×SŸÝÑúäbŸ£[.WŽö±ÊSÉ„«†ÒÆÛ·œÀÂ{ O6÷“ÊüFM ½BàhX¦'r«XÁƒìdr§írÂ6>­v‡Í~F^ÐÁî⺮›ïJ_D¾Ê%*2mP4ëð²Še¯Í‚/3;é:×9 âV”ëÒ°iÑ‹äyr¾Vñ:ÀÃJeµZ6˜½ 9„ Œ¡ÅuOlÆSæÜ|›'.{$:(@Û0Áx 9Èû’Ž>ª­úÞqB=̪s>„¨=-çYVòpUè=}a÷c¦º«¸ë†Ôí:¦`Qé åß8³}¯â0Æ&ñouÊÇ-‚Í-ÕWh†Ä? 'Àûùø?k^ÈÍÂ;+>ÍóÛÎÔ¶·2ò±õiW„yªÖú–§:xÜܽ¶Qwåên™$ÆPnÚ {˼¶ PDg¬Š‚ƧÅÑUŽgŒaщa­°G}›¯xë+쎿áÇü§+vˆ®0-tJHªˆ;¯­¹pðµ'ïuð$S-ÌP窥„âµ–oÈ~6ÿ´*¶ÜÖnI·üòÂ:ÖнzЬ@|ó¶8\ÍÕVm8¶ª(V™ß]놂³C'¼\Ü5TU_a€ kËhá ª’5fàXX·Ã*†ñŽmñâ·ûÕ‡MŒŸ$0E•‰£ËG5Üá½M èS6sá VݾnQÝÑ åuEƒ¬¨Ì W&À¯ÃUDS!ÏiSð*ÿ=   ]·âýœÇV®±½‰ÍBöNáÄ¥xªSé[J_F©9DåU/ï"| `ˆ°o¤£hܬ“Œ…Æžv–UQ¦B*Â9¸?GòîÑ|}:VÿQ¯m5·ã8³"¸ïÑ_ñÒ\ °¢( íÕsðŒíU3R5¶ÞIA*®‘Pº~zªm½©1ÄÅé“BCù:Λöx{!š±{÷!úc yä Nœýïå¡q+Ò¨TwAèIcl»"ad=þ93£5nI”Duˆsn"¯Ž–@¼ióYu÷† qXõ‰”äœ LÅÑ d ·ݯˆòºúÌøûsáï“fúWË««jéí !<.Ávö0²²w fÀû+´-Ðæ·¢`Õˆ0K¬Ãª>q¥h¸Š¨ñÊÓOˆoA! ý5lúaï3™iÒgDh=0WtÏ&qX®¬y¾G=¢ñFʧülæëª&¹ÀþpÒ üš‰†Vöa"ÇkjO£,%Üêæ¾ÃtæïÞ ø-w8i÷a§sµ Ub6J½ÿ‡t+ë}w´‡{ÃÛˆæ(Ÿ¾_kIR~ÏÆª-]øœlpŽØKQP-0­ÐtN¨ì/ÏÛá~´PÐÁ»qeÊ ¤` ­¸X4–'A§ÍP׬m{~ Íïb°÷ž¸òü=¤S³]*‰×|Jñ«~ƒí…ô¶(w9&+²t¼tÊîùköþÓá·3ø§Ôòƒ=MÄ} …ZÛˆ{â&ÐSK’šHcÉòœ‰|nN±Qô¹il‘×±8e 'õ±sæçz ï_©6‡— ¼%޳^H Óaw…ˆLœp™ë"°êKW ‡õœ{,û~zpQÔã7†}Æ / ·ŒU6ÆŽWN­¹:9âèäàý,îB±+p™#{û®s)Úã–„¹[ endstream endobj 498 0 obj << /Type /FontDescriptor /FontName /FMEWEI+CMTI12 /Flags 4 /FontBBox [-36 -251 1103 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 63 /XHeight 431 /CharSet (/E/F/G/M/R/V/a/b/c/colon/d/e/equal/f/fi/fl/g/h/hyphen/i/k/l/m/n/o/one/p/period/r/s/t/two/u/v/w/x/y/z) /FontFile 497 0 R >> endobj 499 0 obj << /Length1 1964 /Length2 12112 /Length3 0 /Length 13190 /Filter /FlateDecode >> stream xÚ­¶UXͲµ'¸ÛÄÝà.ÁÝ™¸OÜ Á%¸'¸;.àîw‡¾kí½’µ¿Óÿâ„»ªºÆèê~¨È”Õ˜DÍ@&æR W&6f6~€¸‚º:;€™‘ŠJÜÙèj rºšóØøøØ¢n–vV7?'?'7"@äèålmiå  §û§ˆ joîlm t(]­ÌíÁ=Lv5©µ¹«3@ÔΠúÏ €ª¹‹¹³»¹3"ÀÌÚÔ`bnií€Èò#Y €çßa37ÇÿM¹›;»€MhÁ&é`‹f ;/€™¹"‹"¬evòÿ‡©ÿÛ\ÊÍÎNhÿOûMéÿÉí­í¼þ§dïèæjî P™™;;üßR-ó›S07³v³ÿ¿YYW µ©¨ƒ¥9€õß!k)kOs3ekWS+€«³›ù¿Âæfÿ×xnÿrÀ"#&/®,Çð?ú¯¤2ÐÚÁUÝËñ?]ÿ©þ³ýaðxœ­=z¬Ì¬¬làBðÏÿþfðÄ$LAfÖàÁÅ :;½ÁWL\6€µƒ™¹'ÀÜl˜…Ùä ^ÏÄ`rFüç<¹¹,¢ÿ„þMܱ?Ä`ÿC¼‰?Ä`‘üñ°X¤þ€Eú±ƒçð‡8,²¬.ÿ‡ÀêÿX]áÕÿX]é?Ä VWþC`u•?VWýC`uµ?Ä `QÿC`/ìEóÕµÿX]ç?¾Ö,Àÿ'Xè¾tÖ.¶JÀËMþClì`] ó_°-g ©¹¹…ë_a®ÿ ÿû+úO7¶‡mÍ]ÿ«žã?ñÿ³ì×ô?Ä6c ²¼ÿñÌùOÄÞþÏ.ØXÁ#5ûr€‡a²³ûÛ3ø6²˜ÿi ®0ÿ/QîòNnàÏûÏðl,þ,Ûµ°vÿ«Ç?iÛßàË?ÁyË^Có¿KÀÞ­þì<1+/G+s‡¿*À1ë¿ìÔæ/Ÿží_ÎÇÜà)Ø™»¸ü•Òþ² þHq€•ÜìMþy-ÿr~VY@<‚[€ÌÿJƒ÷åø' nét6wø¯³ådûŸèŸ,'x3Žàë2û«x" ˆ lêϸÀâ.æöÖÿ}¸ÀK\ÀïÍÚ‚‡âbt±ú« Xé.ØŽ«•³ù_‡¶íêúk¸‡ÛŸ+vá~‹œ]LAÎïýÒ–VsœK*Ó¡Ê NosH׋’3ß”\ÇÚ§ÝH&häÙ¡ÜßøqÅnœÇó«vYM›¥Â{n2¦ !ñW™”óú¶ËULæ Ö&p—)¿‹cˆ¸à•îw d@çrW`€Wß×TÎn›ÆÈ>X§mN2_‹ ÁV¸¦ÃÃVâõ»¡Ro Ÿ®Ë_3‚!ÐjgØ×'ù‚ÍæAˆã͉…”Іk%×gÓöô‹wrÌ¥Âhwz¸4Ô ƒe€ˆoýϱÐÕgÉÕ¶/þ¢Ú8†Ó ãþmúþ™ú£@©•Uža–õ‹+'¤–3ýBíŠÊBÝ‘¹nƒÏëß'Úèyéˆ%¿ö]$€¶Ž¥_†в€73]ëÃ˸ڡÒîüçµc?ßê™á¡güÙƒ–²¶íÔ9Ì5¨+ŸøY‰4k²Ï} `>K[¹È¬µ‚„³Ô&4Wg0Zùðƫ՞’a è-¼ 1HŽ2.ýŒk ûZ‰ë‰ùzÌfÝò–gQP®ç™> m‡8¹®ô„‡V<ÛÖ‰Šã¨+ ²ZbV¢ÙOï¾Tò^SJ'‘¿^ó4“žÆŠ>Ï"™ë[UÇÍñeOZ¿^n@™§'ËV¢X¸òèœ\À¾Gó«959ŠŠââÿÎYZÈ}V›íuMöh#`È÷˜N`›9ÜûÙ½7§8š©'öaµJÏ}(^ôƒ¬Pz·KI¿5¥ÑÓ½=•(ÁÅ­8;C±ôHÞà!KDCËW³Î̳BБN MÄÆûw$¦xuº÷uA#8Bˆ¡¹7‹»V«]¬ÝÇ¡Dœý5¸žv—8…®:‘…ŽD®û9Ü䫉Yå¦L,ÑÝåEÏJ磷¢’•§lîë?vÓŽñx—cÏr]0rÑ”T& ˆRŸ«Üßž5yžYFœy\w";]ÏïÊ¥˜Ô˜4È4"y•äŠ4ù_£%²ñvße¸ n$—„¾[aÔÞsA+Þ©TüA19ö…ï¸~hñnÐöá;¸¼CÎK¥¯¦ÍÓPÎ-èá§Z·_iS{@…×§×Kµ¦øL,{š£8M•Ü’2Â~䜇pþ0¥;ß~‰º§èßLg0cÅ@°úíÖh0Iy–R3²ùF‘d:õȃ¾«µ†õ¹µ µõ÷Œ ðçô«ÕÚCOø6‹‰h#„¹nS%š§d;‡ã£Æ­D[ýÚ{Ÿ_‡–ðÍ·Ò=Ð8Œè9DÄu‡ ;KEVB”Ûó¦Îk.‡ö"Gy>[ùãíÙ~WŒ—ïÎܲÒw2^æ÷Þ3µ_VÕ¸¥ó1‰Uñ\N_ZGíäuîy¤ou‹úèØ1¾}R=_´2ŽÎ]jæÿTc‹Œ~Ù8÷È­@ðåÉg17„¶ÛÉÆ¾®õ®hžWŽËVÓ¼&ÎÛ`2]å磂µNw&?›>?H\ÛŸ¡Ý/aczGÖ7xzŸðô²I†»iôTÓ˜©xÎZ;¶¯Ž©y}'½ØÚ*¢22t¯™úûS¬'Õ5šê1ñì$ƒüÅ1ã€.=Ì#½Éó¼ìÆw©T/M­ò¾I1‘Cz::MŸ@=Ô,Äm¿t«š­\{ÈáʋΜÖḊœú¯µÊE“!ºø` £W¬ÍãyÄóÞþÇŒC ˜Ðˆ²GÄÉ>šÍí-F{\4ñ€ýµvƒnB’)#î-®?†ÍJ°ƒiB2Ùx”ûœ¤ËZ|b}¢*…LqnŒÉr~¡ÖÄj#’…{$iWh¹x½¬=E§Å@~fz§A>Îßê-9`‰]ú½“Sƒ'" ÈúàŠ´÷èé?éÿê0†YòÜXÀ2$XÄÀ‰hóȧæIé!ºœ–þø®J ê…îÖ^RÀjV6ÍWÜ<Ù(xÙ'÷ åéýÅNãÆc±Rac2ÕQP\ˆ¨¡hØ×] CªÂW¨naþ UœçÔ¢ïîórƒ'å î`.zú[ˆ ªgû•™Ç˜ÌÕõØ“r0áçÍèy›Ïg«¸äŸ1ò˜ù²ˆÝÔ^ô‰Ù–ÙÌö™„_±L_~ÿÚ^Ëâê‡Rà {3¬jÒ—qÖ¸ Þbyßë¸1…¦)ñUP‘÷¦á”i< c0OIÚÕÂ蚇úr\JÚ^¡ÎeümÀe¾ŒŠÎulŽNÛÉ ~Ja I¥#„‚p•Zâ±¾K7Üç²ÉpzfX`:G°ô>£ãfí¡ñ³$?ä÷¥‚ˆ]\³ÅùÍz›3¾ÇëÙ}!¿Ž^Ÿôêá`­]š Ìö¬8¬& MT?.³üŒQZ5Œ3ž¢Xdê[¹nÈ7ôî:cJùË»ËoÎ#¥ §œ&Ú×ËOÀ`rY¯ÂÏK8³%FwV.Ý̼Åóä<1 ÇPC²`è±p³þœ»¼›;é¤1ë•Ç\œ3ÜdçDMeä<ô§^e•w6™Ñý˜úNúˆ¼ÔM"vɈaô9~Wöý¡DË £Ê½¯ÏžÌËÙ5"?P1ÍðÄwõ¯’`ú—,+Æïª¼ ãùˆFioÊþÜ™n@þØi”9©Êy¡IGÇ,åZ:  ‚°Ï}”˜‚ZájÇx\ŠûXš¼©#ô”àÍ‘@m‰«á`Û³"ªX3@{ lÀLï껤Èé¯ÙÊF§#&Kfh‰7˜0½/kåß>mmkÛûAþèfv¥: Ñ6r,ÎíÖ²÷Í2 ?Ū§ëÚºjôAªâ]¿\J‰AŽê5ï„ú:—Tß'þóÉ{7ùЛ5¦ÃßÀýT}sÓ‰ùJ–x$†˜¤…¯ÂQtK¹Gì÷ZÕÚ¤6v¿½²¾«ÙºVQÇû¥Ä ö|¬ 15î8ñÁŠÅŠWËãÿœkßD~?–¾,ªótÆ¢IëGŸ¤½å¬‰eæuIÚdKÌŽé¡÷Óõž/ÿzy{í¸®Ë‹ŸÖÔ59—‘ÛåX¾ ªqžKpáü‚•·Û2¢¼âqæ§¢nE€x”‚9¬[¾[Ê£¨Ë…‡nH Ø%¦eÏWßÈ3*•Ê™¿x³Ó£ÄͶOø÷¡Ór •ѰC¢)õI‡.{§]¯šAeV4ßwŠ 0 ¾“Ä&NH©&¢6RœŸ$+IR£ÑHÃ<ïV¦Ý¨EÅâ½X2ÂêÑ=/ñXjÐÜä´¼­Ô«OdrHƒxG‘÷SŠØ}Û)}•Aéb’CÿXºFB tZÚÒ¿­§Þ+œrQ€·«ð€†¼u§ÐµÅ«Ö ªŠqk¾P€hU –«ú…Ù·&:ç{«L að Åx†OgVb#’Õgòƒ™¤KR›´…š¢Ù¼ æ-éØê’L[3 ¹î¨Cfl5 lJÓ,zó&ò¤EîÜôò ™Ê'#õR060äÛ3iFˆòÄÇû9šr½c¥Ö{síRʲúŠl]d¯¬ó†ÈµV]Ÿ3 5ÍÁÜvc9fùµ€çÄÃù1+ ÆW:T˜ò"l÷¢D¾Ï6‚coa  C¬[$SÃ}¥^öi¤]ö]…Ð&¢ ßQ“‘‹7é^M·0Ü4åá‘r#Þ‰ˆ–M]˜YÏ¥Kv͸y~’«ÆÛÊ“HÌóšg1äK’I6þÇŸ†Ûoªˆƒ+RÐZg°É¥«aVÚu\ö¦DQ<§Úžˆ³7¤/QZy}5/ŒÝ2}(_³GíÒ±ŠPé•W˜è÷†}HšáVuã•c71<ùz­â}Ó÷:PXT6Ç“ªÅ¬È«DýȪv;]é.à|&z¨‘iósŠ‚ØæãÅ¿'_–pW¼Õ)ô¿v#¦—°p‡SHMÆêµg°ÅˆºØÕô´¦”oÙ8ªÞÎxýÀ…™ ®:îëîhf,÷qgŸ²±UZr¡¬µÚ[·æ’Â}ÞNHm^¿Ç¾-ÖâçÅ F)o«Öè?”ªUÚp <_z4ìàÄEÇ– â”ò'R4ú›LHว°¸k ‡güÒõÅ»p¢ëšš/vÔ¢©Š =õÜZ^#ó™¿ŠâÌó<{Ç;IÐâ N¼9‰6&®D?ÄWU–»ÞÉ6ÚzN˜þþuì©"}/Ç×LeÞ†I–n÷Zªí«rŒåÎ2{=d¤S!T4Äl bÛct©¿¶™N8Þ–it´»3­\¢'ÖSP’4'*e²Y‚JD}RYŒû"ÊgŸÔ^ †™ÂÞKXË7%–û‹|ißž5®EÊŒ_Ãm«(d{®ù]Cg}—!ÄШ^PAPǃW´ÈUòn T*ËëBùüómð|®‚ g Ê΀ܺ‰Ê Uã ©Ñè/”XsOî/?k”î*oÃÌ«È-Œ¥¸ÞdB?Ø6X­oC¬ÞCßUy#o8ªÚIE‘’ï )Yo²ñsF¯XªFFl¢ê…‰Xûµ›Äà§,‘„Hôª »_IÔ=S§‰Ýq›}>šV'›’^‰>œ =}½{Ñ+ãÚ\Ps¯ã-cÞøÎ$ΖìP|=,LÇÉ)쇵'„½Õ†ˆÍã{_o‚ PYï9ž¶Ž…êÿí‹Ä&Æ)–âGq…"z9t¿È.?aѰwɃRˆÑ#š#ƒ¦è0ŒÐÈ«žìP4)è±sàó"îÉQ xÉ?AÓOœ"ëˆ ^ä˜$0wðXôk¬ÞBÀO!FÜI.fdŪÿâûAB½ƒ!G—ÜEMå' ¨ö_'Ð6ã’-°îÚ½9Æiɬhˆ¿ …¤¶!NÐ5hmrÞCO9pÿÌØð­x¤+4×Гï‡F=^:dUªéU„šW2x?¡X8˜pP:‰©ô‹±s®C”Úv…È.tRÂËJA“ІÏY­Òø¡ iéØTuÛpBÚê¶ò2¬8û¡w¶K´…ap,&@‡1ÈË&¥pT®„ÞséÉXàǦ#5¤!í”\j)V³ÞAl }ÿ™s3wœ|4(Ž`»!&0öwX§ÑA…<ñæ}‘° âo¸‰ õ¥aJ&;'Ûqe訔d㈸§p]ñ/@35ÿ-ü½µâ½ë´öµèr„BBu¬Þ+YƒÅá»Ì=Ÿp(ùë¤øg%åK5Ç3áÙÏÊI'V#ÍÛømèƒÉWYX©bxùÝú?ßðv»2"uzƒ¦¦:ãç“>Ѿ%p¿E–°}X*C¶©ïVÂ8† 3OŸ²,÷ /OüÞD0;²æ:Ò=Q  Š—šûòB³—à¯!ºZ2'P›7Á2"”öŠÊ¹y@J—ÚEÉM«êU×MÑxHe\¯YÖÍ%)Óì¬=¯\Œ6ü¹ Ì¢üa¹ø6üŒµmîTAdвPDŸDÂk¿hf‡5žx‚}ÓcA(Í›à óÁŠ@£µ˜±Á6Á;#%ÉIí)<ótçÎdÎ ê[ñ}—Š.©ëÄb‘G‹¡ß\`ùÐ…»Z.3¹®]Zq)µ'þ· sC³îsö‡@MjìÆ›}Qf½†ÀZ®×sP…Ǩûog3_V3ë·UDŠQûpwç-€:Ð’ñOÔ%¾m’ËÔé¨SÏ‚¡\?äZpZ*˜ú^æ^j«ºŒ¨› É?>Qd˜"Ë#N¦ c±“cfåËÔîz›ÊÔŽI³)>ü4)´ú 4b¸,yâ«eMœ‘$×Ïežuˆ#ºÑÎùF.Ö¯ÑïY6¸Ë8¼ó¨}4”58PJCYï;ñ‹Y öñ CU’®XáoéV|Ù£Øç£½„}+GæÖ•nJ´¬æ—MM7ÇŠ"¯îµ[~qüð9hå}jÒ”À'š}7µ,) wCõ\jÒ(Š\òŽ›¬±M$œufªSH´›Ÿæ¨]«Ý[n.ì; R†Ç”=oeGÝK&¹Fé. AE­c1>)Ûvå½ñ¾Àµ”É qô·Ý{í´§¨žWqêËŸ¾×¯äX†\õ¡î§â1$Ù¿ÂSÍ&š©neü®Æq#P»dé7a6æ2ôœ£ˆ ÂÆBÕ[ONyïÖáÐËèVè ô×ý}„öÒiF¸ï(´w_‰¢DРណ ÊÚ!̪ç‡Ó¹yÝ)aûËõó2^€¬4ܱË3,=IyÚÙ©«Ç…âŒMs ±YÔG§bO¡É³2Ò5ñþNID (<”¥Ìš¸Cõà˜›s&³A ¦[ÛžS:ˆzŒÍ±“ä”'9ìŸ*™Fg¼Ží5jÕhß2Q÷ÃáûbÌ[TÐñ)ÅãÖƒ*ÿÎÌ) CÙ$i¥ê×ù×L(§å™×ó>»'ò®Y'ƒfáÄb¿ðË÷á5›@‡;í÷•ÜÂcì²È|Æé±8`¿¿'éÐk‚œ¯ 6=l@¨+^%6ñÆÑIQG?FÑ»WùPí-}ÄÖðS&†68ŸÒÊiDo' Å®9Æ+^¢FûIÚ×cÖ5Èô}ýÖî  —®‰eMÁ*&5Ð'¿¿Ï"atp3pPëþÅ·©!‰ŒÿT!?‡*7›1NZœš‰}Tå¬T]+u‚œ=®Á8â…>»+»\»?Ê¡´Ùñò ×_)ìzj,Ƕå¡òKþ5· Щ\ sÓùuÒœÊY&•$é‰ÐÉ/xžâvæ+WtA&ÍÌ%þ ~…ð>jä53Qü#V¬˜Ôêèø§ÒòÅ”×] ŠxÍF#îµqñ/òlkYaÞ†§sÊt‹vÐÅ{–ŠÐCWæCðe¯•9~Ø(ø_øéêxà³ FwÚÇÑøô™wyï4> ÞÚþ>“·[J‚è¤X§½ÆGÛoÝcÚ@mP¯Ý?"ŒÃsýMç‘,šfuú“ËHºDP£ê°.Y‘T «}¦;aŠdo¶2Ö¾)ä!ªï2ÐÆt;â(Ú?°µîZW­à¥è÷ãÅ~Ä+íÁŸ­L†sÍ:r£5xv6ˆÓF°:!µ&¡#úÊÔe—âÔÐÂØrQÕS³#vX|î[ÐÛFÇkƒY«ìsßÄ}SCOÈ´çã@†¸Y¸¤Îbh™@¹›ÒÅÖr¤•-!1Pßvâ)½ôúú±a5î¢_°¶6çÒÁÀ4±Y໽'Múa=”»ôÔâüwÿ“ XV!8Ú-­4ñļÁ'ÓiWé¤;ãïÊ7_¯Æo»ñãT£¿ó*$L¦ÂYW3Êd оýó\<Ü.ÚN[ _àÀ9zèÅYAz ßtê䔯¦µÌð1ÃȘõØó.W’ØG0tóë~û´î-ÂÜï˜:ñ‰ì|çÒƒf èä»ðIw{ÿî:Ó C¶í·œ÷¬K¢fŸü˜²âÞ2äúß|êLŽŸiiîI6C(.žçšž?ëóÙ¡öµ_{_È+xÝ÷V¸ùºB÷»žý-zLA™²%ÝÞÊݦöæcd2ö2 l¥ÏŠßnĈcÍÖŠç¡^jºütÙ§êÑò >=ô,á`þÒ Å l&oxÝ·á¶®2] í{f B¹EjTÀ•ô[ˆd~›Ö©Òv#‡š rÙ¬†šQD!¢)†l»U¢§+p>¯ÖK»;;é-Ýaç‰ú;¨6cÛe‘`i!²¯{Ø3A€}BT•ö©†ñ@n÷WóCÂb¤¶s¹«Ñ±kàÈiN Dè½UñÆë]TWDŽ¡!’ŒùÞFvÞ†ý ¿aÁÒš2ÁÏvû©îI'’ÞζB&tHÞåR®/–©äÀ炔ݸeÒt›êÛ™ï tŸ¯Æ8A’ÊMI‚è£ßxJÒ~ÛIíC¼ãÐÈZ]¦á„K…ˆJ¦¢Üõo›ÌK£ª”{.Võæ§|ÐK‹Z–Æ©®híe?ÿœq¹„GwíwD?ÕúH#‚š9AYé–Z¿^³xâb§ÅV'ßP›…ͳ4̨¦.Xº‰¸š†æ)ðˆÊŸUÈ‹B]Õ=Ê,Í|(„ε/,;¥¥z×¼RÚUÆ®sÌ$P$*×ùô*æa;Yˆ_7ßCüÍkë«6¬Ë†­XjS hOHG§b,±¸3>—XRŒnŒd[u^ƒÎ¼½-xÎEZÀÈ–VŸ»³ÈdeõEÙÅË2$îÓ=• ¢FânÆ3„ƶZtÂ<Ù.Àægþª3Á§/6í¨C}{’1û‹„Lj/sj%ìB?Ÿ >M½R}·J¯Kðæ)GhzhZN5üöÅäÊËè;£áÂø¹gÇÍ€¡+ø…ñò4Óà;…Þ45/ÇwáÙt4˜U1y²Î{¤‡žxÀ>'ïÇNþhJéµDï’ÖŸ¸€&–ãl¡àÅ]ŠÙ-wXÁ°Êr~ LµOš7‹$Ýâáá}Cè~h´ÐƒDBFÜÞ0†¡yV]^E@A8‚ûÊ—¨Šôíë³|9¨2Ú­X ïÖFƒÎÅz~ß&‘ÄŰŒˆéx„1ÓBTãI! MoÒ(a¹WgƒØŽf+›ƒsÌq3e4¥HsS@>U:JJå”KEyÚQàÿ {V''2¿ÞÔµÂNòûºDZ*Fx¦ã Æ¤Ï ø© ¿Ë–F­ãi¦'Çé{9CQ•ˆpS@‘|IV¿ÒœÕ ³5€s½*Ëæ/¾ÓÀQbLШÚîB‚Šêdªoüî„Ó[ÝH)qf´œëa,ðèÏ–‚ ø5í¾Y`HàI}ÓõRoäVÒP°!Ž!ij^ÿ‹5>öËN4Ïù͈Նóïù±=ÅüooB»o𶤥:ó+ûüÁ#ÄêÒþÕF@$XDÜOŒëSV¿ºƒÃbc{›)~x }VØ+Tåc¯ïð9Ef’Y%ªyä½}õÕ:§=õd’â¶(ûÐ#Æ»HZ¿·fAE·«é5µp]ÞuÕQh›— ùgr:IWp0¼ªÄRÛµ˜F2'£9&-#¡‡,ˆOo™ù“RŸÀ:jQ U5ÍéïPBTÏџˑԒù^Ø5²÷Ú—ê¬ÑÊ?+ ´rË>¸R¶ pËŽ®,ªG°_”åð ¦ï!¶¶sí‹pzÆ* ®x.n¨r·-9|¿äF-AH.{: ™)2™ó>Ì‚hoAžo¼z9ŒYvsdtx¡4´¥1®mâÙÝ\xòl báä¡”jß÷ZõŠMžù.Âuª9ø˜‚´Cì{ðFFFÇ­8ÇnWÅ|_^+TñÆkØÉM²O«ÜŠð"(‡öyÑA’ÂÕÑd·däýpÈÔÿ€¼Yù“Â!KÑË5Å+µÎîÛmn[¯ŸÜ’= !D óÕúæ¦ÄhyëœðA5Nq08Éåv¡ùÖÅh¬€Þ¯PØ‚C4þLy¥žt5Žì"ˆPk‹èÃôÞŠ'ž|;V£áˆK $õüÌj>0¦^€[–›×ŸCí«¹4—ƒëwýë¬kä)P!ÏØµÂ3c"°òS¹Q»•T{èÎù¼T«Ãw•ÝÃK}4þ]HkU)@—ûÖ ƒyúHç/p¯¯Ý’U¤7Ÿ;n9ór°¶á¬Mpë/ihW†ÜX$΢9êCðgV‡®ëˆ 奷0!’”09Í)=¶=¶^EÓï—+÷¿9ŽÉ µÁ8NÓÑ_'¨…ü iü+Õ d‡ã YÑ¢s$Á~9Î8Ø›°½Ýu‚”È Îÿó`5ʧ¦çûwhOz€àЦw-ìÄ>>y>™‘¡%Œ[NÎGÆQÙK.ÔåÔ_üð)÷JŸô«Y«¤n~”p~Á¢ŽÁ¾Gå4X—¯r_”Ð49;™¼c©Jmð2 åǶ<1•›j¶éÌ·¥A‰l->±¾ÝvCdâÁ£ÂÆt€22¡kß¿F^÷œÂûüB‚ÆÒd´XÖq²Z¦rnà,rÄÎwÞ9ƒÍýq«¥Ý¿gCÐ͆Úu¼²ô¹¤ôm0ã!"ºLw÷="‰ØrÙåØk¡Æq²ãº’|Q[â†I„íÐPSxÖë¸+%€ ©B”ÖFoJäh§u'ï\I‚ia³1$åÍ"ddU®é@ú¨"²ÕgÑ›n%›ÑÝG(ëìûäû ’Sc –—˜|Z)¹×çN.áS™n+–ã; .El‰0ôe vH˜3·¥!LŸ[8¶«ž$ºáuŽª8ˆs'º)1íUSã¹`·u"wvUëµoðíY …îøh àL‰Þœêߊ.²{EÐ@SÔ×€=Q9)RÞ5óªºés]¤M4\ÏýòôñWëæ¢.Gâ ò³¾ÚÑŠù|X±V4‰#ÛxTôÜÏeÊ,þØ_Ó†ïA _O~iÌ­S±ö_9Íu†lí™r(C°fÿ ÛzÏq ´ƒIs†¥…‡=Lu[{ÿ,úT±¾ Û6Ðh¿OTqÑœaâzy,½¼U‡…ÝÇw°E- Ûeñ± AÎãUX"¢«zG>¥{oH°(}I_\e3ïïeú…÷ÛÜ{PP¤ Ä÷*â¨4c3!®÷[Õjõ¬Ž>Õ‰ z)ýU§áþé $Kædp™ç8eW«¼*™ScLª$:o&Ö%°d,ÍûOÍÉ=`ŠŠpz·W1H9tÞ”Û^Ô7>gÆí|ÿj£^ûŒŒp½÷ƒµ ³„Ž zÕ%ñ°K²XácQš×â™^Àë2[šíÆ&.±›Ù·+ÒÛ¬²Ç:1üa!G;8¢E»®d×£R•ÄÁdÉý†¯çMok”Sü#‹úþ).Íe1Fô »Ü/?¶Óèà0ì²k›H LÖ5&P }NŸ"=.» @'0ýìðæMЏü¤mÜ<ÏàÞÀßûø6ü‰Æ›2„pPikè¨ú]”¼g-ØK~´WÞ2è9džà$èá5;Bd7+º®$é'Qiû„V•P j/È@ç4%¾G)ÚHÃf—ŠZü¥…H—6e“~´äÉŽûa@â˜K!}L]Ûùù†3"‹ç ¹åÛ{]kÔéÌow=w¦«¬Ý Ä ¬×ºx)¾ dØ&Òtët‡†³uš0Õ[V6¿žàA¿TÌÞˆjH.4†.¬‰5I¾„¬~⼎ۄ‚ “Ãd¯3·tú±î-„j[ñt¨{„=Ñrw3LÝr‹9®á%MS3 ="zøDç2•²ºª\Û(/УnÀÖÓVË–©à½Þr2¸“ƒLÛcõÞ@T¶F\5fjú¶•Ù°mAQzê-l:ÕÊ ŸÀ 7Ç1 p¼·¡Ç8(³,'«U¬àå¥WEܹ¹õvê´@¶:UVw¹Lßñó‰ªÑþ …CzÓ÷[™’ žu›Æ¦¤ µþûìQ¥tP‡© —TYçµn ¯ú/Å,Ç­o(GxMPèʼ’úÛ|i~‘JÔ•ýGaWVÄß Y‰„¾Ž( ’—: ¥4ŠyE—:ŸòÂÓÚÆ%U N«EŽDæÂK«OµÑ`äÆoÀ=3éM'j=‘¡I•”,¥jŒ§Ò^êS)í3Ú‡-¾­v†®ë‰½/ìZ§ÕÈ»þ4²×îù`OÀ1 ÈרNÖC¼?²€[eÍ‹\T‹ Jìdýeö^"U´ô‡1<Þ¾å…×r9üf»d3ÃdÑÆO²“8w/!­jD§ÉÉ}”ƒ·8!!IßIûBx¡>cKJåȪáϪ9=ù¿×Uv\lÐâ%æ²;º¼ÖŽï¼}£w ž+"Fgе¤5רÕì6ýÙqö4²ù¬ùÈãhìò”Ý¡v‘¢_眊 ‡{ëš&wÖw|jÙŒÀú S‹:çI/nX´/™0¬öC#ˆ8 @¶ÏB@ o|®j›xä/ÐΖ9­ þ ˆt´µÑ†hñÈC–^Gˆ­ç®LFSÍf¸úóX.4ÀZ©Y¾ZÂêŽL/eõ'Qðs…e%Âþ =MÇwjÄ,\÷س>Ð-¡4ý^föÍÔ Eçl_‡7èrÉv,)™y/ÓíÊ=VCØiÄ]% ,x+$lêIlÉaOæhÚÈŽX·õÓ1À6zGH,óKþÚŪˆÉhhi«Ï+þ½—•¹ë„6¨ü˜(ö+Ñìzª1¾Å÷g•'çÇ™·GOÐ ñ"b¯Ð>VªãO¾ò_\µ üò†4WT¨úZX#¬÷ñùmV¨ÓØêNǬÒ&ÎàPaÕ>[™‡Þ³Z‘é¼íæÃy¿cRXY$©ÝB@7‡×²§4±‹·Ó‡æ¸q”âó¾Q¦þ^1Ë‹>ÍϤ-'"_…rþØÞZt›D[0½׊ã衵Ÿ|A•Àoæg7Š£ð¾-pßoÒ¹Ô³p| GÿD<#¹?ªYRR¥<<|KDn"öD½R¿¡³éñÈ-!²é¦œqWð1Ž‚OÒž†â2o}±²Ò÷Å2´H>ñœgŠq«sZ¹¤è6w|®Ä3èÃ\ÔC6©Ð”¡› 'Î÷lqã($öÞÕ9ûi;úŽm1BÃËË Ó¶ì½["ÿ­ŽÉýº–ºSçó.×oç®#Z¥™°/ÒØÆŠçï+Jë¡”ØÄ&¸3ïuü¿%%}©€`‡Ø$ÌT³†è4@U†žK…cÈMè—¸/÷ëß›ìÅû¿l%à1sÀ¢}B2ž™Æuû Š#ks~¥;X6Çx/ç}ž1’‚qQ;JJ¬¢cž&o&Aw‘Ôò|«ÔËXA:P¦„…wšŸm Ðµy!ÑD´„”|éd¯”PùZ_0‰×~NœÐú2Œ¯ŠøM­û”I,ýz“-â祾ÖÀï±?7Q'êÑeC¹J,û‚!Å€<ŸÂËÈ;½".¬—¥[Õ·‚^ŠO$cÒÆ3{Ïï±2Y’÷Ük,oóT&µ ÄÞ‡Ž58@H!øÕÜ$c4RlòHž¿Þ`»ö9«gÌ ºêA'WޤkË÷kÍg«‰Yω×jеܧ]‰åg=àV,2º¬xú€¡Ö·è;!P¯¾¶èŒAÅŸ\`ÈÂóöÅCQ//VÁéÛP3¡W[‘Ó¶kbj `jR‡HÖ=ô=bˆhâÛ,Yª×Å£ßmaý 3Ñkþf !©´ê¡\Ò`GöqÓD/O xEås+z~°úOéÀ¢’LÝŠh4z1ò÷‘ ½›¥?¦ðJ€H÷U±ÍDÌ:X{ìDY~Ä̬@ºñôÑú$ꬋ€\ºödWò˜¤cµ¸l í?‘Ä^¡|¯®yéú‚DdýñÓ ETy-!Bþ©‚k~`jš°óFÌ<¨£M^¸Ý‡™”¿Ð̯ñ¾Öæ9pŽWºæ@V»úf,m#îK¡èF–Ø™ßwŽãe øn‰°äÇÎÛwçî¬TµñG‡¥biÁ¶]·Ÿ®™ózÛj™m|û…|»O”»µ0Ùâ‘3ùÛ¼ïÁ­ËVWC”<¨½¨ :Ôˆ6P3ñ ªƒ¤IÉŸŒà³$‡eöÆ$ŸÇ•ŽÂ?@׋@PD.ã0Z©Åªí9ÔSäùŽ­XÆZG?ÜÑèÛ^waœíýÇì÷¤ü!mÛx›Ž¼Ežú9A ~ÍŽïi½vNåWU»³jÖÀ(œ%'‡êº\¥I°EÆ`“0îìóÍNPšu¹,[Ø{Úþ4©VF°Ö²o èöÜ1\Ï#ÆLÔÿÿBcùŸ endstream endobj 500 0 obj << /Type /FontDescriptor /FontName /HBKCPJ+CMTT12 /Flags 4 /FontBBox [-1 -234 524 695] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 65 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/X/Y/a/asterisk/b/bar/braceleft/braceright/bracketleft/bracketright/c/colon/comma/d/dollar/e/eight/equal/f/five/four/g/greater/h/hyphen/i/j/k/l/less/m/n/numbersign/o/one/p/parenleft/parenright/period/r/s/semicolon/six/slash/t/three/two/u/underscore/v/w/x/y/z/zero) /FontFile 499 0 R >> endobj 239 0 obj << /Type /Font /Subtype /Type1 /BaseFont /GPEOIN+CMBX12 /FontDescriptor 478 0 R /FirstChar 12 /LastChar 122 /Widths 474 0 R >> endobj 405 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VPNCER+CMBXTI10 /FontDescriptor 480 0 R /FirstChar 12 /LastChar 121 /Widths 465 0 R >> endobj 294 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ELNVRF+CMMI12 /FontDescriptor 482 0 R /FirstChar 58 /LastChar 122 /Widths 469 0 R >> endobj 304 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EUFQHP+CMMI8 /FontDescriptor 484 0 R /FirstChar 59 /LastChar 122 /Widths 467 0 R >> endobj 200 0 obj << /Type /Font /Subtype /Type1 /BaseFont /KZRWDG+CMR12 /FontDescriptor 486 0 R /FirstChar 11 /LastChar 127 /Widths 475 0 R >> endobj 199 0 obj << /Type /Font /Subtype /Type1 /BaseFont /WECPER+CMR17 /FontDescriptor 488 0 R /FirstChar 45 /LastChar 88 /Widths 476 0 R >> endobj 295 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IMXRQI+CMR8 /FontDescriptor 490 0 R /FirstChar 49 /LastChar 54 /Widths 468 0 R >> endobj 263 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IUQWOF+CMSL12 /FontDescriptor 492 0 R /FirstChar 40 /LastChar 89 /Widths 473 0 R >> endobj 277 0 obj << /Type /Font /Subtype /Type1 /BaseFont /CZLNDW+CMSY10 /FontDescriptor 494 0 R /FirstChar 0 /LastChar 114 /Widths 471 0 R >> endobj 346 0 obj << /Type /Font /Subtype /Type1 /BaseFont /TMCDBM+CMSY8 /FontDescriptor 496 0 R /FirstChar 0 /LastChar 0 /Widths 466 0 R >> endobj 264 0 obj << /Type /Font /Subtype /Type1 /BaseFont /FMEWEI+CMTI12 /FontDescriptor 498 0 R /FirstChar 12 /LastChar 122 /Widths 472 0 R >> endobj 278 0 obj << /Type /Font /Subtype /Type1 /BaseFont /HBKCPJ+CMTT12 /FontDescriptor 500 0 R /FirstChar 35 /LastChar 125 /Widths 470 0 R >> endobj 201 0 obj << /Type /Pages /Count 6 /Parent 501 0 R /Kids [194 0 R 203 0 R 236 0 R 260 0 R 267 0 R 274 0 R] >> endobj 284 0 obj << /Type /Pages /Count 6 /Parent 501 0 R /Kids [281 0 R 286 0 R 291 0 R 297 0 R 301 0 R 306 0 R] >> endobj 323 0 obj << /Type /Pages /Count 6 /Parent 501 0 R /Kids [317 0 R 325 0 R 330 0 R 334 0 R 339 0 R 343 0 R] >> endobj 351 0 obj << /Type /Pages /Count 6 /Parent 501 0 R /Kids [348 0 R 353 0 R 365 0 R 376 0 R 380 0 R 384 0 R] >> endobj 393 0 obj << /Type /Pages /Count 6 /Parent 501 0 R /Kids [390 0 R 395 0 R 402 0 R 409 0 R 416 0 R 421 0 R] >> endobj 429 0 obj << /Type /Pages /Count 6 /Parent 501 0 R /Kids [426 0 R 432 0 R 436 0 R 440 0 R 444 0 R 448 0 R] >> endobj 455 0 obj << /Type /Pages /Count 3 /Parent 502 0 R /Kids [452 0 R 457 0 R 462 0 R] >> endobj 501 0 obj << /Type /Pages /Count 36 /Parent 503 0 R /Kids [201 0 R 284 0 R 323 0 R 351 0 R 393 0 R 429 0 R] >> endobj 502 0 obj << /Type /Pages /Count 3 /Parent 503 0 R /Kids [455 0 R] >> endobj 503 0 obj << /Type /Pages /Count 39 /Kids [501 0 R 502 0 R] >> endobj 504 0 obj << /Type /Outlines /First 7 0 R /Last 155 0 R /Count 7 >> endobj 191 0 obj << /Title 192 0 R /A 189 0 R /Parent 163 0 R /Prev 187 0 R >> endobj 187 0 obj << /Title 188 0 R /A 185 0 R /Parent 163 0 R /Prev 183 0 R /Next 191 0 R >> endobj 183 0 obj << /Title 184 0 R /A 181 0 R /Parent 163 0 R /Prev 179 0 R /Next 187 0 R >> endobj 179 0 obj << /Title 180 0 R /A 177 0 R /Parent 163 0 R /Prev 175 0 R /Next 183 0 R >> endobj 175 0 obj << /Title 176 0 R /A 173 0 R /Parent 163 0 R /Prev 171 0 R /Next 179 0 R >> endobj 171 0 obj << /Title 172 0 R /A 169 0 R /Parent 163 0 R /Prev 167 0 R /Next 175 0 R >> endobj 167 0 obj << /Title 168 0 R /A 165 0 R /Parent 163 0 R /Next 171 0 R >> endobj 163 0 obj << /Title 164 0 R /A 161 0 R /Parent 155 0 R /Prev 159 0 R /First 167 0 R /Last 191 0 R /Count -7 >> endobj 159 0 obj << /Title 160 0 R /A 157 0 R /Parent 155 0 R /Next 163 0 R >> endobj 155 0 obj << /Title 156 0 R /A 153 0 R /Parent 504 0 R /Prev 119 0 R /First 159 0 R /Last 163 0 R /Count -2 >> endobj 151 0 obj << /Title 152 0 R /A 149 0 R /Parent 119 0 R /Prev 147 0 R >> endobj 147 0 obj << /Title 148 0 R /A 145 0 R /Parent 119 0 R /Prev 123 0 R /Next 151 0 R >> endobj 143 0 obj << /Title 144 0 R /A 141 0 R /Parent 123 0 R /Prev 139 0 R >> endobj 139 0 obj << /Title 140 0 R /A 137 0 R /Parent 123 0 R /Prev 135 0 R /Next 143 0 R >> endobj 135 0 obj << /Title 136 0 R /A 133 0 R /Parent 123 0 R /Prev 131 0 R /Next 139 0 R >> endobj 131 0 obj << /Title 132 0 R /A 129 0 R /Parent 123 0 R /Prev 127 0 R /Next 135 0 R >> endobj 127 0 obj << /Title 128 0 R /A 125 0 R /Parent 123 0 R /Next 131 0 R >> endobj 123 0 obj << /Title 124 0 R /A 121 0 R /Parent 119 0 R /Next 147 0 R /First 127 0 R /Last 143 0 R /Count -5 >> endobj 119 0 obj << /Title 120 0 R /A 117 0 R /Parent 504 0 R /Prev 111 0 R /Next 155 0 R /First 123 0 R /Last 151 0 R /Count -3 >> endobj 115 0 obj << /Title 116 0 R /A 113 0 R /Parent 111 0 R >> endobj 111 0 obj << /Title 112 0 R /A 109 0 R /Parent 504 0 R /Prev 87 0 R /Next 119 0 R /First 115 0 R /Last 115 0 R /Count -1 >> endobj 107 0 obj << /Title 108 0 R /A 105 0 R /Parent 87 0 R /Prev 103 0 R >> endobj 103 0 obj << /Title 104 0 R /A 101 0 R /Parent 87 0 R /Prev 99 0 R /Next 107 0 R >> endobj 99 0 obj << /Title 100 0 R /A 97 0 R /Parent 87 0 R /Prev 95 0 R /Next 103 0 R >> endobj 95 0 obj << /Title 96 0 R /A 93 0 R /Parent 87 0 R /Prev 91 0 R /Next 99 0 R >> endobj 91 0 obj << /Title 92 0 R /A 89 0 R /Parent 87 0 R /Next 95 0 R >> endobj 87 0 obj << /Title 88 0 R /A 85 0 R /Parent 504 0 R /Prev 71 0 R /Next 111 0 R /First 91 0 R /Last 107 0 R /Count -5 >> endobj 83 0 obj << /Title 84 0 R /A 81 0 R /Parent 71 0 R /Prev 79 0 R >> endobj 79 0 obj << /Title 80 0 R /A 77 0 R /Parent 71 0 R /Prev 75 0 R /Next 83 0 R >> endobj 75 0 obj << /Title 76 0 R /A 73 0 R /Parent 71 0 R /Next 79 0 R >> endobj 71 0 obj << /Title 72 0 R /A 69 0 R /Parent 504 0 R /Prev 43 0 R /Next 87 0 R /First 75 0 R /Last 83 0 R /Count -3 >> endobj 67 0 obj << /Title 68 0 R /A 65 0 R /Parent 59 0 R /Prev 63 0 R >> endobj 63 0 obj << /Title 64 0 R /A 61 0 R /Parent 59 0 R /Next 67 0 R >> endobj 59 0 obj << /Title 60 0 R /A 57 0 R /Parent 43 0 R /Prev 55 0 R /First 63 0 R /Last 67 0 R /Count -2 >> endobj 55 0 obj << /Title 56 0 R /A 53 0 R /Parent 43 0 R /Prev 51 0 R /Next 59 0 R >> endobj 51 0 obj << /Title 52 0 R /A 49 0 R /Parent 43 0 R /Prev 47 0 R /Next 55 0 R >> endobj 47 0 obj << /Title 48 0 R /A 45 0 R /Parent 43 0 R /Next 51 0 R >> endobj 43 0 obj << /Title 44 0 R /A 41 0 R /Parent 504 0 R /Prev 7 0 R /Next 71 0 R /First 47 0 R /Last 59 0 R /Count -4 >> endobj 39 0 obj << /Title 40 0 R /A 37 0 R /Parent 23 0 R /Prev 35 0 R >> endobj 35 0 obj << /Title 36 0 R /A 33 0 R /Parent 23 0 R /Prev 31 0 R /Next 39 0 R >> endobj 31 0 obj << /Title 32 0 R /A 29 0 R /Parent 23 0 R /Prev 27 0 R /Next 35 0 R >> endobj 27 0 obj << /Title 28 0 R /A 25 0 R /Parent 23 0 R /Next 31 0 R >> endobj 23 0 obj << /Title 24 0 R /A 21 0 R /Parent 7 0 R /Prev 19 0 R /First 27 0 R /Last 39 0 R /Count -4 >> endobj 19 0 obj << /Title 20 0 R /A 17 0 R /Parent 7 0 R /Prev 15 0 R /Next 23 0 R >> endobj 15 0 obj << /Title 16 0 R /A 13 0 R /Parent 7 0 R /Prev 11 0 R /Next 19 0 R >> endobj 11 0 obj << /Title 12 0 R /A 9 0 R /Parent 7 0 R /Next 15 0 R >> endobj 7 0 obj << /Title 8 0 R /A 5 0 R /Parent 504 0 R /Next 43 0 R /First 11 0 R /Last 23 0 R /Count -4 >> endobj 505 0 obj << /Names [(Doc-Start) 198 0 R (Item.1) 309 0 R (Item.10) 322 0 R (Item.11) 356 0 R (Item.12) 357 0 R (Item.13) 358 0 R] /Limits [(Doc-Start) (Item.13)] >> endobj 506 0 obj << /Names [(Item.14) 359 0 R (Item.15) 360 0 R (Item.16) 361 0 R (Item.17) 362 0 R (Item.18) 363 0 R (Item.19) 368 0 R] /Limits [(Item.14) (Item.19)] >> endobj 507 0 obj << /Names [(Item.2) 310 0 R (Item.20) 369 0 R (Item.21) 370 0 R (Item.22) 371 0 R (Item.23) 372 0 R (Item.24) 373 0 R] /Limits [(Item.2) (Item.24)] >> endobj 508 0 obj << /Names [(Item.25) 374 0 R (Item.3) 311 0 R (Item.4) 312 0 R (Item.5) 313 0 R (Item.6) 314 0 R (Item.7) 315 0 R] /Limits [(Item.25) (Item.7)] >> endobj 509 0 obj << /Names [(Item.8) 320 0 R (Item.9) 321 0 R (chapter*.1) 240 0 R (chapter.1) 6 0 R (chapter.2) 42 0 R (chapter.3) 70 0 R] /Limits [(Item.8) (chapter.3)] >> endobj 510 0 obj << /Names [(chapter.4) 86 0 R (chapter.5) 110 0 R (chapter.6) 118 0 R (chapter.7) 154 0 R (page.1) 197 0 R (page.10) 299 0 R] /Limits [(chapter.4) (page.10)] >> endobj 511 0 obj << /Names [(page.11) 303 0 R (page.12) 308 0 R (page.13) 319 0 R (page.14) 327 0 R (page.15) 332 0 R (page.16) 336 0 R] /Limits [(page.11) (page.16)] >> endobj 512 0 obj << /Names [(page.17) 341 0 R (page.18) 345 0 R (page.19) 350 0 R (page.2) 205 0 R (page.20) 355 0 R (page.21) 367 0 R] /Limits [(page.17) (page.21)] >> endobj 513 0 obj << /Names [(page.22) 378 0 R (page.23) 382 0 R (page.24) 386 0 R (page.25) 392 0 R (page.26) 397 0 R (page.27) 404 0 R] /Limits [(page.22) (page.27)] >> endobj 514 0 obj << /Names [(page.28) 411 0 R (page.29) 418 0 R (page.3) 238 0 R (page.30) 423 0 R (page.31) 428 0 R (page.32) 434 0 R] /Limits [(page.28) (page.32)] >> endobj 515 0 obj << /Names [(page.33) 438 0 R (page.34) 442 0 R (page.35) 446 0 R (page.36) 450 0 R (page.37) 454 0 R (page.38) 459 0 R] /Limits [(page.33) (page.38)] >> endobj 516 0 obj << /Names [(page.39) 464 0 R (page.4) 262 0 R (page.5) 269 0 R (page.6) 276 0 R (page.7) 283 0 R (page.8) 288 0 R] /Limits [(page.39) (page.8)] >> endobj 517 0 obj << /Names [(page.9) 293 0 R (section*.2) 328 0 R (section*.3) 460 0 R (section.1.1) 10 0 R (section.1.2) 14 0 R (section.1.3) 18 0 R] /Limits [(page.9) (section.1.3)] >> endobj 518 0 obj << /Names [(section.1.4) 22 0 R (section.2.1) 46 0 R (section.2.2) 50 0 R (section.2.3) 54 0 R (section.2.4) 58 0 R (section.3.1) 74 0 R] /Limits [(section.1.4) (section.3.1)] >> endobj 519 0 obj << /Names [(section.3.2) 78 0 R (section.3.3) 82 0 R (section.4.1) 90 0 R (section.4.2) 94 0 R (section.4.3) 98 0 R (section.4.4) 102 0 R] /Limits [(section.3.2) (section.4.4)] >> endobj 520 0 obj << /Names [(section.4.5) 106 0 R (section.5.1) 114 0 R (section.6.1) 122 0 R (section.6.2) 146 0 R (section.6.3) 150 0 R (section.7.1) 158 0 R] /Limits [(section.4.5) (section.7.1)] >> endobj 521 0 obj << /Names [(section.7.2) 162 0 R (subsection.1.4.1) 26 0 R (subsection.1.4.2) 30 0 R (subsection.1.4.3) 34 0 R (subsection.1.4.4) 38 0 R (subsection.2.4.1) 62 0 R] /Limits [(section.7.2) (subsection.2.4.1)] >> endobj 522 0 obj << /Names [(subsection.2.4.2) 66 0 R (subsection.6.1.1) 126 0 R (subsection.6.1.2) 130 0 R (subsection.6.1.3) 134 0 R (subsection.6.1.4) 138 0 R (subsection.6.1.5) 142 0 R] /Limits [(subsection.2.4.2) (subsection.6.1.5)] >> endobj 523 0 obj << /Names [(subsection.7.2.1) 166 0 R (subsection.7.2.2) 170 0 R (subsection.7.2.3) 174 0 R (subsection.7.2.4) 178 0 R (subsection.7.2.5) 182 0 R (subsection.7.2.6) 186 0 R] /Limits [(subsection.7.2.1) (subsection.7.2.6)] >> endobj 524 0 obj << /Names [(subsection.7.2.7) 190 0 R] /Limits [(subsection.7.2.7) (subsection.7.2.7)] >> endobj 525 0 obj << /Kids [505 0 R 506 0 R 507 0 R 508 0 R 509 0 R 510 0 R] /Limits [(Doc-Start) (page.10)] >> endobj 526 0 obj << /Kids [511 0 R 512 0 R 513 0 R 514 0 R 515 0 R 516 0 R] /Limits [(page.11) (page.8)] >> endobj 527 0 obj << /Kids [517 0 R 518 0 R 519 0 R 520 0 R 521 0 R 522 0 R] /Limits [(page.9) (subsection.6.1.5)] >> endobj 528 0 obj << /Kids [523 0 R 524 0 R] /Limits [(subsection.7.2.1) (subsection.7.2.7)] >> endobj 529 0 obj << /Kids [525 0 R 526 0 R 527 0 R 528 0 R] /Limits [(Doc-Start) (subsection.7.2.7)] >> endobj 530 0 obj << /Dests 529 0 R >> endobj 531 0 obj << /Type /Catalog /Pages 503 0 R /Outlines 504 0 R /Names 530 0 R /PageMode/UseOutlines /OpenAction 193 0 R >> endobj 532 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.3)/Keywords() /CreationDate (D:20100303091453+01'00') /ModDate (D:20100303091453+01'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX using libpoppler, Version 3.141592-1.40.3-2.2 (Web2C 7.5.6) kpathsea version 3.5.6) >> endobj xref 0 533 0000000001 65535 f 0000000002 00000 f 0000000003 00000 f 0000000004 00000 f 0000000000 00000 f 0000000015 00000 n 0000017229 00000 n 0000504667 00000 n 0000000060 00000 n 0000000093 00000 n 0000017286 00000 n 0000504595 00000 n 0000000140 00000 n 0000000173 00000 n 0000017344 00000 n 0000504509 00000 n 0000000221 00000 n 0000000261 00000 n 0000020072 00000 n 0000504423 00000 n 0000000309 00000 n 0000000349 00000 n 0000020131 00000 n 0000504313 00000 n 0000000397 00000 n 0000000433 00000 n 0000020190 00000 n 0000504239 00000 n 0000000486 00000 n 0000000537 00000 n 0000022557 00000 n 0000504152 00000 n 0000000590 00000 n 0000000638 00000 n 0000022615 00000 n 0000504065 00000 n 0000000691 00000 n 0000000755 00000 n 0000022673 00000 n 0000503991 00000 n 0000000808 00000 n 0000000841 00000 n 0000025514 00000 n 0000503867 00000 n 0000000887 00000 n 0000000941 00000 n 0000029791 00000 n 0000503793 00000 n 0000000989 00000 n 0000001014 00000 n 0000032452 00000 n 0000503706 00000 n 0000001062 00000 n 0000001101 00000 n 0000037709 00000 n 0000503619 00000 n 0000001149 00000 n 0000001190 00000 n 0000037828 00000 n 0000503508 00000 n 0000001238 00000 n 0000001288 00000 n 0000037887 00000 n 0000503434 00000 n 0000001341 00000 n 0000001370 00000 n 0000039321 00000 n 0000503360 00000 n 0000001423 00000 n 0000001459 00000 n 0000041917 00000 n 0000503235 00000 n 0000001505 00000 n 0000001546 00000 n 0000041975 00000 n 0000503161 00000 n 0000001594 00000 n 0000001639 00000 n 0000042033 00000 n 0000503074 00000 n 0000001687 00000 n 0000001726 00000 n 0000042091 00000 n 0000503000 00000 n 0000001774 00000 n 0000001811 00000 n 0000045635 00000 n 0000502873 00000 n 0000001857 00000 n 0000001901 00000 n 0000045693 00000 n 0000502799 00000 n 0000001949 00000 n 0000001982 00000 n 0000045751 00000 n 0000502712 00000 n 0000002030 00000 n 0000002063 00000 n 0000047931 00000 n 0000502623 00000 n 0000002111 00000 n 0000002145 00000 n 0000048229 00000 n 0000502532 00000 n 0000002194 00000 n 0000002239 00000 n 0000050330 00000 n 0000502454 00000 n 0000002288 00000 n 0000002328 00000 n 0000052317 00000 n 0000502323 00000 n 0000002375 00000 n 0000002412 00000 n 0000052376 00000 n 0000502258 00000 n 0000002461 00000 n 0000002503 00000 n 0000090482 00000 n 0000502126 00000 n 0000002550 00000 n 0000002604 00000 n 0000133779 00000 n 0000502008 00000 n 0000002653 00000 n 0000002694 00000 n 0000133838 00000 n 0000501929 00000 n 0000002748 00000 n 0000002786 00000 n 0000133897 00000 n 0000501836 00000 n 0000002840 00000 n 0000002882 00000 n 0000204226 00000 n 0000501743 00000 n 0000002936 00000 n 0000002974 00000 n 0000204286 00000 n 0000501650 00000 n 0000003028 00000 n 0000003066 00000 n 0000248804 00000 n 0000501571 00000 n 0000003120 00000 n 0000003164 00000 n 0000248863 00000 n 0000501478 00000 n 0000003213 00000 n 0000003248 00000 n 0000398510 00000 n 0000501399 00000 n 0000003297 00000 n 0000003338 00000 n 0000400366 00000 n 0000501281 00000 n 0000003385 00000 n 0000003427 00000 n 0000400425 00000 n 0000501202 00000 n 0000003476 00000 n 0000003511 00000 n 0000400484 00000 n 0000501084 00000 n 0000003560 00000 n 0000003589 00000 n 0000400543 00000 n 0000501005 00000 n 0000003643 00000 n 0000003675 00000 n 0000400602 00000 n 0000500912 00000 n 0000003729 00000 n 0000003764 00000 n 0000402164 00000 n 0000500819 00000 n 0000003818 00000 n 0000003857 00000 n 0000403788 00000 n 0000500726 00000 n 0000003911 00000 n 0000003945 00000 n 0000403847 00000 n 0000500633 00000 n 0000003999 00000 n 0000004030 00000 n 0000405693 00000 n 0000500540 00000 n 0000004084 00000 n 0000004116 00000 n 0000406813 00000 n 0000500461 00000 n 0000004170 00000 n 0000004209 00000 n 0000004496 00000 n 0000004726 00000 n 0000004261 00000 n 0000004608 00000 n 0000004667 00000 n 0000498329 00000 n 0000498186 00000 n 0000499326 00000 n 0000005119 00000 n 0000004947 00000 n 0000004811 00000 n 0000005059 00000 n 0000006603 00000 n 0000006754 00000 n 0000006907 00000 n 0000007061 00000 n 0000007215 00000 n 0000007365 00000 n 0000007524 00000 n 0000007682 00000 n 0000007841 00000 n 0000008000 00000 n 0000008151 00000 n 0000008305 00000 n 0000008458 00000 n 0000008612 00000 n 0000008766 00000 n 0000008925 00000 n 0000009084 00000 n 0000009235 00000 n 0000009389 00000 n 0000009541 00000 n 0000009695 00000 n 0000009846 00000 n 0000010000 00000 n 0000010153 00000 n 0000010307 00000 n 0000010461 00000 n 0000010614 00000 n 0000010763 00000 n 0000012148 00000 n 0000011033 00000 n 0000006255 00000 n 0000005191 00000 n 0000010915 00000 n 0000497609 00000 n 0000010974 00000 n 0000012299 00000 n 0000012453 00000 n 0000012612 00000 n 0000012771 00000 n 0000012930 00000 n 0000013089 00000 n 0000013248 00000 n 0000013402 00000 n 0000013556 00000 n 0000013706 00000 n 0000013860 00000 n 0000014014 00000 n 0000014173 00000 n 0000014332 00000 n 0000014491 00000 n 0000014648 00000 n 0000014807 00000 n 0000014966 00000 n 0000015185 00000 n 0000011872 00000 n 0000011118 00000 n 0000015125 00000 n 0000498612 00000 n 0000499038 00000 n 0000017019 00000 n 0000017402 00000 n 0000016887 00000 n 0000015296 00000 n 0000017170 00000 n 0000019495 00000 n 0000019665 00000 n 0000019838 00000 n 0000020249 00000 n 0000019347 00000 n 0000017487 00000 n 0000020012 00000 n 0000498755 00000 n 0000499182 00000 n 0000022323 00000 n 0000022730 00000 n 0000022191 00000 n 0000020373 00000 n 0000022498 00000 n 0000499443 00000 n 0000023207 00000 n 0000023035 00000 n 0000022841 00000 n 0000023147 00000 n 0000025301 00000 n 0000025572 00000 n 0000025169 00000 n 0000023292 00000 n 0000025455 00000 n 0000497899 00000 n 0000498471 00000 n 0000027472 00000 n 0000027300 00000 n 0000025709 00000 n 0000027412 00000 n 0000029849 00000 n 0000029620 00000 n 0000027583 00000 n 0000029732 00000 n 0000498043 00000 n 0000032930 00000 n 0000032280 00000 n 0000029999 00000 n 0000032392 00000 n 0000032510 00000 n 0000032570 00000 n 0000032630 00000 n 0000032690 00000 n 0000032750 00000 n 0000032810 00000 n 0000032870 00000 n 0000035746 00000 n 0000035398 00000 n 0000033080 00000 n 0000035510 00000 n 0000035569 00000 n 0000035628 00000 n 0000035687 00000 n 0000499560 00000 n 0000037946 00000 n 0000037537 00000 n 0000035909 00000 n 0000037649 00000 n 0000037768 00000 n 0000039379 00000 n 0000039150 00000 n 0000038096 00000 n 0000039262 00000 n 0000039891 00000 n 0000039719 00000 n 0000039503 00000 n 0000039831 00000 n 0000041699 00000 n 0000042149 00000 n 0000041567 00000 n 0000039976 00000 n 0000041858 00000 n 0000044069 00000 n 0000043897 00000 n 0000042234 00000 n 0000044009 00000 n 0000498898 00000 n 0000045808 00000 n 0000045464 00000 n 0000044232 00000 n 0000045576 00000 n 0000499677 00000 n 0000048349 00000 n 0000047579 00000 n 0000045945 00000 n 0000047691 00000 n 0000047751 00000 n 0000047811 00000 n 0000047871 00000 n 0000047990 00000 n 0000048050 00000 n 0000048110 00000 n 0000048170 00000 n 0000048289 00000 n 0000050684 00000 n 0000050041 00000 n 0000048486 00000 n 0000050153 00000 n 0000050212 00000 n 0000050271 00000 n 0000050389 00000 n 0000050448 00000 n 0000050507 00000 n 0000050566 00000 n 0000050625 00000 n 0000051214 00000 n 0000051042 00000 n 0000050834 00000 n 0000051154 00000 n 0000052435 00000 n 0000052146 00000 n 0000051299 00000 n 0000052258 00000 n 0000052913 00000 n 0000052741 00000 n 0000052546 00000 n 0000052853 00000 n 0000053735 00000 n 0000090269 00000 n 0000090541 00000 n 0000053603 00000 n 0000052998 00000 n 0000090423 00000 n 0000499794 00000 n 0000092037 00000 n 0000091865 00000 n 0000090675 00000 n 0000091977 00000 n 0000092844 00000 n 0000122540 00000 n 0000134628 00000 n 0000133956 00000 n 0000092732 00000 n 0000092135 00000 n 0000133720 00000 n 0000497753 00000 n 0000183121 00000 n 0000204987 00000 n 0000204346 00000 n 0000134516 00000 n 0000134129 00000 n 0000204166 00000 n 0000218952 00000 n 0000249460 00000 n 0000292060 00000 n 0000248922 00000 n 0000204875 00000 n 0000204506 00000 n 0000248745 00000 n 0000323474 00000 n 0000291592 00000 n 0000249348 00000 n 0000249082 00000 n 0000291532 00000 n 0000347353 00000 n 0000322974 00000 n 0000291948 00000 n 0000291713 00000 n 0000322915 00000 n 0000499911 00000 n 0000368955 00000 n 0000346884 00000 n 0000323362 00000 n 0000323095 00000 n 0000346824 00000 n 0000368394 00000 n 0000347241 00000 n 0000347006 00000 n 0000368335 00000 n 0000398570 00000 n 0000368843 00000 n 0000368516 00000 n 0000398450 00000 n 0000400661 00000 n 0000400195 00000 n 0000398705 00000 n 0000400307 00000 n 0000402224 00000 n 0000401992 00000 n 0000400772 00000 n 0000402104 00000 n 0000403906 00000 n 0000403617 00000 n 0000402335 00000 n 0000403729 00000 n 0000500028 00000 n 0000405753 00000 n 0000405461 00000 n 0000404017 00000 n 0000405573 00000 n 0000405633 00000 n 0000406872 00000 n 0000406642 00000 n 0000405864 00000 n 0000406754 00000 n 0000406996 00000 n 0000407661 00000 n 0000407686 00000 n 0000408087 00000 n 0000408142 00000 n 0000408535 00000 n 0000409100 00000 n 0000409760 00000 n 0000410275 00000 n 0000410563 00000 n 0000411204 00000 n 0000411846 00000 n 0000412125 00000 n 0000422608 00000 n 0000423002 00000 n 0000428492 00000 n 0000428752 00000 n 0000435692 00000 n 0000435973 00000 n 0000440218 00000 n 0000440467 00000 n 0000456276 00000 n 0000456840 00000 n 0000459595 00000 n 0000459840 00000 n 0000462462 00000 n 0000462706 00000 n 0000470264 00000 n 0000470596 00000 n 0000472530 00000 n 0000472807 00000 n 0000474017 00000 n 0000474242 00000 n 0000483457 00000 n 0000483777 00000 n 0000497088 00000 n 0000500121 00000 n 0000500239 00000 n 0000500316 00000 n 0000500386 00000 n 0000504776 00000 n 0000504949 00000 n 0000505119 00000 n 0000505287 00000 n 0000505451 00000 n 0000505625 00000 n 0000505803 00000 n 0000505973 00000 n 0000506142 00000 n 0000506312 00000 n 0000506481 00000 n 0000506651 00000 n 0000506815 00000 n 0000507002 00000 n 0000507198 00000 n 0000507395 00000 n 0000507597 00000 n 0000507824 00000 n 0000508065 00000 n 0000508307 00000 n 0000508414 00000 n 0000508525 00000 n 0000508633 00000 n 0000508750 00000 n 0000508845 00000 n 0000508949 00000 n 0000508987 00000 n 0000509115 00000 n trailer << /Size 533 /Root 531 0 R /Info 532 0 R /ID [<44BFEA45D80FE5DCBC27D22D310D1D35> <44BFEA45D80FE5DCBC27D22D310D1D35>] >> startxref 509446 %%EOF netgen-6.2.1905/doc/CMakeLists.txt0000644000175000017500000000014713504650527015310 0ustar kurtkurtINSTALL(FILES ng4.pdf DESTINATION ${NG_INSTALL_DIR_RES}/${NG_INSTALL_SUFFIX}/doc COMPONENT netgen_doc) netgen-6.2.1905/py_tutorials/0000755000175000017500000000000013504650527014537 5ustar kurtkurtnetgen-6.2.1905/py_tutorials/merge.py0000644000175000017500000000336613504650527016220 0ustar kurtkurtfrom netgen.meshing import * from netgen.csg import * from ngsolve import ngsglobals ngsglobals.msg_level = 2 # generate brick and mesh it geo1 = CSGeometry() geo1.Add (OrthoBrick( Pnt(0,0,0), Pnt(1,1,1) )) m1 = geo1.GenerateMesh (maxh=0.1) m1.Refine() # generate sphere and mesh it geo2 = CSGeometry() geo2.Add (Sphere (Pnt(0.5,0.5,0.5), 0.1)) m2 = geo2.GenerateMesh (maxh=0.05) m2.Refine() m2.Refine() print ("***************************") print ("** merging suface meshes **") print ("***************************") # create an empty mesh mesh = Mesh() # a face-descriptor stores properties associated with a set of surface elements # bc .. boundary condition marker, # domin/domout .. domain-number in front/back of surface elements (0 = void), # surfnr .. number of the surface described by the face-descriptor fd_outside = mesh.Add (FaceDescriptor(bc=1,domin=1,surfnr=1)) fd_inside = mesh.Add (FaceDescriptor(bc=2,domin=2,domout=1,surfnr=2)) # copy all boundary points from first mesh to new mesh. # pmap1 maps point-numbers from old to new mesh pmap1 = { } for e in m1.Elements2D(): for v in e.vertices: if (v not in pmap1): pmap1[v] = mesh.Add (m1[v]) # copy surface elements from first mesh to new mesh # we have to map point-numbers: for e in m1.Elements2D(): mesh.Add (Element2D (fd_outside, [pmap1[v] for v in e.vertices])) # same for the second mesh: pmap2 = { } for e in m2.Elements2D(): for v in e.vertices: if (v not in pmap2): pmap2[v] = mesh.Add (m2[v]) for e in m2.Elements2D(): mesh.Add (Element2D (fd_inside, [pmap2[v] for v in e.vertices])) print ("******************") print ("** merging done **") print ("******************") mesh.GenerateVolumeMesh() mesh.Save ("newmesh.vol") netgen-6.2.1905/py_tutorials/mesh.py0000644000175000017500000000043613504650527016050 0ustar kurtkurtfrom netgen.meshing import * from netgen.csg import * geo = CSGeometry("shaft.geo") param = MeshingParameters() param.maxh = 10 print (param) m1 = GenerateMesh (geo, param) m1.SecondOrder() import exportNeutral exportNeutral.Export (m1, "shaft.mesh") Save (m1, "mesh.vol", geo) netgen-6.2.1905/py_tutorials/csg_first_example.py0000644000175000017500000000336313504650527020614 0ustar kurtkurtfrom netgen.csg import * import netgen.meshing as meshing #from OpenGL.GL import * #from OpenGL.GLU import * #from OpenGL.GLUT import * sp1 = Sphere (Pnt(0,0,0), 0.2) sp2 = Sphere (Pnt(0.5,0,0), 0.2) sp3 = Sphere (Pnt(0,0,0.5), 0.2) sp4 = Sphere (Pnt(0,0.2,0.7), 0.2) all = sp1+sp2+sp3+sp4 geom = CSGeometry() geom.Add (all) #vis = VS(geom) # vis.Draw() #window = 0 # glut window number #width, height = 500, 500 #def mydraw(): # glViewport(0, 0, width, height); # glMatrixMode(GL_PROJECTION); # glLoadIdentity(); # pnear = 0.1; # pfar = 10; # gluPerspective(20.0, 1.0*width / height, pnear, pfar); # glMatrixMode(GL_MODELVIEW); # glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # glLoadIdentity() # gluLookAt (0, 0, 6, 0, 0, 0, 0, 1, 0); ## glBegin(GL_QUADS) ## glColor4d(0.0, 1.0, 0.0, 0.0); ## glVertex3d(0.0,0.0,0.7) ## glVertex3d(1.0,0.0,2.1) ## glColor4d(1.0, 1.0, 1.0, 0.0); ## glVertex3d(1.0,1.0,0.2) ## glVertex3d(0.0,1.0,0.5) ## glEnd() # vis.Draw() # glutSwapBuffers() #glutInit("mainwin") # initialize glut #glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH) #glutInitWindowSize(width, height) # set window size #glutInitWindowPosition(0, 0) # set window position #window = glutCreateWindow(b"ngs") # create window with title #glutDisplayFunc(vis.Draw) # set draw function callback #glutIdleFunc(mydraw) # draw all the time #glutMainLoop() param = meshing.MeshingParameters(maxh=0.2) mesh = GenerateMesh (geom, param) mesh.Save ("test.vol") netgen-6.2.1905/py_tutorials/exportNeutral.py0000644000175000017500000000104213504650527017762 0ustar kurtkurtimport sys def Export (mesh, filename): """ export Netgen mesh to neutral format """ print ("export mesh in neutral format to file = ", filename) f = open (filename, 'w') points = mesh.Points() print (len(points), file=f) for p in points: print (p.p[0], p.p[1], p.p[2], file=f) volels = mesh.Elements3D(); print (len(volels), file=f) for el in volels: print (el.index, end=" ", file=f) for p in el.points: print (p.nr, end=" ", file=f) print(file=f) netgen-6.2.1905/py_tutorials/cube.geo0000644000175000017500000000046013504650527016151 0ustar kurtkurt# ## A cube # algebraic3d # cube consisting of 6 planes: solid cube = plane (0, 0, 0; 0, 0, -1) and plane (0, 0, 0; 0, -1, 0) and plane (0, 0, 0; -1, 0, 0) and plane (1, 1, 1; 0, 0, 1) and plane (1, 1, 1; 0, 1, 0) and plane (1, 1, 1; 1, 0, 0); tlo cube; netgen-6.2.1905/py_tutorials/opengl_thread.py0000644000175000017500000000176713504650527017737 0ustar kurtkurtfrom netgen.csg import * import netgen.meshing as meshing import libvisual from OpenGL.GLUT import * # import Window class from other file from opengl_window import Window sp1 = Sphere (Pnt(0,0,0), 0.2) sp2 = Sphere (Pnt(0.5,0,0), 0.2) all = sp1+sp2 geom = CSGeometry() geom.Add (all) param = meshing.MeshingParameters() param.maxh = 0.1 m1 = GenerateMesh (geom, param) vis = VS(geom) # window callback functions def mydraw(): vis.Draw() glutSwapBuffers() def mymouse(xold, yold, x, y, mode): MouseMove(vis,xold,yold, x,y, mode) ########################################### glutInit("mainwin") # IMPORTANT: create window in the mainloop - thread! ## not working: #win_geom = Window( name=b"ngs", drawfunc=mydraw, mousefunc=mymouse) def runVisualization(): ## working: win_geom = Window( name=b"ngs", drawfunc=mydraw, mousefunc=mymouse) glutMainLoop() # create thread from threading import Thread thread = Thread(target = runVisualization) thread.start() thread.join() netgen-6.2.1905/py_tutorials/opengl_window.py0000644000175000017500000000364213504650527017771 0ustar kurtkurtfrom OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * class Window(): xold = -1; yold = -1; mode = 'r' modes = {0:'r', 1:'m', 2:'z'} drawfunc = None mousefunc = None def draw(self): glutSetWindow(self.handle) self.drawfunc() def __init__( self, name=b"Window", width=500, height=500, drawfunc=None, mousefunc=None ): # glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS) glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH) glutInitWindowSize(width, height) # set window size glutInitWindowPosition(0, 0) # set window position self.handle = glutCreateWindow(b"ngs") # create window with title glutMotionFunc(self.motionHandler) glutMouseFunc(self.mouseHandler) glutPassiveMotionFunc(self.passiveMotionHandler) glMatrixMode(GL_PROJECTION); glLoadIdentity(); pnear = 0.1; pfar = 10; gluPerspective(20.0, 1.0*width / height, pnear, pfar); glViewport(0, 0, width, height); glMatrixMode(GL_MODELVIEW); self.drawfunc = drawfunc self.mousefunc = mousefunc if drawfunc: glutDisplayFunc(self.draw) # set draw function callback def motionHandler(self, x, y ): self.mousefunc(self.xold,self.yold, x,y, self.mode) # 'm','z' self.xold = x self.yold = y glutPostRedisplay() def passiveMotionHandler(self, x, y ): self.xold = x self.yold = y def mouseHandler(self, button, state, x, y ): print(button,state,x,y) if button<3: if state==0: self.mode = self.modes[button] else: self.mode = 'r' glutInit("mainwin") # initialize glut netgen-6.2.1905/py_tutorials/shaft.geo0000644000175000017500000000435713504650527016351 0ustar kurtkurt# ## Crankshaft # algebraic3d solid p1 = plane (0, 0, 0; -1, 0, 0) and plane (10, 0, 0; 1, 0, 0) and ( plane (35, 0, 28; 0, -1, 3) and plane (35, 0, -28; 0, -1, -3) and plane (35, 0, 0; 0, 1, 0) and plane (35, -30, 0; 0, -1, 0) or cylinder (-10, 0, 0; 20, 0, 0; 30) or cylinder (-10, -30, 0; 20, -30, 0; 20) ); solid p2 = plane (35, 0, 0; -1, 0, 0) and plane (45, 0, 0; 1, 0, 0) and ( plane (35, 0, 28; 0, -1, 3) and plane (35, 0, -28; 0, -1, -3) and plane (35, 0, 0; 0, 1, 0) and plane (35, -30, 0; 0, -1, 0) or cylinder (30, 0, 0; 50, 0, 0; 30) or cylinder (30, -30, 0; 50, -30, 0; 20) ); solid p3 = plane (80, 0, 0; -1, 0, 0) and plane (90, 0, 0; 1, 0, 0) and ( plane (0, 0, 28; 0, 1, 3) and plane (0, 0, -28; 0, 1, -3) and plane (0, 0, 0; 0, -1, 0) and plane (0, 30, 0; 0, 1, 0) or cylinder (70, 0, 0; 100, 0, 0; 30) or cylinder (70, 30, 0; 100, 30, 0; 20) ); solid p4 = plane (115, 0, 0; -1, 0, 0) and plane (125, 0, 0; 1, 0, 0) and ( plane (35, 0, 28; 0, 1, 3) and plane (35, 0, -28; 0, 1, -3) and plane (35, 0, 0; 0, -1, 0) and plane (35, 30, 0; 0, 1, 0) or cylinder (110, 0, 0; 130, 0, 0; 30) or cylinder (110, 30, 0;130, 30, 0; 20) ); solid sh1 = cylinder (-50, 0, 0; 10, 0, 0; 15) and plane (-40, 0, 0; -1, 0, 0) and plane (5, 0, 0; 1, 0, 0); solid sh2 = cylinder (30, 0, 0; 90, 0, 0; 15) and plane (40, 0, 0; -1, 0, 0) and plane (85, 0, 0; 1, 0, 0); solid sh3 = cylinder (110, 0, 0; 170, 0, 0; 15) and plane (120, 0, 0; -1, 0, 0) and plane (165, 0, 0; 1, 0, 0); solid pl1 = cylinder (0, -30, 0; 50, -30, 0; 10) and plane (5, 0, 0; -1, 0, 0) and plane (40, 0, 0; 1, 0, 0); solid pl2 = cylinder (80, 30, 0; 130, 30, 0; 10) and plane (85, 0, 0; -1, 0, 0) and plane (120, 0, 0; 1, 0, 0); # # solid main = p1 or p2 or p3 or p4 or sh1 or sh2 or sh3 or pl1 or pl2; tlo main; netgen-6.2.1905/py_tutorials/opengl.py0000644000175000017500000000321413504650527016375 0ustar kurtkurtfrom netgen.csg import * import netgen.meshing as meshing import libvisual from OpenGL.GLUT import * # import Window class from other file from opengl_window import Window sp1 = Sphere (Pnt(0,0,0), 0.2) sp2 = Sphere (Pnt(0.5,0,0), 0.2) all = sp1+sp2 geom = CSGeometry() geom.Add (all) param = meshing.MeshingParameters() param.maxh = 0.1 m1 = GenerateMesh (geom, param) vis = VS(geom) # window callback functions def mydraw(): vis.Draw() glutSwapBuffers() def mymouse(xold, yold, x, y, mode): MouseMove(vis,xold,yold, x,y, mode) # init glut and create window glutInit("mainwin") win_geom = Window( name=b"ngs", drawfunc=mydraw, mousefunc=mymouse) ########################################### # press ctrl+c to break loop while(True): for i in range(10000): glutMainLoopEvent() print('press ctrl+c to create second window!') ########################################### # create second window (transformation matrices are shared) vismesh = libvisual.meshvis.VS(m1) def mydraw2(): vismesh.Draw() glutSwapBuffers() win_mesh = Window( name=b"ngs2", drawfunc=mydraw2, mousefunc=mymouse) ########################################### # press ctrl+c to break loop try: while(True): for i in range(10000): glutMainLoopEvent() print('press ctrl+c to hide/destroy first window!') except: pass ########################################### ## BREAKS (on numericus) as soon as mouse touches remaining window ("Error of failed request: GLXBadContextTag") # glutDestroyWindow(win_geom.handle) ## WORKS glutHideWindow(win_geom.handle) try: while(True): glutMainLoopEvent() except: pass netgen-6.2.1905/py_tutorials/CMakeLists.txt0000644000175000017500000000026213504650527017277 0ustar kurtkurtinstall( FILES shaft.geo mesh.py exportNeutral.py DESTINATION ${NG_INSTALL_DIR_RES}/${NG_INSTALL_SUFFIX}/py_tutorials COMPONENT netgen_tutorial ) netgen-6.2.1905/external_dependencies/0000755000175000017500000000000013504650527016331 5ustar kurtkurtnetgen-6.2.1905/external_dependencies/.gitignore0000644000175000017500000000001113504650527020311 0ustar kurtkurt*.tar.gz netgen-6.2.1905/nglib/0000755000175000017500000000000013504650527013074 5ustar kurtkurtnetgen-6.2.1905/nglib/nglib.cpp0000644000175000017500000007163513504650527014707 0ustar kurtkurt/**************************************************************************/ /* File: nglib.cpp */ /* Author: Joachim Schoeberl */ /* Date: 7. May. 2000 */ /**************************************************************************/ /* Interface to the netgen meshing kernel */ #include #include #include #include #include #include #include #include <../visualization/soldata.hpp> #ifdef OCCGEOMETRY #include #endif #include namespace netgen { extern void MeshFromSpline2D (SplineGeometry2d & geometry, shared_ptr & mesh, MeshingParameters & mp); } #ifdef PARALLEL #include namespace netgen { // int id = 0, ntasks = 1; MPI_Comm mesh_comm; } #endif /* namespace netgen { int id = 0, ntasks = 1; } */ /* // should not be needed (occ currently requires it) namespace netgen { #include "../libsrc/visualization/vispar.hpp" VisualizationParameters vispar; VisualizationParameters :: VisualizationParameters() { ; } } */ namespace nglib { #include "nglib.h" } using namespace netgen; // constants and types: namespace nglib { inline void NOOP_Deleter(void *) { ; } // initialize, deconstruct Netgen library: DLL_HEADER void Ng_Init () { mycout = &cout; myerr = &cerr; // netgen::testout->SetOutStream (new ofstream ("test.out")); // testout = new ofstream ("test.out"); } // Clean-up functions before ending usage of nglib DLL_HEADER void Ng_Exit () { ; } // Create a new netgen mesh object DLL_HEADER Ng_Mesh * Ng_NewMesh () { Mesh * mesh = new Mesh; mesh->AddFaceDescriptor (FaceDescriptor (1, 1, 0, 1)); return (Ng_Mesh*)(void*)mesh; } // Delete an existing netgen mesh object DLL_HEADER void Ng_DeleteMesh (Ng_Mesh * mesh) { if(mesh != NULL) { // Delete the Mesh structures ((Mesh*)mesh)->DeleteMesh(); // Now delete the Mesh class itself delete (Mesh*)mesh; // Set the Ng_Mesh pointer to NULL mesh = NULL; } } // Save a netgen mesh in the native VOL format DLL_HEADER void Ng_SaveMesh(Ng_Mesh * mesh, const char* filename) { ((Mesh*)mesh)->Save(filename); } // Load a netgen native VOL mesh from a given file DLL_HEADER Ng_Mesh * Ng_LoadMesh(const char* filename) { Mesh * mesh = new Mesh; mesh->Load(filename); return ( (Ng_Mesh*)mesh ); } // Merge another mesh file into the currently loaded one DLL_HEADER Ng_Result Ng_MergeMesh( Ng_Mesh* mesh, const char* filename) { Ng_Result status = NG_OK; ifstream infile(filename); Mesh * m = (Mesh*)mesh; if(!infile.good()) { status = NG_FILE_NOT_FOUND; } if(!m) { status = NG_ERROR; } if(status == NG_OK) { const int num_pts = m->GetNP(); const int face_offset = m->GetNFD(); m->Merge(infile, face_offset); if(m->GetNP() > num_pts) { status = NG_OK; } else { status = NG_ERROR; } } return status; } // Merge another mesh file into the currently loaded one DLL_HEADER Ng_Result Ng_MergeMesh( Ng_Mesh* mesh1, Ng_Mesh* mesh2) { return NG_ERROR; } // Manually add a point to an existing mesh object DLL_HEADER void Ng_AddPoint (Ng_Mesh * mesh, double * x) { Mesh * m = (Mesh*)mesh; m->AddPoint (Point3d (x[0], x[1], x[2])); } // Manually add a surface element of a given type to an existing mesh object DLL_HEADER void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et, int * pi) { Mesh * m = (Mesh*)mesh; Element2d el (3); el.SetIndex (1); el.PNum(1) = pi[0]; el.PNum(2) = pi[1]; el.PNum(3) = pi[2]; m->AddSurfaceElement (el); } // Manually add a volume element of a given type to an existing mesh object DLL_HEADER void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et, int * pi) { Mesh * m = (Mesh*)mesh; Element el (4); el.SetIndex (1); el.PNum(1) = pi[0]; el.PNum(2) = pi[1]; el.PNum(3) = pi[2]; el.PNum(4) = pi[3]; m->AddVolumeElement (el); } // Obtain the number of points in the mesh DLL_HEADER int Ng_GetNP (Ng_Mesh * mesh) { return ((Mesh*)mesh) -> GetNP(); } // Obtain the number of surface elements in the mesh DLL_HEADER int Ng_GetNSE (Ng_Mesh * mesh) { return ((Mesh*)mesh) -> GetNSE(); } // Obtain the number of volume elements in the mesh DLL_HEADER int Ng_GetNE (Ng_Mesh * mesh) { return ((Mesh*)mesh) -> GetNE(); } // Return point coordinates of a given point index in the mesh DLL_HEADER void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x) { const Point3d & p = ((Mesh*)mesh)->Point(num); x[0] = p.X(); x[1] = p.Y(); x[2] = p.Z(); } // Return the surface element at a given index "pi" DLL_HEADER Ng_Surface_Element_Type Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi) { const Element2d & el = ((Mesh*)mesh)->SurfaceElement(num); for (int i = 1; i <= el.GetNP(); i++) pi[i-1] = el.PNum(i); Ng_Surface_Element_Type et; switch (el.GetNP()) { case 3: et = NG_TRIG; break; case 4: et = NG_QUAD; break; case 6: switch (el.GetNV()) { case 3: et = NG_TRIG6; break; case 4: et = NG_QUAD6; break; default: et = NG_TRIG6; break; } break; case 8: et = NG_QUAD8; break; default: et = NG_TRIG; break; // for the compiler } return et; } // Return the volume element at a given index "pi" DLL_HEADER Ng_Volume_Element_Type Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi) { const Element & el = ((Mesh*)mesh)->VolumeElement(num); for (int i = 1; i <= el.GetNP(); i++) pi[i-1] = el.PNum(i); Ng_Volume_Element_Type et; switch (el.GetNP()) { case 4: et = NG_TET; break; case 5: et = NG_PYRAMID; break; case 6: et = NG_PRISM; break; case 10: et = NG_TET10; break; default: et = NG_TET; break; // for the compiler } return et; } // Set a global limit on the maximum mesh size allowed DLL_HEADER void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h) { ((Mesh*)mesh) -> SetGlobalH (h); } // Set a local limit on the maximum mesh size allowed around the given point DLL_HEADER void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h) { ((Mesh*)mesh) -> RestrictLocalH (Point3d (p[0], p[1], p[2]), h); } // Set a local limit on the maximum mesh size allowed within a given box region DLL_HEADER void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h) { for (double x = pmin[0]; x < pmax[0]; x += h) for (double y = pmin[1]; y < pmax[1]; y += h) for (double z = pmin[2]; z < pmax[2]; z += h) ((Mesh*)mesh) -> RestrictLocalH (Point3d (x, y, z), h); } // Generates volume mesh from an existing surface mesh DLL_HEADER Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp) { Mesh * m = (Mesh*)mesh; // Philippose - 30/08/2009 // Do not locally re-define "mparam" here... "mparam" is a global // object //MeshingParameters mparam; mp->Transfer_Parameters(); m->CalcLocalH(mparam.grading); MeshVolume (mparam, *m); RemoveIllegalElements (*m); OptimizeVolume (mparam, *m); return NG_OK; } /* ------------------ 2D Meshing Functions ------------------------- */ DLL_HEADER void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x) { Mesh * m = (Mesh*)mesh; m->AddPoint (Point3d (x[0], x[1], 0)); } DLL_HEADER void Ng_AddBoundarySeg_2D (Ng_Mesh * mesh, int pi1, int pi2) { Mesh * m = (Mesh*)mesh; Segment seg; seg[0] = pi1; seg[1] = pi2; m->AddSegment (seg); } DLL_HEADER int Ng_GetNP_2D (Ng_Mesh * mesh) { Mesh * m = (Mesh*)mesh; return m->GetNP(); } DLL_HEADER int Ng_GetNE_2D (Ng_Mesh * mesh) { Mesh * m = (Mesh*)mesh; return m->GetNSE(); } DLL_HEADER int Ng_GetNSeg_2D (Ng_Mesh * mesh) { Mesh * m = (Mesh*)mesh; return m->GetNSeg(); } DLL_HEADER void Ng_GetPoint_2D (Ng_Mesh * mesh, int num, double * x) { Mesh * m = (Mesh*)mesh; Point<3> & p = m->Point(num); x[0] = p(0); x[1] = p(1); } DLL_HEADER Ng_Surface_Element_Type Ng_GetElement_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum) { const Element2d & el = ((Mesh*)mesh)->SurfaceElement(num); for (int i = 1; i <= el.GetNP(); i++) pi[i-1] = el.PNum(i); Ng_Surface_Element_Type et; switch (el.GetNP()) { case 3: et = NG_TRIG; break; case 4: et = NG_QUAD; break; case 6: switch (el.GetNV()) { case 3: et = NG_TRIG6; break; case 4: et = NG_QUAD6; break; default: et = NG_TRIG6; break; } break; case 8: et = NG_QUAD8; break; default: et = NG_TRIG; break; // for the compiler } if (matnum) *matnum = el.GetIndex(); return et; } DLL_HEADER void Ng_GetSegment_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum) { const Segment & seg = ((Mesh*)mesh)->LineSegment(num); pi[0] = seg[0]; pi[1] = seg[1]; if (matnum) *matnum = seg.edgenr; } DLL_HEADER Ng_Geometry_2D * Ng_LoadGeometry_2D (const char * filename) { SplineGeometry2d * geom = new SplineGeometry2d(); geom -> Load (filename); return (Ng_Geometry_2D *)geom; } DLL_HEADER Ng_Result Ng_GenerateMesh_2D (Ng_Geometry_2D * geom, Ng_Mesh ** mesh, Ng_Meshing_Parameters * mp) { // use global variable mparam // MeshingParameters mparam; mp->Transfer_Parameters(); shared_ptr m(new Mesh, &NOOP_Deleter); MeshFromSpline2D (*(SplineGeometry2d*)geom, m, mparam); // new shared_ptr (m); // hack to keep mesh m alive cout << m->GetNSE() << " elements, " << m->GetNP() << " points" << endl; *mesh = (Ng_Mesh*)m.get(); return NG_OK; } DLL_HEADER void Ng_HP_Refinement (Ng_Geometry_2D * geom, Ng_Mesh * mesh, int levels) { Refinement2d ref(*(SplineGeometry2d*)geom); HPRefinement (*(Mesh*)mesh, &ref, levels); } DLL_HEADER void Ng_HP_Refinement (Ng_Geometry_2D * geom, Ng_Mesh * mesh, int levels, double parameter) { Refinement2d ref(*(SplineGeometry2d*)geom); HPRefinement (*(Mesh*)mesh, &ref, levels, parameter); } Array readtrias; //only before initstlgeometry Array > readedges; //only before init stlgeometry // loads geometry from STL file DLL_HEADER Ng_STL_Geometry * Ng_STL_LoadGeometry (const char * filename, int binary) { int i; STLGeometry geom; STLGeometry* geo; ifstream ist(filename); if (binary) { geo = geom.LoadBinary(ist); } else { geo = geom.Load(ist); } readtrias.SetSize(0); readedges.SetSize(0); Point3d p; Vec3d normal; double p1[3]; double p2[3]; double p3[3]; double n[3]; Ng_STL_Geometry * geo2 = Ng_STL_NewGeometry(); for (i = 1; i <= geo->GetNT(); i++) { const STLTriangle& t = geo->GetTriangle(i); p = geo->GetPoint(t.PNum(1)); p1[0] = p.X(); p1[1] = p.Y(); p1[2] = p.Z(); p = geo->GetPoint(t.PNum(2)); p2[0] = p.X(); p2[1] = p.Y(); p2[2] = p.Z(); p = geo->GetPoint(t.PNum(3)); p3[0] = p.X(); p3[1] = p.Y(); p3[2] = p.Z(); normal = t.Normal(); n[0] = normal.X(); n[1] = normal.Y(); n[2] = normal.Z(); Ng_STL_AddTriangle(geo2, p1, p2, p3, n); } return geo2; } // generate new STL Geometry DLL_HEADER Ng_STL_Geometry * Ng_STL_NewGeometry () { return (Ng_STL_Geometry*)(void*)new STLGeometry; } // after adding triangles (and edges) initialize DLL_HEADER Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom) { STLGeometry* geo = (STLGeometry*)geom; geo->InitSTLGeometry(readtrias); readtrias.SetSize(0); if (readedges.Size() != 0) { /* for (int i = 1; i <= readedges.Size(); i+=2) { cout << "e(" << readedges.Get(i) << "," << readedges.Get(i+1) << ")" << endl; } */ geo->AddEdges(readedges); } if (geo->GetStatus() == STLTopology::STL_GOOD || geo->GetStatus() == STLTopology::STL_WARNING) return NG_OK; return NG_SURFACE_INPUT_ERROR; } // automatically generates edges: DLL_HEADER Ng_Result Ng_STL_MakeEdges (Ng_STL_Geometry * geom, Ng_Mesh* mesh, Ng_Meshing_Parameters * mp) { STLGeometry* stlgeometry = (STLGeometry*)geom; Mesh* me = (Mesh*)mesh; // Philippose - 27/07/2009 // Do not locally re-define "mparam" here... "mparam" is a global // object //MeshingParameters mparam; mp->Transfer_Parameters(); me -> SetGlobalH (mparam.maxh); me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), 0.3); // cout << "meshsize = " << mp->meshsize_filename << endl; if (mp->meshsize_filename) me -> LoadLocalMeshSize (mp->meshsize_filename); /* if (mp->meshsize_filename) { ifstream infile (mp->meshsize_filename); if (!infile.good()) return NG_FILE_NOT_FOUND; me -> LoadLocalMeshSize (infile); } */ STLMeshing (*stlgeometry, *me); stlgeometry->edgesfound = 1; stlgeometry->surfacemeshed = 0; stlgeometry->surfaceoptimized = 0; stlgeometry->volumemeshed = 0; return NG_OK; } // generates mesh, empty mesh be already created. DLL_HEADER Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom, Ng_Mesh* mesh, Ng_Meshing_Parameters * mp) { STLGeometry* stlgeometry = (STLGeometry*)geom; Mesh* me = (Mesh*)mesh; // Philippose - 27/07/2009 // Do not locally re-define "mparam" here... "mparam" is a global // object //MeshingParameters mparam; mp->Transfer_Parameters(); /* me -> SetGlobalH (mparam.maxh); me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), 0.3); */ /* STLMeshing (*stlgeometry, *me); stlgeometry->edgesfound = 1; stlgeometry->surfacemeshed = 0; stlgeometry->surfaceoptimized = 0; stlgeometry->volumemeshed = 0; */ int retval = STLSurfaceMeshing (*stlgeometry, *me); if (retval == MESHING3_OK) { (*mycout) << "Success !!!!" << endl; stlgeometry->surfacemeshed = 1; stlgeometry->surfaceoptimized = 0; stlgeometry->volumemeshed = 0; } else if (retval == MESHING3_OUTERSTEPSEXCEEDED) { (*mycout) << "ERROR: Give up because of too many trials. Meshing aborted!" << endl; } else if (retval == MESHING3_TERMINATE) { (*mycout) << "Meshing Stopped!" << endl; } else { (*mycout) << "ERROR: Surface meshing not successful. Meshing aborted!" << endl; } STLSurfaceOptimization (*stlgeometry, *me, mparam); return NG_OK; } // fills STL Geometry // positive orientation // normal vector may be null-pointer DLL_HEADER void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, double * p1, double * p2, double * p3, double * nv) { Point<3> apts[3]; apts[0] = Point<3>(p1[0],p1[1],p1[2]); apts[1] = Point<3>(p2[0],p2[1],p2[2]); apts[2] = Point<3>(p3[0],p3[1],p3[2]); Vec<3> n; if (!nv) n = Cross (apts[0]-apts[1], apts[0]-apts[2]); else n = Vec<3>(nv[0],nv[1],nv[2]); readtrias.Append(STLReadTriangle(apts,n)); } // add (optional) edges: DLL_HEADER void Ng_STL_AddEdge (Ng_STL_Geometry * geom, double * p1, double * p2) { readedges.Append(Point3d(p1[0],p1[1],p1[2])); readedges.Append(Point3d(p2[0],p2[1],p2[2])); } #ifdef OCCGEOMETRY // --------------------- OCC Geometry / Meshing Utility Functions ------------------- // Create new OCC Geometry Object DLL_HEADER Ng_OCC_Geometry * Ng_OCC_NewGeometry () { return (Ng_OCC_Geometry*)(void*)new OCCGeometry; } // Delete the OCC Geometry Object DLL_HEADER Ng_Result Ng_OCC_DeleteGeometry(Ng_OCC_Geometry * geom) { if (geom != NULL) { delete (OCCGeometry*)geom; geom = NULL; return NG_OK; } return NG_ERROR; } // Loads geometry from STEP File DLL_HEADER Ng_OCC_Geometry * Ng_OCC_Load_STEP (const char * filename) { // Call the STEP File Load function. Note.. the geometry class // is created and instantiated within the load function OCCGeometry * occgeo = LoadOCC_STEP(filename); return ((Ng_OCC_Geometry *)occgeo); } // Loads geometry from IGES File DLL_HEADER Ng_OCC_Geometry * Ng_OCC_Load_IGES (const char * filename) { // Call the IGES File Load function. Note.. the geometry class // is created and instantiated within the load function OCCGeometry * occgeo = LoadOCC_IGES(filename); return ((Ng_OCC_Geometry *)occgeo); } // Loads geometry from BREP File DLL_HEADER Ng_OCC_Geometry * Ng_OCC_Load_BREP (const char * filename) { // Call the BREP File Load function. Note.. the geometry class // is created and instantiated within the load function OCCGeometry * occgeo = LoadOCC_BREP(filename); return ((Ng_OCC_Geometry *)occgeo); } // Locally limit the size of the mesh to be generated at various points // based on the topology of the geometry DLL_HEADER Ng_Result Ng_OCC_SetLocalMeshSize (Ng_OCC_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp) { OCCGeometry * occgeom = (OCCGeometry*)geom; Mesh * me = (Mesh*)mesh; me->geomtype = Mesh::GEOM_OCC; mp->Transfer_Parameters(); occparam.resthcloseedgeenable = mp->closeedgeenable; occparam.resthcloseedgefac = mp->closeedgefact; // Delete the mesh structures in order to start with a clean // slate me->DeleteMesh(); OCCSetLocalMeshSize(*occgeom, *me); return(NG_OK); } // Mesh the edges and add Face descriptors to prepare for surface meshing DLL_HEADER Ng_Result Ng_OCC_GenerateEdgeMesh (Ng_OCC_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp) { OCCGeometry * occgeom = (OCCGeometry*)geom; Mesh * me = (Mesh*)mesh; mp->Transfer_Parameters(); OCCFindEdges(*occgeom, *me); if((me->GetNP()) && (me->GetNFD())) { return NG_OK; } else { return NG_ERROR; } } // Mesh the edges and add Face descriptors to prepare for surface meshing DLL_HEADER Ng_Result Ng_OCC_GenerateSurfaceMesh (Ng_OCC_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp) { int numpoints = 0; OCCGeometry * occgeom = (OCCGeometry*)geom; Mesh * me = (Mesh*)mesh; // Set the internal meshing parameters structure from the nglib meshing // parameters structure mp->Transfer_Parameters(); // Only go into surface meshing if the face descriptors have already been added if(!me->GetNFD()) return NG_ERROR; numpoints = me->GetNP(); // Initially set up only for surface meshing without any optimisation int perfstepsend = MESHCONST_MESHSURFACE; // Check and if required, enable surface mesh optimisation step if(mp->optsurfmeshenable) { perfstepsend = MESHCONST_OPTSURFACE; } OCCMeshSurface(*occgeom, *me, perfstepsend); me->CalcSurfacesOfNode(); if(me->GetNP() <= numpoints) return NG_ERROR; if(me->GetNSE() <= 0) return NG_ERROR; return NG_OK; } // Extract the face map from the OCC geometry // The face map basically gives an index to each face in the geometry, // which can be used to access a specific face DLL_HEADER Ng_Result Ng_OCC_GetFMap(Ng_OCC_Geometry * geom, Ng_OCC_TopTools_IndexedMapOfShape * FMap) { OCCGeometry* occgeom = (OCCGeometry*)geom; TopTools_IndexedMapOfShape *occfmap = (TopTools_IndexedMapOfShape *)FMap; // Copy the face map from the geometry to the given variable occfmap->Assign(occgeom->fmap); if(occfmap->Extent()) { return NG_OK; } else { return NG_ERROR; } } // ------------------ End - OCC Geometry / Meshing Utility Functions ---------------- #endif // ------------------ Begin - Meshing Parameters related functions ------------------ // Constructor for the local nglib meshing parameters class DLL_HEADER Ng_Meshing_Parameters :: Ng_Meshing_Parameters() { uselocalh = 1; maxh = 1000; minh = 0.0; fineness = 0.5; grading = 0.3; elementsperedge = 2.0; elementspercurve = 2.0; closeedgeenable = 0; closeedgefact = 2.0; minedgelenenable = 0; minedgelen = 1e-4; second_order = 0; quad_dominated = 0; meshsize_filename = 0; optsurfmeshenable = 1; optvolmeshenable = 1; optsteps_2d = 3; optsteps_3d = 3; invert_tets = 0; invert_trigs = 0; check_overlap = 1; check_overlapping_boundary = 1; } // Reset the local meshing parameters to the default values DLL_HEADER void Ng_Meshing_Parameters :: Reset_Parameters() { uselocalh = 1; maxh = 1000; minh = 0; fineness = 0.5; grading = 0.3; elementsperedge = 2.0; elementspercurve = 2.0; closeedgeenable = 0; closeedgefact = 2.0; minedgelenenable = 0; minedgelen = 1e-4; second_order = 0; quad_dominated = 0; meshsize_filename = 0; optsurfmeshenable = 1; optvolmeshenable = 1; optsteps_2d = 3; optsteps_3d = 3; invert_tets = 0; invert_trigs = 0; check_overlap = 1; check_overlapping_boundary = 1; } // DLL_HEADER void Ng_Meshing_Parameters :: Transfer_Parameters() { mparam.uselocalh = uselocalh; mparam.maxh = maxh; mparam.minh = minh; mparam.grading = grading; mparam.curvaturesafety = elementspercurve; mparam.segmentsperedge = elementsperedge; mparam.secondorder = second_order; mparam.quad = quad_dominated; if (meshsize_filename) mparam.meshsizefilename = meshsize_filename; else mparam.meshsizefilename = ""; mparam.optsteps2d = optsteps_2d; mparam.optsteps3d = optsteps_3d; mparam.inverttets = invert_tets; mparam.inverttrigs = invert_trigs; mparam.checkoverlap = check_overlap; mparam.checkoverlappingboundary = check_overlapping_boundary; } // ------------------ End - Meshing Parameters related functions -------------------- // ------------------ Begin - Second Order Mesh generation functions ---------------- DLL_HEADER void Ng_Generate_SecondOrder(Ng_Mesh * mesh) { Refinement ref; ref.MakeSecondOrder(*(Mesh*) mesh); } DLL_HEADER void Ng_2D_Generate_SecondOrder(Ng_Geometry_2D * geom, Ng_Mesh * mesh) { ( (SplineGeometry2d*)geom ) -> GetRefinement().MakeSecondOrder( * (Mesh*) mesh ); } DLL_HEADER void Ng_STL_Generate_SecondOrder(Ng_STL_Geometry * geom, Ng_Mesh * mesh) { ((STLGeometry*)geom)->GetRefinement().MakeSecondOrder(*(Mesh*) mesh); } DLL_HEADER void Ng_CSG_Generate_SecondOrder (Ng_CSG_Geometry * geom, Ng_Mesh * mesh) { ((CSGeometry*)geom)->GetRefinement().MakeSecondOrder(*(Mesh*) mesh); } #ifdef OCCGEOMETRY DLL_HEADER void Ng_OCC_Generate_SecondOrder (Ng_OCC_Geometry * geom, Ng_Mesh * mesh) { ((OCCGeometry*)geom )->GetRefinement().MakeSecondOrder(*(Mesh*) mesh); } #endif // ------------------ End - Second Order Mesh generation functions ------------------ // ------------------ Begin - Uniform Mesh Refinement functions --------------------- DLL_HEADER void Ng_Uniform_Refinement (Ng_Mesh * mesh) { Refinement ref; ref.Refine ( * (Mesh*) mesh ); } DLL_HEADER void Ng_2D_Uniform_Refinement (Ng_Geometry_2D * geom, Ng_Mesh * mesh) { ( (SplineGeometry2d*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh ); } DLL_HEADER void Ng_STL_Uniform_Refinement (Ng_STL_Geometry * geom, Ng_Mesh * mesh) { ( (STLGeometry*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh ); } DLL_HEADER void Ng_CSG_Uniform_Refinement (Ng_CSG_Geometry * geom, Ng_Mesh * mesh) { ( (CSGeometry*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh ); } #ifdef OCCGEOMETRY DLL_HEADER void Ng_OCC_Uniform_Refinement (Ng_OCC_Geometry * geom, Ng_Mesh * mesh) { ( (OCCGeometry*)geom ) -> GetRefinement().Refine ( * (Mesh*) mesh ); } #endif // ------------------ End - Uniform Mesh Refinement functions ----------------------- } // End of namespace nglib // compatibility functions: namespace netgen { char geomfilename[255]; DLL_HEADER void MyError2 (const char * ch) { cerr << ch; } //Destination for messages, errors, ... DLL_HEADER void Ng_PrintDest2(const char * s) { #ifdef PARALLEL int id = 0; MPI_Comm_rank(MPI_COMM_WORLD, &id); if (id != 0) return; #endif (*mycout) << s << flush; } /* DLL_HEADER double GetTime () { return 0; } */ /* #ifndef WIN32 void ResetTime () { ; } #endif */ void MyBeep (int i) { ; } //void Render() { ; } } // End of namespace netgen /* #ifndef WIN32 void Ng_Redraw () { ; } void Ng_ClearSolutionData() { ; } #endif void Ng_SetSolutionData (Ng_SolutionData * soldata) { delete soldata->solclass; } void Ng_InitSolutionData (Ng_SolutionData * soldata) { ; } */ // Force linking libinterface to libnglib #include <../interface/writeuser.hpp> void MyDummyToForceLinkingLibInterface(Mesh &mesh, NetgenGeometry &geom) { netgen::WriteUserFormat("", mesh, /* geom, */ ""); } netgen-6.2.1905/nglib/ng_occ.cpp0000644000175000017500000000723113504650527015033 0ustar kurtkurt#include #include #include "TopTools_IndexedMapOfShape.hxx" #include "TopoDS.hxx" #include "TopoDS_Face.hxx" #include "TopoDS_Shape.hxx" #include "GProp_GProps.hxx" #include "BRepGProp.hxx" using namespace std; namespace nglib { #include } int main (int argc, char ** argv) { using namespace nglib; cout << "Netgen NgLib - OpenCascade Test Case" << endl; if (argc != 2) { cerr << "use: ng_occ " << endl; return 1; } // Define pointer to OCC Geometry Ng_OCC_Geometry *occ_geom; Ng_Mesh *occ_mesh; Ng_Meshing_Parameters mp; TopTools_IndexedMapOfShape FMap; Ng_OCC_TopTools_IndexedMapOfShape *occ_fmap = (Ng_OCC_TopTools_IndexedMapOfShape*)&FMap; // Result of Netgen Operations Ng_Result ng_res; // Initialise the Netgen Core library Ng_Init(); // Read in the OCC File occ_geom = Ng_OCC_Load_STEP(argv[1]); if(!occ_geom) { cout << "Error reading in STEP File: " << argv[1] << endl; return 1; } cout << "Successfully loaded STEP File: " << argv[1] << endl; occ_mesh = Ng_NewMesh(); ng_res = Ng_OCC_GetFMap(occ_geom,occ_fmap); cout << "ng_res = " << ng_res << endl; if(!FMap.Extent()) { cout << "Error retrieving Face map...." << endl; return 1; } cout << "Successfully extracted the Face Map....:" << FMap.Extent() << endl; for(int i = 1; i <= FMap.Extent(); i++) { TopoDS_Face OCCface; OCCface = TopoDS::Face(FMap.FindKey(i)); GProp_GProps faceProps; BRepGProp::SurfaceProperties(OCCface,faceProps); cout << "Index: " << i << " :: Area: " << faceProps.Mass() << " :: Hash: " << OCCface.HashCode(1e+6) << endl; } mp.uselocalh = 1; mp.elementsperedge = 2.0; mp.elementspercurve = 2.0; mp.maxh = 10.0; mp.grading = 0.2; mp.closeedgeenable = 0; mp.closeedgefact = 1.0; mp.optsurfmeshenable = 1; cout << "Setting Local Mesh size....." << endl; cout << "OCC Mesh Pointer before call = " << occ_mesh << endl; Ng_OCC_SetLocalMeshSize(occ_geom, occ_mesh, &mp); cout << "Local Mesh size successfully set....." << endl; cout << "OCC Mesh Pointer after call = " << occ_mesh << endl; cout << "Creating Edge Mesh....." << endl; ng_res = Ng_OCC_GenerateEdgeMesh(occ_geom, occ_mesh, &mp); if(ng_res != NG_OK) { Ng_DeleteMesh(occ_mesh); cout << "Error creating Edge Mesh.... Aborting!!" << endl; return 1; } else { cout << "Edge Mesh successfully created....." << endl; cout << "Number of points = " << Ng_GetNP(occ_mesh) << endl; } cout << "Creating Surface Mesh....." << endl; ng_res = Ng_OCC_GenerateSurfaceMesh(occ_geom, occ_mesh, &mp); if(ng_res != NG_OK) { Ng_DeleteMesh(occ_mesh); cout << "Error creating Surface Mesh..... Aborting!!" << endl; return 1; } else { cout << "Surface Mesh successfully created....." << endl; cout << "Number of points = " << Ng_GetNP(occ_mesh) << endl; cout << "Number of surface elements = " << Ng_GetNSE(occ_mesh) << endl; } cout << "Creating Volume Mesh....." << endl; ng_res = Ng_GenerateVolumeMesh(occ_mesh, &mp); cout << "Volume Mesh successfully created....." << endl; cout << "Number of points = " << Ng_GetNP(occ_mesh) << endl; cout << "Number of volume elements = " << Ng_GetNE(occ_mesh) << endl; cout << "Saving Mesh as VOL file....." << endl; Ng_SaveMesh(occ_mesh,"test_occ.vol"); return 0; } netgen-6.2.1905/nglib/ng_stl.cpp0000644000175000017500000000564713504650527015102 0ustar kurtkurt/*! \file ng_stl.cpp \author Philippose Rajan \date 14 Feb 2009 (Created) This sample utility demonstrates the use of the Netgen nglib library for reading, and meshing an STL geometry. The Program takes as input the name of an STL file saved in the STL ASCII Format, and generates a 3D Volume mesh which is saved into the file "test.vol". test.vol can be viewed using the usual Netgen Mesher GUI */ #include #include using namespace std; namespace nglib { #include } int main (int argc, char ** argv) { using namespace nglib; cout << "Netgen (nglib) STL Testing" << endl; if (argc < 2) { cerr << "use: ng_stl STL_filename" << endl; return 1; } // Define pointer to a new Netgen Mesh Ng_Mesh *mesh; // Define pointer to STL Geometry Ng_STL_Geometry *stl_geom; // Result of Netgen Operations Ng_Result ng_res; // Initialise the Netgen Core library Ng_Init(); // Actually create the mesh structure mesh = Ng_NewMesh(); int np, ne; // Read in the STL File stl_geom = Ng_STL_LoadGeometry(argv[1]); if(!stl_geom) { cout << "Error reading in STL File: " << argv[1] << endl; return 1; } cout << "Successfully loaded STL File: " << argv[1] << endl; // Set the Meshing Parameters to be used Ng_Meshing_Parameters mp; mp.maxh = 1.0e+6; mp.fineness = 0.4; mp.second_order = 0; cout << "Initialise the STL Geometry structure...." << endl; ng_res = Ng_STL_InitSTLGeometry(stl_geom); if(ng_res != NG_OK) { cout << "Error Initialising the STL Geometry....Aborting!!" << endl; return 1; } cout << "Start Edge Meshing...." << endl; ng_res = Ng_STL_MakeEdges(stl_geom, mesh, &mp); if(ng_res != NG_OK) { cout << "Error in Edge Meshing....Aborting!!" << endl; return 1; } cout << "Start Surface Meshing...." << endl; ng_res = Ng_STL_GenerateSurfaceMesh(stl_geom, mesh, &mp); if(ng_res != NG_OK) { cout << "Error in Surface Meshing....Aborting!!" << endl; return 1; } cout << "Start Volume Meshing...." << endl; ng_res = Ng_GenerateVolumeMesh (mesh, &mp); if(ng_res != NG_OK) { cout << "Error in Volume Meshing....Aborting!!" << endl; return 1; } cout << "Meshing successfully completed....!!" << endl; // volume mesh output np = Ng_GetNP(mesh); cout << "Points: " << np << endl; ne = Ng_GetNE(mesh); cout << "Elements: " << ne << endl; cout << "Saving Mesh in VOL Format...." << endl; Ng_SaveMesh(mesh,"test.vol"); // refinement without geomety adaption: // Ng_Uniform_Refinement (mesh); // refinement with geomety adaption: Ng_STL_Uniform_Refinement (stl_geom, mesh); cout << "elements after refinement: " << Ng_GetNE(mesh) << endl; cout << "points after refinement: " << Ng_GetNP(mesh) << endl; Ng_SaveMesh(mesh,"test_ref.vol"); return 0; } netgen-6.2.1905/nglib/nglib.h0000644000175000017500000006437313504650527014355 0ustar kurtkurt#ifndef NGLIB #define NGLIB /**************************************************************************/ /* File: nglib.h */ /* Author: Joachim Schoeberl */ /* Date: 7. May. 2000 */ /**************************************************************************/ /*! \file nglib.h \brief Library interface to the netgen meshing kernel \author Joachim Schoeberl \date 7. May 2000 This header file provides access to the core functionality of the Netgen Mesher via a library interface, without an interactive User Interface. The intention of providing these set of functions is to allow system developers to integrate Netgen into top-level code, to act as the low level mesh generation / optimisation kernel. */ // Philippose - 14.02.2009 // Modifications for creating a DLL in Windows #ifdef WIN32 #ifdef NGLIB_EXPORTS || nglib_EXPORTS #define DLL_HEADER __declspec(dllexport) #else #define DLL_HEADER __declspec(dllimport) #endif #else #define DLL_HEADER #endif // ** Constants used within Netgen ********************* /// Maximum allowed number of nodes per volume element #define NG_VOLUME_ELEMENT_MAXPOINTS 10 /// Maximum allowed number of nodes per surface element #define NG_SURFACE_ELEMENT_MAXPOINTS 8 // *** Data-types for accessing Netgen functionality *** /// Data type for NETGEN mesh typedef void * Ng_Mesh; /// Data type for NETGEN CSG geometry typedef void * Ng_CSG_Geometry; /// Data type for NETGEN 2D geometry typedef void * Ng_Geometry_2D; /// Data type for NETGEN STL geometry typedef void * Ng_STL_Geometry; #ifdef OCCGEOMETRY /// Data type for NETGEN OpenCascade geometry typedef void * Ng_OCC_Geometry; typedef void * Ng_OCC_TopTools_IndexedMapOfShape; #endif // *** Special Enum types used within Netgen *********** /// Currently implemented surface element types enum Ng_Surface_Element_Type { NG_TRIG = 1, NG_QUAD = 2, NG_TRIG6 = 3, NG_QUAD6 = 4, NG_QUAD8 = 5 }; /// Currently implemented volume element types enum Ng_Volume_Element_Type { NG_TET = 1, NG_PYRAMID = 2, NG_PRISM = 3, NG_TET10 = 4 }; /// Values returned by Netgen functions enum Ng_Result { NG_ERROR = -1, NG_OK = 0, NG_SURFACE_INPUT_ERROR = 1, NG_VOLUME_FAILURE = 2, NG_STL_INPUT_ERROR = 3, NG_SURFACE_FAILURE = 4, NG_FILE_NOT_FOUND = 5 }; // *** Classes required for use within Netgen ********** /// Netgen Meshing Parameters class class Ng_Meshing_Parameters { public: int uselocalh; //!< Switch to enable / disable usage of local mesh size modifiers double maxh; //!< Maximum global mesh size allowed double minh; //!< Minimum global mesh size allowed double fineness; //!< Mesh density: 0...1 (0 => coarse; 1 => fine) double grading; //!< Mesh grading: 0...1 (0 => uniform mesh; 1 => aggressive local grading) double elementsperedge; //!< Number of elements to generate per edge of the geometry double elementspercurve; //!< Elements to generate per curvature radius int closeedgeenable; //!< Enable / Disable mesh refinement at close edges double closeedgefact; //!< Factor to use for refinement at close edges (larger => finer) int minedgelenenable; //!< Enable / Disable user defined minimum edge length for edge subdivision double minedgelen; //!< Minimum edge length to use while subdividing the edges (default = 1e-4) int second_order; //!< Generate second-order surface and volume elements int quad_dominated; //!< Creates a Quad-dominated mesh char * meshsize_filename; //!< Optional external mesh size file int optsurfmeshenable; //!< Enable / Disable automatic surface mesh optimization int optvolmeshenable; //!< Enable / Disable automatic volume mesh optimization int optsteps_3d; //!< Number of optimize steps to use for 3-D mesh optimization int optsteps_2d; //!< Number of optimize steps to use for 2-D mesh optimization // Philippose - 13/09/2010 // Added a couple more parameters into the meshing parameters list // from Netgen into Nglib int invert_tets; //!< Invert all the volume elements int invert_trigs; //!< Invert all the surface triangle elements int check_overlap; //!< Check for overlapping surfaces during Surface meshing int check_overlapping_boundary; //!< Check for overlapping surface elements before volume meshing /*! Default constructor for the Mesh Parameters class Note: This constructor initialises the variables in the class with the following default values - #uselocalh: 1 - #maxh: 1000.0 - #fineness: 0.5 - #grading: 0.3 - #elementsperedge: 2.0 - #elementspercurve: 2.0 - #closeedgeenable: 0 - #closeedgefact: 2.0 - #secondorder: 0 - #meshsize_filename: null - #quad_dominated: 0 - #optsurfmeshenable: 1 - #optvolmeshenable: 1 - #optsteps_2d: 3 - #optsteps_3d: 3 - #invert_tets: 0 - #invert_trigs:0 - #check_overlap: 1 - #check_overlapping_boundary: 1 */ DLL_HEADER Ng_Meshing_Parameters(); /*! Reset the meshing parameters to their defaults This member function resets all the meshing parameters of the object to the default values */ DLL_HEADER void Reset_Parameters(); /*! Transfer local meshing parameters to internal meshing parameters This member function transfers all the meshing parameters defined in the local meshing parameters structure of nglib into the internal meshing parameters structure used by the Netgen core */ DLL_HEADER void Transfer_Parameters(); }; // *** Functions Exported by this Library ************* // ------------------------------------------------------------------ // Netgen library initialisation / destruction functions /*! \brief Initialise the Netgen library and prepare for use This function needs to be called by the third-party program before beginning to use the other Netgen specific functions. */ DLL_HEADER void Ng_Init (); /*! \brief Exit the Netgen meshing kernel in a clean manner Use this function to exit the meshing sub-system in a clean and orderly manner. */ DLL_HEADER void Ng_Exit (); /*! \brief Create a new (and empty) Netgen Mesh Structure This function creates a new Netgen Mesh, initialises it, and returns a pointer to the created mesh structure. Use the returned pointer for subsequent operations which involve mesh operations. \return Ng_Mesh Pointer to a Netgen Mesh type #Ng_Mesh */ DLL_HEADER Ng_Mesh * Ng_NewMesh (); /*! \brief Delete an existing Netgen Mesh Structure Use this function to delete an existing Netgen mesh structure and release the used memory. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh */ DLL_HEADER void Ng_DeleteMesh (Ng_Mesh * mesh); /*! \brief Save a Netgen Mesh to disk This function allows a generated mesh structure to be saved to disk. A Mesh saved using this function, will be written to disk in the Netgen VOL file format. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param filename Pointer to a character array containing the name of the file to which the mesh should be saved */ DLL_HEADER void Ng_SaveMesh(Ng_Mesh * mesh, const char* filename); /*! \brief Load a Netgen VOL Mesh from disk into memory A Netgen mesh saved in the internal VOL format can be loaded into a Netgen Mesh structure using this function. \param filename Pointer to a character array containing the name of the file to load \return Ng_Mesh Pointer to a Netgen Mesh type #Ng_Mesh containing the mesh loaded from disk */ DLL_HEADER Ng_Mesh * Ng_LoadMesh(const char* filename); /*! \brief Merge a Netgen VOL Mesh from disk into an existing mesh in memory A Netgen mesh saved in the internal VOL format can be merged into an existing Netgen Mesh structure using this function. \param mesh Name of the Mesh structure already existent in memory \param filename Pointer to a character array containing the name of the file to load \return Ng_Result Status of the merge operation */ DLL_HEADER Ng_Result Ng_MergeMesh(Ng_Mesh * mesh, const char* filename); /*! \brief Merge one Netgen Mesh into another Netgen Mesh in the case when both are already in memory (NOTE: FUNCTION STILL WORK IN PROGRESS!!!) This function can be used to merge two Netgen meshes already present in memory. \param mesh1 Parent Mesh structure into which the second mesh will be merged \param mesh2 Child mesh structure which will get merged into the parent mesh \return Ng_Result Status of the merge operation */ DLL_HEADER Ng_Result Ng_MergeMesh(Ng_Mesh * mesh1, Ng_Mesh * mesh2); // ------------------------------------------------------------------ // ------------------------------------------------------------------ // Basic Meshing functions for manually adding points, surface elements // and volume elements to a Netgen Mesh structure /*! \brief Add a point to a given Netgen Mesh Structure This function allows points to be directly added to a Netgen mesh structure by providing the co-ordinates. Each call to the function allows only one point to be added. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param x Pointer to an array of type double containing the co-ordinates of the point to be added in the form: \n - x[0] = X co-ordinate - x[1] = Y co-ordinate - x[2] = Z co-ordinate */ DLL_HEADER void Ng_AddPoint (Ng_Mesh * mesh, double * x); /*! \brief Add a surface element to a given Netgen Mesh Structure This function allows the top-level code to directly add individual Surface Elements to a Netgen Mesh Structure by providing the type of element to be added and the indices of the points which constitute the element. Note: - The points referred to by the surface elements must have been added prior to calling this function. - Currently only triangular elements are supported, and the Surface Element Type argument is not used. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param et Surface Element type provided via the enumerated type #Ng_Surface_Element_Type \param pi Pointer to an array of integers containing the indices of the points which constitute the surface element being added */ DLL_HEADER void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et, int * pi); /*! \brief Add a volume element to a given Netgen Mesh Structure This function allows the top-level code to directly add individual Volume Elements to a Netgen Mesh Structure by providing the type of element to be added and the indices of the points which constitute the element. Note: - The points referred to by the volume elements must have been added prior to calling this function. - Currently only tetrahedral elements are supported, and the Volume Element Type argument is not used. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param et Volume Element type provided via the enumerated type #Ng_Volume_Element_Type \param pi Pointer to an array of integers containing the indices of the points which constitute the volume element being added */ DLL_HEADER void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et, int * pi); // ------------------------------------------------------------------ // ------------------------------------------------------------------ // Local Mesh Size restriction / limiting utilities /*! \brief Apply a global restriction on mesh element size This utility allows the user to apply a global mesh element size limitation. During mesh creation, in the absence of an explicit local size restriction around the neighbourhood of a point within the meshing domain, this global size restriction will be utilised. Note: This function only limits the Maximum size of an element within the mesh. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param h Variable of type double, specifying the maximum allowable mesh size */ DLL_HEADER void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h); /*! \brief Locally restrict the mesh element size at the given point Unlike the function #Ng_RestrictMeshSizeGlobal, this function allows the user to locally restrict the maximum allowable mesh size at a given point. The point is specified via its three cartesian co-ordinates. Note: This function only limits the Maximum size of the elements around the specified point. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param p Pointer to an Array of type double, containing the three co-ordinates of the point in the form: \n - p[0] = X co-ordinate - p[1] = Y co-ordinate - p[2] = Z co-ordinate \param h Variable of type double, specifying the maximum allowable mesh size at that point */ DLL_HEADER void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h); /*! \brief Locally restrict the mesh element size within a specified box Similar to the function #Ng_RestrictMeshSizePoint, this function allows the size of elements within a mesh to be locally limited. However, rather than limit the mesh size at a single point, this utility restricts the local mesh size within a 3D Box region, specified via the co-ordinates of the two diagonally opposite points of a cuboid. Note: This function only limits the Maximum size of the elements within the specified region. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param pmin Pointer to an Array of type double, containing the three co-ordinates of the first point of the cuboid: \n - pmin[0] = X co-ordinate - pmin[1] = Y co-ordinate - pmin[2] = Z co-ordinate \param pmax Pointer to an Array of type double, containing the three co-ordinates of the opposite point of the cuboid: \n - pmax[0] = X co-ordinate - pmax[1] = Y co-ordinate - pmax[2] = Z co-ordinate \param h Variable of type double, specifying the maximum allowable mesh size at that point */ DLL_HEADER void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h); // ------------------------------------------------------------------ // ------------------------------------------------------------------ // 3D Mesh Generation functions /*! \brief Create a 3D Volume Mesh given a Surface Mesh After creating a surface mesh, this function can be utilised to automatically generate the corresponding 3D Volume Mesh. Mesh generation parameters (such as grading, maximum element size, etc.) are specified via the meshing parameters class which also needs to be passed to this function. Note: Currently, Netgen generates pure tetrahedral volume meshes. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \param mp Pointer to a copy of the Meshing Parameters class (#Ng_Meshing_Parameters), filled up with the required values \return Ng_Result Status of the Mesh Generation routine. More details regarding the return value can be found in the description of #Ng_Result */ DLL_HEADER Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); // ------------------------------------------------------------------ // ------------------------------------------------------------------ // Basic Mesh information functions /*! \brief Returns the Number of Points present in the specified Mesh Given an already existent Netgen Mesh Structure, this function returns the number of points currently present within the Mesh. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \return Integer Data-type with the number of points in the Mesh */ DLL_HEADER int Ng_GetNP (Ng_Mesh * mesh); /*! \brief Returns the Number of Surface Elements present in the specified Mesh Given an already existent Netgen Mesh Structure, this function returns the number of surface elements currently present within the Mesh. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \return Integer Data-type with the number of surface elements in the Mesh */ DLL_HEADER int Ng_GetNSE (Ng_Mesh * mesh); /*! \brief Returns the Number of Volume Elements present in the specified Mesh Given an already existent Netgen Mesh Structure, this function returns the number of volume elements currently present within the Mesh. \param mesh Pointer to an existing Netgen Mesh structure of type #Ng_Mesh \return Integer Data-type with the number of volume elements in the Mesh */ DLL_HEADER int Ng_GetNE (Ng_Mesh * mesh); // ------------------------------------------------------------------ // ------------------------------------------------------------------ // Mesh Topology functions // Use these functions to extract points, surface / volume elements, // perform topological searches, etc..etc... // Return the Point Coordinates of a specified Point // The x, y and z co-ordinates are returned in the array pointer as // x[0] = x ; x[1] = y ; x[2] = z DLL_HEADER void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x); // return surface and volume element in pi DLL_HEADER Ng_Surface_Element_Type Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi); DLL_HEADER Ng_Volume_Element_Type Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi); // ------------------------------------------------------------------ // ********************************************************** // ** 2D Meshing ** // ********************************************************** // feeds points and boundary to mesh DLL_HEADER void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x); DLL_HEADER void Ng_AddBoundarySeg_2D (Ng_Mesh * mesh, int pi1, int pi2); // ask for number of points, elements and boundary segments DLL_HEADER int Ng_GetNP_2D (Ng_Mesh * mesh); DLL_HEADER int Ng_GetNE_2D (Ng_Mesh * mesh); DLL_HEADER int Ng_GetNSeg_2D (Ng_Mesh * mesh); // return point coordinates DLL_HEADER void Ng_GetPoint_2D (Ng_Mesh * mesh, int num, double * x); // return 2d elements DLL_HEADER Ng_Surface_Element_Type Ng_GetElement_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum = NULL); // return 2d boundary segment DLL_HEADER void Ng_GetSegment_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum = NULL); // load 2d netgen spline geometry DLL_HEADER Ng_Geometry_2D * Ng_LoadGeometry_2D (const char * filename); // generate 2d mesh, mesh is allocated by function DLL_HEADER Ng_Result Ng_GenerateMesh_2D (Ng_Geometry_2D * geom, Ng_Mesh ** mesh, Ng_Meshing_Parameters * mp); DLL_HEADER void Ng_HP_Refinement (Ng_Geometry_2D * geom, Ng_Mesh * mesh, int levels); // ********************************************************** // ** STL Meshing ** // ********************************************************** // loads geometry from STL file DLL_HEADER Ng_STL_Geometry * Ng_STL_LoadGeometry (const char * filename, int binary = 0); // generate new STL Geometry DLL_HEADER Ng_STL_Geometry * Ng_STL_NewGeometry (); // fills STL Geometry // positive orientation // normal vector may be null-pointer DLL_HEADER void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, double * p1, double * p2, double * p3, double * nv = NULL); // add (optional) edges : DLL_HEADER void Ng_STL_AddEdge (Ng_STL_Geometry * geom, double * p1, double * p2); // after adding triangles (and edges) initialize DLL_HEADER Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom); // automatically generates edges: DLL_HEADER Ng_Result Ng_STL_MakeEdges (Ng_STL_Geometry * geom, Ng_Mesh* mesh, Ng_Meshing_Parameters * mp); // generates mesh, empty mesh must be already created. DLL_HEADER Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); #ifdef ACIS // ********************************************************** // ** ACIS Meshing ** // ********************************************************** /// Data type for NETGEN STL geomty typedef void * Ng_ACIS_Geometry; // loads geometry from STL file DLL_HEADER Ng_ACIS_Geometry * Ng_ACIS_LoadGeometry (const char * filename); // generates mesh, empty mesh must be already created. DLL_HEADER Ng_Result Ng_ACIS_GenerateSurfaceMesh (Ng_ACIS_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); #endif #ifdef OCCGEOMETRY // ********************************************************** // ** OpenCascade Geometry / Meshing Utilities ** // ********************************************************** // Create new OCC Geometry Object DLL_HEADER Ng_OCC_Geometry * Ng_OCC_NewGeometry (); // Delete an OCC Geometry Object DLL_HEADER Ng_Result Ng_OCC_DeleteGeometry (Ng_OCC_Geometry * geom); // Loads geometry from STEP file DLL_HEADER Ng_OCC_Geometry * Ng_OCC_Load_STEP (const char * filename); // Loads geometry from IGES file DLL_HEADER Ng_OCC_Geometry * Ng_OCC_Load_IGES (const char * filename); // Loads geometry from BREP file DLL_HEADER Ng_OCC_Geometry * Ng_OCC_Load_BREP (const char * filename); // Set the local mesh size based on geometry / topology DLL_HEADER Ng_Result Ng_OCC_SetLocalMeshSize (Ng_OCC_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); // Mesh the edges and add Face descriptors to prepare for surface meshing DLL_HEADER Ng_Result Ng_OCC_GenerateEdgeMesh (Ng_OCC_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); // Mesh the surfaces of an OCC geometry DLL_HEADER Ng_Result Ng_OCC_GenerateSurfaceMesh (Ng_OCC_Geometry * geom, Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); // Get the face map of an already loaded OCC geometry DLL_HEADER Ng_Result Ng_OCC_GetFMap(Ng_OCC_Geometry * geom, Ng_OCC_TopTools_IndexedMapOfShape * FMap); #endif // OCCGEOMETRY // ********************************************************** // ** Mesh refinement algorithms ** // ********************************************************** // uniform mesh refinement DLL_HEADER void Ng_Uniform_Refinement (Ng_Mesh * mesh); // uniform mesh refinement with geometry adaption: DLL_HEADER void Ng_2D_Uniform_Refinement (Ng_Geometry_2D * geom, Ng_Mesh * mesh); DLL_HEADER void Ng_STL_Uniform_Refinement (Ng_STL_Geometry * geom, Ng_Mesh * mesh); DLL_HEADER void Ng_CSG_Uniform_Refinement (Ng_CSG_Geometry * geom, Ng_Mesh * mesh); #ifdef OCCGEOMETRY DLL_HEADER void Ng_OCC_Uniform_Refinement (Ng_OCC_Geometry * geom, Ng_Mesh * mesh); #endif // ********************************************************** // ** Second Order mesh algorithms ** // ********************************************************** // convert mesh to second order DLL_HEADER void Ng_Generate_SecondOrder (Ng_Mesh * mesh); // convert mesh to second order with geometry adaption: DLL_HEADER void Ng_2D_Generate_SecondOrder (Ng_Geometry_2D * geom, Ng_Mesh * mesh); DLL_HEADER void Ng_STL_Generate_SecondOrder (Ng_STL_Geometry * geom, Ng_Mesh * mesh); DLL_HEADER void Ng_CSG_Generate_SecondOrder (Ng_CSG_Geometry * geom, Ng_Mesh * mesh); #ifdef OCCGEOMETRY DLL_HEADER void Ng_OCC_Generate_SecondOrder (Ng_OCC_Geometry * geom, Ng_Mesh * mesh); #endif #endif // NGLIB netgen-6.2.1905/nglib/ng_vol.cpp0000644000175000017500000000326413504650527015071 0ustar kurtkurt#include #include using namespace std; namespace nglib { #include } int main (int argc, char ** argv) { using namespace nglib; cout << "Netgen Testing" << endl; if (argc < 2) { cerr << "use: ng_vol filename" << endl; return 1; } Ng_Mesh * mesh; Ng_Init(); // creates mesh structure mesh = Ng_NewMesh (); int i, np, nse, ne; double point[3]; int trig[3], tet[4]; // reads surface mesh from file ifstream in(argv[1]); in >> np; cout << "Reading " << np << " points..."; cout.flush(); for (i = 1; i <= np; i++) { in >> point[0] >> point[1] >> point[2]; Ng_AddPoint (mesh, point); } cout << "done" << endl; in >> nse; cout << "Reading " << nse << " faces..."; cout.flush(); for (i = 1; i <= nse; i++) { in >> trig[0] >> trig[1] >> trig[2]; Ng_AddSurfaceElement (mesh, NG_TRIG, trig); } cout << "done" << endl; // generate volume mesh Ng_Meshing_Parameters mp; mp.maxh = 1e6; mp.fineness = 1; mp.second_order = 0; cout << "start meshing" << endl; Ng_GenerateVolumeMesh (mesh, &mp); cout << "meshing done" << endl; // volume mesh output np = Ng_GetNP(mesh); cout << "Points: " << np << endl; for (i = 1; i <= np; i++) { Ng_GetPoint (mesh, i, point); cout << i << ": " << point[0] << " " << point[1] << " " << point[2] << endl; } ne = Ng_GetNE(mesh); cout << "Elements: " << ne << endl; for (i = 1; i <= ne; i++) { Ng_GetVolumeElement (mesh, i, tet); cout << i << ": " << tet[0] << " " << tet[1] << " " << tet[2] << " " << tet[3] << endl; } Ng_SaveMesh(mesh,"test.vol"); return 0; } netgen-6.2.1905/nglib/parallelfunc.cpp0000644000175000017500000000377313504650527016262 0ustar kurtkurt#ifdef PARALLEL #include "dlfcn.h" // #include #include // #include #include void (*NGS_ParallelRun) (const string & message) = NULL; namespace netgen { #include "../interface/writeuser.hpp" extern string ngdir; } void Parallel_Exit(); namespace netgen { extern AutoPtr mesh; // extern VisualSceneMesh vsmesh; extern DLL_HEADER MeshingParameters mparam; } using namespace netgen; using netgen::RegisterUserFormats; namespace netgen { // int id, ntasks; MPI_Comm mesh_comm; } void ParallelRun() { string message; MPI_Status status; MPI_Comm_size(MPI_COMM_WORLD, &ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &id); while ( true ) { message = MyMPI_RecvCmd(); if ( message.compare(0, 3, "ngs") == 0 ) { if (NGS_ParallelRun == NULL) { static int timer = NgProfiler::CreateTimer ("load shared library ngsolve"); NgProfiler::RegionTimer reg (timer); void * handle = dlopen ("libngsolve.so", RTLD_NOW | RTLD_GLOBAL); if (!handle) { cerr << "cannot load shared library libngsolve.so" << endl; exit(1); } NGS_ParallelRun = (void (*) (const string & message)) dlsym (handle, "NGS_ParallelRun"); if (!NGS_ParallelRun) { cerr << "cannot bind function NGS_ParallelRun" << endl; exit(1); } } (*NGS_ParallelRun) (message); } else if ( message == "mesh" ) { VT_USER_START ("Mesh::ReceiveParallelMesh"); mesh.Reset( new netgen::Mesh); mesh->SendRecvMesh(); VT_USER_END ("Mesh::ReceiveParallelMesh"); } else if ( message == "visualize" ) { cout << "parallel message visualize depreciated" << endl; } else if ( message == "bcastparthread" ) { MyMPI_Bcast (mparam.parthread); } else if ( message == "end" ) { break; } else { PrintMessage ( 1, "received unidentified message '" + message + "'\n"); break; } } } #endif netgen-6.2.1905/nglib/hinge.stl0000644000175000017500000115516113504650527014724 0ustar kurtkurtsolid facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 3.853128e+001 1.825847e+001 5.000000e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.878911e+001 1.881140e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 3.957044e+001 1.974256e+001 5.000000e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.007020e+001 2.009249e+001 5.000000e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.121243e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.242797e+001 2.050823e+001 5.000000e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.406996e+001 1.974256e+001 5.000000e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 3.947097e+001 1.620635e+001 4.399139e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 3.965514e+001 1.581140e+001 4.399139e+000 vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 3.990509e+001 1.545443e+001 4.399139e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 4.021323e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.021323e+001 1.514629e+001 4.399139e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.057020e+001 1.489634e+001 4.399139e+000 vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.096515e+001 1.471217e+001 4.399139e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.096515e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.096515e+001 1.471217e+001 4.399139e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.138608e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.138608e+001 1.459938e+001 4.399139e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.182020e+001 1.456140e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.182020e+001 1.456140e+001 4.399139e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 vertex 4.242797e+001 1.361457e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.242797e+001 1.361457e+001 5.000000e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.307020e+001 1.489634e+001 4.399139e+000 vertex 4.267525e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 vertex 4.307020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 4.307020e+001 1.489634e+001 4.399139e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 vertex 4.342717e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 4.342717e+001 1.514629e+001 4.399139e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 4.373531e+001 1.545443e+001 4.399139e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.485129e+001 1.531140e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.485129e+001 1.531140e+001 5.000000e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.620635e+001 4.399139e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.620635e+001 4.399139e+000 vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 4.510912e+001 1.586433e+001 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 4.428222e+001 1.662728e+001 4.399139e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.432020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 vertex 4.526703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.526703e+001 1.766917e+001 5.000000e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.398526e+001 1.831140e+001 4.399139e+000 vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.406996e+001 1.974256e+001 5.000000e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 4.406996e+001 1.974256e+001 5.000000e+000 vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.526703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.373531e+001 1.545443e+001 4.399139e+000 vertex 4.485129e+001 1.531140e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 4.342717e+001 1.514629e+001 4.399139e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.373531e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.242797e+001 1.361457e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.182020e+001 1.456140e+001 4.399139e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.432020e+001 1.706140e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.432020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -9.048915e-016 outer loop vertex 4.432020e+001 1.706140e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.428222e+001 1.749552e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 outer loop vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -1.030095e-015 outer loop vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.428222e+001 1.749552e+001 4.399139e+000 vertex 4.416943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 1.440206e-016 outer loop vertex 4.398526e+001 1.831140e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 4.399139e+000 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -1.586601e-015 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 4.399139e+000 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 outer loop vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.373531e+001 1.866837e+001 4.399139e+000 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -1.324456e-015 outer loop vertex 4.307020e+001 1.922646e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 4.399139e+000 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -1.217252e-015 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 4.399139e+000 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 outer loop vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.267525e+001 1.941063e+001 4.399139e+000 vertex 4.225432e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 outer loop vertex 4.182020e+001 1.956140e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 4.399139e+000 vertex 4.182020e+001 1.956140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 4.399139e+000 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -2.500203e-016 outer loop vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.138608e+001 1.952342e+001 4.399139e+000 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -9.292106e-016 outer loop vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 4.399139e+000 vertex 4.057020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -9.250596e-016 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 4.399139e+000 vertex 4.021323e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -1.142109e-015 outer loop vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -1.059565e-015 outer loop vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 4.399139e+000 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -4.853241e-016 outer loop vertex 3.947097e+001 1.791645e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 4.399139e+000 vertex 3.947097e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 outer loop vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.935818e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.935818e+001 1.749552e+001 4.399139e+000 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.038636e-017 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 4.399139e+000 vertex 3.935818e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.947097e+001 1.620635e+001 4.399139e+000 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 2.316081e-016 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 4.399139e+000 vertex 3.990509e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 2.855272e-016 outer loop vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 3.990509e+001 1.545443e+001 4.399139e+000 vertex 4.021323e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 3.307707e-016 outer loop vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 4.021323e+001 1.514629e+001 4.399139e+000 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -6.826070e-016 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 4.399139e+000 vertex 4.096515e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -4.180408e-016 outer loop vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 4.096515e+001 1.471217e+001 4.399139e+000 vertex 4.138608e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.138608e+001 1.459938e+001 4.399139e+000 vertex 4.182020e+001 1.456140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.182020e+001 1.456140e+001 4.399139e+000 vertex 4.225432e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 2.800343e-017 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 4.399139e+000 vertex 4.267525e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -3.659639e-016 outer loop vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.307020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 5.956618e-016 outer loop vertex 4.342717e+001 1.514629e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 4.399139e+000 vertex 4.342717e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 4.399139e+000 vertex 4.373531e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.373531e+001 1.545443e+001 4.399139e+000 vertex 4.398526e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 4.399139e+000 vertex 4.416943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 4.428222e+001 1.662728e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 4.399139e+000 vertex 4.428222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 4.428222e+001 1.662728e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.373531e+001 1.545443e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 8.614567e-016 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -3.257609e-016 outer loop vertex 4.342717e+001 1.514629e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 3.166431e-016 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.267525e+001 1.471217e+001 4.399139e+000 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 endloop endfacet facet normal -2.588190e-001 9.659258e-001 0.000000e+000 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 0.000000e+000 outer loop vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.182020e+001 1.456140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -1.411631e-016 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 4.138608e+001 1.459938e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -4.198697e-016 outer loop vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 4.096515e+001 1.471217e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 3.691957e-016 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 3.330001e-016 outer loop vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 4.021323e+001 1.514629e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 2.855272e-016 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 3.990509e+001 1.545443e+001 4.399139e+000 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal 8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 3.947097e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 2.090204e-016 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 3.935818e+001 1.662728e+001 4.399139e+000 vertex 3.947097e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.040056e-016 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 3.935818e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 1.030095e-015 outer loop vertex 3.947097e+001 1.791645e+001 -8.881784e-016 vertex 3.947097e+001 1.791645e+001 4.399139e+000 vertex 3.935818e+001 1.749552e+001 -8.881784e-016 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 1.954566e-016 outer loop vertex 3.947097e+001 1.791645e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 2.606088e-016 outer loop vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 5.710544e-016 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 4.021323e+001 1.897651e+001 4.399139e+000 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 3.981523e-016 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 1.216174e-015 outer loop vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 5.284567e-016 outer loop vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.138608e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 outer loop vertex 4.182020e+001 1.956140e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 2.497501e-016 outer loop vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.267525e+001 1.941063e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 2.461305e-016 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 outer loop vertex 4.307020e+001 1.922646e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 0.000000e+000 outer loop vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.373531e+001 1.866837e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 1.520218e-015 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 4.850219e-016 outer loop vertex 4.398526e+001 1.831140e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.235818e+001 1.262728e+001 4.399139e+000 vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.247097e+001 1.220635e+001 4.399139e+000 vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 vertex 2.213904e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 vertex 2.362313e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.362313e+001 9.772476e+000 5.000000e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.438608e+001 1.059938e+001 4.399139e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.438608e+001 1.059938e+001 4.399139e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.421243e+001 9.614573e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.056140e+001 4.399139e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 vertex 2.601727e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.601727e+001 9.772476e+000 5.000000e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.607020e+001 1.089634e+001 4.399139e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.607020e+001 1.089634e+001 4.399139e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.657020e+001 1.003031e+001 5.000000e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.642717e+001 1.114629e+001 4.399139e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 2.785129e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.728222e+001 1.262728e+001 4.399139e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.716943e+001 1.391645e+001 4.399139e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.673531e+001 1.466837e+001 4.399139e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.642717e+001 1.497651e+001 4.399139e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.607020e+001 1.522646e+001 4.399139e+000 vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 2.482020e+001 1.556140e+001 4.399139e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.438608e+001 1.552342e+001 4.399139e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 2.321323e+001 1.497651e+001 4.399139e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 2.257044e+001 1.574256e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 vertex 2.257044e+001 1.574256e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 2.290509e+001 1.466837e+001 4.399139e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.265514e+001 1.431140e+001 4.399139e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 vertex 2.137337e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 2.232020e+001 1.306140e+001 4.399139e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.137337e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 2.728222e+001 1.262728e+001 4.399139e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.785129e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.601727e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.362313e+001 9.772476e+000 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.213904e+001 1.081164e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 -3.438588e-017 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 2.732020e+001 1.306140e+001 0.000000e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -6.515219e-017 outer loop vertex 2.732020e+001 1.306140e+001 4.399139e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.728222e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 1.414640e-015 outer loop vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.716943e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -3.545305e-016 outer loop vertex 2.716943e+001 1.391645e+001 0.000000e+000 vertex 2.728222e+001 1.349552e+001 4.399139e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 -7.585588e-016 outer loop vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -2.635182e-016 outer loop vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -5.710544e-016 outer loop vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -8.612394e-016 outer loop vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -4.853241e-016 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -5.300545e-016 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 outer loop vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -5.029161e-016 outer loop vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -6.400577e-016 outer loop vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -5.879071e-016 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 vertex 2.357020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -5.942889e-016 outer loop vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -5.710544e-016 outer loop vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -8.612394e-016 outer loop vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -3.146724e-016 outer loop vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 outer loop vertex 2.235818e+001 1.349552e+001 0.000000e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 outer loop vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 3.519318e-017 outer loop vertex 2.235818e+001 1.262728e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 -5.710544e-016 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 1.706518e-016 outer loop vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 2.316081e-016 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 -2.855272e-016 outer loop vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 0.000000e+000 outer loop vertex 2.357020e+001 1.089634e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -3.413035e-016 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -2.090204e-016 outer loop vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 vertex 2.438608e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -7.038636e-017 outer loop vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 4.399139e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 -3.318735e-016 outer loop vertex 2.525432e+001 1.059938e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 2.090204e-016 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 0.000000e+000 outer loop vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 vertex 2.607020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 1.324456e-016 outer loop vertex 2.642717e+001 1.114629e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 4.399139e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 5.710544e-016 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 -3.413035e-016 outer loop vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 -1.045102e-016 outer loop vertex 2.728222e+001 1.262728e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 vertex 2.728222e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 -2.063153e-016 outer loop vertex 2.728222e+001 1.262728e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 6.587610e-016 outer loop vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.673531e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 2.895653e-016 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 0.000000e+000 outer loop vertex 2.642717e+001 1.114629e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 3.402392e-016 outer loop vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.567525e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 -1.845979e-016 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 7.058154e-017 outer loop vertex 2.525432e+001 1.059938e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -7.058154e-017 outer loop vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -2.099348e-016 outer loop vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.396515e+001 1.071217e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 0.000000e+000 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 -1.303044e-016 outer loop vertex 2.357020e+001 1.089634e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 2.895653e-016 outer loop vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.290509e+001 1.145443e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 2.316522e-016 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -3.909131e-016 outer loop vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.247097e+001 1.220635e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 1.049674e-016 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.040056e-016 outer loop vertex 2.235818e+001 1.262728e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 outer loop vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 1.134605e-015 outer loop vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.247097e+001 1.391645e+001 4.399139e+000 vertex 2.235818e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 5.863697e-016 outer loop vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 9.266089e-016 outer loop vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 8.542176e-016 outer loop vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 8.612394e-016 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.357020e+001 1.522646e+001 4.399139e+000 vertex 2.321323e+001 1.497651e+001 0.000000e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 8.542176e-016 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 9.193698e-016 outer loop vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 outer loop vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 9.051759e-016 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.525432e+001 1.552342e+001 4.399139e+000 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 1.031576e-015 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 5.863697e-016 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 9.266089e-016 outer loop vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 1.143783e-015 outer loop vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 6.298045e-016 outer loop vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 1.049674e-015 outer loop vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 4.320200e+000 1.706140e+001 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 4.373373e+000 1.766917e+001 5.000000e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex 4.373373e+000 1.766917e+001 5.000000e+000 endloop endfacet facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 4.789111e+000 1.881140e+001 5.000000e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 6.070200e+000 2.009249e+001 5.000000e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 6.623129e+000 2.035032e+001 5.000000e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 6.623129e+000 2.035032e+001 5.000000e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 endloop endfacet facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 7.212431e+000 2.050823e+001 5.000000e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 7.386080e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 7.820200e+000 2.056140e+001 5.000000e+000 vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 vertex 9.070200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 9.070200e+000 1.922646e+001 4.399139e+000 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 1.050136e+001 1.931116e+001 5.000000e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 1.085129e+001 1.881140e+001 5.000000e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 1.126703e+001 1.766917e+001 5.000000e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 outer loop vertex 1.126703e+001 1.766917e+001 5.000000e+000 vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 5.655136e+000 1.581140e+001 4.399139e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 vertex 5.655136e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 5.655136e+000 1.581140e+001 4.399139e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 5.905089e+000 1.545443e+001 4.399139e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex 5.570443e+000 1.438024e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 5.570443e+000 1.438024e+001 5.000000e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 6.965150e+000 1.471217e+001 4.399139e+000 vertex 6.570200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 6.965150e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal 1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 9.070200e+000 1.489634e+001 4.399139e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.545443e+001 4.399139e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 9.735311e+000 1.545443e+001 4.399139e+000 vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal -4.230768e-001 2.962415e-001 8.562984e-001 outer loop vertex 1.050136e+001 1.481164e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 9.985264e+000 1.581140e+001 4.399139e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 2.182745e-001 8.562984e-001 outer loop vertex 1.016943e+001 1.620635e+001 4.399139e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal -4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.028222e+001 1.662728e+001 4.399139e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 1.028222e+001 1.662728e+001 4.399139e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.032020e+001 1.706140e+001 4.399139e+000 endloop endfacet facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 endloop endfacet facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 outer loop vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 outer loop vertex 9.070200e+000 1.922646e+001 4.399139e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 9.570200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 vertex 9.570200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 outer loop vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 endloop endfacet facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal -2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 9.070200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal -2.182745e-001 4.680911e-001 8.562984e-001 outer loop vertex 9.070200e+000 1.489634e+001 4.399139e+000 vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal -1.336752e-001 4.988827e-001 8.562984e-001 outer loop vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal -4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 endloop endfacet facet normal 4.501432e-002 5.145160e-001 8.562984e-001 outer loop vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 endloop endfacet facet normal 2.962415e-001 4.230768e-001 8.562984e-001 outer loop vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 5.570443e+000 1.438024e+001 5.000000e+000 endloop endfacet facet normal 3.652075e-001 3.652075e-001 8.562984e-001 outer loop vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 4.988827e-001 1.336752e-001 8.562984e-001 outer loop vertex 5.358181e+000 1.662728e+001 4.399139e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 5.145160e-001 4.501432e-002 8.562984e-001 outer loop vertex 5.358181e+000 1.662728e+001 4.399139e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 -8.881784e-016 vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 8.715574e-002 0.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal -9.961947e-001 -8.715574e-002 -9.067013e-016 outer loop vertex 1.032020e+001 1.706140e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.028222e+001 1.749552e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 outer loop vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -9.659258e-001 -2.588190e-001 -6.400577e-016 outer loop vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 1.028222e+001 1.749552e+001 4.399139e+000 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 -5.879071e-016 outer loop vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 4.399139e+000 vertex 9.985264e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 -5.942889e-016 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.985264e+000 1.831140e+001 4.399139e+000 vertex 9.735311e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.735311e+000 1.866837e+001 4.399139e+000 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 -6.296313e-016 outer loop vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 4.399139e+000 vertex 9.070200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 -1.046600e-015 outer loop vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 4.399139e+000 vertex 8.675250e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 4.399139e+000 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 outer loop vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 8.254320e+000 1.952342e+001 4.399139e+000 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 outer loop vertex 7.386080e+000 1.952342e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 4.399139e+000 vertex 7.386080e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 -3.545305e-016 outer loop vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 6.965150e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 -7.585588e-016 outer loop vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.965150e+000 1.941063e+001 4.399139e+000 vertex 6.570200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 -1.040864e-015 outer loop vertex 6.213231e+000 1.897651e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 4.399139e+000 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 -8.565816e-016 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 4.399139e+000 vertex 5.905089e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 -3.980232e-016 outer loop vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 -8.512880e-016 outer loop vertex 5.470968e+000 1.791645e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 4.399139e+000 vertex 5.470968e+000 1.791645e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 -7.250733e-016 outer loop vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 5.358181e+000 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 outer loop vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.358181e+000 1.749552e+001 4.399139e+000 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.038636e-017 outer loop vertex 5.358181e+000 1.662728e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 4.399139e+000 vertex 5.358181e+000 1.662728e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 -3.900374e-016 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 4.399139e+000 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -1.829819e-016 outer loop vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.470968e+000 1.620635e+001 4.399139e+000 vertex 5.655136e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 6.622278e-017 outer loop vertex 5.905089e+000 1.545443e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 4.399139e+000 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 7.071068e-001 7.071068e-001 -6.583952e-030 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 4.399139e+000 vertex 6.213231e+000 1.514629e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 2.149666e-016 outer loop vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 6.570200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 -2.559776e-016 outer loop vertex 6.965150e+000 1.471217e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 4.399139e+000 vertex 6.965150e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -1.567653e-016 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 4.399139e+000 vertex 7.386080e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -1.759659e-017 outer loop vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 7.386080e+000 1.459938e+001 4.399139e+000 vertex 7.820200e+000 1.456140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 7.038636e-017 outer loop vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 4.399139e+000 vertex 8.254320e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 -2.855272e-016 outer loop vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 4.399139e+000 vertex 8.675250e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -1.953121e-016 outer loop vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 8.675250e+000 1.471217e+001 4.399139e+000 vertex 9.070200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -9.916256e-017 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 4.399139e+000 vertex 9.427169e+000 1.514629e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 9.427169e+000 1.514629e+001 4.399139e+000 vertex 9.735311e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 4.399139e+000 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 3.659639e-016 outer loop vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 9.985264e+000 1.581140e+001 4.399139e+000 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 0.000000e+000 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 4.399139e+000 vertex 1.028222e+001 1.662728e+001 4.399139e+000 endloop endfacet facet normal -9.659258e-001 2.588190e-001 3.909131e-016 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 4.226183e-001 0.000000e+000 outer loop vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 9.985264e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 5.735764e-001 0.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 7.071068e-001 0.000000e+000 outer loop vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.427169e+000 1.514629e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 8.191520e-001 -9.410872e-017 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 9.063078e-001 -1.954566e-016 outer loop vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 8.675250e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 9.659258e-001 2.099348e-016 outer loop vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 9.961947e-001 1.809783e-017 outer loop vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 4.399139e+000 endloop endfacet facet normal 8.715574e-002 9.961947e-001 -5.429349e-017 outer loop vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 7.386080e+000 1.459938e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 9.659258e-001 -1.592609e-016 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 9.063078e-001 2.750870e-016 outer loop vertex 6.965150e+000 1.471217e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 8.191520e-001 9.916256e-017 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 6.213231e+000 1.514629e+001 4.399139e+000 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 endloop endfacet facet normal 7.071068e-001 7.071068e-001 1.447826e-016 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 5.735764e-001 -1.592609e-016 outer loop vertex 5.905089e+000 1.545443e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 4.399139e+000 endloop endfacet facet normal 9.063078e-001 4.226183e-001 -3.691957e-016 outer loop vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.470968e+000 1.620635e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 2.588190e-001 2.099348e-016 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 8.715574e-002 7.040056e-016 outer loop vertex 5.358181e+000 1.662728e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 4.399139e+000 endloop endfacet facet normal 9.961947e-001 -8.715574e-002 7.040056e-016 outer loop vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex 5.358181e+000 1.749552e+001 4.399139e+000 endloop endfacet facet normal 9.659258e-001 -2.588190e-001 6.400577e-016 outer loop vertex 5.470968e+000 1.791645e+001 -8.881784e-016 vertex 5.470968e+000 1.791645e+001 4.399139e+000 vertex 5.358181e+000 1.749552e+001 -8.881784e-016 endloop endfacet facet normal 9.063078e-001 -4.226183e-001 9.338481e-016 outer loop vertex 5.470968e+000 1.791645e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal 8.191520e-001 -5.735764e-001 5.942889e-016 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 5.905089e+000 1.866837e+001 4.399139e+000 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.071068e-001 -7.071068e-001 4.271088e-016 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal 5.735764e-001 -8.191520e-001 6.298045e-016 outer loop vertex 6.213231e+000 1.897651e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal 4.226183e-001 -9.063078e-001 1.049674e-015 outer loop vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex 6.965150e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal 2.588190e-001 -9.659258e-001 5.300545e-016 outer loop vertex 7.386080e+000 1.952342e+001 -8.881784e-016 vertex 7.386080e+000 1.952342e+001 4.399139e+000 vertex 6.965150e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 outer loop vertex 7.386080e+000 1.952342e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 4.399139e+000 endloop endfacet facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 outer loop vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 8.254320e+000 1.952342e+001 4.399139e+000 endloop endfacet facet normal -2.588190e-001 -9.659258e-001 3.547175e-016 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 4.399139e+000 endloop endfacet facet normal -4.226183e-001 -9.063078e-001 7.601089e-016 outer loop vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 4.399139e+000 endloop endfacet facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 outer loop vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 4.399139e+000 endloop endfacet facet normal -7.071068e-001 -7.071068e-001 8.542176e-016 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.735311e+000 1.866837e+001 4.399139e+000 endloop endfacet facet normal -8.191520e-001 -5.735764e-001 8.614567e-016 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 9.985264e+000 1.831140e+001 4.399139e+000 endloop endfacet facet normal -9.063078e-001 -4.226183e-001 8.542176e-016 outer loop vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 4.399139e+000 endloop endfacet facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 outer loop vertex 1.482020e+001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 2.425509e-016 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -4.635355e-016 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 -2.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 5.101317e-016 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -5.234721e-016 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -4.809511e-016 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -5.134128e-016 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -5.024296e-016 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -4.870609e-016 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal -4.973720e-016 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal -4.930284e-016 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -4.799411e-016 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 2.000000e+000 vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 1.561400e+000 2.401924e+000 vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 -1.438600e+000 7.598076e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex -1.798000e-001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 2.880478e+000 3.973940e+000 vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex -1.798000e-001 1.561400e+000 2.401924e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 1.561400e+000 2.401924e+000 vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex -1.798000e-001 6.140000e-002 2.000000e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 4.891892e-016 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 2.000000e+000 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal 4.741508e-016 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal 4.759201e-016 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 4.706124e-016 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 4.599971e-016 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 4.812277e-016 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 4.546894e-016 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 outer loop vertex 3.482020e+001 -2.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 outer loop vertex 4.982020e+001 -2.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 2.425509e-016 9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -2.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -4.635355e-016 9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -2.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 5.101317e-016 9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -5.234721e-016 9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -4.809511e-016 9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -5.134128e-016 8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -5.024296e-016 7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -4.870609e-016 5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal -4.973720e-016 4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal -4.930284e-016 2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -4.799411e-016 8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 4.982020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 4.982020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 outer loop vertex 3.482020e+001 3.061400e+000 5.000000e+000 vertex 4.982020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 -1.866963e+000 7.298133e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 outer loop vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 outer loop vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 outer loop vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 outer loop vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 outer loop vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 outer loop vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 outer loop vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 3.061400e+000 5.000000e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 outer loop vertex 3.482020e+001 3.061400e+000 5.000000e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 outer loop vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 1.561400e+000 2.401924e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 endloop endfacet facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 3.482020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 4.891892e-016 8.715574e-002 9.961947e-001 outer loop vertex 3.482020e+001 6.140000e-002 2.000000e+000 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal 4.741508e-016 2.588190e-001 9.659258e-001 outer loop vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal 4.759201e-016 4.226183e-001 9.063078e-001 outer loop vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 4.706124e-016 5.735764e-001 8.191520e-001 outer loop vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 4.599971e-016 7.071068e-001 7.071068e-001 outer loop vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 4.812277e-016 8.191520e-001 5.735764e-001 outer loop vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 4.546894e-016 9.063078e-001 4.226183e-001 outer loop vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.893023e+000 4.479055e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -2.757678e+000 3.973940e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.866963e+000 2.701867e+000 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -1.438600e+000 2.401924e+000 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 vertex 3.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.823445e-001 2.045577e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 3.482020e+001 1.087460e+000 2.180922e+000 vertex 3.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 3.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 2.701867e+000 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 4.150665e+000 6.093379e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 4.813319e+000 1.336768e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 3.482020e+001 2.359533e+000 3.071637e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 3.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.015823e+000 5.520945e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 2.880478e+000 6.026060e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 3.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.989763e+000 7.298133e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 1.561400e+000 7.598076e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 3.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 3.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 vertex 3.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -1.866963e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.236733e+000 6.928363e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -2.536676e+000 6.500000e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 3.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 3.015823e+000 4.479055e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 3.482020e+001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 3.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -9.646604e-001 2.180922e+000 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 6.140000e-002 8.000000e+000 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 5.823445e-001 7.954423e+000 vertex 3.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 1.087460e+000 7.819078e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 2.359533e+000 6.928363e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 3.482020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 2.659476e+000 6.500000e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.966323e-001 8.200039e-002 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal -4.306895e-017 -9.698266e-001 2.437957e-001 outer loop vertex 3.482020e+001 5.980711e+000 4.019309e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 vertex 3.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal -4.425936e-017 -9.966323e-001 8.200039e-002 outer loop vertex 3.482020e+001 5.980711e+000 4.019309e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal 1.692405e-017 -9.698266e-001 2.437957e-001 outer loop vertex 1.482020e+001 5.980711e+000 4.019309e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal -3.581497e-018 -9.169362e-001 3.990338e-001 outer loop vertex 3.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 3.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 0.000000e+000 -9.169362e-001 3.990338e-001 outer loop vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 1.313813e-017 -8.393837e-001 5.435393e-001 outer loop vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 4.813319e+000 1.336768e+000 endloop endfacet facet normal 0.000000e+000 -7.392549e-001 6.734257e-001 outer loop vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 4.150665e+000 6.093379e-001 endloop endfacet facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 4.150665e+000 6.093379e-001 endloop endfacet facet normal 2.820675e-018 -7.392549e-001 6.734257e-001 outer loop vertex 3.482020e+001 4.150665e+000 6.093379e-001 vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 4.813319e+000 1.336768e+000 endloop endfacet facet normal 0.000000e+000 -8.393837e-001 5.435393e-001 outer loop vertex 3.482020e+001 4.813319e+000 1.336768e+000 vertex 3.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.893023e+000 5.520945e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -2.757678e+000 6.026060e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.866963e+000 7.298133e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -1.438600e+000 7.598076e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.659476e+000 6.500000e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 2.880478e+000 6.026060e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.015823e+000 4.479055e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.740815e+000 3.064995e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 2.880478e+000 3.973940e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 2.359533e+000 3.071637e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 1.989763e+000 2.701867e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 1.561400e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.087460e+000 2.180922e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 5.823445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 6.140000e-002 2.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.595445e-001 2.045577e+000 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -9.646604e-001 2.180922e+000 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -2.236733e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.236733e+000 3.071637e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.268727e+000 2.500000e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -2.536676e+000 3.500000e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 vertex 1.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 5.980711e+000 4.019309e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.980711e+000 4.019309e+000 vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 5.740815e+000 3.064995e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.989763e+000 7.298133e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 5.823445e-001 7.954423e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 6.140000e-002 8.000000e+000 vertex 1.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -1.866963e+000 2.701867e+000 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 1.989763e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.150665e+000 6.093379e-001 vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 2.359533e+000 3.071637e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 1.482020e+001 4.813319e+000 1.336768e+000 vertex 1.482020e+001 5.348164e+000 2.162726e+000 vertex 1.482020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 vertex 2.657020e+001 1.609249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 3.832020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.706996e+001 1.574256e+001 5.000000e+000 vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 3.837337e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.837337e+001 1.645363e+001 5.000000e+000 vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 2.750136e+001 1.531116e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.007020e+001 1.403031e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 2.810912e+001 1.186433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 4.062313e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.785129e+001 1.131140e+001 5.000000e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 4.121243e+001 1.361457e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.182020e+001 1.356140e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.242797e+001 1.361457e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.242797e+001 1.361457e+001 5.000000e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.657020e+001 1.609249e+001 5.000000e+000 vertex 3.837337e+001 1.766917e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 vertex 3.853128e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 vertex 2.601727e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.881140e+001 5.000000e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.542797e+001 1.650823e+001 5.000000e+000 vertex 3.913904e+001 1.931116e+001 5.000000e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 vertex 9.017271e+000 2.035032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 4.007020e+001 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.570200e+000 2.009249e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 2.482020e+001 1.656140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 1.006996e+001 1.974256e+001 5.000000e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 vertex 1.050136e+001 1.931116e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 2.421243e+001 1.650823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.085129e+001 1.881140e+001 5.000000e+000 vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 1.110912e+001 1.825847e+001 5.000000e+000 vertex 1.126703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 1.126703e+001 1.766917e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.257044e+001 1.574256e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 vertex 1.126703e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 1.126703e+001 1.645363e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.153128e+001 1.425847e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.132020e+001 1.306140e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.153128e+001 1.186433e+001 5.000000e+000 vertex 2.137337e+001 1.245363e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.007020e+001 2.009249e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 9.017271e+000 2.035032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 2.050823e+001 5.000000e+000 vertex 9.017271e+000 2.035032e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 2.050823e+001 5.000000e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.182020e+001 2.056140e+001 5.000000e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.242797e+001 2.050823e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.301727e+001 2.035032e+001 5.000000e+000 vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.357020e+001 2.009249e+001 5.000000e+000 vertex 4.406996e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.406996e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.450136e+001 1.931116e+001 5.000000e+000 vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.485129e+001 1.881140e+001 5.000000e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.526703e+001 1.766917e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.510912e+001 1.825847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.526703e+001 1.766917e+001 5.000000e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.532020e+001 1.706140e+001 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.485129e+001 1.531140e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.510912e+001 1.586433e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.485129e+001 1.531140e+001 5.000000e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.450136e+001 1.481164e+001 5.000000e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.406996e+001 1.438024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.357020e+001 1.403031e+001 5.000000e+000 vertex 4.301727e+001 1.377248e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.121243e+001 1.361457e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 4.182020e+001 1.356140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.062313e+001 1.377248e+001 5.000000e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 vertex 2.826703e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 2.832020e+001 1.306140e+001 5.000000e+000 vertex 4.007020e+001 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.957044e+001 1.438024e+001 5.000000e+000 vertex 3.913904e+001 1.481164e+001 5.000000e+000 vertex 2.826703e+001 1.366917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 2.810912e+001 1.425847e+001 5.000000e+000 vertex 3.913904e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.878911e+001 1.531140e+001 5.000000e+000 vertex 3.853128e+001 1.586433e+001 5.000000e+000 vertex 2.785129e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 1.006996e+001 1.438024e+001 5.000000e+000 vertex 2.132020e+001 1.306140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.137337e+001 1.366917e+001 5.000000e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 vertex 1.050136e+001 1.481164e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.178911e+001 1.481140e+001 5.000000e+000 vertex 1.085129e+001 1.531140e+001 5.000000e+000 vertex 2.153128e+001 1.425847e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 1.110912e+001 1.586433e+001 5.000000e+000 vertex 2.178911e+001 1.481140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.531116e+001 5.000000e+000 vertex 2.257044e+001 1.574256e+001 5.000000e+000 vertex 1.126703e+001 1.645363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.257044e+001 1.574256e+001 5.000000e+000 vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 1.132020e+001 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.307020e+001 1.609249e+001 5.000000e+000 vertex 2.362313e+001 1.635032e+001 5.000000e+000 vertex 1.126703e+001 1.766917e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.482020e+001 1.656140e+001 5.000000e+000 vertex 2.542797e+001 1.650823e+001 5.000000e+000 vertex 3.957044e+001 1.974256e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.750136e+001 1.081164e+001 5.000000e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.706996e+001 1.038024e+001 5.000000e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.601727e+001 9.772476e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.657020e+001 1.003031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.601727e+001 9.772476e+000 5.000000e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.542797e+001 9.614573e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.362313e+001 9.772476e+000 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.421243e+001 9.614573e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.362313e+001 9.772476e+000 5.000000e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.307020e+001 1.003031e+001 5.000000e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 2.257044e+001 1.038024e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.213904e+001 1.081164e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 vertex 8.427969e+000 1.361457e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 2.178911e+001 1.131140e+001 5.000000e+000 vertex 9.017271e+000 1.377248e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 2.132020e+001 1.306140e+001 5.000000e+000 vertex 9.570200e+000 1.403031e+001 5.000000e+000 vertex 2.137337e+001 1.245363e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.373373e+000 1.766917e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.373373e+000 1.766917e+001 5.000000e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.531276e+000 1.825847e+001 5.000000e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.789111e+000 1.881140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.139044e+000 1.931116e+001 5.000000e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 5.570443e+000 1.974256e+001 5.000000e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.623129e+000 2.035032e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 6.070200e+000 2.009249e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 6.623129e+000 2.035032e+001 5.000000e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 7.212431e+000 2.050823e+001 5.000000e+000 vertex 7.820200e+000 2.056140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 8.427969e+000 1.361457e+001 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 7.820200e+000 1.356140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 7.212431e+000 1.361457e+001 5.000000e+000 vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 6.623129e+000 1.377248e+001 5.000000e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.570443e+000 1.438024e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 6.070200e+000 1.403031e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 5.570443e+000 1.438024e+001 5.000000e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 5.139044e+000 1.481164e+001 5.000000e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 4.789111e+000 1.531140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.531276e+000 1.586433e+001 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.373373e+000 1.645363e+001 5.000000e+000 vertex 4.320200e+000 1.706140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 1.482020e+001 6.061400e+000 5.000000e+000 vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 2.482020e+001 9.561400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 3.482020e+001 6.061400e+000 5.000000e+000 vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.526703e+001 1.645363e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.062313e+001 2.035032e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 3.482020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 outer loop vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 outer loop vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 outer loop vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 outer loop vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 -9.961947e-001 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal -5.124559e-017 -8.715574e-002 -9.961947e-001 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 3.482020e+001 6.140000e-002 0.000000e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 3.482020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 outer loop vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 3.482020e+001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 3.482020e+001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 3.482020e+001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 outer loop vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 3.482020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 outer loop vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 3.482020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 3.482020e+001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 3.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 outer loop vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 3.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 3.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 3.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 3.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 3.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 3.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 3.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 3.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 3.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 8.715574e-002 9.961947e-001 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 3.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 0.000000e+000 2.588190e-001 9.659258e-001 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 3.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 4.226183e-001 9.063078e-001 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 3.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 5.735764e-001 8.191520e-001 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 3.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 7.071068e-001 7.071068e-001 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 3.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 8.191520e-001 5.735764e-001 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 3.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 9.063078e-001 4.226183e-001 outer loop vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 3.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 9.659258e-001 2.588190e-001 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 3.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 1.432567e-016 1.253334e-017 -1.000000e+000 outer loop vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.432020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal 1.174024e-016 3.145787e-017 -1.000000e+000 outer loop vertex 4.428222e+001 1.749552e+001 -8.881784e-016 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 9.887861e-017 4.610785e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.416943e+001 1.791645e+001 -8.881784e-016 vertex 4.398526e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 8.409715e-017 5.888546e-017 -1.000000e+000 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.398526e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.118001e-017 7.118001e-017 -1.000000e+000 outer loop vertex 4.373531e+001 1.866837e+001 -8.881784e-016 vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 5.888546e-017 8.409715e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.342717e+001 1.897651e+001 -8.881784e-016 vertex 4.307020e+001 1.922646e+001 -8.881784e-016 endloop endfacet facet normal 4.610785e-017 9.887861e-017 -1.000000e+000 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.307020e+001 1.922646e+001 -8.881784e-016 endloop endfacet facet normal 3.145787e-017 1.174024e-016 -1.000000e+000 outer loop vertex 4.267525e+001 1.941063e+001 -8.881784e-016 vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 1.253334e-017 1.432567e-016 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.225432e+001 1.952342e+001 -8.881784e-016 vertex 4.182020e+001 1.956140e+001 -8.881784e-016 endloop endfacet facet normal -1.618835e-017 1.850337e-016 -1.000000e+000 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.182020e+001 1.956140e+001 -8.881784e-016 endloop endfacet facet normal -7.259975e-017 2.709460e-016 -1.000000e+000 outer loop vertex 4.138608e+001 1.952342e+001 -8.881784e-016 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 1.571783e-016 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.383491e-031 1.571783e-016 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 7.259975e-017 2.709460e-016 -1.000000e+000 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 1.618835e-017 1.850337e-016 -1.000000e+000 outer loop vertex 8.254320e+000 1.952342e+001 -8.881784e-016 vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.253334e-017 1.432567e-016 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 7.820200e+000 1.956140e+001 -8.881784e-016 vertex 7.386080e+000 1.952342e+001 -8.881784e-016 endloop endfacet facet normal -3.145787e-017 1.174024e-016 -1.000000e+000 outer loop vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 7.386080e+000 1.952342e+001 -8.881784e-016 endloop endfacet facet normal -4.610785e-017 9.887861e-017 -1.000000e+000 outer loop vertex 6.965150e+000 1.941063e+001 -8.881784e-016 vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -5.888546e-017 8.409715e-017 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 6.570200e+000 1.922646e+001 -8.881784e-016 vertex 6.213231e+000 1.897651e+001 -8.881784e-016 endloop endfacet facet normal -7.118001e-017 7.118001e-017 -1.000000e+000 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 6.213231e+000 1.897651e+001 -8.881784e-016 endloop endfacet facet normal -8.409715e-017 5.888546e-017 -1.000000e+000 outer loop vertex 5.905089e+000 1.866837e+001 -8.881784e-016 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -9.887861e-017 4.610785e-017 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.655136e+000 1.831140e+001 -8.881784e-016 vertex 5.470968e+000 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -1.174024e-016 3.145787e-017 -1.000000e+000 outer loop vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.470968e+000 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -1.432567e-016 1.253334e-017 -1.000000e+000 outer loop vertex 5.358181e+000 1.749552e+001 -8.881784e-016 vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.850337e-016 -1.618835e-017 -1.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.320200e+000 1.706140e+001 -8.881784e-016 vertex 5.358181e+000 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -2.709460e-016 -7.259975e-017 -1.000000e+000 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex 5.358181e+000 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -1.015055e-016 3.552714e-017 -1.000000e+000 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 5.470968e+000 1.620635e+001 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 5.655136e+000 1.581140e+001 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 5.905089e+000 1.545443e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 6.213231e+000 1.514629e+001 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 6.570200e+000 1.489634e+001 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 6.965150e+000 1.471217e+001 -8.881784e-016 endloop endfacet facet normal 6.691135e-017 -3.482212e-017 -1.000000e+000 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -7.350854e-018 -8.402064e-017 -1.000000e+000 outer loop vertex 7.386080e+000 1.459938e+001 -8.881784e-016 vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 6.587563e-018 -7.529618e-017 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 7.820200e+000 1.456140e+001 -8.881784e-016 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 vertex 2.265514e+001 1.181140e+001 0.000000e+000 endloop endfacet facet normal 4.990041e-017 -4.995282e-017 -1.000000e+000 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.290509e+001 1.145443e+001 0.000000e+000 vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.321323e+001 1.114629e+001 0.000000e+000 vertex 2.357020e+001 1.089634e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.357020e+001 1.089634e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.396515e+001 1.071217e+001 0.000000e+000 vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.438608e+001 1.059938e+001 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 vertex 2.525432e+001 1.059938e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.525432e+001 1.059938e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.567525e+001 1.071217e+001 0.000000e+000 vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.607020e+001 1.089634e+001 0.000000e+000 vertex 2.642717e+001 1.114629e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 2.642717e+001 1.114629e+001 0.000000e+000 endloop endfacet facet normal -4.990041e-017 -4.995282e-017 -1.000000e+000 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 2.673531e+001 1.145443e+001 0.000000e+000 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 endloop endfacet facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 4.138608e+001 1.459938e+001 -8.881784e-016 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 4.096515e+001 1.471217e+001 -8.881784e-016 endloop endfacet facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 2.698526e+001 1.181140e+001 0.000000e+000 vertex 2.716943e+001 1.220635e+001 0.000000e+000 endloop endfacet facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 2.728222e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 vertex 2.728222e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 endloop endfacet facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 2.732020e+001 1.306140e+001 0.000000e+000 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 4.021323e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 4.021323e+001 1.514629e+001 -8.881784e-016 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 3.990509e+001 1.545443e+001 -8.881784e-016 endloop endfacet facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 2.728222e+001 1.349552e+001 0.000000e+000 vertex 2.716943e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 2.716943e+001 1.391645e+001 0.000000e+000 vertex 2.698526e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 2.698526e+001 1.431140e+001 0.000000e+000 vertex 2.673531e+001 1.466837e+001 0.000000e+000 endloop endfacet facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 2.642717e+001 1.497651e+001 0.000000e+000 endloop endfacet facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 2.642717e+001 1.497651e+001 0.000000e+000 vertex 2.607020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 3.947097e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 3.935818e+001 1.749552e+001 -8.881784e-016 vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 2.607020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.096515e+001 1.941063e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 8.675250e+000 1.941063e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 8.675250e+000 1.941063e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 -8.881784e-016 endloop endfacet facet normal 3.279817e-031 -2.423364e-016 -1.000000e+000 outer loop vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal 1.631843e-017 -1.865205e-016 -1.000000e+000 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 2.438608e+001 1.552342e+001 0.000000e+000 endloop endfacet facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 9.985264e+000 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.719385e-017 7.719385e-017 -1.000000e+000 outer loop vertex 9.735311e+000 1.866837e+001 -8.881784e-016 vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 2.438608e+001 1.552342e+001 0.000000e+000 endloop endfacet facet normal -8.446175e-017 1.206239e-016 -1.000000e+000 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 vertex 4.057020e+001 1.922646e+001 -8.881784e-016 endloop endfacet facet normal -1.631843e-017 -1.865205e-016 -1.000000e+000 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal -7.719385e-017 7.719385e-017 -1.000000e+000 outer loop vertex 4.021323e+001 1.897651e+001 -8.881784e-016 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 2.525432e+001 1.552342e+001 0.000000e+000 endloop endfacet facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 outer loop vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 3.990509e+001 1.866837e+001 -8.881784e-016 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 vertex 3.947097e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 2.607020e+001 1.522646e+001 0.000000e+000 vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 3.947097e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 3.932020e+001 1.706140e+001 -8.881784e-016 vertex 3.935818e+001 1.662728e+001 -8.881784e-016 vertex 2.642717e+001 1.497651e+001 0.000000e+000 endloop endfacet facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 2.673531e+001 1.466837e+001 0.000000e+000 vertex 3.935818e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 3.947097e+001 1.620635e+001 -8.881784e-016 vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 2.698526e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 3.965514e+001 1.581140e+001 -8.881784e-016 vertex 3.990509e+001 1.545443e+001 -8.881784e-016 vertex 2.716943e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 4.096515e+001 1.471217e+001 -8.881784e-016 vertex 2.716943e+001 1.220635e+001 0.000000e+000 vertex 4.057020e+001 1.489634e+001 -8.881784e-016 endloop endfacet facet normal -6.587563e-018 -7.529618e-017 -1.000000e+000 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 4.138608e+001 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 7.350854e-018 -8.402064e-017 -1.000000e+000 outer loop vertex 4.182020e+001 1.456140e+001 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 3.482020e+001 3.378025e+000 0.000000e+000 endloop endfacet facet normal -6.691135e-017 -3.482212e-017 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -5.921189e-017 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 6.140000e-002 0.000000e+000 vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.225432e+001 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.267525e+001 1.471217e+001 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.307020e+001 1.489634e+001 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.342717e+001 1.514629e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.373531e+001 1.545443e+001 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.398526e+001 1.581140e+001 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 2.709460e-016 -7.259975e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 vertex 4.428222e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal 1.850337e-016 -1.618835e-017 -1.000000e+000 outer loop vertex 4.432020e+001 1.706140e+001 -8.881784e-016 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.428222e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 2.567525e+001 1.541063e+001 0.000000e+000 vertex 2.525432e+001 1.552342e+001 0.000000e+000 vertex 3.965514e+001 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 2.438608e+001 1.552342e+001 0.000000e+000 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 9.985264e+000 1.831140e+001 -8.881784e-016 endloop endfacet facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.831140e+001 -8.881784e-016 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 endloop endfacet facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 2.396515e+001 1.541063e+001 0.000000e+000 vertex 2.357020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 1.028222e+001 1.749552e+001 -8.881784e-016 vertex 1.016943e+001 1.791645e+001 -8.881784e-016 vertex 2.357020e+001 1.522646e+001 0.000000e+000 endloop endfacet facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 2.357020e+001 1.522646e+001 0.000000e+000 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 1.032020e+001 1.706140e+001 -8.881784e-016 endloop endfacet facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 1.032020e+001 1.706140e+001 -8.881784e-016 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 1.028222e+001 1.662728e+001 -8.881784e-016 endloop endfacet facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 2.321323e+001 1.497651e+001 0.000000e+000 vertex 2.290509e+001 1.466837e+001 0.000000e+000 endloop endfacet facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 2.265514e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 2.265514e+001 1.431140e+001 0.000000e+000 vertex 2.247097e+001 1.391645e+001 0.000000e+000 endloop endfacet facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 2.235818e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 2.235818e+001 1.349552e+001 0.000000e+000 vertex 2.232020e+001 1.306140e+001 0.000000e+000 endloop endfacet facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 outer loop vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 2.235818e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 vertex 2.235818e+001 1.262728e+001 0.000000e+000 endloop endfacet facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 endloop endfacet facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 outer loop vertex 2.247097e+001 1.220635e+001 0.000000e+000 vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 8.675250e+000 1.471217e+001 -8.881784e-016 endloop endfacet facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 outer loop vertex 8.675250e+000 1.471217e+001 -8.881784e-016 vertex 2.265514e+001 1.181140e+001 0.000000e+000 vertex 8.254320e+000 1.459938e+001 -8.881784e-016 endloop endfacet facet normal 8.446175e-017 1.206239e-016 -1.000000e+000 outer loop vertex 9.427169e+000 1.897651e+001 -8.881784e-016 vertex 9.070200e+000 1.922646e+001 -8.881784e-016 vertex 2.482020e+001 1.556140e+001 0.000000e+000 endloop endfacet facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 2.232020e+001 1.306140e+001 0.000000e+000 vertex 9.070200e+000 1.489634e+001 -8.881784e-016 endloop endfacet facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 outer loop vertex 9.427169e+000 1.514629e+001 -8.881784e-016 vertex 9.735311e+000 1.545443e+001 -8.881784e-016 vertex 2.235818e+001 1.349552e+001 0.000000e+000 endloop endfacet facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 2.247097e+001 1.391645e+001 0.000000e+000 vertex 9.735311e+000 1.545443e+001 -8.881784e-016 endloop endfacet facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 outer loop vertex 9.985264e+000 1.581140e+001 -8.881784e-016 vertex 1.016943e+001 1.620635e+001 -8.881784e-016 vertex 2.265514e+001 1.431140e+001 0.000000e+000 endloop endfacet facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 outer loop vertex 1.028222e+001 1.662728e+001 -8.881784e-016 vertex 2.290509e+001 1.466837e+001 0.000000e+000 vertex 1.016943e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 5.921189e-017 0.000000e+000 -1.000000e+000 outer loop vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.015055e-016 3.552714e-017 -1.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.416943e+001 1.620635e+001 -8.881784e-016 endloop endfacet facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 outer loop vertex 3.482020e+001 3.378025e+000 0.000000e+000 vertex 1.482020e+001 3.378025e+000 0.000000e+000 vertex 2.482020e+001 1.056140e+001 0.000000e+000 endloop endfacet facet normal 0.000000e+000 1.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 2.506140e+001 5.000000e+000 endloop endfacet facet normal 0.000000e+000 1.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 vertex -1.798000e-001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex -1.798000e-001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -2.893023e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.893023e+000 5.520945e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.757678e+000 6.026060e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.866963e+000 7.298133e+000 vertex -1.798000e-001 -2.236733e+000 6.928363e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex -1.798000e-001 -2.893023e+000 4.479055e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 vertex -1.798000e-001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 3.500000e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.268727e+000 2.500000e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -2.236733e+000 3.071637e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 vertex -1.798000e-001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.438600e+000 2.401924e+000 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -9.646604e-001 2.180922e+000 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 vertex -1.798000e-001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 6.140000e-002 2.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 5.823445e-001 2.045577e+000 vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 1.087460e+000 2.180922e+000 vertex -1.798000e-001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 1.561400e+000 2.401924e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.989763e+000 2.701867e+000 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 2.506140e+001 0.000000e+000 endloop endfacet facet normal -1.000000e+000 -2.095500e-016 -1.548743e-015 outer loop vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 1.776357e-016 0.000000e+000 outer loop vertex -1.798000e-001 2.506140e+001 5.000000e+000 vertex -1.798000e-001 2.506140e+001 0.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 -2.628500e-015 1.840496e-015 outer loop vertex -1.798000e-001 2.359533e+000 3.071637e+000 vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 -2.086809e-015 9.730950e-016 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 2.659476e+000 3.500000e+000 vertex -1.798000e-001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 -1.863973e-015 4.994500e-016 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 2.880478e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 -1.776357e-015 1.554111e-016 outer loop vertex -1.798000e-001 3.015823e+000 4.479055e+000 vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 endloop endfacet facet normal -1.000000e+000 -1.776357e-015 -1.554111e-016 outer loop vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 3.061400e+000 5.000000e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 vertex -1.798000e-001 2.359533e+000 6.928363e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex -1.798000e-001 1.989763e+000 7.298133e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.989763e+000 7.298133e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 2.561400e+000 9.330127e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 1.771501e+000 9.698463e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 1.561400e+000 7.598076e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 vertex -1.798000e-001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 5.823445e-001 7.954423e+000 vertex -1.798000e-001 6.140000e-002 8.000000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -1.438600e+000 7.598076e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex -1.798000e-001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex -1.798000e-001 -2.536676e+000 6.500000e+000 vertex -1.798000e-001 -2.757678e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -4.595445e-001 2.045577e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 vertex -1.798000e-001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex -1.798000e-001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 6.140000e-002 8.000000e+000 vertex -1.798000e-001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 5.823445e-001 7.954423e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 1.087460e+000 7.819078e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 2.359533e+000 6.928363e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex -1.798000e-001 4.391527e+000 7.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 2.659476e+000 6.500000e+000 endloop endfacet facet normal -1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 2.880478e+000 6.026060e+000 endloop endfacet facet normal -1.000000e+000 -7.105427e-016 4.029688e-015 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 3.015823e+000 5.520945e+000 endloop endfacet facet normal -1.061532e-017 -8.715574e-002 -9.961947e-001 outer loop vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 5.124559e-017 -8.715574e-002 -9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 -8.881784e-016 vertex 1.482020e+001 6.140000e-002 0.000000e+000 vertex -1.798000e-001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 2.547676e-017 -2.588190e-001 -9.659258e-001 outer loop vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal -3.065033e-017 -2.588190e-001 -9.659258e-001 outer loop vertex -1.798000e-001 -8.068409e-001 7.596123e-002 vertex 1.482020e+001 -8.068409e-001 7.596123e-002 vertex -1.798000e-001 -1.648701e+000 3.015369e-001 endloop endfacet facet normal 4.246127e-018 -4.226183e-001 -9.063078e-001 outer loop vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 3.616145e-018 -4.226183e-001 -9.063078e-001 outer loop vertex -1.798000e-001 -1.648701e+000 3.015369e-001 vertex 1.482020e+001 -1.648701e+000 3.015369e-001 vertex -1.798000e-001 -2.438600e+000 6.698730e-001 endloop endfacet facet normal 8.492254e-018 -5.735764e-001 -8.191520e-001 outer loop vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal -2.427694e-017 -5.735764e-001 -8.191520e-001 outer loop vertex -1.798000e-001 -2.438600e+000 6.698730e-001 vertex 1.482020e+001 -2.438600e+000 6.698730e-001 vertex -1.798000e-001 -3.152538e+000 1.169778e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 outer loop vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal -4.186913e-017 -7.071068e-001 -7.071068e-001 outer loop vertex -1.798000e-001 -3.152538e+000 1.169778e+000 vertex 1.482020e+001 -3.152538e+000 1.169778e+000 vertex -1.798000e-001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 2.123063e-017 -8.191520e-001 -5.735764e-001 outer loop vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -4.268727e+000 2.500000e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal -2.908199e-017 -8.191520e-001 -5.735764e-001 outer loop vertex -1.798000e-001 -3.768822e+000 1.786062e+000 vertex 1.482020e+001 -3.768822e+000 1.786062e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal -3.616145e-018 -9.063078e-001 -4.226183e-001 outer loop vertex 1.482020e+001 -4.268727e+000 2.500000e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 outer loop vertex -1.798000e-001 -4.268727e+000 2.500000e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.637063e+000 3.289899e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 6.130066e-017 -9.659258e-001 -2.588190e-001 outer loop vertex -1.798000e-001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.637063e+000 3.289899e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal -2.802264e-017 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 3.318329e-017 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 7.232290e-018 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -2.172279e-030 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 3.884310e-017 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal 8.428841e-017 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal -2.322295e-017 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 4.159406e-017 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 endloop endfacet facet normal 0.000000e+000 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal 5.816399e-017 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 3.884310e-017 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 7.145594e-017 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 0.000000e+000 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex 1.482020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 0.000000e+000 9.961947e-001 8.715574e-002 outer loop vertex 1.482020e+001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 5.061400e+000 5.000000e+000 vertex -1.798000e-001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 1.910757e-017 9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 4.985439e+000 5.868241e+000 vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex 1.482020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal -8.492254e-018 9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 4.759863e+000 6.710101e+000 vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex 1.482020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 4.391527e+000 7.500000e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 vertex 1.482020e+001 3.891622e+000 8.213938e+000 endloop endfacet facet normal -4.344559e-030 7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex 1.482020e+001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 3.891622e+000 8.213938e+000 endloop endfacet facet normal 0.000000e+000 5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 3.275338e+000 8.830222e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 vertex 1.482020e+001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -1.153573e-017 4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex 1.482020e+001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 2.561400e+000 9.330127e+000 endloop endfacet facet normal -6.793803e-017 2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 1.771501e+000 9.698463e+000 vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex 1.482020e+001 9.296409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 9.296409e-001 9.924039e+000 vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex 1.482020e+001 6.140000e-002 1.000000e+001 endloop endfacet facet normal 2.866136e-017 -8.715574e-002 9.961947e-001 outer loop vertex -1.798000e-001 6.140000e-002 1.000000e+001 vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex 1.482020e+001 -8.068409e-001 9.924039e+000 endloop endfacet facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 outer loop vertex -1.798000e-001 -8.068409e-001 9.924039e+000 vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex 1.482020e+001 -1.648701e+000 9.698463e+000 endloop endfacet facet normal -8.492254e-018 -4.226183e-001 9.063078e-001 outer loop vertex -1.798000e-001 -1.648701e+000 9.698463e+000 vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex 1.482020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal -5.944578e-017 -5.735764e-001 8.191520e-001 outer loop vertex -1.798000e-001 -2.438600e+000 9.330127e+000 vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex 1.482020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 outer loop vertex -1.798000e-001 -3.152538e+000 8.830222e+000 vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex 1.482020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal -3.821514e-017 -8.191520e-001 5.735764e-001 outer loop vertex -1.798000e-001 -3.768822e+000 8.213938e+000 vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex 1.482020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 outer loop vertex -1.798000e-001 -4.268727e+000 7.500000e+000 vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex 1.482020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal -1.910757e-017 -9.659258e-001 2.588190e-001 outer loop vertex -1.798000e-001 -4.637063e+000 6.710101e+000 vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex 1.482020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal -9.023020e-017 -9.961947e-001 8.715574e-002 outer loop vertex -1.798000e-001 -4.862639e+000 5.868241e+000 vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex 1.482020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 2.016910e-017 -9.961947e-001 -8.715574e-002 outer loop vertex -1.798000e-001 -4.938600e+000 5.000000e+000 vertex -1.798000e-001 -4.862639e+000 4.131759e+000 vertex 1.482020e+001 -4.862639e+000 4.131759e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 4.982020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 4.982020e+001 -4.862639e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.893023e+000 5.520945e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -4.637063e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.637063e+000 6.710101e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -4.268727e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 4.982020e+001 -2.757678e+000 6.026060e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -2.236733e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 4.982020e+001 -3.768822e+000 8.213938e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 7.298133e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -3.152538e+000 8.830222e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.152538e+000 8.830222e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -2.438600e+000 9.330127e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 4.982020e+001 -1.438600e+000 7.598076e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 6.140000e-002 8.000000e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 5.823445e-001 7.954423e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.891622e+000 8.213938e+000 vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 2.359533e+000 6.928363e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.359533e+000 6.928363e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 4.391527e+000 7.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.391527e+000 7.500000e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 4.759863e+000 6.710101e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 4.982020e+001 2.659476e+000 6.500000e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 3.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.015823e+000 4.479055e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 2.880478e+000 3.973940e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 2.659476e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.359533e+000 3.071637e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 5.000000e+000 vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 2.506140e+001 0.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.506140e+001 0.000000e+000 vertex 4.982020e+001 1.989763e+000 2.701867e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.561400e+000 2.401924e+000 vertex 4.982020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 1.087460e+000 2.180922e+000 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 5.823445e-001 2.045577e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 2.000000e+000 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 6.140000e-002 -8.881784e-016 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 -8.881784e-016 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -8.068409e-001 7.596123e-002 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 4.982020e+001 -4.595445e-001 2.045577e+000 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.152538e+000 1.169778e+000 vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -1.866963e+000 2.701867e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.866963e+000 2.701867e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -3.768822e+000 1.786062e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.768822e+000 1.786062e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -4.268727e+000 2.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 4.982020e+001 -2.236733e+000 3.071637e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 5.868241e+000 vertex 4.982020e+001 -4.938600e+000 5.000000e+000 vertex 4.982020e+001 -2.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 5.061400e+000 5.000000e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 vertex 4.982020e+001 3.015823e+000 5.520945e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 4.759863e+000 6.710101e+000 vertex 4.982020e+001 2.880478e+000 6.026060e+000 vertex 4.982020e+001 4.985439e+000 5.868241e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 3.275338e+000 8.830222e+000 vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 1.989763e+000 7.298133e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 2.561400e+000 9.330127e+000 vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 1.561400e+000 7.598076e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 1.771501e+000 9.698463e+000 vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 1.087460e+000 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 9.296409e-001 9.924039e+000 vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 5.823445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 6.140000e-002 1.000000e+001 vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 6.140000e-002 8.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 9.924039e+000 vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -4.595445e-001 7.954423e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -1.648701e+000 9.698463e+000 vertex 4.982020e+001 -2.438600e+000 9.330127e+000 vertex 4.982020e+001 -9.646604e-001 7.819078e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -3.768822e+000 8.213938e+000 vertex 4.982020e+001 -4.268727e+000 7.500000e+000 vertex 4.982020e+001 -2.536676e+000 6.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -2.893023e+000 4.479055e+000 vertex 4.982020e+001 -4.938600e+000 5.000000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.862639e+000 4.131759e+000 vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -2.757678e+000 3.973940e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -4.637063e+000 3.289899e+000 vertex 4.982020e+001 -4.268727e+000 2.500000e+000 vertex 4.982020e+001 -2.536676e+000 3.500000e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -2.438600e+000 6.698730e-001 vertex 4.982020e+001 -1.648701e+000 3.015369e-001 vertex 4.982020e+001 -1.438600e+000 2.401924e+000 endloop endfacet facet normal 1.000000e+000 0.000000e+000 0.000000e+000 outer loop vertex 4.982020e+001 -8.068409e-001 7.596123e-002 vertex 4.982020e+001 -9.646604e-001 2.180922e+000 vertex 4.982020e+001 -1.648701e+000 3.015369e-001 endloop endfacet endsolid netgen-6.2.1905/nglib/cube.surf0000644000175000017500000000105113504650527014710 0ustar kurtkurt8 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 12 2 1 7 8 2 7 6 1 2 4 6 2 4 3 5 5 6 4 8 3 4 8 4 2 5 3 8 7 5 8 1 6 5 7 1 5 netgen-6.2.1905/nglib/netgen.py0000644000175000017500000000043613504650527014731 0ustar kurtkurtimport sys try: # Linux from libmesh import meshing from libgeom2d import geom2d from libcsg import csg except: # Windows from nglib import * sys.modules['netgen.meshing'] = meshing sys.modules['netgen.geom2d'] = geom2d sys.modules['netgen.csg'] = csg del sys netgen-6.2.1905/nglib/CMakeLists.txt0000644000175000017500000000272013504650527015635 0ustar kurtkurtadd_definitions(-DNGLIB_EXPORTS) if(WIN32) set(nglib_objects $ $ $ $ $ $ $ $ ) if(USE_GUI) set(nglib_objects ${nglib_objects} $ $ $ ) endif(USE_GUI) endif(WIN32) add_library(nglib SHARED nglib.cpp ${nglib_objects}) if(NOT WIN32) target_link_libraries( nglib PUBLIC mesh stl interface geom2d csg stl visual) if(USE_GUI) target_link_libraries( nglib PUBLIC stlvis geom2dvis csgvis ) endif(USE_GUI) endif(NOT WIN32) # target_link_libraries(nglib PRIVATE gen la gprim PUBLIC ngcore) target_link_libraries(nglib PUBLIC ngcore) target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) if(USE_OCC AND NOT WIN32) target_link_libraries(nglib PUBLIC occ) endif(USE_OCC AND NOT WIN32) if(USE_PYTHON) target_link_libraries(nglib PRIVATE ${PYTHON_LIBRARIES}) endif(USE_PYTHON) install(TARGETS nglib ${NG_INSTALL_DIR}) install(FILES nglib.h DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel) netgen-6.2.1905/README.md0000644000175000017500000000076513504650527013270 0ustar kurtkurtNetgen mesh generator NETGEN is an automatic 3d tetrahedral mesh generator. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STL file format. The connection to a geometry kernel allows the handling of IGES and STEP files. NETGEN contains modules for mesh optimization and hierarchical mesh refinement. Netgen 6.x supports scripting via a Python interface. Netgen is open source based on the LGPL license. It is available for Unix/Linux, Windows, and OSX.netgen-6.2.1905/TODO0000644000175000017500000000000013504650527012457 0ustar kurtkurtnetgen-6.2.1905/NEWS0000644000175000017500000000000013504650527012466 0ustar kurtkurtnetgen-6.2.1905/rules/0000755000175000017500000000000013504650527013133 5ustar kurtkurtnetgen-6.2.1905/rules/makerlsfile.cpp0000644000175000017500000000202613504650527016135 0ustar kurtkurt#include #include #include using namespace std; #define maxlen 1000 int main (int argc, char ** argv) { if (argc != 3) { cout << "use: makerlsfile infile outfile" << endl; exit(1); } char line[maxlen], infile[maxlen], outfile[maxlen];\ char ch; int i, j; /* cout << "infile: "; cin >> infile; cout << "outfile: "; cin >> outfile; */ ifstream inf (argv[1]); ofstream outf (argv[2]); outf << "const char * ngscript[] = {" << endl; while (inf.good()) { i = 0; inf.get(ch); while (ch != '\n' && inf.good() && i < maxlen) { if (ch == '\"') { line[i] = '\\'; line[i+1] = '\"'; i+= 2; } else if (ch == '\\') { line[i] = '\\'; line[i+1] = '\\'; i+= 2; } else { line[i] = ch; i++; } inf.get(ch); } line[i] = 0; cout << line << endl; outf << "\"" << line << "\\n\",\\" << endl; } outf << "0};" << endl; return 0; } netgen-6.2.1905/rules/hexa.rls0000644000175000017500000000516413504650527014610 0ustar kurtkurtrule "Hexa left-right-top" quality 1 flags t; mappoints (0, 0, 0); (1, 0, 0) { 1 } ; (1, 1, 0) { 1 } ; (0, 1, 0) { 1 } ; (0, 0, 1) { 1 } ; (1, 0, 1) { 1 } ; (1, 1, 1) { 1 } ; (0, 1, 1) { 1 } ; mapfaces (4, 3, 2, 1) del; (3, 7, 6, 2) del; (7, 8, 5, 6) del; (8, 4, 1, 5) del; newpoints newfaces (5, 6, 2, 1); (7, 8, 4, 3); elements (4, 3, 2, 1, 8, 7, 6, 5); freezone2 { 1 P5 }; { 1 P6 }; { 1 P2 }; { 1 P3 }; { 0.3 P1, 0.3 P2, 0.3 P5, 0.3 P6, -0.05 P3, -0.05 P4, -0.05 P7, -0.05 P8 }; { 0.3 P3, 0.3 P4, 0.3 P7, 0.3 P8, -0.05 P1, -0.05 P2, -0.05 P5, -0.05 P6 }; freezonelimit { 1 P5 }; { 1 P6 }; { 1 P2 }; { 1 P3 }; { 0.25 P1, 0.25 P2, 0.25 P5, 0.25 P6, -0.0 P3, -0.0 P4, -0.0 P7, -0.0 P8 }; { 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 }; endrule rule "Hexa left-right-top (10)" quality 10 flags t; mappoints (0, 0, 0); (1, 0, 0) { 1 } ; (1, 1, 0) { 1 } ; (0, 1, 0) { 1 } ; (0, 0, 1) { 1 } ; (1, 0, 1) { 1 } ; (1, 1, 1) { 1 } ; (0, 1, 1) { 1 } ; mapfaces (4, 3, 2, 1) del; (3, 7, 6, 2) del; (7, 8, 5, 6) del; (8, 4, 1, 5) del; newpoints newfaces (5, 6, 2, 1); (7, 8, 4, 3); elements (4, 3, 2, 1, 8, 7, 6, 5); freezone2 { 1 P5 }; { 1 P6 }; { 1 P2 }; { 1 P3 }; { 0.251 P1, 0.251 P2, 0.251 P5, 0.251 P6, -0.05 P3, -0.001 P4, -0.001 P7, -0.001 P8 }; { 0.251 P3, 0.251 P4, 0.251 P7, 0.251 P8, -0.05 P1, -0.001 P2, -0.001 P5, -0.001 P6 }; freezonelimit { 1 P5 }; { 1 P6 }; { 1 P2 }; { 1 P3 }; { 0.25 P1, 0.25 P2, 0.25 P5, 0.25 P6, -0.0 P3, -0.0 P4, -0.0 P7, -0.0 P8 }; { 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 }; endrule rule "Hexa left-right-top-front" quality 1 flags t; mappoints (0, 0, 0); (1, 0, 0) { 1 } ; (1, 1, 0) { 1 } ; (0, 1, 0) { 1 } ; (0, 0, 1) { 1 } ; (1, 0, 1) { 1 } ; (1, 1, 1) { 1 } ; (0, 1, 1) { 1 } ; mapfaces (4, 3, 2, 1) del; (3, 7, 6, 2) del; (7, 8, 5, 6) del; (8, 4, 1, 5) del; (1, 2, 6, 5) del; newpoints newfaces (7, 8, 4, 3); elements (4, 3, 2, 1, 8, 7, 6, 5); freezone2 { 1 P5 }; { 1 P6 }; { 1 P2 }; { 1 P3 }; { 0.3 P3, 0.3 P4, 0.3 P7, 0.3 P8, -0.05 P1, -0.05 P2, -0.05 P5, -0.05 P6 }; freezonelimit { 1 P5 }; { 1 P6 }; { 1 P2 }; { 1 P3 }; { 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 }; endrule rule "Hexa fill" quality 1 flags t; mappoints (0, 0, 0); (1, 0, 0) { 1 } ; (1, 1, 0) { 1 } ; (0, 1, 0) { 1 } ; (0, 0, 1) { 1 } ; (1, 0, 1) { 1 } ; (1, 1, 1) { 1 } ; (0, 1, 1) { 1 } ; mapfaces (4, 3, 2, 1) del; (3, 7, 6, 2) del; (7, 8, 5, 6) del; (8, 4, 1, 5) del; (1, 2, 6, 5) del; (3, 4, 8, 7) del; newpoints newfaces elements (4, 3, 2, 1, 8, 7, 6, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P5 }; { 1 P3 }; endrule netgen-6.2.1905/rules/quad.rls0000644000175000017500000001773313504650527014622 0ustar kurtkurtrule "Free Quad (1)" quality 1 mappoints (0, 0); (1, 0); maplines (1, 2) del; newpoints (1, 1) { 1 X2 } { }; (0, 1) { } { }; newlines (3, 2); (4, 3); (1, 4); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 1.5) { 1.5 X2 } { }; (-0.5, 1.5) { -0.5 X2 } { }; elements (1, 2, 3, 4); endrule rule "Free Quad (5)" quality 5 mappoints (0, 0); (1, 0); maplines (1, 2) del; newpoints (1, 1) { 1 X2 } { }; (0, 1) { } { }; newlines (3, 2); (4, 3); (1, 4); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 1.5) { 1.5 X2 } { }; (-0.5, 1.5) { -0.5 X2 } { }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X2 } { }; (0, 1) { } { }; elements (1, 2, 3, 4); endrule rule "Quad Right (1)" quality 1 mappoints (0, 0); (1, 0); (1, 1); maplines (1, 2) del; (2, 3) del; newpoints (0, 1) { } { 1 y3 }; newlines (1, 4); (4, 3); freearea (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (-0.5, 1.5) { } { 1.5 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { } { 1 Y3 }; elements (1, 2, 3, 4); endrule rule "Quad P Right (2)" quality 2 mappoints (0, 0); (1, 0); (1, 1); maplines (1, 2) del; newpoints (0, 1) { -1 X2, 1 X3 } { 1 Y3 }; newlines (1, 4); (4, 3); (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.2, 0.5) { 0.7 X2, 0.5 X3 } { 0.5 Y3 }; (1, 1) { 1 X3 } { 1 Y3 }; (-0.5, 1.5) { -2 X2, 1.5 X3 } { 1.5 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { -1 X2, 1 X3 } { 1 Y3 }; elements (1, 2, 3, 4); orientations (1, 2, 3); endrule rule "Quad Right PL (2)" quality 2 mappoints (0, 0); (1, 0); (1, 1); (0, 1); maplines (1, 2) del; (2, 3) del; newpoints newlines (1, 4); (4, 3); freearea (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 }; (0, 1) { 1 X4 } { 1 Y4 }; (-0.2, 0.5) { -0.1 X2, -0.1 X3, 0.6 X4 } { -0.1 Y2, -0.1 Y3, 0.6 Y4 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 }; (0, 1) { 1 X4 } { 1 Y4 }; (0, 0.5) { 0.5 X4 } { 0.5 Y4 }; elements (1, 2, 3, 4); orientations (1, 2, 3); (1, 3, 4); (1, 2, 4); (4, 2, 3); endrule rule "Left Quad (1)" quality 1 mappoints (0, 0); (1, 0); (0, 1); maplines (1, 2) del; (3, 1) del; newpoints (1, 1) { 1 X2, 1 X3 } { 1 Y3 }; newlines (3, 4); (4, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 }; (0, 1) { 1 X3 } { 1 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X2, 1 X3 } { 1 Y3 }; (0, 1) { 1 X3 } { 1 Y3 }; elements (1, 2, 4, 3); endrule rule "Left P Quad (2)" quality 2 mappoints (0, 0); (1, 0); (0, 1); maplines (1, 2) del; newpoints (1, 1) { 1 X2, 1 X3 } { 1 Y3 }; newlines (1, 3); (3, 4); (4, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 }; (0, 1) { 1 X3 } { 1 Y3 }; (-0.2, 0.6) { -0.2 X2, 0.6 X3 } { 0.6 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X2, 1 X3 } { 1 Y3 }; (0, 1) { 1 X3 } { 1 Y3 }; (0, 0.5) { 0.5 X3 } { 0.5 Y3 }; elements (1, 2, 4, 3); endrule rule "Left Quad RP (2)" quality 2 mappoints (0, 0); (1, 0); (0, 1); (1, 1); maplines (1, 2) del; (3, 1) del; newpoints newlines (3, 4); (4, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.2, 0.5) { 0.6 X2, 0.6 X4, -0.1 X3 } { 0.6 Y2, 0.6 Y4, -0.1 Y3 }; (1, 1) { 1 X4 } { 1 Y4 }; (0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 }; (0, 1) { 1 X3 } { 1 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 0.5) { 0.5 X2, 0.5 X4 } { 0.5 Y2, 0.5 Y4 }; (1, 1) { 1 X4 } { 1 Y4 }; (0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 }; (0, 1) { 1 X3 } { 1 Y3 }; elements (1, 2, 4, 3); orientations (1, 2, 4); (1, 4, 3); endrule rule "Two left (1)" quality 1 mappoints (0, 0); (1, 0); (1, 1); (0, 1); maplines (1, 2) del; (3, 4) del; (4, 1) del; newpoints newlines (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { 1 X4 } { 1 Y4 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { 1 X4 } { 1 Y4 }; elements (1, 2, 3, 4); endrule rule "Two Right (1)" quality 1 mappoints (0, 0); (1, 0); (1, 1); (0, 1); maplines (1, 2) del; (2, 3) del; (3, 4) del; newpoints newlines (1, 4); freearea (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { 1 X4 } { 1 Y4 }; (-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { 1 X4 } { 1 Y4 }; (0, 0.5) { 0.5 X4 } { 0.5 Y4 }; elements (1, 2, 3, 4); endrule rule "Right 120 (1)" quality 1000 mappoints (0, 0); (1, 0); (1.5, 0.866); maplines (1, 2) del; (2, 3) del; newpoints (0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 }; newlines (1, 4); (4, 3); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.866) { 1 X3 } { 1 Y3 }; (1, 1.732) { -2 X2, 2 X3 } { 2 Y3 }; (0, 1.732) { -3 X2, 2 X3 } { 2 Y3 }; (-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 }; elements (1, 2, 4); (2, 3, 4); endrule rule "Left 120 (1)" quality 1000 mappoints (0, 0); (1, 0); (-0.5, 0.866); maplines (1, 2) del; (3, 1) del; newpoints (0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 }; newlines (3, 4); (4, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 }; (1, 1.732) { 2 X2, 2 X3 } { 2 Y3 }; (0, 1.732) { -1 X2, 2 X3 } { 2 Y3 }; (-0.5, 0.866) { 1 X3 } {1 Y3 }; elements (1, 2, 4); (2, 3, 4); endrule rule "Left Right (1)" quality 1 mappoints (0, 0); (1, 0); (1, 1); (0, 1); maplines (1, 2) del; (2, 3) del; (4, 1) del; newlines (4, 3); freearea (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (0.5, 1.5) { -0.25 X2, 0.75 X3, 0.75 X4 } { 0.75 Y3, 0.75 Y4 }; (0, 1) { 1 X4 } { 1 Y4 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 1) { 1 X3 } { 1 Y3 }; (0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 }; (0, 1) { 1 X4 } { 1 Y4 }; elements (1, 2, 3, 4); endrule rule "Fill Quad" quality 1 mappoints (0, 0); (1, 0); (1, 1); (0, 1); maplines (1, 2) del; (2, 3) del; (3, 4) del; (4, 1) del; newpoints newlines freearea (0, 0); (1, 0) { 1 X2 } { 1 Y2 }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { 1 X4 } { 1 Y4 }; elements (1, 2, 3, 4); endrule rule "Fill Triangle" quality 10 mappoints (0, 0); (1, 0); (0.5, 0.86); maplines (1, 2) del; (2, 3) del; (3, 1) del; newpoints newlines freearea (0, 0); (1, 0) { 1 X2 } { 1 Y2 }; (0.5, 0.86) { 1 X3 } { 1 Y3 }; elements (1, 2, 3); endrule rule "Right 60 (1)" quality 10 mappoints (0, 0); (1, 0) { 0.5, 0, 1.0 }; (0.5, 0.866) { 0.6, 0, 0.8 }; maplines (1, 2) del; (2, 3) del; newpoints newlines (1, 3); freearea (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; (-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; (0.25, 0.433) { 0.5 X3 } { 0.5 Y3 }; elements (1, 2, 3); endrule rule "Vis A Vis (2)" quality 2 mappoints (0, 0); (1, 0); (1, 1); (0, 1); maplines (1, 2) del; (3, 4) del; newpoints newlines (1, 4); (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { 1 X4 } { 1 Y4 }; (-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 }; (1, 1) { 1 X3 } { 1 Y3 }; (0, 1) { 1 X4 } { 1 Y4 }; (0, 0.5) { 0.5 X4 } { 0.5 Y4 }; elements (1, 2, 3, 4); orientations (1, 3, 4); (2, 3, 4); (1, 2, 3); (1, 2, 4); endrule rule "2 h Vis A Vis (1)" quality 3000 mappoints (0, 0); (1, 0); (1, 1.732); (0, 1.732); maplines (1, 2) del; (3, 4) del; newpoints (0.5, 0.866) { 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 }; newlines (1, 5); (5, 4); (3, 5); (5, 2); freearea (0, 0); (1, 0) { 1 X2 } { 1 Y2 }; (1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 }; (1, 1.732) { 1 X3 } { 1 Y3 }; (0, 1.732) { 1 X4 } { 1 Y4 }; (-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 }; elements (1, 2, 5); (3, 4, 5); endrule netgen-6.2.1905/rules/pyramids.rls0000644000175000017500000000471713504650527015516 0ustar kurtkurttolfak 0.5 rule "Pyramid on quad" quality 100 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); mapfaces (1, 2, 3, 4) del; newpoints (0.5, 0.5, -0.5) { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { }; newfaces (1, 2, 5); (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule rule "small Pyramid on quad" quality 100 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); mapfaces (1, 2, 3, 4) del; newpoints (0.5, 0.5, -0.1 ) { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { }; newfaces (1, 2, 5); (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule rule "connect pyramid" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0.5, -0.5); mapfaces (1, 2, 3, 4) del; newpoints newfaces (1, 2, 5); (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule rule "pyramid with one trig" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0.5, -0.5); mapfaces (1, 2, 3, 4) del; (2, 1, 5) del; newpoints newfaces (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 }; { 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 }; { 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P3 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 }; { 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 }; { 0.333 P1, 0.333 P4, 0.334 P5, 0 P3 }; orientations (1, 2, 3, 5); (1, 3, 4, 5); freeset 1 2 3 5; freeset 1 3 4 5; freeset 2 3 5 6; freeset 3 4 5 7; freeset 1 4 5 8; endrule rule "pyramid with two trig" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0.5, -0.5); mapfaces (1, 2, 3, 4) del; (2, 1, 5) del; (3, 2, 5) del; newpoints newfaces (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule netgen-6.2.1905/rules/prisms.rls0000644000175000017500000000477213504650527015204 0ustar kurtkurttolfak 0.5 rule "prism on quad" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces (5, 2, 3, 6); (1, 5, 6, 4); elements (1, 5, 2, 4, 6, 3); orientations (1, 2, 3, 5); (1, 3, 4, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 }; { -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 }; { 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 }; endrule rule "prism on 2 quad" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (2, 5, 6, 3) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces (1, 5, 6, 4); elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 }; freeset 1 2 4 5 6 7; freeset 2 3 4 6; endrule rule "prism on 2 quada" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (5, 1, 4, 6) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces (5, 2, 3, 6); elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 }; freeset 1 2 3 5 6 7; freeset 1 3 4 6; endrule rule "fill prism" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (2, 5, 6, 3) del; (5, 1, 4, 6) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; freeset 1 2 4 5; freeset 2 3 4 6; endrule rule "flat prism" quality 1 mappoints (0, 0, 0); (1, 0, 0); (0.5, 0.866, 0); (0, 0, -1); (1, 0, -1); (0.5, 0.866, -1); mapfaces (1, 2, 3) del; (5, 4, 6) del; newpoints newfaces (1, 2, 4); (4, 2, 5); (2, 3, 5); (5, 3, 6); (3, 1, 6); (6, 1, 4); elements (1, 2, 3, 5, 4, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P5 }; { 1 P6 }; endrule netgen-6.2.1905/rules/pyramids2.rls0000644000175000017500000000547113504650527015576 0ustar kurtkurttolfak 0.5 rule "Pyramid on quad" quality 100 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); mapfaces (1, 2, 3, 4) del; newpoints (0.5, 0.5, -0.5) { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { }; newfaces (1, 2, 5); (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule rule "small Pyramid on quad" quality 100 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); mapfaces (1, 2, 3, 4) del; newpoints (0.5, 0.5, -0.1 ) { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { }; newfaces (1, 2, 5); (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule rule "connect pyramid" quality 100 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0.5, -0.5); mapfaces (1, 2, 3, 4) del; newpoints newfaces (1, 2, 5); (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule rule "pyramid with one trig" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0.5, -0.5); mapfaces (1, 2, 3, 4) del; (2, 1, 5) del; newpoints newfaces (2, 3, 5); (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 }; { 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 }; { 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P2 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 }; { 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 }; { 0.333 P1, 0.333 P4, 0.334 P5, 0 P2 }; orientations (1, 2, 3, 5); (1, 3, 4, 5); freeset 1 2 3 5; freeset 1 3 4 5; freeset 2 3 5 6; freeset 3 4 5 7; freeset 1 4 5 8; endrule rule "pyramid with two trig" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0.5, -0.5); mapfaces (1, 2, 3, 4) del; (2, 1, 5) del; (3, 2, 5) del; newpoints newfaces (3, 4, 5); (4, 1, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule rule "pyramid with two trig, left" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0.5, -0.5); mapfaces (1, 2, 3, 4) del; (2, 1, 5) del; (1, 4, 5) del; newpoints newfaces (3, 4, 5); (2, 3, 5); elements (1, 2, 3, 4, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; endrule netgen-6.2.1905/rules/triangle.rls0000644000175000017500000001172213504650527015465 0ustar kurtkurtrule "Free Triangle (1)" quality 1 mappoints (0, 0); (1, 0) { 1.0, 0, 1.0 }; maplines (1, 2) del; newpoints (0.5, 0.866) { 0.5 X2 } { }; newlines (1, 3); (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.7) { 0.5 X2 } { }; (0.5, 1.5) { 0.5 X2 } { }; (-0.5, 0.7) { 0.5 X2 } { }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.866) { 0.5 X2 } { }; (0.5, 0.866) { 0.5 X2 } { }; (0.5, 0.866) { 0.5 X2 } { }; elements (1, 2, 3); endrule rule "Free Triangle (5)" quality 5 mappoints (0, 0); (1, 0) { 1.0, 0, 1.0 }; maplines (1, 2) del; newpoints (0.5, 0.5) { 0.5 X2 } { }; newlines (1, 3); (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1, 0.7) { 1 X2 } { }; (0, 0.7) { } { }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.5) { 0.5 X2 } { }; (0.5, 0.5) { 0.5 X2 } { }; elements (1, 2, 3); endrule rule "Free Triangle (10)" quality 10 mappoints (0, 0); (1, 0) { 1.0, 0, 1.0 }; maplines (1, 2) del; newpoints (0.5, 0.3) { 0.5 X2 } { }; newlines (1, 3); (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1, 0.5) { 1 X2 } { }; (0, 0.5) { } { }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.3) { 0.5 X2 } { }; (0.5, 0.3) { 0.5 X2 } { }; elements (1, 2, 3); endrule rule "Free Triangle (20)" quality 20 mappoints (0, 0); (1, 0) { 1.0, 0, 1.0 }; maplines (1, 2) del; newpoints (0.5, 0.1) { 0.5 X2 } { }; newlines (1, 3); (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1, 0.2) { 1 X2 } { }; (0, 0.2) { } { }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.1) { 0.5 X2 } { }; (0.5, 0.1) { 0.5 X2 } { }; elements (1, 2, 3); endrule rule "Right 60 (1)" quality 1 mappoints (0, 0); (1, 0) { 0.5, 0, 1.0 }; (0.5, 0.866) { 0.6, 0, 0.8 }; maplines (1, 2) del; (2, 3) del; newpoints newlines (1, 3); freearea (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; (-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; (0.25, 0.433) { 0.5 X3 } { 0.5 Y3 }; elements (1, 2, 3); endrule rule "Left 60 (1)" quality 1 mappoints (0, 0); (1, 0); (0.5, 0.866); maplines (1, 2) del; (3, 1) del; newpoints newlines (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.125, 0.6495) { 0.75 X2, 0.75 X3 } { 0.75 Y3 }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; elements (1, 2, 3); endrule rule "Right 120 (1)" quality 1 mappoints (0, 0); (1, 0); (1.5, 0.866); maplines (1, 2) del; (2, 3) del; newpoints (0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 }; newlines (1, 4); (4, 3); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.866) { 1 X3 } { 1 Y3 }; (1, 1.732) { -2 X2, 2 X3 } { 2 Y3 }; (0, 1.732) { -3 X2, 2 X3 } { 2 Y3 }; (-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 }; elements (1, 2, 4); (2, 3, 4); endrule rule "Left 120 (1)" quality 1 mappoints (0, 0); (1, 0); (-0.5, 0.866); maplines (1, 2) del; (3, 1) del; newpoints (0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 }; newlines (3, 4); (4, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 }; (1, 1.732) { 2 X2, 2 X3 } { 2 Y3 }; (0, 1.732) { 1 X2, 2 X3 } { 2 Y3 }; (-0.5, 0.866) { 1 X3 } {1 Y3 }; elements (1, 2, 4); (1, 4, 3); endrule rule "Left Right 120 (1)" quality 1 mappoints (0, 0); (1, 0); (-0.5, 0.866); (1.5, 0.866); maplines (1, 2) del; (3, 1) del; (2, 4) del; newpoints (0.5, 0.866) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 }; newlines (3, 5); (5, 4); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.5, 0.866) { 1 X4 } { 1 Y4 }; (1, 1.299) { -0.5 X2, 0.375 X3, 1.125 X4 } { -0.5 Y2, 0.375 Y3, 1.125 Y4 }; (0, 1.299) { 1.125 X3, 0.375 X4 } { 1.125 Y3, 0.375 Y4 }; (-0.5, 0.866) { 1 X3 } { 1 Y3 }; elements (1, 2, 5); (3, 1, 5); (2, 4, 5); endrule rule "Fill Triangle" quality 1 mappoints (0, 0); (1, 0); (0.5, 0.866); maplines (1, 2) del; (2, 3) del; (3, 1) del; newpoints newlines freearea (0, 0); (1, 0) { 1 X2 } { 1 Y2 }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; elements (1, 2, 3); endrule rule "Vis A Vis (1)" quality 1 mappoints (0, 0); (1, 0); (0.5, 0.866); maplines (1, 2) del; newpoints newlines (1, 3); (3, 2); freearea (0, 0); (1, 0) { 1 X2 } { }; (1.2, 0.693) { 0.8 X2, 0.8 X3 } { 0.8 Y2, 0.8 Y3 }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; (-0.2, 0.693) { -0.6 X2, 0.8 X3 } { -0.6 Y2, 0.8 Y3 }; freearea2 (0, 0); (1, 0) { 1 X2 } { }; (0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 }; (0.5, 0.866) { 1 X3 } { 1 Y3 }; (0.25, 0.433) { 0.5 X3 } { 0.5 Y3 }; elements (1, 2, 3); endrule rule "2 h Vis A Vis (1)" quality 3 mappoints (0, 0); (1, 0); (1, 1.732); (0, 1.732); maplines (1, 2) del; (3, 4) del; newpoints (0.5, 0.866) { 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 }; newlines (1, 5); (5, 4); (3, 5); (5, 2); freearea (0, 0); (1, 0) { 1 X2 } { 1 Y2 }; (1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 }; (1, 1.732) { 1 X3 } { 1 Y3 }; (0, 1.732) { 1 X4 } { 1 Y4 }; (-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 }; elements (1, 2, 5); (3, 4, 5); endrule netgen-6.2.1905/rules/prisms2.rls0000644000175000017500000001033313504650527015254 0ustar kurtkurttolfak 0.5 rule "prism on quad" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces (5, 2, 3, 6); (1, 5, 6, 4); elements (1, 5, 2, 4, 6, 3); orientations (1, 2, 3, 5); (1, 3, 4, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 }; { -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 }; { 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 }; freeset 1 2 4 5 6 7; freeset 2 3 4 5 6 8; endrule rule "prism on quad, one trig" quality 2 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (1, 5, 2) del; newpoints newfaces (5, 2, 3, 6); (1, 5, 6, 4); (4, 6, 3); elements (1, 5, 2, 4, 6, 3); orientations (1, 2, 3, 5); (1, 3, 4, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 }; { -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 }; { 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 }; freeset 1 2 4 5 6 7; freeset 2 3 4 5 6 8; endrule rule "prism on 2 quad" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (2, 5, 6, 3) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces (1, 5, 6, 4); elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 }; freeset 1 2 4 5 6 7; freeset 2 3 4 6; endrule rule "prism on 2 quad, one trig" quality 2 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (2, 5, 6, 3) del; (1, 5, 2) del; newpoints newfaces (1, 5, 6, 4); (4, 6, 3); elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 }; freeset 1 2 4 5 6 7; freeset 2 3 4 6; endrule rule "prism on 2 quada" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (5, 1, 4, 6) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces (5, 2, 3, 6); elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 }; freeset 1 2 3 5 6 7; freeset 1 3 4 6; endrule rule "fill prism" quality 1 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (2, 5, 6, 3) del; (5, 1, 4, 6) del; (1, 5, 2) del; (4, 3, 6) del; newpoints newfaces elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; freeset 1 2 4 5; freeset 2 3 4 6; endrule rule "prism on 3 quad, one trig" quality 2 mappoints (0, 0, 0); (1, 0, 0); (1, 1, 0); (0, 1, 0); (0.5, 0, -0.86); (0.5, 1, -0.86); mapfaces (1, 2, 3, 4) del; (2, 5, 6, 3) del; (5, 1, 4, 6) del; (1, 5, 2) del; newpoints newfaces (4, 6, 3); elements (1, 5, 2, 4, 6, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; freeset 1 2 4 5; freeset 2 3 4 6; endrule rule "flat prism" quality 100 mappoints (0, 0, 0); (1, 0, 0); (0.5, 0.866, 0); (0, 0, -1); (1, 0, -1); (0.5, 0.866, -1); mapfaces (1, 2, 3) del; (5, 4, 6) del; newpoints newfaces (1, 2, 4); (4, 2, 5); (2, 3, 5); (5, 3, 6); (3, 1, 6); (6, 1, 4); elements (1, 2, 3, 5, 4, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P5 }; { 1 P6 }; endrule netgen-6.2.1905/rules/tetra.rls0000644000175000017500000004302213504650527014775 0ustar kurtkurttolfak 0.5 rule "Free Tetrahedron" quality 1 mappoints (0, 0, 0); (1, 0, 0); (0.5, 0.866, 0); mapfaces (1, 2, 3) del; newpoints (0.5, 0.288, -0.816) { 0.333 X1, 0.333 X2, 0.333 X3 } { 0.333 Y1, 0.333 Y2, 0.333 Y3 } { }; newfaces (4, 1, 2); (4, 2, 3); (4, 3, 1); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1.6 P4, -0.2 P1, -0.2 P2, -0.2 P3 }; { -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 }; { 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 }; { 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 }; endrule rule "Tetrahedron 60" quality 1 flags c; mappoints (0, 0, 0); (1, 0, 0) { 0.5 } ; (0.5, 0.866, 0) { 0.5 }; (0.5, 0.288, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; newpoints newfaces (1, 4, 3); (4, 2, 3); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 }; { 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 }; { -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.3333 P2, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P3, 0.3334 P4 }; { 0.65 P3, 0.35 P4 }; endrule rule "Tetrahedron 60 with edge(1)" quality 1 flags c; mappoints (0, 0, 0); (1, 0, 0) { 0.8 }; (0.5, 0.866, 0) { 0.8 }; (0.5, 0.288, -0.816) { 0.8 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; mapedges (3, 4); newpoints newfaces (1, 4, 3); (4, 2, 3); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 }; { 0.4 P2, 0.4 P4, 0.4 P3, -0.2 P1 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.3333 P1, 0.3333 P4, 0.3334 P3 }; { 0.3333 P2, 0.3333 P4, 0.3334 P3 }; endrule rule "Tetrahedron Vis a Vis Point (1)" quality 1 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 0.866, 0) { 0.5 }; (0.5, 0.288, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; newpoints newfaces (4, 3, 1); (4, 2, 3); (4, 1, 2); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 }; { 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 }; { 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 }; { 0.8 P1, -0.1 P2, -0.1 P3, 0.4 P4 }; { -0.1 P1, 0.8 P2, -0.1 P3, 0.4 P4 }; { -0.1 P1, -0.1 P2, 0.8 P3, 0.4 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.3333 P2, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P2, 0.3334 P4 }; { 0.7 P1, 0.3 P4 }; { 0.7 P2, 0.3 P4 }; { 0.7 P3, 0.3 P4 }; endrule rule "Tetrahedron Vis a Vis Point with edge(1)" quality 1 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 0.866, 0) { 0.5 }; (0.5, 0.288, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; mapedges (1, 4); newpoints newfaces (4, 3, 1); (4, 2, 3); (4, 1, 2); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 }; { 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 }; { 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 }; { -0.05 P1, 0.7 P2, -0.05 P3, 0.4 P4 }; { -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.3333 P2, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P2, 0.3334 P4 }; { 0.65 P2, 0.35 P4 }; { 0.65 P3, 0.35 P4 }; endrule rule "Tetrahedron Vis a Vis Point with 2 edges (1)" quality 1 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 0.866, 0) { 0.5 }; (0.5, 0.288, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; mapedges (1, 4); (2, 4); newpoints newfaces (4, 3, 1); (4, 2, 3); (4, 1, 2); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 }; { 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 }; { 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 }; { -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.3333 P2, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P2, 0.3334 P4 }; { 0.65 P3, 0.35 P4 }; endrule rule "Tetrahedron Vis a Vis Point with 3 edges (1)" quality 1 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 0.866, 0) { 0.5 }; (0.5, 0.288, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; mapedges (1, 4); (2, 4); (3, 4); newpoints newfaces (4, 3, 1); (4, 2, 3); (4, 1, 2); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 }; { 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 }; { 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.3333 P2, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P3, 0.3334 P4 }; { 0.3333 P1, 0.3333 P2, 0.3334 P4 }; endrule rule "Tetrahedron Vis a Vis Triangle (1)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 0.866, 0) { 0.5 }; (0, 0, -0.816) { 0.5 }; (1, 0, -0.816) { 0.5 }; (0.5, 0.866, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; (4, 6, 5) del; newpoints newfaces (1, 2, 4); (2, 5, 4); (2, 3, 6); (2, 6, 5); (3, 1, 4); (3, 4, 6); elements (1, 2, 3, 4); (4, 2, 3, 6); (4, 2, 6, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { -0.2 P1, 0.35 P2, 0.35 P3, -0.2 P4, 0.35 P5, 0.35 P6 }; { 0.35 P1, -0.2 P2, 0.35 P3, 0.35 P4, -0.2 P5, 0.35 P6 }; { 0.35 P1, 0.35 P2, -0.2 P3, 0.35 P4, 0.35 P5, -0.2 P6 }; endrule rule "Octaeder 1" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.95 }; (0.5, 0.866, 0) { 0.95 }; (0.5, -0.288, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; newpoints (1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 }; (0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 }; newfaces (2, 3, 5); (3, 1, 6); (3, 6, 5); (2, 5, 4); (1, 4, 6); (4, 5, 6); elements (3, 4, 1, 2); (3, 4, 2, 5); (3, 4, 5, 6); (3, 4, 6, 1); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { }; (0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 }; (-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 }; ( 1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 }; endrule rule "Octaeder 2" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.95 }; (0.5, 0.866, 0) { 0.95 }; (0.5, -0.288, -0.816) { 0.5 }; (1, 0.578, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; newpoints (0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 }; newfaces (2, 3, 5); (3, 1, 6); (3, 6, 5); (2, 5, 4); (1, 4, 6); (4, 5, 6); elements (3, 4, 1, 2); (3, 4, 2, 5); (3, 4, 5, 6); (3, 4, 6, 1); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { }; (0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 }; (1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 }; (0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 } { 0.333 Y2, 0.333 Y4, 0.333 Y5 } { 0.333 Z2, 0.333 Z4, 0.333 Z5 }; (0.9, 0.481, -0.272) { 0.333 X2, 0.333 X3, 0.333 X5 } { 0.333 Y2, 0.333 Y3, 0.333 Y5 } { 0.333 Z2, 0.333 Z3, 0.333 Z5 }; (-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 }; endrule rule "Octaeder 2a" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.95 }; (0.5, 0.866, 0) { 0.95 }; (0.5, -0.288, -0.816) { 0.5 }; (1, 0.578, -0.816) { 0.5 }; mapfaces (1, 2, 3) del; (3, 2, 5) del; newpoints (0, 0.578, -0.816) { -1 X2, 1 X3, 1 X4 } { -1 Y2, 1 Y3, 1 Y4 } { -1 Z2, 1 Z3, 1 Z4 }; newfaces (1, 2, 4); (3, 1, 6); (3, 6, 5); (2, 5, 4); (1, 4, 6); (4, 5, 6); elements (3, 4, 1, 2); (3, 4, 2, 5); (3, 4, 5, 6); (3, 4, 6, 1); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { }; (0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 }; (1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 }; (0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 } { 0.333 Y2, 0.333 Y4, 0.333 Y5 } { 0.333 Z2, 0.333 Z4, 0.333 Z5 }; (0.5, -0.097, -0.272) { 0.333 X2, 0.333 X4, 0.333 X1 } { 0.333 Y2, 0.333 Y4, 0.333 Y1 } { 0.333 Z2, 0.333 Z4, 0.333 Z1 }; (-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 }; endrule rule "Pyramid 1" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 1 }; (0.5, 0.866, 0) { 1 }; (0.5, -0.288, -0.816) { 1 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; newpoints (1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 }; newfaces (1, 4, 3); (2, 3, 5); (2, 5, 4); (4, 5, 3); elements (1, 2, 3, 4); (4, 2, 3, 5); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { }; (0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 }; (0, 1, -1) { 0.5 X3, 0.5 X4 } { 1 Y3 } { 1 Z4 }; (1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 }; endrule rule "Tetrahedron 2 times 60" quality 1 mappoints (0, 0, 0); (1, 0, 0) { 0.3 }; (0.5, 0.866, 0) { 0.3 }; (0.5, 0.288, -0.816) { 0.3 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (2, 4, 3) del; newpoints newfaces (1, 4, 3); elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 0.3333 P1, 0.3333 P3, 0.3334 P4 }; endrule rule "Fill Tetrahedron (1)" quality 1 mappoints (0, 0, 0); (1, 0, 0) { 0.2 }; (0.5, 0.866, 0) { 0.2 }; (0.5, 0.288, -0.816) { 0.2 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (2, 4, 3) del; (3, 4, 1) del; newpoints newfaces elements (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; endrule rule "Tetrahedron 120 (1)" quality 1 mappoints (0, 0, 0); (1, 0, 0) { 1 }; (0.5, 0.866, 0) { 1 }; (0.5, -0.674, -0.544) { 1 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; newpoints (0.5, 0.288, -0.816) { -0.5 X1, -0.5 X2, 1 X3, 1 X4 } { -0.5 Y1, -0.5 Y2, 1 Y3, 1 Y4} { -0.5 Z1, -0.5 Z2, 1 Z3, 1 Z4}; newfaces (1, 5, 3); (3, 5, 2); (1, 4, 5); (2, 5, 4); elements (1, 2, 3, 5); (1, 4, 2, 5); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.3 P5, -0.3 P1 }; { 1.3 P5, -0.3 P2 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P5 }; endrule rule "Tetrahedron 2 times 120 (1)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 1 }; (0.5, 0.866, 0) { 1 }; (0.5, -0.674, -0.544) { 0.8 }; (1.334, 0.77, -0.544) { 0.8 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (3, 2, 5) del; newpoints (0.5, 0.288, -0.816) { 0.25 X1, -0.5 X2, 0.25 X3, 0.5 X4, 0.5 X5 } { 0.25 Y1, -0.5 Y2, 0.25 Y3, 0.5 Y4, 0.5 Y5 } { 0.25 Z1, -0.5 Z2, 0.25 Z3, 0.5 Z4, 0.5 Z5 }; newfaces (6, 3, 1); (6, 1, 4); (6, 4, 2); (6, 2, 5); (6, 5, 3); elements (1, 2, 3, 6); (1, 4, 2, 6); (2, 5, 3, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1.4 P6, -0.4 P2 }; { 1.4 P6, -0.4 P1 }; { 1.4 P6, -0.4 P3 }; endrule rule "four Tetrahedron non convex (4)" quality 4 flags l; mappoints (0, 0, 0); (1, 0, 0) { 0.1 }; (0.5, 1, 0) { 0.1 }; (0.5, 0, -1) { 0.1 }; (0.5, 0.3, -0.3) { 0.1 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (1, 5, 4) del; (1, 3, 5) del; newpoints (0.5, 0.1, -0.1) { 0.333 X1, 0.333 X2, 0.334 X5 } { 0.333 Y1, 0.333 Y2, 0.334 Y5 } { 0.333 Z1, 0.333 Z2, 0.334 Z5 }; newfaces (6, 2, 3) del; (6, 4, 2) del; (6, 5, 4) del; (6, 3, 5) del; elements (1, 2, 3, 6); (1, 4, 2, 6); (1, 5, 4, 6); (1, 3, 5, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1.5 P6, -0.5 P1 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; freeset 1 6 2 3; freeset 1 6 3 5; freeset 1 6 5 4; freeset 1 6 4 2; endrule rule "five Tetrahedron non convex (4)" quality 4 flags l; mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 1, 0) { 0.5 }; (0, 0.8, -0.2) { 0.5 }; (0, 0.2, -0.8) { 0.5 }; (0.5, 0, -1) { 0.5 }; mapfaces (1, 2, 3) del; (1, 3, 4) del; (1, 4, 5) del; (1, 5, 6) del; (1, 6, 2) del; newpoints (0.1, 0.1, -0.1) { 0.75 X1, 0.05 X2, 0.05 X3, 0.05 X4, 0.05 X5, 0.05 X6 } { 0.75 Y1, 0.05 Y2, 0.05 Y3, 0.05 Y4, 0.05 Y5, 0.05 Y6 } { 0.75 Z1, 0.05 Z2, 0.05 Z3, 0.05 Z4, 0.05 Z5, 0.05 Z6 }; newfaces (7, 2, 3); (7, 3, 4); (7, 4, 5); (7, 5, 6); (7, 6, 2); elements (1, 2, 3, 7); (1, 3, 4, 7); (1, 4, 5, 7); (1, 5, 6, 7); (1, 6, 2, 7); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 1.5 P7, -0.5 P1 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; { 1 P7 }; freeset 1 7 2 3; freeset 1 7 3 4; freeset 1 7 4 5; freeset 1 7 5 6; freeset 1 7 6 2; endrule rule "four Tetrahedron non convex (6)" quality 6 flags l; mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 1, 0) { 0.5 }; (0.5, 0, -1) { 0.5 }; (0.5, 0.3, -0.3) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (1, 5, 4) del; (1, 3, 5) del; newpoints (0.095, 0.003, -0.003) { 0.9 X1, 0.09 X2, 0.01 X5 } { 0.9 Y1, 0.09 Y2, 0.01 Y5 } { 0.9 Z1, 0.09 Z2, 0.01 Z5 }; newfaces (6, 2, 3) del; (6, 4, 2) del; (6, 5, 4) del; (6, 3, 5) del; elements (1, 2, 3, 6); (1, 4, 2, 6); (1, 5, 4, 6); (1, 3, 5, 6); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1.499 P6, -0.5 P1, 0.001 P2 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; freeset 1 6 2 3; freeset 1 6 3 5; freeset 1 6 5 4; freeset 1 6 4 2; endrule rule "four Tetrahedron non convex (6)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 1, 0) { 0.5 }; (0.5, 0, -1) { 0.5 }; (0.5, 0.4, -0.4) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (4, 5, 2) del; (5, 3, 2) del; newpoints (0.925, 0.02, -0.02) { 0.05 X1, 0.9 X2, 0.05 X5 } { 0.05 Y1, 0.9 Y2, 0.05 Y5 } { 0.05 Z1, 0.9 Z2, 0.05 Z5 }; newfaces (3, 1, 6); (1, 4, 6); (4, 5, 6); (5, 3, 6); elements (3, 1, 2, 6); (1, 4, 2, 6); (4, 5, 2, 6); (5, 3, 2, 6); orientations (3, 1, 2, 5); (1, 4, 2, 5); (2, 4, 5, 1); (3, 2, 5, 1); (5, 4, 2, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1.5 P6, -0.5 P2 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; { 1 P6 }; freeset 3 1 2 6; freeset 1 4 2 6; freeset 4 5 2 6; freeset 5 3 2 6; endrule rule "three Tetrahedron non convex (4)" quality 4 flags l; mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 1, 0) { 0.5 }; (0.5, 0, -1) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (1, 3, 4) del; newpoints (0.5, 0.25, -0.25) { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { 0.25 Z1, 0.25 Z2, 0.25 Z3, 0.25 Z4 }; newfaces (5, 2, 3); (5, 4, 2); (5, 3, 4); elements (2, 3, 1, 5); (3, 4, 1, 5); (4, 2, 1, 5; orientations (1, 2, 4, 3); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.5 P5, -0.5 P1 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; freeset 1 4 2 5; endrule rule "three Tetrahedron non convex (6)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 1, 0) { 0.5 }; (0.5, 0, -1) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (1, 3, 4) del; newpoints (0.2, 0.1, -0.1) { 0.7 X1, 0.1 X2, 0.1 X3, 0.1 X4 } { 0.7 Y1, 0.1 Y2, 0.1 Y3, 0.1 Y4 } { 0.7 Z1, 0.1 Z2, 0.1 Z3, 0.1 Z4 }; newfaces (5, 2, 3); (5, 4, 2); (5, 3, 4); elements (2, 3, 1, 5); (3, 4, 1, 5); (4, 2, 1, 5; orientations (1, 2, 3, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.5 P5, -0.5 P1 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 3 4 5; freeset 1 4 2 5; endrule rule "four Tetrahedron non convex (6)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 1, 0) { 0.5 }; (0.5, 0, -1) { 0.5 }; (0.5, 0.4, -0.4) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; (4, 5, 2) del; (5, 3, 2) del; newpoints (0.7, 0.08, -0.08) { 0.6 X2, 0.2 X5 } { 0.2 Y5 } { 0.2 Z5 }; newfaces (3, 1, 6); (1, 4, 6); (4, 5, 6); (5, 3, 6); elements (3, 1, 2, 6); (1, 4, 2, 6); (4, 5, 2, 6); (5, 3, 2, 6); orientations (3, 1, 2, 5); (5, 1, 2, 4); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 1, 0) { 1 X3 } { 1 Y3 } { }; (0.5, 0, -1) { 1 X4 } { 1 Y4 } { 1 Z4 }; (0.5, 0.4, -0.4) { 1 X5 } { 1 Y5 } { 1 Z5 }; (0.55, 0.12, -0.12) { 0.4 X2, 0.3 X5 } { 0.3 Y5 } { 0.3 Z5 }; freeset 3 1 2 6; freeset 1 4 2 6; freeset 4 5 2 6; freeset 5 3 2 6; endrule rule "Tetrahedron 2 in 60 (12)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 0.5 }; (0.5, 1, 0) { 0.5 }; (0.5, 0, -1) { 0.5 }; mapfaces (1, 2, 3) del; (1, 4, 2) del; newpoints (0.5, 0.1, -0.1) { 0.4 X1, 0.4 X2, 0.1 X3, 0.1 X4 } { 0.4 Y1, 0.4 Y2, 0.1 Y3, 0.1 Y4 } { 0.4 Z1, 0.4 Z2, 0.1 Z3, 0.1 Z4 }; newfaces (5, 2, 3); (5, 3, 1); (5, 4, 2); (5, 1, 4); elements (1, 2, 3, 5); (1, 2, 5, 4); freezone2 { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1.5 P5, -0.25 P1, -0.25 P2 }; freezonelimit { 1 P1 }; { 1 P2 }; { 1 P3 }; { 1 P4 }; { 1 P5 }; freeset 1 2 3 5; freeset 1 2 4 5; endrule rule "Tetrahedron 120, but more than 180 (13)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 1 }; (0.5, 0.866, 0) { 1 }; (0.5, -0.866, 0) { 1 }; mapfaces (1, 2, 3) del; (1, 4, 2); newpoints (0.5, 0, -0.3) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 }; newfaces (1, 5, 3); (3, 5, 2); (2, 5, 1); elements (1, 2, 3, 5); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { }; (0.5, -0.1, -0.4) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 }; endrule rule "Free Tetrahedron (14)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 1.0 }; (0.5, 0.866, 0) { 1.0 }; mapfaces (1, 2, 3) del; newpoints (0.5, 0.288, -0.2) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { }; newfaces (4, 1, 2); (4, 2, 3); (4, 3, 1); elements (1, 2, 3, 4); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { }; (0.5, 0.288, -0.25) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { }; endrule rule "Free Tetrahedron (15)" quality 100 mappoints (0, 0, 0); (1, 0, 0) { 1.0 }; (0.5, 0.866, 0) { 1.0 }; mapfaces (1, 2, 3) del; newpoints (0.5, 0.288, -0.1) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { }; newfaces (4, 1, 2); (4, 2, 3); (4, 3, 1); elements (1, 2, 3, 4); freezone (0, 0, 0); (1, 0, 0) { 1 X2 } { } { }; (0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { }; (0.5, 0.288, -0.15) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { }; endrule netgen-6.2.1905/tests/0000755000175000017500000000000013504650527013143 5ustar kurtkurtnetgen-6.2.1905/tests/build_mpi.sh0000644000175000017500000000016413504650527015444 0ustar kurtkurtcd mkdir -p build/netgen cd build/netgen cmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_MPI=ON make -j12 make install netgen-6.2.1905/tests/build_ngsolve.sh0000755000175000017500000000037513504650527016343 0ustar kurtkurtcd ~/src git clone https://github.com/NGSolve/ngsolve.git mkdir -p ~/build/ngsolve cd ~/build/ngsolve cmake \ -DUSE_MKL=ON \ -DUSE_CCACHE=ON \ -DNETGEN_DIR=/opt/netgen \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ ~/src/ngsolve make -j12 make install netgen-6.2.1905/tests/build_nospdlog.sh0000644000175000017500000000026713504650527016510 0ustar kurtkurtcd mkdir -p build/netgen cd build/netgen cmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_SPDLOG=OFF -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_C_COMPILER=clang make -j12 make install netgen-6.2.1905/tests/dockerfile_mpi0000644000175000017500000000057513504650527016051 0ustar kurtkurtFROM ubuntu:18.04 ENV DEBIAN_FRONTEND=noninteractive MAINTAINER Matthias Hochsteger RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy python3-distutils clang libopenmpi-dev openmpi-bin gfortran ADD . /root/src/netgen netgen-6.2.1905/tests/build_guidelines.sh0000644000175000017500000000031413504650527017004 0ustar kurtkurtcd mkdir -p build/netgen cd build/netgen cmake ../../src/netgen -DUSE_CCACHE=ON -DENABLE_CPP_CORE_GUIDELINES_CHECK=ON -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_C_COMPILER=clang make -j12 make install netgen-6.2.1905/tests/pytest/0000755000175000017500000000000013504650527014473 5ustar kurtkurtnetgen-6.2.1905/tests/pytest/test_pickling.py0000644000175000017500000000745513504650527017717 0ustar kurtkurt import pickle, numpy def test_pickle_csg(): import netgen.csg as csg geo = csg.CSGeometry() geo.Add(csg.Sphere(csg.Pnt(0,0,0), 2).bc("sphere")) brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3)) geo.Add(csg.Cylinder(csg.Pnt(0,0,0), csg.Pnt(1,0,0), 0.5) * brick) geo.Add(csg.Ellipsoid(csg.Pnt(0,0,0), csg.Vec(1,0,0), csg.Vec(0,1,0), csg.Vec(0,0,0.5))) geo.Add(csg.Cone(csg.Pnt(0,0,0), csg.Pnt(3,0,0), 1, 0.5) * brick) geo.Add(csg.EllipticCone(csg.Pnt(0,0,0), csg.Vec(2,0,0), csg.Vec(0,1,0), 3, 0.5) * brick) geo.Add(csg.Torus(csg.Pnt(0,0,0), csg.Vec(0,1,0), 0.3, 0.05)) pts2d = [[1,1], [1,-1], [-1,-1], [-1,1]] segs = [[0,1], [1,2], [2,3], [3,0]] curve = csg.SplineCurve2d() pnrs = [curve.AddPoint(*p) for p in pts2d] for s in segs: curve.AddSegment(pnrs[s[0]], pnrs[s[1]]) geo.Add(csg.Revolution(csg.Pnt(0,0,0), csg.Pnt(1,0,0), curve)) path = csg.SplineCurve3d() pnts = [(0,0,0), (2,0,0), (2,2,0)] segs = [(0,1,2)] for pnt in pnts: path.AddPoint (*pnt) for seg in segs: path.AddSegment (*seg) geo.Add(csg.Extrusion(path, curve, csg.Vec(0,0,1))) geo_dump = pickle.dumps(geo) geo2 = pickle.loads(geo_dump) vd1 = geo._visualizationData() vd2 = geo2._visualizationData() for val1, val2 in zip(vd1.values(), vd2.values()): assert numpy.array_equal(val1, val2) def test_pickle_stl(): import netgen.stl as stl geo = stl.LoadSTLGeometry("../../tutorials/hinge.stl") geo_dump = pickle.dumps(geo) geo2 = pickle.loads(geo_dump) vd1 = geo._visualizationData() vd2 = geo2._visualizationData() for val1, val2 in zip(vd1.values(), vd2.values()): assert numpy.array_equal(val1, val2) def test_pickle_occ(): try: import netgen.NgOCC as occ except: import pytest pytest.skip("can't import occ") geo = occ.LoadOCCGeometry("../../tutorials/frame.step") geo_dump = pickle.dumps(geo) geo2 = pickle.loads(geo_dump) vd1 = geo._visualizationData() vd2 = geo2._visualizationData() # TODO: it looks fine, but tests fail, so I assume we loose some info? # for val1, val2 in zip(vd1.values(), vd2.values()): # assert numpy.allclose(val1, val2, rtol=0.01) def test_pickle_geom2d(): import netgen.geom2d as geom2d geo = geom2d.SplineGeometry() # point coordinates ... pnts = [ (0,0), (1,0), (1,0.6), (0,0.6), \ (0.2,0.6), (0.8,0.6), (0.8,0.8), (0.2,0.8), \ (0.5,0.15), (0.65,0.3), (0.5,0.45), (0.35,0.3) ] pnums = [geo.AppendPoint(*p) for p in pnts] # start-point, end-point, boundary-condition, domain on left side, domain on right side: lines = [ (0,1,1,1,0), (1,2,2,1,0), (2,5,2,1,0), (5,4,2,1,2), (4,3,2,1,0), (3,0,2,1,0), \ (5,6,2,2,0), (6,7,2,2,0), (7,4,2,2,0), \ (8,9,2,3,1), (9,10,2,3,1), (10,11,2,3,1), (11,8,2,3,1) ] for p1,p2,bc,left,right in lines: geo.Append( ["line", pnums[p1], pnums[p2]], bc=bc, leftdomain=left, rightdomain=right) geo_dump = pickle.dumps(geo) geo2 = pickle.loads(geo_dump) vd1 = geo._visualizationData() vd2 = geo2._visualizationData() for val1, val2 in zip(vd1.values(), vd2.values()): assert numpy.array_equal(val1, val2) def test_pickle_mesh(): import netgen.csg as csg geo = csg.CSGeometry() brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3)) mesh = geo.GenerateMesh(maxh=0.2) assert geo == mesh.GetGeometry() dump = pickle.dumps([geo,mesh]) geo2, mesh2 = pickle.loads(dump) assert geo2 == mesh2.GetGeometry() mesh.Save("msh1.vol.gz") mesh2.Save("msh2.vol.gz") import filecmp, os assert filecmp.cmp("msh1.vol.gz", "msh2.vol.gz") os.remove("msh1.vol.gz") os.remove("msh2.vol.gz") if __name__ == "__main__": test_pickle_mesh() netgen-6.2.1905/tests/pytest/test_savemesh.py0000644000175000017500000000310313504650527017714 0ustar kurtkurt from netgen.csg import * from netgen import meshing import filecmp import difflib from math import sqrt, cos, sin def CreateQuad(): base = Plane(Pnt(0,0,0),Vec(0,0,1)) surface = SplineSurface(base) pts = [(-0.2,-0.2,0),(-0.2,0.2,0),(0.2,0.2,0),(0.2,-0.2,0)] geopts = [surface.AddPoint(*p) for p in pts] for p1,p2,bc in [(0,1,"wire"), (1, 2,"contact"),(2,3,"wire"),(3,0,"wire")]: surface.AddSegment(geopts[p1],geopts[p2],bc) return surface Cross = lambda a,b: [a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-b[0]*a[1]] def CreateGeo(): geo = CSGeometry() air = OrthoBrick(Pnt(-1,-1,-1),Pnt(1,1,1)) geo.Add(air.mat("air")) surface = CreateQuad() geo.AddSplineSurface(surface) return geo def test_BBNDsave(): mesh = CreateGeo().GenerateMesh(maxh=0.4,perfstepsend = meshing.MeshingStep.MESHSURFACE) for i in range(2): mesh.GenerateVolumeMesh(mp = MeshingParameters(only3D_domain=i+1,maxh=0.4)) mesh.SetGeometry(None) mesh.Save("test.vol") mesh2 = meshing.Mesh() mesh2.Load("test.vol") mesh2.Save("test2.vol") with open("test.vol","r") as f: first = f.readlines() with open("test2.vol","r") as f: second = f.readlines() # exclude the face colours section (because they aren't in the same order) for i,line in enumerate(first): if line[0:12] == "face_colours": first = first[0:i] second = second[0:i] break diff = difflib.context_diff(first,second) print("File diff:") l = list(diff) print(*l) assert len(l)==0 netgen-6.2.1905/tests/pytest/test_gui.py0000644000175000017500000000027013504650527016667 0ustar kurtkurtimport netgen import pytest def test_gui(): try: from tkinter import Tk win = Tk() except: pytest.skip("can't create a window") import netgen.gui netgen-6.2.1905/tests/pytest/CMakeLists.txt0000644000175000017500000000037313504650527017236 0ustar kurtkurtif(USE_PYTHON) add_test(NAME pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) add_custom_target(pytest ${PYTHON_EXECUTABLE} -m pytest WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endif(USE_PYTHON) netgen-6.2.1905/tests/catch/0000755000175000017500000000000013504650527014225 5ustar kurtkurtnetgen-6.2.1905/tests/catch/version.cpp0000644000175000017500000000060413504650527016416 0ustar kurtkurt #include "catch.hpp" #include <../core/ngcore.hpp> using namespace ngcore; using namespace std; TEST_CASE("Version") { VersionInfo v("v6.2.1811-3-asdf"); CHECK(v.to_string() == "v6.2.1811-3-asdf"); VersionInfo v2("6.2"); CHECK(v2.to_string() == "v6.2"); CHECK(v < "v7"); CHECK(v >= "6.2"); CHECK(v > "6.2.1811"); CHECK(v < "6.2.1811-5"); CHECK(v == "v6.2.1811-3"); } netgen-6.2.1905/tests/catch/symboltable.cpp0000644000175000017500000000314113504650527017245 0ustar kurtkurt #include "catch.hpp" #include <../core/ngcore.hpp> using namespace ngcore; using namespace std; TEST_CASE("Symboltable") { SymbolTable table; CHECK_THROWS_AS(table["test"], RangeException); table.Set("first", 1); CHECK(table["first"] == 1); table["first"] = 2; CHECK(table["first"] == 2); auto index = table.Index("first"); CHECK(index == 0); CHECK(table[index] == 2); table[index] = 3; CHECK(table["first"] == 3); #ifndef NDEBUG int a; CHECK_THROWS_AS(a = table[5], RangeException); CHECK_THROWS_AS(table.GetName(5), RangeException); #endif CHECK(table.Used("first")); CHECK(!table.Used("second")); SymbolTable another; another.Set("first", 1); another.Set("second", 2); table.Update(another); CHECK(table["first"] == 1); CHECK(table["second"] == 2); std::stringstream s; s << table; CHECK(s.str() == "first : 1\nsecond : 2\n"); auto ss = std::make_shared(); BinaryOutArchive ao(ss); ao & table; ao.FlushBuffer(); BinaryInArchive ai(ss); SymbolTable read; ai & read; for(size_t i = 0; i is special because of vector is special... SymbolTable btable; btable.Set("true", true); btable.Set("false", false); CHECK(btable[0]); CHECK(!btable[1]); CHECK(btable["true"]); CHECK(!btable["false"]); ao & btable; ao.FlushBuffer(); SymbolTable bread; ai & bread; CHECK(bread["true"]); CHECK(!bread["false"]); } netgen-6.2.1905/tests/catch/main.cpp0000644000175000017500000000006013504650527015651 0ustar kurtkurt #define CATCH_CONFIG_MAIN #include netgen-6.2.1905/tests/catch/archive.cpp0000644000175000017500000002054013504650527016353 0ustar kurtkurt #include "catch.hpp" #include <../core/ngcore.hpp> using namespace ngcore; using namespace std; class CommonBase { public: int a; virtual ~CommonBase() {} virtual void DoArchive(Archive& archive) { archive & a; } }; // pure abstract base class class SharedPtrHolder : virtual public CommonBase { public: vector> names; virtual ~SharedPtrHolder() { } virtual void abstract() = 0; virtual void DoArchive(Archive& archive) { CommonBase::DoArchive(archive); archive & names; } }; class PtrHolder : virtual public CommonBase { public: vector numbers; virtual ~PtrHolder() {} virtual void DoArchive(Archive& archive) { CommonBase::DoArchive(archive); archive & numbers; } }; class SharedPtrAndPtrHolder : public SharedPtrHolder, public PtrHolder { public: virtual ~SharedPtrAndPtrHolder() {} virtual void DoArchive(Archive& archive) { SharedPtrHolder::DoArchive(archive); PtrHolder::DoArchive(archive); } virtual void abstract() {} }; // Classes without virt. or multiple inheritance do not need to be registered class SimpleClass : public CommonBase { public: double d; virtual void DoArchive(Archive& ar) { CommonBase::DoArchive(ar); ar & d; } }; class NotRegisteredForArchive : public SharedPtrAndPtrHolder {}; class ClassWithConstPtr { private: const int* ptr; public: ClassWithConstPtr(const int* aptr) : ptr(aptr) { } // constructor only for archive ClassWithConstPtr() {} void DoArchive(Archive& ar) { ar & ptr; } const int* getPtr() { return ptr; } }; class OneMoreDerivedClass : public SharedPtrAndPtrHolder {}; static RegisterClassForArchive regb; static RegisterClassForArchive regsp; static RegisterClassForArchive regp; static RegisterClassForArchive regspp; static RegisterClassForArchive regom; void testNullPtr(Archive& in, Archive& out) { SharedPtrHolder* p = nullptr; shared_ptr sp = nullptr; out & p & sp; out.FlushBuffer(); SharedPtrHolder* pin = nullptr; shared_ptr spin = nullptr; in & pin & spin; CHECK(pin == nullptr); CHECK(spin == nullptr); } void testSharedPointer(Archive& in, Archive& out) { SECTION("Same shared ptr") { static_assert(detail::has_DoArchive::value, ""); SharedPtrAndPtrHolder holder, holder2; holder.names.push_back(make_shared("name")); holder2.names = holder.names; // same shared ptr out & holder & holder2; out.FlushBuffer(); SharedPtrAndPtrHolder inholder, inholder2; in & inholder & inholder2; CHECK(inholder.names.size() == 1); CHECK(inholder.names[0] == inholder2.names[0]); CHECK(inholder.names[0].use_count() == 3); // one shared ptr is still kept in the archive CHECK(*inholder.names[0] == "name"); } } void testPointer(Archive& in, Archive& out) { PtrHolder holder, holder2; holder.numbers.push_back(new int(3)); holder2.numbers = holder.numbers; // same shared ptr out & holder & holder2; out.FlushBuffer(); PtrHolder inholder, inholder2; in & inholder & inholder2; CHECK(inholder.numbers.size() == 1); CHECK(inholder.numbers[0] == inholder2.numbers[0]); CHECK(*inholder.numbers[0] == 3); } void testConstPointer(Archive& in, Archive& out) { SECTION("Const pointer") { int* iptr = new int(4); double d = 0.1; ClassWithConstPtr cls(iptr); out & cls & iptr & d; out.FlushBuffer(); ClassWithConstPtr incls; int* iniptr; double ind; in & incls & iniptr & ind; CHECK(*incls.getPtr() == 4); CHECK(incls.getPtr() == iniptr); CHECK(ind == 0.1); delete iptr; delete iniptr; } } void testMultipleInheritance(Archive& in, Archive& out) { PtrHolder* p = new OneMoreDerivedClass; p->numbers.push_back(new int(2)); p->a = 5; auto p2 = dynamic_cast(p); p2->names.push_back(make_shared("test")); auto sp1 = shared_ptr(p); auto sp2 = dynamic_pointer_cast(sp1); auto checkPtr = [] (auto pin, auto pin2) { CHECK(typeid(*pin) == typeid(*pin2)); CHECK(typeid(*pin) == typeid(OneMoreDerivedClass)); CHECK(*pin2->names[0] == "test"); CHECK(*pin->numbers[0] == 2); CHECK(dynamic_cast(pin) == dynamic_cast(pin2)); CHECK(pin->a == pin2->a); CHECK(pin->a == 5); REQUIRE(dynamic_cast(pin2) != nullptr); CHECK(*dynamic_cast(pin2)->numbers[0] == 2); CHECK(*pin->numbers[0] == *dynamic_cast(pin2)->numbers[0]); REQUIRE(dynamic_cast(pin) != nullptr); CHECK(dynamic_cast(pin)->names[0] == pin2->names[0]); }; SECTION("Archive ptrs to leaves of mult. inh.") { out & p & p2; out.FlushBuffer(); PtrHolder* pin = nullptr; SharedPtrHolder* pin2 = nullptr; in & pin & pin2; checkPtr(pin, pin2); } SECTION("Archive shared ptrs to leaves of mult. inh.") { out & sp1 & sp2; out.FlushBuffer(); shared_ptr pin; shared_ptr pin2; in & pin & pin2; checkPtr(pin.get(), pin2.get()); } SECTION("Virtual base class") { CommonBase* b = dynamic_cast(p); out & b & p; PtrHolder* pin; CommonBase* bin; in & bin & pin; checkPtr(pin, dynamic_cast(bin)); } SECTION("Simple class without register") { auto a = new SimpleClass; a->a = 5; a->d = 2.3; SECTION("check pointer") { out & a; out.FlushBuffer(); SimpleClass* ain; in & ain; CHECK(ain->a == 5); CHECK(ain->d == 2.3); } SECTION("check shared pointer") { auto spa = shared_ptr(a); out & spa; out.FlushBuffer(); shared_ptr spain; in & spain; CHECK(spain->a == 5); CHECK(spain->d == 2.3); } } } void testMap(Archive& in, Archive& out) { map map1; map1["netgen"] = "v6.2.1901"; out & map1; out.FlushBuffer(); map map2; in & map2; CHECK(map2.size() == 1); CHECK(map2["netgen"] == "v6.2.1901"); } enum MyEnum { CASE1, CASE2 }; void testEnum(Archive& in, Archive& out) { MyEnum en = CASE2; out & en; out.FlushBuffer(); MyEnum enin; in & enin; CHECK(enin == CASE2); } void testArchive(Archive& in, Archive& out) { SECTION("Empty String") { char* cstr = nullptr; char* empty = new char[1]; char* simple = new char[7] {'s','i','m','p','l','e','\0'}; empty[0] = '\0'; out << string("") << cstr << empty << simple << string("simple") << long(1); out.FlushBuffer(); string str; long i; char* readempty; char* readsimple; string simplestr; in & str & cstr & readempty & readsimple & simplestr & i; CHECK(str == ""); CHECK(cstr == nullptr); CHECK(strcmp(readempty,"") == 0); CHECK(strcmp(readsimple,"simple") == 0); CHECK(i == 1); CHECK(simplestr == "simple"); delete[] readempty; delete[] empty; delete[] simple; delete[] readsimple; } SECTION("SharedPtr") { testSharedPointer(in, out); } SECTION("Pointer") { testPointer(in, out); } SECTION("Const Pointer") { testConstPointer(in, out); } SECTION("Multiple inheritance") { testMultipleInheritance(in, out); } SECTION("Not registered") { SharedPtrAndPtrHolder* p = new NotRegisteredForArchive; REQUIRE_THROWS(out & p, Catch::Contains("not registered for archive")); } SECTION("nullptr") { testNullPtr(in, out); } SECTION("map") { testMap(in, out); } SECTION("enum") { testEnum(in, out); } } TEST_CASE("BinaryArchive") { auto stream = make_shared(); BinaryOutArchive out(stream); BinaryInArchive in(stream); testArchive(in, out); } TEST_CASE("TextArchive") { auto stream = make_shared(); TextOutArchive out(stream); TextInArchive in(stream); testArchive(in, out); } netgen-6.2.1905/tests/catch/CMakeLists.txt0000644000175000017500000000233413504650527016767 0ustar kurtkurt if(ENABLE_UNIT_TESTS) add_custom_target(unit_tests) # Build catch_main test object include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR}) add_library(catch_main STATIC main.cpp) set_target_properties(catch_main PROPERTIES CXX_STANDARD 17) add_dependencies(unit_tests catch_main) add_dependencies(catch_main project_catch) # ensure the test targets are built before testing add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_tests --config ${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../.. ) macro(add_unit_test name sources) add_executable(test_${name} ${sources} ) target_link_libraries(test_${name} ngcore catch_main ${PYTHON_LIBRARIES}) add_dependencies(unit_tests test_${name}) add_test(NAME unit_${name} COMMAND test_${name}) set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) set_target_properties(test_${name} PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) endmacro() add_unit_test(archive archive.cpp) add_unit_test(symboltable symboltable.cpp) add_unit_test(version version.cpp) endif(ENABLE_UNIT_TESTS) netgen-6.2.1905/tests/build.sh0000755000175000017500000000014713504650527014603 0ustar kurtkurtcd mkdir -p build/netgen cd build/netgen cmake ../../src/netgen -DUSE_CCACHE=ON make -j12 make install netgen-6.2.1905/tests/dockerfile0000644000175000017500000000053113504650527015174 0ustar kurtkurtFROM ubuntu:18.04 ENV DEBIAN_FRONTEND=noninteractive MAINTAINER Matthias Hochsteger RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy python3-distutils clang ADD . /root/src/netgen netgen-6.2.1905/tests/CMakeLists.txt0000644000175000017500000000006113504650527015700 0ustar kurtkurtadd_subdirectory(catch) add_subdirectory(pytest) netgen-6.2.1905/libsrc/0000755000175000017500000000000013504650527013257 5ustar kurtkurtnetgen-6.2.1905/libsrc/geom2d/0000755000175000017500000000000013504650527014434 5ustar kurtkurtnetgen-6.2.1905/libsrc/geom2d/geom2dpkg.cpp0000644000175000017500000000215013504650527017015 0ustar kurtkurt#include #include #include #include #include "vsgeom2d.hpp" // extern "C" int Ng_CSG_Init (Tcl_Interp * interp); namespace netgen { // extern DLL_HEADER NetgenGeometry * ng_geometry; static VisualSceneGeometry2d vsgeom2d; class SplineGeometryVisRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const { return NULL; } virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const; }; VisualScene * SplineGeometryVisRegister :: GetVisualScene (const NetgenGeometry * geom) const { const SplineGeometry2d * geometry = dynamic_cast (geom); if (geometry) { vsgeom2d.SetGeometry (geometry); return &vsgeom2d; } return NULL; } } using namespace netgen; #ifdef WIN32 extern "C" __declspec(dllexport) int Ng_geom2d_Init (Tcl_Interp * interp); #else extern "C" int Ng_geom2d_Init (Tcl_Interp * interp); #endif int Ng_geom2d_Init (Tcl_Interp * interp) { geometryregister.Append (new SplineGeometryVisRegister); return TCL_OK; } netgen-6.2.1905/libsrc/geom2d/geometry2d.hpp0000644000175000017500000001205513504650527017231 0ustar kurtkurt#ifndef FILE_GEOMETRY2D #define FILE_GEOMETRY2D /* *************************************************************************/ /* File: geometry2d.hpp */ /* Author: Joachim Schoeberl */ /* Date: 20. Jul. 02 */ /* *************************************************************************/ #include #include // #include "../gprim/spline.hpp" // #include "../gprim/splinegeometry.hpp" #include "geom2dmesh.hpp" namespace netgen { class SplineSegExt : public SplineSeg<2> { public: SplineSeg<2>* seg; /// left domain int leftdom; /// right domain int rightdom; /// refinement at line double reffak; /// maximal h; double hmax; /// boundary condition number int bc; /// copy spline mesh from other spline (-1.. do not copy) int copyfrom; /// perform anisotropic refinement (hp-refinement) to edge double hpref_left; /// perform anisotropic refinement (hp-refinement) to edge double hpref_right; /// int layer; SplineSegExt (SplineSeg<2> & hseg) : seg(&hseg) { layer = 1; } // default constructor for archive SplineSegExt() {} ~SplineSegExt () { delete seg; } virtual void DoArchive(Archive& ar) { ar & seg & leftdom & rightdom & reffak & hmax & bc & copyfrom & hpref_left & hpref_right & layer; } virtual const GeomPoint<2> & StartPI () const { return seg->StartPI(); } virtual const GeomPoint<2> & EndPI () const { return seg->EndPI(); } virtual Point<2> GetPoint (double t) const { return seg->GetPoint(t); } virtual Vec<2> GetTangent (const double t) const { return seg->GetTangent(t); } virtual void GetDerivatives (const double t, Point<2> & point, Vec<2> & first, Vec<2> & second) const { seg->GetDerivatives (t, point, first, second); } virtual void GetCoeff (Vector & coeffs) const { seg->GetCoeff (coeffs); } virtual void GetPoints (int n, Array > & points) const { seg->GetPoints (n, points); } virtual double MaxCurvature () const { return seg->MaxCurvature(); } virtual string GetType () const { return seg->GetType(); } virtual double CalcCurvature (double t) const { Point<2> point; Vec<2> first, second; GetDerivatives (t, point, first, second); double curv = fabs(first(0)*second(1)-first(1)*second(0)) / pow(first.Length(), 3); return curv; } virtual bool InConvexHull (Point<2> p, double eps) const { return seg->InConvexHull (p, eps); } }; class SplineGeometry2d : public SplineGeometry<2>, public NetgenGeometry { protected: Array materials; Array maxh; Array quadmeshing; Array tensormeshing; Array layer; Array bcnames; double elto0 = 1.0; public: DLL_HEADER virtual ~SplineGeometry2d(); DLL_HEADER void Load (const char * filename); DLL_HEADER void LoadData( ifstream & infile ); DLL_HEADER void LoadDataNew ( ifstream & infile ); DLL_HEADER void LoadDataV2 ( ifstream & infile ); void TestComment ( ifstream & infile ) ; void DoArchive(Archive& ar) { SplineGeometry<2>::DoArchive(ar); ar & materials & maxh & quadmeshing & tensormeshing & layer & bcnames & elto0; } const SplineSegExt & GetSpline (const int i) const { return dynamic_cast (*splines[i]); } SplineSegExt & GetSpline (const int i) { return dynamic_cast (*splines[i]); } DLL_HEADER virtual int GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam); void PartitionBoundary (MeshingParameters & mp, double h, Mesh & mesh2d); void CopyEdgeMesh (int from, int to, Mesh & mesh2d, Point3dTree & searchtree); size_t GetNDomains() const { return materials.Size(); } void GetMaterial (int domnr, char* & material ); void SetMaterial (int domnr, const string & material); double GetDomainMaxh ( const int domnr ); void SetDomainMaxh ( const int domnr, double maxh ); bool GetDomainQuadMeshing ( int domnr ) { if ( quadmeshing.Size() ) return quadmeshing[domnr-1]; else return false; } bool GetDomainTensorMeshing ( int domnr ) { if ( tensormeshing.Size() ) return tensormeshing[domnr-1]; else return false; } int GetDomainLayer ( int domnr ) { if ( layer.Size() ) return layer[domnr-1]; else return 1; } string GetBCName (int bcnr) const; void SetBCName (int bcnr, string name); int GetBCNumber (string name) const; // 0 if not exists int AddBCName (string name); string * BCNamePtr ( const int bcnr ); DLL_HEADER virtual Refinement & GetRefinement () const; }; } #endif netgen-6.2.1905/libsrc/geom2d/geom2dmesh.hpp0000644000175000017500000000314513504650527017202 0ustar kurtkurt#ifndef FILE_GEOM2DMESH #define FILE_GEOM2DMESH /**************************************************************************/ /* File: geom2dmesh.hh */ /* Author: Joachim Schoeberl */ /* Date: 22. Jan. 01 */ /**************************************************************************/ namespace netgen { class Refinement2d : public Refinement { const class SplineGeometry2d & geometry; public: Refinement2d (const class SplineGeometry2d & ageometry); virtual ~Refinement2d (); virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const; virtual Vec<3> GetTangent (const Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & ap1) const; virtual Vec<3> GetNormal (const Point<3> & p, int surfi1, const PointGeomInfo & gi) const; virtual void ProjectToSurface (Point<3> & p, int surfi, const PointGeomInfo & /* gi */) const; virtual void ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const; }; } #endif netgen-6.2.1905/libsrc/geom2d/spline2d.hpp0000644000175000017500000001333613504650527016673 0ustar kurtkurt das File sollte nicht mehr verwendet werden ---> spline.hpp #ifndef FILE_SPLINE2D #define FILE_SPLINE2D /**************************************************************************/ /* File: spline2d.hh */ /* Author: Joachim Schoeberl */ /* Date: 24. Jul. 96 */ /**************************************************************************/ /* Spline curves for 2D mesh generation */ #include "spline.hpp" //#define OLDSPLINEVERSION #ifdef OLDSPLINEVERSION /// Geometry point class GeomPoint2d : public Point<2> { public: /// refinement to point double refatpoint; bool hpref; GeomPoint2d () { ; } /// GeomPoint2d (double ax, double ay, double aref = 1) : Point<2> (ax, ay), refatpoint(aref) { ; } }; /// base class for 2d - segment class SplineSegment { public: /// left domain int leftdom; /// right domain int rightdom; /// refinement at line double reffak; /// boundary condition number int bc; /// copy spline mesh from other spline (-1.. do not copy) int copyfrom; /// perform anisotropic refinement (hp-refinement) to edge bool hpref_left; bool hpref_right; /// calculates length of curve virtual double Length () const; /// returns point at curve, 0 <= t <= 1 virtual Point<2> GetPoint (double t) const = 0; /// partitionizes curve void Partition (double h, double elto0, Mesh & mesh, Point3dTree & searchtree, int segnr) const; /// returns initial point on curve virtual const GeomPoint2d & StartPI () const = 0; /// returns terminal point on curve virtual const GeomPoint2d & EndPI () const = 0; /** writes curve description for fepp: for implicitly given quadratic curves, the 6 coefficients of the polynomial $$ a x^2 + b y^2 + c x y + d x + e y + f = 0 $$ are written to ost */ void PrintCoeff (ostream & ost) const; virtual void GetCoeff (Vector & coeffs) const = 0; virtual void GetPoints (int n, Array > & points); /** calculates lineintersections: for lines $$ a x + b y + c = 0 $$ the interecting points are calculated and stored in points */ virtual void LineIntersections (const double a, const double b, const double c, Array < Point<2> > & points, const double eps) const {points.SetSize(0);} virtual double MaxCurvature(void) const = 0; virtual string GetType(void) const {return "splinebase";} }; /// Straight line form p1 to p2 class LineSegment : public SplineSegment { /// const GeomPoint2d &p1, &p2; public: /// LineSegment (const GeomPoint2d & ap1, const GeomPoint2d & ap2); /// virtual double Length () const; /// virtual Point<2> GetPoint (double t) const; /// virtual const GeomPoint2d & StartPI () const { return p1; }; /// virtual const GeomPoint2d & EndPI () const { return p2; } /// //virtual void PrintCoeff (ostream & ost) const; virtual void GetCoeff (Vector & coeffs) const; virtual string GetType(void) const {return "line";} virtual void LineIntersections (const double a, const double b, const double c, Array < Point<2> > & points, const double eps) const; virtual double MaxCurvature(void) const {return 0;} }; /// curve given by a rational, quadratic spline (including ellipses) class SplineSegment3 : public SplineSegment { /// const GeomPoint2d &p1, &p2, &p3; public: /// SplineSegment3 (const GeomPoint2d & ap1, const GeomPoint2d & ap2, const GeomPoint2d & ap3); /// virtual Point<2> GetPoint (double t) const; /// virtual const GeomPoint2d & StartPI () const { return p1; }; /// virtual const GeomPoint2d & EndPI () const { return p3; } /// //virtual void PrintCoeff (ostream & ost) const; virtual void GetCoeff (Vector & coeffs) const; virtual string GetType(void) const {return "spline3";} const GeomPoint2d & TangentPoint (void) const { return p2; } virtual void LineIntersections (const double a, const double b, const double c, Array < Point<2> > & points, const double eps) const; virtual double MaxCurvature(void) const; }; // Gundolf Haase 8/26/97 /// A circle class CircleSegment : public SplineSegment { /// private: const GeomPoint2d &p1, &p2, &p3; Point<2> pm; double radius, w1,w3; public: /// CircleSegment (const GeomPoint2d & ap1, const GeomPoint2d & ap2, const GeomPoint2d & ap3); /// virtual Point<2> GetPoint (double t) const; /// virtual const GeomPoint2d & StartPI () const { return p1; } /// virtual const GeomPoint2d & EndPI () const { return p3; } /// //virtual void PrintCoeff (ostream & ost) const; virtual void GetCoeff (Vector & coeffs) const; /// double Radius() const { return radius; } /// double StartAngle() const { return w1; } /// double EndAngle() const { return w3; } /// const Point<2> & MidPoint(void) const {return pm; } virtual string GetType(void) const {return "circle";} virtual void LineIntersections (const double a, const double b, const double c, Array < Point<2> > & points, const double eps) const; virtual double MaxCurvature(void) const {return 1./radius;} }; /// class DiscretePointsSegment : public SplineSegment { Array > pts; GeomPoint2d p1, p2; public: /// DiscretePointsSegment (const Array > & apts); /// virtual ~DiscretePointsSegment (); /// virtual Point<2> GetPoint (double t) const; /// virtual const GeomPoint2d & StartPI () const { return p1; }; /// virtual const GeomPoint2d & EndPI () const { return p2; } /// //virtual void PrintCoeff (ostream & /* ost */) const { ; } virtual void GetCoeff (Vector & coeffs) const {;} virtual double MaxCurvature(void) const {return 1;} }; #endif #endif netgen-6.2.1905/libsrc/geom2d/python_geom2d.cpp0000644000175000017500000003573513504650527017733 0ustar kurtkurt#ifdef NG_PYTHON #include <../general/ngpython.hpp> #include #include using namespace netgen; namespace netgen { extern std::shared_ptr ng_geometry; } DLL_HEADER void ExportGeom2d(py::module &m) { py::class_> (m, "Spline", "Spline of a SplineGeometry object") .def_property("leftdom", [] (SplineSegExt& self) { return self.leftdom; }, [](SplineSegExt& self, int dom) { self.leftdom = dom; }) .def_property("rightdom", [] (SplineSegExt& self) { return self.rightdom; }, [](SplineSegExt& self, int dom) { self.rightdom = dom; }) .def_property_readonly("bc", [] (SplineSegExt& self) { return self.bc; }) .def("GetNormal", [](SplineSegExt& self, double t) { auto tang = self.GetTangent(t).Normalize(); return Vec<2>(tang[1], -tang[0]); }) .def("StartPoint", [](SplineSegExt& self) { return Point<2>(self.StartPI()); }) .def("EndPoint", [](SplineSegExt& self) { return Point<2>(self.EndPI()); }) ; py::class_> (m, "SplineGeometry", "a 2d boundary representation geometry model by lines and splines", py::multiple_inheritance()) .def(py::init<>()) .def(py::init([](const string& filename) { auto geo = make_shared(); geo->Load(filename.c_str()); ng_geometry = geo; return geo; })) .def(NGSPickle()) .def("Load",&SplineGeometry2d::Load) .def("AppendPoint", FunctionPointer ([](SplineGeometry2d &self, double px, double py, double maxh, double hpref, string name) { Point<2> p; p(0) = px; p(1) = py; GeomPoint<2> gp(p); gp.hmax = maxh; gp.hpref = hpref; gp.name = name; self.geompoints.Append(gp); return self.geompoints.Size()-1; }), py::arg("x"), py::arg("y"), py::arg("maxh") = 1e99, py::arg("hpref")=0, py::arg("name")="") .def("Append", FunctionPointer([](SplineGeometry2d &self, py::list segment, int leftdomain, int rightdomain, py::object bc, py::object copy, double maxh, double hpref) { py::extract segtype(segment[0]); SplineSegExt * seg; if (segtype().compare("line") == 0) { py::extract point_index1(segment[1]); py::extract point_index2(segment[2]); //point_index1.check() LineSeg<2> * l = new LineSeg<2>(self.GetPoint(point_index1()), self.GetPoint(point_index2())); seg = new SplineSegExt(*l); } else if (segtype().compare("spline3") == 0) { py::extract point_index1(segment[1]); py::extract point_index2(segment[2]); py::extract point_index3(segment[3]); SplineSeg3<2> * seg3 = new SplineSeg3<2>(self.GetPoint(point_index1()), self.GetPoint(point_index2()), self.GetPoint(point_index3())); seg = new SplineSegExt(*seg3); } else { cout << "Appended segment is not a line or a spline3" << endl; } seg->leftdom = leftdomain; seg->rightdom = rightdomain; seg->hmax = maxh; seg->hpref_left = hpref; seg->hpref_right = hpref; seg->reffak = 1; seg->copyfrom = -1; if (py::extract(copy).check()) seg->copyfrom = py::extract(copy)()+1; if (py::extract(bc).check()) seg->bc = py::extract(bc)(); else if (py::extract(bc).check()) { string bcname = py::extract(bc)(); seg->bc = self.GetNSplines()+1; self.SetBCName(seg->bc, bcname); } else seg->bc = self.GetNSplines()+1; self.AppendSegment(seg); return self.GetNSplines()-1; }), py::arg("point_indices"), py::arg("leftdomain") = 1, py::arg("rightdomain") = py::int_(0), py::arg("bc")=NGDummyArgument(), py::arg("copy")=NGDummyArgument(), py::arg("maxh")=1e99, py::arg("hpref")=0) .def("AppendSegment", FunctionPointer([](SplineGeometry2d &self, py::list point_indices, int leftdomain, int rightdomain) { int npts = py::len(point_indices); SplineSegExt * seg; //int a = py::extract(point_indices[0]); if (npts == 2) { LineSeg<2> * l = new LineSeg<2>(self.GetPoint(py::extract(point_indices[0])()), self.GetPoint(py::extract(point_indices[1])())); seg = new SplineSegExt(*l); } else if (npts == 3) { SplineSeg3<2> * seg3 = new SplineSeg3<2>(self.GetPoint(py::extract(point_indices[0])()), self.GetPoint(py::extract(point_indices[1])()), self.GetPoint(py::extract(point_indices[2])())); seg = new SplineSegExt(*seg3); } seg->leftdom = leftdomain; seg->rightdom = rightdomain; seg->hmax = 1e99; seg->reffak = 1; seg->copyfrom = -1; self.AppendSegment(seg); }), py::arg("point_indices"), py::arg("leftdomain") = 1, py::arg("rightdomain") = py::int_(0)) .def("AddCurve", [] (SplineGeometry2d & self, py::object func, int leftdomain, int rightdomain, py::object bc, double maxh) { int n = 1000; Array> points; for (int i = 0; i <= n; i++) { double t = double(i)/n; py::tuple xy = func(t); double x = py::cast(xy[0]); double y = py::cast(xy[1]); points.Append (Point<2>(x,y)); } auto spline = new DiscretePointsSeg<2> (points); SplineSegExt * spex = new SplineSegExt (*spline); spex -> leftdom = leftdomain; spex -> rightdom = rightdomain; spex->hmax = maxh; spex->reffak = 1; spex->copyfrom = -1; if (py::extract(bc).check()) spex->bc = py::extract(bc)(); else if (py::extract(bc).check()) { string bcname = py::extract(bc)(); spex->bc = self.GetNSplines()+1; self.SetBCName(spex->bc, bcname); } else spex->bc = self.GetNSplines()+1; self.AppendSegment (spex); }, py::arg("func"), py::arg("leftdomain") = 1, py::arg("rightdomain") = py::int_(0), py::arg("bc")=NGDummyArgument(), py::arg("maxh")=1e99, "Curve is given as parametrization on the interval [0,1]") .def("SetMaterial", &SplineGeometry2d::SetMaterial) .def("SetDomainMaxH", &SplineGeometry2d::SetDomainMaxh) .def("GetBCName", [](SplineGeometry2d& self, size_t index) { return self.GetBCName(index); }) .def("GetNDomains", [](SplineGeometry2d& self) { return self.GetNDomains(); }) .def("GetNSplines", [](SplineGeometry2d& self) { return self.splines.Size(); }) .def("GetSpline", [](SplineGeometry2d& self, size_t index) { return shared_ptr(&self.GetSpline(index), NOOP_Deleter); }, py::return_value_policy::reference_internal) .def("GetNPoints", [](SplineGeometry2d& self) { return self.GetNP(); }) .def("GetPoint", [](SplineGeometry2d& self, size_t index) { return Point<2>(self.GetPoint(index)); }) .def("PlotData", FunctionPointer([](SplineGeometry2d &self) { Box<2> box(self.GetBoundingBox()); double xdist = box.PMax()(0) - box.PMin()(0); double ydist = box.PMax()(1) - box.PMin()(1); py::tuple xlim = py::make_tuple(box.PMin()(0) - 0.1*xdist, box.PMax()(0) + 0.1*xdist); py::tuple ylim = py::make_tuple(box.PMin()(1) - 0.1*ydist, box.PMax()(1) + 0.1*ydist); py::list xpoints, ypoints; for (int i = 0; i < self.splines.Size(); i++) { py::list xp, yp; if (self.splines[i]->GetType().compare("line")==0) { GeomPoint<2> p1 = self.splines[i]->StartPI(); GeomPoint<2> p2 = self.splines[i]->EndPI(); xp.append(py::cast(p1(0))); xp.append(py::cast(p2(0))); yp.append(py::cast(p1(1))); yp.append(py::cast(p2(1))); } else if (self.splines[i]->GetType().compare("spline3")==0) { double len = self.splines[i]->Length(); int n = floor(len/(0.05*min(xdist,ydist))); for (int j = 0; j <= n; j++) { GeomPoint<2> point = self.splines[i]->GetPoint(j*1./n); xp.append(py::cast(point(0))); yp.append(py::cast(point(1))); } } else { cout << "spline is neither line nor spline3" << endl; } xpoints.append(xp); ypoints.append(yp); } return py::tuple(py::make_tuple(xlim, ylim, xpoints, ypoints)); })) .def("_visualizationData", [](SplineGeometry2d &self) { Box<2> box(self.GetBoundingBox()); double xdist = box.PMax()(0) - box.PMin()(0); double ydist = box.PMax()(1) - box.PMin()(1); py::dict data; py::dict segment_data; auto min_val = py::make_tuple(box.PMin()(0), box.PMin()(1),0); auto max_val = py::make_tuple(box.PMax()(1),box.PMax()(1),0); py::list vertices; py::list domains; py::list segment_points; py::list segment_normals; py::list leftdom; py::list rightdom; int max_bcnr = 0; for(int i = 0; i < self.splines.Size(); i++) { std::vector> lst; if (self.splines[i]->GetType().compare("line") == 0) lst = { self.splines[i]->StartPI(), self.splines[i]->EndPI() }; else if(self.splines[i]->GetType().compare("spline3") == 0) { double len = self.splines[i]->Length(); int n = floor(len/(0.05*min(xdist,ydist))); lst.push_back(self.splines[i]->StartPI()); for (int j = 1; j < n; j++){ lst.push_back(self.splines[i]->GetPoint(j*1./n)); lst.push_back(self.splines[i]->GetPoint(j*1./n)); } lst.push_back(self.splines[i]->EndPI()); } else { throw NgException("Spline is neither line nor spline3"); } for (auto point : lst) { for(auto val : {point(0), point(1), 0.}) vertices.append(val); int bcnr = self.GetSpline(i).bc; max_bcnr = max2(max_bcnr, bcnr); domains.append(bcnr); domains.append(self.GetSpline(i).leftdom); domains.append(self.GetSpline(i).rightdom); } // segment data auto pnt = self.splines[i]->GetPoint(0.5); segment_points.append(py::make_tuple(pnt(0),pnt(1))); auto normal = self.GetSpline(i).GetTangent(0.5); std::swap(normal(0),normal(1)); normal(1) *= -1; normal *= 1./sqrt(normal(0) * normal(0) + normal(1)*normal(1)); segment_normals.append(py::make_tuple(normal(0),normal(1))); leftdom.append(self.GetSpline(i).leftdom); rightdom.append(self.GetSpline(i).rightdom); } py::list bcnames; for (int i = 1; i point = self.splines[i]->GetPoint(0.5); Vec<2> normal = self.GetSpline(i).GetTangent(0.5); double temp = normal(0); normal(0) = normal(1); normal(1) = -temp; leftdom.append(py::cast(self.GetSpline(i).leftdom)); rightdom.append(py::cast(self.GetSpline(i).rightdom)); rightpoints.append(py::make_tuple(point(0), point(1), normal(0)<0, normal(1)<0)); leftpoints.append(py::make_tuple(point(0), point(1), normal(0)<0, normal(1)<0)); } return py::tuple(py::make_tuple(leftpoints, rightpoints, leftdom, rightdom)); })) .def("Print", FunctionPointer([](SplineGeometry2d &self) { for (int i = 0; i < self.geompoints.Size(); i++) { cout << i << " : " << self.geompoints[i][0] << " , " << self.geompoints[i][1] << endl; } //Box<2> box(self.GetBoundingBox()); //cout << box.PMin() << endl; //cout << box.PMax() << endl; cout << self.splines.Size() << endl; for (int i = 0; i < self.splines.Size(); i++) { cout << self.splines[i]->GetType() << endl; //cout << i << " : " << self.splines[i]->GetPoint(0.1) << " , " << self.splines[i]->GetPoint(0.5) << endl; } })) .def("GenerateMesh", [](shared_ptr self, MeshingParameters & mparam) { shared_ptr mesh = make_shared (); mesh->SetGeometry(self); SetGlobalMesh (mesh); ng_geometry = self; self->GenerateMesh(mesh, mparam); return mesh; },py::call_guard()) ; } PYBIND11_MODULE(libgeom2d, m) { ExportGeom2d(m); } #endif netgen-6.2.1905/libsrc/geom2d/vsgeom2d.cpp0000644000175000017500000000435213504650527016672 0ustar kurtkurt#include #include #include #include "vsgeom2d.hpp" namespace netgen { /* *********************** Draw 2D Geometry **************** */ VisualSceneGeometry2d :: VisualSceneGeometry2d () : VisualScene() { ; } VisualSceneGeometry2d :: ~VisualSceneGeometry2d () { ; } void VisualSceneGeometry2d :: DrawScene () { if (changeval != geometry2d->GetSplines().Size()) BuildScene(); changeval = geometry2d->GetSplines().Size(); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); // glEnable (GL_LIGHT0); glDisable (GL_LIGHTING); glPushMatrix(); glMultMatrixd (transformationmat); // SetClippingPlane (); glShadeModel (GL_SMOOTH); glEnable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); // float mat_col[] = { 0, 0, 1, 1 }; // glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glColor3f (0, 0, 1); Array > points, otherpoints; for (int i = 1; i <= geometry2d->GetSplines().Size(); i++) { geometry2d->GetSplines().Get(i)->GetPoints (200, points); glBegin (GL_LINE_STRIP); for (int j = 0; j < points.Size(); j++) glVertex3d (points[j](0), points[j](1), 0); glEnd(); } glColor3f (1, 0, 0); for (int i = 1; i <= geometry2d->GetSplines().Size(); i++) { int other = geometry2d->GetSpline(i-1).copyfrom; if (other != -1) { geometry2d->GetSplines().Get(i)->GetPoints (6, points); geometry2d->GetSplines().Get(other)->GetPoints (6, otherpoints); glBegin (GL_LINES); for (int j = 1; j < 5; j++) { glVertex3d (points[j](0), points[j](1), 0); glVertex3d (otherpoints[j](0), otherpoints[j](1), 0); } glEnd (); } } glPopMatrix(); DrawCoordinateCross (); DrawNetgenLogo (); glFinish(); } void VisualSceneGeometry2d :: BuildScene (int zoomall) { Box<2> bbox; geometry2d->GetBoundingBox (bbox); Point<2> c = Center (bbox.PMin(), bbox.PMax()); center = Point3d (c(0), c(1), 0); rad = Dist (bbox.PMin(), bbox.PMax()) / 2; CalcTransformationMatrices(); } } netgen-6.2.1905/libsrc/geom2d/geometry2d.cpp0000644000175000017500000005446113504650527017233 0ustar kurtkurt/* 2d Spline curve for Mesh generator */ #include #include namespace netgen { SplineGeometry2d :: ~SplineGeometry2d() { for ( int i = 0; i < bcnames.Size(); i++ ) delete bcnames[i]; for (int i=0; i x; char buf[50]; infile.open (filename); if ( ! infile.good() ) throw NgException(string ("Input file '") + string (filename) + string ("' not available!")); TestComment ( infile ); infile >> buf; // file recognition tensormeshing.SetSize(0); quadmeshing.SetSize(0); TestComment ( infile ); if ( strcmp (buf, "splinecurves2dnew") == 0 ) { LoadDataNew ( infile ); } else if ( strcmp (buf, "splinecurves2dv2") == 0 ) { LoadDataV2 ( infile ); } else { LoadData(infile ); } infile.close(); } // herbert: fixed TestComment void SplineGeometry2d :: TestComment ( ifstream & infile ) { bool comment = true; char ch; while ( comment == true && !infile.eof() ) { infile.get(ch); if ( ch == '#' ) { // skip comments while ( ch != '\n' && !infile.eof() ) { infile.get(ch); } } else if ( ch == '\n' ) { // skip empty lines ; } else if ( isspace(ch) ) { // skip whitespaces ; } else { // end of comment infile.putback(ch); comment = false; } } return; } void SplineGeometry2d :: LoadData ( ifstream & infile ) { enum { D = 2 }; int nump, numseg, leftdom, rightdom; Point x; int hi1, hi2, hi3; double hd; char buf[50], ch; materials.SetSize(0); maxh.SetSize(0); infile >> elto0; TestComment ( infile ); infile >> nump; for (int i = 0; i < nump; i++) { TestComment ( infile ); for(int j=0; j> x(j); infile >> hd; Flags flags; ch = 'a'; // infile >> ch; do { infile.get (ch); } while (isspace(ch) && ch != '\n'); while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; do { infile.get (ch); } while (isspace(ch) && ch != '\n'); } if (infile.good()) infile.putback (ch); geompoints.Append (GeomPoint(x, hd)); geompoints.Last().hpref = flags.GetDefineFlag ("hpref"); geompoints.Last().hmax = flags.GetNumFlag("hmax", 1e99); } PrintMessage (3, nump, " points loaded"); TestComment ( infile ); infile >> numseg; bcnames.SetSize(numseg); for ( int i = 0; i < numseg; i++ ) bcnames[i] = 0; // "default"; SplineSeg * spline = 0; PrintMessage (3, numseg, " segments loaded"); for (int i = 0; i < numseg; i++) { TestComment ( infile ); infile >> leftdom >> rightdom; // cout << "add spline " << i << ", left = " << leftdom << ", right = " << rightdom << endl; infile >> buf; // type of spline segment if (strcmp (buf, "2") == 0) { // a line infile >> hi1 >> hi2; spline = new LineSeg(geompoints[hi1-1], geompoints[hi2-1]); } else if (strcmp (buf, "3") == 0) { // a rational spline infile >> hi1 >> hi2 >> hi3; spline = new SplineSeg3 (geompoints[hi1-1], geompoints[hi2-1], geompoints[hi3-1]); } else if (strcmp (buf, "4") == 0) { // an arc infile >> hi1 >> hi2 >> hi3; spline = new CircleSeg (geompoints[hi1-1], geompoints[hi2-1], geompoints[hi3-1]); // break; } else if (strcmp (buf, "discretepoints") == 0) { int npts; infile >> npts; Array< Point > pts(npts); for (int j = 0; j < npts; j++) for(int k=0; k> pts[j](k); spline = new DiscretePointsSeg (pts); } SplineSegExt * spex = new SplineSegExt (*spline); infile >> spex->reffak; spex -> leftdom = leftdom; spex -> rightdom = rightdom; splines.Append (spex); Flags flags; ch = 'a'; infile >> ch; while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; infile >> ch; } if (infile.good()) infile.putback (ch); spex->bc = int (flags.GetNumFlag ("bc", i+1)); spex->hpref_left = int (flags.GetDefineFlag ("hpref")) || int (flags.GetDefineFlag ("hprefleft")); spex->hpref_right = int (flags.GetDefineFlag ("hpref")) || int (flags.GetDefineFlag ("hprefright")); spex->copyfrom = int (flags.GetNumFlag ("copy", -1)); if ( flags.StringFlagDefined("bcname") ) { int mybc = spex->bc-1; delete bcnames[mybc]; bcnames[mybc] = new string (flags.GetStringFlag("bcname","") ); } spex -> hmax = flags.GetNumFlag("hmax", 1e99); } } void SplineGeometry2d :: LoadDataNew ( ifstream & infile ) { enum { D = 2 }; int nump, numseg, leftdom, rightdom; Point x; int hi1, hi2, hi3; double hd; char buf[50], ch; int pointnr; TestComment ( infile ); infile >> elto0; TestComment ( infile ); infile >> nump; geompoints.SetSize(nump); for (int i = 0; i < nump; i++) { TestComment ( infile ); infile >> pointnr; if ( pointnr > nump ) { throw NgException(string ("Point number greater than total number of points") ); } for(int j=0; j> x(j); // hd is now optional, default 1 // infile >> hd; hd = 1; Flags flags; // get flags, ch = 'a'; // infile >> ch; do { infile.get (ch); // if another int-value, set refinement flag to this value // (corresponding to old files) if ( int (ch) >= 48 && int(ch) <= 57 ) { infile.putback(ch); infile >> hd; infile.get(ch); } } while (isspace(ch) && ch != '\n'); while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; do { infile.get (ch); } while (isspace(ch) && ch != '\n'); } if (infile.good()) infile.putback (ch); if ( hd == 1 ) hd = flags.GetNumFlag ( "ref", 1.0); // geompoints.Append (GeomPoint(x, hd)); geompoints[pointnr-1] = GeomPoint(x, hd); geompoints[pointnr-1].hpref = flags.GetDefineFlag ("hpref"); } TestComment ( infile ); infile >> numseg; bcnames.SetSize(numseg); for ( int i = 0; i < numseg; i++ ) bcnames[i] = 0;//new"default"; SplineSeg * spline = 0; for (int i = 0; i < numseg; i++) { TestComment ( infile ); infile >> leftdom >> rightdom; // cout << "add spline " << i << ", left = " << leftdom << endl; infile >> buf; // type of spline segment if (strcmp (buf, "2") == 0) { // a line infile >> hi1 >> hi2; spline = new LineSeg (geompoints[hi1-1], geompoints[hi2-1]); } else if (strcmp (buf, "3") == 0) { // a rational spline infile >> hi1 >> hi2 >> hi3; spline = new SplineSeg3 (geompoints[hi1-1], geompoints[hi2-1], geompoints[hi3-1]); } else if (strcmp (buf, "4") == 0) { // an arc infile >> hi1 >> hi2 >> hi3; spline = new CircleSeg (geompoints[hi1-1], geompoints[hi2-1], geompoints[hi3-1]); // break; } else if (strcmp (buf, "discretepoints") == 0) { int npts; infile >> npts; Array< Point > pts(npts); for (int j = 0; j < npts; j++) for(int k=0; k> pts[j](k); spline = new DiscretePointsSeg (pts); } // infile >> spline->reffak; SplineSegExt * spex = new SplineSegExt (*spline); spex -> leftdom = leftdom; spex -> rightdom = rightdom; splines.Append (spex); // hd is now optional, default 1 // infile >> hd; hd = 1; infile >> ch; // get refinement parameter, if it is there // infile.get (ch); // if another int-value, set refinement flag to this value // (corresponding to old files) if ( int (ch) >= 48 && int(ch) <= 57 ) { infile.putback(ch); infile >> hd; infile >> ch ; } Flags flags; while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; infile >> ch; } if (infile.good()) infile.putback (ch); spex->bc = int (flags.GetNumFlag ("bc", i+1)); spex->hpref_left = int (flags.GetDefineFlag ("hpref")) || int (flags.GetDefineFlag ("hprefleft")); spex->hpref_right = int (flags.GetDefineFlag ("hpref")) || int (flags.GetDefineFlag ("hprefright")); spex->copyfrom = int (flags.GetNumFlag ("copy", -1)); spex->reffak = flags.GetNumFlag ("ref", 1 ); spex->hmax = flags.GetNumFlag ("maxh", 1e99 ); if ( flags.StringFlagDefined("bcname") ) { int mybc = spex->bc-1; if ( bcnames[mybc] ) delete bcnames[mybc]; bcnames[mybc] = new string (flags.GetStringFlag("bcname","") ); } if ( hd != 1 ) spex->reffak = hd; } if ( !infile.good() ) return; TestComment ( infile ); int numdomains; int domainnr; char material[100]; if ( !infile.good() ) return; infile >> numdomains; materials.SetSize(numdomains) ; maxh.SetSize ( numdomains ) ; maxh = 1e99; TestComment ( infile ); for ( int i=0; i> domainnr; infile >> material; strcpy(materials[domainnr-1], material); Flags flags; ch = 'a'; infile >> ch; while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; infile >> ch; } if (infile.good()) infile.putback (ch); maxh[domainnr-1] = flags.GetNumFlag ( "maxh", 1e99); } return; } void SplineGeometry2d :: LoadDataV2 ( ifstream & infile ) { enum { D = 2 }; // new parser by Astrid Sinwel PrintMessage (1, "Load 2D Geometry V2"); int nump, leftdom, rightdom; Point x; int hi1, hi2, hi3; double hd; char buf[50], ch; int pointnr; string keyword; Array < GeomPoint > infilepoints (0); Array pointnrs (0); nump = 0; int numdomains = 0; TestComment ( infile ); // refinement factor infile >> elto0; TestComment ( infile ); // test if next ch is a letter, i.e. new keyword starts bool ischar = false; while ( infile.good() ) { infile >> keyword; ischar = false; if ( keyword == "points" ) { PrintMessage (3, "load points"); infile.get(ch); infile.putback(ch); // test if ch is a letter if ( int(ch) >= 65 && int(ch) <=90 ) ischar = true; if ( int(ch) >= 97 && int(ch) <= 122 ) ischar = true; while ( ! ischar ) { TestComment ( infile ); infile >> pointnr; // pointnrs 1-based if ( pointnr > nump ) nump = pointnr; pointnrs.Append(pointnr); for(int j=0; j> x(j); // hd is now optional, default 1 // infile >> hd; hd = 1; Flags flags; // get flags, ch = 'a'; // infile >> ch; do { infile.get (ch); // if another int-value, set refinement flag to this value // (corresponding to old files) if ( int (ch) >= 48 && int(ch) <= 57 ) { infile.putback(ch); infile >> hd; infile.get(ch); } } while (isspace(ch) && ch != '\n'); while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; do { infile.get (ch); } while (isspace(ch) && ch != '\n'); } if (infile.good()) infile.putback (ch); if ( hd == 1 ) hd = flags.GetNumFlag ( "ref", 1.0); // geompoints.Append (GeomPoint(x, hd)); infilepoints.Append ( GeomPoint(x, hd) ); infilepoints.Last().hpref = flags.GetDefineFlag ("hpref"); infilepoints.Last().hmax = flags.GetNumFlag ("maxh", 1e99); TestComment(infile); infile.get(ch); infile.putback(ch); // test if letter if ( int(ch) >= 65 && int(ch) <=90 ) ischar = true; if ( int(ch) >= 97 && int(ch) <= 122 ) ischar = true; } // infile.putback (ch); geompoints.SetSize(nump); for ( int i = 0; i < nump; i++ ) { geompoints[pointnrs[i] - 1] = infilepoints[i]; geompoints[pointnrs[i] - 1].hpref = infilepoints[i].hpref; } TestComment(infile); } else if ( keyword == "segments" ) { PrintMessage (3, "load segments"); bcnames.SetSize(0); infile.get(ch); infile.putback(ch); int i = 0; // test if ch is a letter if ( int(ch) >= 65 && int(ch) <=90 ) ischar = true; if ( int(ch) >= 97 && int(ch) <= 122 ) ischar = true; while ( !ischar ) //ch != 'p' && ch != 'm' ) { i++; TestComment ( infile ); SplineSeg * spline = 0; TestComment ( infile ); infile >> leftdom >> rightdom; if ( leftdom > numdomains ) numdomains = leftdom; if ( rightdom > numdomains ) numdomains = rightdom; infile >> buf; // type of spline segment if (strcmp (buf, "2") == 0) { // a line infile >> hi1 >> hi2; spline = new LineSeg(geompoints[hi1-1], geompoints[hi2-1]); } else if (strcmp (buf, "3") == 0) { // a rational spline infile >> hi1 >> hi2 >> hi3; spline = new SplineSeg3 (geompoints[hi1-1], geompoints[hi2-1], geompoints[hi3-1]); } else if (strcmp (buf, "4") == 0) { // an arc infile >> hi1 >> hi2 >> hi3; spline = new CircleSeg (geompoints[hi1-1], geompoints[hi2-1], geompoints[hi3-1]); } else if (strcmp (buf, "discretepoints") == 0) { int npts; infile >> npts; Array< Point > pts(npts); for (int j = 0; j < npts; j++) for(int k=0; k> pts[j](k); spline = new DiscretePointsSeg (pts); } else if (strcmp (buf, "bsplinepoints") == 0) { int npts,order; infile >> npts; infile >> order; Array< Point > pts(npts); for (int j = 0; j < npts; j++) for(int k=0; k> pts[j](k); if(order<2) cerr<<"Minimum order of 2 is required!!"< (pts); else if(order==3) spline = new BSplineSeg (pts); else if(order==4) spline = new BSplineSeg (pts); else if(order>4) cerr<<"Maximum allowed order is 4!!"<> spline->reffak; SplineSegExt * spex = new SplineSegExt (*spline); spex -> leftdom = leftdom; spex -> rightdom = rightdom; splines.Append (spex); // hd is now optional, default 1 // infile >> hd; hd = 1; infile >> ch; // get refinement parameter, if it is there //infile.get (ch); // if another int-value, set refinement flag to this value // (corresponding to old files) /* if ( int (ch) >= 48 && int(ch) <= 57 ) { infile.putback(ch); infile >> hd; infile >> ch ; } */ // get flags, Flags flags; while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; infile >> ch; } if (infile.good()) infile.putback (ch); spex->bc = int (flags.GetNumFlag ("bc", i+1)); spex->hpref_left = int (flags.GetDefineFlag ("hpref")) || int (flags.GetDefineFlag ("hprefleft")); spex->hpref_right = int (flags.GetDefineFlag ("hpref")) || int (flags.GetDefineFlag ("hprefright")); spex->copyfrom = int (flags.GetNumFlag ("copy", -1)); spex->reffak = flags.GetNumFlag ("ref", 1 ); spex->hmax = flags.GetNumFlag ("maxh", 1e99 ); if ( hd != 1 ) spex->reffak = hd; if ( flags.StringFlagDefined("bcname") ) { int mybc = spex->bc-1; for ( int ii = bcnames.Size(); ii <= mybc; ii++ ) bcnames.Append ( new string ("default")); if ( bcnames[mybc] ) delete bcnames[mybc]; bcnames[mybc] = new string (flags.GetStringFlag("bcname","") ); } TestComment(infile); infile.get(ch); infile.putback(ch); // test if ch is a letter if ( int(ch) >= 65 && int(ch) <=90 ) ischar = true; if ( int(ch) >= 97 && int(ch) <= 122 ) ischar = true; } infile.get(ch); infile.putback(ch); } else if ( keyword == "materials" ) { TestComment ( infile ); int domainnr; char material[100]; if ( !infile.good() ) return; materials.SetSize(numdomains) ; maxh.SetSize ( numdomains ) ; for ( int i = 0; i < numdomains; i++) maxh[i] = 1000; quadmeshing.SetSize ( numdomains ); quadmeshing = false; tensormeshing.SetSize ( numdomains ); tensormeshing = false; layer.SetSize ( numdomains ); layer = 1; TestComment ( infile ); for ( int i=0; i> domainnr; infile >> material; strcpy (materials[domainnr-1], material); Flags flags; ch = 'a'; infile >> ch; while (ch == '-') { char flag[100]; flag[0]='-'; infile >> (flag+1); flags.SetCommandLineFlag (flag); ch = 'a'; infile >> ch; } if (infile.good()) infile.putback (ch); maxh[domainnr-1] = flags.GetNumFlag ( "maxh", 1000); if (flags.GetDefineFlag("quad")) quadmeshing[domainnr-1] = true; if (flags.GetDefineFlag("tensor")) tensormeshing[domainnr-1] = true; layer[domainnr-1] = int(flags.GetNumFlag ("layer", 1)); } } } return; } /* void CalcPartition (const SplineSegExt & spline, double l, double h, double h1, double h2, double hcurve, double elto0, Array & points) { double fperel, oldf, f; int n = 1000; points.SetSize (0); double dt = l / n; double sum = 0; for (int i = 1; i <= n; i++) { double t = (i-0.5)*dt; double fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2); double curv = spline.CalcCurvature (t/l); cout << "curv = " << curv << endl; if (curv < 1e-10) curv = 1e-10; fun = min2 (fun, 0.1/curv); sum += dt / fun; } int nel = int (sum+1); fperel = sum / nel; points.Append (0); int i = 1; oldf = 0; // t = 0.5 * dt; for (int j = 1; j <= n && i < nel; j++) { double t = (j-0.5)*dt; double fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2); double curv = spline.CalcCurvature (t/l); if (curv < 1e-10) curv = 1e-10; fun = min2 (fun, 0.1/curv); f = oldf + dt / fun; while (i * fperel < f && i < nel) { points.Append ( dt * (j-1) + (i * fperel - oldf) * fun); i++; } oldf = f; t += dt; } points.Append (l); } */ void SplineGeometry2d :: SetBCName (int bcnr, string name) { if (bcnr < 1) throw NgException ("Illegal nr in SetBCName"); int new_to_add = bcnr - bcnames.Size(); for (int i = 0; i < new_to_add; i++) bcnames.Append (new string("default")); delete bcnames[bcnr-1]; bcnames[bcnr-1] = new string(name); } string SplineGeometry2d :: GetBCName( int bcnr ) const { if (bcnames.Size() >= bcnr) if (bcnames[bcnr-1] ) return *bcnames[bcnr-1]; return "default"; } string * SplineGeometry2d :: BCNamePtr( int bcnr ) { if ( bcnr > bcnames.Size() ) return nullptr; else return bcnames[bcnr-1]; } int SplineGeometry2d :: GetBCNumber (string name) const { for (int i = 0; i < bcnames.Size(); i++) if (*bcnames[i] == name) return i+1; return 0; } int SplineGeometry2d :: AddBCName (string name) { bcnames.Append (new string(name)); return bcnames.Size(); } void SplineGeometry2d :: GetMaterial (int domnr, char* & material ) { if ( materials.Size() >= domnr) material = materials[domnr-1]; else material = 0; } void SplineGeometry2d :: SetMaterial (int domnr, const string & material) { int oldsize = materials.Size(); if (domnr > materials.Size()) materials.SetSize (domnr); for (int i = oldsize; i < domnr; i++) materials[i] = nullptr; if (domnr >= 1) // && domnr <= materials.Size()) { delete materials[domnr-1]; materials[domnr-1] = new char[material.size()+1]; strcpy(materials[domnr-1], material.c_str()); } else throw NgException ("material index out of range"); } double SplineGeometry2d :: GetDomainMaxh (const int domnr ) { if ( maxh.Size() >= domnr && domnr > 0) return maxh[domnr-1]; else return -1; } void SplineGeometry2d :: SetDomainMaxh (int domnr, double h) { int oldsize = maxh.Size(); if (domnr > maxh.Size()) maxh.SetSize (domnr); for (int i = oldsize; i < domnr; i++) maxh[i] = 1e99; if (domnr >= 1) maxh[domnr-1] = h; else throw NgException ("material index out of range"); } extern void MeshFromSpline2D (SplineGeometry2d & geometry, shared_ptr & mesh, MeshingParameters & mp); int SplineGeometry2d :: GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam) { MeshFromSpline2D (*this, mesh, mparam); return 0; } Refinement & SplineGeometry2d :: GetRefinement () const { return * new Refinement2d (*this); } class SplineGeometryRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const; }; NetgenGeometry * SplineGeometryRegister :: Load (string filename) const { const char * cfilename = filename.c_str(); if (strcmp (&cfilename[strlen(cfilename)-4], "in2d") == 0) { PrintMessage (1, "Load 2D-Spline geometry file ", cfilename); ifstream infile(cfilename); SplineGeometry2d * hgeom = new SplineGeometry2d(); hgeom -> Load (cfilename); return hgeom; } return NULL; } class SplineGeoInit { public: SplineGeoInit() { geometryregister.Append (new SplineGeometryRegister); } }; SplineGeoInit sginit; static RegisterClassForArchive, NetgenGeometry> regspg2; static RegisterClassForArchive> regssext; } netgen-6.2.1905/libsrc/geom2d/vsgeom2d.hpp0000644000175000017500000000150313504650527016672 0ustar kurtkurt#ifndef FILE_VSGEOM2D #define FILE_VSGEOM2D /**************************************************************************/ /* File: vsgeom2d.hpp */ /* Author: Joachim Schoeberl */ /* Date: 05. Jan. 2011 */ /**************************************************************************/ namespace netgen { class DLL_HEADER VisualSceneGeometry2d : public VisualScene { const class SplineGeometry2d * geometry2d; public: VisualSceneGeometry2d (); virtual ~VisualSceneGeometry2d (); void SetGeometry (const class SplineGeometry2d * ageometry2d) { geometry2d = ageometry2d; } virtual void BuildScene (int zoomall = 0); virtual void DrawScene (); }; } #endif netgen-6.2.1905/libsrc/geom2d/geom2dmesh.cpp0000644000175000017500000000644313504650527017201 0ustar kurtkurt#include #include namespace netgen { Refinement2d :: Refinement2d (const SplineGeometry2d & ageometry) : Refinement(), geometry(ageometry) { ; } Refinement2d :: ~Refinement2d () { ; } void Refinement2d :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const { newp = p1+secpoint*(p2-p1); newgi.trignum = 1; } void Refinement2d :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const { Point<2> p2d; double newdist; auto spline = geometry.GetSplines().Get(ap1.edgenr); if( (ap1.dist == 0.0) && (ap2.dist == 0.0) ) { // used for manually generated meshes const SplineSeg3<2> * ss3; const LineSeg<2> * ls; auto ext = dynamic_cast(spline); if(ext) { ss3 = dynamic_cast *>(ext->seg); ls = dynamic_cast *>(ext->seg); } else { ss3 = dynamic_cast *>(spline); ls = dynamic_cast *>(spline); } Point<2> p12d(p1(0),p1(1)), p22d(p2(0),p2(1)); Point<2> p1_proj(0.0,0.0), p2_proj(0.0,0.0); double t1_proj = 0.0; double t2_proj = 0.0; if(ss3) { ss3->Project(p12d,p1_proj,t1_proj); ss3->Project(p22d,p2_proj,t2_proj); } else if(ls) { ls->Project(p12d,p1_proj,t1_proj); ls->Project(p22d,p2_proj,t2_proj); } p2d = spline->GetPoint (((1-secpoint)*t1_proj+secpoint*t2_proj)); newdist = (1-secpoint)*t1_proj+secpoint*t2_proj; } else { p2d = spline->GetPoint (((1-secpoint)*ap1.dist+secpoint*ap2.dist)); newdist = (1-secpoint)*ap1.dist+secpoint*ap2.dist; } // (*testout) << "refine 2d line, ap1.dist, ap2.dist = " << ap1.dist << ", " << ap2.dist << endl; // (*testout) << "p1, p2 = " << p1 << p2 << ", newp = " << p2d << endl; newp = Point3d (p2d(0), p2d(1), 0); newgi.edgenr = ap1.edgenr; newgi.dist = newdist; }; Vec<3> Refinement2d :: GetTangent (const Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & ap1) const { Vec<2> t2d = geometry.GetSplines().Get(ap1.edgenr) -> GetTangent(ap1.dist); return Vec<3> (t2d(0), t2d(1), 0); } Vec<3> Refinement2d :: GetNormal (const Point<3> & p, int surfi1, const PointGeomInfo & gi) const { return Vec<3> (0,0,1); } void Refinement2d :: ProjectToSurface (Point<3> & p, int surfi, const PointGeomInfo & /* gi */) const { p(2) = 0; } void Refinement2d :: ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const { Point<2> p2d (p(0), p(1)), pp; double t; geometry.GetSplines().Get(egi.edgenr) -> Project (p2d, pp, t); p = Point<3> (pp(0), pp(1), 0); } } netgen-6.2.1905/libsrc/geom2d/genmesh2d.cpp0000644000175000017500000004174313504650527017025 0ustar kurtkurt#include #include namespace netgen { // extern DLL_HEADER MeshingParameters mparam; extern void Optimize2d (Mesh & mesh, MeshingParameters & mp); void CalcPartition (const SplineSegExt & spline, // double l, MeshingParameters & mp, Mesh & mesh, // double h, double h1, double h2, double hcurve, double elto0, Array & points) { double fperel, oldf, f; int n = 10000; Array > xi(n); Array hi(n); for (int i = 0; i < n; i++) { xi[i] = spline.GetPoint ( (i+0.5) / n ); hi[i] = mesh.GetH (Point<3> (xi[i](0), xi[i](1), 0)); } // limit slope double gradh = min(1/elto0,mp.grading); for (int i = 0; i < n-1; i++) { double hnext = hi[i] + gradh * (xi[i+1]-xi[i]).Length(); hi[i+1] = min(hi[i+1], hnext); } for (int i = n-1; i > 1; i--) { double hnext = hi[i] + gradh * (xi[i-1]-xi[i]).Length(); hi[i-1] = min(hi[i-1], hnext); } points.SetSize (0); double len = spline.Length(); double dt = len / n; double sum = 0; for (int i = 1; i <= n; i++) { // double t = (i-0.5)*dt; double fun = hi[i-1]; sum += dt / fun; } int nel = int (sum+0.5); if (nel == 0) nel = 1; fperel = sum / nel; points.Append (0); int i = 1; oldf = 0; for (int j = 1; j <= n && i < nel; j++) { double t = (j-0.5)*dt; double fun = hi[j-1]; f = oldf + dt / fun; while (i * fperel < f && i < nel) { points.Append ( dt * (j-1) + (i * fperel - oldf) * fun); i++; } oldf = f; t += dt; } points.Append (len); } // partitionizes spline curve void Partition (const SplineSegExt & spline, MeshingParameters & mp, double hxxx, double elto0, Mesh & mesh, Point3dTree & searchtree, int segnr) { int n = 100; Point<2> mark, oldmark; Array curvepoints; double edgelength, edgelengthold; CalcPartition (spline, mp, mesh, elto0, curvepoints); double dt = 1.0 / n; int j = 1; Point<2> pold = spline.GetPoint (0); double lold = 0; oldmark = pold; edgelengthold = 0; Array locsearch; for (int i = 1; i <= n; i++) { Point<2> p = spline.GetPoint (i*dt); double l = lold + Dist (p, pold); while (j < curvepoints.Size() && (l >= curvepoints[j] || i == n)) { double frac = (curvepoints[j]-lold) / (l-lold); edgelength = i*dt + (frac-1)*dt; mark = spline.GetPoint (edgelength); { PointIndex pi1 = -1, pi2 = -1; Point3d mark3(mark(0), mark(1), 0); Point3d oldmark3(oldmark(0), oldmark(1), 0); double h = mesh.GetH (Point<3> (oldmark(0), oldmark(1), 0)); Vec<3> v (1e-4*h, 1e-4*h, 1e-4*h); searchtree.GetIntersecting (oldmark3 - v, oldmark3 + v, locsearch); for (int k = 0; k < locsearch.Size(); k++) if ( mesh[PointIndex(locsearch[k])].GetLayer() == spline.layer) pi1 = locsearch[k]; searchtree.GetIntersecting (mark3 - v, mark3 + v, locsearch); for (int k = 0; k < locsearch.Size(); k++) if ( mesh[PointIndex(locsearch[k])].GetLayer() == spline.layer) pi2 = locsearch[k]; if (pi1 == -1) { pi1 = mesh.AddPoint(oldmark3, spline.layer); searchtree.Insert (oldmark3, pi1); } if (pi2 == -1) { pi2 = mesh.AddPoint(mark3, spline.layer); searchtree.Insert (mark3, pi2); } Segment seg; seg.edgenr = segnr; seg.si = spline.bc; // segnr; seg[0] = pi1; seg[1] = pi2; seg.domin = spline.leftdom; seg.domout = spline.rightdom; seg.epgeominfo[0].edgenr = segnr; seg.epgeominfo[0].dist = edgelengthold; seg.epgeominfo[1].edgenr = segnr; seg.epgeominfo[1].dist = edgelength; seg.singedge_left = spline.hpref_left; seg.singedge_right = spline.hpref_right; mesh.AddSegment (seg); } oldmark = mark; edgelengthold = edgelength; j++; } pold = p; lold = l; } } void SplineGeometry2d :: PartitionBoundary (MeshingParameters & mp, double h, Mesh & mesh2d) { enum { D = 2 }; Box bbox; GetBoundingBox (bbox); double dist = Dist (bbox.PMin(), bbox.PMax()); Point<3> pmin; Point<3> pmax; pmin(2) = -dist; pmax(2) = dist; for(int j=0;j (point(0), point(1), 0), point.hmax); for (int i = 0; i < splines.Size(); i++) { const SplineSegExt & spline = GetSpline(i); const GeomPoint<2> & p1 = spline.StartPI(); const GeomPoint<2> & p2 = spline.EndPI(); double h1 = min (p1.hmax, h/p1.refatpoint); mesh2d.RestrictLocalH (Point<3>(p1(0),p1(1),0), h1); double h2 = min (p2.hmax, h/p2.refatpoint); mesh2d.RestrictLocalH (Point<3>(p2(0),p2(1),0), h2); double len = spline.Length(); mesh2d.RestrictLocalHLine (Point<3>(p1(0),p1(1),0), Point<3>(p2(0),p2(1),0), len/mp.segmentsperedge); double hcurve = min (spline.hmax, h/spline.reffak); double hl = GetDomainMaxh (spline.leftdom); if (hl > 0) hcurve = min2 (hcurve, hl); double hr = GetDomainMaxh (spline.rightdom); if (hr > 0) hcurve = min2 (hcurve, hr); int np = 1000; for (double t = 0.5/np; t < 1; t += 1.0/np) { Point<2> x = spline.GetPoint(t); double hc = 1.0/mp.curvaturesafety / (1e-99+spline.CalcCurvature (t)); mesh2d.RestrictLocalH (Point<3> (x(0), x(1), 0), min2(hc, hcurve)); } } for (auto mspnt : mp.meshsize_points) mesh2d.RestrictLocalH (mspnt.pnt, mspnt.h); // add point elements for (auto & point : geompoints) if (point.name.length()) { Point<3> newp(point(0), point(1), 0); PointIndex npi = mesh2d.AddPoint (newp, 1, FIXEDPOINT); mesh2d.AddLockedPoint(npi); Element0d el(npi, npi); el.name = point.name; mesh2d.SetCD2Name(npi, point.name); mesh2d.pointelements.Append (el); searchtree.Insert (newp, npi); } // first add all vertices (for compatible orientation on periodic bnds) { double diam2 = Dist2(pmin, pmax); for (int i = 0; i < splines.Size(); i++) for (int j : { 1, 2 }) { Point<2> hnewp = (j == 1) ? splines[i]->StartPI() : splines[i]->EndPI(); Point<3> newp(hnewp(0), hnewp(1), 0); int layer = GetSpline(i).layer; int npi = -1; for (PointIndex pi = PointIndex::BASE; pi < mesh2d.GetNP()+PointIndex::BASE; pi++) if (Dist2 (mesh2d.Point(pi), newp) < 1e-12 * diam2 && mesh2d.Point(pi).GetLayer() == layer) npi = pi; if (npi == -1) { npi = mesh2d.AddPoint (newp, layer); searchtree.Insert (newp, npi); } } } for (int i = 0; i < splines.Size(); i++) if (GetSpline(i).copyfrom == -1) { // astrid - set boundary meshsize to domain meshsize h // if no domain mesh size is given, the max h value from the bounding box is used double hl = GetDomainMaxh ( GetSpline(i).leftdom ); double hr = GetDomainMaxh ( GetSpline(i).rightdom ); double useh = h; if (hl > 0) useh = min2 (h, hl); if (hr > 0) useh = min2 (h, hr); Partition(GetSpline(i), mp, useh, elto0, mesh2d, searchtree, i+1); } else { CopyEdgeMesh (GetSpline(i).copyfrom, i+1, mesh2d, searchtree); } } void SplineGeometry2d :: CopyEdgeMesh (int from, int to, Mesh & mesh, Point3dTree & searchtree) { // const int D = 2; Array mappoints (mesh.GetNP()); Array param (mesh.GetNP()); mappoints = -1; param = 0; Point3d pmin, pmax; mesh.GetBox (pmin, pmax); double diam2 = Dist2(pmin, pmax); if (printmessage_importance>0) cout << "copy edge, from = " << from << " to " << to << endl; for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); if (seg.edgenr == from) { mappoints.Elem(seg[0]) = 1; param.Elem(seg[0]) = seg.epgeominfo[0].dist; mappoints.Elem(seg[1]) = 1; param.Elem(seg[1]) = seg.epgeominfo[1].dist; } } bool mapped = false; for (int i = 1; i <= mappoints.Size(); i++) { if (mappoints.Get(i) != -1) { Point<2> newp = splines.Get(to)->GetPoint (param.Get(i)); Point<3> newp3 (newp(0), newp(1), 0); int npi = -1; for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist2 (mesh.Point(pi), newp3) < 1e-12 * diam2) npi = pi; if (npi == -1) { npi = mesh.AddPoint (newp3); searchtree.Insert (newp3, npi); } mappoints.Elem(i) = npi; mesh.GetIdentifications().Add (i, npi, to); mapped = true; } } if(mapped) mesh.GetIdentifications().SetType(to,Identifications::PERIODIC); // copy segments int oldnseg = mesh.GetNSeg(); for (int i = 1; i <= oldnseg; i++) { const Segment & seg = mesh.LineSegment(i); if (seg.edgenr == from) { Segment nseg; nseg.edgenr = to; nseg.si = GetSpline(to-1).bc; // splines.Get(to)->bc; nseg[0] = mappoints.Get(seg[0]); nseg[1] = mappoints.Get(seg[1]); nseg.domin = GetSpline(to-1).leftdom; nseg.domout = GetSpline(to-1).rightdom; nseg.epgeominfo[0].edgenr = to; nseg.epgeominfo[0].dist = param.Get(seg[0]); nseg.epgeominfo[1].edgenr = to; nseg.epgeominfo[1].dist = param.Get(seg[1]); mesh.AddSegment (nseg); } } } void MeshFromSpline2D (SplineGeometry2d & geometry, shared_ptr & mesh, MeshingParameters & mp) { PrintMessage (1, "Generate Mesh from spline geometry"); Box<2> bbox = geometry.GetBoundingBox (); if (bbox.Diam() < mp.maxh) mp.maxh = bbox.Diam(); // double h = mp.maxh; // mesh = make_shared(); mesh->SetDimension (2); Point3d pmin(bbox.PMin()(0), bbox.PMin()(1), -bbox.Diam()); Point3d pmax(bbox.PMax()(0), bbox.PMax()(1), bbox.Diam()); mesh->SetLocalH (pmin, pmax, mp.grading); mesh->SetGlobalH (mp.maxh); geometry.PartitionBoundary (mp, mp.maxh, *mesh); PrintMessage (3, "Boundary mesh done, np = ", mesh->GetNP()); // marks mesh points for hp-refinement for (int i = 0; i < geometry.GetNP(); i++) if (geometry.GetPoint(i).hpref) { double mindist = 1e99; PointIndex mpi(0); Point<2> gp = geometry.GetPoint(i); Point<3> gp3(gp(0), gp(1), 0); for (PointIndex pi = PointIndex::BASE; pi < mesh->GetNP()+PointIndex::BASE; pi++) if (Dist2(gp3, (*mesh)[pi]) < mindist) { mpi = pi; mindist = Dist2(gp3, (*mesh)[pi]); } (*mesh)[mpi].Singularity(geometry.GetPoint(i).hpref); } int maxdomnr = 0; for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) { if ( (*mesh)[si].domin > maxdomnr) maxdomnr = (*mesh)[si].domin; if ( (*mesh)[si].domout > maxdomnr) maxdomnr = (*mesh)[si].domout; } mesh->ClearFaceDescriptors(); for (int i = 1; i <= maxdomnr; i++) mesh->AddFaceDescriptor (FaceDescriptor (i, 0, 0, i)); // set Array bcnames... // number of bcnames int maxsegmentindex = 0; for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) if ( (*mesh)[si].si > maxsegmentindex) maxsegmentindex = (*mesh)[si].si; mesh->SetNBCNames(maxsegmentindex); for ( int sindex = 0; sindex < maxsegmentindex; sindex++ ) mesh->SetBCName ( sindex, geometry.GetBCName( sindex+1 ) ); for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) (*mesh)[si].SetBCName ( (*mesh).GetBCNamePtr( (*mesh)[si].si-1 ) ); mesh->CalcLocalH(mp.grading); int bnp = mesh->GetNP(); // boundary points auto BndPntRange = mesh->Points().Range(); int hquad = mp.quad; for (int domnr = 1; domnr <= maxdomnr; domnr++) if (geometry.GetDomainTensorMeshing (domnr)) { // tensor product mesh Array nextpi(bnp); Array si1(bnp), si2(bnp); PointIndex firstpi; nextpi = -1; si1 = -1; si2 = -1; for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) { int p1 = -1, p2 = -2; if ( (*mesh)[si].domin == domnr) { p1 = (*mesh)[si][0]; p2 = (*mesh)[si][1]; } if ( (*mesh)[si].domout == domnr) { p1 = (*mesh)[si][1]; p2 = (*mesh)[si][0]; } if (p1 == -1) continue; nextpi[p1] = p2; // counter-clockwise int index = (*mesh)[si].si; if (si1[p1] != index && si2[p1] != index) { si2[p1] = si1[p1]; si1[p1] = index; } if (si1[p2] != index && si2[p2] != index) { si2[p2] = si1[p2]; si1[p2] = index; } } PointIndex c1(0), c2, c3, c4; // 4 corner points int nex = 1, ney = 1; for (PointIndex pi = 1; pi <= si2.Size(); pi++) if (si2[pi] != -1) { c1 = pi; break; } for (c2 = nextpi[c1]; si2[c2] == -1; c2 = nextpi[c2], nex++); for (c3 = nextpi[c2]; si2[c3] == -1; c3 = nextpi[c3], ney++); for (c4 = nextpi[c3]; si2[c4] == -1; c4 = nextpi[c4]); Array pts ( (nex+1) * (ney+1) ); // x ... inner loop pts = -1; for (PointIndex pi = c1, i = 0; pi != c2; pi = nextpi[pi], i++) pts[i] = pi; for (PointIndex pi = c2, i = 0; pi != c3; pi = nextpi[pi], i++) pts[(nex+1)*i+nex] = pi; for (PointIndex pi = c3, i = 0; pi != c4; pi = nextpi[pi], i++) pts[(nex+1)*(ney+1)-i-1] = pi; for (PointIndex pi = c4, i = 0; pi != c1; pi = nextpi[pi], i++) pts[(nex+1)*(ney-i)] = pi; for (PointIndex pix = nextpi[c1], ix = 0; pix != c2; pix = nextpi[pix], ix++) for (PointIndex piy = nextpi[c2], iy = 0; piy != c3; piy = nextpi[piy], iy++) { Point<3> p = (*mesh)[pix] + ( (*mesh)[piy] - (*mesh)[c2] ); pts[(nex+1)*(iy+1) + ix+1] = mesh -> AddPoint (p , 1, FIXEDPOINT); } for (int i = 0; i < ney; i++) for (int j = 0; j < nex; j++) { Element2d el(QUAD); el[0] = pts[i*(nex+1)+j]; el[1] = pts[i*(nex+1)+j+1]; el[2] = pts[(i+1)*(nex+1)+j+1]; el[3] = pts[(i+1)*(nex+1)+j]; el.SetIndex (domnr); mesh -> AddSurfaceElement (el); } } for (int domnr = 1; domnr <= maxdomnr; domnr++) { if (geometry.GetDomainTensorMeshing (domnr)) continue; double h = mp.maxh; if ( geometry.GetDomainMaxh ( domnr ) > 0 ) h = geometry.GetDomainMaxh(domnr); PrintMessage (3, "Meshing domain ", domnr, " / ", maxdomnr); int oldnf = mesh->GetNSE(); mp.quad = hquad || geometry.GetDomainQuadMeshing (domnr); Meshing2 meshing (mp, Box<3> (pmin, pmax)); Array compress(bnp); compress = -1; int cnt = 0; for (PointIndex pi : BndPntRange) if ( (*mesh)[pi].GetLayer() == geometry.GetDomainLayer(domnr)) { meshing.AddPoint ((*mesh)[pi], pi); cnt++; compress[pi] = cnt; } PointGeomInfo gi; gi.trignum = 1; for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) { if ( (*mesh)[si].domin == domnr) { meshing.AddBoundaryElement (compress[(*mesh)[si][0]], compress[(*mesh)[si][1]], gi, gi); } if ( (*mesh)[si].domout == domnr) { meshing.AddBoundaryElement (compress[(*mesh)[si][1]], compress[(*mesh)[si][0]], gi, gi); } } // not complete, use at own risk ... // meshing.Delaunay(*mesh, domnr, mp); mp.checkoverlap = 0; auto res = meshing.GenerateMesh (*mesh, mp, h, domnr); if (res != 0) throw NgException("meshing failed"); for (SurfaceElementIndex sei = oldnf; sei < mesh->GetNSE(); sei++) (*mesh)[sei].SetIndex (domnr); // astrid char * material; geometry.GetMaterial (domnr, material); if (material) mesh->SetMaterial (domnr, material); } mp.quad = hquad; int hsteps = mp.optsteps2d; mp.optimize2d = "smcm"; mp.optsteps2d = hsteps/2; Optimize2d (*mesh, mp); mp.optimize2d = "Smcm"; mp.optsteps2d = (hsteps+1)/2; Optimize2d (*mesh, mp); mp.optsteps2d = hsteps; mesh->Compress(); mesh->OrderElements(); mesh -> SetNextMajorTimeStamp(); mp.Render(); } } netgen-6.2.1905/libsrc/geom2d/CMakeLists.txt0000644000175000017500000000136213504650527017176 0ustar kurtkurtadd_definitions(-DNGLIB_EXPORTS) add_library(geom2d ${NG_LIB_TYPE} genmesh2d.cpp geom2dmesh.cpp geometry2d.cpp python_geom2d.cpp ) if(APPLE) set_target_properties( geom2d PROPERTIES SUFFIX ".so") endif(APPLE) target_link_libraries(geom2d mesh ${PYTHON_LIBRARIES}) if(NOT WIN32) install( TARGETS geom2d ${NG_INSTALL_DIR}) endif(NOT WIN32) target_link_libraries(geom2d ngcore) if(USE_GUI) add_library(geom2dvis ${NG_LIB_TYPE} vsgeom2d.cpp) if(NOT WIN32) target_link_libraries(geom2dvis geom2d) install( TARGETS geom2dvis ${NG_INSTALL_DIR}) endif(NOT WIN32) endif(USE_GUI) install(FILES geom2dmesh.hpp geometry2d.hpp spline2d.hpp vsgeom2d.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/geom2d COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/core/0000755000175000017500000000000013504650527014207 5ustar kurtkurtnetgen-6.2.1905/libsrc/core/logging.cpp0000644000175000017500000000764013504650527016350 0ustar kurtkurt#include "logging.hpp" #ifdef NETGEN_USE_SPDLOG #include #include #include #else // NETGEN_USE_SPDLOG #include #endif // NETGEN_USE_SPDLOG namespace ngcore { std::ostream* testout = new std::ostream(nullptr); // NOLINT void Logger::log(level::level_enum level, std::string && s) { #ifdef NETGEN_USE_SPDLOG logger->log(spdlog::level::level_enum(level), s); #else // NETGEN_USE_SPDLOG if(level>level::debug) std::clog << s << '\n'; #endif // NETGEN_USE_SPDLOG } #ifdef NETGEN_USE_SPDLOG namespace detail { std::vector>& GetDefaultSinks() { static std::vector> sinks = { std::make_shared() }; return sinks; } std::shared_ptr CreateDefaultLogger(const std::string& name) { auto& default_sinks = GetDefaultSinks(); auto logger = std::make_shared(name, default_sinks.begin(), default_sinks.end()); spdlog::details::registry::instance().register_and_init(logger); return logger; } } // namespace detail std::shared_ptr GetLogger(const std::string& name) { auto logger = spdlog::get(name); if(!logger) logger = detail::CreateDefaultLogger(name); return std::make_shared(logger); } void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name) { if(!name.empty()) spdlog::get(name)->set_level(level); else spdlog::set_level(level); } void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger) { auto sink = std::make_shared(filename); sink->set_level(level); if(!logger.empty()) GetLogger(logger)->logger->sinks().push_back(sink); else { detail::GetDefaultSinks().push_back(sink); spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); }); } } void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger) { auto sink = std::make_shared(); sink->set_level(level); if(!logger.empty()) GetLogger(logger)->logger->sinks().push_back(sink); else { detail::GetDefaultSinks().push_back(sink); spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); }); } } void ClearLoggingSinks(const std::string& logger) { if(!logger.empty()) GetLogger(logger)->logger->sinks().clear(); else { detail::GetDefaultSinks().clear(); spdlog::details::registry::instance().apply_all([](auto logger) { logger->sinks().clear(); }); } } void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger) { if(!logger.empty()) GetLogger(logger)->logger->flush_on(level); else spdlog::flush_on(level); } #else // NETGEN_USE_SPDLOG } //namespace ngcore namespace spdlog { class logger { public: logger() = default; }; } // namespace spdlog namespace ngcore { // Dummy functions if no spdlog is available std::shared_ptr GetLogger(const std::string& /*unused*/) { return std::make_shared(std::make_shared()); } void SetLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} void AddFileSink(const std::string& /*unused*/, level::level_enum /*unused*/, const std::string& /*unused*/) {} void AddConsoleSink(level::level_enum /*unused*/, const std::string& /*unused*/) {} void ClearLoggingSinks(const std::string& /*unused*/) {} void FlushOnLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} } //namespace ngcore #endif // NETGEN_USE_SPDLOG netgen-6.2.1905/libsrc/core/profiler.cpp0000644000175000017500000000566613504650527016552 0ustar kurtkurt#include #include "profiler.hpp" namespace ngcore { std::vector NgProfiler::timers(NgProfiler::SIZE); // NOLINT std::string NgProfiler::filename; std::array NgProfiler::dummy_thread_times; size_t * NgProfiler::thread_times = NgProfiler::dummy_thread_times.data(); // NOLINT std::array NgProfiler::dummy_thread_flops; size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops.data(); // NOLINT std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT NgProfiler :: NgProfiler() { for (auto & t : timers) { t.tottime = 0.0; t.usedcounter = 0; t.flops = 0.0; } } NgProfiler :: ~NgProfiler() { if (filename.length()) { logger->debug( "write profile to file {}", filename ); FILE *prof = fopen(filename.c_str(),"w"); // NOLINT Print (prof); fclose(prof); // NOLINT } if (getenv ("NGPROFILE")) { std::string filename = "netgen.prof"; #ifdef PARALLEL filename += "."+ToString(id); #endif if (id == 0) logger->info( "write profile to file {}", filename ); FILE *prof = fopen(filename.c_str(),"w"); // NOLINT Print (prof); fclose(prof); // NOLINT } } void NgProfiler :: Print (FILE * prof) { int i = 0; for (auto & t : timers) { if (t.count != 0 || t.usedcounter != 0) { fprintf(prof,"job %3i calls %8li, time %6.4f sec",i,t.count,t.tottime); // NOLINT if(t.flops != 0.0) fprintf(prof,", MFlops = %6.2f",t.flops / (t.tottime) * 1e-6); // NOLINT if(t.loads != 0.0) fprintf(prof,", MLoads = %6.2f",t.loads / (t.tottime) * 1e-6); // NOLINT if(t.stores != 0.0) fprintf(prof,", MStores = %6.2f",t.stores / (t.tottime) * 1e-6); // NOLINT if(t.usedcounter) fprintf(prof," %s",t.name.c_str()); // NOLINT fprintf(prof,"\n"); // NOLINT } i++; } } int NgProfiler :: CreateTimer (const std::string & name) { static std::mutex createtimer_mutex; int nr = -1; { std::lock_guard guard(createtimer_mutex); for (int i = SIZE-1; i > 0; i--) { auto & t = timers[i]; if (!t.usedcounter) { t.usedcounter = 1; t.name = name; nr = i; break; } } } if (nr > -1) return nr; static bool first_overflow = true; if (first_overflow) { first_overflow = false; NgProfiler::logger->warn("no more timer available, reusing last one"); } return 0; } void NgProfiler :: Reset () { for(auto & t : timers) { t.tottime = 0.0; t.count = 0; t.flops = 0.0; t.loads = 0; t.stores = 0; } } NgProfiler prof; // NOLINT } // namespace ngcore netgen-6.2.1905/libsrc/core/mpi_wrapper.hpp0000644000175000017500000001413713504650527017253 0ustar kurtkurt#ifndef NGCORE_MPIWRAPPER_HPP #define NGCORE_MPIWRAPPER_HPP #ifdef PARALLEL #define OMPI_SKIP_MPICXX #include #endif namespace ngcore { #ifdef PARALLEL template struct MPI_typetrait { }; template <> struct MPI_typetrait { static MPI_Datatype MPIType () { return MPI_INT; } }; template <> struct MPI_typetrait { static MPI_Datatype MPIType () { return MPI_SHORT; } }; template <> struct MPI_typetrait { static MPI_Datatype MPIType () { return MPI_CHAR; } }; template <> struct MPI_typetrait { static MPI_Datatype MPIType () { return MPI_CHAR; } }; template <> struct MPI_typetrait { static MPI_Datatype MPIType () { return MPI_UINT64_T; } }; template <> struct MPI_typetrait { static MPI_Datatype MPIType () { return MPI_DOUBLE; } }; template <> struct MPI_typetrait { static MPI_Datatype MPIType () { return MPI_C_BOOL; } }; template ::MPIType())> inline MPI_Datatype GetMPIType () { return MPI_typetrait::MPIType(); } class NgMPI_Comm { protected: MPI_Comm comm; bool valid_comm; int * refcount; int rank, size; public: NgMPI_Comm () : valid_comm(false), refcount(nullptr), rank(0), size(1) { ; } NgMPI_Comm (MPI_Comm _comm, bool owns = false) : comm(_comm), valid_comm(true) { if (!owns) refcount = nullptr; else refcount = new int{1}; MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size); } NgMPI_Comm (const NgMPI_Comm & c) : comm(c.comm), valid_comm(c.valid_comm), refcount(c.refcount), rank(c.rank), size(c.size) { if (refcount) (*refcount)++; } NgMPI_Comm (NgMPI_Comm && c) : comm(c.comm), valid_comm(c.valid_comm), refcount(c.refcount), rank(c.rank), size(c.size) { c.refcount = nullptr; } ~NgMPI_Comm() { if (refcount) if (--(*refcount) == 0) MPI_Comm_free(&comm); } NgMPI_Comm & operator= (const NgMPI_Comm & c) { if (refcount) if (--(*refcount) == 0) MPI_Comm_free(&comm); refcount = c.refcount; if (refcount) (*refcount)++; comm = c.comm; valid_comm = c.valid_comm; size = c.size; rank = c.rank; return *this; } class InvalidCommException : public Exception { public: InvalidCommException() : Exception("Do not have a valid communicator") { ; } }; operator MPI_Comm() const { if (!valid_comm) throw InvalidCommException(); return comm; } int Rank() const { return rank; } int Size() const { return size; } void Barrier() const { if (size > 1) MPI_Barrier (comm); } /** --- blocking P2P --- **/ template())> void Send (T & val, int dest, int tag) const { MPI_Send (&val, 1, GetMPIType(), dest, tag, comm); } template())> void Recv (T & val, int src, int tag) const { MPI_Recv (&val, 1, GetMPIType(), src, tag, comm, MPI_STATUS_IGNORE); } /** --- non-blocking P2P --- **/ template())> MPI_Request ISend (T & val, int dest, int tag) const { MPI_Request request; MPI_Isend (&val, 1, GetMPIType(), dest, tag, comm, &request); return request; } template())> MPI_Request IRecv (T & val, int dest, int tag) const { MPI_Request request; MPI_Irecv (&val, 1, GetMPIType(), dest, tag, comm, &request); return request; } /** --- collectives --- **/ template ())> T Reduce (T d, const MPI_Op & op, int root = 0) const { if (size == 1) return d; T global_d; MPI_Reduce (&d, &global_d, 1, GetMPIType(), op, root, comm); return global_d; } template ())> T AllReduce (T d, const MPI_Op & op) const { if (size == 1) return d; T global_d; MPI_Allreduce ( &d, &global_d, 1, GetMPIType(), op, comm); return global_d; } template ())> void Bcast (T & s, int root = 0) const { if (size == 1) return ; MPI_Bcast (&s, 1, GetMPIType(), root, comm); } void Bcast (std::string & s, int root = 0) const { if (size == 1) return; int len = s.length(); Bcast (len, root); if (rank != 0) s.resize (len); MPI_Bcast (&s[0], len, MPI_CHAR, root, comm); } }; #else class MPI_Comm { int nr; public: MPI_Comm (int _nr = 0) : nr(_nr) { ; } operator int() const { return nr; } bool operator== (MPI_Comm c2) const { return nr == c2.nr; } }; static MPI_Comm MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 10000; typedef int MPI_Op; typedef int MPI_Request; enum { MPI_SUM = 0, MPI_MIN = 1, MPI_MAX = 2 }; class NgMPI_Comm { public: NgMPI_Comm () { ; } NgMPI_Comm (MPI_Comm _comm, bool owns = false) { ; } size_t Rank() const { return 0; } size_t Size() const { return 1; } void Barrier() const { ; } operator MPI_Comm() const { return MPI_Comm(); } template void Send( T & val, int dest, int tag) const { ; } template void MyMPI_Recv (T & val, int src, int tag) const { ; } template MPI_Request ISend (T & val, int dest, int tag) const { return 0; } template MPI_Request IRecv (T & val, int dest, int tag) const { return 0; } template T Reduce (T d, const MPI_Op & op, int root = 0) { return d; } template T AllReduce (T d, const MPI_Op & op) const { return d; } template void Bcast (T & s, int root = 0) const { ; } }; #endif } #endif netgen-6.2.1905/libsrc/core/profiler.hpp0000644000175000017500000001747613504650527016561 0ustar kurtkurt#ifndef NETGEN_CORE_PROFILER_HPP #define NETGEN_CORE_PROFILER_HPP #include #include #include #include "logging.hpp" #include "paje_trace.hpp" #include "utils.hpp" namespace ngcore { class NgProfiler { public: /// maximal number of timers enum { SIZE = 8*1024 }; struct TimerVal { TimerVal() = default; double tottime = 0.0; double starttime = 0.0; double flops = 0.0; double loads = 0.0; double stores = 0.0; long count = 0; std::string name = ""; int usedcounter = 0; }; NGCORE_API static std::vector timers; NGCORE_API static TTimePoint * thread_times; NGCORE_API static TTimePoint * thread_flops; NGCORE_API static std::shared_ptr logger; NGCORE_API static std::array dummy_thread_times; NGCORE_API static std::array dummy_thread_flops; private: NGCORE_API static std::string filename; public: NgProfiler(); ~NgProfiler(); NgProfiler(const NgProfiler &) = delete; NgProfiler(NgProfiler &&) = delete; void operator=(const NgProfiler &) = delete; void operator=(NgProfiler &&) = delete; static void SetFileName (const std::string & afilename) { filename = afilename; } /// create new timer, use integer index NGCORE_API static int CreateTimer (const std::string & name); NGCORE_API static void Reset (); /// start timer of index nr static void StartTimer (int nr) { timers[nr].starttime = WallTime(); timers[nr].count++; } /// stop timer of index nr static void StopTimer (int nr) { timers[nr].tottime += WallTime()-timers[nr].starttime; } static void StartThreadTimer (size_t nr, size_t tid) { thread_times[tid*SIZE+nr] -= GetTimeCounter(); // NOLINT } static void StopThreadTimer (size_t nr, size_t tid) { thread_times[tid*SIZE+nr] += GetTimeCounter(); // NOLINT } static void AddThreadFlops (size_t nr, size_t tid, size_t flops) { thread_flops[tid*SIZE+nr] += flops; // NOLINT } /// if you know number of flops, provide them to obtain the MFlop - rate static void AddFlops (int nr, double aflops) { timers[nr].flops += aflops; } static void AddLoads (int nr, double aloads) { timers[nr].loads += aloads; } static void AddStores (int nr, double astores) { timers[nr].stores += astores; } static int GetNr (const std::string & name) { for (int i = SIZE-1; i >= 0; i--) if (timers[i].name == name) return i; return -1; } static double GetTime (int nr) { return timers[nr].tottime; } static double GetTime (const std::string & name) { for (int i = SIZE-1; i >= 0; i--) if (timers[i].name == name) return GetTime (i); return 0; } static long int GetCounts (int nr) { return timers[nr].count; } static double GetFlops (int nr) { return timers[nr].flops; } /// change name static void SetName (int nr, const std::string & name) { timers[nr].name = name; } static std::string GetName (int nr) { return timers[nr].name; } /// print profile NGCORE_API static void Print (FILE * prof); class RegionTimer { int nr; public: /// start timer RegionTimer (int anr) : nr(anr) { NgProfiler::StartTimer(nr); } /// stop timer ~RegionTimer () { NgProfiler::StopTimer(nr); } RegionTimer() = delete; RegionTimer(const RegionTimer &) = delete; RegionTimer(RegionTimer &&) = delete; void operator=(const RegionTimer &) = delete; void operator=(RegionTimer &&) = delete; }; }; class NGCORE_API Timer { int timernr; int priority; public: Timer (const std::string & name, int apriority = 1) : priority(apriority) { timernr = NgProfiler::CreateTimer (name); } void SetName (const std::string & name) { NgProfiler::SetName (timernr, name); } void Start () { if (priority <= 2) NgProfiler::StartTimer (timernr); if (priority <= 1) if(trace) trace->StartTimer(timernr); } void Stop () { if (priority <= 2) NgProfiler::StopTimer (timernr); if (priority <= 1) if(trace) trace->StopTimer(timernr); } void AddFlops (double aflops) { if (priority <= 2) NgProfiler::AddFlops (timernr, aflops); } double GetTime () { return NgProfiler::GetTime(timernr); } long int GetCounts () { return NgProfiler::GetCounts(timernr); } double GetMFlops () { return NgProfiler::GetFlops(timernr) / NgProfiler::GetTime(timernr) * 1e-6; } operator int () { return timernr; } }; /** Timer object. Start / stop timer at constructor / destructor. */ class RegionTimer { Timer & timer; public: /// start timer RegionTimer (Timer & atimer) : timer(atimer) { timer.Start(); } /// stop timer ~RegionTimer () { timer.Stop(); } RegionTimer() = delete; RegionTimer(const RegionTimer &) = delete; RegionTimer(RegionTimer &&) = delete; void operator=(const RegionTimer &) = delete; void operator=(RegionTimer &&) = delete; }; class ThreadRegionTimer { size_t nr; size_t tid; public: /// start timer ThreadRegionTimer (size_t _nr, size_t _tid) : nr(_nr), tid(_tid) { NgProfiler::StartThreadTimer(nr, tid); } /// stop timer ~ThreadRegionTimer () { NgProfiler::StopThreadTimer(nr, tid); } ThreadRegionTimer() = delete; ThreadRegionTimer(ThreadRegionTimer &&) = delete; ThreadRegionTimer(const ThreadRegionTimer &) = delete; void operator=(const ThreadRegionTimer &) = delete; void operator=(ThreadRegionTimer &&) = delete; }; class RegionTracer { int nr; int thread_id; public: static constexpr int ID_JOB = PajeTrace::Task::ID_JOB; static constexpr int ID_NONE = PajeTrace::Task::ID_NONE; static constexpr int ID_TIMER = PajeTrace::Task::ID_TIMER; RegionTracer() = delete; RegionTracer(RegionTracer &&) = delete; RegionTracer(const RegionTracer &) = delete; void operator=(const RegionTracer &) = delete; void operator=(RegionTracer &&) = delete; /// start trace RegionTracer (int athread_id, int region_id, int id_type = ID_NONE, int additional_value = -1 ) : thread_id(athread_id) { if (trace) nr = trace->StartTask (athread_id, region_id, id_type, additional_value); } /// start trace with timer RegionTracer (int athread_id, Timer & timer, int additional_value = -1 ) : thread_id(athread_id) { if (trace) nr = trace->StartTask (athread_id, static_cast(timer), ID_TIMER, additional_value); } /// set user defined value void SetValue( int additional_value ) { if (trace) trace->SetTask( thread_id, nr, additional_value ); } /// stop trace ~RegionTracer () { if (trace) trace->StopTask (thread_id, nr); } }; // Helper function for timings // Run f() at least min_iterations times until max_time seconds elapsed // returns minimum runtime for a call of f() template double RunTiming( TFunc f, double max_time = 0.5, int min_iterations = 10 ) { // Make sure the whole test run does not exceed maxtime double tend = WallTime()+max_time; // warmup f(); double tres = std::numeric_limits::max(); int iteration = 0; while(WallTime() #include #include #include "archive.hpp" #include "exception.hpp" #include "ngcore_api.hpp" namespace ngcore { /** A symbol table. The symboltable provides a mapping from string identifiers to the generic type T. The strings are copied. Complexity by name access is linear, by index is constant. */ template class SymbolTable { std::vector names; std::vector data; public: using value_type = T; using reference = typename std::vector::reference; using const_reference = typename std::vector::const_reference; /// Creates a symboltable SymbolTable () = default; SymbolTable (const SymbolTable &) = default; SymbolTable (SymbolTable &&) noexcept = default; ~SymbolTable() = default; SymbolTable& operator=(const SymbolTable&) = default; SymbolTable& operator=(SymbolTable&&) = default; template auto DoArchive(Archive& ar) -> typename std::enable_if_t> { ar & names & data; } /// INDEX of symbol name, throws exception if unused size_t Index (const std::string & name) const { for (size_t i = 0; i < names.size(); i++) if (names[i] == name) return i; throw RangeException("SymbolTable", name); } /// Index of symbol name, returns -1 if unused int CheckIndex (const std::string & name) const { for (int i = 0; i < names.size(); i++) if (names[i] == name) return i; return -1; } /// number of identifiers size_t Size() const { return data.size(); } /// Returns reference to element. exception for unused identifier reference operator[] (const std::string & name) { return data[Index (name)]; } const_reference operator[] (const std::string & name) const { return data[Index (name)]; } /// Returns reference to i-th element, range check only in debug build reference operator[] (size_t i) { NETGEN_CHECK_RANGE(i, 0, data.size()); return data[i]; } /// Returns const reference to i-th element, range check only in debug build const_reference operator[] (size_t i) const { NETGEN_CHECK_RANGE(i, 0, data.size()); return data[i]; } /// Returns name of i-th element, range check only in debug build const std::string & GetName (size_t i) const { NETGEN_CHECK_RANGE(i, 0, names.size()); return names[i]; } /// Associates el to the string name, overrides if name is used void Set (const std::string & name, const T & el) { int i = CheckIndex (name); if (i >= 0) data[i] = el; else { data.push_back(el); names.push_back(name); } } bool Used (const std::string & name) const { return CheckIndex(name) >= 0; } /// Deletes symboltable inline void DeleteAll () { names.clear(); data.clear(); } // Adds all elements from other symboltable SymbolTable& Update(const SymbolTable& tbl2) { for (size_t i = 0; i < tbl2.Size(); i++) Set (tbl2.GetName(i), tbl2[i]); return *this; } }; template std::ostream & operator<< (std::ostream & ost, const SymbolTable & st) { for (int i = 0; i < st.Size(); i++) ost << st.GetName(i) << " : " << st[i] << std::endl; return ost; } } // namespace ngcore #endif // NETGEN_CORE_SYMBOLTABLE_HPP netgen-6.2.1905/libsrc/core/ngcore_api.hpp0000644000175000017500000000202713504650527017027 0ustar kurtkurt#ifndef NETGEN_CORE_NGCORE_API_HPP #define NETGEN_CORE_NGCORE_API_HPP #ifdef WIN32 #define NGCORE_API_EXPORT __declspec(dllexport) #define NGCORE_API_IMPORT __declspec(dllimport) #else #define NGCORE_API_EXPORT __attribute__((visibility("default"))) #define NGCORE_API_IMPORT __attribute__((visibility("default"))) #endif #ifdef NGCORE_EXPORTS #define NGCORE_API NGCORE_API_EXPORT #else #define NGCORE_API NGCORE_API_IMPORT #endif #ifdef __INTEL_COMPILER #ifdef WIN32 #define NETGEN_INLINE __forceinline inline #define NETGEN_LAMBDA_INLINE #else #define NETGEN_INLINE __forceinline inline #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) #endif #else #ifdef __GNUC__ #define NETGEN_INLINE __attribute__ ((__always_inline__)) inline #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) #define NETGEN_VLA #else #define NETGEN_INLINE inline #define NETGEN_LAMBDA_INLINE #endif #endif #endif // NETGEN_CORE_NGCORE_API_HPP netgen-6.2.1905/libsrc/core/ngcore.hpp0000644000175000017500000000041513504650527016175 0ustar kurtkurt#ifndef NETGEN_CORE_NGCORE_HPP #define NETGEN_CORE_NGCORE_HPP #include "archive.hpp" #include "exception.hpp" #include "logging.hpp" #include "profiler.hpp" #include "symboltable.hpp" #include "version.hpp" #include "mpi_wrapper.hpp" #endif // NETGEN_CORE_NGCORE_HPP netgen-6.2.1905/libsrc/core/version.hpp0000644000175000017500000000607313504650527016413 0ustar kurtkurt#ifndef NETGEN_CORE_VERSION_HPP #define NETGEN_CORE_VERSION_HPP #include #include #include #include "ngcore_api.hpp" namespace ngcore { class VersionInfo { private: size_t mayor_{}, minor_{}, release{}, patch{}; std::string git_hash{}; public: VersionInfo() = default; VersionInfo(std::string vstring) { minor_ = release = patch = 0; git_hash = ""; if(vstring.substr(0,1) == "v") vstring = vstring.substr(1,vstring.size()-1); auto dot = vstring.find('.'); mayor_ = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); if(!vstring.empty()) { dot = vstring.find('.'); minor_ = std::stoi(vstring.substr(0,dot)); if (dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); if(!vstring.empty()) { dot = vstring.find('-'); release = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1,vstring.size()-dot-1); if(!vstring.empty()) { dot = vstring.find('-'); patch = std::stoi(vstring.substr(0,dot)); if(dot == size_t(-1)) vstring = ""; else vstring = vstring.substr(dot+1, vstring.size()-dot-1); if(!vstring.empty()) git_hash = vstring; } } } } VersionInfo(const char* cstr) : VersionInfo(std::string(cstr)) { } std::string to_string() const { std::string vstring = "v" + std::to_string(mayor_); if(minor_ || release || patch || !git_hash.empty()) { vstring += "." + std::to_string(minor_); if(release || patch || !git_hash.empty()) { vstring += "." + std::to_string(release); if(patch || !git_hash.empty()) { vstring += "-" + std::to_string(patch); if(!git_hash.empty()) vstring += "-" + git_hash; } } } return vstring; } bool operator <(const VersionInfo& other) const { return std::tie(mayor_, minor_, release, patch) < std::tie(other.mayor_, other.minor_, other.release, other.patch); } bool operator ==(const VersionInfo& other) const { return mayor_ == other.mayor_ && minor_ == other.minor_ && release == other.release && patch == other.patch; } bool operator >(const VersionInfo& other) const { return other < (*this); } bool operator <=(const VersionInfo& other) const { return !((*this) > other); } bool operator >=(const VersionInfo& other) const { return !((*this) < other); } }; inline std::ostream& operator << (std::ostream& ost, const VersionInfo& version) { return ost << version.to_string(); } } // namespace ngcore #endif // NETGEN_CORE_VERSION_HPP netgen-6.2.1905/libsrc/core/python_ngcore.cpp0000644000175000017500000000245413504650527017576 0ustar kurtkurt #include #include "logging.hpp" namespace py = pybind11; using namespace ngcore; PYBIND11_MODULE(pyngcore, m) // NOLINT { py::enum_(m, "LOG_LEVEL", "Logging level") .value("Trace", level::trace) .value("Debug", level::debug) .value("Info", level::info) .value("Warn", level::warn) .value("Error", level::err) .value("Critical", level::critical) .value("Off", level::off); m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="", "Set logging level, if name is given only to the specific logger, else set the global logging level"); m.def("AddFileSink", &AddFileSink, py::arg("filename"), py::arg("level"), py::arg("logger")="", "Add File sink, either only to logger specified or globally to all loggers"); m.def("AddConsoleSink", &AddConsoleSink, py::arg("level"), py::arg("logger")="", "Add console output for specific logger or all if none given"); m.def("ClearLoggingSinks", &ClearLoggingSinks, py::arg("logger")="", "Clear sinks of specific logger, or all if none given"); m.def("FlushOnLoggingLevel", &FlushOnLoggingLevel, py::arg("level"), py::arg("logger")="", "Flush every message with level at least `level` for specific logger or all loggers if none given."); } netgen-6.2.1905/libsrc/core/exception.hpp0000644000175000017500000000601113504650527016714 0ustar kurtkurt#ifndef NETGEN_CORE_EXCEPTION_HPP #define NETGEN_CORE_EXCEPTION_HPP #include // for stringstream #include // for exception #include // for string #include "ngcore_api.hpp" // for NGCORE_API namespace ngcore { // Exception for code that shouldn't be executed class NGCORE_API UnreachableCodeException : public std::exception { const char* what() const noexcept override { return "Shouldn't get here, something went wrong!"; } }; // Default exception class class NGCORE_API Exception : public std::exception { /// a verbal description of the exception std::string m_what; public: Exception() = default; Exception(const Exception&) = default; Exception(Exception&&) = default; Exception(const std::string& s) : m_what(s) {} Exception(const char* s) : m_what(s) {} ~Exception() override = default; Exception& operator =(const Exception&) = default; Exception& operator =(Exception&&) noexcept = default; /// append string to description Exception & Append (const std::string & s) { m_what += s; return *this; } /// append string to description Exception & Append (const char * s) { m_what += s; return *this; } /// verbal description of exception const std::string & What() const { return m_what; } /// implement virtual function of std::exception const char* what() const noexcept override { return m_what.c_str(); } }; // Out of Range exception class NGCORE_API RangeException : public Exception { public: /// where it occurs, index, minimal and maximal indices RangeException (const std::string & where, int ind, int imin, int imax) : Exception("") { std::stringstream str; str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n"; Append (str.str()); } template RangeException(const std::string& where, const T& value) { std::stringstream str; str << where << " called with wrong value " << value << "\n"; Append(str.str()); } }; // Exception used if no simd implementation is available to fall back to standard evaluation class NGCORE_API ExceptionNOSIMD : public Exception { public: using Exception::Exception; }; } // namespace ngcore #define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x #define NETGEN_CORE_NGEXEPTION_STR(x) NETGEN_CORE_NGEXEPTION_STR_HELPER(x) // Convenience macro to append file name and line of exception origin to the string #define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s)) #ifdef NETGEN_ENABLE_CHECK_RANGE #define NETGEN_CHECK_RANGE(value, min, max) \ { if ((value)<(min) || (value)>=(max)) \ throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", (value), (min), (max)); } #else // NETGEN_ENABLE_CHECK_RANGE #define NETGEN_CHECK_RANGE(value, min, max) #endif // NETGEN_ENABLE_CHECK_RANGE #endif // NETGEN_CORE_EXCEPTION_HPP netgen-6.2.1905/libsrc/core/type_traits.hpp0000644000175000017500000000156213504650527017273 0ustar kurtkurt#ifndef NETGEN_CORE_TYPE_TRAITS_HPP #define NETGEN_CORE_TYPE_TRAITS_HPP #include #include namespace ngcore { namespace detail { template struct _BoolArray{}; template constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; // NOLINT template struct is_any_pointer_impl : std::false_type {}; template struct is_any_pointer_impl : std::true_type {}; template struct is_any_pointer_impl> : std::true_type {}; template struct is_any_pointer_impl> : std::true_type {}; template constexpr bool is_any_pointer = is_any_pointer_impl::value; } // namespace detail } // namespace ngcore #endif // NETGEN_CORE_TYPE_TRAITS_HPP netgen-6.2.1905/libsrc/core/utils.cpp0000644000175000017500000000230113504650527016047 0ustar kurtkurt#include "utils.hpp" #include "logging.hpp" #ifndef WIN32 #include #endif #include namespace ngcore { // parallel netgen int id = 0, ntasks = 1; #ifdef WIN32 // windows does demangling in typeid(T).name() NGCORE_API std::string Demangle(const char* typeinfo) { return typeinfo; } #else NGCORE_API std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, nullptr, nullptr, &status); } #endif double ticks_per_second = [] () noexcept { auto tick_start = GetTimeCounter(); double tstart = WallTime(); double tend = WallTime()+0.001; // wait for 1ms and compare wall time with time counter while(WallTime()(tick_end-tick_start)/(tend-tstart); }(); const std::chrono::time_point wall_time_start = TClock::now(); } // namespace ngcore netgen-6.2.1905/libsrc/core/utils.hpp0000644000175000017500000000340613504650527016063 0ustar kurtkurt#ifndef NETGEN_CORE_UTILS_HPP #define NETGEN_CORE_UTILS_HPP #include #include #include #include #include #ifdef WIN32 #include // for __rdtsc() CPU time step counter #else #include // for __rdtsc() CPU time step counter #endif // WIN32 #include "ngcore_api.hpp" // for NGCORE_API namespace ngcore { // MPI rank, nranks TODO: Rename extern NGCORE_API int id, ntasks; NGCORE_API std::string Demangle(const char* typeinfo); #if defined(__GNUC__) inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); } inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); } #else inline bool likely (bool x) { return x; } inline bool unlikely (bool x) { return x; } #endif using TClock = std::chrono::system_clock; extern NGCORE_API const std::chrono::time_point wall_time_start; // Time in seconds since program start inline double WallTime () noexcept { std::chrono::time_point now = TClock::now(); std::chrono::duration elapsed_seconds = now-wall_time_start; return elapsed_seconds.count(); } // High precision clock counter register using TTimePoint = size_t; extern NGCORE_API double ticks_per_second; inline TTimePoint GetTimeCounter() noexcept { return TTimePoint(__rdtsc()); } template inline std::string ToString (const T& t) { std::stringstream ss; ss << t; return ss.str(); } template std::ostream& operator << (std::ostream& ost, const std::map& map) { for(auto& val : map) ost << "\n" << val.first << ": " << val.second; return ost; } } // namespace ngcore #endif // NETGEN_CORE_UTILS_HPP netgen-6.2.1905/libsrc/core/archive.hpp0000644000175000017500000011171213504650527016344 0ustar kurtkurt#ifndef NETGEN_CORE_ARCHIVE_HPP #define NETGEN_CORE_ARCHIVE_HPP #include // for array #include // for complex #include // for size_t, strlen #include // for ifstream, ofstream #include // for function #include // for map #include // for shared_ptr #include // for string #include // for declval, enable_if_t, false_type, is_co... #include // for type_info #include // for move, swap, pair #include // for vector #include "exception.hpp" // for UnreachableCodeException, Exception #include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API #include "type_traits.hpp" // for all_of_tmpl #include "utils.hpp" // for Demangle, unlikely #include "version.hpp" // for VersionInfo #ifdef NETGEN_PYTHON #include #endif // NETGEN_PYTHON namespace ngcore { // Libraries using this archive can store their version here to implement backwards compatibility NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library); NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version); class NGCORE_API Archive; namespace detail { // create new pointer of type T if it is default constructible, else throw template T* constructIfPossible_impl(Rest... /*unused*/) { throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } template::value>> T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT template T* constructIfPossible() { return constructIfPossible_impl(int{}); } //Type trait to check if a class implements a 'void DoArchive(Archive&)' function template struct has_DoArchive { private: template static constexpr auto check(T2*) -> typename std::is_same().DoArchive(std::declval())),void>::type; template static constexpr std::false_type check(...); using type = decltype(check(nullptr)); // NOLINT public: NGCORE_API static constexpr bool value = type::value; }; // Check if class is archivable template struct is_Archivable_struct { private: template static constexpr auto check(T2*) -> typename std::is_same() & std::declval()),Archive&>::type; template static constexpr std::false_type check(...); using type = decltype(check(nullptr)); // NOLINT public: NGCORE_API static constexpr bool value = type::value; }; struct ClassArchiveInfo { // create new object of this type and return a void* pointer that is points to the location // of the (base)class given by type_info std::function creator; // This caster takes a void* pointer to the type stored in this info and casts it to a // void* pointer pointing to the (base)class type_info std::function upcaster; // This caster takes a void* pointer to the (base)class type_info and returns void* pointing // to the type stored in this info std::function downcaster; }; } // namespace detail template constexpr bool is_archivable = detail::is_Archivable_struct::value; // Base Archive class class NGCORE_API Archive { const bool is_output; // how many different shared_ptr/pointer have been (un)archived int shared_ptr_count{0}, ptr_count{0}; // maps for archived shared pointers and pointers std::map shared_ptr2nr{}, ptr2nr{}; // vectors for storing the unarchived (shared) pointers std::vector> nr2shared_ptr{}; std::vector nr2ptr{}; protected: bool shallow_to_python = false; std::map version_map = GetLibraryVersions(); std::shared_ptr logger = GetLogger("Archive"); public: Archive() = delete; Archive(const Archive&) = delete; Archive(Archive&&) = delete; Archive (bool ais_output) : is_output(ais_output) { ; } virtual ~Archive() { ; } // If the object is pickled, all shallow archived objects will be pickled as a list, // instead of written as a binary archive. This allows pickle to serialize every object only // once and put them together correctly afterwards. Therefore all objects that may live in // Python should be archived using this Shallow function. If Shallow is called from C++ code // it archives the object normally. template Archive& Shallow(T& val) { static_assert(detail::is_any_pointer, "ShallowArchive must be given pointer type!"); #ifdef NETGEN_PYTHON if(shallow_to_python) { if(is_output) ShallowOutPython(pybind11::cast(val)); else val = pybind11::cast(ShallowInPython()); } else #endif // NETGEN_PYTHON *this & val; return *this; } #ifdef NETGEN_PYTHON virtual void ShallowOutPython(const pybind11::object& /*unused*/) { throw UnreachableCodeException{}; } virtual pybind11::object ShallowInPython() { throw UnreachableCodeException{}; } #endif // NETGEN_PYTHON Archive& operator=(const Archive&) = delete; Archive& operator=(Archive&&) = delete; bool Output () const { return is_output; } bool Input () const { return !is_output; } const VersionInfo& GetVersion(const std::string& library) { return version_map[library]; } // only used for PyArchive virtual void NeedsVersion(const std::string& /*unused*/, const std::string& /*unused*/) {} // Pure virtual functions that have to be implemented by In-/OutArchive virtual Archive & operator & (double & d) = 0; virtual Archive & operator & (int & i) = 0; virtual Archive & operator & (long & i) = 0; virtual Archive & operator & (size_t & i) = 0; virtual Archive & operator & (short & i) = 0; virtual Archive & operator & (unsigned char & i) = 0; virtual Archive & operator & (bool & b) = 0; virtual Archive & operator & (std::string & str) = 0; virtual Archive & operator & (char *& str) = 0; Archive & operator & (VersionInfo & version) { if(Output()) (*this) << version.to_string(); else { std::string s; (*this) & s; version = VersionInfo(s); } return *this; } // Archive std classes ================================================ template Archive& operator & (std::complex& c) { if(Output()) (*this) << c.real() << c.imag(); else { T tmp; (*this) & tmp; c.real(tmp); (*this) & tmp; c.imag(tmp); } return (*this); } template Archive& operator & (std::vector& v) { size_t size; if(Output()) size = v.size(); (*this) & size; if(Input()) v.resize(size); Do(&v[0], size); return (*this); } // archive implementation for enums template auto operator & (T& val) -> std::enable_if_t::value, Archive&> { int enumval; if(Output()) enumval = int(val); *this & enumval; if(Input()) val = T(enumval); return *this; } // vector has special implementation (like a bitarray) therefore // it needs a special overload (this could probably be more efficient, but we // don't use it that often anyway) Archive& operator& (std::vector& v) { logger->debug("In special archive for std::vector"); size_t size; if(Output()) size = v.size(); (*this) & size; if(Input()) { v.resize(size); bool b; for(size_t i=0; i Archive& operator& (std::map& map) { if(Output()) { (*this) << size_t(map.size()); for(auto& pair : map) (*this) << pair.first << pair.second; } else { size_t size = 0; (*this) & size; T1 key; T2 val; for(size_t i = 0; i < size; i++) { T1 key; T2 val; (*this) & key & val; map[key] = val; } } return (*this); } // Archive arrays ===================================================== // this functions can be overloaded in Archive implementations for more efficiency template >> Archive & Do (T * data, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT virtual Archive & Do (double * d, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; // NOLINT virtual Archive & Do (int * i, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (long * i, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (size_t * i, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (short * i, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (unsigned char * i, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT virtual Archive & Do (bool * b, size_t n) { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT // Archive a class implementing a (void DoArchive(Archive&)) method ======= template::value>> Archive& operator & (T& val) { val.DoArchive(*this); return *this; } // Archive shared_ptrs ================================================= template Archive& operator & (std::shared_ptr& ptr) { if(Output()) { logger->debug("Store shared ptr of type {}", Demangle(typeid(T).name())); // save -2 for nullptr if(!ptr) { logger->debug("Storing nullptr"); return (*this) << -2; } void* reg_ptr = ptr.get(); bool neededDowncast = false; // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { logger->debug("Typids are different: {} vs {}", Demangle(typeid(T).name()), Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*ptr).name()) + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information if(reg_ptr != static_cast(ptr.get())) { logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); neededDowncast = true; } } auto pos = shared_ptr2nr.find(reg_ptr); // if not found store -1 and the pointer if(pos == shared_ptr2nr.end()) { logger->debug("Didn't find the shared_ptr, create new registry entry at {}", shared_ptr_count); auto p = ptr.get(); (*this) << -1; (*this) & neededDowncast & p; // if we did downcast we store the true type as well if(neededDowncast) (*this) << Demangle(typeid(*ptr).name()); shared_ptr2nr[reg_ptr] = shared_ptr_count++; return *this; } // if found store the position and if it has to be downcasted and how logger->debug("Found shared_ptr at position {}", pos->second); (*this) << pos->second << neededDowncast; if(neededDowncast) (*this) << Demangle(typeid(*ptr).name()); } else // Input { logger->debug("Reading shared_ptr of type {}", Demangle(typeid(T).name())); int nr; (*this) & nr; // -2 restores a nullptr if(nr == -2) { logger->debug("Reading a nullptr"); ptr = nullptr; return *this; } // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it if (nr == -1) { logger->debug("Createing new shared_ptr"); T* p = nullptr; bool neededDowncast; (*this) & neededDowncast & p; ptr = std::shared_ptr(p); // if we did downcast we need to store a shared_ptr to the true object if(neededDowncast) { logger->debug("Shared pointer needed downcasting"); std::string name; (*this) & name; auto info = GetArchiveRegister(name); // for this we use an aliasing constructor to create a shared pointer sharing lifetime // with our shared ptr, but pointing to the true object nr2shared_ptr.push_back(std::shared_ptr(std::static_pointer_cast(ptr), info.downcaster(typeid(T), ptr.get()))); } else { logger->debug("Shared pointer didn't need downcasting"); nr2shared_ptr.push_back(ptr); } } else { logger->debug("Reading already existing pointer at entry {}", nr); auto other = nr2shared_ptr[nr]; bool neededDowncast; (*this) & neededDowncast; if(neededDowncast) { logger->debug("Shared pointer needed pointer downcast"); // if there was a downcast we can expect the class to be registered (since archiving // wouldn't have worked else) std::string name; (*this) & name; auto info = GetArchiveRegister(name); // same trick as above, create a shared ptr sharing lifetime with // the shared_ptr in the register, but pointing to our object ptr = std::static_pointer_cast(std::shared_ptr(other, info.upcaster(typeid(T), other.get()))); } else { logger->debug("Shared pointer didn't need pointer casts"); ptr = std::static_pointer_cast(other); } } } return *this; } // Archive pointers ======================================================= template Archive & operator& (T *& p) { if (Output()) { logger->debug("Store pointer of type {}",Demangle(typeid(T).name())); // if the pointer is null store -2 if (!p) { logger->debug("Storing nullptr"); return (*this) << -2; } auto reg_ptr = static_cast(p); if(typeid(T) != typeid(*p)) { logger->debug("Typeids are different: {} vs {}", Demangle(typeid(T).name()), Demangle(typeid(*p).name())); if(!IsRegistered(Demangle(typeid(*p).name()))) throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); if(reg_ptr != static_cast(p)) { logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); } } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) { logger->debug("Didn't find pointer, create new registry entry at {}", ptr_count); ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) if (std::is_constructible::value) { logger->debug("Store standard class pointer (no virt. inh,...)"); return (*this) << -1 & (*p); } else throw Exception(std::string("Archive error: Class ") + Demangle(typeid(*p).name()) + " does not provide a default constructor!"); else { // if a pointer to a base class is archived, the class hierarchy must be registered // to avoid compile time issues we allow this behaviour only for "our" classes that // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it if(!IsRegistered(Demangle(typeid(*p).name()))) throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); logger->debug("Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } } else { (*this) & pos->second; bool downcasted = !(reg_ptr == static_cast(p) ); logger->debug("Store a the existing position in registry at {}", pos->second); logger->debug("Pointer {} downcasting", downcasted ? "needs" : "doesn't need"); // store if the class has been downcasted and the name (*this) << downcasted << Demangle(typeid(*p).name()); } } else { logger->debug("Reading pointer of type {}", Demangle(typeid(T).name())); int nr; (*this) & nr; if (nr == -2) // restore a nullptr { logger->debug("Loading a nullptr"); p = nullptr; } else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { logger->debug("Load a new pointer to a simple class"); p = detail::constructIfPossible(); nr2ptr.push_back(p); (*this) & *p; } else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { logger->debug("Load a new pointer to a potentially more complicated class " "(allows for multiple/virtual inheritance,...)"); // As stated above, we want this special behaviour only for our classes that implement DoArchive std::string name; (*this) & name; logger->debug("Name = {}", name); auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) p = static_cast(info.creator(typeid(T))); // we store the downcasted pointer (to be able to find it again from // another class in a multiple inheritance tree) nr2ptr.push_back(info.downcaster(typeid(T),p)); (*this) & *p; } else { logger->debug("Restoring pointer to already existing object at registry position {}", nr); bool downcasted; std::string name; (*this) & downcasted & name; logger->debug("{} object of type {}", downcasted ? "Downcasted" : "Not downcasted", name); if(downcasted) { // if the class has been downcasted we can assume it is in the register auto info = GetArchiveRegister(name); p = static_cast(info.upcaster(typeid(T), nr2ptr[nr])); } else p = static_cast(nr2ptr[nr]); } } return *this; } // const ptr template Archive& operator &(const T*& t) { return (*this) & const_cast(t); // NOLINT } // Write a read only variable template Archive & operator << (const T & t) { T ht(t); (*this) & ht; return *this; } virtual void FlushBuffer() {} protected: static std::map& GetLibraryVersions(); private: template friend class RegisterClassForArchive; // Returns ClassArchiveInfo of Demangled typeid static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname); // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of // RegisterClassForArchive static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info); static bool IsRegistered(const std::string& classname); // Helper class for up-/downcasting template struct Caster{}; template struct Caster { static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/) { throw Exception("Upcast not successful, some classes are not registered properly for archiving!"); } static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/) { throw Exception("Downcast not successful, some classes are not registered properly for archiving!"); } }; template struct Caster { static void* tryUpcast(const std::type_info& ti, T* p) { try { return GetArchiveRegister(Demangle(typeid(B1).name())). upcaster(ti, static_cast(dynamic_cast(p))); } catch(const Exception&) { return Caster::tryUpcast(ti, p); } } static void* tryDowncast(const std::type_info& ti, void* p) { if(typeid(B1) == ti) return dynamic_cast(static_cast(p)); try { return dynamic_cast(static_cast(GetArchiveRegister(Demangle(typeid(B1).name())). downcaster(ti, p))); } catch(const Exception&) { return Caster::tryDowncast(ti, p); } } }; }; template class RegisterClassForArchive { public: RegisterClassForArchive() { static_assert(detail::all_of_tmpl::value...>, "Variadic template arguments must be base classes of T"); detail::ClassArchiveInfo info {}; info.creator = [this,&info](const std::type_info& ti) -> void* { return typeid(T) == ti ? detail::constructIfPossible() : Archive::Caster::tryUpcast(ti, detail::constructIfPossible()); }; info.upcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, static_cast(p)); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info); } }; // BinaryOutArchive ====================================================================== class NGCORE_API BinaryOutArchive : public Archive { static constexpr size_t BUFFERSIZE = 1024; std::array buffer{}; size_t ptr = 0; protected: std::shared_ptr stream; public: BinaryOutArchive() = delete; BinaryOutArchive(const BinaryOutArchive&) = delete; BinaryOutArchive(BinaryOutArchive&&) = delete; BinaryOutArchive(std::shared_ptr&& astream) : Archive(true), stream(std::move(astream)) { } BinaryOutArchive(const std::string& filename) : BinaryOutArchive(std::make_shared(filename)) {} ~BinaryOutArchive () override { FlushBuffer(); } BinaryOutArchive& operator=(const BinaryOutArchive&) = delete; BinaryOutArchive& operator=(BinaryOutArchive&&) = delete; using Archive::operator&; Archive & operator & (double & d) override { return Write(d); } Archive & operator & (int & i) override { return Write(i); } Archive & operator & (short & i) override { return Write(i); } Archive & operator & (long & i) override { return Write(i); } Archive & operator & (size_t & i) override { return Write(i); } Archive & operator & (unsigned char & i) override { return Write(i); } Archive & operator & (bool & b) override { return Write(b); } Archive & operator & (std::string & str) override { int len = str.length(); (*this) & len; FlushBuffer(); if(len) stream->write (&str[0], len); return *this; } Archive & operator & (char *& str) override { long len = str ? static_cast(strlen (str)) : -1; (*this) & len; FlushBuffer(); if(len > 0) stream->write (&str[0], len); // NOLINT return *this; } void FlushBuffer() override { if (ptr > 0) { stream->write(&buffer[0], ptr); ptr = 0; } } private: template Archive & Write (T x) { if (unlikely(ptr > BUFFERSIZE-sizeof(T))) { stream->write(&buffer[0], ptr); *reinterpret_cast(&buffer[0]) = x; // NOLINT ptr = sizeof(T); return *this; } *reinterpret_cast(&buffer[ptr]) = x; // NOLINT ptr += sizeof(T); return *this; } }; // BinaryInArchive ====================================================================== class NGCORE_API BinaryInArchive : public Archive { protected: std::shared_ptr stream; public: BinaryInArchive (std::shared_ptr&& astream) : Archive(false), stream(std::move(astream)) { } BinaryInArchive (const std::string& filename) : BinaryInArchive(std::make_shared(filename)) { ; } using Archive::operator&; Archive & operator & (double & d) override { Read(d); return *this; } Archive & operator & (int & i) override { Read(i); return *this; } Archive & operator & (short & i) override { Read(i); return *this; } Archive & operator & (long & i) override { Read(i); return *this; } Archive & operator & (size_t & i) override { Read(i); return *this; } Archive & operator & (unsigned char & i) override { Read(i); return *this; } Archive & operator & (bool & b) override { Read(b); return *this; } Archive & operator & (std::string & str) override { int len; (*this) & len; str.resize(len); if(len) stream->read(&str[0], len); // NOLINT return *this; } Archive & operator & (char *& str) override { long len; (*this) & len; if(len == -1) str = nullptr; else { str = new char[len+1]; // NOLINT stream->read(&str[0], len); // NOLINT str[len] = '\0'; // NOLINT } return *this; } Archive & Do (double * d, size_t n) override { stream->read(reinterpret_cast(d), n*sizeof(double)); return *this; } // NOLINT Archive & Do (int * i, size_t n) override { stream->read(reinterpret_cast(i), n*sizeof(int)); return *this; } // NOLINT Archive & Do (size_t * i, size_t n) override { stream->read(reinterpret_cast(i), n*sizeof(size_t)); return *this; } // NOLINT private: template inline void Read(T& val) { stream->read(reinterpret_cast(&val), sizeof(T)); } // NOLINT }; // TextOutArchive ====================================================================== class NGCORE_API TextOutArchive : public Archive { protected: std::shared_ptr stream; public: TextOutArchive (std::shared_ptr&& astream) : Archive(true), stream(std::move(astream)) { } TextOutArchive (const std::string& filename) : TextOutArchive(std::make_shared(filename)) { } using Archive::operator&; Archive & operator & (double & d) override { *stream << d << '\n'; return *this; } Archive & operator & (int & i) override { *stream << i << '\n'; return *this; } Archive & operator & (short & i) override { *stream << i << '\n'; return *this; } Archive & operator & (long & i) override { *stream << i << '\n'; return *this; } Archive & operator & (size_t & i) override { *stream << i << '\n'; return *this; } Archive & operator & (unsigned char & i) override { *stream << int(i) << '\n'; return *this; } Archive & operator & (bool & b) override { *stream << (b ? 't' : 'f') << '\n'; return *this; } Archive & operator & (std::string & str) override { int len = str.length(); *stream << len << '\n'; if(len) { stream->write(&str[0], len); // NOLINT *stream << '\n'; } return *this; } Archive & operator & (char *& str) override { long len = str ? static_cast(strlen (str)) : -1; *this & len; if(len > 0) { stream->write (&str[0], len); // NOLINT *stream << '\n'; } return *this; } }; // TextInArchive ====================================================================== class NGCORE_API TextInArchive : public Archive { protected: std::shared_ptr stream; public: TextInArchive (std::shared_ptr&& astream) : Archive(false), stream(std::move(astream)) { } TextInArchive (const std::string& filename) : TextInArchive(std::make_shared(filename)) {} using Archive::operator&; Archive & operator & (double & d) override { *stream >> d; return *this; } Archive & operator & (int & i) override { *stream >> i; return *this; } Archive & operator & (short & i) override { *stream >> i; return *this; } Archive & operator & (long & i) override { *stream >> i; return *this; } Archive & operator & (size_t & i) override { *stream >> i; return *this; } Archive & operator & (unsigned char & i) override { int _i; *stream >> _i; i = _i; return *this; } Archive & operator & (bool & b) override { char c; *stream >> c; b = (c=='t'); return *this; } Archive & operator & (std::string & str) override { int len; *stream >> len; char ch; stream->get(ch); // '\n' str.resize(len); if(len) stream->get(&str[0], len+1, '\0'); return *this; } Archive & operator & (char *& str) override { long len; (*this) & len; char ch; if(len == -1) { str = nullptr; return (*this); } str = new char[len+1]; // NOLINT if(len) { stream->get(ch); // \n stream->get(&str[0], len+1, '\0'); // NOLINT } str[len] = '\0'; // NOLINT return *this; } }; #ifdef NETGEN_PYTHON template class PyArchive : public ARCHIVE { private: pybind11::list lst; size_t index = 0; std::map version_needed; protected: using ARCHIVE::stream; using ARCHIVE::version_map; using ARCHIVE::logger; using ARCHIVE::GetLibraryVersions; public: PyArchive(const pybind11::object& alst = pybind11::none()) : ARCHIVE(std::make_shared()), lst(alst.is_none() ? pybind11::list() : pybind11::cast(alst)) { ARCHIVE::shallow_to_python = true; if(Input()) { stream = std::make_shared (pybind11::cast(lst[pybind11::len(lst)-1])); *this & version_needed; logger->debug("versions needed for unpickling = {}", version_needed); for(auto& libversion : version_needed) if(libversion.second > GetLibraryVersion(libversion.first)) throw Exception("Error in unpickling data:\nLibrary " + libversion.first + " must be at least " + libversion.second.to_string()); stream = std::make_shared (pybind11::cast(lst[pybind11::len(lst)-2])); *this & version_map; stream = std::make_shared (pybind11::cast(lst[pybind11::len(lst)-3])); } } void NeedsVersion(const std::string& library, const std::string& version) override { if(Output()) { logger->debug("Need version {} of library {}.", version, library); version_needed[library] = version_needed[library] > version ? version_needed[library] : version; } } using ARCHIVE::Output; using ARCHIVE::Input; using ARCHIVE::FlushBuffer; using ARCHIVE::operator&; using ARCHIVE::operator<<; using ARCHIVE::GetVersion; void ShallowOutPython(const pybind11::object& val) override { lst.append(val); } pybind11::object ShallowInPython() override { return lst[index++]; } pybind11::list WriteOut() { FlushBuffer(); lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); stream = std::make_shared(); *this & GetLibraryVersions(); FlushBuffer(); lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); stream = std::make_shared(); logger->debug("Writeout version needed = {}", version_needed); *this & version_needed; FlushBuffer(); lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); return lst; } }; template auto NGSPickle() { return pybind11::pickle([](T* self) { PyArchive ar; ar & self; auto output = pybind11::make_tuple(ar.WriteOut()); GetLogger("Archive")->trace("Pickling output for object of type {} = {}", Demangle(typeid(T).name()), std::string(pybind11::str(output))); return output; }, [](const pybind11::tuple & state) { T* val = nullptr; GetLogger("Archive")->trace("State for unpickling of object of type {} = {}", Demangle(typeid(T).name()), std::string(pybind11::str(state[0]))); PyArchive ar(state[0]); ar & val; return val; }); } #endif // NETGEN_PYTHON } // namespace ngcore #endif // NETGEN_CORE_ARCHIVE_HPP netgen-6.2.1905/libsrc/core/archive.cpp0000644000175000017500000000306713504650527016342 0ustar kurtkurt #include "archive.hpp" #ifndef WIN32 #include #endif namespace ngcore { // clang-tidy should ignore this static object static std::map library_versions; // NOLINT std::map& Archive :: GetLibraryVersions() { return library_versions; } const VersionInfo& GetLibraryVersion(const std::string& library) { return library_versions[library]; } void SetLibraryVersion(const std::string& library, const VersionInfo& version) { library_versions[library] = version; } // clang-tidy should ignore this static object static std::unique_ptr> type_register; // NOLINT const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) { if(type_register == nullptr) type_register = std::make_unique>(); return (*type_register)[classname]; } void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info) { if(type_register == nullptr) type_register = std::make_unique>(); (*type_register)[classname] = info; } bool Archive :: IsRegistered(const std::string& classname) { if(type_register == nullptr) type_register = std::make_unique>(); return type_register->count(classname) != 0; } } // namespace ngcore netgen-6.2.1905/libsrc/core/paje_trace.cpp0000644000175000017500000006641713504650527017026 0ustar kurtkurt#include #include #include #include #include #include #include "archive.hpp" // for Demangle #include "paje_trace.hpp" #include "profiler.hpp" extern const char *header; namespace ngcore { // Produce no traces by default size_t PajeTrace::max_tracefile_size = 0; // If true, produce variable counting active threads // increases trace by a factor of two bool PajeTrace::trace_thread_counter = true; bool PajeTrace::trace_threads = true; PajeTrace :: PajeTrace(int anthreads, std::string aname) { start_time = GetTimeCounter(); nthreads = anthreads; tracefile_name = std::move(aname); int bytes_per_event=33; max_num_events_per_thread = std::min( static_cast(std::numeric_limits::max()), max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); if(max_num_events_per_thread>0) { logger->info( "Tracefile size = {}MB", max_tracefile_size/1024/1024); logger->info( "Tracing {} events per thread", max_num_events_per_thread); } tasks.resize(nthreads); int reserve_size = std::min(1000000U, max_num_events_per_thread); for(auto & t : tasks) t.reserve(reserve_size); links.resize(nthreads); for(auto & l : links) l.reserve(reserve_size); jobs.reserve(reserve_size); timer_events.reserve(reserve_size); tracing_enabled = true; } PajeTrace :: ~PajeTrace() { if(!tracefile_name.empty()) Write(tracefile_name); } void PajeTrace::StopTracing() { if(tracing_enabled && max_num_events_per_thread>0) { logger->warn("Maximum number of traces reached, tracing is stopped now."); } tracing_enabled = false; } class PajeFile { public: static void Hue2RGB ( double x, double &r, double &g, double &b ) { double d = 1.0/6.0; if(x logger = GetLogger("PajeTrace"); double ConvertTime(TTimePoint t) { // return time in milliseconds as double // return std::chrono::duration(t-start_time).count()*1000.0; // return std::chrono::duration(t-start_time).count() / 2.7e3; return 1000.0*static_cast(t-start_time) / ticks_per_second; } enum PType { SET_VARIABLE=1, ADD_VARIABLE, SUB_VARIABLE, PUSH_STATE, POP_STATE, START_LINK, STOP_LINK }; struct PajeEvent { PajeEvent( int aevent_type, double atime, int atype, int acontainer, double avar_value ) : time(atime), var_value(avar_value), event_type(aevent_type), type(atype), container(acontainer) { } PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue = 0, int aid = 0, bool avalue_is_alias = true ) : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), id(aid), value_is_alias(avalue_is_alias) { } PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue, int astart_container, int akey ) : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), start_container(astart_container), id(akey) { } double time; double var_value = 0.0; int event_type; int type; int container; int value = 0; int start_container = 0; int id = 0; bool value_is_alias = true; bool operator < (const PajeEvent & other) const { // Same start and stop times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState) if(time == other.time) return event_type < other.event_type; return (time < other.time); } int write(FILE *stream) { const int &key = id; const int &end_container = start_container; switch(event_type) { case PajeSetVariable: return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); // NOLINT case PajeAddVariable: return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); // NOLINT case PajeSubVariable: return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); // NOLINT case PajePushState: if(value_is_alias) return fprintf( stream, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT else return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT case PajePopState: return fprintf( stream, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); // NOLINT case PajeStartLink: return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); // NOLINT case PajeEndLink: return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); // NOLINT } return 0; } }; std::vector events; public: PajeFile() = delete; PajeFile(const PajeFile &) = delete; PajeFile(PajeFile &&) = delete; void operator=(const PajeFile &) = delete; void operator=(PajeFile &&) = delete; PajeFile( const std::string & filename, TTimePoint astart_time ) { start_time = astart_time; ctrace_stream = fopen (filename.c_str(),"w"); // NOLINT fprintf(ctrace_stream, "%s", header ); // NOLINT alias_counter = 0; } ~PajeFile() { fclose (ctrace_stream); // NOLINT } int DefineContainerType ( int parent_type, const std::string & name ) { int alias = ++alias_counter; if(parent_type!=0) fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT else fprintf( ctrace_stream, "%d\ta%d\t%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT return alias; } int DefineVariableType ( int container_type, const std::string & name ) { int alias = ++alias_counter; fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"1.0 1.0 1.0\"\n", PajeDefineVariableType, alias, container_type, name.c_str() ); // NOLINT return alias; } int DefineStateType ( int type, const std::string & name ) { int alias = ++alias_counter; fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); // NOLINT return alias; } // int DefineEventType () // { // Write("event not implemented"); // } int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, const std::string & name) { int alias = ++alias_counter; fprintf( ctrace_stream, "%d\ta%d\ta%d\ta%d\ta%d\t\"%s\"\n", PajeDefineLinkType, alias, parent_container_type, start_container_type, stop_container_type, name.c_str() ); // NOLINT return alias; } int DefineEntityValue (int type, const std::string & name, double hue = -1) { if(hue==-1) { std::hash shash; size_t h = shash(name); h ^= h>>32U; h = static_cast(h); hue = h*1.0/std::numeric_limits::max(); } int alias = ++alias_counter; double r; double g; double b; Hue2RGB( hue, r, g, b ); fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"%.15g %.15g %.15g\"\n", PajeDefineEntityValue, alias, type, name.c_str(), r,g,b ); // NOLINT return alias; } int CreateContainer ( int type, int parent, const std::string & name ) { int alias = ++alias_counter; if(parent!=0) fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\ta%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT else fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\t%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT return alias; } void DestroyContainer () {} void SetVariable (TTimePoint time, int type, int container, double value ) { events.emplace_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); } void AddVariable (TTimePoint time, int type, int container, double value ) { events.emplace_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); } void SubVariable (TTimePoint time, int type, int container, double value ) { events.emplace_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) ); } void SetState () {} void PushState ( TTimePoint time, int type, int container, int value, int id = 0, bool value_is_alias = true ) { events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id, value_is_alias) ); } void PopState ( TTimePoint time, int type, int container ) { events.emplace_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) ); } void ResetState () {} void StartLink ( TTimePoint time, int type, int container, int value, int start_container, int key ) { events.emplace_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, key ) ); } void EndLink ( TTimePoint time, int type, int container, int value, int end_container, int key ) { events.emplace_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) ); } void NewEvent () {} void WriteEvents() { logger->info("Sorting traces..."); std::sort (events.begin(), events.end()); logger->info("Writing traces... "); for (auto & event : events) { event.write( ctrace_stream ); // fprintf( ctrace_stream, "%s", buf ); // NOLINT } logger->info("Done"); } private: enum { PajeDefineContainerType = 0, PajeDefineVariableType = 1, PajeDefineStateType = 2, PajeDefineEventType = 3, PajeDefineLinkType = 4, PajeDefineEntityValue = 5, PajeCreateContainer = 6, PajeDestroyContainer = 7, PajeSetVariable = 8, PajeAddVariable = 9, PajeSubVariable = 10, PajeSetState = 11, PajePushState = 12, PajePopState = 13, PajeResetState = 14, PajeStartLink = 15, PajeEndLink = 16, PajeNewEvent = 17 }; }; NGCORE_API PajeTrace *trace; void PajeTrace::Write( const std::string & filename ) { auto n_events = jobs.size() + timer_events.size(); for(auto & vtasks : tasks) n_events += vtasks.size(); logger->info("{} events traced", n_events); if(n_events==0) { logger->info("No data traced, skip writing trace file"); return; } if(!tracing_enabled) { logger->warn("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); } PajeFile paje(filename, start_time); const int container_type_task_manager = paje.DefineContainerType( 0, "Task Manager" ); const int container_type_node = paje.DefineContainerType( container_type_task_manager, "Node"); const int container_type_thread = paje.DefineContainerType( container_type_task_manager, "Thread"); const int container_type_timer = container_type_thread; //paje.DefineContainerType( container_type_task_manager, "Timers"); const int container_type_jobs = paje.DefineContainerType( container_type_task_manager, "Jobs"); const int state_type_job = paje.DefineStateType( container_type_jobs, "Job" ); const int state_type_task = paje.DefineStateType( container_type_thread, "Task" ); const int state_type_timer = paje.DefineStateType( container_type_timer, "Timer state" ); const int variable_type_active_threads = paje.DefineVariableType( container_type_jobs, "Active threads" ); const int container_task_manager = paje.CreateContainer( container_type_task_manager, 0, "The task manager" ); const int container_jobs = paje.CreateContainer( container_type_jobs, container_task_manager, "Jobs" ); paje.SetVariable( start_time, variable_type_active_threads, container_jobs, 0.0 ); const int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1; std::vector container_nodes; container_nodes.reserve(num_nodes); for(int i=0; i thread_aliases; thread_aliases.reserve(nthreads); if(trace_threads) for (int i=0; i job_map; std::map job_task_map; for(Job & j : jobs) if(job_map.find(j.type) == job_map.end()) { std::string name = Demangle(j.type->name()); job_map[j.type] = paje.DefineEntityValue( state_type_job, name, -1 ); job_task_map[j.type] = paje.DefineEntityValue( state_type_task, name, -1 ); } for(Job & j : jobs) { paje.PushState( j.start_time, state_type_job, container_jobs, job_map[j.type] ); paje.PopState( j.stop_time, state_type_job, container_jobs ); } std::set timer_ids; std::map timer_aliases; for(auto & event : timer_events) timer_ids.insert(event.timer_id); for(auto & vtasks : tasks) for (Task & t : vtasks) if(t.id_type==Task::ID_TIMER) timer_ids.insert(t.id); for(auto id : timer_ids) timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id), -1 ); int timerdepth = 0; int maxdepth = 0; for(auto & event : timer_events) { if(event.is_start) { timerdepth++; maxdepth = timerdepth>maxdepth ? timerdepth : maxdepth; } else timerdepth--; } std::vector timer_container_aliases; timer_container_aliases.resize(maxdepth); for(int i=0; i links_merged; links_merged.reserve(nlinks); std::vector pos(nthreads); int nlinks_merged = 0; while(nlinks_merged < nlinks) { int minpos = -1; TTimePoint mintime = -1; for (int t = 0; t started_links; int link_type = paje.DefineLinkType(container_type_node, container_type_thread, container_type_thread, "links"); // match links for ( auto & l : links_merged ) { if(l.is_start) { started_links.push_back(l); } else { unsigned int i = 0; while(i children; double time = 0.0; std::string name; TTimePoint start_time = 0; }; void PrintNode (const TreeNode &n, int &level, std::ofstream & f); void PrintNode (const TreeNode &n, int &level, std::ofstream & f) { f << "{ name: \"" + n.name + "\", size: " + ToString(n.time); int size = n.children.size(); if(size>0) { int i = 0; f << ", children: ["; for(auto & c : n.children) { PrintNode(c.second, level, f); if(++i events; TreeNode root; root.time=0; root.name="all"; TreeNode *current = &root; std::vector node_stack; node_stack.push_back(&root); TTimePoint stop_time = 0; for(auto & event : timer_events) { events.push_back(event); stop_time = std::max(event.time, stop_time); } std::map jobs_map; std::vector job_names; for(auto & job : jobs) { auto name = Demangle(job.type->name()); int id = job_names.size(); if(jobs_map.count(name)==0) { jobs_map[name] = id; job_names.push_back(name); } else id = jobs_map[name]; events.push_back(TimerEvent{-1, job.start_time, true, id}); events.push_back(TimerEvent{-1, job.stop_time, false, id}); stop_time = std::max(job.stop_time, stop_time); } std::sort (events.begin(), events.end()); root.time = 1000.0*static_cast(stop_time-start_time)/ticks_per_second; for(auto & event : events) { bool is_timer_event = event.timer_id != -1; int id = is_timer_event ? event.timer_id : event.thread_id; if(event.is_start) { bool need_init = !current->children.count(id); node_stack.push_back(current); current = ¤t->children[id]; if(need_init) { current->name = is_timer_event ? NgProfiler::GetName(id) : job_names[id]; current->time = 0.0; current->id = id; } current->start_time = event.time; } else { double time = 1000.0*static_cast(event.time-current->start_time)/ticks_per_second; current->time += time; current = node_stack.back(); current->time -= time; node_stack.pop_back(); } } int level = 0; std::ofstream f(tracefile_name+".html"); f.precision(4); f << R"CODE_(

)CODE_" << std::endl; } } // namespace ngcore const char *header = "%EventDef PajeDefineContainerType 0 \n" "% Alias string \n" "% Type string \n" "% Name string \n" "%EndEventDef \n" "%EventDef PajeDefineVariableType 1 \n" "% Alias string \n" "% Type string \n" "% Name string \n" "% Color color \n" "%EndEventDef \n" "%EventDef PajeDefineStateType 2 \n" "% Alias string \n" "% Type string \n" "% Name string \n" "%EndEventDef \n" "%EventDef PajeDefineEventType 3 \n" "% Alias string \n" "% Type string \n" "% Name string \n" "% Color color \n" "%EndEventDef \n" "%EventDef PajeDefineLinkType 4 \n" "% Alias string \n" "% Type string \n" "% StartContainerType string \n" "% EndContainerType string \n" "% Name string \n" "%EndEventDef \n" "%EventDef PajeDefineEntityValue 5 \n" "% Alias string \n" "% Type string \n" "% Name string \n" "% Color color \n" "%EndEventDef \n" "%EventDef PajeCreateContainer 6 \n" "% Time date \n" "% Alias string \n" "% Type string \n" "% Container string \n" "% Name string \n" "%EndEventDef \n" "%EventDef PajeDestroyContainer 7 \n" "% Time date \n" "% Type string \n" "% Name string \n" "%EndEventDef \n" "%EventDef PajeSetVariable 8 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value double \n" "%EndEventDef\n" "%EventDef PajeAddVariable 9 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value double \n" "%EndEventDef\n" "%EventDef PajeSubVariable 10 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value double \n" "%EndEventDef\n" "%EventDef PajeSetState 11 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value string \n" "%EndEventDef\n" "%EventDef PajePushState 12 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value string \n" "% Id string \n" "%EndEventDef\n" "%EventDef PajePopState 13 \n" "% Time date \n" "% Type string \n" "% Container string \n" "%EndEventDef\n" "%EventDef PajeResetState 14 \n" "% Time date \n" "% Type string \n" "% Container string \n" "%EndEventDef\n" "%EventDef PajeStartLink 15 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value string \n" "% StartContainer string \n" "% Key string \n" "%EndEventDef\n" "%EventDef PajeEndLink 16 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value string \n" "% EndContainer string \n" "% Key string \n" "%EndEventDef\n" "%EventDef PajeNewEvent 17 \n" "% Time date \n" "% Type string \n" "% Container string \n" "% Value string \n" "%EndEventDef\n"; netgen-6.2.1905/libsrc/core/logging.hpp0000644000175000017500000000713413504650527016353 0ustar kurtkurt#ifndef NETGEN_CORE_LOGGING_HPP #define NETGEN_CORE_LOGGING_HPP #undef NETGEN_USE_SPDLOG #include #include #include #include #include "exception.hpp" #include "ngcore_api.hpp" #include "utils.hpp" #ifdef NETGEN_USE_SPDLOG #include #include // to be able to parse anything to logger that implements operator << ostream #ifdef NETGEN_LOG_DEBUG #define SPDLOG_DEBUG_ON #define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__) #endif // NETGEN_LOG_DEBUG #endif // NETGEN_USE_SPDLOG #ifndef NETGEN_DEBUG_LOG #define NETGEN_DEBUG_LOG(logger, ...) #endif // NETGEN_DEBUG_LOG namespace spdlog { class logger; } // namespace spdlog namespace ngcore { NGCORE_API extern std::ostream* testout; // NOLINT namespace level { enum level_enum { trace = 0, debug = 1, info = 2, warn = 3, err = 4, critical = 5, off = 6 }; } // namespace level class Logger { public: std::shared_ptr logger; Logger(std::shared_ptr l) : logger(std::move(l)) {} void NGCORE_API log( level::level_enum level, std::string && s); #ifdef NETGEN_USE_SPDLOG template void log( level::level_enum level, const char* str, Args ... args) { log(level, fmt::format(str, args...)); } #else // NETGEN_USE_SPDLOG template std::string replace(std::string s, const T & t) { auto p0 = s.find_first_of('{'); auto p1 = s.find_first_of('}', p0); if(p0==std::string::npos || p1==std::string::npos) throw Exception("invalid format string"); s.replace(p0, p1-p0+1, ToString(t)); return s; } std::string log_helper(std::string s) { return s; } template std::string log_helper(std::string s, const T &t) { return replace(s,t); } template std::string log_helper( std::string s, const T &t, Args ... args) { return log_helper(replace(s,t), args...); } template void log( level::level_enum level, const char* str, Args ... args) { log(level, log_helper(std::string(str), args...)); } #endif // NETGEN_USE_SPDLOG template void trace( const char* str, Args ... args) { log(level::level_enum::trace, str, args...); } template void debug( const char* str, Args ... args) { log(level::level_enum::debug, str, args...); } template void info( const char* str, Args ... args) { log(level::level_enum::info, str, args...); } template void warn( const char* str, Args ... args) { log(level::level_enum::warn, str, args...); } template void error( const char* str, Args ... args) { log(level::level_enum::err, str, args...); } template void critical( const char* str, Args ... args) { log(level::level_enum::critical, str, args...); } }; NGCORE_API std::shared_ptr GetLogger(const std::string& name); NGCORE_API void SetLoggingLevel(level::level_enum level, const std::string& name); NGCORE_API void AddFileSink(const std::string& filename, level::level_enum level, const std::string& logger); NGCORE_API void AddConsoleSink(level::level_enum level, const std::string& logger); NGCORE_API void ClearLoggingSinks(const std::string& logger); NGCORE_API void FlushOnLoggingLevel(level::level_enum level, const std::string& logger); } // namespace ngcore #endif // NETGEN_CORE_LOGGING_HPP netgen-6.2.1905/libsrc/core/paje_trace.hpp0000644000175000017500000001250713504650527017022 0ustar kurtkurt#ifndef NETGEN_CORE_PAJE_TRACE_HPP #define NETGEN_CORE_PAJE_TRACE_HPP #include #include #include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API #include "utils.hpp" namespace ngcore { extern NGCORE_API class PajeTrace *trace; class PajeTrace { public: using TClock = std::chrono::system_clock; protected: std::shared_ptr logger = GetLogger("PajeTrace"); private: NGCORE_API static size_t max_tracefile_size; NGCORE_API static bool trace_thread_counter; NGCORE_API static bool trace_threads; bool tracing_enabled; TTimePoint start_time; int nthreads; public: void WriteSunburstHTML(); // Approximate number of events to trace. Tracing will // be stopped if any thread reaches this number of events unsigned int max_num_events_per_thread; static void SetTraceThreads( bool atrace_threads ) { trace_threads = atrace_threads; } static void SetTraceThreadCounter( bool trace_threads ) { trace_thread_counter = trace_threads; } static void SetMaxTracefileSize( size_t max_size ) { max_tracefile_size = max_size; } std::string tracefile_name; struct Job { int job_id; const std::type_info *type; TTimePoint start_time; TTimePoint stop_time; }; struct Task { int thread_id; int id; int id_type; int additional_value; TTimePoint start_time; TTimePoint stop_time; static constexpr int ID_NONE = -1; static constexpr int ID_JOB = 1; static constexpr int ID_TIMER = 2; }; struct TimerEvent { int timer_id; TTimePoint time; bool is_start; int thread_id; bool operator < (const TimerEvent & other) const { return time < other.time; } }; struct ThreadLink { int thread_id; int key; TTimePoint time; bool is_start; bool operator < (const ThreadLink & other) const { return time < other.time; } }; std::vector > tasks; std::vector jobs; std::vector timer_events; std::vector > links; public: NGCORE_API void StopTracing(); PajeTrace() = delete; PajeTrace(const PajeTrace &) = delete; PajeTrace(PajeTrace &&) = delete; NGCORE_API PajeTrace(int anthreads, std::string aname = ""); NGCORE_API ~PajeTrace(); void operator=(const PajeTrace &) = delete; void operator=(PajeTrace &&) = delete; void StartTimer(int timer_id) { if(!tracing_enabled) return; if(unlikely(timer_events.size() == max_num_events_per_thread)) StopTracing(); timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), true}); } void StopTimer(int timer_id) { if(!tracing_enabled) return; if(unlikely(timer_events.size() == max_num_events_per_thread)) StopTracing(); timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), false}); } NETGEN_INLINE int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1) { if(!tracing_enabled) return -1; if(!trace_threads && !trace_thread_counter) return -1; if(unlikely(tasks[thread_id].size() == max_num_events_per_thread)) StopTracing(); int task_num = tasks[thread_id].size(); tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter()} ); return task_num; } void StopTask(int thread_id, int task_num) { if(!trace_threads && !trace_thread_counter) return; if(task_num>=0) tasks[thread_id][task_num].stop_time = GetTimeCounter(); } void SetTask(int thread_id, int task_num, int additional_value) { if(!trace_threads && !trace_thread_counter) return; if(task_num>=0) tasks[thread_id][task_num].additional_value = additional_value; } void StartJob(int job_id, const std::type_info & type) { if(!tracing_enabled) return; if(jobs.size() == max_num_events_per_thread) StopTracing(); jobs.push_back( Job{job_id, &type, GetTimeCounter()} ); } void StopJob() { if(tracing_enabled) jobs.back().stop_time = GetTimeCounter(); } void StartLink(int thread_id, int key) { if(!tracing_enabled) return; if(links[thread_id].size() == max_num_events_per_thread) StopTracing(); links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), true} ); } void StopLink(int thread_id, int key) { if(!tracing_enabled) return; if(links[thread_id].size() == max_num_events_per_thread) StopTracing(); links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} ); } void Write( const std::string & filename ); }; } // namespace ngcore #endif // NETGEN_CORE_PAJE_TRACE_HPP netgen-6.2.1905/libsrc/core/.clang-tidy0000644000175000017500000000124213504650527016242 0ustar kurtkurtChecks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 - key: cppcoreguidelines-macro-usage.AllowedRegexp value: NGCORE_*|NETGEN_*|NG_EXCEPTION* WarningsAsErrors: '*' netgen-6.2.1905/libsrc/core/CMakeLists.txt0000644000175000017500000000346513504650527016757 0ustar kurtkurt add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp profiler.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) target_compile_options(ngcore PRIVATE -fvisibility=hidden) endif(NOT WIN32) target_compile_definitions(ngcore PUBLIC $<$:NETGEN_ENABLE_CHECK_RANGE>) if(CHECK_RANGE) target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE) endif(CHECK_RANGE) if(USE_SPDLOG) include_directories(${SPDLOG_INCLUDE_DIR}) install(DIRECTORY ${SPDLOG_INCLUDE_DIR} DESTINATION ${NG_INSTALL_DIR_INCLUDE} ) add_dependencies(ngcore project_spdlog) target_compile_definitions(ngcore PUBLIC NETGEN_USE_SPDLOG) if(DEBUG_LOG) target_compile_definitions(ngcore PUBLIC NETGEN_LOG_DEBUG) endif(DEBUG_LOG) endif(USE_SPDLOG) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) if(USE_PYTHON) target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON) target_include_directories(ngcore PRIVATE ${PYTHON_INCLUDE_DIRS}) target_link_libraries(ngcore PRIVATE ${PYTHON_LIBRARIES}) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp mpi_wrapper.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) if(USE_PYTHON) pybind11_add_module(pyngcore SHARED python_ngcore.cpp) target_link_libraries(pyngcore PUBLIC ngcore ${PYTHON_LIBRARIES}) set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}") install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen) endif(USE_PYTHON) netgen-6.2.1905/libsrc/include/0000755000175000017500000000000013504650527014702 5ustar kurtkurtnetgen-6.2.1905/libsrc/include/nginterface_v2_impl.hpp0000644000175000017500000002057113504650527021335 0ustar kurtkurtNGX_INLINE DLL_HEADER Ng_Point Ngx_Mesh :: GetPoint (int nr) const { return Ng_Point (&mesh->Point(PointIndex(nr+PointIndex::BASE))(0)); } template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<0> (size_t nr) const { return (*mesh).pointelements[nr].index; } template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<1> (size_t nr) const { /* if(mesh->GetDimension()==3) return (*mesh)[SegmentIndex(nr)].edgenr; else return (*mesh)[SegmentIndex(nr)].si; */ if(mesh->GetDimension()==3) return mesh->LineSegments()[nr].edgenr; else return mesh->LineSegments()[nr].si; } template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<2> (size_t nr) const { int ind = (*mesh)[SurfaceElementIndex(nr)].GetIndex(); return mesh->GetFaceDescriptor(ind).BCProperty(); } template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetElementIndex<3> (size_t nr) const { return (*mesh)[ElementIndex(nr)].GetIndex(); } template <> NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const { const Element0d & el = mesh->pointelements[nr]; Ng_Element ret; ret.type = NG_PNT; ret.index = el.index; ret.mat = &el.name; ret.points.num = 1; ret.points.ptr = (int*)&el.pnum; ret.vertices.num = 1; ret.vertices.ptr = (int*)&el.pnum; ret.edges.num = 0; ret.edges.ptr = NULL; ret.faces.num = 0; ret.faces.ptr = NULL; ret.facets.num = 1; ret.facets.base = 1; ret.facets.ptr = (int*)&el.pnum; if (mesh->GetDimension() == 1) ret.mat = mesh->GetBCNamePtr(el.index-1); else if (mesh->GetDimension() == 2) ret.mat = mesh->GetCD2NamePtr(el.index-1); else ret.mat = mesh->GetCD3NamePtr(el.index-1); return ret; } template <> NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const { // const Segment & el = mesh->LineSegment (SegmentIndex(nr)); const Segment & el = mesh->LineSegments()[nr]; Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); if(mesh->GetDimension()==3) ret.index = el.edgenr; else ret.index = el.si; if (mesh->GetDimension() == 2) ret.mat = mesh->GetBCNamePtr(el.si-1); else { if (mesh->GetDimension() == 3) ret.mat = mesh->GetCD2NamePtr(el.edgenr-1); else ret.mat = mesh->GetMaterialPtr(el.si); } ret.points.num = el.GetNP(); ret.points.ptr = (int*)&(el[0]); ret.vertices.num = 2; ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = 1; ret.edges.ptr = (T_EDGE2*)mesh->GetTopology().GetSegmentElementEdgesPtr (nr); ret.faces.num = 0; ret.faces.ptr = NULL; if (mesh->GetDimension() == 2) { ret.facets.num = 1; ret.facets.base = 0; ret.facets.ptr = (int*)ret.edges.ptr; } else { ret.facets.num = 2; ret.facets.base = 1; ret.facets.ptr = (int*)&(el[0]); } // ret.is_curved = mesh->GetCurvedElements().IsSegmentCurved(nr); ret.is_curved = el.IsCurved(); return ret; } template <> NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<2> (size_t nr) const { // const Element2d & el = mesh->SurfaceElement (SurfaceElementIndex (nr)); const Element2d & el = mesh->SurfaceElements()[nr]; Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); const FaceDescriptor & fd = mesh->GetFaceDescriptor(el.GetIndex()); ret.index = fd.BCProperty(); if (mesh->GetDimension() == 3) ret.mat = &fd.GetBCName(); else ret.mat = mesh -> GetMaterialPtr(ret.index); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&el[0]; ret.vertices.num = el.GetNV(); ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = MeshTopology::GetNEdges (el.GetType()); ret.edges.ptr = (T_EDGE2*)mesh->GetTopology().GetSurfaceElementEdgesPtr (nr); ret.faces.num = MeshTopology::GetNFaces (el.GetType()); ret.faces.ptr = (T_FACE2*)mesh->GetTopology().GetSurfaceElementFacesPtr (nr); if (mesh->GetDimension() == 3) { ret.facets.num = ret.faces.num; ret.facets.base = 0; ret.facets.ptr = (int*)ret.faces.ptr; } else { ret.facets.num = ret.edges.num; ret.facets.base = 0; ret.facets.ptr = (int*)ret.edges.ptr; } ret.is_curved = el.IsCurved(); return ret; } template <> NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<3> (size_t nr) const { // const Element & el = mesh->VolumeElement (ElementIndex (nr)); const Element & el = mesh->VolumeElements()[nr]; Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); ret.index = el.GetIndex(); ret.mat = mesh -> GetMaterialPtr(ret.index); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&el[0]; ret.vertices.num = el.GetNV(); ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = MeshTopology::GetNEdges (el.GetType()); ret.edges.ptr = (T_EDGE2*)mesh->GetTopology().GetElementEdgesPtr (nr); ret.faces.num = MeshTopology::GetNFaces (el.GetType()); ret.faces.ptr = (T_FACE2*)mesh->GetTopology().GetElementFacesPtr (nr); ret.facets.num = ret.faces.num; ret.facets.base = 0; ret.facets.ptr = (int*)ret.faces.ptr; ret.is_curved = el.IsCurved(); return ret; } template <> NGX_INLINE DLL_HEADER const string & Ngx_Mesh :: GetMaterialCD<0> (int region_nr) const { return mesh->GetMaterial(region_nr+1); } template <> NGX_INLINE DLL_HEADER const string & Ngx_Mesh :: GetMaterialCD<1> (int region_nr) const { return mesh->GetBCName(region_nr); } template <> NGX_INLINE DLL_HEADER const string & Ngx_Mesh :: GetMaterialCD<2> (int region_nr) const { return mesh->GetCD2Name(region_nr); } template <> NGX_INLINE DLL_HEADER const string & Ngx_Mesh :: GetMaterialCD<3> (int region_nr) const { return mesh->GetCD3Name(region_nr); } template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetNNodes<1> () { return mesh->GetTopology().GetNEdges(); } template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetNNodes<2> () { return mesh->GetTopology().GetNFaces(); } template <> NGX_INLINE DLL_HEADER const Ng_Node<0> Ngx_Mesh :: GetNode<0> (int vnr) const { Ng_Node<0> node; vnr++; switch (mesh->GetDimension()) { case 3: { FlatArray ia = mesh->GetTopology().GetVertexElements(vnr); node.elements.ne = ia.Size(); node.elements.ptr = (int*)&ia[0]; FlatArray bia = mesh->GetTopology().GetVertexSurfaceElements(vnr); node.bnd_elements.ne = bia.Size(); node.bnd_elements.ptr = (int*)&bia[0]; break; } case 2: { FlatArray ia = mesh->GetTopology().GetVertexSurfaceElements(vnr); node.elements.ne = ia.Size(); node.elements.ptr = (int*)&ia[0]; FlatArray bia = mesh->GetTopology().GetVertexSegments(vnr); node.bnd_elements.ne = bia.Size(); node.bnd_elements.ptr = (int*)&bia[0]; break; } case 1: { FlatArray ia = mesh->GetTopology().GetVertexSegments(vnr); node.elements.ne = ia.Size(); node.elements.ptr = (int*)&ia[0]; FlatArray bia = mesh->GetTopology().GetVertexPointElements(vnr); node.bnd_elements.ne = bia.Size(); node.bnd_elements.ptr = (int*)&bia[0]; break; } default: ; } return node; } template <> NGX_INLINE DLL_HEADER const Ng_Node<1> Ngx_Mesh :: GetNode<1> (int nr) const { Ng_Node<1> node; node.vertices.ptr = mesh->GetTopology().GetEdgeVerticesPtr(nr); return node; } template <> NGX_INLINE DLL_HEADER const Ng_Node<2> Ngx_Mesh :: GetNode<2> (int nr) const { Ng_Node<2> node; node.vertices.ptr = mesh->GetTopology().GetFaceVerticesPtr(nr); node.vertices.nv = (node.vertices.ptr[3] == 0) ? 3 : 4; node.surface_el = mesh->GetTopology().GetFace2SurfaceElement (nr+1)-1; return node; } NGX_INLINE DLL_HEADER Ng_Buffer Ngx_Mesh :: GetPeriodicVertices(int idnr) const { Array apairs; mesh->GetIdentifications().GetPairs (idnr+1, apairs); for(auto& ind : apairs) { ind.I1()--; ind.I2()--; } typedef int ti2[2]; return { apairs.Size(), (ti2*)(void*)apairs.Release() }; } NGX_INLINE void Ngx_Mesh :: GetParentNodes (int ni, int * parents) const { ni++; if (ni <= mesh->mlbetweennodes.Size()) { parents[0] = mesh->mlbetweennodes.Get(ni).I1()-1; parents[1] = mesh->mlbetweennodes.Get(ni).I2()-1; } else parents[0] = parents[1] = -1; } inline auto Ngx_Mesh :: GetTimeStamp() const { return mesh->GetTimeStamp(); } netgen-6.2.1905/libsrc/include/visual.hpp0000644000175000017500000000004713504650527016717 0ustar kurtkurt#include "../visualization/visual.hpp" netgen-6.2.1905/libsrc/include/mydefs.hpp0000644000175000017500000000274213504650527016707 0ustar kurtkurt#ifndef FILE_MYDEFS #define FILE_MYDEFS /**************************************************************************/ /* File: mydefs.hh */ /* Author: Joachim Schoeberl */ /* Date: 10. Mar. 98 */ /**************************************************************************/ /* defines for graphics, testmodes, ... */ #define PACKAGE_VERSION "6.2-dev" // #define DEBUG #ifdef WIN32 #if NGINTERFACE_EXPORTS || NGLIB_EXPORTS || nglib_EXPORTS #define DLL_HEADER __declspec(dllexport) #else #define DLL_HEADER __declspec(dllimport) #endif #else #if __GNUC__ >= 4 #define DLL_HEADER __attribute__ ((visibility ("default"))) #else #define DLL_HEADER #endif #endif #ifndef __assume #ifdef __GNUC__ #define __assume(cond) if (!(cond)) __builtin_unreachable(); else; #else #define __assume(cond) #endif #endif #ifndef NG_INLINE #ifdef __INTEL_COMPILER #ifdef WIN32 #define NG_INLINE __forceinline inline #else #define NG_INLINE __forceinline inline #endif #else #ifdef __GNUC__ #define NG_INLINE __attribute__ ((__always_inline__)) inline #define VLA #else #define NG_INLINE inline #endif #endif #endif // #define BASE0 // #define DEBUG #define noDEMOVERSION #define noDEVELOP #define noSTEP #define noSOLIDGEOM #define noDEMOAPP #define noMODELLER #define noSTAT_STREAM #define noLOG_STREAM #endif netgen-6.2.1905/libsrc/include/geometry2d.hpp0000644000175000017500000000004413504650527017472 0ustar kurtkurt#include "../geom2d/geometry2d.hpp" netgen-6.2.1905/libsrc/include/nginterface.h0000644000175000017500000003710513504650527017346 0ustar kurtkurt#ifndef NGINTERFACE #define NGINTERFACE /**************************************************************************/ /* File: nginterface.h */ /* Author: Joachim Schoeberl */ /* Date: 20. Nov. 99 */ /**************************************************************************/ #include "../core/ngcore.hpp" /* Application program interface to Netgen */ #ifdef WIN32 #if NGINTERFACE_EXPORTS || NGLIB_EXPORTS || nglib_EXPORTS #define DLL_HEADER __declspec(dllexport) #else #define DLL_HEADER __declspec(dllimport) #endif #else #if __GNUC__ >= 4 #define DLL_HEADER __attribute__ ((visibility ("default"))) #else #define DLL_HEADER #endif #endif // max number of nodes per element #define NG_ELEMENT_MAXPOINTS 20 // max number of nodes per surface element #define NG_SURFACE_ELEMENT_MAXPOINTS 8 // #ifndef PARALLEL // typedef int MPI_Comm; // #endif // namespace netgen { extern DLL_HEADER ngcore::NgMPI_Comm ng_comm; } // implemented element types: enum NG_ELEMENT_TYPE { NG_PNT = 0, NG_SEGM = 1, NG_SEGM3 = 2, NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, NG_TET = 20, NG_TET10 = 21, NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28, NG_HEX = 25, NG_HEX20 = 26 }; typedef double NG_POINT[3]; // coordinates typedef int NG_EDGE[2]; // initial point, end point typedef int NG_FACE[4]; // points, last one is 0 for trig #ifdef __cplusplus extern "C" { #endif // load geometry from file DLL_HEADER void Ng_LoadGeometry (const char * filename); // load netgen mesh DLL_HEADER void Ng_LoadMesh (const char * filename, ngcore::NgMPI_Comm comm = ngcore::NgMPI_Comm{}); // load netgen mesh DLL_HEADER void Ng_LoadMeshFromString (const char * mesh_as_string); // space dimension (2 or 3) DLL_HEADER int Ng_GetDimension (); // number of mesh points DLL_HEADER int Ng_GetNP (); // number of mesh vertices (differs from GetNP for 2nd order elements) DLL_HEADER int Ng_GetNV (); // number of mesh elements DLL_HEADER int Ng_GetNE (); // number of surface triangles DLL_HEADER int Ng_GetNSE (); // Get Point coordintes, index from 1 .. np DLL_HEADER void Ng_GetPoint (int pi, double * p); // Get Element Points DLL_HEADER NG_ELEMENT_TYPE Ng_GetElement (int ei, int * epi, int * np = 0); // Get Element Type DLL_HEADER NG_ELEMENT_TYPE Ng_GetElementType (int ei); // Get sub-domain of element ei DLL_HEADER int Ng_GetElementIndex (int ei); DLL_HEADER void Ng_SetElementIndex(const int ei, const int index); // Get Material of element ei DLL_HEADER const char * Ng_GetElementMaterial (int ei); // Get Material of domain dom DLL_HEADER const char * Ng_GetDomainMaterial (int dom); // Get User Data DLL_HEADER int Ng_GetUserDataSize (char * id); DLL_HEADER void Ng_GetUserData (char * id, double * data); // Get Surface Element Points DLL_HEADER NG_ELEMENT_TYPE Ng_GetSurfaceElement (int ei, int * epi, int * np = 0); // Get Surface Element Type DLL_HEADER NG_ELEMENT_TYPE Ng_GetSurfaceElementType (int ei); // Get Surface Element Index DLL_HEADER int Ng_GetSurfaceElementIndex (int ei); // Get Surface Element Surface Number DLL_HEADER int Ng_GetSurfaceElementSurfaceNumber (int ei); // Get Surface Element Number DLL_HEADER int Ng_GetSurfaceElementFDNumber (int ei); // Get BCName for Surface Element DLL_HEADER char * Ng_GetSurfaceElementBCName (int ei); //void Ng_GetSurfaceElementBCName (int ei, char * name); // Get BCName for bc-number DLL_HEADER char * Ng_GetBCNumBCName (int bcnr); //void Ng_GetBCNumBCName (int bcnr, char * name); // Get BCName for bc-number of co dim 2 DLL_HEADER char * Ng_GetCD2NumCD2Name (int cd2nr); // Get normal vector of surface element node // DLL_HEADER void Ng_GetNormalVector (int sei, int locpi, double * nv); DLL_HEADER void Ng_SetPointSearchStartElement(int el); // Find element of point, returns local coordinates DLL_HEADER int Ng_FindElementOfPoint (double * p, double * lami, int build_searchtrees = 0, const int * const indices = NULL, const int numind = 0); // Find surface element of point, returns local coordinates DLL_HEADER int Ng_FindSurfaceElementOfPoint (double * p, double * lami, int build_searchtrees = 0, const int * const indices = NULL, const int numind = 0); // is element ei curved ? DLL_HEADER int Ng_IsElementCurved (int ei); // is element sei curved ? DLL_HEADER int Ng_IsSurfaceElementCurved (int sei); /// Curved Elements: /// xi..local coordinates /// x ..global coordinates /// dxdxi...D x D Jacobian matrix (row major storage) DLL_HEADER void Ng_GetElementTransformation (int ei, const double * xi, double * x, double * dxdxi); /// buffer must be at least 100 doubles, alignment of double DLL_HEADER void Ng_GetBufferedElementTransformation (int ei, const double * xi, double * x, double * dxdxi, void * buffer, int buffervalid); /// Curved Elements: /// xi..local coordinates /// x ..global coordinates /// dxdxi...D x D-1 Jacobian matrix (row major storage) /// curved ...is element curved ? DLL_HEADER void Ng_GetSurfaceElementTransformation (int sei, const double * xi, double * x, double * dxdxi); /// Curved Elements: /// xi..local coordinates /// sxi..step xi /// x ..global coordinates /// dxdxi...D x D Jacobian matrix (row major storage) DLL_HEADER void Ng_GetMultiElementTransformation (int ei, int n, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi); DLL_HEADER int Ng_GetSegmentIndex (int elnr); DLL_HEADER NG_ELEMENT_TYPE Ng_GetSegment (int elnr, int * epi, int * np = 0); // Mark element for refinement DLL_HEADER void Ng_SetRefinementFlag (int ei, int flag); DLL_HEADER void Ng_SetSurfaceRefinementFlag (int sei, int flag); // Do local refinement enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; DLL_HEADER void Ng_Refine (NG_REFINEMENT_TYPE reftype); // Use second order elements DLL_HEADER void Ng_SecondOrder (); DLL_HEADER void Ng_HighOrder (int order, bool rational = false); //void Ng_HPRefinement (int levels, double parameter = 0.125); DLL_HEADER void Ng_HPRefinement (int levels, double parameter = 0.125, bool setorders = true,bool ref_level = false); // void Ng_HPRefinement (int levels); // void Ng_HPRefinement (int levels, double parameter); // Topology and coordinate information of master element: DLL_HEADER int Ng_ME_GetNVertices (NG_ELEMENT_TYPE et); DLL_HEADER int Ng_ME_GetNEdges (NG_ELEMENT_TYPE et); DLL_HEADER int Ng_ME_GetNFaces (NG_ELEMENT_TYPE et); DLL_HEADER const NG_POINT * Ng_ME_GetVertices (NG_ELEMENT_TYPE et); DLL_HEADER const NG_EDGE * Ng_ME_GetEdges (NG_ELEMENT_TYPE et); DLL_HEADER const NG_FACE * Ng_ME_GetFaces (NG_ELEMENT_TYPE et); DLL_HEADER void Ng_UpdateTopology(); DLL_HEADER int Ng_GetNEdges(); DLL_HEADER int Ng_GetNFaces(); DLL_HEADER int Ng_GetElement_Edges (int elnr, int * edges, int * orient = 0); DLL_HEADER int Ng_GetElement_Faces (int elnr, int * faces, int * orient = 0); DLL_HEADER int Ng_GetSurfaceElement_Edges (int selnr, int * edges, int * orient = 0); DLL_HEADER int Ng_GetSurfaceElement_Face (int selnr, int * orient = 0); DLL_HEADER void Ng_GetSurfaceElementNeighbouringDomains(const int selnr, int & in, int & out); DLL_HEADER int Ng_GetFace_Vertices (int fnr, int * vert); DLL_HEADER void Ng_GetEdge_Vertices (int ednr, int * vert); DLL_HEADER int Ng_GetFace_Edges (int fnr, int * edge); DLL_HEADER int Ng_GetNVertexElements (int vnr); DLL_HEADER void Ng_GetVertexElements (int vnr, int * els); DLL_HEADER int Ng_GetElementOrder (int enr); DLL_HEADER void Ng_GetElementOrders (int enr, int * ox, int * oy, int * oz); DLL_HEADER void Ng_SetElementOrder (int enr, int order); DLL_HEADER void Ng_SetElementOrders (int enr, int ox, int oy, int oz); DLL_HEADER int Ng_GetSurfaceElementOrder (int enr); DLL_HEADER void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy); DLL_HEADER void Ng_SetSurfaceElementOrder (int enr, int order); DLL_HEADER void Ng_SetSurfaceElementOrders (int enr, int ox, int oy); // Multilevel functions: // number of levels: DLL_HEADER int Ng_GetNLevels (); // get two parent nodes (indeed vertices !) of node ni DLL_HEADER void Ng_GetParentNodes (int ni, int * parents); // get parent element (first child has always same number) DLL_HEADER int Ng_GetParentElement (int ei); // get parent surface element (first child has always same number) DLL_HEADER int Ng_GetParentSElement (int ei); // representant of anisotropic cluster DLL_HEADER int Ng_GetClusterRepVertex (int vi); DLL_HEADER int Ng_GetClusterRepEdge (int edi); DLL_HEADER int Ng_GetClusterRepFace (int fai); DLL_HEADER int Ng_GetClusterRepElement (int eli); void Ng_SurfaceElementTransformation (int eli, double x, double y, double * p3d, double * jacobian); #ifdef PARALLEL // the following functions are 0-base !! // number on distant processor // returns pairs (dist_proc, num_on_dist_proc) int NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * pnums ); int NgPar_GetNDistantNodeNums ( int nodetype, int locnum ); int NgPar_GetGlobalNodeNum (int nodetype, int locnum); #endif namespace netgen { // #include "../visualization/soldata.hpp" class SolutionData; class MouseEventHandler; class UserVisualizationObject; } enum Ng_SolutionType { NG_SOLUTION_NODAL = 1, NG_SOLUTION_ELEMENT = 2, NG_SOLUTION_SURFACE_ELEMENT = 3, NG_SOLUTION_NONCONTINUOUS = 4, NG_SOLUTION_SURFACE_NONCONTINUOUS = 5, NG_SOLUTION_VIRTUAL_FUNCTION = 6, NG_SOLUTION_MARKED_ELEMENTS = 10, NG_SOLUTION_ELEMENT_ORDER = 11 }; struct Ng_SolutionData { std::string name; // name of gridfunction double * data; // solution values int components; // relevant (double) components in solution vector int dist; // # doubles per entry alignment! int iscomplex; // complex vector ? bool draw_surface; bool draw_volume; int order; // order of elements, only partially supported Ng_SolutionType soltype; // type of solution function netgen::SolutionData * solclass; }; // initialize solution data with default arguments DLL_HEADER void Ng_InitSolutionData (Ng_SolutionData * soldata); // set solution data DLL_HEADER void Ng_SetSolutionData (Ng_SolutionData * soldata); /// delete gridfunctions DLL_HEADER void Ng_ClearSolutionData(); // redraw DLL_HEADER void Ng_Redraw(bool blocking = false); /// DLL_HEADER void Ng_TclCmd(std::string cmd); /// DLL_HEADER void Ng_SetMouseEventHandler (netgen::MouseEventHandler * handler); /// DLL_HEADER void Ng_SetUserVisualizationObject (netgen::UserVisualizationObject * vis); // DLL_HEADER void Ng_SetVisualizationParameter (const char * name, const char * value); // number of periodic vertices DLL_HEADER int Ng_GetNPeriodicVertices (int idnr); // pairs should be an integer array of 2*npairs DLL_HEADER void Ng_GetPeriodicVertices (int idnr, int * pairs); // number of periodic edges DLL_HEADER int Ng_GetNPeriodicEdges (int idnr); // pairs should be an integer array of 2*npairs DLL_HEADER void Ng_GetPeriodicEdges (int idnr, int * pairs); DLL_HEADER void RunParallel ( void * (*fun)(void *), void * in); DLL_HEADER void Ng_PushStatus (const char * str); DLL_HEADER void Ng_PopStatus (); DLL_HEADER void Ng_SetThreadPercentage (double percent); DLL_HEADER void Ng_GetStatus (char ** str, double & percent); DLL_HEADER void Ng_SetTerminate(void); DLL_HEADER void Ng_UnSetTerminate(void); DLL_HEADER int Ng_ShouldTerminate(void); DLL_HEADER void Ng_SetRunning(int flag); DLL_HEADER int Ng_IsRunning(); //// added by Roman Stainko .... DLL_HEADER int Ng_GetVertex_Elements( int vnr, int* elems); DLL_HEADER int Ng_GetVertex_SurfaceElements( int vnr, int* elems ); DLL_HEADER int Ng_GetVertex_NElements( int vnr ); DLL_HEADER int Ng_GetVertex_NSurfaceElements( int vnr ); #ifdef SOCKETS int Ng_SocketClientOpen( const int port, const char * host ); void Ng_SocketClientWrite( const char * write, char ** reply); void Ng_SocketClientClose ( void ); void Ng_SocketClientGetServerHost ( const int number, char ** host ); void Ng_SocketClientGetServerPort ( const int number, int * port ); void Ng_SocketClientGetServerClientID ( const int number, int * id ); #endif DLL_HEADER void Ng_InitPointCurve(double red, double green, double blue); DLL_HEADER void Ng_AddPointCurvePoint(const double * point); // #ifdef PARALLEL // void Ng_SetElementPartition ( int elnr, int part ); // int Ng_GetElementPartition ( int elnr ); // #endif DLL_HEADER void Ng_SaveMesh ( const char * meshfile ); DLL_HEADER void Ng_Bisect ( const char * refinementfile ); // if qualityloss is not equal to NULL at input, a (1-based) list of qualitylosses (due to projection) // is saved in *qualityloss, its size is the return value DLL_HEADER int Ng_Bisect_WithInfo ( const char * refinementfile, double ** qualityloss); typedef void * Ng_Mesh; DLL_HEADER Ng_Mesh Ng_SelectMesh (Ng_Mesh mesh); DLL_HEADER void Ng_GetArgs (int & argc, char ** &argv); #ifdef __cplusplus } #endif #endif /* The new node interface ... it is 0-based ! */ extern "C" { /* number of nodes of type nt nt = 0 is Vertex nt = 1 is Edge nt = 2 is Face nt = 3 is Cell */ DLL_HEADER int Ng_GetNNodes (int nt); /* closure nodes of node (nt, nodenr): nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc E.g., nodeset = 6 includes edge and face nodes nodes consists of pairs of integers (nodetype, nodenr) return value is number of nodes */ DLL_HEADER int Ng_GetClosureNodes (int nt, int nodenr, int nodeset, int * nodes); /* number of dim-dimensional elements dim = 3 ... volume elements dim = 2 ... surface elements dim = 1 ... segments dim = 0 ... not available */ DLL_HEADER int Ng_GetNElements (int dim); /* closure nodes of dim-dimensional element elmentnr: nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc E.g., nodeset = 6 includes edge and face nodes nodes consists of pairs of integers (nodetype, nodenr) return value is number of nodes */ DLL_HEADER int Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes); struct Ng_Tcl_Interp; typedef int (Ng_Tcl_CmdProc) (Ng_Tcl_Interp *interp, int argc, const char *argv[]); DLL_HEADER void Ng_Tcl_CreateCommand (Ng_Tcl_Interp * interp, const char * cmdName, Ng_Tcl_CmdProc * proc); void Ng_Tcl_SetResult (Ng_Tcl_Interp * interp, const char * result); } #ifdef __cplusplus #include namespace netgen { DLL_HEADER extern int printmessage_importance; } #endif netgen-6.2.1905/libsrc/include/incvis.hpp0000644000175000017500000000014713504650527016710 0ustar kurtkurt// libraries for User interface: nicht mehr verwendet #include "inctcl.hpp" #include "incopengl.hpp" netgen-6.2.1905/libsrc/include/inctcl.hpp0000644000175000017500000000021013504650527016660 0ustar kurtkurt#include #include #if TK_MAJOR_VERSION==8 && TK_MINOR_VERSION>=4 #define tcl_const const #else #define tcl_const #endif netgen-6.2.1905/libsrc/include/opti.hpp0000644000175000017500000000003613504650527016365 0ustar kurtkurt#include "../linalg/opti.hpp" netgen-6.2.1905/libsrc/include/mystdlib.h0000644000175000017500000000202113504650527016675 0ustar kurtkurt#ifndef FILE_MYSTDLIB #define FILE_MYSTDLIB #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PARALLEL // #undef SEEK_SET // #undef SEEK_CUR // #undef SEEK_END #include #include // for usleep (only for parallel) #endif /* #ifdef METIS namespace metis { extern "C" { #include } } #endif */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /*** Windows headers ***/ #ifdef _MSC_VER # define WIN32_LEAN_AND_MEAN # ifndef NO_PARALLEL_THREADS # ifdef MSVC_EXPRESS # else # include # include # endif // MSVC_EXPRESS # endif # include # undef WIN32_LEAN_AND_MEAN # include #else // Not using MC VC++ #endif using namespace std; #endif netgen-6.2.1905/libsrc/include/linalg.hpp0000644000175000017500000000004013504650527016653 0ustar kurtkurt#include "../linalg/linalg.hpp" netgen-6.2.1905/libsrc/include/incopengl.hpp0000644000175000017500000000225413504650527017374 0ustar kurtkurt#ifndef INCOPENGL_HPP___ #define INCOPENGL_HPP___ #define GL_GLEXT_PROTOTYPES #include # if defined(TOGL_AGL) || defined(TOGL_AGL_CLASSIC) || defined(TOGL_NSOPENGL) # include # include # else # include # include # endif #ifdef TOGL_X11 // parallel #define GLX_GLXEXT_PROTOTYPES #include #include #endif #ifdef WIN32 // part of OpenGL 1.2, but not in Microsoft's OpenGL 1.1 header: // GL version should be checked at runtime #define GL_CLAMP_TO_EDGE 0x812F #define GL_ARRAY_BUFFER 0x8892 #define GL_ELEMENT_ARRAY_BUFFER 0x8893 #define GL_STATIC_DRAW 0x88E4 typedef ptrdiff_t GLintptr; typedef ptrdiff_t GLsizeiptr; extern void (*glBindBuffer) (GLenum a, GLuint b); extern void (*glDeleteBuffers) (GLsizei a, const GLuint *b); extern void (*glGenBuffers) (GLsizei a, GLuint *b); extern void (*glBufferData) (GLenum a, GLsizeiptr b, const GLvoid *c, GLenum d); extern void (*glBufferSubData) (GLenum a, GLintptr b, GLsizeiptr c, const GLvoid *d); #endif DLL_HEADER void LoadOpenGLFunctionPointers(); #endif // INCOPENGL_HPP___ netgen-6.2.1905/libsrc/include/stlgeom.hpp0000644000175000017500000000004213504650527017061 0ustar kurtkurt#include <../stlgeom/stlgeom.hpp> netgen-6.2.1905/libsrc/include/occgeom.hpp0000644000175000017500000000003613504650527017026 0ustar kurtkurt#include "../occ/occgeom.hpp" netgen-6.2.1905/libsrc/include/csg.hpp0000644000175000017500000000003213504650527016162 0ustar kurtkurt#include "../csg/csg.hpp" netgen-6.2.1905/libsrc/include/myadt.hpp0000644000175000017500000000004013504650527016523 0ustar kurtkurt#include <../general/myadt.hpp> netgen-6.2.1905/libsrc/include/acisgeom.hpp0000644000175000017500000000006713504650527017205 0ustar kurtkurt#ifdef ACIS #include "../acisgeom/acisgeom.hpp" #endif netgen-6.2.1905/libsrc/include/parallel.hpp0000644000175000017500000000004413504650527017205 0ustar kurtkurt#include "../parallel/parallel.hpp" netgen-6.2.1905/libsrc/include/gprim.hpp0000644000175000017500000000003613504650527016530 0ustar kurtkurt#include "../gprim/gprim.hpp" netgen-6.2.1905/libsrc/include/nginterface_v2.hpp0000644000175000017500000002337213504650527020316 0ustar kurtkurt#ifndef NGINTERFACE_V2 #define NGINTERFACE_V2 /**************************************************************************/ /* File: nginterface_v2.hpp */ /* Author: Joachim Schoeberl */ /* Date: May 09 */ /**************************************************************************/ #include "../core/ngcore.hpp" /* C++ interface to Netgen */ #ifndef NGINTERFACE // implemented element types: enum NG_ELEMENT_TYPE { NG_PNT = 0, NG_SEGM = 1, NG_SEGM3 = 2, NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, NG_TET = 20, NG_TET10 = 21, NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28, NG_HEX = 25, NG_HEX20 = 26 }; enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; #endif // #ifndef PARALLEL // typedef int MPI_Comm; // #endif namespace netgen { using namespace std; using namespace ngcore; // extern DLL_HEADER NgMPI_Comm ng_comm; static constexpr int POINTINDEX_BASE = 1; struct T_EDGE2 { // int orient:1; // int nr:31; // 0-based int nr; // 0-based }; struct T_FACE2 { // int orient:3; // int nr:29; // 0-based int nr; // 0-based }; template class Ng_Buffer { size_t s; T * data; public: Ng_Buffer (size_t as, T * adata) : s(as), data(adata) { ; } Ng_Buffer (Ng_Buffer && buffer) : s(buffer.Size()), data(buffer.Release()) { ; } ~Ng_Buffer () { delete [] data; } size_t Size() const { return s; } T * Release() { T * hd = data; data = nullptr; return hd; } }; template class Ng_BufferMS { size_t s; T data[S]; public: Ng_BufferMS (size_t as) : s(as) { ; } size_t Size() const { return s; } T & operator[] (size_t i) { return data[i]; } T operator[] (size_t i) const { return data[i]; } }; class Ng_Element { class Ng_Points { public: size_t num; const int * ptr; size_t Size() const { return num; } int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; } }; class Ng_Vertices { public: size_t num; const int * ptr; size_t Size() const { return num; } int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; } }; class Ng_Edges { public: size_t num; const T_EDGE2 * ptr; size_t Size() const { return num; } int operator[] (size_t i) const { return ptr[i].nr; } }; class Ng_Faces { public: size_t num; const T_FACE2 * ptr; size_t Size() const { return num; } int operator[] (size_t i) const { return ptr[i].nr; } }; class Ng_Facets { public: size_t num; int base; const int * ptr; size_t Size() const { return num; } int operator[] (size_t i) const { return ptr[i]-base; } }; public: NG_ELEMENT_TYPE type; int index; // material / boundary condition const string * mat; // material / boundary label NG_ELEMENT_TYPE GetType() const { return type; } int GetIndex() const { return index-1; } Ng_Points points; // all points Ng_Vertices vertices; Ng_Edges edges; Ng_Faces faces; Ng_Facets facets; bool is_curved; }; class Ng_Point { double * pt; public: Ng_Point (double * apt) : pt(apt) { ; } double operator[] (size_t i) { return pt[i]; } operator const double * () { return pt; } }; template class Ng_Node; template <> class Ng_Node<0> { class Ng_Elements { public: size_t ne; const int * ptr; size_t Size() const { return ne; } int operator[] (size_t i) const { return ptr[i]; } }; public: Ng_Elements elements; Ng_Elements bnd_elements; }; template <> class Ng_Node<1> { class Ng_Vertices { public: const int * ptr; size_t Size() const { return 2; } int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; } }; public: Ng_Vertices vertices; }; template <> class Ng_Node<2> { class Ng_Vertices { public: size_t nv; const int * ptr; size_t Size() const { return nv; } int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; } }; /* class Ng_Edges { public: size_t ned; const int * ptr; size_t Size() const { return ned; } int operator[] (size_t i) const { return ptr[i]-1; } }; */ public: Ng_Vertices vertices; // Ng_Edges edges; int surface_el; // -1 if face not on surface }; class Mesh; inline void DummyTaskManager2 (function func) { func(0,1); } inline void DummyTracer2 (string, bool) { ; } class DLL_HEADER Ngx_Mesh { private: shared_ptr mesh; public: // Ngx_Mesh () { ; } // Ngx_Mesh(class Mesh * amesh) : mesh(amesh) { ; } /** reuse a netgen-mesh **/ Ngx_Mesh (shared_ptr amesh); /** load a new mesh **/ Ngx_Mesh (string filename, NgMPI_Comm acomm = NgMPI_Comm{}); void LoadMesh (const string & filename, NgMPI_Comm comm = NgMPI_Comm{}); void LoadMesh (istream & str, NgMPI_Comm comm = NgMPI_Comm{}); void SaveMesh (ostream & str) const; void UpdateTopology (); void DoArchive (Archive & archive); NgMPI_Comm GetCommunicator() const; virtual ~Ngx_Mesh(); bool Valid () const { return mesh != NULL; } int GetDimension() const; int GetNLevels() const; int GetNElements (int dim) const; int GetNNodes (int nt) const; Ng_Point GetPoint (int nr) const; template Ng_Element GetElement (size_t nr) const; template int GetElementIndex (size_t nr) const; /// material/boundary label of region, template argument is co-dimension template const string & GetMaterialCD (int region_nr) const; /// Curved Elements: /// elnr .. element nr /// xi..... DIM_EL local coordinates /// x ..... DIM_SPACE global coordinates /// dxdxi...DIM_SPACE x DIM_EL Jacobian matrix (row major storage) template void ElementTransformation (int elnr, const double * xi, double * x, double * dxdxi) const; /// Curved Elements: /// elnr .. element nr /// npts .. number of points /// xi..... DIM_EL local coordinates /// sxi ... step xi /// x ..... DIM_SPACE global coordinates /// dxdxi...DIM_SPACE x DIM_EL Jacobian matrix (row major storage) template void MultiElementTransformation (int elnr, int npts, const T * xi, size_t sxi, T * x, size_t sx, T * dxdxi, size_t sdxdxi) const; template const Ng_Node GetNode (int nr) const; Ng_BufferMS GetFaceEdges (int fnr) const; template int GetNNodes (); // returns domain numbers of domains next to boundary bnr -> (domin, domout) // 3D only // std::pair GetBoundaryNeighbouringDomains (int bnr); template void SetRefinementFlag (size_t elnr, bool flag); void Curve (int order); void Refine (NG_REFINEMENT_TYPE reftype, void (*taskmanager)(function) = &DummyTaskManager2, void (*tracer)(string, bool) = &DummyTracer2); int GetHPElementLevel (int ei, int dir) const; void GetParentNodes (int ni, int * parents) const; int GetParentElement (int ei) const; int GetParentSElement (int ei) const; int GetNIdentifications() const; int GetIdentificationType(int idnr) const; Ng_Buffer GetPeriodicVertices(int idnr) const; // Find element of point, returns local coordinates template int FindElementOfPoint (double * p, double * lami, bool build_searchtrees = false, int * const indices = NULL, int numind = 0) const; // for MPI-parallel std::tuple GetDistantProcs (int nodetype, int locnum) const; shared_ptr GetMesh () const { return mesh; } shared_ptr SelectMesh () const; inline auto GetTimeStamp() const; // also added from nginterface.h, still 1-based, need redesign void HPRefinement (int levels, double parameter = 0.125, bool setorders = true,bool ref_level = false); size_t GetNP() const; int GetSurfaceElementSurfaceNumber (size_t ei) const; int GetSurfaceElementFDNumber (size_t ei) const; int GetElementOrder (int enr) const; void GetElementOrders (int enr, int * ox, int * oy, int * oz) const; void SetElementOrder (int enr, int order); void SetElementOrders (int enr, int ox, int oy, int oz); int GetSurfaceElementOrder (int enr) const; void GetSurfaceElementOrders (int enr, int * ox, int * oy) const; void SetSurfaceElementOrder (int enr, int order); void SetSurfaceElementOrders (int enr, int ox, int oy); int GetClusterRepVertex (int vi) const; int GetClusterRepEdge (int edi) const; int GetClusterRepFace (int fai) const; int GetClusterRepElement (int eli) const; }; DLL_HEADER Ngx_Mesh * LoadMesh (const string & filename); } #ifdef HAVE_NETGEN_SOURCES #include namespace netgen { #ifdef __GNUC__ #define NGX_INLINE __attribute__ ((__always_inline__)) inline #else #define NGX_INLINE inline #endif #include } #endif #endif netgen-6.2.1905/libsrc/include/ngsimd.hpp0000644000175000017500000000004113504650527016667 0ustar kurtkurt#include <../general/ngsimd.hpp> netgen-6.2.1905/libsrc/include/meshing.hpp0000644000175000017500000000004213504650527017041 0ustar kurtkurt#include <../meshing/meshing.hpp> netgen-6.2.1905/libsrc/include/CMakeLists.txt0000644000175000017500000000070113504650527017440 0ustar kurtkurtinstall(FILES nginterface.h nginterface_v2.hpp mydefs.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel) install(FILES acisgeom.hpp csg.hpp geometry2d.hpp gprim.hpp incopengl.hpp inctcl.hpp incvis.hpp linalg.hpp meshing.hpp myadt.hpp mydefs.hpp mystdlib.h nginterface_v2_impl.hpp occgeom.hpp ngsimd.hpp opti.hpp parallel.hpp stlgeom.hpp visual.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/include COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/occ/0000755000175000017500000000000013504650527014023 5ustar kurtkurtnetgen-6.2.1905/libsrc/occ/Partition_Inter2d.ixx0000644000175000017500000000211413504650527020113 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter2d.ixx // Module : GEOM #include #include "Partition_Inter2d.jxx" netgen-6.2.1905/libsrc/occ/Partition_Loop.hxx0000644000175000017500000000546013504650527017523 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Loop.hxx // Module : GEOM #ifndef _Partition_Loop_HeaderFile #define _Partition_Loop_HeaderFile #ifndef _TopoDS_Face_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile #include #endif #ifndef _Standard_Version_HeaderFile #include #endif class TopoDS_Face; class TopoDS_Edge; #if OCC_VERSION_HEX < 0x070000 class TopTools_ListOfShape; #endif #ifndef _Standard_HeaderFile #include #endif #ifndef _Standard_Macro_HeaderFile #include #endif class Partition_Loop { public: inline void* operator new(size_t,void* anAddress) { return anAddress; } inline void* operator new(size_t size) { return Standard::Allocate(size); } inline void operator delete(void *anAddress) { if (anAddress) Standard::Free((Standard_Address&)anAddress); } // inline void operator delete(void *anAddress, size_t size) // { // if (anAddress) Standard::Free((Standard_Address&)anAddress,size); // } // Methods PUBLIC // Partition_Loop(); void Init(const TopoDS_Face& F) ; void AddConstEdge(const TopoDS_Edge& E) ; void Perform() ; const TopTools_ListOfShape& NewWires() const; void WiresToFaces() ; const TopTools_ListOfShape& NewFaces() const; protected: // Methods PROTECTED // // Fields PROTECTED // private: // Methods PRIVATE // // Fields PRIVATE // TopoDS_Face myFace; TopTools_ListOfShape myConstEdges; TopTools_ListOfShape myNewWires; TopTools_ListOfShape myNewFaces; }; // other inline functions and methods (like "C++: function call" methods) // #endif netgen-6.2.1905/libsrc/occ/vsocc.cpp0000644000175000017500000004756713504650527015667 0ustar kurtkurt#ifndef NOTCL #ifdef OCCGEOMETRY #include #include #include #include #include "TopoDS_Shape.hxx" #include "TopoDS_Vertex.hxx" #include "TopExp_Explorer.hxx" #include "BRep_Tool.hxx" #include "TopoDS.hxx" #include "gp_Pnt.hxx" #include "Geom_Curve.hxx" #include "Poly_Triangulation.hxx" #include "Poly_Array1OfTriangle.hxx" #include "TColgp_Array1OfPnt2d.hxx" #include "Poly_Triangle.hxx" #include "Poly_Polygon3D.hxx" #include "Poly_PolygonOnTriangulation.hxx" #include #include "vsocc.hpp" namespace netgen { // extern OCCGeometry * occgeometry; /* *********************** Draw OCC Geometry **************** */ VisualSceneOCCGeometry :: VisualSceneOCCGeometry () : VisualScene() { trilists.SetSize(0); linelists.SetSize(1); } VisualSceneOCCGeometry :: ~VisualSceneOCCGeometry () { ; } void VisualSceneOCCGeometry :: DrawScene () { if ( occgeometry->changed ) { BuildScene(); occgeometry -> changed = 0; } glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); glShadeModel (GL_SMOOTH); glDisable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glEnable (GL_LIGHTING); double shine = vispar.shininess; // double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); glEnable (GL_NORMALIZE); float mat_col[] = { 0.2f, 0.2f, 0.8f, 1.0f}; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); // Philippose - 30/01/2009 // Added clipping planes to Geometry view SetClippingPlane(); GLfloat matcoledge[] = { 0, 0, 1, 1}; GLfloat matcolhiedge[] = { 1, 0, 0, 1}; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcoledge); glLineWidth (1.0f); if (vispar.occshowedges) glCallList (linelists.Get(1)); if (vispar.occshowsurfaces) glCallList (trilists.Get(1)); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolhiedge); glLineWidth (5.0f); if (vispar.occshowedges) glCallList (linelists.Get(2)); for (int i = 1; i <= occgeometry->vmap.Extent(); i++) if (occgeometry->vvispar[i-1].IsHighlighted()) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolhiedge); glLineWidth (5.0f); glBegin (GL_LINES); gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(occgeometry->vmap(i))); double d = rad/100; glVertex3f (p.X()-d, p.Y(), p.Z()); glVertex3f (p.X()+d, p.Y(), p.Z()); glVertex3f (p.X(), p.Y()-d, p.Z()); glVertex3f (p.X(), p.Y()+d, p.Z()); glVertex3f (p.X(), p.Y(), p.Z()-d); glVertex3f (p.X(), p.Y(), p.Z()+d); glEnd(); } glDisable (GL_POLYGON_OFFSET_FILL); glPopMatrix(); // DrawCoordinateCross (); // DrawNetgenLogo (); glFinish(); glDisable (GL_POLYGON_OFFSET_FILL); } /* void VisualSceneOCCGeometry :: BuildScene (int zoomall) { int i = 0, j, k; TopExp_Explorer ex, ex_edge; if (vispar.occvisproblemfaces || (occgeometry -> changed != 2)) { Box<3> bb = occgeometry -> GetBoundingBox(); center = bb.Center(); rad = bb.Diam() / 2; if (vispar.occvisproblemfaces) { for (i = 1; i <= occgeometry->fmap.Extent(); i++) if (occgeometry->facemeshstatus[i-1] == -1) { GProp_GProps system; BRepGProp::LinearProperties(occgeometry->fmap(i), system); gp_Pnt pnt = system.CentreOfMass(); center = Point<3> (pnt.X(), pnt.Y(), pnt.Z()); cout << "Setting center to mid of face " << i << " = " << center << endl; } } CalcTransformationMatrices(); } for (i = 1; i <= linelists.Size(); i++) glDeleteLists (linelists.Elem(i), 1); linelists.SetSize(0); linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); i = 0; for (ex_edge.Init(occgeometry -> shape, TopAbs_EDGE); ex_edge.More(); ex_edge.Next()) { if (BRep_Tool::Degenerated(TopoDS::Edge(ex_edge.Current()))) continue; i++; TopoDS_Edge edge = TopoDS::Edge(ex_edge.Current()); Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { cout << "cannot visualize edge " << i << endl; continue; } glBegin (GL_LINE_STRIP); int nbnodes = aEdgePoly -> NbNodes(); for (j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); for (i = 1; i <= trilists.Size(); i++) glDeleteLists (trilists.Elem(i), 1); trilists.SetSize(0); trilists.Append (glGenLists (1)); glNewList (trilists.Last(), GL_COMPILE); i = 0; TopExp_Explorer exp0, exp1, exp2, exp3; int shapenr = 0; for (exp0.Init(occgeometry -> shape, TopAbs_SOLID); exp0.More(); exp0.Next()) { shapenr++; if (vispar.occshowvolumenr != 0 && vispar.occshowvolumenr != shapenr) continue; float mat_col[4]; mat_col[3] = 1; switch (shapenr) { case 1: mat_col[0] = 0.2; mat_col[1] = 0.2; mat_col[2] = 0.8; break; case 2: mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.8; break; case 3: mat_col[0] = 0.2; mat_col[1] = 0.8; mat_col[2] = 0.8; break; case 4: mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.2; break; case 5: mat_col[0] = 0.8; mat_col[1] = 0.8; mat_col[2] = 0.8; break; case 6: mat_col[0] = 0.6; mat_col[1] = 0.6; mat_col[2] = 0.6; break; case 7: mat_col[0] = 0.2; mat_col[1] = 0.8; mat_col[2] = 0.2; break; case 8: mat_col[0] = 0.8; mat_col[1] = 0.8; mat_col[2] = 0.2; break; default: // mat_col[0] = 1-(1.0/double(shapenr)); // mat_col[1] = 0.5; mat_col[0] = 0.5+double((shapenr*shapenr*shapenr*shapenr) % 10)/20.0; mat_col[1] = 0.5+double(int(shapenr*shapenr*shapenr*shapenr*sin(double(shapenr))) % 10)/20.0; mat_col[2] = 0.5+double((shapenr*shapenr*shapenr) % 10)/20.0; } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); for (exp1.Init(exp0.Current(), TopAbs_SHELL); exp1.More(); exp1.Next()) for (exp2.Init(exp1.Current().Composed(exp0.Current().Orientation()), TopAbs_FACE); exp2.More(); exp2.Next()) { TopoDS_Face face = TopoDS::Face (exp2.Current().Composed(exp1.Current().Orientation())); i = occgeometry->fmap.FindIndex(face); TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (face); BRepAdaptor_Surface sf(face, Standard_False); BRepLProp_SLProps prop(sf, 1, 1e-5); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) { cout << "cannot visualize face " << i << endl; continue; } if (vispar.occvisproblemfaces) { switch (occgeometry->facemeshstatus[i-1]) { case 0: mat_col[0] = 0.2; mat_col[1] = 0.2; mat_col[2] = 0.8; break; case 1: mat_col[0] = 0.2; mat_col[1] = 0.8; mat_col[2] = 0.2; break; case -1: mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.2; break; } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); } glBegin (GL_TRIANGLES); int ntriangles = triangulation -> NbTriangles(); for (j = 1; j <= ntriangles; j++) { Poly_Triangle triangle = (triangulation -> Triangles())(j); for (k = 1; k <= 3; k++) { gp_Pnt2d uv = (triangulation -> UVNodes())(triangle(k)); gp_Pnt pnt; gp_Vec du, dv; prop.SetParameters (uv.X(), uv.Y()); surf->D0 (uv.X(), uv.Y(), pnt); gp_Vec n; if (prop.IsNormalDefined()) n = prop.Normal(); else n = gp_Vec (0,0,0); if (face.Orientation() == TopAbs_REVERSED) n *= -1; glNormal3f (n.X(), n.Y(), n.Z()); glVertex3f (pnt.X(), pnt.Y(), pnt.Z()); } } glEnd (); } } glEndList (); } */ void VisualSceneOCCGeometry :: BuildScene (int zoomall) { if (occgeometry -> changed == OCCGEOMETRYVISUALIZATIONFULLCHANGE) { occgeometry -> BuildVisualizationMesh (vispar.occdeflection); center = occgeometry -> Center(); rad = occgeometry -> GetBoundingBox().Diam() / 2; if (vispar.occzoomtohighlightedentity) { bool hilite = false; bool hiliteonepoint = false; Bnd_Box bb; for (int i = 1; i <= occgeometry->fmap.Extent(); i++) if (occgeometry->fvispar[i-1].IsHighlighted()) { hilite = true; BRepBndLib::Add (occgeometry->fmap(i), bb); } for (int i = 1; i <= occgeometry->emap.Extent(); i++) if (occgeometry->evispar[i-1].IsHighlighted()) { hilite = true; BRepBndLib::Add (occgeometry->emap(i), bb); } for (int i = 1; i <= occgeometry->vmap.Extent(); i++) if (occgeometry->vvispar[i-1].IsHighlighted()) { hiliteonepoint = true; BRepBndLib::Add (occgeometry->vmap(i), bb); } if (hilite || hiliteonepoint) { double x1,y1,z1,x2,y2,z2; bb.Get (x1,y1,z1,x2,y2,z2); Point<3> p1 = Point<3> (x1,y1,z1); Point<3> p2 = Point<3> (x2,y2,z2); Box<3> boundingbox(p1,p2); center = boundingbox.Center(); if (hiliteonepoint) rad = occgeometry -> GetBoundingBox().Diam() / 100; else rad = boundingbox.Diam() / 2; } } CalcTransformationMatrices(); } // Clear lists for (int i = 1; i <= linelists.Size(); i++) glDeleteLists (linelists.Elem(i), 1); linelists.SetSize(0); for (int i = 1; i <= trilists.Size(); i++) glDeleteLists (trilists.Elem(i), 1); trilists.SetSize(0); // Total wireframe linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->emap.Extent(); i++) { TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i)); if (BRep_Tool::Degenerated(edge)) continue; if (occgeometry->evispar[i-1].IsHighlighted()) continue; Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge) << " without using the occ visualization triangulation" << endl; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); glBegin (GL_LINE_STRIP); for (int i = 0; i<=50; i++) { gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0); glVertex3f (p.X(),p.Y(),p.Z()); } glEnd (); continue; } int nbnodes = aEdgePoly -> NbNodes(); glBegin (GL_LINE_STRIP); for (int j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); // Highlighted edge list linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->emap.Extent(); i++) if (occgeometry->evispar[i-1].IsHighlighted()) { TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i)); if (BRep_Tool::Degenerated(edge)) continue; Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge) << " without using the occ visualization triangulation" << endl; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); glBegin (GL_LINE_STRIP); for (int i = 0; i<=50; i++) { gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0); glVertex3f (p.X(),p.Y(),p.Z()); } glEnd (); continue; } int nbnodes = aEdgePoly -> NbNodes(); glBegin (GL_LINE_STRIP); for (int j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); // display faces trilists.Append (glGenLists (1)); glNewList (trilists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->fmap.Extent(); i++) { if (!occgeometry->fvispar[i-1].IsVisible()) continue; glLoadName (i); float mat_col[4]; mat_col[3] = 1; TopoDS_Face face = TopoDS::Face(occgeometry->fmap(i)); if (!occgeometry->fvispar[i-1].IsHighlighted()) { // Philippose - 30/01/2009 // OpenCascade XDE Support Quantity_Color face_colour; // Philippose - 23/02/2009 // Check to see if colours have been extracted first!! // Forum bug-fox (Jean-Yves - 23/02/2009) if(!(occgeometry->face_colours.IsNull()) && (occgeometry->face_colours->GetColor(face,XCAFDoc_ColorSurf,face_colour))) { mat_col[0] = face_colour.Red(); mat_col[1] = face_colour.Green(); mat_col[2] = face_colour.Blue(); } else { mat_col[0] = 0.0; mat_col[1] = 1.0; mat_col[2] = 0.0; } } else { mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.2; } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (face); BRepAdaptor_Surface sf(face, Standard_False); BRepLProp_SLProps prop(sf, 1, 1e-5); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) { cout << "cannot visualize face " << i << endl; occgeometry->fvispar[i-1].SetNotDrawable(); continue; } gp_Pnt2d uv; gp_Pnt pnt; gp_Vec n; glBegin (GL_TRIANGLES); int ntriangles = triangulation -> NbTriangles(); for (int j = 1; j <= ntriangles; j++) { Poly_Triangle triangle = (triangulation -> Triangles())(j); gp_Pnt p[3]; for (int k = 1; k <= 3; k++) p[k-1] = (triangulation -> Nodes())(triangle(k)).Transformed(loc); for (int k = 1; k <= 3; k++) { uv = (triangulation -> UVNodes())(triangle(k)); prop.SetParameters (uv.X(), uv.Y()); // surf->D0 (uv.X(), uv.Y(), pnt); if (prop.IsNormalDefined()) n = prop.Normal(); else { (*testout) << "Visualization of face " << i << ": Normal vector not defined" << endl; // n = gp_Vec (0,0,0); gp_Vec a(p[0],p[1]); gp_Vec b(p[0],p[2]); n = b^a; } if (face.Orientation() == TopAbs_REVERSED) n *= -1; glNormal3f (n.X(), n.Y(), n.Z()); glVertex3f (p[k-1].X(), p[k-1].Y(), p[k-1].Z()); } } glEnd (); } glEndList (); } void SelectFaceInOCCDialogTree (int facenr); void VisualSceneOCCGeometry :: MouseDblClick (int px, int py) { int hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixd (transformationmat); glInitNames(); glPushName (1); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glDisable(GL_CLIP_PLANE0); // Philippose - 30/01/2009 // Enable clipping planes for Selection mode in OCC Geometry if (vispar.clipping.enable) { Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); double len = Abs(n); double mu = -clipplane[3] / (len*len); Point<3> p (mu * n); n /= len; Vec<3> t1 = n.GetNormal (); Vec<3> t2 = Cross (n, t1); double xi1mid = (center - p) * t1; double xi2mid = (center - p) * t2; glLoadName (0); glBegin (GL_QUADS); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); glEnd (); } glCallList (trilists.Get(1)); glDisable (GL_POLYGON_OFFSET_FILL); glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); int minname = 0; GLuint mindepth = 0; // find clippingplane GLuint clipdepth = 0; // GLuint(-1); for (int i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; if (!curname) clipdepth = selbuf[4*i+1]; } for (int i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; if (curname && (curdepth> clipdepth) && (curdepth < mindepth || !minname)) { mindepth = curdepth; minname = curname; } } occgeometry->LowLightAll(); if (minname) { occgeometry->fvispar[minname-1].Highlight(); if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; cout << "Selected face: " << minname << endl; } else { occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } glDisable(GL_CLIP_PLANE0); SelectFaceInOCCDialogTree (minname); // Philippose - 30/01/2009 // Set the currently selected face in the array // for local face mesh size definition occgeometry->SetSelectedFace(minname); // selecttimestamp = NextTimeStamp(); } } #endif #endif // NOTCL netgen-6.2.1905/libsrc/occ/Partition_Loop2d.hxx0000644000175000017500000000377513504650527017760 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Loop2d.hxx // Module : GEOM #ifndef _Partition_Loop2d_HeaderFile #define _Partition_Loop2d_HeaderFile #ifndef _TopoDS_Face_HeaderFile #include #endif #ifndef _TopAbs_Orientation_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopTools_MapOfShape_HeaderFile #include #endif #ifndef _Standard_Version_HeaderFile #include #endif class TopoDS_Face; class TopoDS_Edge; #if OCC_VERSION_HEX < 0x070000 class TopTools_ListOfShape; #endif class BRepAlgo_Image; #ifndef _Standard_HeaderFile #include #endif #ifndef _Standard_Macro_HeaderFile #include #endif class Partition_Loop2d { public: void* operator new(size_t,void* anAddress) { return anAddress; } void* operator new(size_t size) { return Standard::Allocate(size); } void operator delete(void *anAddress) { if (anAddress) Standard::Free((Standard_Address&)anAddress); } // Methods PUBLIC // Partition_Loop2d(); void Init(const TopoDS_Face& F) ; void AddConstEdge(const TopoDS_Edge& E) ; void AddSectionEdge(const TopoDS_Edge& E) ; void Perform() ; const TopTools_ListOfShape& NewWires() const; void WiresToFaces(const BRepAlgo_Image& EdgeImage) ; const TopTools_ListOfShape& NewFaces() const; protected: // Methods PROTECTED // // Fields PROTECTED // private: // Methods PRIVATE // // Fields PRIVATE // TopoDS_Face myFace; TopAbs_Orientation myFaceOri; TopTools_ListOfShape myConstEdges; TopTools_ListOfShape myNewWires; TopTools_ListOfShape myNewFaces; TopTools_ListOfShape myInternalWL; TopTools_MapOfShape mySectionEdges; }; // other Inline functions and methods (like "C++: function call" methods) // #endif netgen-6.2.1905/libsrc/occ/occconstruction.cpp0000644000175000017500000000760713504650527017760 0ustar kurtkurt #ifdef OCCGEOMETRY #include #include #include "ShapeAnalysis_ShapeTolerance.hxx" #include "ShapeAnalysis_ShapeContents.hxx" #include "ShapeAnalysis_CheckSmallFace.hxx" #include "ShapeAnalysis_DataMapOfShapeListOfReal.hxx" #include "BRepAlgoAPI_Fuse.hxx" #include "BRepCheck_Analyzer.hxx" #include "BRepLib.hxx" #include "ShapeBuild_ReShape.hxx" #include "ShapeFix.hxx" #include "ShapeFix_FixSmallFace.hxx" #include "Partition_Spliter.hxx" //#include "VrmlAPI.hxx" //#include "StlAPI.hxx" #include #include #include #include // #include #include #include #include #include #include #include //#include #include #include namespace netgen { void OCCConstructGeometry (OCCGeometry & geom) { #ifdef NOTHING cout << "OCC construction" << endl; BRep_Builder builder; BRepPrimAPI_MakeBox mbox(gp_Pnt(-10e5, -15e5, 0), gp_Pnt(20e5, 15e5, 10e5)); /* TopoDS_Shape air = TopoDS_Solid (mbox); air = BRepAlgoAPI_Cut (air, geom.somap(1)); air = BRepAlgoAPI_Cut (air, geom.somap(2)); air = BRepAlgoAPI_Cut (air, geom.somap(3)); air = BRepAlgoAPI_Cut (air, geom.somap(4)); air = BRepAlgoAPI_Cut (air, geom.somap(5)); air = BRepAlgoAPI_Cut (air, geom.somap(6)); air = BRepAlgoAPI_Cut (air, geom.somap(7)); // air = BRepAlgoAPI_Cut (air, geom.somap(8)); air = BRepAlgoAPI_Cut (air, geom.somap(9)); // air = BRepAlgoAPI_Cut (air, geom.somap(10)); */ /* BRepOffsetAPI_MakeOffsetShape dom8plus (geom.somap(8), 1e4, 1e-6); BRepOffsetAPI_MakeOffsetShape dom6plus (geom.somap(6), 1e4, 1e-6); dom8plus.Build(); ShapeFix_Shape fixshape(dom8plus.Shape()); fixshape.Perform(); ShapeFix_Shape fix_dom2(geom.somap(2)); fix_dom2.Perform(); BRepAlgoAPI_Cut dom2m8(fix_dom2.Shape(), fixshape.Shape()); ShapeFix_Shape fix_dom2m8 (dom2m8); fix_dom2m8.Perform(); builder.Add (geom.shape, BRepAlgoAPI_Cut (BRepAlgoAPI_Cut (geom.somap(2), dom6plus), dom8plus)); // builder.Add (geom.shape, fix_dom2m8.Shape()); // builder.Add (geom.shape, fixshape.Shape()); */ TopoDS_Shape my_fuse; int cnt = 0; for (TopExp_Explorer exp_solid(geom.shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next()) { if (cnt == 0) my_fuse = exp_solid.Current(); else { cout << "fuse, cnt = " << cnt << endl; if (cnt != 7 && cnt != 9) my_fuse = BRepAlgoAPI_Fuse (my_fuse, exp_solid.Current()); } cnt++; } builder.Add (geom.shape, my_fuse); /* ShapeUpgrade_ShellSewing ss; ss.ApplySewing(geom.shape,1e5); */ /* BRepAlgo_Sewing sewing(1.e5); int cnt = 0; for (TopExp_Explorer exp_solid(geom.shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next()) { cout << "swe, cnt = " << cnt << endl; if (cnt != 7 && cnt != 9) sewing.Add (exp_solid.Current()); cnt++; } sewing.Perform(); builder.Add (geom.shape, sewing.SewedShape()); */ /* cout << "build air domain" << endl; TopoDS_Shape air = BRepAlgoAPI_Cut (TopoDS_Solid (mbox), my_fuse); cnt = 0; for (TopExp_Explorer exp_solid(geom.shape, TopAbs_SOLID); exp_solid.More(); exp_solid.Next()) { cout << "section, cnt = " << cnt << endl; if (cnt == 7) { builder.Add (geom.shape, BRepAlgoAPI_Section (air, exp_solid.Current())); } cnt++; } */ // builder.Add (geom.shape, air); for (int i = 1; i <= 10; i++) builder.Remove (geom.shape, geom.somap(i)); geom.BuildFMap(); geom.BuildVisualizationMesh(); geom.changed = 1; #endif } } #endif netgen-6.2.1905/libsrc/occ/Partition_Loop.cxx0000644000175000017500000003256313504650527017522 0ustar kurtkurt#ifdef OCCGEOMETRY // GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Loop.cxx // Author : Benedicte MARTIN // Module : GEOM // $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Loop.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $ //using namespace std; #include #include #include "Partition_Loop.ixx" #include "utilities.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static char* name = new char[100]; static int nbe = 0; #ifdef WIN32 #define M_PI 3.14159265358979323846 #endif //======================================================================= //function : Partition_Loop //purpose : //======================================================================= Partition_Loop::Partition_Loop() { } //======================================================================= //function : Init //purpose : //======================================================================= void Partition_Loop::Init(const TopoDS_Face& F) { myConstEdges.Clear(); myNewWires .Clear(); myNewFaces .Clear(); myFace = F; } //======================================================================= //function : AddConstEdge //purpose : //======================================================================= void Partition_Loop::AddConstEdge (const TopoDS_Edge& E) { myConstEdges.Append(E); } //======================================================================= //function : FindDelta //purpose : //======================================================================= static Standard_Real FindDelta(TopTools_ListOfShape& LE, const TopoDS_Face& F) { Standard_Real dist, f, l; Standard_Real d = Precision::Infinite(); TopTools_ListIteratorOfListOfShape itl; for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,f,l); gp_Pnt2d p = C->Value(f); gp_Pnt2d pp = C->Value(l); Standard_Real d1 = p.Distance(pp); if (d1 connected by the vertex in the list . // Is erased of the list. If is too in the list // with the same orientation, it's erased of the list //======================================================================= static Standard_Boolean SelectEdge(const TopoDS_Face& F, const TopoDS_Edge& CE, const TopoDS_Vertex& CV, TopoDS_Edge& NE, TopTools_ListOfShape& LE) { TopTools_ListIteratorOfListOfShape itl; NE.Nullify(); for ( itl.Initialize(LE); itl.More(); itl.Next()) { if (itl.Value().IsEqual(CE)) { LE.Remove(itl); break; } } if (LE.Extent() > 1) { //-------------------------------------------------------------- // Several possible edges. // - Test the edge difference of CE //-------------------------------------------------------------- Standard_Real cf, cl, f, l; TopoDS_Face FForward = F; Handle(Geom2d_Curve) Cc, C; FForward.Orientation(TopAbs_FORWARD); Cc = BRep_Tool::CurveOnSurface(CE,FForward,cf,cl); Standard_Real dist,distmin = 100*BRep_Tool::Tolerance(CV); Standard_Real uc,u; if (CE.Orientation () == TopAbs_FORWARD) uc = cl; else uc = cf; gp_Pnt2d P2,PV = Cc->Value(uc); Standard_Real delta = FindDelta(LE,FForward); for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (!E.IsSame(CE)) { C = BRep_Tool::CurveOnSurface(E,FForward,f,l); if (E.Orientation () == TopAbs_FORWARD) u = f; else u = l; P2 = C->Value(u); dist = PV.Distance(P2); if (dist <= distmin){ distmin = dist; } } } Standard_Real anglemax = - M_PI; TopoDS_Edge SelectedEdge; for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (!E.IsSame(CE)) { C = BRep_Tool::CurveOnSurface(E,FForward,f,l); if (E.Orientation () == TopAbs_FORWARD) u = f; else u = l; P2 = C->Value(u); dist = PV.Distance(P2); if (dist <= distmin + (1./3)*delta){ gp_Pnt2d PC, P; gp_Vec2d CTg1, CTg2, Tg1, Tg2; Cc->D2(uc, PC, CTg1, CTg2); C->D2(u, P, Tg1, Tg2); Standard_Real angle; if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_FORWARD) { angle = CTg1.Angle(Tg1.Reversed()); } else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_REVERSED) { angle = (CTg1.Reversed()).Angle(Tg1); } else if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_REVERSED) { angle = CTg1.Angle(Tg1); } else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_FORWARD) { angle = (CTg1.Reversed()).Angle(Tg1.Reversed()); } if (angle >= anglemax) { anglemax = angle ; SelectedEdge = E; } } } } for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (E.IsEqual(SelectedEdge)) { NE = TopoDS::Edge(E); LE.Remove(itl); break; } } } else if (LE.Extent() == 1) { NE = TopoDS::Edge(LE.First()); LE.RemoveFirst(); } else { return Standard_False; } return Standard_True; } //======================================================================= //function : SamePnt2d //purpose : //======================================================================= static Standard_Boolean SamePnt2d(TopoDS_Vertex V, TopoDS_Edge& E1, TopoDS_Edge& E2, TopoDS_Face& F) { Standard_Real f1,f2,l1,l2; gp_Pnt2d P1,P2; TopoDS_Shape aLocalF = F.Oriented(TopAbs_FORWARD); TopoDS_Face FF = TopoDS::Face(aLocalF); Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,FF,f1,l1); Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,FF,f2,l2); if (E1.Orientation () == TopAbs_FORWARD) P1 = C1->Value(f1); else P1 = C1->Value(l1); if (E2.Orientation () == TopAbs_FORWARD) P2 = C2->Value(l2); else P2 = C2->Value(f2); Standard_Real Tol = 100*BRep_Tool::Tolerance(V); Standard_Real Dist = P1.Distance(P2); return Dist < Tol; } //======================================================================= //function : PurgeNewEdges //purpose : //======================================================================= static void PurgeNewEdges(TopTools_ListOfShape& ConstEdges, const TopTools_MapOfOrientedShape& UsedEdges) { TopTools_ListIteratorOfListOfShape it(ConstEdges); while ( it.More()) { const TopoDS_Shape& NE = it.Value(); if (!UsedEdges.Contains(NE)) { ConstEdges.Remove(it); } else { it.Next(); } } } //======================================================================= //function : StoreInMVE //purpose : //======================================================================= static void StoreInMVE (const TopoDS_Face& F, TopoDS_Edge& E, TopTools_DataMapOfShapeListOfShape& MVE ) { TopoDS_Vertex V1, V2; TopTools_ListOfShape Empty; TopExp::Vertices(E,V1,V2); if (!MVE.IsBound(V1)) { MVE.Bind(V1,Empty); } MVE(V1).Append(E); if (!MVE.IsBound(V2)) { MVE.Bind(V2,Empty); } MVE(V2).Append(E); } //======================================================================= //function : Perform //purpose : //======================================================================= void Partition_Loop::Perform() { TopTools_DataMapOfShapeListOfShape MVE; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit, Mapit1; TopTools_ListIteratorOfListOfShape itl; TopoDS_Vertex V1,V2; //----------------------------------- // Construction map vertex => edges //----------------------------------- for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) { TopoDS_Edge& E = TopoDS::Edge(itl.Value()); StoreInMVE(myFace,E,MVE); } //---------------------------------------------- // Construction of all the wires and of all the new faces. //---------------------------------------------- TopTools_MapOfOrientedShape UsedEdges; while (!MVE.IsEmpty()) { TopoDS_Vertex VF,CV; TopoDS_Edge CE,NE,EF; TopoDS_Wire NW; BRep_Builder B; Standard_Boolean End= Standard_False; B.MakeWire(NW); //-------------------------------- // EF first edge. //-------------------------------- Mapit.Initialize(MVE); EF = CE = TopoDS::Edge(Mapit.Value().First()); TopExp::Vertices(CE,V1,V2); //-------------------------------- // VF first vertex //-------------------------------- if (CE.Orientation() == TopAbs_FORWARD) { CV = VF = V1; } else { CV = VF = V2; } if (!MVE.IsBound(CV)) continue; for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) { if (itl.Value().IsEqual(CE)) { MVE(CV).Remove(itl); break; } } int i = 0; while (!End) { //------------------------------- // Construction of a wire. //------------------------------- TopExp::Vertices(CE,V1,V2); if (!CV.IsSame(V1)) CV = V1; else CV = V2; B.Add (NW,CE); UsedEdges.Add(CE); //-------------- // stop test //-------------- if (!MVE.IsBound(CV) || MVE(CV).IsEmpty() || CV.IsSame(VF) ) { if (CV.IsSame(VF)) { if (MVE(CV).Extent() == 1 ) MVE.UnBind(CV); else { for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) { if (itl.Value().IsEqual(CE)) { MVE(CV).Remove(itl); break; } } } } End=Standard_True; } //-------------- // select edge //-------------- else { Standard_Boolean find = SelectEdge(myFace,CE,CV,NE,MVE(CV)); if (find) { CE=NE; if (MVE(CV).IsEmpty()) MVE.UnBind(CV); if (CE.IsNull() ) { MESSAGE ( " CE is NULL !!! " ) End=Standard_True; } } else { MESSAGE ( " edge doesn't exist " ) End=Standard_True; } } } //----------------------------- // Test if the wire is closed //----------------------------- if (VF.IsSame(CV) && SamePnt2d(VF,EF,CE,myFace)) { } else{ MESSAGE ( "wire not closed" ) } myNewWires.Append (NW); } PurgeNewEdges(myConstEdges,UsedEdges); } //======================================================================= //function : NewWires //purpose : //======================================================================= const TopTools_ListOfShape& Partition_Loop::NewWires() const { return myNewWires; } //======================================================================= //function : NewFaces //purpose : //======================================================================= const TopTools_ListOfShape& Partition_Loop::NewFaces() const { return myNewFaces; } //======================================================================= //function : WiresToFaces //purpose : //======================================================================= void Partition_Loop::WiresToFaces() { if (!myNewWires.IsEmpty()) { BRepAlgo_FaceRestrictor FR; TopAbs_Orientation OriF = myFace.Orientation(); TopoDS_Shape aLocalS = myFace.Oriented(TopAbs_FORWARD); FR.Init (TopoDS::Face(aLocalS),Standard_False); TopTools_ListIteratorOfListOfShape it(myNewWires); for (; it.More(); it.Next()) { FR.Add(TopoDS::Wire(it.Value())); } FR.Perform(); if (FR.IsDone()) { for (; FR.More(); FR.Next()) { myNewFaces.Append(FR.Current().Oriented(OriF)); } } } } #endif netgen-6.2.1905/libsrc/occ/occmeshsurf.hpp0000644000175000017500000001122013504650527017051 0ustar kurtkurt#ifdef OCCGEOMETRY #ifndef FILE_OCCMESHSURF #define FILE_OCCMESHSURF #include "occgeom.hpp" #include "mydefs.hpp" #define PARAMETERSPACE -1 #define PLANESPACE 1 class OCCGeometry; class SingularMatrixException {}; class UVBoundsException {}; class OCCSurface { public: TopoDS_Face topods_face; Handle(Geom_Surface) occface; TopAbs_Orientation orient; int projecttype; protected: Point<3> p1; Point<3> p2; /// in plane, directed p1->p2 Vec<3> ex; /// in plane Vec<3> ey; /// outer normal direction Vec<3> ez; /// normal vector in p2 Vec<3> n2; /// average normal vector Vec<3> nmid; // for transformation to parameter space Point<2> psp1; Point<2> psp2; Vec<2> psex; Vec<2> psey; Mat<2,2> Amat, Amatinv; // UV Bounds double umin, umax, vmin, vmax; public: OCCSurface (const TopoDS_Face & aface, int aprojecttype) { topods_face = aface; occface = BRep_Tool::Surface(topods_face); orient = topods_face.Orientation(); projecttype = aprojecttype; ShapeAnalysis::GetFaceUVBounds (topods_face, umin, umax, vmin, vmax); umin -= fabs(umax-umin)/100.0; vmin -= fabs(vmax-vmin)/100.0; umax += fabs(umax-umin)/100.0; vmax += fabs(vmax-vmin)/100.0; // projecttype = PLANESPACE; /* TopExp_Explorer exp1; exp1.Init (topods_face, TopAbs_WIRE); orient = TopAbs::Compose (orient, exp1.Current().Orientation()); */ }; ~OCCSurface() {}; void Project (Point<3> & p, PointGeomInfo & gi); void GetNormalVector (const Point<3> & p, const PointGeomInfo & geominfo, Vec<3> & n) const; /** Defines tangential plane in ap1. The local x-coordinate axis point to the direction of ap2 */ void DefineTangentialPlane (const Point<3> & ap1, const PointGeomInfo & geominfo1, const Point<3> & ap2, const PointGeomInfo & geominfo2); /// Transforms 3d point p3d to local coordinates pplane void ToPlane (const Point<3> & p3d, const PointGeomInfo & geominfo, Point<2> & pplane, double h, int & zone) const; /// Transforms point pplane in local coordinates to 3d point void FromPlane (const Point<2> & pplane, Point<3> & p3d, PointGeomInfo & gi, double h); }; /// class Meshing2OCCSurfaces : public Meshing2 { /// OCCSurface surface; public: /// Meshing2OCCSurfaces (const TopoDS_Shape & asurf, const Box<3> & aboundingbox, int aprojecttype); /// int GetProjectionType () { return surface.projecttype; } protected: /// virtual void DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo1, const PointGeomInfo * geominfo2); /// virtual void TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominfo, Point2d & plainpoint, double h, int & zone); /// virtual int TransformFromPlain (Point2d & plainpoint, Point3d & locpoint, PointGeomInfo & gi, double h); /// virtual double CalcLocalH (const Point3d & p, double gh) const; }; /// class MeshOptimize2dOCCSurfaces : public MeshOptimize2d { /// const OCCGeometry & geometry; public: /// MeshOptimize2dOCCSurfaces (const OCCGeometry & ageometry); /// virtual void ProjectPoint (INDEX surfind, Point<3> & p) const; /// virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const; /// virtual int ProjectPointGI (INDEX surfind, Point<3> & p, PointGeomInfo & gi) const; /// virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const; /// virtual void GetNormalVector(INDEX surfind, const Point<3> & p, PointGeomInfo & gi, Vec<3> & n) const; virtual int CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point<3> & p3) const; }; class OCCGeometry; class DLL_HEADER OCCRefinementSurfaces : public Refinement { const OCCGeometry & geometry; public: OCCRefinementSurfaces (const OCCGeometry & ageometry); virtual ~OCCRefinementSurfaces (); virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const override; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const override; virtual void ProjectToSurface (Point<3> & p, int surfi) const override; virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const override; }; #endif #endif netgen-6.2.1905/libsrc/occ/Partition_Inter3d.ixx0000644000175000017500000000207113504650527020116 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter3d.ixx // Module : GEOM #include "Partition_Inter3d.jxx" netgen-6.2.1905/libsrc/occ/Partition_Loop3d.cxx0000644000175000017500000002406013504650527017742 0ustar kurtkurt#ifdef OCCGEOMETRY // GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Loop3d.cxx // Module : GEOM //using namespace std; #include #include "Partition_Loop3d.ixx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //======================================================================= //function : Partition_Loop3d //purpose : //======================================================================= Partition_Loop3d::Partition_Loop3d() { } //======================================================================= //function : AddConstFaces //purpose : Add faces of as unique faces in the result. //======================================================================= void Partition_Loop3d::AddConstFaces(const TopoDS_Shape& S) { TopExp_Explorer FaceExp(S, TopAbs_FACE); for (; FaceExp.More(); FaceExp.Next()) myFaces.Append( FaceExp.Current() ); TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, myEFMap); } //======================================================================= //function : AddSectionFaces //purpose : Add faces of as double faces in the result. //======================================================================= void Partition_Loop3d::AddSectionFaces(const TopoDS_Shape& S) { AddConstFaces( S ); AddConstFaces( S.Reversed() ); } //======================================================================= //function : MakeShells //purpose : Make and return shells. // can contain faces that must not be // added to result shells. //======================================================================= const TopTools_ListOfShape& Partition_Loop3d::MakeShells (const TopTools_MapOfOrientedShape& AvoidFacesMap) { myNewShells.Clear(); BRep_Builder Builder; TopTools_MapOfShape CheckedEdgesMap; TopTools_MapOfOrientedShape AddedFacesMap; TopTools_ListIteratorOfListOfShape itF (myFaces); for (; itF.More(); itF.Next()) { const TopoDS_Shape& FF = itF.Value(); if (AvoidFacesMap.Contains( FF ) || ! AddedFacesMap.Add( FF ) ) continue; // make a new shell TopoDS_Shell Shell; Builder.MakeShell(Shell); Builder.Add(Shell,FF); // clear the maps from shapes added to previous Shell TopTools_MapIteratorOfMapOfShape itEM (CheckedEdgesMap); for (; itEM.More(); itEM.Next()) { TopTools_ListOfShape& FL = myEFMap.ChangeFromKey( itEM.Key()); TopTools_ListIteratorOfListOfShape it (FL); while ( it.More()) { if (AddedFacesMap.Contains( it.Value())) FL.Remove( it ); else it.Next(); } } CheckedEdgesMap.Clear(); // loop on faces added to Shell; add their neighbor faces to Shell and so on TopoDS_Iterator itAddedF (Shell); for (; itAddedF.More(); itAddedF.Next()) { const TopoDS_Face& F = TopoDS::Face (itAddedF.Value()); // loop on edges of F; find a good neighbor face of F by E TopExp_Explorer EdgeExp(F, TopAbs_EDGE); for (; EdgeExp.More(); EdgeExp.Next()) { const TopoDS_Edge& E = TopoDS::Edge( EdgeExp.Current()); if (! CheckedEdgesMap.Add( E )) continue; // candidate faces list const TopTools_ListOfShape& FL = myEFMap.ChangeFromKey(E); if (FL.IsEmpty()) continue; // select one of neighbors TopoDS_Face SelF; if (FL.Extent() == 2) { if (! F.IsSame( FL.First() )) SelF = TopoDS::Face( FL.First() ); else if (!F.IsSame( FL.Last() )) SelF = TopoDS::Face( FL.Last() ); } else { // check if a face already added to Shell shares E TopTools_ListIteratorOfListOfShape it (FL); Standard_Boolean found = Standard_False; for (; !found && it.More(); it.Next()) if (F != it.Value()) found = AddedFacesMap.Contains( it.Value() ); if (found) continue; // select basing on geometrical check Standard_Boolean GoodOri, inside; Standard_Real dot, MaxDot = -100; TopTools_ListOfShape TangFL; // tangent faces for ( it.Initialize( FL ) ; it.More(); it.Next()) { const TopoDS_Face& NeighborF = TopoDS::Face( it.Value()); if (NeighborF.IsSame( F )) continue; inside = Partition_Loop3d::IsInside( E, F, NeighborF, 1, dot, GoodOri); if (!GoodOri) continue; if (!inside) dot = -dot - 3; if (dot < MaxDot) continue; if ( IsEqual( dot, MaxDot)) TangFL.Append(SelF); else TangFL.Clear(); MaxDot = dot; SelF = NeighborF; } if (!TangFL.IsEmpty()) { for (it.Initialize( TangFL ); it.More(); it.Next()) { const TopoDS_Face& NeighborF = TopoDS::Face( it.Value()); if (Partition_Loop3d:: IsInside( E, SelF , NeighborF, 0, dot, GoodOri)) SelF = NeighborF; } } } if (!SelF.IsNull() && AddedFacesMap.Add( SelF ) && !AvoidFacesMap.Contains( SelF )) Builder.Add( Shell, SelF); } // loop on edges of F } // loop on the faces added to Shell // Shell is complete myNewShells.Append( Shell ); } // loop on myFaces // prepare to the next call myFaces.Clear(); myEFMap.Clear(); return myNewShells; } //======================================================================= //function : Normal //purpose : //======================================================================= gp_Vec Partition_Loop3d::Normal(const TopoDS_Edge& E, const TopoDS_Face& F) { gp_Vec Norm, V1, V2; Standard_Real First, Last; gp_Pnt Ps; Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E, F, First, Last); Handle(Geom_Surface) Sf = BRep_Tool::Surface(F); gp_Pnt2d p = C2d->Value( 0.5*(First+Last) ); Sf->D1(p.X(), p.Y(), Ps, V1, V2); Norm = V1.Crossed(V2); if (F.Orientation() == TopAbs_REVERSED ) Norm.Reverse(); return Norm; } //======================================================================= //function : NextNormal //purpose : find normal to F at point a little inside F near the middle of E //warning : E must be properly oriented in F. //======================================================================= static gp_Vec NextNormal(const TopoDS_Edge& E, const TopoDS_Face& F) { Standard_Real First, Last; Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E, F, First, Last); Handle(Geom_Surface) Sf = BRep_Tool::Surface(F); gp_Pnt2d p; gp_Vec2d v; C2d->D1( 0.5*(First+Last), p, v); if (E.Orientation() != F.Orientation()) v.Reverse(); gp_Dir2d dir( -v.Y(), v.X() ); // dir inside F Standard_Real duv = 1e-6; // this is not Ok and may give incorrect result if // resolutionUV of compared faces is very different. To have a good result, //it is necessary to get normal to faces at points equidistant from E in 3D p.SetX( p.X() + dir.X()*duv ); p.SetY( p.Y() + dir.Y()*duv ); gp_Pnt Ps; gp_Vec Norm, V1, V2, VV1, VV2; Sf->D1( p.X(), p.Y(), Ps, V1, V2); Norm = V1.Crossed(V2); if (F.Orientation() == TopAbs_REVERSED ) Norm.Reverse(); return Norm; } //======================================================================= //function : FindEinF //purpose : find E in F //======================================================================= static TopoDS_Edge FindEinF(const TopoDS_Edge& E, const TopoDS_Face& F) { TopExp_Explorer expl (F, TopAbs_EDGE); for (; expl.More(); expl.Next()) if( E.IsSame( expl.Current() )) return TopoDS::Edge(expl.Current()); TopoDS_Edge nullE; return nullE; } //======================================================================= //function : IsInside //purpose : check if is inside by edge . // if , compute : scalar production of // normalized vectors pointing inside faces, and // check if faces are oriented well for sewing //======================================================================= Standard_Boolean Partition_Loop3d::IsInside(const TopoDS_Edge& E, const TopoDS_Face& F1, const TopoDS_Face& F2, const Standard_Boolean CountDot, Standard_Real& Dot, Standard_Boolean& GoodOri) { Standard_Real f, l; gp_Pnt P; gp_Vec Vc1, Vc2, Vin1, Vin2, Nf1, Nf2; Handle(Geom_Curve) Curve = BRep_Tool::Curve(E,f,l); Curve->D1( 0.5*(f + l), P, Vc2); TopoDS_Edge E1, E2 = FindEinF (E, F2); if (E2.Orientation() == TopAbs_REVERSED ) Vc2.Reverse(); Nf1 = Normal(E,F1); Nf2 = Normal(E,F2); Standard_Real sin = Nf1.CrossSquareMagnitude(Nf2) / Nf1.SquareMagnitude() / Nf2.SquareMagnitude(); Standard_Boolean tangent = sin < 0.001; Standard_Boolean inside = 0; if (tangent) { E1 = FindEinF (E, F1); gp_Vec NNf1 = NextNormal(E1,F1); gp_Vec NNf2 = NextNormal(E2,F2); Vin2 = NNf2.Crossed(Vc2); inside = Vin2 * NNf1 < 0; } else { Vin2 = Nf2.Crossed(Vc2); inside = Vin2 * Nf1 < 0; } if (!CountDot) return inside; if (tangent) Vin2 = Nf2.Crossed(Vc2); else E1 = FindEinF (E, F1); Vc1 = Vc2; if (E1.Orientation() != E2.Orientation()) Vc1.Reverse(); Vin1 = Nf1.Crossed(Vc1); if (tangent) { Standard_Real N1N2 = Nf1 * Nf2; GoodOri = (Vin2 * Vin1 < 0) ? N1N2 > 0 : N1N2 < 0; } else { Standard_Real V1N2 = Vin1 * Nf2; GoodOri = ( inside ? V1N2 <= 0 : V1N2 >= 0); } Vin1.Normalize(); Vin2.Normalize(); Dot = Vin2 * Vin1; return inside; } #endif netgen-6.2.1905/libsrc/occ/Partition_Inter2d.jxx0000644000175000017500000000310413504650527020114 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter2d.jxx // Module : GEOM #include // netgen headers #ifndef _BRepAlgo_AsDes_HeaderFile #include #endif #ifndef _TopoDS_Face_HeaderFile #include #endif #ifndef _TopTools_MapOfShape_HeaderFile #include #endif #ifndef _TopoDS_Vertex_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopoDS_Edge_HeaderFile #include #endif #ifndef _Partition_Inter2d_HeaderFile #include "Partition_Inter2d.hxx" #endif netgen-6.2.1905/libsrc/occ/Partition_Loop.ixx0000644000175000017500000000206313504650527017520 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Loop.ixx // Module : GEOM #include "Partition_Loop.jxx" netgen-6.2.1905/libsrc/occ/Partition_Spliter.cxx0000644000175000017500000021013413504650527020223 0ustar kurtkurt#ifdef OCCGEOMETRY // GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Spliter.cxx // Author : Benedicte MARTIN // Module : GEOM // $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Spliter.cxx,v 1.7 2008/03/31 14:20:28 wabro Exp $ //using namespace std; #include #include "Partition_Inter2d.hxx" #include "Partition_Inter3d.hxx" #include "Partition_Loop2d.hxx" #include "Partition_Loop3d.hxx" #include "Partition_Spliter.ixx" #include "utilities.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEB //# define PART_PERF #endif #ifdef PART_PERF # include #endif //======================================================================= //function : isClosed //purpose : check id a shape is closed, ie is a solid or a closed shell //======================================================================= static Standard_Boolean isClosed(const TopoDS_Shape& theShape) { Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID); if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) { TopTools_IndexedDataMapOfShapeListOfShape MEF; TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF); for (Standard_Integer i=1; isClosed && i<=MEF.Extent(); ++i) isClosed = ( MEF(i).Extent() != 1 ); } return isClosed; } //======================================================================= //function : Partition_Spliter //purpose : constructor //======================================================================= Partition_Spliter::Partition_Spliter() { myAsDes = new BRepAlgo_AsDes; Clear(); } //======================================================================= //function : AddTool //purpose : add cutting tool that will _NOT_ be in result //======================================================================= void Partition_Spliter::AddTool(const TopoDS_Shape& S) { if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid TopoDS_Iterator it (S); for (; it.More(); it.Next()) { AddTool( it.Value()); myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape } return; } for (TopExp_Explorer exp(S,TopAbs_FACE); exp.More(); exp.Next()) { myMapTools.Add(exp.Current()); myFaceShapeMap.Bind( exp.Current(), S ); } if (isClosed( S )) myClosedShapes.Add( S ); } //======================================================================= //function : AddShape //purpose : add object Shape to be splited //======================================================================= void Partition_Spliter::AddShape(const TopoDS_Shape& S) { if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid TopoDS_Iterator it (S); for (; it.More(); it.Next()) { AddShape( it.Value()); myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape } return; } TopExp_Explorer exp(S,TopAbs_FACE); if (!exp.More()) { // do not split edges and vertices //myBuilder.Add( myShape, S ); return; } Standard_Integer nbFacesBefore = myMapFaces.Extent(); // not to add twice the same S for (; exp.More(); exp.Next()) { const TopoDS_Shape & aFace = exp.Current(); if ( ! myFaceShapeMap.IsBound( aFace )) // keep shape of tool face added as object myFaceShapeMap.Bind( aFace, S ); if (myMapFaces.Add( aFace )) myImagesFaces.SetRoot( aFace ); } if (nbFacesBefore == myMapFaces.Extent()) return; // solids must be processed before all if (S.ShapeType() == TopAbs_SOLID) myListShapes.Prepend(S); else myListShapes.Append(S); if (isClosed( S )) myClosedShapes.Add( S ); } //======================================================================= //function : Shape //purpose : return resulting compound //======================================================================= TopoDS_Shape Partition_Spliter::Shape() const { return myShape; } //======================================================================= //function : Clear //purpose : clear fields //======================================================================= void Partition_Spliter::Clear() { myDoneStep = TopAbs_SHAPE; myListShapes.Clear(); myMapFaces.Clear(); myMapTools.Clear(); myEqualEdges.Clear(); myNewSection.Clear(); myClosedShapes.Clear(); mySharedFaces.Clear(); myWrappingSolid.Clear(); myFaceShapeMap.Clear(); myInternalFaces.Clear(); myIntNotClFaces.Clear(); myAsDes->Clear(); myImagesFaces.Clear(); myImagesEdges.Clear(); myImageShape.Clear(); // myInter3d = Partition_Inter3d(myAsDes); Partition_Inter3d hinter3d (myAsDes); myInter3d = hinter3d; myAddedFacesMap.Clear(); } //======================================================================= //function : Compute //purpose : produce a result //======================================================================= void Partition_Spliter::Compute(const TopAbs_ShapeEnum Limit) { if ((Limit != TopAbs_SHAPE && myDoneStep == Limit) || (Limit == TopAbs_SHAPE && myDoneStep == TopAbs_SOLID)) return; myBuilder.MakeCompound( myShape ); TopTools_MapIteratorOfMapOfShape it; TopTools_ListIteratorOfListOfShape itl; TopExp_Explorer exp; #ifdef PART_PERF OSD_Chronometer aCron; #endif if (myDoneStep > TopAbs_VERTEX) { TopTools_ListOfShape aListFaces; aListFaces = myImagesFaces.Roots(); for (it.Initialize(myMapTools); it.More(); it.Next()) aListFaces.Append(it.Key()); #ifdef PART_PERF aCron.Start(); #endif //----------------------------------------------- // Intersection between faces //----------------------------------------------- // result is in myAsDes as a map Face - list of new edges; // special care is done for section edges, same domain faces and vertices: // data about them is inside myInter3d myInter3d.CompletPart3d(aListFaces, myFaceShapeMap); #ifdef PART_PERF MESSAGE("+++ CompletPart3d()"); aCron.Show( cout ); aCron.Reset(); aCron.Start(); #endif //----------------------------------------------- // Intersection of edges //----------------------------------------------- // add tool faces which must be reconstructed to myMapFaces too FindToolsToReconstruct(); #ifdef PART_PERF MESSAGE("+++ FindToolsToReconstruct()"); aCron.Show( cout ); aCron.Reset(); aCron.Start(); #endif // add existing vertices to edges of object faces in myAsDes TopTools_MapOfShape DoneEM; for ( it.Initialize(myMapFaces); it.More(); it.Next()) { const TopoDS_Shape& F = it.Key(); TopoDS_Face FForward = TopoDS::Face(F.Oriented(TopAbs_FORWARD)); for (exp.Init(FForward,TopAbs_EDGE); exp.More(); exp.Next()) { const TopoDS_Edge& E = TopoDS::Edge( exp.Current() ); myAsDes->Add(FForward,E); if (DoneEM.Add(E)) { TopoDS_Iterator itV(E); for (; itV.More(); itV.Next()) { const TopoDS_Vertex& V = TopoDS::Vertex( itV.Value()); myAsDes->Add(E, myInter3d.ReplaceSameDomainV( V, E )); } } } } // intersect edges that are descendants of a face in myAsDes TopTools_MapOfShape& Modif = myInter3d.TouchedFaces(); for ( it.Initialize(Modif); it.More(); it.Next()) { const TopoDS_Face& F = TopoDS::Face(it.Key()); Partition_Inter2d::CompletPart2d (myAsDes, F, myInter3d.NewEdges()); } // now myAsDes contains also new vertices made at edge intersection as // descendant of edges both new and old myDoneStep = TopAbs_VERTEX; #ifdef PART_PERF MESSAGE("+++ CompletPart2d()"); aCron.Show( cout ); aCron.Reset(); aCron.Start(); #endif } // if (myDoneStep > TopAbs_VERTEX) if (Limit == TopAbs_VERTEX) { // add new vertices to myShape for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) { if (! myAsDes->HasDescendant( it.Key() )) continue; itl.Initialize( myAsDes->Descendant( it.Key() )); for (; itl.More(); itl.Next()) myBuilder.Add ( myShape, itl.Value() ); } return; } if (myDoneStep > TopAbs_EDGE) { //----------------------------------------------- //----------------------------------------------- // ------- Reconstruction of all the edges.------ //----------------------------------------------- //----------------------------------------------- // ============== // cut new edges // ============== TopTools_ListOfShape LSE; // all edge splits for ( it.Initialize(myInter3d.NewEdges()); it.More(); it.Next()) { TopoDS_Vertex V1,V2; TopoDS_Edge EE = TopoDS::Edge(it.Key()); TopTools_ListOfShape aListV, aListF; aListV = myAsDes->Descendant(EE); // intersection vertices aListF = myAsDes->Ascendant(EE); // intersected faces if (aListV.IsEmpty()) continue; // new edge does not intersect any other edge // Add end vertices to new edges only if // one face is Tool and the other is Shape Standard_Boolean isTool1 = ! myMapFaces.Contains( aListF.First() ); Standard_Boolean isTool2 = ! myMapFaces.Contains( aListF.Last() ); if (isTool1 || isTool2) { TopExp::Vertices(EE,V1,V2); Standard_Real Tol = Max (BRep_Tool::Tolerance( V1 ), BRep_Tool::Tolerance( V2 )); gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); Standard_Boolean AddV1 = Standard_True; Standard_Boolean AddV2 = Standard_True; // add only if there is no intersection at end vertex for (itl.Initialize(aListV); itl.More(); itl.Next()) { const TopoDS_Vertex& Ve = TopoDS::Vertex(itl.Value()) ; Standard_Real Tol2 = Max ( Tol, BRep_Tool::Tolerance( Ve )); Tol2 *= Tol2; gp_Pnt P = BRep_Tool::Pnt(Ve); if (AddV1 && P.SquareDistance(P1) <= Tol2) AddV1 = Standard_False; if (AddV2 && P.SquareDistance(P2) <= Tol2) AddV2 = Standard_False; } if (AddV1) { aListV.Append(V1); myAsDes->Add(EE,V1); } if (AddV2) { aListV.Append(V2); myAsDes->Add(EE,V2); } } // cut new edges Standard_Integer NbV=aListV.Extent() ; if (NbV>1 || (NbV==1 && V1.IsSame(V2)) ) { TopTools_ListOfShape LNE; MakeEdges (EE,aListV, LNE); myImagesEdges.Bind(EE,LNE); LSE.Append( LNE ); } } // ============== // cut old edges // ============== for ( it.Initialize(myMapFaces); it.More(); it.Next()) { for (exp.Init( it.Key(), TopAbs_EDGE); exp.More(); exp.Next()) { const TopoDS_Edge& EE = TopoDS::Edge( exp.Current() ); if ( myImagesEdges.HasImage( EE )) continue; TopTools_ListOfShape LNE; const TopTools_ListOfShape& aListVV = myAsDes->Descendant(EE); MakeEdges (EE, aListVV, LNE); myImagesEdges.Bind(EE,LNE); LSE.Append( LNE ); } } #ifdef PART_PERF MESSAGE("+++ Cut Edges"); aCron.Show( cout ); aCron.Reset(); aCron.Start(); #endif // process same domain section edges MergeEqualEdges( LSE ); myDoneStep = TopAbs_EDGE; #ifdef PART_PERF MESSAGE("+++ MergeEqualEdges()"); aCron.Show( cout ); aCron.Reset(); aCron.Start(); #endif } // if (myDoneStep > TopAbs_EDGE) if (Limit == TopAbs_EDGE) { // add splits of old edges TopTools_ListIteratorOfListOfShape itNE; for (itl.Initialize( myListShapes );itl.More();itl.Next()) { if (myMapTools.Contains( itl.Value() )) continue; // skip tool faces for ( exp.Init( itl.Value(), TopAbs_EDGE ); exp.More(); exp.Next()) { itNE.Initialize( myImagesEdges.Image( exp.Current() )); for ( ; itNE.More(); itNE.Next()) myBuilder.Add ( myShape, itNE.Value() ); } } // add splits of new edges for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) { itNE.Initialize( myImagesEdges.Image( it.Key() )); for (; itNE.More(); itNE.Next()) myBuilder.Add ( myShape, itNE.Value() ); } return; } //----------------------------------------------- // split faces //----------------------------------------------- if (myDoneStep > TopAbs_FACE) { for (itl.Initialize(myListShapes);itl.More();itl.Next()) { TopoDS_Shape FacesComp = MakeFaces ( itl.Value()); // there is a cunning here: myImagesFaces keeps faces made by Loop2d // but some of them may be replaced with splits of same domain face // and myImageShape keeps ultimate result myImageShape.Bind( itl.Value(), FacesComp ); } myDoneStep = TopAbs_FACE; #ifdef PART_PERF MESSAGE("+++ MakeFaces()"); aCron.Show( cout ); aCron.Reset(); aCron.Start(); #endif } if (Limit == TopAbs_WIRE || Limit == TopAbs_FACE) { for (itl.Initialize(myListShapes);itl.More();itl.Next()) { if ( myMapTools.Contains( itl.Value() )) continue; // no result needed for a tool face const TopoDS_Shape& FacesComp = myImageShape.Image( itl.Value() ).First(); for ( exp.Init( FacesComp, Limit); exp.More(); exp.Next()) myBuilder.Add ( myShape, exp.Current()); } return; } //----------------------------------------------- // split and add solids and shells //----------------------------------------------- Standard_Boolean makeSolids = (Limit == TopAbs_SHAPE || Limit < TopAbs_SHELL); for (itl.Initialize(myListShapes);itl.More();itl.Next()) { const TopoDS_Shape & S = itl.Value(); if (S.ShapeType() > TopAbs_SHELL) continue; TopTools_ListOfShape NSL; // new shape list MakeShells (S , NSL); if (makeSolids && S.ShapeType() == TopAbs_SOLID ) MakeSolids( S, NSL ); // store new shells or solids TopTools_ListIteratorOfListOfShape itNSL (NSL); for ( ; itNSL.More(); itNSL.Next()) myBuilder.Add (myShape, itNSL.Value()); } #ifdef PART_PERF MESSAGE("+++ MakeShells()"); aCron.Show( cout ); #endif //----------------------------------------------- // add split faces //----------------------------------------------- for (itl.Initialize(myListShapes);itl.More();itl.Next()) { const TopoDS_Shape & S = itl.Value(); if (S.ShapeType() != TopAbs_FACE || myMapTools.Contains( S )) continue; TopoDS_Iterator itS( myImageShape.Image(S).First() ); for (; itS.More(); itS.Next()) if (! myAddedFacesMap.Contains( itS.Value() )) myBuilder.Add (myShape, itS.Value()); } myDoneStep = makeSolids ? TopAbs_SOLID : TopAbs_SHELL; } //======================================================================= //function : MakeSolids //purpose : make solids out of Shells //======================================================================= void Partition_Spliter::MakeSolids(const TopoDS_Shape & theSolid, TopTools_ListOfShape & theShellList) { // for a solid wrapping other shells or solids without intersection, // it is necessary to find shells making holes in it TopTools_ListOfShape aNewSolids; // result TopTools_ListOfShape aHoleShells; TopoDS_Shape anInfinitePointShape; Standard_Boolean isWrapping = myWrappingSolid.Contains( theSolid ); if (!isWrapping && !theShellList.IsEmpty()) { // check if theSolid initially has internal shells TopoDS_Iterator aShellExp (theSolid); aShellExp.Next(); isWrapping = aShellExp.More(); } TopTools_ListIteratorOfListOfShape aShellIt(theShellList); for ( ; aShellIt.More(); aShellIt.Next()) { const TopoDS_Shape & aShell = aShellIt.Value(); // check if a shell is a hole if (isWrapping && IsInside (anInfinitePointShape, aShell)) aHoleShells.Append( aShell ); else { // make a solid from a shell TopoDS_Solid Solid; myBuilder.MakeSolid( Solid ); myBuilder.Add (Solid, aShell); aNewSolids.Append (Solid); } } // find an outer shell most close to each hole shell TopTools_DataMapOfShapeShape aInOutMap; for (aShellIt.Initialize( aHoleShells ); aShellIt.More(); aShellIt.Next()) { const TopoDS_Shape & aHole = aShellIt.Value(); TopTools_ListIteratorOfListOfShape aSolisIt (aNewSolids); for ( ; aSolisIt.More(); aSolisIt.Next()) { const TopoDS_Shape & aSolid = aSolisIt.Value(); if (! IsInside( aHole, aSolid )) continue; if ( aInOutMap.IsBound (aHole)) { const TopoDS_Shape & aSolid2 = aInOutMap( aHole ); if ( IsInside( aSolid, aSolid2 )) { aInOutMap.UnBind( aHole ); aInOutMap.Bind ( aHole, aSolid ); } } else aInOutMap.Bind ( aHole, aSolid ); } // add aHole to a solid if (aInOutMap.IsBound( aHole )) myBuilder.Add ( aInOutMap( aHole ), aHole ); } theShellList.Clear(); theShellList.Append( aNewSolids ); } //======================================================================= //function : FindFacesInside //purpose : return compound of faces of other shapes that are // inside . // is an object shape. // makes avoid faces that do not form a // closed shell // makes return already added faces //======================================================================= TopoDS_Shape Partition_Spliter::FindFacesInside(const TopoDS_Shape& theShape, const Standard_Boolean CheckClosed, const Standard_Boolean All) { // ================================================ // check if internal faces have been already found // ================================================ TopExp_Explorer expl; if (myInternalFaces.IsBound( theShape )) { TopoDS_Shape aIntFComp = myInternalFaces.Find ( theShape ); TopoDS_Shape aIntRemFComp = myIntNotClFaces.Find ( theShape ); expl.Init( aIntRemFComp, TopAbs_FACE); if (CheckClosed || !expl.More()) return aIntFComp; TopoDS_Compound C; myBuilder.MakeCompound( C ); // add removed faces for (; expl.More(); expl.Next()) myBuilder.Add( C, expl.Current() ); // add good internal faces for (expl.Init( aIntFComp, TopAbs_FACE); expl.More(); expl.Next()) myBuilder.Add( C, expl.Current() ); return C; } // =================================== // get data for internal faces search // =================================== // compound of split faces of theShape const TopoDS_Shape& CSF = myImageShape.Image(theShape).First(); TopTools_MapOfShape MSE, MFP; TopTools_DataMapOfShapeListOfShape DMSEFP; TopTools_MapIteratorOfMapOfShape itm; TopTools_ListOfShape EmptyL; // MSE filling: map of new section edges of CSF for (expl.Init(CSF,TopAbs_EDGE); expl.More(); expl.Next()) { const TopoDS_Shape & resE = expl.Current() ; if (myNewSection.Contains( resE )) // only new edges MSE.Add(resE); } // DMEF: map edge of CSF - faces of CSF TopTools_IndexedDataMapOfShapeListOfShape DMEF; TopExp::MapShapesAndAncestors(CSF, TopAbs_EDGE, TopAbs_FACE, DMEF); // Fill // 1. MFP - a map of faces to process: map of resulting faces except // those of theShape; we`ll add to C those of them which are inside CSF // 2. DMSEFP - edge of MSE => faces of MFP TopTools_ListIteratorOfListOfShape itl; for (itl.Initialize(myListShapes);itl.More();itl.Next()) { const TopoDS_Shape& aShape = itl.Value(); if ( theShape.IsSame( aShape )) continue; // fill maps // iterate on split faces of aShape TopoDS_Iterator itF ( myImageShape.Image(aShape).First() ); for ( ; itF.More(); itF.Next()) { const TopoDS_Shape& sf = itF.Value(); MFP.Add(sf); // iterate on edges of split faces of aShape, // add to DMSEFP edges that are new for (expl.Init( sf, TopAbs_EDGE ); expl.More(); expl.Next()) { TopoDS_Shape se = expl.Current(); if ( MSE.Contains(se)) {// section edge if (!DMSEFP.IsBound(se)) DMSEFP.Bind(se,EmptyL); DMSEFP(se).Append(sf); } } } } // add tool faces having section edges on faces of theShape to MFP and DMSEFP; // such tool faces need not to be reconstructed and so they are not in myListShapes for (itm.Initialize(myMapTools); itm.More(); itm.Next()) { const TopoDS_Shape & aToolFace = itm.Key(); if (myMapFaces.Contains( aToolFace )) continue; MFP.Add(aToolFace); for (expl.Init( aToolFace, TopAbs_EDGE ); expl.More(); expl.Next()) { TopoDS_Shape se = expl.Current(); if ( MSE.Contains( se )) {// section edge if (!DMSEFP.IsBound( se )) DMSEFP.Bind( se, EmptyL ); DMSEFP( se ).Append( aToolFace ); } } } // =========================== // find faces inside theShape // =========================== Standard_Boolean skipAlreadyAdded = Standard_False; Standard_Boolean GoodOri, inside; Standard_Real dot; TopTools_ListOfShape KeepFaces; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit; // iterate on section edges, check faces of other shapes // sharing section edges and put internal faces to KeepFaces for (Mapit.Initialize(DMSEFP); Mapit.More() ; Mapit.Next() ) { // a new edge of theShape const TopoDS_Edge& E = TopoDS::Edge (Mapit.Key()); // an original edge of which E is a split const TopoDS_Edge& OrigE = TopoDS::Edge ( myImagesEdges.Root( E )); // does OrigE itself splits a face Standard_Boolean isSectionE = myInter3d.IsSectionEdge ( OrigE ); // split faces of other shapes sharing E TopTools_ListOfShape& LSF = DMSEFP.ChangeFind(E); itl.Initialize( LSF ); while (itl.More()) { // a split faces of other shape TopoDS_Face aFace1 = TopoDS::Face(itl.Value()); // remove aFace1 form DMSEFP and MFP LSF.Remove( itl ); // == itl.Next(); if (!MFP.Remove( aFace1 )) continue; // was not is MFP ( i.e already checked) // check if aFace1 was already added to 2 shells if (!All && myAddedFacesMap.Contains( aFace1 ) && myAddedFacesMap.Contains( aFace1.Reversed() )) { skipAlreadyAdded = Standard_True; continue; } // find another face which originates from the same face as aFace1: // usually aFace2 is internal if aFace1 is not and vice versa TopoDS_Shape anOrigFace = aFace1; if (myImagesFaces.IsImage(aFace1)) anOrigFace = myImagesFaces.Root(aFace1); TopoDS_Shape aFace2; if ( !isSectionE ) { while (itl.More()) { aFace2 = itl.Value(); if (!MFP.Contains( aFace2 )) { LSF.Remove( itl ); continue; } if (anOrigFace.IsSame( myImagesFaces.Root( aFace2 ))) break; itl.Next(); } if (itl.More()) { // aFace2 found, remove it from maps LSF.Remove( itl ); MFP.Remove(aFace2); } else aFace2.Nullify(); itl.Initialize( LSF ); } // check that anOrigFace is not same domain with CSF faces it intersects const TopTools_ListOfShape& FL = DMEF.FindFromKey(E); //faces of CSF sharing E const TopoDS_Shape& origF1 = myImagesFaces.Root(FL.First()); const TopoDS_Shape& origF2 = myImagesFaces.Root(FL.Last()); Standard_Boolean sameDom1 = anOrigFace.IsSame( origF1 ); Standard_Boolean sameDom2 = anOrigFace.IsSame( origF2 ); if (!(sameDom1 || sameDom2) && myInter3d.HasSameDomainF( anOrigFace )) { sameDom1 = myInter3d.IsSameDomainF( anOrigFace, origF1); if (origF1 == origF2) sameDom2 = sameDom1; else myInter3d.IsSameDomainF( anOrigFace, origF2); } if (sameDom1 && sameDom2) continue; if ((sameDom1 || sameDom2)) { inside = Partition_Loop3d::IsInside (E, TopoDS::Face(FL.First()), TopoDS::Face(FL.Last()), 1, dot, GoodOri); if (inside || (dot + Precision::Angular() >= 1.0)) continue; // E is convex between origF1 and origF2 or they are tangent } // keep one of found faces //face of CSF sharing E const TopoDS_Shape& aShapeFace = sameDom1 ? FL.Last() : FL.First(); // analyse aFace1 state inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace), aFace1, 1, dot, GoodOri); if (inside && isSectionE) { // aFace1 must be tested with both adjacent faces of CSF const TopoDS_Shape& aShapeFace2 = sameDom1 ? FL.First() : FL.Last(); if (aShapeFace2 != aShapeFace) inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace2), aFace1, 1, dot, GoodOri); } // store internal face if (inside) KeepFaces.Append(aFace1); else if (!aFace2.IsNull()) { if (dot + Precision::Angular() >= 1.0) { // aFace2 state is not clear, it will be analysed alone, // put it back to the maps MFP.Add( aFace2 ); LSF.Append( aFace2 ); } else KeepFaces.Append(aFace2); } } } // =================================================== // add not distributed faces connected with KeepFaces // =================================================== // ultimate list of internal faces TopTools_ListOfShape KeptFaces; // add to MFP unsplit tool faces as well, they may be connected with // tool faces interfering with theShape for ( itm.Initialize(myMapTools); itm.More(); itm.Next() ) { const TopoDS_Shape& aToolFace = itm.Key(); if (!myImageShape.HasImage(aToolFace)) MFP.Add (aToolFace); } if (MFP.IsEmpty()) KeptFaces.Append (KeepFaces); while (!KeepFaces.IsEmpty()) { // KeepEdges : map of edges of faces kept last time TopTools_IndexedMapOfShape KeepEdges; for ( itl.Initialize(KeepFaces); itl.More(); itl.Next() ) { TopExp::MapShapes( itl.Value(), TopAbs_EDGE, KeepEdges); KeptFaces.Append( itl.Value() ); } KeepFaces.Clear(); // keep faces connected with already kept faces by KeepEdges for ( itm.Initialize(MFP); itm.More(); itm.Next() ) { const TopoDS_Shape& FP = itm.Key(); for (expl.Init(FP,TopAbs_EDGE); expl.More(); expl.Next()) { const TopoDS_Shape& se = expl.Current(); if (!MSE.Contains(se) && KeepEdges.Contains(se) ) { KeepFaces.Append(FP); MFP.Remove(FP); break; } } } } // =============================================================== // here MFP contains faces outer of theShape and those of shapes // which do not interfere with theShape at all and between which // there may be those wrapped by theShape and whose faces may be // needed to be returned as well // =============================================================== Standard_Boolean isSolid = (theShape.ShapeType() == TopAbs_SOLID); if (All || isSolid) // All is for sub-result removal { // loop on not used faces; checked faces will be removed from MFP // during the loop for ( itm.Initialize( MFP ); itm.More(); itm.Next() ) { const TopoDS_Shape & aFace = itm.Key(); // a shape which aFace originates from TopoDS_Shape anOrigShape = GetOriginalShape( aFace ); // find out if all split faces of anOrigShape are not in MFP // and by the way remove them from MFP Standard_Boolean isAllOut = Standard_True; TopoDS_Shape aSplitFaces = anOrigShape; if (myImageShape.HasImage(anOrigShape)) aSplitFaces = myImageShape.Image(anOrigShape).First(); TopTools_ListOfShape aSplitFaceL; // faces candidate to be kept for (expl.Init( aSplitFaces, TopAbs_FACE ); expl.More(); expl.Next()) { const TopoDS_Shape & aSpFace = expl.Current(); // a tool face which became object has image but the whole tool shape has not if (myImageShape.HasImage( aSpFace )) { TopExp_Explorer exF (myImageShape.Image( aSpFace ).First(), TopAbs_FACE ); for ( ; exF.More(); exF.Next() ) { aSplitFaceL.Append( exF.Current() ); if ( ! MFP.Remove( exF.Current() ) && isAllOut ) // a shared face might be removed from MFP during a prev loop isAllOut = mySharedFaces.Contains( exF.Current() ); } } else { aSplitFaceL.Append( aSpFace ); if ( ! MFP.Remove( aSpFace ) && isAllOut) // a shared face might be removed from MFP during a prev loop isAllOut = mySharedFaces.Contains( aSpFace ); } } itm.Initialize( MFP ); // iterate remaining faces if ( !isAllOut ) continue; // classify anOrigShape against theShape if (IsInside (anOrigShape, theShape)) { if (isSolid && myClosedShapes.Contains( anOrigShape )) // to make a special care at solid reconstruction myWrappingSolid.Add ( theShape ); // keep faces of an internal shape anOrigShape KeptFaces.Append( aSplitFaceL ); } } } // ==================================================== // check if kept faces form a shell without free edges // ==================================================== DMEF.Clear(); // edge - kept faces MFP.Clear(); // reuse it for wrong faces if (CheckClosed) { for (itl.Initialize(KeptFaces); itl.More(); itl.Next() ) TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, DMEF); Standard_Integer i, nb = DMEF.Extent(); Standard_Boolean isClosed = Standard_False; while (!isClosed) { isClosed = Standard_True; for (i=1; isClosed && i<=nb; ++i) { const TopoDS_Shape& E = DMEF.FindKey( i ); if (! BRep_Tool::Degenerated( TopoDS::Edge( E )) && ! MSE.Contains( E )) isClosed = ( DMEF(i).Extent() != 1 ); } if (!isClosed) { const TopoDS_Shape& F = DMEF.FindFromIndex( i-1 ).First(); // bad face MFP.Add( F ); // remove bad face from DMEF for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) { const TopoDS_Shape& E = expl.Current(); TopTools_ListOfShape& FL = DMEF.ChangeFromKey( E ); for (itl.Initialize( FL ); itl.More(); itl.Next() ) { if ( F.IsSame( itl.Value() )) { FL.Remove( itl ); break; } } } } } } // ============== // make a result // ============== TopoDS_Compound C; // compound of removed internal faces TopoDS_Compound CNotCl; myBuilder.MakeCompound(C); myBuilder.MakeCompound(CNotCl); // add to compounds for (itl.Initialize(KeptFaces); itl.More(); itl.Next() ) { TopoDS_Shape & aIntFace = itl.Value(); if (! MFP.Contains( aIntFace )) myBuilder.Add( C, aIntFace); else myBuilder.Add( CNotCl, aIntFace); } if (!skipAlreadyAdded && CheckClosed) { myInternalFaces.Bind( theShape, C ); myIntNotClFaces.Bind( theShape, CNotCl ); } return C; } //======================================================================= //function : MakeShell //purpose : split S into compound of shells //======================================================================= void Partition_Spliter::MakeShells(const TopoDS_Shape& S, TopTools_ListOfShape& NS) { Partition_Loop3d ShellMaker; // get compound of split faces of S const TopoDS_Shape& FacesComp = myImageShape.Image(S).First(); ShellMaker.AddConstFaces( FacesComp ); // add split faces inside S if (myClosedShapes.Contains( S )) { TopoDS_Shape InternalFacesComp = FindFacesInside(S, Standard_True); ShellMaker.AddSectionFaces( InternalFacesComp ); } NS = ShellMaker.MakeShells( myAddedFacesMap ); // Add faces added to new shell to myAddedFacesMap: // avoid rebuilding twice commont part of 2 solids. TopTools_ListIteratorOfListOfShape itS(NS); while ( itS.More()) { TopExp_Explorer expF (itS.Value(), TopAbs_FACE); for (; expF.More(); expF.Next()) myAddedFacesMap.Add (expF.Current()); itS.Next(); } } //======================================================================= //function : findEqual //purpose : compare edges of EL1 against edges of EL2, // Result is in EMM binding EL1 edges to list of equal edges. // Edges are considered equall only if they have same vertices. // ==True makes consider same edges as equal // Put in all equal edges //======================================================================= static void findEqual (const TopTools_ListOfShape& EL1, const TopTools_ListOfShape& EL2, const Standard_Boolean addSame, TopTools_DataMapOfShapeListOfShape& EEM, TopTools_MapOfShape& AllEqMap) { // map vertices to edges for EL2 TopTools_DataMapOfShapeListOfShape VEM; TopTools_ListIteratorOfListOfShape itE1, itE2(EL2); TopoDS_Iterator itV; TopTools_ListOfShape emptyL; for (; itE2.More(); itE2.Next()) { for (itV.Initialize( itE2.Value() ); itV.More(); itV.Next()) { const TopoDS_Shape& V = itV.Value(); if (! VEM.IsBound( V ) ) VEM.Bind( V, emptyL); VEM( V ).Append( itE2.Value()); } } gp_Vec D1, D2; gp_Pnt P; Standard_Real f,l,u,tol; Handle(Geom_Curve) C1, C2; Extrema_ExtPC Extrema; TopoDS_Vertex V1, V2, V3, V4; AllEqMap.Clear(); for (itE1.Initialize(EL1); itE1.More(); itE1.Next()) { const TopoDS_Edge& E1 = TopoDS::Edge( itE1.Value()); if (BRep_Tool::Degenerated( E1 ) || AllEqMap.Contains (E1)) continue; TopExp::Vertices( E1, V1, V2 ); if (VEM.IsBound(V1)) itE2.Initialize( VEM(V1) ); for (; itE2.More(); itE2.Next()) { const TopoDS_Edge& E2 = TopoDS::Edge( itE2.Value()); if (BRep_Tool::Degenerated( E2 ) || AllEqMap.Contains (E2)) continue; if (E1.IsSame(E2)) { if (!addSame) continue; } else { TopExp::Vertices( E2, V3, V4); if (!V2.IsSame(V4) && !V2.IsSame(V3)) continue; // E1 and E2 have same vertices // check D1 at end points. C2 = BRep_Tool::Curve( E2, f,l); C1 = BRep_Tool::Curve( E1, f,l); u = BRep_Tool::Parameter(V1,E1); C1->D1(u, P, D1); u = BRep_Tool::Parameter(V1.IsSame(V3) ? V3 : V4, E2); C2->D1(u, P, D2); D1.Normalize(); D2.Normalize(); if (Abs(D1*D2) + Precision::Angular() < 1.0) continue; if (! V1.IsSame(V2)) { u = BRep_Tool::Parameter(V2,E1); C1->D1(u, P, D1); u = BRep_Tool::Parameter(V2.IsSame(V3) ? V3 : V4, E2); C2->D1(u, P, D2); D1.Normalize(); D2.Normalize(); if (Abs(D1*D2) + Precision::Angular() < 1.0) continue; } // check distance at a couple of internal points tol = Max(BRep_Tool::Tolerance(E1), BRep_Tool::Tolerance(E2)); GeomAdaptor_Curve AC1(C1); Extrema.Initialize(AC1,f,l); Standard_Boolean ok = Standard_True, hasMin = Standard_False; BRep_Tool::Range( E2, f, l); Standard_Integer i=1, nbi=3; for (; iValue( f+(l-f)*i/nbi )); Standard_Integer j=1, nbj=Extrema.NbExt(); for (; j<=nbj && ok; ++j) { if (Extrema.IsMin(j)) { hasMin = Standard_True; // ok = Extrema.Value(j) <= tol; // V6.3 ok = Extrema.SquareDistance(j) <= tol; // V6.5 } } } if ( !hasMin || !ok) continue; } // bind E2 to E1 in EEM if (!EEM.IsBound(E1)) { EEM.Bind (E1, emptyL); AllEqMap.Add (E1); } EEM(E1).Append(E2); AllEqMap.Add (E2); } } } //======================================================================= //function : MakeFaces //purpose : split faces of S, return compound of new faces //======================================================================= TopoDS_Shape Partition_Spliter::MakeFaces (const TopoDS_Shape& S) { TopoDS_Compound C; myBuilder.MakeCompound(C); TopTools_ListIteratorOfListOfShape itl, itNE; TopExp_Explorer exp(S,TopAbs_FACE); for (; exp.More(); exp.Next()) { const TopoDS_Face& F = TopoDS::Face(exp.Current()); TopTools_ListOfShape LNF; if (myImagesFaces.HasImage( F )) { myImagesFaces.LastImage( F, LNF ); TopAbs_Orientation oriF = F.Orientation(); for ( itl.Initialize( LNF ); itl.More(); itl.Next()) itl.Value().Orientation( oriF ); } else { Partition_Loop2d loops; loops.Init(F); TopTools_IndexedMapOfShape EM; TopExp::MapShapes( F, TopAbs_EDGE, EM); TopTools_MapOfShape AddedEqualM, EqualSeamM; Standard_Boolean needRebuild = Standard_False; // add splits to loops // LE: old edges + new unsplit edges const TopTools_ListOfShape& LE = myAsDes->Descendant(F); for (itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge( itl.Value() ); Standard_Boolean isSectionE = myInter3d.IsSectionEdge(E); Standard_Boolean isNewE = !EM.Contains( E ); // LSE: list of split edges TopTools_ListOfShape LSE; myImagesEdges.LastImage(E,LSE); // splits of E or E itself for (itNE.Initialize(LSE); itNE.More(); itNE.Next()) { TopoDS_Edge NE = TopoDS::Edge( itNE.Value() ); Standard_Boolean isSameE = NE.IsSame ( E ); if ( isNewE || isSectionE || !isSameE) { if (AddedEqualM.Contains( NE )) { // a seam must be twice in a loop if (!BRep_Tool::IsClosed( E, F ) || !EqualSeamM.Add( NE )) continue; } if (isNewE) { if (isSectionE) { if ( ! myInter3d.IsSplitOn( NE, E, F) ) continue; } else { TopoDS_Vertex V1,V2; TopExp::Vertices(NE,V1,V2); const TopTools_ListOfShape& EL1 = myAsDes->Ascendant(V1); const TopTools_ListOfShape& EL2 = myAsDes->Ascendant(V2); if ( EL1.Extent() < 2 && EL2.Extent() < 2 ) continue; } } else { NE.Orientation( E.Orientation()); if (!isSameE) { // orient NE because it may be a split of other edge Standard_Real f,l,u; Handle(Geom_Curve) C3d = BRep_Tool::Curve( E,f,l ); Handle(Geom_Curve) NC3d = BRep_Tool::Curve( NE,f,l); if ( C3d != NC3d) { gp_Vec D1, ND1; gp_Pnt P; TopoDS_Vertex V = TopExp::FirstVertex(NE); u = BRep_Tool::Parameter(V,NE); NC3d->D1 (u, P, ND1); u = BRep_Tool::Parameter(V,E); C3d ->D1 (u, P, D1); if (ND1.Dot(D1) < 0) NE.Reverse(); } } } if (myEqualEdges.Contains( NE )) AddedEqualM.Add( NE ); needRebuild = Standard_True; } if (isNewE || isSectionE) myNewSection.Add( NE ); if (isNewE) loops.AddSectionEdge(NE); else loops.AddConstEdge(NE); } } //------------------- // Build the faces. //------------------- if (needRebuild) { loops.Perform(); loops.WiresToFaces(myImagesEdges); LNF = loops.NewFaces(); myImagesFaces.Bind(F,LNF); // replace the result faces that have already been built // during same domain faces reconstruction done earlier if (myInter3d.HasSameDomainF( F )) { // build map edge to same domain faces: EFM TopTools_IndexedDataMapOfShapeListOfShape EFM; TopTools_MapOfShape SDFM; // avoid doubling itl.Initialize( myInter3d.SameDomain( F )); for (; itl.More(); itl.Next()) { if ( !myImagesFaces.HasImage( itl.Value() )) continue; // loop on splits of a SD face TopTools_ListIteratorOfListOfShape itNF; itNF.Initialize (myImagesFaces.Image( itl.Value() )); for ( ; itNF.More(); itNF.Next()) { TopoDS_Shape SDF = itNF.Value(); if (myImagesFaces.HasImage( SDF )) // already replaced SDF = myImagesFaces.Image( SDF ).First(); if (SDFM.Add (SDF)) TopExp::MapShapesAndAncestors(SDF, TopAbs_EDGE, TopAbs_FACE, EFM); } } // do replace faces in the LNF TopTools_ListOfShape LOF; if ( !EFM.IsEmpty() ) itl.Initialize( LNF ); while (itl.More()) { const TopoDS_Shape& NF = itl.Value(); TopExp_Explorer expE ( NF, TopAbs_EDGE ); const TopoDS_Edge& E = TopoDS::Edge (expE.Current()); if (EFM.Contains( E )) { const TopTools_ListOfShape& SDFL = EFM.FindFromKey( E ); TopoDS_Shape SDF = SDFL.First(); Standard_Boolean GoodOri; Standard_Real dot; Partition_Loop3d::IsInside (E, TopoDS::Face(NF), TopoDS::Face(SDF), 1, dot, GoodOri); if (dot < 0) { // NF and SDF are on different side of E if (SDFL.Extent() == 1) { itl.Next(); continue; } else SDF = SDFL.Last(); // next face must be on the same side } gp_Vec V1 = Partition_Loop3d::Normal( E, TopoDS::Face( NF )); gp_Vec V2 = Partition_Loop3d::Normal( E, TopoDS::Face( SDF )); if (V1*V2 < 0) SDF.Reverse(); if (!myImagesFaces.HasImage( NF )) myImagesFaces.Bind( NF, SDF ); // mySharedFaces is used in FindFacesInside() mySharedFaces.Add( SDF ); LOF.Prepend ( SDF ); LNF.Remove (itl); } else itl.Next(); } LNF.Append (LOF); } } // if (needRebuild) else { LNF.Append( F ); myImagesFaces.Bind(F,LNF); } } // if (myImagesFaces.HasImage( F )) // fill the resulting compound for (itl.Initialize(LNF); itl.More(); itl.Next()) myBuilder.Add ( C, itl.Value()); } // loop on faces of S return C; } //======================================================================= //function : Tri //purpose : //======================================================================= static void Tri(const TopoDS_Edge& E, TopTools_SequenceOfShape& Seq, const Partition_Inter3d & theInter3d) { Standard_Boolean Invert = Standard_True; Standard_Real U1,U2; TopoDS_Vertex V1,V2; while (Invert) { Invert = Standard_False; for ( Standard_Integer i = 1; i < Seq.Length(); i++) { V1 = TopoDS::Vertex(Seq.Value(i)); V2 = TopoDS::Vertex(Seq.Value(i+1)); V1.Orientation(TopAbs_INTERNAL); V2.Orientation(TopAbs_INTERNAL); U1 = BRep_Tool::Parameter(V1,E); U2 = BRep_Tool::Parameter(V2,E); if (IsEqual(U1,U2)) { if (theInter3d.ReplaceSameDomainV( V1, E ).IsSame( V1 )) Seq.Remove(i+1); // remove V2 else Seq.Remove(i); i--; continue; } if (U2 < U1) { Seq.Exchange(i,i+1); Invert = Standard_True; } } } } //======================================================================= //function : MakeEdges //purpose : cut E by vertices VOnE, return list of new edges NE //======================================================================= void Partition_Spliter::MakeEdges (const TopoDS_Edge& E, const TopTools_ListOfShape& VOnE, TopTools_ListOfShape& NE ) const { TopoDS_Edge WE = E; WE.Orientation(TopAbs_FORWARD); Standard_Real U1,U2, f, l; TopoDS_Vertex V1,V2,VF,VL; BRep_Tool::Range(WE,f,l); TopExp::Vertices(WE,VF,VL); if (VOnE.Extent() < 3) { // do not rebuild not cut edge if (( VF.IsSame( VOnE.First() ) && VL.IsSame( VOnE.Last() )) || VL.IsSame( VOnE.First() ) && VF.IsSame( VOnE.Last() ) ) { NE.Append( E ); return; } } TopTools_SequenceOfShape SV; TopTools_ListIteratorOfListOfShape itv(VOnE); TopTools_MapOfOrientedShape VM( VOnE.Extent() ); for (; itv.More(); itv.Next()) if ( VM.Add( itv.Value() )) SV.Append(itv.Value()); Tri( WE, SV, myInter3d ); if (SV.Length() < 3) { // do not rebuild not cut edge if (( VF.IsSame( SV.First() ) && VL.IsSame( SV.Last() )) || VL.IsSame( SV.First() ) && VF.IsSame( SV.Last() ) ) { NE.Append( E ); return; } } Standard_Integer iVer, NbVer = SV.Length(); //---------------------------------------------------------------- // Construction of the new edges . //---------------------------------------------------------------- if (VF.IsSame(VL)) { // closed edge if (NbVer==1) SV.Append( SV.First() ); else if (!SV.First().IsSame(SV.Last())) { Standard_Boolean isFirst=0; Standard_Real minDU = 1.e10; TopoDS_Vertex endV = Partition_Inter2d::FindEndVertex(VOnE, f,l, E, isFirst,minDU); if (endV.IsSame(SV.First())) SV.Append(endV); else if (endV.IsSame(SV.Last())) SV.Prepend(endV); else MESSAGE ("END VERTEX IS IN SEQUNCE MIDDLE"); } NbVer = SV.Length(); } for (iVer=1; iVer < NbVer; iVer++) { V1 = TopoDS::Vertex(SV(iVer)); V2 = TopoDS::Vertex(SV(iVer+1)); TopoDS_Shape NewEdge = WE.EmptyCopied(); V1.Orientation(TopAbs_FORWARD); myBuilder.Add (NewEdge,V1); V2.Orientation(TopAbs_REVERSED); myBuilder.Add (NewEdge,V2); if (iVer==1) U1 = f; else { V1.Orientation(TopAbs_INTERNAL); U1=BRep_Tool::Parameter(V1,WE); } if (iVer+1 == NbVer) U2 = l; else { V2.Orientation(TopAbs_INTERNAL); U2=BRep_Tool::Parameter(V2,WE); } if (Abs(U1-U2) <= Precision::PConfusion()) { MESSAGE( "MakeEdges(), EQUAL PARAMETERS OF DIFFERENT VERTICES"); continue; } TopoDS_Edge EE=TopoDS::Edge(NewEdge); myBuilder.Range (EE,U1,U2); TopoDS_Edge NEdge = TopoDS::Edge(NewEdge); myBuilder.SameParameter(NEdge,Standard_False); Standard_Real tol = 1.0e-2; Standard_Boolean flag = BRep_Tool::SameParameter(NEdge); if (!flag) { BRepLib::SameParameter(NEdge,tol); } NE.Append(NEdge.Oriented(E.Orientation())); } } //======================================================================= //function : MergeEqualEdges //purpose : find equal edges, choose ones to keep and make // them have pcurves on all faces they are shared by //======================================================================= void Partition_Spliter::MergeEqualEdges (const TopTools_ListOfShape& LSE) { // find equal edges // map: edge - equal edges TopTools_DataMapOfShapeListOfShape EEM( LSE.Extent() ); findEqual (LSE, LSE, 0, EEM, myEqualEdges); TopTools_ListOfShape EEL; // list of equal edges TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itM (EEM); for ( ; itM.More(); itM.Next()) { EEL = itM.Value(); EEL.Append( itM.Key() ); // choose an edge to keep, section edges have priority TopoDS_Edge EKeep; TopTools_ListIteratorOfListOfShape itEE (EEL); for (; itEE.More(); itEE.Next()) { EKeep = TopoDS::Edge( itEE.Value() ); const TopoDS_Edge& EKeepOrig = TopoDS::Edge( myImagesEdges.Root( EKeep )); if (myInter3d.IsSectionEdge( EKeepOrig )) break; } // update edge images and build pcurves Standard_Real f,l, tol; for (itEE.Initialize (EEL); itEE.More(); itEE.Next()) { const TopoDS_Edge& E = TopoDS::Edge( itEE.Value() ); if ( E.IsSame( EKeep )) continue; // 1. build pcurves of the kept edge on faces where replaced edges exist const TopoDS_Edge& EReplOrig = TopoDS::Edge( myImagesEdges.Root( E )); TopTools_ListOfShape FL; FL = myAsDes->Ascendant( EReplOrig ); Standard_Integer iFace, iFirstSectionFace = FL.Extent() + 1; // add faces where the replaced edge is a section edge if (myInter3d.IsSectionEdge( EReplOrig )) { TopTools_ListIteratorOfListOfShape seIt; seIt.Initialize( myInter3d.SectionEdgeFaces ( EReplOrig )); for ( ; seIt.More(); seIt.Next()) FL.Append( seIt.Value() ); } // loop on faces TopTools_ListIteratorOfListOfShape itF (FL); for ( iFace = 1 ; itF.More(); itF.Next(), ++iFace ) { const TopoDS_Face& F = TopoDS::Face( itF.Value()); Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( EKeep, F, f,l); if (pc.IsNull()) { Handle(Geom_Curve) C3d = BRep_Tool::Curve( EKeep, f, l); C3d = new Geom_TrimmedCurve( C3d, f,l); pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol); if (pc.IsNull()) { MESSAGE (" CANNOT BUILD PCURVE "); } myBuilder.UpdateEdge( EKeep, pc, F, tol); } if (iFace >= iFirstSectionFace || !BRep_Tool::IsClosed( EReplOrig, F )) continue; // build the second pcurve for a seam TopoDS_Vertex V = TopExp::FirstVertex( EKeep ); Standard_Real Ukeep = BRep_Tool::Parameter( V, EKeep ); Standard_Real Urepl = BRep_Tool::Parameter( V, E ); TopoDS_Edge EReplRev = E; EReplRev.Reverse(); Handle(Geom2d_Curve) pcRepl1 = BRep_Tool::CurveOnSurface( E, F, f,l); Handle(Geom2d_Curve) pcRepl2 = BRep_Tool::CurveOnSurface( EReplRev, F, f,l); gp_Pnt2d p1r, p2r, pk; p1r = pcRepl1->Value( Urepl ); p2r = pcRepl2->Value( Urepl ); pk = pc->Value( Ukeep ); // suppose that pk is equal to either p1r or p2r Standard_Boolean isUPeriod = ( Abs( p1r.X() - p2r.X() ) > Abs( p1r.Y() - p2r.Y() )); Standard_Boolean is1Equal; if (isUPeriod) is1Equal = ( Abs( p1r.X() - pk.X() ) < Abs( p2r.X() - pk.X() )); else is1Equal = ( Abs( p1r.Y() - pk.Y() ) < Abs( p2r.Y() - pk.Y() )); Handle(Geom2d_Curve) pc2 = Handle(Geom2d_Curve)::DownCast ( pc->Translated( pk, is1Equal ? p2r : p1r ) ); if (E.Orientation() == TopAbs_REVERSED) is1Equal = !is1Equal; if (is1Equal) myBuilder.UpdateEdge( EKeep, pc, pc2, F, tol); else myBuilder.UpdateEdge( EKeep, pc2, pc, F, tol); } // loop on a Faces where a replaced edge exists // 2. update edge images according to replacement if (myImagesEdges.HasImage( E )) myImagesEdges.Remove( E ); myImagesEdges.Bind( E, EKeep ); } // loop on a list of equal edges EEL } // loop on a map of equal edges EEM } //======================================================================= //function : KeepShapesInside //purpose : remove shapes that are outside of S from resul //======================================================================= void Partition_Spliter::KeepShapesInside (const TopoDS_Shape& S) { TopoDS_Iterator it; if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid for (it.Initialize( S ); it.More(); it.Next()) KeepShapesInside( it.Value()); return; } Standard_Boolean isTool = Standard_False; if (!myImageShape.HasImage( S )) { isTool = CheckTool( S ); if (!isTool) return; } // build map of internal faces TopTools_IndexedMapOfShape MIF; TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True); TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF ); TopoDS_Compound C; myBuilder.MakeCompound(C); TopAbs_ShapeEnum anInternalShapeType = TopAbs_SHAPE; if (!MIF.IsEmpty()) { // leave in the result only those shapes having a face in MIF for (it.Initialize( myShape ); it.More(); it.Next()) { const TopoDS_Shape & aResShape = it.Value(); TopExp_Explorer expResF( aResShape, TopAbs_FACE ); for (; expResF.More(); expResF.Next()) { if ( MIF.Contains( expResF.Current())) { myBuilder.Add( C, aResShape ); if (aResShape.ShapeType() < anInternalShapeType) anInternalShapeType = aResShape.ShapeType(); break; } } } } // may be S was not split by internal faces then it is missing // in myShape, add it if (!isTool && (anInternalShapeType > TopAbs_SOLID || S.ShapeType() > TopAbs_SOLID)) { TopTools_IndexedMapOfShape MSF; // map of split faces of S TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MSF); // find a shape having all faces in MSF for (it.Initialize( myShape ); it.More(); it.Next()) { TopExp_Explorer expResF( it.Value(), TopAbs_FACE ); for (; expResF.More(); expResF.Next()) { if (! MSF.Contains( expResF.Current())) break; } if (! expResF.More()) { myBuilder.Add( C, it.Value() ); break; } } } myShape = C; } //======================================================================= //function : RemoveShapesInside //purpose : remove shapes that are inside S from resul //======================================================================= void Partition_Spliter::RemoveShapesInside (const TopoDS_Shape& S) { TopoDS_Iterator it; if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid for (it.Initialize( S ); it.More(); it.Next()) RemoveShapesInside( it.Value()); return; } Standard_Boolean isTool = Standard_False; if (!myImageShape.HasImage( S )) { isTool = CheckTool( S ); if (!isTool) return; } TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True); TopTools_IndexedMapOfShape MIF; // map of internal faces TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF); if (MIF.IsEmpty()) return; // add to MIF split faces of S if (myImageShape.HasImage(S)) TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MIF); // leave in the result only those shapes not having all face in MIF TopoDS_Compound C; myBuilder.MakeCompound(C); // RMF : faces of removed shapes that encounter once TopTools_MapOfShape RFM; for (it.Initialize( myShape ); it.More(); it.Next()) { TopExp_Explorer expResF( it.Value(), TopAbs_FACE ); for (; expResF.More(); expResF.Next()) if (!MIF.Contains( expResF.Current())) break; if (expResF.More()) // add shape to result myBuilder.Add( C, it.Value() ); else // add faces of a removed shape to RFM for (expResF.ReInit(); expResF.More(); expResF.Next()) { const TopoDS_Shape& F = expResF.Current(); if ( ! RFM.Remove ( F )) RFM.Add( F ); } } if (!isTool) { // rebuild S, it must remain in the result Standard_Boolean isClosed = Standard_False; switch (S.ShapeType()) { case TopAbs_SOLID : isClosed = Standard_True; break; case TopAbs_SHELL: { TopTools_IndexedDataMapOfShapeListOfShape MEF; TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, MEF); Standard_Integer i; for (i=1; isClosed && i<=MEF.Extent(); ++i) isClosed = ( MEF(i).Extent() != 1 ); break; } default: isClosed = Standard_False; } if (isClosed) { // add to a new shape external faces of removed shapes, ie those in RFM TopoDS_Shell Shell; myBuilder.MakeShell( Shell ); // exclude redundant internal face with edges encounterd only once TopTools_IndexedDataMapOfShapeListOfShape MEF; TopTools_MapIteratorOfMapOfShape itF (RFM); for ( ; itF.More(); itF.Next()) TopExp::MapShapesAndAncestors(itF.Key(), TopAbs_EDGE, TopAbs_FACE, MEF); // add only faces forming a closed shell for (itF.Reset() ; itF.More(); itF.Next()) { TopExp_Explorer expE (itF.Key(), TopAbs_EDGE); for (; expE.More(); expE.Next()) if (MEF.FindFromKey(expE.Current()).Extent() == 1) break; if (!expE.More()) myBuilder.Add( Shell, itF.Key()); } if (S.ShapeType() == TopAbs_SOLID) { TopoDS_Solid Solid; myBuilder.MakeSolid( Solid ); myBuilder.Add (Solid, Shell); myBuilder.Add (C, Solid); } else myBuilder.Add (C, Shell); } else { if (myImageShape.HasImage( S )) { for (it.Initialize( myImageShape.Image(S).First()); it.More(); it.Next()) myBuilder.Add (C, it.Value()); } } } myShape = C; } //======================================================================= //function : CheckTool //purpose : Return True if is a tool shape. Prepare tool // faces of for the search of internal faces. //======================================================================= Standard_Boolean Partition_Spliter::CheckTool(const TopoDS_Shape& S) { // suppose S has not an image Standard_Boolean isTool = Standard_False; TopoDS_Compound C; myBuilder.MakeCompound( C ); TopExp_Explorer expF( S, TopAbs_FACE); for (; expF.More(); expF.Next()) { const TopoDS_Face& F = TopoDS::Face( expF.Current() ); if (myMapTools.Contains( F )) isTool = Standard_True; else continue; if (myImagesFaces.HasImage( F )) { // F has been reconstructed TopAbs_Orientation Fori = F.Orientation(); TopTools_ListOfShape LNF; myImagesFaces.LastImage( F, LNF); TopTools_ListIteratorOfListOfShape itF (LNF); for ( ; itF.More(); itF.Next()) myBuilder.Add( C, itF.Value().Oriented(Fori) ); continue; } Standard_Boolean hasSectionE = myInter3d.HasSectionEdge( F ); Standard_Boolean hasNewE = myAsDes->HasDescendant( F ); if (!hasSectionE && !hasNewE) { // F intersects nothing myBuilder.Add( C, F ); continue; } // make an image for F TopoDS_Face NF = F; NF.Orientation(TopAbs_FORWARD); NF = TopoDS::Face( NF.EmptyCopied() ); // make a copy TopoDS_Wire NW; myBuilder.MakeWire( NW ); // add edges, as less as possible TopTools_ListOfShape NEL; TopTools_ListIteratorOfListOfShape itNE; if (hasSectionE) { // add section edges TopExp_Explorer expE; for ( ; expE.More(); expE.Next()) { if (! myImagesEdges.HasImage( expE.Current() )) continue; myImagesEdges.LastImage( expE.Current(), NEL ); for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next()) myBuilder.Add ( NW, itNE.Value()); } } if (hasNewE) { // add new edges NEL = myAsDes->Descendant( F ); for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next()) { TopTools_ListOfShape SEL; // splits myImagesEdges.LastImage( itNE.Value(), SEL ); TopTools_ListIteratorOfListOfShape itSE (SEL); for ( ; itSE.More(); itSE.Next()) myBuilder.Add ( NW, itSE.Value()); } } myBuilder.Add( NF, NW ); myBuilder.Add (C, NF); NF.Orientation( F.Orientation() ); // NF is most probably invalid myImagesFaces.Bind (F, NF); } if (isTool) myImageShape.Bind (S, C); return isTool; } //======================================================================= //function : IsInside //purpose : Return True if the first vertex of S1 inside S2. // If S1.IsNull(), check infinite point against S2. //======================================================================= Standard_Boolean Partition_Spliter::IsInside (const TopoDS_Shape& theS1, const TopoDS_Shape& theS2) { BRepClass3d_SolidClassifier aClassifier( theS2 ); TopExp_Explorer expl( theS1, TopAbs_VERTEX ); if (!expl.More()) aClassifier.PerformInfinitePoint( ::RealSmall()); else { const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() ); aClassifier.Perform (BRep_Tool::Pnt( aVertex ), BRep_Tool::Tolerance( aVertex )); } return ( aClassifier.State() == TopAbs_IN ); } //======================================================================= //function : GetOriginalShape //purpose : Return the shape aShape originates from. aShape // should be a face or more complex result shape //======================================================================= TopoDS_Shape Partition_Spliter::GetOriginalShape(const TopoDS_Shape& theShape) const { TopoDS_Shape anOrigShape; TopExp_Explorer expl( theShape, TopAbs_FACE); if (expl.More()) { TopoDS_Shape aFace = expl.Current(); if (myImagesFaces.IsImage( aFace )) aFace = myImagesFaces.Root( aFace ); anOrigShape = myFaceShapeMap.Find( aFace ); } return anOrigShape; } //======================================================================= //function : FindToolsToReconstruct //purpose : find and store as objects tools which interfere // with solids or are inside solids without // an interference //======================================================================= void Partition_Spliter::FindToolsToReconstruct() { if (myMapTools.IsEmpty()) return; Standard_Integer nbFoundTools = 0; // build edge - face map in order to detect interference with section edges TopTools_IndexedDataMapOfShapeListOfShape EFM; TopTools_MapIteratorOfMapOfShape aMapIt; for (aMapIt.Initialize(myMapTools); aMapIt.More(); aMapIt.Next()) TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM); for (aMapIt.Initialize(myMapFaces); aMapIt.More(); aMapIt.Next()) TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM); TopTools_MapOfShape aCurrentSolids, aCheckedShapes; // faces cut by new edges TopTools_MapOfShape & aSectionFaces = myInter3d.TouchedFaces(); // keep solids interfering with each other in aCurrentSolids map // and add tool faces intersecting solids as object shapes TopTools_ListIteratorOfListOfShape itS, itF, itCF, itE; for (itS.Initialize( myListShapes ); itS.More(); itS.Next()) { TopExp_Explorer expSo (itS.Value(), TopAbs_SOLID); for (; expSo.More(); expSo.Next()) { // check if a solid has been already processed const TopoDS_Shape & aSo = expSo.Current(); if (!aCheckedShapes.Add( aSo )) continue; aCurrentSolids.Add( aSo ); // faces to check TopTools_ListOfShape aFacesToCheck; TopExp_Explorer exp( aSo, TopAbs_FACE ); for ( ; exp.More(); exp.Next()) aFacesToCheck.Append ( exp.Current()); // add other shapes interefering with a solid. // iterate faces to check while appending new ones for (itCF.Initialize (aFacesToCheck) ; itCF.More(); itCF.Next()) { const TopoDS_Shape& aCheckFace = itCF.Value(); // if (!aCheckedShapes.Add( aCheckFace )) // continue; // find faces interfering with aCheckFace TopTools_ListOfShape anIntFaces; // ** 1. faces intersecting aCheckFace with creation of new edges on it if ( myAsDes->HasDescendant( aCheckFace )) { // new edges on aCheckFace const TopTools_ListOfShape& NEL = myAsDes->Descendant( aCheckFace ); for (itE.Initialize( NEL); itE.More(); itE.Next()) { const TopoDS_Shape & aNewEdge = itE.Value(); if (!aCheckedShapes.Add( aNewEdge )) continue; // faces interfering by aNewEdge itF.Initialize (myAsDes->Ascendant( aNewEdge )); for (; itF.More(); itF.Next()) if (aCheckFace != itF.Value()) anIntFaces.Append( itF.Value() ); // ** 2. faces having section edge aNewEdge on aFacesToCheck if (EFM.Contains( aNewEdge)) { itF.Initialize ( EFM.FindFromKey (itE.Value())); for (; itF.More(); itF.Next()) if (aCheckFace != itF.Value()) anIntFaces.Append( itF.Value() ); } } } // ** 3. faces cut by edges of aCheckFace TopExp_Explorer expE (aCheckFace, TopAbs_EDGE); for ( ; expE.More(); expE.Next()) { const TopoDS_Shape & aCheckEdge = expE.Current(); if (aCheckedShapes.Add( aCheckEdge ) && myInter3d.IsSectionEdge( TopoDS::Edge( aCheckEdge ))) { itF.Initialize( myInter3d.SectionEdgeFaces( TopoDS::Edge( aCheckEdge ))); for (; itF.More(); itF.Next()) if (aCheckFace != itF.Value()) anIntFaces.Append( itF.Value() ); } } // process faces interfering with aCheckFace and shapes they // belong to for (itF.Initialize (anIntFaces); itF.More(); itF.Next()) { const TopoDS_Shape & F = itF.Value(); if (! aCheckedShapes.Add( F )) continue; Standard_Boolean isTool = myMapTools.Contains( F ); if (isTool && myFaceShapeMap( aCheckFace ).ShapeType() == TopAbs_SOLID ) { // a tool interfering with a solid if (aSectionFaces.Contains( F )) AddShape( F ); ++ nbFoundTools; if (nbFoundTools == myMapTools.Extent()) return; } const TopoDS_Shape & S = myFaceShapeMap( F ); if (aCheckedShapes.Add( S )) { // a new shape interefering with aCurrentSolids is found if (!isTool && S.ShapeType() == TopAbs_SOLID) aCurrentSolids.Add ( S ); // add faces to aFacesToCheck list for ( exp.Init( S, TopAbs_FACE ); exp.More(); exp.Next()) aFacesToCheck.Append ( exp.Current() ); } } } // loop on aFacesToCheck // Here aCurrentSolids contains all solids interfering with each other. // aCheckedShapes contains all faces belonging to shapes included // in or interfering with aCurrentSolids or previously checked solids. // Test if tool faces that do not interefere with other shapes are // wrapped by any of aCurrentSolids TopTools_MapIteratorOfMapOfShape aSolidIt (aCurrentSolids); for ( ; aSolidIt.More(); aSolidIt.Next()) { const TopoDS_Shape & aSolid = aSolidIt.Key(); TopTools_MapOfShape aCheckedTools( myMapTools.Extent() ); TopTools_MapIteratorOfMapOfShape aToolIt (myMapTools); for ( ; aToolIt.More(); aToolIt.Next()) { const TopoDS_Shape & aToolFace = aToolIt.Key(); if (aCheckedShapes.Contains( aToolFace ) || // already found aCheckedTools.Contains( aToolFace )) // checked against aSolid continue; const TopoDS_Shape & aToolShape = myFaceShapeMap( aToolFace ); TopExp_Explorer aToolFaceIt( aToolShape, TopAbs_FACE ); Standard_Boolean isInside = IsInside( aToolShape, aSolid ); for ( ; aToolFaceIt.More(); aToolFaceIt.Next() ) { const TopoDS_Shape & aTool = aToolFaceIt.Current(); aCheckedTools.Add( aTool ); if (isInside) { if (aSectionFaces.Contains( aTool )) AddShape( aTool ); ++ nbFoundTools; if (nbFoundTools == myMapTools.Extent()) return; aCheckedShapes.Add( aTool ); } } } } } // loop on solid shapes } } #endif netgen-6.2.1905/libsrc/occ/python_occ.cpp0000644000175000017500000001354113504650527016700 0ustar kurtkurt#ifdef NG_PYTHON #ifdef OCCGEOMETRY #include <../general/ngpython.hpp> #include #include using namespace netgen; namespace netgen { extern std::shared_ptr ng_geometry; } DLL_HEADER void ExportNgOCC(py::module &m) { py::class_, NetgenGeometry> (m, "OCCGeometry", R"raw_string(Use LoadOCCGeometry to load the geometry from a *.step file.)raw_string") .def(py::init<>()) .def(NGSPickle()) .def("Heal",[](OCCGeometry & self, double tolerance, bool fixsmalledges, bool fixspotstripfaces, bool sewfaces, bool makesolids, bool splitpartitions) { self.tolerance = tolerance; self.fixsmalledges = fixsmalledges; self.fixspotstripfaces = fixspotstripfaces; self.sewfaces = sewfaces; self.makesolids = makesolids; self.splitpartitions = splitpartitions; self.HealGeometry(); self.BuildFMap(); },py::arg("tolerance")=1e-3, py::arg("fixsmalledges")=true, py::arg("fixspotstripfaces")=true, py::arg("sewfaces")=true, py::arg("makesolids")=true, py::arg("splitpartitions")=false,R"raw_string(Heal the OCCGeometry.)raw_string",py::call_guard()) .def("_visualizationData", [] (shared_ptr occ_geo) { std::vector vertices; std::vector trigs; std::vector normals; std::vector min = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; std::vector max = {std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::lowest()}; std::vector surfnames; auto box = occ_geo->GetBoundingBox(); for(int i = 0; i < 3; i++) { min[i] = box.PMin()[i]; max[i] = box.PMax()[i]; } occ_geo->BuildVisualizationMesh(0.01); gp_Pnt2d uv; gp_Pnt pnt; gp_Vec n; gp_Pnt p[3]; int count = 0; for (int i = 1; i <= occ_geo->fmap.Extent(); i++) { surfnames.push_back("occ_surface" + to_string(i)); auto face = TopoDS::Face(occ_geo->fmap(i)); auto surf = BRep_Tool::Surface(face); TopLoc_Location loc; BRepAdaptor_Surface sf(face, Standard_False); BRepLProp_SLProps prop(sf, 1, 1e-5); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) cout << "cannot visualize face " << i << endl; trigs.reserve(trigs.size() + triangulation->NbTriangles()*4); vertices.reserve(vertices.size() + triangulation->NbTriangles()*3*3); normals.reserve(normals.size() + triangulation->NbTriangles()*3*3); for (int j = 1; j < triangulation->NbTriangles()+1; j++) { auto triangle = (triangulation->Triangles())(j); for (int k = 1; k < 4; k++) p[k-1] = (triangulation->Nodes())(triangle(k)).Transformed(loc); for (int k = 1; k < 4; k++) { vertices.insert(vertices.end(),{float(p[k-1].X()), float(p[k-1].Y()), float(p[k-1].Z())}); trigs.insert(trigs.end(),{count, count+1, count+2,i}); count += 3; uv = (triangulation->UVNodes())(triangle(k)); prop.SetParameters(uv.X(), uv.Y()); if (prop.IsNormalDefined()) n = prop.Normal(); else { gp_Vec a(p[0], p[1]); gp_Vec b(p[0], p[2]); n = b^a; } if (face.Orientation() == TopAbs_REVERSED) n*= -1; normals.insert(normals.end(),{float(n.X()), float(n.Y()), float(n.Z())}); } } } py::gil_scoped_acquire ac; py::dict res; py::list snames; for(auto name : surfnames) snames.append(py::cast(name)); res["vertices"] = MoveToNumpy(vertices); res["triangles"] = MoveToNumpy(trigs); res["normals"] = MoveToNumpy(normals); res["surfnames"] = snames; res["min"] = MoveToNumpy(min); res["max"] = MoveToNumpy(max); return res; }, py::call_guard()) ; m.def("LoadOCCGeometry",FunctionPointer([] (const string & filename) { cout << "load OCC geometry"; ifstream ist(filename); OCCGeometry * instance = new OCCGeometry(); instance = LoadOCC_STEP(filename.c_str()); ng_geometry = shared_ptr(instance, NOOP_Deleter); return ng_geometry; }),py::call_guard()); m.def("GenerateMesh", FunctionPointer([] (shared_ptr geo, MeshingParameters ¶m) { auto mesh = make_shared(); SetGlobalMesh(mesh); mesh->SetGeometry(geo); ng_geometry = geo; try { geo->GenerateMesh(mesh,param); } catch (NgException ex) { cout << "Caught NgException: " << ex.What() << endl; } return mesh; }),py::call_guard()) ; } PYBIND11_MODULE(libNgOCC, m) { ExportNgOCC(m); } #endif // OCCGEOMETRY #endif // NG_PYTHON netgen-6.2.1905/libsrc/occ/Partition_Inter3d.cxx0000644000175000017500000007071113504650527020116 0ustar kurtkurt#ifdef OCCGEOMETRY // GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter3d.cxx // Author : Benedicte MARTIN // Module : GEOM // $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Inter3d.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $ //using namespace std; #include #include "Partition_Inter2d.hxx" #include "Partition_Inter3d.ixx" #include "utilities.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEB #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //======================================================================= //function : Partition_Inter3d //purpose : //======================================================================= Partition_Inter3d::Partition_Inter3d() { } //======================================================================= //function : Partition_Inter3d //purpose : //======================================================================= Partition_Inter3d::Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes) :myAsDes(AsDes) { mySectionEdgesAD = new BRepAlgo_AsDes; } //======================================================================= //function : CompletPart3d //purpose : FaceShapeMap is just to know the shape a face belongs to //======================================================================= void Partition_Inter3d::CompletPart3d(const TopTools_ListOfShape& SetOfFaces1, const TopTools_DataMapOfShapeShape& FaceShapeMap) { if (myAsDes.IsNull()) myAsDes = new BRepAlgo_AsDes; TopTools_ListIteratorOfListOfShape it; //--------------------------------------------------------------- // Construction of bounding boxes. //--------------------------------------------------------------- BRep_Builder B; TopoDS_Compound CompOS; B.MakeCompound(CompOS); for (it.Initialize(SetOfFaces1); it.More(); it.Next()) B.Add(CompOS, it.Value()); TopOpeBRepTool_BoxSort BOS; BOS.AddBoxesMakeCOB(CompOS,TopAbs_FACE); for (it.Initialize(SetOfFaces1); it.More(); it.Next()) { TopoDS_Face F1 = TopoDS::Face(it.Value()); // avoid intersecting faces of one shape TopoDS_Shape S1; if (FaceShapeMap.IsBound(F1)) S1 = FaceShapeMap.Find(F1); // to filter faces sharing an edge TopTools_IndexedMapOfShape EM; TopExp::MapShapes( F1, TopAbs_EDGE, EM); TColStd_ListIteratorOfListOfInteger itLI = BOS.Compare(F1); for (; itLI.More(); itLI.Next()) { TopoDS_Face F2 = TopoDS::Face(BOS.TouchedShape(itLI)); if (F1.IsSame(F2) || IsDone(F1,F2)) continue; TopoDS_Shape S2; if (FaceShapeMap.IsBound(F2)) S2 = FaceShapeMap.Find(F2); if (!S1.IsNull() && S1.IsSame(S2)) continue; // descendants of one shape TopExp_Explorer expE (F2, TopAbs_EDGE); for ( ; expE.More(); expE.Next()) if (EM.Contains( expE.Current() )) break; if (expE.More()) { // faces have a common edge, check if they are a tool and a face // generated by the tool in another shape; in that case they are // to be intersected TopLoc_Location L1, L2; Handle(Geom_Surface) S1 = BRep_Tool::Surface( F1, L1 ); Handle(Geom_Surface) S2 = BRep_Tool::Surface( F2, L2 ); if ( S1 != S2 || L1 != L2 ) continue; } F1.Orientation(TopAbs_FORWARD); F2.Orientation(TopAbs_FORWARD); FacesPartition(F1,F2); } // mark as modified a face which has at least one new edge if (!myAsDes->HasDescendant( F1 )) continue; TopTools_ListIteratorOfListOfShape itE (myAsDes->Descendant( F1 )); for ( ; itE.More(); itE.Next()) { if (myNewEdges.Contains( itE.Value())) { myTouched.Add( F1 ); break; } } } } //======================================================================= //function : PutInBounds //purpose : //======================================================================= static void PutInBounds (const TopoDS_Face& F, const TopoDS_Edge& E, Handle(Geom2d_Curve)& C2d) { Standard_Real umin,umax,vmin,vmax; Standard_Real f,l; BRep_Tool::Range(E,f,l); TopLoc_Location L; // Recup S avec la location pour eviter la copie. Handle (Geom_Surface) S = BRep_Tool::Surface(F,L); if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { S = (*(Handle_Geom_RectangularTrimmedSurface*)&S)->BasisSurface(); } if (!S->IsUPeriodic() && !S->IsVPeriodic()) return; BRepTools::UVBounds(F,umin,umax,vmin,vmax); gp_Pnt2d Pf = C2d->Value(f); gp_Pnt2d Pl = C2d->Value(l); const Standard_Real Um = 0.34*f + 0.66*l; gp_Pnt2d Pm = C2d->Value( Um ); // sometimes on shpere, pcurve is out of domain by V though S is // UPeriodic, sometimes it is in domain but nonetheless it has // wrong position. // Check pcurve position by 3D point if (S->IsKind(STANDARD_TYPE( Geom_SphericalSurface ))) { // get point on the surface gp_Pnt Ps = S->Value( Pm.X(), Pm.Y() ); // get point on the edge Handle(Geom_Curve) C = BRep_Tool::Curve( E, f, l ); gp_Pnt Pc = C->Value( Um ); // compare points Standard_Real TolE = BRep_Tool::Tolerance( E ); if ( Pc.SquareDistance( Ps ) * 0.95 < TolE * TolE ) return; // OK // find good UV for Pc: project Pc on S GeomAdaptor_Surface SA (S); Extrema_ExtPS anExtPS (Pc, SA, SA.UResolution( TolE ), SA.VResolution( TolE )); if (anExtPS.IsDone()) { Standard_Integer i, nbExt = anExtPS.NbExt(); Extrema_POnSurf aPOnSurf; for (i = 1; i <= nbExt; ++i ) // if (anExtPS.Value( i ) <= TolE) // V6.3 if (anExtPS.SquareDistance( i ) <= TolE) // V6.5 { aPOnSurf = anExtPS.Point( i ); break; } if (i <= nbExt) { // a point found Standard_Real u, v; aPOnSurf.Parameter( u, v ); gp_Pnt2d aGoodPm ( u, v ); C2d->Translate( Pm , aGoodPm ); } } } //--------------- // Recadre en U. //--------------- if (S->IsUPeriodic()) { Standard_Real period = S->UPeriod(); Standard_Real eps = period*1.e-6; Standard_Real minC = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X()); Standard_Real maxC = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X()); Standard_Real du = 0.; if (minC< umin - eps) { du = (int((umin - minC)/period) + 1)*period; } if (minC > umax + eps) { du = -(int((minC - umax)/period) + 1)*period; } if (du != 0) { gp_Vec2d T1(du,0.); C2d->Translate(T1); minC += du; maxC += du; } // Ajuste au mieux la courbe dans le domaine. if (maxC > umax +100*eps) { Standard_Real d1 = maxC - umax; Standard_Real d2 = umin - minC + period; if (d2 < d1) du =-period; if ( du != 0.) { gp_Vec2d T2(du,0.); C2d->Translate(T2); } } } //------------------ // Recadre en V. //------------------ if (S->IsVPeriodic()) { Standard_Real period = S->VPeriod(); Standard_Real eps = period*1.e-6; Standard_Real minC = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y()); Standard_Real maxC = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y()); Standard_Real dv = 0.; if (minC< vmin - eps) { dv = (int((vmin - minC)/period) + 1)*period; } if (minC > vmax + eps) { dv = -(int((minC - vmax)/period) + 1)*period; } if (dv != 0) { gp_Vec2d T1(0.,dv); C2d->Translate(T1); minC += dv; maxC += dv; } // Ajuste au mieux la courbe dans le domaine. if (maxC > vmax +100*eps) { Standard_Real d1 = maxC - vmax; Standard_Real d2 = vmin - minC + period; if (d2 < d1) dv =-period; if ( dv != 0.) { gp_Vec2d T2(0.,dv); C2d->Translate(T2); } } } } //======================================================================= //function : Inter3D //purpose : //======================================================================= void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, const TopoDS_Face& F2, TopTools_ListOfShape& L) { BRep_Builder B; // fill the data Structure Handle(TopOpeBRepDS_HDataStructure) DatStr = new TopOpeBRepDS_HDataStructure(); TopOpeBRep_DSFiller DSFiller; DSFiller.Insert(F1,F2,DatStr); // define the GeomTool used by the DSFiller : // compute BSpline of degree 1 on intersection curves. Standard_Real tol3dAPPROX = 1e-7; Standard_Real tol2dAPPROX = 1e-7; TopOpeBRepTool_GeomTool GT2 (TopOpeBRepTool_APPROX); GT2.SetTolerances(tol3dAPPROX,tol2dAPPROX); TopOpeBRepDS_BuildTool BT(GT2); // Perform Section TopOpeBRepBuild_Builder TopB(BT); TopB.Perform(DatStr); // =============== // Store new edges // =============== L.Clear(); TopOpeBRepDS_CurveExplorer cex(DatStr->DS()); for (; cex.More(); cex.Next()) { const TopOpeBRepDS_Curve& CDS = cex.Curve(); Standard_Integer ic = cex.Index(); Handle(Geom2d_Curve) pc1 = CDS.Curve1(); Handle(Geom2d_Curve) pc2 = CDS.Curve2(); TopTools_ListIteratorOfListOfShape itLE = TopB.NewEdges(ic); while (itLE.More()) { TopoDS_Edge E = TopoDS::Edge(itLE.Value()); PutInBounds (F1,E,pc1); PutInBounds (F2,E,pc2); B.UpdateEdge (E,pc1,F1,0.); B.UpdateEdge (E,pc2,F2,0.); L.Append (E); itLE.Next(); if (itLE.More()) { pc1 = Handle(Geom2d_Curve)::DownCast(pc1->Copy()); pc2 = Handle(Geom2d_Curve)::DownCast(pc2->Copy()); } } } // ======================== // store same domain faces // ======================== if ( DatStr->HasSameDomain( F1 )) { TopTools_ListOfShape emptyList; if (!mySameDomainFM.IsBound(F1)) mySameDomainFM.Bind(F1,emptyList); if (!mySameDomainFM.IsBound(F2)) mySameDomainFM.Bind(F2,emptyList); mySameDomainFM(F1).Append(F2); mySameDomainFM(F2).Append(F1); } // ==================== // Store section edges // ==================== const TopOpeBRepDS_DataStructure& DS = DatStr->DS(); Standard_Integer j,i,nse = DS.NbSectionEdges(); if (nse == 0) return; TopoDS_Vertex V, sdeV1, sdeV2; TopTools_MapOfShape MV; TopTools_ListOfShape LSE; // list of section edges TopoDS_Face dummyF; for (i = 1; i <= nse; i++) { const TopoDS_Edge & se = DS.SectionEdge(i); if (! TopB.IsSplit(se,TopAbs_ON)) continue; LSE.Append( se ); // add vertices where section edges interferes with other // edges as its descendant in myAsDes TopoDS_Edge sde, oe; // same domain, other edge if (DatStr->HasSameDomain(se)) { sde = TopoDS::Edge( DatStr->SameDomain(se).Value() ); TopExp::Vertices( sde, sdeV1, sdeV2); } TColStd_MapOfInteger MIV; // indices of added edges TopOpeBRepDS_PointIterator itP (DS.ShapeInterferences( se )); itP.SupportKind( TopOpeBRepDS_EDGE ); // loop on intersections of se for (; itP.More(); itP.Next()) { oe = TopoDS::Edge( DS.Shape( itP.Support())); if (itP.IsVertex()) { // there is a vertex at intersection if ( !MIV.Add( itP.Current() )) continue; V = TopoDS::Vertex( DS.Shape( itP.Current())); if ( !sde.IsNull() && (V.IsSame(sdeV1) || V.IsSame(sdeV2)) ) oe = sde; V = ReplaceSameDomainV( V , oe ); V.Orientation( TopAbs_INTERNAL); B.UpdateVertex( V, itP.Parameter(), se, 0.); // AddVonE() sets real U } else { // create a new vertex at the intersection point const TopOpeBRepDS_Point& DSP = DS.Point( itP.Current()); V = BRepLib_MakeVertex( DSP.Point() ); V.Orientation( TopAbs_INTERNAL); B.UpdateVertex( V, itP.Parameter(), se, DSP.Tolerance()); // make V be on the other edge TopOpeBRepDS_PointIterator itOP (DS.ShapeInterferences( oe )); for (; itOP.More(); itOP.Next()) { const TopOpeBRepDS_Point& ODSP = DS.Point( itOP.Current()); if ( DSP.IsEqual (ODSP)) { B.UpdateVertex( V, itOP.Parameter(), TopoDS::Edge(oe), ODSP.Tolerance()); break; } } } // add V on the both intersecting edges TopoDS_Vertex addedV = Partition_Inter2d::AddVonE( V,se,oe,myAsDes,dummyF); if (!addedV.IsSame( V )) mySameDomainVM.Bind (V, addedV); // equal vertex is already there MV.Add( addedV ); // to ease storage of vertices of ON splits } } // add section edge to the face it intersects and find // splits ON that do not have same domain pair TopB.SplitSectionEdges(); // let TopB find ON splits TopTools_MapOfShape SPM; // map of ON splits TopTools_IndexedMapOfShape ME[2]; TopExp::MapShapes( F1, TopAbs_EDGE, ME[1]); TopExp::MapShapes( F2, TopAbs_EDGE, ME[0]); TopTools_ListIteratorOfListOfShape itSP, itLSE (LSE); while ( itLSE.More() ) { TopoDS_Edge se = TopoDS::Edge( itLSE.Value() ); // move itLSE to the next se Standard_Integer ancRank = DS.AncestorRank(se); if (ME[ancRank-1].Contains( se )) { LSE.Remove( itLSE ); // se is an edge of face it intersects continue; } else { itLSE.Next(); } const TopoDS_Face& F = (ancRank == 1) ? F2 : F1; // add se to face but dont add twice TopTools_ListIteratorOfListOfShape itE( myAsDes->Descendant( F )); if (myAsDes->HasDescendant( F )) { for ( ; itE.More(); itE.Next()) if (se.IsSame( itE.Value() )) break; } if (!itE.More()) { myAsDes->Add( F, se ); // check se pcurve on F Standard_Real tol, f,l, umin=1e100, umax=-1e100; Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( se, F, f,l); if (pc.IsNull()) { itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); for ( ; itSP.More(); itSP.Next()) { const TopoDS_Edge& E = TopoDS::Edge ( itSP.Value()); BRep_Tool::Range(E, f, l); umin = Min( umin, f); umax = Max( umax, l); } Handle(Geom_Curve) C3d = BRep_Tool::Curve( se, f, l); if (umin < umax) // sometimes umin == umax for closed edge C3d = new Geom_TrimmedCurve( C3d, umin, umax); pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol); if (pc.IsNull()) { MESSAGE (" CANNOT BUILD PCURVE "); } B.UpdateEdge( se, pc, F, tol); } } // to detect splits that do not have same domain pair // ie which split a face into parts and not pass by its boundary itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); for ( ; itSP.More(); itSP.Next()) { const TopoDS_Shape& SP = itSP.Value(); if (!SPM.Add( SP )) SPM.Remove( SP ); } } // store vertices of ON splits and bind section edges to faces for (itLSE.Initialize (LSE); itLSE.More(); itLSE.Next()) { const TopoDS_Shape& se = itLSE.Value(); Standard_Integer ancRank = DS.AncestorRank(se); TopoDS_Face F = (ancRank == 1) ? F2 : F1; // add vertices of ON splits which have no same domain pair Standard_Boolean added = Standard_False; itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); for ( ; itSP.More(); itSP.Next()) { if (!SPM.Contains( itSP.Value() )) continue; const TopoDS_Edge& S = TopoDS::Edge ( itSP.Value()); added = Standard_True; mySectionEdgesAD->Add( F, se ); TopoDS_Vertex VS[2]; TopExp::Vertices (S, VS[0], VS[1]); for (j=0; j<2; ++j) { if (mySameDomainVM.IsBound( VS[j] )) VS[j] = TopoDS::Vertex( mySameDomainVM( VS[j] )); if ( !MV.Contains( VS[j] )) { // find equal vertex on se - point interference gp_Pnt P1 = BRep_Tool::Pnt( VS[j] ); TopTools_ListIteratorOfListOfShape itV( myAsDes->Descendant(se) ); for (; itV.More(); itV.Next()) { V = TopoDS::Vertex( itV.Value() ); if ( V.IsSame( VS[j] )) break; gp_Pnt P2 = BRep_Tool::Pnt( V ); if (P1.IsEqual( P2, Precision::Confusion())) { mySameDomainVM.Bind (VS[j], V); VS[j] = V; break; } } if (!itV.More()) // no interferences with edges myAsDes->Add( se, VS[j]); } // add ends of ON splits to F in order to detect later // if a split is on face in IsSplitOn() mySectionEdgesAD->Add( F, VS[j]); } // in the descendants of F, first go ends of an ON split and // then a split itself mySectionEdgesAD->Add( F, S ); } if (!added) mySectionEdgesAD->Add( F, se ); myNewEdges.Add( se ); } } //======================================================================= //function : FacesPartition //purpose : //======================================================================= void Partition_Inter3d::FacesPartition(const TopoDS_Face& F1, const TopoDS_Face& F2) //(const TopTools_DataMapOfShapeListOfShape& /*SetOfFaces2*/) { TopTools_ListOfShape LInt; Inter3D (F1,F2,LInt); StorePart3d (F1,F2,LInt); } //======================================================================= //function : SetDone //purpose : //======================================================================= void Partition_Inter3d::SetDone(const TopoDS_Face& F1, const TopoDS_Face& F2) { if (!myDone.IsBound(F1)) { TopTools_ListOfShape emptyList; myDone.Bind(F1,emptyList); } myDone(F1).Append(F2); if (!myDone.IsBound(F2)) { TopTools_ListOfShape emptyList; myDone.Bind(F2,emptyList); } myDone(F2).Append(F1); } //======================================================================= //function : IsDone //purpose : //======================================================================= Standard_Boolean Partition_Inter3d::IsDone(const TopoDS_Face& F1, const TopoDS_Face& F2) const { if (myDone.IsBound(F1)) { TopTools_ListIteratorOfListOfShape it (myDone(F1)); for (; it.More(); it.Next()) { if (it.Value().IsSame(F2)) return Standard_True; } } return Standard_False; } //======================================================================= //function : StorePart3d //purpose : //======================================================================= void Partition_Inter3d::StorePart3d(const TopoDS_Face& F1, const TopoDS_Face& F2, const TopTools_ListOfShape& LInt) { if (!LInt.IsEmpty()) { myAsDes->Add( F1,LInt); myAsDes->Add( F2,LInt); TopTools_ListIteratorOfListOfShape it(LInt); for (; it.More(); it.Next()) { TopoDS_Edge E = TopoDS::Edge(it.Value()); BRep_Builder B; B.SameParameter(E,Standard_False); BRepLib::SameParameter(E,1.0e-7); myNewEdges.Add(E); } } SetDone(F1,F2); } //======================================================================= //function : TouchedFaces //purpose : //======================================================================= TopTools_MapOfShape& Partition_Inter3d::TouchedFaces() { return myTouched; } //======================================================================= //function : AsDes //purpose : //======================================================================= Handle_BRepAlgo_AsDes Partition_Inter3d::AsDes() const { return myAsDes; } //======================================================================= //function : NewEdges //purpose : //======================================================================= TopTools_MapOfShape& Partition_Inter3d::NewEdges() { return myNewEdges; } //======================================================================= //function : Affiche //purpose : //======================================================================= void Partition_Inter3d::Affiche(const TopTools_ListOfShape& SetOfFaces) const { #ifdef DEB char PSection[1024]; char *section=PSection; Standard_Integer i = 0; Standard_Real j=1; TopTools_ListOfShape aList; TopTools_ListIteratorOfListOfShape it; for (it.Initialize(SetOfFaces); it.More(); it.Next()) { const TopoDS_Shape& OS = it.Value(); aList=myAsDes->Descendant(OS); MESSAGE ( " the number of items stored in the list " << j << " : " << aList.Extent() ) j++; TopTools_ListIteratorOfListOfShape itaList; for (itaList.Initialize(aList); itaList.More(); itaList.Next()) { const TopoDS_Shape& SS = itaList.Value(); i++; sprintf(PSection,"section_%d",i); DBRep::Set(section,SS); } } #endif } //======================================================================= //function : SameDomain //purpose : //======================================================================= const TopTools_ListOfShape& Partition_Inter3d::SameDomain(const TopoDS_Face& F) const { if (mySameDomainFM.IsBound( F )) return mySameDomainFM (F); static TopTools_ListOfShape emptyList; return emptyList; } //======================================================================= //function : HasSameDomainF //purpose : Return true if F has same domain faces //======================================================================= Standard_Boolean Partition_Inter3d::HasSameDomainF(const TopoDS_Shape& F) const { return mySameDomainFM.IsBound( F ); } //======================================================================= //function : IsSameDomain //purpose : Return true if F1 and F2 are same domain faces //======================================================================= Standard_Boolean Partition_Inter3d::IsSameDomainF(const TopoDS_Shape& F1, const TopoDS_Shape& F2) const { if (mySameDomainFM.IsBound( F1 )) { TopTools_ListIteratorOfListOfShape it (mySameDomainFM( F1 )); for (; it.More(); it.Next()) if (F2.IsSame( it.Value())) return Standard_True; } return F1.IsSame( F2 ); } //======================================================================= //function : ReplaceSameDomainV //purpose : return same domain vertex of V if it was replaced // and make this vertex to be on E too, else return V //======================================================================= TopoDS_Vertex Partition_Inter3d::ReplaceSameDomainV(const TopoDS_Vertex& V, const TopoDS_Edge& E) const { TopoDS_Vertex SDV = V; if (mySameDomainVM.IsBound( V )) { TopoDS_Vertex V1,V2; TopExp::Vertices(E,V1,V2); Standard_Boolean isClosed = V1.IsSame( V2 ) && V.IsSame(V1); SDV = TopoDS::Vertex( mySameDomainVM(V) ); Standard_Real tol = BRep_Tool::Tolerance( V ); BRep_Builder B; SDV.Orientation( V.Orientation()); if (isClosed) { Standard_Real f, l; BRep_Tool::Range (E, f, l); Standard_Boolean isFirst = IsEqual( BRep_Tool::Parameter(V,E), f ); B.UpdateVertex(SDV, (isFirst ? f : l), E, tol); SDV.Reverse(); B.UpdateVertex(SDV, (isFirst ? l : f), E, tol); } else B.UpdateVertex (SDV, BRep_Tool::Parameter(V,E), E, tol); } return SDV; } //======================================================================= //function : SectionEdgesAD //purpose : //======================================================================= Handle_BRepAlgo_AsDes Partition_Inter3d::SectionEdgesAD() const { return mySectionEdgesAD; } //======================================================================= //function : IsSectionEdge //purpose : return True if E is an edge of a face and it // intersects an other face //======================================================================= Standard_Boolean Partition_Inter3d::IsSectionEdge(const TopoDS_Edge& E) const { return mySectionEdgesAD->HasAscendant(E); } //======================================================================= //function : HasSectionEdge //purpose : return True if an edge of F intersects an other // face or F is intersected by edge of an other face //======================================================================= Standard_Boolean Partition_Inter3d::HasSectionEdge(const TopoDS_Face& F) const { return mySectionEdgesAD->HasDescendant(F); } //======================================================================= //function : IsSplitOn //purpose : return True if NewE is split of OldE on F //======================================================================= Standard_Boolean Partition_Inter3d::IsSplitOn(const TopoDS_Edge& NewE, const TopoDS_Edge& OldE, const TopoDS_Face& F) const { if (! mySectionEdgesAD->HasDescendant(F)) return Standard_False; TopTools_ListIteratorOfListOfShape itE ( mySectionEdgesAD->Descendant(F) ); for ( ; itE.More(); itE.Next()) { if ( itE.Value().ShapeType() != TopAbs_EDGE || ! OldE.IsSame ( itE.Value() )) continue; // an edge encountered, its vertices and a split come next itE.Next(); if (!itE.More()) break; const TopoDS_Shape& V3 = itE.Value(); if (V3.ShapeType() != TopAbs_VERTEX) continue; itE.Next(); if (!itE.More()) break; const TopoDS_Shape& V4 = itE.Value(); if (V4.ShapeType() != TopAbs_VERTEX) continue; TopoDS_Vertex V1, V2; TopExp::Vertices( OldE, V1, V2); if ( V1.IsSame(V2) && (V1.IsSame(V3) || V1.IsSame(V4)) ) { // closed old edge; use the split for the test itE.Next(); if (!itE.More()) break; const TopoDS_Edge& split = TopoDS::Edge( itE.Value() ); // check distance at middle point of NewE Standard_Real f1,l1, f2,l2; Handle(Geom2d_Curve) PC1 = BRep_Tool::CurveOnSurface( split, F ,f1,l1); if (!PC1.IsNull()) { Handle(Geom2d_Curve) PC2 = BRep_Tool::CurveOnSurface(NewE, F ,f2,l2); gp_Pnt2d P = PC2->Value( 0.5*(f2+l2) ); Geom2dAPI_ProjectPointOnCurve proj (P, PC1, f1, l1); if (proj.NbPoints() && proj.LowerDistance() <= Precision::Confusion()) return Standard_True; } else { Handle(Geom_Curve) C1 = BRep_Tool::Curve( split ,f1,l1); Handle(Geom_Curve) C2 = BRep_Tool::Curve( NewE ,f2,l2); gp_Pnt P = C2->Value( 0.5*(f2+l2) ); GeomAPI_ProjectPointOnCurve proj (P, C1, f1, l1); if (proj.NbPoints() && proj.LowerDistance() <= Precision::Confusion()) return Standard_True; } } else { Standard_Real u3 = BRep_Tool::Parameter( TopoDS::Vertex(V3), OldE); Standard_Real u4 = BRep_Tool::Parameter( TopoDS::Vertex(V4), OldE); Standard_Real f,l, u; BRep_Tool::Range( NewE, f,l); u = 0.5*(f+l); f = Min(u3,u4); l = Max(u3,u4); if (u <= l && u >= f) return Standard_True; } } return Standard_False; } //======================================================================= //function : SectionEdgeFaces //purpose : return faces cut by section edge //======================================================================= const TopTools_ListOfShape& Partition_Inter3d::SectionEdgeFaces(const TopoDS_Edge& SecE) const { return mySectionEdgesAD->Ascendant( SecE ); } #endif netgen-6.2.1905/libsrc/occ/utilities.h0000644000175000017500000000671013504650527016213 0ustar kurtkurt// SALOME Utils : general SALOME's definitions and tools // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : utilities.h // Author : Antoine YESSAYAN, Paul RASCLE, EDF // Module : SALOME // $Header: /cvs/netgen/netgen/libsrc/occ/utilities.h,v 1.3 2008/03/31 14:20:28 wabro Exp $ /* --- Definition macros file to print information if _DEBUG_ is defined --- */ #ifndef UTILITIES_H #define UTILITIES_H #include #include #include // #include "SALOME_Log.hxx" /* --- INFOS is always defined (without _DEBUG_): to be used for warnings, with release version --- */ #define INFOS(msg) {SLog->putMessage(*SLog<<__FILE__<<" ["<<__LINE__<<"] : "<putMessage(*SLog<<"---PYSCRIPT--- "<putMessage(\ *SLog<<__FILE__<<" ["<< __LINE__<<"] : "\ << "COMPILED with " << COMPILER \ << ", " << __DATE__ \ << " at " << __TIME__ <putMessage( MYTRACE <putMessage( MYTRACE << #var << "=" << var < #include #include #include "ShapeAnalysis_ShapeTolerance.hxx" #include "ShapeAnalysis_ShapeContents.hxx" #include "ShapeAnalysis_CheckSmallFace.hxx" #include "ShapeAnalysis_DataMapOfShapeListOfReal.hxx" #include "ShapeAnalysis_Surface.hxx" #include "BRepCheck_Analyzer.hxx" #include "BRepLib.hxx" #include "ShapeBuild_ReShape.hxx" #include "ShapeFix.hxx" #include "ShapeFix_FixSmallFace.hxx" #include "Partition_Spliter.hxx" #include "BRepAlgoAPI_Fuse.hxx" #include "XSControl_WorkSession.hxx" #include "XSControl_TransferReader.hxx" #include "StepRepr_RepresentationItem.hxx" #ifndef _Standard_Version_HeaderFile #include #endif #if OCC_VERSION_HEX < 0x070000 // pass #elif OCC_VERSION_HEX < 0x070200 #include "StlTransfer.hxx" #include "TopoDS_Iterator.hxx" #else #include "TopoDS_Iterator.hxx" #endif namespace netgen { void STEP_GetEntityName(const TopoDS_Shape & theShape, STEPCAFControl_Reader * aReader, char * acName) { const Handle(XSControl_WorkSession)& theSession = aReader->Reader().WS(); const Handle(XSControl_TransferReader)& aTransferReader = theSession->TransferReader(); Handle(Standard_Transient) anEntity = aTransferReader->EntityFromShapeResult(theShape, 1); if (anEntity.IsNull()) { // as just mapped anEntity = aTransferReader->EntityFromShapeResult (theShape,-1); } if (anEntity.IsNull()) { // as anything anEntity = aTransferReader->EntityFromShapeResult (theShape,4); } if (anEntity.IsNull()) { cout<<"Warning: XSInterVertex_STEPReader::ReadAttributes()\nentity not found"<Name()->ToCString()); } } void OCCGeometry :: PrintNrShapes () { TopExp_Explorer e; int count = 0; for (e.Init(shape, TopAbs_COMPSOLID); e.More(); e.Next()) count++; cout << "CompSolids: " << count << endl; cout << "Solids : " << somap.Extent() << endl; cout << "Shells : " << shmap.Extent() << endl; cout << "Faces : " << fmap.Extent() << endl; cout << "Edges : " << emap.Extent() << endl; cout << "Vertices : " << vmap.Extent() << endl; } void PrintContents (OCCGeometry * geom) { ShapeAnalysis_ShapeContents cont; cont.Clear(); cont.Perform(geom->shape); (*testout) << "OCC CONTENTS" << endl; (*testout) << "============" << endl; (*testout) << "SOLIDS : " << cont.NbSolids() << endl; (*testout) << "SHELLS : " << cont.NbShells() << endl; (*testout) << "FACES : " << cont.NbFaces() << endl; (*testout) << "WIRES : " << cont.NbWires() << endl; (*testout) << "EDGES : " << cont.NbEdges() << endl; (*testout) << "VERTICES : " << cont.NbVertices() << endl; TopExp_Explorer e; int count = 0; for (e.Init(geom->shape, TopAbs_COMPOUND); e.More(); e.Next()) count++; (*testout) << "Compounds: " << count << endl; count = 0; for (e.Init(geom->shape, TopAbs_COMPSOLID); e.More(); e.Next()) count++; (*testout) << "CompSolids: " << count << endl; (*testout) << endl; cout << "Highest entry in topology hierarchy: " << endl; if (count) cout << count << " composite solid(s)" << endl; else if (geom->somap.Extent()) cout << geom->somap.Extent() << " solid(s)" << endl; else if (geom->shmap.Extent()) cout << geom->shmap.Extent() << " shells(s)" << endl; else if (geom->fmap.Extent()) cout << geom->fmap.Extent() << " face(s)" << endl; else if (geom->wmap.Extent()) cout << geom->wmap.Extent() << " wire(s)" << endl; else if (geom->emap.Extent()) cout << geom->emap.Extent() << " edge(s)" << endl; else if (geom->vmap.Extent()) cout << geom->vmap.Extent() << " vertices(s)" << endl; else cout << "no entities" << endl; } void OCCGeometry :: HealGeometry () { int nrc = 0, nrcs = 0, nrso = somap.Extent(), nrsh = shmap.Extent(), nrf = fmap.Extent(), nrw = wmap.Extent(), nre = emap.Extent(), nrv = vmap.Extent(); TopExp_Explorer exp0; TopExp_Explorer exp1; for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nrc++; for (exp0.Init(shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nrcs++; double surfacecont = 0; { Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) rebuild->Remove(edge); } shape = rebuild->Apply(shape); } BuildFMap(); for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()) { TopoDS_Face face = TopoDS::Face(exp0.Current()); GProp_GProps system; BRepGProp::SurfaceProperties(face, system); surfacecont += system.Mass(); } cout << "Starting geometry healing procedure (tolerance: " << tolerance << ")" << endl << "-----------------------------------" << endl; { cout << endl << "- repairing faces" << endl; Handle(ShapeFix_Face) sff; Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()) { // Variable to hold the colour (if there exists one) of // the current face being processed Quantity_Color face_colour; TopoDS_Face face = TopoDS::Face (exp0.Current()); if(face_colours.IsNull() || (!(face_colours->GetColor(face,XCAFDoc_ColorSurf,face_colour)))) { // Set the default face colour to green (Netgen Standard) // if no colour has been defined for the face face_colour = Quantity_Color(0.0,1.0,0.0,Quantity_TOC_RGB); } sff = new ShapeFix_Face (face); sff->FixAddNaturalBoundMode() = Standard_True; sff->FixSmallAreaWireMode() = Standard_True; sff->Perform(); if(sff->Status(ShapeExtend_DONE1) || sff->Status(ShapeExtend_DONE2) || sff->Status(ShapeExtend_DONE3) || sff->Status(ShapeExtend_DONE4) || sff->Status(ShapeExtend_DONE5)) { cout << "repaired face " << fmap.FindIndex(face) << " "; if(sff->Status(ShapeExtend_DONE1)) cout << "(some wires are fixed)" <Status(ShapeExtend_DONE2)) cout << "(orientation of wires fixed)" <Status(ShapeExtend_DONE3)) cout << "(missing seam added)" <Status(ShapeExtend_DONE4)) cout << "(small area wire removed)" <Status(ShapeExtend_DONE5)) cout << "(natural bounds added)" <Face(); rebuild->Replace(face, newface); } // Set the original colour of the face to the newly created // face (after the healing process) face = TopoDS::Face (exp0.Current()); face_colours->SetColor(face,face_colour,XCAFDoc_ColorSurf); } shape = rebuild->Apply(shape); } { Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) rebuild->Remove(edge); } shape = rebuild->Apply(shape); } if (fixsmalledges) { cout << endl << "- fixing small edges" << endl; Handle(ShapeFix_Wire) sfw; Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()) { TopoDS_Face face = TopoDS::Face(exp0.Current()); for (exp1.Init (face, TopAbs_WIRE); exp1.More(); exp1.Next()) { TopoDS_Wire oldwire = TopoDS::Wire(exp1.Current()); sfw = new ShapeFix_Wire (oldwire, face ,tolerance); sfw->ModifyTopologyMode() = Standard_True; sfw->ClosedWireMode() = Standard_True; bool replace = false; replace = sfw->FixReorder() || replace; replace = sfw->FixConnected() || replace; if (sfw->FixSmall (Standard_False, tolerance) && ! (sfw->StatusSmall(ShapeExtend_FAIL1) || sfw->StatusSmall(ShapeExtend_FAIL2) || sfw->StatusSmall(ShapeExtend_FAIL3))) { cout << "Fixed small edge in wire " << wmap.FindIndex (oldwire) << endl; replace = true; } else if (sfw->StatusSmall(ShapeExtend_FAIL1)) cerr << "Failed to fix small edge in wire " << wmap.FindIndex (oldwire) << ", edge cannot be checked (no 3d curve and no pcurve)" << endl; else if (sfw->StatusSmall(ShapeExtend_FAIL2)) cerr << "Failed to fix small edge in wire " << wmap.FindIndex (oldwire) << ", edge is null-length and has different vertives at begin and end, and lockvtx is True or ModifiyTopologyMode is False" << endl; else if (sfw->StatusSmall(ShapeExtend_FAIL3)) cerr << "Failed to fix small edge in wire " << wmap.FindIndex (oldwire) << ", CheckConnected has failed" << endl; replace = sfw->FixEdgeCurves() || replace; replace = sfw->FixDegenerated() || replace; replace = sfw->FixSelfIntersection() || replace; replace = sfw->FixLacking(Standard_True) || replace; if(replace) { TopoDS_Wire newwire = sfw->Wire(); rebuild->Replace(oldwire, newwire); } //delete sfw; sfw = NULL; } } shape = rebuild->Apply(shape); { BuildFMap(); Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if (vmap.FindIndex(TopExp::FirstVertex (edge)) == vmap.FindIndex(TopExp::LastVertex (edge))) { GProp_GProps system; BRepGProp::LinearProperties(edge, system); if (system.Mass() < tolerance) { cout << "removing degenerated edge " << emap.FindIndex(edge) << " from vertex " << vmap.FindIndex(TopExp::FirstVertex (edge)) << " to vertex " << vmap.FindIndex(TopExp::LastVertex (edge)) << endl; rebuild->Remove(edge); } } } shape = rebuild->Apply(shape); //delete rebuild; rebuild = NULL; } { Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) rebuild->Remove(edge); } shape = rebuild->Apply(shape); } Handle(ShapeFix_Wireframe) sfwf = new ShapeFix_Wireframe; sfwf->SetPrecision(tolerance); sfwf->Load (shape); sfwf->ModeDropSmallEdges() = Standard_True; sfwf->SetPrecision(boundingbox.Diam()); if (sfwf->FixWireGaps()) { cout << endl << "- fixing wire gaps" << endl; if (sfwf->StatusWireGaps(ShapeExtend_OK)) cout << "no gaps found" << endl; if (sfwf->StatusWireGaps(ShapeExtend_DONE1)) cout << "some 2D gaps fixed" << endl; if (sfwf->StatusWireGaps(ShapeExtend_DONE2)) cout << "some 3D gaps fixed" << endl; if (sfwf->StatusWireGaps(ShapeExtend_FAIL1)) cout << "failed to fix some 2D gaps" << endl; if (sfwf->StatusWireGaps(ShapeExtend_FAIL2)) cout << "failed to fix some 3D gaps" << endl; } sfwf->SetPrecision(tolerance); { for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) cout << "degenerated edge at position 4" << endl; } } if (sfwf->FixSmallEdges()) { cout << endl << "- fixing wire frames" << endl; if (sfwf->StatusSmallEdges(ShapeExtend_OK)) cout << "no small edges found" << endl; if (sfwf->StatusSmallEdges(ShapeExtend_DONE1)) cout << "some small edges fixed" << endl; if (sfwf->StatusSmallEdges(ShapeExtend_FAIL1)) cout << "failed to fix some small edges" << endl; } shape = sfwf->Shape(); //delete sfwf; sfwf = NULL; //delete rebuild; rebuild = NULL; } { for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) cout << "degenerated edge at position 5" << endl; } } if (fixspotstripfaces) { cout << endl << "- fixing spot and strip faces" << endl; Handle(ShapeFix_FixSmallFace) sffsm = new ShapeFix_FixSmallFace(); sffsm -> Init (shape); sffsm -> SetPrecision (tolerance); sffsm -> Perform(); shape = sffsm -> FixShape(); //delete sffsm; sffsm = NULL; } { for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) cout << "degenerated edge at position 6" << endl; } } if (sewfaces) { cout << endl << "- sewing faces" << endl; BRepOffsetAPI_Sewing sewedObj(tolerance); for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()) { TopoDS_Face face = TopoDS::Face (exp0.Current()); sewedObj.Add (face); } sewedObj.Perform(); if (!sewedObj.SewedShape().IsNull()) shape = sewedObj.SewedShape(); else cout << " not possible"; } { Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(shape); for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) rebuild->Remove(edge); } shape = rebuild->Apply(shape); } if (makesolids) { cout << endl << "- making solids" << endl; BRepBuilderAPI_MakeSolid ms; int count = 0; for (exp0.Init(shape, TopAbs_SHELL); exp0.More(); exp0.Next()) { count++; ms.Add (TopoDS::Shell(exp0.Current())); } if (!count) { cout << " not possible (no shells)" << endl; } else { BRepCheck_Analyzer ba(ms); if (ba.IsValid ()) { Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; sfs->Init (ms); sfs->SetPrecision(tolerance); sfs->SetMaxTolerance(tolerance); sfs->Perform(); shape = sfs->Shape(); for (exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()) { TopoDS_Solid solid = TopoDS::Solid(exp0.Current()); TopoDS_Solid newsolid = solid; BRepLib::OrientClosedSolid (newsolid); Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; // rebuild->Apply(shape); rebuild->Replace(solid, newsolid); TopoDS_Shape newshape = rebuild->Apply(shape, TopAbs_COMPSOLID);//, 1); // TopoDS_Shape newshape = rebuild->Apply(shape); shape = newshape; } //delete sfs; sfs = NULL; } else cout << " not possible" << endl; } } if (splitpartitions) { cout << "- running SALOME partition splitter" << endl; TopExp_Explorer e2; Partition_Spliter ps; int count = 0; for (e2.Init (shape, TopAbs_SOLID); e2.More(); e2.Next()) { count++; ps.AddShape (e2.Current()); } ps.Compute(); shape = ps.Shape(); cout << " before: " << count << " solids" << endl; count = 0; for (e2.Init (shape, TopAbs_SOLID); e2.More(); e2.Next()) count++; cout << " after : " << count << " solids" << endl; } BuildFMap(); { for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); if ( BRep_Tool::Degenerated(edge) ) cout << "degenerated edge at position 8" << endl; } } double newsurfacecont = 0; for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()) { TopoDS_Face face = TopoDS::Face(exp0.Current()); GProp_GProps system; BRepGProp::SurfaceProperties(face, system); newsurfacecont += system.Mass(); } int nnrc = 0, nnrcs = 0, nnrso = somap.Extent(), nnrsh = shmap.Extent(), nnrf = fmap.Extent(), nnrw = wmap.Extent(), nnre = emap.Extent(), nnrv = vmap.Extent(); for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nnrc++; for (exp0.Init(shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nnrcs++; cout << "-----------------------------------" << endl; cout << "Compounds : " << nnrc << " (" << nrc << ")" << endl; cout << "Composite solids: " << nnrcs << " (" << nrcs << ")" << endl; cout << "Solids : " << nnrso << " (" << nrso << ")" << endl; cout << "Shells : " << nnrsh << " (" << nrsh << ")" << endl; cout << "Wires : " << nnrw << " (" << nrw << ")" << endl; cout << "Faces : " << nnrf << " (" << nrf << ")" << endl; cout << "Edges : " << nnre << " (" << nre << ")" << endl; cout << "Vertices : " << nnrv << " (" << nrv << ")" << endl; cout << endl; cout << "Totol surface area : " << newsurfacecont << " (" << surfacecont << ")" << endl; cout << endl; } void OCCGeometry :: BuildFMap() { somap.Clear(); shmap.Clear(); fmap.Clear(); wmap.Clear(); emap.Clear(); vmap.Clear(); TopExp_Explorer exp0, exp1, exp2, exp3, exp4, exp5; for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) { TopoDS_Compound compound = TopoDS::Compound (exp0.Current()); (*testout) << "compound" << endl; int i = 0; for (exp1.Init(compound, TopAbs_SHELL); exp1.More(); exp1.Next()) { (*testout) << "shell " << ++i << endl; } } for (exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()) { TopoDS_Solid solid = TopoDS::Solid (exp0.Current()); if (somap.FindIndex(solid) < 1) { somap.Add (solid); for (exp1.Init(solid, TopAbs_SHELL); exp1.More(); exp1.Next()) { TopoDS_Shell shell = TopoDS::Shell (exp1.Current()); if (shmap.FindIndex(shell) < 1) { shmap.Add (shell); for (exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next()) { TopoDS_Face face = TopoDS::Face(exp2.Current()); if (fmap.FindIndex(face) < 1) { fmap.Add (face); (*testout) << "face " << fmap.FindIndex(face) << " "; (*testout) << ((face.Orientation() == TopAbs_REVERSED) ? "-" : "+") << ", "; (*testout) << ((exp2.Current().Orientation() == TopAbs_REVERSED) ? "-" : "+") << endl; for (exp3.Init(exp2.Current(), TopAbs_WIRE); exp3.More(); exp3.Next()) { TopoDS_Wire wire = TopoDS::Wire (exp3.Current()); if (wmap.FindIndex(wire) < 1) { wmap.Add (wire); for (exp4.Init(exp3.Current(), TopAbs_EDGE); exp4.More(); exp4.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp4.Current()); if (emap.FindIndex(edge) < 1) { emap.Add (edge); for (exp5.Init(exp4.Current(), TopAbs_VERTEX); exp5.More(); exp5.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current()); if (vmap.FindIndex(vertex) < 1) vmap.Add (vertex); } } } } } } } } } } } // Free Shells for (exp1.Init(shape, TopAbs_SHELL, TopAbs_SOLID); exp1.More(); exp1.Next()) { TopoDS_Shell shell = TopoDS::Shell(exp1.Current()); if (shmap.FindIndex(shell) < 1) { shmap.Add (shell); (*testout) << "shell " << shmap.FindIndex(shell) << " "; (*testout) << ((shell.Orientation() == TopAbs_REVERSED) ? "-" : "+") << ", "; (*testout) << ((exp1.Current().Orientation() == TopAbs_REVERSED) ? "-" : "+") << endl; for (exp2.Init(shell, TopAbs_FACE); exp2.More(); exp2.Next()) { TopoDS_Face face = TopoDS::Face(exp2.Current()); if (fmap.FindIndex(face) < 1) { fmap.Add (face); for (exp3.Init(face, TopAbs_WIRE); exp3.More(); exp3.Next()) { TopoDS_Wire wire = TopoDS::Wire (exp3.Current()); if (wmap.FindIndex(wire) < 1) { wmap.Add (wire); for (exp4.Init(wire, TopAbs_EDGE); exp4.More(); exp4.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp4.Current()); if (emap.FindIndex(edge) < 1) { emap.Add (edge); for (exp5.Init(edge, TopAbs_VERTEX); exp5.More(); exp5.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current()); if (vmap.FindIndex(vertex) < 1) vmap.Add (vertex); } } } } } } } } } // Free Faces for (exp2.Init(shape, TopAbs_FACE, TopAbs_SHELL); exp2.More(); exp2.Next()) { TopoDS_Face face = TopoDS::Face(exp2.Current()); if (fmap.FindIndex(face) < 1) { fmap.Add (face); for (exp3.Init(exp2.Current(), TopAbs_WIRE); exp3.More(); exp3.Next()) { TopoDS_Wire wire = TopoDS::Wire (exp3.Current()); if (wmap.FindIndex(wire) < 1) { wmap.Add (wire); for (exp4.Init(exp3.Current(), TopAbs_EDGE); exp4.More(); exp4.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp4.Current()); if (emap.FindIndex(edge) < 1) { emap.Add (edge); for (exp5.Init(exp4.Current(), TopAbs_VERTEX); exp5.More(); exp5.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current()); if (vmap.FindIndex(vertex) < 1) vmap.Add (vertex); } } } } } } } // Free Wires for (exp3.Init(shape, TopAbs_WIRE, TopAbs_FACE); exp3.More(); exp3.Next()) { TopoDS_Wire wire = TopoDS::Wire (exp3.Current()); if (wmap.FindIndex(wire) < 1) { wmap.Add (wire); for (exp4.Init(exp3.Current(), TopAbs_EDGE); exp4.More(); exp4.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp4.Current()); if (emap.FindIndex(edge) < 1) { emap.Add (edge); for (exp5.Init(exp4.Current(), TopAbs_VERTEX); exp5.More(); exp5.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current()); if (vmap.FindIndex(vertex) < 1) vmap.Add (vertex); } } } } } // Free Edges for (exp4.Init(shape, TopAbs_EDGE, TopAbs_WIRE); exp4.More(); exp4.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp4.Current()); if (emap.FindIndex(edge) < 1) { emap.Add (edge); for (exp5.Init(exp4.Current(), TopAbs_VERTEX); exp5.More(); exp5.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current()); if (vmap.FindIndex(vertex) < 1) vmap.Add (vertex); } } } // Free Vertices for (exp5.Init(shape, TopAbs_VERTEX, TopAbs_EDGE); exp5.More(); exp5.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(exp5.Current()); if (vmap.FindIndex(vertex) < 1) vmap.Add (vertex); } facemeshstatus.DeleteAll(); facemeshstatus.SetSize (fmap.Extent()); facemeshstatus = 0; // Philippose - 15/01/2009 face_maxh.DeleteAll(); face_maxh.SetSize (fmap.Extent()); face_maxh = mparam.maxh; // Philippose - 15/01/2010 face_maxh_modified.DeleteAll(); face_maxh_modified.SetSize(fmap.Extent()); face_maxh_modified = 0; // Philippose - 17/01/2009 face_sel_status.DeleteAll(); face_sel_status.SetSize (fmap.Extent()); face_sel_status = 0; fvispar.SetSize (fmap.Extent()); evispar.SetSize (emap.Extent()); vvispar.SetSize (vmap.Extent()); fsingular.SetSize (fmap.Extent()); esingular.SetSize (emap.Extent()); vsingular.SetSize (vmap.Extent()); fsingular = esingular = vsingular = false; } void OCCGeometry :: SewFaces () { (*testout) << "Trying to sew faces ..." << endl; cout << "Trying to sew faces ..." << flush; BRepOffsetAPI_Sewing sewedObj(1); for (int i = 1; i <= fmap.Extent(); i++) { TopoDS_Face face = TopoDS::Face (fmap(i)); sewedObj.Add (face); } sewedObj.Perform(); if (!sewedObj.SewedShape().IsNull()) { shape = sewedObj.SewedShape(); cout << " done" << endl; } else cout << " not possible"; } void OCCGeometry :: MakeSolid () { TopExp_Explorer exp0; (*testout) << "Trying to build solids ..." << endl; cout << "Trying to build solids ..." << flush; BRepBuilderAPI_MakeSolid ms; int count = 0; for (exp0.Init(shape, TopAbs_SHELL); exp0.More(); exp0.Next()) { count++; ms.Add (TopoDS::Shell(exp0.Current())); } if (!count) { cout << " not possible (no shells)" << endl; return; } BRepCheck_Analyzer ba(ms); if (ba.IsValid ()) { Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; sfs->Init (ms); sfs->SetPrecision(1e-5); sfs->SetMaxTolerance(1e-5); sfs->Perform(); shape = sfs->Shape(); for (exp0.Init(shape, TopAbs_SOLID); exp0.More(); exp0.Next()) { TopoDS_Solid solid = TopoDS::Solid(exp0.Current()); TopoDS_Solid newsolid = solid; BRepLib::OrientClosedSolid (newsolid); Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Replace(solid, newsolid); TopoDS_Shape newshape = rebuild->Apply(shape, TopAbs_SHAPE, 1); shape = newshape; } cout << " done" << endl; } else cout << " not possible" << endl; } void OCCGeometry :: BuildVisualizationMesh (double deflection) { cout << "Preparing visualization (deflection = " << deflection << ") ... " << flush; BRepTools::Clean (shape); // BRepMesh_IncrementalMesh:: BRepMesh_IncrementalMesh (shape, deflection, true); cout << "done" << endl; } void OCCGeometry :: CalcBoundingBox () { Bnd_Box bb; #if OCC_VERSION_HEX < 0x070000 BRepBndLib::Add (shape, bb); #else BRepBndLib::Add ((const TopoDS_Shape) shape, bb,(Standard_Boolean)true); #endif double x1,y1,z1,x2,y2,z2; bb.Get (x1,y1,z1,x2,y2,z2); Point<3> p1 = Point<3> (x1,y1,z1); Point<3> p2 = Point<3> (x2,y2,z2); (*testout) << "Bounding Box = [" << p1 << " - " << p2 << "]" << endl; boundingbox = Box<3> (p1,p2); SetCenter(); } void OCCGeometry :: Project (int surfi, Point<3> & p) const { static int cnt = 0; if (++cnt % 1000 == 0) cout << "Project cnt = " << cnt << endl; gp_Pnt pnt(p(0), p(1), p(2)); double u,v; Handle( Geom_Surface ) thesurf = BRep_Tool::Surface(TopoDS::Face(fmap(surfi))); Handle( ShapeAnalysis_Surface ) su = new ShapeAnalysis_Surface( thesurf ); gp_Pnt2d suval = su->ValueOfUV ( pnt, BRep_Tool::Tolerance( TopoDS::Face(fmap(surfi)) ) ); suval.Coord( u, v); pnt = thesurf->Value( u, v ); p = Point<3> (pnt.X(), pnt.Y(), pnt.Z()); } bool OCCGeometry :: FastProject (int surfi, Point<3> & ap, double& u, double& v) const { gp_Pnt p(ap(0), ap(1), ap(2)); Handle(Geom_Surface) surface = BRep_Tool::Surface(TopoDS::Face(fmap(surfi))); gp_Pnt x = surface->Value (u,v); if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return true; gp_Vec du, dv; surface->D1(u,v,x,du,dv); int count = 0; gp_Pnt xold; gp_Vec n; double det, lambda, mu; do { count++; n = du^dv; det = Det3 (n.X(), du.X(), dv.X(), n.Y(), du.Y(), dv.Y(), n.Z(), du.Z(), dv.Z()); if (det < 1e-15) return false; lambda = Det3 (n.X(), p.X()-x.X(), dv.X(), n.Y(), p.Y()-x.Y(), dv.Y(), n.Z(), p.Z()-x.Z(), dv.Z())/det; mu = Det3 (n.X(), du.X(), p.X()-x.X(), n.Y(), du.Y(), p.Y()-x.Y(), n.Z(), du.Z(), p.Z()-x.Z())/det; u += lambda; v += mu; xold = x; surface->D1(u,v,x,du,dv); } while (xold.SquareDistance(x) > sqr(PROJECTION_TOLERANCE) && count < 50); // (*testout) << "FastProject count: " << count << endl; if (count == 50) return false; ap = Point<3> (x.X(), x.Y(), x.Z()); return true; } // void OCCGeometry :: WriteOCC_STL(char * filename) // { // cout << "writing stl..."; cout.flush(); // StlAPI_Writer writer; // writer.RelativeMode() = Standard_False; // // writer.SetDeflection(0.02); // writer.Write(shape,filename); // // cout << "done" << endl; // } void LoadOCCInto(OCCGeometry* occgeo, const char* filename) { // Initiate a dummy XCAF Application to handle the STEP XCAF Document static Handle_XCAFApp_Application dummy_app = XCAFApp_Application::GetApplication(); // Create an XCAF Document to contain the STEP file itself Handle_TDocStd_Document step_doc; // Check if a STEP File is already open under this handle, if so, close it to prevent // Segmentation Faults when trying to create a new document if(dummy_app->NbDocuments() > 0) { dummy_app->GetDocument(1,step_doc); dummy_app->Close(step_doc); } dummy_app->NewDocument ("STEP-XCAF",step_doc); STEPCAFControl_Reader reader; // Enable transfer of colours reader.SetColorMode(Standard_True); reader.SetNameMode(Standard_True); Standard_Integer stat = reader.ReadFile((char*)filename); if(stat != IFSelect_RetDone) { throw NgException("Couldn't load OCC geometry"); } reader.Transfer(step_doc); // Read in the shape(s) and the colours present in the STEP File Handle_XCAFDoc_ShapeTool step_shape_contents = XCAFDoc_DocumentTool::ShapeTool(step_doc->Main()); Handle_XCAFDoc_ColorTool step_colour_contents = XCAFDoc_DocumentTool::ColorTool(step_doc->Main()); TDF_LabelSequence step_shapes; step_shape_contents->GetShapes(step_shapes); // List out the available colours in the STEP File as Colour Names TDF_LabelSequence all_colours; step_colour_contents->GetColors(all_colours); PrintMessage(1,"Number of colours in STEP File: ",all_colours.Length()); for(int i = 1; i <= all_colours.Length(); i++) { Quantity_Color col; stringstream col_rgb; step_colour_contents->GetColor(all_colours.Value(i),col); col_rgb << " : (" << col.Red() << "," << col.Green() << "," << col.Blue() << ")"; PrintMessage(1, "Colour [", i, "] = ",col.StringName(col.Name()),col_rgb.str()); } // For the STEP File Reader in OCC, the 1st Shape contains the entire // compound geometry as one shape occgeo->shape = step_shape_contents->GetShape(step_shapes.Value(1)); occgeo->face_colours = step_colour_contents; occgeo->changed = 1; occgeo->BuildFMap(); occgeo->CalcBoundingBox(); PrintContents (occgeo); char * name = new char[50]; //string name; STEP_GetEntityName(occgeo->shape,&reader,name); occgeo->snames.Append(name); TopExp_Explorer exp0,exp1; for (exp0.Init(occgeo->shape, TopAbs_FACE); exp0.More(); exp0.Next()) { TopoDS_Face face = TopoDS::Face(exp0.Current()); STEP_GetEntityName(face,&reader,name); if (name == string("")) snprintf(name, 50, "bc_%zu", occgeo->fnames.Size()); occgeo->fnames.Append(name); for (exp1.Init(face, TopAbs_EDGE); exp1.More(); exp1.Next()) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); STEP_GetEntityName(edge,&reader,name); occgeo->enames.Append(name); } } // Gerhard BEGIN // cout << "Solid Names: "<snames.Size();i++) // cout << occgeo->snames[i] << endl; // cout << " " <fnames.Size();i++) // cout << occgeo->fnames[i] << endl; // cout << " " <enames.Size();i++) // cout << occgeo->enames[i] << endl; // cout << " " <NbDocuments() > 0) { dummy_app->GetDocument(1,iges_doc); dummy_app->Close(iges_doc); } dummy_app->NewDocument ("IGES-XCAF",iges_doc); IGESCAFControl_Reader reader; Standard_Integer stat = reader.ReadFile((char*)filename); if(stat != IFSelect_RetDone) { throw NgException("Couldn't load occ"); } // Enable transfer of colours reader.SetColorMode(Standard_True); reader.Transfer(iges_doc); // Read in the shape(s) and the colours present in the IGES File Handle_XCAFDoc_ShapeTool iges_shape_contents = XCAFDoc_DocumentTool::ShapeTool(iges_doc->Main()); Handle_XCAFDoc_ColorTool iges_colour_contents = XCAFDoc_DocumentTool::ColorTool(iges_doc->Main()); TDF_LabelSequence iges_shapes; iges_shape_contents->GetShapes(iges_shapes); // List out the available colours in the IGES File as Colour Names TDF_LabelSequence all_colours; iges_colour_contents->GetColors(all_colours); PrintMessage(1,"Number of colours in IGES File: ",all_colours.Length()); for(int i = 1; i <= all_colours.Length(); i++) { Quantity_Color col; stringstream col_rgb; iges_colour_contents->GetColor(all_colours.Value(i),col); col_rgb << " : (" << col.Red() << "," << col.Green() << "," << col.Blue() << ")"; PrintMessage(1, "Colour [", i, "] = ",col.StringName(col.Name()),col_rgb.str()); } // For the IGES Reader, all the shapes can be exported as one compound shape // using the "OneShape" member occgeo->shape = reader.OneShape(); occgeo->face_colours = iges_colour_contents; occgeo->changed = 1; occgeo->BuildFMap(); occgeo->CalcBoundingBox(); PrintContents (occgeo); return occgeo; } // Philippose - 29/01/2009 /* Special STEP File load function including the ability to extract individual surface colours via the extended OpenCascade XDE and XCAF Feature set. */ OCCGeometry * LoadOCC_STEP (const char * filename) { OCCGeometry * occgeo; occgeo = new OCCGeometry; LoadOCCInto(occgeo, filename); return occgeo; } OCCGeometry *LoadOCC_BREP (const char *filename) { OCCGeometry * occgeo; occgeo = new OCCGeometry; BRep_Builder aBuilder; Standard_Boolean result = BRepTools::Read(occgeo->shape, const_cast (filename),aBuilder); if(!result) { delete occgeo; return NULL; } // Philippose - 23/02/2009 // Fixed a bug in the OpenCascade XDE Colour handling when // opening BREP Files, since BREP Files have no colour data. // Hence, the face_colours Handle needs to be created as a NULL handle. occgeo->face_colours = Handle_XCAFDoc_ColorTool(); occgeo->face_colours.Nullify(); occgeo->changed = 1; occgeo->BuildFMap(); occgeo->CalcBoundingBox(); PrintContents (occgeo); return occgeo; } void OCCGeometry :: Save (string sfilename) const { const char * filename = sfilename.c_str(); if (strlen(filename) < 4) throw NgException ("illegal filename"); if (strcmp (&filename[strlen(filename)-3], "igs") == 0) { IGESControl_Writer writer("millimeters", 1); writer.AddShape (shape); writer.Write (filename); } else if (strcmp (&filename[strlen(filename)-3], "stp") == 0) { STEPControl_Writer writer; writer.Transfer (shape, STEPControl_AsIs); writer.Write (filename); } else if (strcmp (&filename[strlen(filename)-3], "stl") == 0) { StlAPI_Writer writer; writer.ASCIIMode() = Standard_True; writer.Write (shape, filename); } else if (strcmp (&filename[strlen(filename)-4], "stlb") == 0) { StlAPI_Writer writer; writer.ASCIIMode() = Standard_False; writer.Write (shape, filename); } } void OCCGeometry :: DoArchive(Archive& ar) { if(ar.Output()) { std::stringstream ss; STEPControl_Writer writer; writer.Transfer(shape, STEPControl_AsIs); auto filename = ".tmpfile_out.step"; writer.Write(filename); std::ifstream is(filename); ss << is.rdbuf(); ar << ss.str(); std::remove(filename); } else { std::string str; ar & str; auto filename = ".tmpfile.step"; auto tmpfile = std::fopen(filename, "w"); std::fputs(str.c_str(), tmpfile); std::fclose(tmpfile); LoadOCCInto(this, filename); std::remove(filename); } } const char * shapesname[] = {" ", "CompSolids", "Solids", "Shells", "Faces", "Wires", "Edges", "Vertices"}; const char * shapename[] = {" ", "CompSolid", "Solid", "Shell", "Face", "Wire", "Edge", "Vertex"}; const char * orientationstring[] = {"+", "-"}; void OCCGeometry :: RecursiveTopologyTree (const TopoDS_Shape & sh, stringstream & str, TopAbs_ShapeEnum l, bool isfree, const char * lname) { if (l > TopAbs_VERTEX) return; TopExp_Explorer e; int count = 0; int count2 = 0; if (isfree) e.Init(sh, l, TopAbs_ShapeEnum(l-1)); else e.Init(sh, l); for (; e.More(); e.Next()) { count++; stringstream lname2; lname2 << lname << "/" << shapename[l] << count; str << lname2.str() << " "; switch (e.Current().ShapeType()) { case TopAbs_SOLID: count2 = somap.FindIndex(TopoDS::Solid(e.Current())); break; case TopAbs_SHELL: count2 = shmap.FindIndex(TopoDS::Shell(e.Current())); break; case TopAbs_FACE: count2 = fmap.FindIndex(TopoDS::Face(e.Current())); break; case TopAbs_WIRE: count2 = wmap.FindIndex(TopoDS::Wire(e.Current())); break; case TopAbs_EDGE: count2 = emap.FindIndex(TopoDS::Edge(e.Current())); break; case TopAbs_VERTEX: count2 = vmap.FindIndex(TopoDS::Vertex(e.Current())); break; default: cout << "RecursiveTopologyTree: Case " << e.Current().ShapeType() << " not handeled" << endl; } int nrsubshapes = 0; if (l <= TopAbs_WIRE) { TopExp_Explorer e2; for (e2.Init (e.Current(), TopAbs_ShapeEnum (l+1)); e2.More(); e2.Next()) nrsubshapes++; } str << "{" << shapename[l] << " " << count2; if (l <= TopAbs_EDGE) { str << " (" << orientationstring[e.Current().Orientation()]; if (nrsubshapes != 0) str << ", " << nrsubshapes; str << ") } "; } else str << " } "; RecursiveTopologyTree (e.Current(), str, TopAbs_ShapeEnum (l+1), false, (char*)lname2.str().c_str()); } } void OCCGeometry :: GetTopologyTree (stringstream & str) { cout << "Building topology tree ... " << flush; RecursiveTopologyTree (shape, str, TopAbs_COMPSOLID, false, "CompSolids"); RecursiveTopologyTree (shape, str, TopAbs_SOLID, true, "FreeSolids"); RecursiveTopologyTree (shape, str, TopAbs_SHELL, true, "FreeShells"); RecursiveTopologyTree (shape, str, TopAbs_FACE, true, "FreeFaces"); RecursiveTopologyTree (shape, str, TopAbs_WIRE, true, "FreeWires"); RecursiveTopologyTree (shape, str, TopAbs_EDGE, true, "FreeEdges"); RecursiveTopologyTree (shape, str, TopAbs_VERTEX, true, "FreeVertices"); str << flush; // cout << "done" << endl; } void OCCGeometry :: CheckIrregularEntities(stringstream & str) { ShapeAnalysis_CheckSmallFace csm; csm.SetTolerance (1e-6); TopTools_DataMapOfShapeListOfShape mapEdges; ShapeAnalysis_DataMapOfShapeListOfReal mapParam; TopoDS_Compound theAllVert; int spotfaces = 0; int stripsupportfaces = 0; int singlestripfaces = 0; int stripfaces = 0; int facessplitbyvertices = 0; int stretchedpinfaces = 0; int smoothpinfaces = 0; int twistedfaces = 0; // int edgessamebutnotidentified = 0; cout << "checking faces ... " << flush; int i; for (i = 1; i <= fmap.Extent(); i++) { TopoDS_Face face = TopoDS::Face (fmap(i)); TopoDS_Edge e1, e2; if (csm.CheckSpotFace (face)) { if (!spotfaces++) str << "SpotFace {Spot face} "; (*testout) << "Face " << i << " is a spot face" << endl; str << "SpotFace/Face" << i << " "; str << "{Face " << i << " } "; } if (csm.IsStripSupport (face)) { if (!stripsupportfaces++) str << "StripSupportFace {Strip support face} "; (*testout) << "Face " << i << " has strip support" << endl; str << "StripSupportFace/Face" << i << " "; str << "{Face " << i << " } "; } if (csm.CheckSingleStrip(face, e1, e2)) { if (!singlestripfaces++) str << "SingleStripFace {Single strip face} "; (*testout) << "Face " << i << " is a single strip (edge " << emap.FindIndex(e1) << " and edge " << emap.FindIndex(e2) << " are identical)" << endl; str << "SingleStripFace/Face" << i << " "; str << "{Face " << i << " (edge " << emap.FindIndex(e1) << " and edge " << emap.FindIndex(e2) << " are identical)} "; } if (csm.CheckStripFace(face, e1, e2)) { if (!stripfaces++) str << "StripFace {Strip face} "; (*testout) << "Face " << i << " is a strip (edge " << emap.FindIndex(e1) << " and edge " << emap.FindIndex(e2) << " are identical)" << endl; str << "StripFace/Face" << i << " "; str << "{Face " << i << " (edge " << emap.FindIndex(e1) << " and edge " << emap.FindIndex(e2) << " are identical)} "; } if (int count = csm.CheckSplittingVertices(face, mapEdges, mapParam, theAllVert)) { if (!facessplitbyvertices++) str << "FaceSplitByVertices {Face split by vertices} "; (*testout) << "Face " << i << " is split by " << count << " vertex/vertices " << endl; str << "FaceSplitByVertices/Face" << i << " "; str << "{Face " << i << " (split by " << count << "vertex/vertices)} "; } int whatrow, sens; if (int type = csm.CheckPin (face, whatrow, sens)) { if (type == 1) { if (!smoothpinfaces++) str << "SmoothPinFace {Smooth pin face} "; (*testout) << "Face " << i << " is a smooth pin" << endl; str << "SmoothPinFace/Face" << i << " "; str << "{Face " << i << " } "; } else { if (!stretchedpinfaces++) str << "StretchedPinFace {Stretched pin face} "; (*testout) << "Face " << i << " is a stretched pin" << endl; str << "StretchedPinFace/Face" << i << " "; str << "{Face " << i << " } "; } } double paramu, paramv; if (csm.CheckTwisted (face, paramu, paramv)) { if (!twistedfaces++) str << "TwistedFace {Twisted face} "; (*testout) << "Face " << i << " is twisted" << endl; str << "TwistedFace/Face" << i << " "; str << "{Face " << i << " } "; } } cout << "done" << endl; cout << "checking edges ... " << flush; // double dmax; // int cnt = 0; Array edgeLengths; Array order; edgeLengths.SetSize (emap.Extent()); order.SetSize (emap.Extent()); for (i = 1; i <= emap.Extent(); i++) { TopoDS_Edge edge1 = TopoDS::Edge (emap(i)); GProp_GProps system; BRepGProp::LinearProperties(edge1, system); edgeLengths[i-1] = system.Mass(); } Sort (edgeLengths, order); str << "ShortestEdges {Shortest edges} "; for (i = 1; i <= min(20, emap.Extent()); i++) { str << "ShortestEdges/Edge" << i; str << " {Edge " << order[i-1] << " (L=" << edgeLengths[order[i-1]-1] << ")} "; } str << flush; cout << "done" << endl; } void OCCGeometry :: GetUnmeshedFaceInfo (stringstream & str) { for (int i = 1; i <= fmap.Extent(); i++) { if (facemeshstatus[i-1] == -1) str << "Face" << i << " {Face " << i << " } "; } str << flush; } void OCCGeometry :: GetNotDrawableFaces (stringstream & str) { for (int i = 1; i <= fmap.Extent(); i++) { if (!fvispar[i-1].IsDrawable()) str << "Face" << i << " {Face " << i << " } "; } str << flush; } bool OCCGeometry :: ErrorInSurfaceMeshing () { for (int i = 1; i <= fmap.Extent(); i++) if (facemeshstatus[i-1] == -1) return true; return false; } int OCCGeometry :: GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam) { return OCCGenerateMesh (*this, mesh, mparam); } const Refinement & OCCGeometry :: GetRefinement () const { return * new OCCRefinementSurfaces (*this); } OCCParameters :: OCCParameters() { resthcloseedgefac = 1; resthcloseedgeenable = 1; resthminedgelen = 0.001; resthminedgelenenable = 1; } void OCCParameters :: Print(ostream & ost) const { ost << "OCC Parameters:" << endl << "close edges: " << resthcloseedgeenable << ", fac = " << resthcloseedgefac << endl << "minimum edge length: " << resthminedgelenenable << ", min len = " << resthminedgelen << endl; } OCCParameters occparam; } #endif netgen-6.2.1905/libsrc/occ/Partition_Loop3d.hxx0000644000175000017500000000444713504650527017756 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Loop3d.hxx // Module : GEOM #ifndef _Partition_Loop3d_HeaderFile #define _Partition_Loop3d_HeaderFile #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopTools_IndexedDataMapOfShapeListOfShape_HeaderFile #include #endif #ifndef _Standard_Boolean_HeaderFile #include #endif #ifndef _Standard_Real_HeaderFile #include #endif #ifndef _Standard_Version_HeaderFile #include #endif #if OCC_VERSION_HEX < 0x070000 #else #include #include #include #endif class TopoDS_Shape; #if OCC_VERSION_HEX < 0x070000 class TopTools_ListOfShape; class TopTools_MapOfOrientedShape; #endif class TopoDS_Edge; class TopoDS_Face; class gp_Vec; #ifndef _Standard_HeaderFile #include #endif #ifndef _Standard_Macro_HeaderFile #include #endif class Partition_Loop3d { public: void* operator new(size_t,void* anAddress) { return anAddress; } void* operator new(size_t size) { return Standard::Allocate(size); } void operator delete(void *anAddress) { if (anAddress) Standard::Free((Standard_Address&)anAddress); } // Methods PUBLIC // Partition_Loop3d(); void AddConstFaces(const TopoDS_Shape& S) ; void AddSectionFaces(const TopoDS_Shape& S) ; const TopTools_ListOfShape& MakeShells(const TopTools_MapOfOrientedShape& AvoidFacesMap) ; static Standard_Boolean IsInside(const TopoDS_Edge& E,const TopoDS_Face& F1,const TopoDS_Face& F2,const Standard_Boolean CountDot,Standard_Real& Dot,Standard_Boolean& GoodOri) ; static gp_Vec Normal(const TopoDS_Edge& E,const TopoDS_Face& F) ; protected: // Methods PROTECTED // // Fields PROTECTED // private: // Methods PRIVATE // // Fields PRIVATE // TopTools_ListOfShape myNewShells; TopTools_ListOfShape myFaces; TopTools_IndexedDataMapOfShapeListOfShape myEFMap; }; // other Inline functions and methods (like "C++: function call" methods) // #endif netgen-6.2.1905/libsrc/occ/Partition_Loop2d.ixx0000644000175000017500000000027013504650527017744 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Loop2d.ixx // Module : GEOM #include "Partition_Loop2d.jxx" netgen-6.2.1905/libsrc/occ/Partition_Loop2d.jxx0000644000175000017500000000077713504650527017761 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Loop2d.jxx // Module : GEOM #ifndef _TopoDS_Face_HeaderFile #include #endif #ifndef _TopoDS_Edge_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _BRepAlgo_Image_HeaderFile #include #endif #ifndef _Partition_Loop2d_HeaderFile #include "Partition_Loop2d.hxx" #endif netgen-6.2.1905/libsrc/occ/Partition_Loop3d.ixx0000644000175000017500000000027013504650527017745 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Loop3d.ixx // Module : GEOM #include "Partition_Loop3d.jxx" netgen-6.2.1905/libsrc/occ/Partition_Inter2d.hxx0000644000175000017500000000604013504650527020114 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter2d.hxx // Module : GEOM #ifndef _Partition_Inter2d_HeaderFile #define _Partition_Inter2d_HeaderFile #ifndef _Standard_Version_HeaderFile #include #endif #if OCC_VERSION_HEX < 0x070000 #ifndef _Handle_BRepAlgo_AsDes_HeaderFile #include #endif #else #include #include #endif #ifndef _Standard_Real_HeaderFile #include #endif #ifndef _Standard_Boolean_HeaderFile #include #endif class BRepAlgo_AsDes; class TopoDS_Face; #if OCC_VERSION_HEX < 0x070000 class TopTools_MapOfShape; class TopTools_ListOfShape; #endif class TopoDS_Vertex; class TopoDS_Edge; #ifndef _Standard_HeaderFile #include #endif #ifndef _Standard_Macro_HeaderFile #include #endif class Partition_Inter2d { public: void* operator new(size_t,void* anAddress) { return anAddress; } void* operator new(size_t size) { return Standard::Allocate(size); } void operator delete(void *anAddress) { if (anAddress) Standard::Free((Standard_Address&)anAddress); } // Methods PUBLIC // static void CompletPart2d(const Handle(BRepAlgo_AsDes)& AsDes,const TopoDS_Face& F,const TopTools_MapOfShape& NewEdges) ; static TopoDS_Vertex FindEndVertex(const TopTools_ListOfShape& VertList,const Standard_Real f,const Standard_Real l,const TopoDS_Edge& E,Standard_Boolean& First,Standard_Real& DU) ; static TopoDS_Vertex AddVonE(const TopoDS_Vertex& V,const TopoDS_Edge& E1,const TopoDS_Edge& E2,const Handle(BRepAlgo_AsDes)& AsDes,const TopoDS_Face& F) ; static Standard_Real GetTolerance(const TopoDS_Vertex& theV,const Standard_Real theU,const TopoDS_Edge& theE,const Handle(BRepAlgo_AsDes)& theAsDes) ; protected: // Methods PROTECTED // // Fields PROTECTED // private: // Methods PRIVATE // // Fields PRIVATE // }; // other Inline functions and methods (like "C++: function call" methods) // #endif netgen-6.2.1905/libsrc/occ/Partition_Spliter.hxx0000644000175000017500000000765613504650527020245 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Spliter.hxx // Module : GEOM #ifndef _Partition_Spliter_HeaderFile #define _Partition_Spliter_HeaderFile #ifndef _Standard_Version_HeaderFile #include #endif #ifndef _TopAbs_ShapeEnum_HeaderFile #include #endif #ifndef _TopoDS_Compound_HeaderFile #include #endif #ifndef _BRep_Builder_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopTools_MapOfShape_HeaderFile #include #endif #ifndef _TopTools_DataMapOfShapeShape_HeaderFile #include #endif #if OCC_VERSION_HEX < 0x070000 #ifndef _Handle_BRepAlgo_AsDes_HeaderFile #include #endif #else #include #include #endif #ifndef _BRepAlgo_Image_HeaderFile #include #endif #ifndef _Partition_Inter3d_HeaderFile #include "Partition_Inter3d.hxx" #endif #ifndef _TopTools_MapOfOrientedShape_HeaderFile #include #endif #ifndef _Standard_Boolean_HeaderFile #include #endif class BRepAlgo_AsDes; class TopoDS_Shape; #if OCC_VERSION_HEX < 0x070000 class TopTools_ListOfShape; #endif class TopoDS_Edge; #ifndef _Standard_HeaderFile #include #endif #ifndef _Standard_Macro_HeaderFile #include #endif class Partition_Spliter { public: void* operator new(size_t,void* anAddress) { return anAddress; } void* operator new(size_t size) { return Standard::Allocate(size); } void operator delete(void *anAddress) { if (anAddress) Standard::Free((Standard_Address&)anAddress); } // Methods PUBLIC // Partition_Spliter(); void AddShape(const TopoDS_Shape& S) ; void AddTool(const TopoDS_Shape& S) ; void Compute(const TopAbs_ShapeEnum Limit = TopAbs_SHAPE) ; void KeepShapesInside(const TopoDS_Shape& S) ; void RemoveShapesInside(const TopoDS_Shape& S) ; TopoDS_Shape Shape() const; void Clear() ; protected: // Methods PROTECTED // // Fields PROTECTED // private: // Methods PRIVATE // void MakeSolids(const TopoDS_Shape& Solid,TopTools_ListOfShape& Shells) ; void MakeShells(const TopoDS_Shape& S,TopTools_ListOfShape& NS) ; TopoDS_Shape MakeFaces(const TopoDS_Shape& S) ; void MakeEdges(const TopoDS_Edge& E,const TopTools_ListOfShape& VOnE,TopTools_ListOfShape& NE) const; TopoDS_Shape FindFacesInside(const TopoDS_Shape& S,const Standard_Boolean CheckClosed = Standard_False,const Standard_Boolean All = Standard_False) ; Standard_Boolean CheckTool(const TopoDS_Shape& S) ; void MergeEqualEdges(const TopTools_ListOfShape& LE) ; static Standard_Boolean IsInside(const TopoDS_Shape& S1,const TopoDS_Shape& S2) ; TopoDS_Shape GetOriginalShape(const TopoDS_Shape& aShape) const; void FindToolsToReconstruct() ; // Fields PRIVATE // TopAbs_ShapeEnum myDoneStep; TopoDS_Compound myShape; BRep_Builder myBuilder; TopTools_ListOfShape myListShapes; TopTools_MapOfShape myMapFaces; TopTools_MapOfShape myMapTools; TopTools_MapOfShape myEqualEdges; TopTools_MapOfShape myNewSection; TopTools_MapOfShape myClosedShapes; TopTools_MapOfShape mySharedFaces; TopTools_MapOfShape myWrappingSolid; TopTools_DataMapOfShapeShape myFaceShapeMap; TopTools_DataMapOfShapeShape myInternalFaces; TopTools_DataMapOfShapeShape myIntNotClFaces; Handle_BRepAlgo_AsDes myAsDes; BRepAlgo_Image myImagesFaces; BRepAlgo_Image myImagesEdges; BRepAlgo_Image myImageShape; Partition_Inter3d myInter3d; TopTools_MapOfOrientedShape myAddedFacesMap; }; // other Inline functions and methods (like "C++: function call" methods) // #endif netgen-6.2.1905/libsrc/occ/Partition_Spliter.jxx0000644000175000017500000000260313504650527020232 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Spliter.jxx // Module : GEOM #ifndef _BRepAlgo_AsDes_HeaderFile #include #endif #ifndef _TopoDS_Shape_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopoDS_Edge_HeaderFile #include #endif #ifndef _Partition_Spliter_HeaderFile #include "Partition_Spliter.hxx" #endif netgen-6.2.1905/libsrc/occ/vsocc.hpp0000644000175000017500000000161313504650527015652 0ustar kurtkurt#ifndef FILE_VSOCC #define FILE_VSOCC /**************************************************************************/ /* File: vsocc.hpp */ /* Author: Joachim Schoeberl */ /* Date: 05. Jan. 2011 */ /**************************************************************************/ namespace netgen { class VisualSceneOCCGeometry : public VisualScene { Array trilists; Array linelists; int selsurf; class OCCGeometry * occgeometry; public: VisualSceneOCCGeometry (); virtual ~VisualSceneOCCGeometry (); void SetGeometry (class OCCGeometry * ageom) { occgeometry = ageom; } virtual void BuildScene (int zoomall = 0); virtual void DrawScene (); virtual void MouseDblClick (int px, int py); }; } #endif netgen-6.2.1905/libsrc/occ/Partition_Loop2d.cxx0000644000175000017500000011063113504650527017741 0ustar kurtkurt#ifdef OCCGEOMETRY // GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R& D // // // // File : Partition_Loop2d.cxx // Author : Benedicte MARTIN // Module : GEOM // $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Loop2d.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $ //using namespace std; #include #include "Partition_Loop2d.ixx" #include "utilities.h" #include #include #include #include #include // #include // V6.3 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // V6.5 #include #include #include #include #include #include #include #include #include #include #include #include #include #define PI 3.14159265358979323846 //======================================================================= //function : Partition_Loop2d //purpose : //======================================================================= Partition_Loop2d::Partition_Loop2d() { } //======================================================================= //function : Init //purpose : Init with the set of edges must have // pcurves on . //======================================================================= void Partition_Loop2d::Init(const TopoDS_Face& F) { myConstEdges.Clear(); myNewWires .Clear(); myNewFaces .Clear(); myFace = F; myFaceOri = myFace.Orientation(); myFace.Orientation( TopAbs_FORWARD ); } //======================================================================= //function : AddConstEdge //purpose : Add as unique edge in the result. //======================================================================= void Partition_Loop2d::AddConstEdge (const TopoDS_Edge& E) { #ifdef DEB Standard_Real f,l; Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l); if (pc.IsNull()) { INFOS( "AddConstEdge(): EDGE W/O PCURVE on FACE"); } else #endif { myConstEdges.Append(E); } } void Partition_Loop2d::AddSectionEdge (const TopoDS_Edge& E) { #ifdef DEB Standard_Real f,l; Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l); if (pc.IsNull()) pc = BRep_Tool::CurveOnSurface( E, myFace, f,l); gp_Vec2d Tg1; gp_Pnt2d PC; pc->D1(0.5*(f+l), PC, Tg1); if (Tg1.Magnitude() <= gp::Resolution()) { MESSAGE (""); } if (pc.IsNull()) { INFOS( "AddConstEdge(): EDGE W/O PCURVE on FACE"); } else #endif { myConstEdges.Append(E); myConstEdges.Append(E.Reversed()); mySectionEdges.Add( E ); } } //======================================================================= //function : preciseU //purpose : find u such that the 3D point on theE is just out of tolerance // of theV //======================================================================= static Standard_Real preciseU (const BRepAdaptor_Surface& theSurf, const TopoDS_Edge& theE, const TopoDS_Vertex& theV, const Handle(Geom2d_Curve)& theC, const Standard_Boolean theFirstEnd) { Standard_Boolean isForward = ( theE.Orientation () == TopAbs_FORWARD ); if (theFirstEnd) isForward = !isForward; // find the first point in 2d and 3d Standard_Real f,l; BRep_Tool::Range( theE, f, l ); Standard_Real u0 = isForward ? l : f; gp_Pnt2d aP2d0 = theC->Value( u0 ); gp_Pnt aPnt0 = theSurf.Value( aP2d0.X(), aP2d0.Y() ); // shift in 2d and 3d Standard_Real du = ( l - f ) / 100, du3d = 0; if (isForward) du = -du; // target parameter Standard_Real u; while (du3d < ::RealSmall()) { // u for test u = u0 + du; du *= 10; // for the next iteration: increase du until du3d is large enough // find out how u is far from u0 in 3D gp_Pnt2d aP2d = theC->Value( u ); gp_Pnt aPnt = theSurf.Value( aP2d.X(), aP2d.Y() ); du3d = aPnt0.Distance( aPnt ); } // find u such that the 3D point is just out of tolerance of theV Standard_Real tolV = BRep_Tool::Tolerance( theV ) + Precision::Confusion(); u = u0 + du * tolV / du3d; // check that u is within the range if ( isForward ? (u < f) : (u > l) ) u = u0 + du; return u; } //======================================================================= //function : SelectEdge //purpose : Find in the list the edge connected with by // the vertex . // is removed from the list. If is in // with the same orientation, it's removed from the list //======================================================================= static Standard_Boolean SelectEdge(const BRepAdaptor_Surface& Surf, const TopoDS_Edge& CE, const TopoDS_Vertex& CV, TopoDS_Edge& NE, const TopTools_ListOfShape& LE) { NE.Nullify(); if (LE.Extent() > 1) { //-------------------------------------------------------------- // Several possible edges. // - Test the edge difference of CE //-------------------------------------------------------------- TopoDS_Face FForward = Surf.Face(); TopoDS_Edge aPrevNE; gp_Vec2d CTg1, Tg1, CTg2, Tg2; gp_Pnt2d PC, P; Standard_Real f, l; Handle(Geom2d_Curve) Cc, C; Cc = BRep_Tool::CurveOnSurface(CE,FForward,f,l); Standard_Boolean isForward = ( CE.Orientation () == TopAbs_FORWARD ); Standard_Real uc, u, du = Precision::PConfusion(); uc = isForward ? ( l - du ) : ( f + du ); Cc->D1(uc, PC, CTg1); if (!isForward) CTg1.Reverse(); Standard_Real anglemin = 3 * M_PI, tolAng = 1.e-8; // select an edge whose first derivative is most left of CTg1 // ie an angle between Tg1 and CTg1 is least TopTools_ListIteratorOfListOfShape itl; for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (E.IsSame(CE)) continue; if (! CV.IsSame( TopExp::FirstVertex( E, Standard_True ))) continue; isForward = ( E.Orientation () == TopAbs_FORWARD ); // get E curve C = BRep_Tool::CurveOnSurface(E,FForward,f,l); // get the first derivative Tg1 u = isForward ? ( f + du ) : ( l - du ); C->D1(u, P, Tg1); if (!isForward) Tg1.Reverse(); // -PI < angle < PI Standard_Real angle = Tg1.Angle(CTg1); if (M_PI - Abs(angle) <= tolAng) { // an angle is too close to PI; assure that an angle sign really // reflects an edge position: +PI - an edge is worst, // -PI - an edge is best. u = preciseU( Surf, CE, CV, Cc, Standard_False); gp_Vec2d CTg; Cc->D1(u, PC, CTg); if (CE.Orientation() == TopAbs_REVERSED) CTg.Reverse(); u = preciseU( Surf, E, CV, C, Standard_True); C->D1(u, P, Tg1); if (!isForward) Tg1.Reverse(); angle = Tg1.Angle(CTg); } Standard_Boolean isClose = ( Abs( angle - anglemin ) <= tolAng ); if (angle <= anglemin) { if (isClose) aPrevNE = NE; else aPrevNE.Nullify(); anglemin = angle ; NE = E; } else if (isClose) aPrevNE = E; } if (!aPrevNE.IsNull()) { // select one of close edges, the most left one. Cc = BRep_Tool::CurveOnSurface( NE, FForward, f, l ); uc = preciseU( Surf, NE, CV, Cc, Standard_True); Cc->D1(uc, PC, CTg1); if (NE.Orientation() != TopAbs_FORWARD) CTg1.Reverse(); u = preciseU( Surf, aPrevNE, CV, C, Standard_True); C->D1(u, P, Tg1); if (aPrevNE.Orientation() != TopAbs_FORWARD) Tg1.Reverse(); if ( Tg1.Angle(CTg1) < 0) NE = aPrevNE; } } else if (LE.Extent() == 1) { NE = TopoDS::Edge(LE.First()); } else { return Standard_False; } return !NE.IsNull(); } //======================================================================= //function : SamePnt2d //purpose : //======================================================================= static Standard_Boolean SamePnt2d(const TopoDS_Vertex& V1, const TopoDS_Edge& E1, const TopoDS_Vertex& V2, const TopoDS_Edge& E2, const TopoDS_Face& F) { Standard_Real f1,f2,l1,l2; Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,F,f1,l1); Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,F,f2,l2); gp_Pnt2d P1 = C1->Value( BRep_Tool::Parameter(V1,E1)); gp_Pnt2d P2 = C2->Value( BRep_Tool::Parameter(V2,E2)); Standard_Real Tol = 100 * BRep_Tool::Tolerance(V1); Standard_Real Dist = P1.Distance(P2); return Dist < Tol; } //======================================================================= //function : StoreInMVE //purpose : //======================================================================= static void StoreInMVE (const TopoDS_Face& /*F*/, TopoDS_Edge& E, TopTools_DataMapOfShapeListOfShape& MVE ) { TopoDS_Vertex V1, V2; TopTools_ListOfShape Empty; TopExp::Vertices(E,V1,V2); if (!MVE.IsBound(V1)) { MVE.Bind(V1,Empty); } MVE(V1).Append(E); if (!MVE.IsBound(V2)) { MVE.Bind(V2,Empty); } MVE(V2).Append(E); } //======================================================================= //function : RemoveFromMVE //purpose : //======================================================================= static void RemoveFromMVE(const TopoDS_Edge& E, TopTools_DataMapOfShapeListOfShape& MVE) { TopTools_ListIteratorOfListOfShape itl; TopoDS_Vertex V1,V2; TopExp::Vertices (E,V1,V2); if (MVE.IsBound(V1)) for ( itl.Initialize(MVE(V1)); itl.More(); itl.Next()) { if (itl.Value().IsEqual(E)) { MVE(V1).Remove(itl); break; } } if (MVE.IsBound(V2)) for ( itl.Initialize(MVE(V2)); itl.More(); itl.Next()) { if (itl.Value().IsEqual(E)) { MVE(V2).Remove(itl); break; } } } //======================================================================= //function : addConnected //purpose : add to all edges reachable from //======================================================================= static void addConnected(const TopoDS_Shape& E, TopTools_MapOfShape& EM, TopTools_MapOfShape& VM, const TopTools_DataMapOfShapeListOfShape& MVE) { // Loop on vertices of E TopoDS_Iterator itV ( E ); for ( ; itV.More(); itV.Next()) { if ( ! VM.Add ( itV.Value() )) continue; // Loop on edges sharing V TopTools_ListIteratorOfListOfShape itE( MVE( itV.Value() ) ); for (; itE.More(); itE.Next()) { if ( EM.Add( itE.Value() )) addConnected ( itE.Value(), EM, VM, MVE ); } } } //======================================================================= //function : canPassToOld //purpose : //======================================================================= // static Standard_Boolean canPassToOld (const TopoDS_Shape& V, // TopTools_MapOfShape& UsedShapesMap, // const TopTools_DataMapOfShapeListOfShape& MVE, // const TopTools_MapOfShape& SectionEdgesMap) // { // TopTools_ListIteratorOfListOfShape itE( MVE(V) ); // // Loop on edges sharing V // for (; itE.More(); itE.Next()) { // if ( !UsedShapesMap.Add( itE.Value() )) // continue; // already checked // if ( !SectionEdgesMap.Contains( itE.Value() )) // return Standard_True; // WE PASSED // TopoDS_Iterator itV( itE.Value() ); // // Loop on vertices of an edge // for (; itV.More(); itV.Next()) { // if ( !UsedShapesMap.Add( itV.Value() )) // continue; // already checked // else // return canPassToOld( itV.Value(), UsedShapesMap, MVE, SectionEdgesMap); // } // } // return Standard_False; // } //======================================================================= //function : MakeDegenAndSelect //purpose : Find parameter of intersection of with and // select an edge with its parameter closest to found one. // Return new degenerated edge trimming by found parameters //======================================================================= static TopoDS_Edge MakeDegenAndSelect(const TopoDS_Edge& CE, const TopoDS_Vertex& CV, TopoDS_Edge& NE, TopTools_SequenceOfShape& EdgesSeq, TColStd_SequenceOfReal& USeq, const TopoDS_Edge& DE) { if (EdgesSeq.Length() < 3) { if (CE == EdgesSeq.First()) NE = TopoDS::Edge( EdgesSeq.Last() ); else NE = TopoDS::Edge( EdgesSeq.First() ); return DE; } // find parameter on DE where it intersects CE Standard_Real U1; Standard_Integer i, nb = EdgesSeq.Length(); for (i=1; i<= nb; ++i) { if (CE == EdgesSeq(i)) { U1 = USeq(i); break; } } // select NE with param closest to U1 thus finding U2 for a new degen edge Standard_Real U2, dU, dUmin = 1.e100; Standard_Boolean isReversed = ( DE.Orientation() == TopAbs_REVERSED ); for (i=1; i<= nb; ++i) { dU = USeq(i) - U1; if (isReversed ? (dU > 0) : (dU < 0)) continue; dU = Abs( dU ); if ( dU > dUmin || IsEqual( dU, 0.)) continue; const TopoDS_Edge& E = TopoDS::Edge ( EdgesSeq(i) ); if ( ! CV.IsSame( TopExp::FirstVertex( E , Standard_True ))) continue; NE = E; dUmin = dU + Epsilon(dU); U2 = USeq(i); } // make a new degenerated edge TopoDS_Edge NewDegen = TopoDS::Edge ( DE.EmptyCopied() ); Standard_Real Tol = BRep_Tool::Tolerance( CV ); TopoDS_Vertex V = CV; BRep_Builder B; V.Orientation( NewDegen.Orientation() ); B.UpdateVertex( V, U1, NewDegen, Tol); B.Add ( NewDegen , V ); V.Reverse(); B.UpdateVertex( V, U2, NewDegen, Tol); B.Add ( NewDegen , V ); return NewDegen; } //======================================================================= //function : prepareDegen //purpose : Intersect with edges bound to its vertex in // and store intersection parameter on in // as well as the edges them-self in . // Bind to vertex of in //======================================================================= static void prepareDegen (const TopoDS_Edge& DegEdge, const TopoDS_Face& F, const TopTools_DataMapOfShapeListOfShape& MVE, TopTools_SequenceOfShape& EdgesSeq, TColStd_SequenceOfReal& USeq, TopTools_DataMapOfShapeInteger& MVDEI, const Standard_Integer DegEdgeIndex) { const TopoDS_Vertex& V = TopExp::FirstVertex ( DegEdge ); MVDEI.Bind ( V, DegEdgeIndex ); const TopTools_ListOfShape& EdgesList = MVE ( V ); // if only 2 edges come to degenerated one, no pb in selection and // no need to intersect them, just simulate asked data Standard_Boolean doIntersect = ( EdgesList.Extent() > 2 ); BRepAdaptor_Curve2d DC, C; Geom2dInt_GInter InterCC; Standard_Real Tol = Precision::PConfusion(); if ( doIntersect ) DC.Initialize( DegEdge, F ); // avoid intersecting twice the same edge // BRepOffset_DataMapOfShapeReal EUMap ( EdgesList.Extent() ); // V6.3 TopTools_DataMapOfShapeReal EUMap ( EdgesList.Extent() ); // V6.5 Standard_Real U, f, l; BRep_Tool::Range (DegEdge, f, l); TopTools_ListIteratorOfListOfShape itE (EdgesList); for (; itE.More(); itE.Next()) { const TopoDS_Edge& E = TopoDS::Edge ( itE.Value() ); if ( !doIntersect) { U = 0.; // it won't be used } else if ( BRep_Tool::IsClosed( E, F )) { // seam edge: select U among f and l Standard_Boolean first = Standard_True; if ( V.IsSame ( TopExp::FirstVertex( E, Standard_True ) )) first = Standard_False; if ( DegEdge.Orientation() == TopAbs_REVERSED ) first = !first; U = first ? f : l; } else if ( EUMap.IsBound( E ) ) { // same edge already bound U = EUMap( E ); } else { // intersect 2d curves C.Initialize( E, F ); InterCC.Perform ( DC, C , Tol, Tol ); if (! InterCC.IsDone() || InterCC.NbPoints() == 0) { MESSAGE ( "NO 2d INTERSECTION ON DEGENERATED EDGE" ); continue; } // hope there is only one point of intersection U = InterCC.Point( 1 ).ParamOnFirst(); } USeq.Append ( U ); EdgesSeq.Append ( E ); } } //======================================================================= //function : Perform //purpose : Make loops. //======================================================================= void Partition_Loop2d::Perform() { Standard_Integer NbConstEdges = myConstEdges.Extent(); TopTools_DataMapOfShapeListOfShape MVE(NbConstEdges) , MVE2(NbConstEdges); TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit; TopTools_ListIteratorOfListOfShape itl; TopoDS_Vertex V1,V2; BRepAdaptor_Surface Surface ( myFace, Standard_False ); // degenerated edges and parameters of their 2d intersection with other edges TopoDS_Edge DE [2]; TopTools_SequenceOfShape SEID [2]; // seq of edges intersecting degenerated TColStd_SequenceOfReal SeqU [2]; // n-th U corresponds to n-th edge in SEID TopTools_DataMapOfShapeInteger MVDEI(2); // map vertex - degenerated edge index Standard_Integer iDeg = 0; // index of degenerated edge [0,1] //--------------------------------------------------------- // Construction map vertex => edges, find degenerated edges //--------------------------------------------------------- for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) { TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if ( BRep_Tool::Degenerated( E )) { if (DE[0].IsNull()) DE[0] = E; else DE[1] = E; } else StoreInMVE(myFace,E,MVE); } // fill data for degenerated edges if ( ! DE[0].IsNull() ) prepareDegen ( DE[0], myFace, MVE, SEID[0], SeqU[0], MVDEI, 0); if ( ! DE[1].IsNull() ) prepareDegen ( DE[1], myFace, MVE, SEID[1], SeqU[1], MVDEI, 1); // to detect internal wires Standard_Boolean isInternCW = 0; MVE2 = MVE; //------------------------------ // Construction of all the wires //------------------------------ // first, we collect wire edges in WEL list looking for same edges that // will be then removed possibly exploding a wire into parts; // second, build wire(s) while (!MVE.IsEmpty()) { TopoDS_Vertex VF,CV; TopoDS_Edge CE,NE,EF; TopoDS_Wire NW; BRep_Builder B; Standard_Boolean End = Standard_False; TopTools_ListOfShape WEL; Mapit.Initialize(MVE); if (Mapit.Value().IsEmpty()) { MVE.UnBind(Mapit.Key()); continue; } // EF first edge. EF = CE = TopoDS::Edge(Mapit.Value().First()); // VF first vertex VF = TopExp::FirstVertex( CE, Standard_True); isInternCW = Standard_True; TopTools_MapOfShape addedEM (NbConstEdges); // map of edges added to WEL TopTools_MapOfShape doubleEM (NbConstEdges); // edges encountered twice in WEL //------------------------------- // Construction of a wire. //------------------------------- while (!End) { // only a seam is allowed twice in a wire, the others should be removed if (addedEM.Add ( CE ) || BRep_Tool::IsClosed( CE, myFace ) ) WEL.Append( CE ); else { doubleEM.Add( CE ); RemoveFromMVE (CE,MVE2); TopoDS_Edge CERev = CE; CERev.Reverse(); RemoveFromMVE (CERev,MVE2); } RemoveFromMVE (CE,MVE); CV = TopExp::LastVertex( CE, Standard_True); if (isInternCW && !mySectionEdges.Contains(CE)) // wire is internal if all edges are section ones isInternCW = Standard_False; if (MVDEI.IsBound( CV )) { // CE comes to the degeneration iDeg = MVDEI( CV ); TopoDS_Edge NewDegen; NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]); WEL.Append( NewDegen ); CE = NE; End = CV.IsSame( VF ); continue; } //-------------- // stop test //-------------- if (MVE(CV).IsEmpty()) { End=Standard_True; MVE.UnBind(CV); } else if (CV.IsSame(VF) && SamePnt2d(CV,CE, VF,EF, myFace) ) { End = Standard_True; } else { //---------------------------- // select new current edge //---------------------------- if (! SelectEdge (Surface,CE,CV,NE,MVE(CV))) { MESSAGE ( " NOT CLOSED WIRE " ); End=Standard_True; } else CE = NE; } } // while ( !End ) // WEL is built, built wire(s) itl.Initialize( WEL ); if ( doubleEM.IsEmpty()) { // no double edges B.MakeWire( NW ); for (; itl.More(); itl.Next()) B.Add ( NW, itl.Value()); if (isInternCW) myInternalWL.Append(NW); else myNewWires.Append (NW); } else { // remove double and degenerated edges from WEL while (itl.More()) { const TopoDS_Edge& E = TopoDS::Edge ( itl.Value() ); if ( doubleEM.Contains( E ) || BRep_Tool::Degenerated( E )) WEL.Remove( itl ); else itl.Next(); } if ( WEL.IsEmpty()) continue; // remove double edges from SEID and SeqU Standard_Integer i,j; for (j=0; j<2; ++j) { for (i=1; i<=SEID[j].Length(); ++i) { if (doubleEM.Contains( SEID[j].Value(i))) { SEID[j].Remove( i ); SeqU[j].Remove( i-- ); } } } // removal of double edges can explode a wire into parts, // make new wires of them. // A Loop like previous one but without 2d check while ( !WEL.IsEmpty() ) { CE = TopoDS::Edge( WEL.First() ); WEL.RemoveFirst(); B.MakeWire( NW ); VF = TopExp::FirstVertex ( CE, Standard_True); End = Standard_False; while ( !End) { B.Add( NW, CE ); CV = TopExp::LastVertex ( CE, Standard_True); if (MVDEI.IsBound( CV )) { // CE comes to the degeneration iDeg = MVDEI( CV ); TopoDS_Edge NewDegen; NewDegen = MakeDegenAndSelect( CE, CV, NE, SEID[iDeg], SeqU[iDeg], DE[iDeg]); B.Add( NW, NewDegen ); End = CV.IsSame( VF ); CE = NE; if (!NE.IsNull()) { // remove NE from WEL for (itl.Initialize( WEL ); itl.More(); itl.Next()) if ( NE == itl.Value()) { WEL.Remove( itl ); break; } } } // end degeneration else { if (CV.IsSame( VF )) { End = Standard_True; continue; } // edges in WEL most often are well ordered // so try to iterate until the End Standard_Boolean add = Standard_False; itl.Initialize(WEL); while ( itl.More() && !End) { NE = TopoDS::Edge( itl.Value() ); if ( CV.IsSame( TopExp::FirstVertex( NE, Standard_True ))) { WEL.Remove( itl ); if (add) B.Add( NW, CE ); CE = NE; add = Standard_True; CV = TopExp::LastVertex( CE, Standard_True); if (MVDEI.IsBound( CV ) || CV.IsSame( VF )) break; } else itl.Next(); } if (!add) End = Standard_True; } } // !End myInternalWL.Append( NW ); } } // end building new wire(s) from WEL } // end Loop on MVE // all wires are built // ============================================================ // select really internal wires i.e. those from which we can`t // pass to an old (not section) edge // ============================================================ Standard_Integer nbIW = myInternalWL.Extent(); if (nbIW == 0) return; if ( myNewWires.Extent() != 1 && nbIW > 1) { TopTools_MapOfShape outerEM (NbConstEdges); // edges connected to non-section ones TopTools_MapOfShape visitedVM (NbConstEdges); for ( itl.Initialize( myConstEdges ); itl.More(); itl.Next()) { if ( ! mySectionEdges.Contains( itl.Value() )) addConnected (itl.Value(), outerEM, visitedVM, MVE2); } // if an edge of a wire is in , the wire is not internal TopExp_Explorer expIWE; TopTools_ListIteratorOfListOfShape itIW ( myInternalWL ); while (itIW.More()) { expIWE.Init ( itIW.Value() , TopAbs_EDGE ); if ( outerEM.Contains( expIWE.Current() )) { myNewWires.Append ( itIW.Value() ); myInternalWL.Remove( itIW ); // == itIW.Next() } else itIW.Next(); } } } //======================================================================= //function : isHole //purpose : //======================================================================= static Standard_Boolean isHole (const TopoDS_Wire& W, const TopoDS_Face& F) { BRep_Builder B; TopoDS_Shape newFace = F.EmptyCopied(); B.Add(newFace,W.Oriented(TopAbs_FORWARD)); BRepTopAdaptor_FClass2d classif (TopoDS::Face(newFace), Precision::PConfusion()); return (classif.PerformInfinitePoint() == TopAbs_IN); } //======================================================================= //function : IsInside //purpose : check if W1 is inside W2. Suppose W2 is not a hole !!!! //======================================================================= static Standard_Boolean isInside(const TopoDS_Face& F, const TopoDS_Wire& W1, const TopoDS_Wire& W2) { // make a face with wire W2 BRep_Builder B; TopoDS_Shape aLocalShape = F.EmptyCopied(); TopoDS_Face newFace = TopoDS::Face(aLocalShape); B.Add(newFace,W2); // get any 2d point of W1 TopExp_Explorer exp(W1,TopAbs_EDGE); if (BRep_Tool::Degenerated( TopoDS::Edge( exp.Current() ))) exp.Next(); const TopoDS_Edge& e = TopoDS::Edge(exp.Current()); Standard_Real f,l; Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(e,F,f,l); gp_Pnt2d pt2d(C2d->Value( 0.5 * ( f + l ))); BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion()); return (classif.Perform(pt2d) == TopAbs_IN); } //======================================================================= //function : NewWires //purpose : Returns the list of wires performed. // can be an empty list. //======================================================================= const TopTools_ListOfShape& Partition_Loop2d::NewWires() const { return myNewWires; } //======================================================================= //function : NewFaces //purpose : Returns the list of faces. //Warning : The method as to be called before. // can be an empty list. //======================================================================= const TopTools_ListOfShape& Partition_Loop2d::NewFaces() const { return myNewFaces; } //======================================================================= //function : findEqual //purpose : move wires form to pairs of wires build of the // same edges //======================================================================= static void findEqual (TopTools_ListOfShape& WL, TopTools_DataMapOfShapeShape& EqWM, const TopoDS_Face& F) { TopTools_ListIteratorOfListOfShape it1, it2; Standard_Integer i,j; TColStd_MapOfInteger IndMap; for (it1.Initialize(WL), i=1; it1.More(); it1.Next(), i++) { if (IndMap.Contains(i)) continue; const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value()); for (it2.Initialize(WL), j=1; it2.More(); it2.Next(), j++) { if (j <= i || IndMap.Contains(j)) continue; TopTools_IndexedMapOfShape EdgesMap; TopExp::MapShapes (Wire1, TopAbs_EDGE, EdgesMap); const TopoDS_Shape& Wire2 = it2.Value(); TopoDS_Iterator itE ( Wire2); for (; itE.More(); itE.Next()) { if ( !EdgesMap.Contains( itE.Value()) ) break; } if (!itE.More()) { // all edges are same if (isHole( Wire1, F)) { EqWM.Bind ( Wire1, Wire2 ); } else { EqWM.Bind ( Wire2, Wire1 ); } IndMap.Add(i); IndMap.Add(j); break; } } } // clear WL it1.Initialize(WL); i=1; while (it1.More()) { if (IndMap.Contains(i)) WL.Remove(it1); // next node becomes current and with Next() we would miss it else it1.Next(); i++; } } //======================================================================= //function : classify //purpose : bind to a wire a list of internal wires //======================================================================= static void classify(const TopTools_DataMapOfShapeShape& EqWM, BRepAlgo_AsDes& OuterInner, const TopoDS_Face& F) { TopTools_DataMapIteratorOfDataMapOfShapeShape it1, it2; for (it1.Initialize(EqWM); it1.More(); it1.Next()) { // find next after it1.Value() for (it2.Initialize(EqWM); it2.More(); it2.Next()) if (it1.Value().IsSame( it2.Value() )) { it2.Next(); break; } for ( ; it2.More(); it2.Next()) { const TopoDS_Wire& Wire1 = TopoDS::Wire( it1.Value() ); const TopoDS_Wire& Wire2 = TopoDS::Wire( it2.Value() ); if (isInside(F, Wire1, Wire2)) OuterInner.Add (Wire2, Wire1); else if (isInside(F, Wire2, Wire1)) OuterInner.Add (Wire1, Wire2); } } } //======================================================================= //function : WiresToFaces //purpose : Build faces from the wires result. // serves to find original edge by new // one.
contains edges resulting from face // intersections //======================================================================= void Partition_Loop2d::WiresToFaces(const BRepAlgo_Image& ) { Standard_Integer nbW = myNewWires.Extent() + myInternalWL.Extent(); if (nbW==0) return; BRepAlgo_FaceRestrictor FR; FR.Init (myFace,Standard_False); // FaceRestrictor is instable in rather simple cases // (ex. a single face of bellecoque.brep splited by 10 planes: // sometimes 1-2 faces are missing ). // So we use it as less as possible: no holes -> make faces by hands // are there holes in myFace ? Standard_Boolean hasOldHoles = Standard_False; TopoDS_Iterator itOldW (myFace); if ( itOldW.More()) { const TopoDS_Wire& FirstOldWire = TopoDS::Wire( itOldW.Value() ); itOldW.Next(); hasOldHoles = itOldW.More() || isHole( FirstOldWire, myFace); } if (myInternalWL.IsEmpty() && !hasOldHoles) { // each wire bounds one face BRep_Builder B; TopTools_ListIteratorOfListOfShape itNW (myNewWires); for (; itNW.More(); itNW.Next()) { TopoDS_Face NF = TopoDS::Face ( myFace.EmptyCopied() ); B.Add ( NF, itNW.Value() ); NF.Orientation( myFaceOri); myNewFaces.Append ( NF ); } return; } // FaceRestrictor can't classify wires build on all the same edges // and gives incorrect result in such cases (ex. a plane cut into 2 parts by cylinder) // We must make faces of equal wires separately. One of equal wires makes a // hole in a face and should come together with outer wires of face. // The other of a wires pair bounds a face that may have holes in turn. // Find equal wires among internal wires TopTools_DataMapOfShapeShape EqWM; // key is a hole part of a pair of equal wires findEqual (myInternalWL, EqWM, myFace); if (!EqWM.IsEmpty()) { // there are equal wires if (hasOldHoles) myInternalWL.Append( myNewWires ); // an old wire can be inside an equal wire // classify equal wire pairs BRepAlgo_AsDes OuterInner; classify (EqWM,OuterInner,myFace); // make face of most internal of equal wires and its inner wires while ( !EqWM.IsEmpty()) { TopTools_ListOfShape prevHolesL; // list of hole-part of previous most internal equal wires // find most internal wires among pairs (key - hole, value - outer part) TopTools_DataMapIteratorOfDataMapOfShapeShape it(EqWM); Standard_Integer nbEqW = EqWM.Extent(); // protection against infinite loop for ( ; it.More(); it.Next()) { TopoDS_Wire outerW = TopoDS::Wire ( it.Value() ); if ( OuterInner.HasDescendant( outerW ) && // has internal ! OuterInner.Descendant( outerW ).IsEmpty() ) continue; FR.Add( outerW ); // add internal wires that are inside of outerW TopTools_ListIteratorOfListOfShape itIW (myInternalWL); while ( itIW.More()) { TopoDS_Wire IW = TopoDS::Wire ( itIW.Value() ); if ( isInside (myFace, IW, outerW)) { FR.Add (IW); myInternalWL.Remove( itIW ); // == itIW.Next() !!! } else itIW.Next(); } // the hole-part of current pair of equal wires will be in the next new face prevHolesL.Append ( it.Key() ); } // Loop on map of equal pairs searching for innermost wires // make faces FR.Perform(); if (FR.IsDone()) { for (; FR.More(); FR.Next()) myNewFaces.Append(FR.Current()); } FR.Clear(); // add hole-parts to FaceRestrictor, // remove them from the EqWM, // remove found wires as internal of resting classified wires Standard_Boolean clearOuterInner = ( prevHolesL.Extent() < EqWM.Extent() ); TopTools_ListIteratorOfListOfShape itPrev (prevHolesL); for (; itPrev.More(); itPrev.Next()) { TopoDS_Wire& Hole = TopoDS::Wire ( itPrev.Value() ); FR.Add ( Hole ); if (clearOuterInner) { const TopoDS_Wire& outerW = TopoDS::Wire ( EqWM.Find( Hole ) ); // Loop on wires including outerW TopTools_ListIteratorOfListOfShape itO( OuterInner.Ascendant( outerW )); for (; itO.More(); itO.Next()) { TopTools_ListOfShape& innerL = OuterInner.ChangeDescendant( itO.Value() ); TopTools_ListIteratorOfListOfShape itI (innerL); // Loop on internal wires of current including wire for (; itI.More(); itI.Next()) if ( outerW.IsSame( itI.Value() )) { innerL.Remove( itI ); break; } } } EqWM.UnBind ( Hole ); } if (nbEqW == EqWM.Extent()) { // error: pb with wires classification #ifdef DEB MESSAGE("Partition_Loop2d::WiresToFaces(), pb with wires classification"); #endif break; } } // while (!EqWM.IsEmpty) } // if !EqWM.IsEmpty() myNewWires.Append ( myInternalWL ); TopTools_ListIteratorOfListOfShape itW (myNewWires); for (; itW.More(); itW.Next()) { TopoDS_Wire& W = TopoDS::Wire ( itW.Value() ); FR.Add(W); } FR.Perform(); for (; FR.IsDone() && FR.More(); FR.Next()) myNewFaces.Append(FR.Current()); TopTools_ListIteratorOfListOfShape itNF (myNewFaces); for (; itNF.More(); itNF.Next()) itNF.Value().Orientation( myFaceOri ); } #endif netgen-6.2.1905/libsrc/occ/Partition_Spliter.ixx0000644000175000017500000000207113504650527020230 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Spliter.ixx // Module : GEOM #include "Partition_Spliter.jxx" netgen-6.2.1905/libsrc/occ/Partition_Inter2d.cxx0000644000175000017500000005543013504650527020116 0ustar kurtkurt#ifdef OCCGEOMETRY // GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R& D, LEG, PRINCIPIA R& D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter2d.cxx // Author : Benedicte MARTIN // Module : GEOM // $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Inter2d.cxx,v 1.5 2008/03/31 14:20:28 wabro Exp $ //using namespace std; #include "Partition_Inter2d.ixx" #include "utilities.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEB static Standard_Boolean TestEdges = 0; static Standard_Integer NbF2d = 0; static Standard_Integer NbE2d = 0; #endif //======================================================================= //function : getOtherShape //purpose : //======================================================================= static TopoDS_Shape getOtherShape(const TopoDS_Shape& theS, const TopTools_ListOfShape& theSList) { TopTools_ListIteratorOfListOfShape anIt( theSList ); for ( ; anIt.More(); anIt.Next() ) if (!theS.IsSame( anIt.Value() )) return anIt.Value(); return TopoDS_Shape(); } //======================================================================= //function : findVOnE //purpose : on theE, find a vertex close to theV, such that an edge // passing through it is an itersection of theF1 and theF2. // theE intersects theE2 at theV //======================================================================= static Standard_Boolean findVOnE(const TopoDS_Vertex & theV, const TopoDS_Edge& theE, const TopoDS_Edge& theE2, const TopoDS_Shape& theF1, const TopoDS_Shape& theF2, const Handle(BRepAlgo_AsDes)& theAsDes, TopoDS_Vertex & theFoundV) { Standard_Real MinDist2 = ::RealLast(); gp_Pnt P; // check all vertices on theE const TopTools_ListOfShape& aVList = theAsDes->Descendant( theE ); TopTools_ListIteratorOfListOfShape anIt( aVList ); if (anIt.More()) P = BRep_Tool::Pnt( theV ); for ( ; anIt.More(); anIt.Next() ) { // check by distance TopoDS_Vertex & V = TopoDS::Vertex( anIt.Value() ); Standard_Real dist2 = P.SquareDistance( BRep_Tool::Pnt( V )); if (dist2 < MinDist2) MinDist2 = dist2; else continue; // V is a candidate if among edges passing through V there is one // which is an intersection of theF1 and theF2 TopTools_ListIteratorOfListOfShape anEIt( theAsDes->Ascendant( V )); Standard_Boolean isOk = Standard_False; for ( ; !isOk && anEIt.More(); anEIt.Next() ) { const TopoDS_Shape & E2 = anEIt.Value(); if ( theE2.IsSame( E2 )) continue; const TopTools_ListOfShape & aFList = theAsDes->Ascendant( E2 ); if (aFList.IsEmpty()) continue; if ( theF1.IsSame( aFList.First() )) isOk = theF2.IsSame( aFList.Last() ); else isOk = theF2.IsSame( aFList.First() ) && theF1.IsSame( aFList.Last() ); } if (isOk) theFoundV = V; } if (theFoundV.IsNull()) return Standard_False; // check that MinDist2 is not too large Standard_Real f, l; TopLoc_Location L; Handle(Geom_Curve) aCurve = BRep_Tool::Curve( theE, L, f, l ); gp_Pnt P1 = aCurve->Value( f ); gp_Pnt P2 = aCurve->Value( 0.3 * f + 0.7 * l ); //gp_Pnt P2 = aCurve->Value( 0.5 * ( f + l )); if (MinDist2 > P1.SquareDistance( P2 )) return Standard_False; #ifdef DEB MESSAGE("findVOnE: found MinDist = " << sqrt (MinDist2)); #endif return Standard_True; } //======================================================================= //function : AddVonE //purpose : Put V in AsDes as intersection of E1 and E2. // Check that vertex equal to V already exists on one // of edges, in such a case, V is not added but // existing vertex is updated to be on E1 and E2 and // is returned insead of V. //======================================================================= TopoDS_Vertex Partition_Inter2d::AddVonE(const TopoDS_Vertex& theV, const TopoDS_Edge& E1, const TopoDS_Edge& E2, const Handle(BRepAlgo_AsDes)& AsDes, const TopoDS_Face& theF) { //------------------------------------------------------------- // test if the points of intersection already exist. If not, // add as descendants of the edges. // nb: theses points are only vertices of intersection. //------------------------------------------------------------- const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1); const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2); gp_Pnt P1,P2; TopoDS_Vertex V1,V2; TopTools_ListIteratorOfListOfShape it; BRep_Builder B; TopAbs_Orientation O1,O2; Standard_Real U1,U2; Standard_Real Tol,Tol1,Tol2; Standard_Boolean OnE1,OnE2; TopoDS_Vertex V = theV; U1 = BRep_Tool::Parameter(V,E1); U2 = BRep_Tool::Parameter(V,E2); O1 = V.Orientation(); O2 = O1; P1 = BRep_Tool::Pnt(V); Tol = BRep_Tool::Tolerance( V ); OnE1 = OnE2 = Standard_False; //----------------------------------------------------------------- // Search if the point of intersection is a vertex of E1. //----------------------------------------------------------------- for (it.Initialize(VOnE1); it.More(); it.Next()) { const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() ); if (V.IsSame( CV )) { V1 = V; OnE1 = Standard_True; break; } P2 = BRep_Tool::Pnt( CV ); Tol1 = 1.1*(Tol + BRep_Tool::Tolerance( CV )); if (P1.SquareDistance(P2) <= Tol1*Tol1) { V = CV; V1 = V; OnE1 = Standard_True; break; } } if (OnE1) { //----------------------------------------------------------------- // Search if the vertex found is still on E2. //----------------------------------------------------------------- for (it.Initialize(VOnE2); it.More(); it.Next()) { if (V.IsSame( it.Value() )) { OnE2 = Standard_True; V2 = V; break; } } } if (!OnE2) { for (it.Initialize(VOnE2); it.More(); it.Next()) { //----------------------------------------------------------------- // Search if the point of intersection is a vertex of E2. //----------------------------------------------------------------- const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() ); P2 = BRep_Tool::Pnt( CV ); Tol2 = 1.1*(Tol + BRep_Tool::Tolerance( CV )); if (P1.SquareDistance(P2) <= Tol2*Tol2) { V = CV; V2 = V; OnE2 = Standard_True; break; } } } if (!OnE1 && !OnE2 && !theF.IsNull()) { // if 3 faces intersects each others, 3 new edges on them must pass // through one vertex but real intersection points of each // pair of edges are sometimes more far than a tolerance. // Try to analitically find vertices that E1 and E2 must pass trough TopoDS_Shape F1 = getOtherShape( theF, AsDes->Ascendant( E1 )); TopoDS_Shape F2 = getOtherShape( theF, AsDes->Ascendant( E2 )); if (!F1.IsNull() && !F2.IsNull() && !F1.IsSame( F2 )) { OnE1 = findVOnE ( theV, E1, E2, F1, F2, AsDes, V1 ); OnE2 = findVOnE ( theV, E2, E1, F1, F2, AsDes, V2 ); if (OnE2) V = V2; if (OnE1) V = V1; } } if (OnE1 && OnE2) { if (!V1.IsSame(V2)) { // replace V1 with V2 on all edges V1 is on Standard_Real UV1; TopoDS_Edge EWE1; TopoDS_Vertex VI; const TopTools_ListOfShape& EdgeWithV1 = AsDes->Ascendant(V1); for (it.Initialize(EdgeWithV1); it.More(); it.Next()) { EWE1 = TopoDS::Edge(it.Value()); VI = V1; VI.Orientation(TopAbs_INTERNAL); UV1 = BRep_Tool::Parameter(VI,EWE1); VI = V2; VI.Orientation(TopAbs_INTERNAL); B.UpdateVertex( VI, UV1, EWE1, GetTolerance( VI, UV1, EWE1, AsDes)); } AsDes->Replace(V1,V2); V = V2; } } // add existing vertices instead of new ones if (!OnE1) { if (OnE2) { V.Orientation(TopAbs_INTERNAL); B.UpdateVertex (V, U1, E1, GetTolerance( V, U1, E1, AsDes)); } V.Orientation(O1); AsDes->Add(E1,V); } if (!OnE2) { if (OnE1) { V.Orientation(TopAbs_INTERNAL); B.UpdateVertex (V, U2, E2, GetTolerance( V, U2, E2, AsDes )); } V.Orientation(O2); AsDes->Add(E2,V); } return V; } //======================================================================= //function : FindEndVertex //purpose : Returns a vertex from having parameter on // closest to or . is True if // found vertex is closer to . returns parameter // difference. //======================================================================= TopoDS_Vertex Partition_Inter2d::FindEndVertex(const TopTools_ListOfShape& LV, const Standard_Real f, const Standard_Real l, const TopoDS_Edge& E, Standard_Boolean& isFirst, Standard_Real& minDU) { TopoDS_Vertex endV; Standard_Real U, endU, min; minDU = 1.e10; TopTools_ListIteratorOfListOfShape it; it.Initialize(LV); for (; it.More(); it.Next()) { const TopoDS_Vertex& v = TopoDS::Vertex(it.Value()); U = BRep_Tool::Parameter(v, E); min = Min( Abs(U-f), Abs(U-l) ); if (min < minDU) { endV = v; endU = U; minDU = min; } } if (Abs(endU-f) < Abs(endU-l)) isFirst = Standard_True; else isFirst = Standard_False; return endV; } //======================================================================= //function : treatClosed //purpose : add second vertex to closed edge. Vertex is one of //======================================================================= static void treatClosed (const TopoDS_Edge& E1, const Standard_Real f, const Standard_Real l, TopTools_ListOfShape& LV1, TopTools_ListOfShape& /*LV2*/) { Standard_Boolean isFirst=0; Standard_Real minDU = 1.e10; TopoDS_Vertex endV; endV = Partition_Inter2d::FindEndVertex(LV1, f,l, E1, isFirst,minDU); if (minDU > Precision::PConfusion()) return; // not end point Standard_Real newU; if (isFirst) newU = f + (l - f); else newU = l - (l - f); // update end parameter BRep_Builder B; endV.Orientation(TopAbs_INTERNAL); B.UpdateVertex(endV,newU,E1,BRep_Tool::Tolerance(endV)); } //======================================================================= //function : EdgesPartition //purpose : //======================================================================= static void EdgesPartition(const TopoDS_Face& F, const TopoDS_Edge& E1, const TopoDS_Edge& E2, const Handle(BRepAlgo_AsDes)& AsDes, const TopTools_MapOfShape& NewEdges, const Standard_Boolean WithOri) { Standard_Real f[3],l[3]; Standard_Real MilTol2; Standard_Real Tol = Max (BRep_Tool::Tolerance(E1), BRep_Tool::Tolerance(E2)); MilTol2 = Tol * Tol * 10; BRep_Tool::Range(E1, f[1], l[1]); BRep_Tool::Range(E2, f[2], l[2]); BRepAdaptor_Curve CE1(E1,F); BRepAdaptor_Curve CE2(E2,F); TopoDS_Edge EI[3]; EI[1] = E1; EI[2] = E2; TopTools_ListOfShape LV1; // new vertices at intersections on E1 TopTools_ListOfShape LV2; // ... on E2 BRep_Builder B; // if E1 and E2 are results of intersection of F and two connex faces then // no need to intersect edges, they can contact by vertices only // (encounted an exception in TopOpeBRep_EdgesIntersector in such a case) Standard_Boolean intersect = Standard_True; TopTools_IndexedMapOfShape ME; TopExp::MapShapes(F, TopAbs_EDGE, ME); if (!ME.Contains(E1) && ! ME.Contains(E2)) { // if E1 and E2 are new on F TopoDS_Shape F1, F2; const TopTools_ListOfShape& LF1 = AsDes->Ascendant( E1 ); F1 = F.IsSame( LF1.First() ) ? LF1.Last() : LF1.First(); const TopTools_ListOfShape& LF2 = AsDes->Ascendant( E2 ); F2 = F.IsSame( LF2.First() ) ? LF2.Last() : LF2.First(); if (!F.IsSame(F2) && !F.IsSame(F1) ) { TopExp_Explorer exp(F2, TopAbs_EDGE); TopExp::MapShapes(F1, TopAbs_EDGE, ME); for (; exp.More(); exp.Next()) { if (ME.Contains( exp.Current())) { intersect = Standard_False; break; } } } } if (intersect) { //------------------------------------------------------ // compute the points of Intersection in 2D //----------------------------------------------------- // i.e. fill LV1 and LV2 TopOpeBRep_EdgesIntersector EInter; EInter.SetFaces(F,F); Standard_Real TolDub = 1.e-7; EInter.ForceTolerances(TolDub,TolDub); Standard_Boolean reducesegments = Standard_False; EInter.Perform (E1,E2,reducesegments); Standard_Boolean rejectreducedsegmentpoints = Standard_False; EInter.InitPoint(rejectreducedsegmentpoints); for ( ; EInter.MorePoint(); EInter.NextPoint() ) { const TopOpeBRep_Point2d& P2D = EInter.Point(); const gp_Pnt& P = P2D.Value(); TopoDS_Vertex V = BRepLib_MakeVertex(P); //------------------------- // control the point found. //------------------------- gp_Pnt P1 = CE1.Value(P2D.Parameter(1)); gp_Pnt P2 = CE2.Value(P2D.Parameter(2)); Standard_Real sqd1 = P1.SquareDistance(P); Standard_Real sqd2 = P2.SquareDistance(P); if (sqd1 > MilTol2 || sqd2 > MilTol2 ) continue; // add a new vertex to the both edges Standard_Real toler = Max( Tol, sqrt( Max( sqd1, sqd2 ))); Standard_Integer i; for (i = 1; i <= 2; i++) { Standard_Real U = P2D.Parameter(i); V.Orientation(TopAbs_INTERNAL); B.UpdateVertex( V,U,EI[i], toler); TopAbs_Orientation OO = TopAbs_REVERSED; if (WithOri) { if (P2D.IsVertex(i)) OO = P2D.Vertex(i).Orientation(); else if (P2D.Transition(i).Before() == TopAbs_OUT) { OO = TopAbs_FORWARD; } V.Orientation(OO); if (i == 1) LV1.Append(V); else LV2.Append(V); } } } } // if (intersect) //---------------------------------- // Test the extremities of the edges. //---------------------------------- // add to LV* vertices for vertex-vertex closeness Standard_Real U1,U2; Standard_Real TolConf2, TolConf; TopoDS_Vertex V1[2],V2[2]; TopExp::Vertices(E1,V1[0],V1[1]); TopExp::Vertices(E2,V2[0],V2[1]); Standard_Integer i,j,k; for (j = 0; j < 2; j++) { if (V1[j].IsNull()) continue; for ( k = 0; k < 2; k++) { if (V2[k].IsNull()) continue; gp_Pnt P1 = BRep_Tool::Pnt(V1[j]); gp_Pnt P2 = BRep_Tool::Pnt(V2[k]); TolConf = BRep_Tool::Tolerance(V1[j]) + BRep_Tool::Tolerance(V2[k]); TolConf = Max (Tol, TolConf); TolConf2 = TolConf * TolConf; if (!intersect) TolConf2 *= 100; Standard_Real SqDist = P1.SquareDistance(P2); if (SqDist <= TolConf2) { TopoDS_Vertex V = BRepLib_MakeVertex(P1); V.Orientation(TopAbs_INTERNAL); U1 = (j == 0) ? f[1] : l[1]; U2 = (k == 0) ? f[2] : l[2]; B.UpdateVertex(V,U1,E1,TolConf); B.UpdateVertex(V,U2,E2,TolConf); LV1.Prepend(V.Oriented(V1[j].Orientation())); LV2.Prepend(V.Oriented(V2[k].Orientation())); } } } Standard_Boolean AffichPurge = Standard_False; if ( LV1.IsEmpty()) return; //---------------------------------- // Purge of all the vertices. //---------------------------------- // remove one of close vertices TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1; gp_Pnt P1,P2; Standard_Boolean Purge = Standard_True; while (Purge) { i = 1; Purge = Standard_False; for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); it1LV1.More(); it1LV1.Next(),it1LV2.Next()) { j = 1; it2LV1.Initialize(LV1); while (j < i) { const TopoDS_Vertex& VE1 = TopoDS::Vertex(it1LV1.Value()); const TopoDS_Vertex& VE2 = TopoDS::Vertex(it2LV1.Value()); Standard_Real Tol1 = BRep_Tool::Tolerance( VE1 ); Standard_Real Tol2 = BRep_Tool::Tolerance( VE2 ); P1 = BRep_Tool::Pnt( VE1 ); P2 = BRep_Tool::Pnt( VE2 ); if (P1.IsEqual(P2, Tol1 + Tol2)) { LV1.Remove(it1LV1); LV2.Remove(it1LV2); Purge = Standard_True; break; } j++; it2LV1.Next(); } if (Purge) break; i++; } } // care of new closed edges, they always intersect with seam at end if (V1[0].IsSame( V1[1] ) && NewEdges.Contains(E1) ) treatClosed (E1, f[1], l[1], LV1, LV2); if (V2[0].IsSame( V2[1] ) && NewEdges.Contains(E2) ) treatClosed (E2, f[2], l[2], LV2, LV1); //---------------- // Stocking vertex //---------------- for ( it1LV1.Initialize( LV1 ); it1LV1.More(); it1LV1.Next()) Partition_Inter2d::AddVonE (TopoDS::Vertex( it1LV1.Value()), E1, E2, AsDes, F); } //======================================================================= //function : CompletPart2d //purpose : Computes the intersections between the edges stored // is AsDes as descendants of . Intersections is computed // between two edges if one of them is bound in NewEdges. //======================================================================= void Partition_Inter2d::CompletPart2d (const Handle(BRepAlgo_AsDes)& AsDes, const TopoDS_Face& F, const TopTools_MapOfShape& NewEdges) { #ifdef DEB NbF2d++; NbE2d = 0; #endif //Do not intersect the edges of a face TopTools_IndexedMapOfShape EdgesOfFace; TopExp::MapShapes( F, TopAbs_EDGE , EdgesOfFace); //------------------------------------------------------------------- // compute the intersection2D on the faces touched by the intersection3D //------------------------------------------------------------------- TopTools_ListIteratorOfListOfShape it1LE ; TopTools_ListIteratorOfListOfShape it2LE ; //----------------------------------------------- // Intersection edge-edge. //----------------------------------------------- const TopTools_ListOfShape& LE = AsDes->Descendant(F); TopoDS_Vertex V1,V2; Standard_Integer j, i = 1; TopoDS_Face FF = F; FF.Orientation(TopAbs_FORWARD); for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next()) { const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value()); j = 1; it2LE.Initialize(LE); while (j < i && it2LE.More()) { const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value()); //---------------------------------------------------------- // Intersections of the new edges obtained by intersection // between them and with the restrictions edges //---------------------------------------------------------- if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) && (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) { EdgesPartition(FF,E1,E2,AsDes,NewEdges,Standard_True); } it2LE.Next(); j++; } i++; } } //======================================================================= //function : GetTolerance //purpose : Returns tolerance theV must have atfer its // addition to theE with theU parameter. theAsDes is // used to find pcurves of theE //======================================================================= Standard_Real Partition_Inter2d::GetTolerance (const TopoDS_Vertex & theV, const Standard_Real theU, const TopoDS_Edge & theE, const Handle(BRepAlgo_AsDes)& theAsDes) { Standard_Real aTol = BRep_Tool::Tolerance( theV ); gp_Pnt aPnt = BRep_Tool::Pnt( theV ); // check point on 3D curve Standard_Real f,l; Handle(Geom_Curve) C = BRep_Tool::Curve( theE, f, l ); if (!C.IsNull()) aTol = Max ( aTol, aPnt.Distance( C->Value( theU ))); // check points on pcurves const TopTools_ListOfShape& aFList = theAsDes->Ascendant( theE ); TopTools_ListIteratorOfListOfShape aFIt( aFList ); for ( ; aFIt.More(); aFIt.Next() ) { const TopoDS_Face& F = TopoDS::Face( aFIt.Value() ); Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( theE, F, f, l ); if (!pcurve.IsNull()) { gp_Pnt2d aPnt2d = pcurve->Value( theU ); TopLoc_Location L; Handle(Geom_Surface) S = BRep_Tool::Surface( F, L ); gp_Pnt aPntOnS = S->Value( aPnt2d.X(), aPnt2d.Y() ); if (!L.IsIdentity()) aPntOnS.Transform( L.Transformation() ); aTol = Max ( aTol, aPnt.Distance( aPntOnS )); } } return aTol; } #endif netgen-6.2.1905/libsrc/occ/occgeom.hpp0000644000175000017500000003077013504650527016157 0ustar kurtkurt#ifndef FILE_OCCGEOM #define FILE_OCCGEOM /* *************************************************************************/ /* File: occgeom.hpp */ /* Author: Robert Gaisbauer */ /* Date: 26. May 03 */ /* *************************************************************************/ #ifdef OCCGEOMETRY #include #include "BRep_Tool.hxx" #include "Geom_Curve.hxx" #include "Geom2d_Curve.hxx" #include "Geom_Surface.hxx" #include "GeomAPI_ProjectPointOnSurf.hxx" #include "GeomAPI_ProjectPointOnCurve.hxx" #include "BRepTools.hxx" #include "TopExp.hxx" #include "BRepBuilderAPI_MakeVertex.hxx" #include "BRepBuilderAPI_MakeShell.hxx" #include "BRepBuilderAPI_MakeSolid.hxx" #include "BRepOffsetAPI_Sewing.hxx" #include "BRepLProp_SLProps.hxx" #include "BRepAdaptor_Surface.hxx" #include "Poly_Triangulation.hxx" #include "Poly_Array1OfTriangle.hxx" #include "TColgp_Array1OfPnt2d.hxx" #include "Poly_Triangle.hxx" #include "GProp_GProps.hxx" #include "BRepGProp.hxx" #include "Geom_Surface.hxx" #include "TopExp.hxx" #include "gp_Pnt.hxx" #include "TopoDS.hxx" #include "TopoDS_Solid.hxx" #include "TopExp_Explorer.hxx" #include "TopTools_ListIteratorOfListOfShape.hxx" #include "BRep_Tool.hxx" #include "Geom_Curve.hxx" #include "Geom2d_Curve.hxx" #include "Geom_Surface.hxx" #include "GeomAPI_ProjectPointOnSurf.hxx" #include "GeomAPI_ProjectPointOnCurve.hxx" #include "TopoDS_Wire.hxx" #include "BRepTools_WireExplorer.hxx" #include "BRepTools.hxx" #include "TopTools_IndexedMapOfShape.hxx" #include "TopExp.hxx" #include "BRepBuilderAPI_MakeVertex.hxx" #include "BRepBuilderAPI_MakeShell.hxx" #include "BRepBuilderAPI_MakeSolid.hxx" #include "BRepOffsetAPI_Sewing.hxx" #include "BRepLProp_CLProps.hxx" #include "BRepLProp_SLProps.hxx" #include "BRepAdaptor_Surface.hxx" #include "BRepAdaptor_Curve.hxx" #include "Poly_Triangulation.hxx" #include "Poly_Array1OfTriangle.hxx" #include "TColgp_Array1OfPnt2d.hxx" #include "Poly_Triangle.hxx" #include "GProp_GProps.hxx" #include "BRepGProp.hxx" #include "TopoDS_Shape.hxx" #include "TopoDS_Face.hxx" #include "IGESToBRep_Reader.hxx" #include "Interface_Static.hxx" #include "GeomAPI_ExtremaCurveCurve.hxx" #include "Standard_ErrorHandler.hxx" #include "Standard_Failure.hxx" #include "ShapeUpgrade_ShellSewing.hxx" #include "ShapeFix_Shape.hxx" #include "ShapeFix_Wireframe.hxx" #include "BRepMesh.hxx" #include "BRepMesh_IncrementalMesh.hxx" #include "BRepBndLib.hxx" #include "Bnd_Box.hxx" #include "ShapeAnalysis.hxx" #include "ShapeBuild_ReShape.hxx" // Philippose - 29/01/2009 // OpenCascade XDE Support // Include support for OpenCascade XDE Features #include "TDocStd_Document.hxx" #include "Quantity_Color.hxx" #include "XCAFApp_Application.hxx" #include "XCAFDoc_ShapeTool.hxx" #include "XCAFDoc_Color.hxx" #include "XCAFDoc_ColorTool.hxx" #include "XCAFDoc_ColorType.hxx" #include "XCAFDoc_LayerTool.hxx" #include "XCAFDoc_DimTolTool.hxx" #include "XCAFDoc_MaterialTool.hxx" #include "XCAFDoc_DocumentTool.hxx" #include "TDF_Label.hxx" #include "TDF_LabelSequence.hxx" #include "STEPCAFControl_Reader.hxx" #include "STEPCAFControl_Writer.hxx" #include "IGESCAFControl_Reader.hxx" #include "IGESCAFControl_Writer.hxx" #include "IGESControl_Reader.hxx" #include "STEPControl_Reader.hxx" #include "IGESControl_Writer.hxx" #include "STEPControl_Writer.hxx" #include "StlAPI_Writer.hxx" #include "STEPControl_StepModelType.hxx" namespace netgen { #include "occmeshsurf.hpp" extern DLL_HEADER MeshingParameters mparam; #define PROJECTION_TOLERANCE 1e-10 #define ENTITYISVISIBLE 1 #define ENTITYISHIGHLIGHTED 2 #define ENTITYISDRAWABLE 4 #define OCCGEOMETRYVISUALIZATIONNOCHANGE 0 #define OCCGEOMETRYVISUALIZATIONFULLCHANGE 1 // Compute transformation matrices and redraw #define OCCGEOMETRYVISUALIZATIONHALFCHANGE 2 // Redraw class EntityVisualizationCode { int code; public: EntityVisualizationCode() { code = ENTITYISVISIBLE + !ENTITYISHIGHLIGHTED + ENTITYISDRAWABLE;} int IsVisible () { return code & ENTITYISVISIBLE;} int IsHighlighted () { return code & ENTITYISHIGHLIGHTED;} int IsDrawable () { return code & ENTITYISDRAWABLE;} void Show () { code |= ENTITYISVISIBLE;} void Hide () { code &= ~ENTITYISVISIBLE;} void Highlight () { code |= ENTITYISHIGHLIGHTED;} void Lowlight () { code &= ~ENTITYISHIGHLIGHTED;} void SetDrawable () { code |= ENTITYISDRAWABLE;} void SetNotDrawable () { code &= ~ENTITYISDRAWABLE;} }; class Line { public: Point<3> p0, p1; double Dist (Line l); double Length (); }; inline double Det3 (double a00, double a01, double a02, double a10, double a11, double a12, double a20, double a21, double a22) { return a00*a11*a22 + a01*a12*a20 + a10*a21*a02 - a20*a11*a02 - a10*a01*a22 - a21*a12*a00; } class OCCGeometry : public NetgenGeometry { Point<3> center; public: TopoDS_Shape shape; TopTools_IndexedMapOfShape fmap, emap, vmap, somap, shmap, wmap; Array fsingular, esingular, vsingular; Box<3> boundingbox; Array fnames, enames, snames; // Philippose - 29/01/2009 // OpenCascade XDE Support // XCAF Handle to make the face colours available to the rest of // the system Handle_XCAFDoc_ColorTool face_colours; mutable int changed; Array facemeshstatus; // Philippose - 15/01/2009 // Maximum mesh size for a given face // (Used to explicitly define mesh size limits on individual faces) Array face_maxh; // Philippose - 14/01/2010 // Boolean array to detect whether a face has been explicitly modified // by the user or not Array face_maxh_modified; // Philippose - 15/01/2009 // Indicates which faces have been selected by the user in geometry mode // (Currently handles only selection of one face at a time, but an array would // help to extend this to multiple faces) Array face_sel_status; Array fvispar, evispar, vvispar; double tolerance; bool fixsmalledges; bool fixspotstripfaces; bool sewfaces; bool makesolids; bool splitpartitions; OCCGeometry() { somap.Clear(); shmap.Clear(); fmap.Clear(); wmap.Clear(); emap.Clear(); vmap.Clear(); } DLL_HEADER virtual void Save (string filename) const; void DoArchive(Archive& ar); DLL_HEADER void BuildFMap(); Box<3> GetBoundingBox() { return boundingbox;} int NrSolids() { return somap.Extent();} // Philippose - 17/01/2009 // Total number of faces in the geometry int NrFaces() { return fmap.Extent();} void SetCenter() { center = boundingbox.Center();} Point<3> Center() { return center;} void Project (int surfi, Point<3> & p) const; bool FastProject (int surfi, Point<3> & ap, double& u, double& v) const; OCCSurface GetSurface (int surfi) { cout << "OCCGeometry::GetSurface using PLANESPACE" << endl; return OCCSurface (TopoDS::Face(fmap(surfi)), PLANESPACE); } DLL_HEADER void CalcBoundingBox (); DLL_HEADER void BuildVisualizationMesh (double deflection); void RecursiveTopologyTree (const TopoDS_Shape & sh, stringstream & str, TopAbs_ShapeEnum l, bool free, const char * lname); DLL_HEADER void GetTopologyTree (stringstream & str); DLL_HEADER void PrintNrShapes (); DLL_HEADER void CheckIrregularEntities (stringstream & str); DLL_HEADER void SewFaces(); DLL_HEADER void MakeSolid(); DLL_HEADER void HealGeometry(); // Philippose - 15/01/2009 // Sets the maximum mesh size for a given face // (Note: Local mesh size limited by the global max mesh size) void SetFaceMaxH(int facenr, double faceh) { if((facenr> 0) && (facenr <= fmap.Extent())) { face_maxh[facenr-1] = min(mparam.maxh,faceh); // Philippose - 14/01/2010 // If the face maxh is greater than or equal to the // current global maximum, then identify the face as // not explicitly controlled by the user any more if(faceh >= mparam.maxh) { face_maxh_modified[facenr-1] = 0; } else { face_maxh_modified[facenr-1] = 1; } } } // Philippose - 15/01/2009 // Returns the local mesh size of a given face double GetFaceMaxH(int facenr) { if((facenr> 0) && (facenr <= fmap.Extent())) { return face_maxh[facenr-1]; } else { return 0.0; } } // Philippose - 14/01/2010 // Returns the flag whether the given face // has a mesh size controlled by the user or not bool GetFaceMaxhModified(int facenr) { return face_maxh_modified[facenr-1]; } // Philippose - 17/01/2009 // Returns the index of the currently selected face int SelectedFace() { int i; for(i = 1; i <= fmap.Extent(); i++) { if(face_sel_status[i-1]) { return i; } } return 0; } // Philippose - 17/01/2009 // Sets the currently selected face void SetSelectedFace(int facenr) { face_sel_status = 0; if((facenr >= 1) && (facenr <= fmap.Extent())) { face_sel_status[facenr-1] = 1; } } void LowLightAll() { for (int i = 1; i <= fmap.Extent(); i++) fvispar[i-1].Lowlight(); for (int i = 1; i <= emap.Extent(); i++) evispar[i-1].Lowlight(); for (int i = 1; i <= vmap.Extent(); i++) vvispar[i-1].Lowlight(); } DLL_HEADER void GetUnmeshedFaceInfo (stringstream & str); DLL_HEADER void GetNotDrawableFaces (stringstream & str); DLL_HEADER bool ErrorInSurfaceMeshing (); // void WriteOCC_STL(char * filename); DLL_HEADER virtual int GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam); DLL_HEADER virtual const Refinement & GetRefinement () const; }; class DLL_HEADER OCCParameters { public: /// Factor for meshing close edges double resthcloseedgefac; /// Enable / Disable detection of close edges int resthcloseedgeenable; /// Minimum edge length to be used for dividing edges to mesh points double resthminedgelen; /// Enable / Disable use of the minimum edge length (by default use 1e-4) int resthminedgelenenable; /*! Default Constructor for the OpenCascade Mesh generation parameter set */ OCCParameters(); /*! Dump all the OpenCascade specific meshing parameters to console */ void Print (ostream & ost) const; }; void PrintContents (OCCGeometry * geom); DLL_HEADER OCCGeometry * LoadOCC_IGES (const char * filename); DLL_HEADER OCCGeometry * LoadOCC_STEP (const char * filename); DLL_HEADER OCCGeometry * LoadOCC_BREP (const char * filename); DLL_HEADER extern OCCParameters occparam; // Philippose - 31.09.2009 // External access to the mesh generation functions within the OCC // subsystem (Not sure if this is the best way to implement this....!!) DLL_HEADER extern int OCCGenerateMesh (OCCGeometry & occgeometry, shared_ptr & mesh, MeshingParameters & mparam); DLL_HEADER extern void OCCSetLocalMeshSize(OCCGeometry & geom, Mesh & mesh); DLL_HEADER extern void OCCMeshSurface (OCCGeometry & geom, Mesh & mesh, int perfstepsend); DLL_HEADER extern void OCCFindEdges (OCCGeometry & geom, Mesh & mesh); } #endif #endif netgen-6.2.1905/libsrc/occ/occpkg.cpp0000644000175000017500000007115113504650527016002 0ustar kurtkurt#ifdef OCCGEOMETRY #include #include #include #include #include #include #include #include #include "../meshing/bcfunctions.hpp" #include "vsocc.hpp" // __declspec(dllimport) void AutoColourBcProps(Mesh & mesh, const char *bccolourfile); // __declspec(dllimport) void GetFaceColours(Mesh & mesh, Array & face_colours); // __declspec(dllimport) bool ColourMatch(Vec3d col1, Vec3d col2, double eps = 2.5e-05); extern "C" int Ng_occ_Init (Tcl_Interp * interp); namespace netgen { extern DLL_HEADER shared_ptr ng_geometry; extern DLL_HEADER shared_ptr mesh; char * err_needsoccgeometry = (char*) "This operation needs an OCC geometry"; extern char * err_needsmesh; extern char * err_jobrunning; class OCCGeometryRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const; virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const; virtual void SetParameters (Tcl_Interp * interp) { occparam.resthcloseedgefac = atof (Tcl_GetVar (interp, "::stloptions.resthcloseedgefac", 0)); occparam.resthcloseedgeenable = atoi (Tcl_GetVar (interp, "::stloptions.resthcloseedgeenable", 0)); occparam.resthminedgelen = atof (Tcl_GetVar (interp, "::stloptions.resthminedgelen", 0)); occparam.resthminedgelenenable = atoi (Tcl_GetVar (interp, "::stloptions.resthminedgelenenable", 0)); } }; int Ng_SetOCCVisParameters (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { #ifdef OCCGEOMETRY int showvolume; OCCGeometry * occgeometry = dynamic_cast (ng_geometry.get()); showvolume = atoi (Tcl_GetVar (interp, "::occoptions.showvolumenr", 0)); if (occgeometry) if (showvolume != vispar.occshowvolumenr) { if (showvolume < 0 || showvolume > occgeometry->NrSolids()) { char buf[20]; sprintf (buf, "%5i", vispar.occshowvolumenr); Tcl_SetVar (interp, "::occoptions.showvolumenr", buf, 0); } else { vispar.occshowvolumenr = showvolume; if (occgeometry) occgeometry -> changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } } int temp; temp = atoi (Tcl_GetVar (interp, "::occoptions.visproblemfaces", 0)); if ((bool) temp != vispar.occvisproblemfaces) { vispar.occvisproblemfaces = temp; if (occgeometry) occgeometry -> changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } vispar.occshowsurfaces = atoi (Tcl_GetVar (interp, "::occoptions.showsurfaces", 0)); vispar.occshowedges = atoi (Tcl_GetVar (interp, "::occoptions.showedges", 0)); vispar.occzoomtohighlightedentity = atoi (Tcl_GetVar (interp, "::occoptions.zoomtohighlightedentity", 0)); vispar.occdeflection = pow(10.0,-1-atof (Tcl_GetVar (interp, "::occoptions.deflection", 0))); #endif #ifdef ACIS vispar.ACISshowfaces = atoi (Tcl_GetVar (interp, "::occoptions.showsurfaces", 0)); vispar.ACISshowedges = atoi (Tcl_GetVar (interp, "::occoptions.showedges", 0)); vispar.ACISshowsolidnr = atoi (Tcl_GetVar (interp, "::occoptions.showsolidnr", 0)); vispar.ACISshowsolidnr2 = atoi (Tcl_GetVar (interp, "::occoptions.showsolidnr2", 0)); #endif return TCL_OK; } int Ng_GetOCCData (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { #ifdef OCCGEOMETRY OCCGeometry * occgeometry = dynamic_cast (ng_geometry.get()); // static char buf[1000]; // buf[0] = 0; stringstream str; if (argc >= 2) { if (strcmp (argv[1], "getentities") == 0) { if (occgeometry) { occgeometry->GetTopologyTree(str); } } } Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE); #endif return TCL_OK; } int Ng_OCCCommand (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { #ifdef OCCGEOMETRY OCCGeometry * occgeometry = dynamic_cast (ng_geometry.get()); stringstream str; if (argc >= 2) { if (strcmp (argv[1], "isoccgeometryloaded") == 0) { if (occgeometry) str << "1 " << flush; else str << "0 " << flush; Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE); } if (occgeometry) { if (strcmp (argv[1], "buildvisualizationmesh") == 0) { occgeometry->BuildVisualizationMesh(vispar.occdeflection); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[1], "mesherror") == 0) { if (occgeometry->ErrorInSurfaceMeshing()) str << 1; else str << 0; } if (strcmp (argv[1], "sewfaces") == 0) { cout << "Before operation:" << endl; occgeometry->PrintNrShapes(); occgeometry->SewFaces(); occgeometry->BuildFMap(); cout << endl << "After operation:" << endl; occgeometry->PrintNrShapes(); occgeometry->BuildVisualizationMesh(vispar.occdeflection); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[1], "makesolid") == 0) { cout << "Before operation:" << endl; occgeometry->PrintNrShapes(); occgeometry->MakeSolid(); occgeometry->BuildFMap(); cout << endl << "After operation:" << endl; occgeometry->PrintNrShapes(); occgeometry->BuildVisualizationMesh(vispar.occdeflection); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[1], "upgradetopology") == 0) { cout << "Before operation:" << endl; occgeometry->PrintNrShapes(); occgeometry->SewFaces(); occgeometry->MakeSolid(); occgeometry->BuildFMap(); cout << endl << "After operation:" << endl; occgeometry->PrintNrShapes(); occgeometry->BuildVisualizationMesh(vispar.occdeflection); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[1], "shapehealing") == 0) { occgeometry->tolerance = atof (Tcl_GetVar (interp, "::occoptions.tolerance", 0)); occgeometry->fixsmalledges = atoi (Tcl_GetVar (interp, "::occoptions.fixsmalledges", 0)); occgeometry->fixspotstripfaces = atoi (Tcl_GetVar (interp, "::occoptions.fixspotstripfaces", 0)); occgeometry->sewfaces = atoi (Tcl_GetVar (interp, "::occoptions.sewfaces", 0)); occgeometry->makesolids = atoi (Tcl_GetVar (interp, "::occoptions.makesolids", 0)); occgeometry->splitpartitions = atoi (Tcl_GetVar (interp, "::occoptions.splitpartitions", 0)); // cout << "Before operation:" << endl; // occgeometry->PrintNrShapes(); occgeometry->HealGeometry(); occgeometry->BuildFMap(); // cout << endl << "After operation:" << endl; // occgeometry->PrintNrShapes(); occgeometry->BuildVisualizationMesh(vispar.occdeflection); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[1], "highlightentity") == 0) { if (strcmp (argv[2], "Face") == 0) { int nr = atoi (argv[3]); occgeometry->LowLightAll(); occgeometry->fvispar[nr-1].Highlight(); if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[2], "Shell") == 0) { int nr = atoi (argv[3]); occgeometry->LowLightAll(); TopExp_Explorer exp; for (exp.Init (occgeometry->shmap(nr), TopAbs_FACE); exp.More(); exp.Next()) { int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current())); occgeometry->fvispar[i-1].Highlight(); } if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[2], "Solid") == 0) { int nr = atoi (argv[3]); occgeometry->LowLightAll(); TopExp_Explorer exp; for (exp.Init (occgeometry->somap(nr), TopAbs_FACE); exp.More(); exp.Next()) { int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current())); occgeometry->fvispar[i-1].Highlight(); } if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } /* if (strcmp (argv[2], "CompSolid") == 0) { int nr = atoi (argv[3]); occgeometry->LowLightAll(); TopExp_Explorer exp; for (exp.Init (occgeometry->cmap(nr), TopAbs_FACE); exp.More(); exp.Next()) { int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current())); occgeometry->fvispar[i-1].Highlight(); } occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } */ if (strcmp (argv[2], "Edge") == 0) { int nr = atoi (argv[3]); occgeometry->LowLightAll(); occgeometry->evispar[nr-1].Highlight(); if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[2], "Wire") == 0) { int nr = atoi (argv[3]); occgeometry->LowLightAll(); TopExp_Explorer exp; for (exp.Init (occgeometry->wmap(nr), TopAbs_EDGE); exp.More(); exp.Next()) { int i = occgeometry->emap.FindIndex (TopoDS::Edge(exp.Current())); occgeometry->evispar[i-1].Highlight(); } if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } if (strcmp (argv[2], "Vertex") == 0) { int nr = atoi (argv[3]); occgeometry->LowLightAll(); occgeometry->vvispar[nr-1].Highlight(); if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } } if (strcmp (argv[1], "show") == 0) { int nr = atoi (argv[3]); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; if (strcmp (argv[2], "Face") == 0) { occgeometry->fvispar[nr-1].Show(); } if (strcmp (argv[2], "Shell") == 0) { TopExp_Explorer exp; for (exp.Init (occgeometry->shmap(nr), TopAbs_FACE); exp.More(); exp.Next()) { int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current())); occgeometry->fvispar[i-1].Show(); } } if (strcmp (argv[2], "Solid") == 0) { TopExp_Explorer exp; for (exp.Init (occgeometry->somap(nr), TopAbs_FACE); exp.More(); exp.Next()) { int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current())); occgeometry->fvispar[i-1].Show(); } } if (strcmp (argv[2], "Edge") == 0) { occgeometry->evispar[nr-1].Show(); } if (strcmp (argv[2], "Wire") == 0) { TopExp_Explorer exp; for (exp.Init (occgeometry->wmap(nr), TopAbs_EDGE); exp.More(); exp.Next()) { int i = occgeometry->emap.FindIndex (TopoDS::Edge(exp.Current())); occgeometry->evispar[i-1].Show(); } } } if (strcmp (argv[1], "hide") == 0) { int nr = atoi (argv[3]); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; if (strcmp (argv[2], "Face") == 0) { occgeometry->fvispar[nr-1].Hide(); } if (strcmp (argv[2], "Shell") == 0) { TopExp_Explorer exp; for (exp.Init (occgeometry->shmap(nr), TopAbs_FACE); exp.More(); exp.Next()) { int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current())); occgeometry->fvispar[i-1].Hide(); } } if (strcmp (argv[2], "Solid") == 0) { TopExp_Explorer exp; for (exp.Init (occgeometry->somap(nr), TopAbs_FACE); exp.More(); exp.Next()) { int i = occgeometry->fmap.FindIndex (TopoDS::Face(exp.Current())); occgeometry->fvispar[i-1].Hide(); } } if (strcmp (argv[2], "Edge") == 0) { occgeometry->evispar[nr-1].Hide(); } if (strcmp (argv[2], "Wire") == 0) { TopExp_Explorer exp; for (exp.Init (occgeometry->wmap(nr), TopAbs_EDGE); exp.More(); exp.Next()) { int i = occgeometry->emap.FindIndex (TopoDS::Edge(exp.Current())); occgeometry->evispar[i-1].Hide(); } } } if (strcmp (argv[1], "findsmallentities") == 0) { stringstream str(""); occgeometry->CheckIrregularEntities(str); Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE); } if (strcmp (argv[1], "getunmeshedfaceinfo") == 0) { occgeometry->GetUnmeshedFaceInfo(str); Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE); } if (strcmp (argv[1], "getnotdrawablefaces") == 0) { occgeometry->GetNotDrawableFaces(str); Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE); } if (strcmp (argv[1], "redrawstatus") == 0) { int i = atoi (argv[2]); occgeometry->changed = i; } if (strcmp (argv[1], "swaporientation") == 0) { IGESControl_Writer writer("millimeters", 1); writer.AddShape (occgeometry->shape); writer.Write ("1.igs"); /* int nr = atoi (argv[3]); // const_cast (occgeometry->fmap(nr)).Reverse(); Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape; rebuild->Apply(occgeometry->shape); TopoDS_Shape sh; // if (strcmp (argv[2], "CompSolid") == 0) sh = occgeometry->cmap(nr); if (strcmp (argv[2], "Solid") == 0) sh = occgeometry->somap(nr); if (strcmp (argv[2], "Shell") == 0) sh = occgeometry->shmap(nr); if (strcmp (argv[2], "Face") == 0) sh = occgeometry->fmap(nr); if (strcmp (argv[2], "Wire") == 0) sh = occgeometry->wmap(nr); if (strcmp (argv[2], "Edge") == 0) sh = occgeometry->emap(nr); rebuild->Replace(sh, sh.Reversed(), Standard_False); TopoDS_Shape newshape = rebuild->Apply(occgeometry->shape, TopAbs_SHELL, 1); occgeometry->shape = newshape; occgeometry->BuildFMap(); occgeometry->BuildVisualizationMesh(); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; */ } if (strcmp (argv[1], "marksingular") == 0) { int nr = atoi (argv[3]); cout << "marking " << argv[2] << " " << nr << endl; char buf[2]; buf[0] = '0'; buf[1] = 0; bool sing = false; if (strcmp (argv[2], "Face") == 0) sing = occgeometry->fsingular[nr-1] = !occgeometry->fsingular[nr-1]; if (strcmp (argv[2], "Edge") == 0) sing = occgeometry->esingular[nr-1] = !occgeometry->esingular[nr-1]; if (strcmp (argv[2], "Vertex") == 0) sing = occgeometry->vsingular[nr-1] = !occgeometry->vsingular[nr-1]; if (sing) buf[0] = '1'; Tcl_SetVar (interp, "::ismarkedsingular", buf, 0); stringstream str; occgeometry->GetTopologyTree (str); char* cstr = (char*)str.str().c_str(); (*testout) << cstr << endl; char helpstr[1000]; while (strchr (cstr, '}')) { strncpy (helpstr, cstr+2, strlen(strchr(cstr+2, '}'))); (*testout) << "***" << cstr << "***" << endl; cstr = strchr (cstr, '}'); } } } } #endif return TCL_OK; } #ifdef OCCGEOMETRY /* void OCCConstructGeometry (OCCGeometry & geom); int Ng_OCCConstruction (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (occgeometry) OCCConstructGeometry (*occgeometry); return TCL_OK; } */ #endif // Philippose - 30/01/2009 // TCL interface function for the Local Face Mesh size // definition functionality int Ng_SurfaceMeshSize (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { #ifdef OCCGEOMETRY static char buf[100]; if (argc < 2) { Tcl_SetResult (interp, (char *)"Ng_SurfaceMeshSize needs arguments", TCL_STATIC); return TCL_ERROR; } OCCGeometry * occgeometry = dynamic_cast (ng_geometry.get()); if (!occgeometry) { Tcl_SetResult (interp, (char *)"Ng_SurfaceMeshSize currently supports only OCC (STEP/IGES) Files", TCL_STATIC); return TCL_ERROR; } // Update the face mesh sizes to reflect the global maximum mesh size for(int i = 1; i <= occgeometry->NrFaces(); i++) { if(!occgeometry->GetFaceMaxhModified(i)) { occgeometry->SetFaceMaxH(i, mparam.maxh); } } if (strcmp (argv[1], "setsurfms") == 0) { int facenr = atoi (argv[2]); double surfms = atof (argv[3]); if (occgeometry && facenr >= 1 && facenr <= occgeometry->NrFaces()) occgeometry->SetFaceMaxH(facenr, surfms); } if (strcmp (argv[1], "setall") == 0) { double surfms = atof (argv[2]); if (occgeometry) { int nrFaces = occgeometry->NrFaces(); for (int i = 1; i <= nrFaces; i++) occgeometry->SetFaceMaxH(i, surfms); } } if (strcmp (argv[1], "getsurfms") == 0) { int facenr = atoi (argv[2]); if (occgeometry && facenr >= 1 && facenr <= occgeometry->NrFaces()) { sprintf (buf, "%5.2f", occgeometry->GetFaceMaxH(facenr)); } else { sprintf (buf, "%5.2f", mparam.maxh); } Tcl_SetResult (interp, buf, TCL_STATIC); } if (strcmp (argv[1], "getactive") == 0) { sprintf (buf, "%d", occgeometry->SelectedFace()); Tcl_SetResult (interp, buf, TCL_STATIC); } if (strcmp (argv[1], "setactive") == 0) { int facenr = atoi (argv[2]); if (occgeometry && facenr >= 1 && facenr <= occgeometry->NrFaces()) { occgeometry->SetSelectedFace (facenr); occgeometry->LowLightAll(); occgeometry->fvispar[facenr-1].Highlight(); occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } } if (strcmp (argv[1], "getnfd") == 0) { if (occgeometry) sprintf (buf, "%d", occgeometry->NrFaces()); else sprintf (buf, "0"); Tcl_SetResult (interp, buf, TCL_STATIC); } return TCL_OK; #else // No OCCGEOMETRY Tcl_SetResult (interp, (char *)"Ng_SurfaceMeshSize currently supports only OCC (STEP/IGES) Files", TCL_STATIC); return TCL_ERROR; #endif // OCCGEOMETRY } // Philippose - 25/07/2010 // TCL interface function for extracting and eventually // setting or editing the current colours present in the mesh int Ng_CurrentFaceColours (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if(argc < 1) { Tcl_SetResult (interp, (char *)"Ng_GetCurrentFaceColours needs arguments", TCL_STATIC); return TCL_ERROR; } if(!mesh) { Tcl_SetResult (interp, (char *)"Ng_GetCurrentFaceColours: Valid netgen mesh required...please mesh the Geometry first", TCL_STATIC); return TCL_ERROR; } if(strcmp(argv[1], "getcolours") == 0) { stringstream outVar; Array face_colours; GetFaceColours(*mesh, face_colours); for(int i = 0; i < face_colours.Size();i++) { outVar << "{ " << face_colours[i].X(1) << " " << face_colours[i].X(2) << " " << face_colours[i].X(3) << " } "; } tcl_const char * valuevar = argv[2]; Tcl_SetVar (interp, valuevar, (char*)outVar.str().c_str(), 0); } if(strcmp(argv[1], "showalso") == 0) { Array face_colours; GetFaceColours(*mesh,face_colours); int colourind = atoi (argv[2]); for(int i = 1; i <= mesh->GetNFD(); i++) { Array surfElems; mesh->GetSurfaceElementsOfFace(i,surfElems); if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour())) { for(int j = 0; j < surfElems.Size(); j++) { mesh->SurfaceElement(surfElems[j]).Visible(1); } } } mesh->SetNextTimeStamp(); } if(strcmp(argv[1], "hidealso") == 0) { Array face_colours; GetFaceColours(*mesh,face_colours); int colourind = atoi (argv[2]); for(int i = 1; i <= mesh->GetNFD(); i++) { Array surfElems; mesh->GetSurfaceElementsOfFace(i,surfElems); if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour())) { for(int j = 0; j < surfElems.Size(); j++) { mesh->SurfaceElement(surfElems[j]).Visible(0); } } } mesh->SetNextTimeStamp(); } if(strcmp(argv[1], "showonly") == 0) { Array face_colours; GetFaceColours(*mesh,face_colours); int colourind = atoi (argv[2]); for(int i = 1; i <= mesh->GetNFD(); i++) { Array surfElems; mesh->GetSurfaceElementsOfFace(i,surfElems); if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour())) { for(int j = 0; j < surfElems.Size(); j++) { mesh->SurfaceElement(surfElems[j]).Visible(1); } } else { for(int j = 0; j < surfElems.Size(); j++) { mesh->SurfaceElement(surfElems[j]).Visible(0); } } } mesh->SetNextTimeStamp(); } if(strcmp(argv[1], "hideonly") == 0) { Array face_colours; GetFaceColours(*mesh,face_colours); int colourind = atoi (argv[2]); for(int i = 1; i <= mesh->GetNFD(); i++) { Array surfElems; mesh->GetSurfaceElementsOfFace(i,surfElems); if(ColourMatch(face_colours[colourind],mesh->GetFaceDescriptor(i).SurfColour())) { for(int j = 0; j < surfElems.Size(); j++) { mesh->SurfaceElement(surfElems[j]).Visible(0); } } else { for(int j = 0; j < surfElems.Size(); j++) { mesh->SurfaceElement(surfElems[j]).Visible(1); } } } mesh->SetNextTimeStamp(); } if(strcmp(argv[1], "showall") == 0) { for(int i = 1; i <= mesh->GetNSE(); i++) { mesh->SurfaceElement(i).Visible(1); } mesh->SetNextTimeStamp(); } if(strcmp(argv[1], "hideall") == 0) { for(int i = 1; i <= mesh->GetNSE(); i++) { mesh->SurfaceElement(i).Visible(0); } mesh->SetNextTimeStamp(); } return TCL_OK; } // Philippose - 10/03/2009 // TCL interface function for the Automatic Colour-based // definition of boundary conditions for OCC Geometry int Ng_AutoColourBcProps (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if(argc < 1) { Tcl_SetResult (interp, (char *)"Ng_AutoColourBcProps needs arguments", TCL_STATIC); return TCL_ERROR; } if(!mesh) { Tcl_SetResult (interp, (char *)"Ng_AutoColourBcProps: Valid netgen mesh required...please mesh the Geometry first", TCL_STATIC); return TCL_ERROR; } if(strcmp(argv[1], "auto") == 0) { AutoColourBcProps(*mesh, 0); } if(strcmp(argv[1], "profile") == 0) { AutoColourBcProps(*mesh, argv[2]); } return TCL_OK; } int Ng_SetOCCParameters (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { OCCGeometryRegister reg; reg.SetParameters (interp); /* occparam.resthcloseedgefac = atof (Tcl_GetVar (interp, "::stloptions.resthcloseedgefac", 0)); occparam.resthcloseedgeenable = atoi (Tcl_GetVar (interp, "::stloptions.resthcloseedgeenable", 0)); */ return TCL_OK; } NetgenGeometry * OCCGeometryRegister :: Load (string filename) const { const char * lgfilename = filename.c_str(); /* if (strcmp (&cfilename[strlen(cfilename)-3], "geo") == 0) { PrintMessage (1, "Load OCCG geometry file ", cfilename); extern OCCGeometry * ParseOCCG (istream & istr); ifstream infile(cfilename); OCCGeometry * hgeom = ParseOCCG (infile); if (!hgeom) throw NgException ("geo-file should start with 'algebraic3d'"); hgeom -> FindIdenticSurfaces(1e-8 * hgeom->MaxSize()); return hgeom; } */ if ((strcmp (&lgfilename[strlen(lgfilename)-4], "iges") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "igs") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "IGS") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "IGES") == 0)) { PrintMessage (1, "Load IGES geometry file ", lgfilename); OCCGeometry * occgeometry = LoadOCC_IGES (lgfilename); return occgeometry; } else if ((strcmp (&lgfilename[strlen(lgfilename)-4], "step") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "stp") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "STP") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "STEP") == 0)) { PrintMessage (1, "Load STEP geometry file ", lgfilename); OCCGeometry * occgeometry = LoadOCC_STEP (lgfilename); return occgeometry; } else if ((strcmp (&lgfilename[strlen(lgfilename)-4], "brep") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "Brep") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "BREP") == 0)) { PrintMessage (1, "Load BREP geometry file ", lgfilename); OCCGeometry * occgeometry = LoadOCC_BREP (lgfilename); return occgeometry; } return NULL; } static VisualSceneOCCGeometry vsoccgeom; VisualScene * OCCGeometryRegister :: GetVisualScene (const NetgenGeometry * geom) const { OCCGeometry * geometry = dynamic_cast (ng_geometry.get()); if (geometry) { vsoccgeom.SetGeometry (geometry); return &vsoccgeom; } return NULL; } } using namespace netgen; int Ng_occ_Init (Tcl_Interp * interp) { geometryregister.Append (new OCCGeometryRegister); Tcl_CreateCommand (interp, "Ng_SetOCCVisParameters", Ng_SetOCCVisParameters, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GetOCCData", Ng_GetOCCData, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); /* #ifdef OCCGEOMETRY Tcl_CreateCommand (interp, "Ng_OCCConstruction", Ng_OCCConstruction, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); #endif */ Tcl_CreateCommand (interp, "Ng_OCCCommand", Ng_OCCCommand, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SetOCCParameters", Ng_SetOCCParameters, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); // Philippose - 30/01/2009 // Register the TCL Interface Command for local face mesh size // definition Tcl_CreateCommand (interp, "Ng_SurfaceMeshSize", Ng_SurfaceMeshSize, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_AutoColourBcProps", Ng_AutoColourBcProps, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); // Philippose - 25/07/2010 // Register the TCL Interface Command for handling the face colours // present in the mesh Tcl_CreateCommand(interp, "Ng_CurrentFaceColours", Ng_CurrentFaceColours, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); return TCL_OK; } #endif netgen-6.2.1905/libsrc/occ/occgenmesh.cpp0000644000175000017500000013440613504650527016652 0ustar kurtkurt#ifdef OCCGEOMETRY #include #include #include namespace netgen { #include "occmeshsurf.hpp" #define TCL_OK 0 #define TCL_ERROR 1 #define DIVIDEEDGESECTIONS 1000 #define IGNORECURVELENGTH 1e-4 #define VSMALL 1e-10 DLL_HEADER bool merge_solids = 1; // can you please explain what you intend to compute here (JS) !!! double Line :: Dist (Line l) { Vec<3> n = p1-p0; Vec<3> q = l.p1-l.p0; double nq = n*q; Point<3> p = p0 + 0.5*n; double lambda = (p-l.p0)*n / (nq + VSMALL); if (lambda >= 0 && lambda <= 1) { double d = (p-l.p0-lambda*q).Length(); // if (d < 1e-3) d = 1e99; return d; } else return 1e99; } double Line :: Length () { return (p1-p0).Length(); } inline Point<3> occ2ng (const gp_Pnt & p) { return Point<3> (p.X(), p.Y(), p.Z()); } double ComputeH (double kappa) { double hret; kappa *= mparam.curvaturesafety; if (mparam.maxh * kappa < 1) hret = mparam.maxh; else hret = 1 / (kappa + VSMALL); if (mparam.maxh < hret) hret = mparam.maxh; return (hret); } void RestrictHTriangle (gp_Pnt2d & par0, gp_Pnt2d & par1, gp_Pnt2d & par2, BRepLProp_SLProps * prop, Mesh & mesh, int depth, double h = 0) { int ls = -1; gp_Pnt pnt0,pnt1,pnt2; prop->SetParameters (par0.X(), par0.Y()); pnt0 = prop->Value(); prop->SetParameters (par1.X(), par1.Y()); pnt1 = prop->Value(); prop->SetParameters (par2.X(), par2.Y()); pnt2 = prop->Value(); double aux; double maxside = pnt0.Distance(pnt1); ls = 2; aux = pnt1.Distance(pnt2); if(aux > maxside) { maxside = aux; ls = 0; } aux = pnt2.Distance(pnt0); if(aux > maxside) { maxside = aux; ls = 1; } gp_Pnt2d parmid; parmid.SetX( (par0.X()+par1.X()+par2.X()) / 3 ); parmid.SetY( (par0.Y()+par1.Y()+par2.Y()) / 3 ); if (depth%3 == 0) { double curvature = 0; prop->SetParameters (parmid.X(), parmid.Y()); if (!prop->IsCurvatureDefined()) { (*testout) << "curvature not defined!" << endl; return; } curvature = max(fabs(prop->MinCurvature()), fabs(prop->MaxCurvature())); prop->SetParameters (par0.X(), par0.Y()); if (!prop->IsCurvatureDefined()) { (*testout) << "curvature not defined!" << endl; return; } curvature = max(curvature,max(fabs(prop->MinCurvature()), fabs(prop->MaxCurvature()))); prop->SetParameters (par1.X(), par1.Y()); if (!prop->IsCurvatureDefined()) { (*testout) << "curvature not defined!" << endl; return; } curvature = max(curvature,max(fabs(prop->MinCurvature()), fabs(prop->MaxCurvature()))); prop->SetParameters (par2.X(), par2.Y()); if (!prop->IsCurvatureDefined()) { (*testout) << "curvature not defined!" << endl; return; } curvature = max(curvature,max(fabs(prop->MinCurvature()), fabs(prop->MaxCurvature()))); //(*testout) << "curvature " << curvature << endl; if (curvature < 1e-3) { //(*testout) << "curvature too small (" << curvature << ")!" << endl; return; // return war bis 10.2.05 auskommentiert } h = ComputeH (curvature+1e-10); if(h < 1e-4*maxside) return; if (h > 30) return; } if (h < maxside && depth < 10) { //cout << "\r h " << h << flush; gp_Pnt2d pm; //cout << "h " << h << " maxside " << maxside << " depth " << depth << endl; //cout << "par0 " << par0.X() << " " << par0.Y() //<< " par1 " << par1.X() << " " << par1.Y() // << " par2 " << par2.X() << " " << par2.Y()<< endl; if(ls == 0) { pm.SetX(0.5*(par1.X()+par2.X())); pm.SetY(0.5*(par1.Y()+par2.Y())); RestrictHTriangle(pm, par2, par0, prop, mesh, depth+1, h); RestrictHTriangle(pm, par0, par1, prop, mesh, depth+1, h); } else if(ls == 1) { pm.SetX(0.5*(par0.X()+par2.X())); pm.SetY(0.5*(par0.Y()+par2.Y())); RestrictHTriangle(pm, par1, par2, prop, mesh, depth+1, h); RestrictHTriangle(pm, par0, par1, prop, mesh, depth+1, h); } else if(ls == 2) { pm.SetX(0.5*(par0.X()+par1.X())); pm.SetY(0.5*(par0.Y()+par1.Y())); RestrictHTriangle(pm, par1, par2, prop, mesh, depth+1, h); RestrictHTriangle(pm, par2, par0, prop, mesh, depth+1, h); } } else { gp_Pnt pnt; Point3d p3d; prop->SetParameters (parmid.X(), parmid.Y()); pnt = prop->Value(); p3d = Point3d(pnt.X(), pnt.Y(), pnt.Z()); mesh.RestrictLocalH (p3d, h); p3d = Point3d(pnt0.X(), pnt0.Y(), pnt0.Z()); mesh.RestrictLocalH (p3d, h); p3d = Point3d(pnt1.X(), pnt1.Y(), pnt1.Z()); mesh.RestrictLocalH (p3d, h); p3d = Point3d(pnt2.X(), pnt2.Y(), pnt2.Z()); mesh.RestrictLocalH (p3d, h); //(*testout) << "p = " << p3d << ", h = " << h << ", maxside = " << maxside << endl; } } void DivideEdge (TopoDS_Edge & edge, Array & ps, Array & params, Mesh & mesh) { double s0, s1; double maxh = mparam.maxh; int nsubedges = 1; gp_Pnt pnt, oldpnt; double svalue[DIVIDEEDGESECTIONS]; GProp_GProps system; BRepGProp::LinearProperties(edge, system); double L = system.Mass(); Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); double hvalue[DIVIDEEDGESECTIONS+1]; hvalue[0] = 0; pnt = c->Value(s0); double olddist = 0; double dist = 0; int tmpVal = (int)(DIVIDEEDGESECTIONS); for (int i = 1; i <= tmpVal; i++) { oldpnt = pnt; pnt = c->Value(s0+(i/double(DIVIDEEDGESECTIONS))*(s1-s0)); hvalue[i] = hvalue[i-1] + 1.0/mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z()))* pnt.Distance(oldpnt); //(*testout) << "mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z())) " << mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z())) // << " pnt.Distance(oldpnt) " << pnt.Distance(oldpnt) << endl; olddist = dist; dist = pnt.Distance(oldpnt); } // nsubedges = int(ceil(hvalue[DIVIDEEDGESECTIONS])); nsubedges = max (1, int(floor(hvalue[DIVIDEEDGESECTIONS]+0.5))); ps.SetSize(nsubedges-1); params.SetSize(nsubedges+1); int i = 1; int i1 = 0; do { if (hvalue[i1]/hvalue[DIVIDEEDGESECTIONS]*nsubedges >= i) { params[i] = s0+(i1/double(DIVIDEEDGESECTIONS))*(s1-s0); pnt = c->Value(params[i]); ps[i-1] = MeshPoint (Point3d(pnt.X(), pnt.Y(), pnt.Z())); i++; } i1++; if (i1 > DIVIDEEDGESECTIONS) { nsubedges = i; ps.SetSize(nsubedges-1); params.SetSize(nsubedges+1); cout << "divide edge: local h too small" << endl; } } while (i < nsubedges); params[0] = s0; params[nsubedges] = s1; if (params[nsubedges] <= params[nsubedges-1]) { cout << "CORRECTED" << endl; ps.SetSize (nsubedges-2); params.SetSize (nsubedges); params[nsubedges] = s1; } } void OCCFindEdges (OCCGeometry & geom, Mesh & mesh) { const char * savetask = multithread.task; multithread.task = "Edge meshing"; (*testout) << "edge meshing" << endl; int nvertices = geom.vmap.Extent(); int nedges = geom.emap.Extent(); (*testout) << "nvertices = " << nvertices << endl; (*testout) << "nedges = " << nedges << endl; double eps = 1e-6 * geom.GetBoundingBox().Diam(); for (int i = 1; i <= nvertices; i++) { gp_Pnt pnt = BRep_Tool::Pnt (TopoDS::Vertex(geom.vmap(i))); MeshPoint mp( Point<3>(pnt.X(), pnt.Y(), pnt.Z()) ); bool exists = 0; if (merge_solids) for (PointIndex pi = 1; pi <= mesh.GetNP(); pi++) if ( Dist2 (mesh[pi], Point<3>(mp)) < eps*eps) { exists = 1; break; } if (!exists) mesh.AddPoint (mp); } (*testout) << "different vertices = " << mesh.GetNP() << endl; int first_ep = mesh.GetNP()+1; Array face2solid[2]; for (int i = 0; i<2; i++) { face2solid[i].SetSize (geom.fmap.Extent()); face2solid[i] = 0; } int solidnr = 0; for (TopExp_Explorer exp0(geom.shape, TopAbs_SOLID); exp0.More(); exp0.Next()) { solidnr++; for (TopExp_Explorer exp1(exp0.Current(), TopAbs_FACE); exp1.More(); exp1.Next()) { TopoDS_Face face = TopoDS::Face(exp1.Current()); int facenr = geom.fmap.FindIndex(face); if (face2solid[0][facenr-1] == 0) face2solid[0][facenr-1] = solidnr; else face2solid[1][facenr-1] = solidnr; } } int total = 0; for (int i3 = 1; i3 <= geom.fmap.Extent(); i3++) for (TopExp_Explorer exp2(geom.fmap(i3), TopAbs_WIRE); exp2.More(); exp2.Next()) for (TopExp_Explorer exp3(exp2.Current(), TopAbs_EDGE); exp3.More(); exp3.Next()) total++; int facenr = 0; int edgenr = 0; (*testout) << "faces = " << geom.fmap.Extent() << endl; int curr = 0; for (int i3 = 1; i3 <= geom.fmap.Extent(); i3++) { TopoDS_Face face = TopoDS::Face(geom.fmap(i3)); facenr = geom.fmap.FindIndex (face); // sollte doch immer == i3 sein ??? JS int solidnr0 = face2solid[0][i3-1]; int solidnr1 = face2solid[1][i3-1]; /* auskommentiert am 3.3.05 von robert for (exp2.Init (geom.somap(solidnr0), TopAbs_FACE); exp2.More(); exp2.Next()) { TopoDS_Face face2 = TopoDS::Face(exp2.Current()); if (geom.fmap.FindIndex(face2) == facenr) { // if (face.Orientation() != face2.Orientation()) swap (solidnr0, solidnr1); } } */ mesh.AddFaceDescriptor (FaceDescriptor(facenr, solidnr0, solidnr1, 0)); // Philippose - 06/07/2009 // Add the face colour to the mesh data Quantity_Color face_colour; if(!(geom.face_colours.IsNull()) && (geom.face_colours->GetColor(face,XCAFDoc_ColorSurf,face_colour))) { mesh.GetFaceDescriptor(facenr).SetSurfColour(Vec3d(face_colour.Red(),face_colour.Green(),face_colour.Blue())); } else { mesh.GetFaceDescriptor(facenr).SetSurfColour(Vec3d(0.0,1.0,0.0)); } if(geom.fnames.Size()>=facenr) mesh.GetFaceDescriptor(facenr).SetBCName(&geom.fnames[facenr-1]); mesh.GetFaceDescriptor(facenr).SetBCProperty(facenr); // ACHTUNG! STIMMT NICHT ALLGEMEIN (RG) Handle(Geom_Surface) occface = BRep_Tool::Surface(face); for (TopExp_Explorer exp2 (face, TopAbs_WIRE); exp2.More(); exp2.Next()) { TopoDS_Shape wire = exp2.Current(); for (TopExp_Explorer exp3 (wire, TopAbs_EDGE); exp3.More(); exp3.Next()) { curr++; (*testout) << "edge nr " << curr << endl; multithread.percent = 100 * curr / double (total); if (multithread.terminate) return; TopoDS_Edge edge = TopoDS::Edge (exp3.Current()); if (BRep_Tool::Degenerated(edge)) { //(*testout) << "ignoring degenerated edge" << endl; continue; } if (geom.vmap.FindIndex(TopExp::FirstVertex (edge)) == geom.vmap.FindIndex(TopExp::LastVertex (edge))) { GProp_GProps system; BRepGProp::LinearProperties(edge, system); if (system.Mass() < eps) { cout << "ignoring edge " << geom.emap.FindIndex (edge) << ". closed edge with length < " << eps << endl; continue; } } Handle(Geom2d_Curve) cof; double s0, s1; cof = BRep_Tool::CurveOnSurface (edge, face, s0, s1); int geomedgenr = geom.emap.FindIndex(edge); Array mp; Array params; DivideEdge (edge, mp, params, mesh); Array pnums; pnums.SetSize (mp.Size()+2); if (!merge_solids) { pnums[0] = geom.vmap.FindIndex (TopExp::FirstVertex (edge)); pnums[pnums.Size()-1] = geom.vmap.FindIndex (TopExp::LastVertex (edge)); } else { Point<3> fp = occ2ng (BRep_Tool::Pnt (TopExp::FirstVertex (edge))); Point<3> lp = occ2ng (BRep_Tool::Pnt (TopExp::LastVertex (edge))); pnums[0] = -1; pnums.Last() = -1; for (PointIndex pi = 1; pi < first_ep; pi++) { if (Dist2 (mesh[pi], fp) < eps*eps) pnums[0] = pi; if (Dist2 (mesh[pi], lp) < eps*eps) pnums.Last() = pi; } } for (int i = 1; i <= mp.Size(); i++) { bool exists = 0; int j; for (j = first_ep; j <= mesh.GetNP(); j++) if ((mesh.Point(j)-Point<3>(mp[i-1])).Length() < eps) { exists = 1; break; } if (exists) pnums[i] = j; else { mesh.AddPoint (mp[i-1]); (*testout) << "add meshpoint " << mp[i-1] << endl; pnums[i] = mesh.GetNP(); } } (*testout) << "NP = " << mesh.GetNP() << endl; //(*testout) << pnums[pnums.Size()-1] << endl; for (int i = 1; i <= mp.Size()+1; i++) { edgenr++; Segment seg; seg[0] = pnums[i-1]; seg[1] = pnums[i]; seg.edgenr = edgenr; seg.si = facenr; seg.epgeominfo[0].dist = params[i-1]; seg.epgeominfo[1].dist = params[i]; seg.epgeominfo[0].edgenr = geomedgenr; seg.epgeominfo[1].edgenr = geomedgenr; gp_Pnt2d p2d; p2d = cof->Value(params[i-1]); // if (i == 1) p2d = cof->Value(s0); seg.epgeominfo[0].u = p2d.X(); seg.epgeominfo[0].v = p2d.Y(); p2d = cof->Value(params[i]); // if (i == mp.Size()+1) p2d = cof -> Value(s1); seg.epgeominfo[1].u = p2d.X(); seg.epgeominfo[1].v = p2d.Y(); /* if (occface->IsUPeriodic()) { cout << "U Periodic" << endl; if (fabs(seg.epgeominfo[1].u-seg.epgeominfo[0].u) > fabs(seg.epgeominfo[1].u- (seg.epgeominfo[0].u-occface->UPeriod()))) seg.epgeominfo[0].u = p2d.X()+occface->UPeriod(); if (fabs(seg.epgeominfo[1].u-seg.epgeominfo[0].u) > fabs(seg.epgeominfo[1].u- (seg.epgeominfo[0].u+occface->UPeriod()))) seg.epgeominfo[0].u = p2d.X()-occface->UPeriod(); } if (occface->IsVPeriodic()) { cout << "V Periodic" << endl; if (fabs(seg.epgeominfo[1].v-seg.epgeominfo[0].v) > fabs(seg.epgeominfo[1].v- (seg.epgeominfo[0].v-occface->VPeriod()))) seg.epgeominfo[0].v = p2d.Y()+occface->VPeriod(); if (fabs(seg.epgeominfo[1].v-seg.epgeominfo[0].v) > fabs(seg.epgeominfo[1].v- (seg.epgeominfo[0].v+occface->VPeriod()))) seg.epgeominfo[0].v = p2d.Y()-occface->VPeriod(); } */ if (edge.Orientation() == TopAbs_REVERSED) { swap (seg[0], seg[1]); swap (seg.epgeominfo[0].dist, seg.epgeominfo[1].dist); swap (seg.epgeominfo[0].u, seg.epgeominfo[1].u); swap (seg.epgeominfo[0].v, seg.epgeominfo[1].v); } mesh.AddSegment (seg); //edgesegments[geomedgenr-1]->Append(mesh.GetNSeg()); } } } } // for(i=1; i<=mesh.GetNSeg(); i++) // (*testout) << "edge " << mesh.LineSegment(i).edgenr << " face " << mesh.LineSegment(i).si // << " p1 " << mesh.LineSegment(i)[0] << " p2 " << mesh.LineSegment(i)[1] << endl; // exit(10); mesh.CalcSurfacesOfNode(); multithread.task = savetask; } void OCCMeshSurface (OCCGeometry & geom, Mesh & mesh, int perfstepsend) { int i, j, k; int changed; const char * savetask = multithread.task; multithread.task = "Surface meshing"; geom.facemeshstatus = 0; int noldp = mesh.GetNP(); double starttime = GetTime(); Array glob2loc(noldp); //int projecttype = PARAMETERSPACE; int projecttype = PARAMETERSPACE; int notrys = 1; int surfmesherror = 0; for (k = 1; k <= mesh.GetNFD(); k++) { if(1==0 && !geom.fvispar[k-1].IsDrawable()) { (*testout) << "ignoring face " << k << endl; cout << "ignoring face " << k << endl; continue; } (*testout) << "mesh face " << k << endl; multithread.percent = 100 * k / (mesh.GetNFD() + VSMALL); geom.facemeshstatus[k-1] = -1; /* if (k != 42) { cout << "skipped" << endl; continue; } */ FaceDescriptor & fd = mesh.GetFaceDescriptor(k); int oldnf = mesh.GetNSE(); Box<3> bb = geom.GetBoundingBox(); // int projecttype = PLANESPACE; Meshing2OCCSurfaces meshing(TopoDS::Face(geom.fmap(k)), bb, projecttype); if (meshing.GetProjectionType() == PLANESPACE) PrintMessage (2, "Face ", k, " / ", mesh.GetNFD(), " (plane space projection)"); else PrintMessage (2, "Face ", k, " / ", mesh.GetNFD(), " (parameter space projection)"); if (surfmesherror) cout << "Surface meshing error occurred before (in " << surfmesherror << " faces)" << endl; // Meshing2OCCSurfaces meshing(f2, bb); meshing.SetStartTime (starttime); //(*testout) << "Face " << k << endl << endl; if (meshing.GetProjectionType() == PLANESPACE) { int cntp = 0; glob2loc = 0; for (i = 1; i <= mesh.GetNSeg(); i++) { Segment & seg = mesh.LineSegment(i); if (seg.si == k) { for (j = 1; j <= 2; j++) { int pi = (j == 1) ? seg[0] : seg[1]; if (!glob2loc.Get(pi)) { meshing.AddPoint (mesh.Point(pi), pi); cntp++; glob2loc.Elem(pi) = cntp; } } } } for (i = 1; i <= mesh.GetNSeg(); i++) { Segment & seg = mesh.LineSegment(i); if (seg.si == k) { PointGeomInfo gi0, gi1; gi0.trignum = gi1.trignum = k; gi0.u = seg.epgeominfo[0].u; gi0.v = seg.epgeominfo[0].v; gi1.u = seg.epgeominfo[1].u; gi1.v = seg.epgeominfo[1].v; meshing.AddBoundaryElement (glob2loc.Get(seg[0]), glob2loc.Get(seg[1]), gi0, gi1); //(*testout) << gi0.u << " " << gi0.v << endl; //(*testout) << gi1.u << " " << gi1.v << endl; } } } else { int cntp = 0; for (i = 1; i <= mesh.GetNSeg(); i++) if (mesh.LineSegment(i).si == k) cntp+=2; Array< PointGeomInfo > gis; gis.SetAllocSize (cntp); gis.SetSize (0); for (i = 1; i <= mesh.GetNSeg(); i++) { Segment & seg = mesh.LineSegment(i); if (seg.si == k) { PointGeomInfo gi0, gi1; gi0.trignum = gi1.trignum = k; gi0.u = seg.epgeominfo[0].u; gi0.v = seg.epgeominfo[0].v; gi1.u = seg.epgeominfo[1].u; gi1.v = seg.epgeominfo[1].v; int locpnum[2] = {0, 0}; for (j = 0; j < 2; j++) { PointGeomInfo gi = (j == 0) ? gi0 : gi1; int l; for (l = 0; l < gis.Size() && locpnum[j] == 0; l++) { double dist = sqr (gis[l].u-gi.u)+sqr(gis[l].v-gi.v); if (dist < 1e-10) locpnum[j] = l+1; } if (locpnum[j] == 0) { int pi = (j == 0) ? seg[0] : seg[1]; meshing.AddPoint (mesh.Point(pi), pi); gis.SetSize (gis.Size()+1); gis[l] = gi; locpnum[j] = l+1; } } meshing.AddBoundaryElement (locpnum[0], locpnum[1], gi0, gi1); //(*testout) << gi0.u << " " << gi0.v << endl; //(*testout) << gi1.u << " " << gi1.v << endl; } } } // Philippose - 15/01/2009 double maxh = geom.face_maxh[k-1]; //double maxh = mparam.maxh; mparam.checkoverlap = 0; // int noldpoints = mesh->GetNP(); int noldsurfel = mesh.GetNSE(); GProp_GProps sprops; BRepGProp::SurfaceProperties(TopoDS::Face(geom.fmap(k)),sprops); meshing.SetMaxArea(2.*sprops.Mass()); MESHING2_RESULT res; try { res = meshing.GenerateMesh (mesh, mparam, maxh, k); } catch (SingularMatrixException) { (*myerr) << "Singular Matrix" << endl; res = MESHING2_GIVEUP; } catch (UVBoundsException) { (*myerr) << "UV bounds exceeded" << endl; res = MESHING2_GIVEUP; } projecttype = PARAMETERSPACE; if (res != MESHING2_OK) { if (notrys == 1) { for (int i = noldsurfel+1; i <= mesh.GetNSE(); i++) mesh.DeleteSurfaceElement (i); mesh.Compress(); cout << "retry Surface " << k << endl; k--; projecttype*=-1; notrys++; continue; } else { geom.facemeshstatus[k-1] = -1; PrintError ("Problem in Surface mesh generation"); surfmesherror++; // throw NgException ("Problem in Surface mesh generation"); } } else { geom.facemeshstatus[k-1] = 1; } notrys = 1; for (i = oldnf+1; i <= mesh.GetNSE(); i++) mesh.SurfaceElement(i).SetIndex (k); } // ofstream problemfile("occmesh.rep"); // problemfile << "SURFACEMESHING" << endl << endl; if (surfmesherror) { cout << "WARNING! NOT ALL FACES HAVE BEEN MESHED" << endl; cout << "SURFACE MESHING ERROR OCCURRED IN " << surfmesherror << " FACES:" << endl; for (int i = 1; i <= geom.fmap.Extent(); i++) if (geom.facemeshstatus[i-1] == -1) { cout << "Face " << i << endl; // problemfile << "problem with face " << i << endl; // problemfile << "vertices: " << endl; TopExp_Explorer exp0,exp1,exp2; for ( exp0.Init(TopoDS::Face (geom.fmap(i)), TopAbs_WIRE); exp0.More(); exp0.Next() ) { TopoDS_Wire wire = TopoDS::Wire(exp0.Current()); for ( exp1.Init(wire,TopAbs_EDGE); exp1.More(); exp1.Next() ) { TopoDS_Edge edge = TopoDS::Edge(exp1.Current()); for ( exp2.Init(edge,TopAbs_VERTEX); exp2.More(); exp2.Next() ) { TopoDS_Vertex vertex = TopoDS::Vertex(exp2.Current()); gp_Pnt point = BRep_Tool::Pnt(vertex); // problemfile << point.X() << " " << point.Y() << " " << point.Z() << endl; } } } // problemfile << endl; } cout << endl << endl; cout << "for more information open IGES/STEP Topology Explorer" << endl; // problemfile.close(); throw NgException ("Problem in Surface mesh generation"); } else { // problemfile << "OK" << endl << endl; // problemfile.close(); } if (multithread.terminate || perfstepsend < MESHCONST_OPTSURFACE) return; multithread.task = "Optimizing surface"; static Timer timer_opt2d("Optimization 2D"); timer_opt2d.Start(); for (k = 1; k <= mesh.GetNFD(); k++) { // if (k != 42) continue; // if (k != 36) continue; // (*testout) << "optimize face " << k << endl; multithread.percent = 100 * k / (mesh.GetNFD() + VSMALL); FaceDescriptor & fd = mesh.GetFaceDescriptor(k); PrintMessage (1, "Optimize Surface ", k); for (i = 1; i <= mparam.optsteps2d; i++) { // (*testout) << "optstep " << i << endl; if (multithread.terminate) return; { MeshOptimize2dOCCSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); meshopt.SetMetricWeight (mparam.elsizeweight); //meshopt.SetMetricWeight (0.2); meshopt.SetWriteStatus (0); // (*testout) << "EdgeSwapping (mesh, (i > mparam.optsteps2d/2))" << endl; meshopt.EdgeSwapping (mesh, (i > mparam.optsteps2d/2)); } if (multithread.terminate) return; { MeshOptimize2dOCCSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); //meshopt.SetMetricWeight (0.2); meshopt.SetMetricWeight (mparam.elsizeweight); meshopt.SetWriteStatus (0); // (*testout) << "ImproveMesh (mesh)" << endl; meshopt.ImproveMesh (mesh, mparam); } { MeshOptimize2dOCCSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); //meshopt.SetMetricWeight (0.2); meshopt.SetMetricWeight (mparam.elsizeweight); meshopt.SetWriteStatus (0); // (*testout) << "CombineImprove (mesh)" << endl; meshopt.CombineImprove (mesh); } if (multithread.terminate) return; { MeshOptimize2dOCCSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); //meshopt.SetMetricWeight (0.2); meshopt.SetMetricWeight (mparam.elsizeweight); meshopt.SetWriteStatus (0); // (*testout) << "ImproveMesh (mesh)" << endl; meshopt.ImproveMesh (mesh, mparam); } } } mesh.CalcSurfacesOfNode(); mesh.Compress(); timer_opt2d.Stop(); multithread.task = savetask; // Gerhard BEGIN for(int i = 0; i maxhdom; maxhdom.SetSize (geom.NrSolids()); maxhdom = mparam.maxh; mesh.SetMaxHDomain (maxhdom); Box<3> bb = geom.GetBoundingBox(); bb.Increase (bb.Diam()/10); mesh.SetLocalH (bb.PMin(), bb.PMax(), 0.5); if (mparam.uselocalh) { const char * savetask = multithread.task; multithread.percent = 0; mesh.SetLocalH (bb.PMin(), bb.PMax(), mparam.grading); int nedges = geom.emap.Extent(); double mincurvelength = IGNORECURVELENGTH; double maxedgelen = 0; double minedgelen = 1e99; if(occparam.resthminedgelenenable) { mincurvelength = occparam.resthminedgelen; if(mincurvelength < IGNORECURVELENGTH) mincurvelength = IGNORECURVELENGTH; } multithread.task = "Setting local mesh size (elements per edge)"; // setting elements per edge for (int i = 1; i <= nedges && !multithread.terminate; i++) { TopoDS_Edge e = TopoDS::Edge (geom.emap(i)); multithread.percent = 100 * (i-1)/double(nedges); if (BRep_Tool::Degenerated(e)) continue; GProp_GProps system; BRepGProp::LinearProperties(e, system); double len = system.Mass(); if (len < mincurvelength) { (*testout) << "ignored" << endl; continue; } double localh = len/mparam.segmentsperedge; double s0, s1; // Philippose - 23/01/2009 // Find all the parent faces of a given edge // and limit the mesh size of the edge based on the // mesh size limit of the face TopTools_IndexedDataMapOfShapeListOfShape edge_face_map; edge_face_map.Clear(); TopExp::MapShapesAndAncestors(geom.shape, TopAbs_EDGE, TopAbs_FACE, edge_face_map); const TopTools_ListOfShape& parent_faces = edge_face_map.FindFromKey(e); TopTools_ListIteratorOfListOfShape parent_face_list; for(parent_face_list.Initialize(parent_faces); parent_face_list.More(); parent_face_list.Next()) { TopoDS_Face parent_face = TopoDS::Face(parent_face_list.Value()); int face_index = geom.fmap.FindIndex(parent_face); if(face_index >= 1) localh = min(localh,geom.face_maxh[face_index - 1]); } Handle(Geom_Curve) c = BRep_Tool::Curve(e, s0, s1); maxedgelen = max (maxedgelen, len); minedgelen = min (minedgelen, len); // Philippose - 23/01/2009 // Modified the calculation of maxj, because the // method used so far always results in maxj = 2, // which causes the localh to be set only at the // starting, mid and end of the edge. // Old Algorithm: // int maxj = 2 * (int) ceil (localh/len); int maxj = max((int) ceil(len/localh), 2); for (int j = 0; j <= maxj; j++) { gp_Pnt pnt = c->Value (s0+double(j)/maxj*(s1-s0)); mesh.RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), localh); } } multithread.task = "Setting local mesh size (edge curvature)"; // setting edge curvature int nsections = 20; for (int i = 1; i <= nedges && !multithread.terminate; i++) { double maxcur = 0; multithread.percent = 100 * (i-1)/double(nedges); TopoDS_Edge edge = TopoDS::Edge (geom.emap(i)); if (BRep_Tool::Degenerated(edge)) continue; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); BRepAdaptor_Curve brepc(edge); BRepLProp_CLProps prop(brepc, 2, 1e-5); for (int j = 1; j <= nsections; j++) { double s = s0 + j/(double) nsections * (s1-s0); prop.SetParameter (s); double curvature = prop.Curvature(); if(curvature> maxcur) maxcur = curvature; if (curvature >= 1e99) continue; gp_Pnt pnt = c->Value (s); mesh.RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), ComputeH (fabs(curvature))); } // (*testout) << "edge " << i << " max. curvature: " << maxcur << endl; } multithread.task = "Setting local mesh size (face curvature)"; // setting face curvature int nfaces = geom.fmap.Extent(); for (int i = 1; i <= nfaces && !multithread.terminate; i++) { multithread.percent = 100 * (i-1)/double(nfaces); TopoDS_Face face = TopoDS::Face(geom.fmap(i)); TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (face); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) { BRepTools::Clean (geom.shape); BRepMesh_IncrementalMesh (geom.shape, 0.01, true); triangulation = BRep_Tool::Triangulation (face, loc); } BRepAdaptor_Surface sf(face, Standard_True); BRepLProp_SLProps prop(sf, 2, 1e-5); int ntriangles = triangulation -> NbTriangles(); for (int j = 1; j <= ntriangles; j++) { gp_Pnt p[3]; gp_Pnt2d par[3]; for (int k = 1; k <=3; k++) { int n = triangulation->Triangles()(j)(k); p[k-1] = triangulation->Nodes()(n).Transformed(loc); par[k-1] = triangulation->UVNodes()(n); } //double maxside = 0; //maxside = max (maxside, p[0].Distance(p[1])); //maxside = max (maxside, p[0].Distance(p[2])); //maxside = max (maxside, p[1].Distance(p[2])); //cout << "\rFace " << i << " pos11 ntriangles " << ntriangles << " maxside " << maxside << flush; RestrictHTriangle (par[0], par[1], par[2], &prop, mesh, 0); //cout << "\rFace " << i << " pos12 ntriangles " << ntriangles << flush; } } // setting close edges if (occparam.resthcloseedgeenable) { multithread.task = "Setting local mesh size (close edges)"; int sections = 100; Array lines(sections*nedges); BoxTree<3> * searchtree = new BoxTree<3> (bb.PMin(), bb.PMax()); int nlines = 0; for (int i = 1; i <= nedges && !multithread.terminate; i++) { TopoDS_Edge edge = TopoDS::Edge (geom.emap(i)); if (BRep_Tool::Degenerated(edge)) continue; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); BRepAdaptor_Curve brepc(edge); BRepLProp_CLProps prop(brepc, 1, 1e-5); prop.SetParameter (s0); gp_Vec d0 = prop.D1().Normalized(); double s_start = s0; int count = 0; for (int j = 1; j <= sections; j++) { double s = s0 + (s1-s0)*(double)j/(double)sections; prop.SetParameter (s); gp_Vec d1 = prop.D1().Normalized(); double cosalpha = fabs(d0*d1); if ((j == sections) || (cosalpha < cos(10.0/180.0*M_PI))) { count++; gp_Pnt p0 = c->Value (s_start); gp_Pnt p1 = c->Value (s); lines[nlines].p0 = Point<3> (p0.X(), p0.Y(), p0.Z()); lines[nlines].p1 = Point<3> (p1.X(), p1.Y(), p1.Z()); Box3d box; box.SetPoint (Point3d(lines[nlines].p0)); box.AddPoint (Point3d(lines[nlines].p1)); searchtree->Insert (box.PMin(), box.PMax(), nlines+1); nlines++; s_start = s; d0 = d1; } } } Array linenums; for (int i = 0; i < nlines; i++) { multithread.percent = (100*i)/double(nlines); Line & line = lines[i]; Box3d box; box.SetPoint (Point3d(line.p0)); box.AddPoint (Point3d(line.p1)); double maxhline = max (mesh.GetH(box.PMin()), mesh.GetH(box.PMax())); box.Increase(maxhline); double mindist = 1e99; linenums.SetSize(0); searchtree->GetIntersecting(box.PMin(),box.PMax(),linenums); for (int j = 0; j < linenums.Size(); j++) { int num = linenums[j]-1; if (i == num) continue; if ((line.p0-lines[num].p0).Length2() < 1e-15) continue; if ((line.p0-lines[num].p1).Length2() < 1e-15) continue; if ((line.p1-lines[num].p0).Length2() < 1e-15) continue; if ((line.p1-lines[num].p1).Length2() < 1e-15) continue; mindist = min (mindist, line.Dist(lines[num])); } mindist /= (occparam.resthcloseedgefac + VSMALL); if (mindist < 1e-3) { (*testout) << "extremely small local h: " << mindist << " --> setting to 1e-3" << endl; (*testout) << "somewhere near " << line.p0 << " - " << line.p1 << endl; mindist = 1e-3; } mesh.RestrictLocalHLine(line.p0, line.p1, mindist); } } multithread.task = savetask; } // Philippose - 09/03/2009 // Added the capability to load the mesh size from a // file also for OpenCascade Geometry // Note: // ** If the "uselocalh" option is ticked in // the "mesh options...insider" menu, the mesh // size will be further modified by the topology // analysis routines. // ** To use the mesh size file as the sole source // for defining the mesh size, uncheck the "uselocalh" // option. mesh.LoadLocalMeshSize (mparam.meshsizefilename); } int OCCGenerateMesh (OCCGeometry & geom, shared_ptr & mesh, MeshingParameters & mparam) { multithread.percent = 0; if (mparam.perfstepsstart <= MESHCONST_ANALYSE) { if(mesh.get() == nullptr) mesh = make_shared(); mesh->geomtype = Mesh::GEOM_OCC; OCCSetLocalMeshSize(geom,*mesh); } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_ANALYSE) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_MESHEDGES) { OCCFindEdges (geom, *mesh); /* cout << "Removing redundant points" << endl; int i, j; int np = mesh->GetNP(); Array equalto; equalto.SetSize (np); equalto = 0; for (i = 1; i <= np; i++) { for (j = i+1; j <= np; j++) { if (!equalto[j-1] && (Dist2 (mesh->Point(i), mesh->Point(j)) < 1e-12)) equalto[j-1] = i; } } for (i = 1; i <= np; i++) if (equalto[i-1]) { cout << "Point " << i << " is equal to Point " << equalto[i-1] << endl; for (j = 1; j <= mesh->GetNSeg(); j++) { Segment & seg = mesh->LineSegment(j); if (seg[0] == i) seg[0] = equalto[i-1]; if (seg[1] == i) seg[1] = equalto[i-1]; } } cout << "Removing degenerated segments" << endl; for (j = 1; j <= mesh->GetNSeg(); j++) { Segment & seg = mesh->LineSegment(j); if (seg[0] == seg[1]) { mesh->DeleteSegment(j); cout << "Deleting Segment " << j << endl; } } mesh->Compress(); */ /* for (int i = 1; i <= geom.fmap.Extent(); i++) { Handle(Geom_Surface) hf1 = BRep_Tool::Surface(TopoDS::Face(geom.fmap(i))); for (int j = i+1; j <= geom.fmap.Extent(); j++) { Handle(Geom_Surface) hf2 = BRep_Tool::Surface(TopoDS::Face(geom.fmap(j))); if (hf1 == hf2) cout << "face " << i << " and face " << j << " lie on same surface" << endl; } } */ #ifdef LOG_STREAM (*logout) << "Edges meshed" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE) { OCCMeshSurface (geom, *mesh, mparam.perfstepsend); if (multithread.terminate) return TCL_OK; #ifdef LOG_STREAM (*logout) << "Surfaces meshed" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif #ifdef STAT_STREAM (*statout) << mesh->GetNSeg() << " & " << mesh->GetNSE() << " & - &" << GetTime() << " & " << endl; #endif // MeshQuality2d (*mesh); mesh->CalcSurfacesOfNode(); } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_OPTSURFACE) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_MESHVOLUME) { multithread.task = "Volume meshing"; MESHING3_RESULT res = MeshVolume (mparam, *mesh); /* ofstream problemfile("occmesh.rep",ios_base::app); problemfile << "VOLUMEMESHING" << endl << endl; if(res != MESHING3_OK) problemfile << "ERROR" << endl << endl; else problemfile << "OK" << endl << mesh->GetNE() << " elements" << endl << endl; problemfile.close(); */ if (res != MESHING3_OK) return TCL_ERROR; if (multithread.terminate) return TCL_OK; RemoveIllegalElements (*mesh); if (multithread.terminate) return TCL_OK; MeshQuality3d (*mesh); #ifdef STAT_STREAM (*statout) << GetTime() << " & "; #endif #ifdef LOG_STREAM (*logout) << "Volume meshed" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHVOLUME) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME) { multithread.task = "Volume optimization"; OptimizeVolume (mparam, *mesh); if (multithread.terminate) return TCL_OK; #ifdef STAT_STREAM (*statout) << GetTime() << " & " << mesh->GetNE() << " & " << mesh->GetNP() << " " << '\\' << '\\' << " \\" << "hline" << endl; #endif #ifdef LOG_STREAM (*logout) << "Volume optimized" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif // cout << "Optimization complete" << endl; } (*testout) << "NP: " << mesh->GetNP() << endl; for (int i = 1; i <= mesh->GetNP(); i++) (*testout) << mesh->Point(i) << endl; (*testout) << endl << "NSegments: " << mesh->GetNSeg() << endl; for (int i = 1; i <= mesh->GetNSeg(); i++) (*testout) << mesh->LineSegment(i) << endl; for (int i = 0; i < mesh->GetNDomains(); i++) if(geom.snames.Size()) mesh->SetMaterial( i+1, geom.snames[i] ); return TCL_OK; } } #endif netgen-6.2.1905/libsrc/occ/Partition_Loop.jxx0000644000175000017500000000262413504650527017524 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Loop.jxx // Module : GEOM #ifndef _TopoDS_Face_HeaderFile #include #endif #ifndef _TopoDS_Edge_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopTools_DataMapOfShapeShape_HeaderFile #include #endif #ifndef _Partition_Loop_HeaderFile #include "Partition_Loop.hxx" #endif netgen-6.2.1905/libsrc/occ/Partition_Inter3d.hxx0000644000175000017500000001064413504650527020122 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter3d.hxx // Module : GEOM #ifndef _Partition_Inter3d_HeaderFile #define _Partition_Inter3d_HeaderFile #ifndef _Standard_Version_HeaderFile #include #endif #if OCC_VERSION_HEX < 0x070000 #ifndef _Handle_BRepAlgo_AsDes_HeaderFile #include #endif #else #include #include #endif #ifndef _TopTools_DataMapOfShapeListOfShape_HeaderFile #include #endif #ifndef _TopTools_MapOfShape_HeaderFile #include #endif #ifndef _TopTools_DataMapOfShapeShape_HeaderFile #include #endif #ifndef _Standard_Boolean_HeaderFile #include #endif #if OCC_VERSION_HEX < 0x070000 class TopTools_ListOfShape; class TopTools_DataMapOfShapeShape; class TopTools_MapOfShape; #endif class BRepAlgo_AsDes; class TopoDS_Face; class TopoDS_Shape; class TopoDS_Vertex; class TopoDS_Edge; #ifndef _Standard_HeaderFile #include #endif #ifndef _Standard_Macro_HeaderFile #include #endif class Partition_Inter3d { public: void* operator new(size_t,void* anAddress) { return anAddress; } void* operator new(size_t size) { return Standard::Allocate(size); } void operator delete(void *anAddress) { if (anAddress) Standard::Free((Standard_Address&)anAddress); } // Methods PUBLIC // Partition_Inter3d(); Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes); void CompletPart3d(const TopTools_ListOfShape& SetOfFaces1,const TopTools_DataMapOfShapeShape& FaceShapeMap) ; void FacesPartition(const TopoDS_Face& F1,const TopoDS_Face& F2) ; Standard_Boolean IsDone(const TopoDS_Face& F1,const TopoDS_Face& F2) const; TopTools_MapOfShape& TouchedFaces() ; Handle_BRepAlgo_AsDes AsDes() const; TopTools_MapOfShape& NewEdges() ; Standard_Boolean HasSameDomainF(const TopoDS_Shape& F) const; Standard_Boolean IsSameDomainF(const TopoDS_Shape& F1,const TopoDS_Shape& F2) const; const TopTools_ListOfShape& SameDomain(const TopoDS_Face& F) const; TopoDS_Vertex ReplaceSameDomainV(const TopoDS_Vertex& V,const TopoDS_Edge& E) const; Handle_BRepAlgo_AsDes SectionEdgesAD() const; Standard_Boolean IsSectionEdge(const TopoDS_Edge& E) const; Standard_Boolean HasSectionEdge(const TopoDS_Face& F) const; Standard_Boolean IsSplitOn(const TopoDS_Edge& NewE,const TopoDS_Edge& OldE,const TopoDS_Face& F) const; const TopTools_ListOfShape& SectionEdgeFaces(const TopoDS_Edge& SecE) const; protected: // Methods PROTECTED // // Fields PROTECTED // private: // Methods PRIVATE // void Inter3D(const TopoDS_Face& F1,const TopoDS_Face& F2,TopTools_ListOfShape& LInt) ; void StorePart3d(const TopoDS_Face& F1,const TopoDS_Face& F2,const TopTools_ListOfShape& LInt1) ; void SetDone(const TopoDS_Face& F1,const TopoDS_Face& F2) ; void Affiche(const TopTools_ListOfShape& SetOfFaces) const; // Fields PRIVATE // Handle_BRepAlgo_AsDes myAsDes; TopTools_DataMapOfShapeListOfShape myDone; TopTools_MapOfShape myTouched; TopTools_MapOfShape myNewEdges; Handle_BRepAlgo_AsDes mySectionEdgesAD; TopTools_DataMapOfShapeListOfShape mySameDomainFM; TopTools_DataMapOfShapeShape mySameDomainVM; }; // other Inline functions and methods (like "C++: function call" methods) // #endif netgen-6.2.1905/libsrc/occ/occmeshsurf.cpp0000644000175000017500000004152113504650527017053 0ustar kurtkurt#ifdef OCCGEOMETRY #include #include #include #include #include namespace netgen { #include "occmeshsurf.hpp" bool glob_testout(false); void OCCSurface :: GetNormalVector (const Point<3> & p, const PointGeomInfo & geominfo, Vec<3> & n) const { gp_Pnt pnt; gp_Vec du, dv; /* double gu = geominfo.u; double gv = geominfo.v; if (fabs (gu) < 1e-3) gu = 0; if (fabs (gv) < 1e-3) gv = 0; occface->D1(gu,gv,pnt,du,dv); */ /* occface->D1(geominfo.u,geominfo.v,pnt,du,dv); n = Cross (Vec<3>(du.X(), du.Y(), du.Z()), Vec<3>(dv.X(), dv.Y(), dv.Z())); n.Normalize(); */ GeomLProp_SLProps lprop(occface,geominfo.u,geominfo.v,1,1e-5); double setu=geominfo.u,setv=geominfo.v; if(lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5) { double ustep = 0.01*(umax-umin); double vstep = 0.01*(vmax-vmin); n=0; while(setu < umax && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5)) setu += ustep; if(setu < umax) { lprop.SetParameters(setu,setv); n(0)+=lprop.Normal().X(); n(1)+=lprop.Normal().Y(); n(2)+=lprop.Normal().Z(); } setu = geominfo.u; while(setu > umin && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5)) setu -= ustep; if(setu > umin) { lprop.SetParameters(setu,setv); n(0)+=lprop.Normal().X(); n(1)+=lprop.Normal().Y(); n(2)+=lprop.Normal().Z(); } setu = geominfo.u; while(setv < vmax && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5)) setv += ustep; if(setv < vmax) { lprop.SetParameters(setu,setv); n(0)+=lprop.Normal().X(); n(1)+=lprop.Normal().Y(); n(2)+=lprop.Normal().Z(); } setv = geominfo.v; while(setv > vmin && (lprop.D1U().Magnitude() < 1e-5 || lprop.D1V().Magnitude() < 1e-5)) setv -= ustep; if(setv > vmin) { lprop.SetParameters(setu,setv); n(0)+=lprop.Normal().X(); n(1)+=lprop.Normal().Y(); n(2)+=lprop.Normal().Z(); } setv = geominfo.v; n.Normalize(); } else { n(0)=lprop.Normal().X(); n(1)=lprop.Normal().Y(); n(2)=lprop.Normal().Z(); } if(glob_testout) { (*testout) << "u " << geominfo.u << " v " << geominfo.v << " du " << lprop.D1U().X() << " "<< lprop.D1U().Y() << " "<< lprop.D1U().Z() << " dv " << lprop.D1V().X() << " "<< lprop.D1V().Y() << " "<< lprop.D1V().Z() << endl; } if (orient == TopAbs_REVERSED) n = -1*n; // (*testout) << "GetNormalVector" << endl; } void OCCSurface :: DefineTangentialPlane (const Point<3> & ap1, const PointGeomInfo & geominfo1, const Point<3> & ap2, const PointGeomInfo & geominfo2) { if (projecttype == PLANESPACE) { p1 = ap1; p2 = ap2; //cout << "p1 = " << p1 << endl; //cout << "p2 = " << p2 << endl; GetNormalVector (p1, geominfo1, ez); ex = p2 - p1; ex -= (ex * ez) * ez; ex.Normalize(); ey = Cross (ez, ex); GetNormalVector (p2, geominfo2, n2); nmid = 0.5*(n2+ez); ez = nmid; ez.Normalize(); ex = (p2 - p1).Normalize(); ez -= (ez * ex) * ex; ez.Normalize(); ey = Cross (ez, ex); nmid = ez; //cout << "ex " << ex << " ey " << ey << " ez " << ez << endl; } else { if ( (geominfo1.u < umin) || (geominfo1.u > umax) || (geominfo2.u < umin) || (geominfo2.u > umax) || (geominfo1.v < vmin) || (geominfo1.v > vmax) || (geominfo2.v < vmin) || (geominfo2.v > vmax) ) throw UVBoundsException(); p1 = ap1; p2 = ap2; psp1 = Point<2>(geominfo1.u, geominfo1.v); psp2 = Point<2>(geominfo2.u, geominfo2.v); Vec<3> n; GetNormalVector (p1, geominfo1, n); gp_Pnt pnt; gp_Vec du, dv; occface->D1 (geominfo1.u, geominfo1.v, pnt, du, dv); DenseMatrix D1(3,2), D1T(2,3), DDTinv(2,2); D1(0,0) = du.X(); D1(1,0) = du.Y(); D1(2,0) = du.Z(); D1(0,1) = dv.X(); D1(1,1) = dv.Y(); D1(2,1) = dv.Z(); /* (*testout) << "DefineTangentialPlane" << endl << "---------------------" << endl; (*testout) << "D1 = " << endl << D1 << endl; */ Transpose (D1, D1T); DenseMatrix D1TD1(3,3); D1TD1 = D1T*D1; if (D1TD1.Det() == 0) throw SingularMatrixException(); CalcInverse (D1TD1, DDTinv); DenseMatrix Y(3,2); Vec<3> y1 = (ap2-ap1).Normalize(); Vec<3> y2 = Cross(n, y1).Normalize(); for (int i = 0; i < 3; i++) { Y(i,0) = y1(i); Y(i,1) = y2(i); } DenseMatrix A(2,2); A = DDTinv * D1T * Y; DenseMatrix Ainv(2,2); if (A.Det() == 0) throw SingularMatrixException(); CalcInverse (A, Ainv); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) { Amat(i,j) = A(i,j); Amatinv(i,j) = Ainv(i,j); } Vec<2> temp = Amatinv * (psp2-psp1); double r = temp.Length(); // double alpha = -acos (temp(0)/r); double alpha = -atan2 (temp(1),temp(0)); DenseMatrix R(2,2); R(0,0) = cos (alpha); R(1,0) = -sin (alpha); R(0,1) = sin (alpha); R(1,1) = cos (alpha); A = A*R; if (A.Det() == 0) throw SingularMatrixException(); CalcInverse (A, Ainv); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) { Amat(i,j) = A(i,j); Amatinv(i,j) = Ainv(i,j); } temp = Amatinv * (psp2-psp1); }; } void OCCSurface :: ToPlane (const Point<3> & p3d, const PointGeomInfo & geominfo, Point<2> & pplane, double h, int & zone) const { if (projecttype == PLANESPACE) { Vec<3> p1p, n; GetNormalVector (p3d, geominfo, n); p1p = p3d - p1; pplane(0) = (p1p * ex) / h; pplane(1) = (p1p * ey) / h; if (n * nmid < 0) zone = -1; else zone = 0; /* if(zone == -1) { (*testout) << "zone = -1 for " << p3d << " 2D: " << pplane << " n " << n << " nmid " << nmid << endl; glob_testout = true; GetNormalVector (p3d, geominfo, n); glob_testout = false; } */ } else { pplane = Point<2>(geominfo.u, geominfo.v); // (*testout) << "(u,v) = " << geominfo.u << ", " << geominfo.v << endl; pplane = Point<2> (1/h * (Amatinv * (pplane-psp1))); // pplane = Point<2> (h * (Amatinv * (pplane-psp1))); // pplane = Point<2> (1/h * ((pplane-psp1))); zone = 0; }; } void OCCSurface :: FromPlane (const Point<2> & pplane, Point<3> & p3d, PointGeomInfo & gi, double h) { if (projecttype == PLANESPACE) { // cout << "2d : " << pplane << endl; p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey; // cout << "3d : " << p3d << endl; Project (p3d, gi); // cout << "proj : " << p3d << endl; } else { // Point<2> pspnew = Point<2>(1/h * (Amat * Vec<2>(pplane)) + Vec<2>(psp1)); Point<2> pspnew = Point<2>(h * (Amat * Vec<2>(pplane)) + Vec<2>(psp1)); // Point<2> pspnew = Point<2>(h * (Vec<2>(pplane)) + Vec<2>(psp1)); gi.u = pspnew(0); gi.v = pspnew(1); gi.trignum = 1; gp_Pnt val = occface->Value (gi.u, gi.v); p3d = Point<3> (val.X(), val.Y(), val.Z()); }; } void OCCSurface :: Project (Point<3> & p, PointGeomInfo & gi) { // static int cnt = 0; // if (cnt++ % 1000 == 0) cout << "********************************************** OCCSurfce :: Project, cnt = " << cnt << endl; gp_Pnt pnt(p(0), p(1), p(2)); //(*testout) << "pnt = " << pnt.X() << ", " << pnt.Y() << ", " << pnt.Z() << endl; /* GeomAPI_ProjectPointOnSurf proj(pnt, occface, umin, umax, vmin, vmax); if (!proj.NbPoints()) { cout << "Project Point on Surface FAIL" << endl; throw UVBoundsException(); } */ /* cout << "NP = " << proj.NbPoints() << endl; for (int i = 1; i <= proj.NbPoints(); i++) { gp_Pnt pnt2 = proj.Point(i); Point<3> p2 = Point<3> (pnt2.X(), pnt2.Y(), pnt2.Z()); cout << i << ". p = " << p2 << ", dist = " << (p2-p).Length() << endl; } */ /* pnt = proj.NearestPoint(); proj.LowerDistanceParameters (gi.u, gi.v); */ double u,v; Handle( ShapeAnalysis_Surface ) su = new ShapeAnalysis_Surface( occface ); gp_Pnt2d suval = su->ValueOfUV ( pnt, BRep_Tool::Tolerance( topods_face ) ); suval.Coord( u, v); pnt = occface->Value( u, v ); //(*testout) << "pnt(proj) = " << pnt.X() << ", " << pnt.Y() << ", " << pnt.Z() << endl; gi.u = u; gi.v = v; gi.trignum = 1; p = Point<3> (pnt.X(), pnt.Y(), pnt.Z()); } Meshing2OCCSurfaces :: Meshing2OCCSurfaces (const TopoDS_Shape & asurf, const Box<3> & abb, int aprojecttype) : Meshing2(mparam, Box<3>(abb.PMin(), abb.PMax())), surface(TopoDS::Face(asurf), aprojecttype) { ; } void Meshing2OCCSurfaces :: DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo1, const PointGeomInfo * geominfo2) { ((OCCSurface&)surface).DefineTangentialPlane (p1, *geominfo1, p2, *geominfo2); } void Meshing2OCCSurfaces :: TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominfo, Point2d & planepoint, double h, int & zone) { Point<2> hp; surface.ToPlane (locpoint, geominfo.GetPGI(1), hp, h, zone); planepoint.X() = hp(0); planepoint.Y() = hp(1); } int Meshing2OCCSurfaces :: TransformFromPlain (Point2d & planepoint, Point3d & locpoint, PointGeomInfo & gi, double h) { Point<3> hp; Point<2> hp2 (planepoint.X(), planepoint.Y()); surface.FromPlane (hp2, hp, gi, h); locpoint = hp; return 0; } double Meshing2OCCSurfaces :: CalcLocalH (const Point3d & p, double gh) const { return gh; } MeshOptimize2dOCCSurfaces :: MeshOptimize2dOCCSurfaces (const OCCGeometry & ageometry) : MeshOptimize2d(), geometry(ageometry) { ; } void MeshOptimize2dOCCSurfaces :: ProjectPoint (INDEX surfind, Point<3> & p) const { geometry.Project (surfind, p); } int MeshOptimize2dOCCSurfaces :: ProjectPointGI (INDEX surfind, Point<3> & p, PointGeomInfo & gi) const { double u = gi.u; double v = gi.v; Point<3> hp = p; if (geometry.FastProject (surfind, hp, u, v)) { p = hp; return 1; } ProjectPoint (surfind, p); return CalcPointGeomInfo (surfind, gi, p); } void MeshOptimize2dOCCSurfaces :: ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const { TopExp_Explorer exp0, exp1; bool done = false; Handle(Geom_Curve) c; for (exp0.Init(geometry.fmap(surfind), TopAbs_EDGE); !done && exp0.More(); exp0.Next()) for (exp1.Init(geometry.fmap(surfind2), TopAbs_EDGE); !done && exp1.More(); exp1.Next()) { if (TopoDS::Edge(exp0.Current()).IsSame(TopoDS::Edge(exp1.Current()))) { done = true; double s0, s1; c = BRep_Tool::Curve(TopoDS::Edge(exp0.Current()), s0, s1); } } gp_Pnt pnt(p(0), p(1), p(2)); GeomAPI_ProjectPointOnCurve proj(pnt, c); pnt = proj.NearestPoint(); p(0) = pnt.X(); p(1) = pnt.Y(); p(2) = pnt.Z(); } void MeshOptimize2dOCCSurfaces :: GetNormalVector(INDEX surfind, const Point<3> & p, PointGeomInfo & geominfo, Vec<3> & n) const { gp_Pnt pnt; gp_Vec du, dv; Handle(Geom_Surface) occface; occface = BRep_Tool::Surface(TopoDS::Face(geometry.fmap(surfind))); occface->D1(geominfo.u,geominfo.v,pnt,du,dv); n = Cross (Vec<3>(du.X(), du.Y(), du.Z()), Vec<3>(dv.X(), dv.Y(), dv.Z())); n.Normalize(); if (geometry.fmap(surfind).Orientation() == TopAbs_REVERSED) n = -1*n; // GetNormalVector (surfind, p, n); } void MeshOptimize2dOCCSurfaces :: GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const { // static int cnt = 0; // if (cnt++ % 1000 == 0) cout << "GetNV cnt = " << cnt << endl; Standard_Real u,v; gp_Pnt pnt(p(0), p(1), p(2)); Handle(Geom_Surface) occface; occface = BRep_Tool::Surface(TopoDS::Face(geometry.fmap(surfind))); /* GeomAPI_ProjectPointOnSurf proj(pnt, occface); if (proj.NbPoints() < 1) { cout << "ERROR: OCCSurface :: GetNormalVector: GeomAPI_ProjectPointOnSurf failed!" << endl; cout << p << endl; return; } proj.LowerDistanceParameters (u, v); */ Handle( ShapeAnalysis_Surface ) su = new ShapeAnalysis_Surface( occface ); gp_Pnt2d suval = su->ValueOfUV ( pnt, BRep_Tool::Tolerance( TopoDS::Face(geometry.fmap(surfind)) ) ); suval.Coord( u, v); pnt = occface->Value( u, v ); gp_Vec du, dv; occface->D1(u,v,pnt,du,dv); /* if (!occface->IsCNu (1) || !occface->IsCNv (1)) (*testout) << "SurfOpt: Differentiation FAIL" << endl; */ n = Cross (Vec3d(du.X(), du.Y(), du.Z()), Vec3d(dv.X(), dv.Y(), dv.Z())); n.Normalize(); if (geometry.fmap(surfind).Orientation() == TopAbs_REVERSED) n = -1*n; } int MeshOptimize2dOCCSurfaces :: CalcPointGeomInfo(int surfind, PointGeomInfo& gi, const Point<3> & p) const { Standard_Real u,v; gp_Pnt pnt(p(0), p(1), p(2)); Handle(Geom_Surface) occface; occface = BRep_Tool::Surface(TopoDS::Face(geometry.fmap(surfind))); /* GeomAPI_ProjectPointOnSurf proj(pnt, occface); if (proj.NbPoints() < 1) { cout << "ERROR: OCCSurface :: GetNormalVector: GeomAPI_ProjectPointOnSurf failed!" << endl; cout << p << endl; return 0; } proj.LowerDistanceParameters (u, v); */ Handle( ShapeAnalysis_Surface ) su = new ShapeAnalysis_Surface( occface ); gp_Pnt2d suval = su->ValueOfUV ( pnt, BRep_Tool::Tolerance( TopoDS::Face(geometry.fmap(surfind)) ) ); suval.Coord( u, v); //pnt = occface->Value( u, v ); gi.u = u; gi.v = v; return 1; } OCCRefinementSurfaces :: OCCRefinementSurfaces (const OCCGeometry & ageometry) : Refinement(), geometry(ageometry) { ; } OCCRefinementSurfaces :: ~OCCRefinementSurfaces () { ; } /* inline double Det3 (double a00, double a01, double a02, double a10, double a11, double a12, double a20, double a21, double a22) { return a00*a11*a22 + a01*a12*a20 + a10*a21*a02 - a20*a11*a02 - a10*a01*a22 - a21*a12*a00; } bool ProjectToSurface (gp_Pnt & p, Handle(Geom_Surface) surface, double& u, double& v) { gp_Pnt x = surface->Value (u,v); if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return true; gp_Vec du, dv; surface->D1(u,v,x,du,dv); int count = 0; gp_Pnt xold; gp_Vec n; double det, lambda, mu; do { count++; n = du^dv; det = Det3 (n.X(), du.X(), dv.X(), n.Y(), du.Y(), dv.Y(), n.Z(), du.Z(), dv.Z()); if (det < 1e-15) return false; lambda = Det3 (n.X(), p.X()-x.X(), dv.X(), n.Y(), p.Y()-x.Y(), dv.Y(), n.Z(), p.Z()-x.Z(), dv.Z())/det; mu = Det3 (n.X(), du.X(), p.X()-x.X(), n.Y(), du.Y(), p.Y()-x.Y(), n.Z(), du.Z(), p.Z()-x.Z())/det; u += lambda; v += mu; xold = x; surface->D1(u,v,x,du,dv); } while (xold.SquareDistance(x) > sqr(PROJECTION_TOLERANCE) || count > 50); if (count > 50) return false; p = x; return true; } */ void OCCRefinementSurfaces :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const { Point<3> hnewp; hnewp = p1+secpoint*(p2-p1); if (surfi > 0) { double u = gi1.u+secpoint*(gi2.u-gi1.u); double v = gi1.v+secpoint*(gi2.v-gi1.v); auto savept = hnewp; if (!geometry.FastProject (surfi, hnewp, u, v) || Dist(hnewp, savept) > Dist(p1,p2)) { // cout << "Fast projection to surface fails! Using OCC projection" << endl; hnewp = savept; geometry.Project (surfi, hnewp); } newgi.trignum = 1; newgi.u = u; newgi.v = v; } newp = hnewp; } void OCCRefinementSurfaces :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const { double s0, s1; Point<3> hnewp = p1+secpoint*(p2-p1); gp_Pnt pnt(hnewp(0), hnewp(1), hnewp(2)); GeomAPI_ProjectPointOnCurve proj(pnt, BRep_Tool::Curve(TopoDS::Edge(geometry.emap(ap1.edgenr)), s0, s1)); pnt = proj.NearestPoint(); hnewp = Point<3> (pnt.X(), pnt.Y(), pnt.Z()); newp = hnewp; newgi = ap1; }; void OCCRefinementSurfaces :: ProjectToSurface (Point<3> & p, int surfi) const { if (surfi > 0) geometry.Project (surfi, p); }; void OCCRefinementSurfaces :: ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const { if (surfi > 0) if (!geometry.FastProject (surfi, p, gi.u, gi.v)) { cout << "Fast projection to surface fails! Using OCC projection" << endl; geometry.Project (surfi, p); } }; } #endif netgen-6.2.1905/libsrc/occ/Partition_Loop3d.jxx0000644000175000017500000000122513504650527017747 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 CEA/DEN, EDF R&D // // // // File : Partition_Loop3d.jxx // Module : GEOM #ifndef _TopoDS_Shape_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopTools_MapOfOrientedShape_HeaderFile #include #endif #ifndef _TopoDS_Edge_HeaderFile #include #endif #ifndef _TopoDS_Face_HeaderFile #include #endif #ifndef _gp_Vec_HeaderFile #include #endif #ifndef _Partition_Loop3d_HeaderFile #include "Partition_Loop3d.hxx" #endif netgen-6.2.1905/libsrc/occ/Partition_Inter3d.jxx0000644000175000017500000000330113504650527020114 0ustar kurtkurt// GEOM PARTITION : partition algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter3d.jxx // Module : GEOM #ifndef _BRepAlgo_AsDes_HeaderFile #include #endif #ifndef _TopTools_ListOfShape_HeaderFile #include #endif #ifndef _TopTools_DataMapOfShapeShape_HeaderFile #include #endif #ifndef _TopoDS_Face_HeaderFile #include #endif #ifndef _TopTools_MapOfShape_HeaderFile #include #endif #ifndef _TopoDS_Shape_HeaderFile #include #endif #ifndef _TopoDS_Vertex_HeaderFile #include #endif #ifndef _TopoDS_Edge_HeaderFile #include #endif #ifndef _Partition_Inter3d_HeaderFile #include "Partition_Inter3d.hxx" #endif netgen-6.2.1905/libsrc/occ/CMakeLists.txt0000644000175000017500000000151713504650527016567 0ustar kurtkurtadd_definitions(-DNGINTERFACE_EXPORTS) add_library(occ ${NG_LIB_TYPE} Partition_Inter2d.cxx Partition_Inter3d.cxx Partition_Loop.cxx Partition_Loop2d.cxx Partition_Loop3d.cxx Partition_Spliter.cxx occconstruction.cpp occgenmesh.cpp occgeom.cpp occmeshsurf.cpp python_occ.cpp ) if(USE_GUI) add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) endif(USE_GUI) target_link_libraries(occ PUBLIC ngcore) if(NOT WIN32) target_link_libraries( occ PUBLIC ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) install( TARGETS occ ${NG_INSTALL_DIR}) if (USE_GUI) target_link_libraries( occvis PUBLIC occ ) install( TARGETS occvis ${NG_INSTALL_DIR}) endif(USE_GUI) endif(NOT WIN32) install(FILES occgeom.hpp occmeshsurf.hpp vsocc.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/occ COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/stlgeom/0000755000175000017500000000000013504650527014731 5ustar kurtkurtnetgen-6.2.1905/libsrc/stlgeom/stltool.cpp0000644000175000017500000007730113504650527017145 0ustar kurtkurt#include #include #include #include #include #include "stlgeom.hpp" namespace netgen { //add a point into a pointlist, return pointnumber int AddPointIfNotExists(Array& ap, const Point3d& p, double eps) { double eps2 = sqr(eps); for (int i = 1; i <= ap.Size(); i++) if (Dist2(ap.Get(i),p) <= eps2 ) return i; ap.Append(p); return ap.Size(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ double GetDistFromLine(const Point<3> & lp1, const Point<3> & lp2, Point<3> & p) { Vec3d vn = lp2 - lp1; Vec3d v1 = p - lp1; Vec3d v2 = lp2 - p; Point3d pold = p; if (v2 * vn <= 0) {p = lp2; return (pold - p).Length();} if (v1 * vn <= 0) {p = lp1; return (pold - p).Length();} double vnl = vn.Length(); if (vnl == 0) {return Dist(lp1,p);} vn /= vnl; p = lp1 + (v1 * vn) * vn; return (pold - p).Length(); }; double GetDistFromInfiniteLine(const Point<3>& lp1, const Point<3>& lp2, const Point<3>& p) { Vec3d vn(lp1, lp2); Vec3d v1(lp1, p); double vnl = vn.Length(); if (vnl == 0) { return Dist (lp1, p); } else { return Cross (vn, v1).Length() / vnl; } }; //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Binary IO-Manipulation void FIOReadInt(istream& ios, int& i) { const int ilen = sizeof(int); char buf[ilen]; for (int j = 0; j < ilen; j++) ios.get(buf[j]); memcpy(&i, &buf, ilen); } void FIOWriteInt(ostream& ios, const int& i) { const int ilen = sizeof(int); char buf[ilen]; memcpy(&buf, &i, ilen); for (int j = 0; j < ilen; j++) ios << buf[j]; } void FIOReadDouble(istream& ios, double& i) { const int ilen = sizeof(double); char buf[ilen]; for (int j = 0; j < ilen; j++) ios.get(buf[j]); memcpy(&i, &buf, ilen); } void FIOWriteDouble(ostream& ios, const double& i) { const int ilen = sizeof(double); char buf[ilen]; memcpy(&buf, &i, ilen); for (int j = 0; j < ilen; j++) ios << buf[j]; } void FIOReadFloat(istream& ios, float& i) { const int ilen = sizeof(float); char buf[ilen]; int j; for (j = 0; j < ilen; j++) { ios.get(buf[j]); } memcpy(&i, &buf, ilen); } void FIOWriteFloat(ostream& ios, const float& i) { const int ilen = sizeof(float); char buf[ilen]; memcpy(&buf, &i, ilen); for (int j = 0; j < ilen; j++) ios << buf[j]; } void FIOReadString(istream& ios, char* str, int len) { for (int j = 0; j < len; j++) ios.get(str[j]); } //read string and add terminating 0 void FIOReadStringE(istream& ios, char* str, int len) { for (int j = 0; j < len; j++) ios.get(str[j]); str[len] = 0; } void FIOWriteString(ostream& ios, char* str, int len) { for (int j = 0; j < len; j++) ios << str[j]; } /* void FIOReadInt(istream& ios, int& i) { const int ilen = sizeof(int); char buf[ilen]; int j; for (j = 0; j < ilen; j++) { ios.get(buf[ilen-j-1]); } memcpy(&i, &buf, ilen); } void FIOWriteInt(ostream& ios, const int& i) { const int ilen = sizeof(int); char buf[ilen]; memcpy(&buf, &i, ilen); int j; for (j = 0; j < ilen; j++) { ios << buf[ilen-j-1]; } } void FIOReadDouble(istream& ios, double& i) { const int ilen = sizeof(double); char buf[ilen]; int j; for (j = 0; j < ilen; j++) { ios.get(buf[ilen-j-1]); } memcpy(&i, &buf, ilen); } void FIOWriteDouble(ostream& ios, const double& i) { const int ilen = sizeof(double); char buf[ilen]; memcpy(&buf, &i, ilen); int j; for (j = 0; j < ilen; j++) { ios << buf[ilen-j-1]; } } void FIOReadFloat(istream& ios, float& i) { const int ilen = sizeof(float); char buf[ilen]; int j; for (j = 0; j < ilen; j++) { ios.get(buf[ilen-j-1]); } memcpy(&i, &buf, ilen); } void FIOWriteFloat(ostream& ios, const float& i) { const int ilen = sizeof(float); char buf[ilen]; memcpy(&buf, &i, ilen); int j; for (j = 0; j < ilen; j++) { ios << buf[ilen-j-1]; } } void FIOReadString(istream& ios, char* str, int len) { int j; for (j = 0; j < len; j++) { ios.get(str[j]); } } //read string and add terminating 0 void FIOReadStringE(istream& ios, char* str, int len) { int j; for (j = 0; j < len; j++) { ios.get(str[j]); } str[len] = 0; } void FIOWriteString(ostream& ios, char* str, int len) { int j; for (j = 0; j < len; j++) { ios << str[j]; } } */ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STLReadTriangle :: STLReadTriangle (const Point<3> * apts, const Vec<3> & anormal) { pts[0] = apts[0]; pts[1] = apts[1]; pts[2] = apts[2]; normal = anormal; } STLTriangle :: STLTriangle(const int * apts) { pts[0] = apts[0]; pts[1] = apts[1]; pts[2] = apts[2]; facenum = 0; } int STLTriangle :: IsNeighbourFrom(const STLTriangle& t) const { //triangles must have same orientation!!! for(int i = 0; i <= 2; i++) for(int j = 0; j <= 2; j++) if (t.pts[(i+1)%3] == pts[j] && t.pts[i] == pts[(j+1)%3]) return 1; return 0; } int STLTriangle :: IsWrongNeighbourFrom(const STLTriangle& t) const { //triangles have not same orientation!!! for(int i = 0; i <= 2; i++) for(int j = 0; j <= 2; j++) if (t.pts[(i+1)%3] == pts[(j+1)%3] && t.pts[i] == pts[j]) return 1; return 0; } void STLTriangle :: GetNeighbourPoints(const STLTriangle& t, int& p1, int& p2) const { for(int i = 1; i <= 3; i++) for(int j = 1; j <= 3; j++) if (t.PNumMod(i+1) == PNumMod(j) && t.PNumMod(i) == PNumMod(j+1)) { p1 = PNumMod(j); p2 = PNumMod(j+1); return; } PrintSysError("Get neighbourpoints failed!"); } int STLTriangle :: GetNeighbourPointsAndOpposite(const STLTriangle& t, int& p1, int& p2, int& po) const { for(int i = 1; i <= 3; i++) for(int j = 1; j <= 3; j++) if (t.PNumMod(i+1) == PNumMod(j) && t.PNumMod(i) == PNumMod(j+1)) { p1 = PNumMod(j); p2 = PNumMod(j+1); po = PNumMod(j+2); return 1; } return 0; } Vec<3> STLTriangle :: GeomNormal(const Array >& ap) const { const Point<3> & p1 = ap.Get(PNum(1)); const Point<3> & p2 = ap.Get(PNum(2)); const Point<3> & p3 = ap.Get(PNum(3)); return Cross(p2-p1, p3-p1); } void STLTriangle :: SetNormal (const Vec<3> & n) { double len = n.Length(); if (len > 0) { normal = n; normal.Normalize(); } else { normal = Vec<3> (1, 0, 0); } } void STLTriangle :: ChangeOrientation() { normal *= -1; Swap(pts[0],pts[1]); } double STLTriangle :: Area(const Array >& ap) const { return 0.5 * Cross(ap.Get(PNum(2))-ap.Get(PNum(1)), ap.Get(PNum(3))-ap.Get(PNum(1))).Length(); } double STLTriangle :: MinHeight(const Array >& ap) const { double ml = MaxLength(ap); if (ml != 0) {return 2.*Area(ap)/ml;} PrintWarning("max Side Length of a triangle = 0!!!"); return 0; } double STLTriangle :: MaxLength(const Array >& ap) const { return max3(Dist(ap.Get(PNum(1)),ap.Get(PNum(2))), Dist(ap.Get(PNum(2)),ap.Get(PNum(3))), Dist(ap.Get(PNum(3)),ap.Get(PNum(1)))); } void STLTriangle :: ProjectInPlain(const Array >& ap, const Vec<3> & n, Point<3> & pp) const { const Point<3> & p1 = ap.Get(PNum(1)); const Point<3> & p2 = ap.Get(PNum(2)); const Point<3> & p3 = ap.Get(PNum(3)); Vec<3> v1 = p2 - p1; Vec<3> v2 = p3 - p1; Vec<3> nt = Cross(v1, v2); double c = - (p1(0)*nt(0) + p1(1)*nt(1) + p1(2)*nt(2)); double prod = n * nt; if (fabs(prod) == 0) { pp = Point<3>(1.E20,1.E20,1.E20); return; } double nfact = -(pp(0)*nt(0) + pp(1)*nt(1) + pp(2)*nt(2) + c) / (prod); pp = pp + (nfact) * n; } int STLTriangle :: ProjectInPlain (const Array >& ap, const Vec<3> & nproj, Point<3> & pp, Vec<3> & lam) const { const Point<3> & p1 = ap.Get(PNum(1)); const Point<3> & p2 = ap.Get(PNum(2)); const Point<3> & p3 = ap.Get(PNum(3)); Vec<3> v1 = p2-p1; Vec<3> v2 = p3-p1; Mat<3> mat; for (int i = 0; i < 3; i++) { mat(i,0) = v1(i); mat(i,1) = v2(i); mat(i,2) = nproj(i); } int err = 0; mat.Solve (pp-p1, lam); // int err = SolveLinearSystem (v1, v2, nproj, pp-p1, lam); if (!err) { // pp = p1 + lam(0) * v1 + lam(1) * v2; pp(0) = p1(0) + lam(0) * v1(0) + lam(1) * v2(0); pp(1) = p1(1) + lam(0) * v1(1) + lam(1) * v2(1); pp(2) = p1(2) + lam(0) * v1(2) + lam(1) * v2(2); } return err; } void STLTriangle :: ProjectInPlain(const Array >& ap, Point<3> & pp) const { const Point<3> & p1 = ap.Get(PNum(1)); const Point<3> & p2 = ap.Get(PNum(2)); const Point<3> & p3 = ap.Get(PNum(3)); Vec<3> v1 = p2 - p1; Vec<3> v2 = p3 - p1; Vec<3> nt = Cross(v1, v2); double c = - (p1(0)*nt(0) + p1(1)*nt(1) + p1(2)*nt(2)); double prod = nt * nt; double nfact = -(pp(0)*nt(0) + pp(1)*nt(1) + pp(2)*nt(2) + c) / (prod); pp = pp + (nfact) * nt; } int STLTriangle :: PointInside(const Array > & ap, const Point<3> & pp) const { const Point<3> & p1 = ap.Get(PNum(1)); const Point<3> & p2 = ap.Get(PNum(2)); const Point<3> & p3 = ap.Get(PNum(3)); Vec<3> v1 = p2 - p1; Vec<3> v2 = p3 - p1; Vec<3> v = pp - p1; double det, l1, l2; Vec<3> ex, ey, ez; ez = GeomNormal(ap); ez /= ez.Length(); ex = v1; ex /= ex.Length(); ey = Cross (ez, ex); Vec<2> v1p(v1*ex, v1*ey); Vec<2> v2p(v2*ex, v2*ey); Vec<2> vp(v*ex, v*ey); det = v2p(1) * v1p(0) - v2p(0) * v1p(1); if (fabs(det) == 0) {return 0;} l2 = (vp(1) * v1p(0) - vp(0) * v1p(1)) / det; if (v1p(0) != 0.) { l1 = (vp(0) - l2 * v2p(0)) / v1p(0); } else if (v1p(1) != 0.) { l1 = (vp(1) - l2 * v2p(1)) / v1p(1); } else {return 0;} if (l1 >= -1E-10 && l2 >= -1E-10 && l1 + l2 <= 1.+1E-10) {return 1;} return 0; } double STLTriangle :: GetNearestPoint(const Array >& ap, Point<3> & p3d) const { Point<3> p = p3d; ProjectInPlain(ap, p); double dist = (p - p3d).Length(); if (PointInside(ap, p)) {p3d = p; return dist;} else { Point<3> pf = 0.0; double nearest = 1E50; //int fi = 0; for (int j = 1; j <= 3; j++) { p = p3d; dist = GetDistFromLine(ap.Get(PNum(j)), ap.Get(PNumMod(j+1)), p); if (dist < nearest) { nearest = dist; pf = p; } } p3d = pf; return nearest; } } int STLTriangle :: HasEdge(int p1, int p2) const { int i; for (i = 1; i <= 3; i++) { if (p1 == PNum(i) && p2 == PNumMod(i+1)) {return 1;} } return 0; } ostream& operator<<(ostream& os, const STLTriangle& t) { os << "["; os << t[0] << ","; os << t[1] << ","; os << t[2] << "]"; return os; }; STLTopEdge :: STLTopEdge () { pts[0] = pts[1] = 0; trigs[0] = trigs[1] = 0; cosangle = 1; status = ED_UNDEFINED; } STLTopEdge :: STLTopEdge (int p1, int p2, int trig1, int trig2) { pts[0] = p1; pts[1] = p2; trigs[0] = trig1; trigs[1] = trig2; cosangle = 1; status = ED_UNDEFINED; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++ STL CHART +++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STLChart :: STLChart(STLGeometry * ageometry) { // charttrigs = new Array (0,0); // outertrigs = new Array (0,0); // ilimit = new Array (0,0); // olimit = new Array (0,0); geometry = ageometry; if ( stlparam.usesearchtree == 1) { Box<3> box = geometry->GetBoundingBox(); box.Increase (0.2*box.Diam()+1e-12); searchtree = new BoxTree<3> (box); /* searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1), geometry->GetBoundingBox().PMax() + Vec3d(1,1,1)); */ } else searchtree = NULL; } STLChart :: ~STLChart() { delete searchtree; } void STLChart :: AddChartTrig(int i) { // static int timer = NgProfiler::CreateTimer ("STLChart::AddChartTrig"); // NgProfiler::RegionTimer reg(timer); charttrigs.Append(i); const STLTriangle & trig = geometry->GetTriangle(i); const Point<3> & p1 = geometry->GetPoint (trig.PNum(1)); const Point<3> & p2 = geometry->GetPoint (trig.PNum(2)); const Point<3> & p3 = geometry->GetPoint (trig.PNum(3)); /* Point3d pmin(p1), pmax(p1); pmin.SetToMin (p2); pmin.SetToMin (p3); pmax.SetToMax (p2); pmax.SetToMax (p3); */ /* Box<3> box(p1); box.Add(p2); box.Add(p3); */ Box<3> box(p1,p2,p3); if (!geomsearchtreeon && (stlparam.usesearchtree == 1)) // {searchtree->Insert (pmin, pmax, i);} { searchtree->Insert (box, i); } } void STLChart :: AddOuterTrig(int i) { // static int timer = NgProfiler::CreateTimer ("STLChart::AddOuterTrig"); // NgProfiler::RegionTimer reg(timer); outertrigs.Append(i); const STLTriangle & trig = geometry->GetTriangle(i); const Point3d & p1 = geometry->GetPoint (trig.PNum(1)); const Point3d & p2 = geometry->GetPoint (trig.PNum(2)); const Point3d & p3 = geometry->GetPoint (trig.PNum(3)); Point3d pmin(p1), pmax(p1); pmin.SetToMin (p2); pmin.SetToMin (p3); pmax.SetToMax (p2); pmax.SetToMax (p3); if (!geomsearchtreeon && (stlparam.usesearchtree==1)) {searchtree->Insert (pmin, pmax, i);} } int STLChart :: IsInWholeChart(int nr) const { for (int i = 1; i <= charttrigs.Size(); i++) if (charttrigs.Get(i) == nr) return 1; for (int i = 1; i <= outertrigs.Size(); i++) if (outertrigs.Get(i) == nr) return 1; return 0; } void STLChart :: GetTrianglesInBox (const Point3d & pmin, const Point3d & pmax, Array & trias) const { if (geomsearchtreeon) {PrintMessage(5,"geomsearchtreeon is set!!!");} if (searchtree) searchtree -> GetIntersecting (pmin, pmax, trias); else { Box<3> box1(pmin, pmax); box1.Increase (1e-2*box1.Diam()); trias.SetSize(0); int nt = GetNT(); for (int i = 1; i <= nt; i++) { int trignum = GetTrig(i); const STLTriangle & trig = geometry->GetTriangle(trignum); Box<3> box2(geometry->GetPoint (trig.PNum(1)), geometry->GetPoint (trig.PNum(2)), geometry->GetPoint (trig.PNum(3))); if (box1.Intersect (box2)) trias.Append (trignum); } } } //trigs may contain the same triangle double void STLChart :: MoveToOuterChart(const Array& trigs) { if (!trigs.Size()) return; for (int i = 1; i <= trigs.Size(); i++) { if (charttrigs.Get(trigs.Get(i)) != -1) {AddOuterTrig(charttrigs.Get(trigs.Get(i)));} charttrigs.Elem(trigs.Get(i)) = -1; } DelChartTrigs(trigs); } //trigs may contain the same triangle double void STLChart :: DelChartTrigs(const Array& trigs) { if (!trigs.Size()) return; for (int i = 1; i <= trigs.Size(); i++) charttrigs.Elem(trigs.Get(i)) = -1; int cnt = 0; for (int i = 1; i <= charttrigs.Size(); i++) { if (charttrigs.Elem(i) == -1) cnt++; if (cnt != 0 && i < charttrigs.Size()) charttrigs.Elem(i-cnt+1) = charttrigs.Get(i+1); } int i = charttrigs.Size() - trigs.Size(); charttrigs.SetSize(i); if (!geomsearchtreeon && stlparam.usesearchtree == 1) { PrintMessage(7, "Warning: unsecure routine due to first use of searchtrees!!!"); //bould new searchtree!!! searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1), geometry->GetBoundingBox().PMax() + Vec3d(1,1,1)); for (int i = 1; i <= charttrigs.Size(); i++) { const STLTriangle & trig = geometry->GetTriangle(i); const Point3d & p1 = geometry->GetPoint (trig.PNum(1)); const Point3d & p2 = geometry->GetPoint (trig.PNum(2)); const Point3d & p3 = geometry->GetPoint (trig.PNum(3)); Point3d pmin(p1), pmax(p1); pmin.SetToMin (p2); pmin.SetToMin (p3); pmax.SetToMax (p2); pmax.SetToMax (p3); searchtree->Insert (pmin, pmax, i); } } } void STLChart :: SetNormal (const Point<3> & apref, const Vec<3> & anormal) { pref = apref; normal = anormal; double len = normal.Length(); if (len) normal /= len; else normal = Vec<3> (1, 0, 0); t1 = normal.GetNormal (); t2 = Cross (normal, t1); } /* Point<2> STLChart :: Project2d (const Point<3> & p3d) const { Vec<3> v = p3d-pref; return Point<2> (t1 * v, t2 * v); } */ /* Point3d p1, p2, center; double rad; int i1, i2; public: */ /* STLBoundarySeg :: STLBoundarySeg (int ai1, int ai2, const Array > & points, const STLChart * chart) { i1 = ai1; i2 = ai2; p1 = points.Get(i1); p2 = points.Get(i2); center = ::netgen::Center (p1, p2); rad = Dist (p1, center); p2d1 = chart->Project2d (p1); p2d2 = chart->Project2d (p2); boundingbox.Set (p2d1); boundingbox.Add (p2d2); } */ void STLBoundarySeg :: Swap () { ::netgen::Swap (i1, i2); ::netgen::Swap (p1, p2); } STLBoundary :: STLBoundary (STLGeometry * ageometry) : geometry(ageometry) { ; } void STLBoundary :: AddOrDelSegment(const STLBoundarySeg & seg) { bool found = false; for (int i = 1; i <= boundary.Size(); i++) { if (found) { boundary.Elem(i-1) = boundary.Get(i); } if (boundary.Get(i) == seg) { found = true; } } if (!found) { boundary.Append(seg); } else { boundary.SetSize(boundary.Size()-1); } } void STLBoundary ::AddTriangle(const STLTriangle & t) { // static int timer_old = NgProfiler::CreateTimer ("STLChart::AddTriangle_old"); // static int timer_new = NgProfiler::CreateTimer ("STLChart::AddTriangle_new"); // NgProfiler::StartTimer (timer_old); #ifdef ADDTRIGOLD int i; int found1 = 0; int found2 = 0; int found3 = 0; //int offset = 0; STLBoundarySeg seg1(t[0],t[1], geometry->GetPoints(), chart); STLBoundarySeg seg2(t[1],t[2], geometry->GetPoints(), chart); STLBoundarySeg seg3(t[2],t[0], geometry->GetPoints(), chart); seg1.SetSmoothEdge (geometry->IsSmoothEdge (seg1.I1(), seg1.I2())); seg2.SetSmoothEdge (geometry->IsSmoothEdge (seg2.I1(), seg2.I2())); seg3.SetSmoothEdge (geometry->IsSmoothEdge (seg3.I1(), seg3.I2())); /* for (i = 1; i <= boundary.Size(); i++) { if (offset) {boundary.Elem(i-offset) = boundary.Get(i);} if (boundary.Get(i) == seg1) {found1 = 1; offset++;} if (boundary.Get(i) == seg2) {found2 = 1; offset++;} if (boundary.Get(i) == seg3) {found3 = 1; offset++;} } if (offset) { boundary.SetSize(boundary.Size()-offset); } */ for (i = boundary.Size(); i >= 1; i--) { if (boundary.Get(i) == seg1) { boundary.DeleteElement (i); found1 = 1; } else if (boundary.Get(i) == seg2) { boundary.DeleteElement (i); found2 = 1; } else if (boundary.Get(i) == seg3) { boundary.DeleteElement (i); found3 = 1; } } if (!found1) { seg1.Swap(); boundary.Append(seg1); /* int newnr; if (freelist.Size()) { newnr = freelist.Last(); freelist.DeleteLast(); boundary[newnr] = seg1; } else { boundary.Append(seg1); newnr = boundary.Size(); } // cout << "tree add el " << boundary.Size() << endl; if (searchtree) { // cout << "add " << boundary.Size() << endl; searchtree->Insert (seg1.BoundingBox(), newnr); } */ } if (!found2) { seg2.Swap(); boundary.Append(seg2); /* int newnr; if (freelist.Size()) { newnr = freelist.Last(); freelist.DeleteLast(); boundary[newnr] = seg2; } else { boundary.Append(seg2); newnr = boundary.Size(); } // boundary.Append(seg2); // cout << "tree add el " << boundary.Size() << endl; if (searchtree) { // cout << "add " << boundary.Size() << endl; searchtree->Insert (seg2.BoundingBox(), newnr); } */ } if (!found3) { seg3.Swap(); boundary.Append(seg3); /* int newnr; if (freelist.Size()) { newnr = freelist.Last(); freelist.DeleteLast(); boundary[newnr] = seg3; } else { boundary.Append(seg3); newnr = boundary.Size(); } // cout << "tree add el " << boundary.Size() << endl; if (searchtree) { // cout << "add " << boundary.Size() << endl; searchtree->Insert (seg3.BoundingBox(), newnr); } */ } #endif // NgProfiler::StopTimer (timer_old); // NgProfiler::StartTimer (timer_new); INDEX_2 segs[3]; segs[0] = INDEX_2(t[0], t[1]); segs[1] = INDEX_2(t[1], t[2]); segs[2] = INDEX_2(t[2], t[0]); for (auto seg : segs) { STLBoundarySeg bseg(seg[0], seg[1], geometry->GetPoints(), chart); bseg.SetSmoothEdge (geometry->IsSmoothEdge (seg[0],seg[1])); INDEX_2 op(seg[1], seg[0]); if (boundary_ht.Used(op)) { // cout << "delete " << op << endl; boundary_ht.Delete(op); } else { // cout << "insert " << seg << endl; boundary_ht[seg] = bseg; } } /* // cout << "bounds = " << boundary << endl; cout << "bounds:"; for (auto & val : boundary) cout << val.I1() << "-" << val.I2() << endl; cout << "ht = " << boundary_ht << endl; if (boundary_ht.UsedElements() != boundary.Size()) { cout << "wrong count" << endl; char key; cin >> key; } */ // NgProfiler::StopTimer (timer_new); } int STLBoundary :: TestSeg(const Point<3>& p1, const Point<3> & p2, const Vec<3> & sn, double sinchartangle, int divisions, Array >& points, double eps) { if (usechartnormal) return TestSegChartNV (p1, p2, sn); #ifdef NONE // for statistics { int i; static Array cntclass; static int cnt = 0; static int cnti = 0, cnto = 0; static long int cntsegs = 0; if (cntclass.Size() == 0) { cntclass.SetSize (20); for (i = 1; i <= cntclass.Size(); i++) cntclass.Elem(i) = 0; } cntsegs += NOSegments(); int cla = int (log (double(NOSegments()+1)) / log(2.0)); if (cla < 1) cla = 1; if (cla > cntclass.Size()) cla = cntclass.Size(); cntclass.Elem(cla)++; cnt++; if (divisions) cnti++; else cnto++; if (cnt > 100000) { cnt = 0; /* (*testout) << "TestSeg-calls for classes:" << endl; (*testout) << cnti << " inner calls, " << cnto << " outercalls" << endl; (*testout) << "total testes segments: " << cntsegs << endl; for (i = 1; i <= cntclass.Size(); i++) { (*testout) << int (exp (i * log(2.0))) << " bnd segs: " << cntclass.Get(i) << endl; } */ } } #endif int i,j,k; Point<3> seg1p/*, seg2p*/; Point<3> sp1,sp2; double lambda1, lambda2, vlen2; Vec<3> vptpl; double sinchartangle2 = sqr(sinchartangle); double scal; int possible; //double maxval = -1; //double maxvalnew = -1; double scalp1 = p1(0) * sn(0) + p1(1) * sn(1) + p1(2) * sn(2); double scalp2 = p2(0) * sn(0) + p2(1) * sn(1) + p2(2) * sn(2); double minl = min2(scalp1, scalp2); double maxl = max2(scalp1, scalp2); Point<3> c = Center (p1, p2); double dist1 = Dist (c, p1); int nseg = NOSegments(); for (j = 1; j <= nseg; j++) { const STLBoundarySeg & seg = GetSegment(j); if (seg.IsSmoothEdge()) continue; sp1 = seg.P1(); sp2 = seg.P2(); // Test, ob Spiral Konfikt moeglich possible = 1; double scalsp1 = sp1(0) * sn(0) + sp1(1) * sn(1) + sp1(2) * sn(2); double scalsp2 = sp2(0) * sn(0) + sp2(1) * sn(1) + sp2(2) * sn(2); double minsl = min2(scalsp1, scalsp2); double maxsl = max2(scalsp1, scalsp2); double maxdiff = max2 (maxsl - minl, maxl - minsl); /* Point3d sc = Center (sp1, sp2); double mindist = Dist(c, sc) - dist1 - GetSegment(j).Radius(); if (maxdiff < sinchartangle * mindist) { possible = 0; } */ double hscal = maxdiff + sinchartangle * (dist1 + seg.Radius()); if (hscal * hscal < sinchartangle * Dist2(c, seg.center )) possible = 0; /* if (possible) { double mindist2ex = MinDistLL2 (p1, p2, sp1, sp2); if (maxdiff * maxdiff < sinchartangle2 * mindist2ex) possible = 0; } */ if (possible) { LinearPolynomial2V lp (scalp1 - scalsp1, scalp2 - scalp1, -(scalsp2 - scalsp1)); QuadraticPolynomial2V slp; slp.Square (lp); Vec3d v (p1, sp1); Vec3d vl (p1, p2); Vec3d vsl (sp1, sp2); QuadraticPolynomial2V qp (v.Length2(), -2 * (v * vl), 2 * (v * vsl), vl.Length2(), -2 * (vl * vsl), vsl.Length2()); slp.Add (-sinchartangle2, qp); double hv = slp.MaxUnitSquare(); if (hv > eps) return 0; /* if (hv > maxvalnew) maxvalnew = hv; */ } // if (possible && 0) if (false) for (i = 0; i <= divisions; i++) { lambda1 = (double)i/(double)divisions; seg1p = Point3d(p1(0)*lambda1+p2(0)*(1.-lambda1), p1(1)*lambda1+p2(1)*(1.-lambda1), p1(2)*lambda1+p2(2)*(1.-lambda1)); for (k = 0; k <= divisions; k++) { lambda2 = (double)k/(double)divisions; vptpl = Vec3d(sp1(0)*lambda2+sp2(0)*(1.-lambda2)-seg1p(0), sp1(1)*lambda2+sp2(1)*(1.-lambda2)-seg1p(1), sp1(2)*lambda2+sp2(2)*(1.-lambda2)-seg1p(2)); vlen2 = vptpl.Length2(); // if (vlen2 > 0) { scal = vptpl * sn; double hv = scal*scal - sinchartangle2*vlen2; /* if (hv > maxval) maxval = hv; */ if (hv > eps) return 0; } } } } return 1; // return (maxvalnew < eps); } void STLBoundary :: BuildSearchTree() { // static int timer = NgProfiler::CreateTimer ("BuildSearchTree"); // NgProfiler::RegionTimer reg(timer); delete searchtree; /* Box<2> box2d(Box<2>::EMPTY_BOX); int nseg = NOSegments(); for (int j = 1; j <= nseg; j++) { const STLBoundarySeg & seg = GetSegment(j); if (seg.IsSmoothEdge()) continue; box2d.Add(seg.BoundingBox().PMin()); box2d.Add(seg.BoundingBox().PMax()); } searchtree = new BoxTree<2> (box2d); for (int j = 1; j <= nseg; j++) { const STLBoundarySeg & seg = GetSegment(j); if (seg.IsSmoothEdge()) continue; searchtree -> Insert (seg.BoundingBox(), j); } */ Box<2> box2d(Box<2>::EMPTY_BOX); Box<3> box3d = geometry->GetBoundingBox(); for (size_t i = 0; i < 8; i++) box2d.Add ( chart->Project2d (box3d.GetPointNr(i))); searchtree = new BoxTree<2,INDEX_2> (box2d); } void STLBoundary :: DeleteSearchTree() { // static int timer = NgProfiler::CreateTimer ("DeleteSearchTree"); // NgProfiler::RegionTimer reg(timer); delete searchtree; searchtree = nullptr; } // checks, whether 2d projection intersects int STLBoundary :: TestSegChartNV(const Point3d & p1, const Point3d& p2, const Vec3d& sn) { // static int timerquick = NgProfiler::CreateTimer ("TestSegChartNV-searchtree"); // static int timer = NgProfiler::CreateTimer ("TestSegChartNV"); int nseg = NOSegments(); Point<2> p2d1 = chart->Project2d (p1); Point<2> p2d2 = chart->Project2d (p2); Box<2> box2d; box2d.Set (p2d1); box2d.Add (p2d2); Line2d l1 (p2d1, p2d2); double eps = 1e-3; bool ok = true; /* static long int cnt = 0; static long int totnseg = 0; totnseg += nseg; cnt++; if ( (cnt % 100000) == 0) cout << "avg nseg = " << double(totnseg)/cnt << endl; */ if (searchtree) { // NgProfiler::RegionTimer reg(timerquick); ArrayMem pis; searchtree -> GetIntersecting (box2d.PMin(), box2d.PMax(), pis); for (auto i2 : pis) { // const STLBoundarySeg & seg = GetSegment(j); const STLBoundarySeg & seg = boundary_ht[i2]; if (seg.IsSmoothEdge()) continue; if (!box2d.Intersect (seg.BoundingBox())) continue; const Point<2> & sp1 = seg.P2D1(); const Point<2> & sp2 = seg.P2D2(); Line2d l2 (sp1, sp2); double lam1, lam2; int err = CrossPointBarycentric (l1, l2, lam1, lam2); if (!err && lam1 > eps && lam1 < 1-eps && lam2 > eps && lam2 < 1-eps) { ok = false; break; } } } else { // NgProfiler::RegionTimer reg(timer); for (int j = 1; j <= nseg; j++) { const STLBoundarySeg & seg = GetSegment(j); if (seg.IsSmoothEdge()) continue; if (!box2d.Intersect (seg.BoundingBox())) continue; const Point<2> & sp1 = seg.P2D1(); const Point<2> & sp2 = seg.P2D2(); Line2d l2 (sp1, sp2); double lam1, lam2; int err = CrossPointBarycentric (l1, l2, lam1, lam2); if (!err && lam1 > eps && lam1 < 1-eps && lam2 > eps && lam2 < 1-eps) { ok = false; break; } } } return ok; } STLDoctorParams :: STLDoctorParams() { drawmeshededges = 1; geom_tol_fact = 1E-6; longlinefact = 0; showexcluded = 1; selectmode = 0; edgeselectmode = 0; useexternaledges = 0; showfaces = 0; showtouchedtrigchart = 1; showedgecornerpoints = 1; conecheck = 1; spiralcheck = 1; selecttrig = 0; nodeofseltrig = 1; selectwithmouse = 1; showmarkedtrigs = 1; dirtytrigfact = 0.001; smoothangle = 90; smoothnormalsweight = 0.2; vicinity = 0; showvicinity = 0; } STLDoctorParams stldoctor; void STLDoctorParams :: Print (ostream & ost) const { ost << "STL doctor parameters:" << endl << "selecttrig = " << selecttrig << endl << "selectlocalpoint = " << nodeofseltrig << endl << "selectwithmouse = " << selectwithmouse << endl << "showmarkedtrigs = " << showmarkedtrigs << endl << "dirtytrigfact = " << dirtytrigfact << endl << "smoothangle = " << smoothangle << endl; } STLParameters :: STLParameters() { yangle = 30; contyangle = 20; edgecornerangle = 60; chartangle = 15; outerchartangle = 70; usesearchtree = 0; atlasminh = 1E-4; resthsurfcurvfac = 2; resthsurfcurvenable = 0; resthatlasfac = 2; resthatlasenable = 1; resthchartdistfac = 1.2; resthchartdistenable = 1; resthlinelengthfac = 0.5; resthlinelengthenable = 1; resthcloseedgefac = 1; resthcloseedgeenable = 1; resthedgeanglefac = 1; resthedgeangleenable = 0; resthsurfmeshcurvfac = 1; resthsurfmeshcurvenable = 0; recalc_h_opt = 1; } void STLParameters :: Print (ostream & ost) const { ost << "STL parameters:" << endl << "yellow angle = " << yangle << endl << "continued yellow angle = " << contyangle << endl << "edgecornerangle = " << edgecornerangle << endl << "chartangle = " << chartangle << endl << "outerchartangle = " << outerchartangle << endl << "restrict h due to ..., enable and safety factor: " << endl << "surface curvature: " << resthsurfcurvenable << ", fac = " << resthsurfcurvfac << endl << "atlas surface curvature: " << resthatlasenable << ", fac = " << resthatlasfac << endl << "chart distance: " << resthchartdistenable << ", fac = " << resthchartdistfac << endl << "line length: " << resthlinelengthenable << ", fac = " << resthlinelengthfac << endl << "close edges: " << resthcloseedgeenable << ", fac = " << resthcloseedgefac << endl << "edge angle: " << resthedgeangleenable << ", fac = " << resthedgeanglefac << endl; } STLParameters stlparam; } netgen-6.2.1905/libsrc/stlgeom/stlgeom.cpp0000644000175000017500000023260613504650527017120 0ustar kurtkurt#include #include "stlgeom.hpp" namespace netgen { //globalen searchtree fuer gesamte geometry aktivieren int geomsearchtreeon = 0; int usechartnormal = 1; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void STLMeshing (STLGeometry & geom, Mesh & mesh) { geom.Clear(); geom.BuildEdges(); geom.MakeAtlas(mesh); if (multithread.terminate) { return; } geom.CalcFaceNums(); geom.AddFaceEdges(); geom.LinkEdges(); mesh.ClearFaceDescriptors(); for (int i = 1; i <= geom.GetNOFaces(); i++) mesh.AddFaceDescriptor (FaceDescriptor (i, 1, 0, 0)); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++ STL GEOMETRY ++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STLGeometry :: STLGeometry() /* : edges(), edgesperpoint(), normals(), externaledges(), atlas(), chartmark(), lines(), outerchartspertrig(), vicinity(), markedtrigs(), markedsegs(), lineendpoints(), spiralpoints(), selectedmultiedge() */ { ref = NULL; edgedata = new STLEdgeDataList(*this); externaledges.SetSize(0); Clear(); meshchart = 0; // initialize all ?? JS if (geomsearchtreeon) searchtree = new BoxTree<3> (GetBoundingBox().PMin() - Vec3d(1,1,1), GetBoundingBox().PMax() + Vec3d(1,1,1)); else searchtree = NULL; status = STL_GOOD; statustext = "Good Geometry"; smoothedges = NULL; area = -1; } STLGeometry :: ~STLGeometry() { for (auto p : atlas) delete p; delete edgedata; delete ref; } void STLGeometry :: Save (string filename) const { const char * cfilename = filename.c_str(); if (strlen(cfilename) < 4) throw NgException ("illegal filename"); if (strlen(cfilename) > 3 && strcmp (&cfilename[strlen(cfilename)-3], "stl") == 0) { STLTopology::Save (cfilename); } else if (strlen(cfilename) > 4 && strcmp (&cfilename[strlen(cfilename)-4], "stlb") == 0) { SaveBinary (cfilename,"Binary STL Geometry"); } else if (strlen(cfilename) > 4 && strcmp (&cfilename[strlen(cfilename)-4], "stle") == 0) { SaveSTLE (cfilename); } } int STLGeometry :: GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam) { return STLMeshingDummy (this, mesh, mparam); } const Refinement & STLGeometry :: GetRefinement () const { delete ref; ref = new RefinementSTLGeometry(*this); // ref -> Set2dOptimizer(new MeshOptimizeSTLSurface(*this)); ??? copied from CSG return *ref; } void STLGeometry :: STLInfo(double* data) { data[0] = GetNT(); Box<3> b = GetBoundingBox(); data[1] = b.PMin()(0); data[2] = b.PMax()(0); data[3] = b.PMin()(1); data[4] = b.PMax()(1); data[5] = b.PMin()(2); data[6] = b.PMax()(2); int i; int cons = 1; for (i = 1; i <= GetNT(); i++) { if (NONeighbourTrigs(i) != 3) {cons = 0;} } data[7] = cons; } void STLGeometry :: MarkNonSmoothNormals() { PrintFnStart("Mark Non-Smooth Normals"); int i,j; markedtrigs.SetSize(GetNT()); for (i = 1; i <= GetNT(); i++) { SetMarkedTrig(i, 0); } double dirtyangle = stlparam.yangle/180.*M_PI; int cnt = 0; int lp1,lp2; for (i = 1; i <= GetNT(); i++) { for (j = 1; j <= NONeighbourTrigs(i); j++) { if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle) { GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), lp1, lp2); if (!IsEdge(lp1,lp2)) { if (!IsMarkedTrig(i)) {SetMarkedTrig(i,1); cnt++;} } } } } PrintMessage(5,"marked ",cnt," non-smooth trig-normals"); } void STLGeometry :: SmoothNormals() { multithread.terminate = 0; // UseExternalEdges(); BuildEdges(); DenseMatrix m(3), hm(3); Vector rhs(3), sol(3), hv(3), hv2(3); Vec<3> ri; double wnb = stldoctor.smoothnormalsweight; // neighbour normal weight double wgeom = 1-wnb; // geometry normal weight // minimize // wgeom sum_T \sum ri \| ri^T (n - n_geom) \|^2 // + wnb sum_SE \| ri x (n - n_nb) \|^2 int i, j, k, l; int nt = GetNT(); PushStatusF("Smooth Normals"); //int testmode; for (i = 1; i <= nt; i++) { SetThreadPercent( 100.0 * (double)i / (double)nt); const STLTriangle & trig = GetTriangle (i); m = 0; rhs = 0; // normal of geometry: Vec<3> ngeom = trig.GeomNormal(points); ngeom.Normalize(); for (j = 1; j <= 3; j++) { int pi1 = trig.PNumMod (j); int pi2 = trig.PNumMod (j+1); // edge vector ri = GetPoint (pi2) - GetPoint (pi1); for (k = 0; k < 3; k++) for (l = 0; l < 3; l++) hm.Elem(k+1, l+1) = wgeom * ri(k) * ri(l); for (k = 0; k < 3; k++) hv(k) = ngeom(k); hm.Mult (hv, hv2); /* if (testmode) (*testout) << "add vec " << hv2 << endl << " add m " << hm << endl; */ rhs.Add (1, hv2); m += hm; int nbt = 0; int fp1,fp2; for (k = 1; k <= NONeighbourTrigs(i); k++) { trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2); if (fp1 == pi1 && fp2 == pi2) { nbt = NeighbourTrig(i, k); } } if (!nbt) { cerr << "ERROR: stlgeom::Smoothnormals, nbt = 0" << endl; } // smoothed normal Vec<3> nnb = GetTriangle(nbt).Normal(); // neighbour normal nnb.Normalize(); if (!IsEdge(pi1,pi2)) { double lr2 = ri * ri; for (k = 0; k < 3; k++) { for (l = 0; l < k; l++) { hm.Elem(k+1, l+1) = -wnb * ri(k) * ri(l); hm.Elem(l+1, k+1) = -wnb * ri(k) * ri(l); } hm.Elem(k+1, k+1) = wnb * (lr2 - ri(k) * ri(k)); } for (k = 0; k < 3; k++) hv(k) = nnb(k); hm.Mult (hv, hv2); /* if (testmode) (*testout) << "add nb vec " << hv2 << endl << " add nb m " << hm << endl; */ rhs.Add (1, hv2); m += hm; } } m.Solve (rhs, sol); Vec3d newn(sol(0), sol(1), sol(2)); newn /= (newn.Length() + 1e-24); GetTriangle(i).SetNormal(newn); // setnormal (sol); } /* for (i = 1; i <= nt; i++) SetMarkedTrig(i, 0); int crloop; for (crloop = 1; crloop <= 3; crloop++) { // find critical: Array critpairs; for (i = 1; i <= nt; i++) { const STLTriangle & trig = GetTriangle (i); Vec3d ngeom = GetTriangleNormal (i); // trig.Normal(points); ngeom /= (ngeom.Length() + 1e-24); for (j = 1; j <= 3; j++) { int pi1 = trig.PNumMod (j); int pi2 = trig.PNumMod (j+1); int nbt = 0; int fp1,fp2; for (k = 1; k <= NONeighbourTrigs(i); k++) { trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2); if (fp1 == pi1 && fp2 == pi2) { nbt = NeighbourTrig(i, k); } } if (!nbt) { cerr << "ERROR: stlgeom::Smoothnormals, nbt = 0" << endl; } Vec3d nnb = GetTriangleNormal(nbt); // neighbour normal nnb /= (nnb.Length() + 1e-24); if (!IsEdge(pi1,pi2)) { if (Angle (nnb, ngeom) > 150 * M_PI/180) { SetMarkedTrig(i, 1); SetMarkedTrig(nbt, 1); critpairs.Append (INDEX_2 (i, nbt)); } } } } if (!critpairs.Size()) { break; } if (critpairs.Size()) { Array friends; double area1 = 0, area2 = 0; for (i = 1; i <= critpairs.Size(); i++) { int tnr1 = critpairs.Get(i).I1(); int tnr2 = critpairs.Get(i).I2(); (*testout) << "t1 = " << tnr1 << ", t2 = " << tnr2 << " angle = " << Angle (GetTriangleNormal (tnr1), GetTriangleNormal (tnr2)) << endl; // who has more friends ? int side; area1 = 0; area2 = 0; for (side = 1; side <= 2; side++) { friends.SetSize (0); friends.Append ( (side == 1) ? tnr1 : tnr2); for (j = 1; j <= 3; j++) { int fsize = friends.Size(); for (k = 1; k <= fsize; k++) { int testtnr = friends.Get(k); Vec3d ntt = GetTriangleNormal(testtnr); ntt /= (ntt.Length() + 1e-24); for (l = 1; l <= NONeighbourTrigs(testtnr); l++) { int testnbnr = NeighbourTrig(testtnr, l); Vec3d nbt = GetTriangleNormal(testnbnr); nbt /= (nbt.Length() + 1e-24); if (Angle (nbt, ntt) < 15 * M_PI/180) { int ii; int found = 0; for (ii = 1; ii <= friends.Size(); ii++) { if (friends.Get(ii) == testnbnr) { found = 1; break; } } if (!found) friends.Append (testnbnr); } } } } // compute area: for (k = 1; k <= friends.Size(); k++) { double area = GetTriangle (friends.Get(k)).Area(points); if (side == 1) area1 += area; else area2 += area; } } (*testout) << "area1 = " << area1 << " area2 = " << area2 << endl; if (area1 < 0.1 * area2) { Vec3d n = GetTriangleNormal (tnr1); n *= -1; SetTriangleNormal(tnr1, n); } if (area2 < 0.1 * area1) { Vec3d n = GetTriangleNormal (tnr2); n *= -1; SetTriangleNormal(tnr2, n); } } } } */ calcedgedataanglesnew = 1; PopStatus(); } int STLGeometry :: AddEdge(int ap1, int ap2) { STLEdge e(ap1,ap2); e.SetLeftTrig(GetLeftTrig(ap1,ap2)); e.SetRightTrig(GetRightTrig(ap1,ap2)); edges.Append(e); return edges.Size(); } void STLGeometry :: STLDoctorConfirmEdge() { StoreEdgeData(); if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) { if (stldoctor.selectmode == 1) { int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED); } else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { int i; for (i = 1; i <= selectedmultiedge.Size(); i++) { int ap1 = selectedmultiedge.Get(i).i1; int ap2 = selectedmultiedge.Get(i).i2; edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED); } } } } void STLGeometry :: STLDoctorCandidateEdge() { StoreEdgeData(); if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) { if (stldoctor.selectmode == 1) { int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE); } else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { int i; for (i = 1; i <= selectedmultiedge.Size(); i++) { int ap1 = selectedmultiedge.Get(i).i1; int ap2 = selectedmultiedge.Get(i).i2; edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE); } } } } void STLGeometry :: STLDoctorExcludeEdge() { StoreEdgeData(); if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) { if (stldoctor.selectmode == 1) { int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED); } else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { int i; for (i = 1; i <= selectedmultiedge.Size(); i++) { int ap1 = selectedmultiedge.Get(i).i1; int ap2 = selectedmultiedge.Get(i).i2; edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED); } } } } void STLGeometry :: STLDoctorUndefinedEdge() { StoreEdgeData(); if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig()) { if (stldoctor.selectmode == 1) { int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED); } else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { int i; for (i = 1; i <= selectedmultiedge.Size(); i++) { int ap1 = selectedmultiedge.Get(i).i1; int ap2 = selectedmultiedge.Get(i).i2; edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED); } } } } void STLGeometry :: STLDoctorSetAllUndefinedEdges() { edgedata->ResetAll(); } void STLGeometry :: STLDoctorEraseCandidateEdges() { StoreEdgeData(); edgedata->ChangeStatus(ED_CANDIDATE, ED_UNDEFINED); } void STLGeometry :: STLDoctorConfirmCandidateEdges() { StoreEdgeData(); edgedata->ChangeStatus(ED_CANDIDATE, ED_CONFIRMED); } void STLGeometry :: STLDoctorConfirmedToCandidateEdges() { StoreEdgeData(); edgedata->ChangeStatus(ED_CONFIRMED, ED_CANDIDATE); } void STLGeometry :: STLDoctorDirtyEdgesToCandidates() { StoreEdgeData(); } void STLGeometry :: STLDoctorLongLinesToCandidates() { StoreEdgeData(); } twoint STLGeometry :: GetNearestSelectedDefinedEdge() { Point<3> pestimate = Center(GetTriangle(GetSelectTrig()).center, GetPoint(GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()))); //Point3d pestimate = GetTriangle(GetSelectTrig()).center; int i, j, en; Array vic; GetVicinity(GetSelectTrig(),4,vic); twoint fedg; fedg.i1 = 0; fedg.i2 = 0; double mindist = 1E50; double dist; Point<3> p; for (i = 1; i <= vic.Size(); i++) { const STLTriangle& t = GetTriangle(vic.Get(i)); for (j = 1; j <= 3; j++) { en = edgedata->GetEdgeNum(t.PNum(j),t.PNumMod(j+1)); if (edgedata->Get(en).GetStatus() != ED_UNDEFINED) { p = pestimate; dist = GetDistFromLine(GetPoint(t.PNum(j)),GetPoint(t.PNumMod(j+1)),p); if (dist < mindist) { mindist = dist; fedg.i1 = t.PNum(j); fedg.i2 = t.PNumMod(j+1); } } } } return fedg; } void STLGeometry :: BuildSelectedMultiEdge(twoint ep) { if (edgedata->Size() == 0 || !GetEPPSize()) { return; } selectedmultiedge.SetSize(0); int tenum = GetTopEdgeNum (ep.i1, ep.i2); if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED) { twoint epnew = GetNearestSelectedDefinedEdge(); if (epnew.i1) { ep = epnew; tenum = GetTopEdgeNum (ep.i1, ep.i2); } } selectedmultiedge.Append(twoint(ep)); if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED) { return; } edgedata->BuildLineWithEdge(ep.i1,ep.i2,selectedmultiedge); } void STLGeometry :: BuildSelectedEdge(twoint ep) { if (edgedata->Size() == 0 || !GetEPPSize()) { return; } selectedmultiedge.SetSize(0); selectedmultiedge.Append(twoint(ep)); } void STLGeometry :: BuildSelectedCluster(twoint ep) { if (edgedata->Size() == 0 || !GetEPPSize()) { return; } selectedmultiedge.SetSize(0); int tenum = GetTopEdgeNum (ep.i1, ep.i2); if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED) { twoint epnew = GetNearestSelectedDefinedEdge(); if (epnew.i1) { ep = epnew; tenum = GetTopEdgeNum (ep.i1, ep.i2); } } selectedmultiedge.Append(twoint(ep)); if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED) { return; } edgedata->BuildClusterWithEdge(ep.i1,ep.i2,selectedmultiedge); } void STLGeometry :: ImportEdges() { StoreEdgeData(); PrintMessage(5, "import edges from file 'edges.ng'"); ifstream fin("edges.ng"); int ne; fin >> ne; Array > eps; int i; Point<3> p; for (i = 1; i <= 2*ne; i++) { fin >> p(0); fin >> p(1); fin >> p(2); eps.Append(p); } AddEdges(eps); } void STLGeometry :: AddEdges(const Array >& eps) { int i; int ne = eps.Size()/2; Array epsi; Box<3> bb = GetBoundingBox(); bb.Increase(1); Point3dTree ptree (bb.PMin(), bb.PMax()); Array pintersect; double gtol = GetBoundingBox().Diam()/1.E10; Point<3> p; for (i = 1; i <= GetNP(); i++) { p = GetPoint(i); ptree.Insert (p, i); } int error = 0; for (i = 1; i <= 2*ne; i++) { p = eps.Get(i); Point3d pmin = p - Vec3d (gtol, gtol, gtol); Point3d pmax = p + Vec3d (gtol, gtol, gtol); ptree.GetIntersecting (pmin, pmax, pintersect); if (pintersect.Size() > 1) { PrintError("Found too much points in epsilon-dist"); error = 1; } else if (pintersect.Size() == 0) { error = 1; PrintError("edgepoint does not exist!"); PrintMessage(5,"p=",Point3d(eps.Get(i))); } else { epsi.Append(pintersect.Get(1)); } } if (error) return; int en; for (i = 1; i <= ne; i++) { if (epsi.Get(2*i-1) == epsi.Get(2*i)) {PrintError("Edge with zero length!");} else { en = edgedata->GetEdgeNum(epsi.Get(2*i-1),epsi.Get(2*i)); edgedata->Elem(en).SetStatus (ED_CONFIRMED); } } } void STLGeometry :: ImportExternalEdges(const char * filename) { //AVL edges!!!!!! ifstream inf (filename); char ch; //int cnt = 0; int records, units, i, j; PrintFnStart("Import edges from ",filename); const int flen=30; char filter[flen+1]; filter[flen] = 0; char buf[20]; Array importpoints; Array importlines; Array importpnums; while (inf.good()) { inf.get(ch); // (*testout) << cnt << ": " << ch << endl; for (i = 0; i < flen; i++) filter[i] = filter[i+1]; filter[flen-1] = ch; // (*testout) << filter << endl; if (strcmp (filter+flen-7, "RECORDS") == 0) { inf.get(ch); // '=' inf >> records; } if (strcmp (filter+flen-5, "UNITS") == 0) { inf.get(ch); // '=' inf >> units; } if (strcmp (filter+flen-17, "EDGE NODE NUMBERS") == 0) { int nodenr; importlines.SetSize (units); for (i = 1; i <= units; i++) { inf >> nodenr; importlines.Elem(i) = nodenr; // (*testout) << nodenr << endl; } } if (strcmp (filter+flen-23, "EDGE POINT COORD IN DIR") == 0) { int coord; inf >> coord; importpoints.SetSize (units); inf >> ch; inf.putback (ch); for (i = 1; i <= units; i++) { for (j = 0; j < 12; j++) inf.get (buf[j]); buf[12] = 0; importpoints.Elem(i).X(coord) = 1000 * atof (buf); } } } /* (*testout) << "lines: " << endl; for (i = 1; i <= importlines.Size(); i++) (*testout) << importlines.Get(i) << endl; (*testout) << "points: " << endl; for (i = 1; i <= importpoints.Size(); i++) (*testout) << importpoints.Get(i) << endl; */ importpnums.SetSize (importpoints.Size()); Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1), GetBoundingBox().PMax() + Vec3d (1, 1, 1)); Point3dTree ptree (bb.PMin(), bb.PMax()); PrintMessage(7,"stl - bb: ",bb.PMin(), " - ", bb.PMax()); Box3d ebb; ebb.SetPoint (importpoints.Get(1)); for (i = 1; i <= importpoints.Size(); i++) ebb.AddPoint (importpoints.Get(i)); PrintMessage(7,"edgep - bb: ", ebb.PMin(), " - ", ebb.PMax()); Array pintersect; double gtol = GetBoundingBox().Diam()/1.E6; for (i = 1; i <= GetNP(); i++) { Point3d p = GetPoint(i); // (*testout) << "stlpt: " << p << endl; ptree.Insert (p, i); } for (i = 1; i <= importpoints.Size(); i++) { Point3d p = importpoints.Get(i); Point3d pmin = p - Vec3d (gtol, gtol, gtol); Point3d pmax = p + Vec3d (gtol, gtol, gtol); ptree.GetIntersecting (pmin, pmax, pintersect); if (pintersect.Size() > 1) { importpnums.Elem(i) = 0; PrintError("Found too many points in epsilon-dist"); } else if (pintersect.Size() == 0) { importpnums.Elem(i) = 0; PrintError("Edgepoint does not exist!"); } else { importpnums.Elem(i) = pintersect.Get(1); } } // if (!error) { PrintMessage(7,"found all edge points in stl file"); StoreEdgeData(); int oldp = 0; for (i = 1; i <= importlines.Size(); i++) { int newp = importlines.Get(i); if (!importpnums.Get(abs(newp))) newp = 0; if (oldp && newp) { int en = edgedata->GetEdgeNum(importpnums.Get(oldp), importpnums.Get(abs(newp))); edgedata->Elem(en).SetStatus (ED_CONFIRMED); } if (newp < 0) oldp = 0; else oldp = newp; } } } void STLGeometry :: ExportEdges() { PrintFnStart("Save edges to file 'edges.ng'"); ofstream fout("edges.ng"); fout.precision(16); int n = edgedata->GetNConfEdges(); fout << n << endl; int i; for (i = 1; i <= edgedata->Size(); i++) { if (edgedata->Get(i).GetStatus() == ED_CONFIRMED) { const STLTopEdge & e = edgedata->Get(i); fout << GetPoint(e.PNum(1))(0) << " " << GetPoint(e.PNum(1))(1) << " " << GetPoint(e.PNum(1))(2) << endl; fout << GetPoint(e.PNum(2))(0) << " " << GetPoint(e.PNum(2))(1) << " " << GetPoint(e.PNum(2))(2) << endl; } } } void STLGeometry :: LoadEdgeData(const char* file) { StoreEdgeData(); PrintFnStart("Load edges from file '", file, "'"); ifstream fin(file); edgedata->Read(fin); // calcedgedataanglesnew = 1; } void STLGeometry :: SaveEdgeData(const char* file) { PrintFnStart("save edges to file '", file, "'"); ofstream fout(file); edgedata->Write(fout); } /* void STLGeometry :: SaveExternalEdges() { ofstream fout("externaledgesp3.ng"); fout.precision(16); int n = NOExternalEdges(); fout << n << endl; int i; for (i = 1; i <= n; i++) { twoint e = GetExternalEdge(i); fout << GetPoint(e.i1)(0) << " " << GetPoint(e.i1)(1) << " " << GetPoint(e.i1)(2) << endl; fout << GetPoint(e.i2)(0) << " " << GetPoint(e.i2)(1) << " " << GetPoint(e.i2)(2) << endl; } } */ void STLGeometry :: StoreExternalEdges() { storedexternaledges.SetSize(0); undoexternaledges = 1; int i; for (i = 1; i <= externaledges.Size(); i++) { storedexternaledges.Append(externaledges.Get(i)); } } void STLGeometry :: UndoExternalEdges() { if (!undoexternaledges) { PrintMessage(1, "undo not further possible!"); return; } RestoreExternalEdges(); undoexternaledges = 0; } void STLGeometry :: RestoreExternalEdges() { externaledges.SetSize(0); int i; for (i = 1; i <= storedexternaledges.Size(); i++) { externaledges.Append(storedexternaledges.Get(i)); } } void STLGeometry :: AddExternalEdgeAtSelected() { StoreExternalEdges(); if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT()) { int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);} } } void STLGeometry :: AddClosedLinesToExternalEdges() { StoreExternalEdges(); int i, j; for (i = 1; i <= GetNLines(); i++) { STLLine* l = GetLine(i); if (l->StartP() == l->EndP()) { for (j = 1; j < l->NP(); j++) { int ap1 = l->PNum(j); int ap2 = l->PNum(j+1); if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);} } } } } void STLGeometry :: AddLongLinesToExternalEdges() { StoreExternalEdges(); double diamfact = stldoctor.dirtytrigfact; double diam = GetBoundingBox().Diam(); int i, j; for (i = 1; i <= GetNLines(); i++) { STLLine* l = GetLine(i); if (l->GetLength(points) >= diamfact*diam) { for (j = 1; j < l->NP(); j++) { int ap1 = l->PNum(j); int ap2 = l->PNum(j+1); if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);} } } } } void STLGeometry :: AddAllNotSingleLinesToExternalEdges() { StoreExternalEdges(); int i, j; for (i = 1; i <= GetNLines(); i++) { STLLine* l = GetLine(i); if (GetNEPP(l->StartP()) > 1 || GetNEPP(l->EndP()) > 1) { for (j = 1; j < l->NP(); j++) { int ap1 = l->PNum(j); int ap2 = l->PNum(j+1); if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);} } } } } void STLGeometry :: DeleteDirtyExternalEdges() { //delete single triangle edges and single edge-lines in clusters" StoreExternalEdges(); int i, j; for (i = 1; i <= GetNLines(); i++) { STLLine* l = GetLine(i); if (l->NP() <= 3 || (l->StartP() == l->EndP() && l->NP() == 4)) { for (j = 1; j < l->NP(); j++) { int ap1 = l->PNum(j); int ap2 = l->PNum(j+1); if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);} } } } } void STLGeometry :: AddExternalEdgesFromGeomLine() { StoreExternalEdges(); if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT()) { int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); if (IsEdge(ap1,ap2)) { int edgenum = IsEdgeNum(ap1,ap2); if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);} int noend = 1; int startp = ap1; int laste = edgenum; int np1, np2; while (noend) { if (GetNEPP(startp) == 2) { if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);} else {laste = GetEdgePP(startp,2);} np1 = GetEdge(laste).PNum(1); np2 = GetEdge(laste).PNum(2); if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);} else {noend = 0;} if (np1 != startp) {startp = np1;} else {startp = np2;} } else {noend = 0;} } startp = ap2; laste = edgenum; noend = 1; while (noend) { if (GetNEPP(startp) == 2) { if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);} else {laste = GetEdgePP(startp,2);} np1 = GetEdge(laste).PNum(1); np2 = GetEdge(laste).PNum(2); if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);} else {noend = 0;} if (np1 != startp) {startp = np1;} else {startp = np2;} } else {noend = 0;} } } } } void STLGeometry :: ClearEdges() { edgesfound = 0; edges.SetSize(0); //edgedata->SetSize(0); // externaledges.SetSize(0); edgesperpoint.SetSize(0); undoexternaledges = 0; } void STLGeometry :: STLDoctorBuildEdges() { // if (!trigsconverted) {return;} ClearEdges(); meshlines.SetSize(0); FindEdgesFromAngles(); } void STLGeometry :: DeleteExternalEdgeAtSelected() { StoreExternalEdges(); if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT()) { int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1); if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);} } } void STLGeometry :: DeleteExternalEdgeInVicinity() { StoreExternalEdges(); if (!stldoctor.showvicinity || vicinity.Size() != GetNT()) {return;} int i, j, ap1, ap2; for (i = 1; i <= GetNT(); i++) { if (vicinity.Elem(i)) { for (j = 1; j <= 3; j++) { ap1 = GetTriangle(i).PNum(j); ap2 = GetTriangle(i).PNumMod(j+1); if (IsExternalEdge(ap1,ap2)) { DeleteExternalEdge(ap1,ap2); } } } } } void STLGeometry :: BuildExternalEdgesFromEdges() { StoreExternalEdges(); if (GetNE() == 0) {PrintWarning("Edges possibly not generated!");} int i; externaledges.SetSize(0); for (i = 1; i <= GetNE(); i++) { STLEdge e = GetEdge(i); AddExternalEdge(e.PNum(1), e.PNum(2)); } } void STLGeometry :: AddExternalEdge(int ap1, int ap2) { externaledges.Append(twoint(ap1,ap2)); } void STLGeometry :: DeleteExternalEdge(int ap1, int ap2) { int i; int found = 0; for (i = 1; i <= NOExternalEdges(); i++) { if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) || (GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {found = 1;}; if (found && i < NOExternalEdges()) { externaledges.Elem(i) = externaledges.Get(i+1); } } if (!found) {PrintWarning("edge not found");} else { externaledges.SetSize(externaledges.Size()-1); } } int STLGeometry :: IsExternalEdge(int ap1, int ap2) { int i; for (i = 1; i <= NOExternalEdges(); i++) { if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) || (GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {return 1;}; } return 0; } void STLGeometry :: DestroyDirtyTrigs() { PrintFnStart("Destroy dirty triangles"); PrintMessage(5,"original number of triangles=", GetNT()); //destroy every triangle with other than 3 neighbours; int changed = 1; int i, j, k; while (changed) { changed = 0; Clear(); for (i = 1; i <= GetNT(); i++) { int dirty = NONeighbourTrigs(i) < 3; for (j = 1; j <= 3; j++) { int pnum = GetTriangle(i).PNum(j); /* if (pnum == 1546) { // for (k = 1; k <= NOTrigsPerPoint(pnum); k++) } */ if (NOTrigsPerPoint(pnum) <= 2) dirty = 1; } int pi1 = GetTriangle(i).PNum(1); int pi2 = GetTriangle(i).PNum(2); int pi3 = GetTriangle(i).PNum(3); if (pi1 == pi2 || pi1 == pi3 || pi2 == pi3) { PrintMessage(5,"triangle with Volume 0: ", i, " nodes: ", pi1, ", ", pi2, ", ", pi3); dirty = 1; } if (dirty) { for (k = i+1; k <= GetNT(); k++) { trias.Elem(k-1) = trias.Get(k); // readtrias: not longer permanent, JS // readtrias.Elem(k-1) = readtrias.Get(k); } int size = GetNT(); trias.SetSize(size-1); // readtrias.SetSize(size-1); changed = 1; break; } } } FindNeighbourTrigs(); PrintMessage(5,"final number of triangles=", GetNT()); } void STLGeometry :: CalcNormalsFromGeometry() { int i; for (i = 1; i <= GetNT(); i++) { const STLTriangle & tr = GetTriangle(i); const Point3d& ap1 = GetPoint(tr.PNum(1)); const Point3d& ap2 = GetPoint(tr.PNum(2)); const Point3d& ap3 = GetPoint(tr.PNum(3)); Vec3d normal = Cross (ap2-ap1, ap3-ap1); if (normal.Length() != 0) { normal /= (normal.Length()); } GetTriangle(i).SetNormal(normal); } PrintMessage(5,"Normals calculated from geometry!!!"); calcedgedataanglesnew = 1; } void STLGeometry :: SetSelectTrig(int trig) { stldoctor.selecttrig = trig; } int STLGeometry :: GetSelectTrig() const { return stldoctor.selecttrig; } void STLGeometry :: SetNodeOfSelTrig(int n) { stldoctor.nodeofseltrig = n; } int STLGeometry :: GetNodeOfSelTrig() const { return stldoctor.nodeofseltrig; } void STLGeometry :: MoveSelectedPointToMiddle() { if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT()) { int p = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()); Point<3> pm(0.,0.,0.); //Middlevector; Point<3> p0(0.,0.,0.); PrintMessage(5,"original point=", Point3d(GetPoint(p))); int i; int cnt = 0; for (i = 1; i <= trigsperpoint.EntrySize(p); i++) { const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,i)); int j; for (j = 1; j <= 3; j++) { if (tr.PNum(j) != p) { cnt++; pm(0) += GetPoint(tr.PNum(j))(0); pm(1) += GetPoint(tr.PNum(j))(1); pm(2) += GetPoint(tr.PNum(j))(2); } } } Point<3> origp = GetPoint(p); double fact = 0.2; SetPoint(p, p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0)); PrintMessage(5,"middle point=", Point3d (GetPoint(p))); PrintMessage(5,"moved point ", Point3d (p)); } } void STLGeometry :: PrintSelectInfo() { //int trig = GetSelectTrig(); //int p = GetTriangle(trig).PNum(GetNodeOfSelTrig()); PrintMessage(1,"touch triangle ", GetSelectTrig() , ", local node ", GetNodeOfSelTrig() , " (=", GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()), ")"); if (AtlasMade() && GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT()) { PrintMessage(1," chartnum=",GetChartNr(GetSelectTrig())); /* PointBetween(Center(Center(GetPoint(GetTriangle(270).PNum(1)), GetPoint(GetTriangle(270).PNum(2))), GetPoint(GetTriangle(270).PNum(3))),270, Center(Center(GetPoint(GetTriangle(trig).PNum(1)), GetPoint(GetTriangle(trig).PNum(2))), GetPoint(GetTriangle(trig).PNum(3))),trig); */ //PointBetween(Point3d(5.7818, 7.52768, 4.14879),260,Point3d(6.80292, 6.55392, 4.70184),233); } } void STLGeometry :: ShowSelectedTrigChartnum() { int st = GetSelectTrig(); if (st >= 1 && st <= GetNT() && AtlasMade()) PrintMessage(1,"selected trig ", st, " has chartnumber ", GetChartNr(st)); } void STLGeometry :: ShowSelectedTrigCoords() { int st = GetSelectTrig(); /* //testing!!!! Array trigs; GetSortedTrianglesAroundPoint(GetTriangle(st).PNum(GetNodeOfSelTrig()),st,trigs); */ if (st >= 1 && st <= GetNT()) { PrintMessage(1, "coordinates of selected trig ", st, ":"); PrintMessage(1, " p1 = ", GetTriangle(st).PNum(1), " = ", Point3d (GetPoint(GetTriangle(st).PNum(1)))); PrintMessage(1, " p2 = ", GetTriangle(st).PNum(2), " = ", Point3d (GetPoint(GetTriangle(st).PNum(2)))); PrintMessage(1, " p3 = ", GetTriangle(st).PNum(3), " = ", Point3d (GetPoint(GetTriangle(st).PNum(3)))); } } void STLGeometry :: LoadMarkedTrigs() { PrintFnStart("load marked trigs from file 'markedtrigs.ng'"); ifstream fin("markedtrigs.ng"); int n; fin >> n; if (n != GetNT() || n == 0) {PrintError("Not a suitable marked-trig-file!"); return;} int i, m; for (i = 1; i <= n; i++) { fin >> m; SetMarkedTrig(i, m); } fin >> n; if (n != 0) { Point<3> ap1, ap2; for (i = 1; i <= n; i++) { fin >> ap1(0); fin >> ap1(1); fin >> ap1(2); fin >> ap2(0); fin >> ap2(1); fin >> ap2(2); AddMarkedSeg(ap1,ap2); } } } void STLGeometry :: SaveMarkedTrigs() { PrintFnStart("save marked trigs to file 'markedtrigs.ng'"); ofstream fout("markedtrigs.ng"); int n = GetNT(); fout << n << endl; int i; for (i = 1; i <= n; i++) { fout << IsMarkedTrig(i) << "\n"; } n = GetNMarkedSegs(); fout << n << endl; Point<3> ap1,ap2; for (i = 1; i <= n; i++) { GetMarkedSeg(i,ap1,ap2); fout << ap1(0) << " " << ap1(1) << " " << ap1(2) << " "; fout << ap2(0) << " " << ap2(1) << " " << ap2(2) << " " << "\n"; } } void STLGeometry :: NeighbourAnglesOfSelectedTrig() { int st = GetSelectTrig(); if (st >= 1 && st <= GetNT()) { int i; PrintMessage(1,"Angle to triangle ", st, ":"); for (i = 1; i <= NONeighbourTrigs(st); i++) { PrintMessage(1," triangle ", NeighbourTrig(st,i), ": angle = ", 180./M_PI*GetAngle(st, NeighbourTrig(st,i)), "°", ", calculated = ", 180./M_PI*Angle(GetTriangle(st).GeomNormal(points), GetTriangle(NeighbourTrig(st,i)).GeomNormal(points)), "°"); } } } void STLGeometry :: GetVicinity(int starttrig, int size, Array& vic) { if (starttrig == 0 || starttrig > GetNT()) {return;} Array vicarray; vicarray.SetSize(GetNT()); int i; for (i = 1; i <= vicarray.Size(); i++) { vicarray.Elem(i) = 0; } vicarray.Elem(starttrig) = 1; int j = 0,k; Array list1; list1.SetSize(0); Array list2; list2.SetSize(0); list1.Append(starttrig); while (j < size) { j++; for (i = 1; i <= list1.Size(); i++) { for (k = 1; k <= NONeighbourTrigs(i); k++) { int nbtrig = NeighbourTrig(list1.Get(i),k); if (nbtrig && vicarray.Get(nbtrig) == 0) { list2.Append(nbtrig); vicarray.Elem(nbtrig) = 1; } } } list1.SetSize(0); for (i = 1; i <= list2.Size(); i++) { list1.Append(list2.Get(i)); } list2.SetSize(0); } vic.SetSize(0); for (i = 1; i <= vicarray.Size(); i++) { if (vicarray.Get(i)) {vic.Append(i);} } } void STLGeometry :: CalcVicinity(int starttrig) { if (starttrig == 0 || starttrig > GetNT()) {return;} vicinity.SetSize(GetNT()); if (!stldoctor.showvicinity) {return;} int i; for (i = 1; i <= vicinity.Size(); i++) { vicinity.Elem(i) = 0; } vicinity.Elem(starttrig) = 1; int j = 0,k; Array list1; list1.SetSize(0); Array list2; list2.SetSize(0); list1.Append(starttrig); // int cnt = 1; while (j < stldoctor.vicinity) { j++; for (i = 1; i <= list1.Size(); i++) { for (k = 1; k <= NONeighbourTrigs(i); k++) { int nbtrig = NeighbourTrig(list1.Get(i),k); if (nbtrig && vicinity.Get(nbtrig) == 0) { list2.Append(nbtrig); vicinity.Elem(nbtrig) = 1; //cnt++; } } } list1.SetSize(0); for (i = 1; i <= list2.Size(); i++) { list1.Append(list2.Get(i)); } list2.SetSize(0); } } int STLGeometry :: Vicinity(int trig) const { if (trig <= vicinity.Size() && trig >=1) { return vicinity.Get(trig); } else {PrintSysError("In STLGeometry::Vicinity");} return 0; } void STLGeometry :: InitMarkedTrigs() { markedtrigs.SetSize(GetNT()); int i; for (i = 1; i <= GetNT(); i++) { SetMarkedTrig(i, 0); } } void STLGeometry :: MarkDirtyTrigs() { PrintFnStart("mark dirty trigs"); int i,j; markedtrigs.SetSize(GetNT()); for (i = 1; i <= GetNT(); i++) { SetMarkedTrig(i, 0); } int found; double dirtyangle = stlparam.yangle/2./180.*M_PI; int cnt = 0; for (i = 1; i <= GetNT(); i++) { found = 0; for (j = 1; j <= NONeighbourTrigs(i); j++) { if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle) { found++; } } if (found && GetTriangle(i).MinHeight(points) < stldoctor.dirtytrigfact*GetTriangle(i).MaxLength(points)) { SetMarkedTrig(i, 1); cnt++; } /* else if (found == 3) { SetMarkedTrig(i, 1); cnt++; } */ } PrintMessage(1, "marked ", cnt, " dirty trigs"); } void STLGeometry :: MarkTopErrorTrigs() { int cnt = 0; markedtrigs.SetSize(GetNT()); for (int i = 1; i <= GetNT(); i++) { const STLTriangle & trig = GetTriangle(i); SetMarkedTrig(i, trig.flags.toperror); if (trig.flags.toperror) cnt++; } PrintMessage(1,"marked ", cnt, " inconsistent triangles"); } double STLGeometry :: CalcTrigBadness(int i) { int j; double maxbadness = 0; int ap1, ap2; for (j = 1; j <= NONeighbourTrigs(i); j++) { GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2); if (!IsEdge(ap1,ap2) && GetGeomAngle(i, NeighbourTrig(i,j)) > maxbadness) { maxbadness = GetGeomAngle(i, NeighbourTrig(i,j)); } } return maxbadness; } void STLGeometry :: GeomSmoothRevertedTrigs() { //double revertedangle = stldoctor.smoothangle/180.*M_PI; double fact = stldoctor.dirtytrigfact; MarkRevertedTrigs(); int i, j, k, l, p; for (i = 1; i <= GetNT(); i++) { if (IsMarkedTrig(i)) { for (j = 1; j <= 3; j++) { double origbadness = CalcTrigBadness(i); p = GetTriangle(i).PNum(j); Point<3> pm(0.,0.,0.); //Middlevector; Point<3> p0(0.,0.,0.); int cnt = 0; for (k = 1; k <= trigsperpoint.EntrySize(p); k++) { const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,k)); for (l = 1; l <= 3; l++) { if (tr.PNum(l) != p) { cnt++; pm(0) += GetPoint(tr.PNum(l))(0); pm(1) += GetPoint(tr.PNum(l))(1); pm(2) += GetPoint(tr.PNum(l))(2); } } } Point3d origp = GetPoint(p); Point3d newp = p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0); SetPoint(p, newp); if (CalcTrigBadness(i) > 0.9*origbadness) {SetPoint(p,origp); PrintDot('f');} else {PrintDot('s');} } } } MarkRevertedTrigs(); } void STLGeometry :: MarkRevertedTrigs() { int i,j; if (edgesperpoint.Size() != GetNP()) {BuildEdges();} PrintFnStart("mark reverted trigs"); InitMarkedTrigs(); int found; double revertedangle = stldoctor.smoothangle/180.*M_PI; int cnt = 0; int ap1, ap2; for (i = 1; i <= GetNT(); i++) { found = 0; for (j = 1; j <= NONeighbourTrigs(i); j++) { GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2); if (!IsEdge(ap1,ap2)) { if (GetGeomAngle(i, NeighbourTrig(i,j)) > revertedangle) { found = 1; break; } } } if (found) { SetMarkedTrig(i, 1); cnt++; } } PrintMessage(5, "found ", cnt, " reverted trigs"); } void STLGeometry :: SmoothDirtyTrigs() { PrintFnStart("smooth dirty trigs"); MarkDirtyTrigs(); int i,j; int changed = 1; int ap1, ap2; while (changed) { changed = 0; for (i = 1; i <= GetNT(); i++) { if (IsMarkedTrig(i)) { int foundtrig = 0; double maxlen = 0; // JS: darf normalvector nicht ueber kurze Seite erben maxlen = GetTriangle(i).MaxLength(GetPoints()) / 2.1; //JG: bei flachem dreieck auch kurze Seite for (j = 1; j <= NONeighbourTrigs(i); j++) { if (!IsMarkedTrig(NeighbourTrig(i,j))) { GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)),ap1,ap2); if (Dist(GetPoint(ap1),GetPoint(ap2)) >= maxlen) { foundtrig = NeighbourTrig(i,j); maxlen = Dist(GetPoint(ap1),GetPoint(ap2)); } } } if (foundtrig) { GetTriangle(i).SetNormal(GetTriangle(foundtrig).Normal()); changed = 1; SetMarkedTrig(i,0); } } } } calcedgedataanglesnew = 1; MarkDirtyTrigs(); int cnt = 0; for (i = 1; i <= GetNT(); i++) { if (IsMarkedTrig(i)) {cnt++;} } PrintMessage(5,"NO marked dirty trigs=", cnt); } int STLGeometry :: IsMarkedTrig(int trig) const { if (trig <= markedtrigs.Size() && trig >=1) { return markedtrigs.Get(trig); } else {PrintSysError("In STLGeometry::IsMarkedTrig");} return 0; } void STLGeometry :: SetMarkedTrig(int trig, int num) { if (trig <= markedtrigs.Size() && trig >=1) { markedtrigs.Elem(trig) = num; } else {PrintSysError("In STLGeometry::SetMarkedTrig");} } void STLGeometry :: Clear() { PrintFnStart("Clear"); surfacemeshed = 0; surfaceoptimized = 0; volumemeshed = 0; selectedmultiedge.SetSize(0); meshlines.SetSize(0); // neighbourtrigs.SetSize(0); outerchartspertrig.SetSize(0); atlas.SetSize(0); ClearMarkedSegs(); ClearSpiralPoints(); ClearLineEndPoints(); SetSelectTrig(0); SetNodeOfSelTrig(1); facecnt = 0; SetThreadPercent(100.); ClearEdges(); } double STLGeometry :: Area() { if (area >= 0) return area; area = 0; for (int i = 1; i <= GetNT(); i++) area += GetTriangle(i).Area(points); return area; } double STLGeometry :: GetAngle(int t1, int t2) { return Angle(GetTriangle(t1).Normal(),GetTriangle(t2).Normal()); } double STLGeometry :: GetGeomAngle(int t1, int t2) { Vec3d n1 = GetTriangle(t1).GeomNormal(points); Vec3d n2 = GetTriangle(t2).GeomNormal(points); return Angle(n1,n2); } void STLGeometry :: InitSTLGeometry(const Array & readtrias) { PrintFnStart("Init STL Geometry"); STLTopology::InitSTLGeometry(readtrias); int i, k; //const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored int np = GetNP(); PrintMessage(5,"NO points= ", GetNP()); normals.SetSize(GetNP()); Array normal_cnt(GetNP()); // counts number of added normals in a point for (i = 1; i <= np; i++) { normal_cnt.Elem(i) = 0; normals.Elem(i) = Vec3d (0,0,0); } for(i = 1; i <= GetNT(); i++) { // STLReadTriangle t = GetReadTriangle(i); // STLTriangle st; Vec<3> n = GetTriangle(i).Normal (); for (k = 1; k <= 3; k++) { int pi = GetTriangle(i).PNum(k); normal_cnt.Elem(pi)++; SetNormal(pi, GetNormal(pi) + n); } } //normalize the normals for (i = 1; i <= GetNP(); i++) { SetNormal(i,1./(double)normal_cnt.Get(i)*GetNormal(i)); } trigsconverted = 1; vicinity.SetSize(GetNT()); markedtrigs.SetSize(GetNT()); for (i = 1; i <= GetNT(); i++) { markedtrigs.Elem(i) = 0; vicinity.Elem(i) = 1; } ha_points.SetSize(GetNP()); for (i = 1; i <= GetNP(); i++) ha_points.Elem(i) = 0; calcedgedataanglesnew = 0; edgedatastored = 0; edgedata->Clear(); if (GetStatus() == STL_ERROR) return; CalcEdgeData(); CalcEdgeDataAngles(); ClearLineEndPoints(); CheckGeometryOverlapping(); } void STLGeometry :: TopologyChanged() { calcedgedataanglesnew = 1; } int STLGeometry :: CheckGeometryOverlapping() { PrintMessageCR(3,"Check overlapping geometry ..."); Box<3> geombox = GetBoundingBox(); Point<3> pmin = geombox.PMin(); Point<3> pmax = geombox.PMax(); BoxTree<3> setree(pmin, pmax); int oltrigs = 0; markedtrigs.SetSize(GetNT()); for (int i = 1; i <= GetNT(); i++) SetMarkedTrig(i, 0); for (int i = 1; i <= GetNT(); i++) { const STLTriangle & tri = GetTriangle(i); Point<3> tpmin = tri.box.PMin(); Point<3> tpmax = tri.box.PMax(); Vec<3> diag = tpmax - tpmin; tpmax = tpmax + 0.001 * diag; tpmin = tpmin - 0.001 * diag; setree.Insert (tpmin, tpmax, i); } { mutex inters_mutex; ParallelFor( 1, GetNT()+1, [&] (int first, int next) { Array inters; for (int i=first; i tpmin = tri.box.PMin(); Point<3> tpmax = tri.box.PMax(); setree.GetIntersecting (tpmin, tpmax, inters); for (int j = 1; j <= inters.Size(); j++) { const STLTriangle & tri2 = GetTriangle(inters.Get(j)); const Point<3> *trip1[3], *trip2[3]; Point<3> hptri1[3], hptri2[3]; /* for (k = 1; k <= 3; k++) { trip1[k-1] = &GetPoint (tri.PNum(k)); trip2[k-1] = &GetPoint (tri2.PNum(k)); } */ for (int k = 0; k < 3; k++) { hptri1[k] = GetPoint (tri[k]); hptri2[k] = GetPoint (tri2[k]); trip1[k] = &hptri1[k]; trip2[k] = &hptri2[k]; } if (IntersectTriangleTriangle (&trip1[0], &trip2[0])) { lock_guard guard(inters_mutex); { oltrigs++; PrintMessage(5,"Intersecting Triangles: trig ",i," with ",inters.Get(j),"!"); SetMarkedTrig(i, 1); SetMarkedTrig(inters.Get(j), 1); } } } } }); } PrintMessage(3,"Check overlapping geometry ... ", oltrigs, " triangles overlap"); return oltrigs; } /* void STLGeometry :: InitSTLGeometry() { STLTopology::InitSTLGeometry(); int i, j, k; const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored trias.SetSize(0); points.SetSize(0); normals.SetSize(0); Array normal_cnt; // counts number of added normals in a point Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1), GetBoundingBox().PMax() + Vec3d (1, 1, 1)); Point3dTree pointtree (bb.PMin(), bb.PMax()); Array pintersect; double gtol = GetBoundingBox().CalcDiam()/geometry_tol_fact; for(i = 1; i <= GetReadNT(); i++) { //if (i%500==499) {(*mycout) << (double)i/(double)GetReadNT()*100. << "%" << endl;} STLReadTriangle t = GetReadTriangle(i); STLTriangle st; Vec3d n = t.normal; for (k = 0; k < 3; k++) { Point3d p = t.pts[k]; Point3d pmin = p - Vec3d (gtol, gtol, gtol); Point3d pmax = p + Vec3d (gtol, gtol, gtol); pointtree.GetIntersecting (pmin, pmax, pintersect); if (pintersect.Size() > 1) (*mycout) << "found too much " << char(7) << endl; int foundpos = 0; if (pintersect.Size()) foundpos = pintersect.Get(1); if (foundpos) { normal_cnt[foundpos]++; SetNormal(foundpos,GetNormal(foundpos)+n); // (*testout) << "found p " << p << endl; } else { foundpos = AddPoint(p); AddNormal(n); normal_cnt.Append(1); pointtree.Insert (p, foundpos); } //(*mycout) << "foundpos=" << foundpos << endl; st.pts[k] = foundpos; } if ( (st.pts[0] == st.pts[1]) || (st.pts[0] == st.pts[2]) || (st.pts[1] == st.pts[2]) ) { (*mycout) << "ERROR: STL Triangle degenerated" << endl; } else { // do not add ? js AddTriangle(st); } //(*mycout) << "TRIG" << i << " = " << st << endl; } //normal the normals for (i = 1; i <= GetNP(); i++) { SetNormal(i,1./(double)normal_cnt[i]*GetNormal(i)); } trigsconverted = 1; vicinity.SetSize(GetNT()); markedtrigs.SetSize(GetNT()); for (i = 1; i <= GetNT(); i++) { markedtrigs.Elem(i) = 0; vicinity.Elem(i) = 1; } ha_points.SetSize(GetNP()); for (i = 1; i <= GetNP(); i++) ha_points.Elem(i) = 0; calcedgedataanglesnew = 0; edgedatastored = 0; edgedata->Clear(); CalcEdgeData(); CalcEdgeDataAngles(); ClearLineEndPoints(); (*mycout) << "done" << endl; } */ void STLGeometry :: SetLineEndPoint(int pn) { if (pn <1 || pn > lineendpoints.Size()) {PrintSysError("Illegal pnum in SetLineEndPoint!!!"); return; } lineendpoints.Elem(pn) = 1; } int STLGeometry :: IsLineEndPoint(int pn) { // return 0; if (pn <1 || pn > lineendpoints.Size()) {PrintSysError("Illegal pnum in IsLineEndPoint!!!"); return 0;} return lineendpoints.Get(pn); } void STLGeometry :: ClearLineEndPoints() { lineendpoints.SetSize(GetNP()); int i; for (i = 1; i <= GetNP(); i++) { lineendpoints.Elem(i) = 0; } } int STLGeometry :: IsEdge(int ap1, int ap2) { int i,j; for (i = 1; i <= GetNEPP(ap1); i++) { for (j = 1; j <= GetNEPP(ap2); j++) { if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return 1;} } } return 0; } int STLGeometry :: IsEdgeNum(int ap1, int ap2) { int i,j; for (i = 1; i <= GetNEPP(ap1); i++) { for (j = 1; j <= GetNEPP(ap2); j++) { if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return GetEdgePP(ap1,i);} } } return 0; } void STLGeometry :: BuildEdges() { //PrintFnStart("build edges"); edges.SetSize(0); meshlines.SetSize(0); FindEdgesFromAngles(); } void STLGeometry :: UseExternalEdges() { for (int i = 1; i <= NOExternalEdges(); i++) AddEdge(GetExternalEdge(i).i1,GetExternalEdge(i).i2); //BuildEdgesPerPointy(); } void STLGeometry :: UndoEdgeChange() { if (edgedatastored) { RestoreEdgeData(); } else { PrintWarning("no edge undo possible"); } } void STLGeometry :: StoreEdgeData() { // edgedata_store = *edgedata; edgedata->Store(); edgedatastored = 1; // put stlgeom-edgedata to stltopology edgedata /* int i; for (i = 1; i <= GetNTE(); i++) { const STLTopEdge & topedge = GetTopEdge (i); int ednum = edgedata->GetEdgeNum (topedge.PNum(1), topedge.PNum(2)); topedges.Elem(i).SetStatus (edgedata->Get (ednum).status); } */ } void STLGeometry :: RestoreEdgeData() { // *edgedata = edgedata_store; edgedata->Restore(); edgedatastored=0; } void STLGeometry :: CalcEdgeData() { PushStatus("Calc Edge Data"); int np1, np2; int ecnt = 0; edgedata->SetSize(GetNT()/2*3); for (int i = 1; i <= GetNT(); i++) { SetThreadPercent((double)i/(double)GetNT()*100.); const STLTriangle & t1 = GetTriangle(i); for (int j = 1; j <= NONeighbourTrigs(i); j++) { int nbti = NeighbourTrig(i,j); if (nbti > i) { const STLTriangle & t2 = GetTriangle(nbti); if (t1.IsNeighbourFrom(t2)) { ecnt++; if (ecnt > edgedata->Size()) {PrintError("In Calc edge data, illegal geometry");} t1.GetNeighbourPoints(t2,np1,np2); /* ang = GetAngle(i,nbti); if (ang < -M_PI) {ang += 2*M_PI;}*/ // edgedata->Add(STLEdgeData(0, np1, np2, i, nbti),ecnt); edgedata->Elem(ecnt).SetStatus(ED_UNDEFINED); // edgedata->Elem(ecnt).top = this; // edgedata->Elem(ecnt).topedgenr = GetTopEdgeNum (np1, np2); } } } } //BuildEdgesPerPoint(); PopStatus(); } void STLGeometry :: CalcEdgeDataAngles() { PrintMessageCR (5,"calc edge data angles ... "); for (int i = 1; i <= GetNTE(); i++) { STLTopEdge & edge = GetTopEdge (i); double cosang = GetTriangle(edge.TrigNum(1)).Normal() * GetTriangle(edge.TrigNum(2)).Normal(); edge.SetCosAngle (cosang); } for (int i = 1; i <= edgedata->Size(); i++) { /* const STLEdgeData& e = edgedata->Get(i); ang = GetAngle(e.lt,e.rt); if (ang < -M_PI) {ang += 2*M_PI;} edgedata->Elem(i).angle = fabs(ang); */ } PrintMessage (5,"calc edge data angles ... done"); } void STLGeometry :: FindEdgesFromAngles() { // PrintFnStart("find edges from angles"); double min_edge_angle = stlparam.yangle/180.*M_PI; double cont_min_edge_angle = stlparam.contyangle/180.*M_PI; double cos_min_edge_angle = cos (min_edge_angle); double cos_cont_min_edge_angle = cos (cont_min_edge_angle); if (calcedgedataanglesnew) {CalcEdgeDataAngles(); calcedgedataanglesnew = 0;} for (int i = 1; i <= edgedata->Size(); i++) { STLTopEdge & sed = edgedata->Elem(i); if (sed.GetStatus() == ED_CANDIDATE || sed.GetStatus() == ED_UNDEFINED) { if (sed.CosAngle() <= cos_min_edge_angle) { sed.SetStatus (ED_CANDIDATE); } else { sed.SetStatus(ED_UNDEFINED); } } } if (stlparam.contyangle < stlparam.yangle) { int changed = 1; int its = 0; while (changed && stlparam.contyangle < stlparam.yangle) { its++; //(*mycout) << "." << flush; changed = 0; for (int i = 1; i <= edgedata->Size(); i++) { STLTopEdge & sed = edgedata->Elem(i); if (sed.CosAngle() <= cos_cont_min_edge_angle && sed.GetStatus() == ED_UNDEFINED && (edgedata->GetNConfCandEPP(sed.PNum(1)) == 1 || edgedata->GetNConfCandEPP(sed.PNum(2)) == 1)) { changed = 1; sed.SetStatus (ED_CANDIDATE); } } } } int confcand = 0; if (edgedata->GetNConfEdges() == 0) { confcand = 1; } for (int i = 1; i <= edgedata->Size(); i++) { STLTopEdge & sed = edgedata->Elem(i); if (sed.GetStatus() == ED_CONFIRMED || (sed.GetStatus() == ED_CANDIDATE && confcand)) { STLEdge se(sed.PNum(1),sed.PNum(2)); se.SetLeftTrig(sed.TrigNum(1)); se.SetRightTrig(sed.TrigNum(2)); AddEdge(se); } } BuildEdgesPerPoint(); //(*mycout) << "its for continued angle = " << its << endl; PrintMessage(5,"built ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree"); } /* void STLGeometry :: FindEdgesFromAngles() { double yangle = stlparam.yangle; char * savetask = multithread.task; multithread.task = "find edges"; const double min_edge_angle = yangle/180.*M_PI; int np1, np2; double ang; int i; //(*mycout) << "area=" << Area() << endl; for (i = 1; i <= GetNT(); i++) { multithread.percent = (double)i/(double)GetReadNT()*100.; const STLTriangle & t1 = GetTriangle(i); //NeighbourTrigs(nt,i); for (int j = 1; j <= NONeighbourTrigs(i); j++) { int nbti = NeighbourTrig(i,j); if (nbti > i) { const STLTriangle & t2 = GetTriangle(nbti); if (t1.IsNeighbourFrom(t2)) { ang = GetAngle(i,nbti); if (ang < -M_PI*0.5) {ang += 2*M_PI;} t1.GetNeighbourPoints(t2,np1,np2); if (fabs(ang) >= min_edge_angle) { STLEdge se(np1,np2); se.SetLeftTrig(i); se.SetRightTrig(nbti); AddEdge(se); } } } } } (*mycout) << "added " << GetNE() << " edges" << endl; //BuildEdgesPerPoint(); multithread.percent = 100.; multithread.task = savetask; } */ void STLGeometry :: BuildEdgesPerPoint() { //cout << "*** build edges per point" << endl; edgesperpoint.SetSize(GetNP()); //add edges to points for (int i = 1; i <= GetNE(); i++) { //(*mycout) << "EDGE " << GetEdge(i).PNum(1) << " - " << GetEdge(i).PNum(2) << endl; for (int j = 1; j <= 2; j++) { AddEdgePP(GetEdge(i).PNum(j),i); } } } void STLGeometry :: AddFaceEdges() { PrintFnStart("Add starting edges for faces"); //für Kugel eine STLLine hinzufügen (Vorteil: verfeinerbar, unabhängig von Auflösung der Geometrie!!!): //Grenze von 1. gefundener chart Array edgecnt; Array chartindex; edgecnt.SetSize(GetNOFaces()); chartindex.SetSize(GetNOFaces()); for (int i = 1; i <= GetNOFaces(); i++) { edgecnt.Elem(i) = 0; chartindex.Elem(i) = 0; } for (int i = 1; i <= GetNT(); i++) { int fn = GetTriangle(i).GetFaceNum(); if (!chartindex.Get(fn)) {chartindex.Elem(fn) = GetChartNr(i);} for (int j = 1; j <= 3; j++) { edgecnt.Elem(fn) += GetNEPP(GetTriangle(i).PNum(j)); } } for (int i = 1; i <= GetNOFaces(); i++) { if (!edgecnt.Get(i)) {PrintMessage(5,"Face", i, " has no edge!");} } int changed = 0; int ap1, ap2; for (int i = 1; i <= GetNOFaces(); i++) { if (!edgecnt.Get(i)) { const STLChart& c = GetChart(chartindex.Get(i)); // bool foundone = false; int longest_ap1 = -1, longest_ap2 = -1; double maxlen = -1; for (int j = 1; j <= c.GetNChartT(); j++) { const STLTriangle& t1 = GetTriangle(c.GetChartTrig(j)); for (int k = 1; k <= 3; k++) { int nt = NeighbourTrig(c.GetChartTrig(j),k); if (GetChartNr(nt) != chartindex.Get(i)) { t1.GetNeighbourPoints(GetTriangle(nt),ap1,ap2); // AddEdge(ap1,ap2); double len = Dist(GetPoint(ap1), GetPoint(ap2)); if (len > maxlen) { maxlen = len; longest_ap1 = ap1; longest_ap2 = ap2; } changed = 1; } } } if (maxlen > 0) AddEdge(longest_ap1,longest_ap2); } } if (changed) BuildEdgesPerPoint(); } void STLGeometry :: LinkEdges() { PushStatusF("Link Edges"); PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree"); int i; lines.SetSize(0); int starte(0); int edgecnt = 0; int found; int rev(0); //indicates, that edge is inserted reverse //worked edges Array we(GetNE()); //setlineendpoints; wenn 180°, dann keine endpunkte //nur punkte mit 2 edges kommen in frage, da bei mehr oder weniger punkten ohnehin ein meshpoint hinkommt Vec3d v1,v2; double cos_eca = cos(stlparam.edgecornerangle/180.*M_PI); int ecnt = 0; int lp1, lp2; if (stlparam.edgecornerangle < 180) { for (i = 1; i <= GetNP(); i++) { if (GetNEPP(i) == 2) { if (GetEdge(GetEdgePP(i,1)).PNum(2) == GetEdge(GetEdgePP(i,2)).PNum(1) || GetEdge(GetEdgePP(i,1)).PNum(1) == GetEdge(GetEdgePP(i,2)).PNum(2)) { lp1 = 1; lp2 = 2; } else { lp1 = 2; lp2 = 1; } v1 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,1)).PNum(1)), GetPoint(GetEdge(GetEdgePP(i,1)).PNum(2))); v2 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp1)), GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp2))); if ((v1*v2)/sqrt(v1.Length2()*v2.Length2()) < cos_eca) { //(*testout) << "add edgepoint " << i << endl; SetLineEndPoint(i); ecnt++; } } } } PrintMessage(5, "added ", ecnt, " mesh_points due to edge corner angle (", stlparam.edgecornerangle, " degree)"); for (i = 1; i <= GetNE(); i++) {we.Elem(i) = 0;} while(edgecnt < GetNE()) { SetThreadPercent((double)edgecnt/(double)GetNE()*100.); STLLine* line = new STLLine(this); //find start edge int j = 1; found = 0; //try second time, if only rings are left!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! int second = 0; //find a starting edge at point with 1 or more than 2 edges or at lineendpoint while (!found && j<=GetNE()) { if (!we.Get(j)) { if (GetNEPP(GetEdge(j).PNum(1)) != 2 || IsLineEndPoint(GetEdge(j).PNum(1))) { starte = j; found = 1; rev = 0; } else if (GetNEPP(GetEdge(j).PNum(2)) != 2 || IsLineEndPoint(GetEdge(j).PNum(2))) { starte = j; found = 1; rev = 1; } else if (second) { starte = j; found = 1; rev = 0; //0 or 1 are possible } } j++; if (!second && j == GetNE()) {second = 1; j = 1;} } if (!found) {PrintSysError("No starting edge found, edgecnt=", edgecnt, ", GETNE=", GetNE());} line->AddPoint(GetEdge(starte).PNum(1+rev)); line->AddPoint(GetEdge(starte).PNum(2-rev)); if (!rev) { line->AddLeftTrig(GetEdge(starte).LeftTrig()); line->AddRightTrig(GetEdge(starte).RightTrig()); } else { line->AddLeftTrig(GetEdge(starte).RightTrig()); line->AddRightTrig(GetEdge(starte).LeftTrig()); } edgecnt++; we.Elem(starte) = 1; //add segments to line as long as segments other than starting edge are found or lineendpoint is reached found = 1; int other; while(found) { found = 0; int fp = GetEdge(starte).PNum(2-rev); if (GetNEPP(fp) == 2 && !IsLineEndPoint(fp)) { //find the "other" edge of point fp other = 0; if (GetEdgePP(fp,1) == starte) {other = 1;} starte = GetEdgePP(fp,1+other); //falls ring -> aufhoeren !!!!!!!!!!! if (!we.Elem(starte)) { found = 1; rev = 0; if (GetEdge(starte).PNum(2) == fp) {rev = 1;} else if (GetEdge(starte).PNum(1) != fp) {PrintSysError("In Link Edges!");} line->AddPoint(GetEdge(starte).PNum(2-rev)); if (!rev) { line->AddLeftTrig(GetEdge(starte).LeftTrig()); line->AddRightTrig(GetEdge(starte).RightTrig()); } else { line->AddLeftTrig(GetEdge(starte).RightTrig()); line->AddRightTrig(GetEdge(starte).LeftTrig()); } edgecnt++; we.Elem(starte) = 1; } } } AddLine(line); } PrintMessage(5,"number of lines generated = ", GetNLines()); //check, which lines must have at least one midpoint INDEX_2_HASHTABLE lineht(GetNLines()+1); for (i = 1; i <= GetNLines(); i++) { if (GetLine(i)->StartP() == GetLine(i)->EndP()) { GetLine(i)->DoSplit(); } } for (i = 1; i <= GetNLines(); i++) { INDEX_2 lineep (GetLine(i)->StartP(),GetLine(i)->EndP()); lineep.Sort(); if (lineht.Used (lineep)) { GetLine(i)->DoSplit(); int other = lineht.Get(lineep); GetLine(other)->DoSplit(); } else { lineht.Set (lineep, i); } } for (i = 1; i <= GetNLines(); i++) { STLLine* line = GetLine(i); for (int ii = 1; ii <= line->GetNS(); ii++) { int ap1, ap2; line->GetSeg(ii,ap1,ap2); // (*mycout) << "SEG " << p1 << " - " << p2 << endl; } } PopStatus(); } int STLGeometry :: GetNOBodys() { int markedtrigs1 = 0; int starttrig = 1; int i, k, nnt; int bodycnt = 0; Array bodynum(GetNT()); for (i = 1; i <= GetNT(); i++) bodynum.Elem(i)=0; while (markedtrigs1 < GetNT()) { for (i = starttrig; i <= GetNT(); i++) { if (!bodynum.Get(i)) { starttrig = i; break; } } //add all triangles around starttriangle, which is reachable without going over an edge Array todolist; Array nextlist; bodycnt++; markedtrigs1++; bodynum.Elem(starttrig) = bodycnt; todolist.Append(starttrig); while(todolist.Size()) { for (i = 1; i <= todolist.Size(); i++) { //const STLTriangle& tt = GetTriangle(todolist.Get(i)); for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++) { nnt = NeighbourTrig(todolist.Get(i),k); if (!bodynum.Get(nnt)) { nextlist.Append(nnt); bodynum.Elem(nnt) = bodycnt; markedtrigs1++; } } } todolist.SetSize(0); for (i = 1; i <= nextlist.Size(); i++) { todolist.Append(nextlist.Get(i)); } nextlist.SetSize(0); } } PrintMessage(3, "Geometry has ", bodycnt, " separated bodys"); return bodycnt; } void STLGeometry :: CalcFaceNums() { int markedtrigs1 = 0; int starttrig(0); int laststarttrig = 1; int i, k, nnt; facecnt = 0; for (i = 1; i <= GetNT(); i++) GetTriangle(i).SetFaceNum(0); while (markedtrigs1 < GetNT()) { for (i = laststarttrig; i <= GetNT(); i++) { if (!GetTriangle(i).GetFaceNum()) { starttrig = i; laststarttrig = i; break; } } //add all triangles around starttriangle, which is reachable without going over an edge Array todolist; Array nextlist; facecnt++; markedtrigs1++; GetTriangle(starttrig).SetFaceNum(facecnt); todolist.Append(starttrig); int ap1, ap2; while(todolist.Size()) { for (i = 1; i <= todolist.Size(); i++) { const STLTriangle& tt = GetTriangle(todolist.Get(i)); for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++) { nnt = NeighbourTrig(todolist.Get(i),k); STLTriangle& nt = GetTriangle(nnt); if (!nt.GetFaceNum()) { tt.GetNeighbourPoints(nt,ap1,ap2); if (!IsEdge(ap1,ap2)) { nextlist.Append(nnt); nt.SetFaceNum(facecnt); markedtrigs1++; } } } } todolist.SetSize(0); for (i = 1; i <= nextlist.Size(); i++) { todolist.Append(nextlist.Get(i)); } nextlist.SetSize(0); } } GetNOBodys(); PrintMessage(3,"generated ", facecnt, " faces"); } void STLGeometry :: ClearSpiralPoints() { spiralpoints.SetSize(GetNP()); int i; for (i = 1; i <= spiralpoints.Size(); i++) { spiralpoints.Elem(i) = 0; } } void STLGeometry :: BuildSmoothEdges () { if (smoothedges) delete smoothedges; smoothedges = new INDEX_2_HASHTABLE (GetNE()/10 + 1); // Jack: Ok ? // UseExternalEdges(); PushStatusF("Build Smooth Edges"); int nt = GetNT(); Vec3d ng1, ng2; for (int i = 1; i <= nt; i++) { if (multithread.terminate) {PopStatus();return;} SetThreadPercent(100.0 * (double)i / (double)nt); const STLTriangle & trig = GetTriangle (i); ng1 = trig.GeomNormal(points); ng1 /= (ng1.Length() + 1e-24); for (int j = 1; j <= 3; j++) { int nbt = NeighbourTrig (i, j); ng2 = GetTriangle(nbt).GeomNormal(points); ng2 /= (ng2.Length() + 1e-24); int pi1, pi2; trig.GetNeighbourPoints(GetTriangle(nbt), pi1, pi2); if (!IsEdge(pi1,pi2)) { if (ng1 * ng2 < 0) { PrintMessage(7,"smoothedge found"); INDEX_2 i2(pi1, pi2); i2.Sort(); smoothedges->Set (i2, 1); } } } } PopStatus(); } int STLGeometry :: IsSmoothEdge (int pi1, int pi2) const { if (!smoothedges) return 0; INDEX_2 i2(pi1, pi2); i2.Sort(); return smoothedges->Used (i2); } /* //function is not used now int IsInArray(int n, const Array& ia) { int i; for (i = 1; i <= ia.Size(); i++) { if (ia.Get(i) == n) {return 1;} } return 0; } */ void STLGeometry :: AddConeAndSpiralEdges() { PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree"); PrintFnStart("AddConeAndSpiralEdges"); int i,j,k,n; // int changed = 0; //check edges, where inner chart and no outer chart come together without an edge int np1, np2, nt; int cnt = 0; for (i = 1; i <= GetNOCharts(); i++) { STLChart& chart = GetChart(i); for (j = 1; j <= chart.GetNChartT(); j++) { int t = chart.GetChartTrig(j); const STLTriangle& tt = GetTriangle(t); for (k = 1; k <= 3; k++) { nt = NeighbourTrig(t,k); if (GetChartNr(nt) != i && !TrigIsInOC(nt,i)) { tt.GetNeighbourPoints(GetTriangle(nt),np1,np2); if (!IsEdge(np1,np2)) { STLEdge se(np1,np2); se.SetLeftTrig(t); se.SetRightTrig(nt); int edgenum = AddEdge(se); AddEdgePP(np1,edgenum); AddEdgePP(np2,edgenum); //changed = 1; PrintWarning("Found a spiral like structure: chart=", i, ", trig=", t, ", p1=", np1, ", p2=", np2); cnt++; } } } } } PrintMessage(5, "found ", cnt, " spiral like structures"); PrintMessage(5, "added ", cnt, " edges due to spiral like structures"); cnt = 0; int edgecnt = 0; Array trigsaroundp; Array chartpointchecked; //gets number of chart, if in this chart already checked chartpointchecked.SetSize(GetNP()); for (i = 1; i <= GetNP(); i++) { chartpointchecked.Elem(i) = 0; } int onoc, notonoc, tpp, pn; int ap1, ap2, tn1, tn2, l, problem; if (!stldoctor.conecheck) {PrintWarning("++++++++++++ \ncone checking deactivated by user!!!!!\n+++++++++++++++"); return ;} PushStatus("Find Critical Points"); int addedges = 0; for (i = 1; i <= GetNOCharts(); i++) { SetThreadPercent((double)i/(double)GetNOCharts()*100.); if (multithread.terminate) {PopStatus();return;} STLChart& chart = GetChart(i); for (j = 1; j <= chart.GetNChartT(); j++) { int t = chart.GetChartTrig(j); const STLTriangle& tt = GetTriangle(t); for (k = 1; k <= 3; k++) { pn = tt.PNum(k); if (chartpointchecked.Get(pn) == i) {continue;} int checkpoint = 0; for (n = 1; n <= trigsperpoint.EntrySize(pn); n++) { if (trigsperpoint.Get(pn,n) != t && GetChartNr(trigsperpoint.Get(pn,n)) != i && !TrigIsInOC(trigsperpoint.Get(pn,n),i)) {checkpoint = 1;}; } if (checkpoint) { chartpointchecked.Elem(pn) = i; int worked = 0; int spworked = 0; GetSortedTrianglesAroundPoint(pn,t,trigsaroundp); trigsaroundp.Append(t); problem = 0; for (l = 2; l <= trigsaroundp.Size()-1; l++) { tn1 = trigsaroundp.Get(l-1); tn2 = trigsaroundp.Get(l); const STLTriangle& t1 = GetTriangle(tn1); const STLTriangle& t2 = GetTriangle(tn2); t1.GetNeighbourPoints(t2, ap1, ap2); if (IsEdge(ap1,ap2)) break; if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;} } if (problem) { for (l = 2; l <= trigsaroundp.Size()-1; l++) { tn1 = trigsaroundp.Get(l-1); tn2 = trigsaroundp.Get(l); const STLTriangle& t1 = GetTriangle(tn1); const STLTriangle& t2 = GetTriangle(tn2); t1.GetNeighbourPoints(t2, ap1, ap2); if (IsEdge(ap1,ap2)) break; if ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) || (GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i))) { if (addedges || !GetNEPP(pn)) { STLEdge se(ap1,ap2); se.SetLeftTrig(tn1); se.SetRightTrig(tn2); int edgenum = AddEdge(se); AddEdgePP(ap1,edgenum); AddEdgePP(ap2,edgenum); edgecnt++; } if (!addedges && !GetSpiralPoint(pn)) { SetSpiralPoint(pn); spworked = 1; } worked = 1; } } } //backwards: problem = 0; for (l = trigsaroundp.Size()-1; l >= 2; l--) { tn1 = trigsaroundp.Get(l+1); tn2 = trigsaroundp.Get(l); const STLTriangle& t1 = GetTriangle(tn1); const STLTriangle& t2 = GetTriangle(tn2); t1.GetNeighbourPoints(t2, ap1, ap2); if (IsEdge(ap1,ap2)) break; if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;} } if (problem) for (l = trigsaroundp.Size()-1; l >= 2; l--) { tn1 = trigsaroundp.Get(l+1); tn2 = trigsaroundp.Get(l); const STLTriangle& t1 = GetTriangle(tn1); const STLTriangle& t2 = GetTriangle(tn2); t1.GetNeighbourPoints(t2, ap1, ap2); if (IsEdge(ap1,ap2)) break; if ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) || (GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i))) { if (addedges || !GetNEPP(pn)) { STLEdge se(ap1,ap2); se.SetLeftTrig(tn1); se.SetRightTrig(tn2); int edgenum = AddEdge(se); AddEdgePP(ap1,edgenum); AddEdgePP(ap2,edgenum); edgecnt++; } if (!addedges && !GetSpiralPoint(pn)) { SetSpiralPoint(pn); spworked = 1; //if (GetNEPP(pn) == 0) {(*mycout) << "ERROR: spiralpoint with no edge found!" << endl;} } worked = 1; } } if (worked) { //(*testout) << "set edgepoint due to spirals: pn=" << i << endl; SetLineEndPoint(pn); } if (spworked) { /* (*mycout) << "Warning: Critical Point " << tt.PNum(k) << "( chart " << i << ", trig " << t << ") has been neutralized!!!" << endl; */ cnt++; } // markedpoints.Elem(tt.PNum(k)) = 1; } } } } PrintMessage(5, "found ", cnt, " critical points!"); PrintMessage(5, "added ", edgecnt, " edges due to critical points!"); PopStatus(); //search points where inner chart and outer chart and "no chart" trig come together at edge-point PrintMessage(7,"search for special chart points"); for (i = 1; i <= GetNOCharts(); i++) { STLChart& chart = GetChart(i); for (j = 1; j <= chart.GetNChartT(); j++) { int t = chart.GetChartTrig(j); const STLTriangle& tt = GetTriangle(t); for (k = 1; k <= 3; k++) { pn = tt.PNum(k); if (GetNEPP(pn) == 2) { onoc = 0; notonoc = 0; for (n = 1; n <= trigsperpoint.EntrySize(pn); n++) { tpp = trigsperpoint.Get(pn,n); if (tpp != t && GetChartNr(tpp) != i) { if (TrigIsInOC(tpp,i)) {onoc = 1;} if (!TrigIsInOC(tpp,i)) {notonoc = 1;} } } if (onoc && notonoc && !IsLineEndPoint(pn)) { GetSortedTrianglesAroundPoint(pn,t,trigsaroundp); int here = 1; //we start on this side of edge, !here = there int thereOC = 0; int thereNotOC = 0; for (l = 2; l <= trigsaroundp.Size(); l++) { GetTriangle(trigsaroundp.Get(l-1)). GetNeighbourPoints(GetTriangle(trigsaroundp.Get(l)), ap1, ap2); if (IsEdge(ap1,ap2)) {here = (here+1)%2;} if (!here && TrigIsInOC(trigsaroundp.Get(l),i)) {thereOC = 1;} if (!here && !TrigIsInOC(trigsaroundp.Get(l),i)) {thereNotOC = 1;} } if (thereOC && thereNotOC) { //(*mycout) << "Special OCICnotC - point " << pn << " found!" << endl; //(*testout) << "set edgepoint due to spirals: pn=" << i << endl; SetLineEndPoint(pn); } } } } } } PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree"); } //get trigs at a point, started with starttrig, then every left void STLGeometry :: GetSortedTrianglesAroundPoint(int p, int starttrig, Array& trigs) { int acttrig = starttrig; trigs.SetAllocSize(trigsperpoint.EntrySize(p)); trigs.SetSize(0); trigs.Append(acttrig); int i, j, t, ap1, ap2, locindex1(0), locindex2(0); //(*mycout) << "trigs around point " << p << endl; int end = 0; while (!end) { const STLTriangle& at = GetTriangle(acttrig); for (i = 1; i <= trigsperpoint.EntrySize(p); i++) { t = trigsperpoint.Get(p,i); const STLTriangle& nt = GetTriangle(t); if (at.IsNeighbourFrom(nt)) { at.GetNeighbourPoints(nt, ap1, ap2); if (ap2 == p) {Swap(ap1,ap2);} if (ap1 != p) {PrintSysError("In GetSortedTrianglesAroundPoint!!!");} for (j = 1; j <= 3; j++) { if (at.PNum(j) == ap1) {locindex1 = j;}; if (at.PNum(j) == ap2) {locindex2 = j;}; } if ((locindex2+1)%3+1 == locindex1) { if (t != starttrig) { trigs.Append(t); // (*mycout) << "trig " << t << endl; acttrig = t; } else { end = 1; } break; } } } } } /* int STLGeometry :: NeighbourTrig(int trig, int nr) const { return neighbourtrigs.Get(trig,nr); } */ void STLGeometry :: SmoothGeometry () { int i, j, k; double maxerr0, maxerr; for (i = 1; i <= GetNP(); i++) { if (GetNEPP(i)) continue; maxerr0 = 0; for (j = 1; j <= NOTrigsPerPoint(i); j++) { int tnum = TrigPerPoint(i, j); double err = Angle (GetTriangle(tnum).Normal (), GetTriangle(tnum).GeomNormal(GetPoints())); if (err > maxerr0) maxerr0 = err; } Point3d pi = GetPoint (i); if (maxerr0 < 1.1) continue; // about 60 degree maxerr0 /= 2; // should be at least halfen for (k = 1; k <= NOTrigsPerPoint(i); k++) { const STLTriangle & trig = GetTriangle (TrigPerPoint (i, k)); Point3d c = Center(GetPoint (trig.PNum(1)), GetPoint (trig.PNum(2)), GetPoint (trig.PNum(3))); Point3d np = pi + 0.1 * (c - pi); SetPoint (i, np); maxerr = 0; for (j = 1; j <= NOTrigsPerPoint(i); j++) { int tnum = TrigPerPoint(i, j); double err = Angle (GetTriangle(tnum).Normal (), GetTriangle(tnum).GeomNormal(GetPoints())); if (err > maxerr) maxerr = err; } if (maxerr < maxerr0) { pi = np; } } SetPoint (i, pi); } } class STLGeometryRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const; }; NetgenGeometry * STLGeometryRegister :: Load (string filename) const { const char * cfilename = filename.c_str(); if (strcmp (&cfilename[strlen(cfilename)-3], "stl") == 0) { PrintMessage (1, "Load STL geometry file ", cfilename); ifstream infile(cfilename); STLGeometry * hgeom = STLGeometry :: Load (infile); hgeom -> edgesfound = 0; return hgeom; } else if (strcmp (&cfilename[strlen(cfilename)-4], "stlb") == 0) { PrintMessage (1, "Load STL binary geometry file ", cfilename); ifstream infile(cfilename); STLGeometry * hgeom = STLGeometry :: LoadBinary (infile); hgeom -> edgesfound = 0; return hgeom; } else if (strcmp (&cfilename[strlen(cfilename)-3], "nao") == 0) { PrintMessage (1, "Load naomi (F. Kickinger) geometry file ", cfilename); ifstream infile(cfilename); STLGeometry * hgeom = STLGeometry :: LoadNaomi (infile); hgeom -> edgesfound = 0; return hgeom; } return NULL; } class STLInit { public: STLInit() { geometryregister.Append (new STLGeometryRegister); } }; STLInit stlinit; static RegisterClassForArchive stlgeo; } netgen-6.2.1905/libsrc/stlgeom/stltool.hpp0000644000175000017500000001746613504650527017160 0ustar kurtkurt#ifndef FILE_STLTOOL #define FILE_STLTOOL //#include "gprim/gprim.hh" /**************************************************************************/ /* File: stlgeom.hh */ /* Author: Joachim Schoeberl */ /* Author2: Johannes Gerstmayr */ /* Date: 20. Nov. 99 */ /**************************************************************************/ // use one normal vector for whole chart extern int usechartnormal; extern int chartdebug; extern int geomsearchtreeon; extern int AddPointIfNotExists(Array& ap, const Point3d& p, double eps = 1e-8); //get distance from line lp1-lp2 to point p extern double GetDistFromLine(const Point<3>& lp1, const Point<3>& lp2, Point<3>& p); extern double GetDistFromInfiniteLine(const Point<3>& lp1, const Point<3>& lp2, const Point<3>& p); extern void FIOReadInt(istream& ios, int& i); extern void FIOWriteInt(ostream& ios, const int& i); extern void FIOReadDouble(istream& ios, double& i); extern void FIOWriteDouble(ostream& ios, const double& i); extern void FIOReadFloat(istream& ios, float& i); extern void FIOWriteFloat(ostream& ios, const float& i); extern void FIOReadString(istream& ios, char* str, int len); extern void FIOReadStringE(istream& ios, char* str, int len); extern void FIOWriteString(ostream& ios, char* str, int len); typedef Array * ArrayINTPTR; class STLGeometry; class STLChart { private: STLGeometry * geometry; Array charttrigs; // trigs which only belong to this chart Array outertrigs; // trigs which belong to other charts BoxTree<3> * searchtree; // ADT containing outer trigs Array olimit; //outer limit of outer chart Array ilimit; //outer limit of inner chart public: STLChart(STLGeometry * ageometry); ~STLChart(); void AddChartTrig(int i); void AddOuterTrig(int i); int IsInWholeChart(int nr) const; int GetChartTrig(int i) const {return charttrigs.Get(i);} int GetOuterTrig(int i) const {return outertrigs.Get(i);} //get all trigs: int GetTrig(int i) const { if (i <= charttrigs.Size()) {return charttrigs.Get(i);} else {return outertrigs.Get(i-charttrigs.Size());} } int GetNChartT() const {return charttrigs.Size();} int GetNOuterT() const {return outertrigs.Size();} int GetNT() const {return charttrigs.Size()+outertrigs.Size(); } void GetTrianglesInBox (const Point3d & pmin, const Point3d & pmax, Array & trias) const; void AddOLimit(twoint l) {olimit.Append(l);} void AddILimit(twoint l) {ilimit.Append(l);} void ClearOLimit() {olimit.SetSize(0);} void ClearILimit() {ilimit.SetSize(0);} int GetNOLimit() const {return olimit.Size();} int GetNILimit() const {return ilimit.Size();} twoint GetOLimit(int i) const {return olimit.Get(i);} twoint GetILimit(int i) const {return ilimit.Get(i);} //move triangles trigs (local chart-trig numbers) to outer chart void MoveToOuterChart(const Array& trigs); void DelChartTrigs(const Array& trigs); // define local coordinate system, JS: private: Vec<3> normal; Point<3> pref; Vec<3> t1, t2; public: void SetNormal (const Point<3> & apref, const Vec<3> & anormal); const Vec<3> & GetNormal () const { return normal; } Point<2> Project2d (const Point<3> & p3d) const { Vec<3> v = p3d-pref; return Point<2> (t1 * v, t2 * v); } }; class STLBoundarySeg { Point<3> p1, p2, center; Point<2> p2d1, p2d2; Box<2> boundingbox; // Point<2> p2dmin, p2dmax; double rad; int i1, i2; int smoothedge; public: STLBoundarySeg () { ; } STLBoundarySeg (int ai1, int ai2, const Array > & points, const STLChart * chart) : p1(points.Get(ai1)), p2(points.Get(ai2)), i1(ai1), i2(ai2) { center = ::netgen::Center (p1, p2); rad = Dist (p1, center); p2d1 = chart->Project2d (p1); p2d2 = chart->Project2d (p2); boundingbox.Set (p2d1); boundingbox.Add (p2d2); } int operator== (const STLBoundarySeg & s2) const { return i1 == s2.i1 && i2 == s2.i2; } void Swap (); int I1() const { return i1; } int I2() const { return i2; } const Point<3> & P1() const { return p1; } const Point<3> & P2() const { return p2; } const Point<2> & P2D1() const { return p2d1; } const Point<2> & P2D2() const { return p2d2; } const Point<2> & P2DMin() const { return boundingbox.PMin(); } const Point<2> & P2DMax() const { return boundingbox.PMax(); } const Point<3> & Center() const { return center; } const Box<2> & BoundingBox() const { return boundingbox; } double Radius () const { return rad; } void SetSmoothEdge (int se) { smoothedge = se; } int IsSmoothEdge () const { return smoothedge; } friend class STLBoundary; }; class STLBoundary { private: STLGeometry * geometry; const STLChart * chart; Array boundary; ClosedHashTable boundary_ht; BoxTree<2,INDEX_2> * searchtree = nullptr; public: STLBoundary(STLGeometry * ageometry); ~STLBoundary() { delete searchtree; } void Clear() {boundary.SetSize(0); boundary_ht = ClosedHashTable(); } void SetChart (const STLChart * achart) { chart = achart; } //don't check, if already exists! void AddNewSegment(const STLBoundarySeg & seg) {boundary.Append(seg);}; //check if segment exists void AddOrDelSegment(const STLBoundarySeg & seg); //addordelsegment for all 3 triangle segments! void AddTriangle(const STLTriangle & t); int NOSegments() {return boundary.Size();}; const STLBoundarySeg & GetSegment(int i) {return boundary.Get(i);} void BuildSearchTree(); void DeleteSearchTree(); int TestSeg(const Point<3> & p1, const Point<3> & p2, const Vec<3> & sn, double sinchartangle, int divisions, Array >& points, double eps); int TestSegChartNV(const Point3d& p1, const Point3d& p2, const Vec3d& sn); }; class STLDoctorParams { public: int drawmeshededges; double geom_tol_fact; double longlinefact; int showexcluded; int selectmode; //0==trig, 1==edge, 2==point, 3==multiedge, 4==line cluster int edgeselectmode; int useexternaledges; int showfaces; int showedgecornerpoints; int showtouchedtrigchart; int conecheck; int spiralcheck; int selecttrig; int nodeofseltrig; int selectwithmouse; int showmarkedtrigs; double dirtytrigfact; double smoothangle; double smoothnormalsweight; int showvicinity; int vicinity; /// STLDoctorParams(); /// void Print (ostream & ost) const; }; DLL_HEADER extern STLDoctorParams stldoctor; class STLParameters { public: /// angle for edge detection double yangle; double contyangle; //edges continued with contyangle /// angle of geometry edge at which the mesher should set a point double edgecornerangle; /// angle inside on chart double chartangle; /// angle for overlapping parts of char double outerchartangle; /// 0 .. no, 1 .. local, (2 .. global) int usesearchtree; /// double resthatlasfac; int resthatlasenable; double atlasminh; double resthsurfcurvfac; int resthsurfcurvenable; double resthchartdistfac; int resthchartdistenable; double resthcloseedgefac; int resthcloseedgeenable; double resthedgeanglefac; int resthedgeangleenable; double resthsurfmeshcurvfac; int resthsurfmeshcurvenable; double resthlinelengthfac; int resthlinelengthenable; /// int recalc_h_opt; /// STLParameters(); /// void Print (ostream & ost) const; }; DLL_HEADER extern STLParameters stlparam; void STLMeshing (STLGeometry & geom, class Mesh & mesh); int STLSurfaceMeshing (STLGeometry & geom, class Mesh & mesh); void STLSurfaceOptimization (STLGeometry & geom, class Mesh & mesh, class MeshingParameters & mparam); #endif netgen-6.2.1905/libsrc/stlgeom/vsstl.hpp0000644000175000017500000000252713504650527016623 0ustar kurtkurt#ifndef FILE_VSSTL #define FILE_VSSTL /**************************************************************************/ /* File: vsstl.hpp */ /* Author: Joachim Schoeberl */ /* Date: 05. Jan. 2011 */ /**************************************************************************/ namespace netgen { class VisualSceneSTLGeometry : public VisualScene { Array trilists; class STLGeometry * stlgeometry; public: DLL_HEADER VisualSceneSTLGeometry (); DLL_HEADER virtual ~VisualSceneSTLGeometry (); DLL_HEADER void SetGeometry (class STLGeometry * astlgeometry) { stlgeometry = astlgeometry; } DLL_HEADER virtual void BuildScene (int zoomall = 0); DLL_HEADER virtual void DrawScene (); }; class VisualSceneSTLMeshing : public VisualScene { Array trilists; int selecttrig, nodeofseltrig; class STLGeometry * stlgeometry; public: DLL_HEADER VisualSceneSTLMeshing (); DLL_HEADER virtual ~VisualSceneSTLMeshing (); void SetGeometry (class STLGeometry * astlgeometry) { stlgeometry = astlgeometry; } virtual void BuildScene (int zoomall = 0); virtual void DrawScene (); virtual void MouseDblClick (int px, int py); int seltria; }; } #endif netgen-6.2.1905/libsrc/stlgeom/stlgeomchart.cpp0000644000175000017500000005467313504650527020150 0ustar kurtkurt//20.11.1999 third part of stlgeom.cc, functions with chart and atlas #include #include #include #include #include #include "stlgeom.hpp" namespace netgen { int chartdebug = 0; void STLGeometry :: MakeAtlas(Mesh & mesh) { // int timer1 = NgProfiler::CreateTimer ("makeatlas"); /* int timerb = NgProfiler::CreateTimer ("makeatlas - begin"); int timere = NgProfiler::CreateTimer ("makeatlas - end"); int timere1 = NgProfiler::CreateTimer ("makeatlas - end1"); int timere2 = NgProfiler::CreateTimer ("makeatlas - end2"); int timer2 = NgProfiler::CreateTimer ("makeatlas - part 2"); int timer3 = NgProfiler::CreateTimer ("makeatlas - part 3"); int timer4 = NgProfiler::CreateTimer ("makeatlas - part 4"); int timer4a = NgProfiler::CreateTimer ("makeatlas - part 4a"); int timer4b = NgProfiler::CreateTimer ("makeatlas - part 4b"); int timer4c = NgProfiler::CreateTimer ("makeatlas - part 4c"); int timer4d = NgProfiler::CreateTimer ("makeatlas - part 4d"); int timer4e = NgProfiler::CreateTimer ("makeatlas - part 4e"); int timer5 = NgProfiler::CreateTimer ("makeatlas - part 5"); int timer5a = NgProfiler::CreateTimer ("makeatlas - part 5a"); int timer5b = NgProfiler::CreateTimer ("makeatlas - part 5b"); int timer5cs = NgProfiler::CreateTimer ("makeatlas - part 5cs"); int timer5cl = NgProfiler::CreateTimer ("makeatlas - part 5cl"); */ PushStatusF("Make Atlas"); double h = mparam.maxh; double atlasminh = 5e-3 * Dist (boundingbox.PMin(), boundingbox.PMax()); PrintMessage(5, "atlasminh = ", atlasminh); //speedup for make atlas if (GetNT() > 50000) mesh.SetGlobalH(min2 (0.05*Dist (boundingbox.PMin(), boundingbox.PMax()), mparam.maxh)); atlas.SetSize(0); ClearSpiralPoints(); BuildSmoothEdges(); // NgProfiler::StartTimer (timer1); double chartangle = stlparam.chartangle; double outerchartangle = stlparam.outerchartangle; chartangle = chartangle/180.*M_PI; outerchartangle = outerchartangle/180.*M_PI; double coschartangle = cos(chartangle); double cosouterchartangle = cos(outerchartangle); double cosouterchartanglehalf = cos(0.5*outerchartangle); double sinchartangle = sin(chartangle); double sinouterchartangle = sin(outerchartangle); Array outermark(GetNT()); //marks all trigs form actual outer region Array outertested(GetNT()); //marks tested trigs for outer region Array pointstochart(GetNP()); //point in chart becomes chartnum Array innerpointstochart(GetNP()); //point in chart becomes chartnum Array chartpoints; //point in chart becomes chartnum Array innerchartpoints; Array> innerchartpts; Array dirtycharttrigs; Array chartdistacttrigs (GetNT()); //outercharttrigs chartdistacttrigs = 0; STLBoundary chartbound(this); //knows the actual chart boundary //int chartboundarydivisions = 10; markedsegs.SetSize(0); //for testing!!! Array chartpointchecked(GetNP()); //for dirty-chart-trigs pointstochart.SetSize(GetNP()); innerpointstochart.SetSize(GetNP()); chartmark.SetSize(GetNT()); for (int i = 1; i <= GetNP(); i++) { innerpointstochart.Elem(i) = 0; pointstochart.Elem(i) = 0; chartpointchecked.Elem(i) = 0; } double eps = 1e-12 * Dist (boundingbox.PMin(), boundingbox.PMax()); int spiralcheckon = stldoctor.spiralcheck; if (!spiralcheckon) {PrintWarning("++++++++++++\nspiral deactivated by user!!!!\n+++++++++++++++"); } chartmark = 0; outermark = 0; outertested = 0; double atlasarea = Area(); double workedarea = 0; double showinc = 100.*5000./(double)GetNT(); double nextshow = 0; // Point<3> startp; int lastunmarked = 1; PrintMessage(5,"one dot per 5000 triangles: "); int markedtrigcnt = 0; while (markedtrigcnt < GetNT()) { if (multithread.terminate) { PopStatus(); return; } // NgProfiler::StartTimer (timerb); if (workedarea / atlasarea*100. >= nextshow) {PrintDot(); nextshow+=showinc;} SetThreadPercent(100.0 * workedarea / atlasarea); STLChart * chart = new STLChart(this); atlas.Append(chart); // *testout << "Chart " << atlas.Size() << endl; //find unmarked trig int prelastunmarked = lastunmarked; bool found = false; for (int j = lastunmarked; j <= GetNT(); j++) if (!GetMarker(j)) { found = true; lastunmarked = j; break; } chartpoints.SetSize(0); innerchartpoints.SetSize(0); innerchartpts.SetSize(0); chartbound.Clear(); chartbound.SetChart(chart); chartbound.BuildSearchTree(); // different !!! if (!found) { PrintSysError("Make Atlas, no starttrig found"); return; } //find surrounding trigs // int starttrig = j; int starttrig = lastunmarked; Point<3> startp = GetPoint(GetTriangle(starttrig).PNum(1)); int accepted; int chartnum = GetNOCharts(); Vec<3> sn = GetTriangle(starttrig).Normal(); chart->SetNormal (startp, sn); // *testout << "first trig " << starttrig << ", n = " << sn << endl; SetMarker(starttrig, chartnum); markedtrigcnt++; chart->AddChartTrig(starttrig); chartbound.AddTriangle(GetTriangle(starttrig)); workedarea += GetTriangle(starttrig).Area(points); for (int i = 1; i <= 3; i++) { innerpointstochart.Elem(GetTriangle(starttrig).PNum(i)) = chartnum; pointstochart.Elem(GetTriangle(starttrig).PNum(i)) = chartnum; chartpoints.Append(GetTriangle(starttrig).PNum(i)); innerchartpoints.Append(GetTriangle(starttrig).PNum(i)); } bool changed = true; int oldstartic = 1; int oldstartic2; // NgProfiler::StopTimer (timerb); // NgProfiler::StartTimer (timer2); while (changed) { changed = false; oldstartic2 = oldstartic; oldstartic = chart->GetNT(); // for (ic = oldstartic2; ic <= chart->GetNT(); ic++) for (int ic = oldstartic2; ic <= oldstartic; ic++) { int i = chart->GetTrig(ic); if (GetMarker(i) == chartnum) { for (int j = 1; j <= NONeighbourTrigs(i); j++) { int nt = NeighbourTrig(i,j); // *testout << "check trig " << nt << endl; int np1, np2; GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2); if (GetMarker(nt) == 0 && !IsEdge(np1,np2)) { Vec<3> n2 = GetTriangle(nt).Normal(); // *testout << "acos = " << 180/M_PI*acos (n2*sn) << endl; if ( (n2 * sn) >= coschartangle ) { // *testout << "good angle " << endl; accepted = 1; /* //alter spiralentest, schnell, aber ungenau for (k = 1; k <= 3; k++) { //find overlapping charts: Point3d pt = GetPoint(GetTriangle(nt).PNum(k)); if (innerpointstochart.Get(GetTriangle(nt).PNum(k)) != chartnum) { for (l = 1; l <= chartpoints.Size(); l++) { Vec3d vptpl(GetPoint(chartpoints.Get(l)), pt); double vlen = vptpl.Length(); if (vlen > 0) { vptpl /= vlen; if ( fabs( vptpl * sn) > sinchartangle ) { accepted = 0; break; } } } } } */ //find overlapping charts exacter (fast, too): for (int k = 1; k <= 3; k++) { int nnt = NeighbourTrig(nt,k); if (GetMarker(nnt) != chartnum) { int nnp1, nnp2; GetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2); accepted = chartbound.TestSeg(GetPoint(nnp1), GetPoint(nnp2), sn,sinchartangle,1 /*chartboundarydivisions*/ ,points, eps); // if (!accepted) *testout << "not acc due to testseg" << endl; Vec<3> n3 = GetTriangle(nnt).Normal(); if ( (n3 * sn) >= coschartangle && IsSmoothEdge (nnp1, nnp2) ) accepted = 1; } if (!accepted) break; } if (accepted) { // *testout << "trig accepted" << endl; SetMarker(nt, chartnum); changed = true; markedtrigcnt++; workedarea += GetTriangle(nt).Area(points); chart->AddChartTrig(nt); chartbound.AddTriangle(GetTriangle(nt)); for (int k = 1; k <= 3; k++) { if (innerpointstochart.Get(GetTriangle(nt).PNum(k)) != chartnum) { innerpointstochart.Elem(GetTriangle(nt).PNum(k)) = chartnum; pointstochart.Elem(GetTriangle(nt).PNum(k)) = chartnum; chartpoints.Append(GetTriangle(nt).PNum(k)); innerchartpoints.Append(GetTriangle(nt).PNum(k)); } } } } } } } } } innerchartpts.SetSize(innerchartpoints.Size()); for (size_t i = 0; i < innerchartpoints.Size(); i++) innerchartpts[i] = GetPoint(innerchartpoints[i]); // chartbound.BuildSearchTree(); // different !!! // NgProfiler::StopTimer (timer2); // NgProfiler::StartTimer (timer3); //find outertrigs // chartbound.Clear(); // warum, ic-bound auf edge macht Probleme js ??? outermark.Elem(starttrig) = chartnum; //chart->AddOuterTrig(starttrig); changed = true; oldstartic = 1; while (changed) { changed = false; oldstartic2 = oldstartic; oldstartic = chart->GetNT(); for (int ic = oldstartic2; ic <= oldstartic; ic++) { int i = chart->GetTrig(ic); if (outermark.Get(i) != chartnum) continue; for (int j = 1; j <= NONeighbourTrigs(i); j++) { int nt = NeighbourTrig(i,j); if (outermark.Get(nt) == chartnum) continue; const STLTriangle & ntrig = GetTriangle(nt); int np1, np2; GetTriangle(i).GetNeighbourPoints(GetTriangle(nt),np1,np2); if (IsEdge (np1, np2)) continue; /* if (outertested.Get(nt) == chartnum) continue; */ outertested.Elem(nt) = chartnum; Vec<3> n2 = GetTriangle(nt).Normal(); //abfragen, ob noch im tolerierten Winkel if ( (n2 * sn) >= cosouterchartangle ) { accepted = 1; // NgProfiler::StartTimer (timer4); bool isdirtytrig = false; Vec<3> gn = GetTriangle(nt).GeomNormal(points); double gnlen = gn.Length(); if (n2 * gn <= cosouterchartanglehalf * gnlen) isdirtytrig = true; //zurueckweisen, falls eine Spiralartige outerchart entsteht //find overlapping charts exacter: //do not check dirty trigs! // NgProfiler::StartTimer (timer4a); if (spiralcheckon && !isdirtytrig) for (int k = 1; k <= 3; k++) { // NgProfiler::StartTimer (timer4b); int nnt = NeighbourTrig(nt,k); if (outermark.Elem(nnt) != chartnum) { // NgProfiler::StartTimer (timer4c); int nnp1, nnp2; GetTriangle(nt).GetNeighbourPoints(GetTriangle(nnt),nnp1,nnp2); // NgProfiler::StopTimer (timer4c); // NgProfiler::StartTimer (timer4d); accepted = chartbound.TestSeg(GetPoint(nnp1),GetPoint(nnp2), sn,sinouterchartangle, 0 /*chartboundarydivisions*/ ,points, eps); // NgProfiler::StopTimer (timer4d); // NgProfiler::StartTimer (timer4e); Vec<3> n3 = GetTriangle(nnt).Normal(); if ( (n3 * sn) >= cosouterchartangle && IsSmoothEdge (nnp1, nnp2) ) accepted = 1; // NgProfiler::StopTimer (timer4e); } // NgProfiler::StopTimer (timer4b); if (!accepted) break; } // NgProfiler::StopTimer (timer4a); // NgProfiler::StopTimer (timer4); // NgProfiler::RegionTimer reg5(timer5); // outer chart is only small environment of // inner chart: if (accepted) { // NgProfiler::StartTimer (timer5a); accepted = 0; for (int k = 1; k <= 3; k++) if (innerpointstochart.Get(ntrig.PNum(k)) == chartnum) { accepted = 1; break; } // NgProfiler::StopTimer (timer5a); // int timer5csl = (innerchartpts.Size() < 100) ? timer5cs : timer5cl; // NgProfiler::StartTimer (timer5csl); if (!accepted) for (int k = 1; k <= 3; k++) { Point<3> pt = GetPoint(ntrig.PNum(k)); double h2 = sqr(mesh.GetH(pt)); /* for (int l = 1; l <= innerchartpoints.Size(); l++) { double tdist = Dist2(pt, GetPoint (innerchartpoints.Get(l))); if (tdist < 4 * h2) { accepted = 1; break; } } */ for (int l = 0; l < innerchartpts.Size(); l++) { double tdist = Dist2(pt, innerchartpts[l]); if (tdist < 4 * h2) { accepted = 1; break; } } if (accepted) break; } // NgProfiler::StopTimer (timer5csl); } // NgProfiler::StartTimer (timer5b); if (accepted) { changed = true; outermark.Elem(nt) = chartnum; if (GetMarker(nt) != chartnum) { chartbound.AddTriangle(GetTriangle(nt)); chart->AddOuterTrig(nt); for (int k = 1; k <= 3; k++) { if (pointstochart.Get(GetTriangle(nt).PNum(k)) != chartnum) { pointstochart.Elem(GetTriangle(nt).PNum(k)) = chartnum; chartpoints.Append(GetTriangle(nt).PNum(k)); } } } } // NgProfiler::StopTimer (timer5b); } } } } // NgProfiler::StopTimer (timer3); // NgProfiler::StartTimer (timere); // NgProfiler::StartTimer (timere1); //end of while loop for outer chart GetDirtyChartTrigs(chartnum, *chart, outermark, chartpointchecked, dirtycharttrigs); //dirtycharttrigs are local (chart) point numbers!!!!!!!!!!!!!!!! if (dirtycharttrigs.Size() != 0 && (dirtycharttrigs.Size() != chart->GetNChartT() || dirtycharttrigs.Size() != 1)) { if (dirtycharttrigs.Size() == chart->GetNChartT() && dirtycharttrigs.Size() != 1) { //if all trigs would be eliminated -> leave 1 trig! dirtycharttrigs.SetSize(dirtycharttrigs.Size() - 1); } for (int k = 1; k <= dirtycharttrigs.Size(); k++) { int tn = chart->GetChartTrig(dirtycharttrigs.Get(k)); outermark.Elem(tn) = 0; //not necessary, for later use SetMarker(tn, 0); markedtrigcnt--; workedarea -= GetTriangle(tn).Area(points); } chart->MoveToOuterChart(dirtycharttrigs); lastunmarked = 1; lastunmarked = prelastunmarked; } chartbound.DeleteSearchTree(); // NgProfiler::StopTimer (timere1); // NgProfiler::StartTimer (timere2); // cout << "key" << endl; // char key; // cin >> key; //calculate an estimate meshsize, not to produce too large outercharts, with factor 2 larger! RestrictHChartDistOneChart(chartnum, chartdistacttrigs, mesh, h, 0.5, atlasminh); // NgProfiler::Print(stdout); // NgProfiler::StopTimer (timere2); // NgProfiler::StopTimer (timere); } // NgProfiler::StopTimer (timer1); // NgProfiler::Print(stdout); PrintMessage(5,""); PrintMessage(5,"NO charts=", atlas.Size()); int cnttrias = 0; outerchartspertrig.SetSize(GetNT()); for (int i = 1; i <= atlas.Size(); i++) { for (int j = 1; j <= GetChart(i).GetNT(); j++) { int tn = GetChart(i).GetTrig(j); AddOCPT(tn,i); } cnttrias += GetChart(i).GetNT(); } PrintMessage(5, "NO outer chart trias=", cnttrias); //sort outerchartspertrig for (int i = 1; i <= GetNT(); i++) { for (int k = 1; k < GetNOCPT(i); k++) for (int j = 1; j < GetNOCPT(i); j++) { int swap = GetOCPT(i,j); if (GetOCPT(i,j+1) < swap) { SetOCPT(i,j,GetOCPT(i,j+1)); SetOCPT(i,j+1,swap); } } // check make atlas if (GetChartNr(i) <= 0 || GetChartNr(i) > GetNOCharts()) PrintSysError("Make Atlas: chartnr(", i, ")=0!!"); } mesh.SetGlobalH(mparam.maxh); mesh.SetMinimalH(mparam.minh); AddConeAndSpiralEdges(); PrintMessage(5,"Make Atlas finished"); PopStatus(); } int STLGeometry::TrigIsInOC(int tn, int ocn) const { if (tn < 1 || tn > GetNT()) { // assert (1); abort (); PrintSysError("STLGeometry::TrigIsInOC illegal tn: ", tn); return 0; } /* int firstval = 0; int i; for (i = 1; i <= GetNOCPT(tn); i++) { if (GetOCPT(tn, i) == ocn) {firstval = 1;} } */ int found = 0; int inc = 1; while (inc <= GetNOCPT(tn)) {inc *= 2;} inc /= 2; int start = inc; while (!found && inc > 0) { if (GetOCPT(tn,start) > ocn) {inc = inc/2; start -= inc;} else if (GetOCPT(tn,start) < ocn) {inc = inc/2; if (start+inc <= GetNOCPT(tn)) {start += inc;}} else {found = 1;} } return GetOCPT(tn, start) == ocn; } int STLGeometry :: GetChartNr(int i) const { if (i > chartmark.Size()) { PrintSysError("GetChartNr(", i, ") not possible!!!"); i = 1; } return chartmark.Get(i); } /* int STLGeometry :: GetMarker(int i) const { return chartmark.Get(i); } */ void STLGeometry :: SetMarker(int nr, int m) { chartmark.Elem(nr) = m; } int STLGeometry :: GetNOCharts() const { return atlas.Size(); } const STLChart& STLGeometry :: GetChart(int nr) const { if (nr > atlas.Size()) { PrintSysError("GetChart(", nr, ") not possible!!!"); nr = 1; } return *(atlas.Get(nr)); } int STLGeometry :: AtlasMade() const { return chartmark.Size() != 0; } /* //return 1 if not exists int AddIfNotExists(Array& list, int x) { int i; for (i = 1; i <= list.Size(); i++) { if (list.Get(i) == x) {return 0;} } list.Append(x); return 1; } */ void STLGeometry :: GetInnerChartLimes(Array& limes, int chartnum) { int j, k; int t, nt, np1, np2; limes.SetSize(0); STLChart& chart = GetChart(chartnum); for (j = 1; j <= chart.GetNChartT(); j++) { t = chart.GetChartTrig(j); const STLTriangle& tt = GetTriangle(t); for (k = 1; k <= 3; k++) { nt = NeighbourTrig(t,k); if (GetChartNr(nt) != chartnum) { tt.GetNeighbourPoints(GetTriangle(nt),np1,np2); if (!IsEdge(np1,np2)) { limes.Append(twoint(np1,np2)); /* p3p1 = GetPoint(np1); p3p2 = GetPoint(np2); if (AddIfNotExists(limes,np1)) { plimes1.Append(p3p1); //plimes1trigs.Append(t); //plimes1origin.Append(np1); } if (AddIfNotExists(limes1,np2)) { plimes1.Append(p3p2); //plimes1trigs.Append(t); //plimes1origin.Append(np2); } //chart.AddILimit(twoint(np1,np2)); for (int di = 1; di <= divisions; di++) { double f1 = (double)di/(double)(divisions+1.); double f2 = (divisions+1.-(double)di)/(double)(divisions+1.); plimes1.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2, p3p1.Y()*f1+p3p2.Y()*f2, p3p1.Z()*f1+p3p2.Z()*f2)); //plimes1trigs.Append(t); //plimes1origin.Append(0); } */ } } } } } void STLGeometry :: GetDirtyChartTrigs(int chartnum, STLChart& chart, const Array& outercharttrigs, Array& chartpointchecked, Array& dirtytrigs) { dirtytrigs.SetSize(0); int j,k,n; int np1, np2, nt; int cnt = 0; for (j = 1; j <= chart.GetNChartT(); j++) { int t = chart.GetChartTrig(j); const STLTriangle& tt = GetTriangle(t); for (k = 1; k <= 3; k++) { nt = NeighbourTrig(t,k); if (GetChartNr(nt) != chartnum && outercharttrigs.Get(nt) != chartnum) { tt.GetNeighbourPoints(GetTriangle(nt),np1,np2); if (!IsEdge(np1,np2)) { dirtytrigs.Append(j); //local numbers!!! cnt++; break; //only once per trig!!! } } } } cnt = 0; int ap1, ap2, tn1, tn2, l, problem, pn; Array trigsaroundp; for (j = chart.GetNChartT(); j >= 1; j--) { int t = chart.GetChartTrig(j); const STLTriangle& tt = GetTriangle(t); for (k = 1; k <= 3; k++) { pn = tt.PNum(k); //if (chartpointchecked.Get(pn) == chartnum) //{continue;} int checkpoint = 0; for (n = 1; n <= trigsperpoint.EntrySize(pn); n++) { if (trigsperpoint.Get(pn,n) != t && //ueberfluessig??? GetChartNr(trigsperpoint.Get(pn,n)) != chartnum && outercharttrigs.Get(trigsperpoint.Get(pn,n)) != chartnum) {checkpoint = 1;}; } if (checkpoint) { chartpointchecked.Elem(pn) = chartnum; GetSortedTrianglesAroundPoint(pn,t,trigsaroundp); trigsaroundp.Append(t); //ring problem = 0; //forward: for (l = 2; l <= trigsaroundp.Size()-1; l++) { tn1 = trigsaroundp.Get(l-1); tn2 = trigsaroundp.Get(l); const STLTriangle& t1 = GetTriangle(tn1); const STLTriangle& t2 = GetTriangle(tn2); t1.GetNeighbourPoints(t2, ap1, ap2); if (IsEdge(ap1,ap2)) break; if (GetChartNr(tn2) != chartnum && outercharttrigs.Get(tn2) != chartnum) {problem = 1;} } //backwards: for (l = trigsaroundp.Size()-1; l >= 2; l--) { tn1 = trigsaroundp.Get(l+1); tn2 = trigsaroundp.Get(l); const STLTriangle& t1 = GetTriangle(tn1); const STLTriangle& t2 = GetTriangle(tn2); t1.GetNeighbourPoints(t2, ap1, ap2); if (IsEdge(ap1,ap2)) break; if (GetChartNr(tn2) != chartnum && outercharttrigs.Get(tn2) != chartnum) {problem = 1;} } // if (problem && !IsInArray(j,dirtytrigs)) if (problem && !dirtytrigs.Contains(j)) { dirtytrigs.Append(j); cnt++; break; //only once per triangle } } } } } } netgen-6.2.1905/libsrc/stlgeom/stltopology.hpp0000644000175000017500000002455113504650527020050 0ustar kurtkurt#ifndef FILE_STLTOPOLOGY #define FILE_STLTOPOLOGY /**************************************************************************/ /* File: stltopology.hpp */ /* Author: Joachim Schoeberl */ /* Author2: Johannes Gerstmayr */ /* Date: 26. Jul. 99 */ /**************************************************************************/ /* The STLTopology contains topologic information as triangle->point, point->triangles, triangle->edge, 2-points->edge,... */ class STLGeometry; #define STLBASE 1 class STLPointIndex { int i; public: STLPointIndex () { ; } STLPointIndex (int ai) : i(ai) { ; } STLPointIndex & operator= (const STLPointIndex & ai) { i = ai.i; return *this; } STLPointIndex & operator= (int ai) { i = ai; return *this; } operator int () const { return i; } STLPointIndex operator++ (int) { return i++; } STLPointIndex operator-- (int) { return i--; } }; class STLTrigIndex { int i; public: STLTrigIndex () { ; } STLTrigIndex (int ai) : i(ai) { ; } STLTrigIndex & operator= (const STLTrigIndex & ai) { i = ai.i; return *this; } STLTrigIndex & operator= (int ai) { i = ai; return *this; } operator int () const { return i; } STLTrigIndex operator++ (int) { return i++; } STLTrigIndex operator-- (int) { return i--; } }; // triangle structure for loading stl files class STLReadTriangle { Vec<3> normal; Point<3> pts[3]; public: STLReadTriangle (const Point<3> * apts, const Vec<3> & anormal); STLReadTriangle () {}; const Point<3> & operator[] (int i) const { return pts[i]; } const Vec<3> & Normal() const { return normal; } }; class STLTriangle { // topology edges of triangle, edge[i] opposite to point[i] int topedges[3]; // neighbour triangles, trig[i] opposite to point[i] int nbtrigs[2][3]; // normalized stored normal vector ?? Vec<3> normal; // point numbers of triangle int pts[3]; // front-side and back-side domains int domains[2]; public: Box<3> box; Point<3> center; double rad; int facenum; struct { unsigned int toperror : 1; } flags; STLTriangle (const int * apts); STLTriangle () {pts[0]=0;pts[1]=0;pts[2]=0;} void DoArchive(Archive& ar) { ar.Do(&topedges[0],3); ar.Do(&nbtrigs[0][0], 6); ar.Do(&pts[0],3); ar.Do(&domains[0],2); size_t i = flags.toperror; ar & normal & box & center & rad & facenum & i; flags.toperror = i; } int operator[] (int i) const { return pts[i]; } int & operator[] (int i) { return pts[i]; } int EdgeNum(int i) const { return topedges[(i-1)]; } int & EdgeNum(int i) { return topedges[(i-1)]; } int NBTrig (bool side, int i) const { return nbtrigs[side][i]; } int & NBTrig (bool side, int i) { return nbtrigs[side][i]; } int Domain (bool side) const { return domains[side]; } int & Domain (bool side) { return domains[side]; } // obsolete: int PNum(int i) const { return pts[(i-1)]; } int & PNum(int i) { return pts[(i-1)]; } int PNumMod(int i) const { return pts[(i-1)%3]; } int & PNumMod(int i) { return pts[(i-1)%3]; } int EdgeNumMod(int i) const { return topedges[(i-1)%3]; } int & EdgeNumMod(int i) { return topedges[(i-1)%3]; } int NBTrigNum(int i) const { return nbtrigs[0][(i-1)]; } int & NBTrigNum(int i) { return nbtrigs[0][(i-1)]; } int NBTrigNumMod(int i) const { return nbtrigs[0][(i-1)%3]; } int & NBTrigNumMod(int i) { return nbtrigs[0][(i-1)%3]; } // consistently oriented neighbour: int IsNeighbourFrom(const STLTriangle& t) const; // opposite to consistently oriented neighbour: int IsWrongNeighbourFrom(const STLTriangle& t) const; ///Get the two points of neighbour-Triangles in orientation of this-Triangle void GetNeighbourPoints(const STLTriangle& t, int& p1, int& p2) const; int GetNeighbourPointsAndOpposite(const STLTriangle& t, int& p1, int& p2, int& po) const; // NON-normalized geometry - normal vector Vec<3> GeomNormal(const Array >& ap) const; // Stored normal vector, normalized void SetNormal (const Vec<3> & n); const Vec<3> & Normal () const { return normal; } void ChangeOrientation(); //project with a certain normal vector in plane void ProjectInPlain(const Array >& ap, const Vec<3> & n, Point<3> & pp) const; //project with the triangle's normal vector in plane void ProjectInPlain(const Array > & ap, Point<3> & pp) const; /* Project the point pp along the nproj into the plane of the triangle. The triangle normal is given by ntrig to avoid numerical instabilities. The local coordinates lam are defined by pp(input) = P1 + lam1 v1 + lam2 v2 + lam3 n the result is pp(output) = P1 + lam1 v1 + lam2 v2 */ int ProjectInPlain (const Array >& ap, const Vec<3> & nproj, Point<3> & pp, Vec<3> & lam) const; int PointInside(const Array >& ap, const Point<3> & pp) const; //get nearest point on triangle and distance to it double GetNearestPoint(const Array >& ap, Point<3> & p3d) const; double Area(const Array >& ap) const; double MinHeight(const Array >& ap) const; double MaxLength(const Array >& ap) const; //max length of a side of triangle int GetFaceNum() {return facenum;} void SetFaceNum(int i) {facenum = i;} int HasEdge(int p1, int p2) const; }; /** Topology Edge: Useful unside a face. A edges sharing more than 2 faces: trigs are undefined */ class STLTopEdge { int pts[2]; int trigs[2]; double cosangle; int status; // excluded, confirmed, candidate, undefined public: STLTopEdge (); STLTopEdge (int p1, int p2, int trig1, int trig2); int operator[] (int i) const { return pts[i]; } int & operator[] (int i) { return pts[i]; } int PNum(int i) const { return pts[(i-1)]; } int & PNum(int i) { return pts[(i-1)]; } int PNumMod(int i) const { return pts[(i-1)%2]; } int & PNumMod(int i) { return pts[(i-1)%2]; } int TrigNum(int i) const { return trigs[(i-1)]; } int & TrigNum(int i) { return trigs[(i-1)]; } int TrigNumMod(int i) const { return trigs[(i-1)%2]; } int & TrigNumMod(int i) { return trigs[(i-1)%2]; } void SetCosAngle (double ca) { cosangle = ca; } double CosAngle () const { return cosangle; } double Angle () const { return acos (cosangle); } void SetStatus (int stat) { status = stat; } int GetStatus () const { return status; } }; ostream& operator<<(ostream& os, const STLTriangle& t); class STLTopology { protected: Array trias; Array topedges; Array > points; // mapping of sorted pair of points to topedge INDEX_2_HASHTABLE * ht_topedges; // mapping of node to trigs TABLE trigsperpoint; // mapping of node to edges TABLE topedgesperpoint; // searchtree for trigs and points BoxTree<3> * searchtree; // ADT Point3dTree * pointtree; Box<3> boundingbox; double pointtol; public: enum STL_GEOM_STATUS { STL_GOOD, STL_WARNING, STL_ERROR }; protected: STL_GEOM_STATUS status; string statustext; bool topology_ok; bool orientation_ok; public: STLTopology(); virtual ~STLTopology(); static STLGeometry * LoadNaomi (istream & ist); static STLGeometry * Load (istream & ist); static STLGeometry * LoadBinary (istream & ist); void Save (const char* filename) const; void SaveBinary (const char* filename, const char* aname) const; void SaveSTLE (const char * filename) const; // stores trigs and edges virtual void DoArchive(Archive& ar) { ar & trias & points & boundingbox & pointtol; if(ar.Input()) FindNeighbourTrigs(); } virtual void InitSTLGeometry (const Array & readtrigs); virtual void TopologyChanged() {}; //do some things, if topology changed! /// Generate topology tables void FindNeighbourTrigs(); void GetTrianglesInBox (const Box<3> & box, Array & trias) const; int GetNP() const { return points.Size(); } int AddPoint(const Point<3> & p) { points.Append(p); return points.Size(); } const Point<3> & GetPoint(int nr) const { return points.Get(nr); } int GetPointNum (const Point<3> & p); void SetPoint(int nr, const Point<3> & p) { points.Elem(nr) = p; } const Array >& GetPoints() const { return points; } const Point<3> & operator[] (STLPointIndex i) const { return points[i]; } Point<3> & operator[] (STLPointIndex i) { return points[i]; } int GetNT() const { return trias.Size(); } void AddTriangle(const STLTriangle& t); const STLTriangle & GetTriangle (int nr) const { return trias.Get(nr); } STLTriangle & GetTriangle (int nr) { return trias.Elem(nr); } const STLTriangle & operator[] (STLTrigIndex i) const { return trias[i]; } STLTriangle & operator[] (STLTrigIndex i) { return trias[i]; } int GetNTE() const { return topedges.Size(); } const STLTopEdge & GetTopEdge (int nr) const { return topedges.Get(nr); } STLTopEdge & GetTopEdge (int nr) { return topedges.Elem(nr); } int GetTopEdgeNum (int pi1, int pi2) const; int NOTrigsPerPoint(int pn) { return trigsperpoint.EntrySize(pn); } int TrigPerPoint(int pn, int i) { return trigsperpoint.Get(pn, i); } int NTopEdgesPerPoint (int pn) const { return topedgesperpoint.EntrySize(pn); } int TopEdgePerPoint (int pn, int ei) const { return topedgesperpoint.Get(pn, ei); } bool Topology_Ok() const { return topology_ok; } bool Orientation_Ok() const { return orientation_ok; } STL_GEOM_STATUS GetStatus () const { return status; } const string & GetStatusText () const { return statustext; } DLL_HEADER void InvertTrig (int trig); DLL_HEADER void DeleteTrig (int trig); DLL_HEADER void OrientAfterTrig (int trig); // Table will be constructed, if topology is not ok /// neighbourtrigs for surfacetrigs TABLE neighbourtrigs; /// get nr-th neighbour Triangle for triangle trig int NONeighbourTrigs(int trig) const { return neighbourtrigs.EntrySize(trig); } int NeighbourTrig(int trig, int nr) const { return neighbourtrigs.Get(trig,nr); } int NeighbourTrigSorted(int trig, int nr) const; void AddNeighbourTrig(int i, int nt) { neighbourtrigs.Add1(i, nt); } int GetLeftTrig (int p1, int p2) const; int GetRightTrig (int p1, int p2) const; const Box<3> & GetBoundingBox () const { return boundingbox; } }; #endif netgen-6.2.1905/libsrc/stlgeom/vsstl.cpp0000644000175000017500000007527113504650527016624 0ustar kurtkurt#include #include #include #include #include #include #include "vsstl.hpp" namespace netgen { /* //mmm #include "stlgeom/modeller.hpp" */ /* *********************** Draw STL Geometry **************** */ extern STLGeometry * stlgeometry; extern shared_ptr mesh; // #include "../../ngtcltk/mvdraw.hpp" VisualSceneSTLMeshing :: VisualSceneSTLMeshing () : VisualScene() { selecttrig = 0; nodeofseltrig = 1; stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); } VisualSceneSTLMeshing :: ~VisualSceneSTLMeshing () { ; } void VisualSceneSTLMeshing :: DrawScene () { int i, j, k; if (changeval != stlgeometry->GetNT()) BuildScene(); changeval = stlgeometry->GetNT(); int colormeshsize = vispar.colormeshsize; double hmin = 0.0, hmax = 1.0; if (colormeshsize) { hmax = -1E50; hmin = +1E50; double ms; for (i = 1; i <= stlgeometry->GetNP(); i++) { ms = mesh->GetH (stlgeometry->GetPoint(i)); hmin = min2(hmin,ms); hmax = max2(hmax,ms); } //hmax = mparam.maxh; //hmin = mesh->GetMinH (stlgeometry->GetBoundingBox().PMin(), // stlgeometry->GetBoundingBox().PMax()); if (hmin == 0) hmin = 0.1 * hmax; //hmax *= 1.1; } glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); SetClippingPlane (); glShadeModel (GL_SMOOTH); glDisable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float mat_spec_col[] = { 1, 1, 1, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col); double shine = vispar.shininess; // double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); float mat_colred[] = { 0.9f, 0.0f, 0.0f, 1.0f }; float mat_colgreen[] = { 0.0f, 0.9f, 0.0f, 1.0f }; float mat_colblue[] = { 0.1f, 0.1f, 1.0f, 1.0f }; float mat_colbluegreen[] = { 0.1f, 0.5f, 0.9f, 1.0f }; // float mat_colpink[] = { 1.0f, 0.1f, 0.5f, 1.0f }; float mat_colviolet[] = { 1.0f, 0.1f, 1.0f, 1.0f }; float mat_colbrown[] = { 0.8f, 0.6f, 0.1f, 1.0f }; // float mat_colorange[] = { 0.9f, 0.7f, 0.1f, 1.0f }; // float mat_colturquis[] = { 0.0f, 1.0f, 0.8f, 1.0f }; float mat_colgrey[] = { 0.3f, 0.3f, 0.3f, 1.0f }; float mat_collred[] = { 1.0f, 0.5f, 0.5f, 1.0f }; float mat_collgreen[] = { 0.2f, 1.9f, 0.2f, 1.0f }; float mat_collbrown[] = { 1.0f, 0.8f, 0.3f, 1.0f }; float mat_collgrey[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // float mat_colmgrey[] = { 0.4f, 0.4f, 0.4f, 1.0f }; float mat_colstlbody[] = { 0.0f, 0.0f, 0.8f, 1.0f }; float mat_colseltrig[] = { 0.7f, 0.7f, 0.3f, 1.0f }; float mat_colseledge[] = { 0.7f, 0.7f, 1.0f, 1.0f }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colblue); float pgoff = 0.5f; glPolygonOffset (pgoff*1, pgoff*1); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_NORMALIZE); /* { //mmm //test modeller Modeller model; //MoZylinder z1(Point3d(0,0,0),Vec3d(100,0,0),20,0.01); //model.Add(&z1); //MoZylinder z2(Point3d(50,50,0),Vec3d(0,-100,0),20,0.01); //model.Add(&z2); MoZylinder z1(Point3d(0,0,0),Vec3d(100,0,0),20,0.01); MoZylinder z2(Point3d(50,50,0),Vec3d(0,-100,0),20,0.01); MoCombine cb1(&z1,&z2); model.Add(&cb1); Array trigs; model.GetTriangles(trigs); int i, k; glBegin (GL_TRIANGLES); for (i = 1; i <= trigs.Size(); i++) { const MoTriangle & tria = trigs.Get(i); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); for (k = 0; k < 3; k++) { glVertex3f (tria.pts[k].X(), tria.pts[k].Y(), tria.pts[k].Z()); } } glEnd (); } */ if (!stlgeometry->trigsconverted) { glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { /* if (j % 10 == seltria) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); */ const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 1; k <= 3; k++) { const Point3d & tp = stlgeometry->GetPoint(stlgeometry->GetTriangle(j).PNum(k)); glVertex3f (tp.X(), tp.Y(), tp.Z()); } /* if (j%10 == seltria) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colblue); */ } glEnd (); glDisable (GL_POLYGON_OFFSET_FILL); int showtrias = vispar.stlshowtrias; if (showtrias) { float mat_coll[] = { 0.2f, 0.2f, 0.2f, 1.f }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_coll); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 1; k <= 3; k++) { const Point3d & tp = stlgeometry->GetPoint(stlgeometry->GetTriangle(j).PNum(k)); glVertex3f (tp.X(), tp.Y(), tp.Z()); } /* for (k = 0; k < 3; k++) { glVertex3f (tria.pts[k].X(), tria.pts[k].Y(), tria.pts[k].Z()); } */ } glEnd (); } } else { int showfilledtrias = vispar.stlshowfilledtrias; //(*mycout) << "in " << showfilledtrias << ", NT=" << stlgeometry -> GetNT() << endl; int chartnumber; if (vispar.stlshowmarktrias) chartnumber = vispar.stlchartnumber + vispar.stlchartnumberoffset; else chartnumber = stlgeometry->GetMeshChartNr(); if (showfilledtrias) { glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); if (colormeshsize) glEnable (GL_COLOR_MATERIAL); glPolygonOffset (pgoff*4, pgoff*4); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); int selt = stlgeometry -> GetSelectTrig(); if (stldoctor.selectmode != 0) {selt = 0; } //do not show selected triangle!!!! glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colstlbody); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} if (j == selt) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colseltrig); } else if (j == selt+1) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colstlbody); } const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { const Point3d & p = stlgeometry->GetPoint(st[k]); if (colormeshsize) { SetOpenGlColor (mesh->GetH (p), hmin, hmax, 1); } glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd (); } int foundseltrig = stlgeometry -> GetSelectTrig(); if (foundseltrig == 0 || foundseltrig > stlgeometry->GetNT() || (stldoctor.showvicinity && !stlgeometry->Vicinity(foundseltrig))) {foundseltrig = 0;} if (foundseltrig) { glPolygonOffset (pgoff*0, 0); glEnable (GL_POLYGON_OFFSET_FILL); //glDisable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colseledge); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glEnable (GL_NORMALIZE); if (stldoctor.selectmode == 2) { //point const STLTriangle& st = stlgeometry -> GetTriangle(foundseltrig); const Point3d & p1 = stlgeometry->GetPoint(st[0]); const Point3d & p2 = stlgeometry->GetPoint(st[1]); const Point3d & p3 = stlgeometry->GetPoint(st[2]); double cs = (Dist(p1,p2)+Dist(p2,p3)+Dist(p3,p1))/100.; const Point3d & p = stlgeometry->GetPoint(st[nodeofseltrig-1]); glLineWidth (4); glBegin (GL_LINES); glVertex3f(p.X()+cs, p.Y()+cs, p.Z()+cs); glVertex3f(p.X()-cs, p.Y()-cs, p.Z()-cs); glVertex3f(p.X()-cs, p.Y()+cs, p.Z()+cs); glVertex3f(p.X()+cs, p.Y()-cs, p.Z()-cs); glVertex3f(p.X()-cs, p.Y()+cs, p.Z()+cs); glVertex3f(p.X()+cs, p.Y()-cs, p.Z()-cs); glVertex3f(p.X()+cs, p.Y()-cs, p.Z()+cs); glVertex3f(p.X()-cs, p.Y()+cs, p.Z()-cs); glEnd (); glLineWidth (1); } else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { //multiedge const Array& me = stlgeometry->SelectedMultiEdge(); if (stlgeometry->GetSelectTrig() > 0 && stlgeometry->GetSelectTrig() <= stlgeometry->GetNT() && me.Size()) { int en = stlgeometry->EdgeDataList().GetEdgeNum(me.Get(1).i1,me.Get(1).i2); int status = stlgeometry->EdgeDataList().Get(en).GetStatus(); switch (status) { case ED_CONFIRMED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collgreen); break; case ED_CANDIDATE: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collbrown); break; case ED_EXCLUDED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collred); break; } glLineWidth (2); glBegin (GL_LINES); for (j = 1; j <= me.Size(); j++) { Point3d p1 = stlgeometry->GetPoint(me.Get(j).i1); Point3d p2 = stlgeometry->GetPoint(me.Get(j).i2); glVertex3f(p1.X(), p1.Y(), p1.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } glEnd (); glLineWidth (1); } } } int showmarktrias = vispar.stlshowmarktrias || vispar.stlshowactivechart; if (stldoctor.showmarkedtrigs) { //(*mycout) << "marked" << endl; glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); //GL_LINE glPolygonOffset (pgoff*1, pgoff*1); glEnable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbluegreen); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} if (!stlgeometry->IsMarkedTrig(j)) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { const Point3d & p = stlgeometry->GetPoint(st[k]); glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd (); //show OpenSegments on original geometry glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colviolet); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glPolygonOffset (pgoff*1, 1); glEnable (GL_NORMALIZE); glBegin (GL_LINES); if (stlgeometry->GetNMarkedSegs()) { Point<3> p1,p2; for (j = 1; j <= stlgeometry -> GetNMarkedSegs(); j++) { stlgeometry->GetMarkedSeg(j,p1,p2); glVertex3dv(&p1(0)); glVertex3dv(&p2(0)); } } glEnd (); } if (stldoctor.showfaces) { int facenumber = vispar.stlchartnumber + vispar.stlchartnumberoffset; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (pgoff*3, 3); glEnable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collgrey); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} //(*mycout) << " facenum = " << stlgeometry->GetTriangle(j).GetFaceNum() << " "; if (stlgeometry->GetTriangle(j).GetFaceNum() != facenumber) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { Point3d p = stlgeometry->GetPoint(st[k]); glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd (); } if (showmarktrias && stlgeometry->AtlasMade()) { glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (pgoff*3, 3); glEnable (GL_POLYGON_OFFSET_FILL); glBegin (GL_TRIANGLES); if (chartnumber >= 1 && chartnumber <= stlgeometry->GetNOCharts()) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown); const STLChart& chart = stlgeometry->GetChart(chartnumber); for (j = 1; j <= chart.GetNChartT(); j++) { /* if (j == charttrignumber) {glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred);} else {glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown);} */ const STLTriangle& st = stlgeometry -> GetTriangle(chart.GetChartTrig(j)); const Vec3d & n = stlgeometry->GetTriangle(chart.GetChartTrig(j)).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(chart.GetChartTrig(j)); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { glVertex3f (stlgeometry->GetPoint(st[k])(0), stlgeometry->GetPoint(st[k])(1), stlgeometry->GetPoint(st[k])(2)); } } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); for (j = 1; j <= chart.GetNOuterT(); j++) { const STLTriangle& st = stlgeometry -> GetTriangle(chart.GetOuterTrig(j)); const Vec3d & n = stlgeometry->GetTriangle(chart.GetOuterTrig(j)).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(chart.GetOuterTrig(j)); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { glVertex3f (stlgeometry->GetPoint(st[k])(0), stlgeometry->GetPoint(st[k])(1), stlgeometry->GetPoint(st[k])(2)); } } } glEnd (); } int showtrias = vispar.stlshowtrias; if (showtrias) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgrey); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glPolygonOffset (pgoff*2, 2); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { glVertex3f (stlgeometry->GetPoint(st[k])(0), stlgeometry->GetPoint(st[k])(1), stlgeometry->GetPoint(st[k])(2)); } } glEnd (); } int showedges = vispar.stlshowedges; if (showedges) { glPolygonOffset (pgoff*1, 1); glEnable (GL_POLYGON_OFFSET_FILL); //glDisable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glEnable (GL_NORMALIZE); glBegin (GL_LINES); /* if (stldoctor.useexternaledges) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colorange); for (j = 1; j <= stlgeometry -> NOExternalEdges(); j++) { twoint v = stlgeometry->GetExternalEdge(j); Point3d p1 = stlgeometry->GetPoint(v.i1); Point3d p2 = stlgeometry->GetPoint(v.i2); Vec3d n1 = stlgeometry->GetNormal(v.i1); Vec3d n2 = stlgeometry->GetNormal(v.i2); glNormal3f(n1.X(), n1.Y(), n1.Z()); glVertex3f(p1.X(), p1.Y(), p1.Z()); glNormal3f(n2.X(), n2.Y(), n2.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } } */ if (!stlgeometry->meshlines.Size() || !stldoctor.drawmeshededges) { /* for (j = 1; j <= stlgeometry -> GetNE(); j++) { STLEdge v = stlgeometry->GetEdge(j); Point3d p1 = stlgeometry->GetPoint(v.pts[0]); Point3d p2 = stlgeometry->GetPoint(v.pts[1]); Vec3d n1 = stlgeometry->GetNormal(v.pts[0]); Vec3d n2 = stlgeometry->GetNormal(v.pts[1]); glNormal3f(n1.X(), n1.Y(), n1.Z()); glVertex3f(p1.X(), p1.Y(), p1.Z()); glNormal3f(n2.X(), n2.Y(), n2.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } */ const STLEdgeDataList& ed = stlgeometry->EdgeDataList(); for (i = 1; i <= ed.Size(); i++) { if (ed.Get(i).GetStatus() != ED_UNDEFINED) { switch (ed.Get(i).GetStatus()) { case ED_CONFIRMED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); break; case ED_CANDIDATE: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown); break; case ED_EXCLUDED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); break; } if (ed.Get(i).GetStatus() == ED_EXCLUDED && !stldoctor.showexcluded) continue; Point3d p1 = stlgeometry->GetPoint(ed.Get(i).PNum(1)); Point3d p2 = stlgeometry->GetPoint(ed.Get(i).PNum(2)); glVertex3f(p1.X(), p1.Y(), p1.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } } } /* else if (stlgeometry->meshlines.Size() == 0) { for (j = 1; j <= stlgeometry->GetNLines(); j++) { STLLine* line = stlgeometry->GetLine(j); int pn1, pn2; for (int k = 1; k <= line->NP()-1; k++) { pn1 = line->PNum(k); pn2 = line->PNum(k+1); Point3d p1 = stlgeometry->GetPoint(pn1); Point3d p2 = stlgeometry->GetPoint(pn2); Vec3d n1 = stlgeometry->GetNormal(pn1); Vec3d n2 = stlgeometry->GetNormal(pn2); glNormal3f(n1.X(), n1.Y(), n1.Z()); glVertex3f(p1.X(), p1.Y(), p1.Z()); glNormal3f(n2.X(), n2.Y(), n2.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } } } */ else if (stlgeometry->meshlines.Size() != 0) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); for (j = 1; j <= stlgeometry->meshlines.Size(); j++) { STLLine* line = stlgeometry->meshlines.Get(j); int pn1, pn2; for (int k = 1; k <= line->NP()-1; k++) { pn1 = line->PNum(k); pn2 = line->PNum(k+1); Point3d p1 = stlgeometry->meshpoints.Get(pn1); Point3d p2 = stlgeometry->meshpoints.Get(pn2); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); glVertex3f(p1.X(), p1.Y(), p1.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); double cs = 0.02*Dist(p1,p2); glVertex3f(p1.X()+cs, p1.Y()+cs, p1.Z()+cs); glVertex3f(p1.X()-cs, p1.Y()-cs, p1.Z()-cs); glVertex3f(p2.X()+cs, p2.Y()+cs, p2.Z()+cs); glVertex3f(p2.X()-cs, p2.Y()-cs, p2.Z()-cs); glVertex3f(p1.X()-cs, p1.Y()+cs, p1.Z()+cs); glVertex3f(p1.X()+cs, p1.Y()-cs, p1.Z()-cs); glVertex3f(p2.X()-cs, p2.Y()+cs, p2.Z()+cs); glVertex3f(p2.X()+cs, p2.Y()-cs, p2.Z()-cs); } } } glEnd (); } if (stldoctor.showedgecornerpoints && stlgeometry->LineEndPointsSet()) { glPointSize (5); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); glBegin (GL_POINTS); for (i = 1; i <= stlgeometry->GetNP(); i++) { if (stlgeometry->IsLineEndPoint(i)) { const Point3d p = stlgeometry->GetPoint(i); glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd(); } } glPopMatrix(); if (vispar.colormeshsize) DrawColorBar (hmin, hmax, 1); glFinish(); } void VisualSceneSTLMeshing :: BuildScene (int zoomall) { if (selecttrig && zoomall == 2) center = stlgeometry -> GetPoint ( stlgeometry->GetTriangle(selecttrig).PNum(nodeofseltrig)); else center = stlgeometry -> GetBoundingBox().Center(); rad = stlgeometry -> GetBoundingBox().Diam() / 2; CalcTransformationMatrices(); } void VisualSceneSTLMeshing :: MouseDblClick (int px, int py) { // (*mycout) << "dblclick: " << px << " - " << py << endl; int i, j, k, hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); /* (*mycout) << "viewport = " << viewport[0] << " " << viewport[1] << " " << viewport[2] << " " << viewport[3] << endl; */ glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixd (transformationmat); glInitNames(); glPushName (1); glEnable (GL_POLYGON_OFFSET_FILL); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); //const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); //glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); if (stldoctor.selectmode == 0) { glLoadName (j); glBegin (GL_TRIANGLES); for (k = 0; k < 3; k++) { Point3d p = stlgeometry->GetPoint(st[k]); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { Point3d pm = Center(stlgeometry->GetPoint(st[0]), stlgeometry->GetPoint(st[1]), stlgeometry->GetPoint(st[2])); for (k = 0; k < 3; k++) { glLoadName (j*3+k-2); glBegin (GL_TRIANGLES); Point3d p1 = stlgeometry->GetPoint(st[k]); Point3d p2 = stlgeometry->GetPoint(st[(k+1)%3]); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (p2.X(), p2.Y(), p2.Z()); glVertex3f (pm.X(), pm.Y(), pm.Z()); glEnd (); } } else { Point3d pm1 = Center(stlgeometry->GetPoint(st[0]), stlgeometry->GetPoint(st[1])); Point3d pm2 = Center(stlgeometry->GetPoint(st[1]), stlgeometry->GetPoint(st[2])); Point3d pm3 = Center(stlgeometry->GetPoint(st[2]), stlgeometry->GetPoint(st[0])); Point3d p1 = stlgeometry->GetPoint(st[0]); Point3d p2 = stlgeometry->GetPoint(st[1]); Point3d p3 = stlgeometry->GetPoint(st[2]); glLoadName (j*4-3); glBegin (GL_TRIANGLES); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (pm1.X(), pm1.Y(), pm1.Z()); glVertex3f (pm3.X(), pm3.Y(), pm3.Z()); glEnd (); glLoadName (j*4-2); glBegin (GL_TRIANGLES); glVertex3f (p2.X(), p2.Y(), p2.Z()); glVertex3f (pm2.X(), pm2.Y(), pm2.Z()); glVertex3f (pm1.X(), pm1.Y(), pm1.Z()); glEnd (); glLoadName (j*4-1); glBegin (GL_TRIANGLES); glVertex3f (p3.X(), p3.Y(), p3.Z()); glVertex3f (pm3.X(), pm3.Y(), pm3.Z()); glVertex3f (pm2.X(), pm2.Y(), pm2.Z()); glEnd (); glLoadName (j*4); glBegin (GL_TRIANGLES); glVertex3f (pm1.X(), pm1.Y(), pm1.Z()); glVertex3f (pm2.X(), pm2.Y(), pm2.Z()); glVertex3f (pm3.X(), pm3.Y(), pm3.Z()); glEnd (); } } glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); // (*mycout) << "hits = " << hits << endl; //int minrec = -1; int minname = 0; GLuint mindepth = 0; for (i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; /* (*mycout) << selbuf[4*i] << " " << selbuf[4*i+1] << " " << selbuf[4*i+2] << " " << selbuf[4*i+3] << endl; */ if (curname && (curdepth < mindepth || !minname)) { //minrec = i; mindepth = curdepth; minname = curname; } } if (!minname) {return;} if (stldoctor.selectmode == 0) { int oldtrig = selecttrig; selecttrig = minname; if (selecttrig == oldtrig) nodeofseltrig = (nodeofseltrig % 3) + 1; else nodeofseltrig = 1; stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); stlgeometry->PrintSelectInfo(); } else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { selecttrig = (minname-1) / 3 + 1; nodeofseltrig = minname-selecttrig*3+3; stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); stlgeometry->PrintSelectInfo(); if (stldoctor.selectmode == 1) { stlgeometry->BuildSelectedEdge(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig), stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1))); } if (stldoctor.selectmode == 3) { stlgeometry->BuildSelectedMultiEdge(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig), stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1))); } else if (stldoctor.selectmode == 4) { stlgeometry->BuildSelectedCluster(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig), stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1))); } switch (stldoctor.edgeselectmode) { case 1: stlgeometry->STLDoctorUndefinedEdge(); break; case 2: stlgeometry->STLDoctorConfirmEdge(); break; case 3: stlgeometry->STLDoctorCandidateEdge(); break; case 4: stlgeometry->STLDoctorExcludeEdge(); break; default: break; } } else if (stldoctor.selectmode == 2) { selecttrig = (minname-1) / 4 + 1; nodeofseltrig = minname-selecttrig*4+4; if (nodeofseltrig == 4) {nodeofseltrig = 1;} stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); stlgeometry->PrintSelectInfo(); } if (stldoctor.showtouchedtrigchart && stlgeometry->AtlasMade() && stlgeometry->GetSelectTrig()) { vispar.stlchartnumber = stlgeometry->GetChartNr(stlgeometry->GetSelectTrig()); vispar.stlchartnumberoffset = 0; } } // VisualSceneSTLMeshing vsstlmeshing; /* *********************** Draw STL Geometry **************** */ VisualSceneSTLGeometry :: VisualSceneSTLGeometry () : VisualScene() { ; } VisualSceneSTLGeometry :: ~VisualSceneSTLGeometry () { ; } void VisualSceneSTLGeometry :: DrawScene () { if (changeval != stlgeometry->GetNT()) BuildScene(); changeval = stlgeometry->GetNT(); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); glShadeModel (GL_SMOOTH); glDisable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); double shine = vispar.shininess; // double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); float mat_col[] = { 0.2f, 0.2f, 0.8f, 1.0f}; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glCallList (trilists.Get(1)); glDisable (GL_POLYGON_OFFSET_FILL); int showtrias = vispar.showstltrias; if (showtrias) { float mat_coll[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_coll); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glCallList (trilists.Get(1)); } /* glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { const STLTriangle & tria = stlgeometry -> GetTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); for (k = 0; k < 3; k++) { glVertex3f (tria.pts[k].X(), tria.pts[k].Y(), tria.pts[k].Z()); } } glEnd (); */ glPopMatrix(); glFinish(); } void VisualSceneSTLGeometry :: BuildScene (int zoomall) { // cout << "rebuild stl geometry scene" << endl; center = stlgeometry -> GetBoundingBox().Center(); rad = stlgeometry -> GetBoundingBox().Diam() / 2; CalcTransformationMatrices(); for (int i = 1; i <= trilists.Size(); i++) glDeleteLists (trilists.Elem(i), 1); trilists.SetSize(0); trilists.Append (glGenLists (1)); glNewList (trilists.Last(), GL_COMPILE); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (int j = 1; j <= stlgeometry -> GetNT(); j++) { const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); for (int k = 1; k <= 3; k++) { const Point3d & p = stlgeometry->GetPoint (stlgeometry -> GetTriangle(j).PNum(k)); glVertex3f (p.X(),p.Y(), p.Z()); } } glEnd (); glEndList (); } } #ifdef NG_PYTHON #ifdef WIN32 #define DLL_HEADER __declspec(dllexport) #endif #include <../general/ngpython.hpp> DLL_HEADER void ExportSTLVis(py::module &m) { using namespace netgen; py::class_> (m, "VisualSceneSTLGeometry") .def("Draw", &VisualSceneSTLGeometry::DrawScene) ; m.def("SetBackGroundColor", &VisualSceneSTLGeometry::SetBackGroundColor); m.def("VS", [](STLGeometry & geom) { auto vs = make_shared(); vs->SetGeometry(&geom); return vs; }); } PYBIND11_MODULE(libstlvis, m) { ExportSTLVis(m); } #endif netgen-6.2.1905/libsrc/stlgeom/stlpkg.cpp0000644000175000017500000003512513504650527016747 0ustar kurtkurt#include #include #include #include #include #include #include #include #include "vsstl.hpp" extern "C" int Ng_STL_Init (Tcl_Interp * interp); namespace netgen { DLL_HEADER extern shared_ptr ng_geometry; DLL_HEADER extern shared_ptr mesh; static VisualSceneSTLGeometry vsstlgeom; static VisualSceneSTLMeshing vsstlmeshing; char * err_needsstlgeometry = (char*) "This operation needs an STL geometry"; class STLGeometryVisRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const { return NULL; } virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const; virtual void SetParameters (Tcl_Interp * interp) { stlparam.yangle = atof (Tcl_GetVar (interp, "::stloptions.yangle", 0)); stlparam.contyangle = atof (Tcl_GetVar (interp, "::stloptions.contyangle", 0)); stlparam.edgecornerangle = atof (Tcl_GetVar (interp, "::stloptions.edgecornerangle", 0)); stlparam.chartangle = atof (Tcl_GetVar (interp, "::stloptions.chartangle", 0)); stlparam.outerchartangle = atof (Tcl_GetVar (interp, "::stloptions.outerchartangle", 0)); stlparam.usesearchtree = atoi (Tcl_GetVar (interp, "::stloptions.usesearchtree", 0)); stlparam.atlasminh = atof (Tcl_GetVar (interp, "::stloptions.atlasminh", 0)); stlparam.resthsurfcurvfac = atof (Tcl_GetVar (interp, "::stloptions.resthsurfcurvfac", 0)); stlparam.resthsurfcurvenable = atoi (Tcl_GetVar (interp, "::stloptions.resthsurfcurvenable", 0)); stlparam.resthatlasfac = atof (Tcl_GetVar (interp, "::stloptions.resthatlasfac", 0)); stlparam.resthatlasenable = atoi (Tcl_GetVar (interp, "::stloptions.resthatlasenable", 0)); stlparam.resthchartdistfac = atof (Tcl_GetVar (interp, "::stloptions.resthchartdistfac", 0)); stlparam.resthchartdistenable = atoi (Tcl_GetVar (interp, "::stloptions.resthchartdistenable", 0)); stlparam.resthlinelengthfac = atof (Tcl_GetVar (interp, "::stloptions.resthlinelengthfac", 0)); stlparam.resthlinelengthenable = atoi (Tcl_GetVar (interp, "::stloptions.resthlinelengthenable", 0)); stlparam.resthcloseedgefac = atof (Tcl_GetVar (interp, "::stloptions.resthcloseedgefac", 0)); stlparam.resthcloseedgeenable = atoi (Tcl_GetVar (interp, "::stloptions.resthcloseedgeenable", 0)); stlparam.resthedgeanglefac = atof (Tcl_GetVar (interp, "::stloptions.resthedgeanglefac", 0)); stlparam.resthedgeangleenable = atoi (Tcl_GetVar (interp, "::stloptions.resthedgeangleenable", 0)); stlparam.resthsurfmeshcurvfac = atof (Tcl_GetVar (interp, "::stloptions.resthsurfmeshcurvfac", 0)); stlparam.resthsurfmeshcurvenable = atoi (Tcl_GetVar (interp, "::stloptions.resthsurfmeshcurvenable", 0)); stlparam.recalc_h_opt = atoi (Tcl_GetVar (interp, "::stloptions.recalchopt", 0)); // stlparam.Print (cout); } }; int Ng_SetSTLParameters (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { STLGeometryVisRegister reg; reg.SetParameters (interp); return TCL_OK; } int Ng_STLDoctor (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { //cout << "STL doctor" << endl; STLGeometry * stlgeometry = dynamic_cast (ng_geometry.get()); stldoctor.drawmeshededges = atoi (Tcl_GetVar (interp, "::stldoctor.drawmeshededges", 0)); stldoctor.geom_tol_fact = atof (Tcl_GetVar (interp, "::stldoctor.geom_tol_fact", 0)); stldoctor.useexternaledges = atoi (Tcl_GetVar (interp, "::stldoctor.useexternaledges", 0)); stldoctor.showfaces = atoi (Tcl_GetVar (interp, "::stldoctor.showfaces", 0)); stldoctor.conecheck = atoi (Tcl_GetVar (interp, "::stldoctor.conecheck", 0)); stldoctor.spiralcheck = atoi (Tcl_GetVar (interp, "::stldoctor.spiralcheck", 0)); stldoctor.selectwithmouse = atoi (Tcl_GetVar (interp, "::stldoctor.selectwithmouse", 0)); stldoctor.showedgecornerpoints = atoi (Tcl_GetVar (interp, "::stldoctor.showedgecornerpoints", 0)); stldoctor.showmarkedtrigs = atoi (Tcl_GetVar (interp, "::stldoctor.showmarkedtrigs", 0)); stldoctor.showtouchedtrigchart = atoi (Tcl_GetVar (interp, "::stldoctor.showtouchedtrigchart", 0)); //cout << "smt=" << stldoctor.showmarkedtrigs << endl; stldoctor.dirtytrigfact = atof (Tcl_GetVar (interp, "::stldoctor.dirtytrigfact", 0)); stldoctor.smoothnormalsweight = atof (Tcl_GetVar (interp, "::stldoctor.smoothnormalsweight", 0)); stldoctor.smoothangle = atof (Tcl_GetVar (interp, "::stldoctor.smoothangle", 0)); stldoctor.selectmode = atoi (Tcl_GetVar (interp, "::stldoctor.selectmode", 0)); stldoctor.edgeselectmode = atoi (Tcl_GetVar (interp, "::stldoctor.edgeselectmode", 0)); stldoctor.longlinefact = atoi (Tcl_GetVar (interp, "::stldoctor.longlinefact", 0)); stldoctor.showexcluded = atoi (Tcl_GetVar (interp, "::stldoctor.showexcluded", 0)); if (!stldoctor.selectwithmouse) { stldoctor.selecttrig = atoi (Tcl_GetVar (interp, "::stldoctor.selecttrig", 0)); stldoctor.nodeofseltrig = atoi (Tcl_GetVar (interp, "::stldoctor.nodeofseltrig", 0)); } stldoctor.showvicinity = atoi (Tcl_GetVar (interp, "::stldoctor.showvicinity", 0)); stldoctor.vicinity = atoi (Tcl_GetVar (interp, "::stldoctor.vicinity", 0)); if (argc >= 2) { if (!stlgeometry) { Tcl_SetResult (interp, err_needsstlgeometry, TCL_STATIC); return TCL_ERROR; } if (strcmp (argv[1], "destroy0trigs") == 0) { stlgeometry->DestroyDirtyTrigs(); } else if (strcmp (argv[1], "movepointtomiddle") == 0) { stlgeometry->MoveSelectedPointToMiddle(); } else if (strcmp (argv[1], "calcnormals") == 0) { stlgeometry->CalcNormalsFromGeometry(); } else if (strcmp (argv[1], "showchartnum") == 0) { stlgeometry->ShowSelectedTrigChartnum(); } else if (strcmp (argv[1], "showcoords") == 0) { stlgeometry->ShowSelectedTrigCoords(); } else if (strcmp (argv[1], "loadmarkedtrigs") == 0) { stlgeometry->LoadMarkedTrigs(); } else if (strcmp (argv[1], "savemarkedtrigs") == 0) { stlgeometry->SaveMarkedTrigs(); } else if (strcmp (argv[1], "neighbourangles") == 0) { stlgeometry->NeighbourAnglesOfSelectedTrig(); } else if (strcmp (argv[1], "vicinity") == 0) { stlgeometry->CalcVicinity(stldoctor.selecttrig); } else if (strcmp (argv[1], "markdirtytrigs") == 0) { stlgeometry->MarkDirtyTrigs(); } else if (strcmp (argv[1], "smoothdirtytrigs") == 0) { stlgeometry->SmoothDirtyTrigs(); } else if (strcmp (argv[1], "smoothrevertedtrigs") == 0) { stlgeometry->GeomSmoothRevertedTrigs(); } else if (strcmp (argv[1], "invertselectedtrig") == 0) { stlgeometry->InvertTrig(stlgeometry->GetSelectTrig()); } else if (strcmp (argv[1], "deleteselectedtrig") == 0) { stlgeometry->DeleteTrig(stlgeometry->GetSelectTrig()); } else if (strcmp (argv[1], "smoothgeometry") == 0) { stlgeometry->SmoothGeometry(); } else if (strcmp (argv[1], "orientafterselectedtrig") == 0) { stlgeometry->OrientAfterTrig(stlgeometry->GetSelectTrig()); } else if (strcmp (argv[1], "marktoperrortrigs") == 0) { stlgeometry->MarkTopErrorTrigs(); } else if (strcmp (argv[1], "exportedges") == 0) { stlgeometry->ExportEdges(); } else if (strcmp (argv[1], "importedges") == 0) { stlgeometry->ImportEdges(); } else if (strcmp (argv[1], "importexternaledges") == 0) { stlgeometry->ImportExternalEdges(argv[2]); } else if (strcmp (argv[1], "loadedgedata") == 0) { if (argc >= 3) { stlgeometry->LoadEdgeData(argv[2]); } } else if (strcmp (argv[1], "saveedgedata") == 0) { if (argc >= 3) { stlgeometry->SaveEdgeData(argv[2]); } } else if (strcmp (argv[1], "buildexternaledges") == 0) { stlgeometry->BuildExternalEdgesFromEdges(); } else if (strcmp (argv[1], "smoothnormals") == 0) { stlgeometry->SmoothNormals(); } else if (strcmp (argv[1], "marknonsmoothnormals") == 0) { stlgeometry->MarkNonSmoothNormals(); } else if (strcmp (argv[1], "addexternaledge") == 0) { stlgeometry->AddExternalEdgeAtSelected(); } else if (strcmp (argv[1], "addgeomline") == 0) { stlgeometry->AddExternalEdgesFromGeomLine(); } else if (strcmp (argv[1], "addlonglines") == 0) { stlgeometry->AddLongLinesToExternalEdges(); } else if (strcmp (argv[1], "addclosedlines") == 0) { stlgeometry->AddClosedLinesToExternalEdges(); } else if (strcmp (argv[1], "addnotsinglelines") == 0) { stlgeometry->AddAllNotSingleLinesToExternalEdges(); } else if (strcmp (argv[1], "deletedirtyexternaledges") == 0) { stlgeometry->DeleteDirtyExternalEdges(); } else if (strcmp (argv[1], "deleteexternaledge") == 0) { stlgeometry->DeleteExternalEdgeAtSelected(); } else if (strcmp (argv[1], "deletevicexternaledge") == 0) { stlgeometry->DeleteExternalEdgeInVicinity(); } else if (strcmp (argv[1], "addlonglines") == 0) { stlgeometry->STLDoctorLongLinesToCandidates(); } else if (strcmp (argv[1], "deletedirtyedges") == 0) { stlgeometry->STLDoctorDirtyEdgesToCandidates(); } else if (strcmp (argv[1], "undoedgechange") == 0) { stlgeometry->UndoEdgeChange(); } else if (strcmp (argv[1], "buildedges") == 0) { stlgeometry->STLDoctorBuildEdges(); } else if (strcmp (argv[1], "confirmedge") == 0) { stlgeometry->STLDoctorConfirmEdge(); } else if (strcmp (argv[1], "candidateedge") == 0) { stlgeometry->STLDoctorCandidateEdge(); } else if (strcmp (argv[1], "excludeedge") == 0) { stlgeometry->STLDoctorExcludeEdge(); } else if (strcmp (argv[1], "undefinededge") == 0) { stlgeometry->STLDoctorUndefinedEdge(); } else if (strcmp (argv[1], "setallundefinededges") == 0) { stlgeometry->STLDoctorSetAllUndefinedEdges(); } else if (strcmp (argv[1], "erasecandidateedges") == 0) { stlgeometry->STLDoctorEraseCandidateEdges(); } else if (strcmp (argv[1], "confirmcandidateedges") == 0) { stlgeometry->STLDoctorConfirmCandidateEdges(); } else if (strcmp (argv[1], "confirmedtocandidateedges") == 0) { stlgeometry->STLDoctorConfirmedToCandidateEdges(); } } return TCL_OK; } int Ng_STLInfo (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { double data[10]; static char buf[20]; STLGeometry * stlgeometry = dynamic_cast (ng_geometry.get()); if (!stlgeometry) { Tcl_SetResult (interp, err_needsstlgeometry, TCL_STATIC); return TCL_ERROR; } if (stlgeometry) { stlgeometry->STLInfo(data); // cout << "NT=" << data[0] << endl; if (argc == 2) { if (strcmp (argv[1], "status") == 0) { switch (stlgeometry->GetStatus()) { case STLGeometry::STL_GOOD: strcpy (buf, "GOOD"); break; case STLGeometry::STL_WARNING: strcpy (buf, "WARNING"); break; case STLGeometry::STL_ERROR: strcpy (buf, "ERROR"); break; } Tcl_SetResult (interp, buf, TCL_STATIC); return TCL_OK; } if (strcmp (argv[1], "statustext") == 0) { Tcl_SetResult (interp, (char*)stlgeometry->GetStatusText().c_str(), TCL_STATIC); return TCL_OK; } if (strcmp (argv[1], "topology_ok") == 0) { sprintf (buf, "%d", stlgeometry->Topology_Ok()); Tcl_SetResult (interp, buf, TCL_STATIC); } if (strcmp (argv[1], "orientation_ok") == 0) { sprintf (buf, "%d", stlgeometry->Orientation_Ok()); Tcl_SetResult (interp, buf, TCL_STATIC); } } } else { data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; data[4] = 0; data[5] = 0; data[6] = 0; data[7] = 0; } sprintf (buf, "%i", (int)data[0]); Tcl_SetVar (interp, argv[1], buf, 0); sprintf (buf, "%5.3g", data[1]); Tcl_SetVar (interp, argv[2], buf, 0); sprintf (buf, "%5.3g", data[2]); Tcl_SetVar (interp, argv[3], buf, 0); sprintf (buf, "%5.3g", data[3]); Tcl_SetVar (interp, argv[4], buf, 0); sprintf (buf, "%5.3g", data[4]); Tcl_SetVar (interp, argv[5], buf, 0); sprintf (buf, "%5.3g", data[5]); Tcl_SetVar (interp, argv[6], buf, 0); sprintf (buf, "%5.3g", data[6]); Tcl_SetVar (interp, argv[7], buf, 0); sprintf (buf, "%i", (int)data[7]); Tcl_SetVar (interp, argv[8], buf, 0); return TCL_OK; } extern int Ng_SetMeshingParameters (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]); int Ng_STLCalcLocalH (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { for (int i = 0; i < geometryregister.Size(); i++) geometryregister[i] -> SetParameters (interp); Ng_SetMeshingParameters (clientData, interp, argc, argv); STLGeometry * stlgeometry = dynamic_cast (ng_geometry.get()); if (mesh && stlgeometry) { mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), mparam.grading); stlgeometry -> RestrictLocalH(*mesh, mparam.maxh); if (stlparam.resthsurfmeshcurvenable) mesh -> CalcLocalHFromSurfaceCurvature (mparam.grading, stlparam.resthsurfmeshcurvfac); } return TCL_OK; } VisualScene * STLGeometryVisRegister :: GetVisualScene (const NetgenGeometry * geom) const { const STLGeometry * geometry = dynamic_cast (geom); if (geometry) { vsstlmeshing.SetGeometry (const_cast (geometry)); return &vsstlmeshing; } return NULL; } } using namespace netgen; extern "C" int Ng_stl_Init (Tcl_Interp * interp); int Ng_stl_Init (Tcl_Interp * interp) { geometryregister.Append (new STLGeometryVisRegister); Tcl_CreateCommand (interp, "Ng_SetSTLParameters", Ng_SetSTLParameters, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_STLDoctor", Ng_STLDoctor, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_STLInfo", Ng_STLInfo, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_STLCalcLocalH", Ng_STLCalcLocalH, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); return TCL_OK; } netgen-6.2.1905/libsrc/stlgeom/stlline.cpp0000644000175000017500000003565613504650527017126 0ustar kurtkurt#include #include #include #include #include #include "stlgeom.hpp" namespace netgen { //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++ EDGE DATA ++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /* void STLEdgeData :: Write(ofstream& of) const { of // << angle << " " << p1 << " " << p2 << " " << lt << " " << rt << " " // << status << endl; } void STLEdgeData :: Read(ifstream& ifs) { // ifs >> angle; ifs >> p1; ifs >> p2; ifs >> lt; ifs >> rt; // ifs >> status; } int STLEdgeData :: GetStatus () const { if (topedgenr <= 0 || topedgenr > top->GetNTE()) return 0; return top->GetTopEdge (topedgenr).GetStatus(); } void STLEdgeData ::SetStatus (int stat) { if (topedgenr >= 1 && topedgenr <= top->GetNTE()) top->GetTopEdge (topedgenr).SetStatus(stat); } float STLEdgeData :: CosAngle() const { return top->GetTopEdge (topedgenr).CosAngle(); } void STLEdgeDataList :: ResetAll() { int i; for (i = 1; i <= edgedata.Size(); i++) { edgedata.Elem(i).SetUndefined(); } } void STLEdgeDataList :: ResetCandidates() { int i; for (i = 1; i <= edgedata.Size(); i++) { if (edgedata.Get(i).Candidate()) {edgedata.Elem(i).SetUndefined();} } } int STLEdgeDataList :: GetNConfEdges() const { int i; int cnt = 0; for (i = 1; i <= edgedata.Size(); i++) { if (edgedata.Get(i).Confirmed()) {cnt++;} } return cnt; } void STLEdgeDataList :: ConfirmCandidates() { int i; for (i = 1; i <= edgedata.Size(); i++) { if (edgedata.Get(i).Candidate()) {edgedata.Elem(i).SetConfirmed();} } } int STLEdgeDataList :: GetEdgeNum(int np1, int np2) const { INDEX_2 ed(np1,np2); ed.Sort(); if (hashtab.Used(ed)) { return hashtab.Get(ed); } // int i; // for (i = 1; i <= Size(); i++) // { // if ((Get(i).p1 == np1 && Get(i).p2 == np2) || // (Get(i).p2 == np1 && Get(i).p1 == np2)) // { // return i; // } // } return 0; } const STLEdgeDataList& STLEdgeDataList :: operator=(const STLEdgeDataList& edl) { int i; SetSize(edl.Size()); for (i = 1; i <= Size(); i++) { Add(edl.Get(i), i); } return *this; } void STLEdgeDataList :: Add(const STLEdgeData& ed, int i) { INDEX_2 edge(ed.p1,ed.p2); edge.Sort(); hashtab.Set(edge, i); Elem(i) = ed; AddEdgePP(ed.p1,i); AddEdgePP(ed.p2,i); } void STLEdgeDataList :: Write(ofstream& of) const { of.precision(16); int i; of << Size() << endl; for (i = 1; i <= Size(); i++) { Get(i).Write(of); } } void STLEdgeDataList :: Read(ifstream& ifs) { int i,n; ifs >> n; SetSize(n); STLEdgeData ed; for (i = 1; i <= n; i++) { ed.Read(ifs); Add(ed,i); } } int STLEdgeDataList :: GetNEPPStat(int p, int status) const { int i; int cnt = 0; for (i = 1; i <= GetNEPP(p); i++) { if (Get(GetEdgePP(p,i)).GetStatus() == status) { cnt++; } } return cnt; } int STLEdgeDataList :: GetNConfCandEPP(int p) const { int i; int cnt = 0; for (i = 1; i <= GetNEPP(p); i++) { if (Get(GetEdgePP(p,i)).ConfCand()) { cnt++; } } return cnt; } void STLEdgeDataList :: BuildLineWithEdge(int ep1, int ep2, Array& line) { int status = Get(GetEdgeNum(ep1,ep2)).GetStatus(); int found, pstart, p, en, pnew, ennew; int closed = 0; int j, i; for (j = 1; j <= 2; j++) { if (j == 1) {p = ep1;} if (j == 2) {p = ep2;} pstart = p; en = GetEdgeNum(ep1,ep2); found = 1; while (found && !closed) { found = 0; if (GetNEPPStat(p,status) == 2) { for (i = 1; i <= GetNEPP(p); i++) { const STLEdgeData& e = Get(GetEdgePP(p,i)); if (GetEdgePP(p,i) != en && e.GetStatus() == status) { if (e.p1 == p) {pnew = e.p2;} else {pnew = e.p1;} ennew = GetEdgePP(p,i); } } if (pnew == pstart) {closed = 1;} else { line.Append(twoint(p,pnew)); p = pnew; en = ennew; found = 1; } } } } } */ STLEdgeDataList :: STLEdgeDataList (STLTopology & ageom) : geom(ageom) { ; } STLEdgeDataList :: ~STLEdgeDataList() { ; } void STLEdgeDataList :: Store () { int i, ne = geom.GetNTE(); storedstatus.SetSize(ne); for (i = 1; i <= ne; i++) { storedstatus.Elem(i) = Get(i).GetStatus(); } } void STLEdgeDataList :: Restore () { int i, ne = geom.GetNTE(); if (storedstatus.Size() == ne) for (i = 1; i <= ne; i++) geom.GetTopEdge(i).SetStatus (storedstatus.Elem(i)); } void STLEdgeDataList :: ResetAll() { int i, ne = geom.GetNTE(); for (i = 1; i <= ne; i++) geom.GetTopEdge (i).SetStatus (ED_UNDEFINED); } int STLEdgeDataList :: GetNConfEdges() const { int i, ne = geom.GetNTE(); int cnt = 0; for (i = 1; i <= ne; i++) if (geom.GetTopEdge (i).GetStatus() == ED_CONFIRMED) cnt++; return cnt; } void STLEdgeDataList :: ChangeStatus(int status1, int status2) { int i, ne = geom.GetNTE(); for (i = 1; i <= ne; i++) if (geom.GetTopEdge (i).GetStatus() == status1) geom.GetTopEdge (i).SetStatus (status2); } /* void STLEdgeDataList :: Add(const STLEdgeData& ed, int i) { INDEX_2 edge(ed.p1,ed.p2); edge.Sort(); hashtab.Set(edge, i); Elem(i) = ed; AddEdgePP(ed.p1,i); AddEdgePP(ed.p2,i); } */ void STLEdgeDataList :: Write(ofstream& of) const { /* of.precision(16); int i; of << Size() << endl; for (i = 1; i <= Size(); i++) { Get(i).Write(of); } */ of.precision(16); int i, ne = geom.GetNTE(); //of << GetNConfEdges() << endl; of << geom.GetNTE() << endl; for (i = 1; i <= ne; i++) { const STLTopEdge & edge = geom.GetTopEdge(i); //if (edge.GetStatus() == ED_CONFIRMED) of << edge.GetStatus() << " "; const Point3d & p1 = geom.GetPoint (edge.PNum(1)); const Point3d & p2 = geom.GetPoint (edge.PNum(2)); of << p1.X() << " " << p1.Y() << " " << p1.Z() << " " << p2.X() << " " << p2.Y() << " " << p2.Z() << endl; } } void STLEdgeDataList :: Read(ifstream& ifs) { int i, nce; Point3d p1, p2; int pi1, pi2; int status, ednum; ifs >> nce; for (i = 1; i <= nce; i++) { ifs >> status; ifs >> p1.X() >> p1.Y() >> p1.Z(); ifs >> p2.X() >> p2.Y() >> p2.Z(); pi1 = geom.GetPointNum (p1); pi2 = geom.GetPointNum (p2); ednum = geom.GetTopEdgeNum (pi1, pi2); if (ednum) { geom.GetTopEdge(ednum).SetStatus (status); // geom.GetTopEdge (ednum).SetStatus (ED_CONFIRMED); } } /* int i,n; ifs >> n; SetSize(n); STLEdgeData ed; for (i = 1; i <= n; i++) { ed.Read(ifs); Add(ed,i); } */ } int STLEdgeDataList :: GetNEPPStat(int p, int status) const { int i; int cnt = 0; for (i = 1; i <= GetNEPP(p); i++) { if (Get(GetEdgePP(p,i)).GetStatus() == status) { cnt++; } } return cnt; } int STLEdgeDataList :: GetNConfCandEPP(int p) const { int i; int cnt = 0; for (i = 1; i <= GetNEPP(p); i++) { if (Get(GetEdgePP(p,i)).GetStatus() == ED_CANDIDATE || Get(GetEdgePP(p,i)).GetStatus() == ED_CONFIRMED) { cnt++; } } return cnt; } void STLEdgeDataList :: BuildLineWithEdge(int ep1, int ep2, Array& line) { int status = Get(GetEdgeNum(ep1,ep2)).GetStatus(); int found, pstart, p(0), en, pnew(0), ennew(0); int closed = 0; int j, i; for (j = 1; j <= 2; j++) { if (j == 1) {p = ep1;} if (j == 2) {p = ep2;} pstart = p; en = GetEdgeNum(ep1,ep2); found = 1; while (found && !closed) { found = 0; if (GetNEPPStat(p,status) == 2) { for (i = 1; i <= GetNEPP(p); i++) { const STLTopEdge & e = Get(GetEdgePP(p,i)); if (GetEdgePP(p,i) != en && e.GetStatus() == status) { if (e.PNum(1) == p) {pnew = e.PNum(2);} else {pnew = e.PNum(1);} ennew = GetEdgePP(p,i); } } if (pnew == pstart) {closed = 1;} else { line.Append(twoint(p,pnew)); p = pnew; en = ennew; found = 1; } } } } } int Exists(int p1, int p2, const Array& line) { int i; for (i = 1; i <= line.Size(); i++) { if ( (line.Get(i).i1 == p1 && line.Get(i).i2 == p2) || (line.Get(i).i1 == p2 && line.Get(i).i2 == p1) ) {return 1;} } return 0; } void STLEdgeDataList :: BuildClusterWithEdge(int ep1, int ep2, Array& line) { int status = Get(GetEdgeNum(ep1,ep2)).GetStatus(); int p(0), en; int j, i, k; int oldend; int newend = 1; int pnew, ennew(0); int changed = 1; while (changed) { changed = 0; for (j = 1; j <= 2; j++) { oldend = newend; newend = line.Size(); for (k = oldend; k <= line.Size(); k++) { if (j == 1) p = line.Get(k).i1; if (j == 2) p = line.Get(k).i2; en = GetEdgeNum(line.Get(k).i1, line.Get(k).i2); for (i = 1; i <= GetNEPP(p); i++) { pnew = 0; const STLTopEdge & e = Get(GetEdgePP(p,i)); if (GetEdgePP(p,i) != en && e.GetStatus() == status) { if (e.PNum(1) == p) {pnew = e.PNum(2);} else {pnew = e.PNum(1);} ennew = GetEdgePP(p,i); } if (pnew && !Exists(p,pnew,line)) { changed = 1; line.Append(twoint(p,pnew)); p = pnew; en = ennew; } } } } } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++ STL LINE +++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STLLine :: STLLine(const STLGeometry * ageometry) : pts(), lefttrigs(), righttrigs() { geometry = ageometry; split = 0; }; int STLLine :: GetNS() const { if (pts.Size() <= 1) {return 0;} return pts.Size()-1; } void STLLine :: GetSeg(int nr, int& p1, int& p2) const { p1 = pts.Get(nr); p2 = pts.Get(nr+1); } int STLLine :: GetLeftTrig(int nr) const { if (nr > lefttrigs.Size()) {PrintSysError("In STLLine::GetLeftTrig!!!"); return 0;} return lefttrigs.Get(nr); }; int STLLine :: GetRightTrig(int nr) const { if (nr > righttrigs.Size()) {PrintSysError("In STLLine::GetRightTrig!!!"); return 0;} return righttrigs.Get(nr); }; double STLLine :: GetSegLen(const Array >& ap, int nr) const { return Dist(ap.Get(PNum(nr)),ap.Get(PNum(nr+1))); } double STLLine :: GetLength(const Array >& ap) const { double len = 0; for (int i = 2; i <= pts.Size(); i++) { len += (ap.Get(pts.Get(i)) - ap.Get(pts.Get(i-1))).Length(); } return len; } void STLLine :: GetBoundingBox (const Array > & ap, Box<3> & box) const { box.Set (ap.Get (pts[0])); for (int i = 1; i < pts.Size(); i++) box.Add (ap.Get(pts[i])); } Point<3> STLLine :: GetPointInDist(const Array >& ap, double dist, int& index) const { if (dist <= 0) { index = 1; return ap.Get(StartP()); } double len = 0; int i; for (i = 1; i < pts.Size(); i++) { double seglen = Dist (ap.Get(pts.Get(i)), ap.Get(pts.Get(i+1))); if (len + seglen > dist) { index = i; double relval = (dist - len) / (seglen + 1e-16); Vec3d v (ap.Get(pts.Get(i)), ap.Get(pts.Get(i+1))); return ap.Get(pts.Get(i)) + relval * v; } len += seglen; } index = pts.Size() - 1; return ap.Get(EndP()); } /* double stlgh; double GetH(const Point3d& p, double x) { return stlgh;//+0.5)*(x+0.5); } */ STLLine* STLLine :: Mesh(const Array >& ap, Array& mp, double ghi, class Mesh& mesh) const { static int timer1a = NgProfiler::CreateTimer ("mesh stl-line 1a"); static int timer1b = NgProfiler::CreateTimer ("mesh stl-line 1b"); static int timer2 = NgProfiler::CreateTimer ("mesh stl-line 2"); static int timer3 = NgProfiler::CreateTimer ("mesh stl-line 3"); NgProfiler::StartTimer (timer1a); STLLine* line = new STLLine(geometry); //stlgh = ghi; //uebergangsloesung!!!! double len = GetLength(ap); double inthl = 0; //integral of 1/h double dist = 0; double h; int ind; Point3d p; Box<3> bbox; GetBoundingBox (ap, bbox); double diam = bbox.Diam(); double minh = mesh.LocalHFunction().GetMinH (bbox.PMin(), bbox.PMax()); double maxseglen = 0; for (int i = 1; i <= GetNS(); i++) maxseglen = max2 (maxseglen, GetSegLen (ap, i)); int nph = 10+int(maxseglen / minh); //anzahl der integralauswertungen pro segment Array inthi(GetNS()*nph); Array curvelen(GetNS()*nph); NgProfiler::StopTimer (timer1a); NgProfiler::StartTimer (timer1b); for (int i = 1; i <= GetNS(); i++) { //double seglen = GetSegLen(ap,i); for (int j = 1; j <= nph; j++) { p = GetPointInDist(ap,dist,ind); //h = GetH(p,dist/len); h = mesh.GetH(p); dist += GetSegLen(ap,i)/(double)nph; inthl += GetSegLen(ap,i)/nph/(h); inthi.Elem((i-1)*nph+j) = GetSegLen(ap,i)/nph/h; curvelen.Elem((i-1)*nph+j) = GetSegLen(ap,i)/nph; } } int inthlint = int(inthl+1); if ( (inthlint < 3) && (StartP() == EndP())) { inthlint = 3; } if ( (inthlint == 1) && ShouldSplit()) { inthlint = 2; } double fact = inthl/(double)inthlint; dist = 0; int j = 1; p = ap.Get(StartP()); int pn = AddPointIfNotExists(mp, p, 1e-10*diam); int segn = 1; line->AddPoint(pn); line->AddLeftTrig(GetLeftTrig(segn)); line->AddRightTrig(GetRightTrig(segn)); line->AddDist(dist); NgProfiler::StopTimer (timer1b); NgProfiler::StartTimer (timer2); inthl = 0; //restart each meshseg for (int i = 1; i <= inthlint; i++) { while (inthl < 1.000000001 && j <= inthi.Size()) { inthl += inthi.Get(j)/fact; dist += curvelen.Get(j); j++; } //went too far: j--; double tofar = (inthl - 1)/inthi.Get(j); inthl -= tofar*inthi.Get(j); dist -= tofar*curvelen.Get(j)*fact; if (i == inthlint && fabs(dist - len) >= 1E-8) { PrintSysError("meshline failed!!!"); } if (i != inthlint) { p = GetPointInDist(ap,dist,ind); pn = AddPointIfNotExists(mp, p, 1e-10*diam); segn = ind; line->AddPoint(pn); line->AddLeftTrig(GetLeftTrig(segn)); line->AddRightTrig(GetRightTrig(segn)); line->AddDist(dist); } inthl = tofar*inthi.Get(j); dist += tofar*curvelen.Get(j)*fact; j++; } NgProfiler::StopTimer (timer2); NgProfiler::StartTimer (timer3); p = ap.Get(EndP()); pn = AddPointIfNotExists(mp, p, 1e-10*diam); segn = GetNS(); line->AddPoint(pn); line->AddLeftTrig(GetLeftTrig(segn)); line->AddRightTrig(GetRightTrig(segn)); line->AddDist(dist); for (int ii = 1; ii <= line->GetNS(); ii++) { int p1, p2; line->GetSeg(ii,p1,p2); } /* (*testout) << "line, " << ap.Get(StartP()) << "-" << ap.Get(EndP()) << " len = " << Dist (ap.Get(StartP()), ap.Get(EndP())) << endl; */ NgProfiler::StopTimer (timer3); return line; } } netgen-6.2.1905/libsrc/stlgeom/meshstlsurface.cpp0000644000175000017500000006703413504650527020477 0ustar kurtkurt#include #include #include #include #include #include "stlgeom.hpp" namespace netgen { static void STLFindEdges (STLGeometry & geom, class Mesh & mesh) { double h = mparam.maxh; // mark edge points: //int ngp = geom.GetNP(); geom.RestrictLocalH(mesh, h); PushStatusF("Mesh Lines"); Array meshlines; Array meshpoints; PrintMessage(3,"Mesh Lines"); /* cout << geom.GetNLines() << " lines" << endl; double totnp = 0; for (int i = 1; i <= geom.GetNLines(); i++) totnp += geom.GetLine(i)->NP(); cout << "avg np per line " << totnp/geom.GetNLines() << endl; */ for (int i = 1; i <= geom.GetNLines(); i++) { meshlines.Append(geom.GetLine(i)->Mesh(geom.GetPoints(), meshpoints, h, mesh)); SetThreadPercent(100.0 * (double)i/(double)geom.GetNLines()); } geom.meshpoints.SetSize(0); //testing geom.meshlines.SetSize(0); //testing for (int i = 1; i <= meshpoints.Size(); i++) { geom.meshpoints.Append(meshpoints.Get(i)); //testing mesh.AddPoint(meshpoints.Get(i)); } //(++++++++++++++testing for (int i = 1; i <= geom.GetNLines(); i++) { geom.meshlines.Append(meshlines.Get(i)); } //++++++++++++++testing) PrintMessage(7,"feed with edges"); for (int i = 1; i <= meshlines.Size(); i++) { STLLine* line = meshlines.Get(i); (*testout) << "store line " << i << endl; for (int j = 1; j <= line->GetNS(); j++) { int p1, p2; line->GetSeg(j, p1, p2); int trig1, trig2, trig1b, trig2b; if (p1 == p2) cout << "Add Segment, p1 == p2 == " << p1 << endl; // Test auf geschlossener Rand mit 2 Segmenten if ((j == 2) && (line->GetNS() == 2)) { int oldp1, oldp2; line->GetSeg (1, oldp1, oldp2); if (oldp1 == p2 && oldp2 == p1) { PrintMessage(7,"MESSAGE: don't use second segment"); continue; } } //mesh point number //p1 = geom2meshnum.Get(p1); // for unmeshed lines!!! //p2 = geom2meshnum.Get(p2); // for unmeshed lines!!! //left and right trigs trig1 = line->GetLeftTrig(j); trig2 = line->GetRightTrig(j); trig1b = line->GetLeftTrig(j+1); trig2b = line->GetRightTrig(j+1); (*testout) << "j = " << j << ", p1 = " << p1 << ", p2 = " << p2 << endl; (*testout) << "segm-trigs: " << "trig1 = " << trig1 << ", trig1b = " << trig1b << ", trig2 = " << trig2 << ", trig2b = " << trig2b << endl; if (trig1 <= 0 || trig2 <= 0 || trig1b <= 0 || trig2b <= 0) { cout << "negative trigs, " << ", trig1 = " << trig1 << ", trig1b = " << trig1b << ", trig2 = " << trig2 << ", trig2b = " << trig2b << endl; } /* (*testout) << " trigs p1: " << trig1 << " - " << trig2 << endl; (*testout) << " trigs p2: " << trig1b << " - " << trig2b << endl; (*testout) << " charts p1: " << geom.GetChartNr(trig1) << " - " << geom.GetChartNr(trig2) << endl; (*testout) << " charts p2: " << geom.GetChartNr(trig1b) << " - " << geom.GetChartNr(trig2b) << endl; */ Point3d hp, hp2; Segment seg; seg[0] = p1 + PointIndex::BASE-1; seg[1] = p2 + PointIndex::BASE-1; seg.si = geom.GetTriangle(trig1).GetFaceNum(); seg.edgenr = i; seg.epgeominfo[0].edgenr = i; seg.epgeominfo[0].dist = line->GetDist(j); seg.epgeominfo[1].edgenr = i; seg.epgeominfo[1].dist = line->GetDist(j+1); /* (*testout) << "seg = " << "edgenr " << seg.epgeominfo[0].edgenr << " dist " << seg.epgeominfo[0].dist << " edgenr " << seg.epgeominfo[1].edgenr << " dist " << seg.epgeominfo[1].dist << endl; */ seg.geominfo[0].trignum = trig1; seg.geominfo[1].trignum = trig1b; /* geom.SelectChartOfTriangle (trig1); hp = hp2 = mesh.Point (seg[0]); seg.geominfo[0].trignum = geom.Project (hp); (*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[0].trignum << endl; if (Dist (hp, hp2) > 1e-5 || seg.geominfo[0].trignum == 0) { (*testout) << "PROBLEM" << endl; } geom.SelectChartOfTriangle (trig1b); hp = hp2 = mesh.Point (seg[1]); seg.geominfo[1].trignum = geom.Project (hp); (*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[1].trignum << endl; if (Dist (hp, hp2) > 1e-5 || seg.geominfo[1].trignum == 0) { (*testout) << "PROBLEM" << endl; } */ if (Dist (mesh.Point(seg[0]), mesh.Point(seg[1])) < 1e-10) { (*testout) << "ERROR: Line segment of length 0" << endl; (*testout) << "pi1, 2 = " << seg[0] << ", " << seg[1] << endl; (*testout) << "p1, 2 = " << mesh.Point(seg[0]) << ", " << mesh.Point(seg[1]) << endl; throw NgException ("Line segment of length 0"); } mesh.AddSegment (seg); Segment seg2; seg2[0] = p2 + PointIndex::BASE-1;; seg2[1] = p1 + PointIndex::BASE-1;; seg2.si = geom.GetTriangle(trig2).GetFaceNum(); seg2.edgenr = i; seg2.epgeominfo[0].edgenr = i; seg2.epgeominfo[0].dist = line->GetDist(j+1); seg2.epgeominfo[1].edgenr = i; seg2.epgeominfo[1].dist = line->GetDist(j); /* (*testout) << "seg = " << "edgenr " << seg2.epgeominfo[0].edgenr << " dist " << seg2.epgeominfo[0].dist << " edgenr " << seg2.epgeominfo[1].edgenr << " dist " << seg2.epgeominfo[1].dist << endl; */ seg2.geominfo[0].trignum = trig2b; seg2.geominfo[1].trignum = trig2; /* geom.SelectChartOfTriangle (trig2); hp = hp2 = mesh.Point (seg[0]); seg2.geominfo[0].trignum = geom.Project (hp); (*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[0].trignum << endl; if (Dist (hp, hp2) > 1e-5 || seg2.geominfo[0].trignum == 0) { (*testout) << "Get GeomInfo PROBLEM" << endl; } geom.SelectChartOfTriangle (trig2b); hp = hp2 = mesh.Point (seg[1]); seg2.geominfo[1].trignum = geom.Project (hp); (*testout) << "hp = " << hp2 << ", hp proj = " << hp << ", trignum = " << seg.geominfo[1].trignum << endl; if (Dist (hp, hp2) > 1e-5 || seg2.geominfo[1].trignum == 0) { (*testout) << "Get GeomInfo PROBLEM" << endl; } */ mesh.AddSegment (seg2); } } PopStatus(); } void STLSurfaceMeshing1 (STLGeometry & geom, class Mesh & mesh, int retrynr); int STLSurfaceMeshing (STLGeometry & geom, class Mesh & mesh) { PrintFnStart("Do Surface Meshing"); geom.PrepareSurfaceMeshing(); if (mesh.GetNSeg() == 0) STLFindEdges (geom, mesh); int nopen; int outercnt = 20; for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment (i); if (seg.geominfo[0].trignum <= 0 || seg.geominfo[1].trignum <= 0) (*testout) << "Problem with segment " << i << ": " << seg << endl; } do { outercnt--; if (outercnt <= 0) return MESHING3_OUTERSTEPSEXCEEDED; if (multithread.terminate) return MESHING3_TERMINATE; mesh.FindOpenSegments(); nopen = mesh.GetNOpenSegments(); if (nopen) { int trialcnt = 0; while (nopen && trialcnt <= 5) { if (multithread.terminate) { return MESHING3_TERMINATE; } trialcnt++; STLSurfaceMeshing1 (geom, mesh, trialcnt); mesh.FindOpenSegments(); nopen = mesh.GetNOpenSegments(); if (nopen) { geom.ClearMarkedSegs(); for (int i = 1; i <= nopen; i++) { const Segment & seg = mesh.GetOpenSegment (i); geom.AddMarkedSeg(mesh.Point(seg[0]),mesh.Point(seg[1])); } geom.InitMarkedTrigs(); for (int i = 1; i <= nopen; i++) { const Segment & seg = mesh.GetOpenSegment (i); geom.SetMarkedTrig(seg.geominfo[0].trignum,1); geom.SetMarkedTrig(seg.geominfo[1].trignum,1); } MeshOptimizeSTLSurface optmesh(geom); optmesh.SetFaceIndex (0); optmesh.SetImproveEdges (0); optmesh.SetMetricWeight (0); mesh.CalcSurfacesOfNode(); optmesh.EdgeSwapping (mesh, 0); mesh.CalcSurfacesOfNode(); optmesh.ImproveMesh (mesh, mparam); } mesh.Compress(); mesh.FindOpenSegments(); nopen = mesh.GetNOpenSegments(); if (trialcnt <= 5 && nopen) { mesh.RemoveOneLayerSurfaceElements(); if (trialcnt >= 4) { mesh.FindOpenSegments(); mesh.RemoveOneLayerSurfaceElements(); mesh.FindOpenSegments (); nopen = mesh.GetNOpenSegments(); } } } if (multithread.terminate) return MESHING3_TERMINATE; if (nopen) { PrintMessage(3,"Meshing failed, trying to refine"); mesh.FindOpenSegments (); nopen = mesh.GetNOpenSegments(); mesh.FindOpenSegments (); mesh.RemoveOneLayerSurfaceElements(); mesh.FindOpenSegments (); mesh.RemoveOneLayerSurfaceElements(); // Open edge-segments will be refined ! INDEX_2_HASHTABLE openseght (nopen+1); for (int i = 1; i <= mesh.GetNOpenSegments(); i++) { const Segment & seg = mesh.GetOpenSegment (i); INDEX_2 i2(seg[0], seg[1]); i2.Sort(); openseght.Set (i2, 1); } mesh.FindOpenSegments (); mesh.RemoveOneLayerSurfaceElements(); mesh.FindOpenSegments (); mesh.RemoveOneLayerSurfaceElements(); INDEX_2_HASHTABLE newpht(100); int nsegold = mesh.GetNSeg(); for (int i = 1; i <= nsegold; i++) { Segment seg = mesh.LineSegment(i); INDEX_2 i2(seg[0], seg[1]); i2.Sort(); if (openseght.Used (i2)) { // segment will be split PrintMessage(7,"Split segment ", int(seg[0]), "-", int(seg[1])); Segment nseg1, nseg2; EdgePointGeomInfo newgi; const EdgePointGeomInfo & gi1 = seg.epgeominfo[0]; const EdgePointGeomInfo & gi2 = seg.epgeominfo[1]; newgi.dist = 0.5 * (gi1.dist + gi2.dist); newgi.edgenr = gi1.edgenr; int hi; Point3d newp; int newpi; if (!newpht.Used (i2)) { newp = geom.GetLine (gi1.edgenr)-> GetPointInDist (geom.GetPoints(), newgi.dist, hi); newpi = mesh.AddPoint (newp); newpht.Set (i2, newpi); } else { newpi = newpht.Get (i2); newp = mesh.Point (newpi); } nseg1 = seg; nseg2 = seg; nseg1[1] = newpi; nseg1.epgeominfo[1] = newgi; nseg2[0] = newpi; nseg2.epgeominfo[0] = newgi; mesh.LineSegment(i) = nseg1; mesh.AddSegment (nseg2); mesh.RestrictLocalH (Center (mesh.Point(nseg1[0]), mesh.Point(nseg1[1])), Dist (mesh.Point(nseg1[0]), mesh.Point(nseg1[1]))); mesh.RestrictLocalH (Center (mesh.Point(nseg2[0]), mesh.Point(nseg2[1])), Dist (mesh.Point(nseg2[0]), mesh.Point(nseg2[1]))); } } } nopen = -1; } else { PrintMessage(5,"mesh is closed, verifying ..."); // no open elements, check wrong elements (intersecting..) PrintMessage(5,"check overlapping"); // mesh.FindOpenElements(); // would leed to locked points if(mesh.CheckOverlappingBoundary()) return MESHING3_BADSURFACEMESH; geom.InitMarkedTrigs(); for (int i = 1; i <= mesh.GetNSE(); i++) if (mesh.SurfaceElement(i).BadElement()) { int trig = mesh.SurfaceElement(i).PNum(1); geom.SetMarkedTrig(trig,1); PrintMessage(7, "overlapping element, will be removed"); } Array refpts; Array refh; // was commented: for (int i = 1; i <= mesh.GetNSE(); i++) if (mesh.SurfaceElement(i).BadElement()) { for (int j = 1; j <= 3; j++) { refpts.Append (mesh.Point (mesh.SurfaceElement(i).PNum(j))); refh.Append (mesh.GetH (refpts.Last()) / 2); } mesh.DeleteSurfaceElement(i); } // delete wrong oriented element for (int i = 1; i <= mesh.GetNSE(); i++) { const Element2d & el = mesh.SurfaceElement(i); if (!el.PNum(1)) continue; Vec3d n = Cross (Vec3d (mesh.Point(el.PNum(1)), mesh.Point(el.PNum(2))), Vec3d (mesh.Point(el.PNum(1)), mesh.Point(el.PNum(3)))); Vec3d ng = geom.GetTriangle(el.GeomInfoPi(1).trignum).Normal(); if (n * ng < 0) { refpts.Append (mesh.Point (mesh.SurfaceElement(i).PNum(1))); refh.Append (mesh.GetH (refpts.Last()) / 2); mesh.DeleteSurfaceElement(i); } } // end comments for (int i = 1; i <= refpts.Size(); i++) mesh.RestrictLocalH (refpts.Get(i), refh.Get(i)); mesh.RemoveOneLayerSurfaceElements(); mesh.Compress(); mesh.FindOpenSegments (); nopen = mesh.GetNOpenSegments(); /* if (!nopen) { // mesh is still ok void STLSurfaceOptimization (STLGeometry & geom, class Mesh & mesh, MeshingParameters & mparam) } */ } } while (nopen); mesh.Compress(); mesh.CalcSurfacesOfNode(); return MESHING3_OK; } void STLSurfaceMeshing1 (STLGeometry & geom, class Mesh & mesh, int retrynr) { static int timer1 = NgProfiler::CreateTimer ("STL surface meshing1"); static int timer1a = NgProfiler::CreateTimer ("STL surface meshing1a"); static int timer1b = NgProfiler::CreateTimer ("STL surface meshing1b"); static int timer1c = NgProfiler::CreateTimer ("STL surface meshing1c"); static int timer1d = NgProfiler::CreateTimer ("STL surface meshing1d"); double h = mparam.maxh; mesh.FindOpenSegments(); Array spiralps(0); spiralps.SetSize(0); for (int i = 1; i <= geom.GetNP(); i++) if (geom.GetSpiralPoint(i)) spiralps.Append(i); PrintMessage(7,"NO spiralpoints = ", spiralps.Size()); //int spfound; /* Array meshsp(mesh.GetNP()); meshsp = 0; for (int i = 1; i <= mesh.GetNP(); i++) for (int j = 1; j <= spiralps.Size(); j++) if (Dist2(geom.GetPoint(spiralps.Get(j)), mesh.Point(i)) < 1e-20) meshsp.Elem(i) = spiralps.Get(j); Array imeshsp; for (int i = 1; i <= meshsp.Size(); i++) if (meshsp.Elem(i)) imeshsp.Append(i); */ Array imeshsp; Array ispiral_point; for (int i = 1; i <= mesh.GetNP(); i++) { for (int j = 1; j <= spiralps.Size(); j++) if (Dist2(geom.GetPoint(spiralps.Get(j)), mesh.Point(i)) < 1e-20) { imeshsp.Append(i); ispiral_point.Append(spiralps.Get(j)); break; } } double starttime = GetTime (); mesh.SurfaceArea().ReCalc(); // int oldnp = mesh.GetNP(); Array compress(mesh.GetNP()); compress = 0; Array icompress; Array opensegsperface(mesh.GetNFD()); opensegsperface = 0; for (int i = 1; i <= mesh.GetNOpenSegments(); i++) opensegsperface[mesh.GetOpenSegment(i).si]++; TABLE opensegments(mesh.GetNFD()); for (int i = 1; i <= mesh.GetNOpenSegments(); i++) { const Segment & seg = mesh.GetOpenSegment (i); if (seg.si < 1 || seg.si > mesh.GetNFD()) cerr << "segment index " << seg.si << " out of range [1, " << mesh.GetNFD() << "]" << endl; opensegments.Add (seg.si, i); } for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++) { if (!opensegsperface[fnr]) continue; if (multithread.terminate) return; NgProfiler::StartTimer (timer1); NgProfiler::StartTimer (timer1a); PrintMessage(5,"Meshing surface ", fnr, "/", mesh.GetNFD()); MeshingSTLSurface meshing (geom, mparam); meshing.SetStartTime (starttime); // compress = 0; icompress.SetSize(0); int cntused = 0; for (int i = 0; i < imeshsp.Size(); i++) { compress[imeshsp[i]] = ++cntused; icompress.Append(imeshsp[i]); } NgProfiler::StopTimer (timer1a); NgProfiler::StartTimer (timer1b); /* for (int i = 1; i <= mesh.GetNOpenSegments(); i++) { const Segment & seg = mesh.GetOpenSegment (i); if (seg.si == fnr) for (int j = 0; j < 2; j++) if (compress[seg[j]] == 0) { compress[seg[j]] = ++cntused; icompress.Append(seg[j]); } } */ FlatArray segs = opensegments[fnr]; for (int hi = 0; hi < segs.Size(); hi++) { int i = segs[hi]; const Segment & seg = mesh.GetOpenSegment (i); for (int j = 0; j < 2; j++) if (compress[seg[j]] == 0) { compress[seg[j]] = ++cntused; icompress.Append(seg[j]); } } NgProfiler::StopTimer (timer1b); NgProfiler::StartTimer (timer1c); for (int hi = 0; hi < icompress.Size(); hi++) { PointIndex pi = icompress[hi]; /* // int sppointnum = meshsp.Get(i); int sppointnum = 0; if (hi < ispiral_point.Size()) sppointnum = ispiral_point[hi]; if (sppointnum) { */ if (hi < ispiral_point.Size()) { int sppointnum = ispiral_point[hi]; MultiPointGeomInfo mgi; int ntrigs = geom.NOTrigsPerPoint(sppointnum); for (int j = 0; j < ntrigs; j++) { PointGeomInfo gi; gi.trignum = geom.TrigPerPoint(sppointnum, j+1); mgi.AddPointGeomInfo (gi); } // Einfuegen von ConePoint: Point bekommt alle // Dreiecke (werden dann intern kopiert) // Ein Segment zum ConePoint muss vorhanden sein !!! // meshing.AddPoint (mesh.Point(i), i, &mgi); meshing.AddPoint (mesh[pi], pi, &mgi); } else meshing.AddPoint (mesh[pi], pi); } NgProfiler::StopTimer (timer1c); NgProfiler::StartTimer (timer1d); /* for (int i = 1; i <= mesh.GetNOpenSegments(); i++) { const Segment & seg = mesh.GetOpenSegment (i); if (seg.si == fnr) meshing.AddBoundaryElement (compress[seg[0]], compress[seg[1]], seg.geominfo[0], seg.geominfo[1]); } */ // FlatArray segs = opensegments[fnr]; for (int hi = 0; hi < segs.Size(); hi++) { int i = segs[hi]; const Segment & seg = mesh.GetOpenSegment (i); meshing.AddBoundaryElement (compress[seg[0]], compress[seg[1]], seg.geominfo[0], seg.geominfo[1]); } NgProfiler::StopTimer (timer1d); NgProfiler::StopTimer (timer1); PrintMessage(3,"start meshing, trialcnt = ", retrynr); meshing.GenerateMesh (mesh, mparam, h, fnr); for (int i = 0; i < icompress.Size(); i++) compress[icompress[i]] = 0; mparam.Render(); } // NgProfiler::Print(stdout); mesh.CalcSurfacesOfNode(); } void STLSurfaceOptimization (STLGeometry & geom, class Mesh & mesh, MeshingParameters & meshparam) { PrintFnStart("optimize STL Surface"); MeshOptimizeSTLSurface optmesh(geom); optmesh.SetFaceIndex (0); optmesh.SetImproveEdges (0); optmesh.SetMetricWeight (meshparam.elsizeweight); PrintMessage(5,"optimize string = ", meshparam.optimize2d, " elsizew = ", meshparam.elsizeweight); for (int i = 1; i <= meshparam.optsteps2d; i++) for (size_t j = 1; j <= meshparam.optimize2d.length(); j++) { if (multithread.terminate) break; //(*testout) << "optimize, before, step = " << meshparam.optimize2d[j-1] << mesh.Point (3679) << endl; mesh.CalcSurfacesOfNode(); switch (meshparam.optimize2d[j-1]) { case 's': { optmesh.EdgeSwapping (mesh, 0); break; } case 'S': { optmesh.EdgeSwapping (mesh, 1); break; } case 'm': { optmesh.ImproveMesh(mesh, mparam); break; } case 'c': { optmesh.CombineImprove (mesh); break; } } //(*testout) << "optimize, after, step = " << meshparam.optimize2d[j-1] << mesh.Point (3679) << endl; } geom.surfaceoptimized = 1; mesh.Compress(); mesh.CalcSurfacesOfNode(); } MeshingSTLSurface :: MeshingSTLSurface (STLGeometry & ageom, const MeshingParameters & mp) : Meshing2(mp, ageom.GetBoundingBox()), geom(ageom) { ; } void MeshingSTLSurface :: DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo, const PointGeomInfo * geominfo2) { transformationtrig = geominfo[0].trignum; geom.DefineTangentialPlane(p1, p2, transformationtrig); } void MeshingSTLSurface :: TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & gi, Point2d & plainpoint, double h, int & zone) { int trigs[10000]; if (gi.GetNPGI() >= 9999) { PrintError("In Transform to plane: increase size of trigs!!!"); } for (int i = 1; i <= gi.GetNPGI(); i++) trigs[i-1] = gi.GetPGI(i).trignum; trigs[gi.GetNPGI()] = 0; // int trig = gi.trignum; // (*testout) << "locpoint = " << locpoint; Point<2> hp2d; geom.ToPlane (locpoint, trigs, hp2d, h, zone, 1); plainpoint = hp2d; // geom.ToPlane (locpoint, NULL, plainpoint, h, zone, 1); /* (*testout) << " plainpoint = " << plainpoint << " h = " << h << endl; */ } /* int MeshingSTLSurface :: ComputeLineGeoInfo (const Point3d & p1, const Point3d & p2, int & geoinfosize, void *& geoinfo) { static int geomtrig[2] = { 0, 0 }; Point3d hp; hp = p1; geomtrig[0] = geom.Project (hp); hp = p2; geomtrig[1] = geom.Project (hp); geoinfosize = sizeof (geomtrig); geoinfo = &geomtrig; if (geomtrig[0] == 0) { return 1; } return 0; } */ int MeshingSTLSurface :: ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi) { // compute triangle of point, // if non-unique: 0 Point<3> hp = p; gi.trignum = geom.Project (hp); if (!gi.trignum) { return 1; } return 0; } int MeshingSTLSurface :: ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, PointGeomInfo & pgi) { for (int i = 1; i <= mpgi.GetNPGI(); i++) if (geom.TrigIsInOC (mpgi.GetPGI(i).trignum, geom.meshchart)) { pgi = mpgi.GetPGI(i); return 0; } /* for (i = 0; i < mpgi.cnt; i++) { // (*testout) << "d" << endl; if (geom.TrigIsInOC (mpgi.mgi[i].trignum, geom.meshchart)) { pgi = mpgi.mgi[i]; return 0; } } */ PrintMessage(7,"INFORM: no gi on chart"); pgi.trignum = 1; return 1; } int MeshingSTLSurface :: IsLineVertexOnChart (const Point3d & p1, const Point3d & p2, int endpoint, const PointGeomInfo & gi) { int lineendtrig = gi.trignum; return geom.TrigIsInOC (lineendtrig, geom.meshchart); // Vec3d baselinenormal = geom.meshtrignv; // Vec3d linenormal = geom.GetTriangleNormal (lineendtrig); // return ( (baselinenormal * linenormal) > cos (30 * (M_PI/180)) ); } void MeshingSTLSurface :: GetChartBoundary (Array & points, Array & points3d, Array & lines, double h) const { points.SetSize (0); points3d.SetSize (0); lines.SetSize (0); geom.GetMeshChartBoundary (points, points3d, lines, h); } int MeshingSTLSurface :: TransformFromPlain (Point2d & plainpoint, Point3d & locpoint, PointGeomInfo & gi, double h) { //return 0, wenn alles OK Point<3> hp3d; int res = geom.FromPlane (plainpoint, hp3d, h); locpoint = hp3d; ComputePointGeomInfo (locpoint, gi); return res; } int MeshingSTLSurface :: BelongsToActiveChart (const Point3d & p, const PointGeomInfo & gi) { return (geom.TrigIsInOC(gi.trignum, geom.meshchart) != 0); } double MeshingSTLSurface :: CalcLocalH (const Point3d & p, double gh) const { return gh; } double MeshingSTLSurface :: Area () const { return geom.Area(); } MeshOptimizeSTLSurface :: MeshOptimizeSTLSurface (STLGeometry & ageom) : MeshOptimize2d(), geom(ageom) { ; } void MeshOptimizeSTLSurface :: SelectSurfaceOfPoint (const Point<3> & p, const PointGeomInfo & gi) { // (*testout) << "sel char: " << gi.trignum << endl; geom.SelectChartOfTriangle (gi.trignum); // geom.SelectChartOfPoint (p); } void MeshOptimizeSTLSurface :: ProjectPoint (INDEX surfind, Point<3> & p) const { if (!geom.Project (p)) { PrintMessage(7,"project failed"); if (!geom.ProjectOnWholeSurface(p)) { PrintMessage(7, "project on whole surface failed"); } } // geometry.GetSurface(surfind)->Project (p); } void MeshOptimizeSTLSurface :: ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const { /* ProjectToEdge ( geometry.GetSurface(surfind), geometry.GetSurface(surfind2), p); */ } int MeshOptimizeSTLSurface :: CalcPointGeomInfo(PointGeomInfo& gi, const Point<3> & p3) const { Point<3> hp = p3; gi.trignum = geom.Project (hp); if (gi.trignum) return 1; return 0; } void MeshOptimizeSTLSurface :: GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const { n = geom.GetChartNormalVector(); } RefinementSTLGeometry :: RefinementSTLGeometry (const STLGeometry & ageom) : Refinement(), geom(ageom) { ; } RefinementSTLGeometry :: ~RefinementSTLGeometry () { ; } void RefinementSTLGeometry :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const { newp = p1+secpoint*(p2-p1); /* (*testout) << "surf-between: p1 = " << p1 << ", p2 = " << p2 << ", gi = " << gi1 << " - " << gi2 << endl; */ if (gi1.trignum > 0) { // ((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum); Point<3> np1 = newp; Point<3> np2 = newp; ((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum); int tn1 = geom.Project (np1); ((STLGeometry&)geom).SelectChartOfTriangle (gi2.trignum); int tn2 = geom.Project (np2); newgi.trignum = tn1; //urspruengliche version newp = np1; //urspruengliche version if (!newgi.trignum) { newgi.trignum = tn2; newp = np2; } if (!newgi.trignum) newgi.trignum = gi1.trignum; /* if (tn1 != 0 && tn2 != 0 && ((STLGeometry&)geom).GetAngle(tn1,tn2) < M_PI*0.05) { newgi.trignum = tn1; newp = np1; } else { newp = ((STLGeometry&)geom).PointBetween(p1, gi1.trignum, p2, gi2.trignum); tn1 = ((STLGeometry&)geom).Project(newp); newgi.trignum = tn1; if (!tn1) { newp = Center (p1, p2); newgi.trignum = 0; } } */ } else { // (*testout) << "WARNING: PointBetween got geominfo = 0" << endl; newp = p1+secpoint*(p2-p1); newgi.trignum = 0; } // (*testout) << "newp = " << newp << ", ngi = " << newgi << endl; } void RefinementSTLGeometry :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & gi1, const EdgePointGeomInfo & gi2, Point<3> & newp, EdgePointGeomInfo & newgi) const { /* (*testout) << "edge-between: p1 = " << p1 << ", p2 = " << p2 << ", gi1,2 = " << gi1 << ", " << gi2 << endl; */ /* newp = Center (p1, p2); ((STLGeometry&)geom).SelectChartOfTriangle (gi1.trignum); newgi.trignum = geom.Project (newp); */ int hi; newgi.dist = (1.0-secpoint) * gi1.dist + secpoint*gi2.dist; newgi.edgenr = gi1.edgenr; /* (*testout) << "p1 = " << p1 << ", p2 = " << p2 << endl; (*testout) << "refedge: " << gi1.edgenr << " d1 = " << gi1.dist << ", d2 = " << gi2.dist << endl; */ newp = geom.GetLine (gi1.edgenr)->GetPointInDist (geom.GetPoints(), newgi.dist, hi); // (*testout) << "newp = " << newp << endl; } void RefinementSTLGeometry :: ProjectToSurface (Point<3> & p, int surfi) const { cout << "RefinementSTLGeometry :: ProjectToSurface not implemented!" << endl; }; void RefinementSTLGeometry :: ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const { ((STLGeometry&)geom).SelectChartOfTriangle (gi.trignum); gi.trignum = geom.Project (p); // if (!gi.trignum) // cout << "projectSTL failed" << endl; }; } netgen-6.2.1905/libsrc/stlgeom/python_stl.cpp0000644000175000017500000000644113504650527017645 0ustar kurtkurt #ifdef NG_PYTHON #include <../general/ngpython.hpp> #include #ifdef WIN32 #define DLL_HEADER __declspec(dllexport) #endif using namespace netgen; namespace netgen { //extern shared_ptr mesh; extern shared_ptr ng_geometry; } DLL_HEADER void ExportSTL(py::module & m) { py::class_, NetgenGeometry> (m,"STLGeometry") .def(py::init<>()) .def(NGSPickle()) .def("_visualizationData", [](shared_ptr stl_geo) { std::vector vertices; std::vector trigs; std::vector normals; std::vector min = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; std::vector max = {std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::lowest()}; std::vector surfnames; surfnames.push_back("stl"); vertices.reserve(stl_geo->GetNT()*3*3); trigs.reserve(stl_geo->GetNT()*4); normals.reserve(stl_geo->GetNT()*3*3); size_t ii = 0; for(int i = 0; i < stl_geo->GetNT(); i++) { auto& trig = stl_geo->GetTriangle(i+1); for(int k = 0; k < 3; k++) { trigs.push_back(ii++); auto& pnt = stl_geo->GetPoint(trig[k]); for (int l = 0; l < 3; l++) { float val = pnt[l]; vertices.push_back(val); min[l] = min2(min[l], val); max[l] = max2(max[l], val); normals.push_back(trig.Normal()[l]); } } trigs.push_back(0); } py::gil_scoped_acquire ac; py::dict res; py::list snames; for(auto name : surfnames) snames.append(py::cast(name)); res["vertices"] = MoveToNumpy(vertices); res["triangles"] = MoveToNumpy(trigs); res["normals"] = MoveToNumpy(normals); res["surfnames"] = snames; res["min"] = MoveToNumpy(min); res["max"] = MoveToNumpy(max); return res; }, py::call_guard()) ; m.def("LoadSTLGeometry", FunctionPointer([] (const string & filename) { ifstream ist(filename); return shared_ptr(STLGeometry::Load(ist)); }),py::call_guard()); m.def("GenerateMesh", FunctionPointer([] (shared_ptr geo, MeshingParameters ¶m) { auto mesh = make_shared(); SetGlobalMesh(mesh); mesh->SetGeometry(geo); ng_geometry = geo; try { geo->GenerateMesh(mesh,param); } catch (NgException ex) { cout << "Caught NgException: " << ex.What() << endl; } return mesh; }),py::call_guard()) ; } PYBIND11_MODULE(libstl, m) { ExportSTL(m); } #endif netgen-6.2.1905/libsrc/stlgeom/stlgeom.hpp0000644000175000017500000003421013504650527017114 0ustar kurtkurt#ifndef FILE_STLGEOM #define FILE_STLGEOM /**************************************************************************/ /* File: stlgeom.hpp */ /* Author: Joachim Schoeberl */ /* Author2: Johannes Gerstmayr */ /* Date: 26. Jul. 99 */ /**************************************************************************/ /** STL Geometry Terminology: Point ... coordinates of STL triangles Triangle (short Trig) STL triangle TopEdge .... edge in topology, boundary of STL triangles (many) Edge .... Edges which will occur in the mesh (confirmed edges, less) */ #include namespace netgen { /* inline int IsInArray(int n, const Array& ia) { return ia.Contains(n); } inline bool AddIfNotExists(Array& list, int x) { if (list.Contains(x)) return false; list.Append(x); return true; } */ extern DLL_HEADER MeshingParameters mparam; #include "stltopology.hpp" #include "stltool.hpp" #include "stlline.hpp" class STLEdgeDataList { Array storedstatus; STLTopology & geom; public: STLEdgeDataList(STLTopology & ageom); ~STLEdgeDataList(); void Store (); void Restore (); void SetSize(int /* size */) { }; void Clear() { }; int Size() const { return geom.GetNTE(); } const STLTopEdge & Get(int i) const { return geom.GetTopEdge(i); } STLTopEdge & Elem(int i) { return geom.GetTopEdge(i); } int GetNEPP(int pn) const {return geom.NTopEdgesPerPoint(pn); } int GetEdgePP(int pn, int vi) const {return geom.TopEdgePerPoint(pn, vi);}; //void AddEdgePP(int pn, int vn) { } ; void ResetAll(); void ChangeStatus(int status1, int status2); int GetEdgeNum(int np1, int np2) const { return geom.GetTopEdgeNum (np1, np2); } int GetNConfEdges() const; void Write(ofstream& of) const; void Read(ifstream& ifs); void BuildLineWithEdge(int ep1, int ep2, Array& line); void BuildClusterWithEdge(int ep1, int ep2, Array& line); int GetNEPPStat(int p, int status) const; int GetNConfCandEPP(int p) const; }; class STLGeometry : public NetgenGeometry, public STLTopology { // edges to be meshed: Array edges; //edges per point TABLE edgesperpoint; // line: a connection of edges Array lines; Array lineendpoints; //per geometrypoint, 1 = is endpoint; 0 = no endpoint, Array normals; //normals belong to points! Array externaledges; int undoexternaledges; Array storedexternaledges; STLEdgeDataList * edgedata; // STLEdgeDataList edgedata_store; int calcedgedataanglesnew; int edgedatastored; int facecnt; //meshpoint is only set, if an edge is at this point!!! Array vicinity; //is one, if a triangle belongs to vicinity (eg. of selecttrig) Array markedtrigs; //is one, if a triangle belongs to marked triangles (calcdirtystrigs) Array markedsegs; //every pointpair is a segment!!! Array selectedmultiedge; //spiralpoints: Array spiralpoints; // Array atlas; //marks all already charted trigs with chartnumber Array chartmark; //outerchartspertrig, ascending sorted TABLE outerchartspertrig; //for meshing and project: Array meshcharttrigs; //per trig: 1=belong to chart, 0 not int meshchart; Array ha_points; // help array, np long, filled with 0 // sharp geometric edges not declared as edges // (not considered for spiral check) INDEX_2_HASHTABLE * smoothedges; //transformation: Vec<3> meshtrignv; Vec<3> ex, ey, ez; Point<3> p1; mutable class RefinementSTLGeometry * ref; public: int edgesfound; int surfacemeshed; int surfaceoptimized; int volumemeshed; int trigsconverted; //when STLTriangles exist -> 1 //for selecting nodes //int selecttrig, nodeofseltrig; //only for testing; Array meshlines; Array meshpoints; double area; public: STLGeometry(); virtual ~STLGeometry(); void DoArchive(Archive& ar) { STLTopology::DoArchive(ar); } void Clear(); virtual void Save (string filename) const; DLL_HEADER void STLInfo(double* data); //stldoctor: DLL_HEADER void SmoothNormals(); DLL_HEADER void MarkNonSmoothNormals(); DLL_HEADER void CalcEdgeData(); DLL_HEADER void CalcEdgeDataAngles(); const STLEdgeDataList& EdgeDataList() const {return *edgedata;} DLL_HEADER void UndoEdgeChange(); DLL_HEADER void StoreEdgeData(); DLL_HEADER void RestoreEdgeData(); //void ClearSelectedMultiEdge() {selectedmultiedge.SetSize(0);} //void AddSelectedMultiEdge(twoint ep) {selectedmultiedge.Append(ep);} //int SelectedMultiEdgeSize() {return selectedmultiedge.Size();} const Array& SelectedMultiEdge() {return selectedmultiedge;} twoint GetNearestSelectedDefinedEdge(); void BuildSelectedMultiEdge(twoint ep); void BuildSelectedEdge(twoint ep); void BuildSelectedCluster(twoint ep); DLL_HEADER void ImportEdges(); DLL_HEADER void AddEdges(const Array >& eps); DLL_HEADER void ExportEdges(); DLL_HEADER void LoadEdgeData(const char* file); DLL_HEADER void SaveEdgeData(const char* file); // void SetEdgeAtSelected(int mode); DLL_HEADER void STLDoctorConfirmEdge(); DLL_HEADER void STLDoctorCandidateEdge(); DLL_HEADER void STLDoctorExcludeEdge(); DLL_HEADER void STLDoctorUndefinedEdge(); DLL_HEADER void STLDoctorSetAllUndefinedEdges(); DLL_HEADER void STLDoctorEraseCandidateEdges(); DLL_HEADER void STLDoctorConfirmCandidateEdges(); DLL_HEADER void STLDoctorConfirmedToCandidateEdges(); DLL_HEADER void STLDoctorDirtyEdgesToCandidates(); DLL_HEADER void STLDoctorLongLinesToCandidates(); DLL_HEADER void UndoExternalEdges(); DLL_HEADER void StoreExternalEdges(); DLL_HEADER void RestoreExternalEdges(); DLL_HEADER void ImportExternalEdges(const char * filename); // Flame edges, JS // void LoadExternalEdges(); DLL_HEADER void BuildExternalEdgesFromEdges(); DLL_HEADER void SaveExternalEdges(); DLL_HEADER void AddExternalEdgeAtSelected(); DLL_HEADER void AddClosedLinesToExternalEdges(); DLL_HEADER void AddLongLinesToExternalEdges(); DLL_HEADER void AddAllNotSingleLinesToExternalEdges(); DLL_HEADER void STLDoctorBuildEdges(); DLL_HEADER void AddExternalEdgesFromGeomLine(); DLL_HEADER void DeleteDirtyExternalEdges(); DLL_HEADER void DeleteExternalEdgeAtSelected(); DLL_HEADER void DeleteExternalEdgeInVicinity(); void AddExternalEdge(int p1, int p2); void DeleteExternalEdge(int p1, int p2); int IsExternalEdge(int p1, int p2); int NOExternalEdges() const {return externaledges.Size();} twoint GetExternalEdge(int i) const {return externaledges.Get(i);} DLL_HEADER void DestroyDirtyTrigs(); DLL_HEADER void CalcNormalsFromGeometry(); DLL_HEADER void MoveSelectedPointToMiddle(); DLL_HEADER void NeighbourAnglesOfSelectedTrig(); DLL_HEADER void PrintSelectInfo(); DLL_HEADER void ShowSelectedTrigChartnum(); DLL_HEADER void ShowSelectedTrigCoords(); DLL_HEADER void SmoothGeometry (); DLL_HEADER void LoadMarkedTrigs(); DLL_HEADER void SaveMarkedTrigs(); void ClearMarkedSegs() {markedsegs.SetSize(0);} void AddMarkedSeg(const Point<3> & ap1, const Point<3> & ap2) { markedsegs.Append(ap1);markedsegs.Append(ap2); } void GetMarkedSeg(int i, Point<3> & ap1, Point<3> & ap2) { ap1=markedsegs.Get(i*2-1); ap2=markedsegs.Get(i*2); } int GetNMarkedSegs() {return markedsegs.Size()/2;} DLL_HEADER void CalcVicinity(int starttrig); DLL_HEADER void GetVicinity(int starttrig, int size, Array& vic); DLL_HEADER int Vicinity(int trig) const; DLL_HEADER void InitMarkedTrigs(); DLL_HEADER void MarkDirtyTrigs(); DLL_HEADER void SmoothDirtyTrigs(); DLL_HEADER void GeomSmoothRevertedTrigs(); DLL_HEADER void MarkRevertedTrigs(); DLL_HEADER double CalcTrigBadness(int i); DLL_HEADER int IsMarkedTrig(int trig) const; DLL_HEADER void SetMarkedTrig(int trig, int num); DLL_HEADER void MarkTopErrorTrigs (); //Selected triangle DLL_HEADER void SetSelectTrig(int trig); DLL_HEADER int GetSelectTrig() const; DLL_HEADER void SetNodeOfSelTrig(int n); DLL_HEADER int GetNodeOfSelTrig() const; int AddNormal(const Vec3d& n) { normals.Append(n); return normals.Size(); } const Vec3d & GetNormal(int nr) const {return normals.Get(nr);} void SetNormal(int nr, const Vec3d& n) {normals.Elem(nr) = n;} int AddEdge(const STLEdge& v) { edges.Append(v); return edges.Size(); } int AddEdge(int p1, int p2); STLEdge GetEdge(int nr) {return edges.Get(nr);} int GetNE() {return edges.Size();} double Area(); double GetAngle(int t1, int t2); double GetGeomAngle(int t1, int t2); //if triangles t1 and t2 touch, return 1 and in p1, p2 the touching points //int TrigsTouch(int t1, int t2, int& p1, int& p2); /// ///ReadTriangle->STLTriangle, initialise some important variables, always after load!!! virtual void InitSTLGeometry (const Array & readtrigs); virtual void TopologyChanged(); //do some things, if topology changed! int CheckGeometryOverlapping(); //get NO edges per point int GetEPPSize() const {return edgesperpoint.Size();}; int GetNEPP(int pn) { if (edgesperpoint.Size() == 0) {BuildEdgesPerPoint();} return edgesperpoint.EntrySize(pn); }; int GetEdgePP(int pn, int vi) { if (edgesperpoint.Size() == 0) {BuildEdgesPerPoint();} return edgesperpoint.Get(pn,vi); }; void AddEdgePP(int pn, int vn) {edgesperpoint.Add1(pn,vn);}; //von 2 punkten ermitteln, ob sie eine Kante sind int IsEdge(int p1, int p2); int IsEdgeNum(int p1, int p2); ///Build EdgeSegments void ClearEdges(); void BuildEdges(); void BuildEdgesPerPoint(); void UseExternalEdges(); void FindEdgesFromAngles(); void CalcFaceNums(); int GetNOBodys(); int GetNOFaces() {return facecnt;} void LinkEdges(); void AddConeAndSpiralEdges(); void AddFaceEdges(); //each face should have at least one starting edge (outherwise it won't be meshed) void GetDirtyChartTrigs(int chartnum, STLChart& chart, const Array& outercharttrigs, Array& chartpointchecked, Array& dirtytrigs); void ClearSpiralPoints(); void SetSpiralPoint(int pn) {spiralpoints.Elem(pn) = 1;}; int GetSpiralPoint(int pn) const {return spiralpoints.Get(pn);}; void GetSortedTrianglesAroundPoint(int p, int starttrig, Array& trigs); // smooth edges: sharp geometric edges not declared as edges void BuildSmoothEdges (); int IsSmoothEdge (int pi1, int pi2) const; //make charts with regions of a max. angle void MakeAtlas(class Mesh & mesh); //outerchartspertrig, sorted! int GetOCPTSize() const {return outerchartspertrig.Size();}; int GetNOCPT(int tn) const {return outerchartspertrig.EntrySize(tn);}; int GetOCPT(int tn, int vi) const {return outerchartspertrig.Get(tn,vi);}; void SetOCPT(int tn, int vi, int ocn) {outerchartspertrig.Set(tn,vi,ocn);}; void AddOCPT(int tn, int ocn) {outerchartspertrig.Add1(tn, ocn);}; int TrigIsInOC(int tn, int ocn) const; //get chart number of a trig or 0 if unmarked int GetChartNr(int i) const; int GetMarker(int i) const { return chartmark.Get(i); } void SetMarker(int nr, int m); int GetNOCharts() const; //get a chart from atlas const STLChart& GetChart(int nr) const; STLChart& GetChart(int nr) {return *(atlas.Get(nr));}; int AtlasMade() const; void GetInnerChartLimes(Array& limes, int chartnum); //FOR MESHING int GetMeshChartNr () { return meshchart; } void GetMeshChartBoundary (Array & points, Array & points3d, Array & lines, double h); Point<3> PointBetween(const Point<3> & p1, int t1, const Point<3> & p2, int t2); //select triangles in meshcharttrigs of actual (defined by trig) whole chart void PrepareSurfaceMeshing(); // void DefineTangentialPlane(const Point<3> & ap1, const Point<3> & ap2, int trig); // void SelectChartOfTriangle (int trignum); // void SelectChartOfPoint (const Point<3> & p); // const Vec<3> & GetChartNormalVector () const { return meshtrignv; } // list of trigs void ToPlane (const Point<3> & locpoint, int * trigs, Point<2> & plainpoint, double h, int& zone, int checkchart); //return 0, wenn alles OK, 1 sonst int FromPlane (const Point<2> & plainpoint, Point<3> & locpoint, double h); //get nearest point in actual chart and return any triangle where it lies on int ProjectNearest(Point<3> & p3d) const; //project point with normal nv from last define tangential plane int LastTrig() const; int Project(Point<3> & p3d) const; int ProjectOnWholeSurface (Point<3> & p3d) const; int GetNLines() const {return lines.Size();} int AddLine(STLLine* line) { lines.Append(line); return lines.Size(); } STLLine* GetLine(int nr) const {return lines.Get(nr);} int GetLineP(int lnr, int pnr) const {return lines.Get(lnr)->PNum(pnr);} int GetLineNP(int nr) const {return lines.Get(nr)->NP();} void SetLineEndPoint(int pn); int IsLineEndPoint(int pn); int LineEndPointsSet() const {return lineendpoints.Size() == GetNP();} void ClearLineEndPoints(); DLL_HEADER void RestrictLocalH(class Mesh & mesh, double gh); void RestrictLocalHCurv(class Mesh & mesh, double gh); void RestrictHChartDistOneChart(int chartnum, Array& acttrigs, class Mesh & mesh, double gh, double fact, double minh); friend class MeshingSTLSurface; virtual int GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam); virtual const Refinement & GetRefinement () const; }; #include "meshstlsurface.hpp" extern int STLMeshingDummy (STLGeometry* stlgeometry, shared_ptr & mesh, MeshingParameters & mparam); } #endif netgen-6.2.1905/libsrc/stlgeom/stlline.hpp0000644000175000017500000001144013504650527017114 0ustar kurtkurt#ifndef FILE_STLLINE #define FILE_STLLINE /**************************************************************************/ /* File: stlline.hh */ /* Author: Joachim Schoeberl */ /* Author2: Johannes Gerstmayr */ /* Date: 20. Nov. 99 */ /**************************************************************************/ class STLGeometry; class STLTopology; class STLEdge { public: int pts[2]; int trigs[2]; //left and right trig STLEdge (const int * apts) {pts[0] = apts[0]; pts[1] = apts[1];} STLEdge (int v1, int v2) {pts[0] = v1; pts[1] = v2;} STLEdge () {pts[0]=0;pts[1]=0;} int PNum(int i) const {return pts[(i-1)];} int LeftTrig() const {return trigs[0];} int RightTrig() const {return trigs[1];} void SetLeftTrig(int i) {trigs[0] = i;} void SetRightTrig(int i) {trigs[1] = i;} }; enum STL_ED_STATUS { ED_EXCLUDED, ED_CONFIRMED, ED_CANDIDATE, ED_UNDEFINED }; /* class STLEdgeData { public: // float angle; int p1; int p2; int lt; //left trig int rt; //right trig // int status; STLTopology * top; // pointer to stl topology int topedgenr; // number of corresponding topology edge STLEdgeData() {}; STLEdgeData(float anglei, int p1i, int p2i, int lti, int rti) { // angle = anglei; p1 = p1i; p2 = p2i; lt = lti; rt = rti; } int GetStatus () const; void SetStatus (int stat); void SetExcluded() { SetStatus (ED_EXCLUDED); } void SetConfirmed() { SetStatus (ED_CONFIRMED); } void SetCandidate() { SetStatus (ED_CANDIDATE); } void SetUndefined() { SetStatus (ED_UNDEFINED); } int Excluded() const {return GetStatus() == ED_EXCLUDED;} int Confirmed() const {return GetStatus() == ED_CONFIRMED;} int Candidate() const {return GetStatus() == ED_CANDIDATE;} int Undefined() const {return GetStatus() == ED_UNDEFINED;} int ConfCand() const {return GetStatus() == ED_CONFIRMED || GetStatus() == ED_CANDIDATE;} float CosAngle() const; void Write(ofstream& of) const; void Read(ifstream& ifs); }; class STLEdgeDataList { private: INDEX_2_HASHTABLE hashtab; Array edgedata; TABLE edgesperpoint; public: STLEdgeDataList():edgedata(),hashtab(1),edgesperpoint() {}; const STLEdgeDataList& operator=(const STLEdgeDataList& edl); void SetSize(int size) { edgedata.SetSize(size); hashtab.SetSize(size); edgesperpoint.SetSize(size); } void Clear() {SetSize(0);} int Size() const {return edgedata.Size();} const STLEdgeData& Get(int i) const {return edgedata.Get(i);} STLEdgeData& Elem(int i) {return edgedata.Elem(i);} void Add(const STLEdgeData& ed, int i); int GetNEPP(int pn) const { return edgesperpoint.EntrySize(pn); }; int GetEdgePP(int pn, int vi) const { return edgesperpoint.Get(pn,vi); }; void AddEdgePP(int pn, int vn) {edgesperpoint.Add(pn,vn);}; void ResetAll(); void ResetCandidates(); void ConfirmCandidates(); int GetEdgeNum(int np1, int np2) const; int GetNConfEdges() const; void Write(ofstream& of) const; void Read(ifstream& ifs); void BuildLineWithEdge(int ep1, int ep2, Array& line); int GetNEPPStat(int p, int status) const; int GetNConfCandEPP(int p) const; }; */ //a line defined by several points (polyline) class STLLine { private: const STLGeometry * geometry; Array pts; Array lefttrigs; Array righttrigs; Array dists; int split; public: STLLine(const STLGeometry * ageometry); void AddPoint(int i) {pts.Append(i);} int PNum(int i) const {return pts.Get(i);} int NP() const {return pts.Size();} int GetNS() const; void GetSeg(int nr, int& p1, int& p2) const; double GetSegLen(const Array >& ap, int nr) const; int GetLeftTrig(int nr) const; int GetRightTrig(int nr) const; double GetDist(int nr) const { return dists.Get(nr);}; void GetBoundingBox (const Array > & ap, Box<3> & box) const; void AddLeftTrig(int nr) {lefttrigs.Append(nr);} void AddRightTrig(int nr) {righttrigs.Append(nr);} void AddDist (double dist) {dists.Append(dist); } int StartP() const {return pts.Get(1);} int EndP() const {return pts.Get(pts.Size());} double GetLength(const Array >& ap) const; //suche punkt in entfernung (in linienkoordinaten) dist //in index ist letzter punkt VOR dist (d.h. max pts.Size()-1) Point<3> GetPointInDist(const Array >& ap, double dist, int& index) const; //return a meshed polyline STLLine* Mesh(const Array >& ap, Array& mp, double ghi, class Mesh& mesh) const; void DoSplit() {split = 1;} int ShouldSplit() const {return split;} }; #endif netgen-6.2.1905/libsrc/stlgeom/stltopology.cpp0000644000175000017500000005376213504650527020051 0ustar kurtkurt#include #include #include #include #include #include "stlgeom.hpp" #include namespace netgen { STLTopology :: STLTopology() : trias(), topedges(), points(), ht_topedges(NULL), trigsperpoint(), neighbourtrigs() { ; } STLTopology :: ~STLTopology() { ; } STLGeometry * STLTopology :: LoadBinary (istream & ist) { STLGeometry * geom = new STLGeometry(); Array readtrigs; PrintMessage(1,"Read STL binary file"); if (sizeof(int) != 4 || sizeof(float) != 4) { PrintWarning("for stl-binary compatibility only use 32 bit compilation!!!"); } //specific settings for stl-binary format const int namelen = 80; //length of name of header in file const int nospaces = 2; //number of spaces after a triangle //read header: name char buf[namelen+1]; FIOReadStringE(ist,buf,namelen); PrintMessage(5,"header = ",buf); //Read Number of facets int nofacets; FIOReadInt(ist,nofacets); PrintMessage(5,"NO facets = ",nofacets); Point<3> pts[3]; Vec<3> normal; char spaces[nospaces+1]; for (int cntface = 0; cntface < nofacets; cntface++) { if (cntface % 10000 == 0) // { PrintDot(); } PrintMessageCR (3, cntface, " triangles loaded\r"); float f; FIOReadFloat(ist,f); normal(0) = f; FIOReadFloat(ist,f); normal(1) = f; FIOReadFloat(ist,f); normal(2) = f; for (int j = 0; j < 3; j++) { FIOReadFloat(ist,f); pts[j](0) = f; FIOReadFloat(ist,f); pts[j](1) = f; FIOReadFloat(ist,f); pts[j](2) = f; } readtrigs.Append (STLReadTriangle (pts, normal)); FIOReadString(ist,spaces,nospaces); } PrintMessage (3, nofacets, " triangles loaded\r"); geom->InitSTLGeometry(readtrigs); return geom; } void STLTopology :: SaveBinary (const char* filename, const char* aname) const { ofstream ost(filename); PrintFnStart("Write STL binary file '",filename,"'"); if (sizeof(int) != 4 || sizeof(float) != 4) {PrintWarning("for stl-binary compatibility only use 32 bit compilation!!!");} //specific settings for stl-binary format const int namelen = 80; //length of name of header in file const int nospaces = 2; //number of spaces after a triangle //write header: aname int i, j; char buf[namelen+1]; int strend = 0; for(i = 0; i <= namelen; i++) { if (aname[i] == 0) {strend = 1;} if (!strend) {buf[i] = aname[i];} else {buf[i] = 0;} } FIOWriteString(ost,buf,namelen); PrintMessage(5,"header = ",buf); //RWrite Number of facets int nofacets = GetNT(); FIOWriteInt(ost,nofacets); PrintMessage(5,"NO facets = ", nofacets); float f; char spaces[nospaces+1]; for (i = 0; i < nospaces; i++) {spaces[i] = ' ';} spaces[nospaces] = 0; for (i = 1; i <= GetNT(); i++) { const STLTriangle & t = GetTriangle(i); const Vec<3> & n = t.Normal(); f = n(0); FIOWriteFloat(ost,f); f = n(1); FIOWriteFloat(ost,f); f = n(2); FIOWriteFloat(ost,f); for (j = 1; j <= 3; j++) { const Point3d p = GetPoint(t.PNum(j)); f = p.X(); FIOWriteFloat(ost,f); f = p.Y(); FIOWriteFloat(ost,f); f = p.Z(); FIOWriteFloat(ost,f); } FIOWriteString(ost,spaces,nospaces); } PrintMessage(5,"done"); } void STLTopology :: SaveSTLE (const char* filename) const { ofstream outf (filename); int i, j; outf << GetNT() << endl; for (i = 1; i <= GetNT(); i++) { const STLTriangle & t = GetTriangle(i); for (j = 1; j <= 3; j++) { const Point3d p = GetPoint(t.PNum(j)); outf << p.X() << " " << p.Y() << " " << p.Z() << endl; } } int ned = 0; for (i = 1; i <= GetNTE(); i++) { if (GetTopEdge (i).GetStatus() == ED_CONFIRMED) ned++; } outf << ned << endl; for (i = 1; i <= GetNTE(); i++) { const STLTopEdge & edge = GetTopEdge (i); if (edge.GetStatus() == ED_CONFIRMED) for (j = 1; j <= 2; j++) { const Point3d p = GetPoint(edge.PNum(j)); outf << p.X() << " " << p.Y() << " " << p.Z() << endl; } } } STLGeometry * STLTopology :: LoadNaomi (istream & ist) { int i; STLGeometry * geom = new STLGeometry(); Array readtrigs; PrintFnStart("read NAOMI file format"); char buf[100]; Vec<3> normal; //int cntface = 0; //int cntvertex = 0; double px, py, pz; int noface, novertex; Array > readpoints; ist >> buf; if (strcmp (buf, "NODES") == 0) { ist >> novertex; PrintMessage(5,"nuber of vertices = ", novertex); for (i = 0; i < novertex; i++) { ist >> px; ist >> py; ist >> pz; readpoints.Append(Point<3> (px,py,pz)); } } else { PrintFileError("no node information"); } ist >> buf; if (strcmp (buf, "2D_EDGES") == 0) { ist >> noface; PrintMessage(5,"number of faces=",noface); int dummy, p1, p2, p3; Point<3> pts[3]; for (i = 0; i < noface; i++) { ist >> dummy; //2 ist >> dummy; //1 ist >> p1; ist >> p2; ist >> p3; ist >> dummy; //0 pts[0] = readpoints.Get(p1); pts[1] = readpoints.Get(p2); pts[2] = readpoints.Get(p3); normal = Cross (pts[1]-pts[0], pts[2]-pts[0]) . Normalize(); readtrigs.Append (STLReadTriangle (pts, normal)); } PrintMessage(5,"read ", readtrigs.Size(), " triangles"); } else { PrintMessage(5,"read='",buf,"'\n"); PrintFileError("ERROR: no Triangle information"); } geom->InitSTLGeometry(readtrigs); return geom; } void STLTopology :: Save (const char* filename) const { PrintFnStart("Write stl-file '",filename, "'"); ofstream fout(filename); fout << "solid\n"; char buf1[50]; char buf2[50]; char buf3[50]; int i, j; for (i = 1; i <= GetNT(); i++) { const STLTriangle & t = GetTriangle(i); fout << "facet normal "; const Vec3d& n = GetTriangle(i).Normal(); sprintf(buf1,"%1.9g",n.X()); sprintf(buf2,"%1.9g",n.Y()); sprintf(buf3,"%1.9g",n.Z()); fout << buf1 << " " << buf2 << " " << buf3 << "\n"; fout << "outer loop\n"; for (j = 1; j <= 3; j++) { const Point3d p = GetPoint(t.PNum(j)); sprintf(buf1,"%1.9g",p.X()); sprintf(buf2,"%1.9g",p.Y()); sprintf(buf3,"%1.9g",p.Z()); fout << "vertex " << buf1 << " " << buf2 << " " << buf3 << "\n"; } fout << "endloop\n"; fout << "endfacet\n"; } fout << "endsolid\n"; // write also NETGEN surface mesh: ofstream fout2("geom.surf"); fout2 << "surfacemesh" << endl; fout2 << GetNP() << endl; for (i = 1; i <= GetNP(); i++) { for (j = 0; j < 3; j++) { fout2.width(8); fout2 << GetPoint(i)(j); } fout2 << endl; } fout2 << GetNT() << endl; for (i = 1; i <= GetNT(); i++) { const STLTriangle & t = GetTriangle(i); for (j = 1; j <= 3; j++) { fout2.width(8); fout2 << t.PNum(j); } fout2 << endl; } } STLGeometry * STLTopology ::Load (istream & ist) { STLGeometry * geom = new STLGeometry(); Array readtrigs; char buf[100]; Point<3> pts[3]; Vec<3> normal; int cntface = 0; int vertex = 0; bool badnormals = false; while (ist.good()) { ist >> buf; int n = strlen (buf); for (int i = 0; i < n; i++) buf[i] = tolower (buf[i]); if (strcmp (buf, "facet") == 0) { cntface++; } if (strcmp (buf, "normal") == 0) { ist >> normal(0) >> normal(1) >> normal(2); normal.Normalize(); } if (strcmp (buf, "vertex") == 0) { ist >> pts[vertex](0) >> pts[vertex](1) >> pts[vertex](2); vertex++; if (vertex == 3) { if (normal.Length() <= 1e-5) { normal = Cross (pts[1]-pts[0], pts[2]-pts[0]); normal.Normalize(); } else { Vec<3> hnormal = Cross (pts[1]-pts[0], pts[2]-pts[0]); hnormal.Normalize(); if (normal * hnormal < 0.5) badnormals = true; } vertex = 0; if ( (Dist2 (pts[0], pts[1]) > 1e-16) && (Dist2 (pts[0], pts[2]) > 1e-16) && (Dist2 (pts[1], pts[2]) > 1e-16) ) { readtrigs.Append (STLReadTriangle (pts, normal)); if (readtrigs.Size() % 100000 == 0) PrintMessageCR (3, readtrigs.Size(), " triangles loaded\r"); } else { cout << "Skipping flat triangle " << "l1 = " << Dist(pts[0], pts[1]) << ", l2 = " << Dist(pts[0], pts[2]) << ", l3 = " << Dist(pts[2], pts[1]) << endl; } } } } PrintMessage (3, readtrigs.Size(), " triangles loaded"); if (badnormals) { PrintWarning("File has normal vectors which differ extremely from geometry->correct with stldoctor!!!"); } geom->InitSTLGeometry(readtrigs); return geom; } void STLTopology :: InitSTLGeometry(const Array & readtrigs) { // const double geometry_tol_fact = 1E6; // distances lower than max_box_size/tol are ignored trias.SetSize(0); points.SetSize(0); PrintMessage(3,"number of triangles = ", readtrigs.Size()); if (!readtrigs.Size()) return; boundingbox.Set (readtrigs[0][0]); for (int i = 0; i < readtrigs.Size(); i++) for (int k = 0; k < 3; k++) boundingbox.Add (readtrigs[i][k]); PrintMessage(5,"boundingbox: ", Point3d(boundingbox.PMin()), " - ", Point3d(boundingbox.PMax())); Box<3> bb = boundingbox; bb.Increase (1); pointtree = new Point3dTree (bb.PMin(), bb.PMax()); Array pintersect; pointtol = boundingbox.Diam() * stldoctor.geom_tol_fact; PrintMessage(5,"point tolerance = ", pointtol); PrintMessageCR(5,"identify points ..."); for(int i = 0; i < readtrigs.Size(); i++) { const STLReadTriangle & t = readtrigs[i]; STLTriangle st; st.SetNormal (t.Normal()); for (int k = 0; k < 3; k++) { Point<3> p = t[k]; Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol); Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol); pointtree->GetIntersecting (pmin, pmax, pintersect); if (pintersect.Size() > 1) PrintError("too many close points"); int foundpos = -1; if (pintersect.Size()) foundpos = pintersect[0]; if (foundpos == -1) { foundpos = AddPoint(p); pointtree->Insert (p, foundpos); } if (Dist(p, points.Get(foundpos)) > 1e-10) cout << "identify close points: " << p << " " << points.Get(foundpos) << ", dist = " << Dist(p, points.Get(foundpos)) << endl; st[k] = foundpos; } if ( (st[0] == st[1]) || (st[0] == st[2]) || (st[1] == st[2]) ) { PrintError("STL Triangle degenerated"); } else { AddTriangle(st); } } PrintMessage(5,"identify points ... done"); FindNeighbourTrigs(); } int STLTopology :: GetPointNum (const Point<3> & p) { Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol); Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol); Array pintersect; pointtree->GetIntersecting (pmin, pmax, pintersect); if (pintersect.Size() == 1) return pintersect[0]; else return 0; } void STLTopology :: FindNeighbourTrigs() { // if (topedges.Size()) return; PushStatusF("Find Neighbour Triangles"); PrintMessage(5,"build topology ..."); // build up topology tables int nt = GetNT(); INDEX_2_HASHTABLE * oldedges = ht_topedges; ht_topedges = new INDEX_2_HASHTABLE (GetNP()+1); topedges.SetSize(0); for (int i = 1; i <= nt; i++) { STLTriangle & trig = GetTriangle(i); for (int j = 1; j <= 3; j++) { int pi1 = trig.PNumMod (j+1); int pi2 = trig.PNumMod (j+2); INDEX_2 i2(pi1, pi2); i2.Sort(); int enr; int othertn; if (ht_topedges->Used(i2)) { enr = ht_topedges->Get(i2); topedges.Elem(enr).TrigNum(2) = i; othertn = topedges.Get(enr).TrigNum(1); STLTriangle & othertrig = GetTriangle(othertn); trig.NBTrigNum(j) = othertn; trig.EdgeNum(j) = enr; for (int k = 1; k <= 3; k++) if (othertrig.EdgeNum(k) == enr) othertrig.NBTrigNum(k) = i; } else { topedges.Append (STLTopEdge (pi1, pi2, i, 0)); enr = topedges.Size(); ht_topedges->Set (i2, enr); trig.EdgeNum(j) = enr; } } } PrintMessage(5,"topology built, checking"); topology_ok = 1; int ne = GetNTE(); for (int i = 1; i <= nt; i++) GetTriangle(i).flags.toperror = 0; for (int i = 1; i <= nt; i++) for (int j = 1; j <= 3; j++) { const STLTopEdge & edge = GetTopEdge (GetTriangle(i).EdgeNum(j)); if (edge.TrigNum(1) != i && edge.TrigNum(2) != i) { topology_ok = 0; GetTriangle(i).flags.toperror = 1; } } for (int i = 1; i <= ne; i++) { const STLTopEdge & edge = GetTopEdge (i); if (!edge.TrigNum(2)) { topology_ok = 0; GetTriangle(edge.TrigNum(1)).flags.toperror = 1; } } if (topology_ok) { orientation_ok = 1; for (int i = 1; i <= nt; i++) { const STLTriangle & t = GetTriangle (i); for (int j = 1; j <= 3; j++) { const STLTriangle & nbt = GetTriangle (t.NBTrigNum(j)); if (!t.IsNeighbourFrom (nbt)) orientation_ok = 0; } } } else orientation_ok = 0; status = STL_GOOD; statustext = ""; if (!topology_ok || !orientation_ok) { status = STL_ERROR; if (!topology_ok) statustext = "Topology not ok"; else statustext = "Orientation not ok"; } PrintMessage(3,"topology_ok = ",topology_ok); PrintMessage(3,"orientation_ok = ",orientation_ok); PrintMessage(3,"topology found"); // generate point -> trig table trigsperpoint.SetSize(GetNP()); for (int i = 1; i <= GetNT(); i++) for (int j = 1; j <= 3; j++) trigsperpoint.Add1(GetTriangle(i).PNum(j),i); //check trigs per point: /* for (i = 1; i <= GetNP(); i++) { if (trigsperpoint.EntrySize(i) < 3) { (*testout) << "ERROR: Point " << i << " has " << trigsperpoint.EntrySize(i) << " triangles!!!" << endl; } } */ topedgesperpoint.SetSize (GetNP()); for (int i = 1; i <= ne; i++) for (int j = 1; j <= 2; j++) topedgesperpoint.Add1 (GetTopEdge (i).PNum(j), i); PrintMessage(5,"point -> trig table generated"); // transfer edge data: // .. to be done delete oldedges; for (STLTrigIndex ti = 0; ti < GetNT(); ti++) { STLTriangle & trig = trias[ti]; for (int k = 0; k < 3; k++) { STLPointIndex pi = trig[k] - STLBASE; STLPointIndex pi2 = trig[(k+1)%3] - STLBASE; STLPointIndex pi3 = trig[(k+2)%3] - STLBASE; // vector along edge Vec<3> ve = points[pi2] - points[pi]; ve.Normalize(); // vector along third point Vec<3> vt = points[pi3] - points[pi]; vt -= (vt * ve) * ve; vt.Normalize(); Vec<3> vn = trig.GeomNormal (points); vn.Normalize(); double phimin = 10, phimax = -1; // out of (0, 2 pi) for (int j = 0; j < trigsperpoint[pi].Size(); j++) { STLTrigIndex ti2 = trigsperpoint[pi][j] - STLBASE; const STLTriangle & trig2 = trias[ti2]; if (ti == ti2) continue; bool hasboth = 0; for (int l = 0; l < 3; l++) if (trig2[l] - STLBASE == pi2) { hasboth = 1; break; } if (!hasboth) continue; STLPointIndex pi4(0); for (int l = 0; l < 3; l++) if (trig2[l] - STLBASE != pi && trig2[l] - STLBASE != pi2) pi4 = trig2[l] - STLBASE; Vec<3> vt2 = points[pi4] - points[pi]; double phi = atan2 (vt2 * vn, vt2 * vt); if (phi < 0) phi += 2 * M_PI; if (phi < phimin) { phimin = phi; trig.NBTrig (0, (k+2)%3) = ti2 + STLBASE; } if (phi > phimax) { phimax = phi; trig.NBTrig (1, (k+2)%3) = ti2 + STLBASE; } } } } if (status == STL_GOOD) { // for compatibility: neighbourtrigs.SetSize(GetNT()); for (int i = 1; i <= GetNT(); i++) for (int k = 1; k <= 3; k++) AddNeighbourTrig (i, GetTriangle(i).NBTrigNum(k)); } else { // assemble neighbourtrigs (should be done only for illegal topology): neighbourtrigs.SetSize(GetNT()); int tr, found; int wrongneighbourfound = 0; for (int i = 1; i <= GetNT(); i++) { SetThreadPercent((double)i/(double)GetNT()*100.); if (multithread.terminate) { PopStatus(); return; } for (int k = 1; k <= 3; k++) { for (int j = 1; j <= trigsperpoint.EntrySize(GetTriangle(i).PNum(k)); j++) { tr = trigsperpoint.Get(GetTriangle(i).PNum(k),j); if (i != tr && (GetTriangle(i).IsNeighbourFrom(GetTriangle(tr)) || GetTriangle(i).IsWrongNeighbourFrom(GetTriangle(tr)))) { if (GetTriangle(i).IsWrongNeighbourFrom(GetTriangle(tr))) { /*(*testout) << "ERROR: triangle " << i << " has a wrong neighbour triangle!!!" << endl;*/ wrongneighbourfound ++; } found = 0; for (int ii = 1; ii <= NONeighbourTrigs(i); ii++) {if (NeighbourTrig(i,ii) == tr) {found = 1;break;};} if (! found) {AddNeighbourTrig(i,tr);} } } } if (NONeighbourTrigs(i) != 3) { PrintError("TRIG ",i," has ",NONeighbourTrigs(i)," neighbours!!!!"); for (int kk=1; kk <= NONeighbourTrigs(i); kk++) { PrintMessage(5,"neighbour-trig",kk," = ",NeighbourTrig(i,kk)); } }; } if (wrongneighbourfound) { PrintError("++++++++++++++++++++\n"); PrintError(wrongneighbourfound, " wrong oriented neighbourtriangles found!"); PrintError("try to correct it (with stldoctor)!"); PrintError("++++++++++++++++++++\n"); status = STL_ERROR; statustext = "STL Mesh not consistent"; multithread.terminate = 1; #ifdef STAT_STREAM (*statout) << "non-conform stl geometry \\hline" << endl; #endif } } TopologyChanged(); PopStatus(); } void STLTopology :: GetTrianglesInBox (/* const Point<3> & pmin, const Point<3> & pmax, */ const Box<3> & box, Array & btrias) const { if (searchtree) searchtree -> GetIntersecting (box.PMin(), box.PMax(), btrias); else { int i; Box<3> box1 = box; box1.Increase (1e-4); btrias.SetSize(0); int nt = GetNT(); for (i = 1; i <= nt; i++) { if (box1.Intersect (GetTriangle(i).box)) { btrias.Append (i); } } } } void STLTopology :: AddTriangle(const STLTriangle& t) { trias.Append(t); const Point<3> & p1 = GetPoint (t.PNum(1)); const Point<3> & p2 = GetPoint (t.PNum(2)); const Point<3> & p3 = GetPoint (t.PNum(3)); Box<3> box; box.Set (p1); box.Add (p2); box.Add (p3); /* // Point<3> pmin(p1), pmax(p1); pmin.SetToMin (p2); pmin.SetToMin (p3); pmax.SetToMax (p2); pmax.SetToMax (p3); */ trias.Last().box = box; trias.Last().center = Center (p1, p2, p3); double r1 = Dist (p1, trias.Last().center); double r2 = Dist (p2, trias.Last().center); double r3 = Dist (p3, trias.Last().center); trias.Last().rad = max2 (max2 (r1, r2), r3); if (geomsearchtreeon) {searchtree->Insert (box.PMin(), box.PMax(), trias.Size());} } int STLTopology :: GetLeftTrig(int p1, int p2) const { int i; for (i = 1; i <= trigsperpoint.EntrySize(p1); i++) { if (GetTriangle(trigsperpoint.Get(p1,i)).HasEdge(p1,p2)) {return trigsperpoint.Get(p1,i);} } PrintSysError("ERROR in GetLeftTrig !!!"); return 0; } int STLTopology :: GetRightTrig(int p1, int p2) const { return GetLeftTrig(p2,p1); } int STLTopology :: NeighbourTrigSorted(int trig, int edgenum) const { int i, p1, p2; int psearch = GetTriangle(trig).PNum(edgenum); for (i = 1; i <= 3; i++) { GetTriangle(trig).GetNeighbourPoints(GetTriangle(NeighbourTrig(trig,i)),p1,p2); if (p1 == psearch) {return NeighbourTrig(trig,i);} } PrintSysError("ERROR in NeighbourTrigSorted"); return 0; } int STLTopology :: GetTopEdgeNum (int pi1, int pi2) const { if (!ht_topedges) return 0; INDEX_2 i2(pi1, pi2); i2.Sort(); if (!ht_topedges->Used(i2)) return 0; return ht_topedges->Get(i2); } void STLTopology :: InvertTrig (int trig) { if (trig >= 1 && trig <= GetNT()) { GetTriangle(trig).ChangeOrientation(); FindNeighbourTrigs(); } else { PrintUserError("no triangle selected!"); } } void STLTopology :: DeleteTrig (int trig) { if (trig >= 1 && trig <= GetNT()) { trias.DeleteElement(trig); FindNeighbourTrigs(); } else { PrintUserError("no triangle selected!"); } } void STLTopology :: OrientAfterTrig (int trig) { int starttrig = trig; if (starttrig >= 1 && starttrig <= GetNT()) { Array oriented; oriented.SetSize(GetNT()); int i; for (i = 1; i <= oriented.Size(); i++) { oriented.Elem(i) = 0; } oriented.Elem(starttrig) = 1; int k; Array list1; list1.SetSize(0); Array list2; list2.SetSize(0); list1.Append(starttrig); int cnt = 1; int end = 0; int nt; while (!end) { end = 1; for (i = 1; i <= list1.Size(); i++) { const STLTriangle& tt = GetTriangle(list1.Get(i)); for (k = 1; k <= 3; k++) { nt = tt.NBTrigNum (k); // NeighbourTrig(list1.Get(i),k); if (oriented.Get(nt) == 0) { if (tt.IsWrongNeighbourFrom(GetTriangle(nt))) { GetTriangle(nt).ChangeOrientation(); } oriented.Elem(nt) = 1; list2.Append(nt); cnt++; end = 0; } } } list1.SetSize(0); for (i = 1; i <= list2.Size(); i++) { list1.Append(list2.Get(i)); } list2.SetSize(0); } PrintMessage(5,"NO corrected triangles = ",cnt); if (cnt == GetNT()) { PrintMessage(5,"ALL triangles oriented in same way!"); } else { PrintWarning("NOT ALL triangles oriented in same way!"); } // topedges.SetSize(0); FindNeighbourTrigs(); } else { PrintUserError("no triangle selected!"); } } static RegisterClassForArchive stltop; } netgen-6.2.1905/libsrc/stlgeom/stlgeommesh.cpp0000644000175000017500000011626513504650527017777 0ustar kurtkurt//20.11.1999 second part of stlgeom.cc, mainly mesh functions #include #include #include #include #include #include "stlgeom.hpp" namespace netgen { int EdgeUsed(int p1, int p2, Array& edges, INDEX_2_HASHTABLE& hashtab) { if (p1 > p2) {swap (p1,p2);} if (hashtab.Used(INDEX_2(p1,p2))) {return hashtab.Get(INDEX_2(p1,p2));} return 0; } Point<3> STLGeometry :: PointBetween(const Point<3> & ap1, int t1, const Point<3> & ap2, int t2) { //funktioniert nicht in allen Fällen! PrintWarning("Point between"); ClearMarkedSegs(); InitMarkedTrigs(); SetMarkedTrig(t1,1); SetMarkedTrig(t2,1); TABLE edgepoints; TABLE edgepointdists; TABLE edgepointorigines; TABLE edgepointoriginps; Array edgetrigs; Array edgepointnums; Array edgetriglocinds; int size = 3*GetNT(); INDEX_2_HASHTABLE hashtab(size); int divisions = 10; edgepoints.SetSize(size); edgepointdists.SetSize(size); edgepointorigines.SetSize(size); edgepointoriginps.SetSize(size); edgetrigs.SetSize(size); edgepointnums.SetSize(size); edgetriglocinds.SetSize(size); Array edgelist1; Array edgelist2; edgelist1.SetSize(0); edgelist2.SetSize(0); int i, j, k, l, m; int edgecnt = 0; //first triangle: for (i = 1; i <= 3; i++) { int ptn1 = GetTriangle(t1).PNum(i); int ptn2 = GetTriangle(t1).PNumMod(i+1); if (ptn1 > ptn2) {swap(ptn1,ptn2);} Point3d pt1 = GetPoint(ptn1); Point3d pt2 = GetPoint(ptn2); edgecnt++; edgetrigs.Elem(edgecnt) = t1; edgepointnums.Elem(edgecnt) = INDEX_2(ptn1,ptn2); hashtab.Set(edgepointnums.Get(edgecnt),edgecnt); edgetriglocinds.Elem(edgecnt) = i; edgelist1.Append(edgecnt); for (j = 1; j <= divisions; j++) { double lfact = (double)j/(double)divisions; Point3d pbtw(lfact*pt1.X()+(1.-lfact)*pt2.X(), lfact*pt1.Y()+(1.-lfact)*pt2.Y(), lfact*pt1.Z()+(1.-lfact)*pt2.Z()); //AddMarkedSeg(ap1,pbtw); edgepoints.Add1(edgecnt,pbtw); edgepointdists.Add1(edgecnt,Dist(pbtw,ap1)); edgepointorigines.Add1(edgecnt,0); edgepointoriginps.Add1(edgecnt,0); } } int finished = 0; int endpointorigine = 0; int endpointoriginp = 0; double endpointmindist = 1E50; int maxsize = 0; while (!finished) { finished = 1; if (edgelist1.Size() > maxsize) {maxsize = edgelist1.Size();} for (i = 1; i <= edgelist1.Size(); i++) { int en = edgelist1.Get(i); int trig = edgetrigs.Get(en); int edgenum = edgetriglocinds.Get(en); int tn = NeighbourTrigSorted(trig,edgenum); if (tn != t2) { for (k = 1; k <= 3; k++) { int pnt1 = GetTriangle(tn).PNum(k); int pnt2 = GetTriangle(tn).PNumMod(k+1); if (pnt1 > pnt2) {swap(pnt1,pnt2);} Point3d pt1 = GetPoint(pnt1); Point3d pt2 = GetPoint(pnt2); //AddMarkedSeg(pt1,pt2); //if (!(pnt1 == ep1 && pnt2 == ep2)) // { int edgeused = 0; edgenum = EdgeUsed(pnt1, pnt2, edgepointnums, hashtab); if (edgenum != en) { if (edgenum != 0) {edgeused = 1;} else { edgecnt++; edgenum = edgecnt; edgetrigs.Elem(edgenum) = tn; edgepointnums.Elem(edgenum) = INDEX_2(pnt1,pnt2); hashtab.Set(edgepointnums.Get(edgenum),edgenum); edgetriglocinds.Elem(edgenum) = k; } if (edgenum > size || edgenum == 0) {PrintSysError("edgenum = ", edgenum);} double minofmindist = 1E50; int changed = 0; for (l = 1; l <= divisions; l++) { double lfact = (double)l/(double)divisions; Point3d pbtw(lfact*pt1.X()+(1.-lfact)*pt2.X(), lfact*pt1.Y()+(1.-lfact)*pt2.Y(), lfact*pt1.Z()+(1.-lfact)*pt2.Z()); double mindist = 1E50; int index=0; for (m = 1; m <= divisions; m++) { const Point3d& p = edgepoints.Get(en,m); if (Dist(pbtw,p) + edgepointdists.Get(en,m) < mindist) {mindist = Dist(pbtw,p) + edgepointdists.Get(en,m); index = m;} } //if (mindist < endpointmindist) {finished = 0;} if (mindist < minofmindist) {minofmindist = mindist;} if (!edgeused) { //AddMarkedSeg(pbtw,edgepoints.Get(en,index)); edgepoints.Add1(edgenum,pbtw); edgepointdists.Add1(edgenum,mindist); edgepointorigines.Add1(edgenum,en); edgepointoriginps.Add1(edgenum,index); changed = 1; } else { if (mindist < edgepointdists.Get(edgenum,l)) { edgepointdists.Set(edgenum,l,mindist); edgepointorigines.Set(edgenum,l,en); edgepointoriginps.Set(edgenum,l,index); changed = 1; } } } if (minofmindist < endpointmindist-1E-10 && changed) { finished = 0; edgelist2.Append(edgenum); } } } } else { double mindist = 1E50; int index(0); for (m = 1; m <= divisions; m++) { const Point3d& p = edgepoints.Get(en,m); if (Dist(ap2,p) + edgepointdists.Get(en,m) < mindist) {mindist = Dist(ap2,p) + edgepointdists.Get(en,m); index = m;} } if (mindist < endpointmindist) { endpointorigine = en; endpointoriginp = index; endpointmindist = mindist; } } } edgelist1.SetSize(0); for (i = 1; i <= edgelist2.Size(); i++) { edgelist1.Append(edgelist2.Get(i)); } } if (!endpointorigine) {PrintSysError("No connection found!");} Array plist; plist.Append(ap2); int laste = endpointorigine; int lastp = endpointoriginp; int lle, llp; while (laste) { plist.Append(edgepoints.Get(laste,lastp)); lle = laste; llp = lastp; laste = edgepointorigines.Get(lle,llp); lastp = edgepointoriginps.Get(lle,llp); } plist.Append(ap1); for (i = 1; i <= plist.Size()-1; i++) { AddMarkedSeg(plist.Get(i),plist.Get(i+1)); } PrintMessage(5,"PointBetween: complexity=", maxsize); Point3d pm; double dist = 0; int found = 0; for (i = 1; i <= plist.Size()-1; i++) { dist += Dist(plist.Get(i),plist.Get(i+1)); if (dist > endpointmindist*0.5) { double segl = Dist(plist.Get(i), plist.Get(i+1)); double d = dist - endpointmindist * 0.5; pm = Point3d(d/segl*plist.Get(i).X() + (1.-d/segl)*plist.Get(i+1).X(), d/segl*plist.Get(i).Y() + (1.-d/segl)*plist.Get(i+1).Y(), d/segl*plist.Get(i).Z() + (1.-d/segl)*plist.Get(i+1).Z()); found = 1; break; } } if (!found) {PrintWarning("Problem in PointBetween"); pm = Center(ap1,ap2);} AddMarkedSeg(pm, Point3d(0.,0.,0.)); return pm; } void STLGeometry :: PrepareSurfaceMeshing() { meshchart = -1; //clear no old chart meshcharttrigs.SetSize(GetNT()); meshcharttrigs = 0; } void STLGeometry::GetMeshChartBoundary (Array & apoints, Array & points3d, Array & alines, double h) { twoint seg, newseg; int zone; Point<2> p2; const STLChart& chart = GetChart(meshchart); for (int i = 1; i <= chart.GetNOLimit(); i++) { seg = chart.GetOLimit(i); INDEX_2 i2; for (int j = 1; j <= 2; j++) { int pi = (j == 1) ? seg.i1 : seg.i2; int lpi; if (ha_points.Get(pi) == 0) { const Point<3> & p3d = GetPoint (pi); Point<2> p2d; points3d.Append (p3d); ToPlane(p3d, 0, p2d, h, zone, 0); apoints.Append (p2d); lpi = apoints.Size(); ha_points.Elem(pi) = lpi; } else lpi = ha_points.Get(pi); i2.I(j) = lpi; } alines.Append (i2); /* seg = chart.GetOLimit(i); psize = points.Size(); newseg.i1 = psize+1; newseg.i2 = psize+2; ToPlane(GetPoint(seg.i1), 0, p2, h, zone, 0); points.Append(p2); points3d.Append (GetPoint(seg.i1)); ToPlane(GetPoint(seg.i2), 0, p2, h, zone, 0); points.Append(p2); points3d.Append (GetPoint(seg.i2)); lines.Append (INDEX_2 (points.Size()-1, points.Size())); */ } for (int i = 1; i <= chart.GetNOLimit(); i++) { seg = chart.GetOLimit(i); ha_points.Elem(seg.i1) = 0; ha_points.Elem(seg.i2) = 0; } } void STLGeometry :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2, int trig) { p1 = ap1; //save for ToPlane, in data of STLGeometry class Point<3> p2 = ap2; //only locally used meshchart = GetChartNr(trig); if (usechartnormal) meshtrignv = GetChart(meshchart).GetNormal(); else meshtrignv = GetTriangle(trig).Normal(); //meshtrignv = GetTriangle(trig).Normal(points); meshtrignv /= meshtrignv.Length(); GetTriangle(trig).ProjectInPlain(points, meshtrignv, p2); ez = meshtrignv; ez /= ez.Length(); ex = p2 - p1; ex -= (ex * ez) * ez; ex /= ex.Length(); ey = Cross (ez, ex); } void STLGeometry :: SelectChartOfTriangle (int trignum) { meshchart = GetChartNr(trignum); meshtrignv = GetTriangle(trignum).Normal(); } void STLGeometry :: SelectChartOfPoint (const Point<3> & p) { int i, ii; Array trigsinbox; Box<3> box(p,p); box.Increase (1e-6); GetTrianglesInBox (box, trigsinbox); // for (i = 1; i <= GetNT(); i++) for (ii = 1; ii <= trigsinbox.Size(); ii++) { i = trigsinbox.Get(ii); Point<3> hp = p; if (GetTriangle(i).GetNearestPoint(points, hp) <= 1E-8) { SelectChartOfTriangle (i); break; } } return; } void STLGeometry :: ToPlane (const Point<3> & locpoint, int * trigs, Point<2> & plainpoint, double h, int& zone, int checkchart) { if (checkchart) { //check if locpoint lies on actual chart: zone = 0; // Point3d p; int i = 1; const STLChart& chart = GetChart(meshchart); int foundinchart = 0; const double range = 1e-6; //1e-4 old if (trigs) { int * htrigs = trigs; while (*htrigs) { if (TrigIsInOC (*htrigs, meshchart)) { foundinchart = 1; break; } htrigs++; } } else { Array trigsinbox; if (!geomsearchtreeon) { //alter chart-tree Box<3> box(locpoint, locpoint); box.Increase (range); chart.GetTrianglesInBox (box.PMin(), box.PMax(), trigsinbox); } else { Array trigsinbox2; Box<3> box(locpoint, locpoint); box.Increase (range); GetTrianglesInBox (box, trigsinbox2); for (i = 1; i <= trigsinbox2.Size(); i++) { if (TrigIsInOC(trigsinbox2.Get(i),meshchart)) {trigsinbox.Append(trigsinbox2.Get(i));} } } for (i = 1; i <= trigsinbox.Size(); i++) { Point<3> p = locpoint; if (GetTriangle(trigsinbox.Get(i)).GetNearestPoint(points, p) <= 1E-8) { foundinchart = 1; break; } } } //do not use this point (but do correct projection (joachim) if (!foundinchart) { zone = -1; // plainpoint.X() = 11111; plainpoint.Y() = 11111; return; } } else { zone = 0; } //transform in plane Vec<3> p1p = locpoint - p1; plainpoint(0) = (p1p * ex) / h; plainpoint(1) = (p1p * ey) / h; } int STLGeometry :: FromPlane (const Point<2> & plainpoint, Point<3> & locpoint, double h) { Point2d plainpoint2 (plainpoint); plainpoint2.X() *= h; plainpoint2.Y() *= h; Vec3d p1p = plainpoint2.X() * ex + plainpoint2.Y() * ey; locpoint = p1 + p1p; int rv = Project(locpoint); if (!rv) {return 1;} //project nicht gegangen return 0; } int lasttrig; int STLGeometry :: LastTrig() const {return lasttrig;}; //project normal to tangential plane int STLGeometry :: Project(Point<3> & p3d) const { Point<3> p, pf; int i, j; int fi = 0; int cnt = 0; int different = 0; const double lamtol = 1e-6; const STLChart& chart = GetChart(meshchart); int nt = chart.GetNT(); QuadraticFunction3d quadfun(p3d, meshtrignv); /* Vec3d hv = meshtrignv; hv /= hv.Length(); Vec3d t1, t2; hv.GetNormal (t1); Cross (hv, t1, t2); */ for (j = 1; j <= nt; j++) { i = chart.GetTrig(j); const Point<3> & c = GetTriangle(i).center; /* double d1 = t1 * (c-p3d); double d2 = t2 * (c-p3d); */ /* if (d1 * d1 + d2 * d2 > sqr (GetTriangle(i).rad)) continue; */ if (quadfun.Eval(c) > sqr (GetTriangle(i).rad)) continue; p = p3d; Vec<3> lam; int err = GetTriangle(i).ProjectInPlain(points, meshtrignv, p, lam); int inside = (err == 0 && lam(0) > -lamtol && lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol); /* p = p3d; GetTriangle(i).ProjectInPlain(points, meshtrignv, p); if (GetTriangle(i).PointInside(points, p)) */ if (inside) { if (cnt != 0) { if (Dist2(p,pf)>=1E-16) { // (*testout) << "ERROR: found two points to project which are different" << endl; //(*testout) << "p=" << p << ", pf=" << pf << endl; different = 1; } } pf = p; fi = i; cnt++; } if (inside) break; } // if (cnt == 2) {(*testout) << "WARNING: found 2 triangles to project" << endl;} //if (cnt == 3) {(*testout) << "WARNING: found 3 triangles to project" << endl;} //if (cnt > 3) {(*testout) << "WARNING: found more than 3 triangles to project" << endl;} if (fi != 0) {lasttrig = fi;} if (fi != 0 && !different) {p3d = pf; return fi;} // (*testout) << "WARNING: Project failed" << endl; return 0; } //project normal to tangential plane int STLGeometry :: ProjectOnWholeSurface(Point<3> & p3d) const { Point<3> p, pf; int i; int fi = 0; int cnt = 0; int different = 0; const double lamtol = 1e-6; for (i = 1; i <= GetNT(); i++) { p = p3d; Vec<3> lam; int err = GetTriangle(i).ProjectInPlain(points, meshtrignv, p, lam); int inside = (err == 0 && lam(0) > -lamtol && lam(1) > -lamtol && (1-lam(0)-lam(1)) > -lamtol); /* p = p3d; GetTriangle(i).ProjectInPlain(points, meshtrignv, p); if (GetTriangle(i).PointInside(points, p)) */ if (inside) { if (cnt != 0) { if (Dist2(p,pf)>=1E-16) { // (*testout) << "ERROR: found two points to project which are different" << endl; // (*testout) << "p=" << p << ", pf=" << pf << endl; different = 1; } } pf = p; fi = i; cnt++; } } /* if (cnt == 2) {(*testout) << "WARNING: found 2 triangles to project" << endl;} if (cnt == 3) {(*testout) << "WARNING: found 3 triangles to project" << endl;} if (cnt > 3) {(*testout) << "WARNING: found more than 3 triangles to project" << endl;} */ if (fi != 0) {lasttrig = fi;} if (fi != 0 && !different) {p3d = pf; return fi;} // (*testout) << "WARNING: Project failed" << endl; return 0; } int STLGeometry :: ProjectNearest(Point<3> & p3d) const { Point<3> p, pf = 0.0; //set new chart const STLChart& chart = GetChart(meshchart); int i; double nearest = 1E50; double dist; int ft = 0; for (i = 1; i <= chart.GetNT(); i++) { p = p3d; dist = GetTriangle(chart.GetTrig(i)).GetNearestPoint(points, p); if (dist < nearest) { pf = p; nearest = dist; ft = chart.GetTrig(i); } } p3d = pf; //if (!ft) {(*testout) << "ERROR: ProjectNearest failed" << endl;} return ft; } //Restrict local h due to curvature for make atlas void STLGeometry :: RestrictLocalHCurv(class Mesh & mesh, double gh) { PushStatusF("Restrict H due to surface curvature"); //bei jedem Dreieck alle Nachbardreiecke vergleichen, und, fallskein Kante dazwischen, //die Meshsize auf ein bestimmtes Mass limitieren int i,j; int ap1,ap2,p3,p4; Point<3> p1p, p2p, p3p, p4p; Vec<3> n, ntn; double rzyl, localh; // double localhfact = 0.5; // double geometryignorelength = 1E-4; double minlocalh = stlparam.atlasminh; Box<3> bb = GetBoundingBox(); // mesh.SetLocalH(bb.PMin() - Vec3d(10, 10, 10),bb.PMax() + Vec3d(10, 10, 10), // mparam.grading); // mesh.SetGlobalH(gh); double mincalch = 1E10; double maxcalch = -1E10 ; double objectsize = bb.Diam(); double geometryignoreedgelength = objectsize * 1e-5; if (stlparam.resthatlasenable) { Array minh; //minimales h pro punkt minh.SetSize(GetNP()); for (i = 1; i <= GetNP(); i++) { minh.Elem(i) = gh; } for (i = 1; i <= GetNT(); i++) { SetThreadPercent((double)i/(double)GetNT()*100.); if (multithread.terminate) {PopStatus(); return;} const STLTriangle& trig = GetTriangle(i); n = GetTriangle(i).Normal(); for (j = 1; j <= 3; j++) { const STLTriangle& nt = GetTriangle(NeighbourTrig(i,j)); trig.GetNeighbourPointsAndOpposite(nt,ap1,ap2,p3); //checken, ob ap1-ap2 eine Kante sind if (IsEdge(ap1,ap2)) continue; p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - ap1 - ap2; p1p = GetPoint(ap1); p2p = GetPoint(ap2); p3p = GetPoint(p3); p4p = GetPoint(p4); double h1 = GetDistFromInfiniteLine(p1p,p2p, p4p); double h2 = GetDistFromInfiniteLine(p1p,p2p, p3p); double diaglen = Dist (p1p, p2p); if (diaglen < geometryignoreedgelength) continue; rzyl = ComputeCylinderRadius (n, GetTriangle(NeighbourTrig(i,j)).Normal(), h1, h2); if (h1 < 1e-3 * diaglen && h2 < 1e-3 * diaglen) continue; if (h1 < 1e-5 * objectsize && h2 < 1e-5 * objectsize) continue; // rzyl = mindist/(2*sinang); localh = 10.*rzyl / stlparam.resthatlasfac; if (localh < mincalch) {mincalch = localh;} if (localh > maxcalch) {maxcalch = localh;} if (localh < minlocalh) {localh = minlocalh;} if (localh < gh) { minh.Elem(ap1) = min2(minh.Elem(ap1),localh); minh.Elem(ap2) = min2(minh.Elem(ap2),localh); } mesh.RestrictLocalHLine(p1p, p2p, localh); } } } PrintMessage(5, "done\nATLAS H: nmin local h=", mincalch); PrintMessage(5, "ATLAS H: max local h=", maxcalch); PrintMessage(5, "Local h tree has ", mesh.LocalHFunction().GetNBoxes(), " boxes of size ", (int)sizeof(GradingBox)); PopStatus(); } //restrict local h due to near edges and due to outer chart distance void STLGeometry :: RestrictLocalH(class Mesh & mesh, double gh) { //bei jedem Dreieck alle Nachbardreiecke vergleichen, und, fallskein Kante dazwischen, //die Meshsize auf ein bestimmtes Mass limitieren int i,j; int ap1,ap2,p3,p4; Point3d p1p, p2p, p3p, p4p; Vec3d n, ntn; double rzyl, localh; // double localhfact = 0.5; // double geometryignorelength = 1E-4; Box<3> bb = GetBoundingBox(); //mesh.SetLocalH(bb.PMin() - Vec3d(10, 10, 10),bb.PMax() + Vec3d(10, 10, 10), // mparam.grading); //mesh.SetGlobalH(gh); double mincalch = 1E10; double maxcalch = -1E10; double objectsize = bb.Diam(); double geometryignoreedgelength = objectsize * 1e-5; if (stlparam.resthsurfcurvenable) { PushStatusF("Restrict H due to surface curvature"); Array minh; //minimales h pro punkt minh.SetSize(GetNP()); for (i = 1; i <= GetNP(); i++) { minh.Elem(i) = gh; } for (i = 1; i <= GetNT(); i++) { SetThreadPercent((double)i/(double)GetNT()*100.); if (i%20000==19999) {PrintMessage(7, (double)i/(double)GetNT()*100. , "%");} if (multithread.terminate) {PopStatus(); return;} const STLTriangle& trig = GetTriangle(i); n = GetTriangle(i).Normal(); for (j = 1; j <= 3; j++) { const STLTriangle& nt = GetTriangle(NeighbourTrig(i,j)); trig.GetNeighbourPointsAndOpposite(nt,ap1,ap2,p3); //checken, ob ap1-ap2 eine Kante sind if (IsEdge(ap1,ap2)) continue; p4 = trig.PNum(1) + trig.PNum(2) + trig.PNum(3) - ap1 - ap2; p1p = GetPoint(ap1); p2p = GetPoint(ap2); p3p = GetPoint(p3); p4p = GetPoint(p4); double h1 = GetDistFromInfiniteLine(p1p,p2p, p4p); double h2 = GetDistFromInfiniteLine(p1p,p2p, p3p); double diaglen = Dist (p1p, p2p); if (diaglen < geometryignoreedgelength) continue; rzyl = ComputeCylinderRadius (n, GetTriangle (NeighbourTrig(i,j)).Normal(), h1, h2); if (h1 < 1e-3 * diaglen && h2 < 1e-3 * diaglen) continue; if (h1 < 1e-5 * objectsize && h2 < 1e-5 * objectsize) continue; // rzyl = mindist/(2*sinang); localh = rzyl / stlparam.resthsurfcurvfac; if (localh < mincalch) {mincalch = localh;} if (localh > maxcalch) {maxcalch = localh;} if (localh < gh) { minh.Elem(ap1) = min2(minh.Elem(ap1),localh); minh.Elem(ap2) = min2(minh.Elem(ap2),localh); } //if (localh < 0.2) {localh = 0.2;} if(localh < objectsize) mesh.RestrictLocalHLine(p1p, p2p, localh); (*testout) << "restrict h along " << p1p << " - " << p2p << " to " << localh << endl; if (localh < 0.1) { localh = 0.1; } } } PrintMessage(7, "done\nmin local h=", mincalch, "\nmax local h=", maxcalch); PopStatus(); } if (stlparam.resthcloseedgeenable) { PushStatusF("Restrict H due to close edges"); //geht nicht für spiralen!!!!!!!!!!!!!!!!!! double disttohfact = sqr(10.0 / stlparam.resthcloseedgefac); int k,l; double h1, h2, dist; int rc = 0; Point3d p3p1; double mindist = 1E50; PrintMessage(7,"build search tree..."); BoxTree<3> * lsearchtree = new BoxTree<3> (GetBoundingBox().PMin() - Vec3d(1,1,1), GetBoundingBox().PMax() + Vec3d(1,1,1)); Array pmins(GetNLines()); Array pmaxs(GetNLines()); double maxhline; for (i = 1; i <= GetNLines(); i++) { maxhline = 0; STLLine* l1 = GetLine(i); Point3d pmin(GetPoint(l1->StartP())), pmax(GetPoint(l1->StartP())), px; for (j = 2; j <= l1->NP(); j++) { px = GetPoint(l1->PNum(j)); maxhline = max2(maxhline,mesh.GetH(px)); pmin.SetToMin (px); pmax.SetToMax (px); } Box3d box(pmin,pmax); box.Increase(maxhline); lsearchtree->Insert (box.PMin(), box.PMax(), i); pmins.Elem(i) = box.PMin(); pmaxs.Elem(i) = box.PMax(); } Array linenums; int k2; for (i = 1; i <= GetNLines(); i++) { SetThreadPercent((double)i/(double)GetNLines()*100.); if (multithread.terminate) {PopStatus(); return;} linenums.SetSize(0); lsearchtree->GetIntersecting(pmins.Get(i),pmaxs.Get(i),linenums); STLLine* l1 = GetLine(i); for (j = 1; j <= l1->NP(); j++) { p3p1 = GetPoint(l1->PNum(j)); h1 = sqr(mesh.GetH(p3p1)); for (k2 = 1; k2 <= linenums.Size(); k2++) { k = linenums.Get(k2); if (k <= i) {continue;} /* //old, without searchtrees for (k = i+1; k <= GetNLines(); k++) { */ STLLine* l2 = GetLine(k); for (l = 1; l <= l2->NP(); l++) { const Point3d& p3p2 = GetPoint(l2->PNum(l)); h2 = sqr(mesh.GetH(p3p2)); dist = Dist2(p3p1,p3p2)*disttohfact; if (dist > 1E-12) { if (dist < h1) { mesh.RestrictLocalH(p3p1,sqrt(dist)); rc++; mindist = min2(mindist,sqrt(dist)); } if (dist < h2) { mesh.RestrictLocalH(p3p2,sqrt(dist)); rc++; mindist = min2(mindist,sqrt(dist)); } } } } } } PrintMessage(5, "done\n Restricted h in ", rc, " points due to near edges!"); PopStatus(); } if (stlparam.resthedgeangleenable) { PushStatusF("Restrict h due to close edges"); int lp1, lp2; Vec3d v1,v2; mincalch = 1E50; maxcalch = -1E50; for (i = 1; i <= GetNP(); i++) { SetThreadPercent((double)i/(double)GetNP()*100.); if (multithread.terminate) {PopStatus(); return;} if (GetNEPP(i) == 2 && !IsLineEndPoint(i)) { if (GetEdge(GetEdgePP(i,1)).PNum(2) == GetEdge(GetEdgePP(i,2)).PNum(1) || GetEdge(GetEdgePP(i,1)).PNum(1) == GetEdge(GetEdgePP(i,2)).PNum(2)) { lp1 = 1; lp2 = 2; } else { lp1 = 2; lp2 = 1; } v1 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,1)).PNum(1)), GetPoint(GetEdge(GetEdgePP(i,1)).PNum(2))); v2 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp1)), GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp2))); rzyl = ComputeCylinderRadius(v1, v2, v1.Length(), v2.Length()); localh = rzyl / stlparam.resthedgeanglefac; if (localh < mincalch) {mincalch = localh;} if (localh > maxcalch) {maxcalch = localh;} if (localh != 0) mesh.RestrictLocalH(GetPoint(i), localh); } } PrintMessage(7,"edge-angle min local h=", mincalch, "\nedge-angle max local h=", maxcalch); PopStatus(); } if (stlparam.resthchartdistenable) { PushStatusF("Restrict H due to outer chart distance"); // mesh.LocalHFunction().Delete(); //berechne minimale distanz von chart zu einem nicht-outerchart-punkt in jedem randpunkt einer chart Array acttrigs(GetNT()); //outercharttrigs acttrigs = 0; for (i = 1; i <= GetNOCharts(); i++) { SetThreadPercent((double)i/(double)GetNOCharts()*100.); if (multithread.terminate) {PopStatus(); return;} RestrictHChartDistOneChart(i, acttrigs, mesh, gh, 1., 0.); } PopStatus(); // NgProfiler::Print(stdout); } if (stlparam.resthlinelengthenable) { //restrict h due to short lines PushStatusF("Restrict H due to line-length"); double minhl = 1E50; double linefact = 1./stlparam.resthlinelengthfac; double l; for (i = 1; i <= GetNLines(); i++) { SetThreadPercent((double)i/(double)GetNLines()*100.); if (multithread.terminate) {PopStatus(); return;} l = GetLine(i)->GetLength(points); const Point3d& pp1 = GetPoint(GetLine(i)->StartP()); const Point3d& pp2 = GetPoint(GetLine(i)->EndP()); if (l != 0) { minhl = min2(minhl,l*linefact); mesh.RestrictLocalH(pp1, l*linefact); mesh.RestrictLocalH(pp2, l*linefact); } } PopStatus(); PrintMessage(5, "minh due to line length=", minhl); } } void STLGeometry :: RestrictHChartDistOneChart(int chartnum, Array& acttrigs, class Mesh & mesh, double gh, double fact, double minh) { static int timer1 = NgProfiler::CreateTimer ("restrictH OneChart 1"); static int timer2 = NgProfiler::CreateTimer ("restrictH OneChart 2"); static int timer3 = NgProfiler::CreateTimer ("restrictH OneChart 3"); static int timer3a = NgProfiler::CreateTimer ("restrictH OneChart 3a"); static int timer3b = NgProfiler::CreateTimer ("restrictH OneChart 3b"); NgProfiler::StartTimer (timer1); double limessafety = stlparam.resthchartdistfac*fact; // original: 2 double localh; // mincalch = 1E10; //maxcalch = -1E10; Array limes1; Array limes2; Array plimes1; Array plimes2; Array plimes1trigs; //check from which trig the points come Array plimes2trigs; Array plimes1origin; //either the original pointnumber or zero, if new point int divisions = 10; int np1, np2; // Point3d p3p1, p3p2; STLTriangle tt; limes1.SetSize(0); limes2.SetSize(0); plimes1.SetSize(0); plimes2.SetSize(0); plimes1trigs.SetSize(0); plimes2trigs.SetSize(0); plimes1origin.SetSize(0); STLChart& chart = GetChart(chartnum); chart.ClearOLimit(); chart.ClearILimit(); for (int j = 1; j <= chart.GetNChartT(); j++) { int t = chart.GetChartTrig(j); tt = GetTriangle(t); for (int k = 1; k <= 3; k++) { int nt = NeighbourTrig(t,k); if (GetChartNr(nt) != chartnum) { tt.GetNeighbourPoints(GetTriangle(nt),np1,np2); if (!IsEdge(np1,np2) && !GetSpiralPoint(np1) && !GetSpiralPoint(np2)) { Point3d p3p1 = GetPoint(np1); Point3d p3p2 = GetPoint(np2); // if (AddIfNotExists(limes1,np1)) if (!limes1.Contains(np1)) { limes1.Append(np1); plimes1.Append(p3p1); plimes1trigs.Append(t); plimes1origin.Append(np1); } // if (AddIfNotExists(limes1,np2)) if (!limes1.Contains(np2)) { limes1.Append(np2); plimes1.Append(p3p2); plimes1trigs.Append(t); plimes1origin.Append(np2); } chart.AddILimit(twoint(np1,np2)); for (int di = 1; di <= divisions; di++) { double f1 = (double)di/(double)(divisions+1.); double f2 = (divisions+1.-(double)di)/(double)(divisions+1.); plimes1.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2, p3p1.Y()*f1+p3p2.Y()*f2, p3p1.Z()*f1+p3p2.Z()*f2)); plimes1trigs.Append(t); plimes1origin.Append(0); } } } } } NgProfiler::StopTimer (timer1); NgProfiler::StartTimer (timer2); for (int j = 1; j <= chart.GetNT(); j++) acttrigs.Elem(chart.GetTrig(j)) = chartnum; for (int j = 1; j <= chart.GetNOuterT(); j++) { int t = chart.GetOuterTrig(j); tt = GetTriangle(t); for (int k = 1; k <= 3; k++) { int nt = NeighbourTrig(t,k); if (acttrigs.Get(nt) != chartnum) { tt.GetNeighbourPoints(GetTriangle(nt),np1,np2); if (!IsEdge(np1,np2)) { Point3d p3p1 = GetPoint(np1); Point3d p3p2 = GetPoint(np2); // if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);} // if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);} if (!limes2.Contains(np1)) { limes2.Append(np1); plimes2.Append(p3p1); plimes2trigs.Append(t); } if (!limes2.Contains(np2)) { limes2.Append(np2); plimes2.Append(p3p2); plimes2trigs.Append(t); } chart.AddOLimit(twoint(np1,np2)); for (int di = 1; di <= divisions; di++) { double f1 = (double)di/(double)(divisions+1.); double f2 = (divisions+1.-(double)di)/(double)(divisions+1.); plimes2.Append(Point3d(p3p1.X()*f1+p3p2.X()*f2, p3p1.Y()*f1+p3p2.Y()*f2, p3p1.Z()*f1+p3p2.Z()*f2)); plimes2trigs.Append(t); } } } } } NgProfiler::StopTimer (timer2); NgProfiler::StartTimer (timer3); double chartmindist = 1E50; if (plimes2.Size()) { NgProfiler::StartTimer (timer3a); Box3d bbox; bbox.SetPoint (plimes2.Get(1)); for (int j = 2; j <= plimes2.Size(); j++) bbox.AddPoint (plimes2.Get(j)); Point3dTree stree(bbox.PMin(), bbox.PMax()); for (int j = 1; j <= plimes2.Size(); j++) stree.Insert (plimes2.Get(j), j); Array foundpts; NgProfiler::StopTimer (timer3a); NgProfiler::StartTimer (timer3b); for (int j = 1; j <= plimes1.Size(); j++) { double mindist = 1E50; const Point3d & ap1 = plimes1.Get(j); double boxs = mesh.GetH (plimes1.Get(j)) * limessafety; Point3d pmin = ap1 - Vec3d (boxs, boxs, boxs); Point3d pmax = ap1 + Vec3d (boxs, boxs, boxs); stree.GetIntersecting (pmin, pmax, foundpts); for (int kk = 1; kk <= foundpts.Size(); kk++) { int k = foundpts.Get(kk); double dist = Dist2(plimes1.Get(j),plimes2.Get(k)); if (dist < mindist) mindist = dist; } /* const Point3d & ap1 = plimes1.Get(j); double his = mesh.GetH (plimes1.Get(j)); double xmin = ap1.X() - his * limessafety; double xmax = ap1.X() + his * limessafety; double ymin = ap1.Y() - his * limessafety; double ymax = ap1.Y() + his * limessafety; double zmin = ap1.Z() - his * limessafety; double zmax = ap1.Z() + his * limessafety; for (k = 1; k <= plimes2.Size(); k++) { const Point3d & ap2 = plimes2.Get(k); if (ap2.X() >= xmin && ap2.X() <= xmax && ap2.Y() >= ymin && ap2.Y() <= ymax && ap2.Z() >= zmin && ap2.Z() <= zmax) { dist = Dist2(plimes1.Get(j),plimes2.Get(k)); if (dist < mindist) { mindist = dist; } } } */ mindist = sqrt(mindist); localh = mindist/limessafety; if (localh < minh && localh != 0) {localh = minh;} //minh is generally 0! (except make atlas) if (localh < gh && localh > 0) { mesh.RestrictLocalH(plimes1.Get(j), localh); // if (mindist < mincalch) {mincalch = mindist;} // if (mindist > maxcalch) {maxcalch = mindist;} if (mindist < chartmindist) {chartmindist = mindist;} } } NgProfiler::StopTimer (timer3b); } NgProfiler::StopTimer (timer3); } int STLMeshingDummy (STLGeometry* stlgeometry, shared_ptr & mesh, MeshingParameters & mparam) { if (mparam.perfstepsstart > mparam.perfstepsend) return 0; multithread.terminate = 0; int success = 1; //int trialcntouter = 0; if (mparam.perfstepsstart <= MESHCONST_MESHEDGES) { if (mesh) mesh -> DeleteMesh(); else mesh = make_shared(); mesh->geomtype = Mesh::GEOM_STL; mesh -> SetGlobalH (mparam.maxh); mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), mparam.grading); mesh -> LoadLocalMeshSize (mparam.meshsizefilename); success = 0; //mesh->DeleteMesh(); STLMeshing (*stlgeometry, *mesh); stlgeometry->edgesfound = 1; stlgeometry->surfacemeshed = 0; stlgeometry->surfaceoptimized = 0; stlgeometry->volumemeshed = 0; } if (multithread.terminate) return 0; if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE && mparam.perfstepsend >= MESHCONST_MESHSURFACE) { if (!stlgeometry->edgesfound) { PrintUserError("You have to do 'analyse geometry' first!!!"); return 0; } if (stlgeometry->surfacemeshed || stlgeometry->surfacemeshed) { PrintUserError("Already meshed. Please start again with 'Analyse Geometry'!!!"); return 0; } success = 0; int retval = STLSurfaceMeshing (*stlgeometry, *mesh); if (retval == MESHING3_OK) { PrintMessage(3,"Success !!!!"); stlgeometry->surfacemeshed = 1; stlgeometry->surfaceoptimized = 0; stlgeometry->volumemeshed = 0; success = 1; } else if (retval == MESHING3_OUTERSTEPSEXCEEDED) { PrintError("Give up because of too many trials. Meshing aborted!"); } else if (retval == MESHING3_TERMINATE) { PrintWarning("Meshing Stopped by user!"); } else { PrintError("Surface meshing not successful. Meshing aborted!"); } #ifdef STAT_STREAM (*statout) << mesh->GetNSeg() << " & " << endl << mesh->GetNSE() << " & " << endl << GetTime() << " & "; #endif } if (multithread.terminate) return 0; if (success) { if (mparam.perfstepsstart <= MESHCONST_OPTSURFACE && mparam.perfstepsend >= MESHCONST_OPTSURFACE) { if (!stlgeometry->edgesfound) { PrintUserError("You have to do 'meshing->analyse geometry' first!!!"); return 0; } if (!stlgeometry->surfacemeshed) { PrintUserError("You have to do 'meshing->mesh surface' first!!!"); return 0; } if (stlgeometry->volumemeshed) { PrintWarning("Surface optimization with meshed volume is dangerous!!!"); } /* if (!optstring || strlen(optstring) == 0) { mparam.optimize2d = "smcm"; } else { mparam.optimize2d = optstring; } */ STLSurfaceOptimization (*stlgeometry, *mesh, mparam); if (stlparam.recalc_h_opt) { mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), mparam.grading); mesh -> LoadLocalMeshSize (mparam.meshsizefilename); mesh -> CalcLocalHFromSurfaceCurvature (mparam.grading, stlparam.resthsurfmeshcurvfac); mparam.optimize2d = "cmsmSm"; STLSurfaceOptimization (*stlgeometry, *mesh, mparam); #ifdef STAT_STREAM (*statout) << GetTime() << " & "; #endif mparam.Render(); } stlgeometry->surfaceoptimized = 1; } if (multithread.terminate) return 0; if (mparam.perfstepsstart <= MESHCONST_MESHVOLUME && mparam.perfstepsend >= MESHCONST_MESHVOLUME) { if (stlgeometry->volumemeshed) { PrintUserError("Volume already meshed!"); return 0; } if (!stlgeometry->edgesfound) { PrintUserError("You have to do 'meshing->analyse geometry' first!!!"); return 0; } if (!stlgeometry->surfacemeshed) { PrintUserError("You have to do 'meshing->mesh surface' first!!!"); return 0; } if (!stlgeometry->surfaceoptimized) { PrintWarning("You should do 'meshing->optimize surface' first!!!"); } PrintMessage(5,"Check Overlapping boundary: "); mesh->FindOpenElements(); mesh->CheckOverlappingBoundary(); PrintMessage(5,""); if (stlparam.recalc_h_opt) { mesh -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), mparam.grading); mesh -> LoadLocalMeshSize (mparam.meshsizefilename); mesh -> CalcLocalH (mparam.grading); } PrintMessage(5,"Volume meshing"); int retval = MeshVolume (mparam, *mesh); if (retval == MESHING3_OK) { RemoveIllegalElements(*mesh); stlgeometry->volumemeshed = 1; } else if (retval == MESHING3_OUTERSTEPSEXCEEDED) { PrintError("Give up because of too many trials. Meshing aborted!"); return 0; } else if (retval == MESHING3_TERMINATE) { PrintWarning("Meshing Stopped by user!"); } else { PrintError("Volume meshing not successful. Meshing aborted!"); return 0; } #ifdef STAT_STREAM (*statout) << GetTime() << " & " << endl; #endif MeshQuality3d (*mesh); } if (multithread.terminate) return 0; if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME && mparam.perfstepsend >= MESHCONST_OPTVOLUME) { if (!stlgeometry->edgesfound) { PrintUserError("You have to do 'meshing->analyse geometry' first!!!"); return 0; } if (!stlgeometry->surfacemeshed) { PrintUserError("You have to do 'meshing->mesh surface' first!!!"); return 0; } if (!stlgeometry->volumemeshed) { PrintUserError("You have to do 'meshing->mesh volume' first!!!"); return 0; } /* if (!optstring || strlen(optstring) == 0) { mparam.optimize3d = "cmdmstm"; } else { mparam.optimize3d = optstring; } */ OptimizeVolume (mparam, *mesh); #ifdef STAT_STREAM (*statout) << GetTime() << " & " << endl; (*statout) << mesh->GetNE() << " & " << endl << mesh->GetNP() << " " << '\\' << '\\' << " \\" << "hline" << endl; #endif mparam.Render(); } } return 0; } } netgen-6.2.1905/libsrc/stlgeom/meshstlsurface.hpp0000644000175000017500000000642113504650527020475 0ustar kurtkurt#ifndef FILE_MESHSTLSURF #define FILE_MESHSTLSURF /* *************************************************************************/ /* File: meshstlsurf.hpp */ /* Author: Johannes Gerstmayr, Joachim Schoeberl */ /* Date: 01. Aug. 99 */ /* *************************************************************************/ /* The interface between mesh generation and stl geometry */ /// class MeshingSTLSurface : public Meshing2 { /// STLGeometry & geom; /// int transformationtrig; public: /// MeshingSTLSurface (STLGeometry & ageom, const MeshingParameters & mp); protected: /// virtual void DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo1, const PointGeomInfo * geominfo2); /// virtual void TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominfo, Point2d & plainpoint, double h, int & zone); /// virtual int TransformFromPlain (Point2d & plainpoint, Point3d & locpoint, PointGeomInfo & gi, double h); /// virtual int BelongsToActiveChart (const Point3d & p, const PointGeomInfo & gi); /// virtual int ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi); /// virtual int ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, PointGeomInfo & pgi); /// virtual int IsLineVertexOnChart (const Point3d & p1, const Point3d & p2, int endpoint, const PointGeomInfo & gi); virtual void GetChartBoundary (Array & points, Array & poitns3d, Array & lines, double h) const; /// virtual double CalcLocalH (const Point3d & p, double gh) const; /// virtual double Area () const; }; /// class MeshOptimizeSTLSurface : public MeshOptimize2d { /// STLGeometry & geom; public: /// MeshOptimizeSTLSurface (STLGeometry & ageom); /// virtual void SelectSurfaceOfPoint (const Point<3> & p, const PointGeomInfo & gi); /// virtual void ProjectPoint (INDEX surfind, Point<3> & p) const; /// virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const; /// virtual int CalcPointGeomInfo(PointGeomInfo& gi, const Point<3> & p3) const; /// virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const; }; class RefinementSTLGeometry : public Refinement { const STLGeometry & geom; public: RefinementSTLGeometry (const STLGeometry & ageom); virtual ~RefinementSTLGeometry (); virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const override; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const override; virtual void ProjectToSurface (Point<3> & p, int surfi) const override; virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const override; }; #endif netgen-6.2.1905/libsrc/stlgeom/CMakeLists.txt0000644000175000017500000000136613504650527017477 0ustar kurtkurtadd_library(stl ${NG_LIB_TYPE} meshstlsurface.cpp stlgeom.cpp stlgeomchart.cpp stlgeommesh.cpp stlline.cpp stltool.cpp stltopology.cpp python_stl.cpp ) if(NOT WIN32) target_link_libraries( stl mesh ${PYTHON_LIBRARIES}) install( TARGETS stl ${NG_INSTALL_DIR}) endif(NOT WIN32) target_link_libraries( stl ngcore ) if(USE_GUI) add_library(stlvis ${NG_LIB_TYPE} vsstl.cpp ) if(NOT WIN32) target_link_libraries( stlvis stl ) install( TARGETS stlvis ${NG_INSTALL_DIR}) endif(NOT WIN32) endif(USE_GUI) install(FILES meshstlsurface.hpp stlgeom.hpp stlline.hpp stltool.hpp stltopology.hpp vsstl.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/stlgeom COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/interface/0000755000175000017500000000000013504650527015217 5ustar kurtkurtnetgen-6.2.1905/libsrc/interface/nginterface_v2.cpp0000644000175000017500000010366513504650527020632 0ustar kurtkurt#include #ifdef SOCKETS #include "../sockets/sockets.hpp" #endif #include "nginterface.h" #include "nginterface_v2.hpp" // #include #include "writeuser.hpp" namespace netgen { extern shared_ptr mesh; } namespace netgen { #define NGX_INLINE #include "nginterface_v2_impl.hpp" shared_ptr Ngx_Mesh :: SelectMesh () const { shared_ptr hmesh = netgen::mesh; netgen::mesh = mesh; SetGlobalMesh (mesh); return hmesh; } Ngx_Mesh :: Ngx_Mesh (shared_ptr amesh) { mesh = amesh ? amesh : netgen::mesh; } Ngx_Mesh :: Ngx_Mesh (string filename, NgMPI_Comm acomm) { LoadMesh(filename, acomm); } Ngx_Mesh * LoadMesh (const string & filename, NgMPI_Comm comm) { netgen::mesh.reset(); Ng_LoadMesh (filename.c_str(), comm); return new Ngx_Mesh (netgen::mesh); } void Ngx_Mesh :: LoadMesh (const string & filename, NgMPI_Comm comm) { netgen::mesh.reset(); Ng_LoadMesh (filename.c_str(), comm); // mesh = move(netgen::mesh); mesh = netgen::mesh; } void Ngx_Mesh :: LoadMesh (istream & ist, NgMPI_Comm comm) { netgen::mesh = make_shared(); netgen::mesh->SetCommunicator(comm); netgen::mesh -> Load (ist); // mesh = move(netgen::mesh); mesh = netgen::mesh; SetGlobalMesh (mesh); } NgMPI_Comm Ngx_Mesh :: GetCommunicator() const { return Valid() ? mesh->GetCommunicator() : NgMPI_Comm{}; } void Ngx_Mesh :: SaveMesh (ostream & ost) const { mesh -> Save (ost); } void Ngx_Mesh :: DoArchive (Archive & archive) { #ifdef PARALLEL if (archive.Input()) { mesh = make_shared(); mesh->SetCommunicator(GetCommunicator()); } #endif mesh->DoArchive(archive); if (archive.Input()) { netgen::mesh = mesh; SetGlobalMesh (mesh); } /* if (archive.Output()) { stringstream str; SaveMesh (str); string st = str.str(); archive & st; } else { string st; archive & st; stringstream str(st); LoadMesh (str); } */ } void Ngx_Mesh :: UpdateTopology () { if (mesh) mesh -> UpdateTopology(); } /* Ngx_Mesh :: Ngx_Mesh (Mesh * amesh) : mesh(amesh) { ; } */ Ngx_Mesh :: ~Ngx_Mesh () { // causes crashes when global variable netgen::mesh is destructed // before visualization data if (mesh == netgen::mesh) netgen::mesh = nullptr; } int Ngx_Mesh :: GetDimension() const { return mesh -> GetDimension(); } int Ngx_Mesh :: GetNLevels() const { return mesh -> mglevels; } int Ngx_Mesh :: GetNElements (int dim) const { switch (dim) { case 0: return mesh -> pointelements.Size(); case 1: return mesh -> GetNSeg(); case 2: return mesh -> GetNSE(); case 3: return mesh -> GetNE(); } return -1; } int Ngx_Mesh :: GetNNodes (int nt) const { switch (nt) { case 0: return mesh -> GetNV(); case 1: return mesh->GetTopology().GetNEdges(); case 2: return mesh->GetTopology().GetNFaces(); case 3: return mesh -> GetNE(); } return -1; } /* Ng_Point Ngx_Mesh :: GetPoint (int nr) const { return Ng_Point (&mesh->Point(nr + PointIndex::BASE)(0)); } */ /* template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (int nr) const { const Element0d & el = mesh->pointelements[nr]; Ng_Element ret; ret.type = NG_PNT; ret.index = el.index; ret.points.num = 1; ret.points.ptr = (int*)&el.pnum; ret.vertices.num = 1; ret.vertices.ptr = (int*)&el.pnum; ret.edges.num = 0; ret.edges.ptr = NULL; ret.faces.num = 0; ret.faces.ptr = NULL; return ret; } */ /* template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (int nr) const { const Segment & el = mesh->LineSegment (SegmentIndex(nr)); Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&(el[0]); ret.vertices.num = 2; ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = 1; ret.edges.ptr = mesh->GetTopology().GetSegmentElementEdgesPtr (nr); ret.faces.num = 0; ret.faces.ptr = NULL; return ret; } template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<2> (int nr) const { const Element2d & el = mesh->SurfaceElement (SurfaceElementIndex (nr)); Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&el[0]; ret.vertices.num = el.GetNV(); ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = MeshTopology::GetNEdges (el.GetType()); ret.edges.ptr = mesh->GetTopology().GetSurfaceElementEdgesPtr (nr); ret.faces.num = MeshTopology::GetNFaces (el.GetType()); ret.faces.ptr = mesh->GetTopology().GetSurfaceElementFacesPtr (nr); return ret; } template <> DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<3> (int nr) const { const Element & el = mesh->VolumeElement (ElementIndex (nr)); Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&el[0]; ret.vertices.num = el.GetNV(); ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = MeshTopology::GetNEdges (el.GetType()); ret.edges.ptr = mesh->GetTopology().GetElementEdgesPtr (nr); ret.faces.num = MeshTopology::GetNFaces (el.GetType()); ret.faces.ptr = mesh->GetTopology().GetElementFacesPtr (nr); return ret; } */ /* template <> DLL_HEADER int Ngx_Mesh :: GetElementIndex<0> (int nr) const { return 0; } template <> DLL_HEADER int Ngx_Mesh :: GetElementIndex<1> (int nr) const { return (*mesh)[SegmentIndex(nr)].si; } template <> DLL_HEADER int Ngx_Mesh :: GetElementIndex<2> (int nr) const { int ind = (*mesh)[SurfaceElementIndex(nr)].GetIndex(); return mesh->GetFaceDescriptor(ind).BCProperty(); } template <> DLL_HEADER int Ngx_Mesh :: GetElementIndex<3> (int nr) const { return (*mesh)[ElementIndex(nr)].GetIndex(); } */ /* DLL_HEADER Ng_Point Ng_GetPoint (int nr) { Ng_Point ret; ret.pt = &mesh->Point(nr + PointIndex::BASE)(0); return ret; } template <> DLL_HEADER int Ng_GetElementIndex<1> (int nr) { return (*mesh)[SegmentIndex(nr)].si; } template <> DLL_HEADER int Ng_GetElementIndex<2> (int nr) { int ind = (*mesh)[SurfaceElementIndex(nr)].GetIndex(); return mesh->GetFaceDescriptor(ind).BCProperty(); } template <> DLL_HEADER int Ng_GetElementIndex<3> (int nr) { return (*mesh)[ElementIndex(nr)].GetIndex(); } template <> int DLL_HEADER Ng_GetNElements<0> () { return 0; } template <> int DLL_HEADER Ng_GetNElements<1> () { return mesh->GetNSeg(); } template <> DLL_HEADER int Ng_GetNElements<2> () { return mesh->GetNSE(); } template <> DLL_HEADER int Ng_GetNElements<3> () { return mesh->GetNE(); } template <> DLL_HEADER Ng_Element Ng_GetElement<0> (int nr) { cout << "Netgen does not support 0-D elements" << endl; Ng_Element ret; return ret; } template <> DLL_HEADER Ng_Element Ng_GetElement<1> (int nr) { const Segment & el = mesh->LineSegment (SegmentIndex(nr)); Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&(el[0]); ret.vertices.num = 2; ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = 1; ret.edges.ptr = mesh->GetTopology().GetSegmentElementEdgesPtr (nr); ret.faces.num = 0; ret.faces.ptr = NULL; return ret; } template <> DLL_HEADER Ng_Element Ng_GetElement<2> (int nr) { const Element2d & el = mesh->SurfaceElement (SurfaceElementIndex (nr)); Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&el[0]; ret.vertices.num = el.GetNV(); ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = MeshTopology::GetNEdges (el.GetType()); ret.edges.ptr = mesh->GetTopology().GetSurfaceElementEdgesPtr (nr); ret.faces.num = MeshTopology::GetNFaces (el.GetType()); ret.faces.ptr = mesh->GetTopology().GetSurfaceElementFacesPtr (nr); return ret; } template <> DLL_HEADER Ng_Element Ng_GetElement<3> (int nr) { const Element & el = mesh->VolumeElement (ElementIndex (nr)); Ng_Element ret; ret.type = NG_ELEMENT_TYPE(el.GetType()); ret.points.num = el.GetNP(); ret.points.ptr = (int*)&el[0]; ret.vertices.num = el.GetNV(); ret.vertices.ptr = (int*)&(el[0]); ret.edges.num = MeshTopology::GetNEdges (el.GetType()); ret.edges.ptr = mesh->GetTopology().GetElementEdgesPtr (nr); ret.faces.num = MeshTopology::GetNFaces (el.GetType()); ret.faces.ptr = mesh->GetTopology().GetElementFacesPtr (nr); return ret; } */ template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<3,3> (int elnr, const double * xi, double * x, double * dxdxi) const { Point<3> xl(xi[0], xi[1], xi[2]); Point<3> xg; Mat<3,3> dx; mesh->GetCurvedElements().CalcElementTransformation (xl, elnr, xg, dx); if (x) for (int i = 0; i < 3; i++) x[i] = xg(i); if (dxdxi) for (int i=0; i<3; i++) { dxdxi[3*i] = dx(i,0); dxdxi[3*i+1] = dx(i,1); dxdxi[3*i+2] = dx(i,2); } } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<2,3> (int elnr, const double * xi, double * x, double * dxdxi) const { Point<2> xl(xi[0], xi[1]); Point<3> xg; Mat<3,2> dx; mesh->GetCurvedElements().CalcSurfaceTransformation (xl, elnr, xg, dx); if (x) for (int i = 0; i < 3; i++) x[i] = xg(i); if (dxdxi) for (int i=0; i<3; i++) { dxdxi[2*i] = dx(i,0); dxdxi[2*i+1] = dx(i,1); } } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<1,3> (int elnr, const double * xi, double * x, double * dxdxi) const { Point<3> xg; Vec<3> dx; mesh->GetCurvedElements().CalcSegmentTransformation(xi[0],elnr,xg,dx); if(x) for(int i=0;i<3;i++) x[i] = xg(i); if(dxdxi) for(int i=0;i<3;i++) dxdxi[i] = dx(i); } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<0,3> (int elnr, const double * xi, double * x, double * dxdxi) const { PointIndex pi = mesh->pointelements[elnr].pnum; Point<3> xg = mesh->Point(pi); if (x) for(int i=0;i<3;i++) x[i] = xg(i); } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<2,2> (int elnr, const double * xi, double * x, double * dxdxi) const { Point<2> xl(xi[0], xi[1]); Point<3> xg; Mat<3,2> dx; mesh->GetCurvedElements().CalcSurfaceTransformation (xl, elnr, xg, dx); if (x) for (int i = 0; i < 2; i++) x[i] = xg(i); if (dxdxi) for (int i=0; i<2; i++) { dxdxi[2*i] = dx(i,0); dxdxi[2*i+1] = dx(i,1); } } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<1,2> (int elnr, const double * xi, double * x, double * dxdxi) const { Point<3> xg; Vec<3> dx; mesh->GetCurvedElements().CalcSegmentTransformation (xi[0], elnr, xg, dx); if (x) for (int i = 0; i < 2; i++) x[i] = xg(i); if (dxdxi) for (int i=0; i < 2; i++) dxdxi[i] = dx(i); } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<1,1> (int elnr, const double * xi, double * x, double * dxdxi) const { Point<3> xg; Vec<3> dx; mesh->GetCurvedElements().CalcSegmentTransformation (xi[0], elnr, xg, dx); if (x) x[0] = xg(0); if (dxdxi) dxdxi[0] = dx(0); } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<0,2> (int elnr, const double *xi, double * x, double * dxdxi) const { PointIndex pnum = mesh->pointelements[elnr].pnum; if (x) for (int i = 0; i< 2; i++) x[i] = (*mesh)[pnum](i); } template <> DLL_HEADER void Ngx_Mesh :: ElementTransformation<0,1> (int elnr, const double * xi, double * x, double * dxdxi) const { PointIndex pnum = mesh->pointelements[elnr].pnum; if (x) x[0] = (*mesh)[pnum](0); // if (dxdxi) dxdxi[0] = 0; // Jacobi-matrix is 1 x 0 !!! } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<3,3> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointElementTransformation (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<2,2> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<2> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<2,3> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<3> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<1,3> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<3> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<0,3> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { for (int i = 0; i < npts; i++) ElementTransformation<0,3> (elnr, xi+i*sxi, x+i*sx, dxdxi+i*sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<1,2> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<2> (elnr, npts, xi, sxi, x, sx, dxdxi, sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<1,1> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { for (int i = 0; i < npts; i++) ElementTransformation<1,1> (elnr, xi + i*sxi, x+i*sx, dxdxi+i*sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<0,2> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { for (int i = 0; i < npts; i++) ElementTransformation<0,2> (elnr, xi + i*sxi, x+i*sx, dxdxi+i*sdxdxi); } template <> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<0,1> (int elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) const { for (int i = 0; i < npts; i++) ElementTransformation<0,1> (elnr, xi + i*sxi, x+i*sx, dxdxi+i*sdxdxi); } int Ngx_Mesh :: GetHPElementLevel (int ei, int dir) const { ei++; int level = -1; if (mesh->hpelements) { int hpelnr = -1; if (mesh->GetDimension() == 2) hpelnr = mesh->SurfaceElement(ei).hp_elnr; else hpelnr = mesh->VolumeElement(ei).hp_elnr; if (hpelnr < 0) throw NgException("Ngx_Mesh::GetHPElementLevel: Wrong hp-element number!"); if (dir == 1) level = (*mesh->hpelements)[hpelnr].levelx; else if (dir == 2) level = (*mesh->hpelements)[hpelnr].levely; else if (dir == 3) level = (*mesh->hpelements)[hpelnr].levelz; else throw NgException("Ngx_Mesh::GetHPElementLevel: dir has to be 1, 2 or 3!"); } //else // throw NgException("Ngx_Mesh::GetHPElementLevel only for HPRefinement implemented!"); return level; } int Ngx_Mesh :: GetParentElement (int ei) const { ei++; if (mesh->GetDimension() == 3) { if (ei <= mesh->mlparentelement.Size()) return mesh->mlparentelement.Get(ei)-1; } else { if (ei <= mesh->mlparentsurfaceelement.Size()) return mesh->mlparentsurfaceelement.Get(ei)-1; } return -1; } int Ngx_Mesh :: GetParentSElement (int ei) const { ei++; if (mesh->GetDimension() == 3) { if (ei <= mesh->mlparentsurfaceelement.Size()) return mesh->mlparentsurfaceelement.Get(ei)-1; } else { return -1; } return -1; } int Ngx_Mesh :: GetNIdentifications () const { return mesh->GetIdentifications().GetMaxNr(); } int Ngx_Mesh :: GetIdentificationType(int idnr) const { return mesh->GetIdentifications().GetType(idnr+1); } Ng_BufferMS Ngx_Mesh::GetFaceEdges (int fnr) const { const MeshTopology & topology = mesh->GetTopology(); ArrayMem ia; topology.GetFaceEdges (fnr+1, ia); Ng_BufferMS res(ia.Size()); for (size_t i = 0; i < ia.Size(); i++) res[i] = ia[i]-1; return res; } #ifdef __SSE__ #include template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<1,1> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { cout << "multi-eltrafo simd called, 1,1,simd" << endl; } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<2,2> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<2> (elnr, npts, reinterpret_cast*> (xi), sxi, reinterpret_cast*> (x), sx, reinterpret_cast*> (dxdxi), sdxdxi); /* for (int i = 0; i < npts; i++) { double hxi[4][2]; double hx[4][2]; double hdxdxi[4][4]; for (int j = 0; j < 4; j++) for (int k = 0; k < 2; k++) hxi[j][k] = ((double*)&(xi[k]))[j]; MultiElementTransformation<2,2> (elnr, 4, &hxi[0][0], 2, &hx[0][0], 2, &hdxdxi[0][0], 4); for (int j = 0; j < 4; j++) for (int k = 0; k < 2; k++) ((double*)&(x[k]))[j] = hx[j][k]; for (int j = 0; j < 4; j++) for (int k = 0; k < 4; k++) ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k]; xi += sxi; x += sx; dxdxi += sdxdxi; } */ } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<3,3> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointElementTransformation (elnr, npts, reinterpret_cast*> (xi), sxi, reinterpret_cast*> (x), sx, reinterpret_cast*> (dxdxi), sdxdxi); /* for (int i = 0; i < npts; i++) { double hxi[4][3]; double hx[4][3]; double hdxdxi[4][9]; for (int j = 0; j < 4; j++) for (int k = 0; k < 3; k++) hxi[j][k] = ((double*)&(xi[k]))[j]; MultiElementTransformation<3,3> (elnr, 4, &hxi[0][0], 3, &hx[0][0], 3, &hdxdxi[0][0], 9); for (int j = 0; j < 4; j++) for (int k = 0; k < 3; k++) ((double*)&(x[k]))[j] = hx[j][k]; for (int j = 0; j < 4; j++) for (int k = 0; k < 9; k++) ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k]; xi += sxi; x += sx; dxdxi += sdxdxi; } */ } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<0,2> (int elnr, int npts, const tAVXd *xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { cout << "MultiElementtransformation<0,2> simd not implemented" << endl; } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<0,1> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { cout << "multi-eltrafo simd called, 0,1,simd" << endl; } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<1,3> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<3> (elnr, npts, reinterpret_cast*> (xi), sxi, reinterpret_cast*> (x), sx, reinterpret_cast*> (dxdxi), sdxdxi); /* double hxi[4][1]; double hx[4][3]; double hdxdxi[4][3]; for (int j = 0; j<4;j++) hxi[j][0] = ((double*)&(xi[0]))[j]; MultiElementTransformation<1,3> (elnr, 4, &hxi[0][0], 1, &hx[0][0], 3, &hdxdxi[0][0],3); for(int j=0; j<4; j++) for(int k=0; k<3; k++) ((double*)&(x[k]))[j] = hx[j][k]; for(int j=0; j< 4; j++) for (int k = 0; k<3; k++) ((double*) & (dxdxi[k]))[j] = hdxdxi[j][k]; xi += sxi; x += sx; dxdxi += sdxdxi; */ } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<1,2> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSegmentTransformation<2> (elnr, npts, reinterpret_cast*> (xi), sxi, reinterpret_cast*> (x), sx, reinterpret_cast*> (dxdxi), sdxdxi); /* for (int i = 0; i < npts; i++) { double hxi[4][1]; double hx[4][2]; double hdxdxi[4][2]; for (int j = 0; j < 4; j++) for (int k = 0; k < 1; k++) hxi[j][k] = ((double*)&(xi[k]))[j]; MultiElementTransformation<1,2> (elnr, 4, &hxi[0][0], 1, &hx[0][0], 2, &hdxdxi[0][0], 2); for (int j = 0; j < 4; j++) for (int k = 0; k < 2; k++) ((double*)&(x[k]))[j] = hx[j][k]; for (int j = 0; j < 4; j++) for (int k = 0; k < 2; k++) ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k]; xi += sxi; x += sx; dxdxi += sdxdxi; } */ } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<2,3> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<3> (elnr, npts, reinterpret_cast*> (xi), sxi, reinterpret_cast*> (x), sx, reinterpret_cast*> (dxdxi), sdxdxi); /* for (int i = 0; i < npts; i++) { double hxi[4][2]; double hx[4][3]; double hdxdxi[4][6]; for (int j = 0; j < 4; j++) for (int k = 0; k < 2; k++) hxi[j][k] = ((double*)&(xi[k]))[j]; MultiElementTransformation<2,3> (elnr, 4, &hxi[0][0], 2, &hx[0][0], 3, &hdxdxi[0][0], 6); for (int j = 0; j < 4; j++) for (int k = 0; k < 3; k++) ((double*)&(x[k]))[j] = hx[j][k]; for (int j = 0; j < 4; j++) for (int k = 0; k < 6; k++) ((double*)&(dxdxi[k]))[j] = hdxdxi[j][k]; xi += sxi; x += sx; dxdxi += sdxdxi; } */ } template<> DLL_HEADER void Ngx_Mesh :: MultiElementTransformation<0,3> (int elnr, int npts, const tAVXd * xi, size_t sxi, tAVXd * x, size_t sx, tAVXd * dxdxi, size_t sdxdxi) const { for (int i = 0; i < npts; i++) { double hxi[4][1]; double hx[4][3]; for (int j = 0; j < 4; j++) for (int k = 0; k < 1; k++) hxi[j][k] = ((double*)&(xi[k]))[j]; MultiElementTransformation<0,3> (elnr, 4, &hxi[0][0], 2, &hx[0][0], 3, (double*)nullptr, 0); for (int j = 0; j < 4; j++) for (int k = 0; k < 3; k++) ((double*)&(x[k]))[j] = hx[j][k]; xi += sxi; x += sx; dxdxi += sdxdxi; } } #endif template <> DLL_HEADER int Ngx_Mesh :: FindElementOfPoint <1> (double * hp, double * lami, bool build_searchtree, int * const indices, int numind) const { switch (mesh->GetDimension()) { case 1: { Point<3> p(hp[0], 0,0); for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) { auto & seg = (*mesh)[si]; Point<3> p1 = (*mesh)[seg[0]]; Point<3> p2 = (*mesh)[seg[1]]; double lam = (p(0)-p1(0)) / (p2(0)-p1(0)); if (lam >= -1e-10 && lam <= 1+1e-10) { lami[0] = 1-lam; return si; } } } break; case 2: { Point<3> p(hp[0], hp[1],0); for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) { auto & seg = (*mesh)[si]; Point<3> p1 = (*mesh)[seg[0]]; Point<3> p2 = (*mesh)[seg[1]]; double lam; double r; if (fabs(p2[0]-p1[0]) >= fabs(p2[1]-p1[1])) { lam = (p[0]-p1[0])/(p2[0]-p1[0]); r = p[1] - p1[1] - lam*(p2[1]-p1[1]); } else { lam = (p[1]-p1[1])/(p2[1]-p1[1]); r = p[0] - p1[0] - lam*(p2[0]-p1[0]); } if ( lam >= -1e-10 && lam <= 1+1e-10 && fabs(r) <= 1e-10 ) { lami[0] = 1-lam; return si; } } } break; case 3: default: throw Exception("FindElementOfPoint<1> only implemented for mesh-dimension 1 and 2!"); break; } return -1; } template <> DLL_HEADER int Ngx_Mesh :: FindElementOfPoint <2> (double * p, double * lami, bool build_searchtree, int * const indices, int numind) const { Array dummy(numind); for (int i = 0; i < numind; i++) dummy[i] = indices[i]+1; double lam3[3]; int ind; if (mesh->GetDimension() == 2) { Point<3> p2d(p[0], p[1], 0); ind = mesh->GetElementOfPoint(p2d, lam3, &dummy, build_searchtree); } else { Point3d p3d(p[0], p[1], p[2]); ind = mesh->GetSurfaceElementOfPoint(p3d, lam3, &dummy, build_searchtree); } if (ind > 0) { if(mesh->SurfaceElement(ind).GetType()==QUAD || mesh->SurfaceElement(ind).GetType()==TRIG6) { lami[0] = lam3[0]; lami[1] = lam3[1]; } else { lami[0] = 1-lam3[0]-lam3[1]; lami[1] = lam3[0]; } } return ind-1; } template <> DLL_HEADER int Ngx_Mesh :: FindElementOfPoint <3> (double * p, double * lami, bool build_searchtree, int * const indices, int numind) const { Array dummy(numind); for (int i = 0; i < numind; i++) dummy[i] = indices[i]+1; Point<3> p3d(p[0], p[1], p[2]); int ind = mesh->GetElementOfPoint(p3d, lami, &dummy, build_searchtree); return ind-1; } void Ngx_Mesh :: Curve (int order) { NgLock meshlock (mesh->MajorMutex(), true); mesh->BuildCurvedElements(order); } template <> DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<2> (size_t elnr, bool flag) { mesh->SurfaceElement(elnr+1).SetRefinementFlag(flag); } template <> DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<3> (size_t elnr, bool flag) { mesh->VolumeElement(elnr+1).SetRefinementFlag(flag); } void Ngx_Mesh :: Refine (NG_REFINEMENT_TYPE reftype, void (*task_manager)(function), Tracer tracer) { NgLock meshlock (mesh->MajorMutex(), 1); BisectionOptions biopt; biopt.usemarkedelements = 1; biopt.refine_p = 0; biopt.refine_hp = 0; if (reftype == NG_REFINE_P) biopt.refine_p = 1; if (reftype == NG_REFINE_HP) biopt.refine_hp = 1; biopt.task_manager = task_manager; biopt.tracer = tracer; const Refinement & ref = mesh->GetGeometry()->GetRefinement(); ref.Bisect (*mesh, biopt); (*tracer)("call updatetop", false); mesh -> UpdateTopology(task_manager, tracer); (*tracer)("call updatetop", true); mesh -> GetCurvedElements().SetIsHighOrder (false); } // just copied with redesign size_t Ngx_Mesh::GetNP() const { return mesh->GetNP(); } int Ngx_Mesh::GetSurfaceElementSurfaceNumber (size_t ei) const { if (mesh->GetDimension() == 3) return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).SurfNr(); else return mesh->LineSegment(ei).si; } int Ngx_Mesh::GetSurfaceElementFDNumber (size_t ei) const { if (mesh->GetDimension() == 3) return mesh->SurfaceElement(ei).GetIndex(); else return -1; } void Ngx_Mesh::HPRefinement (int levels, double parameter, bool setorders, bool ref_level) { NgLock meshlock (mesh->MajorMutex(), true); Refinement & ref = const_cast (mesh->GetGeometry()->GetRefinement()); ::netgen::HPRefinement (*mesh, &ref, levels, parameter, setorders, ref_level); } int Ngx_Mesh::GetElementOrder (int enr) const { if (mesh->GetDimension() == 3) return mesh->VolumeElement(enr).GetOrder(); else return mesh->SurfaceElement(enr).GetOrder(); } void Ngx_Mesh::GetElementOrders (int enr, int * ox, int * oy, int * oz) const { if (mesh->GetDimension() == 3) mesh->VolumeElement(enr).GetOrder(*ox, *oy, *oz); else mesh->SurfaceElement(enr).GetOrder(*ox, *oy, *oz); } void Ngx_Mesh::SetElementOrder (int enr, int order) { if (mesh->GetDimension() == 3) return mesh->VolumeElement(enr).SetOrder(order); else return mesh->SurfaceElement(enr).SetOrder(order); } void Ngx_Mesh::SetElementOrders (int enr, int ox, int oy, int oz) { if (mesh->GetDimension() == 3) mesh->VolumeElement(enr).SetOrder(ox, oy, oz); else mesh->SurfaceElement(enr).SetOrder(ox, oy); } int Ngx_Mesh::GetSurfaceElementOrder (int enr) const { return mesh->SurfaceElement(enr).GetOrder(); } int Ngx_Mesh::GetClusterRepVertex (int pi) const { return mesh->GetClusters().GetVertexRepresentant(pi); } int Ngx_Mesh::GetClusterRepEdge (int pi) const { return mesh->GetClusters().GetEdgeRepresentant(pi); } int Ngx_Mesh::GetClusterRepFace (int pi) const { return mesh->GetClusters().GetFaceRepresentant(pi); } int Ngx_Mesh::GetClusterRepElement (int pi) const { return mesh->GetClusters().GetElementRepresentant(pi); } //HERBERT: falsche Anzahl von Argumenten //void Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy, int * oz) void Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy) const { int d; mesh->SurfaceElement(enr).GetOrder(*ox, *oy, d); } void Ngx_Mesh::SetSurfaceElementOrder (int enr, int order) { return mesh->SurfaceElement(enr).SetOrder(order); } void Ngx_Mesh::SetSurfaceElementOrders (int enr, int ox, int oy) { mesh->SurfaceElement(enr).SetOrder(ox, oy); } std::tuple Ngx_Mesh :: GetDistantProcs (int nodetype, int locnum) const { #ifdef PARALLEL switch (nodetype) { case 0: { FlatArray dn = mesh->GetParallelTopology().GetDistantPNums(locnum); return std::tuple(dn.Size(), &dn[0]); } case 1: { FlatArray dn = mesh->GetParallelTopology().GetDistantEdgeNums(locnum); return std::tuple(dn.Size(), &dn[0]); } case 2: { FlatArray dn = mesh->GetParallelTopology().GetDistantFaceNums(locnum); return std::tuple(dn.Size(), &dn[0]); } default: return std::tuple(0,nullptr); } #else return std::tuple(0,nullptr); #endif } } int link_it_nginterface_v2; netgen-6.2.1905/libsrc/interface/writetet.cpp0000644000175000017500000006556613504650527017614 0ustar kurtkurt #include #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteTETFormat (const Mesh & mesh, const string & filename)//, const string& problemType ) { string problemType = ""; if(!mesh.PureTetMesh()) throw NgException("Can only export pure tet mesh in this format"); cout << "starting .tet export to file " << filename << endl; Array point_ids,edge_ids,face_ids; Array elnum(mesh.GetNE()); elnum = -1; Array userdata_int; Array userdata_double; Array ports; Array uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D; int pos_int = 0; int pos_double = 0; bool haveuserdata = (mesh.GetUserData("TETmesh:double",userdata_double) && mesh.GetUserData("TETmesh:int",userdata_int) && mesh.GetUserData("TETmesh:ports",ports) && mesh.GetUserData("TETmesh:point_id",point_ids,PointIndex::BASE) && mesh.GetUserData("TETmesh:uid_to_group_3D",uid_to_group_3D) && mesh.GetUserData("TETmesh:uid_to_group_2D",uid_to_group_2D) && mesh.GetUserData("TETmesh:uid_to_group_1D",uid_to_group_1D) && mesh.GetUserData("TETmesh:uid_to_group_0D",uid_to_group_0D)); int version,subversion; if(haveuserdata) { version = int(userdata_double[0]); subversion = int(10*(userdata_double[0] - version)); pos_double++; } else { version = 2; subversion = 0; } if(version >= 2) { // test if ids are disjunct, if not version 2.0 not possible int maxbc(-1),mindomain(-1); for(ElementIndex i=0; i maxbc) maxbc = mesh.GetFaceDescriptor(i).BCProperty(); if(maxbc >= mindomain) { cout << "WARNING: writing version " << version << "." << subversion << " tetfile not possible, "; version = 1; subversion = 1; cout << "using version " << version << "." << subversion << endl; } } int startsize = point_ids.Size(); point_ids.SetSize(mesh.GetNP()+1); for(int i=startsize; i edgenumbers(6*mesh.GetNE()+3*mesh.GetNSE());; INDEX_3_CLOSED_HASHTABLE facenumbers(4*mesh.GetNE()+mesh.GetNSE()); Array edge2node; Array face2edge; Array element2face; int numelems(0),numfaces(0),numedges(0),numnodes(0); for(SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { const Segment & seg = mesh[si]; INDEX_2 i2(seg[0],seg[1]); i2.Sort(); if(edgenumbers.Used(i2)) continue; numedges++; edgenumbers.Set(i2,numedges); edge2node.Append(i2); edge_ids.Append(seg.edgenr); if(point_ids[seg[0]] == -1) point_ids[seg[0]] = (version >= 2) ? seg.edgenr : 0; if(point_ids[seg[1]] == -1) point_ids[seg[1]] = (version >= 2) ? seg.edgenr : 0; } for(SurfaceElementIndex si = 0; si < mesh.GetNSE(); si++) { if(mesh[si].IsDeleted()) continue; const Element2d & elem = mesh[si]; numfaces++; INDEX_3 i3(elem[0], elem[1], elem[2]); int min = i3[0]; int minpos = 0; for(int j=1; j<3; j++) if(i3[j] < min) { min = i3[j]; minpos = j; } if(minpos == 1) { int aux = i3[0]; i3[0] = i3[1]; i3[1] = i3[2]; i3[2] = aux; } else if(minpos == 2) { int aux = i3[0]; i3[0] = i3[2]; i3[2] = i3[1]; i3[1] = aux; } facenumbers.Set(i3,numfaces); int bc = mesh.GetFaceDescriptor(elem.GetIndex()).BCProperty(); face_ids.Append(bc); for(int j=0; j<3; j++) if(point_ids[elem[j]] == -1) point_ids[elem[j]] = (version >= 2) ? bc : 0; INDEX_2 i2a,i2b; INDEX_3 f_to_n; for(int j=0; j<3; j++) { i2a = INDEX_2(i3[j],i3[(j+1)%3]); i2b[0] = i2a[1]; i2b[1] = i2a[0]; if(edgenumbers.Used(i2a)) f_to_n[j] = edgenumbers.Get(i2a); else if(edgenumbers.Used(i2b)) f_to_n[j] = -edgenumbers.Get(i2b); else { numedges++; edgenumbers.Set(i2a,numedges); edge2node.Append(i2a); f_to_n[j] = numedges; if(version >= 2) edge_ids.Append(bc); else edge_ids.Append(0); } } face2edge.Append(f_to_n); } for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; if(el.IsDeleted()) continue; numelems++; elnum[ei] = numelems; static int tetfaces[4][3] = { { 0, 2, 1 }, { 0, 1, 3 }, { 1, 2, 3 }, { 2, 0, 3 } }; for(int j=0; j<4; j++) if(point_ids[el[j]] == -1) point_ids[el[j]] = (version >= 2) ? el.GetIndex() : 0; INDEX_4 e_to_f; for(int i = 0; i < 4; i++) { INDEX_3 i3a(el[tetfaces[i][0]],el[tetfaces[i][1]],el[tetfaces[i][2]]); int min = i3a[0]; int minpos = 0; for(int j=1; j<3; j++) if(i3a[j] < min) { min = i3a[j]; minpos = j; } if(minpos == 1) { int aux = i3a[0]; i3a[0] = i3a[1]; i3a[1] = i3a[2]; i3a[2] = aux; } else if(minpos == 2) { int aux = i3a[0]; i3a[0] = i3a[2]; i3a[2] = i3a[1]; i3a[1] = aux; } INDEX_3 i3b(i3a[0],i3a[2],i3a[1]); if(facenumbers.Used(i3a)) e_to_f[i] = facenumbers.Get(i3a); else if(facenumbers.Used(i3b)) e_to_f[i] = -facenumbers.Get(i3b); else { numfaces++; facenumbers.Set(i3a,numfaces); e_to_f[i] = numfaces; if(version >= 2) face_ids.Append(el.GetIndex()); else face_ids.Append(0); INDEX_2 i2a,i2b; INDEX_3 f_to_n; for(int j=0; j<3; j++) { i2a = INDEX_2(i3a[j],i3a[(j+1)%3]); i2b[0] = i2a[1]; i2b[1] = i2a[0]; if(edgenumbers.Used(i2a)) f_to_n[j] = edgenumbers.Get(i2a); else if(edgenumbers.Used(i2b)) f_to_n[j] = -edgenumbers.Get(i2b); else { numedges++; edgenumbers.Set(i2a,numedges); edge2node.Append(i2a); f_to_n[j] = numedges; if(version >= 2) edge_ids.Append(el.GetIndex()); else edge_ids.Append(0); } } face2edge.Append(f_to_n); } } element2face.Append(e_to_f); } ofstream outfile(filename.c_str()); outfile.precision(16); int unitcode; double tolerance; double dS1,dS2, alphaDeg; double x3D,y3D,z3D; int modelverts(0), modeledges(0), modelfaces(0), modelcells(0); int numObj0D,numObj1D,numObj2D,numObj3D; int numports = ports.Size(); Array nodenum(point_ids.Size()+1); nodenum = -1; numnodes = 0; for(int i=0; i* > idmaps; for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) { if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) { idmaps.Append(new Array); mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true); } } Array id_num,id_type; Array< Array *> id_groups; // sst 2008-03-12: Write problem class... { std::string block; block = "// CST Tetrahedral "; block += !problemType.empty() ? problemType : "High Frequency"; block += " Mesh, Version no.:\n"; size_t size = block.size()-3; block += "// "; block.append( size, '^' ); block += "\n"; outfile << block << version << "." << subversion << "\n\n"; } outfile << "// User Units Code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << unitcode << "\n\n" \ << "// Geometric coord \"zero\" tolerance threshold:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << tolerance << "\n\n" \ << "// Periodic UnitCell dS1 , dS2 , alphaDeg:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << dS1 << " " << dS2 << " " << alphaDeg <<"\n\n" \ << "// Periodic UnitCell origin in global coords (x3D,y3D,z3D):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << x3D << " " << y3D << " " << z3D << "\n" << endl; if(version == 2) { outfile << "// Model entity count: Vertices, Edges, Faces, Cells:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << modelverts << " " << modeledges << " " << modelfaces << " " << modelcells << endl << endl; } outfile << "// Topological mesh-entity counts (#elements,#faces,#edges,#nodes):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; outfile << numelems << " " << numfaces << " " << numedges << " " << numnodes << endl << endl; outfile << "// NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<< uidpid <<":\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; id_num.SetSize(mesh.GetNP()+1); id_type.SetSize(mesh.GetNP()+1); id_num = 0; id_type = 0; int n2,n4,n8; n2 = n4 = n8 = 0; for(int i=PointIndex::BASE; i group; group.Append(i); for(int j=0; j 1) { id_groups.Append(new Array(group)); if(group.Size() == 2) { id_type[i] = 1; id_type[group[1]] = 2; n2++; } else if(group.Size() == 4) { id_type[i] = 3; for(int j=1; jSize() != 2) continue; for(int j=0; jSize(); j++) outfile << nodenum[(*id_groups[i])[j]] << " "; for(int j=1; jSize(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// Number of Corner Periodic Master Nodes:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << n4 << "\n" \ << "\n" \ << "// MasterNodeID, 3-SlaveNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; iSize() != 4) continue; for(int j=0; jSize(); j++) outfile << nodenum[(*id_groups[i])[j]] << " "; for(int j=1; jSize(); j++) { outfile << id_num[(*id_groups[i])[j]] << " "; } outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// Number of Cubic Periodic Master Nodes:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << n8 << "\n" \ << "\n" \ << "// MasterNodeID, 7-SlaveNodeID's, TranslCodes:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; iSize() != 8) continue; for(int j=0; jSize(); j++) outfile << nodenum[(*id_groups[i])[j]] << " "; for(int j=1; jSize(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<* > vertex_to_edge(mesh.GetNP()+1); for(int i=0; i<=mesh.GetNP(); i++) vertex_to_edge[i] = new Array; Array< Array* > idmaps_edge(idmaps.Size()); for(int i=0; i(numedges); (*idmaps_edge[i]) = 0; } Array possible; for(int i=0; i 0) { cerr << "ERROR: too many possible edge identifications" << endl; (*testout) << "ERROR: too many possible edge identifications" << endl << "*vertex_to_edge["<Append(i+1); vertex_to_edge[v[1]]->Append(i+1); } for(int i=0; i group; group.Append(i); for(int j=0; j 1) { id_num[i] = 1; id_groups.Append(new Array(group)); if(group.Size() == 2) { id_type[i] = 1; id_type[group[1]] = 2; n2++; } else if(group.Size() == 4) { id_type[i] = 3; for(int j=1; j group; group.Append(i); for(int j=0; j 1) { id_num[i] = 1; id_groups.Append(new Array(group)); if(group.Size() == 2) { id_type[i] = 1; id_type[group[1]] = 2; n2++; } else if(group.Size() == 4) { id_type[i] = 3; for(int j=1; jSize() != 2) continue; for(int j=0; jSize(); j++) outfile << (*id_groups[i])[j] << " "; for(int j=1; jSize(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// Number of Corner Periodic Master Edges:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ << n4 << "\n" \ << "\n"\ << "// MasterEdgeID, 3 SlaveEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; iSize() != 4) continue; for(int j=0; jSize(); j++) outfile << (*id_groups[i])[j] << " "; for(int j=1; jSize(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; id_groups[i] = NULL; } outfile << endl; outfile << "// FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PSlave), "<* > edge_to_face(numedges+1); for(int i=0; i; for(int i=0; iSetSize(numfaces); (*idmaps[i]) = 0; } for(int i=0; i 0) cerr << "ERROR: too many possible face identifications" << endl; } } edge_to_face[abs(face2edge[i][0])]->Append(i+1); edge_to_face[abs(face2edge[i][1])]->Append(i+1); edge_to_face[abs(face2edge[i][2])]->Append(i+1); } for(int i=0; i group; group.Append(i); for(int j=0; j 1) { id_num[i] = -1; id_groups.Append(new Array(group)); if(group.Size() == 2) n2++; else cerr << "ERROR: face identification group size = " << group.Size() << endl; } } for(int i=0; iSize() != 2) continue; for(int j=0; jSize(); j++) outfile << (*id_groups[i])[j] << " "; for(int j=1; jSize(); j++) outfile << id_num[(*id_groups[i])[j]] << " "; outfile << "\n"; delete id_groups[i]; } outfile << endl; outfile << "// ElemID, FaceID0, FaceID1, FaceID2, FaceID3, "<= 0) { outfile << elnum[i] << " "; for(int j=0; j<4; j++) outfile << element2face[elnum[i]-1][j] << " "; outfile << mesh[i].GetIndex() << "\n"; } } outfile << endl; outfile << "// ElemID, NodeID0, NodeID1, NodeID2, NodeID3:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(ElementIndex i=0; i= 0) outfile << elnum[i] << " " << nodenum[mesh[i][1]] << " " << nodenum[mesh[i][0]] << " " << nodenum[mesh[i][2]] << " " << nodenum[mesh[i][3]] << "\n"; } outfile << endl; outfile << "// Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D):\n" << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" << " "<< numObj3D << " " << numObj2D << " " << numObj1D << " " << numObj0D << "\n" \ << "\n" \ << "// Number of Ports (Ports are a subset of Object2D list):\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ << numports << "\n" \ << endl; Array< Array * > groups; int maxg = -1; for(int i = 0; i maxg) maxg = uid_to_group_3D[i]; for(int i = 0; i maxg) maxg = uid_to_group_2D[i]; for(int i = 0; i maxg) maxg = uid_to_group_1D[i]; for(int i = 0; i maxg) maxg = uid_to_group_0D[i]; groups.SetSize(maxg+1); for(int i=0; i; for(ElementIndex i=0; i= 0) groups[uid_to_group_3D[mesh[i].GetIndex()]]->Append(i+1); outfile << "// Object3D GroupID, #Elems ElemID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; iSize() << "\n"; for(int j=0; jSize(); j++) outfile << (*groups[i])[j] << "\n"; } for(int i=0; iSetSize(0); for(int i=0; i= 0) groups[uid_to_group_2D[face_ids[i]]]->Append(i+1); outfile << "// Object2D GroupID, #Faces FaceID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; iSize() << "\n"; for(int j=0; jSize(); j++) { outfile << (*groups[i])[j]; if(ports.Contains(face_ids[(*groups[i])[j]-1])) outfile << " P"; outfile << "\n"; } } outfile << endl; for(int i=0; iSetSize(0); for(int i=0; i= 0) groups[uid_to_group_1D[edge_ids[i]]]->Append(i+1); outfile << "// Object1D GroupID, #Edges EdgeID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; iSize() << "\n"; for(int j=0; jSize(); j++) outfile << (*groups[i])[j] << "\n"; } outfile << endl; for(int i=0; iSetSize(0); for(PointIndex i = mesh.Points().Begin(); i < mesh.Points().End(); i++) { if(i-PointIndex::BASE < point_ids.Size()) { if(uid_to_group_0D[point_ids[i]] >= 0) groups[uid_to_group_0D[point_ids[i]]]->Append(i+1-PointIndex::BASE); } else groups[uid_to_group_0D[0]]->Append(i+1-PointIndex::BASE); } outfile << "// Object0D GroupID, #Nodes NodeID List:\n" \ << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; for(int i=0; iSize() << "\n"; for(int j=0; jSize(); j++) outfile << (*groups[i])[j] << "\n"; } outfile << endl; for(int i=0; i #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteAbaqusFormat (const Mesh & mesh, const string & filename) { cout << "\nWrite Abaqus Volume Mesh" << endl; ofstream outfile (filename.c_str()); outfile << "*Heading" << endl; outfile << " " << filename << endl; outfile.precision(8); outfile << "*Node" << endl; int np = mesh.GetNP(); int ne = mesh.GetNE(); int i, j, k; for (i = 1; i <= np; i++) { outfile << i << ", "; outfile << mesh.Point(i)(0) << ", "; outfile << mesh.Point(i)(1) << ", "; outfile << mesh.Point(i)(2) << "\n"; } int elemcnt = 0; //element counter int finished = 0; int indcnt = 1; //index counter while (!finished) { int actcnt = 0; const Element & el1 = mesh.VolumeElement(1); int non = el1.GetNP(); if (non == 4) { outfile << "*Element, type=C3D4, ELSET=PART" << indcnt << endl; } else if (non == 10) { outfile << "*Element, type=C3D10, ELSET=PART" << indcnt << endl; } else { cout << "unsupported Element type!!!" << endl; } for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); if (el.GetIndex() == indcnt) { actcnt++; if (el.GetNP() != non) { cout << "different element-types in a subdomain are not possible!!!" << endl; continue; } elemcnt++; outfile << elemcnt << ", "; if (non == 4) { outfile << el.PNum(1) << ", "; outfile << el.PNum(2) << ", "; outfile << el.PNum(4) << ", "; outfile << el.PNum(3) << "\n"; } else if (non == 10) { outfile << el.PNum(1) << ", "; outfile << el.PNum(2) << ", "; outfile << el.PNum(4) << ", "; outfile << el.PNum(3) << ", "; outfile << el.PNum(5) << ", "; outfile << el.PNum(9) << ", "; outfile << el.PNum(7) << ", " << "\n"; outfile << el.PNum(6) << ", "; outfile << el.PNum(8) << ", "; outfile << el.PNum(10) << "\n"; } else { cout << "unsupported Element type!!!" << endl; for (j = 1; j <= el.GetNP(); j++) { outfile << el.PNum(j); if (j != el.GetNP()) outfile << ", "; } outfile << "\n"; } } } indcnt++; if (elemcnt == ne) {finished = 1; cout << "all elements found by Index!" << endl;} if (actcnt == 0) {finished = 1;} } if (mesh.GetIdentifications().GetMaxNr()) { // periodic identification, implementation for // Helmut J. Boehm, TU Vienna char cfilename[255]; strcpy (cfilename, filename.c_str()); char mpcfilename[255]; strcpy (mpcfilename, cfilename); size_t len = strlen (cfilename); if (len >= 4 && (strcmp (mpcfilename+len-4, ".inp") == 0)) strcpy (mpcfilename+len-4, ".mpc"); else strcat (mpcfilename, ".mpc"); ofstream mpc (mpcfilename); int masternode(0); Array pairs; BitArray master(np), help(np); master.Set(); for (i = 1; i <= 3; i++) { mesh.GetIdentifications().GetPairs (i, pairs); help.Clear(); for (j = 1; j <= pairs.Size(); j++) { help.Set (pairs.Get(j).I1()); } master.And (help); } for (i = 1; i <= np; i++) if (master.Test(i)) masternode = i; cout << "masternode = " << masternode << " = " << mesh.Point(masternode) << endl; Array slaves(3); for (i = 1; i <= 3; i++) { mesh.GetIdentifications().GetPairs (i, pairs); for (j = 1; j <= pairs.Size(); j++) { if (pairs.Get(j).I1() == masternode) slaves.Elem(i) = pairs.Get(j).I2(); } cout << "slave(" << i << ") = " << slaves.Get(i) << " = " << mesh.Point(slaves.Get(i)) << endl; } outfile << "**\n" << "*NSET,NSET=CTENODS\n" << slaves.Get(1) << ", " << slaves.Get(2) << ", " << slaves.Get(3) << endl; outfile << "**\n" << "**POINT_fixed\n" << "**\n" << "*BOUNDARY, OP=NEW\n"; for (j = 1; j <= 3; j++) outfile << masternode << ", " << j << ",, 0.\n"; outfile << "**\n" << "*BOUNDARY, OP=NEW\n"; for (j = 1; j <= 3; j++) { Vec3d v(mesh.Point(masternode), mesh.Point(slaves.Get(j))); double vlen = v.Length(); int dir = 0; if (fabs (v.X()) > 0.9 * vlen) dir = 2; if (fabs (v.Y()) > 0.9 * vlen) dir = 3; if (fabs (v.Z()) > 0.9 * vlen) dir = 1; if (!dir) cout << "ERROR: Problem with rigid body constraints" << endl; outfile << slaves.Get(j) << ", " << dir << ",, 0.\n"; } outfile << "**\n" << "*EQUATION, INPUT=" << mpcfilename << endl; BitArray eliminated(np); eliminated.Clear(); for (i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) { mesh.GetIdentifications().GetPairs (i, pairs); if (!pairs.Size()) continue; for (j = 1; j <= pairs.Size(); j++) if (pairs.Get(j).I1() != masternode && !eliminated.Test(pairs.Get(j).I2())) { eliminated.Set (pairs.Get(j).I2()); for (k = 1; k <= 3; k++) { mpc << "4" << "\n"; mpc << pairs.Get(j).I2() << "," << k << ", -1.0, "; mpc << pairs.Get(j).I1() << "," << k << ", 1.0, "; mpc << slaves.Get(i) << "," << k << ", 1.0, "; mpc << masternode << "," << k << ", -1.0 \n"; } } } } cout << "done" << endl; } } netgen-6.2.1905/libsrc/interface/writetecplot.cpp0000644000175000017500000000507513504650527020457 0ustar kurtkurt// // // TECPLOT file by Jawor Georgiew // #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteTecPlotFormat (const Mesh & mesh, const CSGeometry & geom, const string & filename) { INDEX i; int j, k, e, z; Vec<3> n; INDEX np = mesh.GetNP(); INDEX ne = mesh.GetNE(); INDEX nse = mesh.GetNSE(); Array sn(np); ofstream outfile(filename.c_str()); outfile << "TITLE=\" " << filename << "\"" << endl; // fill hashtable INDEX_3_HASHTABLE face2volelement(ne); for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); INDEX_3 i3; int l; for (j = 1; j <= 4; j++) // loop over faces of tet { l = 0; for (k = 1; k <= 4; k++) if (k != j) { l++; i3.I(l) = el.PNum(k); } i3.Sort(); face2volelement.Set (i3, i); } } for (j = 1; j <= geom.GetNSurf(); j++) /* Flaeche Nummer j */ { for (i = 1; i <= np; i++) sn.Elem(i) = 0; e = 0; for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (j == mesh.GetFaceDescriptor (el.GetIndex ()).SurfNr()) { for (k = 1; k <= 3; k++) sn.Elem(el.PNum(k)) = 1; e++; /* e= Anzahl der neuen Elemente */ } } z = 0; for (i = 1; i <= np; i++) if (sn.Elem(i) == 1) sn.Elem(i) = ++z; outfile << "ZONE T=\" Surface " << j << " \", N=" << z << ", E=" << e << ", ET=TRIANGLE, F=FEPOINT" << endl; for (i = 1; i <= np; i++) if (sn.Elem(i) != 0) { n = geom.GetSurface(j) -> GetNormalVector ( mesh.Point(i) ); outfile << mesh.Point(i)(0) << " " /* Knoten Koordinaten */ << mesh.Point(i)(1) << " " << mesh.Point(i)(2) << " " << n(0) << " " << n(1) << " " << n(2) << " " << i << endl; } for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (j == mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr()) /* FlaechenKnoten (3) */ outfile << sn.Get(el.PNum(1)) << " " << sn.Get(el.PNum(2)) << " " << sn.Get(el.PNum(3)) << endl; /// Hier soll noch die Ausgabe der Nummer des angrenzenden /// Vol.elements erfolgen ! for (k = 1; k <= nse; k++) { const Element2d & sel = mesh.SurfaceElement(k); INDEX_3 i3; for (j = 1; j <= 3; j++) i3.I(j) = sel.PNum(j); i3.Sort(); //int elind = face2volelement.Get(i3); } } } } } netgen-6.2.1905/libsrc/interface/writepermas.cpp0000644000175000017500000001544413504650527020275 0ustar kurtkurt// // Write Permas file // for Intes GmbH, Stuttgart // #include #include #include #include #include #include using namespace std; #include "writeuser.hpp" namespace netgen { // Forward declarations (don't know, where to define them, sorry) int addComponent(string &strComp, string &strSitu, ofstream &out); // This should be the new function to export a PERMAS file void WritePermasFormat (const Mesh &mesh, const string &filename, string &strComp, string &strSitu) { ofstream outfile (filename.c_str()); addComponent(strComp, strSitu, outfile); WritePermasFormat ( mesh, filename); } void WritePermasFormat (const Mesh &mesh, const string &filename) { string strComp, strSitu; ofstream outfile (filename.c_str()); outfile.precision(8); strSitu = strComp = ""; if (addComponent(strComp, strSitu, outfile) == 1) { printf("Error while exporting PERMAS dat!\n"); return; } int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int i, j, k; if (ne == 0) { // pure surface mesh cout << "\nWrite Permas Surface Mesh" << endl; int elnr = 0; for (j = 1; j <= 2; j++) { int nelp(0); switch (j) { case 1: nelp = 3; outfile << "$ELEMENT TYPE = TRIA3 ESET = ALLQUAD" << endl; break; case 2: nelp = 4; outfile << "$ELEMENT TYPE = QUAD4 ESET = ALLQUAD" << endl; break; } for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (el.GetNP() != nelp) continue; elnr++; outfile << elnr << " "; for (k = 1; k <= nelp; k++) outfile << " " << el.PNum(k); outfile << endl; } } } else { cout << "\nWrite Permas Volume Mesh" << endl; int secondorder = (mesh.VolumeElement(1).GetNP() == 10); if (!secondorder) { outfile << "$ELEMENT TYPE = TET4 ESET = ALLTET" << endl; for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); outfile << i << " " << el.PNum(1) << " " << el.PNum(2) << " " << el.PNum(3) << " " << el.PNum(4) << endl; } } else { outfile << "$ELEMENT TYPE = TET10 ESET = ALLTET" << endl; for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); outfile << i << " " << el.PNum(1) << " " << el.PNum(5) << " " << el.PNum(2) << " " << el.PNum(8) << " " << el.PNum(3) << " " << el.PNum(6) << endl << "& " << " " << el.PNum(7) << " " << el.PNum(9) << " " << el.PNum(10) << " " << el.PNum(4) << endl; } } outfile << endl << endl; outfile << "$SURFACE GEO SURFID = 1 SFSET = ALLSUR" << endl; for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (el.GetNP() == 3) outfile << "STRIA3" << " " << el.PNum(1) << " " << el.PNum(2) << " " << el.PNum(3) << endl; } for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (el.GetNP() == 4) outfile << "SQUAD4" << " " << el.PNum(1) << " " << el.PNum(2) << " " << el.PNum(3) << " " << el.PNum(4) << endl; } for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (el.GetNP() == 6) outfile << "STRIA6" << " " << el.PNum(1) << " " << el.PNum(4) << " " << el.PNum(2) << " " << el.PNum(5) << " " << el.PNum(3) << " " << el.PNum(6) << endl; } } outfile << endl << endl; outfile << "$COOR NSET = ALLNODES" << endl; outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); for (i = 1; i <= np; i++) { outfile << i << " "; outfile << mesh.Point(i)(0) << " "; outfile << mesh.Point(i)(1) << " "; outfile << mesh.Point(i)(2) << "\n"; } } ////////////////////////////////////////////////////////////////////////////////// // \brief Writes PERMAS configuration header into export file // Returns >0 in case of errors // \par string &strComp : Reference to component description // \par string &strComp : Reference to situation description ////////////////////////////////////////////////////////////////////////////////// int addComponent(string &strComp, string &strSitu, ofstream &out) { if (strComp.size() > 12 || strSitu > 12) return 1; if (0 == strComp.size()) strComp = "KOMPO1"; if (0 == strSitu.size()) strSitu = "SIT1"; // Writing description header of configuration out << "$ENTER COMPONENT NAME = " << strComp << " DOFTYPE = DISP MATH" << endl << endl; out << " $SITUATION NAME = " << strSitu << endl; out << " $END SITUATION" << endl << endl; out << " $STRUCTURE" << endl; return 0; } } netgen-6.2.1905/libsrc/interface/readuser.cpp0000644000175000017500000004021013504650527017532 0ustar kurtkurt// // Read user dependent output file // #include #include #include #include #include #include "writeuser.hpp" namespace netgen { void ReadFile (Mesh & mesh, const string & hfilename) { PrintMessage(3, "Read User File"); const char * filename = hfilename.c_str(); char reco[100]; int np, nbe; // ".surf" - mesh if ( (strlen (filename) > 5) && strcmp (&filename[strlen (filename)-5], ".surf") == 0 ) { cout << "Surface file" << endl; ifstream in (filename); in >> reco; in >> np; for (int i = 1; i <= np; i++) { Point3d p; in >> p.X() >> p.Y() >> p.Z(); p.Z() *= 10; mesh.AddPoint (p); } mesh.ClearFaceDescriptors(); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); in >> nbe; // int invert = globflags.GetDefineFlag ("invertsurfacemesh"); for (int i = 1; i <= nbe; i++) { Element2d el; el.SetIndex(1); for (int j = 1; j <= 3; j++) { in >> el.PNum(j); // el.PNum(j)++; if (el.PNum(j) < PointIndex(1) || el.PNum(j) > PointIndex(np)) { cerr << "Point Number " << el.PNum(j) << " out of range 1..." << np << endl; return; } } /* if (invert) swap (el.PNum(2), el.PNum(3)); */ mesh.AddSurfaceElement (el); } cout << "points: " << np << " faces: " << nbe << endl; } if ( (strlen (filename) > 4) && strcmp (&filename[strlen (filename)-4], ".unv") == 0 ) { char reco[100]; // int invert; ifstream in(filename); mesh.ClearFaceDescriptors(); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); mesh.GetFaceDescriptor(1).SetBCProperty (1); // map from unv element nr to our element number + an index if it is vol (0), bnd(1), ... std::map> element_map; Array tmp_segments; while (in.good()) { in >> reco; if (strcmp(reco, "-1") == 0) continue; else if (strcmp (reco, "2411") == 0) { cout << "nodes found" << endl; while (1) { int pi, hi; Point<3> p; in >> pi; if (pi == -1) break; in >> hi >> hi >> hi; in >> p(0) >> p(1) >> p(2); mesh.AddPoint (p); } cout << "read " << mesh.GetNP() << " points" << endl; } else if (strcmp (reco, "2412") == 0) { cout << "elements found" << endl; while (1) { int label, fe_id, phys_prop, mat_prop, color, nnodes; int nodes[100]; int hi; in >> label; if (label == -1) break; in >> fe_id >> phys_prop >> mat_prop >> color >> nnodes; if (fe_id >= 11 && fe_id <= 32) in >> hi >> hi >> hi; for (int j = 0; j < nnodes; j++) in >> nodes[j]; switch (fe_id) { case 22: // (Tapered beam) SEGM { Segment el; el[0] = nodes[0]; el[1] = nodes[2]; el[2] = nodes[1]; auto nr = tmp_segments.Size(); tmp_segments.Append(el); element_map[label] = std::make_tuple(nr+1, 2); break; } case 41: // TRIG { Element2d el (TRIG); el.SetIndex (1); for (int j = 0; j < nnodes; j++) el[j] = nodes[j]; auto nr = mesh.AddSurfaceElement (el); element_map[label] = std::make_tuple(nr+1, 1); break; } case 42: // TRIG6 { Element2d el(TRIG6); el.SetIndex(1); int jj = 0; for(auto j : {0,2,4,3,5,1}) el[jj++] = nodes[j]; auto nr = mesh.AddSurfaceElement(el); element_map[label] = std::make_tuple(nr+1, 1); break; } case 111: // TET { Element el (TET); el.SetIndex (1); for (int j = 0; j < nnodes; j++) el[j] = nodes[j]; auto nr = mesh.AddVolumeElement (el); element_map[label] = std::make_tuple(nr+1, 0); break; } case 118: // TET10 { Element el(TET10); el.SetIndex(1); int jj = 0; for(auto j : {0,2,4,9,1,5,6,3,7,8}) el[jj++] = nodes[j]; auto nr = mesh.AddVolumeElement(el); element_map[label] = std::make_tuple(nr+1, 0); break; } default: cout << "Do not know fe_id = " << fe_id << ", skipping it." << endl; break; } } cout << mesh.GetNE() << " elements found" << endl; cout << mesh.GetNSE() << " surface elements found" << endl; } else if(strcmp (reco, "2467") == 0) { int matnr = 1; cout << "Groups found" << endl; while(in.good()) { int len; string name; in >> len; if(len == -1) break; for(int i=0; i < 7; i++) in >> len; in >> name; cout << len << " element are in group " << name << endl; int hi, index; int fdnr, ednr; in >> hi >> index >> hi >> hi; int codim = get<1>(element_map[index]); // use first element to determine if boundary or volume switch (codim) { case 0: { mesh.SetMaterial(++matnr, name); mesh.VolumeElement(get<0>(element_map[index])).SetIndex(matnr); break; } case 1: { int bcpr = mesh.GetNFD()+1; fdnr = mesh.AddFaceDescriptor(FaceDescriptor(bcpr, 0,0,0)); mesh.GetFaceDescriptor(fdnr).SetBCProperty(bcpr+1); mesh.SetBCName(bcpr, name); mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(fdnr); break; } case 2: { int bcpr = mesh.GetNCD2Names()+1; auto ed = EdgeDescriptor(); ed.SetSurfNr(0,bcpr);//? ednr = mesh.AddEdgeDescriptor(ed); mesh.SetCD2Name(bcpr, name); auto nr = mesh.AddSegment(tmp_segments[get<0>(element_map[index])-1]); mesh[nr].SetBCName(mesh.GetCD2NamePtr(mesh.GetNCD2Names())); mesh[nr].edgenr = ednr+1; break; } default: { cout << "Codim " << codim << " not implemented yet!" << endl; } } for(int i=0; i> hi >> index >> hi >> hi; switch (codim) { case 0: mesh.VolumeElement(get<0>(element_map[index])).SetIndex(matnr); break; case 1: mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(fdnr); break; case 2: { auto nr = mesh.AddSegment(tmp_segments[get<0>(element_map[index])-1]); mesh[nr].edgenr = ednr+1; mesh[nr].SetBCName(mesh.GetCD2NamePtr(mesh.GetNCD2Names())); } break; default: break; } } } } else { cout << "Do not know data field type " << reco << ", skipping it" << endl; while(in.good()) { in >> reco; if(strcmp(reco, "-1") == 0) break; } } } Point3d pmin, pmax; mesh.ComputeNVertices(); mesh.RebuildSurfaceElementLists(); mesh.GetBox (pmin, pmax); mesh.UpdateTopology(); cout << "bounding-box = " << pmin << "-" << pmax << endl; } // fepp format2d: if ( (strlen (filename) > 7) && strcmp (&filename[strlen (filename)-7], ".mesh2d") == 0 ) { cout << "Reading FEPP2D Mesh" << endl; char buf[100]; int np, ne, nseg, i, j; ifstream in (filename); in >> buf; in >> nseg; for (i = 1; i <= nseg; i++) { int bound, p1, p2; in >> bound >> p1 >> p2; // forget them } in >> ne; for (i = 1; i <= ne; i++) { int mat, nelp; in >> mat >> nelp; Element2d el (nelp == 3 ? TRIG : QUAD); el.SetIndex (mat); for (j = 1; j <= nelp; j++) in >> el.PNum(j); mesh.AddSurfaceElement (el); } in >> np; for (i = 1; i <= np; i++) { Point3d p(0,0,0); in >> p.X() >> p.Y(); mesh.AddPoint (p); } } else if ( (strlen (filename) > 5) && strcmp (&filename[strlen (filename)-5], ".mesh") == 0 ) { cout << "Reading Neutral Format" << endl; int np, ne, nse, i, j; ifstream in (filename); in >> np; if (in.good()) { // file starts with an integer for (i = 1; i <= np; i++) { Point3d p(0,0,0); in >> p.X() >> p.Y() >> p.Z(); mesh.AddPoint (p); } in >> ne; for (i = 1; i <= ne; i++) { int mat; in >> mat; Element el (4); el.SetIndex (mat); for (j = 1; j <= 4; j++) in >> el.PNum(j); mesh.AddVolumeElement (el); } mesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0)); int nfd = 1; in >> nse; for (i = 1; i <= nse; i++) { int mat; // , nelp; in >> mat; Element2d el (TRIG); el.SetIndex (mat); while(nfd> el.PNum(j); mesh.AddSurfaceElement (el); } } else { char buf[100]; in.clear(); do { in >> buf; cout << "buf = " << buf << endl; if (strcmp (buf, "points") == 0) { in >> np; cout << "np = " << np << endl; } } while (in.good()); } } if ( (strlen (filename) > 4) && strcmp (&filename[strlen (filename)-4], ".emt") == 0 ) { ifstream inemt (filename); string pktfile = filename; int len = strlen (filename); pktfile[len-3] = 'p'; pktfile[len-2] = 'k'; pktfile[len-1] = 't'; cout << "pktfile = " << pktfile << endl; int np, nse, i; int bcprop; ifstream inpkt (pktfile.c_str()); inpkt >> np; Array values(np); for (i = 1; i <= np; i++) { Point3d p(0,0,0); inpkt >> p.X() >> p.Y() >> p.Z() >> bcprop >> values.Elem(i); mesh.AddPoint (p); } mesh.ClearFaceDescriptors(); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); mesh.GetFaceDescriptor(1).SetBCProperty (1); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); mesh.GetFaceDescriptor(2).SetBCProperty (2); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); mesh.GetFaceDescriptor(3).SetBCProperty (3); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); mesh.GetFaceDescriptor(4).SetBCProperty (4); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); mesh.GetFaceDescriptor(5).SetBCProperty (5); int p1, p2, p3; double value; inemt >> nse; for (i = 1; i <= nse; i++) { inemt >> p1 >> p2 >> p3 >> bcprop >> value; if (bcprop < 1 || bcprop > 4) cerr << "bcprop out of range, bcprop = " << bcprop << endl; p1++; p2++; p3++; if (p1 < 1 || p1 > np || p2 < 1 || p2 > np || p3 < 1 || p3 > np) { cout << "p1 = " << p1 << " p2 = " << p2 << " p3 = " << p3 << endl; } if (i > 110354) Swap (p2, p3); if (mesh.Point(p1)(0) < 0.25) Swap (p2,p3); Element2d el(TRIG); if (bcprop == 1) { if (values.Get(p1) < -69999) el.SetIndex(1); else el.SetIndex(2); } else el.SetIndex(3); el.PNum(1) = p1; el.PNum(2) = p2; el.PNum(3) = p3; mesh.AddSurfaceElement (el); } ifstream incyl ("ngusers/guenter/cylinder.surf"); int npcyl, nsecyl; incyl >> npcyl; cout << "npcyl = " << npcyl << endl; for (i = 1; i <= npcyl; i++) { Point3d p(0,0,0); incyl >> p.X() >> p.Y() >> p.Z(); mesh.AddPoint (p); } incyl >> nsecyl; cout << "nsecyl = " << nsecyl << endl; for (i = 1; i <= nsecyl; i++) { incyl >> p1 >> p2 >> p3; p1 += np; p2 += np; p3 += np; Element2d el(TRIG); el.SetIndex(5); el.PNum(1) = p1; el.PNum(2) = p2; el.PNum(3) = p3; mesh.AddSurfaceElement (el); } } // .tet mesh if ( (strlen (filename) > 4) && strcmp (&filename[strlen (filename)-4], ".tet") == 0 ) { ReadTETFormat (mesh, filename); } // .fnf mesh (FNF - PE neutral format) if ( (strlen (filename) > 4) && strcmp (&filename[strlen (filename)-4], ".fnf") == 0 ) { ReadFNFFormat (mesh, filename); } } } netgen-6.2.1905/libsrc/interface/writeOpenFOAM15x.cpp0000644000175000017500000006600013504650527020702 0ustar kurtkurt/*! \file writeOpenFOAM15x.cpp * \brief Export Netgen Mesh in the OpenFOAM 1.5+ File format * \author Philippose Rajan * \date 25 October 2009 * * This function extends the export capabilities of * Netgen to include the OpenFOAM 1.5+ File Format. * * The OpenFOAM 1.5+ mesh format consists of a set of 5 files * which together define the mesh points, faces, cells and * boundary conditions. * * The files are: * 1. points -> A list of the point co-ordinates * 2. faces -> A list of the faces with format (pnt_ind1 pnt_ind2 .... pnt_ind) * 3. owner -> The owner cell of each face * 4. neighbour -> The neighbour cell of each face * 5. boundary -> The set of boundaries with name, start face, and num. of faces * * For a detailed description of the format, refer to the following link: * http://openfoamwiki.net/index.php/Write_OpenFOAM_meshes * */ #include #include #include #include #include #include namespace netgen { #include "writeuser.hpp" extern MeshingParameters mparam; // Global arrays used to maintain the owner, neighbour and face lists // so that they are accessible across functions static Array owner_facelist; static Array owner_celllist; static Array neighbour_celllist; static Array surfelem_bclist; static Array surfelem_lists; static void WriteOpenFOAM15xBanner(ostream * outfile) { static char FOAMversion[4] = "1.5"; static char spaces[40]; memset(spaces, ' ', 40); spaces[38 - strlen(FOAMversion)] = '\0'; *outfile << "/*--------------------------------*- C++ -*----------------------------------*\\\n"; *outfile << "| ========= | |\n" "| \\\\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n" "| \\\\ / O peration | Version: " << FOAMversion << spaces << "|\n" "| \\\\ / A nd | Web: http://www.OpenFOAM.org |\n" "| \\\\/ M anipulation | |\n" "\\*---------------------------------------------------------------------------*/\n"; } static void WriteOpenFOAM15xDividerStart(ostream * outfile) { *outfile << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n"; } static void WriteOpenFOAM15xDividerEnd(ostream * outfile) { *outfile << "// ************************************************************************* //\n"; } static bool BuildOwnerNeighbourLists (const Mesh & mesh) { // Clear all the arrays owner_facelist.DeleteAll(); owner_celllist.DeleteAll(); neighbour_celllist.DeleteAll(); surfelem_bclist.DeleteAll(); surfelem_lists.DeleteAll(); const MeshTopology& meshtopo = mesh.GetTopology(); // Update the mesh topology structures const_cast (meshtopo).SetBuildEdges(true); const_cast (meshtopo).SetBuildFaces(true); const_cast (meshtopo).Update(); // Extract important mesh metrics int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int totfaces = meshtopo.GetNFaces(); // Preset the size of the arrays to speed up future operations // Number of internal faces = total faces - num. of surface faces owner_facelist.SetSize(totfaces - nse); owner_celllist.SetSize(totfaces - nse); neighbour_celllist.SetSize(totfaces - nse); surfelem_bclist.SetSize(nse); surfelem_lists.SetSize(nse); // Initialise arrays to zero if required neighbour_celllist = 0; // Array used to keep track of Faces which have already been // processed and added to the Owner list... In addition, also the // location where the face appears in the Owner list is also stored // to speed up creation of the Neighbour list Array ownerfaces(totfaces); ownerfaces = 0; // Array to hold the set of local faces of each volume element // while running through the set of volume elements // NOTE: The size is set automatically by the Netgen topology function Array locfaces; // Secondary indices used to independently advance the owner // and boundary condition arrays within the main loop int owner_ind = 1; int bc_ind = 1; // Loop through all the volume elements for(int elind = 1; elind <= ne; elind++) { // Extract the current volume element // const Element & el = mesh.VolumeElement(elind); // Get the face numbers of the faces of the current volume element // The values returned are given a sign depending on the orientation // of the faces. This is used while writing the faces file, to // determine whether or not to invert the face triangle before writing // it to file meshtopo.GetElementFaces(elind,locfaces,true); // Loop through the faces for(int i = 1; i <= locfaces.Size(); i++) { // The absolute value of a face number (because the faces // returned by the GetElementFaces function prepend it // with a sign depending on the face orientation) int absfacenr = abs(locfaces.Elem(i)); // If the face already exists in the owner list, add // the current cell into the neighbour list, in the // same location where the face appears in the owner list int owner_face = ownerfaces.Elem(absfacenr); if(owner_face) { neighbour_celllist.Elem(owner_face) = elind; // From this point on, the code within this "if" block // basically sorts the order of the Neighbour cells (along // with the faces list) in ascending order. // The approach used is..... to traverse the owner and neighbour cell lists // up and down, and sort the neighbour cells of a given owner cell // as the list evolves. // NOTE: A value of "zero" in the neighbour list implies that // the neighbour has not been found yet, so the "zero" locations need // to be skipped while sorting in ascending order int curr_owner = owner_celllist.Elem(owner_face); int peek_loc = owner_face - 1; int new_loc = owner_face; // Traversing upwards in the list while((owner_celllist.Elem(peek_loc) == curr_owner) && (peek_loc >= 1)) { if((neighbour_celllist.Elem(peek_loc) != 0) && (neighbour_celllist.Elem(new_loc) < neighbour_celllist.Elem(peek_loc))) { Swap(neighbour_celllist.Elem(new_loc),neighbour_celllist.Elem(peek_loc)); Swap(owner_facelist.Elem(new_loc),owner_facelist.Elem(peek_loc)); new_loc = peek_loc; } peek_loc--; } peek_loc = owner_face + 1; // Traversing downwards in the list while((owner_celllist.Elem(peek_loc) == curr_owner) && (peek_loc <= owner_ind)) { if((neighbour_celllist.Elem(peek_loc) != 0) && (neighbour_celllist.Elem(new_loc) > neighbour_celllist.Elem(peek_loc))) { Swap(neighbour_celllist.Elem(new_loc),neighbour_celllist.Elem(peek_loc)); Swap(owner_facelist.Elem(new_loc),owner_facelist.Elem(peek_loc)); new_loc = peek_loc; } peek_loc++; } continue; } // Check if the face is a surface element (boundary face) // if not, add the current volume element and the corresponding face into // the owner list int surfelem = meshtopo.GetFace2SurfaceElement(absfacenr); if(!surfelem) { // If it is a new face which has not been listed before, // add the current cell into the owner list, and save // the index location to be used later by the neighbour list owner_celllist.Elem(owner_ind) = elind; owner_facelist.Elem(owner_ind) = locfaces.Elem(i); // Update the array to indicate that the face is already processed ownerfaces.Elem(absfacenr) = owner_ind; owner_ind++; } // If the face is a boundary face, extract the boundary condition number of the // face, and append that along with the face number and the current cell // into the various surface elements lists else { Element2d sel = mesh.SurfaceElement(surfelem); surfelem_bclist.Elem(bc_ind) = mesh.GetFaceDescriptor(sel.GetIndex()).BCProperty(); surfelem_lists.Elem(bc_ind) = INDEX_2(locfaces.Elem(i),elind); bc_ind++; } } } // This correction is required in cases where the mesh has been "uniform refined".... for // some reason, the number of faces reported by Netgen is higher than the actual number // of faces in the mesh owner_facelist.SetSize(owner_ind-1); owner_celllist.SetSize(owner_ind-1); neighbour_celllist.SetSize(owner_ind-1); // Sort the list of surface elements in ascending order of boundary condition number // also sort the cell list in the same manner QuickSort(surfelem_bclist,surfelem_lists); /* // Debugging output to a file ofstream dbg("OpenFOAMDebug.log"); dbg << " ------- Boundary List -------- \n"; for(int i = 1; i <= surfelem_bclist.Size(); i++) { dbg << "bc = " << surfelem_bclist.Elem(i) << " : face = " << surfelem_lists.Elem(i).I1() << " : cell = " << surfelem_lists.Elem(i).I2() << "\n"; } dbg << "\n ------- Owner / Face / Neighbour List ------- \n"; for(int i = 1; i <= owner_celllist.Size(); i++) { dbg << "Ind:" << i << " :: (" << owner_celllist.Elem(i) << " " << owner_facelist.Elem(i) << " " << neighbour_celllist.Elem(i) << ")\n"; } dbg.close(); */ return(false); } static void WriteNeighbourFile (ostream * outfile) { // Write the OpenFOAM standard banner and dividers, etc... WriteOpenFOAM15xBanner(outfile); *outfile << "FoamFile \n" << "{ \n" << " version 2.0; \n" << " format ascii; \n" << " class labelList; \n" << " note \"Mesh generated and converted using NETGEN-" << PACKAGE_VERSION << "\"; \n" << " location \"constant\\polyMesh\"; \n" << " object neighbour; \n" << "} \n"; WriteOpenFOAM15xDividerStart(outfile); *outfile << "\n\n"; int nneighbours = neighbour_celllist.Size(); *outfile << nneighbours << "\n"; *outfile << "(\n"; // Write the neighbour cells to file for(int i = 1; i <= neighbour_celllist.Size(); i++) { *outfile << neighbour_celllist.Elem(i) - 1 << "\n"; } *outfile << ")\n\n"; WriteOpenFOAM15xDividerEnd(outfile); } static void WriteOwnerFile (ostream * outfile) { // Write the OpenFOAM standard banner and dividers, etc... WriteOpenFOAM15xBanner(outfile); *outfile << "FoamFile \n" << "{ \n" << " version 2.0; \n" << " format ascii; \n" << " class labelList; \n" << " note \"Mesh generated and converted using NETGEN-" << PACKAGE_VERSION << "\"; \n" << " location \"constant\\polyMesh\"; \n" << " object owner; \n" << "} \n"; WriteOpenFOAM15xDividerStart(outfile); *outfile << "\n\n"; int nowners = owner_celllist.Size() + surfelem_lists.Size(); *outfile << nowners << "\n"; *outfile << "(\n"; // Write the owners of the internal cells to file for(int i = 1; i <= owner_celllist.Size(); i++) { *outfile << owner_celllist.Elem(i) - 1 << "\n"; } // Write the owners of the boundary cells to file // (Written in order of ascending boundary condition numbers) for(int i = 1; i <= surfelem_lists.Size(); i++) { *outfile << surfelem_lists.Elem(i).I2() - 1 << "\n"; } *outfile << ")\n\n"; WriteOpenFOAM15xDividerEnd(outfile); } static void WriteFacesFile (ostream * outfile, const Mesh & mesh) { const MeshTopology& meshtopo = mesh.GetTopology(); // Write the OpenFOAM standard banner and dividers, etc... WriteOpenFOAM15xBanner(outfile); *outfile << "FoamFile \n" << "{ \n" << " version 2.0; \n" << " format ascii; \n" << " class faceList; \n" << " note \"Mesh generated and converted using NETGEN-" << PACKAGE_VERSION << "\"; \n" << " location \"constant\\polyMesh\"; \n" << " object faces; \n" << "} \n"; WriteOpenFOAM15xDividerStart(outfile); *outfile << "\n\n"; int nfaces = owner_facelist.Size() + surfelem_lists.Size(); *outfile << nfaces << "\n"; *outfile << "(\n"; // Array to hold the indices of the points of each face to // flip if required Array facepnts; // Write the faces in the order specified in the owners lists of the // internal cells and the boundary cells for(int i = 1; i <= owner_facelist.Size(); i++) { int face_w_orientation = owner_facelist.Elem(i); int facenr = abs(face_w_orientation); meshtopo.GetFaceVertices(facenr,facepnts); // Get the orientation of the face, and invert it if required // Since the faces already have the orientation "embedded" into // them by means of the prepended sign, only this needs to be // checked for... if(face_w_orientation > 0) { int tmppnts = 0; if(facepnts.Size() == 4) { tmppnts = facepnts.Elem(1); facepnts.Elem(1) = facepnts.Elem(2); facepnts.Elem(2) = tmppnts; tmppnts = facepnts.Elem(3); facepnts.Elem(3) = facepnts.Elem(4); facepnts.Elem(4) = tmppnts; } else if(facepnts.Size() == 3) { tmppnts = facepnts.Elem(1); facepnts.Elem(1) = facepnts.Elem(3); facepnts.Elem(3) = tmppnts; } } *outfile << facepnts.Size(); *outfile << "("; for(int j = 1; j <= facepnts.Size(); j++) { *outfile << facepnts.Elem(j)-1; if(j != facepnts.Size()) *outfile << " "; } *outfile << ")\n"; } // Now append the faces of the surface elements (written in // ascending order of boundary condition number) also into // the faces file for(int i = 1; i <= surfelem_lists.Size(); i++) { int face_w_orientation = surfelem_lists.Elem(i).I1(); int facenr = abs(face_w_orientation); meshtopo.GetFaceVertices(facenr,facepnts); // Get the orientation of the face, and invert it if required if(face_w_orientation > 0) { int tmppnts = 0; if(facepnts.Size() == 4) { tmppnts = facepnts.Elem(1); facepnts.Elem(1) = facepnts.Elem(2); facepnts.Elem(2) = tmppnts; tmppnts = facepnts.Elem(3); facepnts.Elem(3) = facepnts.Elem(4); facepnts.Elem(4) = tmppnts; } else if(facepnts.Size() == 3) { tmppnts = facepnts.Elem(1); facepnts.Elem(1) = facepnts.Elem(3); facepnts.Elem(3) = tmppnts; } } *outfile << facepnts.Size(); *outfile << "("; for(int j = 1; j <= facepnts.Size(); j++) { *outfile << facepnts.Elem(j)-1; if(j != facepnts.Size()) *outfile << " "; } *outfile << ")\n"; } *outfile << ")\n\n"; WriteOpenFOAM15xDividerEnd(outfile); } static void WritePointsFile (ostream * outfile, const Mesh & mesh) { int np = mesh.GetNP(); // Write the OpenFOAM standard banner and dividers, etc... WriteOpenFOAM15xBanner(outfile); *outfile << "FoamFile \n" << "{ \n" << " version 2.0; \n" << " format ascii; \n" << " class vectorField; \n" << " note \"Mesh generated and converted using NETGEN-" << PACKAGE_VERSION << "\"; \n" << " location \"constant\\polyMesh\"; \n" << " object points; \n" << "} \n"; WriteOpenFOAM15xDividerStart(outfile); *outfile << "\n\n"; // Number of points in the following list *outfile << np << "\n"; outfile->precision(6); outfile->setf (ios::fixed, ios::floatfield); outfile->setf (ios::showpoint); // Coordinate list starts here *outfile << "(\n"; for(int i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); // Write coordinates to file *outfile << "("; *outfile << p.X() << " "; *outfile << p.Y() << " "; *outfile << p.Z(); *outfile << ")\n"; } *outfile << ")\n\n"; WriteOpenFOAM15xDividerEnd(outfile); } static void WriteBoundaryFile (ostream * outfile) { // Write the OpenFOAM standard banner and dividers, etc... WriteOpenFOAM15xBanner(outfile); *outfile << "FoamFile \n" << "{ \n" << " version 2.0; \n" << " format ascii; \n" << " class polyBoundaryMesh; \n" << " note \"Mesh generated and converted using NETGEN-" << PACKAGE_VERSION << "\"; \n" << " location \"constant\\polyMesh\"; \n" << " object boundary; \n" << "} \n"; WriteOpenFOAM15xDividerStart(outfile); *outfile << "\n"; Array bcarray; int ind = 1; // Since the boundary conditions are already sorted in ascending // order, the last element will give the maximum number of possible // boundary condition entries int bcmax = surfelem_bclist.Elem(surfelem_bclist.Size()); bcarray.SetSize(bcmax+1); bcarray.Elem(ind) = INDEX_3(surfelem_bclist.Elem(1),1,0); for(int i = 2; i <= surfelem_bclist.Size(); i++) { if(surfelem_bclist.Elem(i) == bcarray.Elem(ind).I1()) { bcarray.Elem(ind).I2() = bcarray.Elem(ind).I2()+1; } else { ind++; bcarray.Elem(ind) = INDEX_3(surfelem_bclist.Elem(i),1,i-1); } } bcarray.SetSize(ind); *outfile << bcarray.Size() << "\n"; *outfile << "(\n"; int startface = 0; for(int i = 1; i <= bcarray.Size(); i++) { startface = owner_celllist.Size() + bcarray.Elem(i).I3(); *outfile << " patch" << bcarray.Elem(i).I1() << "\n" << " {\n" << " type patch;\n" << " physicalType patch;\n" << " nFaces " << bcarray.Elem(i).I2() << ";\n" << " startFace " << startface << ";\n" << " }\n"; } *outfile << ")\n\n"; WriteOpenFOAM15xDividerEnd(outfile); } void WriteOpenFOAM15xFormat (const Mesh & mesh, const string & casename, const bool compressed) { bool error = false; char casefiles[256]; // Make sure that the mesh data has been updated const_cast (mesh).Compress(); const_cast (mesh).CalcSurfacesOfNode(); const_cast (mesh).RebuildSurfaceElementLists(); const_cast (mesh).BuildElementSearchTree(); int np = mesh.GetNP(); int nse = mesh.GetNSE(); int ne = mesh.GetNE(); cout << "Write OpenFOAM 1.5+ Mesh Files....\n"; // Abort if there are no points, surface elements or volume elements if((np <= 0) || (ne <= 0) || (nse <= 0)) { cout << "Export Error: Invalid mesh.... Aborting!\n"; return; } // OpenFOAM only supports linear meshes! if(mparam.secondorder || mesh.GetCurvedElements().IsHighOrder()) { cout << "Export Error: OpenFOAM 1.5+ does not support non-linear elements.... Aborting!\n"; return; } if(( (mesh.SurfaceElement(nse/2).GetType() != TRIG) && (mesh.SurfaceElement(nse/2).GetType() != QUAD) ) || (mesh.VolumeElement(ne/2).GetType() == TET10) || (mesh.VolumeElement(ne/2).GetType() == PRISM12)) { cout << "Export Error: OpenFOAM 1.5+ does not support non-linear elements.... Aborting!\n"; return; } cout << "Writing OpenFOAM 1.5+ Mesh files to case: " << casename << "\n"; // Create the case directory if it does not already exist // NOTE: This needs to be improved for the Linux variant....!!! #ifdef WIN32 char casedir[256]; sprintf(casedir, "mkdir %s\\constant\\polyMesh", casename.c_str()); system(casedir); #else char casedir[256]; mkdir(casename.c_str(), S_IRWXU|S_IRWXG); sprintf(casedir, "%s/constant", casename.c_str()); mkdir(casedir, S_IRWXU|S_IRWXG); sprintf(casedir, "%s/constant/polyMesh", casename.c_str()); mkdir(casedir, S_IRWXU|S_IRWXG); #endif // Open handles to the five required mesh files // points // faces // owner // neighbour // boundary ostream *outfile_pnts; ostream *outfile_faces; ostream *outfile_own; ostream *outfile_nei; ostream *outfile_bnd; if(compressed) { sprintf(casefiles, "%s/constant/polyMesh/points.gz", casename.c_str()); outfile_pnts = new ogzstream(casefiles); } else { sprintf(casefiles, "%s/constant/polyMesh/points", casename.c_str()); outfile_pnts = new ofstream(casefiles); } if(compressed) { sprintf(casefiles, "%s/constant/polyMesh/faces.gz", casename.c_str()); outfile_faces = new ogzstream(casefiles); } else { sprintf(casefiles, "%s/constant/polyMesh/faces", casename.c_str()); outfile_faces = new ofstream(casefiles); } if(compressed) { sprintf(casefiles, "%s/constant/polyMesh/owner.gz", casename.c_str()); outfile_own = new ogzstream(casefiles); } else { sprintf(casefiles, "%s/constant/polyMesh/owner", casename.c_str()); outfile_own = new ofstream(casefiles); } if(compressed) { sprintf(casefiles, "%s/constant/polyMesh/neighbour.gz", casename.c_str()); outfile_nei = new ogzstream(casefiles); } else { sprintf(casefiles, "%s/constant/polyMesh/neighbour", casename.c_str()); outfile_nei = new ofstream(casefiles); } // Note... the boundary file is not compressed sprintf(casefiles, "%s/constant/polyMesh/boundary", casename.c_str()); outfile_bnd = new ofstream(casefiles); ResetTime(); // Build the owner, neighbour, faces and boundary lists // from the Netgen mesh cout << "\nBuilding Owner, Neighbour and Face Lists: "; error = BuildOwnerNeighbourLists(mesh); cout << "Done! (Time Elapsed = " << GetTime() << " sec)\n"; // Write the "owner" file if(outfile_own->good() && !error) { cout << "Writing the owner file: "; WriteOwnerFile(outfile_own); delete outfile_own; cout << "Done! (Time Elapsed = " << GetTime() << " sec)\n"; } else { cout << "Export Error: Error creating file: owner.... Aborting\n"; error = true; } // Write the "neighbour" file if(outfile_nei->good() && !error) { cout << "Writing the neighbour file: "; WriteNeighbourFile(outfile_nei); delete outfile_nei; cout << "Done! (Time Elapsed = " << GetTime() << " sec)\n"; } else { cout << "Export Error: Error creating file: neighbour.... Aborting\n"; error = true; } // Write the "faces" file if(outfile_faces->good() && !error) { cout << "Writing the faces file: "; WriteFacesFile(outfile_faces, mesh); delete outfile_faces; cout << "Done! (Time Elapsed = " << GetTime() << " sec)\n"; } else { cout << "Export Error: Error creating file: faces.... Aborting\n"; error = true; } // Write the "points" file if(outfile_pnts->good() && !error) { cout << "Writing the points file: "; WritePointsFile(outfile_pnts,mesh); delete outfile_pnts; cout << "Done! (Time Elapsed = " << GetTime() << " sec)\n"; } else { cout << "Export Error: Error creating file: points.... Aborting\n"; error = true; } // Write the "boundary" file if(outfile_bnd->good() && !error) { cout << "Writing the boundary file: "; WriteBoundaryFile(outfile_bnd); delete outfile_bnd; cout << "Done! (Time Elapsed = " << GetTime() << " sec)\n"; } else { cout << "Export Error: Error creating file: boundary.... Aborting\n"; error = true; } if(!error) { cout << "OpenFOAM 1.5+ Export successfully completed (Time elapsed = " << GetTime() << " sec) !\n"; } else { cout << "Error in OpenFOAM 1.5+ Export.... Aborted!\n"; } } } netgen-6.2.1905/libsrc/interface/writediffpack.cpp0000644000175000017500000002114113504650527020544 0ustar kurtkurt// // Write diffpack file // // by // Bartosz Sawicki // extended by // Jacques Lechelle // #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteDiffPackFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename) { // double scale = globflags.GetNumFlag ("scale", 1); double scale = 1; ofstream outfile(filename.c_str()); outfile.precision(14); if (mesh.GetDimension() == 3) { // Output compatible to Diffpack grid format // Bartosz Sawicki int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); Array BIname; Array BCsinpoint; int i, j, k, l; outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); const Element & eldummy = mesh.VolumeElement((int)1); outfile << "\n\n" "Finite element mesh (GridFE):\n\n" " Number of space dim. = 3\n" " Number of elements = " << ne << "\n" " Number of nodes = " << np << "\n\n" " All elements are of the same type : dpTRUE\n" " Max number of nodes in an element: "<< eldummy.GetNP() << "\n" " Only one subdomain : dpFALSE\n" " Lattice data ? 0\n\n\n\n"; for (i = 1; i <= nse; i++) { int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty(); int nbi=BIname.Size(); int found=0; for (j = 1; j <= nbi; j++) if(BI == BIname.Get(j)) found = 1; if( ! found ) BIname.Append(BI); } outfile << " " << BIname.Size() << " Boundary indicators: "; for (i =1 ; i <= BIname.Size(); i++) outfile << BIname.Get(i) << " "; outfile << "\n\n\n"; outfile << " Nodal coordinates and nodal boundary indicators,\n" " the columns contain:\n" " - node number\n" " - coordinates\n" " - no of boundary indicators that are set (ON)\n" " - the boundary indicators that are set (ON) if any.\n" "#\n"; // setup point-to-surfaceelement table TABLE point2sel(np); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = mesh[sei]; for (int j = 0; j < el.GetNP(); j++) point2sel.Add (el[j], sei); } for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile.width(12); outfile << i << " ("; outfile.width(16); outfile << p.X()/scale << ", "; outfile.width(16); outfile << p.Y()/scale << ", "; outfile.width(16); outfile << p.Z()/scale << ") "; if(mesh[PointIndex(i)].Type() != INNERPOINT) { BCsinpoint.DeleteAll(); /* for (j = 1; j <= nse; j++) */ FlatArray sels = point2sel[i]; for (int jj = 0; jj < sels.Size(); jj++) { for (k = 1; k <= mesh[sels[jj]].GetNP(); k++) { if(mesh[sels[jj]].PNum(k)==i) { int BC=mesh.GetFaceDescriptor(mesh[sels[jj]].GetIndex()).BCProperty(); int nbcsp=BCsinpoint.Size(); int found = 0; for (l = 1; l <= nbcsp; l++) if(BC == BCsinpoint.Get(l)) found = 1; if( ! found ) BCsinpoint.Append(BC); } } } int nbcsp = BCsinpoint.Size(); outfile << "[" << nbcsp << "] "; for (j = 1; j <= nbcsp; j++) outfile << BCsinpoint.Get(j) << " "; outfile << "\n"; } else outfile << "[0]\n"; } outfile << "\n" " Element types and connectivity\n" " the columns contain:\n" " - element number\n" " - element type\n" " - subdomain number\n" " - the global node numbers of the nodes in the element.\n" "#\n"; for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); outfile.width(5); if(el.GetNP()==4) outfile << i << " ElmT4n3D "; else outfile << i << " ElmT10n3D "; outfile.width(4); outfile << el.GetIndex() << " "; if(el.GetNP()==10) { outfile.width(8); outfile << el.PNum(1); outfile.width(8); outfile << el.PNum(3); outfile.width(8); outfile << el.PNum(2); outfile.width(8); outfile << el.PNum(4); outfile.width(8); outfile << el.PNum(6); outfile.width(8); outfile << el.PNum(8); outfile.width(8); outfile << el.PNum(5); outfile.width(8); outfile << el.PNum(7); outfile.width(8); outfile << el.PNum(10); outfile.width(8); outfile << el.PNum(9); } else { outfile.width(8); outfile << el.PNum(1); outfile.width(8); outfile << el.PNum(3); outfile.width(8); outfile << el.PNum(2); outfile.width(8); outfile << el.PNum(4); } outfile << "\n"; } } /* Diffpack */ else { // Output compatible to Diffpack grid format 2D int np = mesh.GetNP(); //int ne = mesh.GetNE(); int nse = mesh.GetNSE(); Array BIname; Array BCsinpoint; int i, j, k, l; outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); const Element2d & eldummy = mesh.SurfaceElement((int)1); outfile << "\n\n" "Finite element mesh (GridFE):\n\n" " Number of space dim. = 2\n" " Number of elements = " << nse << "\n" " Number of nodes = " << np << "\n\n" " All elements are of the same type : dpTRUE\n" " Max number of nodes in an element: "< #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteJCMFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename) { if (mesh.GetDimension() != 3) { cout <<"\n Error: Dimension 3 only supported by this output format!"< identmap1, identmap2, identmap3; mesh.GetIdentifications().GetMap(1, identmap1); mesh.GetIdentifications().GetMap(2, identmap2); mesh.GetIdentifications().GetMap(3, identmap3); // number of volume elements int ne = mesh.GetNE(); int ntets = 0; int nprisms = 0; for (i = 1; i <= ne; i++) { Element el = mesh.VolumeElement(i); if (el.GetNP() == 4) { ntets++; // Check that no two points on a tetrahedron are identified with each other for (j = 1; j <= 4; j++) for (jj = 1; jj <=4; jj++) { if (identmap1.Elem(el.PNum(j)) == el.PNum(jj)) { cout << "\n Error: two points on a tetrahedron identified (1) with each other" << "\n REFINE MESH !" << endl; return; } if (identmap2.Elem(el.PNum(j)) == el.PNum(jj)) { cout << "\n Error: two points on a tetrahedron identified (2) with each other" << "\n REFINE MESH !" << endl; return; } if (identmap3.Elem(el.PNum(j)) == el.PNum(jj)) { cout << "\n Error: two points on a tetrahedron identified (3) with each other" << "\n REFINE MESH !" << endl; return; } } } else if (el.GetNP() == 6) nprisms++; } if ( ne != (ntets+nprisms)) { cout<< "\n Error in determining number of volume elements!\n" << "\n Prisms and tetrahedra only implemented in the JCMwave format!\n"< 0) cout << " Please note: Boundaries at infinity have to carry the bc-attribute '-bc=" << bc_at_infinity <<"'."< pointsOnTetras; pointsOnTetras.SetSize (mesh.GetNP()); pointsOnTetras = 0; for (i = 1; i <= ne; i++) { Element el = mesh.VolumeElement(i); if (el.GetNP() == 4) { for (j = 1; j <= 4; j++) pointsOnTetras.Set(int (el.PNum(j)),1); } } // number of boundary triangles and boundary quadrilaterals for (i = 1; i <= nse; i++) { Element2d el = mesh.SurfaceElement(i); if (el.GetNP() == 3 && ( mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 || mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0 ) ) nbtri++; else if (el.GetNP() == 4 && ( mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 || mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0 ) ) nbquad++; } ofstream outfile (filename.c_str()); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); outfile << "/* \n"; outfile << "__BLOBTYPE__=Grid\n"; outfile << "__OWNER__=JCMwave\n"; outfile << "SpaceDim=3\n"; outfile << "ManifoldDim=3\n"; outfile << "NRefinementSteps=0\n"; outfile << "NPoints="<NTetrahedra="<NPrisms="<NBoundaryTriangles="<NBoundaryQuadrilaterals="< & p = mesh.Point(i); outfile << i << "\n"; outfile << p(0) << "e-6\n"; outfile << p(1) << "e-6\n"; outfile << p(2) << "e-6\n\n"; } outfile << "\n"; outfile << "# Tetrahedra\n"; counter = 0; for (i = 1; i <= ne; i++) { Element el = mesh.VolumeElement(i); if (el.GetNP() == 4) { counter++; dx1 = mesh.Point(el.PNum(2))(0) - mesh.Point(el.PNum(1))(0); dx2 = mesh.Point(el.PNum(3))(0) - mesh.Point(el.PNum(1))(0); dx3 = mesh.Point(el.PNum(4))(0) - mesh.Point(el.PNum(1))(0); dy1 = mesh.Point(el.PNum(2))(1) - mesh.Point(el.PNum(1))(1); dy2 = mesh.Point(el.PNum(3))(1) - mesh.Point(el.PNum(1))(1); dy3 = mesh.Point(el.PNum(4))(1) - mesh.Point(el.PNum(1))(1); dz1 = mesh.Point(el.PNum(2))(2) - mesh.Point(el.PNum(1))(2); dz2 = mesh.Point(el.PNum(3))(2) - mesh.Point(el.PNum(1))(2); dz3 = mesh.Point(el.PNum(4))(2) - mesh.Point(el.PNum(1))(2); vol = (dy1*dz2-dz1*dy2)*dx3 + (dz1*dx2-dx1*dz2)*dy3 + (dx1*dy2-dy1*dx2)*dz3; if ( vol > 0 ) for (j = 1; j <= 4; j++) outfile << el.PNum(j)<<"\n"; else { for (j = 2; j >= 1; j--) outfile << el.PNum(j)<<"\n"; for (j = 3; j <= 4; j++) outfile << el.PNum(j)<<"\n"; } outfile << el.GetIndex() << "\n\n"; } } if ( counter != ntets) { cout<< "\n Error in determining number of tetras!\n"< 0) for (j = 1; j <= 6; j++) outfile << el.PNum(j)<<"\n"; else { for (j = 3; j >= 1; j--) outfile << el.PNum(j)<<"\n"; for (j = 6; j >= 4; j--) outfile << el.PNum(j)<<"\n"; } } else if ( pointsOnTetras.Get(el.PNum(4)) && pointsOnTetras.Get(el.PNum(5)) && pointsOnTetras.Get(el.PNum(6)) ) { if ( vol < 0 ) { for (j = 4; j <= 6; j++) outfile << el.PNum(j)<<"\n"; for (j = 1; j <= 3; j++) outfile << el.PNum(j)<<"\n"; } else { for (j = 6; j >= 4; j--) outfile << el.PNum(j)<<"\n"; for (j = 3; j >= 1; j--) outfile << el.PNum(j)<<"\n"; } } else { cout << "\n Error in determining prism point numbering!\n"<= 5 ) jj = jj - 4; outfile << el.PNum(jj)<<"\n"; } outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << "\n"; if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() == bc_at_infinity) { outfile << "-2\n\n"; cout << "\nWarning: Quadrilateral at infinity found (this should not occur)!"<= 5 ) jj = jj - 4; outfile << identmap1.Elem(el.PNum(jj))<<"\n"; } outfile << "\n"; } else if ( identmap2.Elem(el.PNum(1)) && identmap2.Elem(el.PNum(2)) && identmap2.Elem(el.PNum(3)) && identmap2.Elem(el.PNum(4)) ) { outfile << "-1\n"; for (j = 1; j <= 4; j++) { jj = j + ct; if ( jj >= 5 ) jj = jj - 4; outfile << identmap2.Elem(el.PNum(jj))<<"\n"; } outfile << "\n"; } else if ( identmap3.Elem(el.PNum(1)) && identmap3.Elem(el.PNum(2)) && identmap3.Elem(el.PNum(3)) && identmap3.Elem(el.PNum(4)) ) { outfile << "-1\n"; for (j = 1; j <= 4; j++) { jj = j + ct; if ( jj >= 5 ) jj = jj - 4; outfile << identmap3.Elem(el.PNum(jj))<<"\n"; } outfile << "\n"; } else outfile << "1\n\n"; } } cout << " JCMwave grid file written." << endl; } } netgen-6.2.1905/libsrc/interface/wuchemnitz.cpp0000644000175000017500000001717113504650527020127 0ustar kurtkurt// Write Chemnitz file format #include #include #include #include #include namespace netgen { class POINT3D { public: POINT3D () { }; double x, y, z; }; class VOLELEMENT { public: int domnr, p1, p2, p3, p4; int faces[4]; VOLELEMENT () { for (int i = 0; i < 4; i++) faces[i] = 0; } }; class SURFELEMENT { public: SURFELEMENT () { }; int snr, p1, p2, p3; }; class FACE { public: int p1, p2, p3; int edges[3]; FACE () { for (int i = 0; i < 3; i++) edges[i] = 0; } }; class EDGE { public: EDGE () { }; int p1, p2; }; static Array points; static Array volelements; static Array surfelements; static Array faces; static Array edges; void ReadFile (char * filename) { int i, n; ifstream infile(filename); char reco[100]; infile >> reco; // file format recognition infile >> n; // number of surface elements cout << n << " Surface elements" << endl; for (i = 1; i <= n; i++) { SURFELEMENT sel; infile >> sel.snr >> sel.p1 >> sel.p2 >> sel.p3; surfelements.Append (sel); } infile >> n; // number of volume elements cout << n << " Volume elements" << endl; for (i = 1; i <= n; i++) { VOLELEMENT el; infile >> el.p1 >> el.p2 >> el.p3 >> el.p4; volelements.Append (el); } infile >> n; // number of points cout << n << " Points" << endl; for (i = 1; i <= n; i++) { POINT3D p; infile >> p.x >> p.y >> p.z; points.Append (p); } } void ReadFileMesh (const Mesh & mesh) { int i, n; n = mesh.GetNSE(); // number of surface elements cout << n << " Surface elements" << endl; for (i = 1; i <= n; i++) { SURFELEMENT sel; const Element2d & el = mesh.SurfaceElement(i); sel.snr = el.GetIndex(); sel.p1 = el.PNum(1); sel.p2 = el.PNum(2); sel.p3 = el.PNum(3); surfelements.Append (sel); } n = mesh.GetNE(); // number of volume elements cout << n << " Volume elements" << endl; for (i = 1; i <= n; i++) { VOLELEMENT el; const Element & nel = mesh.VolumeElement(i); el.p1 = nel.PNum(1); el.p2 = nel.PNum(2); el.p3 = nel.PNum(3); el.p4 = nel.PNum(4); // infile >> el.p1 >> el.p2 >> el.p3 >> el.p4; volelements.Append (el); } n = mesh.GetNP(); // number of points cout << n << " Points" << endl; for (i = 1; i <= n; i++) { POINT3D p; Point3d mp = mesh.Point(i); p.x = mp.X(); p.y = mp.Y(); p.z = mp.Z(); // infile >> p.x >> p.y >> p.z; points.Append (p); } } void Convert () { int i, j, facei, edgei; INDEX_3 i3; INDEX_2 i2; INDEX_3_HASHTABLE faceindex(volelements.Size()/5 + 1); INDEX_2_HASHTABLE edgeindex(volelements.Size()/5 + 1); for (i = 1; i <= volelements.Size(); i++) { for (j = 1; j <= 4; j++) { switch (j) { case 1: i3.I1() = volelements.Get(i).p2; i3.I2() = volelements.Get(i).p3; i3.I3() = volelements.Get(i).p4; break; case 2: i3.I1() = volelements.Get(i).p1; i3.I2() = volelements.Get(i).p3; i3.I3() = volelements.Get(i).p4; break; case 3: i3.I1() = volelements.Get(i).p1; i3.I2() = volelements.Get(i).p2; i3.I3() = volelements.Get(i).p4; break; case 4: i3.I1() = volelements.Get(i).p1; i3.I2() = volelements.Get(i).p2; i3.I3() = volelements.Get(i).p3; break; default: i3.I1()=i3.I2()=i3.I3()=0; } i3.Sort(); if (faceindex.Used (i3)) facei = faceindex.Get(i3); else { FACE fa; fa.p1 = i3.I1(); fa.p2 = i3.I2(); fa.p3 = i3.I3(); faces.Append (fa); facei = faces.Size(); faceindex.Set (i3, facei); } volelements.Elem(i).faces[j-1] = facei; } } for (i = 1; i <= faces.Size(); i++) { for (j = 1; j <= 3; j++) { switch (j) { case 1: i2.I1() = faces.Get(i).p2; i2.I2() = faces.Get(i).p3; break; case 2: i2.I1() = faces.Get(i).p1; i2.I2() = faces.Get(i).p3; break; case 3: i2.I1() = faces.Get(i).p1; i2.I2() = faces.Get(i).p2; break; default: i2.I1()=i2.I2()=0; } if (i2.I1() > i2.I2()) swap (i2.I1(), i2.I2()); if (edgeindex.Used (i2)) edgei = edgeindex.Get(i2); else { EDGE ed; ed.p1 = i2.I1(); ed.p2 = i2.I2(); edges.Append (ed); edgei = edges.Size(); edgeindex.Set (i2, edgei); } faces.Elem(i).edges[j-1] = edgei; } } } void WriteFile (ostream & outfile) { int i; outfile << "#VERSION: 1.0" << endl << "#PROGRAM: NETGEN" << endl << "#EQN_TYPE: POISSON" << endl << "#DIMENSION: 3D" << endl << "#DEG_OF_FREE: 1" << endl << "#DESCRIPTION: I don't know" << endl << "##RENUM: not done" << endl << "#USER: Kleinzen" << endl << "DATE: 10.06.1996" << endl; outfile << "#HEADER: 8" << endl << points.Size() << " " << edges.Size() << " " << faces.Size() << " " << volelements.Size() << " 0 0 0 0" << endl; outfile << "#VERTEX: " << points.Size() << endl; for (i = 1; i <= points.Size(); i++) outfile << " " << i << " " << points.Get(i).x << " " << points.Get(i).y << " " << points.Get(i).z << endl; outfile << "#EDGE: " << edges.Size() << endl; for (i = 1; i <= edges.Size(); i++) outfile << " " << i << " 1 " << edges.Get(i).p1 << " " << edges.Get(i).p2 << " 0" << endl; outfile << "#FACE: " << faces.Size() << endl; for (i = 1; i <= faces.Size(); i++) outfile << " " << i << " 1 3 " << faces.Get(i).edges[0] << " " << faces.Get(i).edges[1] << " " << faces.Get(i).edges[2] << endl; outfile << "#SOLID: " << volelements.Size() << endl; for (i = 1; i <= volelements.Size(); i++) outfile << " " << i << " 1 4 " << volelements.Get(i).faces[0] << " " << volelements.Get(i).faces[1] << " " << volelements.Get(i).faces[2] << " " << volelements.Get(i).faces[3] << endl; outfile << "#END_OF_DATA" << endl; } void WriteUserChemnitz (const Mesh & mesh, const string & filename) { ofstream outfile (filename.c_str()); ReadFileMesh (mesh); Convert (); WriteFile (outfile); cout << "Wrote Chemnitz standard file" << endl; } } netgen-6.2.1905/libsrc/interface/writegmsh.cpp0000644000175000017500000001322413504650527017736 0ustar kurtkurt/************************************* * Write Gmsh file * First issue the 04/26/2004 by Paul CARRICO (paul.carrico@free.fr) * At the moment, the GMSH format is available for * linear tetrahedron elements i.e. in 3D * (based on Neutral Format) * * Second issue the 05/05/2004 by Paul CARRICO * Thanks to Joachim Schoeberl for the correction of a minor bug * the 2 initial Gmsh Format (i.e. volume format and surface format) are group together) * in only one file **************************************/ #include #include #include #include #include namespace netgen { #include "writeuser.hpp" extern MeshingParameters mparam; /* * GMSH mesh format * points, elements, surface elements and physical entities */ void WriteGmshFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename) { ofstream outfile (filename.c_str()); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); int np = mesh.GetNP(); /// number of point int ne = mesh.GetNE(); /// number of element int nse = mesh.GetNSE(); /// number of surface element (BC) int i, j, k, l; /* * 3D section : Linear volume elements (only tetrahedra) */ if (ne > 0 && mesh.VolumeElement(1).GetNP() == 4) { cout << "Write GMSH Format \n"; cout << "The GMSH format is available for linear tetrahedron elements only in 3D\n" << endl; int inverttets = mparam.inverttets; int invertsurf = mparam.inverttrigs; /// Write nodes outfile << "$NOD\n"; outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile << i << " "; /// node number outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << "\n"; } outfile << "$ENDNOD\n"; /// write elements outfile << "$ELM\n"; outfile << ne + nse << "\n"; //// number of elements + number of surfaces BC for (i = 1; i <= nse; i++) { Element2d el = mesh.SurfaceElement(i); if (invertsurf) el.Invert(); outfile << i; outfile << " "; outfile << "2"; outfile << " "; outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; /// that means that physical entity = elementary entity (arbitrary approach) outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; outfile << "3"; outfile << " "; for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile << el.PNum(j); } outfile << "\n"; } for (i = 1; i <= ne; i++) { Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); outfile << nse + i; /// element number outfile << " "; outfile << "4"; /// element type i.e. Tetraedron == 4 outfile << " "; outfile << 100000 + el.GetIndex(); /// that means that physical entity = elementary entity (arbitrary approach) outfile << " "; outfile << 100000 + el.GetIndex(); /// volume number outfile << " "; outfile << "4"; /// number of nodes i.e. 4 for a tetrahedron for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile << el.PNum(j); } outfile << "\n"; } outfile << "$ENDELM\n"; } /* * End of 3D section */ /* * 2D section : available for triangles and quadrangles */ else if (ne == 0) /// means that there's no 3D element { cout << "\n Write Gmsh Surface Mesh (triangle and/or quadrangles)" << endl; /// Write nodes outfile << "$NOD\n"; outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile << i << " "; /// node number outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << "\n"; } outfile << "$ENDNOD\n"; /// write triangles & quadrangles outfile << "$ELM\n"; outfile << nse << "\n"; for (k = 1; k <= nse; k++) { const Element2d & el = mesh.SurfaceElement(k); outfile << k; outfile << " "; outfile << (el.GetNP()-1); // 2 for a triangle and 3 for a quadrangle outfile << " "; outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; /// that means that physical entity = elementary entity (arbitrary approach) outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; outfile << (el.GetNP()); // number of node per surfacic element outfile << " "; for (l = 1; l <= el.GetNP(); l++) { outfile << " "; outfile << el.PNum(l); } outfile << "\n"; } outfile << "$ENDELM$ \n"; } /* * End of 2D section */ else { cout << " Invalid element type for Gmsh volume Format !\n"; } } } netgen-6.2.1905/libsrc/interface/writefluent.cpp0000644000175000017500000001044313504650527020275 0ustar kurtkurt// // Write Fluent file // Johannes Gerstmayr, University Linz // #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteFluentFormat (const Mesh & mesh, const string & filename) { cout << "start writing fluent export" << endl; int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int i, j; ofstream outfile (filename.c_str()); char str[100]; outfile.precision(6); //outfile.setf (ios::fixed, ios::floatfield); //outfile.setf (ios::showpoint); outfile << "(0 \"Exported file from NETGEN \")" << endl; outfile << "(0 \"Dimension:\")" << endl; outfile << "(2 3)" << endl << endl; outfile << "(0 \"Nodes:\")" << endl; //number of nodes: sprintf(str,"(10 (0 1 %x 1))",np); //hexadecimal!!! outfile << str << endl; //nodes of zone 1: sprintf(str,"(10 (7 1 %x 1)(",np); //hexadecimal!!! outfile << str << endl; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); //outfile.width(10); outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << "\n"; } outfile << "))" << endl << endl; //write faces with elements outfile << "(0 \"Faces:\")" << endl; Element2d face, face2; int i2, j2; Array surfaceelp; Array surfaceeli; Array locels; //no cells=no tets //no faces=2*tets int noverbface = 2*ne-nse/2; sprintf(str,"(13 (0 1 %x 0))",(noverbface+nse)); //hexadecimal!!! outfile << str << endl; sprintf(str,"(13 (4 1 %x 2 3)(",noverbface); //hexadecimal!!! outfile << str << endl; const_cast (mesh).BuildElementSearchTree(); for (i = 1; i <= ne; i++) { if (ne > 2000) { if (i%2000 == 0) { cout << (double)i/(double)ne*100. << "%" << endl; } } Element el = mesh.VolumeElement(i); //if (inverttets) // el.Invert(); //outfile << el.GetIndex() << " "; if (el.GetNP() != 4) {cout << "only tet-meshes supported in write fluent!" << endl;} //faces: Box3d box; el.GetBox(mesh.Points(), box); box.IncreaseRel(1e-6); mesh.GetIntersectingVolEls(box.PMin(),box.PMax(),locels); int nel = locels.Size(); int locind; //cout << "nel=" << nel << endl; for (j = 1; j <= el.GetNFaces(); j++) { el.GetFace(j, face); face.Invert(); int eli2 = 0; int stopsig = 0; for (i2 = 1; i2 <= nel; i2++) { locind = locels.Get(i2); //cout << " locind=" << locind << endl; Element el2 = mesh.VolumeElement(locind); //if (inverttets) // el2.Invert(); for (j2 = 1; j2 <= el2.GetNFaces(); j2++) { el2.GetFace(j2, face2); if (face2.HasFace(face)) {eli2 = locind; stopsig = 1; break;} } if (stopsig) break; } if (eli2==i) cout << "error in WRITE_FLUENT!!!" << endl; if (eli2 > i) //don't write faces two times! { //i: left cell, eli: right cell outfile << hex << face.PNum(2) << " " << hex << face.PNum(1) << " " << hex << face.PNum(3) << " " << hex << i << " " << hex << eli2 << "\n"; } if (eli2 == 0) { surfaceelp.Append(INDEX_3(face.PNum(2),face.PNum(1),face.PNum(3))); surfaceeli.Append(i); } } } outfile << "))" << endl; sprintf(str,"(13 (2 %x %x 3 3)(",(noverbface+1),noverbface+nse); //hexadecimal!!! outfile << str << endl; for (i = 1; i <= surfaceelp.Size(); i++) { outfile << hex << surfaceelp.Get(i).I1() << " " << hex << surfaceelp.Get(i).I2() << " " << hex << surfaceelp.Get(i).I3() << " " << hex << surfaceeli.Get(i) << " " << 0 << "\n"; } outfile << "))" << endl << endl; outfile << "(0 \"Cells:\")" << endl; sprintf(str,"(12 (0 1 %x 0))",ne); //hexadecimal!!! outfile << str << endl; sprintf(str,"(12 (1 1 %x 1 2))",ne); //hexadecimal!!! outfile << str << endl << endl; outfile << "(0 \"Zones:\")\n" << "(45 (1 fluid fluid)())\n" // << "(45 (2 velocity-inlet velocity_inlet.1)())\n" // << "(45 (3 pressure-outlet pressure_outlet.2)())\n" << "(45 (2 wall wall)())\n" << "(45 (4 interior default-interior)())\n" << endl; cout << "done" << endl; } } netgen-6.2.1905/libsrc/interface/writeuser.hpp0000644000175000017500000001076413504650527017771 0ustar kurtkurt#ifndef WRITEUSER #define WRITEUSER /**************************************************************************/ /* File: writeuser.hh */ /* Authors: many */ /* Date: 10. Dec. 97 */ /**************************************************************************/ namespace netgen { DLL_HEADER extern void WriteFile (int typ, const Mesh & mesh, const NetgenGeometry & geom, const char * filename, const char * geomfile = NULL, double h = 0); DLL_HEADER extern void ReadFile (Mesh & mesh, const string & filename); extern void WriteNeutralFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); extern void WriteSurfaceFormat (const Mesh & mesh, const string & filename); extern void WriteSTLFormat (const Mesh & mesh, const string & filename); // Philippose - 16 August 2010 // Added the STL Extended format in which // each face of the geometry is treated as // a separate "solid" entity in the STL file extern void WriteSTLExtFormat (const Mesh & mesh, const string & filename); extern void WriteVRMLFormat (const Mesh & mesh, bool faces, const string & filename); extern void WriteFEPPFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); extern void WriteGmshFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); // Philippose - 29/01/2009 // Added GMSH v2.xx Mesh Export support void WriteGmsh2Format (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); // Philippose - 25/10/2009 // Added OpenFOAM 1.5+ Mesh Export support extern void WriteOpenFOAM15xFormat (const Mesh & mesh, const string & casename, const bool compressed); extern void WriteUserChemnitz (const Mesh & mesh, const string & filename); extern void WriteJCMFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); extern void WriteDiffPackFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); extern void WriteTochnogFormat (const Mesh & mesh, const string & filename); extern void WriteTecPlotFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); extern void WriteAbaqusFormat (const Mesh & mesh, const string & filename); extern void WriteFluentFormat (const Mesh & mesh, const string & filename); extern void WritePermasFormat (const Mesh & mesh, const string & filename); extern void WriteFEAPFormat (const Mesh & mesh, const string & filename); extern void WriteElmerFormat (const Mesh & mesh, const string & filename); extern void WriteEdgeElementFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename); #ifdef OLIVER extern void WriteTETFormat (const Mesh & mesh, const string & filename); #endif extern void ReadTETFormat (Mesh & mesh, const string & filename); extern void ReadFNFFormat (Mesh & mesh, const string & filename); void WriteDolfinFormat (const Mesh & mesh, const string & filename); extern void DLL_HEADER RegisterUserFormats (Array & names, Array & extensions); extern bool DLL_HEADER WriteUserFormat (const string & format, const Mesh & mesh, // const NetgenGeometry & geom, const string & filename); } #endif netgen-6.2.1905/libsrc/interface/writetochnog.cpp0000644000175000017500000000420713504650527020442 0ustar kurtkurt// // Write Tochnog file // // by // // Andreas Seltmann // email: A.Seltmann@lsw.uni-heidelberg.de // #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteTochnogFormat (const Mesh & mesh, const string & filename) { cout << "\nWrite Tochnog Volume Mesh" << endl; ofstream outfile (filename.c_str()); outfile << "(Nodes and Elements generated with NETGEN" << endl; outfile << " " << filename << ")" << endl; outfile.precision(8); outfile << "(Nodes)" << endl; int np = mesh.GetNP(); int ne = mesh.GetNE(); int i, j; for (i = 1; i <= np; i++) { outfile << "node " << " " << i << " "; outfile << mesh.Point(i)(0) << " "; outfile << mesh.Point(i)(1) << " "; outfile << mesh.Point(i)(2) << "\n"; } int elemcnt = 0; //element counter int finished = 0; int indcnt = 1; //index counter while (!finished) { int actcnt = 0; const Element & el1 = mesh.VolumeElement(1); int non = el1.GetNP(); if (non == 4) { outfile << "(Elements, type=-tet4)" << endl; } else { cout << "unsupported Element type!!!" << endl; } for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); if (el.GetIndex() == indcnt) { actcnt++; if (el.GetNP() != non) { cout << "different element-types in a subdomain are not possible!!!" << endl; continue; } elemcnt++; outfile << "element " << elemcnt << " -tet4 "; if (non == 4) { outfile << el.PNum(1) << " "; outfile << el.PNum(2) << " "; outfile << el.PNum(4) << " "; outfile << el.PNum(3) << "\n"; } else { cout << "unsupported Element type!!!" << endl; for (j = 1; j <= el.GetNP(); j++) { outfile << el.PNum(j); if (j != el.GetNP()) outfile << ", "; } outfile << "\n"; } } } indcnt++; if (elemcnt == ne) {finished = 1; cout << "all elements found by Index!" << endl;} if (actcnt == 0) {finished = 1;} } cout << "done" << endl; } } netgen-6.2.1905/libsrc/interface/nginterface.cpp0000644000175000017500000014043213504650527020214 0ustar kurtkurt#include #include #include #include #ifdef SOCKETS #include "../sockets/sockets.hpp" #endif #include "nginterface.h" // #include "../visualization/soldata.hpp" // #include namespace netgen { DLL_HEADER MeshingParameters mparam; /** Force linking of geom2d library (for SplineGeometryRegister)**/ SplineGeometry2d dummy_2dgeom; } static std::thread meshingthread; void RunParallel ( void * (*fun)(void *), void * in) { bool parthread = netgen::mparam.parthread; #ifdef PARALLEL int provided; MPI_Query_thread(&provided); if (provided < 3) if (netgen::ntasks > 1) parthread = false; // cout << "runparallel = " << parthread << endl; #endif if (parthread) { meshingthread = std::thread(fun, in); meshingthread.detach(); } else fun (in); } #include "writeuser.hpp" namespace netgen { extern shared_ptr mesh; extern shared_ptr ng_geometry; extern Tcl_Interp * tcl_interp; #ifdef SOCKETS extern AutoPtr clientsocket; //extern Array< AutoPtr < ServerInfo > > servers; extern Array< ServerInfo* > servers; #endif } using namespace netgen; void Ng_LoadGeometry (const char * filename) { // he: if filename is empty, return // can be used to reset geometry if (!filename || strcmp(filename,"")==0) { ng_geometry.reset (new NetgenGeometry()); return; } for (int i = 0; i < geometryregister.Size(); i++) { NetgenGeometry * hgeom = geometryregister[i]->Load (filename); if (hgeom) { ng_geometry.reset (hgeom); mesh.reset(); return; } } // if (id == 0) cerr << "cannot load geometry '" << filename << "'" << ", id = " << id << endl; } void Ng_LoadMeshFromStream ( istream & input ) { mesh.reset (new Mesh()); mesh -> Load(input); SetGlobalMesh (mesh); for (int i = 0; i < geometryregister.Size(); i++) { NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (input); if (hgeom) { ng_geometry.reset (hgeom); break; } } if (!ng_geometry) ng_geometry = make_shared(); mesh->SetGeometry (ng_geometry); } void Ng_LoadMesh (const char * filename, ngcore::NgMPI_Comm comm) { int id = comm.Rank(); int ntasks = comm.Size(); { ifstream infile(filename); if(!infile.good()) throw NgException(string("Error opening file ") + filename); } if ( string(filename).find(".vol") == string::npos ) { if(ntasks>1) throw NgException("Not sure what to do with this?? Does this work with MPI??"); mesh.reset (new Mesh()); mesh->SetCommunicator(comm); ReadFile(*mesh,filename); //mesh->SetGlobalH (mparam.maxh); //mesh->CalcLocalH(); return; } istream * infile; Array buf; // for distributing geometry! int strs; if( id == 0) { string fn(filename); if (fn.substr (fn.length()-3, 3) == ".gz") infile = new igzstream (filename); else infile = new ifstream (filename); mesh.reset (new Mesh()); mesh->SetCommunicator(comm); mesh -> Load(*infile); SetGlobalMesh (mesh); // make string from rest of file (for geometry info!) // (this might be empty, in which case we take the global ng_geometry) stringstream geom_part; geom_part << infile->rdbuf(); string geom_part_string = geom_part.str(); strs = geom_part_string.size(); // buf = new char[strs]; buf.SetSize(strs); memcpy(&buf[0], geom_part_string.c_str(), strs*sizeof(char)); delete infile; if (ntasks > 1) { char * weightsfilename = new char [strlen(filename)+1]; strcpy (weightsfilename, filename); weightsfilename[strlen (weightsfilename)-3] = 'w'; weightsfilename[strlen (weightsfilename)-2] = 'e'; weightsfilename[strlen (weightsfilename)-1] = 'i'; ifstream weightsfile(weightsfilename); delete [] weightsfilename; if (!(weightsfile.good())) { // cout << "regular distribute" << endl; mesh -> Distribute(); } else { char str[20]; bool endfile = false; int n, dummy; Array segment_weights; Array surface_weights; Array volume_weights; while (weightsfile.good() && !endfile) { weightsfile >> str; if (strcmp (str, "edgeweights") == 0) { weightsfile >> n; segment_weights.SetSize(n); for (int i = 0; i < n; i++) weightsfile >> dummy >> segment_weights[i]; } if (strcmp (str, "surfaceweights") == 0) { weightsfile >> n; surface_weights.SetSize(n); for (int i=0; i> dummy >> surface_weights[i]; } if (strcmp (str, "volumeweights") == 0) { weightsfile >> n; volume_weights.SetSize(n); for (int i=0; i> dummy >> volume_weights[i]; } if (strcmp (str, "endfile") == 0) endfile = true; } mesh -> Distribute(volume_weights, surface_weights, segment_weights); } } // ntasks>1 end } // id==0 end else { mesh.reset (new Mesh()); mesh->SetCommunicator(comm); SetGlobalMesh (mesh); mesh->SendRecvMesh(); } if(ntasks>1) { #ifdef PARALLEL /** Scatter the geometry-string (no dummy-implementation in mpi_interface) **/ int strs = buf.Size(); MyMPI_Bcast(strs, comm); if(strs>0) MyMPI_Bcast(buf, comm); #endif } shared_ptr geo; if(buf.Size()) { // if we had geom-info in the file, take it istringstream geom_infile(string((const char*)&buf[0], buf.Size())); geo = geometryregister.LoadFromMeshFile(geom_infile); } if(geo!=nullptr) { ng_geometry = geo; mesh->SetGeometry(geo); } else if(ng_geometry!=nullptr) mesh->SetGeometry(ng_geometry); } void Ng_LoadMeshFromString (const char * mesh_as_string) { istringstream instream(mesh_as_string); Ng_LoadMeshFromStream(instream); } int Ng_GetDimension () { return (mesh) ? mesh->GetDimension() : -1; } int Ng_GetNP () { return (mesh) ? mesh->GetNP() : 0; } int Ng_GetNV () { return (mesh) ? mesh->GetNV() : 0; } int Ng_GetNE () { if(!mesh) return 0; if (mesh->GetDimension() == 3) return mesh->GetNE(); else return mesh->GetNSE(); } int Ng_GetNSE () { if(!mesh) return 0; if (mesh->GetDimension() == 3) return mesh->GetNSE(); else return mesh->GetNSeg(); } void Ng_GetPoint (int pi, double * p) { if (pi < 1 || pi > mesh->GetNP()) { if (printmessage_importance>0) cout << "Ng_GetPoint: illegal point " << pi << endl; return; } const Point3d & hp = mesh->Point (pi); p[0] = hp.X(); p[1] = hp.Y(); if (mesh->GetDimension() == 3) p[2] = hp.Z(); } NG_ELEMENT_TYPE Ng_GetElement (int ei, int * epi, int * np) { if (mesh->GetDimension() == 3) { int i; const Element & el = mesh->VolumeElement (ei); for (i = 0; i < el.GetNP(); i++) epi[i] = el.PNum(i+1); if (np) *np = el.GetNP(); if (el.GetType() == PRISM) { // degenerated prism, (should be obsolete) const int map1[] = { 3, 2, 5, 6, 1 }; const int map2[] = { 1, 3, 6, 4, 2 }; const int map3[] = { 2, 1, 4, 5, 3 }; const int * map = NULL; int deg1 = 0, deg2 = 0, deg3 = 0; //int deg = 0; if (el.PNum(1) == el.PNum(4)) { map = map1; deg1 = 1; } if (el.PNum(2) == el.PNum(5)) { map = map2; deg2 = 1; } if (el.PNum(3) == el.PNum(6)) { map = map3; deg3 = 1; } switch (deg1+deg2+deg3) { { case 1: if (printmessage_importance>0) cout << "degenerated prism found, deg = 1" << endl; for (i = 0; i < 5; i++) epi[i] = el.PNum (map[i]); if (np) *np = 5; return NG_PYRAMID; break; } case 2: { if (printmessage_importance>0) cout << "degenerated prism found, deg = 2" << endl; if (!deg1) epi[3] = el.PNum(4); if (!deg2) epi[3] = el.PNum(5); if (!deg3) epi[3] = el.PNum(6); if (np) *np = 4; return NG_TET; break; } default: ; } } return NG_ELEMENT_TYPE (el.GetType()); } else { const Element2d & el = mesh->SurfaceElement (ei); for (int i = 0; i < el.GetNP(); i++) epi[i] = el.PNum(i+1); if (np) *np = el.GetNP(); return NG_ELEMENT_TYPE (el.GetType()); } // should not occur return NG_TET; } NG_ELEMENT_TYPE Ng_GetElementType (int ei) { if (mesh->GetDimension() == 3) { return NG_ELEMENT_TYPE (mesh->VolumeElement (ei).GetType()); } else { const Element2d & el = mesh->SurfaceElement (ei); switch (el.GetNP()) { case 3: return NG_TRIG; case 4: return NG_QUAD; case 6: return NG_TRIG6; } } // should not occur return NG_TET; } int Ng_GetElementIndex (int ei) { if (mesh->GetDimension() == 3) return mesh->VolumeElement(ei).GetIndex(); else { int ind = mesh->SurfaceElement(ei).GetIndex(); ind = mesh->GetFaceDescriptor(ind).BCProperty(); return ind; } } void Ng_SetElementIndex(const int ei, const int index) { mesh->VolumeElement(ei).SetIndex(index); } const char * Ng_GetElementMaterial (int ei) { static char empty[] = ""; if (mesh->GetDimension() == 3) { int ind = mesh->VolumeElement(ei).GetIndex(); // cout << "ind = " << ind << endl; const string * mat = mesh->GetMaterialPtr (ind); if (mat) // return const_cast (mat); return mat->c_str(); else return empty; } // add astrid else { int ind = mesh->SurfaceElement(ei).GetIndex(); ind = mesh->GetFaceDescriptor(ind).BCProperty(); const string * mat = mesh->GetMaterialPtr ( ind ); if (mat) return mat->c_str(); else return empty; } return 0; } const char * Ng_GetDomainMaterial (int dom) { static char empty[] = ""; // astrid if ( 1 ) // mesh->GetDimension() == 3) { const string * mat = mesh->GetMaterialPtr(dom); if (mat) return mat->c_str(); else return empty; } return 0; } int Ng_GetUserDataSize (char * id) { Array da; mesh->GetUserData (id, da); return da.Size(); } void Ng_GetUserData (char * id, double * data) { Array da; mesh->GetUserData (id, da); for (int i = 0; i < da.Size(); i++) data[i] = da[i]; } NG_ELEMENT_TYPE Ng_GetSurfaceElement (int ei, int * epi, int * np) { if (mesh->GetDimension() == 3) { const Element2d & el = mesh->SurfaceElement (ei); for (int i = 0; i < el.GetNP(); i++) epi[i] = el[i]; if (np) *np = el.GetNP(); return NG_ELEMENT_TYPE (el.GetType()); } else { const Segment & seg = mesh->LineSegment (ei); if (seg[2] < 0) { epi[0] = seg[0]; epi[1] = seg[1]; if (np) *np = 2; return NG_SEGM; } else { epi[0] = seg[0]; epi[1] = seg[1]; epi[2] = seg[2]; if (np) *np = 3; return NG_SEGM3; } } return NG_TRIG; } int Ng_GetSurfaceElementIndex (int ei) { if (mesh->GetDimension() == 3) return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).BCProperty(); else return mesh->LineSegment(ei).si; } int Ng_GetSurfaceElementSurfaceNumber (int ei) { if (mesh->GetDimension() == 3) return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).SurfNr(); else return mesh->LineSegment(ei).si; } int Ng_GetSurfaceElementFDNumber (int ei) { if (mesh->GetDimension() == 3) return mesh->SurfaceElement(ei).GetIndex(); else return -1; } char * Ng_GetSurfaceElementBCName (int ei) { if ( mesh->GetDimension() == 3 ) return const_cast(mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).GetBCName().c_str()); else return const_cast(mesh->LineSegment(ei).GetBCName().c_str()); } // Inefficient (but maybe safer) version: //void Ng_GetSurfaceElementBCName (int ei, char * name) //{ // if ( mesh->GetDimension() == 3 ) // strcpy(name,mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).GetBCName().c_str()); // else // strcpy(name,mesh->LineSegment(ei).GetBCName().c_str()); //} char * Ng_GetBCNumBCName (int bcnr) { return const_cast(mesh->GetBCName(bcnr).c_str()); } char * Ng_GetCD2NumCD2Name (int cd2nr) { return const_cast(mesh->GetCD2Name(cd2nr).c_str()); } // Inefficient (but maybe safer) version: //void Ng_GetBCNumBCName (int bcnr, char * name) //{ // strcpy(name,mesh->GetBCName(bcnr).c_str()); //} /* void Ng_GetNormalVector (int sei, int locpi, double * nv) { nv[0] = 0; nv[1] = 0; nv[2] = 1; if (mesh->GetDimension() == 3) { Vec<3> n; Point<3> p; p = mesh->Point (mesh->SurfaceElement(sei).PNum(locpi)); int surfi = mesh->GetFaceDescriptor(mesh->SurfaceElement(sei).GetIndex()).SurfNr(); (*testout) << "surfi = " << surfi << endl; #ifdef OCCGEOMETRYxxx OCCGeometry * occgeometry = dynamic_cast (ng_geometry); if (occgeometry) { PointGeomInfo gi = mesh->SurfaceElement(sei).GeomInfoPi(locpi); occgeometry->GetSurface (surfi).GetNormalVector(p, gi, n); nv[0] = n(0); nv[1] = n(1); nv[2] = n(2); } #endif CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (geometry) { n = geometry->GetSurface (surfi) -> GetNormalVector(p); nv[0] = n(0); nv[1] = n(1); nv[2] = n(2); } } } */ void Ng_SetPointSearchStartElement(const int el) { mesh->SetPointSearchStartElement(el); } int Ng_FindElementOfPoint (double * p, double * lami, int build_searchtree, const int * const indices, const int numind) { Array * dummy(NULL); int ind = -1; if(indices != NULL) { dummy = new Array(numind); for(int i=0; iGetDimension() == 3) { Point3d p3d(p[0], p[1], p[2]); ind = mesh->GetElementOfPoint(p3d, lami, dummy, build_searchtree != 0); } else { double lam3[3]; Point3d p2d(p[0], p[1], 0); ind = mesh->GetElementOfPoint(p2d, lam3, dummy, build_searchtree != 0); if (ind > 0) { if(mesh->SurfaceElement(ind).GetType()==QUAD) { lami[0] = lam3[0]; lami[1] = lam3[1]; } else { lami[0] = 1-lam3[0]-lam3[1]; lami[1] = lam3[0]; } } } delete dummy; return ind; } int Ng_FindSurfaceElementOfPoint (double * p, double * lami, int build_searchtree, const int * const indices, const int numind) { Array * dummy(NULL); int ind = -1; if(indices != NULL) { dummy = new Array(numind); for(int i=0; iGetDimension() == 3) { Point3d p3d(p[0], p[1], p[2]); ind = mesh->GetSurfaceElementOfPoint(p3d, lami, dummy, build_searchtree != 0); } else { //throw NgException("FindSurfaceElementOfPoint for 2D meshes not yet implemented"); cerr << "FindSurfaceElementOfPoint for 2D meshes not yet implemented" << endl; } delete dummy; return ind; } int Ng_IsElementCurved (int ei) { switch (mesh->GetDimension()) { case 1: return mesh->GetCurvedElements().IsSegmentCurved (ei-1); case 2: return mesh->GetCurvedElements().IsSurfaceElementCurved (ei-1); case 3: return mesh->GetCurvedElements().IsElementCurved (ei-1); } return 0; /* if (mesh->GetDimension() == 2) return mesh->GetCurvedElements().IsSurfaceElementCurved (ei-1); else return mesh->GetCurvedElements().IsElementCurved (ei-1); */ } int Ng_IsSurfaceElementCurved (int sei) { if (mesh->GetDimension() == 2) return mesh->GetCurvedElements().IsSegmentCurved (sei-1); else return mesh->GetCurvedElements().IsSurfaceElementCurved (sei-1); } void Ng_GetElementTransformation (int ei, const double * xi, double * x, double * dxdxi) { if (mesh->GetDimension() == 2) { Point<2> xl(xi[0], xi[1]); Point<3> xg; Mat<3,2> dx; mesh->GetCurvedElements().CalcSurfaceTransformation (xl, ei-1, xg, dx); if (x) { for (int i = 0; i < 2; i++) x[i] = xg(i); } if (dxdxi) { for (int i=0; i<2; i++) { dxdxi[2*i] = dx(i,0); dxdxi[2*i+1] = dx(i,1); } } } else { Point<3> xl(xi[0], xi[1], xi[2]); Point<3> xg; Mat<3,3> dx; mesh->GetCurvedElements().CalcElementTransformation (xl, ei-1, xg, dx); if (x) { for (int i = 0; i < 3; i++) x[i] = xg(i); } if (dxdxi) { for (int i=0; i<3; i++) { dxdxi[3*i] = dx(i,0); dxdxi[3*i+1] = dx(i,1); dxdxi[3*i+2] = dx(i,2); } } } } void Ng_GetMultiElementTransformation (int ei, int n, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi) { if (mesh->GetDimension() == 2) mesh->GetCurvedElements().CalcMultiPointSurfaceTransformation<2> (ei-1, n, xi, sxi, x, sx, dxdxi, sdxdxi); else mesh->GetCurvedElements().CalcMultiPointElementTransformation (ei-1, n, xi, sxi, x, sx, dxdxi, sdxdxi); } void Ng_GetSurfaceElementTransformation (int sei, const double * xi, double * x, double * dxdxi) { if (mesh->GetDimension() == 2) { Point<3> xg; Vec<3> dx; mesh->GetCurvedElements().CalcSegmentTransformation (xi[0], sei-1, xg, dx); if (x) for (int i = 0; i < 2; i++) x[i] = xg(i); if (dxdxi) for (int i=0; i<2; i++) dxdxi[i] = dx(i); } else { Point<2> xl(xi[0], xi[1]); Point<3> xg; Mat<3,2> dx; mesh->GetCurvedElements().CalcSurfaceTransformation (xl, sei-1, xg, dx); for (int i=0; i<3; i++) { if (x) x[i] = xg(i); if (dxdxi) { dxdxi[2*i] = dx(i,0); dxdxi[2*i+1] = dx(i,1); } } } } int Ng_GetSegmentIndex (int ei) { const Segment & seg = mesh->LineSegment (ei); return seg.edgenr; } NG_ELEMENT_TYPE Ng_GetSegment (int ei, int * epi, int * np) { const Segment & seg = mesh->LineSegment (ei); epi[0] = seg[0]; epi[1] = seg[1]; if (seg[2] < 0) { if (np) *np = 2; return NG_SEGM; } else { epi[2] = seg[2]; if (np) *np = 3; return NG_SEGM3; } } void Ng_GetSurfaceElementNeighbouringDomains(const int selnr, int & in, int & out) { if ( mesh->GetDimension() == 3 ) { in = mesh->GetFaceDescriptor(mesh->SurfaceElement(selnr).GetIndex()).DomainIn(); out = mesh->GetFaceDescriptor(mesh->SurfaceElement(selnr).GetIndex()).DomainOut(); } else { in = mesh -> LineSegment(selnr) . domin; out = mesh -> LineSegment(selnr) . domout; } } #ifdef PARALLEL // gibt anzahl an distant pnums zurueck // * pnums entspricht ARRAY int NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * distnums ) { int size = NgPar_GetNDistantNodeNums (nodetype, locnum); locnum++; switch ( nodetype ) { case 0: mesh->GetParallelTopology().GetDistantPNums( locnum, distnums ); break; case 1: mesh->GetParallelTopology().GetDistantEdgeNums( locnum, distnums ); break; case 2: mesh->GetParallelTopology().GetDistantFaceNums( locnum, distnums ); break; case 3: // mesh->GetParallelTopology().GetDistantElNums( locnum, distnums ); break; default: cerr << "NgPar_GetDistantNodeNums() Unknown nodetype " << nodetype << endl; size = -1; } return size; } int NgPar_GetNDistantNodeNums ( int nodetype, int locnum ) { locnum++; switch ( nodetype ) { case 0: return mesh->GetParallelTopology().GetNDistantPNums (locnum); case 1: return mesh->GetParallelTopology().GetNDistantEdgeNums (locnum); case 2: return mesh->GetParallelTopology().GetNDistantFaceNums(locnum ); case 3: return 0; } return -1; } int NgPar_GetGlobalNodeNum (int nodetype, int locnum) { locnum++; switch (nodetype) { case 0: return mesh->GetParallelTopology().GetGlobalPNum (locnum)-1; case 1: return mesh->GetParallelTopology().GetGlobalEdgeNum (locnum)-1; case 2: return mesh->GetParallelTopology().GetGlobalFaceNum (locnum)-1; case 3: return mesh->GetParallelTopology().GetGlobalElNum (locnum)-1; } return -1; } #endif void Ng_SetRefinementFlag (int ei, int flag) { if (mesh->GetDimension() == 3) { mesh->VolumeElement(ei).SetRefinementFlag (flag != 0); mesh->VolumeElement(ei).SetStrongRefinementFlag (flag >= 10); } else { mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0); mesh->SurfaceElement(ei).SetStrongRefinementFlag (flag >= 10); } } void Ng_SetSurfaceRefinementFlag (int ei, int flag) { if (mesh->GetDimension() == 3) { mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0); mesh->SurfaceElement(ei).SetStrongRefinementFlag (flag >= 10); } } void Ng_Refine (NG_REFINEMENT_TYPE reftype) { NgLock meshlock (mesh->MajorMutex(), 1); BisectionOptions biopt; biopt.usemarkedelements = 1; biopt.refine_p = 0; biopt.refine_hp = 0; if (reftype == NG_REFINE_P) biopt.refine_p = 1; if (reftype == NG_REFINE_HP) biopt.refine_hp = 1; const Refinement & ref = mesh->GetGeometry()->GetRefinement(); // Refinement * ref; MeshOptimize2d * opt = NULL; /* if (geometry2d) ref = new Refinement2d(*geometry2d); else if (stlgeometry) ref = new RefinementSTLGeometry(*stlgeometry); #ifdef OCCGEOMETRY else if (occgeometry) ref = new OCCRefinementSurfaces (*occgeometry); #endif #ifdef ACIS else if (acisgeometry) { ref = new ACISRefinementSurfaces (*acisgeometry); opt = new ACISMeshOptimize2dSurfaces(*acisgeometry); ref->Set2dOptimizer(opt); } #endif else if (geometry && mesh->GetDimension() == 3) { ref = new RefinementSurfaces(*geometry); opt = new MeshOptimize2dSurfaces(*geometry); ref->Set2dOptimizer(opt); } else { ref = new Refinement(); } */ ref.Bisect (*mesh, biopt); mesh -> UpdateTopology(); mesh -> GetCurvedElements().SetIsHighOrder (false); // mesh -> GetCurvedElements().BuildCurvedElements (ref, mparam.elementorder); // delete ref; delete opt; } void Ng_SecondOrder () { const_cast (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder(*mesh); /* if (stlgeometry) { RefinementSTLGeometry ref (*stlgeometry); ref.MakeSecondOrder (*mesh); } else if (geometry2d) { Refinement2d ref (*geometry2d); ref.MakeSecondOrder (*mesh); } else if (geometry && mesh->GetDimension() == 3) { RefinementSurfaces ref (*geometry); ref.MakeSecondOrder (*mesh); } else { if (printmessage_importance>0) cout << "no geom" << endl; Refinement ref; ref.MakeSecondOrder (*mesh); } */ mesh -> UpdateTopology(); } /* void Ng_HPRefinement (int levels) { Refinement * ref; if (stlgeometry) ref = new RefinementSTLGeometry (*stlgeometry); else if (geometry2d) ref = new Refinement2d (*geometry2d); else ref = new RefinementSurfaces (*geometry); HPRefinement (*mesh, ref, levels); } void Ng_HPRefinement (int levels, double parameter) { Refinement * ref; if (stlgeometry) ref = new RefinementSTLGeometry (*stlgeometry); else if (geometry2d) ref = new Refinement2d (*geometry2d); else ref = new RefinementSurfaces (*geometry); HPRefinement (*mesh, ref, levels, parameter); } */ void Ng_HPRefinement (int levels, double parameter, bool setorders, bool ref_level) { NgLock meshlock (mesh->MajorMutex(), true); Refinement & ref = const_cast (mesh->GetGeometry()->GetRefinement()); HPRefinement (*mesh, &ref, levels, parameter, setorders, ref_level); /* Refinement * ref; if (stlgeometry) ref = new RefinementSTLGeometry (*stlgeometry); else if (geometry2d) ref = new Refinement2d (*geometry2d); else ref = new RefinementSurfaces (*geometry); HPRefinement (*mesh, ref, levels, parameter, setorders, ref_level); */ } void Ng_HighOrder (int order, bool rational) { NgLock meshlock (mesh->MajorMutex(), true); /* mesh -> GetCurvedElements().BuildCurvedElements (&const_cast (ng_geometry -> GetRefinement()), order, rational); */ /* if (!mesh->GetGeometry()) throw NgException ("don't have a geometry for mesh curving"); mesh->BuildCurvedElements (&const_cast (mesh->GetGeometry()->GetRefinement()), order, rational); mesh -> SetNextMajorTimeStamp(); */ mesh->BuildCurvedElements(order); } int Ng_ME_GetNVertices (NG_ELEMENT_TYPE et) { switch (et) { case NG_SEGM: case NG_SEGM3: return 2; case NG_TRIG: case NG_TRIG6: return 3; case NG_QUAD: return 4; case NG_TET: case NG_TET10: return 4; case NG_PYRAMID: return 5; case NG_PRISM: case NG_PRISM12: return 6; case NG_HEX: return 8; default: cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; } return 0; } int Ng_ME_GetNEdges (NG_ELEMENT_TYPE et) { switch (et) { case NG_SEGM: case NG_SEGM3: return 1; case NG_TRIG: case NG_TRIG6: return 3; case NG_QUAD: return 4; case NG_TET: case NG_TET10: return 6; case NG_PYRAMID: return 8; case NG_PRISM: case NG_PRISM12: return 9; case NG_HEX: return 12; default: cerr << "Ng_ME_GetNEdges, illegal element type " << et << endl; } return 0; } int Ng_ME_GetNFaces (NG_ELEMENT_TYPE et) { switch (et) { case NG_SEGM: case NG_SEGM3: return 0; case NG_TRIG: case NG_TRIG6: return 1; case NG_QUAD: case NG_QUAD6: return 1; case NG_TET: case NG_TET10: return 4; case NG_PYRAMID: return 5; case NG_PRISM: case NG_PRISM12: return 5; case NG_HEX: return 6; default: cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; } return 0; } const NG_POINT * Ng_ME_GetVertices (NG_ELEMENT_TYPE et) { static double segm_points [][3] = { { 1, 0, 0 }, { 0, 0, 0 } }; static double trig_points [][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }; static double quad_points [][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 } }; static double tet_points [][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 0, 0, 0 } }; static double pyramid_points [][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1-1e-7 }, }; static double prism_points[][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 }, { 1, 0, 1 }, { 0, 1, 1 }, { 0, 0, 1 } }; switch (et) { case NG_SEGM: case NG_SEGM3: return segm_points; case NG_TRIG: case NG_TRIG6: return trig_points; case NG_QUAD: case NG_QUAD6: return quad_points; case NG_TET: case NG_TET10: return tet_points; case NG_PYRAMID: return pyramid_points; case NG_PRISM: case NG_PRISM12: return prism_points; case NG_HEX: default: cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; } return 0; } const NG_EDGE * Ng_ME_GetEdges (NG_ELEMENT_TYPE et) { static int segm_edges[1][2] = { { 1, 2 }}; static int trig_edges[3][2] = { { 3, 1 }, { 3, 2 }, { 1, 2 }}; static int quad_edges[4][2] = { { 1, 2 }, { 4, 3 }, { 1, 4 }, { 2, 3 }}; static int tet_edges[6][2] = { { 4, 1 }, { 4, 2 }, { 4, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 }}; static int prism_edges[9][2] = { { 3, 1 }, { 1, 2 }, { 3, 2 }, { 6, 4 }, { 4, 5 }, { 6, 5 }, { 3, 6 }, { 1, 4 }, { 2, 5 }}; static int pyramid_edges[8][2] = { { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 3 }, { 1, 5 }, { 2, 5 }, { 3, 5 }, { 4, 5 }}; switch (et) { case NG_SEGM: case NG_SEGM3: return segm_edges; case NG_TRIG: case NG_TRIG6: return trig_edges; case NG_QUAD: case NG_QUAD6: return quad_edges; case NG_TET: case NG_TET10: return tet_edges; case NG_PYRAMID: return pyramid_edges; case NG_PRISM: case NG_PRISM12: return prism_edges; case NG_HEX: default: cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; } return 0; } const NG_FACE * Ng_ME_GetFaces (NG_ELEMENT_TYPE et) { static int tet_faces[4][4] = { { 4, 2, 3, 0 }, { 4, 1, 3, 0 }, { 4, 1, 2, 0 }, { 1, 2, 3, 0 } }; static int prism_faces[5][4] = { { 1, 2, 3, 0 }, { 4, 5, 6, 0 }, { 3, 1, 4, 6 }, { 1, 2, 5, 4 }, { 2, 3, 6, 5 } }; static int pyramid_faces[5][4] = { { 1, 2, 5, 0 }, { 2, 3, 5, 0 }, { 3, 4, 5, 0 }, { 4, 1, 5, 0 }, { 1, 2, 3, 4 } }; static int trig_faces[1][4] = { { 1, 2, 3, 0 }, }; switch (et) { case NG_TET: case NG_TET10: return tet_faces; case NG_PRISM: case NG_PRISM12: return prism_faces; case NG_PYRAMID: return pyramid_faces; case NG_SEGM: case NG_SEGM3: case NG_TRIG: case NG_TRIG6: return trig_faces; case NG_QUAD: case NG_HEX: default: cerr << "Ng_ME_GetFaces, illegal element type " << et << endl; } return 0; } void Ng_UpdateTopology() { if (mesh) mesh -> UpdateTopology(); } Ng_Mesh Ng_SelectMesh (Ng_Mesh newmesh) { Mesh * hmesh = mesh.get(); mesh.reset((Mesh*)newmesh); return hmesh; } int Ng_GetNEdges() { return mesh->GetTopology().GetNEdges(); } int Ng_GetNFaces() { return mesh->GetTopology().GetNFaces(); } int Ng_GetElement_Edges (int elnr, int * edges, int * orient) { const MeshTopology & topology = mesh->GetTopology(); if (mesh->GetDimension() == 3) return topology.GetElementEdges (elnr, edges, orient); else return topology.GetSurfaceElementEdges (elnr, edges, orient); } int Ng_GetElement_Faces (int elnr, int * faces, int * orient) { const MeshTopology & topology = mesh->GetTopology(); if (mesh->GetDimension() == 3) return topology.GetElementFaces (elnr, faces, orient); else { faces[0] = elnr; if (orient) orient[0] = 0; return 1; } } int Ng_GetSurfaceElement_Edges (int elnr, int * edges, int * orient) { const MeshTopology & topology = mesh->GetTopology(); if (mesh->GetDimension() == 3) return topology.GetSurfaceElementEdges (elnr, edges, orient); else { if (orient) topology.GetSegmentEdge(elnr, edges[0], orient[0]); else edges[0] = topology.GetSegmentEdge(elnr); } return 1; /* int i, ned; const MeshTopology & topology = mesh->GetTopology(); Array ia; topology.GetSurfaceElementEdges (elnr, ia); ned = ia.Size(); for (i = 1; i <= ned; i++) edges[i-1] = ia.Get(i); if (orient) { topology.GetSurfaceElementEdgeOrientations (elnr, ia); for (i = 1; i <= ned; i++) orient[i-1] = ia.Get(i); } return ned; */ } int Ng_GetSurfaceElement_Face (int selnr, int * orient) { if (mesh->GetDimension() == 3) { const MeshTopology & topology = mesh->GetTopology(); if (orient) *orient = topology.GetSurfaceElementFaceOrientation (selnr); return topology.GetSurfaceElementFace (selnr); } return -1; } int Ng_GetFace_Vertices (int fnr, int * vert) { const MeshTopology & topology = mesh->GetTopology(); ArrayMem ia; topology.GetFaceVertices (fnr, ia); for (int i = 0; i < ia.Size(); i++) vert[i] = ia[i]; // cout << "face verts = " << ia << endl; return ia.Size(); } int Ng_GetFace_Edges (int fnr, int * edge) { const MeshTopology & topology = mesh->GetTopology(); ArrayMem ia; topology.GetFaceEdges (fnr, ia); for (int i = 0; i < ia.Size(); i++) edge[i] = ia[i]; return ia.Size(); } void Ng_GetEdge_Vertices (int ednr, int * vert) { const MeshTopology & topology = mesh->GetTopology(); topology.GetEdgeVertices (ednr, vert[0], vert[1]); } int Ng_GetNVertexElements (int vnr) { switch (mesh->GetDimension()) { case 3: return mesh->GetTopology().GetVertexElements(vnr).Size(); case 2: return mesh->GetTopology().GetVertexSurfaceElements(vnr).Size(); case 1: return mesh->GetTopology().GetVertexSegments(vnr).Size(); /* { int cnt = 0; for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++) if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) cnt++; return cnt; } */ default: cerr << "error: mesh->GetDimension() gives " << mesh->GetDimension() << endl; return 0; } } void Ng_GetVertexElements (int vnr, int * els) { switch (mesh->GetDimension()) { case 3: { FlatArray ia = mesh->GetTopology().GetVertexElements(vnr); for (int i = 0; i < ia.Size(); i++) els[i] = ia[i]+1; break; } case 2: { FlatArray ia = mesh->GetTopology().GetVertexSurfaceElements(vnr); for (int i = 0; i < ia.Size(); i++) els[i] = ia[i]+1; break; } case 1: { FlatArray ia = mesh->GetTopology().GetVertexSegments(vnr); for (int i = 0; i < ia.Size(); i++) els[i] = ia[i]+1; break; /* int cnt = 0; for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++) if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) els[cnt++] = i+1; break; */ } } } int Ng_GetElementOrder (int enr) { if (mesh->GetDimension() == 3) return mesh->VolumeElement(enr).GetOrder(); else return mesh->SurfaceElement(enr).GetOrder(); } void Ng_GetElementOrders (int enr, int * ox, int * oy, int * oz) { if (mesh->GetDimension() == 3) mesh->VolumeElement(enr).GetOrder(*ox, *oy, *oz); else mesh->SurfaceElement(enr).GetOrder(*ox, *oy, *oz); } void Ng_SetElementOrder (int enr, int order) { if (mesh->GetDimension() == 3) return mesh->VolumeElement(enr).SetOrder(order); else return mesh->SurfaceElement(enr).SetOrder(order); } void Ng_SetElementOrders (int enr, int ox, int oy, int oz) { if (mesh->GetDimension() == 3) mesh->VolumeElement(enr).SetOrder(ox, oy, oz); else mesh->SurfaceElement(enr).SetOrder(ox, oy); } int Ng_GetSurfaceElementOrder (int enr) { return mesh->SurfaceElement(enr).GetOrder(); } //HERBERT: falsche Anzahl von Argumenten //void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy, int * oz) void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy) { int d; mesh->SurfaceElement(enr).GetOrder(*ox, *oy, d); } void Ng_SetSurfaceElementOrder (int enr, int order) { return mesh->SurfaceElement(enr).SetOrder(order); } void Ng_SetSurfaceElementOrders (int enr, int ox, int oy) { mesh->SurfaceElement(enr).SetOrder(ox, oy); } int Ng_GetNLevels () { return (mesh) ? mesh->mglevels : 0; } void Ng_GetParentNodes (int ni, int * parents) { if (ni <= mesh->mlbetweennodes.Size()) { parents[0] = mesh->mlbetweennodes.Get(ni).I1(); parents[1] = mesh->mlbetweennodes.Get(ni).I2(); } else parents[0] = parents[1] = 0; } int Ng_GetParentElement (int ei) { if (mesh->GetDimension() == 3) { if (ei <= mesh->mlparentelement.Size()) return mesh->mlparentelement.Get(ei); } else { if (ei <= mesh->mlparentsurfaceelement.Size()) return mesh->mlparentsurfaceelement.Get(ei); } return 0; } int Ng_GetParentSElement (int ei) { if (mesh->GetDimension() == 3) { if (ei <= mesh->mlparentsurfaceelement.Size()) return mesh->mlparentsurfaceelement.Get(ei); } else { return 0; } return 0; } int Ng_GetClusterRepVertex (int pi) { return mesh->GetClusters().GetVertexRepresentant(pi); } int Ng_GetClusterRepEdge (int pi) { return mesh->GetClusters().GetEdgeRepresentant(pi); } int Ng_GetClusterRepFace (int pi) { return mesh->GetClusters().GetFaceRepresentant(pi); } int Ng_GetClusterRepElement (int pi) { return mesh->GetClusters().GetElementRepresentant(pi); } int Ng_GetNPeriodicVertices (int idnr) { Array apairs; mesh->GetIdentifications().GetPairs (idnr, apairs); return apairs.Size(); } // pairs should be an integer array of 2*npairs void Ng_GetPeriodicVertices (int idnr, int * pairs) { Array apairs; mesh->GetIdentifications().GetPairs (idnr, apairs); for (int i = 0; i < apairs.Size(); i++) { pairs[2*i] = apairs[i].I1(); pairs[2*i+1] = apairs[i].I2(); } } int Ng_GetNPeriodicEdges (int idnr) { Array map; //const MeshTopology & top = mesh->GetTopology(); int nse = mesh->GetNSeg(); int cnt = 0; // for (int id = 1; id <= mesh->GetIdentifications().GetMaxNr(); id++) { mesh->GetIdentifications().GetMap(idnr, map); //(*testout) << "ident-map " << id << ":" << endl << map << endl; for (SegmentIndex si = 0; si < nse; si++) { PointIndex other1 = PointIndex (map[(*mesh)[si][0]]); PointIndex other2 = PointIndex (map[(*mesh)[si][1]]); // (*testout) << "seg = " << (*mesh)[si] << "; other = " // << other1 << "-" << other2 << endl; if (other1 && other2 && mesh->IsSegment (other1, other2)) { cnt++; } } } return cnt; } void Ng_GetPeriodicEdges (int idnr, int * pairs) { Array map; const MeshTopology & top = mesh->GetTopology(); int nse = mesh->GetNSeg(); int cnt = 0; // for (int id = 1; id <= mesh->GetIdentifications().GetMaxNr(); id++) { mesh->GetIdentifications().GetMap(idnr, map); //(*testout) << "map = " << map << endl; for (SegmentIndex si = 0; si < nse; si++) { PointIndex other1 = PointIndex (map[(*mesh)[si][0]]); PointIndex other2 = PointIndex (map[(*mesh)[si][1]]); if (other1 && other2 && mesh->IsSegment (other1, other2)) { SegmentIndex otherseg = mesh->SegmentNr (other1, other2); pairs[cnt++] = top.GetSegmentEdge (si+1); pairs[cnt++] = top.GetSegmentEdge (otherseg+1); } } } } void Ng_PushStatus (const char * str) { PushStatus (MyStr (str)); } void Ng_PopStatus () { PopStatus (); } void Ng_SetThreadPercentage (double percent) { SetThreadPercent (percent); } void Ng_GetStatus (char ** str, double & percent) { MyStr s; GetStatus(s,percent); *str = new char[s.Length()+1]; strcpy(*str,s.c_str()); } void Ng_SetTerminate(void) { multithread.terminate = 1; } void Ng_UnSetTerminate(void) { multithread.terminate = 0; } int Ng_ShouldTerminate(void) { return multithread.terminate; } void Ng_SetRunning(int flag) { multithread.running = flag; } int Ng_IsRunning() { return multithread.running; } ///// Added by Roman Stainko .... int Ng_GetVertex_Elements( int vnr, int* elems ) { const MeshTopology& topology = mesh->GetTopology(); ArrayMem indexArray; topology.GetVertexElements( vnr, indexArray ); for( int i=0; iGetDimension()) { case 3: { const MeshTopology& topology = mesh->GetTopology(); ArrayMem indexArray; topology.GetVertexSurfaceElements( vnr, indexArray ); for( int i=0; iGetNSeg(); i++) if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) elems[cnt++] = i+1; return cnt; } case 1: { int cnt = 0; for (int i = 0; i < mesh->pointelements.Size(); i++) if (mesh->pointelements[i].pnum == vnr) elems[cnt++] = i+1; return cnt; } } return 0; } ///// Added by Roman Stainko .... int Ng_GetVertex_NElements( int vnr ) { const MeshTopology& topology = mesh->GetTopology(); ArrayMem indexArray; topology.GetVertexElements( vnr, indexArray ); return indexArray.Size(); } ///// Added by Roman Stainko .... int Ng_GetVertex_NSurfaceElements( int vnr ) { switch (mesh->GetDimension()) { case 3: { const MeshTopology& topology = mesh->GetTopology(); ArrayMem indexArray; topology.GetVertexSurfaceElements( vnr, indexArray ); return indexArray.Size(); } case 2: { int cnt = 0; for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++) if ( ((*mesh)[i][0] == vnr) || ((*mesh)[i][1] == vnr) ) cnt++; return cnt; } } return 0; } #ifdef SOCKETS int Ng_SocketClientOpen( const int port, const char * host ) { try { if(host) clientsocket.Reset(new ClientSocket(port,host)); else clientsocket.Reset(new ClientSocket(port)); } catch( SocketException e) { cerr << e.Description() << endl; return 0; } return 1; } void Ng_SocketClientWrite( const char * write, char** reply) { string output = write; (*clientsocket) << output; string sreply; (*clientsocket) >> sreply; *reply = new char[sreply.size()+1]; strcpy(*reply,sreply.c_str()); } void Ng_SocketClientClose ( void ) { clientsocket.Reset(NULL); } void Ng_SocketClientGetServerHost ( const int number, char ** host ) { *host = new char[servers[number]->host.size()+1]; strcpy(*host,servers[number]->host.c_str()); } void Ng_SocketClientGetServerPort ( const int number, int * port ) { *port = servers[number]->port; } void Ng_SocketClientGetServerClientID ( const int number, int * id ) { *id = servers[number]->clientid; } #endif // SOCKETS /* #ifdef PARALLEL void Ng_SetElementPartition ( const int elnr, const int part ) { mesh->VolumeElement(elnr+1).SetPartition(part); } int Ng_GetElementPartition ( const int elnr ) { return mesh->VolumeElement(elnr+1).GetPartition(); } #endif */ void Ng_InitPointCurve(double red, double green, double blue) { mesh->InitPointCurve(red, green, blue); } void Ng_AddPointCurvePoint(const double * point) { Point3d pt; pt.X() = point[0]; pt.Y() = point[1]; pt.Z() = point[2]; mesh->AddPointCurvePoint(pt); } void Ng_SaveMesh ( const char * meshfile ) { mesh -> Save(string(meshfile)); } int Ng_Bisect_WithInfo ( const char * refinementfile, double ** qualityloss, int * qualityloss_size ) { BisectionOptions biopt; biopt.outfilename = NULL; // "ngfepp.vol"; biopt.femcode = "fepp"; biopt.refinementfilename = refinementfile; Refinement * ref = const_cast (&mesh->GetGeometry()->GetRefinement()); MeshOptimize2d * opt = NULL; /* if (stlgeometry) ref = new RefinementSTLGeometry(*stlgeometry); #ifdef OCCGEOMETRY else if (occgeometry) ref = new OCCRefinementSurfaces (*occgeometry); #endif #ifdef ACIS else if (acisgeometry) { ref = new ACISRefinementSurfaces(*acisgeometry); opt = new ACISMeshOptimize2dSurfaces(*acisgeometry); ref->Set2dOptimizer(opt); } #endif else { ref = new RefinementSurfaces(*geometry); opt = new MeshOptimize2dSurfaces(*geometry); ref->Set2dOptimizer(opt); } */ #ifdef ACIS if (acisgeometry) { // ref = new ACISRefinementSurfaces(*acisgeometry); opt = new ACISMeshOptimize2dSurfaces(*acisgeometry); ref->Set2dOptimizer(opt); } else #endif { // ref = new RefinementSurfaces(*geometry); /* // joachim, oct 2014 CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (geometry) { opt = new MeshOptimize2dSurfaces(*geometry); ref->Set2dOptimizer(opt); } */ } if(!mesh->LocalHFunctionGenerated()) mesh->CalcLocalH(mparam.grading); mesh->LocalHFunction().SetGrading (mparam.grading); Array * qualityloss_arr = NULL; if(qualityloss != NULL) qualityloss_arr = new Array; ref -> Bisect (*mesh, biopt, qualityloss_arr); int retval = 0; if(qualityloss != NULL) { *qualityloss = new double[qualityloss_arr->Size()+1]; for(int i = 0; iSize(); i++) (*qualityloss)[i+1] = (*qualityloss_arr)[i]; retval = qualityloss_arr->Size(); delete qualityloss_arr; } mesh -> UpdateTopology(); mesh -> GetCurvedElements().BuildCurvedElements (ref, mparam.elementorder); multithread.running = 0; delete ref; delete opt; return retval; } void Ng_Bisect ( const char * refinementfile ) { Ng_Bisect_WithInfo( refinementfile, NULL, NULL ); } /* number of nodes of type nt nt = 0 is Vertex nt = 1 is Edge nt = 2 is Face nt = 3 is Cell */ int Ng_GetNNodes (int nt) { switch (nt) { case 0: return mesh -> GetNV(); case 1: return mesh->GetTopology().GetNEdges(); case 2: return mesh->GetTopology().GetNFaces(); case 3: return mesh -> GetNE(); } return -1; } int Ng_GetClosureNodes (int nt, int nodenr, int nodeset, int * nodes) { switch (nt) { case 3: // The closure of a cell { int cnt = 0; if (nodeset & 1) // Vertices { const Element & el = (*mesh)[ElementIndex(nodenr)]; for (int i = 0; i < el.GetNP(); i++) { nodes[cnt++] = 0; nodes[cnt++] = el[i] - PointIndex::BASE; } } if (nodeset & 2) // Edges { int edges[12]; int ned; ned = mesh->GetTopology().GetElementEdges (nodenr+1, edges, 0); for (int i = 0; i < ned; i++) { nodes[cnt++] = 1; nodes[cnt++] = edges[i]-1; } } if (nodeset & 4) // Faces { int faces[12]; int nfa; nfa = mesh->GetTopology().GetElementFaces (nodenr+1, faces, 0); for (int i = 0; i < nfa; i++) { nodes[cnt++] = 2; nodes[cnt++] = faces[i]-1; } } if (nodeset & 8) // Cell { nodes[cnt++] = 3; nodes[cnt++] = nodenr; } return cnt/2; } default: { cerr << "GetClosureNodes not implemented for Nodetype " << nt << endl; } } return 0; } int Ng_GetNElements (int dim) { switch (dim) { case 0: return mesh -> GetNV(); case 1: return mesh -> GetNSeg(); case 2: return mesh -> GetNSE(); case 3: return mesh -> GetNE(); } return -1; } /* closure nodes of element nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc E.g., nodeset = 6 includes edge and face nodes nodes is pair of integers (nodetype, nodenr) return value is number of nodes */ int Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes) { switch (dim) { case 3: // The closure of a volume element = CELL { return Ng_GetClosureNodes (3, elementnr, nodeset, nodes); } case 2: { int cnt = 0; if (nodeset & 1) // Vertices { const Element2d & el = (*mesh)[SurfaceElementIndex(elementnr)]; for (int i = 0; i < el.GetNP(); i++) { nodes[cnt++] = 0; nodes[cnt++] = el[i] - PointIndex::BASE; } } if (nodeset & 2) // Edges { int edges[12]; int ned; ned = mesh->GetTopology().GetSurfaceElementEdges (elementnr+1, edges, 0); for (int i = 0; i < ned; i++) { nodes[cnt++] = 1; nodes[cnt++] = edges[i]-1; } } if (nodeset & 4) // Faces { int face = mesh->GetTopology().GetSurfaceElementFace (elementnr+1); nodes[cnt++] = 2; nodes[cnt++] = face-1; } return cnt/2; } default: { cerr << "GetClosureNodes not implemented for Element of dimension " << dim << endl; } } return 0; } void Ng_GetArgs (int & argc, char ** &argv) { argc = h_argc; argv = h_argv; } void LinkFunction () { Ng_Redraw(); } void Ng_TclCmd(string cmd) { lock_guard guard(tcl_todo_mutex); *(multithread.tcl_todo) += cmd; } netgen-6.2.1905/libsrc/interface/read_fnf_mesh.cpp0000644000175000017500000003650713504650527020516 0ustar kurtkurt // // Read Pro/ENGINEER neutral format // #include #include #include #include #include #include namespace netgen { #include "writeuser.hpp" bool ReadLine (istream & in, string & buf) { do { buf = ""; while (in.good()) { char ch = in.get(); if (ch == '\n') break; if (ch == '\r') break; if (ch == '\\') { // while (iswhite (ch = in.get() ) ch = in.get(); // '\n' CR ch = in.get(); // '\n' LF } else buf += ch; } } while (in.good() && (buf == "" || buf[0] == '#')); return in.good(); } class LoadType { public: int id; string name; string placement; string valuetype; Array places; }; void ReadFNFFormat (Mesh & mesh, const string & filename) { ifstream fin (filename.c_str()); string buf; mesh.SetDimension (3); while (ReadLine (fin, buf)) { stringstream sbuf(buf); string start_sect, token; char ch; sbuf >> start_sect; if (start_sect == "%START_SECT") { sbuf >> ch >> token; if (token == "HEADER") { while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token; sbuf >> token; if (token == "%TITLE") { char ch; string name; sbuf >> ch >> name; PrintMessage(3, "Title: ", name); } else if (token == "%STATISTICS") { ; } else if (token == "%END_SECT") { break; } else { PrintMessage(1, "SECTION HEADER, unknown field: ",buf); } } } else if (token == "ELEM_TYPES") { while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token; sbuf >> token; if (token == "%ELEM_TYPE") { int nr; string def; char ch; sbuf >> nr >> def >> ch; if (def == "DEF") { string classname, type; sbuf >> classname >> type; if (classname != "SOLID" || type != "TETRA") cerr << "Element not supported: " << buf << endl; } } else if (token == "%END_SECT") { break; } else { PrintMessage(1, "SECTION ELEM_TYPE, unknown field: ", buf); } } } else if (token == "COORD_SYSTEMS") { while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token; sbuf >> token; if (token == "%END_SECT") { break; } else { // cout << "COORD_SYSTEMS, unknown field: " << buf << endl; } } } else if (token == "ANALYSIS") { // ignore this section while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token; sbuf >> token; if (token == "%END_SECT") { break; } } } else if (token == "MATERIALS") { *testout << "parse materials" << endl; Array young_modulus, poisson_ratio, mass_density; while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token; sbuf >> token; if (token == "%MATERIAL") { int nr; string prop; char ch; double val; sbuf >> nr >> prop >> ch; if (prop == "DEF") { ; } else { sbuf >> val; *testout << "prop = " << prop << ", val = " << val << endl; if (prop == "YOUNG_MODULUS") young_modulus.Append (val); else if (prop == "POISSON_RATIO") poisson_ratio.Append (val); else if (prop == "MASS_DENSITY") mass_density.Append (val); } } else if (token == "%END_SECT") { mesh.SetUserData ("YOUNG_MODULUS", young_modulus); mesh.SetUserData ("POISSON_RATIO", poisson_ratio); mesh.SetUserData ("MASS_DENSITY", mass_density); *testout << "young = " << young_modulus << endl; *testout << "poisson = " << poisson_ratio << endl; break; } else { PrintMessage(1, "SECTION MATERIALS, unknown field: ", buf); } } } else if (token == "MESH") { while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token; sbuf >> token; if (token == "%NODE") { string st; char ch; int nr, ks_id; double x,y,z; sbuf >> nr >> st >> ch >> x >> y >> z >> ks_id; mesh.AddPoint (Point3d (x,y,z) ); } else if (token == "%ELEM") { string elemid, def; char ch; int elnr, typid, matid; string propid; sbuf >> elnr >> def >> ch; sbuf >> typid >> matid >> propid; Array pnums; while (1) { int pn; sbuf >> pn; if (!sbuf.good()) break; pnums.Append (pn); } int pe2ng [] = { 0, 1, 2, 3, 4, 7, 5, 6, 8, 9 }; Element el(pnums.Size()); for (int j = 0; j < pnums.Size(); j++) el[pe2ng[j]] = pnums[j]; el.SetIndex (matid); mesh.AddVolumeElement (el); } else if (token == "%END_SECT") { break; } else { PrintMessage(1, "SECTION MESH, unknown: ", buf); } } } else if (token == "MESH_TOPOLOGY") { while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token, kw; int nr; char ch; sbuf >> token; if (token == "%EDGE") { sbuf >> nr >> kw >> ch; if (kw == "NODES") { Array enums; while (1) { int en; sbuf >> en; if (!sbuf.good()) break; enums.Append (en); } for (int j = 0; j+2 < enums.Size(); j+=2) { Segment seg; seg[0] = enums[j]; seg[1] = enums[j+2]; seg[2] = enums[j+1]; seg.edgenr = nr; mesh.AddSegment (seg); } } } else if (token == "%SURFACE") { sbuf >> nr >> kw >> ch; if (kw == "FACES") { Array fnums; while (1) { int fn; sbuf >> fn; if (!sbuf.good()) break; fnums.Append (fn); } FaceDescriptor fd(-1, -1, -1, -1); fd.SetBCProperty (nr); *testout << "add fd " << mesh.GetNFD() << ", nr = " << nr << endl; mesh.AddFaceDescriptor (fd); for (int j = 0; j < fnums.Size(); j += 2) { int elnr = fnums[j]; int fnr = fnums[j+1]; const Element & el = mesh.VolumeElement (elnr); if(j == 0) mesh.GetFaceDescriptor(nr).SetDomainIn(el.GetIndex()); Element2d el2d; el.GetFace (fnr, el2d); el2d.SetIndex (nr); mesh.AddSurfaceElement (el2d); } } } else if (token == "%END_SECT") { break; } else { PrintMessage(1, "SECTION MESH, unknown: ", buf); } } } else if (token == "LOADS") { Array loadtypes; while (1) { ReadLine (fin, buf); stringstream sbuf(buf); string token; sbuf >> token; if (token == "%LOAD_TYPE") { string def; char ch; LoadType * lt = new LoadType; sbuf >> lt->id >> def >> ch >> lt->name >> lt->placement >> lt->valuetype; if (lt->name == "DISPLACEMENT") PrintMessage(3, "loadtype DISPLACEMENT found"); if (lt->placement != "FACE" && lt->placement != "EDGE" && lt->placement != "NODE") PrintMessage(1, "unsupported placement ", lt->placement); loadtypes.Append (lt); } else if (token == "%LOAD") { int id; string def; char ch; int placement; int load_type_id, con_case_id; sbuf >> id >> def >> ch; if (def == "DEF") { sbuf >> load_type_id >> con_case_id; } if (def == "VAL") { sbuf >> placement; for (int i = 0; i < loadtypes.Size(); i++) if (load_type_id == loadtypes[i]->id) loadtypes[i]->places.Append (placement); } } else if (token == "%CON_CASE") { ; } else if (token == "%END_SECT") { for (int i = 0; i < loadtypes.Size(); i++) { stringstream str; str << loadtypes[i]->places; if (loadtypes[i]->placement == "FACE" && loadtypes[i]->name == "DISPLACEMENT") { mesh.SetUserData ("CONSTRAINT_DISP_FACE", loadtypes[i]->places); PrintMessage(3, "constrained faces: ", str.str()); } if (loadtypes[i]->placement == "EDGE" && loadtypes[i]->name == "DISPLACEMENT") { mesh.SetUserData ("CONSTRAINT_DISP_EDGE", loadtypes[i]->places); PrintMessage(3,"constrained edges: ", str.str()); } if (loadtypes[i]->placement == "NODE" && loadtypes[i]->name == "DISPLACEMENT") { mesh.SetUserData ("CONSTRAINT_DISP_NODE", loadtypes[i]->places); PrintMessage(3, "constrained nodes: ", str.str()); } } break; } else { PrintMessage(1, "SECTION LOADS, unknown field: ", buf); } } } else { PrintMessage(1, "unknown section ", token); } } else PrintMessage(3, "parse line: (", buf, ")"); } } } netgen-6.2.1905/libsrc/interface/writedolfin.cpp0000644000175000017500000000344513504650527020257 0ustar kurtkurt// // Write dolfin file // // by // Kent-Andre Mardal #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void WriteDolfinFormat (const Mesh & mesh, const string & filename) { cout << "start writing dolfin export" << endl; int np = mesh.GetNP(); int ne = mesh.GetNE(); // int nse = mesh.GetNSE(); int nsd = mesh.GetDimension(); // int invertsurf = mparam.inverttrigs; // int i, j; ofstream outfile (filename.c_str()); // char str[100]; outfile.precision(8); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); if ( nsd == 3) { outfile << "" <"<" <"<"<"<"<"<"<"<"< #include #include #include #include namespace netgen { extern MeshingParameters mparam; #include "writeuser.hpp" void WriteFEAPFormat (const Mesh & mesh, const string & filename) { // Feap format by A. Rieger // rieger@ibnm.uni-hannover.de int inverttets = mparam.inverttets; //int invertsurf = mparam.inverttrigs; int i, j; double scale = 1; // globflags.GetNumFlag ("scale", 1); ofstream outfile(filename.c_str()); outfile << "feap" << "\n"; outfile << mesh.GetNP(); outfile << ","; outfile << mesh.GetNE(); outfile << ","; outfile << "1,3,3,4" << "\n" << "\n"; outfile << "!numnp,numel,nummat,ndm,ndf,nen"; outfile << "\n"; outfile << "\n" << "\n"; outfile << "!node,, X Y Z" << "\n"; outfile << "COOR" << "\n"; outfile.precision(4); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); for (i = 1; i <= mesh.GetNP(); i++) { outfile.width(5); outfile << i; outfile << ",,"; outfile.width(10); outfile << mesh.Point(i)(0)/scale << " "; outfile.width(10); outfile << mesh.Point(i)(1)/scale << " "; outfile.width(10); outfile << mesh.Point(i)(2)/scale << "\n"; } outfile << "\n" << "\n"; outfile << "!elm,,mat, n1 n2 n3 n4" << "\n"; outfile << "ELEM" << "\n"; for (i = 1; i <= mesh.GetNE(); i++) { Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); outfile.width(5); outfile << i; outfile << ",,"; outfile << el.GetIndex(); outfile << ","; for (j = 1; j <= el.NP(); j++) { outfile.width(8); outfile << el.PNum(j); } outfile << "\n"; } outfile << "\n" << "\n"; /* //outfile << "SLOA" << "\n"; //outfile << "2,3,3" << "\n"; //outfile << GetNSE() << "\n"; outfile << "selm" << "\n" << GetNSE() << "\n"; for (i = 1; i <= GetNSE(); i++) { if (SurfaceElement(i).GetIndex()) { outfile.width(8); outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).surfnr; //outfile.width(8); //outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).domin; //outfile.width(8); //outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).domout; } else outfile << " 0 0 0"; Element2d sel = SurfaceElement(i); if (invertsurf) sel.Invert(); //outfile.width(8); //outfile << sel.GetNP(); //if (facedecoding.Get(SurfaceElement(i).GetIndex ()).surfnr == 4) //{ for (j = 1; j <= sel.GetNP(); j++) { outfile.width(8); outfile << sel.PNum(j); } //outfile.width(8); //outfile << "0.0"; //outfile.width(8); //outfile << "0.0"; //outfile.width(8); //outfile << "1.0" << "\n"; //} outfile << "\n"; //outfile << endl; } */ // BEGIN CONTACT OUTPUT /* int masterindex, slaveindex; cout << "Master Surface index = "; cin >> masterindex; cout << "Slave Surface index = "; cin >> slaveindex; // CONTACT SURFACE 1 outfile << "\n"; outfile << "\n"; outfile << "surface,1" << "\n";; outfile.width(6); outfile << "tria" << "\n";; outfile.width(13); outfile << "facet" << "\n";; zz = 0; for (i = 1; i <= mesh.GetNSE(); i++) { Element2d sel = mesh.SurfaceElement(i); if (invertsurf) sel.Invert(); if (mesh.GetFaceDescriptor(sel.GetIndex ()).BCProperty() == masterindex) { zz++; outfile.width(14); outfile << zz; outfile << ",,"; for (j = 1; j <= sel.GetNP(); j++) { outfile << sel.PNum(j); outfile << ","; } outfile << "\n"; } } // CONTACT SURFACE 2 outfile << "\n"; outfile << "\n"; outfile << "surface,2" << "\n";; outfile.width(6); outfile << "tria" << "\n";; outfile.width(13); outfile << "facet" << "\n";; zz = 0; for (i = 1; i <= mesh.GetNSE(); i++) { Element2d sel = mesh.SurfaceElement(i); if (invertsurf) sel.Invert(); if (mesh.GetFaceDescriptor(sel.GetIndex ()).BCProperty() == slaveindex) { zz++; outfile.width(14); outfile << zz; outfile << ",,"; for (j = 1; j <= sel.GetNP(); j++) { outfile << sel.PNum(j); outfile << ","; } outfile << "\n"; } } outfile << "\n"; outfile << "\n"; */ // END CONTACT OUTPUT cout << "done" << endl; } } netgen-6.2.1905/libsrc/interface/writeelmer.cpp0000644000175000017500000000551213504650527020105 0ustar kurtkurt // // Write Elmer file // // #include #include #include #include #include #include #include "writeuser.hpp" namespace netgen { extern MeshingParameters mparam; void WriteElmerFormat (const Mesh &mesh, const string &filename) { cout << "write elmer mesh files" << endl; int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int i, j; char str[200]; int inverttets = mparam.inverttets; int invertsurf = mparam.inverttrigs; #ifdef WIN32 char a[256]; sprintf( a, "mkdir %s", filename.c_str() ); system( a ); #else // int rc = mkdir(filename.c_str(), S_IRWXU|S_IRWXG); #endif sprintf( str, "%s/mesh.header", filename.c_str() ); ofstream outfile_h(str); sprintf( str, "%s/mesh.nodes", filename.c_str() ); ofstream outfile_n(str); sprintf( str, "%s/mesh.elements", filename.c_str() ); ofstream outfile_e(str); sprintf( str, "%s/mesh.boundary", filename.c_str() ); ofstream outfile_b(str); // fill hashtable INDEX_3_HASHTABLE face2volelement(ne); for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); INDEX_3 i3; int k, l; for (j = 1; j <= 4; j++) // loop over faces of tet { l = 0; for (k = 1; k <= 4; k++) if (k != j) { l++; i3.I(l) = el.PNum(k); } i3.Sort(); face2volelement.Set (i3, i); } } // outfile.precision(6); // outfile.setf (ios::fixed, ios::floatfield); // outfile.setf (ios::showpoint); outfile_h << np << " " << ne << " " << nse << "\n"; outfile_h << "2" << "\n"; outfile_h << "303 " << nse << "\n"; outfile_h << "504 " << ne << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile_n << i << " -1 "; outfile_n << p.X() << " "; outfile_n << p.Y() << " "; outfile_n << p.Z() << "\n"; } for (i = 1; i <= ne; i++) { Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); sprintf( str, "5%02d", (int)el.GetNP() ); outfile_e << i << " " << el.GetIndex() << " " << str << " "; for (j = 1; j <= el.GetNP(); j++) { outfile_e << " "; outfile_e << el.PNum(j); } outfile_e << "\n"; } for (i = 1; i <= nse; i++) { Element2d el = mesh.SurfaceElement(i); if (invertsurf) el.Invert(); sprintf( str, "3%02d", (int)el.GetNP() ); { INDEX_3 i3; for (j = 1; j <= 3; j++) i3.I(j) = el.PNum(j); i3.Sort(); int elind = face2volelement.Get(i3); outfile_b << i << " " << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << " " << elind << " 0 " << str << " "; } for (j = 1; j <= el.GetNP(); j++) { outfile_b << " "; outfile_b << el.PNum(j); } outfile_b << "\n"; } } } netgen-6.2.1905/libsrc/interface/writeuser.cpp0000644000175000017500000005740313504650527017765 0ustar kurtkurt// // Write user dependent output file // #include #include #include #include #include #include #include "writeuser.hpp" namespace netgen { extern MeshingParameters mparam; void RegisterUserFormats (Array & names, Array & extensions) { const char *types[] = { "Neutral Format", ".mesh", "Surface Mesh Format", ".mesh" , "DIFFPACK Format", ".mesh", "TecPlot Format", ".mesh", "Tochnog Format", ".mesh", "Abaqus Format", ".mesh", "Fluent Format", ".mesh", "Permas Format", ".mesh", "FEAP Format", ".mesh", "Elmer Format", "*", "STL Format", ".stl", "STL Extended Format", ".stl", "VRML Format", ".*", "Gmsh Format", ".gmsh", "Gmsh2 Format", ".gmsh2", "OpenFOAM 1.5+ Format", "*", "OpenFOAM 1.5+ Compressed", "*", "JCMwave Format", ".jcm", "TET Format", ".tet", // { "Chemnitz Format" }, 0 }; for (int i = 0; types[2*i]; i++) { names.Append (types[2*i]); extensions.Append (types[2*i+1]); } } bool WriteUserFormat (const string & format, const Mesh & mesh, const string & filename) { // cout << "write user &hgeom = " << &hgeom << endl; // const CSGeometry & geom = *dynamic_cast (&hgeom); const CSGeometry & geom = *dynamic_pointer_cast (mesh.GetGeometry()); PrintMessage (1, "Export mesh to file ", filename, ", format is ", format); if (format == "Neutral Format") WriteNeutralFormat (mesh, geom, filename); else if (format == "Surface Mesh Format") WriteSurfaceFormat (mesh, filename); else if (format == "DIFFPACK Format") WriteDiffPackFormat (mesh, geom, filename); else if (format == "Tochnog Format") WriteTochnogFormat (mesh, filename); else if (format == "TecPlot Format") cerr << "ERROR: TecPlot format currently out of order" << endl; // WriteTecPlotFormat (mesh, geom, filename); else if (format == "Abaqus Format") WriteAbaqusFormat (mesh, filename); else if (format == "Fluent Format") WriteFluentFormat (mesh, filename); else if (format == "Permas Format") WritePermasFormat (mesh, filename); else if (format == "FEAP Format") WriteFEAPFormat (mesh, filename); else if (format == "Elmer Format") WriteElmerFormat (mesh, filename); else if (format == "STL Format") WriteSTLFormat (mesh, filename); // Philippose - 16 August 2010 // Added additional STL Export in which // each face of the geometry is treated // as a separate "solid" entity else if (format == "STL Extended Format") WriteSTLExtFormat (mesh, filename); else if (format == "VRML Format") WriteVRMLFormat (mesh, 1, filename); else if (format == "Fepp Format") WriteFEPPFormat (mesh, geom, filename); else if (format == "EdgeElement Format") WriteEdgeElementFormat (mesh, geom, filename); else if (format == "Chemnitz Format") WriteUserChemnitz (mesh, filename); else if (format == "Gmsh Format") WriteGmshFormat (mesh, geom, filename); // Philippose - 29/01/2009 // Added Gmsh v2.xx Mesh export capability else if (format == "Gmsh2 Format") WriteGmsh2Format (mesh, geom, filename); // Philippose - 25/10/2009 // Added OpenFOAM 1.5+ Mesh export capability else if (format == "OpenFOAM 1.5+ Format") WriteOpenFOAM15xFormat (mesh, filename, false); else if (format == "OpenFOAM 1.5+ Compressed") WriteOpenFOAM15xFormat (mesh, filename, true); else if (format == "JCMwave Format") WriteJCMFormat (mesh, geom, filename); #ifdef OLIVER else if (format == "TET Format") WriteTETFormat( mesh, filename);//, "High Frequency" ); #endif else { return 1; } return 0; } /* * Neutral mesh format * points, elements, surface elements */ void WriteNeutralFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename) { cout << "write neutral, new" << endl; int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int nseg = mesh.GetNSeg(); int i, j; int inverttets = mparam.inverttets; int invertsurf = mparam.inverttrigs; ofstream outfile (filename.c_str()); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile.width(10); outfile << p.X() << " "; outfile.width(9); outfile << p.Y() << " "; if (mesh.GetDimension() == 3) { outfile.width(9); outfile << p.Z(); } outfile << "\n"; } if (mesh.GetDimension() == 3) { outfile << ne << "\n"; for (i = 1; i <= ne; i++) { Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); outfile.width(4); outfile << el.GetIndex() << " "; for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile.width(8); outfile << el.PNum(j); } outfile << "\n"; } } outfile << nse << "\n"; for (i = 1; i <= nse; i++) { Element2d el = mesh.SurfaceElement(i); if (invertsurf) el.Invert(); outfile.width(4); outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile.width(8); outfile << el.PNum(j); } outfile << "\n"; } if (mesh.GetDimension() == 2) { outfile << nseg << "\n"; for (int i = 1; i <= nseg; i++) { const Segment & seg = mesh.LineSegment(i); outfile.width(4); outfile << seg.si << " "; for (int j = 0; j < seg.GetNP(); j++) { outfile << " "; outfile.width(8); outfile << seg[j]; } /* outfile << " "; outfile.width(8); outfile << seg[0]; outfile << " "; outfile.width(8); outfile << seg[1]; if (seg[2] != -1) { outfile.width(8); outfile << seg[2]; } */ outfile << "\n"; } } } void WriteSurfaceFormat (const Mesh & mesh, const string & filename) { // surface mesh int i, j; cout << "Write Surface Mesh" << endl; ofstream outfile (filename.c_str()); outfile << "surfacemesh" << endl; outfile << mesh.GetNP() << endl; for (i = 1; i <= mesh.GetNP(); i++) { for (j = 0; j < 3; j++) { outfile.width(10); outfile << mesh.Point(i)(j) << " "; } outfile << endl; } outfile << mesh.GetNSE() << endl; for (i = 1; i <= mesh.GetNSE(); i++) { for (j = 1; j <= 3; j++) { outfile.width(8); outfile << mesh.SurfaceElement(i).PNum(j); } outfile << endl; } } /* * save surface mesh as STL file */ void WriteSTLFormat (const Mesh & mesh, const string & filename) { cout << "\nWrite STL Surface Mesh" << endl; ostream *outfile; if(filename.substr(filename.length()-3,3) == ".gz") outfile = new ogzstream(filename.c_str()); else outfile = new ofstream(filename.c_str()); int i; outfile->precision(10); *outfile << "solid" << endl; for (i = 1; i <= mesh.GetNSE(); i++) { *outfile << "facet normal "; const Point3d& p1 = mesh.Point(mesh.SurfaceElement(i).PNum(1)); const Point3d& p2 = mesh.Point(mesh.SurfaceElement(i).PNum(2)); const Point3d& p3 = mesh.Point(mesh.SurfaceElement(i).PNum(3)); Vec3d normal = Cross(p2-p1,p3-p1); if (normal.Length() != 0) { normal /= (normal.Length()); } *outfile << normal.X() << " " << normal.Y() << " " << normal.Z() << "\n"; *outfile << "outer loop\n"; *outfile << "vertex " << p1.X() << " " << p1.Y() << " " << p1.Z() << "\n"; *outfile << "vertex " << p2.X() << " " << p2.Y() << " " << p2.Z() << "\n"; *outfile << "vertex " << p3.X() << " " << p3.Y() << " " << p3.Z() << "\n"; *outfile << "endloop\n"; *outfile << "endfacet\n"; } *outfile << "endsolid" << endl; } /* * Philippose - 16 August 2010 * Save surface mesh as STL file * with a separate solid definition * for each face * - This helps in splitting up the * STL into named boundary faces * when using a third-party mesher */ void WriteSTLExtFormat (const Mesh & mesh, const string & filename) { cout << "\nWrite STL Surface Mesh (with separated boundary faces)" << endl; ostream *outfile; if(filename.substr(filename.length()-3,3) == ".gz") outfile = new ogzstream(filename.c_str()); else outfile = new ofstream(filename.c_str()); outfile->precision(10); int numBCs = 0; Array faceBCs; TABLE faceBCMapping; faceBCs.SetSize(mesh.GetNFD()); faceBCMapping.SetSize(mesh.GetNFD()); faceBCs = -1; // Collect the BC numbers used in the mesh for(int faceNr = 1; faceNr <= mesh.GetNFD(); faceNr++) { int bcNum = mesh.GetFaceDescriptor(faceNr).BCProperty(); if(faceBCs.Pos(bcNum) < 0) { numBCs++; faceBCs.Set(numBCs,bcNum); faceBCMapping.Add1(numBCs,faceNr); } else { faceBCMapping.Add1(faceBCs.Pos(bcNum)+1,faceNr); } } faceBCs.SetSize(numBCs); faceBCMapping.ChangeSize(numBCs); // Now actually write the data to file for(int bcInd = 1; bcInd <= faceBCs.Size(); bcInd++) { *outfile << "solid Boundary_" << faceBCs.Elem(bcInd) << "\n"; for(int faceNr = 1;faceNr <= faceBCMapping.EntrySize(bcInd); faceNr++) { Array faceSei; mesh.GetSurfaceElementsOfFace(faceBCMapping.Get(bcInd,faceNr),faceSei); for (int i = 0; i < faceSei.Size(); i++) { *outfile << "facet normal "; const Point3d& p1 = mesh.Point(mesh.SurfaceElement(faceSei[i]).PNum(1)); const Point3d& p2 = mesh.Point(mesh.SurfaceElement(faceSei[i]).PNum(2)); const Point3d& p3 = mesh.Point(mesh.SurfaceElement(faceSei[i]).PNum(3)); Vec3d normal = Cross(p2-p1,p3-p1); if (normal.Length() != 0) { normal /= (normal.Length()); } *outfile << normal.X() << " " << normal.Y() << " " << normal.Z() << "\n"; *outfile << "outer loop\n"; *outfile << "vertex " << p1.X() << " " << p1.Y() << " " << p1.Z() << "\n"; *outfile << "vertex " << p2.X() << " " << p2.Y() << " " << p2.Z() << "\n"; *outfile << "vertex " << p3.X() << " " << p3.Y() << " " << p3.Z() << "\n"; *outfile << "endloop\n"; *outfile << "endfacet\n"; } } *outfile << "endsolid Boundary_" << faceBCs.Elem(bcInd) << "\n"; } } /* * * write surface mesh as VRML file * */ void WriteVRMLFormat (const Mesh & mesh, bool faces, const string & filename) { if (faces) { // Output in VRML, IndexedFaceSet is used // Bartosz Sawicki int np = mesh.GetNP(); int nse = mesh.GetNSE(); int i, j; ofstream outfile (filename.c_str()); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); outfile << "#VRML V2.0 utf8 \n" "Background {\n" " skyColor [1 1 1]\n" " groundColor [1 1 1]\n" "}\n" "Group{ children [\n" "Shape{ \n" "appearance Appearance { material Material { }} \n" "geometry IndexedFaceSet { \n" "coord Coordinate { point [ \n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile.width(10); outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << " \n"; } outfile << " ] } \n" "coordIndex [ \n"; for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); for (j = 1; j <= 3; j++) { outfile.width(8); outfile << el.PNum(j)-1; } outfile << " -1 \n"; } outfile << " ] \n"; //define number and RGB definitions of colors outfile << "color Color { color [1 0 0, 0 1 0, 0 0 1, 1 1 0]} \n" "colorIndex [\n"; for (i = 1; i <= nse; i++) { outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).BCProperty(); outfile << endl; } outfile << " ] \n" "colorPerVertex FALSE \n" "creaseAngle 0 \n" "solid FALSE \n" "ccw FALSE \n" "convex TRUE \n" "} } # end of Shape\n" "] }\n"; } /* end of VRMLFACES */ else { // Output in VRML, IndexedLineSet is used // Bartosz Sawicki int np = mesh.GetNP(); int nse = mesh.GetNSE(); int i, j; ofstream outfile (filename.c_str()); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); outfile << "#VRML V2.0 utf8 \n" "Background {\n" " skyColor [1 1 1]\n" " groundColor [1 1 1]\n" "}\n" "Group{ children [\n" "Shape{ \n" "appearance Appearance { material Material { }} \n" "geometry IndexedLineSet { \n" "coord Coordinate { point [ \n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile.width(10); outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << " \n"; } outfile << " ] } \n" "coordIndex [ \n"; for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); for (j = 1; j <= 3; j++) { outfile.width(8); outfile << el.PNum(j)-1; } outfile.width(8); outfile << el.PNum(1)-1; outfile << " -1 \n"; } outfile << " ] \n"; /* Uncomment if you want color mesh outfile << "color Color { color [1 1 1, 0 1 0, 0 0 1, 1 1 0]} \n" "colorIndex [\n"; for (i = 1; i <= nse; i++) { outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).BCProperty(); outfile << endl; } outfile << " ] \n" */ outfile << "colorPerVertex FALSE \n" "} } #end of Shape\n" "] } \n"; } } /* * FEPP .. a finite element package developed at University Linz, Austria */ void WriteFEPPFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename) { ofstream outfile (filename.c_str()); if (mesh.GetDimension() == 3) { // output for FEPP int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); // int ns = mesh.GetNFD(); int i, j; outfile.precision(5); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); outfile << "volumemesh4" << endl; outfile << nse << endl; for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); // int facenr = mesh.facedecoding.Get(el.GetIndex()).surfnr; outfile.width(4); outfile << el.GetIndex() << " "; outfile.width(4); // outfile << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << " "; outfile << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << " "; outfile.width(4); outfile << el.GetNP() << " "; for (j = 1; j <= el.GetNP(); j++) { outfile.width(8); outfile << el.PNum(j); } outfile << "\n"; } outfile << ne << "\n"; for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); outfile.width(4); outfile << el.GetIndex() << " "; outfile.width(4); outfile << el.GetNP() << " "; for (j = 1; j <= el.GetNP(); j++) { outfile.width(8); outfile << el.PNum(j); } outfile << "\n"; } outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile.width(10); outfile << p.X() << " "; outfile.width(9); outfile << p.Y() << " "; outfile.width(9); outfile << p.Z() << "\n"; } /* if (typ == WRITE_FEPPML) { int nbn = mesh.mlbetweennodes.Size(); outfile << nbn << "\n"; for (i = 1; i <= nbn; i++) outfile << mesh.mlbetweennodes.Get(i).I1() << " " << mesh.mlbetweennodes.Get(i).I2() << "\n"; // int ncon = mesh.connectedtonode.Size(); // outfile << ncon << "\n"; // for (i = 1; i <= ncon; i++) // outfile << i << " " << mesh.connectedtonode.Get(i) << endl; } */ /* // write CSG surfaces if (&geom && geom.GetNSurf() >= ns) { outfile << ns << endl; for (i = 1; i <= ns; i++) geom.GetSurface(mesh.GetFaceDescriptor(i).SurfNr())->Print(outfile); } else */ outfile << "0" << endl; } else { // 2D fepp format ; /* extern SplineGeometry2d * geometry2d; if (geometry2d) Save2DMesh (mesh, &geometry2d->GetSplines(), outfile); else Save2DMesh (mesh, 0, outfile); */ } } /* * Edge element mesh format * points, elements, edges */ void WriteEdgeElementFormat (const Mesh & mesh, const NetgenGeometry & geom, const string & filename) { cout << "write edge element format" << endl; const MeshTopology * top = &mesh.GetTopology(); int npoints = mesh.GetNP(); int nelements = mesh.GetNE(); int nsurfelem = mesh.GetNSE(); int nedges = top->GetNEdges(); int i, j; int inverttets = mparam.inverttets; int invertsurf = mparam.inverttrigs; Array edges; ofstream outfile (filename.c_str()); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); // vertices with coordinates outfile << npoints << "\n"; for (i = 1; i <= npoints; i++) { const Point3d & p = mesh.Point(i); outfile.width(10); outfile << p.X() << " "; outfile.width(9); outfile << p.Y() << " "; outfile.width(9); outfile << p.Z() << "\n"; } // element - edge - list outfile << nelements << " " << nedges << "\n"; for (i = 1; i <= nelements; i++) { Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); outfile.width(4); outfile << el.GetIndex() << " "; outfile.width(8); outfile << el.GetNP(); for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile.width(8); outfile << el.PNum(j); } top->GetElementEdges(i,edges); outfile << endl << " "; outfile.width(8); outfile << edges.Size(); for (j=1; j <= edges.Size(); j++) { outfile << " "; outfile.width(8); outfile << edges[j-1]; } outfile << "\n"; // orientation: top->GetElementEdgeOrientations(i,edges); outfile << " "; for (j=1; j <= edges.Size(); j++) { outfile << " "; outfile.width(8); outfile << edges[j-1]; } outfile << "\n"; } // surface element - edge - list (with boundary conditions) outfile << nsurfelem << "\n"; for (i = 1; i <= nsurfelem; i++) { Element2d el = mesh.SurfaceElement(i); if (invertsurf) el.Invert(); outfile.width(4); outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; outfile.width(8); outfile << el.GetNP(); for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile.width(8); outfile << el.PNum(j); } top->GetSurfaceElementEdges(i,edges); outfile << endl << " "; outfile.width(8); outfile << edges.Size(); for (j=1; j <= edges.Size(); j++) { outfile << " "; outfile.width(8); outfile << edges[j-1]; } outfile << "\n"; } int v1, v2; // edge - vertex - list outfile << nedges << "\n"; for (i=1; i <= nedges; i++) { top->GetEdgeVertices(i,v1,v2); outfile.width(4); outfile << v1; outfile << " "; outfile.width(8); outfile << v2 << endl; } } #ifdef OLDSTYLE_WRITE void WriteFile (int typ, const Mesh & mesh, const CSGeometry & geom, const char * filename, const char * geomfile, double h) { int inverttets = mparam.inverttets; int invertsurf = mparam.inverttrigs; if (typ == WRITE_EDGEELEMENT) { // write edge element file // Peter Harscher, ETHZ cout << "Write Edge-Element Format" << endl; ofstream outfile (filename); int i, j; int ned; // hash table representing edges; INDEX_2_HASHTABLE edgeht(mesh.GetNP()); // list of edges Array edgelist; // edge (point) on boundary ? BitArray bedge, bpoint(mesh.GetNP()); static int eledges[6][2] = { { 1, 2 } , { 1, 3 } , { 1, 4 }, { 2, 3 } , { 2, 4 } , { 3, 4 } }; // fill hashtable (point1, point2) ----> edgenr for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement (i); INDEX_2 edge; for (j = 1; j <= 6; j++) { edge.I1() = el.PNum (eledges[j-1][0]); edge.I2() = el.PNum (eledges[j-1][1]); edge.Sort(); if (!edgeht.Used (edge)) { edgelist.Append (edge); edgeht.Set (edge, edgelist.Size()); } } } // set bedges, bpoints bedge.SetSize (edgelist.Size()); bedge.Clear(); bpoint.Clear(); for (i = 1; i <= mesh.GetNSE(); i++) { const Element2d & sel = mesh.SurfaceElement(i); for (j = 1; j <= 3; j++) { bpoint.Set (sel.PNum(j)); INDEX_2 edge; edge.I1() = sel.PNum(j); edge.I2() = sel.PNum(j%3+1); edge.Sort(); bedge.Set (edgeht.Get (edge)); } } outfile << mesh.GetNE() << endl; // write element ---> point for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement(i); outfile.width(8); outfile << i; for (j = 1; j <= 4; j++) { outfile.width(8); outfile << el.PNum(j); } outfile << endl; } // write element ---> edge for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement (i); INDEX_2 edge; for (j = 1; j <= 6; j++) { edge.I1() = el.PNum (eledges[j-1][0]); edge.I2() = el.PNum (eledges[j-1][1]); edge.Sort(); outfile.width(8); outfile << edgeht.Get (edge); } outfile << endl; } // write points outfile << mesh.GetNP() << endl; outfile.precision (6); for (i = 1; i <= mesh.GetNP(); i++) { const Point3d & p = mesh.Point(i); for (j = 1; j <= 3; j++) { outfile.width(8); outfile << p.X(j); } outfile << " " << (bpoint.Test(i) ? "1" : 0) << endl; } // write edges outfile << edgelist.Size() << endl; for (i = 1; i <= edgelist.Size(); i++) { outfile.width(8); outfile << edgelist.Get(i).I1(); outfile.width(8); outfile << edgelist.Get(i).I2(); outfile << " " << (bedge.Test(i) ? "1" : "0") << endl; } } } #endif } netgen-6.2.1905/libsrc/interface/writegmsh2.cpp0000644000175000017500000002056613504650527020027 0ustar kurtkurt/*! \file writegmsh2.cpp * \brief Export Netgen Mesh in the GMSH v2.xx File format * \author Philippose Rajan * \date 02 November 2008 * * This function extends the export capabilities of * Netgen to include the GMSH v2.xx File Format. * * Current features of this function include: * * 1. Exports Triangles, Quadrangles and Tetrahedra \n * 2. Supports upto second order elements of each type * */ #include #include #include #include #include namespace netgen { #include "writeuser.hpp" extern MeshingParameters mparam; // Mapping of entities from Netgen definitions to GMSH definitions enum GMSH_ELEMENTS {GMSH_TRIG = 2, GMSH_TRIG6 = 9, GMSH_QUAD = 3, GMSH_QUAD8 = 16, GMSH_TET = 4, GMSH_TET10 = 11}; const int triGmsh[7] = {0,1,2,3,6,4,5}; const int quadGmsh[9] = {0,1,2,3,4,5,8,6,7}; const int tetGmsh[11] = {0,1,2,3,4,5,8,6,7,10,9}; /*! GMSH v2.xx mesh format export function * * This function extends the export capabilities of * Netgen to include the GMSH v2.xx File Format. * * Current features of this function include: * * 1. Exports Triangles, Quadrangles and Tetrahedra \n * 2. Supports upto second order elements of each type * */ void WriteGmsh2Format (const Mesh & mesh, const NetgenGeometry & geom, const string & filename) { ofstream outfile (filename.c_str()); outfile.precision(6); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); int np = mesh.GetNP(); /// number of points in mesh int ne = mesh.GetNE(); /// number of 3D elements in mesh int nse = mesh.GetNSE(); /// number of surface elements (BC) int i, j, k, l; /* * 3D section : Volume elements (currently only tetrahedra) */ if ((ne > 0) && (mesh.VolumeElement(1).GetNP() <= 10) && (mesh.SurfaceElement(1).GetNP() <= 6)) { cout << "Write GMSH v2.xx Format \n"; cout << "The GMSH v2.xx export is currently available for elements upto 2nd Order\n" << endl; int inverttets = mparam.inverttets; int invertsurf = mparam.inverttrigs; /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) outfile << "$MeshFormat\n"; outfile << (float)2.0 << " " << (int)0 << " " << (int)sizeof(double) << "\n"; outfile << "$EndMeshFormat\n"; /// Write nodes outfile << "$Nodes\n"; outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile << i << " "; /// node number outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << "\n"; } outfile << "$EndNodes\n"; /// write elements (both, surface elements and volume elements) outfile << "$Elements\n"; outfile << ne + nse << "\n"; //// number of elements + number of surfaces BC for (i = 1; i <= nse; i++) { int elType = 0; Element2d el = mesh.SurfaceElement(i); if(invertsurf) el.Invert(); if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle if(elType == 0) { cout << " Invalid surface element type for Gmsh 2.0 3D-Mesh Export Format !\n"; return; } outfile << i; outfile << " "; outfile << elType; outfile << " "; outfile << "2"; //// Number of tags (2 => Physical and elementary entities) outfile << " "; outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; /// that means that physical entity = elementary entity (arbitrary approach) outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile << el.PNum(triGmsh[j]); } outfile << "\n"; } for (i = 1; i <= ne; i++) { int elType = 0; Element el = mesh.VolumeElement(i); if (inverttets) el.Invert(); if(el.GetNP() == 4) elType = GMSH_TET; //// GMSH Element type for 4 node tetrahedron if(el.GetNP() == 10) elType = GMSH_TET10; //// GMSH Element type for 10 node tetrahedron if(elType == 0) { cout << " Invalid volume element type for Gmsh 2.0 3D-Mesh Export Format !\n"; return; } outfile << nse + i; //// element number (Remember to add on surface elements) outfile << " "; outfile << elType; outfile << " "; outfile << "2"; //// Number of tags (2 => Physical and elementary entities) outfile << " "; outfile << 100000 + el.GetIndex(); /// that means that physical entity = elementary entity (arbitrary approach) outfile << " "; outfile << 100000 + el.GetIndex(); /// volume number outfile << " "; for (j = 1; j <= el.GetNP(); j++) { outfile << " "; outfile << el.PNum(tetGmsh[j]); } outfile << "\n"; } outfile << "$EndElements\n"; } /* * End of 3D section */ /* * 2D section : available for triangles and quadrangles * upto 2nd Order */ else if(ne == 0) /// means that there's no 3D element { cout << "\n Write Gmsh v2.xx Surface Mesh (triangle and/or quadrangles upto 2nd Order)" << endl; /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) outfile << "$MeshFormat\n"; outfile << (float)2.0 << " " << (int)0 << " " << (int)sizeof(double) << "\n"; outfile << "$EndMeshFormat\n"; /// Write nodes outfile << "$Nodes\n"; outfile << np << "\n"; for (i = 1; i <= np; i++) { const Point3d & p = mesh.Point(i); outfile << i << " "; /// node number outfile << p.X() << " "; outfile << p.Y() << " "; outfile << p.Z() << "\n"; } outfile << "$EndNodes\n"; /// write triangles & quadrangles outfile << "$Elements\n"; outfile << nse << "\n"; for (k = 1; k <= nse; k++) { int elType = 0; const Element2d & el = mesh.SurfaceElement(k); if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle if(el.GetNP() == 4) elType = GMSH_QUAD; //// GMSH Type for a 4 node quadrangle if(el.GetNP() == 8) elType = GMSH_QUAD8; //// GMSH Type for an 8 node quadrangle if(elType == 0) { cout << " Invalid surface element type for Gmsh 2.0 2D-Mesh Export Format !\n"; return; } outfile << k; outfile << " "; outfile << elType; outfile << " "; outfile << "2"; outfile << " "; outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; /// that means that physical entity = elementary entity (arbitrary approach) outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; for (l = 1; l <= el.GetNP(); l++) { outfile << " "; if((elType == GMSH_TRIG) || (elType == GMSH_TRIG6)) { outfile << el.PNum(triGmsh[l]); } else if((elType == GMSH_QUAD) || (elType == GMSH_QUAD8)) { outfile << el.PNum(quadGmsh[l]); } } outfile << "\n"; } outfile << "$EndElements\n"; } /* * End of 2D section */ else { cout << " Invalid element type for Gmsh v2.xx Export Format !\n"; } } // End: WriteGmsh2Format } // End: namespace netgen netgen-6.2.1905/libsrc/interface/readtetmesh.cpp0000644000175000017500000006201313504650527020232 0ustar kurtkurt // // Read CST file format // #include #include #include #include #include #include namespace netgen { #include "writeuser.hpp" void ReadTETFormat (Mesh & mesh, const string & hfilename) { const char * filename = hfilename.c_str(); cout << "Reading .tet mesh" << endl; ifstream in (filename); int inputsection = 0; bool done = false; char ch; string str; string version; int unitcode; double tolerance; double dS1, dS2, alphaDeg, x3D, y3D, z3D; int nelts,nfaces,nedges,nnodes; int nperiodicmasternodes,ncornerperiodicmasternodes,ncubicperiodicmasternodes; int nperiodicmasteredges,ncornerperiodicmasteredges; int nperiodicmasterfaces; int nodeid,type,pid; int dummyint; int modelverts,modeledges,modelfaces,modelcells; Point3d p; int numObj3D,numObj2D,numObj1D,numObj0D; // bool nullstarted; Array eldom; int minId3D = -1, minId2D = -1; int maxId3D(-1), maxId2D(-1), maxId1D(-1), maxId0D(-1); Array *> segmentdata; Array tris; Array userdata_int; // just save data for 1:1 output Array userdata_double; Array point_pids; Array tetfacedata; Array uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D; while(!done) { // skip "//" comment bool comment = true; while(comment) { ch = in.get(); while(ch == ' ' || ch == '\n' || ch == '\t' || ch =='\r') ch = in.get(); if(ch != '/') { comment = false; in.putback(ch); } else { ch = in.get(); if(ch != '/') { comment = false; in.putback(ch); in.putback('/'); } else { in.ignore(10000,'\n'); } } } switch(inputsection) { case 0: // version number in >> version; cout << "Version number " << version << endl; if(version != "1.1" && version != "2" && version != "2.0") { cerr << "WARNING: import only tested for versions 1.1 and 2" << endl; //done = true; } userdata_double.Append(atof(version.c_str())); break; case 1: // unit code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL) in >> unitcode; cout << "unit code " << unitcode << endl; userdata_int.Append(unitcode); break; case 2: // Geometric coord "zero" tolerance threshold in >> tolerance; cout << "tolerance " << tolerance << endl; userdata_double.Append(tolerance); break; case 3: // Periodic UnitCell dS1 , dS2 , alphaDeg in >> dS1 >> dS2 >> alphaDeg; userdata_double.Append(dS1); userdata_double.Append(dS2); userdata_double.Append(alphaDeg); break; case 4: // Periodic UnitCell origin in global coords (x3D,y3D,z3D) in >> x3D >> y3D >> z3D; userdata_double.Append(x3D); userdata_double.Append(y3D); userdata_double.Append(z3D); break; case 5: // Model entity count: Vertices, Edges, Faces, Cells (Version 2) in >> modelverts >> modeledges >> modelfaces >> modelcells; userdata_int.Append(modelverts); userdata_int.Append(modeledges); userdata_int.Append(modelfaces); userdata_int.Append(modelcells); break; case 6: // Topological mesh-entity counts (#elements,#faces,#edges,#nodes) in >> nelts >> nfaces >> nedges >> nnodes; cout << nelts << " elements, " << nfaces << " faces, " << nedges << " edges, " << nnodes << " nodes" << endl; mesh.SetAllocSize(nnodes,2*nedges,nfaces,nelts); break; case 7: // NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), PID: { cout << "read nodes" << endl; for(int i=0; i> nodeid >> p.X() >> p.Y() >> p.Z() >> type >> pid; mesh.AddPoint(p); point_pids.Append(pid); if(pid > maxId0D) maxId0D = pid; //(*testout) << "point " << p << " type " << type << " mastersexist " << mastersexist << endl; } } break; case 8: // Number of Periodic Master Nodes in >> nperiodicmasternodes; break; case 9: // MasterNodeID, SlaveNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2) for(int i=0; i> dummyint; in >> dummyint; } break; case 10: // Number of Corner Periodic Master Nodes in >> ncornerperiodicmasternodes; break; case 11: // MasterNodeID, 3-SlaveNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2) for(int i=0; i> dummyint; for(int j=0; j<3; j++) in >> dummyint; } break; case 12: // Number of Cubic Periodic Master Nodes in >> ncubicperiodicmasternodes; break; case 13: //MasterNodeID, 7-SlaveNodeID's, TranslCodes for(int i=0; i> dummyint; for(int j=0; j<7; j++) in >> dummyint; } break; case 14: // EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), PID cout << "read edges" << endl; // nullstarted = false; segmentdata.SetSize(nedges); for(int i=0; i(7); *segmentdata[i] = -1; in >> dummyint; in >> (*segmentdata[i])[0] >> (*segmentdata[i])[1]; in >> type; in >> (*segmentdata[i])[2]; if((*segmentdata[i])[2] > maxId1D) maxId1D = (*segmentdata[i])[2]; } break; case 15: // Number of Periodic Master Edges in >> nperiodicmasteredges; break; case 16: // MasterEdgeID, SlaveEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2) for(int i=0; i> dummyint >> dummyint >> dummyint; break; case 17: // Number of Corner Periodic Master Edges in >> ncornerperiodicmasteredges; break; case 18: // MasterEdgeID, 3 SlaveEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2) for(int i=0; i> dummyint; for(int j=0; j<3; j++) in >> dummyint; for(int j=0; j<3; j++) in >> dummyint; } break; case 19: // FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PSlave), PID { //Segment seg; int segnum_ng[3]; bool neg[3]; cout << "read faces" << endl; // nullstarted = false; for(int i=0; i> trinum; for(int j=0; j<3; j++) { in >> segnum; neg[j] = (segnum<0); if(!neg[j]) segnum_ng[j] = segnum-1; else segnum_ng[j] = -segnum-1; if(neg[j]) tris.Last()->PNum(j+1) = (*segmentdata[segnum_ng[j]])[1]; else tris.Last()->PNum(j+1) = (*segmentdata[segnum_ng[j]])[0]; tris.Last()->GeomInfoPi(j+1).trignum = trinum; } in >> type; int faceid; in >> faceid; if(faceid > maxId2D) maxId2D = faceid; if(i==0 || faceid < minId2D) minId2D = faceid; tris.Last()->SetIndex(faceid); if(faceid > 0) { //if(nullstarted) // { // cout << "Faces: Assumption about index 0 wrong (face"<> nperiodicmasterfaces; break; case 21: // MasterFaceID, SlaveFaceID, TranslCode (1=dS1 2=dS2) { Vec<3> randomvec(-1.32834,3.82399,0.5429151); int maxtransl = -1; for(int i=0; i nodes1(3),nodes2(3); Array sortval1(3),sortval2(3); in >> tri1 >> tri2 >> transl; if(transl > maxtransl) maxtransl = transl; for(int j=0; j<3; j++) { nodes1[j] = tris[tri1-1]->PNum(j+1); sortval1[j] = Vec<3>(mesh[nodes1[j]])*randomvec; nodes2[j] = tris[tri2-1]->PNum(j+1); sortval2[j] = Vec<3>(mesh[nodes2[j]])*randomvec; } BubbleSort(sortval1,nodes1); BubbleSort(sortval2,nodes2); for(int j=0; j<3; j++) mesh.GetIdentifications().Add(nodes1[j],nodes2[j],transl); } for(int i=1; i<= maxtransl; i++) mesh.GetIdentifications().SetType(i,Identifications::PERIODIC); } break; case 22: // ElemID, FaceID0, FaceID1, FaceID2, FaceID3, PID { cout << "read elements (1)" << endl; //SurfaceElementIndex surf[4]; bool neg[4]; int elemid; int domain; eldom.SetSize(nelts); for(int i=0; i> elemid; for(int j=0; j<4;j++) { in >> dummyint; neg[j] = (dummyint < 0); if(neg[j]) tetfacedata.Append(-dummyint-1); //surf[j] = -dummyint-1; else tetfacedata.Append(dummyint-1); tetfacedata.Append(((neg[j]) ? 1 : 0)); //surf[j] = dummyint-1; } in >> domain; eldom[i] = domain; tetfacedata.Append(domain); if(i==0 || domain < minId3D) minId3D = domain; if(domain > maxId3D) maxId3D = domain; // for(int j=0; j<4; j++) // { // if(mesh.GetNSE() <= surf[j]) // continue; // int faceind = 0; // for(int k=1; k<=mesh.GetNFD(); k++) // { // if(mesh.GetFaceDescriptor(k).SurfNr() == mesh[surf[j]].GetIndex()) // faceind = k; // } // if(faceind) // { // if(neg[j]) // mesh.GetFaceDescriptor(faceind).SetDomainOut(domain); // else // mesh.GetFaceDescriptor(faceind).SetDomainIn(domain); // } // else // { // if(neg[j]) // faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf[j]].GetIndex(),0,domain,0)); // else // faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf[j]].GetIndex(),domain,0,0)); // mesh.GetFaceDescriptor(faceind).SetBCProperty(mesh[surf[j]].GetIndex()); // } // } } cout << endl; // Array indextodescriptor(maxId2D+1); // for(int i=1; i<=mesh.GetNFD(); i++) // indextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i; // for(SurfaceElementIndex i=0; i> dummyint; for(int j=1; j<=4; j++) in >> el.PNum(j); swap(el.PNum(1),el.PNum(2)); el.SetIndex(eldom[i]); mesh.AddVolumeElement(el); } } break; case 24: // Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D) { in >> numObj3D; userdata_int.Append(numObj3D); in >> numObj2D; userdata_int.Append(numObj2D); in >> numObj1D; userdata_int.Append(numObj1D); in >> numObj0D; userdata_int.Append(numObj0D); } break; case 25: // Number of Ports (Ports are a subset of Object2D list) { in >> dummyint; //userdata_int.Append(dummyint); } break; case 26: // Object3D GroupID, #Elems ElemID List { uid_to_group_3D.SetSize(maxId3D+1); uid_to_group_3D = -1; for(int i=0; i> groupid; (*testout) << "3d groupid " << groupid << endl; //userdata_int.Append(groupid); int nelems; in >> nelems; //userdata_int.Append(nelems); for(int j=0; j> dummyint; (*testout) << "read " << dummyint << endl; //userdata_int.Append(dummyint); if(dummyint < 0) dummyint *= -1; uid_to_group_3D[eldom[dummyint-1]] = groupid; } } } break; case 27: // Object2D GroupID, #Faces FaceID List { Array ports; //int totnum = 0; uid_to_group_2D.SetSize(maxId2D+1); uid_to_group_2D = -1; for(int i=0; i> groupid; (*testout) << "2d groupid " << groupid << endl; //userdata_int.Append(groupid); int nelems; in >> nelems; //userdata_int.Append(nelems); for(int j=0; j> dummyint; char port; while((port = in.get()) == ' ') ; (*testout) << "read " << dummyint << endl; if(dummyint < 0) dummyint *= -1; int uid = tris[dummyint-1]->GetIndex(); if(port == 'P' || port == 'p') { if(!ports.Contains(uid)) ports.Append(uid); } else in.putback(port); //userdata_int.Append(dummyint); uid_to_group_2D[uid] = groupid; (*testout) << "setting " << uid << endl; //totnum++; } } mesh.SetUserData("TETmesh:ports",ports); } break; case 28: // Object1D GroupID, #Edges EdgeID List { uid_to_group_1D.SetSize(maxId1D+1); uid_to_group_1D = -1; for(int i=0; i> groupid; //userdata_int.Append(groupid); int nelems; in >> nelems; //userdata_int.Append(nelems); for(int j=0; j> dummyint; //userdata_int.Append(dummyint); if(dummyint < 0) dummyint *= -1; uid_to_group_1D[(*segmentdata[dummyint-1])[2]] = groupid; } } } break; case 29: // Object0D GroupID, #Nodes NodeID List { uid_to_group_0D.SetSize(maxId0D+1); uid_to_group_0D = -1; for(int i=0; i> groupid; //userdata_int.Append(groupid); int nelems; in >> nelems; //userdata_int.Append(nelems); for(int j=0; j> dummyint; //userdata_int.Append(dummyint); if(dummyint < 0) dummyint *= -1; uid_to_group_0D[point_pids[dummyint-1]] = groupid; } } } break; default: done = true; } if(inputsection == 4 && version == "1.1") inputsection++; inputsection++; } in.close(); mesh.SetUserData("TETmesh:double",userdata_double); userdata_int.Append(minId2D); userdata_int.Append(minId3D); mesh.SetUserData("TETmesh:int",userdata_int); //if(version == "1.1") mesh.SetUserData("TETmesh:point_id",point_pids); mesh.SetUserData("TETmesh:uid_to_group_3D",uid_to_group_3D); mesh.SetUserData("TETmesh:uid_to_group_2D",uid_to_group_2D); mesh.SetUserData("TETmesh:uid_to_group_1D",uid_to_group_1D); mesh.SetUserData("TETmesh:uid_to_group_0D",uid_to_group_0D); Array surfindices(tris.Size()); surfindices = -1; for(int i=0; iGetIndex() > 0) surfindices[i] = mesh.AddSurfaceElement(*tris[i]); } else { if(tris[i]->GetIndex() > 0 && tris[i]->GetIndex() < minId3D) { tris[i]->SetIndex(tris[i]->GetIndex()-minId2D+1); surfindices[i] = mesh.AddSurfaceElement(*tris[i]); } } delete tris[i]; } mesh.ClearFaceDescriptors(); if(atof(version.c_str()) <= 1.999999) for(int i = 1; i <= maxId2D; i++) mesh.AddFaceDescriptor(FaceDescriptor(i,0,0,0)); else for(int i=minId2D; i indextodescriptor(maxId2D+1); // for(int i=1; i<=mesh.GetNFD(); i++) // indextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i; // for(SurfaceElementIndex i=0; i 0) || (atof(version.c_str()) > 1.999999 && (*segmentdata[i])[2] > 0 && (*segmentdata[i])[2] < minId2D)) { seg[0] = (*segmentdata[i])[0]; seg[1] = (*segmentdata[i])[1]; seg.edgenr = (*segmentdata[i])[2]; seg.epgeominfo[0].edgenr = (*segmentdata[i])[2]; seg.epgeominfo[1].edgenr = (*segmentdata[i])[2]; seg.si = (*segmentdata[i])[3]-minId2D+1; seg.surfnr1 = -1;//(*segmentdata[i])[3]; seg.surfnr2 = -1;//(*segmentdata[i])[4]; seg.geominfo[0].trignum = (*segmentdata[i])[5]; seg.geominfo[1].trignum = (*segmentdata[i])[5]; mesh.AddSegment(seg); seg[0] = (*segmentdata[i])[1]; seg[1] = (*segmentdata[i])[0]; seg.si = (*segmentdata[i])[4]-minId2D+1; seg.surfnr1 = -1;//(*segmentdata[i])[3]; seg.surfnr2 = -1;//(*segmentdata[i])[4]; seg.geominfo[0].trignum = (*segmentdata[i])[6]; seg.geominfo[1].trignum = (*segmentdata[i])[6]; mesh.AddSegment(seg); } delete segmentdata[i]; } /* for(int i=mesh.GetNSeg(); i>=1; i--) if(mesh.LineSegment(i).epgeominfo[0].edgenr == 0 || mesh.LineSegment(i).epgeominfo[1].edgenr == 0) mesh.FullDeleteSegment(i); */ mesh.CalcSurfacesOfNode(); } } netgen-6.2.1905/libsrc/interface/CMakeLists.txt0000644000175000017500000000134113504650527017756 0ustar kurtkurtadd_definitions(-DNGINTERFACE_EXPORTS) add_library(interface ${NG_LIB_TYPE} nginterface.cpp nginterface_v2.cpp read_fnf_mesh.cpp readtetmesh.cpp readuser.cpp writeabaqus.cpp writediffpack.cpp writedolfin.cpp writeelmer.cpp writefeap.cpp writefluent.cpp writegmsh.cpp writejcm.cpp writepermas.cpp writetecplot.cpp writetet.cpp writetochnog.cpp writeuser.cpp wuchemnitz.cpp writegmsh2.cpp writeOpenFOAM15x.cpp ) target_link_libraries(interface mesh csg geom2d) target_link_libraries(interface visual) if(NOT WIN32) install( TARGETS interface ${NG_INSTALL_DIR}) endif(NOT WIN32) install(FILES writeuser.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/interface COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/csg/0000755000175000017500000000000013504650527014033 5ustar kurtkurtnetgen-6.2.1905/libsrc/csg/triapprox.cpp0000644000175000017500000000201113504650527016561 0ustar kurtkurt#include #include #include #include namespace netgen { TriangleApproximation :: TriangleApproximation () { ; } int TriangleApproximation :: AddTriangle (const TATriangle & tri, bool invert) { trigs.Append (tri); if (invert) { trigs.Last()[1] = tri[2]; trigs.Last()[2] = tri[1]; } return trigs.Size()-1; } void TriangleApproximation :: RemoveUnusedPoints () { BitArray used(GetNP()); Array map (GetNP()); int i, j; int cnt = 0; used.Clear(); for (i = 0; i < GetNT(); i++) for (j = 0; j < 3; j++) used.Set (GetTriangle (i)[j]); for (i = 0; i < GetNP(); i++) if (used.Test(i)) map[i] = cnt++; for (i = 0; i < GetNT(); i++) for (j = 0; j < 3; j++) trigs[i][j] = map[trigs[i][j]]; for (i = 0; i < GetNP(); i++) if (used.Test(i)) { points[map[i]] = points[i]; normals[map[i]] = normals[i]; } points.SetSize (cnt); normals.SetSize (cnt); } } netgen-6.2.1905/libsrc/csg/algprim.cpp0000644000175000017500000013132613504650527016200 0ustar kurtkurt#include #include #include namespace netgen { double QuadraticSurface :: CalcFunctionValue (const Point<3> & p) const { return p(0) * (cxx * p(0) + cxy * p(1) + cxz * p(2) + cx) + p(1) * (cyy * p(1) + cyz * p(2) + cy) + p(2) * (czz * p(2) + cz) + c1; } void QuadraticSurface :: CalcGradient (const Point<3> & p, Vec<3> & grad) const { grad(0) = 2 * cxx * p(0) + cxy * p(1) + cxz * p(2) + cx; grad(1) = 2 * cyy * p(1) + cxy * p(0) + cyz * p(2) + cy; grad(2) = 2 * czz * p(2) + cxz * p(0) + cyz * p(1) + cz; } void QuadraticSurface :: CalcHesse (const Point<3> & /* p */, Mat<3> & hesse) const { hesse(0,0) = 2 * cxx; hesse(1,1) = 2 * cyy; hesse(2,2) = 2 * czz; hesse(0,1) = hesse(1,0) = cxy; hesse(0,2) = hesse(2,0) = cxz; hesse(1,2) = hesse(2,1) = cyz; } void QuadraticSurface :: Read (istream & ist) { ist >> cxx >> cyy >> czz >> cxy >> cxz >> cyz >> cx >> cy >> cz >> c1; } void QuadraticSurface :: Print (ostream & ost) const { ost << cxx << " " << cyy << " " << czz << " " << cxy << " " << cxz << " " << cyz << " " << cx << " " << cy << " " << cz << " " << c1; } void QuadraticSurface :: PrintCoeff (ostream & ost) const { ost << " cxx = " << cxx << " cyy = " << cyy << " czz = " << czz << " cxy = " << cxy << " cxz = " << cxz << " cyz = " << cyz << " cx = " << cx << " cy = " << cy << " cz = " << cz << " c1 = " << c1 << endl; } Point<3> QuadraticSurface :: GetSurfacePoint () const { MyError ("GetSurfacePoint called for QuadraticSurface"); return Point<3> (0, 0, 0); } Plane :: Plane (const Point<3> & ap, Vec<3> an) { eps_base = 1e-8; p = ap; n = an; CalcData(); } void Plane :: CalcData() { n.Normalize(); cxx = cyy = czz = cxy = cxz = cyz = 0; cx = n(0); cy = n(1); cz = n(2); c1 = - (cx * p(0) + cy * p(1) + cz * p(2)); } Primitive * Plane :: Copy () const { return new Plane (p, n); } void Plane :: Print (ostream & ost) const { ost << "plane(" << p << "; " << n << ")"; } void Plane :: Transform (Transformation<3> & trans) { Point<3> hp; Vec<3> hn; trans.Transform (p, hp); trans.Transform (n, hn); p = hp; n = hn; CalcData(); } void Plane :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "plane"; coeffs.SetSize (6); coeffs.Elem(1) = p(0); coeffs.Elem(2) = p(1); coeffs.Elem(3) = p(2); coeffs.Elem(4) = n(0); coeffs.Elem(5) = n(1); coeffs.Elem(6) = n(2); } void Plane :: SetPrimitiveData (Array & coeffs) { p(0) = coeffs.Elem(1); p(1) = coeffs.Elem(2); p(2) = coeffs.Elem(3); n(0) = coeffs.Elem(4); n(1) = coeffs.Elem(5); n(2) = coeffs.Elem(6); CalcData(); } Primitive * Plane :: CreateDefault () { return new Plane (Point<3> (0,0,0), Vec<3> (0,0,1)); } int Plane :: IsIdentic (const Surface & s2, int & inv, double eps) const { const Plane * ps2 = dynamic_cast(&s2); if(ps2) { Point<3> pp2 = ps2->GetSurfacePoint(); Vec<3> n2 = s2.GetNormalVector(pp2); if(fabs(n*n2) < 1.-eps_base) return 0; if (fabs (s2.CalcFunctionValue(p)) > eps) return 0; } else { if (fabs (s2.CalcFunctionValue(p)) > eps) return 0; Vec<3> hv1, hv2; hv1 = n.GetNormal (); hv2 = Cross (n, hv1); Point<3> hp = p + hv1; if (fabs (s2.CalcFunctionValue(hp)) > eps) return 0; hp = p + hv2; if (fabs (s2.CalcFunctionValue(hp)) > eps) return 0; } Vec<3> n1, n2; n1 = GetNormalVector (p); n2 = s2.GetNormalVector (p); inv = (n1 * n2 < 0); return 1; } void Plane :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2) { Surface::DefineTangentialPlane (ap1, ap2); } void Plane :: ToPlane (const Point<3> & p3d, Point<2> & pplane, double h, int & zone) const { Vec<3> p1p; p1p = p3d - p1; p1p /= h; pplane(0) = p1p * ex; pplane(1) = p1p * ey; zone = 0; } void Plane :: FromPlane (const Point<2> & pplane, Point<3> & p3d, double h) const { p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey; } void Plane :: Project (Point<3> & p3d) const { double val = Plane::CalcFunctionValue (p3d); p3d -= val * n; } INSOLID_TYPE Plane :: BoxInSolid (const BoxSphere<3> & box) const { int i; double val; Point<3> pp; val = Plane::CalcFunctionValue (box.Center()); if (val > box.Diam() / 2) return IS_OUTSIDE; if (val < -box.Diam() / 2) return IS_INSIDE; if (val > 0) { /* double modify = ((box.MaxX()-box.MinX()) * fabs (cx) + (box.MaxY()-box.MinY()) * fabs (cy) + (box.MaxZ()-box.MinZ()) * fabs (cz)) / 2; */ Vec<3> vdiag = box.PMax() - box.PMin(); double modify = (vdiag(0) * fabs (cx) + vdiag(1) * fabs (cy) + vdiag(2) * fabs (cz) ) / 2; if (val - modify < 0) return DOES_INTERSECT; return IS_OUTSIDE; // only outside or intersect possible for (i = 0; i < 8; i++) { pp = box.GetPointNr (i); val = Plane::CalcFunctionValue (pp); if (val < 0) return DOES_INTERSECT; } return IS_OUTSIDE; } else { /* double modify = ((box.MaxX()-box.MinX()) * fabs (cx) + (box.MaxY()-box.MinY()) * fabs (cy) + (box.MaxZ()-box.MinZ()) * fabs (cz)) / 2; */ Vec<3> vdiag = box.PMax() - box.PMin(); double modify = (vdiag(0) * fabs (cx) + vdiag(1) * fabs (cy) + vdiag(2) * fabs (cz) ) / 2; if (val + modify > 0) return DOES_INTERSECT; return IS_INSIDE; // only inside or intersect possible for (i = 0; i < 8; i++) { pp = box.GetPointNr (i); val = Plane::CalcFunctionValue (pp); if (val > 0) return DOES_INTERSECT; } return IS_INSIDE; } /* for (i = 1; i <= 8; i++) { box.GetPointNr (i, p); val = CalcFunctionValue (p); if (val > 0) inside = 0; if (val < 0) outside = 0; } if (inside) return IS_INSIDE; if (outside) return IS_OUTSIDE; return DOES_INTERSECT; */ } // double Plane :: CalcFunctionValue (const Point<3> & p3d) const // { // return cx * p3d(0) + cy * p3d(1) + cz * p3d(2) + c1; // } void Plane :: CalcGradient (const Point<3> & /* p */, Vec<3> & grad) const { grad(0) = cx; grad(1) = cy; grad(2) = cz; } void Plane :: CalcHesse (const Point<3> & /* p */, Mat<3> & hesse) const { hesse = 0; } double Plane :: HesseNorm () const { return 0; } Point<3> Plane :: GetSurfacePoint () const { return p; } void Plane :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double /* facets */) const { // find triangle, such that // boundingbox \cap plane is contained in it Point<3> c = boundingbox.Center(); double r = boundingbox.Diam(); Project (c); Vec<3> t1 = n.GetNormal(); Vec<3> t2 = Cross (n, t1); t1.Normalize(); t2.Normalize(); tas.AddPoint (c + (-0.5 * r) * t2 + (sqrt(0.75) * r) * t1); tas.AddPoint (c + (-0.5 * r) * t2 + (-sqrt(0.75) * r) * t1); tas.AddPoint (c + r * t2); tas.AddTriangle (TATriangle (0, 0, 1, 2)); } Sphere :: Sphere (const Point<3> & ac, double ar) { c = ac; r = ar; invr = 1.0/r; cxx = cyy = czz = 0.5 / r; cxy = cxz = cyz = 0; cx = - c(0) / r; cy = - c(1) / r; cz = - c(2) / r; c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2; } void Sphere :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "sphere"; coeffs.SetSize (4); coeffs.Elem(1) = c(0); coeffs.Elem(2) = c(1); coeffs.Elem(3) = c(2); coeffs.Elem(4) = r; } void Sphere :: SetPrimitiveData (Array & coeffs) { c(0) = coeffs.Elem(1); c(1) = coeffs.Elem(2); c(2) = coeffs.Elem(3); r = coeffs.Elem(4); invr = 1.0/r; cxx = cyy = czz = 0.5 / r; cxy = cxz = cyz = 0; cx = - c(0) / r; cy = - c(1) / r; cz = - c(2) / r; c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2; } Primitive * Sphere :: CreateDefault () { return new Sphere (Point<3> (0,0,0), 1); } Primitive * Sphere :: Copy () const { return new Sphere (c, r); } void Sphere :: Transform (Transformation<3> & trans) { Point<3> hp; trans.Transform (c, hp); c = hp; cxx = cyy = czz = 0.5 / r; cxy = cxz = cyz = 0; cx = - c(0) / r; cy = - c(1) / r; cz = - c(2) / r; c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2; } double Sphere :: CalcFunctionValue (const Point<3> & point) const { return 0.5* (invr * Abs2 (point-c) - r); } int Sphere :: IsIdentic (const Surface & s2, int & inv, double eps) const { const Sphere * sp2 = dynamic_cast (&s2); if (!sp2) return 0; if (Dist (sp2->c, c) > eps) return 0; if (fabs (sp2->r - r) > eps) return 0; inv = 0; return 1; } void Sphere :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2) { Surface::DefineTangentialPlane (ap1, ap2); ez = p1 - c; ez /= ez.Length(); ex = p2 - p1; ex -= (ex * ez) * ez; ex /= ex.Length(); ey = Cross (ez, ex); } void Sphere :: ToPlane (const Point<3> & p, Point<2> & pplane, double h, int & zone) const { Vec<3> p1p; p1p = p - p1; /* if (p1p * ez < -r) { zone = -1; pplane = Point<2> (1E8, 1E8); } else { zone = 0; p1p /= h; pplane(0) = p1p * ex; pplane(1) = p1p * ey; } */ Point<3> p1top = c + (c - p1); Vec<3> p1topp = p - p1top; Vec<3> p1topp1 = p1 - p1top; Vec<3> lam; // SolveLinearSystem (ex, ey, p1topp, p1topp1, lam); Mat<3> m; for (int i = 0; i < 3; i++) { m(i, 0) = ex(i); m(i, 1) = ey(i); m(i, 2) = p1topp(i); } m.Solve (p1topp1, lam); pplane(0) = -lam(0) / h; pplane(1) = -lam(1) / h; if (lam(2) > 2) zone = -1; else zone = 0; } void Sphere :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const { /* // Vec<3> p1p; double z; Point<2> pplane2 (pplane); pplane2(0) *= h; pplane2(1) *= h; z = -r + sqrt (sqr (r) - sqr (pplane2(0)) - sqr (pplane2(1))); // p = p1; p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0) + z * ez(0); p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1) + z * ez(1); p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2) + z * ez(2); */ Point<2> pplane2 (pplane); pplane2(0) *= h; pplane2(1) *= h; p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0); p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1); p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2); Project (p); } void Sphere :: Project (Point<3> & p) const { Vec<3> v; v = p - c; v *= (r / v.Length()); p = c + v; } INSOLID_TYPE Sphere :: BoxInSolid (const BoxSphere<3> & box) const { double dist; dist = Dist (box.Center(), c); if (dist - box.Diam()/2 > r) return IS_OUTSIDE; if (dist + box.Diam()/2 < r) return IS_INSIDE; return DOES_INTERSECT; } double Sphere :: HesseNorm () const { return 2 / r; } Point<3> Sphere :: GetSurfacePoint () const { // if two spheres touch at exactly that point meshing fails. return c + r * Vec<3> (0.12345, 0.54321, 0.8304715488203073); } void Sphere :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & /* boundingbox */, double facets) const { int n = int(facets) + 1; for (int j = 0; j <= n; j++) for (int i = 0; i <= n; i++) { double lg = 2 * M_PI * double (i) / n; double bg = M_PI * (double(j) / n - 0.5); Point<3> p(c(0) + r * cos(bg) * sin (lg), c(1) + r * cos(bg) * cos (lg), c(2) + r * sin(bg)); tas.AddPoint (p); } for (int j = 0; j < n; j++) for (int i = 0; i < n; i++) { int pi = i + (n+1) * j; tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2)); tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1)); } } Ellipsoid :: Ellipsoid (const Point<3> & aa, const Vec<3> & av1, const Vec<3> & av2, const Vec<3> & av3) { a = aa; v1 = av1; v2 = av2; v3 = av3; CalcData(); } void Ellipsoid :: CalcData () { // f = (x-a, vl)^2 / |vl|^2 + (x-a, vs)^2 / |vs|^2 -1 // f = sum_{i=1}^3 (x-a,v_i)^2 / |vi|^4 - 1 = sum (x-a,hv_i)^2 Vec<3> hv1, hv2, hv3; double lv1 = v1.Length2 (); if (lv1 < 1e-32) lv1 = 1; double lv2 = v2.Length2 (); if (lv2 < 1e-32) lv2 = 1; double lv3 = v3.Length2 (); if (lv3 < 1e-32) lv3 = 1; rmin = sqrt (min3 (lv1, lv2, lv3)); hv1 = (1.0 / lv1) * v1; hv2 = (1.0 / lv2) * v2; hv3 = (1.0 / lv3) * v3; cxx = hv1(0) * hv1(0) + hv2(0) * hv2(0) + hv3(0) * hv3(0); cyy = hv1(1) * hv1(1) + hv2(1) * hv2(1) + hv3(1) * hv3(1); czz = hv1(2) * hv1(2) + hv2(2) * hv2(2) + hv3(2) * hv3(2); cxy = 2 * (hv1(0) * hv1(1) + hv2(0) * hv2(1) + hv3(0) * hv3(1)); cxz = 2 * (hv1(0) * hv1(2) + hv2(0) * hv2(2) + hv3(0) * hv3(2)); cyz = 2 * (hv1(1) * hv1(2) + hv2(1) * hv2(2) + hv3(1) * hv3(2)); Vec<3> va (a); c1 = sqr(va * hv1) + sqr(va * hv2) + sqr(va * hv3) - 1; Vec<3> v = -2 * (va * hv1) * hv1 - 2 * (va * hv2) * hv2 - 2 * (va * hv3) * hv3; cx = v(0); cy = v(1); cz = v(2); } INSOLID_TYPE Ellipsoid :: BoxInSolid (const BoxSphere<3> & box) const { // double grad = 2.0 / rmin; // double grad = 3*(box.Center()-a).Length() / (rmin*rmin*rmin); double ggrad = 1.0 / (rmin*rmin); Vec<3> g; double val = CalcFunctionValue (box.Center()); CalcGradient (box.Center(), g); double grad = g.Length(); double r = box.Diam() / 2; double maxval = grad * r + ggrad * r * r; // (*testout) << "box = " << box << ", val = " << val << ", maxval = " << maxval << endl; if (val > maxval) return IS_OUTSIDE; if (val < -maxval) return IS_INSIDE; return DOES_INTERSECT; } double Ellipsoid :: HesseNorm () const { return 1.0/ (rmin * rmin); } double Ellipsoid :: MaxCurvature () const { const double a2 = v1.Length2(); const double b2 = v2.Length2(); const double c2 = v3.Length2(); return max3 ( sqrt(a2)/min2(b2,c2), sqrt(b2)/min2(a2,c2), sqrt(c2)/min2(a2,b2) ); } Point<3> Ellipsoid :: GetSurfacePoint () const { return a + v1; } void Ellipsoid :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & /* boundingbox */, double facets) const { int n = int(facets) + 1; for (int j = 0; j <= n; j++) for (int i = 0; i <= n; i++) { double lg = 2 * M_PI * double (i) / n; double bg = M_PI * (double(j) / n - 0.5); Point<3> p(a + sin (bg) * v1 + cos (bg) * sin (lg) * v2 + cos (bg) * cos (lg) * v3); tas.AddPoint (p); } for (int j = 0; j < n; j++) for (int i = 0; i < n; i++) { int pi = i + (n+1) * j; tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2)); tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1)); } } Cylinder :: Cylinder (Array & coeffs) { SetPrimitiveData(coeffs); } Cylinder :: Cylinder (const Point<3> & aa, const Point<3> & ab, double ar) { a = aa; b = ab; vab = (b - a); vab /= vab.Length(); r = ar; // ( - 2 + // - ^2 + 2 - ^2 // - r^2) / (2r) = 0 double hv; cxx = cyy = czz = 0.5 / r; cxy = cxz = cyz = 0; cx = - a(0) / r; cy = - a(1) / r; cz = - a(2) / r; c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r); hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2); cxx -= vab(0) * vab(0) / (2 * r); cyy -= vab(1) * vab(1) / (2 * r); czz -= vab(2) * vab(2) / (2 * r); cxy -= vab(0) * vab(1) / r; cxz -= vab(0) * vab(2) / r; cyz -= vab(1) * vab(2) / r; cx += vab(0) * hv / r; cy += vab(1) * hv / r; cz += vab(2) * hv / r; c1 -= hv * hv / (2 * r); c1 -= r / 2; // PrintCoeff (); } void Cylinder :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "cylinder"; coeffs.SetSize (7); coeffs.Elem(1) = a(0); coeffs.Elem(2) = a(1); coeffs.Elem(3) = a(2); coeffs.Elem(4) = b(0); coeffs.Elem(5) = b(1); coeffs.Elem(6) = b(2); coeffs.Elem(7) = r; } void Cylinder :: SetPrimitiveData (Array & coeffs) { a(0) = coeffs.Elem(1); a(1) = coeffs.Elem(2); a(2) = coeffs.Elem(3); b(0) = coeffs.Elem(4); b(1) = coeffs.Elem(5); b(2) = coeffs.Elem(6); r = coeffs.Elem(7); vab = (b - a); vab /= vab.Length(); double hv; cxx = cyy = czz = 0.5 / r; cxy = cxz = cyz = 0; cx = - a(0) / r; cy = - a(1) / r; cz = - a(2) / r; c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r); hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2); cxx -= vab(0) * vab(0) / (2 * r); cyy -= vab(1) * vab(1) / (2 * r); czz -= vab(2) * vab(2) / (2 * r); cxy -= vab(0) * vab(1) / r; cxz -= vab(0) * vab(2) / r; cyz -= vab(1) * vab(2) / r; cx += vab(0) * hv / r; cy += vab(1) * hv / r; cz += vab(2) * hv / r; c1 -= hv * hv / (2 * r); c1 -= r / 2; } Primitive * Cylinder :: CreateDefault () { return new Cylinder (Point<3> (0,0,0), Point<3> (1,0,0), 1); } Primitive * Cylinder :: Copy () const { return new Cylinder (a, b, r); } void Cylinder :: Print (ostream & ost) const { ost << "cylinder(" << a << "; " << b << "; " << r << ")"; } int Cylinder :: IsIdentic (const Surface & s2, int & inv, double eps) const { const Cylinder * cyl2 = dynamic_cast (&s2); if (!cyl2) return 0; if (fabs (cyl2->r - r) > eps) return 0; Vec<3> v1 = b - a; Vec<3> v2 = cyl2->a - a; if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0; v2 = cyl2->b - a; if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0; inv = 0; return 1; } void Cylinder :: Transform (Transformation<3> & trans) { Point<3> hp; trans.Transform (a, hp); a = hp; trans.Transform (b, hp); b = hp; vab = (b - a); vab /= vab.Length(); // ( - 2 + // - ^2 + 2 - ^2 // - r^2) / (2r) = 0 double hv; cxx = cyy = czz = 0.5 / r; cxy = cxz = cyz = 0; cx = - a(0) / r; cy = - a(1) / r; cz = - a(2) / r; c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r); hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2); cxx -= vab(0) * vab(0) / (2 * r); cyy -= vab(1) * vab(1) / (2 * r); czz -= vab(2) * vab(2) / (2 * r); cxy -= vab(0) * vab(1) / r; cxz -= vab(0) * vab(2) / r; cyz -= vab(1) * vab(2) / r; cx += vab(0) * hv / r; cy += vab(1) * hv / r; cz += vab(2) * hv / r; c1 -= hv * hv / (2 * r); c1 -= r / 2; // PrintCoeff (); } void Cylinder :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2) { Surface::DefineTangentialPlane (ap1, ap2); ez = Center (p1, p2) - a; ez -= (ez * vab) * vab; ez /= ez.Length(); ex = p2 - p1; ex -= (ex * ez) * ez; ex /= ex.Length(); ey = Cross (ez, ex); } void Cylinder :: ToPlane (const Point<3> & p, Point<2> & pplane, double h, int & zone) const { Point<3> cp1p2 = Center (p1, p2); Project (cp1p2); Point<3> ccp1p2 = a + ( (cp1p2 - a) * vab ) * vab; Vec<3> er = cp1p2 - ccp1p2; er.Normalize(); Vec<3> ephi = Cross (vab, er); double co, si; Point<2> p1p, p2p, pp; co = er * (p1 - ccp1p2); si = ephi * (p1 - ccp1p2); p1p(0) = r * atan2 (si, co); p1p(1) = vab * (p1 - ccp1p2); co = er * (p2 - ccp1p2); si = ephi * (p2 - ccp1p2); p2p(0) = r * atan2 (si, co); p2p(1) = vab * (p2 - ccp1p2); co = er * (p - ccp1p2); si = ephi * (p - ccp1p2); double phi = atan2 (si, co); pp(0) = r * phi; pp(1) = vab * (p - ccp1p2); zone = 0; if (phi > 1.57) zone = 1; if (phi < -1.57) zone = 2; Vec<2> e2x = p2p - p1p; e2x /= e2x.Length(); Vec<2> e2y (-e2x(1), e2x(0)); Vec<2> p1pp = pp - p1p; pplane(0) = (p1pp * e2x) / h; pplane(1) = (p1pp * e2y) / h; /* (*testout) << "p1 = " << p1 << ", p2 = " << p2 << endl; (*testout) << "p = " << p << ", pp = " << pp << ", pplane = " << pplane << endl; */ /* Vec<3> p1p; p1p = p - p1; if (p1p * ez < -1 * r) { zone = -1; pplane(0) = 1e8; pplane(1) = 1e8; } else { zone = 0; p1p /= h; pplane(0) = p1p * ex; pplane(1) = p1p * ey; } */ } void Cylinder :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const { Point<2> pplane2 (pplane); pplane2(0) *= h; pplane2(1) *= h; p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0); p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1); p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2); Project (p); } void Cylinder :: Project (Point<3> & p) const { Vec<3> v; Point<3> c; c = a + ((p - a) * vab) * vab; v = p - c; v *= (r / v.Length()); p = c + v; } /* int Cylinder :: RootInBox (const BoxSphere<3> & box) const { double dist; dist = sqrt (2 * CalcFunctionValue(box.Center()) * r + r * r); if (fabs (dist - r) > box.Diam()/2) return 0; return 2; } */ INSOLID_TYPE Cylinder :: BoxInSolid (const BoxSphere<3> & box) const { double dist; // dist = sqrt (2 * CalcFunctionValue(box.Center()) * r + r * r); dist = (2 * CalcFunctionValue(box.Center()) * r + r * r); if (dist <= 0) dist = 0; else dist = sqrt (dist + 1e-16); if (dist - box.Diam()/2 > r) return IS_OUTSIDE; if (dist + box.Diam()/2 < r) return IS_INSIDE; return DOES_INTERSECT; } double Cylinder :: HesseNorm () const { return 2 / r; } Point<3> Cylinder :: GetSurfacePoint () const { Vec<3> vr; if (fabs (vab(0)) > fabs(vab(2))) vr = Vec<3> (vab(1), -vab(0), 0); else vr = Vec<3> (0, -vab(2), vab(1)); vr *= (r / vr.Length()); return a + vr; } void Cylinder :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & /* boundingbox */, double facets) const { int n = int(facets) + 1; Vec<3> lvab = b - a; Vec<3> n1 = lvab.GetNormal(); Vec<3> n2 = Cross (lvab, n1); n1.Normalize(); n2.Normalize(); for (int j = 0; j <= n; j++) for (int i = 0; i <= n; i++) { double lg = 2 * M_PI * double (i) / n; double bg = double(j) / n; Point<3> p = a + (bg * lvab) + ((r * cos(lg)) * n1) + ((r * sin(lg)) * n2); tas.AddPoint (p); } for (int j = 0; j < n; j++) for (int i = 0; i < n; i++) { int pi = i + (n+1) * j; tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2)); tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1)); } } EllipticCylinder :: EllipticCylinder (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs) { a = aa; if(avl.Length2() > avs.Length2()) { vl = avl; vs = avs; } else { vl = avs; vs = avl; } CalcData(); } EllipticCylinder :: EllipticCylinder (Array & coeffs) { SetPrimitiveData(coeffs); } void EllipticCylinder :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "ellipticcylinder"; coeffs.SetSize (9); coeffs[0] = a(0); coeffs[1] = a(1); coeffs[2] = a(2); coeffs[3] = vl(0); coeffs[4] = vl(1); coeffs[5] = vl(2); coeffs[6] = vs(0); coeffs[7] = vs(1); coeffs[8] = vs(2); } void EllipticCylinder :: SetPrimitiveData (Array & coeffs) { a(0) = coeffs[0]; a(1) = coeffs[1]; a(2) = coeffs[2]; vl(0) = coeffs[3]; vl(1) = coeffs[4]; vl(2) = coeffs[5]; vs(0) = coeffs[6]; vs(1) = coeffs[7]; vs(2) = coeffs[8]; CalcData(); } void EllipticCylinder :: CalcData () { // f = (x-a, vl)^2 / |vl|^2 + (x-a, vs)^2 / |vs|^2 -1 Vec<3> hvl, hvs; double lvl = vl.Length2 (); if (lvl < 1e-32) lvl = 1; double lvs = vs.Length2 (); if (lvs < 1e-32) lvs = 1; hvl = (1.0 / lvl) * vl; hvs = (1.0 / lvs) * vs; cxx = hvl(0) * hvl(0) + hvs(0) * hvs(0); cyy = hvl(1) * hvl(1) + hvs(1) * hvs(1); czz = hvl(2) * hvl(2) + hvs(2) * hvs(2); cxy = 2 * (hvl(0) * hvl(1) + hvs(0) * hvs(1)); cxz = 2 * (hvl(0) * hvl(2) + hvs(0) * hvs(2)); cyz = 2 * (hvl(1) * hvl(2) + hvs(1) * hvs(2)); Vec<3> va (a); c1 = pow(va * hvl,2) + pow(va * hvs,2) - 1; Vec<3> v = -2 * (va * hvl) * hvl - 2 * (va * hvs) * hvs; cx = v(0); cy = v(1); cz = v(2); } INSOLID_TYPE EllipticCylinder :: BoxInSolid (const BoxSphere<3> & box) const { double grad = 2.0 / vs.Length (); double ggrad = 1.0 / vs.Length2 (); double val = CalcFunctionValue (box.Center()); double r = box.Diam() / 2; double maxval = grad * r + ggrad * r * r; // (*testout) << "box = " << box << ", val = " << val << ", maxval = " << maxval << endl; if (val > maxval) return IS_OUTSIDE; if (val < -maxval) return IS_INSIDE; return DOES_INTERSECT; } double EllipticCylinder :: HesseNorm () const { return 1.0/min(vs.Length2 (),vl.Length2()); } double EllipticCylinder :: MaxCurvature () const { double aa = vs.Length(); double bb = vl.Length(); return max2(bb/(aa*aa),aa/(bb*bb)); } double EllipticCylinder :: MaxCurvatureLoc (const Point<3> & /* c */, double /* rad */) const { // saubere Loesung wird noch notwendig !!! double aa = vs.Length(); double bb = vl.Length(); return max2(bb/(aa*aa),aa/(bb*bb)); } int EllipticCylinder :: IsIdentic(const Surface& s2, int& inv, double eps) const { const EllipticCylinder* ps2 = dynamic_cast(&s2); if (!ps2) return 0; if((vl - ps2->vl).Length() > eps || (vs - ps2->vs).Length() > eps || (a-ps2->a).Length() > eps) return 0; return 1; } Point<3> EllipticCylinder :: GetSurfacePoint () const { return a + vl; } void EllipticCylinder :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & /* boundingbox */, double facets) const { int n = int(facets) + 1; Vec<3> axis = Cross (vl, vs); for (int j = 0; j <= n; j++) for (int i = 0; i <= n; i++) { double lg = 2 * M_PI * double (i) / n; double bg = double(j) / n; Point<3> p = a + (bg * axis) + cos(lg) * vl + sin(lg) * vs; tas.AddPoint (p); } for (int j = 0; j < n; j++) for (int i = 0; i < n; i++) { int pi = i + (n+1) * j; tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2)); tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1)); } } Cone :: Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb) { a = aa; b = ab; ra = ara; rb = arb; CalcData(); // Print (cout); } Primitive * Cone :: CreateDefault () { return new Cone (Point<3> (0,0,0), Point<3> (1,0,0), 0.5, 0.2); } void Cone :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "cone"; coeffs.SetSize (8); coeffs.Elem(1) = a(0); coeffs.Elem(2) = a(1); coeffs.Elem(3) = a(2); coeffs.Elem(4) = b(0); coeffs.Elem(5) = b(1); coeffs.Elem(6) = b(2); coeffs.Elem(7) = ra; coeffs.Elem(8) = rb; } void Cone :: SetPrimitiveData (Array & coeffs) { a(0) = coeffs.Elem(1); a(1) = coeffs.Elem(2); a(2) = coeffs.Elem(3); b(0) = coeffs.Elem(4); b(1) = coeffs.Elem(5); b(2) = coeffs.Elem(6); ra = coeffs.Elem(7); rb = coeffs.Elem(8); CalcData(); } void Cone :: CalcData () { minr = (ra < rb) ? ra : rb; vab = b - a; vabl = vab.Length(); Vec<3> va (a); // // f = r(P)^2 - R(z(P))^2 // // z(P) = t0vec * P + t0 = (P-a, b-a)/(b-a,b-a) // R(z(P)) = t1vec * P + t1 = rb * z + ra * (1-z) // r(P)^2 =||P-a||^2 - ||a-b||^2 z^2k cosphi = vabl / sqrt (vabl*vabl+sqr(ra-rb)); t0vec = vab; t0vec /= (vabl * vabl); t0 = -(va * vab) / (vabl * vabl); t1vec = t0vec; t1vec *= (rb - ra); t1 = ra + (rb - ra) * t0; cxx = cyy = czz = 1; cxy = cxz = cyz = 0; cxx = 1 - (vab*vab) * t0vec(0) * t0vec(0) - t1vec(0) * t1vec(0); cyy = 1 - (vab*vab) * t0vec(1) * t0vec(1) - t1vec(1) * t1vec(1); czz = 1 - (vab*vab) * t0vec(2) * t0vec(2) - t1vec(2) * t1vec(2); cxy = -2 * (vab * vab) * t0vec(0) * t0vec(1) - 2 * t1vec(0) * t1vec(1); cxz = -2 * (vab * vab) * t0vec(0) * t0vec(2) - 2 * t1vec(0) * t1vec(2); cyz = -2 * (vab * vab) * t0vec(1) * t0vec(2) - 2 * t1vec(1) * t1vec(2); cx = -2 * a(0) - 2 * (vab * vab) * t0 * t0vec(0) - 2 * t1 * t1vec(0); cy = -2 * a(1) - 2 * (vab * vab) * t0 * t0vec(1) - 2 * t1 * t1vec(1); cz = -2 * a(2) - 2 * (vab * vab) * t0 * t0vec(2) - 2 * t1 * t1vec(2); c1 = va.Length2() - (vab * vab) * t0 * t0 - t1 * t1; double maxr = max2(ra,rb); cxx /= maxr; cyy /= maxr; czz /= maxr; cxy /= maxr; cxz /= maxr; cyz /= maxr; cx /= maxr; cy /= maxr; cz /= maxr; c1 /= maxr; // (*testout) << "t0vec = " << t0vec << " t0 = " << t0 << endl; // (*testout) << "t1vec = " << t1vec << " t1 = " << t1 << endl; // PrintCoeff (*testout); } INSOLID_TYPE Cone :: BoxInSolid (const BoxSphere<3> & box) const { Vec<3> cv(box.Center()); double rzp = cv * t1vec + t1; double dist = sqrt (CalcFunctionValue(box.Center()) *max2(ra,rb) + rzp * rzp) - rzp; dist *= cosphi; INSOLID_TYPE res = DOES_INTERSECT; if (dist - box.Diam() > 0) res = IS_OUTSIDE; if (dist + box.Diam() < 0) res = IS_INSIDE; return res; } double Cone :: HesseNorm () const { // cout << "2/minr = " << 2/minr << ", cxx .. = " << cxx << ", " << cyy << ", " << czz << endl; return 2 / minr; } double Cone :: LocH (const Point<3> & p, double /* x */, double /* c */, const MeshingParameters & mparam, double hmax) const { //double bloch = Surface::LocH (p, x, c, hmax); Vec<3> g; CalcGradient (p, g); double lam = Abs(g); double meancurv = -( 2 * g(0)*g(1)*cxy - 2 * czz * (g(0)*g(0)+g(1)*g(1)) +2 * g(1)*g(2)*cyz - 2 * cxx * (g(1)*g(1)+g(2)*g(2)) +2 * g(0)*g(2)*cxz - 2 * cyy * (g(0)*g(0)+g(2)*g(2))) / (3*lam*lam*lam); // cout << "type = " << typeid(*this).name() << ", baseh = " << bloch << ", meancurv = " << meancurv << endl; // return bloch; meancurv = fabs (meancurv); if (meancurv < 1e-20) meancurv = 1e-20; // cout << "c = " << c << ", safety = " << mparam.curvaturesafety << endl; double hcurv = 1.0/(4*meancurv*mparam.curvaturesafety); return min2 (hmax, hcurv); } Point<3> Cone :: GetSurfacePoint () const { Vec<3> vr = vab.GetNormal (); vr *= (ra / vr.Length()); return a + vr; } void Cone :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & /* boundingbox */, double facets) const { int i, j; double lg, bg; int n = int(facets) + 1; Vec<3> lvab = b - a; Vec<3> n1 = lvab.GetNormal(); Vec<3> n2 = Cross (lvab, n1); n1.Normalize(); n2.Normalize(); for (j = 0; j <= n; j++) for (i = 0; i <= n; i++) { lg = 2 * M_PI * double (i) / n; bg = double(j) / n; Point<3> p = a + (bg * lvab) + (( (ra+(rb-ra)*bg) * cos(lg)) * n1) + (( (ra+(rb-ra)*bg) * sin(lg)) * n2); tas.AddPoint (p); } for (j = 0; j < n; j++) for (i = 0; i < n; i++) { int pi = i + (n+1) * j; tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2)); tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1)); } } /// Elliptic Cone /// Josephat Kalezhi (kalezhi@cbu.ac.zm) /// February 21st, 2018 /// EllipticCone :: EllipticCone (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs, double ah, double avlr) { a = aa; h = ah; vlr = avlr; if (avl.Length2() >= avs.Length2()) { vl = avl; vs = avs; } else { vl = avs; vs = avl; } CalcData(); // Print (cout); } Primitive * EllipticCone :: CreateDefault () { return new EllipticCone (Point<3> (0,0,0), Vec<3> (1,0,0), Vec<3> (0,1,0), 1, 0.5); } void EllipticCone :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "ellipticcone"; coeffs.SetSize (15); coeffs.Elem(1) = a(0); coeffs.Elem(2) = a(1); coeffs.Elem(3) = a(2); coeffs.Elem(4) = vl(0); coeffs.Elem(5) = vl(1); coeffs.Elem(6) = vl(2); coeffs.Elem(7) = vs(0); coeffs.Elem(8) = vs(1); coeffs.Elem(9) = vs(2); coeffs.Elem(10) = h; coeffs.Elem(11) = vlr; } void EllipticCone :: SetPrimitiveData (Array & coeffs) { a(0) = coeffs.Elem(1); a(1) = coeffs.Elem(2); a(2) = coeffs.Elem(3); vl(0) = coeffs.Elem(4); vl(1) = coeffs.Elem(5); vl(2) = coeffs.Elem(6); vs(0) = coeffs.Elem(7); vs(1) = coeffs.Elem(8); vs(2) = coeffs.Elem(9); h = coeffs.Elem(10); vlr = coeffs.Elem(11); CalcData(); } void EllipticCone :: CalcData () { Vec<3> nh = Cross(vl, vs); nh.Normalize(); double lvl = vl.Length(); double lvs = vs.Length(); Vec<3> t1vec = lvl*(vlr -1)*(1/h)*nh; Vec<3> va (a); double t1 = lvl*(1 - (vlr -1)*(1/h)*(va*nh)); Vec<3> nvl = (1.0/lvl)*vl; Vec<3> nvs = (1.0/lvs)*vs; double ellipt2 = sqr(lvl/lvs); cxx = nvl(0)*nvl(0) + ellipt2*nvs(0)*nvs(0) - t1vec(0)*t1vec(0); cyy = nvl(1)*nvl(1) + ellipt2*nvs(1)*nvs(1) - t1vec(1)*t1vec(1); czz = nvl(2)*nvl(2) + ellipt2*nvs(2)*nvs(2) - t1vec(2)*t1vec(2); cxy = 2*(nvl(0)*nvl(1) + ellipt2*nvs(0)*nvs(1) - t1vec(0)*t1vec(1)); cxz = 2*(nvl(0)*nvl(2) + ellipt2*nvs(0)*nvs(2) - t1vec(0)*t1vec(2)); cyz = 2*(nvl(1)*nvl(2) + ellipt2*nvs(1)*nvs(2) - t1vec(1)*t1vec(2)); Vec<3> v = -2*((va*nvl)*nvl + ellipt2*(va*nvs)*nvs + t1*t1vec); cx = v(0); cy = v(1); cz = v(2); c1 = pow(va*nvl,2) + ellipt2*pow(va*nvs,2) - t1*t1; double lvltop = vlr*lvl; // double minlvl = (lvl < lvltop) ? lvl : lvltop; double maxlvl = max2( lvl,lvltop); cxx /= maxlvl; cyy /= maxlvl; czz /= maxlvl; cxy /= maxlvl; cxz /= maxlvl; cyz /= maxlvl; cx /= maxlvl; cy /= maxlvl; cz /= maxlvl; c1 /= maxlvl; } INSOLID_TYPE EllipticCone :: BoxInSolid (const BoxSphere<3> & box) const { double rp, dist; Vec<3> cv( box.Center()); Vec<3> nh = Cross(vl, vs); nh.Normalize(); double lvl = vl.Length(); Vec<3> t1vec = lvl*(vlr -1)*(1/h)*nh; Vec<3> va (a); double t1 = lvl*(1 - (vlr -1)*(1/h)*(va*nh)); rp = cv*t1vec + t1; double lvltop = vlr*lvl; double maxlvl = max2( lvl,lvltop); dist = sqrt( CalcFunctionValue(box.Center())*maxlvl + rp*rp) - rp; if (dist - box.Diam() > 0) return IS_OUTSIDE; if (dist + box.Diam() < 0) return IS_INSIDE; return DOES_INTERSECT; } double EllipticCone :: HesseNorm () const { return 1.0/min(vs.Length2 (),vl.Length2()); } double EllipticCone :: MaxCurvature () const { double a = vs.Length(); double b = vl.Length(); return max2(b/(a*a),a/(b*b)); } double EllipticCone :: MaxCurvatureLoc (const Point<3> & c, double rad) const { #ifdef JOACHIMxxx cout << "max curv local" << endl; return 0.02; #endif // saubere Loesung wird noch notwendig !!! double a = vs.Length(); double b = vl.Length(); return max2(b/(a*a),a/(b*b)); } Point<3> EllipticCone :: GetSurfacePoint () const { return a + vl; } void EllipticCone :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const { int i, j; double lg, bg; int n = int(facets) + 1; Vec<3> nh = Cross(vl, vs); nh.Normalize(); Vec<3> vh = h*nh; double lvl = vl.Length(); double lvs = vs.Length(); Vec<3> nvl = (1.0/lvl)*vl; Vec<3> nvs = (1.0/lvs)*vs; for ( j = 0; j <= n; j++ ) for (i = 0; i <= n; i++) { lg = 2 *M_PI * double (i) /n; bg = double(j) /n; Point<3> p = a + (bg *vh) + (( lvl*(1 + (vlr -1)*bg) * cos(lg)) * nvl) + (( lvs*(1 + (vlr -1)*bg)* sin(lg) ) * nvs); tas.AddPoint (p); } for ( j = 0; j < n; j++) for ( i = 0; i < n; i++) { int pi = i + (n+1) * j; tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2)); tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1)); } } /// Torus /// Lorenzo Codecasa (codecasa@elet.polimi.it) /// April 27th, 2005 /// Torus :: Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar) { c = ac; n = an; n.Normalize(); R = aR; r = ar; } void Torus :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "torus"; coeffs.SetSize (8); coeffs.Elem(1) = c(0); coeffs.Elem(2) = c(1); coeffs.Elem(3) = c(2); coeffs.Elem(4) = n(0); coeffs.Elem(5) = n(1); coeffs.Elem(6) = n(2); coeffs.Elem(7) = R; coeffs.Elem(8) = r; } void Torus :: SetPrimitiveData (Array & coeffs) { c(0) = coeffs.Elem(1); c(1) = coeffs.Elem(2); c(2) = coeffs.Elem(3); n(0) = coeffs.Elem(4); n(1) = coeffs.Elem(5); n(2) = coeffs.Elem(6); R = coeffs.Elem(7); r = coeffs.Elem(8); } Primitive * Torus :: CreateDefault () { return new Torus (Point<3> (0,0,0), Vec<3> (0,0,1), 2, 1); } Primitive * Torus :: Copy () const { return new Torus (c, n, R, r); } void Torus :: Transform (Transformation<3> & trans) { Point<3> hc; trans.Transform (c, hc); c = hc; Vec<3> hn; trans.Transform (n, hn); n = hn; } int Torus :: IsIdentic (const Surface & s2, int & inv, double eps) const { const Torus * torus2 = dynamic_cast (&s2); if (!torus2) return 0; if (fabs (torus2->R - R) > eps) return 0; if (fabs (torus2->r - r) > eps) return 0; Vec<3> v2 = torus2->n - n; if ( v2 * v2 > eps ) return 0; v2 = torus2->c - c; if ( v2 * v2 > eps ) return 0; inv = 0; return 1; } double Torus :: CalcFunctionValue (const Point<3> & point) const { /* // original version Vec<3> v1 = point - c; double a1 = Abs2 (v1); // v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2); double a2 = n * v1; // n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2); double a3 = a1 + R * R - r * r; double a4 = Abs2 (n); // n(0) * n(0) + n(1) * n(1) + n(2) * n(2); return ( a3 * a3 -4 * R * R * ( a1 - a2 * a2 / a4 ) ) / ( R * R * R ); */ // JS, April 2011 Vec<3> v1 = point-c; double abs2 = Abs2(v1); double tau = v1 * n; double rho = sqrt (abs2 - tau*tau); return sqr (R - rho) + tau*tau - r*r; // double val2 = sqr (tau*tau + sqr (R - rho) -r*r) / (R*R*R); } void Torus :: CalcGradient (const Point<3> & point, Vec<3> & grad) const { /* Vec<3> v1 = point - c; double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2); double a2 = n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2); double a3 = a1 - R * R - r * r; double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2); grad(0) = ( 4 * a3 * v1(0) + 8 * R * R * a2 / a4 * n(0) ) / ( R * R * R ); grad(1) = ( 4 * a3 * v1(1) + 8 * R * R * a2 / a4 * n(1) ) / ( R * R * R ); grad(2) = ( 4 * a3 * v1(2) + 8 * R * R * a2 / a4 * n(2) ) / ( R * R * R ); */ Vec<3> v1 = point-c; double abs2 = Abs2(v1); double tau = v1 * n; double rho = sqrt (abs2 - tau*tau); // double func = sqr (R - rho) + tau*tau - r*r; Vec<3> gradabs2 = 2 * v1; Vec<3> gradtau = n; Vec<3> gradrho = 0.5 / rho * (gradabs2 - 2 * tau * gradtau); grad = -2 * (R - rho) * gradrho + 2 * tau * gradtau; } void Torus :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const { Surface::CalcHesse (point, hesse); return; Vec<3> v1 = point - c; double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2); double a3 = a1 - R * R - r * r; double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2); hesse(0,0) = ( 4 * a3 + 8 * (v1(0) * v1(0) + (R * n(0)) * (R * n(0)) / a4 ) ) / ( R * R * R ); hesse(1,1) = ( 4 * a3 + 8 * (v1(1) * v1(1) + (R * n(1)) * (R * n(1)) / a4 ) ) / ( R * R * R ); hesse(2,2) = ( 4 * a3 + 8 * (v1(2) * v1(2) + (R * n(2)) * (R * n(2)) / a4 ) ) / ( R * R * R ); hesse(0,1) = hesse(1,0) = 8 * (v1(0) * v1(1) + (R * n(0)) * (R * n(1)) / a4 ) / ( R * R * R ); hesse(1,2) = hesse(2,1) = 8 * (v1(1) * v1(2) + (R * n(1)) * (R * n(2)) / a4) / ( R * R * R ); hesse(0,2) = hesse(2,0) = 8 * (v1(0) * v1(2) + (R * n(0)) * (R * n(2)) / a4) / ( R * R * R ); } double Torus :: HesseNorm () const { return 4/(r*r); // return ( 2 / r + 2 / ( R - r ) ); } Point<3> Torus :: GetSurfacePoint () const { Vec<3> vn = n.GetNormal(); return c + ( R + r ) * vn.Normalize(); } /// void Torus :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2) /// { /// } /// void Torus :: ToPlane (const Point<3> & p, /// Point<2> & pplane, /// double h, int & zone) const /// { /// } /// void Torus :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const /// { /// } /// void Torus :: Project (Point<3> & p) const /// { /// } INSOLID_TYPE Torus :: BoxInSolid (const BoxSphere<3> & box) const { Vec<3> v1 = box.Center() - c; double a1 = Abs2(v1); // v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2); double a2 = n * v1; // n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2); double a4 = Abs2(n); // n(0) * n(0) + n(1) * n(1) + n(2) * n(2); double dist = sqrt( a1 + R * R - 2 * R * sqrt( a1 - a2 * a2 / a4) ); if (dist - box.Diam()/2 > r) return IS_OUTSIDE; if (dist + box.Diam()/2 < r) return IS_INSIDE; return DOES_INTERSECT; } void Torus :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & /* boundingbox */, double facets) const { int N = int(facets) + 1; Vec<3> lvab = n ; lvab.Normalize(); Vec<3> n1 = lvab.GetNormal(); n1.Normalize(); Vec<3> n2 = Cross(lvab, n1); n2.Normalize(); for (int j = 0; j <= N; j++) for (int i = 0; i <= N; i++) { double lg = 2 * M_PI * double (i) / N; double bg = 2 * M_PI * double(j) / N; Point<3> p = c + ( R + r * cos(lg) ) * ( cos(bg) * n1 + sin(bg) * n2 ) + r * sin(lg) * n; tas.AddPoint (p); } for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) { int pi = i + (N+1) * j; tas.AddTriangle (TATriangle (0, pi, pi+1, pi+N+2)); tas.AddTriangle (TATriangle (0, pi, pi+N+2, pi+N+1)); } } void Torus :: Read (istream & ist) { ist >> c(0) >> c(1) >> c(2) >> n(0) >> n(1) >> n(2) >> R >> r; } void Torus :: Print (ostream & ost) const { ost << c(0) << " " << c(1) << " " << c(2) << " " << n(0) << " " << n(1) << " " << n(2) << " " << R << " " << r << endl; } RegisterClassForArchive regqs; RegisterClassForArchive regpl; RegisterClassForArchive regsph; RegisterClassForArchive regcyl; RegisterClassForArchive regelcyl; RegisterClassForArchive regell; RegisterClassForArchive regcone; RegisterClassForArchive regellcone; RegisterClassForArchive regtorus; } netgen-6.2.1905/libsrc/csg/csgpkg.cpp0000644000175000017500000004326313504650527016025 0ustar kurtkurt#include #include #include #include #include #include #include "vscsg.hpp" extern "C" int Ng_CSG_Init (Tcl_Interp * interp); namespace netgen { // extern DLL_HEADER NetgenGeometry * ng_geometry; extern DLL_HEADER shared_ptr ng_geometry; extern DLL_HEADER shared_ptr mesh; static VisualSceneGeometry vsgeom; char * err_needscsgeometry = (char*) "This operation needs an CSG geometry"; char * err_needsmesh = (char*) "This operation needs a mesh"; char * err_jobrunning = (char*) "Meshing Job already running"; int Ng_ParseGeometry (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * csgeom = dynamic_cast (ng_geometry.get()); if (csgeom) { double detail = atof (Tcl_GetVar (interp, "::geooptions.detail", 0)); double facets = atof (Tcl_GetVar (interp, "::geooptions.facets", 0)); if (atoi (Tcl_GetVar (interp, "::geooptions.drawcsg", 0))) csgeom->CalcTriangleApproximation(detail, facets); } return TCL_OK; } int Ng_GeometryOptions (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); const char * command = argv[1]; if (strcmp (command, "get") == 0) { if (geometry) { char buf[20]; Point3d pmin = geometry->BoundingBox ().PMin(); Point3d pmax = geometry->BoundingBox ().PMax(); sprintf (buf, "%5.1lf", pmin.X()); Tcl_SetVar (interp, "::geooptions.minx", buf, 0); sprintf (buf, "%5.1lf", pmin.Y()); Tcl_SetVar (interp, "::geooptions.miny", buf, 0); sprintf (buf, "%5.1lf", pmin.Z()); Tcl_SetVar (interp, "::geooptions.minz", buf, 0); sprintf (buf, "%5.1lf", pmax.X()); Tcl_SetVar (interp, "::geooptions.maxx", buf, 0); sprintf (buf, "%5.1lf", pmax.Y()); Tcl_SetVar (interp, "::geooptions.maxy", buf, 0); sprintf (buf, "%5.1lf", pmax.Z()); Tcl_SetVar (interp, "::geooptions.maxz", buf, 0); } } else if (strcmp (command, "set") == 0) { Point<3> pmin (atof (Tcl_GetVar (interp, "::geooptions.minx", 0)), atof (Tcl_GetVar (interp, "::geooptions.miny", 0)), atof (Tcl_GetVar (interp, "::geooptions.minz", 0))); Point<3> pmax (atof (Tcl_GetVar (interp, "::geooptions.maxx", 0)), atof (Tcl_GetVar (interp, "::geooptions.maxy", 0)), atof (Tcl_GetVar (interp, "::geooptions.maxz", 0))); Box<3> box (pmin, pmax); if (geometry) geometry -> SetBoundingBox (box); CSGeometry::SetDefaultBoundingBox (box); } return TCL_OK; } // attempt of a simple modeller int Ng_CreatePrimitive (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) {/* CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * classname = argv[1]; tcl_const char * name = argv[2]; cout << "Create primitive, class = " << classname << ", name = " << name << endl; Primitive * nprim = Primitive::CreatePrimitive (classname); Solid * nsol = new Solid (nprim); char sname[100]; for (int j = 1; j <= nprim->GetNSurfaces(); j++) { sprintf (sname, "%s,%d", name, j); geometry -> AddSurface (sname, &nprim->GetSurface(j)); nprim -> SetSurfaceId (j, geometry->GetNSurf()); } geometry->SetSolid (name, nsol); */ return TCL_OK; } int Ng_SetPrimitiveData (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * name = argv[1]; tcl_const char * value = argv[2]; Array coeffs; cout << "Set primitive data, name = " << name << ", value = " << value << endl; istringstream vst (value); double val; while (!vst.eof()) { vst >> val; coeffs.Append (val); } ((Primitive*) geometry->GetSolid (name)->GetPrimitive())->SetPrimitiveData (coeffs); return TCL_OK; } int Ng_SetSolidData (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) {/* CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * name = argv[1]; tcl_const char * val = argv[2]; cout << "Set Solid Data, name = " << name << ", value = " << val << endl; istringstream vst (val); Solid * nsol = Solid::CreateSolid (vst, geometry->GetSolids()); geometry->SetSolid (name, nsol); */ return TCL_OK; } int Ng_GetPrimitiveData (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * name = argv[1]; tcl_const char * classnamevar = argv[2]; tcl_const char * valuevar = argv[3]; const char * classname; Array coeffs; geometry->GetSolid (name)->GetPrimitive()->GetPrimitiveData (classname, coeffs); ostringstream vst; for (int i = 1; i <= coeffs.Size(); i++) vst << coeffs.Get(i) << " "; cout << "GetPrimitiveData, name = " << name << ", classnamevar = " << classnamevar << ", classname = " << classname << endl << " valuevar = " << valuevar << ", values = " << vst.str() << endl; Tcl_SetVar (interp, classnamevar, (char*)classname, 0); Tcl_SetVar (interp, valuevar, (char*)vst.str().c_str(), 0); return TCL_OK; } int Ng_GetSolidData (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) {/* CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * name = argv[1]; tcl_const char * valuevar = argv[2]; ostringstream vst; const Solid * sol = geometry->GetSolid (name); sol->GetSolidData (vst); cout << "GetSolidData, name = " << name << ", data = " << vst.str() << endl; Tcl_SetVar (interp, valuevar, (char*)vst.str().c_str(), 0); */ return TCL_OK; } int Ng_GetPrimitiveList (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * valuevar = argv[1]; int i; stringstream vst; for (i = 1; i <= geometry->GetNSolids(); i++) { const Solid * sol = geometry->GetSolid(i); if (sol->GetPrimitive()) vst << sol->Name() << " "; } cout << "primnames = " << vst.str() << endl; Tcl_SetVar (interp, valuevar, (char*)vst.str().c_str(), 0); return TCL_OK; } int Ng_GetSurfaceList (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * valuevar = argv[1]; int i; stringstream vst; for (i = 1; i <= geometry->GetNSurf(); i++) { const Surface * surf = geometry->GetSurface(i); vst << surf->Name() << " "; } cout << "surfnames = " << vst.str() << endl; Tcl_SetVar (interp, valuevar, (char*)vst.str().c_str(), 0); return TCL_OK; } int Ng_GetSolidList (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } tcl_const char * valuevar = argv[1]; int i; stringstream vst; for (i = 1; i <= geometry->GetNSolids(); i++) { const Solid * sol = geometry->GetSolid(i); if (!sol->GetPrimitive()) vst << sol->Name() << " "; } cout << "solnames = " << vst.str() << endl; Tcl_SetVar (interp, valuevar, (char*)vst.str().c_str(), 0); return TCL_OK; } int Ng_TopLevel (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } int i; /* for (i = 0; i < argc; i++) cout << argv[i] << ", "; cout << endl; */ if (strcmp (argv[1], "getlist") == 0) { stringstream vst; for (i = 0; i < geometry->GetNTopLevelObjects(); i++) { const Solid * sol; const Surface * surf; geometry->GetTopLevelObject (i, sol, surf); if (!surf) vst << "{ " << sol->Name() << " } "; else vst << "{ " << sol->Name() << " " << surf->Name() << " } "; } tcl_const char * valuevar = argv[2]; Tcl_SetVar (interp, valuevar, (char*)vst.str().c_str(), 0); } if (strcmp (argv[1], "set") == 0) { tcl_const char * solname = argv[2]; tcl_const char * surfname = argv[3]; Solid * sol = (Solid*)geometry->GetSolid (solname); Surface * surf = (Surface*)geometry->GetSurface (surfname); geometry->SetTopLevelObject (sol, surf); } if (strcmp (argv[1], "remove") == 0) { tcl_const char * solname = argv[2]; tcl_const char * surfname = argv[3]; Solid * sol = (Solid*)geometry->GetSolid (solname); Surface * surf = (Surface*)geometry->GetSurface (surfname); geometry->RemoveTopLevelObject (sol, surf); } if (strcmp (argv[1], "setprop") == 0) { tcl_const char * solname = argv[2]; tcl_const char * surfname = argv[3]; tcl_const char * propvar = argv[4]; Solid * sol = (Solid*)geometry->GetSolid (solname); Surface * surf = (Surface*)geometry->GetSurface (surfname); TopLevelObject * tlo = geometry->GetTopLevelObject (sol, surf); if (!tlo) return TCL_OK; char varname[50]; sprintf (varname, "%s(red)", propvar); double red = atof (Tcl_GetVar (interp, varname, 0)); sprintf (varname, "%s(blue)", propvar); double blue = atof (Tcl_GetVar (interp, varname, 0)); sprintf (varname, "%s(green)", propvar); double green = atof (Tcl_GetVar (interp, varname, 0)); tlo -> SetRGB (red, green, blue); sprintf (varname, "%s(visible)", propvar); tlo -> SetVisible (bool(atoi (Tcl_GetVar (interp, varname, 0)))); sprintf (varname, "%s(transp)", propvar); tlo -> SetTransparent (bool(atoi (Tcl_GetVar (interp, varname, 0)))); } if (strcmp (argv[1], "getprop") == 0) { tcl_const char * solname = argv[2]; tcl_const char * surfname = argv[3]; tcl_const char * propvar = argv[4]; Solid * sol = (Solid*)geometry->GetSolid (solname); Surface * surf = (Surface*)geometry->GetSurface (surfname); TopLevelObject * tlo = geometry->GetTopLevelObject (sol, surf); if (!tlo) return TCL_OK; char varname[50], varval[10]; sprintf (varname, "%s(red)", propvar); sprintf (varval, "%lf", tlo->GetRed()); Tcl_SetVar (interp, varname, varval, 0); sprintf (varname, "%s(green)", propvar); sprintf (varval, "%lf", tlo->GetGreen()); Tcl_SetVar (interp, varname, varval, 0); sprintf (varname, "%s(blue)", propvar); sprintf (varval, "%lf", tlo->GetBlue()); Tcl_SetVar (interp, varname, varval, 0); sprintf (varname, "%s(visible)", propvar); sprintf (varval, "%d", tlo->GetVisible()); Tcl_SetVar (interp, varname, varval, 0); sprintf (varname, "%s(transp)", propvar); sprintf (varval, "%d", tlo->GetTransparent()); Tcl_SetVar (interp, varname, varval, 0); } return TCL_OK; } int Ng_SingularEdgeMS (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } // double globh = mparam.maxh; for (int i = 1; i <= geometry->singedges.Size(); i++) geometry->singedges.Get(i)->SetMeshSize (*mesh, 1e99 /* globh*/); return TCL_OK; } int Ng_SingularPointMS (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (!geometry) { Tcl_SetResult (interp, err_needscsgeometry, TCL_STATIC); return TCL_ERROR; } // double globh = mparam.maxh; for (int i = 1; i <= geometry->singpoints.Size(); i++) geometry->singpoints.Get(i)->SetMeshSize (*mesh, 1e99 /* globh */ ); return TCL_OK; } int Ng_SelectSurface (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { int surfnr = atoi (argv[1]); vsgeom.SelectSurface (surfnr); return TCL_OK; } /* class CSGeometryRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const; virtual NetgenGeometry * LoadFromMeshFile (istream & ist) const; virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const; }; extern CSGeometry * ParseCSG (istream & istr); NetgenGeometry * CSGeometryRegister :: Load (string filename) const { const char * cfilename = filename.c_str(); if (strcmp (&cfilename[strlen(cfilename)-3], "geo") == 0) { PrintMessage (1, "Load CSG geometry file ", cfilename); ifstream infile(cfilename); CSGeometry * hgeom = ParseCSG (infile); if (!hgeom) throw NgException ("geo-file should start with 'algebraic3d'"); hgeom -> FindIdenticSurfaces(1e-8 * hgeom->MaxSize()); return hgeom; } if (strcmp (&cfilename[strlen(cfilename)-3], "ngg") == 0) { PrintMessage (1, "Load new CSG geometry file ", cfilename); ifstream infile(cfilename); CSGeometry * hgeom = new CSGeometry(""); hgeom -> Load (infile); return hgeom; } return NULL; } NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist) const { string auxstring; if (ist.good()) { ist >> auxstring; if (auxstring == "csgsurfaces") { CSGeometry * geometry = new CSGeometry (""); geometry -> LoadSurfaces(ist); return geometry; } // else // ist.putback (auxstring); } return NULL; } VisualScene * CSGeometryRegister :: GetVisualScene (const NetgenGeometry * geom) const { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); if (geometry) { vsgeom.SetGeometry (geometry); return &vsgeom; } return NULL; } */ class CSGeometryVisRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const { return NULL; } virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const; }; VisualScene * CSGeometryVisRegister :: GetVisualScene (const NetgenGeometry * geom) const { const CSGeometry * geometry = dynamic_cast (geom); if (geometry) { vsgeom.SetGeometry (const_cast(geometry)); return &vsgeom; } return NULL; } } using namespace netgen; int Ng_CSG_Init (Tcl_Interp * interp) { geometryregister.Append (new CSGeometryVisRegister); if (interp == NULL) return TCL_OK; Tcl_CreateCommand (interp, "Ng_ParseGeometry", Ng_ParseGeometry, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); // geometry Tcl_CreateCommand (interp, "Ng_CreatePrimitive", Ng_CreatePrimitive, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SetPrimitiveData", Ng_SetPrimitiveData, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GetPrimitiveData", Ng_GetPrimitiveData, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GetPrimitiveList", Ng_GetPrimitiveList, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GetSurfaceList", Ng_GetSurfaceList, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SetSolidData", Ng_SetSolidData, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GetSolidData", Ng_GetSolidData, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GetSolidList", Ng_GetSolidList, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_TopLevel", Ng_TopLevel, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GeometryOptions", Ng_GeometryOptions, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SingularEdgeMS", Ng_SingularEdgeMS, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SingularPointMS", Ng_SingularPointMS, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SelectSurface", Ng_SelectSurface, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); return TCL_OK; } netgen-6.2.1905/libsrc/csg/spline3d.cpp0000644000175000017500000001725513504650527016272 0ustar kurtkurt#include #include #include #include namespace netgen { splinesegment3d :: splinesegment3d (const Point<3> & ap1, const Point<3> & ap2, const Point<3> & ap3) { p1 = ap1; p2 = ap2; p3 = ap3; } /* todo Tip von Joerg Stiller: setzt Du in void splinesegment3d :: Evaluate Zeilen 54 und 56 b2 = 2 * t * (1-t); b2 /= sqrt(2); Das heisst, Du wichtest das zweite Bersteinpolynom mit w2 = 1 / sqrt(2); Das ist aber nur fuer 45-Grad-Segmente korrekt. Fuer den allgemeinen Fall funktioniert w2 = ( e(p3 - p1), e(p2 - p1) ); // also cos(winkel(p3-p1, p2-p1)) bzw. schoen symmetrisch w2 = ( e(p3 - p1), e(p2 - p1) )/2 + ( e(p1 - p3), e(p2 - p3) )/2; Das ist natuerlich kein C++ Code sondern symbolisch, wobei e(p3 - p1) ist der von p1 zu p3 zeigende Einheitsvektor und (a, b) steht fuer das Skalarprodukt zweier Vektoren etc. Eine vergleichbare Information steht auch irgendwo im Hoscheck & Lasser. Ich habe das Buch aber eben nicht zur Hand. */ void splinesegment3d :: Evaluate (double t, Point<3> & p) const { double x, y, z, w; double b1, b2, b3; b1 = (1-t)*(1-t); b2 = 2 * t * (1-t); b3 = t * t; b2 /= sqrt(double(2)); x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3; y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3; z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3; w = b1 + b2 + b3; p(0) = x / w; p(1) = y / w; p(2) = z / w; } void splinesegment3d :: EvaluateTangent (double t, Vec<3> & tang) const { double x, y, z, w, xprime, yprime, zprime, wprime; double b1, b2, b3, b1prime, b2prime, b3prime; b1 = (1-t)*(1-t); b2 = 2 * t * (1-t); b3 = t * t; b2 /= sqrt(double(2)); b1prime = 2 * t - 2; b2prime = - 4 * t + 2; b3prime = 2 * t; b2prime /= sqrt(double(2)); x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3; y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3; z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3; w = b1 + b2 + b3; xprime = p1(0) * b1prime + p2(0) * b2prime + p3(0) * b3prime; yprime = p1(1) * b1prime + p2(1) * b2prime + p3(1) * b3prime; zprime = p1(2) * b1prime + p2(2) * b2prime + p3(2) * b3prime; wprime = b1prime + b2prime + b3prime; tang(0) = (w * xprime - x * wprime) / (w * w); tang(1) = (w * yprime - y * wprime) / (w * w); tang(2) = (w * zprime - z * wprime) / (w * w); } void spline3d :: AddSegment (const Point<3> & ap1, const Point<3> & ap2, const Point<3> & ap3) { segments.Append (new splinesegment3d (ap1, ap2, ap3)); } void spline3d :: Evaluate (double t, Point<3> & p) const { int nr; double loct; static int cnt = 0; cnt++; if (cnt % 10000 == 0) (*mycout) << "Evaluate calls: " << cnt << endl; while (t < 0) t += GetNumSegments(); while (t >= GetNumSegments()) t -= GetNumSegments(); nr = 1 + int (t); loct = t - nr + 1; segments.Get(nr)->Evaluate (loct, p); } void spline3d :: EvaluateTangent (double t, Vec<3> & tang) const { int nr; double loct; while (t < 0) t += GetNumSegments(); while (t >= GetNumSegments()) t -= GetNumSegments(); nr = 1 + int (t); loct = t - nr + 1; segments.Get(nr)->EvaluateTangent (loct, tang); } double spline3d :: ProjectToSpline (Point<3> & p) const { double t, tl, tu, dt, dist, mindist, optt(0); Point<3> hp; Vec<3> tanx, px; dt = 0.01; mindist = 0; for (t = 0; t <= GetNumSegments() + dt/2; t += dt) { Evaluate (t, hp); dist = Dist (hp, p); if (t == 0 || dist < mindist) { optt = t; mindist = dist; } } tu = optt + dt; tl = optt - dt; while (tu - tl > 1e-2) { optt = 0.5 * (tu + tl); Evaluate (optt, hp); EvaluateTangent (optt, tanx); if (tanx * (hp - p) > 0) tu = optt; else tl = optt; } optt = 0.5 * (tu + tl); optt = ProjectToSpline (p, optt); return optt; } double spline3d :: ProjectToSpline (Point<3> & p, double optt) const { double tl, tu, dt, val, dval, valu, vall; Point<3> hp; Vec<3> tanx, px; int its = 0; int cnt = 1000; do { dt = 1e-8; tl = optt - dt; tu = optt + dt; EvaluateTangent (optt, tanx); Evaluate (optt, hp); px = hp - p; val = px * tanx; EvaluateTangent (tl, tanx); Evaluate (tl, hp); px = hp - p; vall = px * tanx; EvaluateTangent (tu, tanx); Evaluate (tu, hp); px = hp - p; valu = px * tanx; dval = (valu - vall) / (2 * dt); if (its % 100 == 99) (*testout) << "optt = " << optt << " val = " << val << " dval = " << dval << endl; optt -= val / dval; its++; if (fabs(val) < 1e-8 && cnt > 5) cnt = 5; cnt--; } while (cnt > 0); Evaluate (optt, p); return optt; } splinetube :: splinetube (const spline3d & amiddlecurve, double ar) : Surface(), middlecurve (amiddlecurve), r(ar) { (*mycout) << "Splinetube Allocated, r = " << r << endl; } void splinetube :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2) { double t; double phi, z; p1 = ap1; p2 = ap2; cp = p1; t = middlecurve.ProjectToSpline (cp); ex = p1 - cp; middlecurve.EvaluateTangent (t, ez); ex.Normalize(); ez.Normalize(); ey = Cross (ez, ex); phi = r * atan2 (ey * (p2-cp), ex * (p2-cp)); z = ez * (p2 - cp); e2x(0) = phi; e2x(1) = z; e2x.Normalize(); e2y(1) = e2x(0); e2y(0) = -e2x(1); // (*testout) << "Defineplane: " << endl // << "p1 = " << p1 << " p2 = " << p2 << endl // << "pc = " << cp << endl // << "ex = " << ex << " ey = " << ey << " ez = " << ez << endl // << "phi = " << phi << " z = " << z << endl // << "e2x = " << e2x << " e2y = " << e2y << endl; } void splinetube :: ToPlane (const Point<3> & p3d, Point<2> & pplain, double h, int & zone) const { Vec<2> v; v(0) = r * atan2 (ey * (p3d-cp), ex * (p3d-cp)); v(1) = ez * (p3d - cp); zone = 0; if (v(0) > r * 2) zone = 1; if (v(0) < r * 2) zone = 2; pplain(0) = (v * e2x) / h; pplain(1) = (v * e2y) / h; } void splinetube :: FromPlane (const Point<2> & pplain, Point<3> & p3d, double h) const { Vec<2> v; v(0) = pplain(0) * h * e2x(0) + pplain(1) * h * e2y(0); v(1) = pplain(0) * h * e2x(1) + pplain(1) * h * e2y(1); p3d = p1 + v(0) * ey + v(1) * ez; Project (p3d); } void splinetube :: Project (Point<3> & p3d) const { Point<3> hp; hp = p3d; middlecurve.ProjectToSpline (hp); p3d = hp + (r / Dist(p3d, hp)) * (p3d - hp); } double splinetube :: CalcFunctionValue (const Point<3> & point) const { Point<3> hcp; double rad; hcp = point; middlecurve.ProjectToSpline (hcp); rad = Dist (hcp, point); return 0.5 * (rad * rad / r - r); } void splinetube :: CalcGradient (const Point<3> & point, Vec<3> & grad) const { Point<3> hcp; hcp = point; middlecurve.ProjectToSpline (hcp); grad = point - hcp; grad /= r; } Point<3> splinetube :: GetSurfacePoint () const { Point<3> p; Vec<3> t, n; middlecurve.Evaluate (0, p); middlecurve.EvaluateTangent (0, t); n = t.GetNormal (); n *= r; (*mycout) << "p = " << p << " t = " << t << " n = " << n << endl; return p + n; } void splinetube :: Print (ostream & str) const { int i; str << "SplineTube, " << middlecurve.GetNumSegments () << " segments, r = " << r << endl; for (i = 1; i <= middlecurve.GetNumSegments(); i++) str << middlecurve.P1(i) << " - " << middlecurve.P2(i) << " - " << middlecurve.P3(i) << endl; } int splinetube :: BoxInSolid (const BoxSphere<3> & box) const // 0 .. no, 1 .. yes, 2 .. maybe { Point<3> pc = box.Center(); middlecurve.ProjectToSpline (pc); double d = Dist (pc, box.Center()); if (d < r - box.Diam()/2) return 1; if (d > r + box.Diam()/2) return 0; return 2; } } netgen-6.2.1905/libsrc/csg/vscsg.cpp0000644000175000017500000002546113504650527015674 0ustar kurtkurt#include #include "incopengl.hpp" #include #include #include #include #include #include "vscsg.hpp" namespace netgen { /* *********************** Draw Geometry **************** */ extern shared_ptr mesh; extern Array specpoints; extern Array > boxes; VisualSceneGeometry :: VisualSceneGeometry () : VisualScene() { selsurf = 0; } VisualSceneGeometry :: ~VisualSceneGeometry () { ; } void VisualSceneGeometry :: SelectSurface (int aselsurf) { selsurf = aselsurf; DrawScene(); } void VisualSceneGeometry :: DrawScene () { if (changeval != geometry->GetChangeVal()) BuildScene(); changeval = geometry->GetChangeVal(); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); SetClippingPlane (); glShadeModel (GL_SMOOTH); glDisable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* float mat_spec_col[] = { 1, 1, 1, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col); */ double shine = vispar.shininess; double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); glEnable (GL_NORMALIZE); for (int i = 0; i < geometry->GetNTopLevelObjects(); i++) { const TopLevelObject * tlo = geometry -> GetTopLevelObject (i); if (tlo->GetVisible() && !tlo->GetTransparent()) { float mat_col[] = { float(tlo->GetRed()), float(tlo->GetGreen()), float(tlo->GetBlue()), 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glCallList (trilists[i]); } } glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glLogicOp (GL_NOOP); for (int i = 0; i < geometry->GetNTopLevelObjects(); i++) { const TopLevelObject * tlo = geometry -> GetTopLevelObject (i); if (tlo->GetVisible() && tlo->GetTransparent()) { float mat_col[] = { float(tlo->GetRed()), float(tlo->GetGreen()), float(tlo->GetBlue()), float(transp) }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glCallList (trilists[i]); } } glDisable (GL_POLYGON_OFFSET_FILL); glPopMatrix(); glDisable(GL_CLIP_PLANE0); DrawCoordinateCross (); DrawNetgenLogo (); glFinish(); } void VisualSceneGeometry :: BuildScene (int zoomall) { VisualScene::BuildScene(zoomall); // setting light ... Box<3> box; int hasp = 0; for (int i = 0; i < geometry->GetNTopLevelObjects(); i++) { const TriangleApproximation * ta = geometry->GetTriApprox(i); if (!ta) continue; for (int j = 0; j < ta->GetNP(); j++) { if (hasp) box.Add (ta->GetPoint(j)); else { hasp = 1; box.Set (ta->GetPoint(j)); } } } if (hasp) { center = box.Center(); rad = box.Diam() / 2; } else { center = Point3d(0,0,0); rad = 1; } CalcTransformationMatrices(); for (int i = 0; i < trilists.Size(); i++) glDeleteLists (trilists[i], 1); trilists.SetSize(0); for (int i = 0; i < geometry->GetNTopLevelObjects(); i++) { trilists.Append (glGenLists (1)); glNewList (trilists.Last(), GL_COMPILE); glEnable (GL_NORMALIZE); const TriangleApproximation * ta = geometry->GetTriApprox(i); if (ta) { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_DOUBLE, 0, &ta->GetPoint(0)(0)); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_DOUBLE, 0, &ta->GetNormal(0)(0)); for (int j = 0; j < ta->GetNT(); j++) glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, & (ta->GetTriangle(j)[0])); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); /* for (int j = 0; j < ta.GetNT(); j++) { glBegin (GL_TRIANGLES); for (int k = 0; k < 3; k++) { int pi = ta.GetTriangle(j)[k]; glNormal3dv (ta.GetNormal(pi)); glVertex3dv (ta.GetPoint(pi)); cout << "v = " << ta.GetPoint(pi) << endl; } glEnd (); } */ } glEndList (); } } VisualSceneSpecPoints :: VisualSceneSpecPoints () : VisualScene() { ; } VisualSceneSpecPoints :: ~VisualSceneSpecPoints () { ; } void VisualSceneSpecPoints :: DrawScene () { if (!mesh) { VisualScene::DrawScene(); return; } if (changeval != specpoints.Size()) BuildScene(); changeval = specpoints.Size(); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable (GL_COLOR_MATERIAL); glColor3f (1.0f, 1.0f, 1.0f); glLineWidth (1.0f); glPushMatrix(); glMultMatrixd (transformationmat); // glEnable (GL_COLOR); // glDisable (GL_COLOR_MATERIAL); if (vispar.drawedtangents) { glColor3d (1, 0, 0); glBegin (GL_LINES); for (int i = 1; i <= specpoints.Size(); i++) { const Point3d p1 = specpoints.Get(i).p; const Point3d p2 = specpoints.Get(i).p + len * specpoints.Get(i).v; glVertex3d (p1.X(), p1.Y(), p1.Z()); glVertex3d (p2.X(), p2.Y(), p2.Z()); } glEnd(); } if (vispar.drawededges) { glColor3d (1, 0, 0); glBegin (GL_LINES); for (int i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh -> LineSegment (i); glVertex3dv ( (*mesh)[seg[0]] ); glVertex3dv ( (*mesh)[seg[1]] ); // glVertex3dv ( &(*mesh)[seg[0]].X() ); // glVertex3dv ( &(*mesh)[seg[1]].X() ); } glEnd(); } glColor3d (1, 0, 0); glBegin (GL_LINES); int edges[12][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, { 0, 2 }, { 1, 3 }, { 4, 6 }, { 5, 7 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } }; for (int i = 0; i < boxes.Size(); i++) { for (int j = 0; j < 12; j++) { glVertex3dv ( boxes[i].GetPointNr(edges[j][0]) ); glVertex3dv ( boxes[i].GetPointNr(edges[j][1]) ); } /* glVertex3dv ( boxes[i].PMin() ); glVertex3dv ( boxes[i].PMax() ); */ } glEnd(); if (vispar.drawededgenrs) { glEnable (GL_COLOR_MATERIAL); GLfloat textcol[3] = { GLfloat(1 - backcolor), GLfloat(1 - backcolor), GLfloat(1 - backcolor) }; glColor3fv (textcol); glNormal3d (0, 0, 1); glPushAttrib (GL_LIST_BIT); // glListBase (fontbase); char buf[20]; for (int i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh -> LineSegment (i); const Point3d p1 = mesh -> Point (seg[0]); const Point3d p2 = mesh -> Point (seg[1]); const Point3d p = Center (p1, p2); glRasterPos3d (p.X(), p.Y(), p.Z()); sprintf (buf, "%d", seg.edgenr); // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); } glPopAttrib (); glDisable (GL_COLOR_MATERIAL); } if (vispar.drawedpoints) { glColor3d (0, 0, 1); /* glPointSize( 3.0 ); float range[2]; glGetFloatv(GL_POINT_SIZE_RANGE, &range[0]); cout << "max ptsize = " << range[0] << "-" << range[1] << endl; glBegin( GL_POINTS ); for (int i = 1; i <= mesh -> GetNP(); i++) { const Point3d & p = mesh -> Point(i); if (i % 2) glVertex3f( p.X(), p.Y(), p.Z()); } glEnd(); */ static GLubyte knoedel[] = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, }; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDisable (GL_COLOR_MATERIAL); glDisable (GL_LIGHTING); glDisable (GL_CLIP_PLANE0); /* for (int i = 1; i <= mesh -> GetNP(); i++) { const Point3d & p = mesh -> Point(i); glRasterPos3d (p.X(), p.Y(), p.Z()); glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]); } */ for (const Point3d & p : mesh->Points()) { glRasterPos3d (p.X(), p.Y(), p.Z()); glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]); } } if (vispar.drawedpointnrs) { glEnable (GL_COLOR_MATERIAL); GLfloat textcol[3] = { GLfloat(1 - backcolor), GLfloat(1 - backcolor), GLfloat(1 - backcolor) }; glColor3fv (textcol); glNormal3d (0, 0, 1); glPushAttrib (GL_LIST_BIT); // glListBase (fontbase); char buf[20]; // for (int i = 1; i <= mesh->GetNP(); i++) for (auto i : mesh->Points().Range()) { const Point3d & p = mesh->Point(i); glRasterPos3d (p.X(), p.Y(), p.Z()); sprintf (buf, "%d", int(i)); // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); } glPopAttrib (); glDisable (GL_COLOR_MATERIAL); } glPopMatrix(); if (vispar.drawcoordinatecross) DrawCoordinateCross (); DrawNetgenLogo (); glFinish(); } void VisualSceneSpecPoints :: BuildScene (int zoomall) { if (!mesh) { VisualScene::BuildScene(zoomall); return; } Box3d box; if (mesh->GetNSeg()) { box.SetPoint (mesh->Point (mesh->LineSegment(1)[0])); for (int i = 1; i <= mesh->GetNSeg(); i++) { box.AddPoint (mesh->Point (mesh->LineSegment(i)[0])); box.AddPoint (mesh->Point (mesh->LineSegment(i)[1])); } } else if (specpoints.Size() >= 2) { box.SetPoint (specpoints.Get(1).p); for (int i = 2; i <= specpoints.Size(); i++) box.AddPoint (specpoints.Get(i).p); } else { box = Box3d (Point3d (0,0,0), Point3d (1,1,1)); } if (zoomall == 2 && ((vispar.centerpoint >= 1 && vispar.centerpoint <= mesh->GetNP()) || vispar.use_center_coords)) { if (vispar.use_center_coords) { center.X() = vispar.centerx; center.Y() = vispar.centery; center.Z() = vispar.centerz; } else center = mesh->Point (vispar.centerpoint); } else center = Center (box.PMin(), box.PMax()); rad = 0.5 * Dist (box.PMin(), box.PMax()); CalcTransformationMatrices(); } } #ifdef NG_PYTHON #include <../general/ngpython.hpp> DLL_HEADER void ExportCSGVis(py::module &m) { using namespace netgen; py::class_> (m, "VisualSceneGeometry") .def("Draw", &VisualSceneGeometry::DrawScene) ; m.def("SetBackGroundColor", &VisualSceneGeometry::SetBackGroundColor); m.def("VS", [](CSGeometry & geom) { geom.FindIdenticSurfaces(1e-6); geom.CalcTriangleApproximation(0.01, 20); auto vs = make_shared(); vs->SetGeometry(&geom); return vs; }); m.def("MouseMove", [](VisualSceneGeometry &vsgeom, int oldx, int oldy, int newx, int newy, char mode) { vsgeom.MouseMove(oldx, oldy, newx, newy, mode); }); } PYBIND11_MODULE(libcsgvis, m) { ExportCSGVis(m); } #endif netgen-6.2.1905/libsrc/csg/triapprox.hpp0000644000175000017500000000324413504650527016577 0ustar kurtkurt#ifndef FILE_TRIAPPROX #define FILE_TRIAPPROX /**************************************************************************/ /* File: triapprox.hh */ /* Author: Joachim Schoeberl */ /* Date: 2. Mar. 98 */ /**************************************************************************/ namespace netgen { /** Triangulated approximation to true surface */ class TATriangle { int pi[3]; int surfind; public: TATriangle () { ; } TATriangle (int si, int pi1, int pi2, int pi3) { surfind = si; pi[0] = pi1; pi[1] = pi2; pi[2] = pi3; } int SurfaceIndex() const { return surfind; } int & SurfaceIndex() { return surfind; } int & operator[] (int i) { return pi[i]; } const int & operator[] (int i) const { return pi[i]; } }; class TriangleApproximation { Array > points; Array > normals; Array trigs; public: TriangleApproximation(); int GetNP () const { return points.Size(); } int GetNT () const { return trigs.Size(); } int AddPoint (const Point<3> & p) { points.Append (p); return points.Size()-1; } int AddNormal (const Vec<3> & n) { normals.Append (n); return normals.Size()-1; } int AddTriangle (const TATriangle & tri, bool invert = 0); const Point<3> & GetPoint (int i) const { return points[i]; } const TATriangle & GetTriangle (int i) const { return trigs[i]; } const Vec<3> & GetNormal (int i) const { return normals[i]; } void RemoveUnusedPoints (); friend class CSGeometry; }; } #endif netgen-6.2.1905/libsrc/csg/curve2d.hpp0000644000175000017500000000247613504650527016127 0ustar kurtkurt#ifndef FILE_CURVE2D #define FILE_CURVE2D /**************************************************************************/ /* File: curve2d.hh */ /* Author: Joachim Schoeberl */ /* Date: 24. Jul. 96 */ /**************************************************************************/ namespace netgen { /* 2D Curve repesentation */ /// class Curve2d : public Manifold { public: /// virtual void Project (Point<2> & p) const = 0; /// virtual void NormalVector (const Point<2> & p, Vec<2> & n) const = 0; }; /// class CircleCurve2d : public Curve2d { /// Point<2> center; /// double rad; public: /// CircleCurve2d (const Point<2> & acenter, double arad); /// virtual void Project (Point<2> & p) const; /// virtual void NormalVector (const Point<2> & p, Vec<2> & n) const; }; /// class QuadraticCurve2d : public Curve2d { /// double cxx, cyy, cxy, cx, cy, c; public: /// QuadraticCurve2d (); /// void Read (istream & ist); /// virtual void Project (Point<2> & p) const; /// virtual void NormalVector (const Point<2> & p, Vec<2> & n) const; }; } #endif netgen-6.2.1905/libsrc/csg/csgeom.hpp0000644000175000017500000002357413504650527016034 0ustar kurtkurt#ifndef FILE_CSGEOM #define FILE_CSGEOM /**************************************************************************/ /* File: csgeom.hh */ /* Author: Joachim Schoeberl */ /* Date: 27. Nov. 97 */ /**************************************************************************/ namespace netgen { /** Constructive Solid Geometry */ class TriangleApproximation; class TATriangle; /** A top level object is an entity to be meshed. I can be either a solid, or one surface patch of a solid. */ class DLL_HEADER TopLevelObject { Solid * solid; Surface * surface; double red, blue, green; bool visible, transp; double maxh; string material; int layer; int bc; // for surface patches, only string bcname; public: TopLevelObject (Solid * asolid, Surface * asurface = NULL); // default constructor for archive TopLevelObject() {} void DoArchive(Archive& archive) { archive & solid & surface & red & blue & green & visible & transp & maxh & material & layer & bc & bcname; } const Solid * GetSolid() const { return solid; } Solid * GetSolid() { return solid; } const Surface * GetSurface () const { return surface; } Surface * GetSurface () { return surface; } void GetData (ostream & ost); void SetData (istream & ist); void SetMaxH (double amaxh) { maxh = amaxh; } double GetMaxH () const { return maxh; } void SetRGB (double ared, double agreen, double ablue) { red = ared; green = agreen; blue = ablue; } double GetRed () const { return red; } double GetGreen () const { return green; } double GetBlue () const { return blue; } void SetTransparent (bool atransp) { transp = atransp; } bool GetTransparent () const { return transp; } void SetVisible (bool avisible) { visible = avisible; } bool GetVisible () const { return visible; } const string GetMaterial () const { return material; } void SetMaterial (const string & mat) { material = mat; } int GetLayer () const { return layer; } void SetLayer (int alayer) { layer = alayer; } void SetBCProp (int abc) { bc = abc; } int GetBCProp () const { return bc; } void SetBCName (string abc) { bcname = abc; } const string GetBCName () const { return bcname; } }; /** CSGeometry has the whole geometric information */ class DLL_HEADER CSGeometry : public NetgenGeometry { private: /// all surfaces SymbolTable surfaces; public: /// primitive of surface Array surf2prim; private: Array delete_them; /// all named solids SymbolTable solids; /// all 2d splinecurves SymbolTable< SplineGeometry<2>* > splinecurves2d; /// all 3d splinecurves SymbolTable< SplineGeometry<3>* > splinecurves3d; /// all top level objects: solids and surfaces Array toplevelobjects; public: /// additional points specified by user class UserPoint : public Point<3> { int index; public: UserPoint() = default; UserPoint (Point<3> p, int _index) : Point<3>(p), index(_index) { ; } int GetIndex() const { return index; } void DoArchive(Archive& archive) { archive & index; Point<3>::DoArchive(archive); } }; private: // Array > userpoints; Array userpoints; Array userpoints_ref_factor; mutable Array > identpoints; /// triangular approximation of top level objects Array triapprox; /// increment, if geometry is changed static int changeval; /// bounding box of geometry Box<3> boundingbox; /// bounding box, if not set by input file static Box<3> default_boundingbox; /// identic surfaces are stored by pair of indizes, val = inverse INDEX_2_HASHTABLE identicsurfaces; Array isidenticto; /// identification of boundaries (periodic, thin domains, ...) double ideps; /// filename of inputfile string filename; /// store splinesurfaces, such that added ones do not get deleted before geometry does Array> spline_surfaces; public: CSGeometry (); CSGeometry (const string & afilename); virtual ~CSGeometry (); void Clean (); virtual void Save (string filename) const override; void Save (ostream & ost) const; void Load (istream & ist); void SaveSurfaces (ostream & out) const; void LoadSurfaces (istream & in); virtual void SaveToMeshFile (ostream & ost) const override; int GetChangeVal() { return changeval; } void Change() { changeval++; } void AddSurface (Surface * surf); void AddSurface (char * name, Surface * surf); void AddSurfaces (Primitive * prim); int GetNSurf () const { return surfaces.Size(); } const Surface * GetSurface (const char * name) const; const Surface * GetSurface (int i) const { return surfaces[i]; } void SetSolid (const char * name, Solid * sol); const Solid * GetSolid (const char * name) const; const Solid * GetSolid (const string & name) const; int GetNSolids () const { return solids.Size(); } const Solid * GetSolid (int i) const { return solids[i]; } const SymbolTable & GetSolids () const { return solids; } void SetSplineCurve (const char * name, SplineGeometry<2> * spl); void SetSplineCurve (const char * name, SplineGeometry<3> * spl); const SplineGeometry<2> * GetSplineCurve2d (const string & name) const; const SplineGeometry<3> * GetSplineCurve3d (const string & name) const; void DoArchive(Archive& archive) override; void SetFlags (const char * solidname, const Flags & flags); int GetNTopLevelObjects () const { return toplevelobjects.Size(); } int SetTopLevelObject (Solid * sol, Surface * surf = NULL); void GetTopLevelObject (int nr, Solid *& sol, Surface *& surf) { sol = toplevelobjects[nr]->GetSolid(); surf = toplevelobjects[nr]->GetSurface(); } void GetTopLevelObject (int nr, const Solid *& sol, const Surface *& surf) const { sol = toplevelobjects[nr]->GetSolid(); surf = toplevelobjects[nr]->GetSurface(); } TopLevelObject * GetTopLevelObject (const Solid * sol, const Surface * surf = NULL); TopLevelObject * GetTopLevelObject (int nr) const { return toplevelobjects[nr]; } // const TopLevelObject * GetTopLevelObject (int nr) const // { return toplevelobjects[nr]; } void RemoveTopLevelObject (Solid * sol, Surface * surf = NULL); void AddUserPoint (const Point<3> & p, double ref_factor = 0) { userpoints.Append (UserPoint(p,userpoints.Size()+1)); userpoints_ref_factor.Append (ref_factor); } void AddUserPoint (const UserPoint up, double ref_factor = 0) { userpoints.Append (up); userpoints_ref_factor.Append (ref_factor); } int GetNUserPoints () const { return userpoints.Size(); } const UserPoint & GetUserPoint (int nr) const { return userpoints[nr]; } double GetUserPointRefFactor (int nr) const { return userpoints_ref_factor[nr]; } void AddIdentPoint (const Point<3> & p) const { identpoints.Append(p);} int GetNIdentPoints (void) const { return identpoints.Size();} const Point<3> & GetIdentPoint(int nr) const { return identpoints[nr]; } void DeleteIdentPoints(void) const { identpoints.DeleteAll();} // quick implementations: Array singfaces; Array singedges; Array singpoints; Array identifications; int GetNIdentifications (void) const { return identifications.Size(); } void AddIdentification (Identification * ident); /// void CalcTriangleApproximation(double detail, double facets); /// void FindIdenticSurfaces (double eps); /// void GetSurfaceIndices (const Solid * sol, const BoxSphere<3> & box, Array & locsurf) const; /// void GetIndependentSurfaceIndices (const Solid * sol, const BoxSphere<3> & box, Array & locsurf) const; /// /* void GetIndependentSurfaceIndices (const Solid * sol, const Point<3> & p, Vec<3> & v, Array & locsurf) const; */ /// void GetIndependentSurfaceIndices (Array & locsurf) const; /// int GetSurfaceClassRepresentant (int si) const { return isidenticto[si]; } /// const TriangleApproximation * GetTriApprox (int msnr) { if (msnr < triapprox.Size()) return triapprox[msnr]; return 0; } void IterateAllSolids (SolidIterator & it, bool only_once = false) const; void RefineTriangleApprox (Solid * locsol, int surfind, const BoxSphere<3> & box, double detail, const TATriangle & tria, TriangleApproximation & tams, IndexSet & iset, int level); const Box<3> & BoundingBox () const { return boundingbox; } void SetBoundingBox (const Box<3> & abox) { boundingbox = abox; } static void SetDefaultBoundingBox (const Box<3> & abox) { default_boundingbox = abox; } double MaxSize () const; void SetIdEps(double eps){ideps = eps;} double GetIdEps(void) const {return ideps;} class BCModification { public: int si; int tlonr; int bcnr; string * bcname; }; Array bcmodifications; virtual int GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam) override; virtual const Refinement & GetRefinement () const override; void AddSplineSurface (shared_ptr ss) { spline_surfaces.Append(ss); } }; } #endif netgen-6.2.1905/libsrc/csg/edgeflw.cpp0000644000175000017500000013502713504650527016164 0ustar kurtkurt#include #include #include // #undef DEVELOP // #define DEVELOP namespace netgen { EdgeCalculation :: EdgeCalculation (const CSGeometry & ageometry, Array & aspecpoints, MeshingParameters & amparam) : geometry(ageometry), specpoints(aspecpoints), mparam(amparam) { Box<3> bbox = geometry.BoundingBox(); searchtree = new Point3dTree (bbox.PMin(), bbox.PMax()); meshpoint_tree = new Point3dTree (bbox.PMin(), bbox.PMax()); for (int i = 0; i < specpoints.Size(); i++) searchtree->Insert (specpoints[i].p, i); ideps = 1e-9; } EdgeCalculation :: ~EdgeCalculation() { delete searchtree; delete meshpoint_tree; } void EdgeCalculation :: Calc(double h, Mesh & mesh) { static int timer = NgProfiler::CreateTimer ("CSG: mesh edges"); NgProfiler::RegionTimer reg (timer); PrintMessage (1, "Find edges"); PushStatus ("Find edges"); for (PointIndex pi : mesh.Points().Range()) meshpoint_tree->Insert (mesh[pi], pi); // add all special points before edge points (important for periodic identification) // JS, Jan 2007 const double di=1e-7*geometry.MaxSize(); Array locsearch; for (int i = 0; i < specpoints.Size(); i++) if (specpoints[i].unconditional) { Point<3> p = specpoints[i].p; meshpoint_tree -> GetIntersecting (p-Vec<3> (di,di,di), p+Vec<3> (di,di,di), locsearch); if (locsearch.Size() == 0) { PointIndex pi = mesh.AddPoint (p, specpoints[i].GetLayer(), FIXEDPOINT); meshpoint_tree -> Insert (p, pi); } } /* // slow version for (int i = 0; i < specpoints.Size(); i++) if (specpoints[i].unconditional) { Point<3> p = specpoints[i].p; bool found = false; for (int j = 1; j <= mesh.GetNP(); j++) if (Dist (p, mesh.Point(j)) < 1e-8) found = true; if (!found) mesh.AddPoint (p, specpoints[i].GetLayer(), FIXEDPOINT); } */ CalcEdges1 (h, mesh); SplitEqualOneSegEdges (mesh); FindClosedSurfaces (h, mesh); PrintMessage (3, cntedge, " edges found"); PopStatus (); } void EdgeCalculation :: CalcEdges1 (double h, Mesh & mesh) { Array hsp(specpoints.Size()); Array glob2hsp(specpoints.Size()); Array startpoints, endpoints; int pos, ep; int layer; Point<3> p, np; int pi1, s1, s2, s1_orig, s2_orig; Array > edgepoints; Array curvelength; int copyedge = 0, copyfromedge = -1, copyedgeidentification = -1; Array locsurfind, locind; int checkedcopy = 0; // double size = geometry.MaxSize(); // double epspointdist2 = sqr (size) * 1e-12; // copy special points to work with for (int i = 0; i < specpoints.Size(); i++) { hsp[i] = i; glob2hsp[i] = i; } //for(int i=0; i identification_used(100); // identification i already used for startpoint j mesh.GetIdentifications().Delete(); TABLE specpoint2surface(specpoints.Size()); if (geometry.identifications.Size()) { for (int i = 0; i < specpoints.Size(); i++) for (int j = 0; j < geometry.GetNSurf(); j++) if (geometry.GetSurface(j)->PointOnSurface (specpoints[i].p)) specpoint2surface.Add (i, j); } TABLE specpoint2tlo(specpoints.Size()); if (geometry.identifications.Size()) { for (int i = 0; i < specpoints.Size(); i++) for (int j = 0; j < geometry.GetNTopLevelObjects(); j++) { const TopLevelObject * tlo = geometry.GetTopLevelObject (j); if (tlo->GetSolid() && tlo->GetSolid()->VectorIn (specpoints[i].p,specpoints[i].v)) //if (tlo->GetSolid() && tlo->GetSolid()->IsIn (specpoints[i].p)) { #ifdef DEVELOP (*testout) << "point " << specpoints[i].p << " v " <GetSolid()->Name() << endl; #endif specpoint2tlo.Add (i, j); } } } for (int i = 0; i < specpoints.Size(); i++) specpoints[i].nr = i; while (hsp.Size()) { SetThreadPercent(100 - 100 * double (hsp.Size()) / specpoints.Size()); #ifdef DEVELOP (*testout) << "hsp.Size() " << hsp.Size() << " specpoints.Size() " << specpoints.Size() << endl; (*testout) << endl << "edge nr " << cntedge+1 << endl; #endif edgepoints.SetSize (0); curvelength.SetSize (0); pi1 = 0; copyedge = 0; // identifyable point available ? for (int i = 0; i < geometry.identifications.Size() && !pi1; i++) for (int j = checkedcopy; j < startpoints.Size() && !pi1; j++) { #ifdef DEVELOP (*testout) << "checking point " << specpoints[startpoints[j]].p << ", v = " << specpoints[startpoints[j]].v << " for copying (i,j = " << i << ", " << j << ")" << endl; #endif if (geometry.identifications[i]->IdentifyableCandidate (specpoints[startpoints[j]]) && geometry.identifications[i]->IdentifyableCandidate (specpoints[endpoints[j]])) { int pi1cand = 0; double mindist = 1e10; for (int k = 0; k < hsp.Size() && !pi1; k++) { //(*testout) << " ? identifyable with " << specpoints[hsp[k]].p //<< ", v = " << specpoints[hsp[k]].v // << endl; if (identification_used.Used (INDEX_2(i, startpoints[j])) || identification_used.Used (INDEX_2(i, hsp[k]))) { //(*testout) << "failed at pos0" << endl; continue; } if (geometry.identifications[i] ->Identifyable(specpoints[startpoints[j]], specpoints[hsp[k]], specpoint2tlo, specpoint2surface) || geometry.identifications[i] ->Identifyable(specpoints[hsp[k]], specpoints[startpoints[j]], specpoint2tlo, specpoint2surface)) { #ifdef DEVELOP (*testout) << "identifyable: " << specpoints[hsp[k]].p << ", v = " << specpoints[hsp[k]].v << " and " << specpoints[startpoints[j]].p << ", v = " << specpoints[startpoints[j]].v << " (identification " << i+1 << ")" << endl; #endif if (Dist (specpoints[startpoints[j]].p, specpoints[hsp[k]].p) < mindist) { mindist = Dist (specpoints[startpoints[j]].p, specpoints[hsp[k]].p); pi1cand = k+1; } } } if (pi1cand) { pi1 = pi1cand; copyedge = 1; copyfromedge = j+1; copyedgeidentification = i+1; identification_used.Set (INDEX_2(i, startpoints[j]), 1); identification_used.Set (INDEX_2(i, hsp.Get(pi1)), 1); } } } // cannot copy from other ege ? if (!pi1) checkedcopy = startpoints.Size(); // unconditional special point available ? if (!pi1) for (int i = 1; i <= hsp.Size(); i++) if (specpoints[hsp.Get(i)].unconditional == 1) { pi1 = i; break; } if (!pi1) { // no unconditional points available, choose first conitional pi1 = 1; } layer = specpoints[hsp.Get(pi1)].GetLayer(); if (!specpoints[hsp.Get(pi1)].unconditional) { specpoints[hsp.Elem(pi1)].unconditional = 1; for (int i = 1; i <= hsp.Size(); i++) if (i != pi1 && Dist (specpoints[hsp.Get(pi1)].p, specpoints[hsp.Get(i)].p) < 1e-8*geometry.MaxSize() && (specpoints[hsp.Get(pi1)].v + specpoints[hsp.Get(i)].v).Length() < 1e-4) { // opposite direction specpoints[hsp.Elem(i)].unconditional = 1; } } cntedge++; startpoints.Append (hsp.Get(pi1)); #ifdef DEVELOP (*testout) << "start followedge: p1 = " << specpoints[hsp.Get(pi1)].p << ", v = " << specpoints[hsp.Get(pi1)].v << endl; #endif FollowEdge (pi1, ep, pos, hsp, h, mesh, edgepoints, curvelength); if (multithread.terminate) return; if (!ep) { // ignore starting point hsp.DeleteElement (pi1); cout << "yes, this happens" << endl; continue; } endpoints.Append (hsp.Get(ep)); double elen = 0; for (int i = 1; i <= edgepoints.Size()-1; i++) elen += Dist (edgepoints.Get(i), edgepoints.Get(i+1)); int shortedge = 0; for (int i = 1; i <= geometry.identifications.Size(); i++) if (geometry.identifications.Get(i)->ShortEdge(specpoints[hsp.Get(pi1)], specpoints[hsp.Get(ep)])) shortedge = 1; // (*testout) << "shortedge = " << shortedge << endl; if (!shortedge) { mesh.RestrictLocalHLine (Point3d (specpoints[hsp.Get(pi1)].p), Point3d (specpoints[hsp.Get(ep)].p), elen / mparam.segmentsperedge); } s1 = specpoints[hsp.Get(pi1)].s1; s2 = specpoints[hsp.Get(pi1)].s2; s1_orig = specpoints[hsp.Get(pi1)].s1_orig; s2_orig = specpoints[hsp.Get(pi1)].s2_orig; // delete initial, terminal and conditional points #ifdef DEVELOP (*testout) << "terminal point: p = " << specpoints[hsp.Get(ep)].p << ", v = " << specpoints[hsp.Get(ep)].v << endl; #endif searchtree -> DeleteElement (hsp.Get(ep)); searchtree -> DeleteElement (hsp.Get(pi1)); if (ep > pi1) { glob2hsp[hsp[ep-1]] = -1; glob2hsp[hsp.Last()] = ep-1; hsp.DeleteElement (ep); glob2hsp[hsp[pi1-1]] = -1; glob2hsp[hsp.Last()] = pi1-1; hsp.DeleteElement (pi1); } else { glob2hsp[hsp[pi1-1]] = -1; glob2hsp[hsp.Last()] = pi1-1; hsp.DeleteElement (pi1); glob2hsp[hsp[ep-1]] = -1; glob2hsp[hsp.Last()] = ep-1; hsp.DeleteElement (ep); } for (int j = 1; j <= edgepoints.Size()-1; j++) { p = edgepoints.Get(j); np = Center (p, edgepoints.Get(j+1)); double hd = Dist (p, np); Box<3> boxp (np - (1.2 * hd) * Vec<3> (1, 1, 1), np + (1.2 * hd) * Vec<3> (1, 1, 1)); searchtree -> GetIntersecting (boxp.PMin(), boxp.PMax(), locind); for (int i = 0; i < locind.Size(); i++) { if ( specpoints[locind[i]].HasSurfaces (s1, s2) && specpoints[locind[i]].unconditional == 0) { searchtree -> DeleteElement (locind[i]); int li = glob2hsp[locind[i]]; glob2hsp[locind[i]] = -1; glob2hsp[hsp.Last()] = li; hsp.Delete (li); } } /* for (int i = 1; i <= hsp.Size(); i++) if ( specpoints[hsp.Get(i)].HasSurfaces (s1, s2) && specpoints[hsp.Get(i)].unconditional == 0 && Dist2 (np, specpoints[hsp.Get(i)].p) < 1.2 * hd) { searchtree -> DeleteElement (hsp.Get(i)+1); hsp.DeleteElement (i); i--; } */ } Array refedges; Array refedgesinv; AnalyzeEdge (s1_orig, s2_orig, s1, s2, pos, layer, edgepoints, refedges, refedgesinv); for (int i = 0; i < refedges.Size(); i++) refedges[i].edgenr = cntedge; #ifdef DEVELOP (*testout) << "edge " << cntedge << endl << "startp: " << specpoints[startpoints.Last()].p << ", v = " << specpoints[startpoints.Last()].v << endl << "copy = " << copyedge << endl << refedges.Size() << " refedges: "; for (int i = 1; i <= refedges.Size(); i++) (*testout) << " " << refedges.Get(i).si; (*testout) << endl; if (refedgesinv.Size()) (*testout) << "inv[1] = " << refedgesinv.Get(1) << endl; #endif if (refedges.Size() == 0) throw NgException ("Problem in edge detection"); if (!copyedge) { // (*testout) << "store edge" << endl; // int oldnseg = mesh.GetNSeg(); if (!shortedge) StoreEdge (refedges, refedgesinv, edgepoints, curvelength, layer, mesh); else StoreShortEdge (refedges, refedgesinv, edgepoints, curvelength, layer, mesh); for(int i = 0; i < refedges.Size(); i++) { refedges[i].surfnr1 = geometry.GetSurfaceClassRepresentant(refedges[i].surfnr1); refedges[i].surfnr2 = geometry.GetSurfaceClassRepresentant(refedges[i].surfnr2); } /* for (int i = oldnseg+1; i <= mesh.GetNSeg(); i++) for (int j = 1; j <= oldnseg; j++) { const Point<3> & l1p1 = mesh.Point (mesh.LineSegment(i).p1); const Point<3> & l1p2 = mesh.Point (mesh.LineSegment(i).p2); const Point<3> & l2p1 = mesh.Point (mesh.LineSegment(j).p1); const Point<3> & l2p2 = mesh.Point (mesh.LineSegment(j).p2); Vec<3> vl1(l1p1, l1p2); for (double lamk = 0; lamk <= 1; lamk += 0.1) { Point<3> l2p = l1p1 + lamk * vl1; double dist = sqrt (MinDistLP2 (l2p1, l2p2, l2p)); if (dist > 1e-12) mesh.RestrictLocalH (l2p, 3*dist); } } */ } else { CopyEdge (refedges, refedgesinv, copyfromedge, specpoints[startpoints.Get(copyfromedge)].p, specpoints[endpoints.Get(copyfromedge)].p, edgepoints.Get(1), edgepoints.Last(), copyedgeidentification, layer, mesh); } for(int i=0; i(geometry.GetSurface(refedges[i].surfnr1)); if(splinesurface) { auto name = splinesurface->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p); mesh.SetCD2Name(refedges[i].edgenr,name); } else { auto splinesurface2 = dynamic_cast(geometry.GetSurface(refedges[i].surfnr2)); if(splinesurface2) { auto name = splinesurface2->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p); mesh.SetCD2Name(refedges[i].edgenr,name); } } } /* // not available ... for (int i = 0; i < refedges.Size(); i++) { EdgeDescriptor ed; ed.SetSurfNr(0, refedges[i].surfnr1); ed.SetSurfNr(1, refedges[i].surfnr2); int hnr = mesh.AddEdgeDescriptor(ed); if (hnr != refedges[i].edgenr) { cerr << "edgedescriptor index wrong: new : " << hnr << " old = " << refedges[i].edgenr << endl; } } */ // for(int i=0; i osedges(cntedge); INDEX_2_HASHTABLE osedgesht (cntedge+1); osedges = 2; // count segments on edges for (si = 0; si < mesh.GetNSeg(); si++) { const Segment & seg = mesh[si]; if (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge) osedges.Elem(seg.edgenr)--; } // flag one segment edges for (int i = 0; i < cntedge; i++) osedges[i] = (osedges[i] > 0) ? 1 : 0; for (si = 0; si < mesh.GetNSeg(); si++) { const Segment & seg = mesh[si]; if (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge) { if (osedges.Get(seg.edgenr)) { INDEX_2 i2(seg[0], seg[1]); i2.Sort (); if (osedgesht.Used (i2)) osedgesht.Set (i2, 2); else osedgesht.Set (i2, 1); } } } // one edge 1 segment, other 2 segments // yes, it happens ! point_on_edge_problem = 0; for (int i = 1; i <= osedgesht.GetNBags(); i++) for (int j = 1; j <= osedgesht.GetBagSize(i); j++) { INDEX_2 i2; int val; osedgesht.GetData (i, j, i2, val); const Point<3> & p1 = mesh[PointIndex(i2.I1())]; const Point<3> & p2 = mesh[PointIndex(i2.I2())]; Vec<3> v = p2 - p1; double vlen = v.Length(); v /= vlen; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (pi != i2.I1() && pi != i2.I2()) { const Point<3> & p = mesh[pi]; Vec<3> v2 = p - p1; double lam = (v2 * v); if (lam > 0 && lam < vlen) { Point<3> hp = p1 + lam * v; if (Dist (p, hp) < 1e-4 * vlen) { PrintWarning ("Point on edge !!!"); cout << "seg: " << i2 << ", p = " << pi << endl; osedgesht.Set (i2, 2); point_on_edge_problem = 1; (*testout) << "Point on edge" << endl << "seg = " << i2 << ", p = " << pi << endl << "pos = " << p << ", projected = " << hp << endl << "seg is = " << mesh.Point(PointIndex(i2.I1())) << " - " << mesh.Point(PointIndex(i2.I2())) << endl; } } } } // insert new points osedges = -1; int nseg = mesh.GetNSeg(); for (si = 0; si < nseg; si++) { const Segment & seg = mesh[si]; if (seg.seginfo && seg.edgenr >= 1 && seg.edgenr <= cntedge) { INDEX_2 i2(seg[0], seg[1]); i2.Sort (); if (osedgesht.Used (i2) && osedgesht.Get (i2) == 2 && osedges.Elem(seg.edgenr) == -1) { Point<3> newp = Center (mesh[PointIndex(seg[0])], mesh[PointIndex(seg[1])]); ProjectToEdge (geometry.GetSurface(seg.surfnr1), geometry.GetSurface(seg.surfnr2), newp); osedges.Elem(seg.edgenr) = mesh.AddPoint (newp, mesh[PointIndex(seg[0])].GetLayer(), EDGEPOINT); meshpoint_tree -> Insert (newp, osedges.Elem(seg.edgenr)); } } } // for (int i = 1; i <= nseg; i++) for (Segment & seg : mesh.LineSegments()) { // Segment & seg = mesh.LineSegment (i); if (seg.edgenr >= 1 && seg.edgenr <= cntedge) { if (osedges.Get(seg.edgenr) != -1) { Segment newseg = seg; newseg[0] = osedges.Get(seg.edgenr); seg[1] = osedges.Get(seg.edgenr); mesh.AddSegment (newseg); } } } } void EdgeCalculation :: FollowEdge (int pi1, int & ep, int & pos, const Array & hsp, double h, const Mesh & mesh, Array > & edgepoints, Array & curvelength) { int s1, s2, s1_rep, s2_rep; double len, steplen, cursteplen, loch; Point<3> p, np, pnp; Vec<3> a1, a2, t; Array locind; double size = geometry.MaxSize(); double epspointdist2 = size * 1e-6; epspointdist2 = sqr (epspointdist2); int uselocalh = mparam.uselocalh; s1_rep = specpoints[hsp.Get(pi1)].s1; s2_rep = specpoints[hsp.Get(pi1)].s2; s1 = specpoints[hsp.Get(pi1)].s1_orig; s2 = specpoints[hsp.Get(pi1)].s2_orig; p = specpoints[hsp.Get(pi1)].p; //ProjectToEdge (geometry.GetSurface(s1), // geometry.GetSurface(s2), p); geometry.GetSurface(s1) -> CalcGradient (p, a1); geometry.GetSurface(s2) -> CalcGradient (p, a2); t = Cross (a1, a2); t.Normalize(); pos = (specpoints[hsp.Get(pi1)].v * t) > 0; if (!pos) t *= -1; edgepoints.Append (p); curvelength.Append (0); len = 0; // (*testout) << "geometry.GetSurface(s1) -> LocH (p, 3, 1, h) " << geometry.GetSurface(s1) -> LocH (p, 3, 1, h) // << " geometry.GetSurface(s2) -> LocH (p, 3, 1, h) " << geometry.GetSurface(s2) -> LocH (p, 3, 1, h) << endl; loch = min2 (geometry.GetSurface(s1) -> LocH (p, 3, 1, mparam, h), geometry.GetSurface(s2) -> LocH (p, 3, 1, mparam, h)); if (uselocalh) { double lh = mesh.GetH(p); // (*testout) << "lh " << lh << endl; if (lh < loch) loch = lh; } steplen = 0.1 * loch; do { if (multithread.terminate) return; if (fabs (p(0)) + fabs (p(1)) + fabs (p(2)) > 100000*size) { ep = 0; PrintWarning ("Give up line"); break; } if (steplen > 0.1 * loch) steplen = 0.1 * loch; steplen *= 2; do { steplen *= 0.5; np = p + steplen * t; pnp = np; ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), pnp); } while (Dist (np, pnp) > 0.1 * steplen); cursteplen = steplen; if (Dist (np, pnp) < 0.01 * steplen) steplen *= 2; np = pnp; ep = 0; double hvtmin = 1.5 * cursteplen; Box<3> boxp (p - (2 * cursteplen) * Vec<3> (1, 1, 1), p + (2 * cursteplen) * Vec<3> (1, 1, 1)); searchtree -> GetIntersecting (boxp.PMin(), boxp.PMax(), locind); for (int i = 0; i < locind.Size(); i++) { Vec<3> hv = specpoints[locind[i]].p - p; if (hv.Length2() > 9 * cursteplen * cursteplen) continue; double hvt = hv * t; hv -= hvt * t; if (hv.Length() < 0.2 * cursteplen && hvt > 0 && // hvt < 1.5 * cursteplen && hvt < hvtmin && specpoints[locind[i]].unconditional == 1 && (specpoints[locind[i]].v + t).Length() < 0.4 ) { Point<3> hep = specpoints[locind[i]].p; ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hep); if (Dist2 (hep, specpoints[locind[i]].p) < epspointdist2 ) { geometry.GetSurface(s1) -> CalcGradient (hep, a1); geometry.GetSurface(s2) -> CalcGradient (hep, a2); Vec<3> ept = Cross (a1, a2); ept /= ept.Length(); if (!pos) ept *= -1; if ( (specpoints[locind[i]].v + ept).Length() < 1e-4 ) { np = specpoints[locind[i]].p; for (int jj = 0; jj < hsp.Size(); jj++) if (hsp[jj] == locind[i]) ep = jj+1; if (!ep) cerr << "endpoint not found" << endl; // ep = i; hvtmin = hvt; // break; } } } } /* for (int i = 1; i <= hsp.Size(); i++) { if (!boxp.IsIn (specpoints[hsp.Get(i)].p)) continue; Vec<3> hv = specpoints[hsp.Get(i)].p - p; if (hv.Length2() > 9 * cursteplen * cursteplen) continue; double hvt = hv * t; hv -= hvt * t; if (hv.Length() < 0.2 * cursteplen && hvt > 0 && // hvt < 1.5 * cursteplen && hvt < hvtmin && specpoints[hsp.Get(i)].unconditional == 1 && (specpoints[hsp.Get(i)].v + t).Length() < 0.4 ) { Point<3> hep = specpoints[hsp.Get(i)].p; ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hep); if (Dist2 (hep, specpoints[hsp.Get(i)].p) < epspointdist2 ) { geometry.GetSurface(s1) -> CalcGradient (hep, a1); geometry.GetSurface(s2) -> CalcGradient (hep, a2); Vec<3> ept = Cross (a1, a2); ept /= ept.Length(); if (!pos) ept *= -1; if ( (specpoints[hsp.Get(i)].v + ept).Length() < 1e-4 ) { np = specpoints[hsp.Get(i)].p; ep = i; hvtmin = hvt; // break; } } } } */ loch = min2 (geometry.GetSurface(s1_rep) -> LocH (np, 3, 1, mparam, h), geometry.GetSurface(s2_rep) -> LocH (np, 3, 1, mparam, h)); loch = max2 (loch, mparam.minh); if (uselocalh) { double lh = mesh.GetH(np); if (lh < loch) loch = lh; } len += Dist (p, np) / loch; edgepoints.Append (np); curvelength.Append (len); p = np; geometry.GetSurface(s1) -> CalcGradient (p, a1); geometry.GetSurface(s2) -> CalcGradient (p, a2); t = Cross (a1, a2); t.Normalize(); if (!pos) t *= -1; } while (! ep); } void EdgeCalculation :: AnalyzeEdge (int s1, int s2, int s1_rep, int s2_rep, int pos, int layer, const Array > & edgepoints, Array & refedges, Array & refedgesinv) { Segment seg; Array locsurfind, locsurfind2; Array edges_priority; double size = geometry.MaxSize(); bool debug = 0; #ifdef DEVELOP debug = 1; #endif if (debug) { (*testout) << "debug edge !!!" << endl; (*testout) << "edgepoints = " << edgepoints << endl; (*testout) << "s1, s2 = " << s1 << " - " << s2 << endl; (*testout) << "s1_rep, s2_rep = " << s1_rep << " - " << s2_rep << endl; } refedges.SetSize(0); refedgesinv.SetSize(0); Point<3> hp = Center (edgepoints[0], edgepoints[1]); ProjectToEdge (geometry.GetSurface(s1), geometry.GetSurface(s2), hp); if (debug) *testout << "hp = " << hp << endl; Vec<3> t, a1, a2; geometry.GetSurface(s1) -> CalcGradient (hp, a1); geometry.GetSurface(s2) -> CalcGradient (hp, a2); t = Cross (a1, a2); t.Normalize(); if (!pos) t *= -1; for (int i = 0; i < geometry.GetNTopLevelObjects(); i++) { Solid * locsol; if (geometry.GetTopLevelObject(i)->GetLayer() != layer) continue; const Solid * sol = geometry.GetTopLevelObject(i)->GetSolid(); const Surface * surf = geometry.GetTopLevelObject(i)->GetSurface(); sol -> TangentialSolid (hp, locsol, locsurfind, size*ideps); //*testout << "hp = " << hp << endl; //(*testout) << "locsol: " << endl; //if (locsol) locsol->Print(*testout); //(*testout) << endl; if (!locsol) continue; BoxSphere<3> boxp (hp, hp); boxp.Increase (1e-8*size); boxp.CalcDiamCenter(); ReducePrimitiveIterator rpi(boxp); UnReducePrimitiveIterator urpi; ((Solid*)locsol) -> IterateSolid (rpi); locsol -> CalcSurfaceInverse (); if (!surf) { locsol -> GetTangentialSurfaceIndices (hp,locsurfind,ideps*size); } else { /* if (fabs (surf->CalcFunctionValue (hp)) < 1e-6) continue; */ locsurfind.SetSize(1); locsurfind[0] = -1; for (int j = 0; j < geometry.GetNSurf(); j++) if (geometry.GetSurface(j) == surf) { locsurfind[0] = j; // geometry.GetSurfaceClassRepresentant(j); break; } } ((Solid*)locsol) -> IterateSolid (urpi); if (debug) (*testout) << "edge of tlo " << i << ", has " << locsurfind.Size() << " faces." << endl; for (int j = locsurfind.Size()-1; j >= 0; j--) if (fabs (geometry.GetSurface(locsurfind[j]) ->CalcFunctionValue (hp) ) > ideps*size) locsurfind.Delete(j); if (debug) (*testout) << locsurfind.Size() << " faces on hp" << endl; for (int j = 0; j < locsurfind.Size(); j++) { int lsi = locsurfind[j]; int rlsi = geometry.GetSurfaceClassRepresentant(lsi); // n is outer normal to solid Vec<3> n = geometry.GetSurface(lsi) -> GetNormalVector (hp); if (debug) *testout << "n1 = " << n << endl; if (geometry.GetSurface (lsi)->Inverse()) n *= -1; if (fabs (t * n) > 1e-4) continue; if (debug) { (*testout) << "face " << locsurfind[j] << ", rep = " << rlsi << " has (t*n) = " << (t*n) << endl; (*testout) << "n = " << n << endl; } // rn is normal to class representant Vec<3> rn = geometry.GetSurface(rlsi) -> GetNormalVector (hp); if (debug) { (*testout) << "rn = " << rn << endl; } //if( n*rn < 0) // rn *= -1; bool sameasref = ((n * rn) > 0); //m = Cross (t, rn); Vec<3> m = Cross (t, n); if(!sameasref) m*=-1.; m.Normalize(); if (debug) (*testout) << "m = " << m << endl; //bool founddirection = false; //int k; double eps = 1e-8*size; Array pre_ok(2); do { eps *= 0.5; pre_ok[0] = (locsol -> VectorIn2 (hp, m, n, eps) == IS_OUTSIDE && locsol -> VectorIn2 (hp, m, -1. * n, eps) == IS_INSIDE); pre_ok[1] = (locsol -> VectorIn2 (hp, -1.*m, n, eps) == IS_OUTSIDE && locsol -> VectorIn2 (hp, -1.*m, -1. * n, eps) == IS_INSIDE); if (debug) { *testout << "eps = " << eps << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, m, n, eps) << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, m, -1. * n, eps) << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, -1.*m, n, eps) << endl; *testout << "in,1 = " << locsol -> VectorIn2 (hp, -1.*m, -1. * n, eps) << endl; } } while(pre_ok[0] && pre_ok[1] && eps > 1e-16*size); if (debug) { *testout << "eps = " << eps << ", size = " << size << endl; *testout << "pre_ok[0,1] = " << pre_ok[0] << "," << pre_ok[1] << endl; } eps = 1e-8*size; for (int k = 1; k <= 2; k ++) { bool edgeinv = (k == 2); if (debug) { (*testout) << "onface(" << hp << ", " << m << ")= " << flush; (*testout) << locsol->OnFace (hp, m, eps) << flush; (*testout) << " n " << n << flush; (*testout) << " vec2in = " << locsol -> VectorIn2 (hp, m, n, eps) << " and " << locsol -> VectorIn2 (hp, m, -1 * n, eps) << endl; } // if (locsol -> OnFace (hp, m)) // one side must be inside, the other must be outside bool ok = (pre_ok[k-1] || (locsol -> VectorIn2 (hp, m, n, eps) == IS_OUTSIDE && locsol -> VectorIn2 (hp, m, -1 * n, eps) == IS_INSIDE)); if (debug) (*testout) << "ok (before) " << ok << endl; // compute second order approximation // curve = hp + t m + t*t/2 m2 Vec<3> grad, m2; Mat<3> hesse; geometry.GetSurface(lsi) -> CalcGradient (hp, grad); geometry.GetSurface(lsi) -> CalcHesse (hp, hesse); double fac = -(m * (hesse * m)) / (grad * grad); m2 = fac * grad; // (*testout) << "hp = " << hp << ", m = " << m << ", m2 = " << m2 << endl; Solid * locsol2; locsol -> TangentialSolid3 (hp, m, m2, locsol2, locsurfind2, ideps*size); if (!locsol2) ok = 0; delete locsol2; if (ok) { if (debug) (*testout) << "is true" << endl; int hi = 0; for (int l = 1; !hi && l <= refedges.Size(); l++) { if (refedges.Get(l).si == rlsi && // JS sept 2006 // if (refedges.Get(l).si == lsi && refedgesinv.Get(l) == edgeinv) { hi = l; } } if (!hi) { seg.si = rlsi; // JS Sept 2006 // seg.si = lsi; seg.domin = -1; seg.domout = -1; seg.tlosurf = -1; //seg.surfnr1 = s1_rep; //seg.surfnr2 = s2_rep; seg.surfnr1 = s1; seg.surfnr2 = s2; refedges.Append (seg); hi = refedges.Size(); refedgesinv.Append (edgeinv); edges_priority.Append((pre_ok[k-1]) ? 1 : 0); } else { if(edges_priority[hi-1] / 10 == -i-1) edges_priority[hi-1] = 10*(i+1); else edges_priority[hi-1] = -10*(i+1); } if (!surf) { if (sameasref) refedges.Elem(hi).domin = i; else refedges.Elem(hi).domout = i; } else { refedges.Elem(hi).tlosurf = i; for(int kk = 0; kk < geometry.GetNTopLevelObjects(); kk++) { auto othersolid = geometry.GetTopLevelObject(kk)->GetSolid(); auto othersurf = geometry.GetTopLevelObject(kk)->GetSurface(); if(!othersurf && dynamic_cast(othersurf)) { if(othersolid->IsIn(edgepoints[0]) && othersolid->IsIn(edgepoints[edgepoints.Size()-1])) { refedges.Elem(hi).domin = kk; refedges.Elem(hi).domout = kk; } } } } if(pre_ok[k-1]) edges_priority[hi-1] = 1; if (debug) (*testout) << "add ref seg:" << "si = " << refedges.Get(hi).si << ", domin = " << refedges.Get(hi).domin << ", domout = " << refedges.Get(hi).domout << ", surfnr1/2 = " << refedges.Get(hi).surfnr1 << ", " << refedges.Get(hi).surfnr2 << ", inv = " << refedgesinv.Get(hi) << ", refedgenr = " << hi << ", priority = " << edges_priority[hi-1] << ", hi = " << hi << endl; } else { if (debug) (*testout) << "is false" << endl; } m *= -1; } } delete locsol; } if (debug) { *testout << "Refsegments, before delete: " << endl << refedges << endl; *testout << "inv: " << endl << refedgesinv << endl; } BitArray todelete(refedges.Size()); todelete.Clear(); for(int i=0; i edges_priority[j]) { todelete.Set(j); } } } } int num = refedges.Size(); for(int i=refedges.Size()-1; num>2 && i>=0; i--) if(todelete.Test(i)) { refedges.Delete(i); refedgesinv.Delete(i); num--; } if (debug) { *testout << "Refsegments: " << endl << refedges << endl; } } void EdgeCalculation :: StoreEdge (const Array & refedges, const Array & refedgesinv, const Array > & edgepoints, const Array & curvelength, int layer, Mesh & mesh) { // Calculate optimal element-length int i, j, k; PointIndex pi; int ne; double len, corr, lam; PointIndex thispi, lastpi; Point<3> p, np; Segment seg; const Surface * surf1 = geometry.GetSurface (refedges.Get(1).surfnr1); const Surface * surf2 = geometry.GetSurface (refedges.Get(1).surfnr2); (*testout) << "s1 " << refedges.Get(1).surfnr1 << " s2 " << refedges.Get(1).surfnr2 << " rs1 " << geometry.GetSurfaceClassRepresentant(refedges.Get(1).surfnr1) << " rs2 " << geometry.GetSurfaceClassRepresentant(refedges.Get(1).surfnr2) << endl; len = curvelength.Last(); ne = int (len + 0.5); if (ne == 0) ne = 1; if (Dist (edgepoints.Get(1), edgepoints.Last()) < 1e-8*geometry.MaxSize() && ne <= 6) ne = 6; corr = len / ne; // generate initial point p = edgepoints.Get(1); lastpi = -1; /* for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist (mesh[pi], p) < 1e-6) { lastpi = pi; break; } */ const double di=1e-7*geometry.MaxSize(); Array locsearch; meshpoint_tree -> GetIntersecting (p-Vec<3> (di,di,di), p+Vec<3> (di,di,di), locsearch); if (locsearch.Size()) lastpi = locsearch[0]; if (lastpi == -1) { lastpi = mesh.AddPoint (p, layer, FIXEDPOINT); meshpoint_tree -> Insert (p, lastpi); // (*testout) << "test1, store point " << lastpi << ", p = " << p << endl; } j = 1; for (i = 1; i <= ne; i++) { while (curvelength.Get(j) < i * corr && j < curvelength.Size()) j++; lam = (i * corr - curvelength.Get(j-1)) / (curvelength.Get(j) - curvelength.Get(j-1)); np(0) = (1-lam) * edgepoints.Get(j-1)(0) + lam * edgepoints.Get(j)(0); np(1) = (1-lam) * edgepoints.Get(j-1)(1) + lam * edgepoints.Get(j)(1); np(2) = (1-lam) * edgepoints.Get(j-1)(2) + lam * edgepoints.Get(j)(2); thispi = -1; if (i == ne) { /* for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist(mesh[pi], np) < 1e-6) thispi = pi; */ meshpoint_tree -> GetIntersecting (np-Vec<3> (di,di,di), np+Vec<3> (di,di,di), locsearch); if (locsearch.Size()) thispi = locsearch[0]; } if (thispi == -1) { ProjectToEdge (surf1, surf2, np); thispi = mesh.AddPoint (np, layer, (i==ne) ? FIXEDPOINT : EDGEPOINT); meshpoint_tree -> Insert (np, thispi); // (*testout) << "test2, store point " << thispi << ", p = " << np << endl; } for (k = 1; k <= refedges.Size(); k++) { if (refedgesinv.Get(k)) { seg[0] = lastpi; seg[1] = thispi; } else { seg[0] = thispi; seg[1] = lastpi; } seg.si = refedges.Get(k).si; seg.domin = refedges.Get(k).domin; seg.domout = refedges.Get(k).domout; seg.tlosurf = refedges.Get(k).tlosurf; seg.edgenr = refedges.Get(k).edgenr; seg.surfnr1 = refedges.Get(k).surfnr1; seg.surfnr2 = refedges.Get(k).surfnr2; seg.seginfo = 0; if (k == 1) seg.seginfo = (refedgesinv.Get(k)) ? 2 : 1; mesh.AddSegment (seg); //(*testout) << "add seg " << mesh[seg.p1] << "-" << mesh[seg.p2] << endl; //(*testout) << "refedge " << k << " surf1 " << seg.surfnr1 << " surf2 " << seg.surfnr2 << " inv " << refedgesinv.Get(k) << endl; double maxh = min2 (geometry.GetSurface(seg.surfnr1)->GetMaxH(), geometry.GetSurface(seg.surfnr2)->GetMaxH()); if (seg.domin != -1) { const Solid * s1 = geometry.GetTopLevelObject(seg.domin) -> GetSolid(); maxh = min2 (maxh, s1->GetMaxH()); maxh = min2 (maxh, geometry.GetTopLevelObject(seg.domin)->GetMaxH()); mesh.RestrictLocalH (p, maxh); mesh.RestrictLocalH (np, maxh); } if (seg.domout != -1) { const Solid * s1 = geometry.GetTopLevelObject(seg.domout) -> GetSolid(); maxh = min2 (maxh, s1->GetMaxH()); maxh = min2 (maxh, geometry.GetTopLevelObject(seg.domout)->GetMaxH()); mesh.RestrictLocalH (p, maxh); mesh.RestrictLocalH (np, maxh); } if (seg.tlosurf != -1) { double hi = geometry.GetTopLevelObject(seg.tlosurf) -> GetMaxH(); maxh = min2 (maxh, hi); mesh.RestrictLocalH (p, maxh); mesh.RestrictLocalH (np, maxh); } } p = np; lastpi = thispi; } #ifdef DEVELOP (*testout) << " eplast = " << lastpi << " = " << p << endl; #endif } void EdgeCalculation :: StoreShortEdge (const Array & refedges, const Array & refedgesinv, const Array > & edgepoints, const Array & curvelength, int layer, Mesh & mesh) { // Calculate optimal element-length PointIndex pi; // int ne; Segment seg; /* double len, corr, lam; int thispi, lastpi; Point<3> p, np; const Surface * surf1 = geometry.GetSurface (refedges.Get(1).surfnr1); const Surface * surf2 = geometry.GetSurface (refedges.Get(1).surfnr2); len = curvelength.Last(); ne = int (len + 0.5); if (ne == 0) ne = 1; if (Dist2 (edgepoints[1], edgepoints.Last()) < 1e-8 && ne <= 6) ne = 6; corr = len / ne; */ // generate initial point Point<3> p = edgepoints[0]; PointIndex pi1 = -1; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize()) { pi1 = pi; break; } if (pi1 == -1) { pi1 = mesh.AddPoint (p, layer, FIXEDPOINT); meshpoint_tree -> Insert (p, pi1); // (*testout) << "test3, store point " << pi1 << ", p = " << p << endl; } p = edgepoints.Last(); PointIndex pi2 = -1; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize()) { pi2 = pi; break; } if (pi2==-1) { pi2 = mesh.AddPoint (p, layer, FIXEDPOINT); meshpoint_tree -> Insert (p, pi2); // (*testout) << "test4, store point " << pi2 << ", p = " << p << endl; } /* j = 1; for (i = 1; i <= ne; i++) { while (curvelength[j] < i * corr && j < curvelength.Size()) j++; lam = (i * corr - curvelength[j-1]) / (curvelength[j] - curvelength[j-1]); np(0) = (1-lam) * edgepoints[j-1](0) + lam * edgepoints[j](0); np(1) = (1-lam) * edgepoints[j-1](1) + lam * edgepoints[j](1); np(2) = (1-lam) * edgepoints[j-1](2) + lam * edgepoints[j](2); thispi = 0; if (i == ne) for (j = 1; j <= mesh.GetNP(); j++) if (Dist(mesh.Point(j), np) < 1e-6) thispi = j; if (!thispi) { ProjectToEdge (surf1, surf2, np); thispi = mesh.AddPoint (np); } */ // (*testout) << "short edge " << pi1 << " - " << pi2 << endl; for (int k = 1; k <= refedges.Size(); k++) { if (refedgesinv.Get(k)) { seg[0] = pi1; seg[1] = pi2; } else { seg[0] = pi2; seg[1] = pi1; } seg.si = refedges.Get(k).si; seg.domin = refedges.Get(k).domin; seg.domout = refedges.Get(k).domout; seg.tlosurf = refedges.Get(k).tlosurf; seg.edgenr = refedges.Get(k).edgenr; seg.surfnr1 = refedges.Get(k).surfnr1; seg.surfnr2 = refedges.Get(k).surfnr2; seg.seginfo = 0; if (k == 1) seg.seginfo = (refedgesinv.Get(k)) ? 2 : 1; mesh.AddSegment (seg); // (*testout) << "add seg " << seg[0] << "-" << seg[1] << endl; } } void EdgeCalculation :: CopyEdge (const Array & refedges, const Array & refedgesinv, int copyfromedge, const Point<3> & fromstart, const Point<3> & fromend, const Point<3> & tostart, const Point<3> & toend, int copyedgeidentification, int layer, Mesh & mesh) { int k; PointIndex pi; double size = geometry.MaxSize(); // copy start and end points for (int i = 1; i <= 2; i++) { Point<3> fromp = (i == 1) ? fromstart : fromend; Point<3> top = (i == 1) ? tostart : toend; PointIndex frompi = -1; PointIndex topi = -1; for (pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) { if (Dist2 (mesh[pi], fromp) <= 1e-16*size) frompi = pi; if (Dist2 (mesh[pi], top) <= 1e-16*size) topi = pi; } if (topi == -1) { topi = mesh.AddPoint (top, layer, FIXEDPOINT); meshpoint_tree -> Insert (top, topi); } const Identification & csi = (*geometry.identifications.Get(copyedgeidentification)); if (csi.Identifyable (mesh[frompi], mesh[topi])) mesh.GetIdentifications().Add(frompi, topi, copyedgeidentification); else if (csi.Identifyable (mesh[topi], mesh[frompi])) mesh.GetIdentifications().Add(topi, frompi, copyedgeidentification); else { cerr << "edgeflw.cpp: should identify, but cannot"; exit(1); } #ifdef DEVELOP (*testout) << "adding identification " << mesh[frompi] << "; " << mesh[topi] << " (id " << copyedgeidentification <<")" << endl; #endif /* (*testout) << "Add Identification from CopyEdge, p1 = " << mesh[PointIndex(frompi)] << ", p2 = " << mesh[PointIndex(topi)] << endl; mesh.GetIdentifications().Add(frompi, topi, copyedgeidentification); */ } int oldns = mesh.GetNSeg(); for (int i = 1; i <= oldns; i++) { // real copy, since array might be reallocated !! const Segment oldseg = mesh.LineSegment(i); if (oldseg.edgenr != copyfromedge) continue; if (oldseg.seginfo == 0) continue; int pi1 = oldseg[0]; int pi2 = oldseg[1]; int npi1 = geometry.identifications.Get(copyedgeidentification) -> GetIdentifiedPoint (mesh, pi1); int npi2 = geometry.identifications.Get(copyedgeidentification) -> GetIdentifiedPoint (mesh, pi2); //(*testout) << "copy edge, pts = " << npi1 << " - " << npi2 << endl; Segment seg; for (k = 1; k <= refedges.Size(); k++) { bool inv = refedgesinv.Get(k); // other edge is inverse if (oldseg.seginfo == 1) inv = !inv; // (*testout) << "inv, now = " << inv << endl; if (inv) { seg[0] = npi1; seg[1] = npi2; } else { seg[0] = npi2; seg[1] = npi1; } seg.si = refedges.Get(k).si; seg.domin = refedges.Get(k).domin; seg.domout = refedges.Get(k).domout; seg.tlosurf = refedges.Get(k).tlosurf; seg.edgenr = refedges.Get(k).edgenr; seg.surfnr1 = refedges.Get(k).surfnr1; seg.surfnr2 = refedges.Get(k).surfnr2; seg.seginfo = 0; if (k == 1) seg.seginfo = refedgesinv.Get(k) ? 2 : 1; mesh.AddSegment (seg); // (*testout) << "copy seg " << seg[0] << "-" << seg[1] << endl; #ifdef DEVELOP (*testout) << "copy seg, face = " << seg.si << ": " << " inv = " << inv << ", refinv = " << refedgesinv.Get(k) << mesh.Point(seg[0]) << ", " << mesh.Point(seg[1]) << endl; #endif } } } void EdgeCalculation :: FindClosedSurfaces (double h, Mesh & mesh) { // if there is no special point at a sphere, one has to add a segment pair int nsurf = geometry.GetNSurf(); int layer = 0; Solid * tansol; Array tansurfind; double size = geometry.MaxSize(); int nsol = geometry.GetNTopLevelObjects(); BitArray pointatsurface (nsurf); pointatsurface.Clear(); for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); #ifdef DEVELOP (*testout) << seg.surfnr1 << ", " << seg.surfnr2 << ", si = " << seg.si << endl; #endif int classrep = geometry.GetSurfaceClassRepresentant (seg.si); pointatsurface.Set (classrep); } for (int i = 0; i < nsurf; i++) { int classrep = geometry.GetSurfaceClassRepresentant (i); if (!pointatsurface.Test(classrep)) { const Surface * s = geometry.GetSurface(i); Point<3> p1 = s -> GetSurfacePoint(); Vec<3> nv = s -> GetNormalVector (p1); double hloc = min2 (s->LocH (p1, 3, 1, mparam, h), mesh.GetH(p1)); Segment seg1; seg1.si = i; seg1.domin = -1; seg1.domout = -1; Segment seg2; seg2.si = i; seg2.domin = -1; seg2.domout = -1; seg1.surfnr1 = i; seg2.surfnr1 = i; seg1.surfnr2 = i; seg2.surfnr2 = i; for (int j = 0; j < nsol; j++) { if (geometry.GetTopLevelObject(j)->GetSurface()) continue; const Solid * sol = geometry.GetTopLevelObject(j)->GetSolid(); sol -> TangentialSolid (p1, tansol, tansurfind, ideps*size); layer = geometry.GetTopLevelObject(j)->GetLayer(); if (tansol) { tansol -> GetSurfaceIndices (tansurfind); if (tansurfind.Size() == 1 && tansurfind.Get(1) == i) { hloc = min2 (hloc, geometry.GetTopLevelObject(j)->GetMaxH()); if (!tansol->VectorIn(p1, nv)) { seg1.domin = j; seg2.domin = j; seg1.tlosurf = -1; seg2.tlosurf = -1; } else { seg1.domout = j; seg2.domout = j; seg1.tlosurf = -1; seg2.tlosurf = -1; } // seg.s2 = i; // seg.invs1 = surfaces[i] -> Inverse(); // seg.invs2 = ! (surfaces[i] -> Inverse()); } delete tansol; } } Vec<3> tv = nv.GetNormal (); tv *= (hloc / tv.Length()); Point<3> p2 = p1 + tv; s->Project (p2); if (seg1.domin != -1 || seg1.domout != -1) { mesh.AddPoint (p1, layer, EDGEPOINT); mesh.AddPoint (p2, layer, EDGEPOINT); seg1[0] = mesh.GetNP()-1; seg1[1] = mesh.GetNP(); seg2[1] = mesh.GetNP()-1; seg2[0] = mesh.GetNP(); seg1.geominfo[0].trignum = 1; seg1.geominfo[1].trignum = 1; seg2.geominfo[0].trignum = 1; seg2.geominfo[1].trignum = 1; mesh.AddSegment (seg1); mesh.AddSegment (seg2); PrintMessage (5, "Add line segment to smooth surface"); #ifdef DEVELOP (*testout) << "Add segment at smooth surface " << i; if (i != classrep) (*testout) << ", classrep = " << classrep; (*testout) << ": " << mesh.Point (mesh.GetNP()-1) << " - " << mesh.Point (mesh.GetNP()) << endl; #endif } } } } } netgen-6.2.1905/libsrc/csg/extrusion.cpp0000644000175000017500000004471113504650527016606 0ustar kurtkurt#include #include #include namespace netgen { Array > project1, project2; void ExtrusionFace :: Init(void) { p0.SetSize(path->GetNSplines()); x_dir.SetSize(path->GetNSplines()); y_dir.SetSize(path->GetNSplines()); z_dir.SetSize(path->GetNSplines()); loc_z_dir.SetSize(path->GetNSplines()); spline3_path.SetSize(path->GetNSplines()); line_path.SetSize(path->GetNSplines()); for(int i=0; iGetNSplines(); i++) { spline3_path[i] = dynamic_cast < const SplineSeg3<3>* >(&path->GetSpline(i)); line_path[i] = dynamic_cast < const LineSeg<3>* >(&path->GetSpline(i)); if(line_path[i]) { y_dir[i] = line_path[i]->EndPI() - line_path[i]->StartPI(); y_dir[i].Normalize(); z_dir[i] = glob_z_direction; Orthogonalize(y_dir[i],z_dir[i]); x_dir[i] = Cross(y_dir[i],z_dir[i]); loc_z_dir[i] = z_dir[i]; } else { z_dir[i] = glob_z_direction; loc_z_dir[i] = glob_z_direction; } } profile->GetCoeff(profile_spline_coeff); latest_point3d = -1.111e30; } ExtrusionFace :: ExtrusionFace(const SplineSeg<2> * profile_in, const SplineGeometry<3> * path_in, const Vec<3> & z_direction) : profile(profile_in), path(path_in), glob_z_direction(z_direction) { deletable = false; Init(); } ExtrusionFace :: ExtrusionFace(const Array & raw_data) { deletable = true; int pos=0; Array< Point<2> > p(3); int ptype = int(raw_data[pos]); pos++; for(int i=0; i(GeomPoint<2>(p[0],1), GeomPoint<2>(p[1],1)); } else if(ptype == 3) { profile = new SplineSeg3<2>(GeomPoint<2>(p[0],1), GeomPoint<2>(p[1],1), GeomPoint<2>(p[2],1)); } path = new SplineGeometry<3>; pos = const_cast< SplineGeometry<3> *>(path)->Load(raw_data,pos); for(int i = 0; i < 3; i++) { glob_z_direction(i) = raw_data[pos]; pos++; } Init(); } ExtrusionFace :: ~ExtrusionFace() { if(deletable) { delete profile; delete path; } } int ExtrusionFace :: IsIdentic (const Surface & s2, int & inv, double eps) const { const ExtrusionFace * ext2 = dynamic_cast(&s2); if(!ext2) return 0; if(ext2 == this) return 1; return 0; } void ExtrusionFace :: Orthogonalize(const Vec<3> & v1, Vec<3> & v2) const { v2 -= (v1*v2)*v1; v2.Normalize(); } void ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d, int & seg, double & t) const { if (Dist2 (point3d, latest_point3d) < 1e-25 * Dist2(path->GetSpline(0).StartPI(), path->GetSpline(0).EndPI())) { point2d = latest_point2d; seg = latest_seg; t = latest_t; return; } latest_point3d = point3d; double cutdist = -1; Array mindist(path->GetNSplines()); for(int i = 0; i < path->GetNSplines(); i++) { double auxcut = -1; double auxmin = -1; if(spline3_path[i]) { Point<3> startp(path->GetSpline(i).StartPI()); Point<3> endp(path->GetSpline(i).EndPI()); Point<3> tanp(spline3_path[i]->TangentPoint()); // lower bound for dist auxmin = sqrt (MinDistTP2 (startp, endp, tanp, point3d)); // upper bound for dist auxcut = min2 (Dist (startp, point3d), Dist (endp, point3d)); } else if(line_path[i]) { auxmin = auxcut = sqrt (MinDistLP2 (path->GetSpline(i).StartPI(), path->GetSpline(i).EndPI(), point3d)); } mindist[i] = auxmin; if(i==0 || auxcut < cutdist) cutdist = auxcut; } Point<2> testpoint2d; Point<3> testpoint3d; double minproj(-1); bool minproj_set(false); for(int i=0; iGetNSplines(); i++) { if(mindist[i] > cutdist*(1+1e-10)) continue; double thist = CalcProj(point3d,testpoint2d,i); testpoint3d = p0[i] + testpoint2d(0)*x_dir[i] + testpoint2d(1)*loc_z_dir[i]; double d = Dist2(point3d,testpoint3d); if(!minproj_set || d < minproj) { minproj_set = true; minproj = d; point2d = testpoint2d; t = thist; seg = i; latest_seg = i; latest_t = t; latest_point2d = point2d; } } } double ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d, int seg) const { double t = -1; if(line_path[seg]) { point2d(0) = (point3d-line_path[seg]->StartPI())*x_dir[seg]; point2d(1) = (point3d-line_path[seg]->StartPI())*z_dir[seg]; double l = Dist(line_path[seg]->StartPI(), line_path[seg]->EndPI()); t = min2(max2((point3d - line_path[seg]->StartPI()) * y_dir[seg],0.), l); p0[seg] = line_path[seg]->StartPI() + t*y_dir[seg]; t *= 1./l; } else if(spline3_path[seg]) { spline3_path[seg]->Project(point3d,p0[seg],t); y_dir[seg] = spline3_path[seg]->GetTangent(t); y_dir[seg].Normalize(); loc_z_dir[seg] = z_dir[seg]; Orthogonalize(y_dir[seg],loc_z_dir[seg]); x_dir[seg] = Cross(y_dir[seg],loc_z_dir[seg]); Vec<3> dir = point3d-p0[seg]; point2d(0) = x_dir[seg]*dir; point2d(1) = loc_z_dir[seg]*dir; } return t; } double ExtrusionFace :: CalcFunctionValue (const Point<3> & point) const { Point<2> p; double dummyd; int dummyi; CalcProj(point, p, dummyi, dummyd); return profile_spline_coeff(0)*p(0)*p(0) + profile_spline_coeff(1)*p(1)*p(1) + profile_spline_coeff(2)*p(0)*p(1) + profile_spline_coeff(3)*p(0) + profile_spline_coeff(4)*p(1) + profile_spline_coeff(5); } void ExtrusionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const { Point<2> p2d; double t_path; int seg; CalcProj (point, p2d, seg, t_path); Point<3> phi; Vec<3> phip, phipp, phi_minus_point; path->GetSpline(seg).GetDerivatives(t_path, phi, phip, phipp); phi_minus_point = phi-point; Vec<3> grad_t = (1.0/(phipp*phi_minus_point + phip*phip)) * phip; Vec<3> grad_xbar, grad_ybar; Vec<3> hex, hey, hez, dex, dey, dez; CalcLocalCoordinatesDeriv (seg, t_path, hex, hey, hez, dex, dey, dez); grad_xbar = hex - (phi_minus_point*dex + hex*phip) * grad_t; grad_ybar = hez - (phi_minus_point*dez + hez*phip) * grad_t; double dFdxbar = 2.*profile_spline_coeff(0)*p2d(0) + profile_spline_coeff(2)*p2d(1) + profile_spline_coeff(3); double dFdybar = 2.*profile_spline_coeff(1)*p2d(1) + profile_spline_coeff(2)*p2d(0) + profile_spline_coeff(4); grad = dFdxbar * grad_xbar + dFdybar * grad_ybar; } void ExtrusionFace :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const { const double eps = 1e-7*Dist(path->GetSpline(0).StartPI(),path->GetSpline(0).EndPI()); Point<3> auxpoint1(point),auxpoint2(point); Vec<3> auxvec,auxgrad1,auxgrad2; for(int i=0; i<3; i++) { auxpoint1(i) -= eps; auxpoint2(i) += eps; CalcGradient(auxpoint1,auxgrad1); CalcGradient(auxpoint2,auxgrad2); auxvec = (1./(2.*eps)) * (auxgrad2-auxgrad1); for(int j=0; j<3; j++) hesse(i,j) = auxvec(j); auxpoint1(i) = point(i); auxpoint2(i) = point(i); } /* Vec<3> grad; CalcGradient(point,grad); Point<3> auxpoint(point); Vec<3> auxvec,auxgrad; for(int i=0; i<3; i++) { auxpoint(i) -= eps; CalcGradient(auxpoint,auxgrad); auxvec = (1./eps) * (grad-auxgrad); for(int j=0; j<3; j++) hesse(i,j) = auxvec(j); auxpoint(i) = point(i); } */ for(int i=0; i<3; i++) for(int j=i+1; j<3; j++) hesse(i,j) = hesse(j,i) = 0.5*(hesse(i,j)+hesse(j,i)); } double ExtrusionFace :: HesseNorm () const { return fabs(profile_spline_coeff(0) + profile_spline_coeff(1)) + sqrt(pow(profile_spline_coeff(0)+profile_spline_coeff(1),2)+4.*pow(profile_spline_coeff(2),2)); } double ExtrusionFace :: MaxCurvature () const { double retval,actmax; retval = profile->MaxCurvature(); for(int i=0; iGetNSplines(); i++) { actmax = path->GetSpline(i).MaxCurvature(); if(actmax > retval) retval = actmax; } return 2.*retval; } void ExtrusionFace :: Project (Point<3> & p) const { double dummyt; int seg; Point<2> p2d; CalcProj(p,p2d,seg,dummyt); profile->Project(p2d,p2d,profile_par); p = p0[seg] + p2d(0)*x_dir[seg] + p2d(1)*loc_z_dir[seg]; Vec<2> tangent2d = profile->GetTangent(profile_par); profile_tangent = tangent2d(0)*x_dir[seg] + tangent2d(1)*y_dir[seg]; } Point<3> ExtrusionFace :: GetSurfacePoint () const { p0[0] = path->GetSpline(0).GetPoint(0.5); if(!line_path[0]) { y_dir[0] = path->GetSpline(0).GetTangent(0.5); y_dir[0].Normalize(); loc_z_dir[0] = z_dir[0]; Orthogonalize(y_dir[0],loc_z_dir[0]); x_dir[0] = Cross(y_dir[0],loc_z_dir[0]); } Point<2> locpoint = profile->GetPoint(0.5); return p0[0] + locpoint(0)*x_dir[0] + locpoint(1)*loc_z_dir[0]; } bool ExtrusionFace :: BoxIntersectsFace(const Box<3> & box) const { Point<3> center = box.Center(); Project(center); //(*testout) << "box.Center() " << box.Center() << " projected " << center << " diam " << box.Diam() // << " dist " << Dist(box.Center(),center) << endl; return (Dist(box.Center(),center) < 0.5*box.Diam()); } void ExtrusionFace :: LineIntersections ( const Point<3> & p, const Vec<3> & v, const double eps, int & before, int & after, bool & intersecting ) const { Point<2> p2d; Vec<2> v2d; intersecting = false; double segt; int seg; CalcProj(p,p2d,seg,segt); if(seg == 0 && segt < 1e-20) { Vec<3> v1,v2; v1 = path->GetSpline(0).GetTangent(0); v2 = p-p0[seg]; if(v1*v2 < -eps) return; } if(seg == path->GetNSplines()-1 && 1.-segt < 1e-20) { Vec<3> v1,v2; v1 = path->GetSpline(seg).GetTangent(1); v2 = p-p0[seg]; if(v1*v2 > eps) return; } v2d(0) = v * x_dir[seg]; v2d(1) = v * loc_z_dir[seg]; Vec<2> n(v2d(1),-v2d(0)); Array < Point<2> > ips; profile->LineIntersections(v2d(1), -v2d(0), -v2d(1)*p2d(0) + v2d(0)*p2d(1), ips,eps); int comp; if(fabs(v2d(0)) >= fabs(v2d(1))) comp = 0; else comp = 1; //(*testout) << "p2d " << p2d; for(int i=0; i eps) after++; else intersecting = true; } //(*testout) << endl; } void ExtrusionFace :: Print (ostream & str) const{} INSOLID_TYPE ExtrusionFace :: VecInFace ( const Point<3> & p, const Vec<3> & v, const double eps ) const { Vec<3> normal1; CalcGradient(p,normal1); normal1.Normalize(); double d1 = normal1*v; if(d1 > eps) return IS_OUTSIDE; if(d1 < -eps) return IS_INSIDE; return DOES_INTERSECT; /* Point<2> p2d; double t_path; int seg; CalcProj(p,p2d,seg,t_path); double t; profile.Project(p2d,p2d,t); Vec<2> profile_tangent = profile.GetTangent(t); double d; Vec<3> normal1; CalcGradient(p,normal1); normal1.Normalize(); double d1 = normal1*v; Vec<2> v2d; v2d(0) = v*x_dir[seg]; v2d(1) = v*loc_z_dir[seg]; Vec<2> normal(-profile_tangent(1),profile_tangent(0)); //d = normal*v2d; d = d1; if(d > eps) return IS_OUTSIDE; if(d < -eps) return IS_INSIDE; return DOES_INTERSECT; */ } void ExtrusionFace :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const { int n = int(facets) + 1; for(int k = 0; k < path -> GetNSplines(); k++) { for(int i = 0; i <= n; i++) { Point<3> origin = path -> GetSpline(k).GetPoint(double(i)/double(n)); if(!line_path[k]) { y_dir[k] = path->GetSpline(k).GetTangent(double(i)/double(n)); y_dir[k].Normalize(); } loc_z_dir[k] = z_dir[k]; Orthogonalize(y_dir[k],loc_z_dir[k]); if(!line_path[k]) x_dir[k] = Cross(y_dir[k],loc_z_dir[k]); for(int j = 0; j <= n; j++) { Point<2> locp = profile->GetPoint(double(j)/double(n)); tas.AddPoint(origin + locp(0)*x_dir[k] + locp(1)*loc_z_dir[k]); } } } for(int k = 0; k < path->GetNSplines(); k++) for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { int pi = k*(n+1)*(n+1) + (n+1)*i +j; tas.AddTriangle( TATriangle (0, pi,pi+1,pi+n+1) ); tas.AddTriangle( TATriangle (0, pi+1,pi+n+1,pi+n+2) ); } } void ExtrusionFace :: GetRawData(Array & data) const { data.DeleteAll(); profile->GetRawData(data); path->GetRawData(data); for(int i=0; i<3; i++) data.Append(glob_z_direction[i]); } void ExtrusionFace :: CalcLocalCoordinates (int seg, double t, Vec<3> & ex, Vec<3> & ey, Vec<3> & ez) const { ey = path->GetSpline(seg).GetTangent(t); ey /= ey.Length(); ex = Cross (ey, glob_z_direction); ex /= ex.Length(); ez = Cross (ex, ey); } void ExtrusionFace :: CalcLocalCoordinatesDeriv (int seg, double t, Vec<3> & ex, Vec<3> & ey, Vec<3> & ez, Vec<3> & dex, Vec<3> & dey, Vec<3> & dez) const { Point<3> point; Vec<3> first, second; path->GetSpline(seg).GetDerivatives (t, point, first, second); ey = first; ex = Cross (ey, glob_z_direction); ez = Cross (ex, ey); dey = second; dex = Cross (dey, glob_z_direction); dez = Cross (dex, ey) + Cross (ex, dey); double lenx = ex.Length(); double leny = ey.Length(); double lenz = ez.Length(); ex /= lenx; ey /= leny; ez /= lenz; dex /= lenx; dex -= (dex * ex) * ex; dey /= leny; dey -= (dey * ey) * ey; dez /= lenz; dez -= (dez * ez) * ez; } Extrusion :: Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir) : path(&path_in), profile(&profile_in), z_direction(z_dir) { surfaceactive.SetSize(0); surfaceids.SetSize(0); for(int j=0; jGetNSplines(); j++) { ExtrusionFace * face = new ExtrusionFace(&((*profile).GetSpline(j)), path, z_direction); faces.Append(face); surfaceactive.Append(true); surfaceids.Append(0); } } Extrusion :: ~Extrusion() { for(int i=0; i & box) const { for(int i=0; iBoxIntersectsFace(box)) return DOES_INTERSECT; } return PointInSolid(box.Center(),0); } INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p, const double eps, Array * const facenums) const { Vec<3> random_vec(-0.4561,0.7382,0.4970247); int before(0), after(0); bool intersects(false); bool does_intersect(false); for(int i=0; iLineIntersections(p,random_vec,eps,before,after,intersects); //(*testout) << "intersects " << intersects << " before " << before << " after " << after << endl; if(intersects) { if(facenums) { facenums->Append(i); does_intersect = true; } else return DOES_INTERSECT; } } if(does_intersect) return DOES_INTERSECT; if(before % 2 == 0) return IS_OUTSIDE; return IS_INSIDE; } INSOLID_TYPE Extrusion :: PointInSolid (const Point<3> & p, double eps) const { return PointInSolid(p,eps,NULL); } INSOLID_TYPE Extrusion :: VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const { Array facenums; INSOLID_TYPE pInSolid = PointInSolid(p,eps,&facenums); if(pInSolid != DOES_INTERSECT) return pInSolid; double d(0); if(facenums.Size() == 1) { Vec<3> normal; faces[facenums[0]]->CalcGradient(p,normal); normal.Normalize(); d = normal*v; latestfacenum = facenums[0]; } else if (facenums.Size() == 2) { Vec<3> checkvec; Point<3> dummy(p); faces[facenums[0]]->Project(dummy); if(fabs(faces[facenums[0]]->GetProfilePar()) < 0.1) { int aux = facenums[0]; facenums[0] = facenums[1]; facenums[1] = aux; } checkvec = faces[facenums[0]]->GetYDir(); Vec<3> n0, n1; faces[facenums[0]]->CalcGradient(p,n0); faces[facenums[1]]->CalcGradient(p,n1); n0.Normalize(); n1.Normalize(); Vec<3> t = Cross(n0,n1); if(checkvec*t < 0) t*= (-1.); Vec<3> t0 = Cross(n0,t); Vec<3> t1 = Cross(t,n1); t0.Normalize(); t1.Normalize(); const double t0v = t0*v; const double t1v = t1*v; if(t0v > t1v) { latestfacenum = facenums[0]; d = n0*v; } else { latestfacenum = facenums[1]; d = n1*v; } if(fabs(t0v) < eps && fabs(t1v) < eps) latestfacenum = -1; } else { cerr << "WHY ARE THERE " << facenums.Size() << " FACES?" << endl; } if(d > eps) return IS_OUTSIDE; if(d < -eps) return IS_INSIDE; return DOES_INTERSECT; } // checks if lim s->0 lim t->0 p + t(v1 + s v2) in solid INSOLID_TYPE Extrusion :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { INSOLID_TYPE retval; retval = VecInSolid(p,v1,eps); // *testout << "extr, vecinsolid=" << int(retval) << endl; if(retval != DOES_INTERSECT) return retval; if(latestfacenum >= 0) return faces[latestfacenum]->VecInFace(p,v2,0); else return VecInSolid(p,v2,eps); } int Extrusion :: GetNSurfaces() const { return faces.Size(); } Surface & Extrusion :: GetSurface (int i) { return *faces[i]; } const Surface & Extrusion :: GetSurface (int i) const { return *faces[i]; } void Extrusion :: Reduce (const BoxSphere<3> & box) { for(int i = 0; i < faces.Size(); i++) surfaceactive[i] = faces[i]->BoxIntersectsFace(box); } void Extrusion :: UnReduce () { for(int i = 0; i < faces.Size(); i++) surfaceactive[i] = true; } RegisterClassForArchive regexf; RegisterClassForArchive regextr; } netgen-6.2.1905/libsrc/csg/brick.cpp0000644000175000017500000002420113504650527015630 0ustar kurtkurt#include #include #include namespace netgen { Parallelogram3d :: Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3) { p1 = ap1; p2 = ap2; p3 = ap3; CalcData(); } Parallelogram3d ::~Parallelogram3d () { ; } void Parallelogram3d :: SetPoints (Point<3> ap1, Point<3> ap2, Point<3> ap3) { p1 = ap1; p2 = ap2; p3 = ap3; CalcData(); } void Parallelogram3d :: CalcData() { v12 = p2 - p1; v13 = p3 - p1; p4 = p2 + v13; n = Cross (v12, v13); n.Normalize(); } int Parallelogram3d :: IsIdentic (const Surface & s2, int & inv, double eps) const { int id = (fabs (s2.CalcFunctionValue (p1)) <= eps) && (fabs (s2.CalcFunctionValue (p2)) <= eps) && (fabs (s2.CalcFunctionValue (p3)) <= eps); if (id) { Vec<3> n2; n2 = s2.GetNormalVector(p1); inv = (n * n2) < 0; } return id; } double Parallelogram3d :: CalcFunctionValue (const Point<3> & point) const { return n * (point - p1); } void Parallelogram3d :: CalcGradient (const Point<3> & /* point */, Vec<3> & grad) const { grad = n; } void Parallelogram3d :: CalcHesse (const Point<3> & /* point */, Mat<3> & hesse) const { hesse = 0; } double Parallelogram3d :: HesseNorm () const { return 0; } Point<3> Parallelogram3d :: GetSurfacePoint () const { return p1; } void Parallelogram3d :: Print (ostream & str) const { str << "Parallelogram3d " << p1 << " - " << p2 << " - " << p3 << endl; } void Parallelogram3d :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & /* bbox */, double /* facets */) const { tas.AddPoint (p1); tas.AddPoint (p2); tas.AddPoint (p3); tas.AddPoint (p4); tas.AddTriangle (TATriangle (0, 0, 1, 2)); tas.AddTriangle (TATriangle (0, 2, 1, 3)); } Brick :: Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4) { faces.SetSize (6); surfaceids.SetSize (6); surfaceactive.SetSize(6); p1 = ap1; p2 = ap2; p3 = ap3; p4 = ap4; for (int i = 0; i < 6; i++) { faces[i] = new Plane (Point<3>(0,0,0), Vec<3> (0,0,1)); surfaceactive[i] = 1; } CalcData(); } Brick :: ~Brick () { for (int i = 0; i < 6; i++) delete faces[i]; } Primitive * Brick :: CreateDefault () { return new Brick (Point<3> (0,0,0), Point<3> (1,0,0), Point<3> (0,1,0), Point<3> (0,0,1)); } Primitive * Brick :: Copy () const { return new Brick (p1, p2, p3, p4); } void Brick :: Transform (Transformation<3> & trans) { trans.Transform (p1); trans.Transform (p2); trans.Transform (p3); trans.Transform (p4); CalcData(); } INSOLID_TYPE Brick :: BoxInSolid (const BoxSphere<3> & box) const { /* int i; double maxval; for (i = 1; i <= 6; i++) { double val = faces.Get(i)->CalcFunctionValue (box.Center()); if (i == 1 || val > maxval) maxval = val; } if (maxval > box.Diam()) return IS_OUTSIDE; if (maxval < -box.Diam()) return IS_INSIDE; return DOES_INTERSECT; */ bool inside = 1; bool outside = 0; Point<3> p[8]; for (int j = 0; j < 8; j++) p[j] = box.GetPointNr(j); for (int i = 0; i < 6; i++) { bool outsidei = 1; for (int j = 0; j < 8; j++) { // Point<3> p = box.GetPointNr (j); double val = faces[i]->Plane::CalcFunctionValue (p[j]); if (val > 0) inside = 0; if (val < 0) outsidei = 0; } if (outsidei) outside = 1; } if (outside) return IS_OUTSIDE; if (inside) return IS_INSIDE; return DOES_INTERSECT; } INSOLID_TYPE Brick :: PointInSolid (const Point<3> & p, double eps) const { double maxval = faces[0] -> Plane::CalcFunctionValue (p); for (int i = 1; i < 6; i++) { double val = faces[i] -> Plane::CalcFunctionValue (p); if (val > maxval) maxval = val; } if (maxval > eps) return IS_OUTSIDE; if (maxval < -eps) return IS_INSIDE; return DOES_INTERSECT; } INSOLID_TYPE Brick :: VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const { INSOLID_TYPE result = IS_INSIDE; for (int i = 0; i < faces.Size(); i++) { INSOLID_TYPE hres = faces[i]->VecInSolid(p, v, eps); if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE; else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT; else result = IS_INSIDE; } return result; /* INSOLID_TYPE is = IS_INSIDE; Vec<3> grad; double scal; for (int i = 0; i < faces.Size(); i++) { if (faces[i] -> PointOnSurface (p, eps)) { GetSurface(i).CalcGradient (p, grad); scal = v * grad; if (scal >= eps) is = IS_OUTSIDE; if (scal >= -eps && is == IS_INSIDE) is = DOES_INTERSECT; } } return is; */ /* Point<3> p2 = p + 1e-2 * v; return PointInSolid (p2, eps); */ } INSOLID_TYPE Brick :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { INSOLID_TYPE result = IS_INSIDE; for (int i = 0; i < faces.Size(); i++) { INSOLID_TYPE hres = faces[i]->VecInSolid2(p, v1, v2, eps); if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE; else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT; else result = IS_INSIDE; } return result; } INSOLID_TYPE Brick :: VecInSolid3 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { INSOLID_TYPE result = IS_INSIDE; for (int i = 0; i < faces.Size(); i++) { INSOLID_TYPE hres = faces[i]->VecInSolid3(p, v1, v2, eps); if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE; else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT; else result = IS_INSIDE; } return result; } INSOLID_TYPE Brick :: VecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, double eps) const { INSOLID_TYPE result = IS_INSIDE; for (int i = 0; i < faces.Size(); i++) { INSOLID_TYPE hres = faces[i]->VecInSolid4(p, v, v2, m, eps); if (hres == IS_OUTSIDE || result == IS_OUTSIDE) result = IS_OUTSIDE; else if (hres == DOES_INTERSECT || result == DOES_INTERSECT) result = DOES_INTERSECT; else result = IS_INSIDE; } return result; } void Brick :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "brick"; coeffs.SetSize(12); coeffs.Elem(1) = p1(0); coeffs.Elem(2) = p1(1); coeffs.Elem(3) = p1(2); coeffs.Elem(4) = p2(0); coeffs.Elem(5) = p2(1); coeffs.Elem(6) = p2(2); coeffs.Elem(7) = p3(0); coeffs.Elem(8) = p3(1); coeffs.Elem(9) = p3(2); coeffs.Elem(10) = p4(0); coeffs.Elem(11) = p4(1); coeffs.Elem(12) = p4(2); } void Brick :: SetPrimitiveData (Array & coeffs) { p1(0) = coeffs.Elem(1); p1(1) = coeffs.Elem(2); p1(2) = coeffs.Elem(3); p2(0) = coeffs.Elem(4); p2(1) = coeffs.Elem(5); p2(2) = coeffs.Elem(6); p3(0) = coeffs.Elem(7); p3(1) = coeffs.Elem(8); p3(2) = coeffs.Elem(9); p4(0) = coeffs.Elem(10); p4(1) = coeffs.Elem(11); p4(2) = coeffs.Elem(12); CalcData(); } void Brick :: CalcData() { v12 = p2 - p1; v13 = p3 - p1; v14 = p4 - p1; Point<3> pi[8]; int i1, i2, i3; int i, j; i = 0; for (i3 = 0; i3 <= 1; i3++) for (i2 = 0; i2 <= 1; i2++) for (i1 = 0; i1 <= 1; i1++) { pi[i] = p1 + i1 * v12 + i2 * v13 + i3 * v14; i++; } static int lface[6][4] = { { 1, 3, 2, 4 }, { 5, 6, 7, 8 }, { 1, 2, 5, 6 }, { 3, 7, 4, 8 }, { 1, 5, 3, 7 }, { 2, 4, 6, 8 } }; Array data(6); for (i = 0; i < 6; i++) { const Point<3> lp1 = pi[lface[i][0]-1]; const Point<3> lp2 = pi[lface[i][1]-1]; const Point<3> lp3 = pi[lface[i][2]-1]; Vec<3> n = Cross ((lp2-lp1), (lp3-lp1)); n.Normalize(); for (j = 0; j < 3; j++) { data[j] = lp1(j); data[j+3] = n(j); } faces[i] -> SetPrimitiveData (data); /* { faces.Elem(i+1) -> SetPoints (pi[lface[i][0]-1], pi[lface[i][1]-1], pi[lface[i][2]-1]); } */ } } void Brick :: Reduce (const BoxSphere<3> & box) { double val; // Point<3> p; Point<3> p[8]; for(int j=0;j<8;j++) p[j]=box.GetPointNr(j); for (int i = 0; i < 6; i++) { bool hasout = 0; bool hasin = 0; for (int j = 0; j < 8; j++) { // p = box.GetPointNr (j); val = faces[i]->Plane::CalcFunctionValue (p[j]); if (val > 0) hasout = 1; else if (val < 0) hasin = 1; if (hasout && hasin) break; } surfaceactive[i] = hasout && hasin; } } void Brick :: UnReduce () { for (int i = 0; i < 6; i++) surfaceactive[i] = 1; } OrthoBrick :: OrthoBrick (const Point<3> & ap1, const Point<3> & ap2) : Brick (ap1, Point<3> (ap2(0), ap1(1), ap1(2)), Point<3> (ap1(0), ap2(1), ap1(2)), Point<3> (ap1(0), ap1(1), ap2(2))) { pmin = ap1; pmax = ap2; } INSOLID_TYPE OrthoBrick :: BoxInSolid (const BoxSphere<3> & box) const { if (pmin(0) > box.PMax()(0) || pmin(1) > box.PMax()(1) || pmin(2) > box.PMax()(2) || pmax(0) < box.PMin()(0) || pmax(1) < box.PMin()(1) || pmax(2) < box.PMin()(2)) return IS_OUTSIDE; if (pmin(0) < box.PMin()(0) && pmin(1) < box.PMin()(1) && pmin(2) < box.PMin()(2) && pmax(0) > box.PMax()(0) && pmax(1) > box.PMax()(1) && pmax(2) > box.PMax()(2)) return IS_INSIDE; return DOES_INTERSECT; } void OrthoBrick :: Reduce (const BoxSphere<3> & box) { surfaceactive.Elem(1) = (box.PMin()(2) < pmin(2)) && (pmin(2) < box.PMax()(2)); surfaceactive.Elem(2) = (box.PMin()(2) < pmax(2)) && (pmax(2) < box.PMax()(2)); surfaceactive.Elem(3) = (box.PMin()(1) < pmin(1)) && (pmin(1) < box.PMax()(1)); surfaceactive.Elem(4) = (box.PMin()(1) < pmax(1)) && (pmax(1) < box.PMax()(1)); surfaceactive.Elem(5) = (box.PMin()(0) < pmin(0)) && (pmin(0) < box.PMax()(0)); surfaceactive.Elem(6) = (box.PMin()(0) < pmax(0)) && (pmax(0) < box.PMax()(0)); } RegisterClassForArchive regpar; RegisterClassForArchive regbrick; RegisterClassForArchive regob; } netgen-6.2.1905/libsrc/csg/surface.hpp0000644000175000017500000002444713504650527016207 0ustar kurtkurt#ifndef FILE_SURFACE #define FILE_SURFACE /**************************************************************************/ /* File: surface.hh */ /* Author: Joachim Schoeberl */ /* Date: 1. Dez. 95 */ /**************************************************************************/ namespace netgen { class TriangleApproximation; /** Basis class for implicit surface geometry. This class is used for generation of surface meshes in NETGEN */ class Surface { protected: /// invert normal vector bool inverse; /// maximal h in surface double maxh; /// name of surface char * name; /// boundary condition nr int bcprop; /// boundary condition label string bcname; public: Surface (); /** @name Tangential plane. The tangential plane is used for surface mesh generation. */ virtual ~Surface(); protected: /** @name Points in the surface defining tangential plane. Tangential plane is taken in p1, the local x-axis is directed to p2. */ //@{ /// Point<3> p1; /// Point<3> p2; //@} /** @name Base-vectos for local coordinate system. */ //@{ /// in plane, directed p1->p2 Vec<3> ex; /// in plane Vec<3> ey; /// outer normal direction Vec<3> ez; //@} public: virtual void DoArchive(Archive& archive) { archive & inverse & maxh & name & bcprop & bcname & p1 & p2 & ex & ey & ez; } void SetName (const char * aname); const char * Name () const { return name; } //@{ /** Defines tangential plane in ap1. The local x-coordinate axis points to the direction of ap2 */ virtual void DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2); /// Transforms 3d point p3d to local coordinates pplane virtual void ToPlane (const Point<3> & p3d, Point<2> & pplane, double h, int & zone) const; /// Transforms point pplane in local coordinates to 3d point virtual void FromPlane (const Point<2> & pplane, Point<3> & p3d, double h) const; //@} /// Project point p onto surface (closest point) virtual void Project (Point<3> & p) const; /// Project along direction virtual void SkewProject(Point<3> & p, const Vec<3> & direction) const; /// Is current surface identic to surface 2 ? virtual int IsIdentic (const Surface & /* s2 */, int & /* inv */, double /* eps */) const { return 0; } /// virtual int PointOnSurface (const Point<3> & p, double eps = 1e-6) const; /** @name Implicit function. Calculate function value and derivatives. */ //@{ /// Calculate implicit function value in point point virtual double CalcFunctionValue (const Point<3> & point) const = 0; /** Calc gradient of implicit function. gradient should be O(1) at surface */ virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const = 0; /** Calculate second derivatives of implicit function. */ virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; /** Returns outer normal vector. */ // virtual void GetNormalVector (const Point<3> & p, Vec<3> & n) const; virtual Vec<3> GetNormalVector (const Point<3> & p) const; /** Upper bound for spectral norm of Hesse-matrix */ virtual double HesseNorm () const = 0; /** Upper bound for spectral norm of Hesse-matrix in the rad - environment of point c. */ virtual double HesseNormLoc (const Point<3> & /* c */, double /* rad */) const { return HesseNorm (); } //@} /// virtual double MaxCurvature () const; /// virtual double MaxCurvatureLoc (const Point<3> & /* c */ , double /* rad */) const; /** Returns any point in the surface. Needed to start surface mesh generation e.g. on sphere */ virtual Point<3> GetSurfacePoint () const = 0; /// bool Inverse () const { return inverse; } /// void SetInverse (bool ainverse) { inverse = ainverse; } /// virtual void Print (ostream & str) const = 0; /// virtual void Reduce (const BoxSphere<3> & /* box */) { }; /// virtual void UnReduce () { }; /// set max h in surface void SetMaxH (double amaxh) { maxh = amaxh; } /// double GetMaxH () const { return maxh; } /// int GetBCProperty () const { return bcprop; } /// void SetBCProperty (int abc) { bcprop = abc; } /** Determine local mesh-size. Find \[ h \leq hmax, \] such that \[ h \times \kappa (x) \leq c \qquad \mbox{in} B(x, h), \] where kappa(x) is the curvature in x. */ virtual double LocH (const Point<3> & p, double x, double c, const MeshingParameters & mparam, double hmax) const; /** Gets Approximation by triangles, where qual is about the number of triangles per radius */ virtual void GetTriangleApproximation (TriangleApproximation & /* tas */, const Box<3> & /* boundingbox */, double /* facets */ ) const { }; string GetBCName() const { return bcname; } void SetBCName( string abc ) { bcname = abc; } }; inline ostream & operator<< (ostream & ost, const Surface & surf) { surf.Print(ost); return ost; } typedef enum { IS_OUTSIDE = 0, IS_INSIDE = 1, DOES_INTERSECT = 2} INSOLID_TYPE; class DummySurface : public Surface { virtual double CalcFunctionValue (const Point<3> & /* point */) const { return 0; } virtual void CalcGradient (const Point<3> & /* point */, Vec<3> & grad) const { grad = Vec<3> (0,0,0); } virtual Point<3> GetSurfacePoint () const { return Point<3> (0,0,0); } virtual double HesseNorm () const { return 0; } virtual void Project (Point<3> & /* p */) const { ; } virtual void Print (ostream & ost) const { ost << "dummy surface"; } }; class Primitive { protected: Array surfaceids; Array surfaceactive; public: Primitive (); virtual ~Primitive(); virtual void DoArchive(Archive& archive) { archive & surfaceids & surfaceactive; } /* Check, whether box intersects solid defined by surface. return values: 0 .. box outside solid \\ 1 .. box in solid \\ 2 .. can't decide (allowed, iff box is close to solid) */ virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const = 0; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const = 0; virtual void GetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const = 0; // checks if lim s->0 lim t->0 p + t(v1 + s v2) in solid virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; // checks if p + s v1 + s*s/2 v2 is inside virtual INSOLID_TYPE VecInSolid3 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; // like VecInSolid2, but second order approximation virtual INSOLID_TYPE VecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, double eps) const; virtual void GetTangentialVecSurfaceIndices (const Point<3> & p, const Vec<3> & v, Array & surfind, double eps) const; virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, Array & surfind, double eps) const; virtual void CalcSpecialPoints (Array > & /* pts */) const { ; } virtual void AnalyzeSpecialPoint (const Point<3> & /* pt */, Array > & /* specpts */) const { ; } virtual Vec<3> SpecialPointTangentialVector (const Point<3> & /* p */, int /* s1 */, int /* s2 */) const { return Vec<3> (0,0,0); } virtual int GetNSurfaces() const = 0; virtual Surface & GetSurface (int i = 0) = 0; virtual const Surface & GetSurface (int i = 0) const = 0; int GetSurfaceId (int i = 0) const; void SetSurfaceId (int i, int id); int SurfaceActive (int i) const { return surfaceactive[i]; } virtual int SurfaceInverted (int /* i */ = 0) const { return 0; } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); static Primitive * CreatePrimitive (const char * classname); virtual void Reduce (const BoxSphere<3> & /* box */) { }; virtual void UnReduce () { }; virtual Primitive * Copy () const; virtual void Transform (Transformation<3> & trans); }; class OneSurfacePrimitive : public Surface, public Primitive { public: OneSurfacePrimitive(); ~OneSurfacePrimitive(); virtual void DoArchive(Archive& archive) { Surface::DoArchive(archive); Primitive::DoArchive(archive); } virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const; virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; virtual INSOLID_TYPE VecInSolid3 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; virtual INSOLID_TYPE VecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, double eps) const; virtual int GetNSurfaces() const; virtual Surface & GetSurface (int i = 0); virtual const Surface & GetSurface (int i = 0) const; }; /** Projects point to edge. The point hp is projected to the edge described by f1 and f2. It is assumed that the edge is non-degenerated, and the (generalized) Newton method converges. */ extern void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp); } #endif netgen-6.2.1905/libsrc/csg/spline3d.hpp0000644000175000017500000000460013504650527016265 0ustar kurtkurtnamespace netgen { /// class splinesegment3d { /// Point<3> p1, p2, p3; public: /// splinesegment3d (const Point<3> & ap1, const Point<3> & ap2, const Point<3> & ap3); /// void Evaluate (double t, Point<3> & p) const; /// void EvaluateTangent (double t, Vec<3> & tang) const; /// const Point<3> & P1() const { return p1; } /// const Point<3> & P2() const { return p2; } /// const Point<3> & P3() const { return p3; } }; /// class spline3d { /// Array segments; public: /// spline3d () { }; /// void AddSegment (const Point<3> & ap1, const Point<3> & ap2, const Point<3> & ap3); /// int GetNumSegments () const { return segments.Size(); } /// double ProjectToSpline (Point<3> & p) const; /// double ProjectToSpline (Point<3> & p, double t) const; /// void Evaluate (double t, Point<3> & p) const; /// void EvaluateTangent (double t, Vec<3> & tang) const; /// const Point<3> & P1(int i) const { return segments.Get(i)->P1(); } /// const Point<3> & P2(int i) const { return segments.Get(i)->P2(); } /// const Point<3> & P3(int i) const { return segments.Get(i)->P3(); } }; /// class splinetube : public Surface { /// const spline3d & middlecurve; /// double r; /// Vec<3> ex, ey, ez; Vec<2> e2x, e2y; /// Point<3> cp; public: /// splinetube (const spline3d & amiddlecurve, double ar); /// virtual void DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2); /// virtual void ToPlane (const Point<3> & p, Point<2> & pplain, double h, int & zone) const; /// virtual void FromPlane (const Point<2> & pplain, Point<3> & p, double h) const; /// virtual void Project (Point<3> & p) const; // virtual int RootInBox (const box3d & box) const { return 0; } /// 0 .. no, 1 .. yes, 2 .. maybe virtual int BoxInSolid (const BoxSphere<3> & box) const; /// 0 .. no, 1 .. yes, 2 .. maybe virtual double CalcFunctionValue (const Point<3> & point) const; /// virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; /// virtual double HesseNorm () const { return 0.5 / r; } /// virtual Point<3> GetSurfacePoint () const; /// virtual void Print (ostream & str) const; }; } netgen-6.2.1905/libsrc/csg/specpoin.cpp0000644000175000017500000014064313504650527016367 0ustar kurtkurt#include #include #include /* Special Point calculation uses the global Flags: relydegtest when to rely on degeneration ? calccp calculate points of intersection ? cpeps1 eps for degenerated poi calcep calculate points of extreme coordinates ? epeps1 eps for degenerated edge epeps2 eps for axis parallel pec epspointdist eps for distance of special points */ // #define DEVELOP namespace netgen { Array > boxes; void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp); enum { check_crosspoint = 5 }; SpecialPoint :: SpecialPoint (const SpecialPoint & sp) { p = sp.p; v = sp.v; s1 = sp.s1; s2 = sp.s2; s1_orig = sp.s1_orig; s2_orig = sp.s2_orig; layer = sp.layer; unconditional = sp.unconditional; } SpecialPoint & SpecialPoint :: operator= (const SpecialPoint & sp) { p = sp.p; v = sp.v; s1 = sp.s1; s2 = sp.s2; s1_orig = sp.s1_orig; s2_orig = sp.s2_orig; layer = sp.layer; unconditional = sp.unconditional; return *this; } void SpecialPoint :: Print (ostream & str) const { str << "p = " << p << " v = " << v << " s1/s2 = " << s1 << "/" << s2; str << " layer = " << layer << " unconditional = " << unconditional << endl; } static Array numprim_hist; SpecialPointCalculation :: SpecialPointCalculation () { ideps = 1e-9; } void SpecialPointCalculation :: CalcSpecialPoints (const CSGeometry & ageometry, Array & apoints) { static int timer = NgProfiler::CreateTimer ("CSG: find special points"); NgProfiler::RegionTimer reg (timer); geometry = &ageometry; points = &apoints; size = geometry->MaxSize(); (*testout) << "Find Special Points" << endl; (*testout) << "maxsize = " << size << endl; cpeps1 = 1e-6; epeps1 = 1e-3; epeps2 = 1e-6; epspointdist2 = sqr (size * 1e-8); relydegtest = size * 1e-4; BoxSphere<3> box (Point<3> (-size, -size, -size), Point<3> ( size, size, size)); box.CalcDiamCenter(); PrintMessage (3, "main-solids: ", geometry->GetNTopLevelObjects()); numprim_hist.SetSize (geometry->GetNSurf()+1); numprim_hist = 0; for (int i = 0; i < geometry->GetNTopLevelObjects(); i++) { const TopLevelObject * tlo = geometry->GetTopLevelObject(i); (*testout) << "tlo " << i << ":" << endl << *tlo->GetSolid() << endl; if (tlo->GetSolid()) { Array > hpts; tlo->GetSolid()->CalcOnePrimitiveSpecialPoints (box, hpts); // if (hpts.Size()) // cout << "oneprimitivespecialpoints = " << hpts << endl; for (int j = 0; j < hpts.Size(); j++) AddPoint (hpts[j], tlo->GetLayer()); } CalcSpecialPointsRec (tlo->GetSolid(), tlo->GetLayer(), box, 1, 1, 1); } geometry->DeleteIdentPoints(); for (int i = 0; i < geometry->GetNIdentifications(); i++) { CloseSurfaceIdentification * ident = dynamic_cast(geometry->identifications[i]); if(!ident || !ident->IsSkewIdentification()) continue; for(int j=0; jSize(); j++) { if(fabs(ident->GetSurface1().CalcFunctionValue((*points)[j])) < 1e-15) { Point<3> auxpoint = (*points)[j]; ident->GetSurface2().SkewProject(auxpoint,ident->GetDirection()); geometry->AddIdentPoint(auxpoint); geometry->AddIdentPoint((*points)[j]); AddPoint (auxpoint,1); #ifdef DEVELOP (*testout) << "added identpoint " << auxpoint << "; proj. of " << (*points)[j] << endl; #endif break; } } } // add user point: for (int i = 0; i < geometry->GetNUserPoints(); i++) AddPoint (geometry->GetUserPoint(i), 1); PrintMessage (3, "Found points ", apoints.Size()); for (int i = 0; i < boxesinlevel.Size(); i++) (*testout) << "level " << i << " has " << boxesinlevel[i] << " boxes" << endl; (*testout) << "numprim_histogramm = " << endl << numprim_hist << endl; } void SpecialPointCalculation :: CalcSpecialPointsRec (const Solid * sol, int layer, const BoxSphere<3> & box, int level, bool calccp, bool calcep) { // boxes.Append (box); #ifdef DEVELOP *testout << "lev " << level << ", box = " << box << endl; *testout << "calccp = " << calccp << ", calcep = " << calcep << endl; *testout << "locsol = " << *sol << endl; #endif if (multithread.terminate) { *testout << "boxes = " << boxes << endl; *testout << "boxesinlevel = " << boxesinlevel << endl; throw NgException ("Meshing stopped"); } if (!sol) return; if (level >= 100) { MyStr err = MyStr("Problems in CalcSpecialPoints\nPoint: ") + MyStr (box.Center()); throw NgException (err.c_str()); } if (level == 40 || level == 41 || level == 45) { *testout << "level = " << level << " cp = " << calccp << " ep = " << calcep << ", box = " << box << ", solid = " << *sol << endl; } bool decision; bool possiblecrossp, possibleexp; // possible cross or extremalpoint bool surecrossp = 0, sureexp = 0; // sure ... // static Array locsurf; // attention: array is static ArrayMem locsurf; // static int cntbox = 0; // cntbox++; if (level <= boxesinlevel.Size()) boxesinlevel.Elem(level)++; else boxesinlevel.Append (1); /* numprim = sol -> NumPrimitives(); sol -> GetSurfaceIndices (locsurf); */ geometry -> GetIndependentSurfaceIndices (sol, box, locsurf); int numprim = locsurf.Size(); #ifdef DEVELOP (*testout) << "numprim = " << numprim << endl; #endif numprim_hist[numprim]++; Point<3> p = box.Center(); // explicit solution for planes only and at most one quadratic if (numprim <= check_crosspoint) { int nplane = 0, nquad = 0, quadi = -1, nsphere = 0; const QuadraticSurface *qsurf = 0, *qsurfi; for (int i = 0; i < numprim; i++) { qsurfi = dynamic_cast (geometry->GetSurface(locsurf[i])); if (qsurfi) nquad++; if (dynamic_cast (qsurfi)) nplane++; else { quadi = i; qsurf = qsurfi; } if (dynamic_cast (qsurfi)) nsphere++; } /* if (nquad == numprim && nplane == numprim-2) return; */ #ifdef DEVELOP (*testout) << "nquad " << nquad << " nplane " << nplane << endl; #endif if (nquad == numprim && nplane >= numprim-1) { Array > pts; Array surfids; for (int k1 = 0; k1 < numprim - 2; k1++) for (int k2 = k1 + 1; k2 < numprim - 1; k2++) for (int k3 = k2 + 1; k3 < numprim; k3++) if (k1 != quadi && k2 != quadi && k3 != quadi) { ComputeCrossPoints (dynamic_cast (geometry->GetSurface(locsurf[k1])), dynamic_cast (geometry->GetSurface(locsurf[k2])), dynamic_cast (geometry->GetSurface(locsurf[k3])), pts); for (int j = 0; j < pts.Size(); j++) if (Dist (pts[j], box.Center()) < box.Diam()/2) { Solid * tansol; sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size); if(!tansol) continue; bool ok1 = false, ok2 = false, ok3 = false; int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]); int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]); int rep3 = geometry->GetSurfaceClassRepresentant(locsurf[k3]); for(int jj=0; jjGetSurfaceClassRepresentant(surfids[jj]); if(actrep == rep1) ok1 = true; if(actrep == rep2) ok2 = true; if(actrep == rep3) ok3 = true; } if (tansol && ok1 && ok2 && ok3) // if (sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size)) { if (AddPoint (pts[j], layer)) (*testout) << "cross point found, 1: " << pts[j] << endl; } delete tansol; } } if (qsurf) { for (int k1 = 0; k1 < numprim - 1; k1++) for (int k2 = k1 + 1; k2 < numprim; k2++) if (k1 != quadi && k2 != quadi) { ComputeCrossPoints (dynamic_cast (geometry->GetSurface(locsurf[k1])), dynamic_cast (geometry->GetSurface(locsurf[k2])), qsurf, pts); //(*testout) << "checking pot. crosspoints: " << pts << endl; for (int j = 0; j < pts.Size(); j++) if (Dist (pts[j], box.Center()) < box.Diam()/2) { Solid * tansol; sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size); if(!tansol) continue; bool ok1 = false, ok2 = false, ok3 = true;//false; int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]); int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]); //int rep3 = geometry->GetSurfaceClassRepresentant(quadi); for(int jj=0; jjGetSurfaceClassRepresentant(surfids[jj]); if(actrep == rep1) ok1 = true; if(actrep == rep2) ok2 = true; //if(actrep == rep3) ok3 = true; } if (tansol && ok1 && ok2 && ok3) //if (sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size) ) { if (AddPoint (pts[j], layer)) (*testout) << "cross point found, 2: " << pts[j] << endl; } delete tansol; } } for (int k1 = 0; k1 < numprim; k1++) if (k1 != quadi) { ComputeExtremalPoints (dynamic_cast (geometry->GetSurface(locsurf[k1])), qsurf, pts); for (int j = 0; j < pts.Size(); j++) if (Dist (pts[j], box.Center()) < box.Diam()/2) { Solid * tansol; sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size); if (tansol) // sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size) ) { if (AddPoint (pts[j], layer)) (*testout) << "extremal point found, 1: " << pts[j] << endl; } delete tansol; } } } return; } if (nsphere == numprim) // && calccp == false) { Array > pts; Array surfids; for (int k1 = 0; k1 < numprim; k1++) for (int k2 = 0; k2 < k1; k2++) for (int k3 = 0; k3 < k2; k3++) { ComputeCrossPoints (dynamic_cast (geometry->GetSurface(locsurf[k1])), dynamic_cast (geometry->GetSurface(locsurf[k2])), dynamic_cast (geometry->GetSurface(locsurf[k3])), pts); for (int j = 0; j < pts.Size(); j++) if (Dist (pts[j], box.Center()) < box.Diam()/2) { Solid * tansol; sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size); if(!tansol) continue; bool ok1 = false, ok2 = false, ok3 = false; int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]); int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]); int rep3 = geometry->GetSurfaceClassRepresentant(locsurf[k3]); for(int jj=0; jjGetSurfaceClassRepresentant(surfids[jj]); if(actrep == rep1) ok1 = true; if(actrep == rep2) ok2 = true; if(actrep == rep3) ok3 = true; } if (tansol && ok1 && ok2 && ok3) // if (sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size)) { if (AddPoint (pts[j], layer)) (*testout) << "cross point found, 1: " << pts[j] << endl; } delete tansol; } } for (int k1 = 0; k1 < numprim; k1++) for (int k2 = 0; k2 < k1; k2++) { ComputeExtremalPoints (dynamic_cast (geometry->GetSurface(locsurf[k1])), dynamic_cast (geometry->GetSurface(locsurf[k2])), pts); for (int j = 0; j < pts.Size(); j++) if (Dist (pts[j], box.Center()) < box.Diam()/2) { Solid * tansol; sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size); if (tansol) // sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size) ) { if (AddPoint (pts[j], layer)) (*testout) << "extremal point found, spheres: " << pts[j] << endl; } delete tansol; } } return; } } possiblecrossp = (numprim >= 3) && calccp; surecrossp = 0; if (possiblecrossp && (locsurf.Size() <= check_crosspoint || level > 50)) { decision = 1; surecrossp = 0; for (int k1 = 1; k1 <= locsurf.Size() - 2; k1++) for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++) for (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++) { int nc, deg; nc = CrossPointNewtonConvergence (geometry->GetSurface(locsurf.Get(k1)), geometry->GetSurface(locsurf.Get(k2)), geometry->GetSurface(locsurf.Get(k3)), box ); deg = CrossPointDegenerated (geometry->GetSurface(locsurf.Get(k1)), geometry->GetSurface(locsurf.Get(k2)), geometry->GetSurface(locsurf.Get(k3)), box ); #ifdef DEVELOP (*testout) << "k1,2,3 = " << k1 << "," << k2 << "," << k3 << ", nc = " << nc << ", deg = " << deg << endl; #endif if (!nc && !deg) decision = 0; if (nc) surecrossp = 1; } #ifdef DEVELOP (*testout) << "dec = " << decision << ", surcp = " << surecrossp << endl; #endif if (decision && surecrossp) { for (int k1 = 1; k1 <= locsurf.Size() - 2; k1++) for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++) for (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++) { if (CrossPointNewtonConvergence (geometry->GetSurface(locsurf.Get(k1)), geometry->GetSurface(locsurf.Get(k2)), geometry->GetSurface(locsurf.Get(k3)), box ) ) { Point<3> pp = p; CrossPointNewton (geometry->GetSurface(locsurf.Get(k1)), geometry->GetSurface(locsurf.Get(k2)), geometry->GetSurface(locsurf.Get(k3)), pp); BoxSphere<3> hbox (pp, pp); hbox.Increase (1e-8*size); if (pp(0) > box.PMin()(0) - 1e-5*size && pp(0) < box.PMax()(0) + 1e-5*size && pp(1) > box.PMin()(1) - 1e-5*size && pp(1) < box.PMax()(1) + 1e-5*size && pp(2) > box.PMin()(2) - 1e-5*size && pp(2) < box.PMax()(2) + 1e-5*size && sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) && !CrossPointDegenerated (geometry->GetSurface(locsurf.Get(k1)), geometry->GetSurface(locsurf.Get(k2)), geometry->GetSurface(locsurf.Get(k3)), hbox )) { // AddCrossPoint (locsurf, sol, p); BoxSphere<3> boxp (pp, pp); boxp.Increase (1e-3*size); boxp.CalcDiamCenter(); Array locsurf2; geometry -> GetIndependentSurfaceIndices (sol, boxp, locsurf2); bool found1 = false, found2 = false, found3 = false; for (int i = 0; i < locsurf2.Size(); i++) { if (locsurf2[i] == locsurf.Get(k1)) found1 = true; if (locsurf2[i] == locsurf.Get(k2)) found2 = true; if (locsurf2[i] == locsurf.Get(k3)) found3 = true; } if (found1 && found2 && found3) if (AddPoint (pp, layer)) { (*testout) << "Crosspoint found: " << pp << " diam = " << box.Diam() << ", surfs: " << locsurf.Get(k1) << "," << locsurf.Get(k2) << "," << locsurf.Get(k3) << endl; } } } } } if (decision) possiblecrossp = 0; } possibleexp = (numprim >= 2) && calcep; // (*testout) << "l = " << level << "locsize = " << locsurf.Size() << " possexp = " << possibleexp << "\n"; if (possibleexp && (numprim <= check_crosspoint || level >= 50)) { decision = 1; sureexp = 0; /* (*testout) << "extremal surfs = "; for (int k5 = 0; k5 < locsurf.Size(); k5++) (*testout) << typeid(*geometry->GetSurface(locsurf[k5])).name() << " "; (*testout) << "\n"; */ for (int k1 = 0; k1 < locsurf.Size() - 1; k1++) for (int k2 = k1+1; k2 < locsurf.Size(); k2++) { const Surface * surf1 = geometry->GetSurface(locsurf[k1]); const Surface * surf2 = geometry->GetSurface(locsurf[k2]); /* (*testout) << "edgecheck, types = " << typeid(*surf1).name() << ", " << typeid(*surf2).name() << "edge-newton-conv = " << EdgeNewtonConvergence (surf1, surf2, p) << "edge-deg = " << EdgeDegenerated (surf1, surf2, box) << "\n"; */ if (EdgeNewtonConvergence (surf1, surf2, p) ) sureexp = 1; else { if (!EdgeDegenerated (surf1, surf2, box)) decision = 0; } } // (*testout) << "l = " << level << " dec/sureexp = " << decision << sureexp << endl; if (decision && sureexp) { for (int k1 = 0; k1 < locsurf.Size() - 1; k1++) for (int k2 = k1+1; k2 < locsurf.Size(); k2++) { const Surface * surf1 = geometry->GetSurface(locsurf[k1]); const Surface * surf2 = geometry->GetSurface(locsurf[k2]); if (EdgeNewtonConvergence (surf1, surf2, p)) { EdgeNewton (surf1, surf2, p); Point<3> pp; if (IsEdgeExtremalPoint (surf1, surf2, p, pp, box.Diam()/2)) { (*testout) << "extremalpoint (nearly) found:" << pp << "box.diam = " << box.Diam() << ", dist = " << Dist(pp,box.Center()) << endl; if (Dist (pp, box.Center()) < box.Diam()/2 && sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) ) { if (AddPoint (pp, layer)) (*testout) << "Extremal point found: " << pp << endl;//"(eps="<<1e-9*size<<")"<< endl; } } } } } if (decision) possibleexp = 0; } // (*testout) << "l = " << level << " poss cp/ep sure exp = " << possiblecrossp << " " << possibleexp << " " << sureexp << "\n"; if (possiblecrossp || possibleexp) { BoxSphere<3> sbox; for (int i = 0; i < 8; i++) { box.GetSubBox (i, sbox); sbox.Increase (1e-4 * sbox.Diam()); sbox.CalcDiamCenter(); Solid * redsol = sol -> GetReducedSolid (sbox); if (redsol) { CalcSpecialPointsRec (redsol, layer, sbox, level+1, calccp, calcep); delete redsol; } } } } /******* Tests for Point of intersection **********************/ bool SpecialPointCalculation :: CrossPointNewtonConvergence (const Surface * f1, const Surface * f2, const Surface * f3, const BoxSphere<3> & box) { Vec<3> grad, rs, x; Mat<3> jacobi, inv; Point<3> p = box.Center(); f1->CalcGradient (p, grad); jacobi(0,0) = grad(0); jacobi(0,1) = grad(1); jacobi(0,2) = grad(2); f2->CalcGradient (p, grad); jacobi(1,0) = grad(0); jacobi(1,1) = grad(1); jacobi(1,2) = grad(2); f3->CalcGradient (p, grad); jacobi(2,0) = grad(0); jacobi(2,1) = grad(1); jacobi(2,2) = grad(2); if (fabs (Det (jacobi)) > 1e-8) { double gamma = f1 -> HesseNorm() + f2 -> HesseNorm() + f3 -> HesseNorm(); if (gamma == 0.0) return 1; CalcInverse (jacobi, inv); rs(0) = f1->CalcFunctionValue (p); rs(1) = f2->CalcFunctionValue (p); rs(2) = f3->CalcFunctionValue (p); x = inv * rs; double beta = 0; for (int i = 0; i < 3; i++) { double sum = 0; for (int j = 0; j < 3; j++) sum += fabs (inv(i,j)); if (sum > beta) beta = sum; } double eta = Abs (x); #ifdef DEVELOP *testout << "check Newton: " << "beta = " << beta << ", gamma = " << gamma << ", eta = " << eta << endl; double rad = 1.0 / (beta * gamma); *testout << "rad = " << rad << endl; *testout << "rs = " << rs << endl; #endif return (beta * gamma * eta < 0.1) && (2 > box.Diam()*beta*gamma); } return 0; } bool SpecialPointCalculation :: CrossPointDegenerated (const Surface * f1, const Surface * f2, const Surface * f3, const BoxSphere<3> & box) const { Mat<3> mat; Vec<3> g1, g2, g3; double normprod; if (box.Diam() > relydegtest) return 0; f1->CalcGradient (box.Center(), g1); normprod = Abs2 (g1); f2->CalcGradient (box.Center(), g2); normprod *= Abs2 (g2); f3->CalcGradient (box.Center(), g3); normprod *= Abs2 (g3); for (int i = 0; i < 3; i++) { mat(i,0) = g1(i); mat(i,1) = g2(i); mat(i,2) = g3(i); } return sqr (Det (mat)) < sqr(cpeps1) * normprod; } void SpecialPointCalculation :: CrossPointNewton (const Surface * f1, const Surface * f2, const Surface * f3, Point<3> & p) { Vec<3> g1, g2, g3; Vec<3> rs, sol; Mat<3> mat; int i = 10; while (i > 0) { i--; rs(0) = f1->CalcFunctionValue (p); rs(1) = f2->CalcFunctionValue (p); rs(2) = f3->CalcFunctionValue (p); f1->CalcGradient (p, g1); f2->CalcGradient (p, g2); f3->CalcGradient (p, g3); for (int j = 0; j < 3; j++) { mat(0, j) = g1(j); mat(1, j) = g2(j); mat(2, j) = g3(j); } mat.Solve (rs, sol); if (sol.Length2() < 1e-24 && i > 1) i = 1; #ifdef DEVELOP *testout << "CrossPointNewton, err = " << sol.Length2() << endl; #endif p -= sol; } } /******* Tests for Point on edges **********************/ bool SpecialPointCalculation :: EdgeNewtonConvergence (const Surface * f1, const Surface * f2, const Point<3> & p) { Vec<3> g1, g2, sol; Vec<2> vrs; Mat<2,3> mat; Mat<3,2> inv; f1->CalcGradient (p, g1); f2->CalcGradient (p, g2); if ( sqr(g1 * g2) < (1 - 1e-8) * Abs2 (g1) * Abs2 (g2)) { double gamma = f1 -> HesseNorm() + f2 -> HesseNorm(); if (gamma < 1e-32) return 1; gamma = sqr (gamma); for (int i = 0; i < 3; i++) { mat(0,i) = g1(i); mat(1,i) = g2(i); } CalcInverse (mat, inv); vrs(0) = f1->CalcFunctionValue (p); vrs(1) = f2->CalcFunctionValue (p); sol = inv * vrs; double beta = 0; for (int i = 0; i < 3; i++) for (int j = 0; j < 2; j++) beta += inv(i,j) * inv(i,j); // beta = sqrt (beta); double eta = Abs2 (sol); // alpha = beta * gamma * eta; return (beta * gamma * eta < 0.01); } return 0; } bool SpecialPointCalculation :: EdgeDegenerated (const Surface * f1, const Surface * f2, const BoxSphere<3> & box) const { // perform newton steps. normals parallel ? // if not decidable: return 0 Point<3> p = box.Center(); Vec<3> g1, g2, sol; Vec<2> vrs; Mat<2,3> mat; int i = 20; while (i > 0) { if (Dist2 (p, box.Center()) > sqr(box.Diam())) return 0; i--; vrs(0) = f1->CalcFunctionValue (p); vrs(1) = f2->CalcFunctionValue (p); f1->CalcGradient (p, g1); f2->CalcGradient (p, g2); if ( sqr (g1 * g2) > (1 - 1e-10) * Abs2 (g1) * Abs2 (g2)) return 1; for (int j = 0; j < 3; j++) { mat(0,j) = g1(j); mat(1,j) = g2(j); } mat.Solve (vrs, sol); if (Abs2 (sol) < 1e-24 && i > 1) i = 1; p -= sol; } return 0; } void SpecialPointCalculation :: EdgeNewton (const Surface * f1, const Surface * f2, Point<3> & p) { Vec<3> g1, g2, sol; Vec<2> vrs; Mat<2,3> mat; int i = 10; while (i > 0) { i--; vrs(0) = f1->CalcFunctionValue (p); vrs(1) = f2->CalcFunctionValue (p); f1->CalcGradient (p, g1); f2->CalcGradient (p, g2); //(*testout) << "p " << p << " f1 " << vrs(0) << " f2 " << vrs(1) << " g1 " << g1 << " g2 " << g2 << endl; for (int j = 0; j < 3; j++) { mat(0,j) = g1(j); mat(1,j) = g2(j); } mat.Solve (vrs, sol); if (Abs2 (sol) < 1e-24 && i > 1) i = 1; p -= sol; } } bool SpecialPointCalculation :: IsEdgeExtremalPoint (const Surface * f1, const Surface * f2, const Point<3> & p, Point<3> & pp, double rad) { Vec<3> g1, g2, t, t1, t2; f1->CalcGradient (p, g1); f2->CalcGradient (p, g2); t = Cross (g1, g2); t.Normalize(); Point<3> p1 = p + rad * t; Point<3> p2 = p - rad * t; EdgeNewton (f1, f2, p1); EdgeNewton (f1, f2, p2); f1->CalcGradient (p1, g1); f2->CalcGradient (p1, g2); t1 = Cross (g1, g2); t1.Normalize(); f1->CalcGradient (p2, g1); f2->CalcGradient (p2, g2); t2 = Cross (g1, g2); t2.Normalize(); double val = 1e-8 * rad * rad; for (int j = 0; j < 3; j++) if ( (t1(j) * t2(j) < -val) ) { pp = p; ExtremalPointNewton (f1, f2, j+1, pp); return 1; } return 0; } /********** Tests of Points of extremal coordinates ****************/ void SpecialPointCalculation :: ExtremalPointNewton (const Surface * f1, const Surface * f2, int dir, Point<3> & p) { Vec<3> g1, g2, v, curv; Vec<3> rs, x, y1, y2, y; Mat<3> h1, h2; Mat<3> jacobi; int i = 50; while (i > 0) { i--; rs(0) = f1->CalcFunctionValue (p); rs(1) = f2->CalcFunctionValue (p); f1 -> CalcGradient (p, g1); f2 -> CalcGradient (p, g2); f1 -> CalcHesse (p, h1); f2 -> CalcHesse (p, h2); v = Cross (g1, g2); rs(2) = v(dir-1); jacobi(0,0) = g1(0); jacobi(0,1) = g1(1); jacobi(0,2) = g1(2); jacobi(1,0) = g2(0); jacobi(1,1) = g2(1); jacobi(1,2) = g2(2); switch (dir) { case 1: { y1(0) = 0; y1(1) = g2(2); y1(2) = -g2(1); y2(0) = 0; y2(1) = -g1(2); y2(2) = g1(1); break; } case 2: { y1(0) = -g2(2); y1(1) = 0; y1(2) = g2(0); y2(0) = g1(2); y2(1) = 0; y2(2) = -g1(0); break; } case 3: { y1(0) = g2(1); y1(1) = -g2(0); y1(2) = 0; y2(0) = -g1(1); y2(1) = g1(0); y2(2) = 0; break; } } y = h1 * y1 + h2 * y2; jacobi(2,0) = y(0); jacobi(2,1) = y(1); jacobi(2,2) = y(2); /* (*testout) << "p " << p << " f1 " << rs(0) << " f2 " << rs(1) << endl << " jacobi " << jacobi << endl << " rhs " << rs << endl; */ jacobi.Solve (rs, x); if (Abs2 (x) < 1e-24 && i > 1) { i = 1; } double minval(Abs2(rs)),minfac(1); double startval(minval); for(double fac = 1; fac > 1e-7; fac *= 0.6) { Point<3> testpoint = p-fac*x; rs(0) = f1->CalcFunctionValue (testpoint); rs(1) = f2->CalcFunctionValue (testpoint); f1 -> CalcGradient (testpoint, g1); f2 -> CalcGradient (testpoint, g2); v = Cross (g1, g2); rs(2) = v(dir-1); double val = Abs2(rs); if(val < minval) { minfac = fac; if(val < 0.5 * startval) break; minval = val; } } p -= minfac*x; //p -= x; } if (Abs2 (x) > 1e-20) { (*testout) << "Error: extremum Newton not convergent" << endl; (*testout) << "dir = " << dir << endl; (*testout) << "p = " << p << endl; (*testout) << "x = " << x << endl; } } void SpecialPointCalculation :: ComputeCrossPoints (const Plane * plane1, const Plane * plane2, const Plane * plane3, Array > & pts) { Mat<3> mat; Vec<3> rhs, sol; Point<3> p0(0,0,0); pts.SetSize (0); for (int i = 0; i < 3; i++) { const Plane * pi(NULL); switch (i) { case 0: pi = plane1; break; case 1: pi = plane2; break; case 2: pi = plane3; break; } double val; Vec<3> hvec; val = pi -> CalcFunctionValue(p0); pi -> CalcGradient (p0, hvec); for (int j = 0; j < 3; j++) mat(i,j) = hvec(j); rhs(i) = -val; } if (fabs (Det (mat)) > 1e-8) { mat.Solve (rhs, sol); pts.Append (Point<3> (sol)); } } void SpecialPointCalculation :: ComputeCrossPoints (const Plane * plane1, const Plane * plane2, const QuadraticSurface * quadric, Array > & pts) { Mat<2,3> mat; Mat<3,2> inv; Vec<2> rhs; Vec<3> sol, t; Point<3> p0(0,0,0); pts.SetSize (0); for (int i = 0; i < 2; i++) { const Plane * pi(NULL); switch (i) { case 0: pi = plane1; break; case 1: pi = plane2; break; } double val; Vec<3> hvec; val = pi -> CalcFunctionValue(p0); pi -> CalcGradient (p0, hvec); for (int j = 0; j < 3; j++) mat(i,j) = hvec(j); rhs(i) = -val; } CalcInverse (mat, inv); sol = inv * rhs; t = Cross (mat.Row(0), mat.Row(1)); if (t.Length() > 1e-8) { Point<3> p (sol); // quadratic on p + s t = 0 double quad_a; Vec<3> quad_b; Mat<3> quad_c; quad_a = quadric -> CalcFunctionValue(p); quadric -> CalcGradient (p, quad_b); quadric -> CalcHesse (p, quad_c); double a, b, c; a = quad_a; b = quad_b * t; c = 0.5 * t * (quad_c * t); // a + s b + s^2 c = 0; double disc = b*b-4*a*c; if (disc > 1e-10 * fabs (b)) { disc = sqrt (disc); double s1 = (-b-disc) / (2*c); double s2 = (-b+disc) / (2*c); pts.Append (p + s1 * t); pts.Append (p + s2 * t); } } } void SpecialPointCalculation :: ComputeCrossPoints (const Sphere * sphere1, const Sphere * sphere2, const Sphere * sphere3, Array > & pts) { Mat<2,3> mat; Mat<3,2> inv; Vec<2> rhs; Vec<3> sol, t; Point<3> p0(0,0,0); pts.SetSize (0); Point<3> c1 = sphere1 -> Center(); Point<3> c2 = sphere2 -> Center(); Point<3> c3 = sphere3 -> Center(); double r1 = sphere1 -> Radius(); double r2 = sphere2 -> Radius(); double r3 = sphere3 -> Radius(); Vec<3> a1 = c2-c1; double b1 = 0.5 * (sqr(r1) - sqr(r2) - Abs2(Vec<3> (c1)) + Abs2(Vec<3> (c2)) ); Vec<3> a2 = c3-c1; double b2 = 0.5 * (sqr(r1) - sqr(r3) - Abs2(Vec<3> (c1)) + Abs2(Vec<3> (c3)) ); for (int j = 0; j < 3; j++) { mat(0,j) = a1(j); mat(1,j) = a2(j); } rhs(0) = b1; rhs(1) = b2; CalcInverse (mat, inv); sol = inv * rhs; t = Cross (mat.Row(0), mat.Row(1)); if (t.Length() > 1e-8) { Point<3> p (sol); // quadratic on p + s t = 0 double quad_a; Vec<3> quad_b; Mat<3> quad_c; quad_a = sphere1 -> CalcFunctionValue(p); sphere1 -> CalcGradient (p, quad_b); sphere1 -> CalcHesse (p, quad_c); double a, b, c; a = quad_a; b = quad_b * t; c = 0.5 * t * (quad_c * t); // a + s b + s^2 c = 0; double disc = b*b-4*a*c; if (disc > 1e-10 * fabs (b)) { disc = sqrt (disc); double s1 = (-b-disc) / (2*c); double s2 = (-b+disc) / (2*c); pts.Append (p + s1 * t); pts.Append (p + s2 * t); } } } void SpecialPointCalculation :: ComputeExtremalPoints (const Plane * plane, const QuadraticSurface * quadric, Array > & pts) { // 3 equations: // surf1 = 0 <===> plane_a + plane_b x = 0; // surf2 = 0 <===> quad_a + quad_b x + x^T quad_c x = 0 // (grad 1 x grad 2)(i) = 0 <====> (grad 1 x e_i) . grad_2 = 0 pts.SetSize (0); Point<3> p0(0,0,0); double plane_a, quad_a; Vec<3> plane_b, quad_b, ei; Mat<3> quad_c; plane_a = plane -> CalcFunctionValue(p0); plane -> CalcGradient (p0, plane_b); quad_a = quadric -> CalcFunctionValue(p0); quadric -> CalcGradient (p0, quad_b); quadric -> CalcHesse (p0, quad_c); for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) quad_c(i,j) *= 0.5; for (int dir = 0; dir <= 2; dir++) { ei = 0.0; ei(dir) = 1; Vec<3> v1 = Cross (plane_b, ei); // grad_2 . v1 ... linear: double g2v1_c = v1 * quad_b; Vec<3> g2v1_l = 2.0 * (quad_c * v1); // find line of two linear equations: Vec<2> rhs; Vec<3> sol; Mat<2,3> mat; for (int j = 0; j < 3; j++) { mat(0,j) = plane_b(j); mat(1,j) = g2v1_l(j); } rhs(0) = -plane_a; rhs(1) = -g2v1_c; Vec<3> t = Cross (plane_b, g2v1_l); if (Abs2(t) > 0) { mat.Solve (rhs, sol); // solve quadratic equation along line sol + alpha t .... double a = quad_a + quad_b * sol + sol * (quad_c * sol); double b = quad_b * t + 2 * (sol * (quad_c * t)); double c = t * (quad_c * t); // solve a + b alpha + c alpha^2: if (fabs (c) > 1e-32) { double disc = sqr (0.5*b/c) - a/c; if (disc > 0) { disc = sqrt (disc); double alpha1 = -0.5*b/c + disc; double alpha2 = -0.5*b/c - disc; pts.Append (Point<3> (sol+alpha1*t)); pts.Append (Point<3> (sol+alpha2*t)); /* cout << "sol1 = " << sol + alpha1 * t << ", sol2 = " << sol + alpha2 * t << endl; */ } } } } } void SpecialPointCalculation :: ComputeExtremalPoints (const Sphere * sphere1, const Sphere * sphere2, Array > & pts) { // 3 equations: // surf1 = 0 <===> |x-c1|^2 - r1^2 = 0; // surf2 = 0 <===> |x-c2|^2 - r2^2 = 0; // (grad 1 x grad 2)(i) = 0 <====> (x-p1) x (p1-p2) . e_i = 0; pts.SetSize (0); Point<3> c1 = sphere1 -> Center(); Point<3> c2 = sphere2 -> Center(); double r1 = sphere1 -> Radius(); double r2 = sphere2 -> Radius(); /* *testout << "\n\ncompute extremalpoint, sphere-sphere" << endl; *testout << "c1 = " << c1 << ", r1 = " << r1 << endl; *testout << "c2 = " << c2 << ", r2 = " << r2 << endl; *testout << "dist = " << Abs (c2-c1) << ", r1+r2 = " << r1+r2 << endl; */ Vec<3> v12 = c2 - c1; Vec<3> a1, a2; double b1, b2; // eqn: ai . x = bi a1 = v12; b1 = 0.5 * (sqr(r1) - sqr(r2) - Abs2(Vec<3> (c1)) + Abs2(Vec<3> (c2)) ); int dir = 0; for (int j = 1; j < 3; j++) if (fabs (v12(j)) < fabs(v12(dir))) dir = j; Vec<3> ei = 0.0; ei(dir) = 1; a2 = Cross (v12, ei); b2 = Vec<3>(c1) * a2; Point<3> p0 (0,0,0); double quad_a; Vec<3> quad_b; Mat<3> quad_c; quad_a = sphere1 -> CalcFunctionValue(p0); sphere1 -> CalcGradient (p0, quad_b); sphere1 -> CalcHesse (p0, quad_c); for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) quad_c(i,j) *= 0.5; // find line of two linear equations: Vec<2> rhs; Vec<3> sol; Mat<2,3> mat; for (int j = 0; j < 3; j++) { mat(0,j) = a1(j); mat(1,j) = a2(j); } rhs(0) = b1; rhs(1) = b2; // *testout << "mat = " << endl << mat << endl; // *testout << "rhs = " << endl << rhs << endl; Vec<3> t = Cross (a1, a2); if (Abs2(t) > 0) { mat.Solve (rhs, sol); /* *testout << "sol = " << endl << sol << endl; *testout << "a * sol = " << mat * sol << endl; *testout << "c1-sol = " << Abs (Vec<3>(c1)-sol) << endl; *testout << "c2-sol = " << Abs (Vec<3>(c2)-sol) << endl; */ // solve quadratic equation along line sol + alpha t .... double a = quad_a + quad_b * sol + sol * (quad_c * sol); double b = quad_b * t + 2 * (sol * (quad_c * t)); double c = t * (quad_c * t); // solve a + b alpha + c alpha^2: if (fabs (c) > 1e-32) { double disc = sqr (0.5*b/c) - a/c; if (disc > 0) { disc = sqrt (disc); double alpha1 = -0.5*b/c + disc; double alpha2 = -0.5*b/c - disc; pts.Append (Point<3> (sol+alpha1*t)); pts.Append (Point<3> (sol+alpha2*t)); // *testout << "pts = " << endl << pts << endl; /* cout << "sol1 = " << sol + alpha1 * t << ", sol2 = " << sol + alpha2 * t << endl; */ } } } } /* bool SpecialPointCalculation :: ExtremalPointPossible (const Surface * f1, const Surface * f2, int dir, const BoxSphere<3> & box) { double hn1, hn2, gn1, gn2; Point<3> p; Vec<3> g1, g2, v; double f3; double r = box.Diam()/2; p = box.Center(); f1 -> CalcGradient (p, g1); f2 -> CalcGradient (p, g2); gn1 = g1.Length(); gn2 = g2.Length(); hn1 = f1 -> HesseNorm (); hn2 = f2 -> HesseNorm (); v = Cross (g1, g2); f3 = fabs (v(dir-1)); // (*testout) << "f3 = " << f3 << " r = " << r // << "normbound = " // << (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1)) << endl; return (f3 <= 3 * r * (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1))); } bool SpecialPointCalculation :: ExtremalPointNewtonConvergence (const Surface * f1, const Surface * f2, int dir, const BoxSphere<3> & box) { return box.Diam() < 1e-8; } bool SpecialPointCalculation :: ExtremalPointDegenerated (const Surface * f1, const Surface * f2, int dir, const BoxSphere<3> & box) { double gn1, gn2; Point<3> p; Vec<3> g1, g2, v; double maxderiv; double minv; Vec<3> curv, t; Vec<2> rs, x; Mat<3> h1, h2; Mat<2> a, inv; double leftside; if (box.Diam() > relydegtest) return 0; p = box.Center(); f1 -> CalcGradient (p, g1); f2 -> CalcGradient (p, g2); gn1 = g1.Length(); gn2 = g2.Length(); v = Cross (g1, g2); if (Abs (v) < epeps1 * gn1 * gn2) return 1; // irregular edge f1 -> CalcHesse (p, h1); f2 -> CalcHesse (p, h2); // hn1 = f1 -> HesseNorm (); // hn2 = f2 -> HesseNorm (); t = v; a(0, 0) = g1 * g1; a(0, 1) = a(1, 0) = g1 * g2; a(1, 1) = g2 * g2; rs(0) = g1(dir-1); rs(1) = g2(dir-1); a.Solve (rs, x); // (*testout) << "g1 = " << g1 << " g2 = " << g2 << endl; // (*testout) << "lam = " << x << endl; // (*testout) << "h2 = " << h2 << endl; leftside = fabs (x(0) * ( t * (h1 * t)) + x(1) * ( t * (h2 * t))); // (*testout) << "leftside = " << leftside << endl; if (leftside < epeps2 * Abs2 (v)) return 1; return 0; } */ bool SpecialPointCalculation :: AddPoint (const Point<3> & p, int layer) { for (int i = 0; i < points->Size(); i++) if (Dist2 ( (*points)[i], p) < epspointdist2 && (*points)[i].GetLayer() == layer) return false; points->Append (MeshPoint(p, layer)); PrintMessageCR (3, "Found points ", points->Size()); return true; } void SpecialPointCalculation :: AnalyzeSpecialPoints (const CSGeometry & ageometry, Array & apoints, Array & specpoints) { static int timer = NgProfiler::CreateTimer ("CSG: analyze special points"); NgProfiler::RegionTimer reg (timer); Array surfind, rep_surfind, surfind2, rep_surfind2, surfind3; Array > normalvecs; Vec<3> nsurf = 0.0; Array specpoint2point; specpoints.SetSize (0); geometry = &ageometry; double geomsize = ageometry.MaxSize(); (*testout) << "AnalyzeSpecialPoints\n"; if (!apoints.Size()) return; { /* sort points in the (arbitrary) direction dir important for periodic boundaries: corner points on the left and the right boundary come in the same ordering */ Vec<3> dir(1.2, 1.7, 0.9); Array coord(apoints.Size()); for (int i = 0; i < apoints.Size(); i++) coord[i] = dir * Vec<3> (apoints[i]); QuickSort (coord, apoints); } Box<3> bbox (apoints[0], apoints[0]); for (int i = 1; i < apoints.Size(); i++) bbox.Add (apoints[i]); bbox.Increase (0.1 * bbox.Diam()); (*testout) << "points = " << apoints << endl; Point3dTree searchtree (bbox.PMin(), bbox.PMax()); Array locsearch; for (int si = 0; si < ageometry.GetNTopLevelObjects(); si++) { const TopLevelObject * tlo = ageometry.GetTopLevelObject(si); const Solid * sol = tlo->GetSolid(); const Surface * surf = tlo->GetSurface(); for (int i = 0; i < apoints.Size(); i++) { Point<3> p = apoints[i]; #ifdef DEVELOP *testout << " test point " << p << endl; #endif if (tlo->GetLayer() != apoints[i].GetLayer()) continue; Solid * locsol; sol -> TangentialSolid (p, locsol, surfind, ideps*geomsize); rep_surfind.SetSize (surfind.Size()); int num_indep_surfs = 0; for (int j = 0; j < surfind.Size(); j++) { rep_surfind[j] = ageometry.GetSurfaceClassRepresentant (surfind[j]); bool found = false; for (int k = 0; !found && k < j; k++) found = (rep_surfind[k] == rep_surfind[j]); if(!found) num_indep_surfs++; } #ifdef DEVELOP *testout << "surfs = " << surfind << endl; *testout << "rep_surfs = " << rep_surfind << endl; #endif if (!locsol) continue; // get all surface indices, if (surf) { // locsol -> GetSurfaceIndices (surfind); bool hassurf = 0; for (int m = 0; m < surfind.Size(); m++) if (ageometry.GetSurface(surfind[m]) == surf) hassurf = 1; if (!hassurf) continue; nsurf = surf->GetNormalVector (p); } /* // get independent surfaces of tangential solid BoxSphere<3> box(p,p); box.Increase (1e-6*geomsize); box.CalcDiamCenter(); ageometry.GetIndependentSurfaceIndices (locsol, box, surfind); */ // ageometry.GetIndependentSurfaceIndices (surfind); normalvecs.SetSize(surfind.Size()); for (int j = 0; j < surfind.Size(); j++) normalvecs[j] = ageometry.GetSurface(surfind[j]) -> GetNormalVector(apoints[i]); for (int j = 0; j < normalvecs.Size(); j++) for (int k = 0; k < normalvecs.Size(); k++) { if (rep_surfind[j] == rep_surfind[k]) continue; //if (j == k) continue; Vec<3> t; if (dynamic_cast (ageometry.surf2prim[surfind[j]]) && ageometry.surf2prim[surfind[j]] == ageometry.surf2prim[surfind[k]]) { t = ageometry.surf2prim[surfind[j]] -> SpecialPointTangentialVector (p, surfind[j], surfind[k]); } else { t = Cross (normalvecs[j], normalvecs[k]); } if (Abs2 (t) < 1e-8) continue; #ifdef DEVELOP *testout << " tangential vector " << t << endl; #endif t.Normalize(); // try tangential direction t if (surf && fabs (nsurf * t) > 1e-6) continue; #ifdef DEVELOP *testout << " j " << j << " k " << k << endl; #endif if (!surf) { // compute second order approximation // c(s) = p + s t + s*s/2 t2 Vec<3> gradj, gradk; Mat<3> hessej, hessek; ageometry.GetSurface (surfind[j]) -> CalcGradient (p, gradj); ageometry.GetSurface (surfind[k]) -> CalcGradient (p, gradk); ageometry.GetSurface (surfind[j]) -> CalcHesse (p, hessej); ageometry.GetSurface (surfind[k]) -> CalcHesse (p, hessek); Vec<2> rhs; Vec<3> t2; Mat<2,3> mat; Mat<3,2> inv; for (int l = 0; l < 3; l++) { mat(0,l) = gradj(l); mat(1,l) = gradk(l); } rhs(0) = -t * (hessej * t); rhs(1) = -t * (hessek * t); CalcInverse (mat, inv); t2 = inv * rhs; /* ageometry.GetIndependentSurfaceIndices (locsol, p, t, surfind2); */ Solid * locsol2; locsol -> TangentialSolid3 (p, t, t2, locsol2, surfind2, ideps*geomsize); if (!locsol2) continue; // locsol2 -> GetTangentialSurfaceIndices3 (p, t, t2, surfind2, 1e-9*geomsize); rep_surfind2.SetSize (surfind2.Size()); for (int j2 = 0; j2 < surfind2.Size(); j2++) rep_surfind2[j2] = ageometry.GetSurfaceClassRepresentant (surfind2[j2]); #ifdef DEVELOP (*testout) << "surfind2 = " << endl << surfind2 << endl; #endif Array surfind2_aux(surfind2); ageometry.GetIndependentSurfaceIndices (surfind2_aux); #ifdef DEVELOP (*testout) << "surfind2,rep = " << endl << surfind2_aux << endl; #endif bool ok = true; // intersecting surfaces must be in second order tangential solid /* if (!surfind2.Contains(surfind[j]) || !surfind2.Contains(surfind[k])) ok = false; */ if (!surfind2_aux.Contains(rep_surfind[j]) || !surfind2_aux.Contains(rep_surfind[k])) ok = false; #ifdef DEVELOP (*testout) << "ok,1 = " << ok << endl; #endif // there must be 2 different tangential faces to the edge int cnt_tang_faces = 0; for (int l = 0; l < surfind2.Size(); l++) { Vec<3> nv = ageometry.GetSurface(surfind2[l]) -> GetNormalVector(p); Vec<3> m1 = Cross (t, nv); Vec<3> m2 = -m1; bool isface1 = 0, isface2 = 0; Solid * locsol3; // locsol2 -> TangentialSolid2 (p, m1, locsol3, surfind3, 1e-9*geomsize); locsol -> TangentialEdgeSolid (p, t, t2, m1, locsol3, surfind3, ideps*geomsize); //ageometry.GetIndependentSurfaceIndices (surfind3); if (surfind3.Contains(surfind2[l])) isface1 = 1; delete locsol3; // locsol2 -> TangentialSolid2 (p, m2, locsol3, surfind3, 1e-9*geomsize); locsol -> TangentialEdgeSolid (p, t, t2, m2, locsol3, surfind3, ideps*geomsize); // ageometry.GetIndependentSurfaceIndices (surfind3); if (surfind3.Contains(surfind2[l])) isface2 = 1; delete locsol3; if (isface1 != isface2) cnt_tang_faces++; } #ifdef DEVELOP (*testout) << "cnt_tang = " << cnt_tang_faces << endl; #endif if (cnt_tang_faces < 1) ok = false; delete locsol2; if (!ok) continue; } // edge must be on tangential surface bool isedge = locsol->VectorIn (p, t) && !locsol->VectorStrictIn (p, t); #ifdef DEVELOP (*testout) << "isedge,1 = " << isedge << "\n"; #endif // there must exist at least two different faces on edge if (isedge) { // *testout << "succ 1" << endl; int cnts = 0; for (int m = 0; m < surfind.Size(); m++) { if (fabs (normalvecs[m] * t) > 1e-6) continue; Vec<3> s = Cross (normalvecs[m], t); Vec<3> t2a = t + 0.01 *s; Vec<3> t2b = t - 0.01 *s; bool isface = (locsol->VectorIn (p, t2a, 1e-6*geomsize) && !locsol->VectorStrictIn (p, t2a, 1e-6*geomsize)) || (locsol->VectorIn (p, t2b, 1e-6*geomsize) && !locsol->VectorStrictIn (p, t2b, 1e-6*geomsize)); /* bool isface = (locsol->VectorIn (p, t2a) && !locsol->VectorStrictIn (p, t2a)) || (locsol->VectorIn (p, t2b) && !locsol->VectorStrictIn (p, t2b)); */ if (isface) { cnts++; } } if (cnts < 2) isedge = 0; } if (isedge) { #ifdef DEVELOP *testout << "success" << endl; #endif int spi = -1; const double searchradius = 1e-4*geomsize;//1e-5*geomsize; searchtree.GetIntersecting (apoints[i]-Vec3d(searchradius,searchradius,searchradius), apoints[i]+Vec3d(searchradius,searchradius,searchradius), locsearch); for (int m = 0; m < locsearch.Size(); m++) { if (Dist2 (specpoints[locsearch[m]].p, apoints[i]) < 1e-10*geomsize && Abs2(specpoints[locsearch[m]].v - t) < 1e-8) { spi = locsearch[m]; break; } } if (spi == -1) { specpoints.Append (SpecialPoint()); spi = specpoints.Size()-1; specpoint2point.Append (i); specpoints.Last().unconditional = 0; searchtree.Insert (apoints[i], spi); } if(!specpoints[spi].unconditional) { specpoints[spi].p = apoints[i]; specpoints[spi].v = t; //if (surfind.Size() >= 3) if (num_indep_surfs >= 3) specpoints[spi].unconditional = 1; specpoints[spi].s1 = rep_surfind[j]; specpoints[spi].s2 = rep_surfind[k]; specpoints[spi].s1_orig = surfind[j]; specpoints[spi].s2_orig = surfind[k]; specpoints[spi].layer = apoints[i].GetLayer(); for (int up = 0; up < geometry->GetNUserPoints(); up++) if (Dist (geometry->GetUserPoint(up), apoints[i]) < 1e-8*geomsize) specpoints[spi].unconditional = 1; for (int ip = 0; ip < geometry->GetNIdentPoints(); ip++) if (Dist (geometry->GetIdentPoint(ip), apoints[i]) < 1e-8*geomsize) specpoints[spi].unconditional = 1; } } } delete locsol; } } /* BitArray testuncond (specpoints.Size()); testuncond.Clear(); for(int i = 0; i same; same.Append(i); for(int j = i+1; j & specpoints, double h, Mesh & mesh); class EdgeCalculation { const CSGeometry & geometry; Array & specpoints; Point3dTree * searchtree; Point3dTree * meshpoint_tree; int cntedge; double ideps; MeshingParameters & mparam; public: EdgeCalculation (const CSGeometry & ageometry, Array & aspecpoints, MeshingParameters & amparam); ~EdgeCalculation(); void SetIdEps(const double epsin) {ideps = epsin;} void Calc(double h, Mesh & mesh); private: void CalcEdges1 (double h, Mesh & mesh); void FollowEdge (int pi1, int & ep, int & pos, // const Array & hsp, const Array & hsp, double h, const Mesh & mesh, Array > & edgepoints, Array & curvelength); void AnalyzeEdge (int s1, int s2, int s1_rep, int s2_rep, int pos, int layer, const Array > & edgepoints, Array & refedges, Array & refedgesinv); void StoreEdge (const Array & refedges, const Array & refedgesinv, const Array > & edgepoints, const Array & curvelength, int layer, Mesh & mesh); void StoreShortEdge (const Array & refedges, const Array & refedgesinv, const Array > & edgepoints, const Array & curvelength, int layer, Mesh & mesh); void CopyEdge (const Array & refedges, const Array & refedgesinv, int copyfromedge, const Point<3> & fromstart, const Point<3> & fromend, const Point<3> & tostart, const Point<3> & toend, int copyedgeidentification, int layer, Mesh & mesh); void SplitEqualOneSegEdges (Mesh & mesh); void FindClosedSurfaces (double h, Mesh & mesh); public: bool point_on_edge_problem; }; } #endif netgen-6.2.1905/libsrc/csg/splinesurface.hpp0000644000175000017500000000632413504650527017414 0ustar kurtkurt#ifndef FILE_SPLINESURFACE #define FILE_SPLINESURFACE namespace netgen { class SplineSurface : public OneSurfacePrimitive { protected: Array> geompoints; Array>> splines; Array bcnames; Array maxh; shared_ptr baseprimitive; shared_ptr>> cuts; shared_ptr>> all_cuts; public: SplineSurface(shared_ptr abaseprimitive, shared_ptr>> acuts) : OneSurfacePrimitive(), baseprimitive(abaseprimitive), cuts(acuts) { ; } // default constructor for archive SplineSurface() {} virtual ~SplineSurface() { ; } const auto & GetSplines() const { return splines; } int GetNSplines() const { return splines.Size(); } const Array>& GetPoints() const { return geompoints; } string GetSplineType(const int i) const { return splines[i]->GetType(); } SplineSeg<3> & GetSpline(const int i) { return *splines[i]; } const SplineSeg<3> & GetSpline(const int i) const { return *splines[i]; } int GetNP() const { return geompoints.Size(); } const GeomPoint<3> & GetPoint(int i) const { return geompoints[i]; } string GetBCName(int i) const { return bcnames[i]; } string GetBCNameOf(Point<3> p1, Point<3> p2) const; DLL_HEADER void AppendPoint(const Point<3> & p, const double reffac = 1., const bool hpref=false); void AppendSegment(shared_ptr> spline, string & bcname, double amaxh = -1); const shared_ptr>> CreateCuttingSurfaces(); const shared_ptr>> GetCuts() const { return all_cuts; } const shared_ptr GetBase() const { return baseprimitive; } virtual void Project (Point<3> & p3d) const { baseprimitive->Project(p3d); } virtual double CalcFunctionValue (const Point<3> & point) const { return baseprimitive->CalcFunctionValue (point); } virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const { baseprimitive->CalcGradient (point,grad); } virtual double HesseNorm () const { return baseprimitive->HesseNorm(); } virtual Point<3> GetSurfacePoint () const { return baseprimitive->GetSurfacePoint(); } virtual void CalcSpecialPoints(Array> & pts) const { baseprimitive->CalcSpecialPoints(pts); } virtual INSOLID_TYPE BoxInSolid(const BoxSphere<3> & box) const { return baseprimitive->BoxInSolid(box); } virtual void DoArchive(Archive& ar) { ar & geompoints & splines & bcnames & maxh & baseprimitive & cuts & all_cuts; } /* virtual void Project (Point<3> & p3d) const; virtual double CalcFunctionValue (const Point<3> & point) const; virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; virtual double HesseNorm () const; virtual Point<3> GetSurfacePoint () const; virtual void CalcSpecialPoints(Array> & pts) const; virtual INSOLID_TYPE BoxInSolid(const BoxSphere<3> & box) const; */ virtual void Print (ostream & str) const; }; } #endif netgen-6.2.1905/libsrc/csg/gencyl.cpp0000644000175000017500000001032213504650527016016 0ustar kurtkurt#include #include namespace netgen { GeneralizedCylinder :: GeneralizedCylinder (ExplicitCurve2d & acrosssection, Point<3> ap, Vec<3> ae1, Vec<3> ae2) : crosssection(acrosssection) { planep = ap; planee1 = ae1; planee2 = ae2; planee3 = Cross (planee1, planee2); (*testout) << "Vecs = " << planee1 << " " << planee2 << " " << planee3 << endl; }; void GeneralizedCylinder :: Project (Point<3> & p) const { Point<2> p2d; double z; p2d = Point<2> (planee1 * (p - planep), planee2 * (p - planep)); z = planee3 * (p - planep); crosssection.Project (p2d); p = planep + p2d(0) * planee1 + p2d(1) * planee2 + z * planee3; } int GeneralizedCylinder ::BoxInSolid (const BoxSphere<3> & box) const { Point<3> p3d; Point<2> p2d, projp; double t; Vec<2> tan, n; p3d = box.Center(); p2d = Point<2> (planee1 * (p3d - planep), planee2 * (p3d - planep)); t = crosssection.ProjectParam (p2d); projp = crosssection.Eval (t); tan = crosssection.EvalPrime (t); n(0) = tan(1); n(1) = -tan(0); if (Dist (p2d, projp) < box.Diam()/2) return 2; if (n * (p2d - projp) > 0) { return 0; } return 1; } double GeneralizedCylinder :: CalcFunctionValue (const Point<3> & point) const { Point<2> p2d, projp; double t; Vec<2> tan, n; p2d = Point<2> (planee1 * (point - planep), planee2 * (point - planep)); t = crosssection.ProjectParam (p2d); projp = crosssection.Eval (t); tan = crosssection.EvalPrime (t); n(0) = tan(1); n(1) = -tan(0); n /= n.Length(); return n * (p2d - projp); } void GeneralizedCylinder :: CalcGradient (const Point<3> & point, Vec<3> & grad) const { Point<2> p2d, projp; double t; Vec<2> tan, n; p2d = Point<2> (planee1 * (point - planep), planee2 * (point - planep)); t = crosssection.ProjectParam (p2d); projp = crosssection.Eval (t); tan = crosssection.EvalPrime (t); n(0) = tan(1); n(1) = -tan(0); n /= n.Length(); grad = n(0) * planee1 + n(1) * planee2; } void GeneralizedCylinder :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const { Point<2> p2d, projp; double t, dist, val; Point<2> curvp; Vec<2> curvpp; Mat<2> h2d; Mat<3,2> vmat; int i, j, k, l; p2d = Point<2> (planee1 * (point - planep), planee2 * (point - planep)); t = crosssection.ProjectParam (p2d); curvp = crosssection.CurvCircle (t); curvpp = p2d-curvp; dist = curvpp.Length(); curvpp /= dist; h2d(0, 0) = (1 - curvpp(0) * curvpp(0) ) / dist; h2d(0, 1) = h2d(1, 0) = (- curvpp(0) * curvpp(1) ) / dist; h2d(1, 1) = (1 - curvpp(1) * curvpp(1) ) / dist; vmat(0,0) = planee1(0); vmat(1,0) = planee1(1); vmat(2,0) = planee1(2); vmat(0,1) = planee2(0); vmat(1,1) = planee2(1); vmat(2,1) = planee2(2); for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) { val = 0; for (k = 0; k < 2; k++) for (l = 0; l < 2; l++) val += vmat(i,k) * h2d(k,l) * vmat(j,l); hesse(i,j) = val; } } double GeneralizedCylinder :: HesseNorm () const { return crosssection.MaxCurvature(); } double GeneralizedCylinder :: MaxCurvatureLoc (const Point<3> & c, double rad) const { Point<2> c2d = Point<2> (planee1 * (c - planep), planee2 * (c - planep)); return crosssection.MaxCurvatureLoc(c2d, rad); } Point<3> GeneralizedCylinder :: GetSurfacePoint () const { Point<2> p2d; p2d = crosssection.Eval(0); return planep + p2d(0) * planee1 + p2d(1) * planee2; } void GeneralizedCylinder :: Reduce (const BoxSphere<3> & box) { Point<2> c2d = Point<2> (planee1 * (box.Center() - planep), planee2 * (box.Center() - planep)); crosssection.Reduce (c2d, box.Diam()/2); } void GeneralizedCylinder :: UnReduce () { crosssection.UnReduce (); } void GeneralizedCylinder :: Print (ostream & str) const { str << "Generalized Cylinder" << endl; crosssection.Print (str); } } netgen-6.2.1905/libsrc/csg/explicitcurve2d.hpp0000644000175000017500000000510713504650527017663 0ustar kurtkurt#ifndef FILE_EXPLICITCURVE2D #define FILE_EXPLICITCURVE2D /**************************************************************************/ /* File: explicitcurve2d.hh */ /* Author: Joachim Schoeberl */ /* Date: 14. Oct. 96 */ /**************************************************************************/ namespace netgen { /* Explicit 2D Curve repesentation */ /// class ExplicitCurve2d : public Curve2d { public: /// ExplicitCurve2d (); /// virtual void Project (Point<2> & p) const; /// virtual double ProjectParam (const Point<2> & p) const = 0; /// virtual double NumericalProjectParam (const Point<2> & p, double lb, double ub) const; /// virtual double MinParam () const = 0; /// virtual double MaxParam () const = 0; /// virtual Point<2> Eval (double t) const = 0; /// virtual Vec<2> EvalPrime (double t) const = 0; /// virtual Vec<2> Normal (double t) const; /// virtual void NormalVector (const Point<2> & p, Vec<2> & n) const; /// virtual Vec<2> EvalPrimePrime (double t) const = 0; /// virtual double MaxCurvature () const; /// virtual double MaxCurvatureLoc (const Point<2> & p, double rad) const; /// virtual Point<2> CurvCircle (double t) const; /// virtual void Print (ostream & /* str */) const { }; /// virtual int SectionUsed (double /* t */) const { return 1; } /// virtual void Reduce (const Point<2> & /* p */, double /* rad */) { }; /// virtual void UnReduce () { }; }; /// class BSplineCurve2d : public ExplicitCurve2d { /// Array > points; /// Array intervallused; /// int redlevel; public: /// BSplineCurve2d (); /// void AddPoint (const Point<2> & apoint); bool Inside (const Point<2> & p, double & dist) const; /// virtual double ProjectParam (const Point<2> & p) const; /// virtual double MinParam () const { return 0; } /// virtual double MaxParam () const { return points.Size(); } /// virtual Point<2> Eval (double t) const; /// virtual Vec<2> EvalPrime (double t) const; /// virtual Vec<2> EvalPrimePrime (double t) const; /// virtual void Print (ostream & str) const; /// virtual int SectionUsed (double t) const; /// virtual void Reduce (const Point<2> & p, double rad); /// virtual void UnReduce (); }; } #endif netgen-6.2.1905/libsrc/csg/csgparser.cpp0000644000175000017500000007460313504650527016542 0ustar kurtkurt#include #include #include #include namespace netgen { static kwstruct defkw[] = { { TOK_RECO, "algebraic3d" }, { TOK_SOLID, "solid" }, { TOK_TLO, "tlo" }, { TOK_CURVE2D, "curve2d" }, { TOK_CURVE3D, "curve3d" }, { TOK_BOUNDINGBOX, "boundingbox" }, { TOK_OR, "or" }, { TOK_AND, "and" }, { TOK_NOT, "not" }, { TOK_SINGULAR, "singular" }, { TOK_EDGE, "edge" }, { TOK_FACE, "face" }, { TOK_POINT, "point" }, { TOK_IDENTIFY, "identify" }, { TOK_CLOSESURFACES, "closesurfaces" }, { TOK_CLOSEEDGES, "closeedges" }, { TOK_PERIODIC, "periodic" }, { TOK_BOUNDARYCONDITION, "boundarycondition" }, { TOK_BOUNDARYCONDITIONNAME, "boundaryconditionname" }, { TOK_DEFINE, "define" }, { TOK_CONSTANT, "constant" }, { TOKEN_TYPE(0), 0 } }; static primstruct defprim[] = { { TOK_PLANE, "plane" }, { TOK_SPHERE, "sphere" }, { TOK_CYLINDER, "cylinder" }, { TOK_CONE, "cone" }, { TOK_ELLIPTICCONE, "ellipticcone" }, { TOK_ELLIPTICCYLINDER, "ellipticcylinder" }, { TOK_ELLIPSOID, "ellipsoid" }, { TOK_ORTHOBRICK, "orthobrick" }, { TOK_POLYHEDRON, "polyhedron" }, { TOK_TORUS, "torus" }, { TOK_TUBE, "tube" }, { TOK_GENCYL, "gencyl" }, { TOK_EXTRUSION, "extrusion" }, { TOK_REVOLUTION, "revolution" }, { TOK_TRANSLATE, "translate" }, { TOK_MULTITRANSLATE, "multitranslate" }, { TOK_ROTATE, "rotate" }, { TOK_MULTIROTATE, "multirotate" }, { PRIMITIVE_TYPE(0), 0 } }; static CSGeometry * geom; CSGScanner :: CSGScanner (istream & ascanin) { scanin = &ascanin; token = TOK_END; num_value = 0; linenum = 1; } void CSGScanner :: ReadNext () { char ch; // scan whitespaces do { scanin->get(ch); //if (ch == '\n') // linenum++; // end of file reached if (scanin->eof()) { token = TOK_END; return; } if (ch == '\n') linenum++; // skip comment line if (ch == '#') { while (ch != '\n') { scanin->get(ch); if (scanin->eof()) { token = TOK_END; return; } } linenum++; } } while (isspace(ch)); switch (ch) { case '(': case ')': case '[': case ']': case '-': case '=': case ',': case ';': { token = TOKEN_TYPE (ch); break; } default: { if (isdigit (ch) || ch == '.') { scanin->putback (ch); (*scanin) >> num_value; token = TOK_NUM; return; } if (isalpha (ch)) { string_value = string (1, ch); scanin->get(ch); while (isalnum(ch) || ch == '_') { string_value += ch; scanin->get(ch); } scanin->putback (ch); } int nr = 0; while (defkw[nr].kw) { if (string_value == defkw[nr].name) { token = defkw[nr].kw; return; } nr++; } nr = 0; while (defprim[nr].kw) { if (string_value == defprim[nr].name) { token = TOK_PRIMITIVE; prim_token = defprim[nr].kw; return; } nr++; } token = TOK_STRING; } } } void CSGScanner :: Error (const string & err) { stringstream errstr; errstr << "Parsing error in line " << linenum << ": " << endl << err << endl; throw string(errstr.str()); } /* Solid = Term { OR Term } Term = Primary { AND Primary } Primary = PRIM | IDENT | ( Solid ) | NOT Primary */ void ParseChar (CSGScanner & scan, char ch) { if (scan.GetToken() != TOKEN_TYPE(ch)) scan.Error (string ("token '") + string(1, ch) + string("' expected")); scan.ReadNext(); } double ParseNumber(CSGScanner & scan) { if (scan.GetToken() == '-') { scan.ReadNext(); return -ParseNumber (scan); } if (scan.GetToken() != TOK_NUM) scan.Error ("number expected"); double val = scan.GetNumValue(); scan.ReadNext(); return val; } Vec<3> ParseVector (CSGScanner & scan) { Vec<3> v; v(0) = ParseNumber (scan); ParseChar (scan, ','); v(1) = ParseNumber (scan); ParseChar (scan, ','); v(2) = ParseNumber (scan); return v; } CSGScanner & operator>> (CSGScanner & scan, char ch) { if (scan.GetToken() != TOKEN_TYPE(ch)) scan.Error (string ("token '") + string(1, ch) + string("' expected")); scan.ReadNext(); return scan; } CSGScanner & operator>> (CSGScanner & scan, double & d) { d = ParseNumber (scan); return scan; } CSGScanner & operator>> (CSGScanner & scan, int & i) { i = int (ParseNumber (scan)); return scan; } CSGScanner & operator>> (CSGScanner & scan, Point<3> & p) { scan >> p(0) >> ',' >> p(1) >> ',' >> p(2); return scan; } CSGScanner & operator>> (CSGScanner & scan, Vec<3> & v) { scan >> v(0) >> ',' >> v(1) >> ',' >> v(2); return scan; } Solid * ParseSolid (CSGScanner & scan); Solid * ParseTerm (CSGScanner & scan); Solid * ParsePrimary (CSGScanner & scan); Solid * ParsePrimary (CSGScanner & scan) { if (scan.GetToken() == TOK_PRIMITIVE) { switch (scan.GetPrimitiveToken()) { case TOK_PLANE: { Point<3> p; Vec<3> v; scan.ReadNext(); scan >> '(' >> p >> ';' >> v >> ')'; OneSurfacePrimitive * surf = new Plane ( p, v ); geom->AddSurfaces (surf); return new Solid (surf); } case TOK_CYLINDER: { Point<3> pa, pb; double r; scan.ReadNext(); scan >> '(' >> pa >> ';' >> pb >> ';' >> r >> ')'; OneSurfacePrimitive * surf = new Cylinder ( pa, pb, r ); geom->AddSurfaces (surf); return new Solid (surf); } case TOK_ELLIPTICCYLINDER: { Point<3> pa; Vec<3> vl, vs; scan.ReadNext(); scan >> '(' >> pa >> ';' >> vl >> ';' >> vs >> ')'; OneSurfacePrimitive * surf = new EllipticCylinder ( pa, vl, vs); geom->AddSurfaces (surf); return new Solid (surf); } case TOK_ELLIPSOID: { Point<3> pa; Vec<3> v1, v2, v3; scan.ReadNext(); scan >> '(' >> pa >> ';' >> v1 >> ';' >> v2 >> ';' >> v3 >> ')'; OneSurfacePrimitive * surf = new Ellipsoid ( pa, v1, v2, v3); geom->AddSurfaces (surf); return new Solid (surf); } case TOK_CONE: { Point<3> pa, pb; double ra, rb; scan.ReadNext(); scan >> '(' >> pa >> ';' >> ra >> ';' >> pb >> ';' >> rb >> ')'; OneSurfacePrimitive * surf = new Cone ( pa, pb, ra, rb ); geom->AddSurfaces (surf); return new Solid (surf); } case TOK_ELLIPTICCONE: { Point<3> a; Vec<3> vl, vs; double h, vlr; scan.ReadNext(); scan >> '(' >> a >> ';' >> vl >> ';' >> vs >> ';' >> h >>';' >> vlr >> ')'; OneSurfacePrimitive * surf = new EllipticCone ( a, vl, vs, h, vlr ); geom->AddSurfaces (surf); return new Solid (surf); } case TOK_SPHERE: { Point<3> p; double r; scan.ReadNext(); scan >> '(' >> p >> ';' >> r >> ')'; OneSurfacePrimitive * surf = new Sphere ( p, r ); geom->AddSurfaces (surf); return new Solid (surf); } case TOK_ORTHOBRICK: { Point<3> pa, pb; scan.ReadNext(); scan >> '(' >> pa >> ';' >> pb >> ')'; Primitive * nprim = new OrthoBrick (pa, pb); geom->AddSurfaces (nprim); return new Solid (nprim); } case TOK_POLYHEDRON: { // Added by Dalibor Lukas, October 15, 2003 Point<3> p; //int pi1, pi2, pi3, pi4; scan.ReadNext(); ParseChar (scan, '('); Polyhedra * polyhedron = new Polyhedra; // scanning the points while (1) { p = Point<3> (ParseVector (scan)); ParseChar (scan, ';'); polyhedron->AddPoint(p); if (scan.GetToken() == ';') { scan.ReadNext(); break; } } // scanning the faces int inputface = 0; while (1) { Array pnums,cleaned_pnums; for(int i=0; i<3; i++) { pnums.Append((int) (ParseNumber (scan))); if(i<2) ParseChar (scan, ','); } if (scan.GetToken() == TOK_COMMA) { ParseChar (scan, ','); pnums.Append((int) (ParseNumber (scan))); } for(int i=0; iAddFace(cleaned_pnums[0]-1, cleaned_pnums[1]-1, cleaned_pnums[2]-1, inputface); } else if(cleaned_pnums.Size() == 4) { polyhedron->AddFace(cleaned_pnums[0]-1, cleaned_pnums[1]-1, cleaned_pnums[2]-1, inputface); polyhedron->AddFace(cleaned_pnums[0]-1, cleaned_pnums[2]-1, cleaned_pnums[3]-1, inputface); } else { ostringstream msg; msg << "Something wrong with polyhedron face:"; for(int i=0; iAddSurfaces (polyhedron); return new Solid (polyhedron); } case TOK_REVOLUTION: { Point<3> p0,p1; scan.ReadNext(); scan >> '(' >> p0 >> ';' >> p1 >> ';'; string spline = scan.GetStringValue(); scan.ReadNext(); scan >> ')'; if(!geom->GetSplineCurve2d(spline)) { scan.Error ( string("2D Spline curve not found: ") + spline ); break; } Primitive * nprim = new Revolution(p0,p1, *(geom->GetSplineCurve2d(spline))); geom->AddSurfaces (nprim); return new Solid(nprim); } case TOK_EXTRUSION: { scan.ReadNext(); scan >> '('; string epath = scan.GetStringValue(); scan.ReadNext(); scan >> ';'; string profile = scan.GetStringValue(); scan.ReadNext(); Vec<3> z_dir; scan >> ';' >> z_dir(0) >> ',' >> z_dir(1) >> ',' >> z_dir(2) >> ')'; if(!geom->GetSplineCurve2d(profile)) { scan.Error ( string("2D Spline curve not found: ") + profile ); break; } if(!geom->GetSplineCurve3d(epath)) { scan.Error ( string("2D Spline curve not found: ") + epath ); break; } Primitive * nprim = new Extrusion(*(geom->GetSplineCurve3d(epath)), *(geom->GetSplineCurve2d(profile)), z_dir); geom->AddSurfaces (nprim); return new Solid(nprim); } /// Torus /// Lorenzo Codecasa (codecasa@elet.polimi.it) /// April 27th, 2005 /// /// begin... case TOK_TORUS: { Point<3> pc; Vec<3> vn; double R, r; scan.ReadNext(); scan >> '(' >> pc >> ';' >> vn >> ';' >> R >> ';' >> r >> ')'; OneSurfacePrimitive * surf = new Torus ( pc, vn, R, r ); geom->AddSurfaces (surf); return new Solid (surf); } /// ..end case TOK_TRANSLATE: { Vec<3> v; scan.ReadNext(); ParseChar (scan, '('); v = ParseVector (scan); ParseChar (scan, ';'); Solid * sol1 = ParseSolid (scan); ParseChar (scan, ')'); Solid * nsol = sol1 -> Copy(*geom); Transformation<3> trans(v); nsol -> Transform (trans); return nsol; } case TOK_ROTATE: { Point<3> c; Vec<3> v; scan.ReadNext(); scan >> '(' >> c >> ';' >> v >> ';'; Solid * sol1 = ParseSolid (scan); ParseChar (scan, ')'); Solid * nsol = sol1 -> Copy(*geom); Transformation<3> trans(c,v(0),v(1),v(2)); nsol -> Transform (trans); return nsol; } case TOK_MULTITRANSLATE: { Vec<3> v; int n; scan.ReadNext(); scan >> '(' >> v >> ';' >> n >> ';'; Solid * sol1 = ParseSolid (scan); scan >> ')'; Solid * hsol = sol1; for (int i = 1; i <= n; i++) { Solid * nsol = sol1 -> Copy(*geom); Transformation<3> trans(double(i) * v); nsol -> Transform (trans); hsol = new Solid (Solid::UNION, hsol, nsol); } return hsol; } case TOK_MULTIROTATE: { Point<3> c; Vec<3> v; int n; scan.ReadNext(); scan >> '(' >> c >> ';' >> v >> ';' >> n >> ';'; Solid * sol1 = ParseSolid (scan); scan >> ')'; Transformation<3> trans(c, v(0), v(1), v(2)); Transformation<3> multi(Vec<3>(0,0,0)); Transformation<3> ht; Solid * hsol = sol1; for (int i = 1; i <= n; i++) { Solid * nsol = sol1 -> Copy(*geom); nsol -> Transform (multi); hsol = new Solid (Solid::UNION, hsol, nsol); ht=multi; multi.Combine (trans, ht); } return hsol; } default: { scan.Error (string ("unknown primary ") + scan.GetStringValue()); } } } else if (scan.GetToken() == TOK_STRING && geom->GetSolid(scan.GetStringValue())) { Solid * sol = const_cast (geom->GetSolid(scan.GetStringValue())); scan.ReadNext(); return sol; } else if (scan.GetToken() == TOK_NOT) { scan.ReadNext(); Solid * sol1 = ParsePrimary (scan); return new Solid (Solid::SUB, sol1); } else if (scan.GetToken() == '(') { scan.ReadNext(); Solid * sol1 = ParseSolid (scan); scan.ReadNext(); return sol1; } scan.Error (string ("not a primary, name = ")+ scan.GetStringValue()); return 0; } Solid * ParseTerm (CSGScanner & scan) { Solid * sol = ParsePrimary(scan); while (scan.GetToken() == TOK_AND) { scan.ReadNext(); Solid * sol2 = ParsePrimary(scan); sol = new Solid (Solid::SECTION, sol, sol2); } return sol; } Solid * ParseSolid (CSGScanner & scan) { Solid * sol = ParseTerm(scan); while (scan.GetToken() == TOK_OR) { scan.ReadNext(); Solid * sol2 = ParseTerm(scan); sol = new Solid (Solid::UNION, sol, sol2); } return sol; } template void LoadSpline (SplineGeometry & spline, CSGScanner & scan) { double hd; Point x; int nump, numseg; //scan.ReadNext(); scan >> nump >> ';'; hd = 1; spline.geompoints.SetSize(nump); for(int i = 0; i> x(0) >> ',' >> x(1) >> ';'; else if(D==3) scan >> x(0) >> ',' >> x(1) >> ',' >> x(2) >> ';'; spline.geompoints[i] = GeomPoint(x,hd); } scan >> numseg;// >> ';'; spline.splines.SetSize(numseg); int pnums,pnum1,pnum2,pnum3; for(int i = 0; i> ';' >> pnums >> ','; if (pnums == 2) { scan >> pnum1 >> ',' >> pnum2;// >> ';'; spline.splines[i] = new LineSeg(spline.geompoints[pnum1-1], spline.geompoints[pnum2-1]); } else if (pnums == 3) { scan >> pnum1 >> ',' >> pnum2 >> ',' >> pnum3;// >> ';'; spline.splines[i] = new SplineSeg3(spline.geompoints[pnum1-1], spline.geompoints[pnum2-1], spline.geompoints[pnum3-1]); } else if (pnums == 4) { scan >> pnum1 >> ',' >> pnum2 >> ',' >> pnum3;// >> ';'; spline.splines[i] = new CircleSeg(spline.geompoints[pnum1-1], spline.geompoints[pnum2-1], spline.geompoints[pnum3-1]); } } } void ParseFlags (CSGScanner & scan, Flags & flags) { while (scan.GetToken() == '-') { scan.ReadNext(); string name = scan.GetStringValue(); scan.ReadNext(); if (scan.GetToken() == '=') { scan.ReadNext(); if (scan.GetToken() == TOK_STRING) { flags.SetFlag (name.c_str(), scan.GetStringValue().c_str()); scan.ReadNext(); } else if (scan.GetToken() == '[') { scan.ReadNext(); if(scan.GetToken() == '-' || scan.GetToken() == TOK_NUM) { Array vals; vals.Append (ParseNumber(scan)); while (scan.GetToken() == ',') { scan.ReadNext(); vals.Append (ParseNumber(scan)); } ParseChar (scan, ']'); flags.SetFlag (name.c_str(), vals); } else { // string list Array vals; string val = scan.GetStringValue(); vals.Append(new char[val.size()+1]); strcpy(vals.Last(),val.c_str()); scan.ReadNext(); while (scan.GetToken() == ',') { scan.ReadNext(); val = scan.GetStringValue(); vals.Append(new char[val.size()+1]); strcpy(vals.Last(),val.c_str()); scan.ReadNext(); } ParseChar (scan, ']'); flags.SetFlag (name.c_str(), vals); for(int i=0; iGetSolid (name)) scan.Error ("Top-Level-Object "+name+" not defined"); int tlonr = geom->SetTopLevelObject ((Solid*)geom->GetSolid(name)); TopLevelObject * tlo = geom->GetTopLevelObject (tlonr); if (flags.NumListFlagDefined ("col")) { const Array & col = flags.GetNumListFlag ("col"); tlo->SetRGB (col[0], col[1], col[2]); } if (flags.GetDefineFlag ("transparent")) tlo->SetTransparent (1); tlo->SetMaterial (flags.GetStringFlag ("material", "")); tlo->SetLayer (int(flags.GetNumFlag ("layer", 1))); if (flags.NumFlagDefined ("maxh")) tlo->SetMaxH (flags.GetNumFlag("maxh", 1e10)); } else { // a surface TLO string surfname = scan.GetStringValue(); scan.ReadNext(); Flags flags; ParseFlags (scan, flags); ParseChar (scan, ';'); Array si; geom->GetSolid(surfname)->GetSurfaceIndices(si); int tlonr = geom->SetTopLevelObject ((Solid*)geom->GetSolid(name), (Surface*)geom->GetSurface(si.Get(1))); TopLevelObject * tlo = geom->GetTopLevelObject (tlonr); if (flags.NumListFlagDefined ("col")) { const Array & col = flags.GetNumListFlag ("col"); tlo->SetRGB (col.Get(1), col.Get(2), col.Get(3)); } if (flags.GetDefineFlag ("transparent")) tlo->SetTransparent (1); if (flags.NumFlagDefined ("maxh")) tlo->SetMaxH (flags.GetNumFlag("maxh", 1e10)); tlo->SetLayer (int(flags.GetNumFlag ("layer", 1))); tlo->SetBCProp (int(flags.GetNumFlag ("bc", -1))); if ( flags.StringFlagDefined("bcname") ) tlo->SetBCName ( flags.GetStringFlag ("bcname", "default") ); } } else if (scan.GetToken() == TOK_IDENTIFY) { scan.ReadNext(); switch (scan.GetToken()) { case TOK_CLOSESURFACES: { scan.ReadNext(); string name1 = scan.GetStringValue(); scan.ReadNext(); string name2 = scan.GetStringValue(); scan.ReadNext(); Flags flags; ParseFlags (scan, flags); ParseChar (scan, ';'); Array si1, si2; geom->GetSolid(name1)->GetSurfaceIndices(si1); geom->GetSolid(name2)->GetSurfaceIndices(si2); const TopLevelObject * domain = 0; if (flags.StringFlagDefined ("tlo")) { domain = geom->GetTopLevelObject (geom->GetSolid(flags.GetStringFlag ("tlo",""))); if (!domain) scan.Error ("identification needs undefined tlo"); } geom->AddIdentification (new CloseSurfaceIdentification (geom->GetNIdentifications()+1, *geom, geom->GetSurface (si1[0]), geom->GetSurface (si2[0]), domain, flags)); break; } case TOK_PERIODIC: { scan.ReadNext(); string name1 = scan.GetStringValue(); scan.ReadNext(); string name2 = scan.GetStringValue(); scan.ReadNext(); ParseChar (scan, ';'); Array si1, si2; geom->GetSolid(name1)->GetSurfaceIndices(si1); geom->GetSolid(name2)->GetSurfaceIndices(si2); geom->AddIdentification (new PeriodicIdentification (geom->GetNIdentifications()+1, *geom, geom->GetSurface (si1.Get(1)), geom->GetSurface (si2.Get(1)))); break; } default: scan.Error ("keyword 'closesurfaces' or 'periodic' expected"); } } else if (scan.GetToken() == TOK_SINGULAR) { scan.ReadNext(); switch (scan.GetToken()) { case TOK_FACE: { scan.ReadNext(); string name1 = scan.GetStringValue(); // tlo scan.ReadNext(); string name2 = scan.GetStringValue(); scan.ReadNext(); Flags flags; ParseFlags (scan, flags); int factor = int(flags.GetNumFlag("factor",1)); // cout << "Singular Face with factor " << factor << endl; PrintMessageCR (3, "Singular Face with factor ", factor); ParseChar (scan, ';'); const Solid * sol = geom->GetSolid(name2); if(!sol) scan.Error ("unknown solid in singular face definition"); else for (int i = 0; i < geom->GetNTopLevelObjects(); i++) if (name1 == geom->GetTopLevelObject (i)->GetSolid()->Name()) geom->singfaces.Append (new SingularFace (i+1, sol,factor)); break; } case TOK_EDGE: { scan.ReadNext(); string name1 = scan.GetStringValue(); scan.ReadNext(); string name2 = scan.GetStringValue(); scan.ReadNext(); Flags flags; ParseFlags (scan, flags); int factor = int(flags.GetNumFlag("factor",1)); double maxhinit = flags.GetNumFlag("maxh",-1); ParseChar (scan, ';'); const Solid * s1 = geom->GetSolid(name1); const Solid * s2 = geom->GetSolid(name2); PrintMessageCR (3, "Singular Edge with factor ", factor); int domnr = -1; if (flags.StringFlagDefined ("tlo")) { const Solid * sol = geom->GetSolid(flags.GetStringFlag ("tlo","")); for (int i = 0; i < geom->GetNTopLevelObjects(); i++) if (geom->GetTopLevelObject(i)->GetSolid() == sol) domnr = i; // cout << "domnr = " << domnr; } if(!s1 || !s2) scan.Error ("unknown solid ins singular edge definition"); else geom->singedges.Append (new SingularEdge (1, domnr, *geom, s1, s2, factor, maxhinit)); break; } case TOK_POINT: { scan.ReadNext(); string name1 = scan.GetStringValue(); scan.ReadNext(); string name2 = scan.GetStringValue(); scan.ReadNext(); string name3 = scan.GetStringValue(); scan.ReadNext(); Flags flags; ParseFlags (scan, flags); int factor = int(flags.GetNumFlag("factor",1)); ParseChar (scan, ';'); const Solid * s1 = geom->GetSolid(name1); const Solid * s2 = geom->GetSolid(name2); const Solid * s3 = geom->GetSolid(name3); // cout << "Singular Point with factor " << factor << endl; PrintMessageCR (3, "Singular Point with factor ", factor); geom->singpoints.Append (new SingularPoint (1, s1, s2, s3, factor)); break; } default: scan.Error ("keyword 'face' or 'edge' or 'point' expected"); } } else if (scan.GetToken() == TOK_POINT) { Point<3> p; scan.ReadNext(); ParseChar (scan, '('); p = Point<3> (ParseVector (scan)); ParseChar (scan, ')'); Flags flags; ParseFlags (scan, flags); int factor = int(flags.GetNumFlag("factor",0)); ParseChar (scan, ';'); geom->AddUserPoint (p, factor); } else if (scan.GetToken() == TOK_BOUNDINGBOX) { Point<3> p1, p2; scan.ReadNext(); ParseChar (scan, '('); p1 = Point<3> (ParseVector (scan)); ParseChar (scan, ';'); p2 = Point<3> (ParseVector (scan)); ParseChar (scan, ')'); ParseChar (scan, ';'); geom->SetBoundingBox (Box<3> (p1, p2)); } else if (scan.GetToken() == TOK_CURVE2D) { scan.ReadNext(); if (scan.GetToken() != TOK_STRING) scan.Error ("name identifier expected"); string curvename = scan.GetStringValue(); scan.ReadNext(); ParseChar (scan, '='); ParseChar (scan, '('); SplineGeometry<2> * newspline = new SplineGeometry<2>; // newspline->CSGLoad(scan); LoadSpline (*newspline, scan); ParseChar (scan, ')'); ParseChar (scan, ';'); geom->SetSplineCurve(curvename.c_str(),newspline); PrintMessage (4, "define 2d curve ", curvename); } else if (scan.GetToken() == TOK_CURVE3D) { scan.ReadNext(); if (scan.GetToken() != TOK_STRING) scan.Error ("name identifier expected"); string curvename = scan.GetStringValue(); scan.ReadNext(); ParseChar (scan, '='); ParseChar (scan, '('); SplineGeometry<3> * newspline = new SplineGeometry<3>; // newspline->CSGLoad(scan); LoadSpline (*newspline, scan); ParseChar (scan, ')'); ParseChar (scan, ';'); geom->SetSplineCurve(curvename.c_str(),newspline); PrintMessage (4, "define 3d curve ", curvename); } else if (scan.GetToken() == TOK_BOUNDARYCONDITION) { scan.ReadNext(); string name1 = scan.GetStringValue(); scan.ReadNext(); string name2 = scan.GetStringValue(); scan.ReadNext(); int num = int (ParseNumber (scan)); ParseChar (scan, ';'); CSGeometry::BCModification bcm; bcm.bcname = NULL; Array si; geom->GetSolid(name1)->GetSurfaceIndices(si); if(si.Size() == 0) { string errstring = "solid \""; errstring += name1; errstring += "\" has no surfaces"; scan.Error (errstring); } bcm.tlonr = -1; int i; for (i = 0; i < geom->GetNTopLevelObjects(); i++) if (string (geom->GetTopLevelObject(i)->GetSolid()->Name()) == name2) { bcm.tlonr = i; break; } if(bcm.tlonr == -1) { string errstring = "tlo \""; errstring += name2; errstring += "\" not found"; scan.Error(errstring); } bcm.bcnr = num; for (i = 0; i < si.Size(); i++) { bcm.si = si[i]; geom->bcmodifications.Append (bcm); } } else if (scan.GetToken() == TOK_BOUNDARYCONDITIONNAME) { scan.ReadNext(); string name1 = scan.GetStringValue(); scan.ReadNext(); string name2 = scan.GetStringValue(); scan.ReadNext(); string bcname = scan.GetStringValue(); scan.ReadNext(); ParseChar(scan, ';'); CSGeometry::BCModification bcm; bcm.bcname = NULL; Array si; geom->GetSolid(name1)->GetSurfaceIndices(si); if(si.Size() == 0) { string errstring = "solid \""; errstring += name1; errstring += "\" has no surfaces"; scan.Error (errstring); } bcm.tlonr = -1; int i; for (i = 0; i < geom->GetNTopLevelObjects(); i++) if (string (geom->GetTopLevelObject(i)->GetSolid()->Name()) == name2) { bcm.tlonr = i; break; } if(bcm.tlonr == -1) { string errstring = "tlo \""; errstring += name2; errstring += "\" not found"; scan.Error(errstring); } bcm.bcnr = -1; for (i = 0; i < si.Size(); i++) { bcm.si = si[i]; geom->bcmodifications.Append (bcm); geom->bcmodifications.Last().bcname = new string(bcname); } } else if (scan.GetToken() == TOK_DEFINE) { scan.ReadNext(); string name; double val; switch (scan.GetToken()) { case TOK_CONSTANT: scan.ReadNext(); name = scan.GetStringValue(); scan.ReadNext(); ParseChar(scan, '='); val = ParseNumber(scan); if(name == "identprec") geom->SetIdEps(val); break; default: scan.Error ("keyword 'constant' expected"); } } else { cout << "read unidentified token " << scan.GetToken() << " (as char: \"" << char(scan.GetToken()) << "\")" << " string = " << scan.GetStringValue() << endl; scan.ReadNext(); } } } catch (string errstr) { cout << "caught error " << errstr << endl; throw NgException (errstr); } (*testout) << geom->GetNTopLevelObjects() << " TLOs:" << endl; for (int i = 0; i < geom->GetNTopLevelObjects(); i++) { const TopLevelObject * tlo = geom->GetTopLevelObject(i); if (tlo->GetSolid()) (*testout) << i << ": " << *tlo->GetSolid() << endl; } (*testout) << geom->GetNSurf() << " Surfaces" << endl; for (int i = 0; i < geom->GetNSurf(); i++) (*testout) << i << ": " << *geom->GetSurface(i) << endl; return geom; /* do { scan.ReadNext(); if (scan.GetToken() == TOK_STRING) cout << "found string " << scan.GetStringValue() << endl; else cout << "token = " << int(scan.GetToken()) << endl; } while (scan.GetToken() != TOK_END); */ } }; netgen-6.2.1905/libsrc/csg/singularref.cpp0000644000175000017500000001205513504650527017063 0ustar kurtkurt#include #include #include #include #include namespace netgen { SingularEdge :: SingularEdge (double abeta, int adomnr, const CSGeometry & ageom, const Solid * asol1, const Solid * asol2, double sf, const double maxh_at_initialization) : domnr(adomnr), geom(ageom) { beta = abeta; maxhinit = maxh_at_initialization; if (beta > 1) { beta = 1; cout << "Warning: beta set to 1" << endl; } if (beta <= 1e-3) { beta = 1e-3; cout << "Warning: beta set to minimal value 0.001" << endl; } sol1 = asol1; sol2 = asol2; factor = sf; } void SingularEdge :: FindPointsOnEdge (class Mesh & mesh) { (*testout) << "find points on edge" << endl; points.SetSize(0); segms.SetSize(0); Array si1, si2; sol1->GetSurfaceIndices (si1); sol2->GetSurfaceIndices (si2); for (int i = 0; i < si1.Size(); i++) si1[i] = geom.GetSurfaceClassRepresentant(si1[i]); for (int i = 0; i < si2.Size(); i++) si2[i] = geom.GetSurfaceClassRepresentant(si2[i]); for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { INDEX_2 i2 (mesh[si][0], mesh[si][1]); /* bool onedge = 1; for (j = 1; j <= 2; j++) { const Point<3> p = mesh[ PointIndex (i2.I(j)) ]; if (sol1->IsIn (p, 1e-3) && sol2->IsIn(p, 1e-3) && !sol1->IsStrictIn (p, 1e-3) && !sol2->IsStrictIn(p, 1e-3)) { ; } else onedge = 0; } */ if (domnr != -1 && domnr != mesh[si].domin && domnr != mesh[si].domout) continue; /* bool onedge = 1; for (int j = 0; j < 2; j++) { int surfi = (j == 0) ? mesh[si].surfnr1 : mesh[si].surfnr2; surfi = geom.GetSurfaceClassRepresentant(surfi); if (!si1.Contains(surfi) && !si2.Contains(surfi)) onedge = 0; } */ int surfi1 = geom.GetSurfaceClassRepresentant(mesh[si].surfnr1); int surfi2 = geom.GetSurfaceClassRepresentant(mesh[si].surfnr2); if ( (si1.Contains(surfi1) && si2.Contains(surfi2)) || (si1.Contains(surfi2) && si2.Contains(surfi1)) ) // if (onedge) { segms.Append (i2); // PrintMessage (5, "sing segment ", i2.I1(), " - ", i2.I2()); points.Append (mesh[ PointIndex (i2.I1())]); points.Append (mesh[ PointIndex (i2.I2())]); mesh[si].singedge_left = factor; mesh[si].singedge_right = factor; } } /* (*testout) << "Singular edge points:" << endl; for (int i = 0; i < points.Size(); i++) (*testout) << points[i] << endl; */ } void SingularEdge :: SetMeshSize (class Mesh & mesh, double globalh) { double hloc = pow (globalh, 1/beta); if(maxhinit > 0 && maxhinit < hloc) { hloc = maxhinit; if(points.Size() > 1) { for (int i = 0; i < points.Size()-1; i++) mesh.RestrictLocalHLine(points[i],points[i+1],hloc); } else { for (int i = 0; i < points.Size(); i++) mesh.RestrictLocalH (points[i], hloc); } } else { for (int i = 0; i < points.Size(); i++) mesh.RestrictLocalH (points[i], hloc); } } SingularPoint :: SingularPoint (double abeta, const Solid * asol1, const Solid * asol2, const Solid * asol3, double sf) { beta = abeta; sol1 = asol1; sol2 = asol2; sol3 = asol3; factor = sf; } void SingularPoint :: FindPoints (class Mesh & mesh) { points.SetSize(0); Array surfk, surf; for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) { if (mesh[pi].Type() != FIXEDPOINT) continue; const Point<3> p = mesh[pi]; (*testout) << "check singular point" << p << endl; if (sol1->IsIn (p) && sol2->IsIn(p) && sol3->IsIn(p) && !sol1->IsStrictIn (p) && !sol2->IsStrictIn(p) && !sol3->IsStrictIn(p)) { surf.SetSize (0); for (int k = 1; k <= 3; k++) { const Solid * solk(NULL); Solid *tansol; switch (k) { case 1: solk = sol1; break; case 2: solk = sol2; break; case 3: solk = sol3; break; } solk -> TangentialSolid (p, tansol, surfk, 1e-3); (*testout) << "Tansol = " << *tansol << endl; if (!tansol) continue; ReducePrimitiveIterator rpi(Box<3> (p-Vec<3> (1e-3,1e-3,1e-3), p+Vec<3> (1e-3,1e-3,1e-3))); UnReducePrimitiveIterator urpi; tansol -> IterateSolid (rpi); tansol->GetSurfaceIndices (surfk); tansol -> IterateSolid (urpi); (*testout) << "surfinds = " << surfk << endl; for (int i = 0; i < surfk.Size(); i++) if (!surf.Contains (surfk[i])) surf.Append (surfk[i]); delete tansol; } if (surf.Size() < 3) continue; points.Append (p); PrintMessage (5, "Point (", p(0), ", ", p(1), ", ", p(2), ") is singular"); mesh[pi].Singularity(factor); } } } void SingularPoint :: SetMeshSize (class Mesh & mesh, double globalh) { double hloc = pow (globalh, 1/beta); for (int i = 1; i <= points.Size(); i++) mesh.RestrictLocalH (points.Get(i), hloc); } } netgen-6.2.1905/libsrc/csg/singularref.hpp0000644000175000017500000000373213504650527017072 0ustar kurtkurt#ifndef FILE_SINGULARREF #define FILE_SINGULARREF /**************************************************************************/ /* File: singularref.hh */ /* Author: Joachim Schoeberl */ /* Date: 25. Sep. 99 */ /**************************************************************************/ namespace netgen { /** Control for local refinement */ /** Singular Face. Causes a bounday layer mesh refinement. All elements in subdomain domnr will get a boundary layer on faces sharing the solid sol */ class DLL_HEADER SingularFace { public: int domnr; const Solid *sol; double factor; // Array > points; // Array segms; public: SingularFace (int adomnr, const Solid * asol, double sf) : domnr(adomnr), sol(asol), factor(sf) { ; } const Solid * GetSolid() const { return sol; } int GetDomainNr () const { return domnr; } }; /// class DLL_HEADER SingularEdge { public: double beta; int domnr; const CSGeometry& geom; const Solid *sol1, *sol2; Array > points; Array segms; double factor; double maxhinit; public: SingularEdge (double abeta, int adomnr, const CSGeometry & ageom, const Solid * asol1, const Solid * asol2, double sf, const double maxh_at_initialization = -1); void FindPointsOnEdge (class Mesh & mesh); void SetMeshSize (class Mesh & mesh, double globalh); }; /// class DLL_HEADER SingularPoint { public: double beta; const Solid *sol1, *sol2, *sol3; Array > points; double factor; public: SingularPoint (double abeta, const Solid * asol1, const Solid * asol2, const Solid * asol3, double sf); void FindPoints (class Mesh & mesh); void SetMeshSize (class Mesh & mesh, double globalh); }; } #endif netgen-6.2.1905/libsrc/csg/bspline2d.cpp0000644000175000017500000001236413504650527016427 0ustar kurtkurt#include #include namespace netgen { BSplineCurve2d :: BSplineCurve2d () { redlevel = 0; } void BSplineCurve2d :: AddPoint (const Point<2> & apoint) { points.Append (apoint); intervallused.Append (0); } bool BSplineCurve2d :: Inside (const Point<2> & p, double & dist) const { Point<2> hp = p; double t = ProjectParam (p); hp = Eval(t); Vec<2> v = EvalPrime (t); Vec<2> n (v(0), -v(1)); cout << "p = " << p << ", hp = " << hp << endl; dist = Dist (p, hp); double scal = (hp-p) * n; cout << "scal = " << scal << endl; return scal >= 0; } double BSplineCurve2d :: ProjectParam (const Point<2> & p) const { double t, dt, mindist, mint = 0.0; int n1; mindist = 1e10; dt = 0.2; for (n1 = 1; n1 <= points.Size(); n1++) if (intervallused.Get(n1) == 0) for (t = n1; t <= n1+1; t += dt) if (Dist (Eval(t), p) < mindist) { mint = t; mindist = Dist (Eval(t), p); } if (mindist > 1e9) { for (t = 0; t <= points.Size(); t += dt) if (Dist (Eval(t), p) < mindist) { mint = t; mindist = Dist (Eval(t), p); } } while (Dist (Eval (mint-dt), p) < mindist) { mindist = Dist (Eval (mint-dt), p); mint -= dt; } while (Dist (Eval (mint+dt), p) < mindist) { mindist = Dist (Eval (mint+dt), p); mint += dt; } return NumericalProjectParam (p, mint-dt, mint+dt); } // t \in (n1, n2) Point<2> BSplineCurve2d :: Eval (double t) const { int n, n1, n2, n3, n4; double loct, b1, b2, b3, b4; Point<2> hp; static int cnt = 0; cnt++; if (cnt % 100000 == 0) (*mycout) << "cnt = " << cnt << endl; n = int(t); loct = t - n; b1 = 0.25 * (1 - loct) * (1 - loct); b4 = 0.25 * loct * loct; b2 = 0.5 - b4; b3 = 0.5 - b1; n1 = (n + 10 * points.Size() -1) % points.Size() + 1; n2 = n1+1; if (n2 > points.Size()) n2 = 1; n3 = n2+1; if (n3 > points.Size()) n3 = 1; n4 = n3+1; if (n4 > points.Size()) n4 = 1; // (*mycout) << "t = " << t << " n = " << n << " loct = " << loct // << " n1 = " << n1 << endl; hp(0) = b1 * points.Get(n1)(0) + b2 * points.Get(n2)(0) + b3 * points.Get(n3)(0) + b4 * points.Get(n4)(0); hp(1) = b1 * points.Get(n1)(1) + b2 * points.Get(n2)(1) + b3 * points.Get(n3)(1) + b4 * points.Get(n4)(1); return hp; } Vec<2> BSplineCurve2d :: EvalPrime (double t) const { int n, n1, n2, n3, n4; double loct, db1, db2, db3, db4; Vec<2> hv; n = int(t); loct = t - n; db1 = 0.5 * (loct - 1); db4 = 0.5 * loct; db2 = -db4; db3 = -db1; n1 = (n + 10 * points.Size() -1) % points.Size() + 1; n2 = n1+1; if (n2 > points.Size()) n2 = 1; n3 = n2+1; if (n3 > points.Size()) n3 = 1; n4 = n3+1; if (n4 > points.Size()) n4 = 1; hv(0) = db1 * points.Get(n1)(0) + db2 * points.Get(n2)(0) + db3 * points.Get(n3)(0) + db4 * points.Get(n4)(0); hv(1) = db1 * points.Get(n1)(1) + db2 * points.Get(n2)(1) + db3 * points.Get(n3)(1) + db4 * points.Get(n4)(1); return hv; } Vec<2> BSplineCurve2d :: EvalPrimePrime (double t) const { int n, n1, n2, n3, n4; double ddb1, ddb2, ddb3, ddb4; Vec<2> hv; n = int(t); // double loct = t - n; ddb1 = 0.5; ddb4 = 0.5; ddb2 = -0.5; ddb3 = -0.5; n1 = (n + 10 * points.Size() -1) % points.Size() + 1; n2 = n1+1; if (n2 > points.Size()) n2 = 1; n3 = n2+1; if (n3 > points.Size()) n3 = 1; n4 = n3+1; if (n4 > points.Size()) n4 = 1; hv(0) = ddb1 * points.Get(n1)(0) + ddb2 * points.Get(n2)(0) + ddb3 * points.Get(n3)(0) + ddb4 * points.Get(n4)(0); hv(1) = ddb1 * points.Get(n1)(1) + ddb2 * points.Get(n2)(1) + ddb3 * points.Get(n3)(1) + ddb4 * points.Get(n4)(1); return hv; } int BSplineCurve2d :: SectionUsed (double t) const { int n1 = int(t); n1 = (n1 + 10 * points.Size() - 1) % points.Size() + 1; return (intervallused.Get(n1) == 0); } void BSplineCurve2d :: Reduce (const Point<2> & p, double rad) { int n1, n; int j; double minx, miny, maxx, maxy; // (*testout) << "Reduce: " << p << "," << rad << endl; redlevel++; for (n1 = 1; n1 <= points.Size(); n1++) { if (intervallused.Get(n1) != 0) continue; minx = maxx = points.Get(n1)(0); miny = maxy = points.Get(n1)(1); n = n1; for (j = 1; j <= 3; j++) { n++; if (n > points.Size()) n = 1; if (points.Get(n)(0) < minx) minx = points.Get(n)(0); if (points.Get(n)(1) < miny) miny = points.Get(n)(1); if (points.Get(n)(0) > maxx) maxx = points.Get(n)(0); if (points.Get(n)(1) > maxy) maxy = points.Get(n)(1); } if (minx > p(0) + rad || maxx < p(0) - rad || miny > p(1) + rad || maxy < p(1) - rad) { intervallused.Elem(n1) = redlevel; // (*testout) << 0; } else { // (*testout) << 1; intervallused.Elem(n1) = 0; } } // (*testout) << endl; } void BSplineCurve2d :: UnReduce () { int i; for (i = 1; i <= intervallused.Size(); i++) if (intervallused.Get(i) == redlevel) intervallused.Set (i, 0); redlevel--; } void BSplineCurve2d :: Print (ostream & ost) const { ost << "SplineCurve: " << points.Size() << " points." << endl; for (int i = 1; i <= points.Size(); i++) ost << "P" << i << " = " << points.Get(i) << endl; } } netgen-6.2.1905/libsrc/csg/identify.hpp0000644000175000017500000001623013504650527016361 0ustar kurtkurt #ifndef FILE_IDENTIFY #define FILE_IDENTIFY /**************************************************************************/ /* File: identify.hh */ /* Author: Joachim Schoeberl */ /* Date: 1. Aug. 99 */ /**************************************************************************/ namespace netgen { /** Identify surfaces for periodic b.c. or thin domains */ class SpecialPoint; class Identification { protected: const CSGeometry & geom; // identified faces, index sorted INDEX_2_HASHTABLE identfaces; int nr; public: DLL_HEADER Identification (int anr, const CSGeometry & ageom); DLL_HEADER virtual ~Identification (); DLL_HEADER virtual void Print (ostream & ost) const = 0; DLL_HEADER virtual void GetData (ostream & ost) const = 0; /// obsolete // virtual void IdentifySpecialPoints (Array & points); /// can identify both special points (fixed direction) /// (identified points, same tangent) virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const; /// virtual int Identifyable (const Point<3> & p1, const Point<3> & sp2) const; /// is it possible to identify sp1 with some other ? virtual int IdentifyableCandidate (const SpecialPoint & sp1) const; /// are points (if connected) by a short edge (direction anyhow) ? virtual int ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const; /// add entries in mesh identification tables virtual void IdentifyPoints (class Mesh & mesh); /// add entries to identified faces (based on segment infos) virtual void IdentifyFaces (class Mesh & mesh); /// get point on other surface, add entry in mesh identifications virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1); /// copy surfaces, or fill rectangles virtual void BuildSurfaceElements (Array & segs, class Mesh & mesh, const Surface * surf); /// insert volume elements in thin layers virtual void BuildVolumeElements (Array & surfels, class Mesh & mesh); /// get list of identified faces virtual void GetIdentifiedFaces (Array & idfaces) const; friend ostream & operator<< (ostream & ost, Identification & ident); }; class PeriodicIdentification : public Identification { const Surface * s1; const Surface * s2; Transformation<3> trafo; // from s1 to s2 Transformation<3> inv_trafo; // from s2 to s1 public: PeriodicIdentification (int anr, const CSGeometry & ageom, const Surface * as1, const Surface * as2, Transformation<3> atrafo = Vec<3>(0,0,0)); virtual ~PeriodicIdentification () override; virtual void Print (ostream & ost) const override; virtual void GetData (ostream & ost) const override; // virtual void IdentifySpecialPoints (Array & points); virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const override; virtual int Identifyable (const Point<3> & p1, const Point<3> & sp2) const override; virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1) override; virtual void IdentifyPoints (class Mesh & mesh) override; virtual void IdentifyFaces (class Mesh & mesh) override; virtual void BuildSurfaceElements (Array & segs, class Mesh & mesh, const Surface * surf) override; }; /// class TopLevelObject; class CloseSurfaceIdentification : public Identification { const Surface * s1; const Surface * s2; const TopLevelObject * domain; /// int dom_nr; /// number of refinement levels (in Z-refinement) int ref_levels; /// number of refinement levels for layer next to s1 (in Z-refinement) int ref_levels_s1; /// number of refinement levels for layer next to s2 (in Z-refinement) int ref_levels_s2; /// double eps_n; Array slices; /// used only for domain-local identification: Array domain_surfaces; /// bool dom_surf_valid; /// Vec<3> direction; /// bool usedirection; public: CloseSurfaceIdentification (int anr, const CSGeometry & ageom, const Surface * as1, const Surface * as2, const TopLevelObject * adomain, const Flags & flags); virtual ~CloseSurfaceIdentification (); virtual void Print (ostream & ost) const; virtual void GetData (ostream & ost) const; // virtual void IdentifySpecialPoints (Array & points); virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const; virtual int Identifyable (const Point<3> & p1, const Point<3> & sp2) const; virtual int IdentifyableCandidate (const SpecialPoint & sp1) const; virtual int ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const; virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1); const Array & GetSlices () const { return slices; } virtual void IdentifyPoints (class Mesh & mesh); virtual void IdentifyFaces (class Mesh & mesh); virtual void BuildSurfaceElements (Array & segs, class Mesh & mesh, const Surface * surf); void BuildSurfaceElements2 (Array & segs, class Mesh & mesh, const Surface * surf); virtual void BuildVolumeElements (Array & surfels, class Mesh & mesh); int RefLevels () const { return ref_levels; } int RefLevels1 () const { return ref_levels_s1; } int RefLevels2 () const { return ref_levels_s2; } bool IsSkewIdentification(void) const {return usedirection;} const Vec<3> & GetDirection(void) const {return direction;} const Surface & GetSurface1(void) const { return *s1;} const Surface & GetSurface2(void) const { return *s2;} }; class CloseEdgesIdentification : public Identification { const Surface * facet; const Surface * s1; const Surface * s2; public: CloseEdgesIdentification (int anr, const CSGeometry & ageom, const Surface * afacet, const Surface * as1, const Surface * as2); virtual ~CloseEdgesIdentification (); virtual void Print (ostream & ost) const; virtual void GetData (ostream & ost) const; // virtual void IdentifySpecialPoints (Array & points); virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const; virtual void IdentifyPoints (class Mesh & mesh); virtual void BuildSurfaceElements (Array & segs, class Mesh & mesh, const Surface * surf); }; } #endif netgen-6.2.1905/libsrc/csg/csgeom.cpp0000644000175000017500000010737213504650527016026 0ustar kurtkurt#include #include #include #include namespace netgen { int CSGeometry :: changeval = 0; TopLevelObject :: TopLevelObject (Solid * asolid, Surface * asurface) { solid = asolid; surface = asurface; SetRGB (0, 0, 1); SetTransparent (0); SetVisible (1); SetLayer (1); if (!surface) maxh = solid->GetMaxH(); else maxh = surface->GetMaxH(); SetBCProp (-1); bcname = "default"; } void TopLevelObject :: GetData (ostream & ost) { ost << red << " " << green << " " << blue << " " << transp << " " << visible << " "; } void TopLevelObject :: SetData (istream & ist) { ist >> red >> green >> blue >> transp >> visible; } Box<3> CSGeometry::default_boundingbox (Point<3> (-1000, -1000, -1000), Point<3> ( 1000, 1000, 1000)); CSGeometry :: CSGeometry () : boundingbox (default_boundingbox), identicsurfaces (100), ideps(1e-9), filename("") { ; } CSGeometry :: CSGeometry (const string & afilename) : boundingbox (default_boundingbox), identicsurfaces (100), ideps(1e-9), filename(afilename) { changeval++; } CSGeometry :: ~CSGeometry () { Clean(); } void CSGeometry :: Clean () { Array< Solid* > to_delete; for (int i = 0; i < solids.Size(); i++) if(!to_delete.Contains(solids[i]->S1())) to_delete.Append(solids[i]->S1()); for (int i = 0; i < solids.Size(); i++) if(!to_delete.Contains(solids[i])) to_delete.Append(solids[i]); for(int i = 0; i < to_delete.Size(); i++) delete to_delete[i]; solids.DeleteAll (); for (int i = 0; i < splinecurves2d.Size(); i++) delete splinecurves2d[i]; splinecurves2d.DeleteAll(); /* for (int i = 0; i < surfaces.Size(); i++) delete surfaces[i]; surfaces.DeleteAll (); */ for(int i = 0; i & mesh, MeshingParameters & mparam); int CSGeometry :: GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam) { return CSGGenerateMesh (*this, mesh, mparam); } const Refinement & CSGeometry :: GetRefinement () const { // cout << "get CSGeometry - Refinement" << endl; // should become class variables RefinementSurfaces * ref = new RefinementSurfaces(*this); ref -> Set2dOptimizer(new MeshOptimize2dSurfaces(*this)); return *ref; } class WritePrimitivesIt : public SolidIterator { ostream & ost; public: WritePrimitivesIt (ostream & aost) : ost(aost) { ; } virtual ~WritePrimitivesIt () { ; } virtual void Do (Solid * sol); }; void WritePrimitivesIt :: Do (Solid * sol) { Primitive * prim = sol->GetPrimitive(); if (prim) { const char * classname; Array coeffs; prim -> GetPrimitiveData (classname, coeffs); if (sol->Name()) ost << "primitive " << sol->Name() << " " << classname << " " << coeffs.Size(); for (int i = 0; i < coeffs.Size(); i++) ost << " " << coeffs[i]; ost << endl; } } void CSGeometry :: Save (string filename) const { ofstream ost (filename.c_str()); Save (ost); } void CSGeometry :: Save (ostream & ost) const { ost << "boundingbox " << boundingbox.PMin()(0) << " " << boundingbox.PMin()(1) << " " << boundingbox.PMin()(2) << " " << boundingbox.PMax()(0) << " " << boundingbox.PMax()(1) << " " << boundingbox.PMax()(2) << endl; WritePrimitivesIt wpi(ost); IterateAllSolids (wpi, 1); for (int i = 0; i < solids.Size(); i++) { if (!solids[i]->GetPrimitive()) { ost << "solid " << solids.GetName(i) << " "; solids[i] -> GetSolidData (ost); ost << endl; } } for (int i = 0; i < GetNTopLevelObjects(); i++) { TopLevelObject * tlo = GetTopLevelObject (i); ost << "toplevel "; if (tlo -> GetSurface()) ost << "surface " << tlo->GetSolid()->Name() << " " << tlo->GetSurface()->Name() << " "; else ost << "solid " << tlo->GetSolid()->Name() << " "; tlo->GetData(ost); ost << endl; } for (int i = 0; i < identifications.Size(); i++) { ost << "identify "; identifications[i] -> GetData (ost); ost << endl; } ost << "end" << endl; } void CSGeometry :: Load (istream & ist) { // CSGeometry * geo = new CSGeometry; char key[100], name[100], classname[100], sname[100]; int ncoeff, i, j; Array coeff; while (ist.good()) { ist >> key; if (strcmp (key, "boundingbox") == 0) { Point<3> pmin, pmax; ist >> pmin(0) >> pmin(1) >> pmin(2); ist >> pmax(0) >> pmax(1) >> pmax(2); SetBoundingBox (Box<3> (pmin, pmax)); } if (strcmp (key, "primitive") == 0) { ist >> name >> classname >> ncoeff; coeff.SetSize (ncoeff); for (i = 0; i < ncoeff; i++) ist >> coeff[i]; Primitive * nprim = Primitive::CreatePrimitive (classname); nprim -> SetPrimitiveData (coeff); Solid * nsol = new Solid (nprim); for (j = 0; j < nprim->GetNSurfaces(); j++) { sprintf (sname, "%s,%d", name, j); AddSurface (sname, &nprim->GetSurface(j)); nprim -> SetSurfaceId (j, GetNSurf()); } SetSolid (name, nsol); } else if (strcmp (key, "solid") == 0) { ist >> name; Solid * nsol = Solid::CreateSolid (ist, solids); cout << " I have found solid " << name << " = "; nsol -> GetSolidData (cout); cout << endl; SetSolid (name, nsol); } else if (strcmp (key, "toplevel") == 0) { char type[20], solname[50], surfname[50]; const Solid * sol = NULL; const Surface * surf = NULL; int nr; ist >> type; if (strcmp (type, "solid") == 0) { ist >> solname; sol = GetSolid (solname); } if (strcmp (type, "surface") == 0) { ist >> solname >> surfname; sol = GetSolid (solname); surf = GetSurface (surfname); } nr = SetTopLevelObject ((Solid*)sol, (Surface*)surf); GetTopLevelObject (nr) -> SetData (ist); } else if (strcmp (key, "identify") == 0) { char type[10], surfname1[50], surfname2[50]; const Surface * surf1; const Surface * surf2; ist >> type >> surfname1 >> surfname2; surf1 = GetSurface(surfname1); surf2 = GetSurface(surfname2); AddIdentification (new PeriodicIdentification (GetNIdentifications(), *this, surf1, surf2)); } else if (strcmp (key, "end") == 0) break; } changeval++; } void CSGeometry :: DoArchive(Archive& archive) { archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor & identpoints & boundingbox & isidenticto & ideps & filename & spline_surfaces & splinecurves2d & splinecurves3d & surf2prim; if(archive.Input()) FindIdenticSurfaces(1e-6); } void CSGeometry :: SaveSurfaces (ostream & out) const { if(singfaces.Size() > 0 || singedges.Size() > 0 || singpoints.Size() > 0) { PrintMessage(3,"Singular faces/edges/points => no csg-information in .vol file"); return; } Array coeffs; const char * classname; out << "csgsurfaces " << GetNSurf() << "\n"; for(int i=0; i (GetSurface(i)); const ExtrusionFace * ef = dynamic_cast< const ExtrusionFace * > (GetSurface(i)); const RevolutionFace * rf = dynamic_cast< const RevolutionFace * > (GetSurface(i)); const DummySurface * dummyf = dynamic_cast< const DummySurface * > (GetSurface(i)); const SplineSurface * splines = dynamic_cast (GetSurface(i)); if (splines) { splines->GetBase()->GetPrimitiveData(classname,coeffs); out << classname << " " << coeffs.Size() << "\n"; for (int j=0; jGetCuts())) { cut->GetPrimitiveData(classname,coeffs); out << classname << " " << coeffs.Size() << "\n"; for (int j=0; jGetPrimitiveData(classname,coeffs); out << classname << " "; } else if(ef) { out << "extrusionface "; ef->GetRawData(coeffs); } else if(rf) { out << "revolutionface "; rf->GetRawData(coeffs); } else if(dummyf) { out << "dummy "; coeffs.SetSize(0); } else throw NgException ("Cannot write csg surface. Please, contact developers!"); out << coeffs.Size() << "\n"; for(int j=0; j coeffs; string classname; int nsurfaces,size; in >> classname; if(classname == "csgsurfaces") in >> nsurfaces; else nsurfaces = atoi(classname.c_str()); Point<3> dummypoint(0,0,0); Vec<3> dummyvec(0,0,0); double dummydouble(0.1); for(int i=0; i> classname; in >> size; coeffs.SetSize(size); for(int j=0; j> coeffs[j]; if(classname == "plane") { Plane * plane = new Plane(dummypoint,dummyvec); plane->SetPrimitiveData(coeffs); AddSurface(plane); delete_them.Append(plane); } else if(classname == "sphere") { Sphere * sphere = new Sphere(dummypoint,dummydouble); sphere->SetPrimitiveData(coeffs); AddSurface(sphere); delete_them.Append(sphere); } else if(classname == "cylinder") { Cylinder * cylinder = new Cylinder(coeffs); AddSurface(cylinder); delete_them.Append(cylinder); } else if(classname == "ellipticcylinder") { EllipticCylinder * cylinder = new EllipticCylinder(coeffs); AddSurface(cylinder); delete_them.Append(cylinder); } else if(classname == "torus") { Torus * torus = new Torus(dummypoint,dummyvec,dummydouble, dummydouble); torus->SetPrimitiveData(coeffs); AddSurface(torus); delete_them.Append(torus); } else if(classname == "cone") { Cone * cone = new Cone(dummypoint,dummypoint,dummydouble,dummydouble); cone->SetPrimitiveData(coeffs); AddSurface(cone); delete_them.Append(cone); } else if(classname == "ellipticcone") { EllipticCone * ellipticcone = new EllipticCone(dummypoint,dummyvec,dummyvec,dummydouble,dummydouble); ellipticcone->SetPrimitiveData(coeffs); AddSurface(ellipticcone); delete_them.Append(ellipticcone); } else if(classname == "extrusionface") { ExtrusionFace * ef = new ExtrusionFace(coeffs); AddSurface(ef); delete_them.Append(ef); } else if(classname == "revolutionface") { RevolutionFace * rf = new RevolutionFace(coeffs); AddSurface(rf); delete_them.Append(rf); } else if(classname == "dummy") { Surface * surf = new DummySurface(); AddSurface(surf); delete_them.Append(surf); } } } void CSGeometry :: SaveToMeshFile (ostream & ost) const { SaveSurfaces (ost); } void CSGeometry :: AddSurface (Surface * surf) { static int cntsurfs = 0; cntsurfs++; char name[15]; sprintf (name, "nnsurf%d", cntsurfs); AddSurface (name, surf); } void CSGeometry :: AddSurface (char * name, Surface * surf) { (*testout) << "Adding surface " << name << ": " << (*surf) << endl; surfaces.Set (name, surf); surf->SetName (name); changeval++; } void CSGeometry :: AddSurfaces (Primitive * prim) { for (int i = 0; i < prim->GetNSurfaces(); i++) { AddSurface (&prim->GetSurface(i)); prim->SetSurfaceId (i, GetNSurf()-1); surf2prim.Append (prim); } } const Surface * CSGeometry :: GetSurface (const char * name) const { if (surfaces.Used(name)) return surfaces[name]; else return NULL; } /* const Surface * CSGeometry :: GetSurface (int i) const { if (i >= 0 && i < surfaces.Size()) return surfaces[i]; else throw NgException ("CSGeometry::GetSurface out of range"); } */ void CSGeometry :: SetSolid (const char * name, Solid * sol) { Solid * oldsol = NULL; if (solids.Used (name)) oldsol = solids[name]; solids.Set (name, sol); sol->SetName (name); if (oldsol) { if (oldsol->op != Solid::ROOT || sol->op != Solid::ROOT) { cerr << "Setsolid: old or new no root" << endl; } oldsol -> s1 = sol -> s1; } changeval++; } const Solid * CSGeometry :: GetSolid (const char * name) const { if (solids.Used(name)) return solids[name]; else return NULL; } const Solid * CSGeometry :: GetSolid (const string & name) const { if (solids.Used(name)) return solids[name]; else return NULL; } void CSGeometry :: SetSplineCurve (const char * name, SplineGeometry<2> * spl) { splinecurves2d.Set(name,spl); } void CSGeometry :: SetSplineCurve (const char * name, SplineGeometry<3> * spl) { splinecurves3d.Set(name,spl); } const SplineGeometry<2> * CSGeometry :: GetSplineCurve2d (const string & name) const { if (splinecurves2d.Used(name)) return splinecurves2d[name]; else return NULL; } const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const { if (splinecurves3d.Used(name)) return splinecurves3d[name]; else return NULL; } /* class RemoveDummyIterator : public SolidIterator { public: RemoveDummyIterator() { ; } virtual ~RemoveDummyIterator() { ; } virtual void Do(Solid * sol); }; void RemoveDummyIterator :: Do(Solid * sol) { cerr << "remove dummy iterator is obsolete" << endl; if ( (sol->op == Solid::SUB || sol->op == Solid::SECTION || sol->op == Solid::UNION) && sol->s1->op == Solid::DUMMY) sol->s1 = sol->s1->s1; if ( (sol->op == Solid::SECTION || sol->op == Solid::UNION) && sol->s2->op == Solid::DUMMY) sol->s2 = sol->s2->s1; } */ int CSGeometry :: SetTopLevelObject (Solid * sol, Surface * surf) { toplevelobjects.Append (new TopLevelObject (sol, surf)); return toplevelobjects.Size()-1; } TopLevelObject * CSGeometry :: GetTopLevelObject (const Solid * sol, const Surface * surf) { for (int i = 0; i < toplevelobjects.Size(); i++) { if (toplevelobjects[i]->GetSolid() == sol && toplevelobjects[i]->GetSurface() == surf) return (toplevelobjects[i]); } return NULL; } void CSGeometry :: RemoveTopLevelObject (Solid * sol, Surface * surf) { for (int i = 0; i < toplevelobjects.Size(); i++) { if (toplevelobjects[i]->GetSolid() == sol && toplevelobjects[i]->GetSurface() == surf) { delete toplevelobjects[i]; toplevelobjects.DeleteElement (i+1); changeval++; break; } } } void CSGeometry :: AddIdentification (Identification * ident) { identifications.Append (ident); } void CSGeometry :: SetFlags (const char * solidname, const Flags & flags) { Solid * solid = solids[solidname]; Array surfind; int i; double maxh = flags.GetNumFlag ("maxh", -1); if (maxh > 0 && solid) { solid->GetSurfaceIndices (surfind); for (i = 0; i < surfind.Size(); i++) { if (surfaces[surfind[i]]->GetMaxH() > maxh) surfaces[surfind[i]] -> SetMaxH (maxh); } solid->SetMaxH (maxh); } if ( flags.StringFlagDefined ("bcname") ) { solid->GetSurfaceIndices (surfind); string bcn = flags.GetStringFlag("bcname", "default"); for (i = 0; i < surfind.Size(); i++) { if(surfaces[surfind[i]]->GetBCName() == "default") surfaces[surfind[i]]->SetBCName(bcn); } } if (flags.StringListFlagDefined ("bcname")) { const Array & bcname = flags.GetStringListFlag("bcname"); Polyhedra * polyh; if(solid->S1()) polyh = dynamic_cast(solid->S1()->GetPrimitive()); else polyh = dynamic_cast(solid->GetPrimitive()); if(polyh) { Array < Array * > polysurfs; polyh->GetPolySurfs(polysurfs); if(bcname.Size() != polysurfs.Size()) cerr << "WARNING: solid \"" << solidname << "\" has " << polysurfs.Size() << " surfaces and should get " << bcname.Size() << " bc-names!" << endl; for ( i = 0; i < min2(polysurfs.Size(),bcname.Size()); i++) { for (int j = 0; j < polysurfs[i]->Size(); j++) { if(surfaces[(*polysurfs[i])[j]]->GetBCName() == "default") surfaces[(*polysurfs[i])[j]]->SetBCName(bcname[i]); } delete polysurfs[i]; } } else { solid->GetSurfaceIndices (surfind); if(bcname.Size() != surfind.Size()) cerr << "WARNING: solid \"" << solidname << "\" has " << surfind.Size() << " surfaces and should get " << bcname.Size() << " bc-names!" << endl; for (i = 0; i < min2(surfind.Size(),bcname.Size()); i++) { if(surfaces[surfind[i]]->GetBCName() == "default") surfaces[surfind[i]]->SetBCName(bcname[i]); } } } if (flags.NumFlagDefined ("bc")) { solid->GetSurfaceIndices (surfind); int bc = int (flags.GetNumFlag("bc", -1)); for (i = 0; i < surfind.Size(); i++) { if (surfaces[surfind[i]]->GetBCProperty() == -1) surfaces[surfind[i]]->SetBCProperty(bc); } } if (flags.NumListFlagDefined ("bc")) { const Array & bcnum = flags.GetNumListFlag("bc"); Polyhedra * polyh; if(solid->S1()) polyh = dynamic_cast(solid->S1()->GetPrimitive()); else polyh = dynamic_cast(solid->GetPrimitive()); if(polyh) { Array < Array * > polysurfs; polyh->GetPolySurfs(polysurfs); if(bcnum.Size() != polysurfs.Size()) cerr << "WARNING: solid \"" << solidname << "\" has " << polysurfs.Size() << " surfaces and should get " << bcnum.Size() << " bc-numbers!" << endl; for ( i = 0; i < min2(polysurfs.Size(),bcnum.Size()); i++) { for (int j = 0; j < polysurfs[i]->Size(); j++) { if ( surfaces[(*polysurfs[i])[j]]->GetBCProperty() == -1 ) surfaces[(*polysurfs[i])[j]]->SetBCProperty(int(bcnum[i])); } delete polysurfs[i]; } } else { solid->GetSurfaceIndices (surfind); if(bcnum.Size() != surfind.Size()) cerr << "WARNING: solid \"" << solidname << "\" has " << surfind.Size() << " surfaces and should get " << bcnum.Size() << " bc-numbers!" << endl; for (i = 0; i < min2(surfind.Size(),bcnum.Size()); i++) { if (surfaces[surfind[i]]->GetBCProperty() == -1) surfaces[surfind[i]]->SetBCProperty(int(bcnum[i])); } } } } void CSGeometry :: FindIdenticSurfaces (double eps) { int inv; int nsurf = GetNSurf(); isidenticto.SetSize(nsurf); for (int i = 0; i < nsurf; i++) isidenticto[i] = i; for (int i = 0; i < nsurf; i++) for (int j = i+1; j < nsurf; j++) { if (GetSurface(j) -> IsIdentic (*GetSurface(i), inv, eps)) { INDEX_2 i2(i, j); identicsurfaces.Set (i2, inv); isidenticto[j] = isidenticto[i]; } } (*testout) << "identicmap:" << endl; for (int i = 0; i < isidenticto.Size(); i++) (*testout) << i << " -> " << isidenticto[i] << endl; } void CSGeometry :: GetSurfaceIndices (const Solid * sol, const BoxSphere<3> & box, Array & locsurf) const { ReducePrimitiveIterator rpi(box); UnReducePrimitiveIterator urpi; const_cast (sol) -> IterateSolid (rpi); sol -> GetSurfaceIndices (locsurf); const_cast (sol) -> IterateSolid (urpi); for (int i = locsurf.Size()-1; i >= 0; i--) { bool indep = 1; for (int j = 0; j < i; j++) if (locsurf[i] == locsurf[j]) { indep = 0; break; } if (!indep) locsurf.Delete(i); } } void CSGeometry :: GetIndependentSurfaceIndices (const Solid * sol, const BoxSphere<3> & box, Array & locsurf) const { ReducePrimitiveIterator rpi(box); UnReducePrimitiveIterator urpi; ((Solid*)sol) -> IterateSolid (rpi); sol -> GetSurfaceIndices (locsurf); ((Solid*)sol) -> IterateSolid (urpi); for (int i = 0; i < locsurf.Size(); i++) locsurf[i] = isidenticto[locsurf[i]]; for (int i = locsurf.Size()-1; i >= 0; i--) { bool indep = 1; for (int j = 0; j < i; j++) if (locsurf[i] == locsurf[j]) { indep = 0; break; } if (!indep) locsurf.Delete(i); } /* // delete identified for (int i = locsurf.Size()-1; i >= 0; i--) { bool indep = 1; for (int j = 0; j < i; j++) { if (identicsurfaces.Used (INDEX_2::Sort (locsurf[i], locsurf[j])) != (isidenticto[locsurf[i]] == isidenticto[locsurf[j]])) { cerr << "different result" << endl; exit(1); } if (isidenticto[locsurf[i]] == isidenticto[locsurf[j]]) { indep = 0; break; } } if (!indep) locsurf.Delete(i); } for (int i = 0; i < locsurf.Size(); i++) locsurf[i] = isidenticto[locsurf[i]]; */ } /* void CSGeometry :: GetIndependentSurfaceIndices (const Solid * sol, const Point<3> & p, Vec<3> & v, Array & locsurf) const { cout << "very dangerous" << endl; Point<3> p2 = p + 1e-2 * v; BoxSphere<3> box (p2, p2); box.Increase (1e-3); box.CalcDiamCenter(); GetIndependentSurfaceIndices (sol, box, locsurf); } */ void CSGeometry :: GetIndependentSurfaceIndices (Array & locsurf) const { for (int i = 0; i < locsurf.Size(); i++) locsurf[i] = isidenticto[locsurf[i]]; for (int i = locsurf.Size()-1; i >= 0; i--) { bool indep = 1; for (int j = 0; j < i; j++) if (locsurf[i] == locsurf[j]) { indep = 0; break; } if (!indep) locsurf.Delete(i); } } void CSGeometry :: CalcTriangleApproximation(double detail, double facets) { PrintMessage (1, "Calc Triangle Approximation"); try { // FindIdenticSurfaces (1e-6); int ntlo = GetNTopLevelObjects(); for (int i = 0; i < triapprox.Size(); i++) delete triapprox[i]; triapprox.SetSize (ntlo); Array surfind; IndexSet iset(GetNSurf()); for (int i = 0; i < ntlo; i++) { Solid * sol; Surface * surf; GetTopLevelObject (i, sol, surf); sol -> CalcSurfaceInverse (); TriangleApproximation * tams = new TriangleApproximation(); triapprox[i] = tams; // sol -> GetSurfaceIndices (surfind); for (int j = 0; j < GetNSurf(); j++) // for (int jj = 0; jj < surfind.Size(); jj++) { // int j = surfind[jj]; PrintMessageCR (3, "Surface ", j, "/", GetNSurf()); // PrintMessageCR (3, "Surface ", j, "/", surfind.Size()); if (surf && surf != GetSurface(j)) continue; TriangleApproximation tas; GetSurface (j) -> GetTriangleApproximation (tas, boundingbox, facets); int oldnp = tams -> GetNP(); if (!tas.GetNP()) continue; for (int k = 0; k < tas.GetNP(); k++) { tams -> AddPoint (tas.GetPoint(k)); Vec<3> n = GetSurface(j) -> GetNormalVector (tas.GetPoint(k)); n.Normalize(); if (GetSurface(j)->Inverse()) n *= -1; tams -> AddNormal (n); } BoxSphere<3> surfbox; if (tas.GetNP()) surfbox.Set (tas.GetPoint(0)); for (int k = 1; k < tas.GetNP(); k++) surfbox.Add (tas.GetPoint(k)); surfbox.Increase (1e-6); surfbox.CalcDiamCenter(); Solid * surflocsol = sol -> GetReducedSolid (surfbox); if (!surflocsol) continue; for (int k = 0; k < tas.GetNT(); k++) { const TATriangle & tri = tas.GetTriangle (k); // check triangle BoxSphere<3> box; box.Set (tas.GetPoint (tri[0])); box.Add (tas.GetPoint (tri[1])); box.Add (tas.GetPoint (tri[2])); box.Increase (1e-6); box.CalcDiamCenter(); Solid * locsol = surflocsol -> GetReducedSolid (box); if (locsol) { TATriangle tria(j, tri[0] + oldnp, tri[1] + oldnp, tri[2] + oldnp); // tams -> AddTriangle (tria); RefineTriangleApprox (locsol, j, box, detail, tria, *tams, iset, 1); delete locsol; } } } tams->RemoveUnusedPoints (); PrintMessage (2, "Object ", i, " has ", tams->GetNT(), " triangles"); } } catch (exception) { cerr << "*************************************************************" << endl << "**** out of memory problem in CSG visualization ****" << endl << "**** Restart netgen, and disable ****" << endl << "**** 'Draw Geometry' in Geometry -> CSG Options ****" << endl << "**** before loading the geometry ****" << endl << "**** meshing will still work ! ****" << endl << "*************************************************************" << endl; exit(1); } Change(); } void CSGeometry :: RefineTriangleApprox (Solid * locsol, int surfind, const BoxSphere<3> & box, double detail, const TATriangle & tria, TriangleApproximation & tams, IndexSet & iset, int level) { // if (level > 10) return; //tams.AddTriangle (tria); //(*testout) << "tria " << tams.GetPoint(tria[0]) << " - " << tams.GetPoint(tria[1]) << " - " << tams.GetPoint(tria[2]) // << " ( " << tria[0] << " " << tria[1] << " " << tria[2] << ")" < surfused(GetNSurf()); ReducePrimitiveIterator rpi(box); UnReducePrimitiveIterator urpi; locsol -> IterateSolid (rpi); // locsol -> GetSurfaceIndices (lsurfi); // IndexSet iset(GetNSurf()); locsol -> GetSurfaceIndices (iset); const Array & lsurfi = iset.GetArray(); locsol -> IterateSolid (urpi); int surfii = -1; for (int i = 0; i < lsurfi.Size(); i++) if (lsurfi[i] == surfind) { surfii = i; break; } if (surfii == -1) return; int cntindep = 0; for (int i = 0; i < lsurfi.Size(); i++) { int linkto = isidenticto[lsurfi[i]]; surfused[linkto] = 0; } for (int i = 0; i < lsurfi.Size(); i++) { int linkto = isidenticto[lsurfi[i]]; if (!surfused[linkto]) { surfused[linkto] = 1; cntindep++; } } int inverse = surfaces[surfind]->Inverse(); if (cntindep == 1) { tams.AddTriangle (tria); //(*testout) << "pos1 " << tams.GetPoint(tria[0]) << " - " << tams.GetPoint(tria[1]) << " - " << tams.GetPoint(tria[2]) << endl; return; } if (cntindep == 2) { // just 2 surfaces: // if smooth, project inner points to edge and finish int otherind = -1; for (int i = 0; i < lsurfi.Size(); i++) { INDEX_2 i2 (lsurfi[i], surfind); i2.Sort(); if (i != surfii && !identicsurfaces.Used(i2)) otherind = lsurfi[i]; } double kappa = GetSurface(otherind)-> MaxCurvature (); if (kappa * box.Diam() < 0.1) { int pnums[6]; static int between[3][3] = { { 1, 2, 3 }, { 0, 2, 4 }, { 0, 1, 5 } }; int onsurface[3]; for (int j = 0; j < 3; j++) { int pi = tria[j]; pnums[j] = pi; onsurface[j] = !locsol->IsStrictIn (tams.GetPoint (pi), 1e-6) && locsol->IsIn (tams.GetPoint (pi), 1e-6); // /* static int nos=0; if(!onsurface[j]) { nos++; cout << "NOT ON SURFACE!! "<< nos << endl; } */ } for (int j = 0; j < 3; j++) { int lpi1 = between[j][0]; int lpi2 = between[j][1]; int lpin = between[j][2]; if (onsurface[lpi1] == onsurface[lpi2]) pnums[lpin] = -1; else { const Point<3> & p1 = tams.GetPoint (pnums[lpi1]); const Point<3> & p2 = tams.GetPoint (pnums[lpi2]); double f1 = GetSurface(otherind)->CalcFunctionValue (p1); double f2 = GetSurface(otherind)->CalcFunctionValue (p2); Point<3> pn; double l2(100),l1(100); if ( fabs (f1-f2) > 1e-20 ) { l2 = -f1/(f2-f1); l1 = f2/(f2-f1); pn = Point<3>(l1 * p1(0) + l2 * p2(0), l1 * p1(1) + l2 * p2(1), l1 * p1(2) + l2 * p2(2)); } else pn = p1; // if(fabs(pn(0)) > 4 || fabs(pn(1)) > 4 || fabs(pn(2)) > 4) // { // cout << "p1 " << p1 << " p2 " << p2 // << " f1 " << f1 << " f2 " << f2 // << " l1 " << l1 << " l2 " << l2 // << " pn " << pn << endl; // } //GetSurface (surfind)->Project (pn); pnums[lpin] = tams.AddPoint (pn); GetSurface (surfind)->Project (pn); Vec<3> n; n = GetSurface (surfind)->GetNormalVector (pn); if (inverse) n *= -1; tams.AddNormal(n); } } int vcase = 0; if (onsurface[0]) vcase++; if (onsurface[1]) vcase+=2; if (onsurface[2]) vcase+=4; static int trias[8][6] = { { 0, 0, 0, 0, 0, 0 }, { 1, 6, 5, 0, 0, 0 }, { 2, 4, 6, 0, 0, 0 }, { 1, 2, 4, 1, 4, 5 }, { 3, 5, 4, 0, 0, 0 }, { 1, 6, 4, 1, 4, 3 }, { 2, 3, 6, 3, 5, 6 }, { 1, 2, 3, 0, 0, 0 } }; static int ntrias[4] = { 0, 1, 2, 1 }; int nvis = 0; for (int j = 0; j < 3; j++) if (onsurface[j]) nvis++; for (int j = 0; j < ntrias[nvis]; j++) { TATriangle ntria(tria.SurfaceIndex(), pnums[trias[vcase][3*j]-1], pnums[trias[vcase][3*j+1]-1], pnums[trias[vcase][3*j+2]-1]); //(*testout) << "pos2 " << tams.GetPoint(ntria[0]) << " - " << tams.GetPoint(ntria[1]) << " - " << tams.GetPoint(ntria[2]) << endl // << "( " << ntria[0] << " - " << ntria[1] << " - " << ntria[2] << ")" << endl; tams.AddTriangle (ntria); } /* saturn changes: int pvis[3]; for (j = 0; j < 3; j++) pvis[j] = !locsol->IsStrictIn (tams.GetPoint (j+1), 1e-6) && locsol->IsIn (tams.GetPoint (j+1), 1e-6); int newpi[3]; for (j = 0; j < 3; j++) { int pi1 = j; int pi2 = (j+1) % 3; int pic = j; if (pvis[pi1] != pvis[pi2]) { Point<3> hp = Center (tams.GetPoint (tria.PNum (pi1+1)), tams.GetPoint (tria.PNum (pi2+1))); newpi[j] = tams.AddPoint (hp); Vec<3> n = tams.GetNormal (pi1); tams.AddNormal (n); } else newpi[j] = 0; } int nvis = 0; for (j = 0; j <= nvis; j++) if (pvis[j]) nvis++; int si = tria.SurfaceIndex(); switch (nvis) { case 0: break; case 1: { int visj; for (j = 0; j < 3; j++) if (pvis[j]) visj = j; int pivis = tria.PNum (visj+1); int pic1 = newpi[(visj+1)%3]; int pic2 = newpi[(visj+2)%3]; cout << pivis << "," << pic1 << "," << pic2 << endl; tams.AddTriangle (TATriangle (si, pivis, pic1,pic2)); break; } case 2: { int nvisj; for (j = 0; j < 3; j++) if (!pvis[j]) nvisj = j; int pivis1 = tria.PNum ((nvisj+1)%3+1); int pivis2 = tria.PNum ((nvisj+2)%3+1); int pic1 = newpi[nvisj]; int pic2 = newpi[(nvisj+2)%3]; tams.AddTriangle (TATriangle (si, pivis1, pic1,pic2)); tams.AddTriangle (TATriangle (si, pivis1, pic1,pivis2)); break; } case 3: { tams.AddTriangle (tria); break; } } */ return; } } // bisection if (box.Diam() < detail) { //cout << "returning" << endl; return; } for (int i = 0; i < 3; i++) pinds[i] = tria[i]; static int between[3][3] = { { 0, 1, 5 }, { 0, 2, 4 }, { 1, 2, 3 } }; for (int i = 0; i < 3; i++) { // int pi1 = tria[between[i][0]]; Point<3> newp = Center (tams.GetPoint (tria[between[i][0]]), tams.GetPoint (tria[between[i][1]])); Vec<3> n; GetSurface(surfind)->Project (newp); n = GetSurface(surfind)->GetNormalVector (newp); pinds[between[i][2]] = tams.AddPoint (newp); if (inverse) n *= -1; tams.AddNormal (n); } static int trias[4][4] = { { 0, 5, 4 }, { 5, 1, 3 }, { 4, 3, 2 }, { 3, 4, 5 } }; for (int i = 0; i < 4; i++) { TATriangle ntri(surfind, pinds[trias[i][0]], pinds[trias[i][1]], pinds[trias[i][2]]); // check triangle BoxSphere<3> nbox; nbox.Set (tams.GetPoint (ntri[0])); nbox.Add (tams.GetPoint (ntri[1])); nbox.Add (tams.GetPoint (ntri[2])); nbox.Increase (1e-8); nbox.CalcDiamCenter(); Solid * nsol = locsol -> GetReducedSolid (nbox); if (nsol) { RefineTriangleApprox (nsol, surfind, nbox, detail, ntri, tams, iset, level+1); delete nsol; } } } class ClearVisitedIt : public SolidIterator { public: ClearVisitedIt () { ; } virtual ~ClearVisitedIt () { ; } virtual void Do (Solid * sol) { sol -> visited = 0; } }; void CSGeometry :: IterateAllSolids (SolidIterator & it, bool only_once) const { if (only_once) { ClearVisitedIt clit; for (int i = 0; i < solids.Size(); i++) solids[i] -> IterateSolid (clit, 0); } for (int i = 0; i < solids.Size(); i++) solids[i] -> IterateSolid (it, only_once); } double CSGeometry :: MaxSize () const { double maxs, mins; maxs = max3 (boundingbox.PMax()(0), boundingbox.PMax()(1), boundingbox.PMax()(2)); mins = min3 (boundingbox.PMin()(0), boundingbox.PMin()(1), boundingbox.PMin()(2)); return max2 (maxs, -mins) * 1.1; } class CSGeometryRegister : public GeometryRegister { public: virtual NetgenGeometry * Load (string filename) const; virtual NetgenGeometry * LoadFromMeshFile (istream & ist) const; // virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const; }; extern CSGeometry * ParseCSG (istream & istr, CSGeometry *instance=nullptr); NetgenGeometry * CSGeometryRegister :: Load (string filename) const { const char * cfilename = filename.c_str(); if (strcmp (&cfilename[strlen(cfilename)-3], "geo") == 0) { PrintMessage (1, "Load CSG geometry file ", cfilename); ifstream infile(cfilename); CSGeometry * hgeom = ParseCSG (infile); if (!hgeom) throw NgException ("geo-file should start with 'algebraic3d'"); hgeom -> FindIdenticSurfaces(1e-8 * hgeom->MaxSize()); return hgeom; } if (strcmp (&cfilename[strlen(cfilename)-3], "ngg") == 0) { PrintMessage (1, "Load new CSG geometry file ", cfilename); ifstream infile(cfilename); CSGeometry * hgeom = new CSGeometry(""); hgeom -> Load (infile); return hgeom; } return NULL; } NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist) const { string auxstring; if (ist.good()) { ist >> auxstring; if (auxstring == "csgsurfaces") { CSGeometry * geometry = new CSGeometry (""); geometry -> LoadSurfaces(ist); return geometry; } // else // ist.putback (auxstring); } return NULL; } class CSGInit { public: CSGInit() { geometryregister.Append (new CSGeometryRegister); } }; CSGInit csginit; static RegisterClassForArchive regcsg; } netgen-6.2.1905/libsrc/csg/meshsurf.hpp0000644000175000017500000000517413504650527016407 0ustar kurtkurt#ifndef FILE_MESHSURF #define FILE_MESHSURF namespace netgen { /// class Meshing2Surfaces : public Meshing2 { /// const Surface & surface; /// should be movec to base ... const MeshingParameters & mparam; public: /// // Meshing2Surfaces (const Surface & asurf); /// Meshing2Surfaces (const Surface & asurf, const MeshingParameters & mp, const Box<3> & aboundingbox); protected: /// virtual void DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo1, const PointGeomInfo * geominfo2); /// virtual void TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominfo, Point2d & plainpoint, double h, int & zone); /// virtual int TransformFromPlain (Point2d & plainpoint, Point3d & locpoint, PointGeomInfo & gi, double h); /// virtual double CalcLocalH (const Point3d & p, double gh) const; }; /// class MeshOptimize2dSurfaces : public MeshOptimize2d { /// const CSGeometry & geometry; public: /// MeshOptimize2dSurfaces (const CSGeometry & ageometry); /// virtual void ProjectPoint (INDEX surfind, Point<3> & p) const override; /// virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const override; /// virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const override; }; class RefinementSurfaces : public Refinement { const CSGeometry & geometry; public: RefinementSurfaces (const CSGeometry & ageometry); virtual ~RefinementSurfaces (); virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const override; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const override; virtual Vec<3> GetTangent (const Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & ap1) const override; virtual Vec<3> GetNormal (const Point<3> & p, int surfi1, const PointGeomInfo & gi) const override; virtual void ProjectToSurface (Point<3> & p, int surfi) const override; virtual void ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const override; }; } #endif netgen-6.2.1905/libsrc/csg/meshsurf.cpp0000644000175000017500000001175013504650527016377 0ustar kurtkurt#include #include #include namespace netgen { /* Meshing2Surfaces :: Meshing2Surfaces (const Surface & asurface) : surface(asurface) { ; } */ Meshing2Surfaces :: Meshing2Surfaces (const Surface & asurf, const MeshingParameters & mp, const Box<3> & abb) : Meshing2(mp, abb), surface(asurf), mparam (mp) { ; } void Meshing2Surfaces :: DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo1, const PointGeomInfo * geominfo2) { ((Surface&)surface).DefineTangentialPlane (p1, p2); } void Meshing2Surfaces :: TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominfo, Point2d & planepoint, double h, int & zone) { Point<2> hp; surface.ToPlane (locpoint, hp, h, zone); planepoint.X() = hp(0); planepoint.Y() = hp(1); } int Meshing2Surfaces :: TransformFromPlain (Point2d & planepoint, Point3d & locpoint, PointGeomInfo & gi, double h) { Point<3> hp; Point<2> hp2 (planepoint.X(), planepoint.Y()); surface.FromPlane (hp2, hp, h); locpoint = hp; gi.trignum = 1; return 0; } double Meshing2Surfaces :: CalcLocalH (const Point3d & p, double gh) const { return surface.LocH (p, 3, 1, mparam, gh); /* double loch = mesh.lochfunc->GetH(p); if (gh < loch) loch = gh; return loch; */ } MeshOptimize2dSurfaces :: MeshOptimize2dSurfaces (const CSGeometry & ageometry) : MeshOptimize2d(), geometry(ageometry) { ; } void MeshOptimize2dSurfaces :: ProjectPoint (INDEX surfind, Point<3> & p) const { Point<3> hp = p; geometry.GetSurface(surfind)->Project (hp); p = hp; } void MeshOptimize2dSurfaces :: ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const { Point<3> hp = p; ProjectToEdge ( geometry.GetSurface(surfind), geometry.GetSurface(surfind2), hp); p = hp; } void MeshOptimize2dSurfaces :: GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const { Vec<3> hn = n; geometry.GetSurface(surfind)->CalcGradient (p, hn); hn.Normalize(); n = hn; /* if (geometry.GetSurface(surfind)->Inverse()) n *= -1; */ } RefinementSurfaces :: RefinementSurfaces (const CSGeometry & ageometry) : Refinement(), geometry(ageometry) { if(geometry.GetNSurf() == 0) *testout << endl << "WARNING: Initializing 2D refinement with 0-surface geometry" << endl << "==========================================================" << endl << endl << endl; } RefinementSurfaces :: ~RefinementSurfaces () { ; } void RefinementSurfaces :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const { Point<3> hnewp; hnewp = p1+secpoint*(p2-p1); if (surfi != -1) { geometry.GetSurface (surfi) -> Project (hnewp); newgi.trignum = 1; } newp = hnewp; } void RefinementSurfaces :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const { Point<3> hnewp = p1+secpoint*(p2-p1); //(*testout) << "hnewp " << hnewp << " s1 " << surfi1 << " s2 " << surfi2 << endl; if (surfi1 != -1 && surfi2 != -1 && surfi1 != surfi2) { netgen::ProjectToEdge (geometry.GetSurface(surfi1), geometry.GetSurface(surfi2), hnewp); // (*testout) << "Pointbetween, newp = " << hnewp << endl // << ", err = " << sqrt (sqr (hnewp(0))+ sqr(hnewp(1)) + sqr (hnewp(2))) - 1 << endl; newgi.edgenr = 1; //(*testout) << "hnewp (a1) " << hnewp << endl; } else if (surfi1 != -1) { geometry.GetSurface (surfi1) -> Project (hnewp); //(*testout) << "hnewp (a2) " << hnewp << endl; } newp = hnewp; }; Vec<3> RefinementSurfaces :: GetTangent (const Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & ap1) const { Vec<3> n1 = geometry.GetSurface (surfi1)->GetNormalVector (p); Vec<3> n2 = geometry.GetSurface (surfi2)->GetNormalVector (p); Vec<3> tau = Cross (n1, n2).Normalize(); return tau; } Vec<3> RefinementSurfaces :: GetNormal (const Point<3> & p, int surfi1, const PointGeomInfo & gi) const { return geometry.GetSurface (surfi1)->GetNormalVector (p); } void RefinementSurfaces :: ProjectToSurface (Point<3> & p, int surfi) const { if (surfi != -1) geometry.GetSurface (surfi) -> Project (p); }; void RefinementSurfaces :: ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const { netgen::ProjectToEdge (geometry.GetSurface(surfi1), geometry.GetSurface(surfi2), p); } } netgen-6.2.1905/libsrc/csg/specpoin.hpp0000644000175000017500000001103413504650527016363 0ustar kurtkurt#ifndef FILE_SPECPOIN #define FILE_SPECPOIN /**************************************************************************/ /* File: specpoin.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Okt. 95 */ /**************************************************************************/ namespace netgen { // extern DLL_HEADER MeshingParameters mparam; /* Special Point Calculation */ class Surface; class Solid; /// Special point. class SpecialPoint { public: /// coordinates Point<3> p; /// tangential to edge Vec<3> v; /// int layer; /// point must be used in mesh bool unconditional; /// surfaces defining edge int s1, s2; /// if s1 and s2 are only representatives, then these are the original indices int s1_orig, s2_orig; int nr; /// SpecialPoint () : p(0,0,0), v(0,0,0), layer(0), unconditional(0), s1(0), s2(0), s1_orig(0), s2_orig(0) { ; } /// SpecialPoint (const SpecialPoint & sp2); /// SpecialPoint & operator= (const SpecialPoint & sp2); /// void Print (ostream & str) const; int GetLayer() const { return layer; } /// bool HasSurfaces (int as1, int as2) const { return ( (s1 == as1 && s2 == as2) || (s1 == as2 && s2 == as1) ); } }; inline ostream & operator<< (ostream & ost, const SpecialPoint & sp) { sp.Print (ost); return ost; } /// class SpecialPointCalculation { private: /// const CSGeometry * geometry; /// Array * points; /// Array boxesinlevel; /// double size; /// double relydegtest; // maximal dimension of bisection intervall for /// test of degeneration parameters double cpeps1, epeps1, epeps2, epspointdist2; double ideps; public: /// SpecialPointCalculation (); /// void SetIdEps(const double epsin) {ideps = epsin;} /// void CalcSpecialPoints (const CSGeometry & ageometry, Array & points); /// void AnalyzeSpecialPoints (const CSGeometry & geometry, Array & points, Array & specpoints); protected: /// void CalcSpecialPointsRec (const Solid * sol, int layer, const BoxSphere<3> & box, int level, bool calccp, bool calcep); /// bool CrossPointNewtonConvergence (const Surface * f1, const Surface * f2, const Surface * f3, const BoxSphere<3> & box); /// bool CrossPointDegenerated (const Surface * f1, const Surface * f2, const Surface * f3, const BoxSphere<3> & box) const; /// void CrossPointNewton (const Surface * f1, const Surface * f2, const Surface * f3, Point<3> & p); bool EdgeNewtonConvergence (const Surface * f1, const Surface * f2, const Point<3> & p); /// bool EdgeDegenerated (const Surface * f1, const Surface * f2, const BoxSphere<3> & box) const; /// void EdgeNewton (const Surface * f1, const Surface * f2, Point<3> & p); /// bool IsEdgeExtremalPoint (const Surface * f1, const Surface * f2, const Point<3> & p, Point<3> & pp, double rad); /* /// bool ExtremalPointPossible (const Surface * f1, const Surface * f2, int dir, const BoxSphere<3> & box); /// bool ExtremalPointDegenerated (const Surface * f1, const Surface * f2, int dir, const BoxSphere<3> & box); /// bool ExtremalPointNewtonConvergence (const Surface * f1, const Surface * f2, int dir, const BoxSphere<3> & box); */ /// void ExtremalPointNewton (const Surface * f1, const Surface * f2, int dir, Point<3> & p); /// bool AddPoint (const Point<3> & p, int layer); void ComputeExtremalPoints (const Plane * plane, const QuadraticSurface * quadric, Array > & pts); void ComputeExtremalPoints (const Sphere * sphere1, const Sphere * sphere2, Array > & pts); void ComputeCrossPoints (const Plane * plane1, const Plane * plane2, const Plane * plane3, Array > & pts); void ComputeCrossPoints (const Plane * plane1, const Plane * plane2, const QuadraticSurface * quadratic, Array > & pts); void ComputeCrossPoints (const Sphere * sphere1, const Sphere * sphere2, const Sphere * sphere3, Array > & pts); }; } #endif netgen-6.2.1905/libsrc/csg/zrefine.cpp0000644000175000017500000004053313504650527016206 0ustar kurtkurt#include #include "meshing.hpp" #include namespace netgen { // find singular edges void SelectSingularEdges (const Mesh & mesh, const CSGeometry & geom, INDEX_2_HASHTABLE & singedges, ZRefinementOptions & opt) { // edges selected in csg input file for (int i = 1; i <= geom.singedges.Size(); i++) { //if(geom.singedges.Get(i)->maxhinit > 0) // continue; //!!!! const SingularEdge & se = *geom.singedges.Get(i); for (int j = 1; j <= se.segms.Size(); j++) { INDEX_2 i2 = se.segms.Get(j); singedges.Set (i2, 1); } } // edges interactively selected for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); if (seg.singedge_left || seg.singedge_right) { INDEX_2 i2(seg[0], seg[1]); i2.Sort(); singedges.Set (i2, 1); } } } /** Convert elements (vol-tets, surf-trigs) into prisms/quads */ void MakePrismsSingEdge (Mesh & mesh, INDEX_2_HASHTABLE & singedges) { // volume elements for (int i = 1; i <= mesh.GetNE(); i++) { Element & el = mesh.VolumeElement(i); if (el.GetType() != TET) continue; for (int j = 1; j <= 3; j++) for (int k = j+1; k <= 4; k++) { INDEX_2 edge(el.PNum(j), el.PNum(k)); edge.Sort(); if (singedges.Used (edge)) { int pi3 = 1, pi4 = 1; while (pi3 == j || pi3 == k) pi3++; pi4 = 10 - j - k - pi3; int p3 = el.PNum(pi3); int p4 = el.PNum(pi4); el.SetType(PRISM); el.PNum(1) = edge.I1(); el.PNum(2) = p3; el.PNum(3) = p4; el.PNum(4) = edge.I2(); el.PNum(5) = p3; el.PNum(6) = p4; } } } // surface elements for (int i = 1; i <= mesh.GetNSE(); i++) { Element2d & el = mesh.SurfaceElement(i); if (el.GetType() != TRIG) continue; for (int j = 1; j <= 3; j++) { int k = (j % 3) + 1; INDEX_2 edge(el.PNum(j), el.PNum(k)); edge.Sort(); if (singedges.Used (edge)) { int pi3 = 6-j-k; int p3 = el.PNum(pi3); int p1 = el.PNum(j); int p2 = el.PNum(k); el.SetType(QUAD); el.PNum(1) = p2; el.PNum(2) = p3; el.PNum(3) = p3; el.PNum(4) = p1; } } } } /* Convert tets and pyramids next to close (identified) points into prisms */ void MakePrismsClosePoints (Mesh & mesh) { int i, j, k; for (i = 1; i <= mesh.GetNE(); i++) { Element & el = mesh.VolumeElement(i); if (el.GetType() == TET) { for (j = 1; j <= 3; j++) for (k = j+1; k <= 4; k++) { INDEX_2 edge(el.PNum(j), el.PNum(k)); edge.Sort(); if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k))) { int pi3 = 1, pi4 = 1; while (pi3 == j || pi3 == k) pi3++; pi4 = 10 - j - k - pi3; int p3 = el.PNum(pi3); int p4 = el.PNum(pi4); el.SetType(PRISM); el.PNum(1) = edge.I1(); el.PNum(2) = p3; el.PNum(3) = p4; el.PNum(4) = edge.I2(); el.PNum(5) = p3; el.PNum(6) = p4; } } } if (el.GetType() == PYRAMID) { // pyramid, base face = 1,2,3,4 for (j = 0; j <= 1; j++) { PointIndex pi1 = el.PNum( (j+0) % 4 + 1); PointIndex pi2 = el.PNum( (j+1) % 4 + 1); PointIndex pi3 = el.PNum( (j+2) % 4 + 1); PointIndex pi4 = el.PNum( (j+3) % 4 + 1); PointIndex pi5 = el.PNum(5); INDEX_2 edge1(pi1, pi4); INDEX_2 edge2(pi2, pi3); edge1.Sort(); edge2.Sort(); if (mesh.GetIdentifications().GetSymmetric (pi1, pi4) && mesh.GetIdentifications().GetSymmetric (pi2, pi3)) { //int p3 = el.PNum(pi3); //int p4 = el.PNum(pi4); el.SetType(PRISM); el.PNum(1) = pi1; el.PNum(2) = pi2; el.PNum(3) = pi5; el.PNum(4) = pi4; el.PNum(5) = pi3; el.PNum(6) = pi5; } } } } for (i = 1; i <= mesh.GetNSE(); i++) { Element2d & el = mesh.SurfaceElement(i); if (el.GetType() != TRIG) continue; for (j = 1; j <= 3; j++) { k = (j % 3) + 1; INDEX_2 edge(el.PNum(j), el.PNum(k)); edge.Sort(); if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k))) { int pi3 = 6-j-k; int p3 = el.PNum(pi3); int p1 = el.PNum(j); int p2 = el.PNum(k); el.SetType(QUAD); el.PNum(1) = p2; el.PNum(2) = p3; el.PNum(3) = p3; el.PNum(4) = p1; } } } } #ifdef OLD void MakeCornerNodes (Mesh & mesh, INDEX_HASHTABLE & cornernodes) { int i, j; int nseg = mesh.GetNSeg(); Array edgesonpoint(mesh.GetNP()); for (i = 1; i <= mesh.GetNP(); i++) edgesonpoint.Elem(i) = 0; for (i = 1; i <= nseg; i++) { for (j = 1; j <= 2; j++) { int pi = (j == 1) ? mesh.LineSegment(i)[0] : mesh.LineSegment(i)[1]; edgesonpoint.Elem(pi)++; } } /* cout << "cornernodes: "; for (i = 1; i <= edgesonpoint.Size(); i++) if (edgesonpoint.Get(i) >= 6) { cornernodes.Set (i, 1); cout << i << " "; } cout << endl; */ // cornernodes.Set (5, 1); } #endif void RefinePrisms (Mesh & mesh, const CSGeometry * geom, ZRefinementOptions & opt) { int i, j; bool found, change; int cnt = 0; // markers for z-refinement: p1, p2, levels // p1-p2 is an edge to be refined Array ref_uniform; Array ref_singular; Array ref_slices; BitArray first_id(geom->identifications.Size()); first_id.Set(); // if (mesh.GetIdentifications().HasIdentifiedPoints()) { INDEX_2_HASHTABLE & identpts = mesh.GetIdentifications().GetIdentifiedPoints (); for (i = 1; i <= identpts.GetNBags(); i++) for (j = 1; j <= identpts.GetBagSize(i); j++) { INDEX_2 pair; int idnr; identpts.GetData(i, j, pair, idnr); const CloseSurfaceIdentification * csid = dynamic_cast (geom->identifications.Get(idnr)); if (csid) { if (!csid->GetSlices().Size()) { if (first_id.Test (idnr)) { first_id.Clear(idnr); ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels())); ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1())); ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2())); } } else { //const Array & slices = csid->GetSlices(); INDEX_4 i4; i4[0] = pair.I1(); i4[1] = pair.I2(); i4[2] = idnr; i4[3] = csid->GetSlices().Size(); ref_slices.Append (i4); } } } } Array epgi; while (1) { cnt++; PrintMessage (3, "Z-Refinement, level = ", cnt); INDEX_2_HASHTABLE refedges(mesh.GetNSE()+1); found = 0; // mark prisms due to close surface flags: int oldsize = ref_uniform.Size(); for (i = 1; i <= oldsize; i++) { int pi1 = ref_uniform.Get(i).I1(); int pi2 = ref_uniform.Get(i).I2(); int levels = ref_uniform.Get(i).I3(); if (levels > 0) { const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); int npi(0); INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } ref_uniform.Elem(i) = INDEX_3(pi1, npi, levels-1); ref_uniform.Append (INDEX_3(pi2, npi, levels-1)); } } for (i = 1; i <= ref_singular.Size(); i++) { int pi1 = ref_singular.Get(i).I1(); int pi2 = ref_singular.Get(i).I2(); int levels = ref_singular.Get(i).I3(); if (levels > 0) { const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); int npi; INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } else npi = refedges.Get (edge); ref_singular.Elem(i) = INDEX_3(pi1, npi, levels-1); } } for (i = 1; i <= ref_slices.Size(); i++) { int pi1 = ref_slices.Get(i)[0]; int pi2 = ref_slices.Get(i)[1]; int idnr = ref_slices.Get(i)[2]; int slicenr = ref_slices.Get(i)[3]; if (slicenr > 0) { const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); int npi; const CloseSurfaceIdentification * csid = dynamic_cast (geom->identifications.Get(idnr)); INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { const Array & slices = csid->GetSlices(); //(*testout) << "idnr " << idnr << " i " << i << endl; //(*testout) << "slices " << slices << endl; double slicefac = slices.Get(slicenr); double slicefaclast = (slicenr == slices.Size()) ? 1 : slices.Get(slicenr+1); Point3d np = p1 + (slicefac / slicefaclast) * (p2-p1); //(*testout) << "slicenr " << slicenr << " slicefac " << slicefac << " quot " << (slicefac / slicefaclast) << " np " << np << endl; npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } else npi = refedges.Get (edge); ref_slices.Elem(i)[1] = npi; ref_slices.Elem(i)[3] --; } } for (i = 1; i <= mesh.GetNE(); i++) { Element & el = mesh.VolumeElement (i); if (el.GetType() != PRISM) continue; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); bool ref = 0; /* if (Dist (p1, p2) > mesh.GetH (Center (p1, p2))) ref = 1; */ /* if (cnt <= opt.minref) ref = 1; */ /* if ((pi1 == 460 || pi2 == 460 || pi1 == 461 || pi2 == 461) && cnt <= 8) ref = 1; */ if (ref == 1) { INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); int npi = mesh.AddPoint (np); refedges.Set (edge, npi); found = 1; } } } } if (!found) break; // build closure: PrintMessage (5, "start closure"); do { PrintMessage (5, "start loop"); change = 0; for (i = 1; i <= mesh.GetNE(); i++) { Element & el = mesh.VolumeElement (i); if (el.GetType() != PRISM) continue; bool hasref = 0, hasnonref = 0; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); if (pi1 != pi2) { INDEX_2 edge(pi1, pi2); edge.Sort(); if (refedges.Used(edge)) hasref = 1; else hasnonref = 1; } } if (hasref && hasnonref) { // cout << "el " << i << " in closure" << endl; change = 1; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); const Point3d & p1 = mesh.Point(pi1); const Point3d & p2 = mesh.Point(pi2); INDEX_2 edge(pi1, pi2); edge.Sort(); if (!refedges.Used(edge)) { Point3d np = Center (p1, p2); int npi = mesh.AddPoint (np); refedges.Set (edge, npi); } } } } } while (change); PrintMessage (5, "Do segments"); // (*testout) << "closure formed, np = " << mesh.GetNP() << endl; int oldns = mesh.GetNSeg(); for (i = 1; i <= oldns; i++) { const Segment & el = mesh.LineSegment(i); INDEX_2 i2(el[0], el[1]); i2.Sort(); int pnew; EdgePointGeomInfo ngi; if (refedges.Used(i2)) { pnew = refedges.Get(i2); // ngi = epgi.Get(pnew); } else { continue; // Point3d pb; // /* // geom->PointBetween (mesh.Point (el[0]), // mesh.Point (el[1]), // el.surfnr1, el.surfnr2, // el.epgeominfo[0], el.epgeominfo[1], // pb, ngi); // */ // pb = Center (mesh.Point (el[0]), mesh.Point (el[1])); // pnew = mesh.AddPoint (pb); // refedges.Set (i2, pnew); // if (pnew > epgi.Size()) // epgi.SetSize (pnew); // epgi.Elem(pnew) = ngi; } Segment ns1 = el; Segment ns2 = el; ns1[1] = pnew; ns1.epgeominfo[1] = ngi; ns2[0] = pnew; ns2.epgeominfo[0] = ngi; mesh.LineSegment(i) = ns1; mesh.AddSegment (ns2); } PrintMessage (5, "Segments done, NSeg = ", mesh.GetNSeg()); // do refinement int oldne = mesh.GetNE(); for (i = 1; i <= oldne; i++) { Element & el = mesh.VolumeElement (i); if (el.GetNP() != 6) continue; int npi[3]; for (j = 1; j <= 3; j++) { int pi1 = el.PNum(j); int pi2 = el.PNum(j+3); if (pi1 == pi2) npi[j-1] = pi1; else { INDEX_2 edge(pi1, pi2); edge.Sort(); if (refedges.Used (edge)) npi[j-1] = refedges.Get(edge); else { /* (*testout) << "ERROR: prism " << i << " has hanging node !!" << ", edge = " << edge << endl; cerr << "ERROR: prism " << i << " has hanging node !!" << endl; */ npi[j-1] = 0; } } } if (npi[0]) { Element nel1(6), nel2(6); for (j = 1; j <= 3; j++) { nel1.PNum(j) = el.PNum(j); nel1.PNum(j+3) = npi[j-1]; nel2.PNum(j) = npi[j-1]; nel2.PNum(j+3) = el.PNum(j+3); } nel1.SetIndex (el.GetIndex()); nel2.SetIndex (el.GetIndex()); mesh.VolumeElement (i) = nel1; mesh.AddVolumeElement (nel2); } } PrintMessage (5, "Elements done, NE = ", mesh.GetNE()); // do surface elements int oldnse = mesh.GetNSE(); // cout << "oldnse = " << oldnse << endl; for (i = 1; i <= oldnse; i++) { Element2d & el = mesh.SurfaceElement (i); if (el.GetType() != QUAD) continue; int index = el.GetIndex(); int npi[2]; for (j = 1; j <= 2; j++) { int pi1, pi2; if (j == 1) { pi1 = el.PNum(1); pi2 = el.PNum(4); } else { pi1 = el.PNum(2); pi2 = el.PNum(3); } if (pi1 == pi2) npi[j-1] = pi1; else { INDEX_2 edge(pi1, pi2); edge.Sort(); if (refedges.Used (edge)) npi[j-1] = refedges.Get(edge); else { npi[j-1] = 0; } } } if (npi[0]) { Element2d nel1(QUAD), nel2(QUAD); for (j = 1; j <= 4; j++) { nel1.PNum(j) = el.PNum(j); nel2.PNum(j) = el.PNum(j); } nel1.PNum(3) = npi[1]; nel1.PNum(4) = npi[0]; nel2.PNum(1) = npi[0]; nel2.PNum(2) = npi[1]; /* for (j = 1; j <= 2; j++) { nel1.PNum(j) = el.PNum(j); nel1.PNum(j+2) = npi[j-1]; nel2.PNum(j) = npi[j-1]; nel2.PNum(j+2) = el.PNum(j+2); } */ nel1.SetIndex (el.GetIndex()); nel2.SetIndex (el.GetIndex()); mesh.SurfaceElement (i) = nel1; mesh.AddSurfaceElement (nel2); int si = mesh.GetFaceDescriptor (index).SurfNr(); Point<3> hp = mesh.Point(npi[0]); geom->GetSurface(si)->Project (hp); mesh.Point (npi[0]).SetPoint (hp); hp = mesh.Point(npi[1]); geom->GetSurface(si)->Project (hp); mesh.Point (npi[1]).SetPoint (hp); // geom->GetSurface(si)->Project (mesh.Point(npi[0])); // geom->GetSurface(si)->Project (mesh.Point(npi[1])); } } mesh.RebuildSurfaceElementLists(); PrintMessage (5, "Surface elements done, NSE = ", mesh.GetNSE()); } } void CombineSingularPrisms(Mesh& mesh) { for(int i = 1; i<=mesh.GetNE(); i++) { Element& el = mesh.VolumeElement(i); if(el.GetType() != PRISM) continue; if(el.PNum(3) == el.PNum(6)) { if(el.PNum(2) == el.PNum(5)) { el.SetType(TET); } else { el.SetType(PYRAMID); int pnr5 = el.PNum(3); el.PNum(3) = el.PNum(5); el.PNum(5) = pnr5; } } } } void ZRefinement (Mesh & mesh, const NetgenGeometry * hgeom, ZRefinementOptions & opt) { const CSGeometry * geom = dynamic_cast (hgeom); if (!geom) return; INDEX_2_HASHTABLE singedges(mesh.GetNSeg()); SelectSingularEdges (mesh, *geom, singedges, opt); //MakePrismsSingEdge (mesh, singedges); MakePrismsClosePoints (mesh); RefinePrisms (mesh, geom, opt); CombineSingularPrisms(mesh); } ZRefinementOptions :: ZRefinementOptions() { minref = 0; } } netgen-6.2.1905/libsrc/csg/revolution.hpp0000644000175000017500000001041513504650527016753 0ustar kurtkurt#ifndef _REVOLUTION_HPP #define _REVOLUTION_HPP namespace netgen { class Revolution; class RevolutionFace : public Surface { private: bool isfirst, islast; const SplineSeg<2> * spline; bool deletable; Point<3> p0; Vec<3> v_axis; int id; // coefficient for implicizt polynomial mutable Vector spline_coefficient; mutable Vector spline_coefficient_shifted; Array < Vec<2>* > checklines_vec; Array < Point<2>* > checklines_start; Array < Vec<2>* > checklines_normal; private: void Init (void); public: void CalcProj(const Point<3> & point3d, Point<2> & point2d) const; void CalcProj(const Point<3> & point3d, Point<2> & point2d, const Vec<3> & vector3d, Vec<2> & vector2d) const; void CalcProj0(const Vec<3> & point3d_minus_p0, Point<2> & point2d) const; public: RevolutionFace(const SplineSeg<2> & spline_in, const Point<3> & p, const Vec<3> & vec, bool first = false, bool last = false, const int id_in = 0); RevolutionFace(const Array & raw_data); // default constructor for archive RevolutionFace() {} ~RevolutionFace(); virtual void DoArchive(Archive& ar) { Surface::DoArchive(ar); ar & isfirst & islast & spline & deletable & p0 & v_axis & id & spline_coefficient & spline_coefficient_shifted & checklines_vec & checklines_start & checklines_normal; } virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; virtual double CalcFunctionValue (const Point<3> & point) const; virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; virtual double HesseNorm () const; virtual double MaxCurvature () const; //virtual double MaxCurvatureLoc (const Point<3> & /* c */ , // double /* rad */) const; virtual void Project (Point<3> & p) const; virtual Point<3> GetSurfacePoint () const; virtual void Print (ostream & str) const; virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const; bool BoxIntersectsFace (const Box<3> & box) const; /* bool BoxIntersectsFace (const BoxSphere<2> & box, bool & uncertain) const; bool BoxIntersectsFace (const BoxSphere<3> & box, bool & uncertain) const; */ const SplineSeg<2> & GetSpline(void) const {return *spline;} /* INSOLID_TYPE */ bool PointInFace (const Point<3> & p, const double eps) const; void GetRawData(Array & data) const; }; /* Primitive of revolution */ class Revolution : public Primitive { private: Point<3> p0,p1; Vec<3> v_axis; // 1 ... torus-like // 2 ... sphere-like int type; Array faces; mutable int intersecting_face; public: Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in); // default constructor for archive Revolution() {} ~Revolution(); virtual void DoArchive(Archive& ar) { Primitive::DoArchive(ar); ar & p0 & p1 & v_axis & type & faces & intersecting_face; } /* Check, whether box intersects solid defined by surface. return values: 0 .. box outside solid \\ 1 .. box in solid \\ 2 .. can't decide (allowed, iff box is close to solid) */ virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; virtual void GetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const; // checks if lim s->0 lim t->0 p + t(v1 + s v2) in solid virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; virtual int GetNSurfaces() const; virtual Surface & GetSurface (int i = 0); virtual const Surface & GetSurface (int i = 0) const; virtual void Reduce (const BoxSphere<3> & box); virtual void UnReduce (); }; } #endif netgen-6.2.1905/libsrc/csg/manifold.cpp0000644000175000017500000000015513504650527016331 0ustar kurtkurt#include namespace netgen { Manifold :: Manifold () { ; } Manifold :: ~Manifold () { ; } } netgen-6.2.1905/libsrc/csg/revolution.cpp0000644000175000017500000006247013504650527016756 0ustar kurtkurt#include #include #include namespace netgen { void RevolutionFace :: Init(void) { const LineSeg<2> * line = dynamic_cast*>(spline); const SplineSeg3<2> * spline3 = dynamic_cast*>(spline); if(line) { checklines_start.Append(new Point<2>(line->StartPI())); checklines_vec.Append(new Vec<2>(line->EndPI() - line->StartPI())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! } else if (spline3) { checklines_start.Append(new Point<2>(spline3->EndPI())); checklines_start.Append(new Point<2>(spline3->TangentPoint())); checklines_start.Append(new Point<2>(spline3->StartPI())); checklines_vec.Append(new Vec<2>(spline3->StartPI() - spline3->EndPI())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! checklines_vec.Append(new Vec<2>(spline3->EndPI() - spline3->TangentPoint())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! checklines_vec.Append(new Vec<2>(spline3->TangentPoint() - spline3->StartPI())); (*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!! } for(int i=0; i); (*checklines_normal.Last())(0) = - (*checklines_vec[i])(1); (*checklines_normal.Last())(1) = (*checklines_vec[i])(0); checklines_normal.Last()->Normalize(); } } RevolutionFace :: RevolutionFace(const SplineSeg<2> & spline_in, const Point<3> & p, const Vec<3> & vec, bool first, bool last, const int id_in) : isfirst(first), islast(last), spline(&spline_in), p0(p), v_axis(vec), id(id_in) { deletable = false; Init(); } RevolutionFace :: RevolutionFace(const Array & raw_data) { deletable = true; int pos = 0; Array< Point<2> > p(3); int stype = int(raw_data[pos]); pos++; for(int i=0; i(GeomPoint<2>(p[0],1), GeomPoint<2>(p[1],1)); //(*testout) << "appending LineSeg<2> " << p[0] // << " to " << p[1] << endl; } else if(stype == 3) { spline = new SplineSeg3<2>(GeomPoint<2>(p[0],1), GeomPoint<2>(p[1],1), GeomPoint<2>(p[2],1)); //(*testout) << "appending SplineSeg<3> " // << p[0] << " -- " << p[1] << " -- " << p[2] << endl; } for(int i=0; i<3; i++) { p0(i) = raw_data[pos]; pos++; } for(int i=0; i<3; i++) { v_axis(i) = raw_data[pos]; pos++; } isfirst = (raw_data[pos] > 0.9); pos++; islast = (raw_data[pos] < 0.1); pos++; } RevolutionFace :: ~RevolutionFace() { for(int i=0; i & point3d, Point<2> & point2d, const Vec<3> & vector3d, Vec<2> & vector2d) const { Vec<3> pmp0 = point3d-p0; CalcProj0(pmp0,point2d); Vec<3> y=pmp0-point2d(0)*v_axis; y.Normalize(); vector2d(0) = vector3d*v_axis; vector2d(1) = vector3d*y; } void RevolutionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d) const { Vec<3> pmp0 = point3d-p0; CalcProj0(pmp0,point2d); } void RevolutionFace :: CalcProj0(const Vec<3> & point3d_minus_p0, Point<2> & point2d) const { point2d(0) = point3d_minus_p0 * v_axis; point2d(1) = sqrt( point3d_minus_p0 * point3d_minus_p0 - point2d(0)*point2d(0) ); } int RevolutionFace ::IsIdentic (const Surface & s2, int & inv, double eps) const { const RevolutionFace * rev2 = dynamic_cast(&s2); if(!rev2) return 0; if(rev2 == this) return 1; return 0; } double RevolutionFace :: CalcFunctionValue (const Point<3> & point) const { if(spline_coefficient.Size() == 0) spline->GetCoeff(spline_coefficient); if(spline_coefficient_shifted.Size() == 0) spline->GetCoeff(spline_coefficient_shifted, spline->StartPI()); Point<2> p; CalcProj(point,p); /* double val = spline_coefficient(0)*p(0)*p(0) + spline_coefficient(1)*p(1)*p(1) + spline_coefficient(2)*p(0)*p(1) + spline_coefficient(3)*p(0) + spline_coefficient(4)*p(1) + spline_coefficient(5); */ Vec<2> pr = p-spline->StartPI(); // cout << "spline_coefficinet = " << spline_coefficient << endl; // cout << "shifted = " << spline_coefficient_shifted << endl; double val2 = spline_coefficient_shifted(0)*pr(0)*pr(0) + spline_coefficient_shifted(1)*pr(1)*pr(1) + spline_coefficient_shifted(2)*pr(0)*pr(1) + spline_coefficient_shifted(3)*pr(0) + spline_coefficient_shifted(4)*pr(1) + spline_coefficient_shifted(5); // cout << "val = " << val << " =?= " << val2 << endl; return val2; } void RevolutionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const { if(spline_coefficient.Size() == 0) spline->GetCoeff(spline_coefficient); if(spline_coefficient_shifted.Size() == 0) spline->GetCoeff(spline_coefficient_shifted, spline->StartPI()); Vec<3> point_minus_p0 = point-p0; Point<2> p; CalcProj0(point_minus_p0,p); /* const double dFdxbar = 2.*spline_coefficient(0)*p(0) + spline_coefficient(2)*p(1) + spline_coefficient(3); if(fabs(p(1)) > 1e-10) { const double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4); grad(0) = dFdxbar*v_axis(0) + dFdybar * ( point_minus_p0(0)-v_axis(0)*p(0) )/p(1); grad(1) = dFdxbar*v_axis(1) + dFdybar * ( point_minus_p0(1)-v_axis(1)*p(0) )/p(1); grad(2) = dFdxbar*v_axis(2) + dFdybar * ( point_minus_p0(2)-v_axis(2)*p(0) )/p(1); //(*testout) << "grad1("< 1e-10) { double aux = spline_coefficient(0)-spline_coefficient(1); hesse(0,0) = aux*v_axis(0)*v_axis(0) + spline_coefficient(1); hesse(0,0) = aux*v_axis(1)*v_axis(1) + spline_coefficient(1); hesse(0,0) = aux*v_axis(2)*v_axis(2) + spline_coefficient(1); hesse(0,1) = hesse(1,0) = aux*v_axis(0)*v_axis(1); hesse(0,2) = hesse(2,0) = aux*v_axis(0)*v_axis(2); hesse(1,2) = hesse(2,1) = aux*v_axis(1)*v_axis(2); //(*testout) << "hesse2: " << hesse < 1e-10) return 2.*max2(fabs(spline_coefficient(0)),fabs(spline_coefficient(1))); double alpha = fabs(spline_coefficient(2)*(spline->StartPI()(0)-spline->EndPI()(0))) / max2(fabs(spline->StartPI()(1)),fabs(spline->EndPI()(1))); return max2(2.*fabs(spline_coefficient(0))+sqrt(2.)*fabs(spline_coefficient(2)), 2.*fabs(spline_coefficient(1))+spline_coefficient(2)+1.5*alpha); } double RevolutionFace :: MaxCurvature() const { double retval = spline->MaxCurvature(); Array < Point<2> > checkpoints; const SplineSeg3<2> * ss3 = dynamic_cast *>(spline); const LineSeg<2> * ls = dynamic_cast *>(spline); if(ss3) { checkpoints.Append(ss3->StartPI()); checkpoints.Append(ss3->TangentPoint()); checkpoints.Append(ss3->TangentPoint()); checkpoints.Append(ss3->EndPI()); } else if(ls) { checkpoints.Append(ls->StartPI()); checkpoints.Append(ls->EndPI()); } for(int i=0; i v = checkpoints[i+1]-checkpoints[i]; Vec<2> n(v(1),-v(0)); n.Normalize(); //if(ss3) // (*testout) << "n " << n << endl; if(fabs(n(1)) < 1e-15) continue; double t1 = -checkpoints[i](1)/n(1); double t2 = -checkpoints[i+1](1)/n(1); double c1 = (t1 > 0) ? (1./t1) : -1; double c2 = (t2 > 0) ? (1./t2) : -1; //if(ss3) // (*testout) << "t1 " << t1 << " t2 " << t2 << " c1 " << c1 << " c2 " << c2 << endl; if(c1 > retval) retval = c1; if(c2 > retval) retval = c2; } //if(ss3) // (*testout) << "curvature " << retval << endl; return retval; /* // find smallest y value of spline: Array testt; if(!isfirst) testt.Append(0); if(!islast) testt.Append(1); const SplineSegment3 * s3 = dynamic_cast(&spline); if(s3) { double denom = (2.-sqrt(2.))*(s3->EndPI()(1) - s3->StartPI()(1)); if(fabs(denom) < 1e-20) testt.Append(0.5); else { double sD = sqrt(pow(s3->TangentPoint()(1) - s3->StartPI()(1),2)+ pow(s3->TangentPoint()(1) - s3->EndPI()(1),2)); testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) + sD)/denom); testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) - sD)/denom); } } double miny = fabs(spline.GetPoint(testt[0])(1)); for(int i=1; i & p) const { Point<2> p2d; CalcProj(p,p2d); const Vec<3> y = (p-p0)-p2d(0)*v_axis; const double yl = y.Length(); double dummy; spline->Project(p2d,p2d,dummy); p = p0 + p2d(0)*v_axis; if(yl > 1e-20*Dist(spline->StartPI(),spline->EndPI())) p+= (p2d(1)/yl)*y; } Point<3> RevolutionFace :: GetSurfacePoint () const { Vec<3> random_vec(0.760320,-0.241175,0.60311534); Vec<3> n = Cross(v_axis,random_vec); n.Normalize(); Point<2> sp = spline->GetPoint(0.5); Point<3> retval = p0 + sp(0)*v_axis + sp(1)*n; return retval; } void RevolutionFace :: Print (ostream & str) const { if(spline_coefficient.Size() == 0) spline->GetCoeff(spline_coefficient); str << p0(0) << " " << p0(1) << " " << p0(2) << " " << v_axis(0) << " " << v_axis(1) << " " << v_axis(2) << " "; for(int i=0; i<6; i++) str << spline_coefficient(i) << " "; str << endl; } void RevolutionFace :: GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const { Vec<3> random_vec(0.760320,-0.241175,0.60311534); Vec<3> v1 = Cross(v_axis,random_vec); v1.Normalize(); Vec<3> v2 = Cross(v1,v_axis); v2.Normalize(); int n = int(2.*facets) + 1; for(int i=0; i<=n; i++) { Point<2> sp = spline->GetPoint(double(i)/double(n)); for(int j=0; j<=n; j++) { double phi = 2.*M_PI*double(j)/double(n); Point<3> p = p0 + sp(0)*v_axis + sp(1)*cos(phi)*v1 + sp(1)*sin(phi)*v2; tas.AddPoint(p); } } for(int i=0; i & box) const { Point<3> center = box.Center(); Project(center); return (Dist(box.Center(),center) < 0.5*box.Diam()); } /* bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<3> & box, bool & uncertain) const { Point<2> c,pmin,pmax; CalcProj(box.Center(),c); double aux = box.Diam()/sqrt(8.); pmin(0) = c(0)-aux; pmin(1) = c(1)-aux; pmax(0) = c(0)+aux; pmax(1) = c(1)+aux; BoxSphere<2> box2d(pmin,pmax); return BoxIntersectsFace(box2d, uncertain); } bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<2> & box, bool & uncertain) const { const LineSegment * line = dynamic_cast(&spline); const SplineSegment3 * spline3 = dynamic_cast(&spline); bool always_right = true, always_left = true; bool retval = false; bool thisint; bool intdirect = false; bool inttangent = false; uncertain = false; if(line) inttangent = true; for(int i=0; i b = box.Center()- (*checklines_start[i]); double d; double checkdist = b * (*checklines_vec[i]); double ncomp = b * (*checklines_normal[i]); if(checkdist < 0) d = b.Length(); else if (checkdist > 1) { if(spline3) d = Dist(box.Center(),*checklines_start[(i+1)%3]); else d = Dist(box.Center(),(*checklines_start[i]) + pow(checklines_vec[i]->Length(),2)*(*checklines_vec[i])); } else d = fabs(ncomp); thisint = (box.Diam() >= 2.*d); retval = retval || thisint; if(thisint) { if(i==0) intdirect = true; else inttangent = true; } if(ncomp > 0) always_right = false; else if(ncomp < 0) always_left = false; } if(retval && !(intdirect && inttangent)) uncertain = true; if(!retval && spline3 && (always_right || always_left)) { retval = true; uncertain = true; } return retval; } */ /* INSOLID_TYPE */ bool RevolutionFace :: PointInFace (const Point<3> & p, const double eps) const { Point<2> p2d; CalcProj(p,p2d); if (!spline -> InConvexHull(p2d, eps)) return false; /* double val = spline_coefficient(0)*p2d(0)*p2d(0) + spline_coefficient(1)*p2d(1)*p2d(1) + spline_coefficient(2)*p2d(0)*p2d(1) + spline_coefficient(3)*p2d(0) + spline_coefficient(4)*p2d(1) + spline_coefficient(5); */ Vec<2> pr = p2d - spline->StartPI(); double val = spline_coefficient_shifted(0)*pr(0)*pr(0) + spline_coefficient_shifted(1)*pr(1)*pr(1) + spline_coefficient_shifted(2)*pr(0)*pr(1) + spline_coefficient_shifted(3)*pr(0) + spline_coefficient_shifted(4)*pr(1) + spline_coefficient_shifted(5); return (fabs(val) < eps); /* if(val > eps) return IS_OUTSIDE; if(val < -eps) return IS_INSIDE; return DOES_INTERSECT; */ } void RevolutionFace :: GetRawData(Array & data) const { data.DeleteAll(); spline->GetRawData(data); for(int i=0; i<3; i++) data.Append(p0(i)); for(int i=0; i<3; i++) data.Append(v_axis(i)); data.Append((isfirst) ? 1. : 0.); data.Append((islast) ? 1. : 0.); } Revolution :: Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in) : p0(p0_in), p1(p1_in) { auto nsplines = spline_in.GetNSplines(); surfaceactive.SetSize(0); surfaceids.SetSize(0); v_axis = p1-p0; v_axis.Normalize(); if(spline_in.GetSpline(0).StartPI()(1) <= 0. && spline_in.GetSpline(nsplines-1).EndPI()(1) <= 0.) type = 2; else if (Dist(spline_in.GetSpline(0).StartPI(), spline_in.GetSpline(nsplines-1).EndPI()) < 1e-7) type = 1; else cerr << "Surface of revolution cannot be constructed" << endl; for(int i=0; i & box) const { for(int i=0; iBoxIntersectsFace(box)) return DOES_INTERSECT; return PointInSolid(box.Center(),0); /* Point<2> c,pmin,pmax; faces[0]->CalcProj(box.Center(),c); double aux = box.Diam()/sqrt(8.); pmin(0) = c(0)-aux; pmin(1) = c(1)-aux; pmax(0) = c(0)+aux; pmax(1) = c(1)+aux; BoxSphere<2> box2d(pmin,pmax); bool intersection = false; bool uncertain = true; for(int i=0; !(intersection && !uncertain) && iBoxIntersectsFace(box2d,thisuncertain); intersection = intersection || thisintersects; if(thisintersects && !thisuncertain) uncertain = false; } if(intersection) { if(!uncertain) return DOES_INTERSECT; else { Array < Point<3> > pext(2); Point<3> p; pext[0] = box.PMin(); pext[1] = box.PMax(); INSOLID_TYPE position; bool firsttime = true; for(int i=0; i<2; i++) for(int j=0; j<2; j++) for(int k=0; k<2; k++) { p(0) = pext[i](0); p(1) = pext[j](1); p(2) = pext[k](2); INSOLID_TYPE ppos = PointInSolid(p,0); if(ppos == DOES_INTERSECT) return DOES_INTERSECT; if(firsttime) { firsttime = false; position = ppos; } if(position != ppos) return DOES_INTERSECT; } return position; } } return PointInSolid(box.Center(),0); */ } INSOLID_TYPE Revolution :: PointInSolid (const Point<3> & p, double eps) const { Point<2> p2d; faces[0]->CalcProj(p,p2d); int intersections_before(0), intersections_after(0); double randomx = 7.42357; double randomy = 1.814756; randomx *= 1./sqrt(randomx*randomx+randomy*randomy); randomy *= 1./sqrt(randomx*randomx+randomy*randomy); const double a = randomy; const double b = -randomx; const double c = -a*p2d(0)-b*p2d(1); Array < Point<2> > points; //(*testout) << "face intersections at: " << endl; for(int i=0; iGetSpline().LineIntersections(a,b,c,points,eps); for(int j=0; j eps ) intersections_after++; else { intersecting_face = i; return DOES_INTERSECT; } } } if(intersections_after % 2 == 0) return IS_OUTSIDE; else return IS_INSIDE; } void Revolution :: GetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const { for (int j = 0; j < faces.Size(); j++) if (faces[j] -> PointInFace(p, eps)) if (!surfind.Contains (GetSurfaceId(j))) surfind.Append (GetSurfaceId(j)); } INSOLID_TYPE Revolution :: VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const { INSOLID_TYPE pInSolid = PointInSolid(p,eps); if(pInSolid != DOES_INTERSECT) { //(*testout) << "pInSolid" << endl; return pInSolid; } Array intersecting_faces; for(int i=0; iPointInFace(p,eps)) // == DOES_INTERSECT) intersecting_faces.Append(i); Vec<3> hv; if(intersecting_faces.Size() == 1) { faces[intersecting_faces[0]]->CalcGradient(p,hv); double hv1; hv1 = v * hv; if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; return DOES_INTERSECT; } else if(intersecting_faces.Size() == 2) { Point<2> p2d; Vec<2> v2d; faces[intersecting_faces[0]]->CalcProj(p,p2d,v,v2d); if(Dist(faces[intersecting_faces[0]]->GetSpline().StartPI(),p2d) < Dist(faces[intersecting_faces[0]]->GetSpline().EndPI(),p2d)) { int aux = intersecting_faces[0]; intersecting_faces[0] = intersecting_faces[1]; intersecting_faces[1] = aux; } const SplineSeg3<2> * splinesegment3 = dynamic_cast *>(&faces[intersecting_faces[0]]->GetSpline()); const LineSeg<2> * linesegment = dynamic_cast *>(&faces[intersecting_faces[0]]->GetSpline()); Vec<2> t1(0),t2(0); if(linesegment) t1 = linesegment->StartPI() - linesegment->EndPI(); else if(splinesegment3) t1 = splinesegment3->TangentPoint() - splinesegment3->EndPI(); linesegment = dynamic_cast *>(&faces[intersecting_faces[1]]->GetSpline()); splinesegment3 = dynamic_cast *>(&faces[intersecting_faces[1]]->GetSpline()); if(linesegment) t2 = linesegment->EndPI() - linesegment->StartPI(); else if(splinesegment3) t2 = splinesegment3->TangentPoint() - splinesegment3->StartPI(); t1.Normalize(); t2.Normalize(); double d1 = v2d*t1; double d2 = v2d*t2; Vec<2> n; if(d1 > d2) { n(0) = t1(1); n(1) = -t1(0); } else { n(0) = -t2(1); n(1) = t2(0); } double d = v2d*n; if(d > eps) return IS_OUTSIDE; else if (d < -eps) return IS_INSIDE; else return DOES_INTERSECT; } else { cerr << "Jo gibt's denn des?" << endl; } return DOES_INTERSECT; } INSOLID_TYPE Revolution :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { INSOLID_TYPE ret1 = VecInSolid(p,v1,eps); if(ret1 != DOES_INTERSECT) return ret1; return VecInSolid(p,v1+0.01*v2,eps); } int Revolution :: GetNSurfaces() const { return faces.Size(); } Surface & Revolution :: GetSurface (int i) { return *faces[i]; } const Surface & Revolution :: GetSurface (int i) const { return *faces[i]; } void Revolution :: Reduce (const BoxSphere<3> & box) { //bool dummy; for(int i=0; iBoxIntersectsFace(box)); //surfaceactive[i] = (faces[i]->BoxIntersectsFace(box,dummy)); } void Revolution :: UnReduce () { for(int i=0; i regrevf; RegisterClassForArchive regrev; } netgen-6.2.1905/libsrc/csg/gencyl.hpp0000644000175000017500000000313213504650527016024 0ustar kurtkurt#ifndef FILE_GENCYL #define FILE_GENCYL /**************************************************************************/ /* File: gencyl.hh */ /* Author: Joachim Schoeberl */ /* Date: 14. Oct. 96 */ /**************************************************************************/ namespace netgen { /* Generalized Cylinder */ /// class GeneralizedCylinder : public Surface { /// ExplicitCurve2d & crosssection; /// Point<3> planep; /// Vec<3> planee1, planee2, planee3; /// Vec<3> ex, ey, ez; Vec2d e2x, e2y; /// Point<3> cp; public: /// GeneralizedCylinder (ExplicitCurve2d & acrosssection, Point<3> ap, Vec<3> ae1, Vec<3> ae2); /// virtual void Project (Point<3> & p) const; /// virtual int BoxInSolid (const BoxSphere<3> & box) const; /// 0 .. no, 1 .. yes, 2 .. maybe virtual double CalcFunctionValue (const Point<3> & point) const; /// virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; /// virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; /// virtual double HesseNorm () const; /// virtual double MaxCurvatureLoc (const Point<3> & c, double rad) const; /// virtual Point<3> GetSurfacePoint () const; /// virtual void Print (ostream & str) const; /// virtual void Reduce (const BoxSphere<3> & box); /// virtual void UnReduce (); }; } #endif netgen-6.2.1905/libsrc/csg/solid.hpp0000644000175000017500000001705413504650527015665 0ustar kurtkurt#ifndef FILE_SOLID #define FILE_SOLID /**************************************************************************/ /* File: solid.hh */ /* Author: Joachim Schoeberl */ /* Date: 1. Dez. 95 */ /**************************************************************************/ #include namespace netgen { /* Constructive Solid Model (csg) */ class Solid; class SolidIterator { public: SolidIterator () { ; } virtual ~SolidIterator () { ; } virtual void Do (Solid * sol) = 0; }; class Solid { public: typedef enum optyp1 { TERM, TERM_REF, SECTION, UNION, SUB, ROOT /*, DUMMY */ } optyp; private: char * name; Primitive * prim; Solid * s1, * s2; optyp op; bool visited; double maxh; int num_surfs; // static int cntnames; public: Solid (Primitive * aprim); Solid (optyp aop, Solid * as1, Solid * as2 = NULL); // default constructor for archive Solid () {} ~Solid (); void DoArchive(Archive& archive) { archive & name & prim & s1 & s2 & visited & maxh & num_surfs; if(archive.Output()) archive << int(op); else { int iop; archive & iop; op = optyp(iop); } } const char * Name () const { return name; } void SetName (const char * aname); Solid * Copy (class CSGeometry & geom) const; void Transform (Transformation<3> & trans); void IterateSolid (SolidIterator & it, bool only_once = 0); void Boundaries (const Point<3> & p, Array & bounds) const; int NumPrimitives () const; void GetSurfaceIndices (Array & surfind) const; void GetSurfaceIndices (IndexSet & iset) const; void GetTangentialSurfaceIndices (const Point<3> & p, Array & surfids, double eps) const; void GetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, Array & surfids, double eps) const; void GetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, Array & surfids, double eps) const; void ForEachSurface (const std::function & lambda, bool inv = false) const; Primitive * GetPrimitive () { return (op == TERM || op == TERM_REF) ? prim : NULL; } const Primitive * GetPrimitive () const { return (op == TERM || op == TERM_REF) ? prim : NULL; } Solid * S1() { return s1; } Solid * S2() { return s2; } // geometric tests bool IsIn (const Point<3> & p, double eps = 1e-6) const; bool IsStrictIn (const Point<3> & p, double eps = 1e-6) const; bool VectorIn (const Point<3> & p, const Vec<3> & v, double eps = 1e-6) const; bool VectorStrictIn (const Point<3> & p, const Vec<3> & v, double eps = 1e-6) const; bool VectorIn2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; bool VectorIn2Rec (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; /// compute localization in point p void TangentialSolid (const Point<3> & p, Solid *& tansol, Array & surfids, double eps) const; /// compute localization in point p tangential to vector t void TangentialSolid2 (const Point<3> & p, const Vec<3> & t, Solid *& tansol, Array & surfids, double eps) const; /** compute localization in point p, with second order approximation to edge p + s t + s*s/2 t2 **/ void TangentialSolid3 (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, Solid *& tansol, Array & surfids, double eps) const; /** tangential solid, which follows the edge p + s t + s*s/2 t2 with second order, and the neighbouring face p + s t + s*s/2 t2 + r m with first order **/ void TangentialEdgeSolid (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, const Vec<3> & m, Solid *& tansol, Array & surfids, double eps) const; void CalcOnePrimitiveSpecialPoints (const Box<3> & box, Array > & pts) const; /// int Edge (const Point<3> & p, const Vec<3> & v, double eps) const; /// int OnFace (const Point<3> & p, const Vec<3> & v, double eps) const; /// void Print (ostream & str) const; /// void CalcSurfaceInverse (); /// Solid * GetReducedSolid (const BoxSphere<3> & box) const; void SetMaxH (double amaxh) { maxh = amaxh; } double GetMaxH () const { return maxh; } void GetSolidData (ostream & ost, int first = 1) const; static Solid * CreateSolid (istream & ist, const SymbolTable & solids); static BlockAllocator ball; void * operator new(size_t /* s */) { return ball.Alloc(); } void operator delete (void * p) { ball.Free (p); } protected: /// void RecBoundaries (const Point<3> & p, Array & bounds, int & in, int & strin) const; /// void RecTangentialSolid (const Point<3> & p, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const; void RecTangentialSolid2 (const Point<3> & p, const Vec<3> & vec, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const; /// void RecTangentialSolid3 (const Point<3> & p, const Vec<3> & vec,const Vec<3> & vec2, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const; /// void RecTangentialEdgeSolid (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, const Vec<3> & m, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const; /// void RecEdge (const Point<3> & p, const Vec<3> & v, int & in, int & strin, int & faces, double eps) const; /// void CalcSurfaceInverseRec (int inv); /// Solid * RecGetReducedSolid (const BoxSphere<3> & box, INSOLID_TYPE & in) const; /// void RecGetSurfaceIndices (Array & surfind) const; void RecGetTangentialSurfaceIndices (const Point<3> & p, Array & surfids, double eps) const; void RecGetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, Array & surfids, double eps) const; void RecGetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, Array & surfids, double eps) const; void RecGetTangentialEdgeSurfaceIndices (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, Array & surfids, double eps) const; void RecGetSurfaceIndices (IndexSet & iset) const; void RecCalcOnePrimitiveSpecialPoints (Array > & pts) const; friend class SolidIterator; friend class ClearVisitedIt; friend class RemoveDummyIterator; friend class CSGeometry; }; inline ostream & operator<< (ostream & ost, const Solid & sol) { sol.Print (ost); return ost; } class ReducePrimitiveIterator : public SolidIterator { BoxSphere<3> box; public: ReducePrimitiveIterator (const BoxSphere<3> & abox) : SolidIterator(), box(abox) { ; } virtual ~ReducePrimitiveIterator () { ; } virtual void Do (Solid * sol) { if (sol -> GetPrimitive()) sol -> GetPrimitive() -> Reduce (box); } }; class UnReducePrimitiveIterator : public SolidIterator { public: UnReducePrimitiveIterator () { ; } virtual ~UnReducePrimitiveIterator () { ; } virtual void Do (Solid * sol) { if (sol -> GetPrimitive()) sol -> GetPrimitive() -> UnReduce (); } }; } #endif netgen-6.2.1905/libsrc/csg/extrusion.hpp0000644000175000017500000001140413504650527016604 0ustar kurtkurt#ifndef _EXTRUSION_HPP #define _EXTRUSION_HPP namespace netgen { class Extrusion; class ExtrusionFace : public Surface { private: const SplineSeg<2> * profile; const SplineGeometry<3> * path; Vec<3> glob_z_direction; bool deletable; Array< const SplineSeg3<3> * > spline3_path; Array< const LineSeg<3> * > line_path; mutable Array < Vec<3> > x_dir, y_dir, z_dir, loc_z_dir; mutable Array < Point<3> > p0; mutable Vec<3> profile_tangent; mutable double profile_par; mutable Vector profile_spline_coeff; mutable int latest_seg; mutable double latest_t; mutable Point<2> latest_point2d; mutable Point<3> latest_point3d; private: void Orthogonalize(const Vec<3> & v1, Vec<3> & v2) const; void Init(void); public: double CalcProj(const Point<3> & point3d, Point<2> & point2d, int seg) const; void CalcProj(const Point<3> & point3d, Point<2> & point2d, int & seg, double & t) const; public: ExtrusionFace(const SplineSeg<2> * profile_in, const SplineGeometry<3> * path_in, const Vec<3> & z_direction); ExtrusionFace(const Array & raw_data); // default constructor for archive ExtrusionFace() {} ~ExtrusionFace(); virtual void DoArchive(Archive& ar) { Surface::DoArchive(ar); ar & profile & path & glob_z_direction & deletable & spline3_path & line_path & x_dir & y_dir & z_dir & loc_z_dir & p0 & profile_tangent & profile_par & profile_spline_coeff & latest_seg & latest_t & latest_point2d & latest_point3d; } virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; virtual double CalcFunctionValue (const Point<3> & point) const; virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; virtual double HesseNorm () const; virtual double MaxCurvature () const; //virtual double MaxCurvatureLoc (const Point<3> & /* c */ , // double /* rad */) const; virtual void Project (Point<3> & p) const; virtual Point<3> GetSurfacePoint () const; virtual void Print (ostream & str) const; virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const; const SplineGeometry<3> & GetPath(void) const {return *path;} const SplineSeg<2> & GetProfile(void) const {return *profile;} bool BoxIntersectsFace(const Box<3> & box) const; void LineIntersections ( const Point<3> & p, const Vec<3> & v, const double eps, int & before, int & after, bool & intersecting ) const; INSOLID_TYPE VecInFace ( const Point<3> & p, const Vec<3> & v, const double eps ) const; const Vec<3> & GetYDir ( void ) const {return y_dir[latest_seg];} const Vec<3> & GetProfileTangent (void) const {return profile_tangent;} double GetProfilePar(void) const {return profile_par;} void GetRawData(Array & data) const; void CalcLocalCoordinates (int seg, double t, Vec<3> & ex, Vec<3> & ey, Vec<3> & ez) const; void CalcLocalCoordinatesDeriv (int seg, double t, Vec<3> & ex, Vec<3> & ey, Vec<3> & ez, Vec<3> & dex, Vec<3> & dey, Vec<3> & dez) const; }; class Extrusion : public Primitive { private: const SplineGeometry<3>* path; const SplineGeometry<2>* profile; // closed, clockwise oriented curve Vec<3> z_direction; Array faces; mutable int latestfacenum; public: Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir); // default constructor for archive Extrusion() {} ~Extrusion(); virtual void DoArchive(Archive& ar) { Primitive::DoArchive(ar); ar & path & profile & z_direction & faces & latestfacenum; } virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; INSOLID_TYPE PointInSolid (const Point<3> & p, double eps, Array * const facenums) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const; // checks if lim s->0 lim t->0 p + t(v1 + s v2) in solid virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; virtual int GetNSurfaces() const; virtual Surface & GetSurface (int i = 0); virtual const Surface & GetSurface (int i = 0) const; virtual void Reduce (const BoxSphere<3> & box); virtual void UnReduce (); }; } #endif //_EXTRUSION_HPP netgen-6.2.1905/libsrc/csg/csgparser.hpp0000644000175000017500000000427513504650527016545 0ustar kurtkurt#ifndef _CSGPARSER_HPP #define _CSGPARSER_HPP namespace netgen { enum TOKEN_TYPE { TOK_MINUS = '-', TOK_LP = '(', OK_RP = ')', TOK_LSP = '[', TOK_RSP = ']', TOK_EQU = '=', TOK_COMMA = ',', TOK_SEMICOLON = ';', TOK_NUM = 100, TOK_STRING, TOK_NAMED_SOLID, TOK_PRIMITIVE, TOK_OR, TOK_AND, TOK_NOT, TOK_SINGULAR, TOK_EDGE, TOK_POINT, TOK_FACE, TOK_IDENTIFY, TOK_CLOSESURFACES, TOK_CLOSEEDGES, TOK_PERIODIC, TOK_SOLID, TOK_RECO, TOK_TLO, TOK_CURVE2D, TOK_CURVE3D, TOK_BOUNDINGBOX, TOK_BOUNDARYCONDITION, TOK_BOUNDARYCONDITIONNAME, TOK_DEFINE, TOK_CONSTANT, TOK_END }; struct kwstruct { TOKEN_TYPE kw; const char * name; }; enum PRIMITIVE_TYPE { TOK_SPHERE = 1, TOK_CYLINDER, TOK_PLANE, TOK_ELLIPTICCYLINDER, TOK_ELLIPSOID, TOK_CONE, TOK_ELLIPTICCONE, TOK_ORTHOBRICK, TOK_POLYHEDRON, TOK_TORUS, TOK_TUBE, TOK_GENCYL, TOK_EXTRUSION, TOK_REVOLUTION, TOK_TRANSLATE, TOK_MULTITRANSLATE, TOK_ROTATE, TOK_MULTIROTATE }; struct primstruct { PRIMITIVE_TYPE kw; const char * name; }; class CSGScanner { TOKEN_TYPE token; PRIMITIVE_TYPE prim_token; double num_value; string string_value; int linenum; istream * scanin; public: CSGScanner (istream & ascanin); TOKEN_TYPE GetToken() const { return token; } double GetNumValue() const { return num_value; } const string & GetStringValue() const { return string_value; } char GetCharValue() const { return string_value[0]; } PRIMITIVE_TYPE GetPrimitiveToken() const { return prim_token; } void ReadNext(); /* CSGScanner & Parse (char ch); CSGScanner & Parse (int & i); CSGScanner & Parse (double & d); CSGScanner & Parse (Point<3> & p); CSGScanner & Parse (Vec<3> & p); */ void Error (const string & err); }; CSGScanner & operator>> (CSGScanner & scan, char ch); CSGScanner & operator>> (CSGScanner & scan, double & d); CSGScanner & operator>> (CSGScanner & scan, int & i); CSGScanner & operator>> (CSGScanner & scan, Point<3> & p); CSGScanner & operator>> (CSGScanner & scan, Vec<3> & v); } #endif netgen-6.2.1905/libsrc/csg/surface.cpp0000644000175000017500000002514713504650527016200 0ustar kurtkurt#include #include #include #include #include namespace netgen { Surface :: Surface () { maxh = 1e10; name = new char[7]; strcpy (name, "noname"); bcprop = -1; bcname = "default"; } Surface :: ~Surface() { delete [] name; } void Surface :: SetName (const char * aname) { delete [] name; name = new char[strlen (aname)+1]; strcpy (name, aname); } int Surface :: PointOnSurface (const Point<3> & p, double eps) const { double val = CalcFunctionValue (p); return fabs (val) < eps; } void Surface :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const { double dx = 1e-5; Point<3> hp1, hp2; Vec<3> g1, g2; for (int i = 0; i < 3; i++) { hp1 = point; hp2 = point; hp1(i) += dx; hp2(i) -= dx; CalcGradient (hp1, g1); CalcGradient (hp2, g2); for (int j = 0; j < 3; j++) hesse(i, j) = (g1(j) - g2(j)) / (2 * dx); } } /* void Surface :: GetNormalVector (const Point<3> & p, Vec<3> & n) const { CalcGradient (p, n); n.Normalize(); } */ Vec<3> Surface :: GetNormalVector (const Point<3> & p) const { Vec<3> n; CalcGradient (p, n); n.Normalize(); return n; } void Surface :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2) { p1 = ap1; p2 = ap2; ez = GetNormalVector (p1); ex = p2 - p1; ex -= (ex * ez) * ez; ex.Normalize(); ey = Cross (ez, ex); } void Surface :: ToPlane (const Point<3> & p3d, Point<2> & pplane, double h, int & zone) const { Vec<3> p1p, n; n = GetNormalVector (p3d); if (n * ez < 0) { zone = -1; pplane(0) = 1e8; pplane(1) = 1e9; return; } p1p = p3d - p1; pplane(0) = (p1p * ex) / h; pplane(1) = (p1p * ey) / h; zone = 0; } void Surface :: FromPlane (const Point<2> & pplane, Point<3> & p3d, double h) const { p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey; Project (p3d); } void Surface :: Project (Point<3> & p) const { Vec<3> n; double val; for (int i = 1; i <= 10; i++) { val = CalcFunctionValue (p); if (fabs (val) < 1e-12) return; CalcGradient (p, n); p -= (val / Abs2 (n)) * n; } } void Surface :: SkewProject (Point<3> & p, const Vec<3> & direction) const { Point<3> startp(p); double t_old(0),t_new(1); Vec<3> grad; for(int i=0; fabs(t_old-t_new) > 1e-20 && i<15; i++) { t_old = t_new; CalcGradient(p,grad); t_new = t_old - CalcFunctionValue(p)/(grad*direction); p = startp + t_new*direction; } } double Surface :: MaxCurvature () const { return 0.5 * HesseNorm (); } double Surface :: MaxCurvatureLoc (const Point<3> & /* c */ , double /* rad */) const { return MaxCurvature (); } double Surface :: LocH (const Point<3> & p, double x, double c, const MeshingParameters & mparam, double hmax) const // finds h <= hmax, s.t. h * \kappa_x*h < c { /* double h, hmin, kappa; hmin = 0; while (hmin < 0.9 * hmax) { h = 0.5 * (hmin + hmax); kappa = 2 * MaxCurvatureLoc (p, x * h); if (kappa * h >= c) hmax = h; else hmin = h; } return h; */ double hret; double kappa = MaxCurvatureLoc (p, x*hmax); kappa *= c * mparam.curvaturesafety; if (hmax * kappa < 1) hret = hmax; else hret = 1 / kappa; if (maxh < hret) hret = maxh; return hret; } Primitive :: Primitive () { surfaceids.SetSize (1); surfaceactive.SetSize (1); surfaceactive[0] = 1; } Primitive :: ~Primitive() { ; } int Primitive :: GetSurfaceId (int i) const { return surfaceids[i]; } void Primitive :: SetSurfaceId (int i, int id) { surfaceids[i] = id; } void Primitive :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "undef"; coeffs.SetSize (0); } void Primitive :: SetPrimitiveData (Array & coeffs) { ; } Primitive * Primitive :: CreatePrimitive (const char * classname) { if (strcmp (classname, "sphere") == 0) return Sphere::CreateDefault(); if (strcmp (classname, "plane") == 0) return Plane::CreateDefault(); if (strcmp (classname, "cylinder") == 0) return Cylinder::CreateDefault(); if (strcmp (classname, "cone") == 0) return Cone::CreateDefault(); if (strcmp (classname, "brick") == 0) return Brick::CreateDefault(); stringstream ost; ost << "Primitve::CreatePrimitive not implemented for " << classname << endl; throw NgException (ost.str()); } Primitive * Primitive :: Copy () const { stringstream ost; ost << "Primitve::Copy not implemented for " << typeid(*this).name() << endl; throw NgException (ost.str()); } void Primitive :: Transform (Transformation<3> & trans) { stringstream ost; ost << "Primitve::Transform not implemented for " << typeid(*this).name() << endl; throw NgException (ost.str()); } void Primitive :: GetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const { for (int j = 0; j < GetNSurfaces(); j++) if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps) if (!surfind.Contains (GetSurfaceId(j))) surfind.Append (GetSurfaceId(j)); } void Primitive :: GetTangentialVecSurfaceIndices (const Point<3> & p, const Vec<3> & v, Array & surfind, double eps) const { cout << "get tangvecsurfind not implemented" << endl; surfind.SetSize (0); } void Primitive :: GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, Array & surfind, double eps) const { for (int j = 0; j < GetNSurfaces(); j++) { if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps) { Vec<3> grad; GetSurface(j).CalcGradient (p, grad); if (sqr (grad * v1) < 1e-6 * v1.Length2() * grad.Length2() && sqr (grad * v2) < 1e-6 * v2.Length2() * grad.Length2() ) // new, 18032006 JS { if (!surfind.Contains (GetSurfaceId(j))) surfind.Append (GetSurfaceId(j)); } } } } INSOLID_TYPE Primitive :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { //(*testout) << "Primitive::VecInSolid2" << endl; Point<3> hp = p + 1e-3 * v1 + 1e-5 * v2; INSOLID_TYPE res = PointInSolid (hp, eps); // (*testout) << "vectorin2, type = " << typeid(*this).name() << ", res = " << res << endl; return res; } INSOLID_TYPE Primitive :: VecInSolid3 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { //(*testout) << "Primitive::VecInSolid3" << endl; return VecInSolid (p, v1, eps); } INSOLID_TYPE Primitive :: VecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, double eps) const { return VecInSolid2 (p, v, m, eps); } OneSurfacePrimitive :: OneSurfacePrimitive() { ; } OneSurfacePrimitive :: ~OneSurfacePrimitive() { ; } INSOLID_TYPE OneSurfacePrimitive :: PointInSolid (const Point<3> & p, double eps) const { double hv1 = (GetSurface(0).CalcFunctionValue(p)); if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; return DOES_INTERSECT; } INSOLID_TYPE OneSurfacePrimitive :: VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const { double hv1 = (GetSurface(0).CalcFunctionValue(p)); if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; Vec<3> hv; GetSurface(0).CalcGradient (p, hv); hv1 = v * hv; if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; return DOES_INTERSECT; } INSOLID_TYPE OneSurfacePrimitive :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { double hv1 = (GetSurface(0).CalcFunctionValue(p)); if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; Vec<3> hv; GetSurface(0).CalcGradient (p, hv); hv1 = v1 * hv; if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; double hv2 = v2 * hv; if (hv2 <= 0) return IS_INSIDE; else return IS_OUTSIDE; } INSOLID_TYPE OneSurfacePrimitive :: VecInSolid3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, double eps) const { //(*testout) << "OneSurfacePrimitive::VecInSolid3" << endl; double hv1 = (GetSurface(0).CalcFunctionValue(p)); if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; Vec<3> grad; GetSurface(0).CalcGradient (p, grad); hv1 = v * grad; if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; Mat<3> hesse; GetSurface(0).CalcHesse (p, hesse); double hv2 = v2 * grad + v * (hesse * v); if (hv2 <= -eps) return IS_INSIDE; if (hv2 >= eps) return IS_OUTSIDE; return DOES_INTERSECT; } INSOLID_TYPE OneSurfacePrimitive :: VecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, double eps) const { double hv1 = (GetSurface(0).CalcFunctionValue(p)); if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; Vec<3> grad; GetSurface(0).CalcGradient (p, grad); hv1 = v * grad; if (hv1 <= -eps) return IS_INSIDE; if (hv1 >= eps) return IS_OUTSIDE; Mat<3> hesse; GetSurface(0).CalcHesse (p, hesse); double hv2 = v2 * grad + v * (hesse * v); if (hv2 <= -eps) return IS_INSIDE; if (hv2 >= eps) return IS_OUTSIDE; double hv3 = m * grad; if (hv3 <= -eps) return IS_INSIDE; if (hv3 >= eps) return IS_OUTSIDE; return DOES_INTERSECT; } int OneSurfacePrimitive :: GetNSurfaces() const { return 1; } Surface & OneSurfacePrimitive :: GetSurface (int i) { return *this; } const Surface & OneSurfacePrimitive :: GetSurface (int i) const { return *this; } void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp) { Vec<2> rs, lam; Vec<3> a1, a2; Mat<2> a; int i = 10; while (i > 0) { i--; rs(0) = f1 -> CalcFunctionValue (hp); rs(1) = f2 -> CalcFunctionValue (hp); f1->CalcGradient (hp, a1); f2->CalcGradient (hp, a2); double alpha = fabs(a1*a2)/sqrt(a1.Length2()*a2.Length2()); if(fabs(1.-alpha) < 1e-6) { if(fabs(rs(0)) >= fabs(rs(1))) f1 -> Project(hp); else f2 -> Project(hp); } else { a(0,0) = a1 * a1; a(0,1) = a(1,0) = a1 * a2; a(1,1) = a2 * a2; a.Solve (rs, lam); hp -= lam(0) * a1 + lam(1) * a2; } if (Abs2 (rs) < 1e-24 && i > 1) i = 1; } } RegisterClassForArchive regsurf; RegisterClassForArchive regprim; RegisterClassForArchive regosf; } netgen-6.2.1905/libsrc/csg/solid.cpp0000644000175000017500000011462513504650527015662 0ustar kurtkurt#include #include #include namespace netgen { //using namespace netgen; /* SolidIterator :: SolidIterator () { ; } SolidIterator :: ~SolidIterator () { ; } */ // int Solid :: cntnames = 0; Solid :: Solid (Primitive * aprim) { op = TERM; prim = aprim; s1 = s2 = NULL; maxh = 1e10; name = NULL; num_surfs = prim->GetNSurfaces(); } Solid :: Solid (optyp aop, Solid * as1, Solid * as2) { op = aop; s1 = as1; s2 = as2; prim = NULL; name = NULL; maxh = 1e10; num_surfs = 0; if (s1) num_surfs += s1->num_surfs; if (s2) num_surfs += s2->num_surfs; } Solid :: ~Solid () { // cout << "delete solid, op = " << int(op) << endl; delete [] name; switch (op) { case UNION: case SECTION: { if (s1->op != ROOT) delete s1; if (s2->op != ROOT) delete s2; break; } case SUB: // case ROOT: { if (s1->op != ROOT) delete s1; break; } case TERM: { // cout << "has term" << endl; delete prim; break; } default: break; } } void Solid :: SetName (const char * aname) { delete [] name; name = new char[strlen (aname)+1]; strcpy (name, aname); } Solid * Solid :: Copy (CSGeometry & geom) const { Solid * nsol(NULL); switch (op) { case TERM: case TERM_REF: { Primitive * nprim = prim->Copy(); geom.AddSurfaces (nprim); nsol = new Solid (nprim); break; } case SECTION: case UNION: { nsol = new Solid (op, s1->Copy(geom), s2->Copy(geom)); break; } case SUB: { nsol = new Solid (SUB, s1 -> Copy (geom)); break; } case ROOT: { nsol = s1->Copy(geom); break; } } return nsol; } void Solid :: Transform (Transformation<3> & trans) { switch (op) { case TERM: case TERM_REF: { prim -> Transform (trans); break; } case SECTION: case UNION: { s1 -> Transform (trans); s2 -> Transform (trans); break; } case SUB: case ROOT: { s1 -> Transform (trans); break; } } } void Solid :: IterateSolid (SolidIterator & it, bool only_once) { if (only_once) { if (visited) return; visited = 1; } it.Do (this); switch (op) { case SECTION: { s1->IterateSolid (it, only_once); s2->IterateSolid (it, only_once); break; } case UNION: { s1->IterateSolid (it, only_once); s2->IterateSolid (it, only_once); break; } case SUB: case ROOT: { s1->IterateSolid (it, only_once); break; } case TERM: case TERM_REF: break; // do nothing } } bool Solid :: IsIn (const Point<3> & p, double eps) const { switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->PointInSolid (p, eps); return ( (ist == IS_INSIDE) || (ist == DOES_INTERSECT) ) ? 1 : 0; } case SECTION: return s1->IsIn (p, eps) && s2->IsIn (p, eps); case UNION: return s1->IsIn (p, eps) || s2->IsIn (p, eps); case SUB: return !s1->IsStrictIn (p, eps); case ROOT: return s1->IsIn (p, eps); } return 0; } bool Solid :: IsStrictIn (const Point<3> & p, double eps) const { switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->PointInSolid (p, eps); return (ist == IS_INSIDE) ? 1 : 0; } case SECTION: return s1->IsStrictIn(p, eps) && s2->IsStrictIn(p, eps); case UNION: return s1->IsStrictIn(p, eps) || s2->IsStrictIn(p, eps); case SUB: return !s1->IsIn (p, eps); case ROOT: return s1->IsStrictIn (p, eps); } return 0; } bool Solid :: VectorIn (const Point<3> & p, const Vec<3> & v, double eps) const { Vec<3> hv; switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->VecInSolid (p, v, eps); return (ist == IS_INSIDE || ist == DOES_INTERSECT) ? 1 : 0; } case SECTION: return s1 -> VectorIn (p, v, eps) && s2 -> VectorIn (p, v, eps); case UNION: return s1 -> VectorIn (p, v, eps) || s2 -> VectorIn (p, v, eps); case SUB: return !s1->VectorStrictIn(p, v, eps); case ROOT: return s1->VectorIn(p, v, eps); } return 0; } bool Solid :: VectorStrictIn (const Point<3> & p, const Vec<3> & v, double eps) const { Vec<3> hv; switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->VecInSolid (p, v, eps); return (ist == IS_INSIDE) ? true : false; } case SECTION: return s1 -> VectorStrictIn (p, v, eps) && s2 -> VectorStrictIn (p, v, eps); case UNION: return s1 -> VectorStrictIn (p, v, eps) || s2 -> VectorStrictIn (p, v, eps); case SUB: return !s1->VectorIn(p, v, eps); case ROOT: return s1->VectorStrictIn(p, v, eps); } return 0; } bool Solid::VectorIn2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { if (VectorStrictIn (p, v1, eps)) return 1; if (!VectorIn (p, v1, eps)) return 0; bool res = VectorIn2Rec (p, v1, v2, eps); return res; } bool Solid::VectorIn2Rec (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { switch (op) { case TERM: case TERM_REF: return (prim->VecInSolid2 (p, v1, v2, eps) != IS_OUTSIDE); // Is this correct???? case SECTION: return s1->VectorIn2Rec (p, v1, v2, eps) && s2->VectorIn2Rec (p, v1, v2, eps); case UNION: return s1->VectorIn2Rec (p, v1, v2, eps) || s2->VectorIn2Rec (p, v1, v2, eps); case SUB: return !s1->VectorIn2Rec (p, v1, v2, eps); case ROOT: return s1->VectorIn2Rec (p, v1, v2, eps); } return 0; } void Solid :: Print (ostream & str) const { switch (op) { case TERM: case TERM_REF: { str << prim->GetSurfaceId(0); for (int i = 1; i < prim->GetNSurfaces(); i++) str << "," << prim->GetSurfaceId(i); break; } case SECTION: { str << "("; s1 -> Print (str); str << " AND "; s2 -> Print (str); str << ")"; break; } case UNION: { str << "("; s1 -> Print (str); str << " OR "; s2 -> Print (str); str << ")"; break; } case SUB: { str << " NOT "; s1 -> Print (str); break; } case ROOT: { str << " [" << name << "="; s1 -> Print (str); str << "] "; break; } } } void Solid :: GetSolidData (ostream & ost, int first) const { switch (op) { case SECTION: { ost << "("; s1 -> GetSolidData (ost, 0); ost << " AND "; s2 -> GetSolidData (ost, 0); ost << ")"; break; } case UNION: { ost << "("; s1 -> GetSolidData (ost, 0); ost << " OR "; s2 -> GetSolidData (ost, 0); ost << ")"; break; } case SUB: { ost << "NOT "; s1 -> GetSolidData (ost, 0); break; } case TERM: case TERM_REF: { if (name) ost << name; else ost << "(noname)"; break; } case ROOT: { if (first) s1 -> GetSolidData (ost, 0); else ost << name; break; } } } static Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids); static Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids); static Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids); static void ReadString (istream & ist, char * str) { //char * hstr = str; char ch; while (1) { ist.get(ch); if (!ist.good()) break; if (!isspace (ch)) { ist.putback (ch); break; } } while (1) { ist.get(ch); if (!ist.good()) break; if (isalpha(ch) || isdigit(ch)) { *str = ch; str++; } else { ist.putback (ch); break; } } *str = 0; // cout << "Read string (" << hstr << ")" // << "put back: " << ch << endl; } Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids) { // cout << "create expr" << endl; Solid *s1, *s2; char str[100]; s1 = CreateSolidTerm (ist, solids); ReadString (ist, str); if (strcmp (str, "OR") == 0) { // cout << " OR "; s2 = CreateSolidExpr (ist, solids); return new Solid (Solid::UNION, s1, s2); } // cout << "no OR found, put back string: " << str << endl; for (int i = int(strlen(str))-1; i >= 0; i--) ist.putback (str[i]); return s1; } Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids) { // cout << "create term" << endl; Solid *s1, *s2; char str[100]; s1 = CreateSolidPrim (ist, solids); ReadString (ist, str); if (strcmp (str, "AND") == 0) { // cout << " AND "; s2 = CreateSolidTerm (ist, solids); return new Solid (Solid::SECTION, s1, s2); } // cout << "no AND found, put back string: " << str << endl; for (int i = int(strlen(str))-1; i >= 0; i--) ist.putback (str[i]); return s1; } Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids) { Solid * s1; char ch; char str[100]; ist >> ch; if (ch == '(') { s1 = CreateSolidExpr (ist, solids); ist >> ch; // ')' // cout << "close back " << ch << endl; return s1; } ist.putback (ch); ReadString (ist, str); if (strcmp (str, "NOT") == 0) { // cout << " NOT "; s1 = CreateSolidPrim (ist, solids); return new Solid (Solid::SUB, s1); } (*testout) << "get terminal " << str << endl; s1 = solids[str]; if (s1) { // cout << "primitive: " << str << endl; return s1; } cerr << "syntax error" << endl; return NULL; } Solid * Solid :: CreateSolid (istream & ist, const SymbolTable & solids) { Solid * nsol = CreateSolidExpr (ist, solids); nsol = new Solid (ROOT, nsol); (*testout) << "Print new sol: "; nsol -> Print (*testout); (*testout) << endl; return nsol; } void Solid :: Boundaries (const Point<3> & p, Array & bounds) const { int in, strin; bounds.SetSize (0); RecBoundaries (p, bounds, in, strin); } void Solid :: RecBoundaries (const Point<3> & p, Array & bounds, int & in, int & strin) const { switch (op) { case TERM: case TERM_REF: { /* double val; val = surf->CalcFunctionValue (p); in = (val < 1e-6); strin = (val < -1e-6); if (in && !strin) bounds.Append (id); */ if (prim->PointInSolid (p, 1e-6) == DOES_INTERSECT) bounds.Append (prim->GetSurfaceId (1)); break; } case SECTION: { int i, in1, in2, strin1, strin2; Array bounds1, bounds2; s1 -> RecBoundaries (p, bounds1, in1, strin1); s2 -> RecBoundaries (p, bounds2, in2, strin2); if (in1 && in2) { for (i = 1; i <= bounds1.Size(); i++) bounds.Append (bounds1.Get(i)); for (i = 1; i <= bounds2.Size(); i++) bounds.Append (bounds2.Get(i)); } in = (in1 && in2); strin = (strin1 && strin2); break; } case UNION: { int i, in1, in2, strin1, strin2; Array bounds1, bounds2; s1 -> RecBoundaries (p, bounds1, in1, strin1); s2 -> RecBoundaries (p, bounds2, in2, strin2); if (!strin1 && !strin2) { for (i = 1; i <= bounds1.Size(); i++) bounds.Append (bounds1.Get(i)); for (i = 1; i <= bounds2.Size(); i++) bounds.Append (bounds2.Get(i)); } in = (in1 || in2); strin = (strin1 || strin2); break; } case SUB: { int hin, hstrin; s1 -> RecBoundaries (p, bounds, hin, hstrin); in = !hstrin; strin = !hin; break; } case ROOT: { s1 -> RecBoundaries (p, bounds, in, strin); break; } } } void Solid :: TangentialSolid (const Point<3> & p, Solid *& tansol, Array & surfids, double eps) const { int in, strin; RecTangentialSolid (p, tansol, surfids, in, strin, eps); surfids.SetSize (0); if (tansol) tansol -> GetTangentialSurfaceIndices (p, surfids, eps); } void Solid :: RecTangentialSolid (const Point<3> & p, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const { tansol = NULL; switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->PointInSolid(p, eps); in = (ist == IS_INSIDE || ist == DOES_INTERSECT); strin = (ist == IS_INSIDE); if (ist == DOES_INTERSECT) { tansol = new Solid (prim); tansol -> op = TERM_REF; } break; } case SECTION: { int in1, in2, strin1, strin2; Solid * tansol1, * tansol2; s1 -> RecTangentialSolid (p, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialSolid (p, tansol2, surfids, in2, strin2, eps); if (in1 && in2) { if (tansol1 && tansol2) tansol = new Solid (SECTION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } in = (in1 && in2); strin = (strin1 && strin2); break; } case UNION: { int in1, in2, strin1, strin2; Solid * tansol1 = 0, * tansol2 = 0; s1 -> RecTangentialSolid (p, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialSolid (p, tansol2, surfids, in2, strin2, eps); if (!strin1 && !strin2) { if (tansol1 && tansol2) tansol = new Solid (UNION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } else { delete tansol1; delete tansol2; } in = (in1 || in2); strin = (strin1 || strin2); break; } case SUB: { int hin, hstrin; Solid * tansol1; s1 -> RecTangentialSolid (p, tansol1, surfids, hin, hstrin, eps); if (tansol1) tansol = new Solid (SUB, tansol1); in = !hstrin; strin = !hin; break; } case ROOT: { s1 -> RecTangentialSolid (p, tansol, surfids, in, strin, eps); break; } } } void Solid :: TangentialSolid2 (const Point<3> & p, const Vec<3> & t, Solid *& tansol, Array & surfids, double eps) const { int in, strin; surfids.SetSize (0); RecTangentialSolid2 (p, t, tansol, surfids, in, strin, eps); if (tansol) tansol -> GetTangentialSurfaceIndices2 (p, t, surfids, eps); } void Solid :: RecTangentialSolid2 (const Point<3> & p, const Vec<3> & t, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const { tansol = NULL; switch (op) { case TERM: case TERM_REF: { /* double val; val = surf->CalcFunctionValue (p); in = (val < 1e-6); strin = (val < -1e-6); if (in && !strin) tansol = new Solid (surf, id); */ INSOLID_TYPE ist = prim->PointInSolid(p, eps); if (ist == DOES_INTERSECT) ist = prim->VecInSolid (p, t, eps); in = (ist == IS_INSIDE || ist == DOES_INTERSECT); strin = (ist == IS_INSIDE); if (ist == DOES_INTERSECT) { tansol = new Solid (prim); tansol -> op = TERM_REF; } break; } case SECTION: { int in1, in2, strin1, strin2; Solid * tansol1, * tansol2; s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialSolid2 (p, t, tansol2, surfids, in2, strin2, eps); if (in1 && in2) { if (tansol1 && tansol2) tansol = new Solid (SECTION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } in = (in1 && in2); strin = (strin1 && strin2); break; } case UNION: { int in1, in2, strin1, strin2; Solid * tansol1, * tansol2; s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialSolid2 (p, t, tansol2, surfids, in2, strin2, eps); if (!strin1 && !strin2) { if (tansol1 && tansol2) tansol = new Solid (UNION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } in = (in1 || in2); strin = (strin1 || strin2); break; } case SUB: { int hin, hstrin; Solid * tansol1; s1 -> RecTangentialSolid2 (p, t, tansol1, surfids, hin, hstrin, eps); if (tansol1) tansol = new Solid (SUB, tansol1); in = !hstrin; strin = !hin; break; } case ROOT: { s1 -> RecTangentialSolid2 (p, t, tansol, surfids, in, strin, eps); break; } } } void Solid :: TangentialSolid3 (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, Solid *& tansol, Array & surfids, double eps) const { int in, strin; surfids.SetSize (0); RecTangentialSolid3 (p, t, t2, tansol, surfids, in, strin, eps); if (tansol) tansol -> GetTangentialSurfaceIndices3 (p, t, t2, surfids, eps); } void Solid :: RecTangentialSolid3 (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const { tansol = NULL; switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->PointInSolid(p, eps); if (ist == DOES_INTERSECT) ist = prim->VecInSolid3 (p, t, t2, eps); in = (ist == IS_INSIDE || ist == DOES_INTERSECT); strin = (ist == IS_INSIDE); if (ist == DOES_INTERSECT) { tansol = new Solid (prim); tansol -> op = TERM_REF; } break; } case SECTION: { int in1, in2, strin1, strin2; Solid * tansol1, * tansol2; s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialSolid3 (p, t, t2, tansol2, surfids, in2, strin2, eps); if (in1 && in2) { if (tansol1 && tansol2) tansol = new Solid (SECTION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } in = (in1 && in2); strin = (strin1 && strin2); break; } case UNION: { int in1, in2, strin1, strin2; Solid * tansol1, * tansol2; s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialSolid3 (p, t, t2, tansol2, surfids, in2, strin2, eps); if (!strin1 && !strin2) { if (tansol1 && tansol2) tansol = new Solid (UNION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } in = (in1 || in2); strin = (strin1 || strin2); break; } case SUB: { int hin, hstrin; Solid * tansol1; s1 -> RecTangentialSolid3 (p, t, t2, tansol1, surfids, hin, hstrin, eps); if (tansol1) tansol = new Solid (SUB, tansol1); in = !hstrin; strin = !hin; break; } case ROOT: { s1 -> RecTangentialSolid3 (p, t, t2, tansol, surfids, in, strin, eps); break; } } } void Solid :: TangentialEdgeSolid (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, const Vec<3> & m, Solid *& tansol, Array & surfids, double eps) const { int in, strin; surfids.SetSize (0); // *testout << "tangentialedgesolid,sol = " << (*this) << endl; RecTangentialEdgeSolid (p, t, t2, m, tansol, surfids, in, strin, eps); if (tansol) tansol -> RecGetTangentialEdgeSurfaceIndices (p, t, t2, m, surfids, eps); } void Solid :: RecTangentialEdgeSolid (const Point<3> & p, const Vec<3> & t, const Vec<3> & t2, const Vec<3> & m, Solid *& tansol, Array & surfids, int & in, int & strin, double eps) const { tansol = NULL; switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->PointInSolid(p, eps); /* (*testout) << "tangedgesolid, p = " << p << ", t = " << t << " for prim " << typeid (*prim).name() << " with surf " << prim->GetSurface() << endl; (*testout) << "ist = " << ist << endl; */ if (ist == DOES_INTERSECT) ist = prim->VecInSolid4 (p, t, t2, m, eps); // (*testout) << "ist2 = " << ist << endl; in = (ist == IS_INSIDE || ist == DOES_INTERSECT); strin = (ist == IS_INSIDE); if (ist == DOES_INTERSECT) { tansol = new Solid (prim); tansol -> op = TERM_REF; } break; } case SECTION: { int in1, in2, strin1, strin2; Solid * tansol1, * tansol2; s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialEdgeSolid (p, t, t2, m, tansol2, surfids, in2, strin2, eps); if (in1 && in2) { if (tansol1 && tansol2) tansol = new Solid (SECTION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } in = (in1 && in2); strin = (strin1 && strin2); break; } case UNION: { int in1, in2, strin1, strin2; Solid * tansol1, * tansol2; s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, in1, strin1, eps); s2 -> RecTangentialEdgeSolid (p, t, t2, m, tansol2, surfids, in2, strin2, eps); if (!strin1 && !strin2) { if (tansol1 && tansol2) tansol = new Solid (UNION, tansol1, tansol2); else if (tansol1) tansol = tansol1; else if (tansol2) tansol = tansol2; } in = (in1 || in2); strin = (strin1 || strin2); break; } case SUB: { int hin, hstrin; Solid * tansol1; s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol1, surfids, hin, hstrin, eps); if (tansol1) tansol = new Solid (SUB, tansol1); in = !hstrin; strin = !hin; break; } case ROOT: { s1 -> RecTangentialEdgeSolid (p, t, t2, m, tansol, surfids, in, strin, eps); break; } } } int Solid :: Edge (const Point<3> & p, const Vec<3> & v, double eps) const { int in, strin, faces; RecEdge (p, v, in, strin, faces, eps); return faces >= 2; } int Solid :: OnFace (const Point<3> & p, const Vec<3> & v, double eps) const { int in, strin, faces; RecEdge (p, v, in, strin, faces, eps); return faces >= 1; } void Solid :: RecEdge (const Point<3> & p, const Vec<3> & v, int & in, int & strin, int & faces, double eps) const { switch (op) { case TERM: case TERM_REF: { INSOLID_TYPE ist = prim->VecInSolid (p, v, eps); in = (ist == IS_INSIDE || ist == DOES_INTERSECT); strin = (ist == IS_INSIDE); /* in = VectorIn (p, v); strin = VectorStrictIn (p, v); */ faces = 0; if (in && ! strin) { // faces = 1; int i; Vec<3> grad; for (i = 0; i < prim->GetNSurfaces(); i++) { double val = prim->GetSurface(i).CalcFunctionValue(p); prim->GetSurface(i).CalcGradient (p, grad); if (fabs (val) < eps && fabs (v * grad) < 1e-6) faces++; } } // else // faces = 0; break; } case SECTION: { int in1, in2, strin1, strin2, faces1, faces2; s1 -> RecEdge (p, v, in1, strin1, faces1, eps); s2 -> RecEdge (p, v, in2, strin2, faces2, eps); faces = 0; if (in1 && in2) faces = faces1 + faces2; in = in1 && in2; strin = strin1 && strin2; break; } case UNION: { int in1, in2, strin1, strin2, faces1, faces2; s1 -> RecEdge (p, v, in1, strin1, faces1, eps); s2 -> RecEdge (p, v, in2, strin2, faces2, eps); faces = 0; if (!strin1 && !strin2) faces = faces1 + faces2; in = in1 || in2; strin = strin1 || strin2; break; } case SUB: { int in1, strin1; s1 -> RecEdge (p, v, in1, strin1, faces, eps); in = !strin1; strin = !in1; break; } case ROOT: { s1 -> RecEdge (p, v, in, strin, faces, eps); break; } } } void Solid :: CalcSurfaceInverse () { CalcSurfaceInverseRec (0); } void Solid :: CalcSurfaceInverseRec (int inv) { switch (op) { case TERM: case TERM_REF: { bool priminv; for (int i = 0; i < prim->GetNSurfaces(); i++) { priminv = (prim->SurfaceInverted(i) != 0); if (inv) priminv = !priminv; prim->GetSurface(i).SetInverse (priminv); } break; } case UNION: case SECTION: { s1 -> CalcSurfaceInverseRec (inv); s2 -> CalcSurfaceInverseRec (inv); break; } case SUB: { s1 -> CalcSurfaceInverseRec (1 - inv); break; } case ROOT: { s1 -> CalcSurfaceInverseRec (inv); break; } } } Solid * Solid :: GetReducedSolid (const BoxSphere<3> & box) const { INSOLID_TYPE in; return RecGetReducedSolid (box, in); } Solid * Solid :: RecGetReducedSolid (const BoxSphere<3> & box, INSOLID_TYPE & in) const { if (num_surfs <= 2) { // checking special case for degenerated plane - cylinder, Dec 2014 int cnt_plane = 0, cnt_cyl = 0; bool inv_plane, inv_cyl; Plane * plane; Cylinder * cyl; ForEachSurface ( [&] (Surface * surf, bool inv) { if (dynamic_cast(surf)) { cnt_plane++; plane = dynamic_cast(surf); inv_plane = inv; } if (dynamic_cast(surf)) { cnt_cyl++; cyl = dynamic_cast(surf); inv_cyl = inv; } }); if (cnt_plane == 1 && cnt_cyl == 1) { double scala = (cyl->A()-plane->P()) * plane->N(); double scalb = (cyl->B()-plane->P()) * plane->N(); double scal = plane->N() * plane->N(); if ( ( fabs (scala*scala - cyl->R()*cyl->R()*scal) < 1e-10*cyl->R()*cyl->R() ) && ( fabs (scalb*scalb - cyl->R()*cyl->R()*scal) < 1e-10*cyl->R()*cyl->R() ) ) { // intersection edge in box ? Point<3> p0 = cyl->A() - (scala/scal) * plane->N(); Vec<3> vedge = cyl->B() - cyl->A(); Vec<3> ve_center = box.Center()-p0; // dist(lam) = \| ve_center \|^2 - 2 lam (vedge, ve_center) + lam^2 \| vedge \|^2 double num = vedge*ve_center; double den = vedge*vedge; double dist_edge_center2 = ve_center*ve_center - num * num /den; bool edge_in_box = dist_edge_center2 < sqr (box.Diam()); if (!edge_in_box) { if (op == SECTION) { // cout << "solid = " << *this << endl; if (!inv_cyl && !inv_plane && scala < 0) { // cout << "fix for degenerated cyl-plane edge: just the cylinder" << endl; Solid * sol = new Solid (cyl); sol -> op = TERM_REF; return sol; } } if (op == UNION) { // cout << "solid = " << *this << ", inv_plane = " << inv_plane << " inv_cyl = " << inv_cyl << " scalb " << scalb << endl; if (!inv_plane && !inv_cyl && (scala < 0)) { // cout << "fix for degenerated cyl-plane edge: just the plane" << endl; // return new Solid (plane); Solid * sol = new Solid (plane); sol -> op = TERM_REF; return sol; } } ; // *testout << "have 1 plane and 1 cyl, degenerated" << endl; } } } } Solid * redsol = NULL; switch (op) { case TERM: case TERM_REF: { in = prim -> BoxInSolid (box); if (in == DOES_INTERSECT) { redsol = new Solid (prim); redsol -> op = TERM_REF; } break; } case SECTION: { INSOLID_TYPE in1, in2; Solid * redsol1, * redsol2; redsol1 = s1 -> RecGetReducedSolid (box, in1); redsol2 = s2 -> RecGetReducedSolid (box, in2); if (in1 == IS_OUTSIDE || in2 == IS_OUTSIDE) { if (in1 == DOES_INTERSECT) delete redsol1; if (in2 == DOES_INTERSECT) delete redsol2; in = IS_OUTSIDE; } else { if (in1 == DOES_INTERSECT || in2 == DOES_INTERSECT) in = DOES_INTERSECT; else in = IS_INSIDE; if (in1 == DOES_INTERSECT && in2 == DOES_INTERSECT) redsol = new Solid (SECTION, redsol1, redsol2); else if (in1 == DOES_INTERSECT) redsol = redsol1; else if (in2 == DOES_INTERSECT) redsol = redsol2; } break; } case UNION: { INSOLID_TYPE in1, in2; Solid * redsol1, * redsol2; redsol1 = s1 -> RecGetReducedSolid (box, in1); redsol2 = s2 -> RecGetReducedSolid (box, in2); if (in1 == IS_INSIDE || in2 == IS_INSIDE) { if (in1 == DOES_INTERSECT) delete redsol1; if (in2 == DOES_INTERSECT) delete redsol2; in = IS_INSIDE; } else { if (in1 == DOES_INTERSECT || in2 == DOES_INTERSECT) in = DOES_INTERSECT; else in = IS_OUTSIDE; if (in1 == DOES_INTERSECT && in2 == DOES_INTERSECT) redsol = new Solid (UNION, redsol1, redsol2); else if (in1 == DOES_INTERSECT) redsol = redsol1; else if (in2 == DOES_INTERSECT) redsol = redsol2; } break; } case SUB: { INSOLID_TYPE in1; Solid * redsol1 = s1 -> RecGetReducedSolid (box, in1); switch (in1) { case IS_OUTSIDE: in = IS_INSIDE; break; case IS_INSIDE: in = IS_OUTSIDE; break; case DOES_INTERSECT: in = DOES_INTERSECT; break; } if (redsol1) redsol = new Solid (SUB, redsol1); break; } case ROOT: { INSOLID_TYPE in1; redsol = s1 -> RecGetReducedSolid (box, in1); in = in1; break; } } /* if (redsol) (*testout) << "getrecsolid, redsol = " << endl << (*redsol) << endl; else (*testout) << "redsol is null" << endl; */ return redsol; } int Solid :: NumPrimitives () const { switch (op) { case TERM: case TERM_REF: { return 1; } case UNION: case SECTION: { return s1->NumPrimitives () + s2 -> NumPrimitives(); } case SUB: case ROOT: { return s1->NumPrimitives (); } } return 0; } void Solid :: GetSurfaceIndices (Array & surfind) const { surfind.SetSize (0); RecGetSurfaceIndices (surfind); } void Solid :: RecGetSurfaceIndices (Array & surfind) const { switch (op) { case TERM: case TERM_REF: { /* int i; for (i = 1; i <= surfind.Size(); i++) if (surfind.Get(i) == prim->GetSurfaceId()) return; surfind.Append (prim->GetSurfaceId()); break; */ for (int j = 0; j < prim->GetNSurfaces(); j++) if (prim->SurfaceActive (j)) { bool found = 0; int siprim = prim->GetSurfaceId(j); for (int i = 0; i < surfind.Size(); i++) if (surfind[i] == siprim) { found = 1; break; } if (!found) surfind.Append (siprim); } break; } case UNION: case SECTION: { s1 -> RecGetSurfaceIndices (surfind); s2 -> RecGetSurfaceIndices (surfind); break; } case SUB: case ROOT: { s1 -> RecGetSurfaceIndices (surfind); break; } } } void Solid :: ForEachSurface (const std::function & lambda, bool inv) const { switch (op) { case TERM: case TERM_REF: { for (int j = 0; j < prim->GetNSurfaces(); j++) if (prim->SurfaceActive (j)) lambda (&prim->GetSurface(j), inv); break; } case UNION: case SECTION: { s1 -> ForEachSurface (lambda, inv); s2 -> ForEachSurface (lambda, inv); break; } case SUB: { s1 -> ForEachSurface (lambda, !inv); break; } case ROOT: { s1 -> ForEachSurface (lambda, inv); break; } } } void Solid :: GetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const { surfind.SetSize (0); RecGetTangentialSurfaceIndices (p, surfind, eps); } void Solid :: RecGetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const { switch (op) { case TERM: case TERM_REF: { /* for (int j = 0; j < prim->GetNSurfaces(); j++) if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps) if (!surfind.Contains (prim->GetSurfaceId(j))) surfind.Append (prim->GetSurfaceId(j)); */ prim->GetTangentialSurfaceIndices (p, surfind, eps); break; } case UNION: case SECTION: { s1 -> RecGetTangentialSurfaceIndices (p, surfind, eps); s2 -> RecGetTangentialSurfaceIndices (p, surfind, eps); break; } case SUB: case ROOT: { s1 -> RecGetTangentialSurfaceIndices (p, surfind, eps); break; } } } void Solid :: GetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, Array & surfind, double eps) const { surfind.SetSize (0); RecGetTangentialSurfaceIndices2 (p, v, surfind, eps); } void Solid :: RecGetTangentialSurfaceIndices2 (const Point<3> & p, const Vec<3> & v, Array & surfind, double eps) const { switch (op) { case TERM: case TERM_REF: { for (int j = 0; j < prim->GetNSurfaces(); j++) { if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps) { Vec<3> grad; prim->GetSurface(j).CalcGradient (p, grad); if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2()) { if (!surfind.Contains (prim->GetSurfaceId(j))) surfind.Append (prim->GetSurfaceId(j)); } } } break; } case UNION: case SECTION: { s1 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps); s2 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps); break; } case SUB: case ROOT: { s1 -> RecGetTangentialSurfaceIndices2 (p, v, surfind, eps); break; } } } void Solid :: GetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, Array & surfind, double eps) const { surfind.SetSize (0); RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps); } void Solid :: RecGetTangentialSurfaceIndices3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, Array & surfind, double eps) const { switch (op) { case TERM: case TERM_REF: { for (int j = 0; j < prim->GetNSurfaces(); j++) { if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps) { Vec<3> grad; prim->GetSurface(j).CalcGradient (p, grad); if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2()) { Mat<3> hesse; prim->GetSurface(j).CalcHesse (p, hesse); double hv2 = v2 * grad + v * (hesse * v); if (fabs (hv2) < 1e-6) { if (!surfind.Contains (prim->GetSurfaceId(j))) surfind.Append (prim->GetSurfaceId(j)); } /* else { *testout << "QUAD NOT OK" << endl; *testout << "v = " << v << ", v2 = " << v2 << endl; *testout << "v * grad = " << v*grad << endl; *testout << "v2 * grad = " << v2*grad << endl; *testout << "v H v = " << v*(hesse*v) << endl; *testout << "grad = " << grad << endl; *testout << "hesse = " << hesse << endl; *testout << "hv2 = " << v2 * grad + v * (hesse * v) << endl; } */ } } } break; } case UNION: case SECTION: { s1 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps); s2 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps); break; } case SUB: case ROOT: { s1 -> RecGetTangentialSurfaceIndices3 (p, v, v2, surfind, eps); break; } } } void Solid :: RecGetTangentialEdgeSurfaceIndices (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, Array & surfind, double eps) const { switch (op) { case TERM: case TERM_REF: { // *testout << "check vecinsolid4, p = " << p << ", v = " << v << "; m = " << m << endl; if (prim->VecInSolid4 (p, v, v2, m, eps) == DOES_INTERSECT) { prim->GetTangentialVecSurfaceIndices2 (p, v, m, surfind, eps); /* for (int j = 0; j < prim->GetNSurfaces(); j++) { if (fabs (prim->GetSurface(j).CalcFunctionValue (p)) < eps) { Vec<3> grad; prim->GetSurface(j).CalcGradient (p, grad); *testout << "grad = " << grad << endl; if (sqr (grad * v) < 1e-6 * v.Length2() * grad.Length2() && sqr (grad * m) < 1e-6 * m.Length2() * grad.Length2() ) // new, 18032006 JS { *testout << "add surf " << prim->GetSurfaceId(j) << endl; if (!surfind.Contains (prim->GetSurfaceId(j))) surfind.Append (prim->GetSurfaceId(j)); } } } */ } break; } case UNION: case SECTION: { s1 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps); s2 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps); break; } case SUB: case ROOT: { s1 -> RecGetTangentialEdgeSurfaceIndices (p, v, v2, m, surfind, eps); break; } } } void Solid :: GetSurfaceIndices (IndexSet & iset) const { iset.Clear(); RecGetSurfaceIndices (iset); } void Solid :: RecGetSurfaceIndices (IndexSet & iset) const { switch (op) { case TERM: case TERM_REF: { /* int i; for (i = 1; i <= surfind.Size(); i++) if (surfind.Get(i) == prim->GetSurfaceId()) return; surfind.Append (prim->GetSurfaceId()); break; */ for (int j = 0; j < prim->GetNSurfaces(); j++) if (prim->SurfaceActive (j)) { int siprim = prim->GetSurfaceId(j); iset.Add (siprim); } break; } case UNION: case SECTION: { s1 -> RecGetSurfaceIndices (iset); s2 -> RecGetSurfaceIndices (iset); break; } case SUB: case ROOT: { s1 -> RecGetSurfaceIndices (iset); break; } } } void Solid :: CalcOnePrimitiveSpecialPoints (const Box<3> & box, Array > & pts) const { double eps = 1e-8 * box.Diam (); pts.SetSize (0); this -> RecCalcOnePrimitiveSpecialPoints (pts); for (int i = pts.Size()-1; i >= 0; i--) { if (!IsIn (pts[i],eps) || IsStrictIn (pts[i],eps)) pts.Delete (i); } } void Solid :: RecCalcOnePrimitiveSpecialPoints (Array > & pts) const { switch (op) { case TERM: case TERM_REF: { prim -> CalcSpecialPoints (pts); break; } case UNION: case SECTION: { s1 -> RecCalcOnePrimitiveSpecialPoints (pts); s2 -> RecCalcOnePrimitiveSpecialPoints (pts); break; } case SUB: case ROOT: { s1 -> RecCalcOnePrimitiveSpecialPoints (pts); break; } } } BlockAllocator Solid :: ball(sizeof (Solid)); } netgen-6.2.1905/libsrc/csg/geoml.hpp0000644000175000017500000000106613504650527015652 0ustar kurtkurt#ifndef FILE_GEOML #define FILE_GEOML /* *************************************************************************/ /* File: geoml.hh */ /* Author: Joachim Schoeberl */ /* Date: 21. Jun. 98 */ /* *************************************************************************/ #include #include #include #include #include #endif netgen-6.2.1905/libsrc/csg/polyhedra.cpp0000644000175000017500000004111013504650527016523 0ustar kurtkurt#include #include #include namespace netgen { Polyhedra::Face::Face (int pi1, int pi2, int pi3, const Array > & points, int ainputnr) { inputnr = ainputnr; pnums[0] = pi1; pnums[1] = pi2; pnums[2] = pi3; bbox.Set (points[pi1]); bbox.Add (points[pi2]); bbox.Add (points[pi3]); v1 = points[pi2] - points[pi1]; v2 = points[pi3] - points[pi1]; n = Cross (v1, v2); nn = n; nn.Normalize(); // PseudoInverse (v1, v2, w1, w2); Mat<2,3> mat; Mat<3,2> inv; for (int i = 0; i < 3; i++) { mat(0,i) = v1(i); mat(1,i) = v2(i); } CalcInverse (mat, inv); for (int i = 0; i < 3; i++) { w1(i) = inv(i,0); w2(i) = inv(i,1); } } Polyhedra :: Polyhedra () { surfaceactive.SetSize(0); surfaceids.SetSize(0); eps_base1 = 1e-8; } Polyhedra :: ~Polyhedra () { ; } Primitive * Polyhedra :: CreateDefault () { return new Polyhedra(); } INSOLID_TYPE Polyhedra :: BoxInSolid (const BoxSphere<3> & box) const { /* for (i = 1; i <= faces.Size(); i++) if (FaceBoxIntersection (i, box)) return DOES_INTERSECT; */ for (int i = 0; i < faces.Size(); i++) { if (!faces[i].bbox.Intersect (box)) continue; //(*testout) << "face " << i << endl; const Point<3> & p1 = points[faces[i].pnums[0]]; const Point<3> & p2 = points[faces[i].pnums[1]]; const Point<3> & p3 = points[faces[i].pnums[2]]; if (fabs (faces[i].nn * (p1 - box.Center())) > box.Diam()/2) continue; //(*testout) << "still in loop" << endl; double dist2 = MinDistTP2 (p1, p2, p3, box.Center()); //(*testout) << "p1 " << p1 << " p2 " << p2 << " p3 " << p3 << endl // << " box.Center " << box.Center() << " box.Diam() " << box.Diam() << endl // << " dist2 " << dist2 << " sqr(box.Diam()/2) " << sqr(box.Diam()/2) << endl; if (dist2 < sqr (box.Diam()/2)) { //(*testout) << "DOES_INTERSECT" << endl; return DOES_INTERSECT; } }; return PointInSolid (box.Center(), 1e-3 * box.Diam()); } INSOLID_TYPE Polyhedra :: PointInSolid (const Point<3> & p, double eps) const { //(*testout) << "PointInSolid p " << p << " eps " << eps << endl; //(*testout) << "bbox " << poly_bbox << endl; if((p(0) > poly_bbox.PMax()(0) + eps) || (p(0) < poly_bbox.PMin()(0) - eps) || (p(1) > poly_bbox.PMax()(1) + eps) || (p(1) < poly_bbox.PMin()(1) - eps) || (p(2) > poly_bbox.PMax()(2) + eps) || (p(2) < poly_bbox.PMin()(2) - eps)) { //(*testout) << "returning IS_OUTSIDE" << endl; return IS_OUTSIDE; } Vec<3> n, v1, v2; // random (?) numbers: n(0) = -0.424621; n(1) = 0.15432; n(2) = 0.89212238; int cnt = 0; for (int i = 0; i < faces.Size(); i++) { const Point<3> & p1 = points[faces[i].pnums[0]]; Vec<3> v0 = p - p1; double lam3 = faces[i].nn * v0; if(fabs(lam3) < eps) { double lam1 = (faces[i].w1 * v0); double lam2 = (faces[i].w2 * v0); if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1) { //(*testout) << "returning DOES_INTERSECT" << endl; return DOES_INTERSECT; } } else { lam3 = -(faces[i].n * v0) / (faces[i].n * n); if (lam3 < 0) continue; Vec<3> rs = v0 + lam3 * n; double lam1 = (faces[i].w1 * rs); double lam2 = (faces[i].w2 * rs); if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1) cnt++; } } //(*testout) << " cnt = " << cnt%2 << endl; return (cnt % 2) ? IS_INSIDE : IS_OUTSIDE; } void Polyhedra :: GetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const { for (int i = 0; i < faces.Size(); i++) { const Point<3> & p1 = points[faces[i].pnums[0]]; Vec<3> v0 = p - p1; double lam3 = -(faces[i].nn * v0); // n->nn if (fabs (lam3) > eps) continue; double lam1 = (faces[i].w1 * v0); double lam2 = (faces[i].w2 * v0); if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1) if (!surfind.Contains (GetSurfaceId(i))) surfind.Append (GetSurfaceId(i)); } } INSOLID_TYPE Polyhedra :: VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const { Array point_on_faces; INSOLID_TYPE res(DOES_INTERSECT); Vec<3> vn = v; vn.Normalize(); for (int i = 0; i < faces.Size(); i++) { const Point<3> & p1 = points[faces[i].pnums[0]]; Vec<3> v0 = p - p1; double lam3 = -(faces[i].nn * v0); // n->nn if (fabs (lam3) > eps) continue; //(*testout) << "lam3 <= eps" << endl; double lam1 = (faces[i].w1 * v0); double lam2 = (faces[i].w2 * v0); if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1) { point_on_faces.Append(i); double scal = vn * faces[i].nn; // n->nn res = DOES_INTERSECT; if (scal > eps_base1) res = IS_OUTSIDE; if (scal < -eps_base1) res = IS_INSIDE; } } //(*testout) << "point_on_faces.Size() " << point_on_faces.Size() // << " res " << res << endl; if (point_on_faces.Size() == 0) return PointInSolid (p, 0); if (point_on_faces.Size() == 1) return res; double mindist(0); bool first = true; for(int i=0; i eps && (first || dist < mindist)) { mindist = dist; first = false; } } } Point<3> p2 = p + (1e-2*mindist) * vn; res = PointInSolid (p2, eps); // (*testout) << "mindist " << mindist << " res " << res << endl; return res; } /* INSOLID_TYPE Polyhedra :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { INSOLID_TYPE res; res = VecInSolid(p,v1,eps); if(res != DOES_INTERSECT) return res; int point_on_n_faces = 0; Vec<3> v1n = v1; v1n.Normalize(); Vec<3> v2n = v2; v2n.Normalize(); for (int i = 0; i < faces.Size(); i++) { const Point<3> & p1 = points[faces[i].pnums[0]]; Vec<3> v0 = p - p1; double lam3 = -(faces[i].n * v0); if (fabs (lam3) > eps) continue; double lam1 = (faces[i].w1 * v0); double lam2 = (faces[i].w2 * v0); if (lam1 >= -eps && lam2 >= -eps && lam1+lam2 <= 1+eps) { double scal1 = v1n * faces[i].n; if (fabs (scal1) > eps) continue; point_on_n_faces++; double scal2 = v2n * faces[i].n; res = DOES_INTERSECT; if (scal2 > eps) res = IS_OUTSIDE; if (scal2 < -eps) res = IS_INSIDE; } } if (point_on_n_faces == 1) return res; cerr << "primitive::vecinsolid2 makes nonsense for polyhedra" << endl; return Primitive :: VecInSolid2 (p, v1, v2, eps); } */ INSOLID_TYPE Polyhedra :: VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const { //(*testout) << "VecInSolid2 eps " << eps << endl; INSOLID_TYPE res = VecInSolid(p,v1,eps); //(*testout) << "VecInSolid = " < v1n = v1; v1n.Normalize(); Vec<3> v2n = v2 - (v2 * v1n) * v1n; v2n.Normalize(); double cosv2, cosv2max = -99; for (int i = 0; i < faces.Size(); i++) { const Point<3> & p1 = points[faces[i].pnums[0]]; Vec<3> v0 = p - p1; if (fabs (faces[i].nn * v0) > eps) continue; // n->nn if (fabs (v1n * faces[i].nn) > eps_base1) continue; // n->nn double lam1 = (faces[i].w1 * v0); double lam2 = (faces[i].w2 * v0); if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam1+lam2 <= 1+eps_base1) { // v1 is in face Point<3> fc = Center (points[faces[i].pnums[0]], points[faces[i].pnums[1]], points[faces[i].pnums[2]]); Vec<3> vpfc = fc - p; cosv2 = (v2n * vpfc) / vpfc.Length(); if (cosv2 > cosv2max) { cosv2max = cosv2; point_on_n_faces++; double scal2 = v2n * faces[i].nn; // n->nn res = DOES_INTERSECT; if (scal2 > eps_base1) res = IS_OUTSIDE; if (scal2 < -eps_base1) res = IS_INSIDE; } } } if (point_on_n_faces >= 1) return res; (*testout) << "primitive::vecinsolid2 makes nonsense for polyhedra" << endl; cerr << "primitive::vecinsolid2 makes nonsense for polyhedra" << endl; return Primitive :: VecInSolid2 (p, v1, v2, eps); } void Polyhedra :: GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, Array & surfind, double eps) const { Vec<3> v1n = v1; v1n.Normalize(); Vec<3> v2n = v2; // - (v2 * v1n) * v1n; v2n.Normalize(); for (int i = 0; i < faces.Size(); i++) { const Point<3> & p1 = points[faces[i].pnums[0]]; Vec<3> v0 = p - p1; if (fabs (v0 * faces[i].nn) > eps) continue; // n->nn if (fabs (v1n * faces[i].nn) > eps_base1) continue; // n->nn if (fabs (v2n * faces[i].nn) > eps_base1) continue; // n->nn double lam01 = (faces[i].w1 * v0); double lam02 = (faces[i].w2 * v0); double lam03 = 1-lam01-lam02; double lam11 = (faces[i].w1 * v1); double lam12 = (faces[i].w2 * v1); double lam13 = -lam11-lam12; double lam21 = (faces[i].w1 * v2); double lam22 = (faces[i].w2 * v2); double lam23 = -lam21-lam22; bool ok1 = lam01 > eps_base1 || (lam01 > -eps_base1 && lam11 > eps_base1) || (lam01 > -eps_base1 && lam11 > -eps_base1 && lam21 > eps_base1); bool ok2 = lam02 > eps_base1 || (lam02 > -eps_base1 && lam12 > eps_base1) || (lam02 > -eps_base1 && lam12 > -eps_base1 && lam22 > eps_base1); bool ok3 = lam03 > eps_base1 || (lam03 > -eps_base1 && lam13 > eps_base1) || (lam03 > -eps_base1 && lam13 > -eps_base1 && lam23 > eps_base1); if (ok1 && ok2 && ok3) { if (!surfind.Contains (GetSurfaceId(faces[i].planenr))) surfind.Append (GetSurfaceId(faces[i].planenr)); } } } void Polyhedra :: GetPrimitiveData (const char *& classname, Array & coeffs) const { classname = "Polyhedra"; coeffs.SetSize(0); coeffs.Append (points.Size()); coeffs.Append (faces.Size()); coeffs.Append (planes.Size()); /* int i, j; for (i = 1; i <= planes.Size(); i++) { planes.Elem(i)->Print (*testout); } for (i = 1; i <= faces.Size(); i++) { (*testout) << "face " << i << " has plane " << faces.Get(i).planenr << endl; for (j = 1; j <= 3; j++) (*testout) << points.Get(faces.Get(i).pnums[j-1]); (*testout) << endl; } */ } void Polyhedra :: SetPrimitiveData (Array & /* coeffs */) { ; } void Polyhedra :: Reduce (const BoxSphere<3> & box) { for (int i = 0; i < planes.Size(); i++) surfaceactive[i] = 0; for (int i = 0; i < faces.Size(); i++) if (FaceBoxIntersection (i, box)) surfaceactive[faces[i].planenr] = 1; } void Polyhedra :: UnReduce () { for (int i = 0; i < planes.Size(); i++) surfaceactive[i] = 1; } int Polyhedra :: AddPoint (const Point<3> & p) { if(points.Size() == 0) poly_bbox.Set(p); else poly_bbox.Add(p); points.Append (p); return points.Size(); } int Polyhedra :: AddFace (int pi1, int pi2, int pi3, int inputnum) { (*testout) << "polyhedra, add face " << pi1 << ", " << pi2 << ", " << pi3 << endl; if(pi1 == pi2 || pi2 == pi3 || pi3 == pi1) { ostringstream msg; msg << "Illegal point numbers for polyhedron face: " << pi1+1 << ", " << pi2+1 << ", " << pi3+1; throw NgException(msg.str()); } faces.Append (Face (pi1, pi2, pi3, points, inputnum)); Point<3> p1 = points[pi1]; Point<3> p2 = points[pi2]; Point<3> p3 = points[pi3]; Vec<3> v1 = p2 - p1; Vec<3> v2 = p3 - p1; Vec<3> n = Cross (v1, v2); n.Normalize(); Plane pl (p1, n); // int inverse; // int identicto = -1; // for (int i = 0; i < planes.Size(); i++) // if (pl.IsIdentic (*planes[i], inverse, 1e-9*max3(v1.Length(),v2.Length(),Dist(p2,p3)))) // { // if (!inverse) // identicto = i; // } // // cout << "is identic = " << identicto << endl; // identicto = -1; // changed April 10, JS // if (identicto != -1) // faces.Last().planenr = identicto; // else { planes.Append (new Plane (p1, n)); surfaceactive.Append (1); surfaceids.Append (0); faces.Last().planenr = planes.Size()-1; } // (*testout) << "is plane nr " << faces.Last().planenr << endl; return faces.Size(); } int Polyhedra :: FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const { /* (*testout) << "check face box intersection, fnr = " << fnr << endl; (*testout) << "box = " << box << endl; (*testout) << "face-box = " << faces[fnr].bbox << endl; */ if (!faces[fnr].bbox.Intersect (box)) return 0; const Point<3> & p1 = points[faces[fnr].pnums[0]]; const Point<3> & p2 = points[faces[fnr].pnums[1]]; const Point<3> & p3 = points[faces[fnr].pnums[2]]; double dist2 = MinDistTP2 (p1, p2, p3, box.Center()); /* (*testout) << "p1 = " << p1 << endl; (*testout) << "p2 = " << p2 << endl; (*testout) << "p3 = " << p3 << endl; (*testout) << "box.Center() = " << box.Center() << endl; (*testout) << "center = " << box.Center() << endl; (*testout) << "dist2 = " << dist2 << endl; (*testout) << "diam = " << box.Diam() << endl; */ if (dist2 < sqr (box.Diam()/2)) { // (*testout) << "intersect" << endl; return 1; } return 0; } void Polyhedra :: GetPolySurfs(Array < Array * > & polysurfs) { int maxnum = -1; for(int i = 0; i maxnum) maxnum = faces[i].inputnr; } polysurfs.SetSize(maxnum+1); for(int i=0; i; for(int i = 0; iAppend(faces[i].planenr); } void Polyhedra::CalcSpecialPoints (Array > & pts) const { for (int i = 0; i < points.Size(); i++) pts.Append (points[i]); } void Polyhedra :: AnalyzeSpecialPoint (const Point<3> & /* pt */, Array > & /* specpts */) const { ; } Vec<3> Polyhedra :: SpecialPointTangentialVector (const Point<3> & p, int s1, int s2) const { const double eps = 1e-10*poly_bbox.Diam(); for (int fi1 = 0; fi1 < faces.Size(); fi1++) for (int fi2 = 0; fi2 < faces.Size(); fi2++) { int si1 = faces[fi1].planenr; int si2 = faces[fi2].planenr; if (surfaceids[si1] != s1 || surfaceids[si2] != s2) continue; //(*testout) << "check pair fi1/fi2 " << fi1 << "/" << fi2 << endl; Vec<3> n1 = GetSurface(si1) . GetNormalVector (p); Vec<3> n2 = GetSurface(si2) . GetNormalVector (p); Vec<3> t = Cross (n1, n2); //(*testout) << "t = " << t << endl; /* int samepts = 0; for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) if (Dist(points[faces[fi1].pnums[j]], points[faces[fi2].pnums[k]]) < eps) samepts++; if (samepts < 2) continue; */ bool shareedge = false; for(int j = 0; !shareedge && j < 3; j++) { Vec<3> v1 = points[faces[fi1].pnums[(j+1)%3]] - points[faces[fi1].pnums[j]]; double smax = v1.Length(); v1 *= 1./smax; int pospos; if(fabs(v1(0)) > 0.5) pospos = 0; else if(fabs(v1(1)) > 0.5) pospos = 1; else pospos = 2; double sp = (p(pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos); if(sp < -eps || sp > smax+eps) continue; for (int k = 0; !shareedge && k < 3; k ++) { Vec<3> v2 = points[faces[fi2].pnums[(k+1)%3]] - points[faces[fi2].pnums[k]]; v2.Normalize(); if(v2 * v1 > 0) v2 -= v1; else v2 += v1; //(*testout) << "v2.Length2() " << v2.Length2() << endl; if(v2.Length2() > 1e-18) continue; double sa,sb; sa = (points[faces[fi2].pnums[k]](pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos); sb = (points[faces[fi2].pnums[(k+1)%3]](pospos) - points[faces[fi1].pnums[j]](pospos)) / v1(pospos); if(Dist(points[faces[fi1].pnums[j]] + sa*v1, points[faces[fi2].pnums[k]]) > eps) continue; if(sa > sb) { double aux = sa; sa = sb; sb = aux; } //testout->precision(20); //(*testout) << "sa " << sa << " sb " << sb << " smax " << smax << " sp " << sp << " v1 " << v1 << endl; //testout->precision(8); shareedge = (sa < -eps && sb > eps) || (sa < smax-eps && sb > smax+eps) || (sa > -eps && sb < smax+eps); if(!shareedge) continue; sa = max2(sa,0.); sb = min2(sb,smax); if(sp < sa+eps) shareedge = (t * v1 > 0); else if (sp > sb-eps) shareedge = (t * v1 < 0); } } if (!shareedge) continue; t.Normalize(); return t; } return Vec<3> (0,0,0); } } netgen-6.2.1905/libsrc/csg/identify.cpp0000644000175000017500000011133013504650527016351 0ustar kurtkurt#include #include #include #include #include namespace netgen { Identification :: Identification (int anr, const CSGeometry & ageom) : geom(ageom), identfaces(10) { nr = anr; } Identification :: ~Identification () { ; } ostream & operator<< (ostream & ost, Identification & ident) { ident.Print (ost); return ost; } /* void Identification :: IdentifySpecialPoints (Array & points) { ; } */ int Identification :: Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const { cout << "Identification::Identifyable called for base-class" << endl; return 0; } int Identification :: Identifyable (const Point<3> & p1, const Point<3> & sp2) const { cout << "Identification::Identifyable called for base-class" << endl; return 0; } int Identification :: IdentifyableCandidate (const SpecialPoint & sp1) const { return 1; } int Identification :: ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const { return 0; } int Identification :: GetIdentifiedPoint (class Mesh & mesh, int pi) { cout << "Identification::GetIdentifiedPoint called for base-class" << endl; return -1; } void Identification :: IdentifyPoints (Mesh & mesh) { cout << "Identification::IdentifyPoints called for base-class" << endl; ; } void Identification :: IdentifyFaces (class Mesh & mesh) { cout << "Identification::IdentifyFaces called for base-class" << endl; ; } void Identification :: BuildSurfaceElements (Array & segs, Mesh & mesh, const Surface * surf) { cout << "Identification::BuildSurfaceElements called for base-class" << endl; ; } void Identification :: BuildVolumeElements (Array & surfels, class Mesh & mesh) { ; } void Identification :: GetIdentifiedFaces (Array & idfaces) const { idfaces.SetSize(0); for (int i = 1; i <= identfaces.GetNBags(); i++) for (int j = 1; j <= identfaces.GetBagSize(i); j++) { INDEX_2 i2; int val; identfaces.GetData (i, j, i2, val); idfaces.Append (i2); } } PeriodicIdentification :: PeriodicIdentification (int anr, const CSGeometry & ageom, const Surface * as1, const Surface * as2, Transformation<3> atrafo) : Identification(anr, ageom), trafo(atrafo) { inv_trafo = trafo.CalcInverse(); s1 = as1; s2 = as2; } PeriodicIdentification :: ~PeriodicIdentification () { ; } /* void PeriodicIdentification :: IdentifySpecialPoints (Array & points) { int i, j; int bestj; double bestval, val; for (i = 1; i <= points.Size(); i++) { Point<3> p1 = points.Get(i).p; Point<3> hp1 = p1; s1->Project (hp1); if (Dist (p1, hp1) > 1e-6) continue; Vec<3> n1; s1->GetNormalVector (p1, n1); n1 /= n1.Length(); if ( fabs(n1 * points.Get(i).v) > 1e-3) continue; bestval = 1e8; bestj = 1; for (j = 1; j <= points.Size(); j++) { Point<3> p2= points.Get(j).p; Point<3> hp2 = p2; s2->Project (hp2); if (Dist (p2, hp2) > 1e-6) continue; Vec<3> n2; s2->GetNormalVector (p2, n2); n2 /= n2.Length(); if ( fabs(n2 * points.Get(j).v) > 1e-3) continue; Vec<3> v(p1, p2); double vl = v.Length(); double cl = fabs (v*n1); val = 1 - cl*cl/(vl*vl); val += (points.Get(i).v - points.Get(j).v).Length(); if (val < bestval) { bestj = j; bestval = val; } } (*testout) << "Identify Periodic special points: pi = " << points.Get(i).p << ", vi = " << points.Get(i).v << " pj = " << points.Get(bestj).p << ", vj = " << points.Get(bestj).v << " bestval = " << bestval << endl; } } */ int PeriodicIdentification :: Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const { SpecialPoint hsp1 = sp1; SpecialPoint hsp2 = sp2; for (int i = 1; i <= 1; i++) { // Swap (hsp1, hsp2); if (!s1->PointOnSurface (hsp1.p)) continue; Vec<3> n1; n1 = s1->GetNormalVector (hsp1.p); n1 /= n1.Length(); if ( fabs(n1 * hsp1.v) > 1e-3) continue; if (!s2->PointOnSurface(hsp2.p)) continue; Vec<3> n2; n2 = s2->GetNormalVector (hsp2.p); n2 /= n2.Length(); if ( fabs(n2 * hsp2.v) > 1e-3) continue; if ((trafo(hsp1.v)-hsp2.v).Length2() > 1e-12) return false; double d2typ = Dist2(hsp1.p, hsp2.p); if (Dist2 (trafo(hsp1.p),hsp2.p) < 1e-18*d2typ) return true; if (Dist2 (hsp1.p, trafo(hsp1.p)) < 1e-18*d2typ) { // old style without trafo, but normal projection Vec<3> v = hsp2.p - hsp1.p; double vl = v.Length(); double cl = fabs (v*n1); double val1 = 1 - cl*cl/(vl*vl); double val2 = (hsp1.v - hsp2.v).Length(); if (val1 < 1e-10 && val2 < 1e-6) return true; } } return false; } int PeriodicIdentification :: Identifyable (const Point<3> & p1, const Point<3> & p2) const { return (s1->PointOnSurface (p1) && s2->PointOnSurface (p2)); } int PeriodicIdentification :: GetIdentifiedPoint (class Mesh & mesh, int pi) { const Surface *snew; const Point<3> & p = mesh.Point (pi); Point<3> hp = p; if (s1->PointOnSurface (p)) { snew = s2; hp = trafo(hp); } else { if (s2->PointOnSurface (p)) { snew = s1; hp = inv_trafo(hp); } else { throw NgException("GetIdenfifiedPoint: Not possible"); } } // project to other surface snew->Project (hp); int newpi = 0; for (int i = 1; i <= mesh.GetNP(); i++) if (Dist2 (mesh.Point(i), hp) < 1e-12) { newpi = i; break; } if (!newpi) newpi = mesh.AddPoint (hp); if (snew == s2) mesh.GetIdentifications().Add (pi, newpi, nr); else mesh.GetIdentifications().Add (newpi, pi, nr); mesh.GetIdentifications().SetType(nr,Identifications::PERIODIC); /* (*testout) << "Identify points(periodic), nr = " << nr << ": " << mesh.Point(pi) << " and " << mesh.Point(newpi) << ((snew == s2) ? "" : " inverse") << endl; */ return newpi; } void PeriodicIdentification :: IdentifyPoints (class Mesh & mesh) { for (int i = 1; i <= mesh.GetNP(); i++) { Point<3> p = mesh.Point(i); if (s1->PointOnSurface (p)) { Point<3> pp = p; pp = trafo(pp); s2->Project (pp); for (int j = 1; j <= mesh.GetNP(); j++) if (Dist2(mesh.Point(j), pp) < 1e-6) { mesh.GetIdentifications().Add (i, j, nr); /* (*testout) << "Identify points(periodic:), nr = " << nr << ": " << mesh.Point(i) << " - " << mesh.Point(j) << endl; */ } } } mesh.GetIdentifications().SetType(nr,Identifications::PERIODIC); } void PeriodicIdentification :: IdentifyFaces (class Mesh & mesh) { int i, j, k, l; int fi1, fi2, side; for (i = 1; i <= mesh.GetNFD(); i++) for (j = 1; j <= mesh.GetNFD(); j++) { int surfi = mesh.GetFaceDescriptor(i).SurfNr(); int surfj = mesh.GetFaceDescriptor(j).SurfNr(); if (surfi == surfj) continue; if (geom.GetSurface (surfi) != s1 || geom.GetSurface (surfj) != s2) continue; int idok = 1; // (*testout) << "check faces " << i << " and " << j << endl; for (side = 1; side <= 2 && idok; side++) { if (side == 1) { fi1 = i; fi2 = j; } else { fi1 = j; fi2 = i; } for (k = 1; k <= mesh.GetNSeg(); k++) { const Segment & seg1 = mesh.LineSegment(k); if (seg1.si != fi1) continue; int foundother = 0; for (l = 1; l <= mesh.GetNSeg(); l++) { const Segment & seg2 = mesh.LineSegment(l); if (seg2.si != fi2) continue; // (*testout) << "seg1 = " << seg1[0] << "-" << seg1[1] << ", seg2 = " << seg2[0] << "-" << seg2[1]; if (side == 1) { if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) && mesh.GetIdentifications().Get (seg1[1], seg2[1])) { foundother = 1; break; } if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) && mesh.GetIdentifications().Get (seg1[1], seg2[0])) { foundother = 1; break; } } else { if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) && mesh.GetIdentifications().Get (seg2[1], seg1[1])) { foundother = 1; break; } if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) && mesh.GetIdentifications().Get (seg2[1], seg1[0])) { foundother = 1; break; } } } if (!foundother) { idok = 0; break; } } } if (idok) { // (*testout) << "Identify faces " << i << " and " << j << endl; INDEX_2 fpair(i,j); fpair.Sort(); identfaces.Set (fpair, 1); } } } void PeriodicIdentification :: BuildSurfaceElements (Array & segs, Mesh & mesh, const Surface * surf) { int found = 0; int fother = -1; int facei = segs.Get(1).si; int surfnr = mesh.GetFaceDescriptor(facei).SurfNr(); if (geom.GetSurface(surfnr) == s1 || geom.GetSurface(surfnr) == s2) { Array copy_points; for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & sel = mesh[sei]; INDEX_2 fpair (facei, sel.GetIndex()); fpair.Sort(); if (identfaces.Used (fpair)) { for (int k = 0; k < sel.GetNP(); k++) if (!copy_points.Contains (sel[k])) copy_points.Append (sel[k]); } } BubbleSort (copy_points); for (int k = 0; k < copy_points.Size(); k++) GetIdentifiedPoint (mesh, copy_points[k]); for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & sel = mesh[sei]; INDEX_2 fpair (facei, sel.GetIndex()); fpair.Sort(); if (identfaces.Used (fpair)) { found = 1; fother = sel.GetIndex(); // copy element Element2d newel(sel.GetType()); newel.SetIndex (facei); for (int k = 0; k < sel.GetNP(); k++) newel[k] = GetIdentifiedPoint (mesh, sel[k]); Vec<3> nt = Cross (Point<3> (mesh[newel[1]])- Point<3> (mesh[newel[0]]), Point<3> (mesh[newel[2]])- Point<3> (mesh[newel[0]])); Vec<3> nsurf = geom.GetSurface (surfnr)->GetNormalVector (mesh[newel[0]]); if (nsurf * nt < 0) Swap (newel[0], newel[2]); mesh.AddSurfaceElement (newel); } } } if (found) { // (*mycout) << " copy face " << facei << " from face " << fother; PrintMessage (4, " copy face ", facei, " from face ", fother); segs.SetSize(0); } } void PeriodicIdentification :: Print (ostream & ost) const { ost << "Periodic Identifiaction, surfaces: " << s1->Name() << " - " << s2->Name() << endl; s1->Print (ost); ost << " - "; s2->Print (ost); ost << endl; } void PeriodicIdentification :: GetData (ostream & ost) const { ost << "periodic " << s1->Name() << " " << s2->Name(); } CloseSurfaceIdentification :: CloseSurfaceIdentification (int anr, const CSGeometry & ageom, const Surface * as1, const Surface * as2, const TopLevelObject * adomain, const Flags & flags) : Identification(anr, ageom) { s1 = as1; s2 = as2; domain = adomain; ref_levels = int (flags.GetNumFlag ("reflevels", 2)); ref_levels_s1 = int (flags.GetNumFlag ("reflevels1", 0)); ref_levels_s2 = int (flags.GetNumFlag ("reflevels2", 0)); slices = flags.GetNumListFlag ("slices"); for(int i=0; i0 && slices[i] <= slices[i-1]) || (slices[i] >= 1)) throw NgException ("slices have to be in ascending order, between 0 and 1"); // eps_n = 1e-3; eps_n = 1e-6; dom_surf_valid = 0; if (domain) for (int i = 0; i < geom.GetNTopLevelObjects(); i++) if (domain == geom.GetTopLevelObject(i)) dom_nr = i; usedirection = flags.NumListFlagDefined("direction"); if(usedirection) { for(int i=0; i<3; i++) direction(i) = flags.GetNumListFlag("direction")[i]; direction.Normalize(); } } CloseSurfaceIdentification :: ~CloseSurfaceIdentification () { ; } void CloseSurfaceIdentification :: Print (ostream & ost) const { ost << "CloseSurface Identifiaction, surfaces: " << s1->Name() << " - " << s2->Name() << endl; s1->Print (ost); s2->Print (ost); ost << endl; } void CloseSurfaceIdentification :: GetData (ostream & ost) const { ost << "close surface " << s1->Name() << " " << s2->Name(); } /* void CloseSurfaceIdentification :: IdentifySpecialPoints (Array & points) { int i, j; int bestj; double bestval, val; for (i = 1; i <= points.Size(); i++) { Point<3> p1 = points.Get(i).p; Vec<3> n1; if (!s1->PointOnSurface (p1)) continue; s1->GetNormalVector (p1, n1); n1 /= n1.Length(); if ( fabs(n1 * points.Get(i).v) > 1e-3) continue; bestval = 1e8; bestj = 1; for (j = 1; j <= points.Size(); j++) { Point<3> p2= points.Get(j).p; if (!s2->PointOnSurface (p2)) continue; Vec<3> n2; s2->GetNormalVector (p2, n2); n2 /= n2.Length(); if ( fabs(n2 * points.Get(j).v) > 1e-3) continue; Vec<3> v(p1, p2); double vl = v.Length(); double cl = fabs (v*n1); val = 1 - cl*cl/(vl*vl); val += (points.Get(i).v - points.Get(j).v).Length(); if (val < bestval) { bestj = j; bestval = val; } } (*testout) << "Identify close surfaces special points: pi = " << points.Get(i).p << ", vi = " << points.Get(i).v << " pj = " << points.Get(bestj).p << ", vj = " << points.Get(bestj).v << " bestval = " << bestval << endl; } } */ int CloseSurfaceIdentification :: Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const { //(*testout) << "identcheck: " << sp1.p << "; " << sp2.p << endl; if (!dom_surf_valid) { const_cast (dom_surf_valid) = 1; Array & hsurf = const_cast&> (domain_surfaces); if (domain) { BoxSphere<3> hbox (geom.BoundingBox()); geom.GetIndependentSurfaceIndices (domain->GetSolid(), hbox, hsurf); //(*testout) << "surfs of identification " << nr << ": " << endl << hsurf << endl; } else { hsurf.SetSize (geom.GetNSurf()); for (int j = 0; j < hsurf.Size(); j++) hsurf[j] = j; } } if (domain) { bool has1 = 0, has2 = 0; for (int i = 0; i < specpoint2solid[sp1.nr].Size(); i++) if (specpoint2solid[sp1.nr][i] == dom_nr) { has1 = 1; break; } for (int i = 0; i < specpoint2solid[sp2.nr].Size(); i++) if (specpoint2solid[sp2.nr][i] == dom_nr) { has2 = 1; break; } if (!has1 || !has2) { //(*testout) << "failed at pos1" << endl; return 0; } } if (!s1->PointOnSurface (sp1.p)) { //(*testout) << "failed at pos2" << endl; return 0; } // (*testout) << "sp1 " << sp1.p << " sp2 " << sp2.p << endl // << "specpoint2solid[sp1.nr] " << specpoint2solid[sp1.nr] << endl // << "specpoint2solid[sp2.nr] " << specpoint2solid[sp2.nr] << endl; Vec<3> n1 = s1->GetNormalVector (sp1.p); n1.Normalize(); if ( fabs(n1 * sp1.v) > eps_n) { //(*testout) << "failed at pos3" << endl; return 0; } if (!s2->PointOnSurface(sp2.p)) { //(*testout) << "failed at pos4" << endl; return 0; } Vec<3> n2 = s2->GetNormalVector (sp2.p); n2.Normalize(); if ( fabs(n2 * sp2.v) > eps_n) { //(*testout) << "failed at pos5" << endl; return 0; } // must have joint surface bool joint = 0; int j = 0, k = 0; while (1) { int snr1 = specpoint2surface[sp1.nr][j]; int snr2 = specpoint2surface[sp2.nr][k]; if (snr1 < snr2) { j++; if (j == specpoint2surface[sp1.nr].Size()) break; } else if (snr2 < snr1) { k++; if (k == specpoint2surface[sp2.nr].Size()) break; } else { bool dom_surf = 0; for (int l = 0; l < domain_surfaces.Size(); l++) if (domain_surfaces[l] == snr1) dom_surf = 1; if (dom_surf) { Vec<3> hn1 = geom.GetSurface(snr1)->GetNormalVector (sp1.p); Vec<3> hn2 = geom.GetSurface(snr1)->GetNormalVector (sp2.p); if (hn1 * hn2 > 0) { joint = 1; break; } } j++; if (j == specpoint2surface[sp1.nr].Size()) break; k++; if (k == specpoint2surface[sp2.nr].Size()) break; } } if (!joint) { //(*testout) << "failed at pos6" << endl; return 0; } Vec<3> v = sp2.p - sp1.p; double vl = v.Length(); double cl = (usedirection) ? fabs(v*direction) : fabs (v*n1); if(cl <= (1-eps_n*eps_n) * vl) { //(*testout) << "failed at pos7" << endl; return 0; } double dl; if(usedirection) { Vec<3> v1 = sp1.v - (sp1.v*direction)*direction; v1.Normalize(); Vec<3> v2 = sp2.v - (sp2.v*direction)*direction; v2.Normalize(); dl = (v1 - v2).Length(); } else dl = (sp1.v - sp2.v).Length(); if (dl < 0.1) return 1; //(*testout) << "failed at pos8" << endl; return 0; } int CloseSurfaceIdentification :: Identifyable (const Point<3> & p1, const Point<3> & p2) const { // if (domain) // if (!domain->GetSolid()->IsIn (p1) || !domain->GetSolid()->IsIn (p2)) // return 0; return (s1->PointOnSurface (p1) && s2->PointOnSurface (p2)); } int CloseSurfaceIdentification :: IdentifyableCandidate (const SpecialPoint & sp1) const { if (domain) if (!domain->GetSolid()->IsIn (sp1.p)) return 0; if (s1->PointOnSurface (sp1.p)) { Vec<3> n1; n1 = s1->GetNormalVector (sp1.p); n1.Normalize(); if ( fabs(n1 * sp1.v) > eps_n) return 0; return 1; } if (s2->PointOnSurface (sp1.p)) { Vec<3> n1; n1 = s2->GetNormalVector (sp1.p); n1.Normalize(); if ( fabs(n1 * sp1.v) > eps_n) return 0; return 1; } return 0; } int CloseSurfaceIdentification :: ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const { if ( (s1->PointOnSurface (sp1.p) && s2->PointOnSurface (sp2.p)) || (s1->PointOnSurface (sp2.p) && s2->PointOnSurface (sp1.p)) ) { return 1; } return 0; } int CloseSurfaceIdentification :: GetIdentifiedPoint (class Mesh & mesh, int pi) { const Surface *snew; const Point<3> & p = mesh.Point (pi); Array identmap(mesh.GetNP()); mesh.GetIdentifications().GetMap (nr, identmap); if (identmap.Get(pi)) return identmap.Get(pi); if (s1->PointOnSurface (p)) snew = s2; else if (s2->PointOnSurface (p)) snew = s1; else { (*testout) << "GetIdenfifiedPoint: Not possible" << endl; (*testout) << "p = " << p << endl; (*testout) << "surf1: " << (*s1) << endl << "surf2: " << (*s2) << endl; cerr << "GetIdenfifiedPoint: Not possible" << endl; throw NgException ("GetIdenfifiedPoint: Not possible"); } // project to other surface Point<3> hp = p; if(usedirection) snew->SkewProject(hp,direction); else snew->Project (hp); //(*testout) << "projecting " << p << " to " << hp << endl; int newpi = 0; for (int i = 1; i <= mesh.GetNP(); i++) if (Dist2 (mesh.Point(i), hp) < 1e-12) // if (Dist2 (mesh.Point(i), hp) < 1 * Dist2 (hp, p)) { newpi = i; break; } if (!newpi) newpi = mesh.AddPoint (hp); if (snew == s2) { mesh.GetIdentifications().Add (pi, newpi, nr); //(*testout) << "add identification(1) " << pi << " - " << newpi << ", " << nr << endl; } else { mesh.GetIdentifications().Add (newpi, pi, nr); //(*testout) << "add identification(2) " << newpi << " - " << pi << ", " << nr << endl; } mesh.GetIdentifications().SetType(nr,Identifications::CLOSESURFACES); /* (*testout) << "Identify points(closesurface), nr = " << nr << ": " << mesh.Point(pi) << " and " << mesh.Point(newpi) << ((snew == s2) ? "" : " inverse") << endl; */ return newpi; } void CloseSurfaceIdentification :: IdentifyPoints (Mesh & mesh) { int np = mesh.GetNP(); Array points_on_surf2; for (int i2 = 1; i2 <= np; i2++) if (s2->PointOnSurface (mesh.Point(i2))) points_on_surf2.Append (i2); Array surfs_of_p1; for (int i1 = 1; i1 <= np; i1++) { Point<3> p1 = mesh.Point(i1); // (*testout) << "p1 = " << i1 << " = " << p1 << endl; if (domain && !domain->GetSolid()->IsIn (p1)) continue; //if(domain) (*testout) << "p1 is in " << domain->GetSolid()->Name() << endl; if (s1->PointOnSurface (p1)) { int candi2 = 0; double mindist = 1e10; Vec<3> n1; n1 = s1->GetNormalVector (p1); n1.Normalize(); surfs_of_p1.SetSize(0); for (int jj = 0; jj < domain_surfaces.Size(); jj++) { int j = domain_surfaces[jj]; if (geom.GetSurface(j) -> PointOnSurface(p1)) surfs_of_p1.Append (j); } //(*testout) << " surfs of p1 = " << endl << surfs_of_p1 << endl; for (int ii2 = 0; ii2 < points_on_surf2.Size(); ii2++) { int i2 = points_on_surf2[ii2]; if (i2 == i1) continue; const Point<3> p2 = mesh.Point(i2); Vec<3> n = p2 - p1; n.Normalize(); bool joint = 0; for (int jj = 0; jj < surfs_of_p1.Size(); jj++) { int j = surfs_of_p1[jj]; if (geom.GetSurface(j) -> PointOnSurface(p2)) { Vec<3> hn1 = geom.GetSurface(j)->GetNormalVector (p1); Vec<3> hn2 = geom.GetSurface(j)->GetNormalVector (p2); if (hn1 * hn2 > 0) { joint = 1; break; } } } if (!joint) continue; if(usedirection) { if (fabs (n*direction) > 0.9) { Vec<3> p1p2 = p2-p1; double ndist = p1p2.Length2() - pow(p1p2*direction,2); if(ndist < mindist) { candi2 = i2; mindist = ndist; } } } else { if (fabs (n * n1) > 0.9 && Dist (p1, p2) < mindist) { candi2 = i2; mindist = Dist (p1, p2); } } } if (candi2) { //(*testout) << "identify points " << p1 << " - " << mesh.Point(candi2) << endl; /* (*testout) << "Add Identification from CSI2, nr = " << nr << ", p1 = " << i1 << " = " << mesh[PointIndex(i1)] << ", p2 = " << candi2 << " = " << mesh[PointIndex(candi2)] << endl; */ mesh.GetIdentifications().Add (i1, candi2, nr); mesh.GetIdentifications().SetType(nr,Identifications::CLOSESURFACES); //(*testout) << "add identification " << i1 << " - " << candi2 << ", " << nr << endl; } } } } void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh) { int fi1, fi2, side; int s1rep = -1, s2rep = -1; for (int i = 0; i < geom.GetNSurf(); i++) { if (geom.GetSurface (i) == s1) s1rep = geom.GetSurfaceClassRepresentant(i); if (geom.GetSurface (i) == s2) s2rep = geom.GetSurfaceClassRepresentant(i); } Array segs_on_face1, segs_on_face2; identfaces.DeleteData(); //(*testout) << "identify faces, nr = " << nr << endl; for (int i = 1; i <= mesh.GetNFD(); i++) { auto & fdi = mesh.GetFaceDescriptor(i); int surfi = mesh.GetFaceDescriptor(i).SurfNr(); if (s1rep != surfi) continue; if (domain && domain != geom.GetTopLevelObject (mesh.GetFaceDescriptor(i).DomainIn()-1) && domain != geom.GetTopLevelObject (mesh.GetFaceDescriptor(i).DomainOut()-1)) continue; for (int j = 1; j <= mesh.GetNFD(); j++) { auto & fdj = mesh.GetFaceDescriptor(j); int surfj = mesh.GetFaceDescriptor(j).SurfNr(); if (surfi == surfj) continue; if (s2rep != surfj) continue; bool have_common = false; if (fdi.DomainIn() != 0) if (fdi.DomainIn() == fdj.DomainIn() || fdi.DomainIn() == fdj.DomainOut()) have_common = true; if (fdi.DomainOut() != 0) if (fdi.DomainOut() == fdj.DomainIn() || fdi.DomainOut() == fdj.DomainOut()) have_common = true; if (!have_common) continue; int idok = 1; for (side = 1; side <= 2 && idok; side++) { if (side == 1) { fi1 = i; fi2 = j; } else { fi1 = j; fi2 = i; } segs_on_face1.SetSize(0); segs_on_face2.SetSize(0); for (int k = 1; k <= mesh.GetNSeg(); k++) { if (mesh.LineSegment(k).si == fi1) segs_on_face1.Append (k); if (mesh.LineSegment(k).si == fi2) segs_on_face2.Append (k); } for (int k = 1; k <= mesh.GetNSeg(); k++) { const Segment & seg1 = mesh.LineSegment(k); if (seg1.si != fi1) continue; int foundother = 0; /* for (int l = 1; l <= mesh.GetNSeg(); l++) { const Segment & seg2 = mesh.LineSegment(l); if (seg2.si != fi2) continue; */ for (int ll = 0; ll < segs_on_face2.Size(); ll++) { int l = segs_on_face2[ll]; const Segment & seg2 = mesh.LineSegment(l); if (side == 1) { if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) && mesh.GetIdentifications().Get (seg1[1], seg2[1])) { foundother = 1; break; } if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) && mesh.GetIdentifications().Get (seg1[1], seg2[0])) { foundother = 1; break; } } else { if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) && mesh.GetIdentifications().Get (seg2[1], seg1[1])) { foundother = 1; break; } if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) && mesh.GetIdentifications().Get (seg2[1], seg1[0])) { foundother = 1; break; } } } if (!foundother) { idok = 0; break; } } } if (idok) { //(*testout) << "Identification " << nr << ", identify faces " << i << " and " << j << endl; INDEX_2 fpair(i,j); fpair.Sort(); identfaces.Set (fpair, 1); } } } } void CloseSurfaceIdentification :: BuildSurfaceElements (Array & segs, Mesh & mesh, const Surface * surf) { bool found = 0; int cntquads = 0; Array identmap; identmap = 0; mesh.GetIdentifications().GetMap (nr, identmap); for (int i = PointIndex::BASE; i < identmap.Size()+PointIndex::BASE; i++) if (identmap[i]) identmap[identmap[i]] = i; //(*testout) << "identification nr = " << nr << endl; //(*testout) << "surf = " << (*surf) << endl; //(*testout) << "domain = " << domain->GetSolid()->Name() << endl; //(*testout) << "segs = " << endl << segs << endl; //(*testout) << "identmap = " << endl << identmap << endl; //Array foundseg(segs.Size()); //foundseg = false; // insert quad layer: for (int i1 = 0; i1 < segs.Size(); i1++) { const Segment & s1 = segs[i1]; if (identmap[s1[0]] && identmap[s1[1]]) for (int i2 = 0; i2 < i1; i2++) { const Segment & s2 = segs[i2]; //(*testout) << "checking " << s1 << " and " << s2 << " for ident." << endl; if(domain && !((s1.domin == dom_nr || s1.domout == dom_nr) && (s2.domin == dom_nr || s2.domout == dom_nr))) continue; if ((mesh.GetIdentifications().Get (s1[0], s2[1], nr) && mesh.GetIdentifications().Get (s1[1], s2[0], nr)) || (mesh.GetIdentifications().Get (s2[0], s1[1], nr) && mesh.GetIdentifications().Get (s2[1], s1[0], nr))) { Vec<3> ns = surf->GetNormalVector (mesh[s1[0]]); Vec<3> t1 = mesh[s1[1]] - mesh[s1[0]]; // Vec<3> t2 = mesh[s2[1]] - mesh[s2[0]]; Vec<3> nst1 = Cross(t1, ns); // Vec<3> nst2 = Cross(t2, ns); Vec<3> dvec = Center(mesh[s1[0]], mesh[s1[1]])-Center(mesh[s2[0]], mesh[s2[1]]); if (nst1 * dvec < 0) continue; Element2d el(s1[0], s1[1], s2[0], s2[1]); el.SetIndex(s1.si); Vec<3> n = Cross (mesh[el[1]] - mesh[el[0]], mesh[el[3]] - mesh[el[0]]); if (n * ns < 0) { Swap (el.PNum(1), el.PNum(2)); Swap (el.PNum(3), el.PNum(4)); } mesh.AddSurfaceElement (el); // (*testout) << "(id nr "<< nr <<") add rect element: " // << mesh.Point (el.PNum(1)) << " - " // << mesh.Point (el.PNum(2)) << " - " // << mesh.Point (el.PNum(3)) << " - " // << mesh.Point (el.PNum(4)) << endl; found = true; //foundseg[i1]=foundseg[i2] = true; cntquads++; } } } if (found) { PrintMessage(3, "insert quad layer of ", cntquads, " elements at face ", segs.Get(1).si); //Array aux; //for(int i=0; i & segs, Mesh & mesh, const Surface * surf) { // copy mesh // (*testout) << "copy trig face, identnr = " << nr << endl; // (*testout) << "identfaces = " << endl << identfaces << endl; if (!segs.Size()) return; bool found = 0; int fother = -1; int facei = segs[0].si; int surfnr = mesh.GetFaceDescriptor(facei).SurfNr(); bool foundid = 0; for (INDEX_2_HASHTABLE::Iterator it = identfaces.Begin(); it != identfaces.End(); it++) { INDEX_2 i2; int data; identfaces.GetData (it, i2, data); if (i2.I1() == facei || i2.I2() == facei) foundid = 1; } /* for (int i = 1; i <= identfaces.GetNBags(); i++) for (int j = 1; j <= identfaces.GetBagSize(i); j++) { INDEX_2 i2; int data; identfaces.GetData (i, j, i2, data); if (i2.I1() == facei || i2.I2() == facei) foundid = 1; (*testout) << "identface = " << i2 << endl; (*testout) << "face " << i2.I1() << " = " << mesh.GetFaceDescriptor(i2.I1()) << endl; (*testout) << "face " << i2.I2() << " = " << mesh.GetFaceDescriptor(i2.I2()) << endl; } */ if (foundid) { // (*testout) << "surfaces found" << endl; // copy surface for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & sel = mesh[sei]; INDEX_2 fpair (facei, sel.GetIndex()); fpair.Sort(); if (identfaces.Used (fpair)) { found = 1; fother = sel.GetIndex(); // copy element Element2d newel(sel.GetType()); newel.SetIndex (facei); for (int k = 1; k <= sel.GetNP(); k++) newel.PNum(k) = GetIdentifiedPoint (mesh, sel.PNum(k)); Vec<3> nt = Cross (Point<3> (mesh.Point (newel.PNum(2)))- Point<3> (mesh.Point (newel.PNum(1))), Point<3> (mesh.Point (newel.PNum(3)))- Point<3> (mesh.Point (newel.PNum(1)))); Vec<3> nsurf; nsurf = geom.GetSurface (surfnr)->GetNormalVector (mesh.Point(newel.PNum(1))); if (nsurf * nt < 0) Swap (newel.PNum(2), newel.PNum(3)); mesh.AddSurfaceElement (newel); } } } if (found) { // (*mycout) << " copy face " << facei << " from face " << fother; PrintMessage (4, " copy face ", facei, " from face ", fother); segs.SetSize(0); } } void CloseSurfaceIdentification :: BuildVolumeElements (Array & surfels, class Mesh & mesh) { ; } /* ***************** Close Edges Identification ********** */ CloseEdgesIdentification :: CloseEdgesIdentification (int anr, const CSGeometry & ageom, const Surface * afacet, const Surface * as1, const Surface * as2) : Identification(anr, ageom) { facet = afacet; s1 = as1; s2 = as2; } CloseEdgesIdentification :: ~CloseEdgesIdentification () { ; } void CloseEdgesIdentification :: Print (ostream & ost) const { ost << "CloseEdges Identifiaction, facet = " << facet->Name() << ", surfaces: " << s1->Name() << " - " << s2->Name() << endl; facet->Print (ost); s1->Print (ost); s2->Print (ost); ost << endl; } void CloseEdgesIdentification :: GetData (ostream & ost) const { ost << "closeedges " << facet->Name() << " " << s1->Name() << " " << s2->Name(); } /* void CloseEdgesIdentification :: IdentifySpecialPoints (Array & points) { int i, j; int bestj; double bestval, val; for (i = 1; i <= points.Size(); i++) { Point<3> p1 = points.Get(i).p; Vec<3> n1; if (!s1->PointOnSurface (p1)) continue; s1->GetNormalVector (p1, n1); n1 /= n1.Length(); if ( fabs(n1 * points.Get(i).v) > 1e-3) continue; bestval = 1e8; bestj = 1; for (j = 1; j <= points.Size(); j++) { Point<3> p2= points.Get(j).p; if (!s2->PointOnSurface (p2)) continue; Vec<3> n2; s2->GetNormalVector (p2, n2); n2 /= n2.Length(); if ( fabs(n2 * points.Get(j).v) > 1e-3) continue; Vec<3> v(p1, p2); double vl = v.Length(); double cl = fabs (v*n1); val = 1 - cl*cl/(vl*vl); val += (points.Get(i).v - points.Get(j).v).Length(); if (val < bestval) { bestj = j; bestval = val; } } (*testout) << "Identify close surfaces special points: pi = " << points.Get(i).p << ", vi = " << points.Get(i).v << " pj = " << points.Get(bestj).p << ", vj = " << points.Get(bestj).v << " bestval = " << bestval << endl; } } */ int CloseEdgesIdentification :: Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2, const TABLE & specpoint2solid, const TABLE & specpoint2surface) const { int i; double val; SpecialPoint hsp1 = sp1; SpecialPoint hsp2 = sp2; for (i = 1; i <= 1; i++) { if (!s1->PointOnSurface (hsp1.p)) continue; Vec<3> n1; n1 = s1->GetNormalVector (hsp1.p); n1 /= n1.Length(); if ( fabs(n1 * hsp1.v) > 1e-3) continue; if (!s2->PointOnSurface(hsp2.p)) continue; Vec<3> n2; n2 = s2->GetNormalVector (hsp2.p); n2 /= n2.Length(); if ( fabs(n2 * hsp2.v) > 1e-3) continue; Vec<3> v = hsp2.p - hsp1.p; double vl = v.Length(); double cl = fabs (v*n1); val = 1 - cl*cl/(vl*vl); val += (hsp1.v - hsp2.v).Length(); if (val < 1e-3) { return 1; } } return 0; } void CloseEdgesIdentification :: IdentifyPoints (Mesh & mesh) { int np = mesh.GetNP(); for (int i1 = 1; i1 <= np; i1++) for (int i2 = 1; i2 <= np; i2++) { if (i2 == i1) continue; const Point<3> p1 = mesh.Point(i1); const Point<3> p2 = mesh.Point(i2); Point<3> pp1 = p1; Point<3> pp2 = p2; s1->Project (pp1); facet->Project (pp1); s2->Project (pp2); facet->Project (pp2); if (Dist (p1, pp1) > 1e-6 || Dist (p2, pp2) > 1e-6) continue; Vec<3> n1, nf, t; Vec<3> n = p2 - p1; n.Normalize(); n1 = s1->GetNormalVector (p1); nf = facet->GetNormalVector (p1); t = Cross (n1, nf); t /= t.Length(); if (fabs (n * t) < 0.5) { (*testout) << "close edges identify points " << p1 << " - " << p2 << endl; mesh.GetIdentifications().Add (i1, i2, nr); mesh.GetIdentifications().SetType(nr,Identifications::CLOSEEDGES); } } } void CloseEdgesIdentification :: BuildSurfaceElements (Array & segs, Mesh & mesh, const Surface * surf) { int found = 0; if (surf != facet) return; for (int i1 = 1; i1 <= segs.Size(); i1++) for (int i2 = 1; i2 < i1; i2++) { const Segment & s1 = segs.Get(i1); const Segment & s2 = segs.Get(i2); if (mesh.GetIdentifications().Get (s1[0], s2[1]) && mesh.GetIdentifications().Get (s1[1], s2[0])) { Element2d el(QUAD); el.PNum(1) = s1[0]; el.PNum(2) = s1[1]; el.PNum(3) = s2[1]; el.PNum(4) = s2[0]; Vec<3> n = Cross (Point<3> (mesh.Point(el.PNum(2)))- Point<3> (mesh.Point(el.PNum(1))), Point<3> (mesh.Point(el.PNum(3)))- Point<3> (mesh.Point(el.PNum(1)))); Vec<3> ns; ns = surf->GetNormalVector (mesh.Point(el.PNum(1))); //(*testout) << "n = " << n << " ns = " << ns << endl; if (n * ns < 0) { //(*testout) << "Swap the quad" << endl; Swap (el.PNum(1), el.PNum(2)); Swap (el.PNum(3), el.PNum(4)); } Swap (el.PNum(3), el.PNum(4)); mesh.AddSurfaceElement (el); // (*testout) << "add rect element: " // << mesh.Point (el.PNum(1)) << " - " // << mesh.Point (el.PNum(2)) << " - " // << mesh.Point (el.PNum(3)) << " - " // << mesh.Point (el.PNum(4)) << endl; found = 1; } } if (found) segs.SetSize(0); } } netgen-6.2.1905/libsrc/csg/vscsg.hpp0000644000175000017500000000156313504650527015676 0ustar kurtkurt#ifndef FILE_VSCSG #define FILE_VSCSG /**************************************************************************/ /* File: vscsg.hpp */ /* Author: Joachim Schoeberl */ /* Date: 05. Jan. 2011 */ /**************************************************************************/ namespace netgen { class DLL_HEADER VisualSceneGeometry : public VisualScene { class CSGeometry * geometry; Array trilists; int selsurf; public: VisualSceneGeometry (); virtual ~VisualSceneGeometry (); void SetGeometry (class CSGeometry * ageometry) { geometry = ageometry; } virtual void SelectSurface (int aselsurf); virtual void BuildScene (int zoomall = 0); virtual void DrawScene (); }; } #endif netgen-6.2.1905/libsrc/csg/splinesurface.cpp0000644000175000017500000000571713504650527017414 0ustar kurtkurt #include namespace netgen { void SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const bool hpref) { auto pp = p; Project(pp); geompoints.Append(GeomPoint<3>(pp,reffac)); geompoints.Last().hpref = hpref; } void SplineSurface :: AppendSegment(shared_ptr> sp, string & bcname, double amaxh) { splines.Append(sp); bcnames.Append(bcname); maxh.Append(amaxh); } string SplineSurface :: GetBCNameOf (Point<3> p1, Point<3> p2) const { for(int i=0; i(splines[i]->GetPoint(0)); Project(pp1); auto pp2 = Point<3>(splines[i]->GetPoint(1)); Project(pp2); double eps = (p1-p2).Length() * 1e-4; if (((pp1-p1).Length()>> SplineSurface :: CreateCuttingSurfaces() { if(all_cuts) return all_cuts; auto cuttings = make_shared>>(); for (auto cut : *cuts) cuttings->Append(cut); for(int i = 0; i*>(spline.get()); if(lineseg) { auto p1 = Point<3>(spline->GetPoint(0)); Project(p1); auto p2 = Point<3>(spline->GetPoint(1)); Project(p2); auto vec = Vec<3>(p2)-Vec<3>(p1); auto plane = make_shared(p1,-Cross(vec,baseprimitive->GetNormalVector(p1))); if(maxh[i]>0) { plane->SetMaxH(maxh[i]); } cuttings->Append(plane); } else { auto spline3 = dynamic_cast*>(spline.get()); if(spline3) { auto p1 = Point<3>(spline3->StartPI()); Project(p1); auto p2 = Point<3>(spline3->TangentPoint()); Project(p2); auto p3 = Point<3>(spline3->EndPI()); Project(p3); Vec<3> v1 = p2-p1; Vec<3> v2 = p2-p3; Point<3> mid = p1 - v2; cout << "mid point = " << mid << endl; cout << "v1 = " << v1 << endl; cout << "v2 = " << v2 << endl; auto cyl = make_shared(mid, v1, v2); if(maxh[i] > 0) cyl->SetMaxH(maxh[i]); cuttings->Append(cyl); } else throw NgException("Spline type not implemented for SplineSurface!"); } } all_cuts = cuttings; return cuttings; } void SplineSurface :: Print(ostream & str) const { str << "SplineSurface with base " << *baseprimitive << endl; } static RegisterClassForArchive regss; } netgen-6.2.1905/libsrc/csg/brick.hpp0000644000175000017500000000742513504650527015646 0ustar kurtkurt#ifndef FILE_BRICK #define FILE_BRICK /**************************************************************************/ /* File: brick.hpp */ /* Author: Joachim Schoeberl */ /* Date: 11. Mar. 98 */ /**************************************************************************/ namespace netgen { /* brick geometry, has several surfaces */ class Parallelogram3d : public Surface { Point<3> p1, p2, p3, p4; Vec<3> v12, v13; Vec<3> n; public: Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3); // default constructor for archive Parallelogram3d() {} virtual ~Parallelogram3d (); virtual void DoArchive(Archive& ar) { Surface::DoArchive(ar); ar & p1 & p2 & p3 & p4 & v12 & v13 & n; } void SetPoints (Point<3> ap1, Point<3> ap2, Point<3> ap3); virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; virtual double CalcFunctionValue (const Point<3> & point) const; virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; virtual double HesseNorm () const; virtual Point<3> GetSurfacePoint () const; virtual void Print (ostream & str) const; virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const; protected: void CalcData(); }; class Brick : public Primitive { Point<3> p1, p2, p3, p4; Vec<3> v12, v13, v14; // Array faces; Array faces; public: Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4); // default constructor for archive Brick() {} virtual ~Brick (); virtual void DoArchive(Archive& ar) { Primitive::DoArchive(ar); ar & p1 & p2 & p3 & p4 & v12 & v13 & v14 & faces; } static Primitive * CreateDefault (); virtual Primitive * Copy () const; virtual void Transform (Transformation<3> & trans); virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const; virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; virtual INSOLID_TYPE VecInSolid3 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; virtual INSOLID_TYPE VecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2, const Vec<3> & m, double eps) const; virtual int GetNSurfaces() const { return 6; } virtual Surface & GetSurface (int i) { return *faces[i]; } virtual const Surface & GetSurface (int i) const { return *faces[i]; } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); virtual void Reduce (const BoxSphere<3> & box); virtual void UnReduce (); protected: void CalcData(); }; class OrthoBrick : public Brick { protected: Point<3> pmin, pmax; public: OrthoBrick (const Point<3> & ap1, const Point<3> & ap2); // default constructor for archive OrthoBrick() {} virtual void DoArchive(Archive& ar) { Brick::DoArchive(ar); ar & pmin & pmax; } virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual void Reduce (const BoxSphere<3> & box); }; } #endif netgen-6.2.1905/libsrc/csg/polyhedra.hpp0000644000175000017500000000556713504650527016550 0ustar kurtkurt#ifndef FILE_POLYHEDRA #define FILE_POLYHEDRA /**************************************************************************/ /* File: polyhedra.hh */ /* Author: Joachim Schoeberl */ /* Date: 19. Mar. 2000 */ /**************************************************************************/ namespace netgen { /* Polyhedral primitive */ class Polyhedra : public Primitive { class Face { public: int pnums[3]; int planenr; int inputnr; Box<3> bbox; // Point<3> center; Vec<3> v1, v2; // edges Vec<3> w1, w2; // pseudo-inverse Vec<3> n; // normal to face Vec<3> nn; // normed normal Face () { ; } Face (int pi1, int pi2, int pi3, const Array > & points, int ainputnr); }; Array > points; Array faces; Array planes; Box<3> poly_bbox; double eps_base1; public: Polyhedra (); virtual ~Polyhedra (); static Primitive * CreateDefault (); virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, const Vec<3> & v, double eps) const; // checks if lim s->0 lim t->0 p + t(v1 + s v2) in solid virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, double eps) const; virtual void GetTangentialSurfaceIndices (const Point<3> & p, Array & surfind, double eps) const; virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2, Array & surfind, double eps) const; virtual void CalcSpecialPoints (Array > & pts) const; virtual void AnalyzeSpecialPoint (const Point<3> & pt, Array > & specpts) const; virtual Vec<3> SpecialPointTangentialVector (const Point<3> & p, int s1, int s2) const; virtual int GetNSurfaces() const { return planes.Size(); } virtual Surface & GetSurface (int i) { return *planes[i]; } virtual const Surface & GetSurface (int i) const { return *planes[i]; } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); virtual void Reduce (const BoxSphere<3> & box); virtual void UnReduce (); int AddPoint (const Point<3> & p); int AddFace (int pi1, int pi2, int pi3, int inputnum); void GetPolySurfs(Array < Array * > & polysurfs); protected: int FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const; // void CalcData(); }; } #endif netgen-6.2.1905/libsrc/csg/explicitcurve2d.cpp0000644000175000017500000000613513504650527017660 0ustar kurtkurt#include #include namespace netgen { ExplicitCurve2d :: ExplicitCurve2d () { ; } void ExplicitCurve2d :: Project (Point<2> & p) const { double t; t = ProjectParam (p); p = Eval (t); } double ExplicitCurve2d :: NumericalProjectParam (const Point<2> & p, double lb, double ub) const { double t(-1); Vec<2> tan; Vec<2> curv; Point<2> cp; double f, fl, fu; int cnt; tan = EvalPrime (lb); cp = Eval (lb); fl = tan * (cp - p); if (fl > 0) // changed by wmf, originally fl >= 0 { // cerr << "tan = " << tan << " cp - p = " << (cp - p) << endl; // cerr << "ExplicitCurve2d::NumericalProject: lb wrong" << endl; return 0; } tan = EvalPrime (ub); cp = Eval (ub); fu = tan * (cp - p); if (fu < 0) // changed by wmf, originally fu <= 0 { // cerr << "tan = " << tan << " cp - p = " << (cp - p) << endl; // cerr << "ExplicitCurve2d::NumericalProject: ub wrong" << endl; return 0; } cnt = 0; while (ub - lb > 1e-12 && fu - fl > 1e-12) { cnt++; if (cnt > 50) { (*testout) << "Num Proj, cnt = " << cnt << endl; } t = (lb * fu - ub * fl) / (fu - fl); if (t > 0.9 * ub + 0.1 * lb) t = 0.9 * ub + 0.1 * lb; if (t < 0.1 * ub + 0.9 * lb) t = 0.1 * ub + 0.9 * lb; tan = EvalPrime (t); cp = Eval (t); f = tan * (cp - p); if (f >= 0) { ub = t; fu = f; } else { lb = t; fl = f; } } return t; } Vec<2> ExplicitCurve2d :: Normal (double t) const { Vec<2> tan = EvalPrime (t); tan.Normalize(); return Vec<2> (tan(1), -tan(0)); } void ExplicitCurve2d :: NormalVector (const Point<2> & p, Vec<2> & n) const { double t = ProjectParam (p); n = Normal (t); } Point<2> ExplicitCurve2d :: CurvCircle (double t) const { Point<2> cp; Vec<2> tan, n, curv; double den; cp = Eval (t); tan = EvalPrime (t); n = Normal (t); curv = EvalPrimePrime (t); den = n * curv; if (fabs (den) < 1e-12) return cp + 1e12 * n; return cp + (tan.Length2() / den) * n; } double ExplicitCurve2d :: MaxCurvature () const { double t, tmin, tmax, dt; double curv; Vec<2> tan; double maxcurv; maxcurv = 0; tmin = MinParam (); tmax = MaxParam (); dt = (tmax - tmin) / 1000; for (t = tmin; t <= tmax+dt; t += dt) if (SectionUsed (t)) { tan = EvalPrime (t); curv = fabs ( (Normal(t) * EvalPrimePrime(t)) / tan.Length2()); if (curv > maxcurv) maxcurv = curv; } return maxcurv; } double ExplicitCurve2d :: MaxCurvatureLoc (const Point<2> & p, double rad) const { double t, tmin, tmax, dt; double curv; Vec<2> tan; double maxcurv; maxcurv = 0; tmin = MinParam (); tmax = MaxParam (); dt = (tmax - tmin) / 1000; for (t = tmin; t <= tmax+dt; t += dt) if (Dist (Eval(t), p) < rad) { tan = EvalPrime (t); curv = fabs ( (Normal(t) * EvalPrimePrime(t)) / tan.Length2()); if (curv > maxcurv) maxcurv = curv; } return maxcurv; } } netgen-6.2.1905/libsrc/csg/manifold.hpp0000644000175000017500000000114613504650527016337 0ustar kurtkurt#ifndef FILE_MANIFOLD #define FILE_MANIFOLD /**************************************************************************/ /* File: manifold.hh */ /* Author: Joachim Schoeberl */ /* Date: 7. Aug. 96 */ /**************************************************************************/ namespace netgen { /** Basis class for manifolds in 2d and 3d */ class Manifold { public: /// Manifold (); /// virtual ~Manifold (); }; } #endif netgen-6.2.1905/libsrc/csg/csg.hpp0000644000175000017500000000213313504650527015317 0ustar kurtkurt#ifndef FILE_CSG #define FILE_CSG /* *************************************************************************/ /* File: geoml.hpp */ /* Author: Joachim Schoeberl */ /* Date: 21. Jun. 98 */ /* *************************************************************************/ #include #include #include // #include #include "../gprim/spline.hpp" #include "../gprim/splinegeometry.hpp" #include "surface.hpp" #include "solid.hpp" #include "identify.hpp" #include "singularref.hpp" #include "splinesurface.hpp" #include "csgeom.hpp" #include "csgparser.hpp" #include "triapprox.hpp" #include "algprim.hpp" #include "brick.hpp" #include "spline3d.hpp" #include "manifold.hpp" #include "curve2d.hpp" #include "explicitcurve2d.hpp" #include "gencyl.hpp" #include "polyhedra.hpp" #include "extrusion.hpp" #include "revolution.hpp" #include "specpoin.hpp" #include "edgeflw.hpp" #include "meshsurf.hpp" #endif netgen-6.2.1905/libsrc/csg/genmesh.cpp0000644000175000017500000005315613504650527016177 0ustar kurtkurt#include #include #include #include #include namespace netgen { Array specpoints; static Array spoints; #define TCL_OK 0 #define TCL_ERROR 1 static void FindPoints (CSGeometry & geom, Mesh & mesh) { PrintMessage (1, "Start Findpoints"); const char * savetask = multithread.task; multithread.task = "Find points"; mesh.pointelements.SetSize(0); for (int i = 0; i < geom.GetNUserPoints(); i++) { auto up = geom.GetUserPoint(i); auto pnum = mesh.AddPoint(up); mesh.Points().Last().Singularity (geom.GetUserPointRefFactor(i)); mesh.AddLockedPoint (PointIndex (i+1)); mesh.pointelements.Append (Element0d(pnum, up.GetIndex())); } SpecialPointCalculation spc; spc.SetIdEps(geom.GetIdEps()); if (spoints.Size() == 0) spc.CalcSpecialPoints (geom, spoints); PrintMessage (2, "Analyze spec points"); spc.AnalyzeSpecialPoints (geom, spoints, specpoints); PrintMessage (5, "done"); (*testout) << specpoints.Size() << " special points:" << endl; for (int i = 0; i < specpoints.Size(); i++) specpoints[i].Print (*testout); /* for (int i = 1; i <= geom.identifications.Size(); i++) geom.identifications.Elem(i)->IdentifySpecialPoints (specpoints); */ multithread.task = savetask; } static void FindEdges (CSGeometry & geom, Mesh & mesh, MeshingParameters & mparam, const bool setmeshsize = false) { EdgeCalculation ec (geom, specpoints, mparam); ec.SetIdEps(geom.GetIdEps()); ec.Calc (mparam.maxh, mesh); for (int i = 0; i < geom.singedges.Size(); i++) { geom.singedges[i]->FindPointsOnEdge (mesh); if(setmeshsize) geom.singedges[i]->SetMeshSize(mesh,10.*geom.BoundingBox().Diam()); } for (int i = 0; i < geom.singpoints.Size(); i++) geom.singpoints[i]->FindPoints (mesh); for (int i = 1; i <= mesh.GetNSeg(); i++) { //(*testout) << "segment " << mesh.LineSegment(i) << endl; int ok = 0; for (int k = 1; k <= mesh.GetNFD(); k++) if (mesh.GetFaceDescriptor(k).SegmentFits (mesh.LineSegment(i))) { ok = k; //(*testout) << "fits to " << k << endl; } if (!ok) { ok = mesh.AddFaceDescriptor (FaceDescriptor (mesh.LineSegment(i))); //(*testout) << "did not find, now " << ok << endl; } //(*testout) << "change from " << mesh.LineSegment(i).si; mesh.LineSegment(i).si = ok; //(*testout) << " to " << mesh.LineSegment(i).si << endl; } for(int k = 1; k<=mesh.GetNFD(); k++) { *testout << "face: " << k << endl << "FD: " << mesh.GetFaceDescriptor(k) << endl; } if (geom.identifications.Size()) { PrintMessage (3, "Find Identifications"); for (int i = 0; i < geom.identifications.Size(); i++) { geom.identifications[i]->IdentifyPoints (mesh); //(*testout) << "identification " << i << " is " // << *geom.identifications[i] << endl; } for (int i = 0; i < geom.identifications.Size(); i++) geom.identifications[i]->IdentifyFaces (mesh); } // find intersecting segments PrintMessage (3, "Check intersecting edges"); Point3d pmin, pmax; mesh.GetBox (pmin, pmax); BoxTree<3> segtree (pmin, pmax); for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { if (mesh[si].seginfo) { Box<3> hbox; hbox.Set (mesh[mesh[si][0]]); hbox.Add (mesh[mesh[si][1]]); segtree.Insert (hbox.PMin(), hbox.PMax(), si); } } Array loc; if (!ec.point_on_edge_problem) for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { if (!mesh[si].seginfo) continue; Box<3> hbox; hbox.Set (mesh[mesh[si][0]]); hbox.Add (mesh[mesh[si][1]]); hbox.Increase (1e-6); segtree.GetIntersecting (hbox.PMin(), hbox.PMax(), loc); // for (SegmentIndex sj = 0; sj < si; sj++) for (int j = 0; j < loc.Size(); j++) { SegmentIndex sj = loc[j]; if (sj >= si) continue; if (!mesh[si].seginfo || !mesh[sj].seginfo) continue; if (mesh[mesh[si][0]].GetLayer() != mesh[mesh[sj][1]].GetLayer()) continue; Point<3> pi1 = mesh[mesh[si][0]]; Point<3> pi2 = mesh[mesh[si][1]]; Point<3> pj1 = mesh[mesh[sj][0]]; Point<3> pj2 = mesh[mesh[sj][1]]; Vec<3> vi = pi2 - pi1; Vec<3> vj = pj2 - pj1; if (sqr (vi * vj) > (1.-1e-6) * Abs2 (vi) * Abs2 (vj)) continue; // pi1 + vi t = pj1 + vj s Mat<3,2> mat; Vec<3> rhs; Vec<2> sol; for (int jj = 0; jj < 3; jj++) { mat(jj,0) = vi(jj); mat(jj,1) = -vj(jj); rhs(jj) = pj1(jj)-pi1(jj); } mat.Solve (rhs, sol); //(*testout) << "mat " << mat << endl << "rhs " << rhs << endl << "sol " << sol << endl; if (sol(0) > 1e-6 && sol(0) < 1-1e-6 && sol(1) > 1e-6 && sol(1) < 1-1e-6 && Abs (rhs - mat*sol) < 1e-6) { Point<3> ip = pi1 + sol(0) * vi; //(*testout) << "ip " << ip << endl; Point<3> pip = ip; ProjectToEdge (geom.GetSurface (mesh[si].surfnr1), geom.GetSurface (mesh[si].surfnr2), pip); //(*testout) << "Dist (ip, pip_si) " << Dist (ip, pip) << endl; if (Dist (ip, pip) > 1e-6*geom.MaxSize()) continue; pip = ip; ProjectToEdge (geom.GetSurface (mesh[sj].surfnr1), geom.GetSurface (mesh[sj].surfnr2), pip); //(*testout) << "Dist (ip, pip_sj) " << Dist (ip, pip) << endl; if (Dist (ip, pip) > 1e-6*geom.MaxSize()) continue; cout << "Intersection at " << ip << endl; geom.AddUserPoint (ip); spoints.Append (MeshPoint (ip, mesh[mesh[si][0]].GetLayer())); mesh.AddPoint (ip); (*testout) << "found intersection at " << ip << endl; (*testout) << "sol = " << sol << endl; (*testout) << "res = " << (rhs - mat*sol) << endl; (*testout) << "segs = " << pi1 << " - " << pi2 << endl; (*testout) << "and = " << pj1 << " - " << pj2 << endl << endl; } } } } static void MeshSurface (CSGeometry & geom, Mesh & mesh, MeshingParameters & mparam) { const char * savetask = multithread.task; multithread.task = "Surface meshing"; Array segments; int noldp = mesh.GetNP(); double starttime = GetTime(); // find master faces from identified Array masterface(mesh.GetNFD()); for (int i = 1; i <= mesh.GetNFD(); i++) masterface.Elem(i) = i; Array fpairs; bool changed; do { changed = 0; for (int i = 0; i < geom.identifications.Size(); i++) { geom.identifications[i]->GetIdentifiedFaces (fpairs); for (int j = 0; j < fpairs.Size(); j++) { if (masterface.Get(fpairs[j].I1()) < masterface.Get(fpairs[j].I2())) { changed = 1; masterface.Elem(fpairs[j].I2()) = masterface.Elem(fpairs[j].I1()); } if (masterface.Get(fpairs[j].I2()) < masterface.Get(fpairs[j].I1())) { changed = 1; masterface.Elem(fpairs[j].I1()) = masterface.Elem(fpairs[j].I2()); } } } } while (changed); int bccnt=0; for (int k = 0; k < geom.GetNSurf(); k++) bccnt = max2 (bccnt, geom.GetSurface(k)->GetBCProperty()); for (int k = 1; k <= mesh.GetNFD(); k++) { bool increased = false; FaceDescriptor & fd = mesh.GetFaceDescriptor(k); const Surface * surf = geom.GetSurface(fd.SurfNr()); if (fd.TLOSurface() && geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetBCProp() > 0) fd.SetBCProperty (geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetBCProp()); else if (surf -> GetBCProperty() != -1) fd.SetBCProperty (surf->GetBCProperty()); else { bccnt++; fd.SetBCProperty (bccnt); increased = true; } for (int l = 0; l < geom.bcmodifications.Size(); l++) { if (geom.GetSurfaceClassRepresentant (fd.SurfNr()) == geom.GetSurfaceClassRepresentant (geom.bcmodifications[l].si) && (fd.DomainIn() == geom.bcmodifications[l].tlonr+1 || fd.DomainOut() == geom.bcmodifications[l].tlonr+1)) { if(geom.bcmodifications[l].bcname == NULL) fd.SetBCProperty (geom.bcmodifications[l].bcnr); else { if(!increased) { bccnt++; fd.SetBCProperty (bccnt); increased = true; } } } } } mesh.SetNBCNames( bccnt ); for (int k = 1; k <= mesh.GetNFD(); k++) { FaceDescriptor & fd = mesh.GetFaceDescriptor(k); const Surface * surf = geom.GetSurface(fd.SurfNr()); if (fd.TLOSurface() ) { int bcp = fd.BCProperty(); string nextbcname = geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetBCName(); if ( nextbcname != "default" ) mesh.SetBCName ( bcp - 1 , nextbcname ); } else // if (surf -> GetBCProperty() != -1) { int bcp = fd.BCProperty(); string nextbcname = surf->GetBCName(); if ( nextbcname != "default" ) mesh.SetBCName ( bcp - 1, nextbcname ); } } for (int k = 1; k <= mesh.GetNFD(); k++) { FaceDescriptor & fd = mesh.GetFaceDescriptor(k); fd.SetBCName ( mesh.GetBCNamePtr ( fd.BCProperty() - 1 ) ); } //!! for (int k = 1; k <= mesh.GetNFD(); k++) { FaceDescriptor & fd = mesh.GetFaceDescriptor(k); //const Surface * surf = geom.GetSurface(fd.SurfNr()); for (int l = 0; l < geom.bcmodifications.Size(); l++) { if (geom.GetSurfaceClassRepresentant (fd.SurfNr()) == geom.GetSurfaceClassRepresentant (geom.bcmodifications[l].si) && (fd.DomainIn() == geom.bcmodifications[l].tlonr+1 || fd.DomainOut() == geom.bcmodifications[l].tlonr+1) && geom.bcmodifications[l].bcname != NULL ) { int bcp = fd.BCProperty(); mesh.SetBCName ( bcp - 1, *(geom.bcmodifications[l].bcname) ); fd.SetBCName ( mesh.GetBCNamePtr ( bcp - 1) ); } } } for(int k = 0; k surfs; geom.GetIndependentSurfaceIndices (geom.singfaces[j]->GetSolid(), geom.BoundingBox(), surfs); for (int k = 1; k <= mesh.GetNFD(); k++) { FaceDescriptor & fd = mesh.GetFaceDescriptor(k); for (int l = 0; l < surfs.Size(); l++) if (surfs[l] == fd.SurfNr()) { if (geom.singfaces[j]->GetDomainNr() == fd.DomainIn()) fd.SetDomainInSingular (1); if (geom.singfaces[j]->GetDomainNr() == fd.DomainOut()) fd.SetDomainOutSingular (1); } } } // assemble edge hash-table mesh.CalcSurfacesOfNode(); for (int k = 1; k <= mesh.GetNFD(); k++) { multithread.percent = 100.0 * k / (mesh.GetNFD()+1e-10); if (masterface.Get(k) != k) continue; FaceDescriptor & fd = mesh.GetFaceDescriptor(k); (*testout) << "Surface " << k << endl; (*testout) << "Face Descriptor: " << fd << endl; PrintMessage (1, "Surface ", k, " / ", mesh.GetNFD()); int oldnf = mesh.GetNSE(); const Surface * surf = geom.GetSurface((mesh.GetFaceDescriptor(k).SurfNr())); Meshing2Surfaces meshing(*surf, mparam, geom.BoundingBox()); meshing.SetStartTime (starttime); double eps = 1e-8 * geom.MaxSize(); for (PointIndex pi = PointIndex::BASE; pi < noldp+PointIndex::BASE; pi++) { // if(surf->PointOnSurface(mesh[pi])) meshing.AddPoint (mesh[pi], pi, NULL, (surf->PointOnSurface(mesh[pi], eps) != 0)); } segments.SetSize (0); for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) if (mesh[si].si == k) { segments.Append (mesh[si]); (*testout) << "appending segment " << mesh[si] << endl; //<< " from " << mesh[mesh[si][0]] // << " to " < BuildSurfaceElements(segments, mesh, surf); } for (int si = 0; si < segments.Size(); si++) { PointGeomInfo gi; gi.trignum = k; meshing.AddBoundaryElement (segments[si][0] + 1 - PointIndex::BASE, segments[si][1] + 1 - PointIndex::BASE, gi, gi); } double maxh = mparam.maxh; if (fd.DomainIn() != 0) { const Solid * s1 = geom.GetTopLevelObject(fd.DomainIn()-1) -> GetSolid(); if (s1->GetMaxH() < maxh) maxh = s1->GetMaxH(); maxh = min2(maxh, geom.GetTopLevelObject(fd.DomainIn()-1)->GetMaxH()); } if (fd.DomainOut() != 0) { const Solid * s1 = geom.GetTopLevelObject(fd.DomainOut()-1) -> GetSolid(); if (s1->GetMaxH() < maxh) maxh = s1->GetMaxH(); maxh = min2(maxh, geom.GetTopLevelObject(fd.DomainOut()-1)->GetMaxH()); } if (fd.TLOSurface() != 0) { double hi = geom.GetTopLevelObject(fd.TLOSurface()-1) -> GetMaxH(); if (hi < maxh) maxh = hi; } (*testout) << "domin = " << fd.DomainIn() << ", domout = " << fd.DomainOut() << ", tlo-surf = " << fd.TLOSurface() << " mpram.maxh = " << mparam.maxh << ", maxh = " << maxh << endl; mparam.checkoverlap = 0; MESHING2_RESULT res = meshing.GenerateMesh (mesh, mparam, maxh, k); if (res != MESHING2_OK) { PrintError ("Problem in Surface mesh generation"); throw NgException ("Problem in Surface mesh generation"); } if (multithread.terminate) return; for (SurfaceElementIndex sei = oldnf; sei < mesh.GetNSE(); sei++) mesh[sei].SetIndex (k); // mesh.CalcSurfacesOfNode(); if (segments.Size()) { // surface was meshed, not copied static int timer = NgProfiler::CreateTimer ("total surface mesh optimization"); NgProfiler::RegionTimer reg (timer); PrintMessage (2, "Optimize Surface"); for (int i = 1; i <= mparam.optsteps2d; i++) { if (multithread.terminate) return; { MeshOptimize2dSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); meshopt.SetMetricWeight (mparam.elsizeweight); meshopt.SetWriteStatus (0); meshopt.EdgeSwapping (mesh, (i > mparam.optsteps2d/2)); } if (multithread.terminate) return; { // mesh.CalcSurfacesOfNode(); MeshOptimize2dSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); meshopt.SetMetricWeight (mparam.elsizeweight); meshopt.SetWriteStatus (0); meshopt.ImproveMesh (mesh, mparam); } { MeshOptimize2dSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); meshopt.SetMetricWeight (mparam.elsizeweight); meshopt.SetWriteStatus (0); meshopt.CombineImprove (mesh); // mesh.CalcSurfacesOfNode(); } if (multithread.terminate) return; { MeshOptimize2dSurfaces meshopt(geom); meshopt.SetFaceIndex (k); meshopt.SetImproveEdges (0); meshopt.SetMetricWeight (mparam.elsizeweight); meshopt.SetWriteStatus (0); meshopt.ImproveMesh (mesh, mparam); } } } PrintMessage (3, (mesh.GetNSE() - oldnf), " elements, ", mesh.GetNP(), " points"); mparam.Render(); } mesh.Compress(); do { changed = 0; for (int k = 1; k <= mesh.GetNFD(); k++) { multithread.percent = 100.0 * k / (mesh.GetNFD()+1e-10); if (masterface.Get(k) == k) continue; FaceDescriptor & fd = mesh.GetFaceDescriptor(k); (*testout) << "Surface " << k << endl; (*testout) << "Face Descriptor: " << fd << endl; PrintMessage (2, "Surface ", k); int oldnf = mesh.GetNSE(); const Surface * surf = geom.GetSurface((mesh.GetFaceDescriptor(k).SurfNr())); /* if (surf -> GetBCProperty() != -1) fd.SetBCProperty (surf->GetBCProperty()); else { bccnt++; fd.SetBCProperty (bccnt); } */ segments.SetSize (0); for (int i = 1; i <= mesh.GetNSeg(); i++) { Segment * seg = &mesh.LineSegment(i); if (seg->si == k) segments.Append (*seg); } for (int i = 1; i <= geom.identifications.Size(); i++) { geom.identifications.Elem(i)->GetIdentifiedFaces (fpairs); int found = 0; for (int j = 1; j <= fpairs.Size(); j++) if (fpairs.Get(j).I1() == k || fpairs.Get(j).I2() == k) found = 1; if (!found) continue; geom.identifications.Get(i)-> BuildSurfaceElements(segments, mesh, surf); if (!segments.Size()) break; } if (multithread.terminate) return; for (SurfaceElementIndex sei = oldnf; sei < mesh.GetNSE(); sei++) mesh[sei].SetIndex (k); if (!segments.Size()) { masterface.Elem(k) = k; changed = 1; } PrintMessage (3, (mesh.GetNSE() - oldnf), " elements, ", mesh.GetNP(), " points"); } mparam.Render(); } while (changed); mesh.SplitSeparatedFaces(); mesh.CalcSurfacesOfNode(); multithread.task = savetask; } int CSGGenerateMesh (CSGeometry & geom, shared_ptr & mesh, MeshingParameters & mparam) { if (mesh && mesh->GetNSE() && !geom.GetNSolids()) { if (mparam.perfstepsstart < MESHCONST_MESHVOLUME) mparam.perfstepsstart = MESHCONST_MESHVOLUME; } if (mparam.perfstepsstart <= MESHCONST_ANALYSE) { if (mesh) mesh -> DeleteMesh(); else mesh = make_shared(); mesh->SetGlobalH (mparam.maxh); mesh->SetMinimalH (mparam.minh); Array maxhdom(geom.GetNTopLevelObjects()); for (int i = 0; i < maxhdom.Size(); i++) maxhdom[i] = geom.GetTopLevelObject(i)->GetMaxH(); mesh->SetMaxHDomain (maxhdom); if (mparam.uselocalh) { double maxsize = geom.MaxSize(); mesh->SetLocalH (Point<3>(-maxsize, -maxsize, -maxsize), Point<3>(maxsize, maxsize, maxsize), mparam.grading); mesh -> LoadLocalMeshSize (mparam.meshsizefilename); for (auto mspnt : mparam.meshsize_points) mesh -> RestrictLocalH (mspnt.pnt, mspnt.h); } spoints.SetSize(0); FindPoints (geom, *mesh); PrintMessage (5, "find points done"); #ifdef LOG_STREAM (*logout) << "Special points found" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl << endl; #endif } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_ANALYSE) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_MESHEDGES) { FindEdges (geom, *mesh, mparam, true); if (multithread.terminate) return TCL_OK; #ifdef LOG_STREAM (*logout) << "Edges meshed" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif if (multithread.terminate) return TCL_OK; if (mparam.uselocalh) { mesh->CalcLocalH(mparam.grading); mesh->DeleteMesh(); FindPoints (geom, *mesh); if (multithread.terminate) return TCL_OK; FindEdges (geom, *mesh, mparam, true); if (multithread.terminate) return TCL_OK; mesh->DeleteMesh(); FindPoints (geom, *mesh); if (multithread.terminate) return TCL_OK; FindEdges (geom, *mesh, mparam); if (multithread.terminate) return TCL_OK; } } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE) { MeshSurface (geom, *mesh, mparam); if (multithread.terminate) return TCL_OK; #ifdef LOG_STREAM (*logout) << "Surfaces meshed" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif /* if (mparam.uselocalh) { mesh->CalcLocalH(mparam.grading); mesh->DeleteMesh(); FindPoints (geom, *mesh); if (multithread.terminate) return TCL_OK; FindEdges (geom, *mesh, mparam); if (multithread.terminate) return TCL_OK; MeshSurface (geom, *mesh, mparam); if (multithread.terminate) return TCL_OK; } */ #ifdef LOG_STREAM (*logout) << "Surfaces remeshed" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif #ifdef STAT_STREAM (*statout) << mesh->GetNSeg() << " & " << mesh->GetNSE() << " & - &" << GetTime() << " & " << endl; #endif MeshQuality2d (*mesh); mesh->CalcSurfacesOfNode(); } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_OPTSURFACE) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_MESHVOLUME) { multithread.task = "Volume meshing"; MESHING3_RESULT res = MeshVolume (mparam, *mesh); if (res != MESHING3_OK) return TCL_ERROR; if (multithread.terminate) return TCL_OK; RemoveIllegalElements (*mesh); if (multithread.terminate) return TCL_OK; MeshQuality3d (*mesh); for (int i = 0; i < geom.GetNTopLevelObjects(); i++) mesh->SetMaterial (i+1, geom.GetTopLevelObject(i)->GetMaterial().c_str()); #ifdef STAT_STREAM (*statout) << GetTime() << " & "; #endif #ifdef LOG_STREAM (*logout) << "Volume meshed" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHVOLUME) return TCL_OK; if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME) { multithread.task = "Volume optimization"; OptimizeVolume (mparam, *mesh); if (multithread.terminate) return TCL_OK; #ifdef STAT_STREAM (*statout) << GetTime() << " & " << mesh->GetNE() << " & " << mesh->GetNP() << " " << '\\' << '\\' << " \\" << "hline" << endl; #endif #ifdef LOG_STREAM (*logout) << "Volume optimized" << endl << "time = " << GetTime() << " sec" << endl << "points: " << mesh->GetNP() << endl; #endif } mesh -> OrderElements(); return TCL_OK; } } netgen-6.2.1905/libsrc/csg/algprim.hpp0000644000175000017500000003337613504650527016213 0ustar kurtkurt#ifndef FILE_ALGPRIM #define FILE_ALGPRIM /**************************************************************************/ /* File: algprim.hpp */ /* Author: Joachim Schoeberl */ /* Date: 1. Dez. 95 */ /**************************************************************************/ namespace netgen { /* Quadric Surfaces (Plane, Sphere, Cylinder) */ /** A quadric surface. surface defined by cxx x^2 + cyy y^2 + czz z^2 + cxy x y + cxz x z + cyz y z + cx x + cy y + cz z + c1 = 0. **/ class QuadraticSurface : public OneSurfacePrimitive { protected: double cxx, cyy, czz, cxy, cxz, cyz, cx, cy, cz, c1; public: virtual double CalcFunctionValue (const Point<3> & point) const; virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; /* virtual int RootInBox (const Box<3> & box) const { return 0; } virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const { return DOES_INTERSECT; } */ virtual double HesseNorm () const { return cxx + cyy + czz; } virtual Point<3> GetSurfacePoint () const; virtual void Print (ostream & str) const; virtual void Read (istream & ist); void PrintCoeff (ostream & ost) const; virtual void DoArchive(Archive& ar) { OneSurfacePrimitive::DoArchive(ar); ar & cxx & cyy & czz & cxy & cxz & cyz & cx & cy & cz & c1; } }; /// A Plane (i.e., the plane and everything behind it). class Plane : public QuadraticSurface { protected: /// a point in the plane Point<3> p; /// outward normal vector Vec<3> n; double eps_base; public: /// Plane (const Point<3> & ap, Vec<3> an); // default constructor for archive Plane() {} virtual void DoArchive(Archive& ar) { QuadraticSurface::DoArchive(ar); ar & p & n & eps_base; } Point<3> P() const { return p; } Vec<3> N() const { return n; } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); static Primitive * CreateDefault (); virtual Primitive * Copy () const; virtual void Print (ostream & str) const; virtual void Transform (Transformation<3> & trans); virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; /// virtual void DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2); /// virtual void ToPlane (const Point<3> & p3d, Point<2> & pplane, double h, int & zone) const; /// virtual void FromPlane (const Point<2> & pplane, Point<3> & p3d, double h) const; /// virtual void Project (Point<3> & p) const; /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// inline virtual double CalcFunctionValue (const Point<3> & p3d) const {return cx * p3d(0) + cy * p3d(1) + cz * p3d(2) + c1;} /// virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; /// virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; /// virtual double HesseNorm () const; /// virtual Point<3> GetSurfacePoint () const; /// virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & boundingbox, double facets) const; protected: void CalcData(); }; // typedef Plane Plane; /// class Sphere : public QuadraticSurface { /// Point<3> c; /// double r, invr; public: /// Sphere (const Point<3> & ac, double ar); // default constructor for archive Sphere() {} virtual void DoArchive(Archive& ar) { QuadraticSurface::DoArchive(ar); ar & c & r & invr; } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); static Primitive * CreateDefault (); virtual Primitive * Copy () const; virtual void Transform (Transformation<3> & trans); virtual double CalcFunctionValue (const Point<3> & point) const; virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; /// virtual void DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2); /// virtual void ToPlane (const Point<3> & p3d, Point<2> & pplane, double h, int & zone) const; /// virtual void FromPlane (const Point<2> & pplane, Point<3> & p, double h) const; /// virtual void Project (Point<3> & p) const; /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// virtual double HesseNorm () const; /// virtual Point<3> GetSurfacePoint () const; /// const Point<3> & Center () const { return c; } /// double Radius () const { return r; } /// virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & bbox, double facets) const; }; /// class Cylinder : public QuadraticSurface { /// Point<3> a, b; /// double r; /// Vec<3> vab; public: Cylinder (const Point<3> & aa, const Point<3> & ab, double ar); Cylinder (Array & coeffs); // default constructor for archive Cylinder() {} virtual void DoArchive(Archive& ar) { QuadraticSurface::DoArchive(ar); ar & a & b & r & vab; } Point<3> A() const { return a; } Point<3> B() const { return b; } double R() const { return r; } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); static Primitive * CreateDefault (); virtual Primitive * Copy () const; virtual void Print (ostream & str) const; virtual void Transform (Transformation<3> & trans); /// virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; /// virtual void DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2); /// virtual void ToPlane (const Point<3> & p, Point<2> & pplane, double h, int & zone) const; /// virtual void FromPlane (const Point<2> & pplane, Point<3> & p, double h) const; /// virtual void Project (Point<3> & p) const; /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// virtual double HesseNorm () const; /// virtual Point<3> GetSurfacePoint () const; /// virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & bbox, double facets) const; }; /// class EllipticCylinder : public QuadraticSurface { private: /// Point<3> a; /// Vec<3> vl, vs; /// Vec<3> vab, t0vec, t1vec; /// double vabl, t0, t1; public: /// EllipticCylinder (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs); EllipticCylinder (Array & coeffs); // default constructor for archive EllipticCylinder() {} virtual void DoArchive(Archive& ar) { QuadraticSurface::DoArchive(ar); ar & a & vl & vs & vab & t0vec & t1vec & vabl & t0 & t1; } // static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// virtual double HesseNorm () const; /// virtual Point<3> GetSurfacePoint () const; virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & bbox, double facets) const; virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; virtual double MaxCurvature () const; virtual double MaxCurvatureLoc (const Point<3> & /* c */ , double /* rad */) const; private: void CalcData(); }; /// class Ellipsoid : public QuadraticSurface { private: /// Point<3> a; /// Vec<3> v1, v2, v3; /// double rmin; public: /// Ellipsoid (const Point<3> & aa, const Vec<3> & av1, const Vec<3> & av2, const Vec<3> & av3); // default constructor for archive Ellipsoid() {} virtual void DoArchive(Archive& ar) { QuadraticSurface::DoArchive(ar); ar & a & v1 & v2 & v3 & rmin; } /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// virtual double HesseNorm () const; /// virtual double MaxCurvature () const; /// virtual Point<3> GetSurfacePoint () const; virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & bbox, double facets) const; private: void CalcData(); }; /// class Cone : public QuadraticSurface { /// Point<3> a, b; /// double ra, rb, minr; /// Vec<3> vab, t0vec, t1vec; /// double vabl, t0, t1; double cosphi; public: /// Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb); /// // default constructor for archive Cone() {} virtual void DoArchive(Archive& ar) { QuadraticSurface::DoArchive(ar); ar & a & b & ra & rb & minr & vab & t0vec & t1vec & vabl & t0 & t1 & cosphi; } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// virtual double HesseNorm () const; virtual double LocH (const Point<3> & p, double x, double c, const MeshingParameters & mparam, double hmax) const; /// virtual Point<3> GetSurfacePoint () const; virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & bbox, double facets) const; private: void CalcData(); }; /// /// Elliptic Cone /// Josephat Kalezhi (kalezhi@cbu.ac.zm) /// February 21st, 2018 /// /// class EllipticCone : public QuadraticSurface { Point<3> a; Vec<3> vl, vs; double h, vlr; public: /// EllipticCone (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs, double ah, double avlr); // default constructor for archive EllipticCone() {} virtual void DoArchive(Archive& ar) { QuadraticSurface::DoArchive(ar); ar & a & vl & vs & h & vlr; } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// virtual double HesseNorm () const; virtual double MaxCurvature () const; virtual double MaxCurvatureLoc (const Point<3> & /* c */ , double /* rad */) const; /// virtual Point<3> GetSurfacePoint () const; virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & bbox, double facets) const; private: void CalcData(); }; /** Torus /// Lorenzo Codecasa (codecasa@elet.polimi.it) /// April 27th, 2005 */ class Torus : public OneSurfacePrimitive { /// center of the torus Point<3> c; /// vector normal to the symmetry plane of the torus Vec<3> n; /// Large radius of the torus double R; /// Small radius of the torus double r; public: /// OK Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar); // default constructor for archive Torus() {} virtual void DoArchive(Archive& ar) { OneSurfacePrimitive::DoArchive(ar); ar & c & n & R & r; } /// OK const Point<3> & Center () const { return c; } /// OK const Vec<3> & NormalToPlane () const { return n; } /// OK double LargeRadius () const { return R; } /// OK double SmallRadius () const { return r; } /// OK virtual double CalcFunctionValue (const Point<3> & point) const; /// OK virtual void CalcGradient (const Point<3> & point, Vec<3> & grad) const; /// OK virtual void CalcHesse (const Point<3> & point, Mat<3> & hesse) const; /// OK virtual double HesseNorm () const; /// OK virtual Point<3> GetSurfacePoint () const; /// OK virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; /// OK virtual void SetPrimitiveData (Array & coeffs); /// OK static Primitive * CreateDefault (); /// OK virtual Primitive * Copy () const; /// OK virtual void Transform (Transformation<3> & trans); /// OK virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; /// OK /// virtual void DefineTangentialPlane (const Point<3> & ap1, // const Point<3> & ap2); /// OK /// virtual void ToPlane (const Point<3> & p3d, /// Point<2> & pplane, /// double h, int & zone) const; /// OK /// virtual void FromPlane (const Point<2> & pplane, // Point<3> & p, double h) const; /// OK /// virtual void Project (Point<3> & p) const; /// OK virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// OK virtual void GetTriangleApproximation (TriangleApproximation & tas, const Box<3> & bbox, double facets) const; /// OK virtual void Print (ostream & ist) const; /// OK virtual void Read (istream & ist); }; /// ...end } #endif netgen-6.2.1905/libsrc/csg/python_csg.cpp0000644000175000017500000007321713504650527016726 0ustar kurtkurt#ifdef NG_PYTHON #include <../general/ngpython.hpp> #include using namespace netgen; namespace netgen { extern shared_ptr ng_geometry; } // a shadow solid tree using shared pointers. class SPSolid { shared_ptr s1, s2; Solid * solid; int bc = -1; string bcname = ""; double maxh = -1; string material; bool owner; double red = 0, green = 0, blue = 1; bool transp = false; public: enum optyp { TERM, SECTION, UNION, SUB }; SPSolid (Solid * as) : solid(as), owner(true), op(TERM) { ; } ~SPSolid () { ; // if (owner) delete solid; } SPSolid (optyp aop, shared_ptr as1, shared_ptr as2) : s1(as1), s2(as2), owner(true), op(aop) { if (aop == UNION) solid = new Solid (Solid::UNION, s1->GetSolid(), s2->GetSolid()); else if (aop == SECTION) solid = new Solid (Solid::SECTION, s1->GetSolid(), s2->GetSolid()); else if (aop == SUB) solid = new Solid (Solid::SUB, s1->GetSolid()); // , s2->GetSolid()); } Solid * GetSolid() { return solid; } const Solid * GetSolid() const { return solid; } void GiveUpOwner() { owner = false; if (s1) s1 -> GiveUpOwner(); if (s2) s2 -> GiveUpOwner(); } void AddSurfaces(CSGeometry & geom) { if (op == TERM) geom.AddSurfaces (solid->GetPrimitive()); if (s1) s1 -> AddSurfaces (geom); if (s2) s2 -> AddSurfaces (geom); } void SetMaterial (string mat) { material = mat; } string GetMaterial () { if (!material.empty()) return material; if (s1) { string s1mat = s1->GetMaterial(); if (!s1mat.empty()) return s1mat; } if (s2) { string s2mat = s2->GetMaterial(); if (!s2mat.empty()) return s2mat; } return material; } void SetBC(int abc) { if (bc == -1) { bc = abc; if (s1) s1 -> SetBC(bc); if (s2) s2 -> SetBC(bc); if (op == TERM) { Primitive * prim = solid -> GetPrimitive(); for (int i = 0; i < prim->GetNSurfaces(); i++) prim->GetSurface(i).SetBCProperty (abc); // cout << "set " << prim->GetNSurfaces() << " surfaces to bc " << bc << endl; } } } void SetBCName(string name) { if (bcname == "") { bcname = name; if (s1) s1 -> SetBCName(name); if (s2) s2 -> SetBCName(name); if (op == TERM) { Primitive * prim = solid -> GetPrimitive(); for (int i = 0; i < prim->GetNSurfaces(); i++) prim->GetSurface(i).SetBCName (name); // cout << "set " << prim->GetNSurfaces() << " surfaces to bc " << bc << endl; } } } void SetMaxH(double amaxh) { if (maxh == -1) { maxh = amaxh; if (s1) s1 -> SetMaxH(maxh); if (s2) s2 -> SetMaxH(maxh); if (op == TERM) { Primitive * prim = solid -> GetPrimitive(); for (int i = 0; i < prim->GetNSurfaces(); i++) prim->GetSurface(i).SetMaxH (maxh); } } } void SetColor(double ared, double agreen, double ablue) { red = ared; green = agreen; blue = ablue; } double GetRed() const { return red; } double GetGreen() const { return green; } double GetBlue() const { return blue; } void SetTransparent() { transp = true; } bool IsTransparent() { return transp; } private: optyp op; }; inline ostream & operator<< (ostream & ost, const SPSolid & sol) { ost << *sol.GetSolid(); return ost; } namespace netgen { extern CSGeometry * ParseCSG (istream & istr, CSGeometry *instance=nullptr); } DLL_HEADER void ExportCSG(py::module &m) { py::class_> (m, "SplineCurve2d") .def(py::init<>()) .def ("AddPoint", FunctionPointer ([] (SplineGeometry<2> & self, double x, double y) { self.geompoints.Append (GeomPoint<2> (Point<2> (x,y))); return self.geompoints.Size()-1; })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<2> & self, int i1, int i2) { self.splines.Append (new LineSeg<2> (self.geompoints[i1], self.geompoints[i2])); })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<2> & self, int i1, int i2, int i3) { self.splines.Append (new SplineSeg3<2> (self.geompoints[i1], self.geompoints[i2], self.geompoints[i3])); })) ; py::class_,shared_ptr>> (m,"SplineCurve3d") .def(py::init<>()) .def ("AddPoint", FunctionPointer ([] (SplineGeometry<3> & self, double x, double y, double z) { self.geompoints.Append (GeomPoint<3> (Point<3> (x,y,z))); return self.geompoints.Size()-1; })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<3> & self, int i1, int i2) { self.splines.Append (new LineSeg<3> (self.geompoints[i1], self.geompoints[i2])); })) .def ("AddSegment", FunctionPointer ([] (SplineGeometry<3> & self, int i1, int i2, int i3) { self.splines.Append (new SplineSeg3<3> (self.geompoints[i1], self.geompoints[i2], self.geompoints[i3])); })) ; py::class_> (m, "SplineSurface", "A surface for co dim 2 integrals on the splines") .def("__init__", FunctionPointer ([](SplineSurface* instance, shared_ptr base, py::list cuts) { auto primitive = dynamic_cast (base->GetSolid()->GetPrimitive()); auto acuts = make_shared>>(); for(int i = 0; i> sps(cuts[i]); if(!sps.check()) throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!"); auto sp = dynamic_cast(sps()->GetSolid()->GetPrimitive()); if(sp) acuts->Append(shared_ptr(sp)); else throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!"); } if(!primitive) throw NgException("Base is not a SurfacePrimitive in constructor of SplineSurface!"); new (instance) SplineSurface(shared_ptr(primitive),acuts); py::object obj = py::cast(instance); }),py::arg("base"), py::arg("cuts")=py::list()) .def("AddPoint", FunctionPointer ([] (SplineSurface & self, double x, double y, double z, bool hpref) { self.AppendPoint(Point<3>(x,y,z),hpref); return self.GetNP()-1; }), py::arg("x"),py::arg("y"),py::arg("z"),py::arg("hpref")=false) .def("AddSegment", [] (SplineSurface & self, int i1, int i2, string bcname, double maxh) { auto seg = make_shared>(self.GetPoint(i1),self.GetPoint(i2)); self.AppendSegment(seg,bcname,maxh); }, py::arg("pnt1"),py::arg("pnt2"),py::arg("bcname")="default", py::arg("maxh")=-1.) .def("AddSegment", [] (SplineSurface& self, int i1, int i2, int i3, string bcname, double maxh) { auto seg = make_shared>(self.GetPoint(i1), self.GetPoint(i2), self.GetPoint(i3)); self.AppendSegment(seg, bcname, maxh); }, py::arg("pnt1"),py::arg("pnt2"), py::arg("pnt3"),py::arg("bcname")="default", py::arg("maxh")=-1.) ; py::class_> (m, "Solid") .def ("__str__", &ToString) .def ("__add__", FunctionPointer( [] ( shared_ptr self, shared_ptr other) { return make_shared (SPSolid::UNION, self, other); })) .def ("__mul__", FunctionPointer( [] ( shared_ptr self, shared_ptr other) { return make_shared (SPSolid::SECTION, self, other); })) .def ("__sub__", FunctionPointer ([] ( shared_ptr self, shared_ptr other) { return make_shared (SPSolid::SECTION, self, make_shared (SPSolid::SUB, other, nullptr)); })) .def ("bc", FunctionPointer([](shared_ptr & self, int nr) -> shared_ptr { self->SetBC(nr); return self; })) .def ("bc", FunctionPointer([](shared_ptr & self, string name) -> shared_ptr { self->SetBCName(name); return self; })) .def ("maxh", FunctionPointer([](shared_ptr & self, double maxh) -> shared_ptr { self->SetMaxH(maxh); return self; })) .def ("mat", FunctionPointer([](shared_ptr & self, string mat) -> shared_ptr { self->SetMaterial(mat); return self; })) .def ("mat", &SPSolid::GetMaterial) .def("col", FunctionPointer([](shared_ptr & self, py::list rgb) -> shared_ptr { py::extract red(rgb[0]); py::extract green(rgb[1]); py::extract blue(rgb[2]); self->SetColor(red(),green(),blue()); return self; })) .def("transp", FunctionPointer([](shared_ptr & self)->shared_ptr < SPSolid > { self->SetTransparent(); return self; })) ; m.def ("Sphere", FunctionPointer([](Point<3> c, double r) { Sphere * sp = new Sphere (c, r); Solid * sol = new Solid (sp); return make_shared (sol); })); m.def ("Ellipsoid", FunctionPointer([](Point<3> m, Vec<3> a, Vec<3> b, Vec<3> c) { Ellipsoid * ell = new Ellipsoid (m, a, b, c); Solid * sol = new Solid (ell); return make_shared (sol); })); m.def ("Plane", FunctionPointer([](Point<3> p, Vec<3> n) { Plane * sp = new Plane (p,n); Solid * sol = new Solid (sp); return make_shared (sol); })); m.def ("Cone", FunctionPointer([](Point<3> a, Point<3> b, double ra, double rb) { Cone * cyl = new Cone (a, b, ra, rb); Solid * sol = new Solid (cyl); return make_shared (sol); })); m.def ("Cylinder", FunctionPointer([](Point<3> a, Point<3> b, double r) { Cylinder * cyl = new Cylinder (a, b, r); Solid * sol = new Solid (cyl); return make_shared (sol); })); m.def ("OrthoBrick", FunctionPointer([](Point<3> p1, Point<3> p2) { OrthoBrick * brick = new OrthoBrick (p1,p2); Solid * sol = new Solid (brick); return make_shared (sol); })); m.def ("Torus", FunctionPointer([](Point<3> c, Vec<3> n, double R, double r) { Torus * torus = new Torus (c,n,R,r); Solid * sol = new Solid (torus); return make_shared (sol); })); m.def ("Revolution", FunctionPointer([](Point<3> p1, Point<3> p2, const SplineGeometry<2> & spline) { Revolution * rev = new Revolution (p1, p2, spline); Solid * sol = new Solid(rev); return make_shared (sol); })); m.def ("Extrusion", FunctionPointer([](const SplineGeometry<3> & path, const SplineGeometry<2> & profile, Vec<3> n) { Extrusion * extr = new Extrusion (path,profile,n); Solid * sol = new Solid(extr); return make_shared (sol); })); m.def("EllipticCone", [](const Point<3>& a, const Vec<3>& v, const Vec<3>& w, double h, double r) { auto ellcone = new EllipticCone(a,v,w,h,r); auto sol = new Solid(ellcone); return make_shared(sol); }, py::arg("a"), py::arg("vl"), py::arg("vs"), py::arg("h"), py::arg("r"), R"raw_string( An elliptic cone, given by the point 'a' at the base of the cone along the main axis, the vectors v and w of the long and short axis of the ellipse, respectively, the height of the cone, h, and ratio of base long axis length to top long axis length, r Note: The elliptic cone has to be truncated by planes similar to a cone or an elliptic cylinder. When r =1, the truncated elliptic cone becomes an elliptic cylinder. When r tends to zero, the truncated elliptic cone tends to a full elliptic cone. However, when r = 0, the top part becomes a point(tip) and meshing fails! )raw_string"); m.def ("Or", FunctionPointer([](shared_ptr s1, shared_ptr s2) { return make_shared (SPSolid::UNION, s1, s2); })); m.def ("And", FunctionPointer([](shared_ptr s1, shared_ptr s2) { return make_shared (SPSolid::SECTION, s1, s2); })); py::class_> (m, "CSGeometry") .def(py::init<>()) .def(py::init([](const string& filename) { ifstream ist (filename); auto geo = make_shared(); ParseCSG(ist, geo.get()); geo->FindIdenticSurfaces(1e-8 * geo->MaxSize()); return geo; }), py::arg("filename")) .def(NGSPickle()) .def("Save", FunctionPointer([] (CSGeometry & self, string filename) { cout << "save geometry to file " << filename << endl; self.Save (filename); })) .def("Add", [] (CSGeometry & self, shared_ptr solid, py::list bcmod, double maxh, py::tuple col, bool transparent, int layer) { solid->AddSurfaces (self); solid->GiveUpOwner(); int tlonr = self.SetTopLevelObject (solid->GetSolid()); self.GetTopLevelObject(tlonr) -> SetMaterial(solid->GetMaterial()); self.GetTopLevelObject(tlonr) -> SetRGB(solid->GetRed(),solid->GetGreen(),solid->GetBlue()); // self.GetTopLevelObject(tlonr)->SetTransparent(solid->IsTransparent()); self.GetTopLevelObject(tlonr)->SetTransparent(transparent); self.GetTopLevelObject(tlonr)->SetMaxH(maxh); self.GetTopLevelObject(tlonr)->SetLayer(layer); // cout << "rgb = " << py::len(rgb) << endl; if (py::len(col)==3) self.GetTopLevelObject(tlonr) -> SetRGB(py::cast(col[0]), py::cast(col[1]), py::cast(col[2])); // bcmod is list of tuples ( solid, bcnr ) for (int i = 0; i < py::len(bcmod); i++) { py::tuple tup = py::extract (bcmod[i]) (); auto mod_solid = py::extract> (tup[0]) (); int mod_nr = -1; string * bcname = nullptr; py::object val = tup[1]; if (py::extract(val).check()) mod_nr = py::extract (val)(); if (py::extract(val).check()) bcname = new string ( py::extract (val)()); Array si; mod_solid -> GetSolid() -> GetSurfaceIndices (si); // cout << "change bc on surfaces: " << si << " to " << mod_nr << endl; for (int j = 0; j < si.Size(); j++) { CSGeometry::BCModification bcm; bcm.bcname = bcname ? new string (*bcname) : nullptr; bcm.tlonr = tlonr; bcm.si = si[j]; bcm.bcnr = mod_nr; self.bcmodifications.Append (bcm); } delete bcname; } return tlonr; }, py::arg("solid"), py::arg("bcmod")=py::list(), py::arg("maxh")=1e99, py::arg("col")=py::tuple(), py::arg("transparent")=false, py::arg("layer")=1 ) .def("AddSurface", FunctionPointer ([] (CSGeometry & self, shared_ptr surface, shared_ptr solid) { solid->AddSurfaces (self); solid->GiveUpOwner(); Surface & surf = surface->GetSolid()->GetPrimitive()->GetSurface(); int tlonr = self.SetTopLevelObject (solid->GetSolid(), &surf); // self.GetTopLevelObject(tlonr) -> SetMaterial(solid->GetMaterial()); self.GetTopLevelObject(tlonr) -> SetBCProp(surf.GetBCProperty()); self.GetTopLevelObject(tlonr) -> SetBCName(surf.GetBCName()); self.GetTopLevelObject(tlonr) -> SetRGB(solid->GetRed(),solid->GetGreen(),solid->GetBlue()); self.GetTopLevelObject(tlonr)->SetTransparent(solid->IsTransparent()); }), py::arg("surface"), py::arg("solid") ) .def("AddSplineSurface", FunctionPointer ([] (CSGeometry & self, shared_ptr surf) { auto cuttings = surf->CreateCuttingSurfaces(); auto spsol = make_shared(new Solid(surf.get())); for(auto cut : (*cuttings)){ spsol = make_shared(SPSolid::SECTION,spsol,make_shared(new Solid(cut.get()))); } spsol->AddSurfaces(self); int tlonr = self.SetTopLevelObject(spsol->GetSolid(), surf.get()); self.GetTopLevelObject(tlonr) -> SetBCProp(surf->GetBase()->GetBCProperty()); self.GetTopLevelObject(tlonr) -> SetBCName(surf->GetBase()->GetBCName()); self.GetTopLevelObject(tlonr) -> SetMaxH(surf->GetBase()->GetMaxH()); Array> non_midpoints; for(auto spline : surf->GetSplines()) { non_midpoints.Append(spline->GetPoint(0)); } for(auto p : non_midpoints) self.AddUserPoint(p); self.AddSplineSurface(surf); }), py::arg("SplineSurface")) .def("SingularFace", [] (CSGeometry & self, shared_ptr sol, shared_ptr surfaces, double factor) { int tlonum = -1; for (int i = 0; i < self.GetNTopLevelObjects(); i++) if (self.GetTopLevelObject(i)->GetSolid() == sol->GetSolid()) tlonum = i; if (tlonum == -1) throw NgException("not a top-level-object"); if (!surfaces) surfaces = sol; auto singface = new SingularFace(tlonum+1, surfaces->GetSolid(), factor); self.singfaces.Append(singface); }, py::arg("solid"), py::arg("surfaces")=nullptr, py::arg("factor")=0.25) .def("SingularEdge", [] (CSGeometry & self, shared_ptr s1,shared_ptr s2, double factor) { auto singedge = new SingularEdge(1, -1, self, s1->GetSolid(), s2->GetSolid(), factor); self.singedges.Append (singedge); }) .def("SingularPoint", [] (CSGeometry & self, shared_ptr s1,shared_ptr s2, shared_ptr s3, double factor) { auto singpoint = new SingularPoint(1, s1->GetSolid(), s2->GetSolid(), s3->GetSolid(), factor); self.singpoints.Append (singpoint); }) .def("CloseSurfaces", FunctionPointer ([] (CSGeometry & self, shared_ptr s1, shared_ptr s2, py::list aslices ) { Array si1, si2; s1->GetSolid()->GetSurfaceIndices (si1); s2->GetSolid()->GetSurfaceIndices (si2); cout << "surface ids1 = " << si1 << endl; cout << "surface ids2 = " << si2 << endl; Flags flags; try { int n = py::len(aslices); Array slices(n); for(int i=0; i(aslices[i])(); } flags.SetFlag("slices", slices); } catch( py::error_already_set const & ) { cout << "caught python error:" << endl; PyErr_Print(); } const TopLevelObject * domain = nullptr; self.AddIdentification (new CloseSurfaceIdentification (self.GetNIdentifications()+1, self, self.GetSurface (si1[0]), self.GetSurface (si2[0]), domain, flags)); }), py::arg("solid1"), py::arg("solid2"), py::arg("slices") ) .def("CloseSurfaces", FunctionPointer ([] (CSGeometry & self, shared_ptr s1, shared_ptr s2, int reflevels, shared_ptr domain_solid) { Array si1, si2; s1->GetSolid()->GetSurfaceIndices (si1); s2->GetSolid()->GetSurfaceIndices (si2); cout << "surface ids1 = " << si1 << endl; cout << "surface ids2 = " << si2 << endl; Flags flags; const TopLevelObject * domain = nullptr; if (domain_solid) domain = self.GetTopLevelObject(domain_solid->GetSolid()); self.AddIdentification (new CloseSurfaceIdentification (self.GetNIdentifications()+1, self, self.GetSurface (si1[0]), self.GetSurface (si2[0]), domain, flags)); }), py::arg("solid1"), py::arg("solid2"), py::arg("reflevels")=2, py::arg("domain")=nullptr ) .def("PeriodicSurfaces", FunctionPointer ([] (CSGeometry & self, shared_ptr s1, shared_ptr s2, Transformation<3> trafo) { Array si1, si2; s1->GetSolid()->GetSurfaceIndices (si1); s2->GetSolid()->GetSurfaceIndices (si2); cout << "identify surfaces " << si1[0] << " and " << si2[0] << endl; self.AddIdentification (new PeriodicIdentification (self.GetNIdentifications()+1, self, self.GetSurface (si1[0]), self.GetSurface (si2[0]), trafo)); }), py::arg("solid1"), py::arg("solid2"), py::arg("trafo")=Transformation<3>(Vec<3>(0,0,0)) ) .def("AddPoint", [] (CSGeometry & self, Point<3> p, int index) -> CSGeometry& { self.AddUserPoint(CSGeometry::UserPoint(p, index)); return self; }) .def("GetTransparent", FunctionPointer ([] (CSGeometry & self, int tlonr) { return self.GetTopLevelObject(tlonr)->GetTransparent(); }), py::arg("tlonr") ) .def("SetTransparent", FunctionPointer ([] (CSGeometry & self, int tlonr, bool transparent) { self.GetTopLevelObject(tlonr)->SetTransparent(transparent); }), py::arg("tlonr"), py::arg("transparent") ) .def("GetVisible", FunctionPointer ([] (CSGeometry & self, int tlonr) { return self.GetTopLevelObject(tlonr)->GetVisible(); }), py::arg("tlonr") ) .def("SetVisible", FunctionPointer ([] (CSGeometry & self, int tlonr, bool visible) { self.GetTopLevelObject(tlonr)->SetVisible(visible); }), py::arg("tlonr"), py::arg("visible") ) .def("SetBoundingBox", FunctionPointer ([] (CSGeometry & self, Point<3> pmin, Point<3> pmax) { self.SetBoundingBox(Box<3> (pmin, pmax)); }), py::arg("pmin"), py::arg("pmax") ) .def("Draw", FunctionPointer ([] (shared_ptr self) { self->FindIdenticSurfaces(1e-6); self->CalcTriangleApproximation(0.01, 20); ng_geometry = self; }) ) .def_property_readonly ("ntlo", &CSGeometry::GetNTopLevelObjects) .def("_visualizationData", [](shared_ptr csg_geo) { std::vector vertices; std::vector trigs; std::vector normals; std::vector min = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; std::vector max = {std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::lowest()}; std::vector surfnames; for (int i = 0; i < csg_geo->GetNSurf(); i++) { auto surf = csg_geo->GetSurface(i); surfnames.push_back(surf->GetBCName()); } csg_geo->FindIdenticSurfaces(1e-6); csg_geo->CalcTriangleApproximation(0.01,100); auto nto = csg_geo->GetNTopLevelObjects(); size_t np = 0; size_t ntrig = 0; for (int i = 0; i < nto; i++){ np += csg_geo->GetTriApprox(i)->GetNP(); ntrig += csg_geo->GetTriApprox(i)->GetNT(); } vertices.reserve(np*3); trigs.reserve(ntrig*4); normals.reserve(np*3); int offset_points = 0; for (int i = 0; i < nto; i++) { auto triapprox = csg_geo->GetTriApprox(i); for (int j = 0; j < triapprox->GetNP(); j++) for(int k = 0; k < 3; k++) { float val = triapprox->GetPoint(j)[k]; vertices.push_back(val); min[k] = min2(min[k], val); max[k] = max2(max[k],val); normals.push_back(triapprox->GetNormal(j)[k]); } for (int j = 0; j < triapprox->GetNT(); j++) { for(int k = 0; k < 3; k++) trigs.push_back(triapprox->GetTriangle(j)[k]+offset_points); trigs.push_back(triapprox->GetTriangle(j).SurfaceIndex()); } offset_points += triapprox->GetNP(); } py::gil_scoped_acquire ac; py::dict res; py::list snames; for(auto name : surfnames) snames.append(py::cast(name)); res["vertices"] = MoveToNumpy(vertices); res["triangles"] = MoveToNumpy(trigs); res["normals"] = MoveToNumpy(normals); res["surfnames"] = snames; res["min"] = MoveToNumpy(min); res["max"] = MoveToNumpy(max); return res; }, py::call_guard()) ; m.def("GenerateMesh", FunctionPointer ([](shared_ptr geo, MeshingParameters & param) { auto dummy = make_shared(); SetGlobalMesh (dummy); dummy->SetGeometry(geo); ng_geometry = geo; geo->FindIdenticSurfaces(1e-8 * geo->MaxSize()); try { geo->GenerateMesh (dummy, param); } catch (NgException ex) { cout << "Caught NgException: " << ex.What() << endl; } return dummy; }),py::call_guard()) ; m.def("Save", FunctionPointer ([](const Mesh & self, const string & filename, const CSGeometry & geom) { ostream * outfile; if (filename.substr (filename.length()-3, 3) == ".gz") outfile = new ogzstream (filename.c_str()); else outfile = new ofstream (filename.c_str()); self.Save (*outfile); *outfile << endl << endl << "endmesh" << endl << endl; geom.SaveToMeshFile (*outfile); delete outfile; }),py::call_guard()) ; m.def("ZRefinement", FunctionPointer ([](Mesh & mesh, CSGeometry & geom) { ZRefinementOptions opt; opt.minref = 5; ZRefinement (mesh, &geom, opt); }),py::call_guard()) ; } PYBIND11_MODULE(libcsg, m) { ExportCSG(m); } #endif netgen-6.2.1905/libsrc/csg/curve2d.cpp0000644000175000017500000000272613504650527016120 0ustar kurtkurt#include #include #include namespace netgen { CircleCurve2d :: CircleCurve2d (const Point<2> & acenter, double arad) { center = acenter; rad = arad; } void CircleCurve2d :: Project (Point<2> & p) const { Vec<2> v = p - center; v *= rad/v.Length(); p = center + v; } void CircleCurve2d :: NormalVector (const Point<2> & p, Vec<2> & n) const { n = p - center; n /= n.Length(); } QuadraticCurve2d :: QuadraticCurve2d () { cxx = cyy = cxy = cx = cy = c = 0; } void QuadraticCurve2d :: Read (istream & ist) { ist >> cxx >> cyy >> cxy >> cx >> cy >> c; } void QuadraticCurve2d :: Project (Point<2> & p) const { double f, x, y, gradx, grady, grad2; int its = 0; x = p(0); y = p(1); do { f = cxx * x * x + cyy * y * y + cxy * x * y + cx * x + cy * y + c; gradx = 2 * cxx * x + cxy * y + cx; grady = 2 * cyy * y + cxy * x + cy; grad2 = gradx * gradx + grady * grady; x -= f * gradx / grad2; y -= f * grady / grad2; // (*mycout) << "x = " << x << " y = " << y << " f = " << f << endl; its++; } while (fabs (f) > 1e-8 && its < 20); if (its >= 20) cerr << "QuadraticCurve2d::Project: many iterations, f = " << f << endl; p(0) = x; p(1) = y; } void QuadraticCurve2d :: NormalVector (const Point<2> & p, Vec<2> & n) const { n(0) = 2 * cxx * p(0) + cxy * p(1) + cx; n(1) = 2 * cyy * p(1) + cxy * p(0) + cy; n.Normalize(); } } netgen-6.2.1905/libsrc/csg/CMakeLists.txt0000644000175000017500000000266113504650527016600 0ustar kurtkurtadd_definitions(-DNGINTERFACE_EXPORTS) add_library(csg ${NG_LIB_TYPE} algprim.cpp brick.cpp bspline2d.cpp csgeom.cpp csgparser.cpp curve2d.cpp edgeflw.cpp explicitcurve2d.cpp extrusion.cpp gencyl.cpp genmesh.cpp identify.cpp manifold.cpp meshsurf.cpp polyhedra.cpp revolution.cpp singularref.cpp solid.cpp specpoin.cpp spline3d.cpp surface.cpp triapprox.cpp zrefine.cpp python_csg.cpp splinesurface.cpp ) if(APPLE) set_target_properties( csg PROPERTIES SUFFIX ".so") endif(APPLE) target_link_libraries(csg PUBLIC mesh ${PYTHON_LIBRARIES}) if(NOT WIN32) install( TARGETS csg ${NG_INSTALL_DIR}) endif(NOT WIN32) target_link_libraries(csg PUBLIC ngcore) if(USE_GUI) add_library(csgvis ${NG_LIB_TYPE} vscsg.cpp ) if(NOT WIN32) target_link_libraries(csgvis csg visual) if(APPLE) set_target_properties( csgvis PROPERTIES SUFFIX ".so") endif(APPLE) install( TARGETS csgvis ${NG_INSTALL_DIR}) endif(NOT WIN32) endif(USE_GUI) install(FILES algprim.hpp brick.hpp csgeom.hpp csg.hpp csgparser.hpp curve2d.hpp edgeflw.hpp explicitcurve2d.hpp extrusion.hpp gencyl.hpp geoml.hpp identify.hpp manifold.hpp meshsurf.hpp polyhedra.hpp revolution.hpp singularref.hpp solid.hpp specpoin.hpp spline3d.hpp splinesurface.hpp surface.hpp triapprox.hpp vscsg.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/csg COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/linalg/0000755000175000017500000000000013504650527014525 5ustar kurtkurtnetgen-6.2.1905/libsrc/linalg/linopt.cpp0000644000175000017500000000315113504650527016536 0ustar kurtkurt#include #include #include #include "opti.hpp" namespace netgen { void LinearOptimize (const DenseMatrix & a, const Vector & b, const Vector & c, Vector & x) { int i1, i2, i3, j; DenseMatrix m(3), inv(3); Vector rs(3), hx(3), res(a.Height()), res2(3); double f, fmin; int nrest; if (a.Width() != 3) { cerr << "LinearOptimize only implemented for 3 unknowns" << endl; return; } fmin = 1e10; x = 0; nrest = a.Height(); for (i1 = 1; i1 <= nrest; i1++) for (i2 = i1 + 1; i2 <= nrest; i2++) for (i3 = i2 + 1; i3 <= nrest; i3++) { for (j = 1; j <= 3; j++) { m.Elem(1, j) = a.Get(i1, j); m.Elem(2, j) = a.Get(i2, j); m.Elem(3, j) = a.Get(i3, j); } rs(0) = b(i1-1); rs(1) = b(i2-1); rs(2) = b(i3-1); if (fabs (m.Det()) < 1e-12) continue; CalcInverse (m, inv); inv.Mult (rs, hx); a.Residuum (hx, b, res); // m.Residuum (hx, rs, res2); f = c * hx; /* testout -> precision(12); (*testout) << "i = (" << i1 << "," << i2 << "," << i3 << "), f = " << f << " x = " << x << " res = " << res << " resmin = " << res.Min() << " res2 = " << res2 << " prod = " << prod << endl; */ double rmin = res(0); for (int hi = 1; hi < res.Size(); hi++) if (res(hi) < rmin) rmin = res(hi); if ( (f < fmin) && rmin >= -1e-8) { fmin = f; x = hx; } } } } netgen-6.2.1905/libsrc/linalg/linsearch.cpp0000644000175000017500000001701113504650527017201 0ustar kurtkurt/***************************************************************************/ /* */ /* Problem: Liniensuche */ /* */ /* Programmautor: Joachim Schöberl */ /* Matrikelnummer: 9155284 */ /* */ /* Algorithmus nach: */ /* */ /* Optimierung I, Gfrerer, WS94/95 */ /* Algorithmus 2.1: Liniensuche Problem (ii) */ /* */ /***************************************************************************/ #include #include // min, max, sqr #include #include "opti.hpp" namespace netgen { const double eps0 = 1E-15; // Liniensuche double MinFunction :: Func (const Vector & /* x */) const { cerr << "Func of MinFunction called" << endl; return 0; } void MinFunction :: Grad (const Vector & /* x */, Vector & /* g */) const { cerr << "Grad of MinFunction called" << endl; } double MinFunction :: FuncGrad (const Vector & x, Vector & g) const { cerr << "Grad of MinFunction called" << endl; return 0; /* int n = x.Size(); Vector xr(n); Vector xl(n); double eps = 1e-6; double fl, fr; for (int i = 1; i <= n; i++) { xr.Set (1, x); xl.Set (1, x); xr.Elem(i) += eps; fr = Func (xr); xl.Elem(i) -= eps; fl = Func (xl); g.Elem(i) = (fr - fl) / (2 * eps); } double f = Func(x); // (*testout) << "f = " << f << " grad = " << g << endl; return f; */ } double MinFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const { Vector g(x.Size()); double f = FuncGrad (x, g); deriv = (g * dir); // (*testout) << "g = " << g << ", dir = " << dir << ", deriv = " << deriv << endl; return f; } void MinFunction :: ApproximateHesse (const Vector & x, DenseMatrix & hesse) const { int n = x.Size(); int i, j; static Vector hx; hx.SetSize(n); double eps = 1e-6; double f, f11, f12, f21, f22; for (i = 0; i < n; i++) { for (j = 0; j < i; j++) { hx = x; hx(i) = x(i) + eps; hx(j) = x(j) + eps; f11 = Func(hx); hx(i) = x(i) + eps; hx(j) = x(j) - eps; f12 = Func(hx); hx(i) = x(i) - eps; hx(j) = x(j) + eps; f21 = Func(hx); hx(i) = x(i) - eps; hx(j) = x(j) - eps; f22 = Func(hx); hesse(i, j) = hesse(j, i) = (f11 + f22 - f12 - f21) / (2 * eps * eps); } hx = x; f = Func(x); hx(i) = x(i) + eps; f11 = Func(hx); hx(i) = x(i) - eps; f22 = Func(hx); hesse(i, i) = (f11 + f22 - 2 * f) / (eps * eps); } // (*testout) << "hesse = " << hesse << endl; } /// Line search, modified Mangasarien conditions void lines (Vector & x, // i: initial point of line-search Vector & xneu, // o: solution, if successful Vector & p, // i: search direction double & f, // i: function-value at x // o: function-value at xneu, iff ifail = 0 Vector & g, // i: gradient at x // o: gradient at xneu, iff ifail = 0 const MinFunction & fun, // function to minimize const OptiParameters & par, double & alphahat, // i: initial value for alpha_hat // o: solution alpha iff ifail = 0 double fmin, // i: lower bound for f double mu1, // i: Parameter mu_1 of Alg.2.1 double sigma, // i: Parameter sigma of Alg.2.1 double xi1, // i: Parameter xi_1 of Alg.2.1 double xi2, // i: Parameter xi_1 of Alg.2.1 double tau, // i: Parameter tau of Alg.2.1 double tau1, // i: Parameter tau_1 of Alg.2.1 double tau2, // i: Parameter tau_2 of Alg.2.1 int & ifail) // o: 0 on success // -1 bei termination because lower limit fmin // 1 bei illegal termination due to different reasons { double phi0, phi0prime, phi1, phi1prime, phihatprime; double alpha1, alpha2, alphaincr, c; char flag = 1; long it; alpha1 = 0; alpha2 = 1e50; phi0 = phi1 = f; phi0prime = g * p; if (phi0prime > 0) { ifail = 1; return; } ifail = 1; // Markus phi1prime = phi0prime; // (*testout) << "phi0prime = " << phi0prime << endl; // it = 100000l; it = 0; // cout << "lin: "; while (it++ <= par.maxit_linsearch) { // cout << "i = " << it << " f = " << f << " "; xneu.Set2 (1, x, alphahat, p); // f = fun.FuncGrad (xneu, g); // f = fun.Func (xneu); f = fun.FuncDeriv (xneu, p, phihatprime); // (*testout) << "lines, f = " << f << " phip = " << phihatprime << endl; if (f < fmin) { ifail = -1; break; } if (alpha2 - alpha1 < eps0 * alpha2) { ifail = 0; break; } // (*testout) << "i = " << it << " al = " << alphahat << " f = " << f << " fprime " << phihatprime << endl;; if (f - phi0 > mu1 * alphahat * phi1prime + eps0 * fabs (phi0)) { flag = 0; alpha2 = alphahat; c = (f - phi1 - phi1prime * (alphahat-alpha1)) / sqr (alphahat-alpha1); alphahat = alpha1 - 0.5 * phi1prime / c; if (alphahat > alpha2) alphahat = alpha1 + 1/(4*c) * ( (sigma+mu1) * phi0prime - 2*phi1prime + sqrt (sqr(phi1prime - mu1 * phi0prime) - 4 * (phi1 - phi0 - mu1 * alpha1 * phi0prime) * c)); alphahat = max2 (alphahat, alpha1 + tau * (alpha2 - alpha1)); alphahat = min2 (alphahat, alpha2 - tau * (alpha2 - alpha1)); // (*testout) << " if-branch" << endl; } else { /* f = fun.FuncGrad (xneu, g); phihatprime = g * p; */ f = fun.FuncDeriv (xneu, p, phihatprime); if (phihatprime < sigma * phi0prime * (1 + eps0)) { if (phi1prime < phihatprime) // Approximationsfunktion ist konvex alphaincr = (alphahat - alpha1) * phihatprime / (phi1prime - phihatprime); else alphaincr = 1e99; // MAXDOUBLE; if (flag) { alphaincr = max2 (alphaincr, xi1 * (alphahat-alpha1)); alphaincr = min2 (alphaincr, xi2 * (alphahat-alpha1)); } else { alphaincr = max2 (alphaincr, tau1 * (alpha2 - alphahat)); alphaincr = min2 (alphaincr, tau2 * (alpha2 - alphahat)); } alpha1 = alphahat; alphahat += alphaincr; phi1 = f; phi1prime = phihatprime; } else { ifail = 0; // Erfolg !! break; } // (*testout) << " else, " << endl; } } // (*testout) << "linsearch: it = " << it << " ifail = " << ifail << endl; // cout << endl; fun.FuncGrad (xneu, g); if (it < 0) ifail = 1; // (*testout) << "fail = " << ifail << endl; } void SteepestDescent (Vector & x, const MinFunction & fun, const OptiParameters & par) { int it, n = x.Size(); Vector xnew(n), p(n), g(n), g2(n); double val, alphahat; int fail; val = fun.FuncGrad(x, g); alphahat = 1; // testout << "f = "; for (it = 0; it < 10; it++) { // testout << val << " "; // p = -g; p.Set (-1, g); lines (x, xnew, p, val, g, fun, par, alphahat, -1e5, 0.1, 0.1, 1, 10, 0.1, 0.1, 0.6, fail); x = xnew; } // testout << endl; } } netgen-6.2.1905/libsrc/linalg/vector.hpp0000644000175000017500000001111713504650527016541 0ustar kurtkurt#ifndef FILE_VECTOR #define FILE_VECTOR /* *************************************************************************/ /* File: vector.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Oct. 94 */ /* *************************************************************************/ template class TFlatVector { protected: int s; T * data; public: TFlatVector () { ; } TFlatVector (int as, T * adata) { s = as; data = adata; } int Size () const { return s; } TFlatVector & operator= (const TFlatVector & v) { memcpy (data, v.data, s*sizeof(T)); return *this; } TFlatVector & operator= (T scal) { for (int i = 0; i < s; i++) data[i] = scal; return *this; } T & operator[] (int i) { return data[i]; } const T & operator[] (int i) const { return data[i]; } T & operator() (int i) { return data[i]; } const T & operator() (int i) const { return data[i]; } // double & Elem (int i) { return data[i-1]; } // const double & Get (int i) const { return data[i-1]; } // void Set (int i, double val) { data[i-1] = val; } TFlatVector & operator*= (T scal) { for (int i = 0; i < s; i++) data[i] *= scal; return *this; } }; class FlatVector { protected: int s; double *data; public: FlatVector () { ; } FlatVector (int as, double * adata) { s = as; data = adata; } int Size () const { return s; } FlatVector & operator= (const FlatVector & v) { memcpy (data, v.data, s*sizeof(double)); return *this; } FlatVector & operator= (double scal) { for (int i = 0; i < s; i++) data[i] = scal; return *this; } double & operator[] (int i) { return data[i]; } const double & operator[] (int i) const { return data[i]; } double & operator() (int i) { return data[i]; } const double & operator() (int i) const { return data[i]; } // double & Elem (int i) { return data[i-1]; } // const double & Get (int i) const { return data[i-1]; } // void Set (int i, double val) { data[i-1] = val; } FlatVector & operator*= (double scal) { for (int i = 0; i < s; i++) data[i] *= scal; return *this; } FlatVector & Add (double scal, const FlatVector & v2) { for (int i = 0; i < s; i++) data[i] += scal * v2[i]; return *this; } FlatVector & Set (double scal, const FlatVector & v2) { for (int i = 0; i < s; i++) data[i] = scal * v2[i]; return *this; } FlatVector & Set2 (double scal1, const FlatVector & v1, double scal2, const FlatVector & v2) { for (int i = 0; i < s; i++) data[i] = scal1 * v1[i] + scal2 * v2[i]; return *this; } double L2Norm() const { double sum = 0; for (int i = 0; i < s; i++) sum += data[i] * data[i]; return sqrt (sum); } operator TFlatVector () const { return TFlatVector (s, data); } friend double operator* (const FlatVector & v1, const FlatVector & v2); }; class Vector : public FlatVector { bool ownmem; public: Vector () { s = 0; data = 0; ownmem = false; } Vector (int as) { s = as; data = new double[s]; ownmem = true; } Vector (int as, double * mem) { s = as; data = mem; ownmem = false; } ~Vector () { if (ownmem) delete [] data; } virtual void DoArchive(Archive& ar) { auto size = s; ar & ownmem & size; if(!ar.Output()) SetSize(size); ar.Do(data, size); } Vector & operator= (const FlatVector & v) { memcpy (data, &v(0), s*sizeof(double)); return *this; } Vector & operator= (double scal) { for (int i = 0; i < s; i++) data[i] = scal; return *this; } void SetSize (int as) { if (s != as) { s = as; if (ownmem) delete [] data; data = new double [s]; ownmem = true; } } operator TFlatVector () const { return TFlatVector (s, data); } }; template class VectorMem : public Vector { double mem[S]; public: VectorMem () : Vector(S, &mem[0]) { ; } VectorMem & operator= (const FlatVector & v) { memcpy (data, &v(0), S*sizeof(double)); return *this; } VectorMem & operator= (double scal) { for (int i = 0; i < S; i++) data[i] = scal; return *this; } }; inline double operator* (const FlatVector & v1, const FlatVector & v2) { double sum = 0; for (int i = 0; i < v1.s; i++) sum += v1.data[i] * v2.data[i]; return sum; } inline ostream & operator<< (ostream & ost, const FlatVector & v) { for (int i = 0; i < v.Size(); i++) ost << " " << setw(7) << v[i]; return ost; } #endif netgen-6.2.1905/libsrc/linalg/opti.hpp0000644000175000017500000000767613504650527016231 0ustar kurtkurt#ifndef FILE_OPTI #define FILE_OPTI /**************************************************************************/ /* File: opti.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ namespace netgen { /** Function to be minimized. */ class MinFunction { public: /// virtual double Func (const Vector & x) const; /// virtual void Grad (const Vector & x, Vector & g) const; /// function and gradient virtual double FuncGrad (const Vector & x, Vector & g) const; /// directional derivative virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; /// if |g| < gradaccuray, then stop bfgs virtual double GradStopping (const Vector & /* x */) const { return 0; } /// virtual void ApproximateHesse (const Vector & /* x */, DenseMatrix & /* hesse */) const; }; class OptiParameters { public: int maxit_linsearch; int maxit_bfgs; double typf; double typx; OptiParameters () { maxit_linsearch = 100; maxit_bfgs = 100; typf = 1; typx = 1; } }; /** Implementation of BFGS method. Efficient method for non-linear minimiztion problems. @param x initial value and solution @param fun function to be minimized */ extern double BFGS (Vector & x, const MinFunction & fun, const OptiParameters & par, double eps = 1e-8); /** Steepest descent method. Simple method for non-linear minimization problems. @param x initial value and solution @param fun function to be minimized */ void SteepestDescent (Vector & x, const MinFunction & fun, const OptiParameters & par); extern void lines ( Vector & x, // i: Ausgangspunkt der Liniensuche Vector & xneu, // o: Loesung der Liniensuche bei Erfolg Vector & p, // i: Suchrichtung double & f, // i: Funktionswert an der Stelle x // o: Funktionswert an der Stelle xneu, falls ifail = 0 Vector & g, // i: Gradient an der Stelle x // o: Gradient an der Stelle xneu, falls ifail = 0 const MinFunction & fun, // function to minmize const OptiParameters & par, // parameters double & alphahat, // i: Startwert für alpha_hat // o: Loesung falls ifail = 0 double fmin, // i: untere Schranke für f double mu1, // i: Parameter mu_1 aus Alg.2.1 double sigma, // i: Parameter sigma aus Alg.2.1 double xi1, // i: Parameter xi_1 aus Alg.2.1 double xi2, // i: Parameter xi_1 aus Alg.2.1 double tau, // i: Parameter tau aus Alg.2.1 double tau1, // i: Parameter tau_1 aus Alg.2.1 double tau2, // i: Parameter tau_2 aus Alg.2.1 int & ifail); // o: 0 bei erfolgreicher Liniensuche // -1 bei Abbruch wegen Unterschreiten von fmin // 1 bei Abbruch, aus sonstigen Gründen /** Solver for linear programming problem. \begin{verbatim} min c^t x A x <= b \end{verbatim} */ extern void LinearOptimize (const DenseMatrix & a, const Vector & b, const Vector & c, Vector & x); #ifdef NONE /** Simple projection iteration. find $u = argmin_{v >= 0} 0.5 u A u - f u$ */ extern void ApproxProject (const BaseMatrix & a, Vector & u, const Vector & f, double tau, int its); /** CG Algorithm for quadratic programming problem. See: Dostal ... d ... diag(A) ^{-1} */ extern void ApproxProjectCG (const BaseMatrix & a, Vector & x, const Vector & b, const class DiagMatrix & d, double gamma, int & steps, int & changes); #endif } #endif netgen-6.2.1905/libsrc/linalg/bfgs.cpp0000644000175000017500000002063713504650527016162 0ustar kurtkurt/***************************************************************************/ /* */ /* Vorlesung Optimierung I, Gfrerer, WS94/95 */ /* BFGS-Verfahren zur Lösung freier nichtlinearer Optimierungsprobleme */ /* */ /* Programmautor: Joachim Schöberl */ /* Matrikelnummer: 9155284 */ /* */ /***************************************************************************/ #include #include #include #include "opti.hpp" namespace netgen { void Cholesky (const DenseMatrix & a, DenseMatrix & l, Vector & d) { // Factors A = L D L^T double x; int n = a.Height(); // (*testout) << "a = " << a << endl; l = a; for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { x = l.Get(i, j); for (int k = 1; k < i; k++) x -= l.Get(i, k) * l.Get(j, k) * d(k-1); if (i == j) { d(i-1) = x; } else { l.Elem(j, i) = x / d(i-1); } } } for (int i = 1; i <= n; i++) { l.Elem(i, i) = 1; for (int j = i+1; j <= n; j++) l.Elem(i, j) = 0; } /* // Multiply: (*testout) << "multiplied factors: " << endl; for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) { x = 0; for (k = 1; k <= n; k++) x += l.Get(i, k) * l.Get(j, k) * d.Get(k); (*testout) << x << " "; } (*testout) << endl; */ } void MultLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p) { /* int i, j, n; double val; n = l.Height(); p = g; for (i = 1; i <= n; i++) { val = 0; for (j = i; j <= n; j++) val += p.Get(j) * l.Get(j, i); p.Set(i, val); } for (i = 1; i <= n; i++) p.Elem(i) *= d.Get(i); for (i = n; i >= 1; i--) { val = 0; for (j = 1; j <= i; j++) val += p.Get(j) * l.Get(i, j); p.Set(i, val); } */ double val; int n = l.Height(); p = g; for (int i = 0; i < n; i++) { val = 0; for (int j = i; j < n; j++) val += p(j) * l(j, i); p(i) = val; } for (int i = 0; i < n; i++) p(i) *= d(i); for (int i = n-1; i >= 0; i--) { val = 0; for (int j = 0; j <= i; j++) val += p(j) * l(i, j); p(i) = val; } } void SolveLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p) { double val; int n = l.Height(); p = g; for (int i = 0; i < n; i++) { val = 0; for (int j = 0; j < i; j++) val += p(j) * l(i,j); p(i) -= val; } for (int i = 0; i < n; i++) p(i) /= d(i); for (int i = n-1; i >= 0; i--) { val = 0; for (int j = i+1; j < n; j++) val += p(j) * l(j, i); p(i) -= val; } } int LDLtUpdate (DenseMatrix & l, Vector & d, double a, const Vector & u) { // Bemerkung: Es wird a aus R erlaubt // Rueckgabewert: 0 .. D bleibt positiv definit // 1 .. sonst int n = l.Height(); Vector v(n); double t, told, xi; told = 1; v = u; for (int j = 1; j <= n; j++) { t = told + a * sqr (v(j-1)) / d(j-1); if (t <= 0) { (*testout) << "update err, t = " << t << endl; return 1; } xi = a * v(j-1) / (d(j-1) * t); d(j-1) *= t / told; for (int i = j + 1; i <= n; i++) { v(i-1) -= v(j-1) * l.Elem(i, j); l.Elem(i, j) += xi * v(i-1); } told = t; } return 0; } double BFGS ( Vector & x, // i: Startwert // o: Loesung, falls IFAIL = 0 const MinFunction & fun, const OptiParameters & par, double eps ) { int n = x.Size(); long it; char a1crit, a3acrit; Vector d(n), g(n), p(n), temp(n), bs(n), xneu(n), y(n), s(n), x0(n); DenseMatrix l(n); DenseMatrix hesse(n); double /* normg, */ alphahat, hd, fold; double a1, a2; const double mu1 = 0.1, sigma = 0.1, xi1 = 1, xi2 = 10; const double tau = 0.1, tau1 = 0.1, tau2 = 0.6; Vector typx(x.Size()); // i: typische Groessenordnung der Komponenten double f, f0; double typf; // i: typische Groessenordnung der Loesung double fmin = -1e5; // i: untere Schranke fuer Funktionswert // double eps = 1e-8; // i: Abbruchschranke fuer relativen Gradienten double tauf = 0.1; // i: Abbruchschranke fuer die relative Aenderung der // Funktionswerte int ifail; // o: 0 .. Erfolg // -1 .. Unterschreitung von fmin // 1 .. kein Erfolg bei Liniensuche // 2 .. Überschreitung von itmax typx = par.typx; typf = par.typf; l = 0; for (int i = 1; i <= n; i++) l.Elem(i, i) = 1; f = fun.FuncGrad (x, g); f0 = f; x0 = x; it = 0; do { // Restart // cout << "it " << it << "f = " << f << endl; if (it % (5 * n) == 0) { for (int i = 1; i <= n; i++) d(i-1) = typf/ sqr (typx(i-1)); // 1; for (int i = 2; i <= n; i++) for (int j = 1; j < i; j++) l.Elem(i, j) = 0; /* hesse = 0; for (i = 1; i <= n; i++) hesse.Elem(i, i) = typf / sqr (typx.Get(i)); fun.ApproximateHesse (x, hesse); Cholesky (hesse, l, d); */ } it++; if (it > par.maxit_bfgs) { ifail = 2; break; } // Solve with factorized B SolveLDLt (l, d, g, p); // (*testout) << "l " << l << endl // << "d " << d << endl // << "g " << g << endl // << "p " << p << endl; p *= -1; y = g; fold = f; // line search alphahat = 1; lines (x, xneu, p, f, g, fun, par, alphahat, fmin, mu1, sigma, xi1, xi2, tau, tau1, tau2, ifail); if(ifail == 1) (*testout) << "no success with linesearch" << endl; /* // if (it > par.maxit_bfgs/2) { (*testout) << "x = " << x << endl; (*testout) << "xneu = " << xneu << endl; (*testout) << "f = " << f << endl; (*testout) << "g = " << g << endl; } */ // (*testout) << "it = " << it << " f = " << f << endl; // if (ifail != 0) break; s.Set2 (1, xneu, -1, x); y *= -1; y.Add (1,g); // y += g; x = xneu; // BFGS Update MultLDLt (l, d, s, bs); a1 = y * s; a2 = s * bs; if (a1 > 0 && a2 > 0) { if (LDLtUpdate (l, d, 1 / a1, y) != 0) { cerr << "BFGS update error1" << endl; (*testout) << "BFGS update error1" << endl; (*testout) << "l " << endl << l << endl << "d " << d << endl; ifail = 1; break; } if (LDLtUpdate (l, d, -1 / a2, bs) != 0) { cerr << "BFGS update error2" << endl; (*testout) << "BFGS update error2" << endl; (*testout) << "l " << endl << l << endl << "d " << d << endl; ifail = 1; break; } } // Calculate stop conditions hd = eps * max2 (typf, fabs (f)); a1crit = 1; for (int i = 1; i <= n; i++) if ( fabs (g(i-1)) * max2 (typx(i-1), fabs (x(i-1))) > hd) a1crit = 0; a3acrit = (fold - f <= tauf * max2 (typf, fabs (f))); // testout << "g = " << g << endl; // testout << "a1crit, a3crit = " << int(a1crit) << ", " << int(a3acrit) << endl; /* // Output for tests normg = sqrt (g * g); testout << "it =" << setw (5) << it << " f =" << setw (12) << setprecision (5) << f << " |g| =" << setw (12) << setprecision (5) << normg; testout << " x = (" << setw (12) << setprecision (5) << x.Elem(1); for (i = 2; i <= n; i++) testout << "," << setw (12) << setprecision (5) << x.Elem(i); testout << ")" << endl; */ //(*testout) << "it = " << it << " f = " << f << " x = " << x << endl // << " g = " << g << " p = " << p << endl << endl; // (*testout) << "|g| = " << g.L2Norm() << endl; if (g.L2Norm() < fun.GradStopping (x)) break; } while (!a1crit || !a3acrit); /* (*testout) << "it = " << it << " g = " << g << " f = " << f << " fail = " << ifail << endl; */ if (f0 < f || (ifail == 1)) { (*testout) << "fail, f = " << f << " f0 = " << f0 << endl; f = f0; x = x0; } // cout << endl; // (*testout) << "x = " << x << ", x0 = " << x0 << endl; return f; } } netgen-6.2.1905/libsrc/linalg/densemat.hpp0000644000175000017500000002037413504650527017044 0ustar kurtkurt#ifndef FILE_DENSEMAT #define FILE_DENSEMAT /**************************************************************************/ /* File: densemat.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Oct. 94 */ /**************************************************************************/ /** Data type dense matrix */ class DenseMatrix { protected: int height; int width; double * data; public: /// DLL_HEADER DenseMatrix (); /// DLL_HEADER DenseMatrix (int h, int w = 0); /// DLL_HEADER DenseMatrix (const DenseMatrix & m2); /// DLL_HEADER ~DenseMatrix (); /// DLL_HEADER void SetSize (int h, int w = 0); int Height() const { return height; } int Width() const {return width; } double & operator() (int i, int j) { return data[i*width+j]; } double operator() (int i, int j) const { return data[i*width+j]; } double & operator() (int i) { return data[i]; } double operator() (int i) const { return data[i]; } /// DLL_HEADER DenseMatrix & operator= (const DenseMatrix & m2); /// DLL_HEADER DenseMatrix & operator+= (const DenseMatrix & m2); /// DLL_HEADER DenseMatrix & operator-= (const DenseMatrix & m2); /// DLL_HEADER DenseMatrix & operator= (double v); /// DLL_HEADER DenseMatrix & operator*= (double v); /// DLL_HEADER void Mult (const FlatVector & v, FlatVector & prod) const { double sum; const double * mp, * sp; double * dp; #ifdef DEBUG if (prod.Size() != height) { (*myerr) << "Mult: wrong vector size " << endl; } if (!height) { cout << "DenseMatrix::Mult height = 0" << endl; } if (!width) { cout << "DenseMatrix::Mult width = 0" << endl; } if (width != v.Size()) { (*myerr) << "\nMatrix and Vector don't fit" << endl; } else if (Height() != prod.Size()) { (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; } else #endif { mp = data; dp = &prod(0); for (int i = 0; i < height; i++) { sum = 0; sp = &v(0); for (int j = 0; j < width; j++) { // sum += Get(i,j) * v.Get(j); sum += *mp * *sp; mp++; sp++; } *dp = sum; dp++; } } } /// DLL_HEADER void MultTrans (const Vector & v, Vector & prod) const; /// DLL_HEADER void Residuum (const Vector & x, const Vector & b, Vector & res) const; /// DLL_HEADER double Det () const; /// friend DenseMatrix operator* (const DenseMatrix & m1, const DenseMatrix & m2); /// friend DenseMatrix operator+ (const DenseMatrix & m1, const DenseMatrix & m2); /// friend void Transpose (const DenseMatrix & m1, DenseMatrix & m2); /// friend void Mult (const DenseMatrix & m1, const DenseMatrix & m2, DenseMatrix & m3); /// // friend void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2); /// friend void CalcAAt (const DenseMatrix & a, DenseMatrix & m2); /// // friend void CalcAtA (const DenseMatrix & a, DenseMatrix & m2); /// friend void CalcABt (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2); /// friend void CalcAtB (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2); /// DLL_HEADER void Solve (const Vector & b, Vector & x) const; /// void SolveDestroy (const Vector & b, Vector & x); /// const double & Get(int i, int j) const { return data[(i-1)*width+j-1]; } /// const double & Get(int i) const { return data[i-1]; } /// void Set(int i, int j, double v) { data[(i-1)*width+j-1] = v; } /// double & Elem(int i, int j) { return data[(i-1)*width+j-1]; } /// const double & ConstElem(int i, int j) const { return data[(i-1)*width+j-1]; } }; extern ostream & operator<< (ostream & ost, const DenseMatrix & m); template class MatrixFixWidth { protected: int height; T * __restrict data; bool ownmem; public: /// MatrixFixWidth () { height = 0; data = 0; ownmem = false; } /// MatrixFixWidth (int h) { height = h; data = new T[WIDTH*height]; ownmem = true; } /// MatrixFixWidth (int h, T * adata) { height = h; data = adata; ownmem = false; } /// MatrixFixWidth (const MatrixFixWidth & m2) : height(m2.height), data(m2.data), ownmem(false) { ; } /// ~MatrixFixWidth () { if (ownmem) delete [] data; } void SetSize (int h) { if (h != height) { if (ownmem) delete data; height = h; data = new T[WIDTH*height]; ownmem = true; } } /// int Height() const { return height; } /// int Width() const { return WIDTH; } MatrixFixWidth & operator= (const MatrixFixWidth & m2) { for (int i = 0; i < height*WIDTH; i++) data[i] = m2.data[i]; } /// MatrixFixWidth & operator= (T v) { for (int i = 0; i < height*WIDTH; i++) data[i] = v; return *this; } /* /// void Mult (const FlatVector & v, FlatVector & prod) const { T sum; const T * mp, * sp; T * dp; mp = data; dp = &prod[0]; for (int i = 0; i < height; i++) { sum = 0; sp = &v[0]; for (int j = 0; j < WIDTH; j++) { sum += *mp * *sp; mp++; sp++; } *dp = sum; dp++; } } */ T & operator() (int i, int j) { return data[i*WIDTH+j]; } const T & operator() (int i, int j) const { return data[i*WIDTH+j]; } MatrixFixWidth & operator*= (T v) { if (data) for (int i = 0; i < height*WIDTH; i++) data[i] *= v; return *this; } const T & Get(int i, int j) const { return data[(i-1)*WIDTH+j-1]; } /// const T & Get(int i) const { return data[i-1]; } /// void Set(int i, int j, T v) { data[(i-1)*WIDTH+j-1] = v; } /// T & Elem(int i, int j) { return data[(i-1)*WIDTH+j-1]; } /// const T & ConstElem(int i, int j) const { return data[(i-1)*WIDTH+j-1]; } }; template class MatrixFixWidth { protected: int height; double * data; bool ownmem; public: /// MatrixFixWidth () { height = 0; data = 0; ownmem = false; } /// MatrixFixWidth (int h) { height = h; data = new double[WIDTH*height]; ownmem = true; } /// MatrixFixWidth (int h, double * adata) { height = h; data = adata; ownmem = false; } /// ~MatrixFixWidth () { if (ownmem) delete [] data; } void SetSize (int h) { if (h != height) { if (ownmem) delete data; height = h; data = new double[WIDTH*height]; ownmem = true; } } /// int Height() const { return height; } /// int Width() const { return WIDTH; } /// MatrixFixWidth & operator= (double v) { for (int i = 0; i < height*WIDTH; i++) data[i] = v; return *this; } /// void Mult (const FlatVector & v, FlatVector & prod) const { double sum; const double * mp, * sp; double * dp; /* if (prod.Size() != height) { cerr << "MatrixFixWidth::Mult: wrong vector size " << endl; assert (1); } */ mp = data; dp = &prod[0]; for (int i = 0; i < height; i++) { sum = 0; sp = &v[0]; for (int j = 0; j < WIDTH; j++) { sum += *mp * *sp; mp++; sp++; } *dp = sum; dp++; } } double & operator() (int i, int j) { return data[i*WIDTH+j]; } const double & operator() (int i, int j) const { return data[i*WIDTH+j]; } MatrixFixWidth & operator*= (double v) { if (data) for (int i = 0; i < height*WIDTH; i++) data[i] *= v; return *this; } const double & Get(int i, int j) const { return data[(i-1)*WIDTH+j-1]; } /// const double & Get(int i) const { return data[i-1]; } /// void Set(int i, int j, double v) { data[(i-1)*WIDTH+j-1] = v; } /// double & Elem(int i, int j) { return data[(i-1)*WIDTH+j-1]; } /// const double & ConstElem(int i, int j) const { return data[(i-1)*WIDTH+j-1]; } }; template extern ostream & operator<< (ostream & ost, const MatrixFixWidth & m) { for (int i = 0; i < m.Height(); i++) { for (int j = 0; j < m.Width(); j++) ost << m.Get(i+1,j+1) << " "; ost << endl; } return ost; }; extern DLL_HEADER void CalcAtA (const DenseMatrix & a, DenseMatrix & m2); extern DLL_HEADER void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2); #endif netgen-6.2.1905/libsrc/linalg/linalg.hpp0000644000175000017500000000131013504650527016477 0ustar kurtkurt#ifndef FILE_LINALG #define FILE_LINALG /* *************************************************************************/ /* File: linalg.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Oct. 94 */ /* *************************************************************************/ /* Data types for basic linear algebra The basic concepts include the data types Vector SparseMatrix DenseMatrix */ #include "../include/myadt.hpp" namespace netgen { #include "vector.hpp" #include "densemat.hpp" #include "polynomial.hpp" } #endif netgen-6.2.1905/libsrc/linalg/polynomial.hpp0000644000175000017500000000231213504650527017417 0ustar kurtkurt#ifndef FILE_POLYNOMIAL #define FILE_POLYNOMIAL /* *************************************************************************/ /* File: polynomial.hh */ /* Author: Joachim Schoeberl */ /* Date: 25. Nov. 99 */ /* *************************************************************************/ class QuadraticPolynomial1V { double c, cx, cxx; public: QuadraticPolynomial1V (double ac, double acx, double acxx); double Value (double x); double MaxUnitInterval (); }; class LinearPolynomial2V { double c, cx, cy; public: LinearPolynomial2V (double ac, double acx, double acy); friend class QuadraticPolynomial2V; }; class QuadraticPolynomial2V { double c, cx, cy, cxx, cxy, cyy; public: QuadraticPolynomial2V (); QuadraticPolynomial2V (double ac, double acx, double acy, double acxx, double acxy, double acyy); void Square (const LinearPolynomial2V & lp); void Add (double lam, const QuadraticPolynomial2V & qp); double Value (double x, double y); // double MinUnitSquare (); double MaxUnitSquare (); double MaxUnitTriangle (); }; #endif netgen-6.2.1905/libsrc/linalg/polynomial.cpp0000644000175000017500000000651313504650527017421 0ustar kurtkurt#include #include namespace netgen { QuadraticPolynomial1V :: QuadraticPolynomial1V (double ac, double acx, double acxx) { c = ac; cx = acx; cxx = acxx; } double QuadraticPolynomial1V :: Value (double x) { return c + cx * x + cxx * x * x; } double QuadraticPolynomial1V :: MaxUnitInterval () { // inner max if (cxx < 0 && cx > 0 && cx < -2 * cxx) { return c - 0.25 * cx * cx / cxx; } if (cx + cxx > 0) // right edge return c + cx + cxx; // left end return c; } LinearPolynomial2V :: LinearPolynomial2V (double ac, double acx, double acy) { c = ac; cx = acx; cy = acy; }; QuadraticPolynomial2V :: QuadraticPolynomial2V () { ; } QuadraticPolynomial2V :: QuadraticPolynomial2V (double ac, double acx, double acy, double acxx, double acxy, double acyy) { c = ac; cx = acx; cy = acy; cxx = acxx; cxy = acxy; cyy = acyy; } void QuadraticPolynomial2V :: Square (const LinearPolynomial2V & lp) { c = lp.c * lp.c; cx = 2 * lp.c * lp.cx; cy = 2 * lp.c * lp.cy; cxx = lp.cx * lp.cx; cxy = 2 * lp.cx * lp.cy; cyy = lp.cy * lp.cy; } void QuadraticPolynomial2V :: Add (double lam, const QuadraticPolynomial2V & qp2) { c += lam * qp2.c; cx += lam * qp2.cx; cy += lam * qp2.cy; cxx += lam * qp2.cxx; cxy += lam * qp2.cxy; cyy += lam * qp2.cyy; } double QuadraticPolynomial2V :: Value (double x, double y) { return c + cx * x + cy * y + cxx * x * x + cxy * x * y + cyy * y * y; } /* double QuadraticPolynomial2V :: MinUnitSquare () { double x, y; double minv = 1e8; double val; for (x = 0; x <= 1; x += 0.1) for (y = 0; y <= 1; y += 0.1) { val = Value (x, y); if (val < minv) minv = val; } return minv; }; */ double QuadraticPolynomial2V :: MaxUnitSquare () { // find critical point double maxv = c; double hv; double det, x0, y0; det = 4 * cxx * cyy - cxy * cxy; if (det > 0) { // definite surface x0 = (-2 * cyy * cx + cxy * cy) / det; y0 = (cxy * cx -2 * cxx * cy) / det; if (x0 >= 0 && x0 <= 1 && y0 >= 0 && y0 <= 1) { hv = Value (x0, y0); if (hv > maxv) maxv = hv; } } QuadraticPolynomial1V e1(c, cx, cxx); QuadraticPolynomial1V e2(c, cy, cyy); QuadraticPolynomial1V e3(c+cy+cyy, cx+cxy, cxx); QuadraticPolynomial1V e4(c+cx+cxx, cy+cxy, cyy); hv = e1.MaxUnitInterval(); if (hv > maxv) maxv = hv; hv = e2.MaxUnitInterval(); if (hv > maxv) maxv = hv; hv = e3.MaxUnitInterval(); if (hv > maxv) maxv = hv; hv = e4.MaxUnitInterval(); if (hv > maxv) maxv = hv; return maxv; }; double QuadraticPolynomial2V :: MaxUnitTriangle () { // find critical point double maxv = c; double hv; double det, x0, y0; det = 4 * cxx * cyy - cxy * cxy; if (cxx < 0 && det > 0) { // definite surface x0 = (-2 * cyy * cx + cxy * cy) / det; y0 = (cxy * cx -2 * cxx * cy) / det; if (x0 >= 0 && y0 >= 0 && x0+y0 <= 1) { return Value (x0, y0); } } QuadraticPolynomial1V e1(c, cx, cxx); QuadraticPolynomial1V e2(c, cy, cyy); QuadraticPolynomial1V e3(c+cy+cyy, cx-cy+cxy-2*cyy, cxx-cxy+cyy); hv = e1.MaxUnitInterval(); if (hv > maxv) maxv = hv; hv = e2.MaxUnitInterval(); if (hv > maxv) maxv = hv; hv = e3.MaxUnitInterval(); if (hv > maxv) maxv = hv; return maxv; } } netgen-6.2.1905/libsrc/linalg/densemat.cpp0000644000175000017500000007432613504650527017045 0ustar kurtkurt#include #include namespace netgen { DenseMatrix :: DenseMatrix () { data = NULL; height = 0; width = 0; } DenseMatrix :: DenseMatrix (int h, int w) { if (!w) w = h; width = w; height = h; int hw = h*w; if (hw) data = new double[hw]; else data = 0; for (int i = 0 ; i < (hw); i++) data[i] = 0; } /* DenseMatrix :: DenseMatrix (int h, int w, const double * d) : BaseMatrix (h, w) { int size = h * w; int i; if (size) { data = new double[size]; for (i = 0; i < size; i++) data[i] = d[i]; } else data = NULL; } */ DenseMatrix :: DenseMatrix (const DenseMatrix & m2) { data = NULL; height = width = 0; SetSize (m2.Height(), m2.Width()); memcpy (data, m2.data, sizeof(double) * Height() * Width()); } DenseMatrix :: ~DenseMatrix () { delete [] data; } void DenseMatrix :: SetSize (int h, int w) { if (!w) w = h; if (height == h && width == w) return; height = h; width = w; delete[] data; if (h*w) data = new double[h*w]; else data = NULL; } /* DenseMatrix & DenseMatrix :: operator= (const BaseMatrix & m2) { int i, j; SetSize (m2.Height(), m2.Width()); if (data) for (i = 1; i <= Height(); i++) for (j = 1; j <= Width(); j++) Set (i, j, m2(i, j)); else (*myerr) << "DenseMatrix::Operator=: Matrix not allocated" << endl; return *this; } */ DenseMatrix & DenseMatrix :: operator= (const DenseMatrix & m2) { SetSize (m2.Height(), m2.Width()); if (data) memcpy (data, m2.data, sizeof(double) * m2.Height() * m2.Width()); return *this; } DenseMatrix & DenseMatrix :: operator+= (const DenseMatrix & m2) { int i; double * p, * q; if (Height() != m2.Height() || Width() != m2.Width()) { (*myerr) << "DenseMatrix::Operator+=: Sizes don't fit" << endl; return *this; } if (data) { p = data; q = m2.data; for (i = Width() * Height(); i > 0; i--) { *p += *q; p++; q++; } } else (*myerr) << "DenseMatrix::Operator+=: Matrix not allocated" << endl; return *this; } DenseMatrix & DenseMatrix :: operator-= (const DenseMatrix & m2) { int i; double * p, * q; if (Height() != m2.Height() || Width() != m2.Width()) { (*myerr) << "DenseMatrix::Operator-=: Sizes don't fit" << endl; return *this; } if (data) { p = data; q = m2.data; for (i = Width() * Height(); i > 0; i--) { *p -= *q; p++; q++; } } else (*myerr) << "DenseMatrix::Operator-=: Matrix not allocated" << endl; return *this; } DenseMatrix & DenseMatrix :: operator= (double v) { double * p = data; if (data) for (int i = width*height; i > 0; i--, p++) *p = v; return *this; } DenseMatrix & DenseMatrix :: operator*= (double v) { double * p = data; if (data) for (int i = width*height; i > 0; i--, p++) *p *= v; return *this; } double DenseMatrix :: Det () const { if (width != height) { (*myerr) << "DenseMatrix :: Det: width != height" << endl; return 0; } switch (width) { case 1: return data[0]; case 2: return data[0] * data[3] - data[1] * data[2]; case 3: return data[0] * data[4] * data[8] + data[1] * data[5] * data[6] + data[2] * data[3] * data[7] - data[0] * data[5] * data[7] - data[1] * data[3] * data[8] - data[2] * data[4] * data[6]; default: { (*myerr) << "Matrix :: Det: general size not implemented (size=" << width << ")" << endl; return 0; } } } void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2) { double det; if (m1.Width() != m1.Height()) { (*myerr) << "CalcInverse: matrix not symmetric" << endl; return; } if (m1.Width() != m2.Width() || m1.Height() != m2.Height()) { (*myerr) << "CalcInverse: dim(m2) != dim(m1)" << endl; return; } if (m1.Width() <= 3) { det = m1.Det(); if (det == 0) { (*myerr) << "CalcInverse: Matrix singular" << endl; (*testout) << "CalcInverse: Matrix singular" << endl; return; } det = 1.0 / det; switch (m1.Width()) { case 1: { m2(0,0) = det; return; } case 2: { m2(0,0) = det * m1(3); m2(1,1) = det * m1(0); m2(0,1) = -det * m1(1); m2(1,0) = - det * m1(2); return; } case 3: { m2(0, 0) = det * (m1(4) * m1(8) - m1(5) * m1(7)); m2(1, 0) = -det * (m1(3) * m1(8) - m1(5) * m1(6)); m2(2, 0) = det * (m1(3) * m1(7) - m1(4) * m1(6)); m2(0, 1) = -det * (m1(1) * m1(8) - m1(2) * m1(7)); m2(1, 1) = det * (m1(0) * m1(8) - m1(2) * m1(6)); m2(2, 1) = -det * (m1(0) * m1(7) - m1(1) * m1(6)); m2(0, 2) = det * (m1(1) * m1(5) - m1(2) * m1(4)); m2(1, 2) = -det * (m1(0) * m1(5) - m1(2) * m1(3)); m2(2, 2) = det * (m1(0) * m1(4) - m1(1) * m1(3)); return; } } } else { int i, j, k, n; n = m1.Height(); #ifdef CHOL int dots = (n > 200); // Cholesky double x; Vector p(n); m2 = m1; /* m2.SetSymmetric(); if (!m2.Symmetric()) cerr << "m should be symmetric for Cholesky" << endl; */ for (i = 1; i <= n; i++) for (j = 1; j < i; j++) m2.Elem(j, i) = m2.Get(i, j); for (i = 1; i <= n; i++) { if (dots && i % 10 == 0) (*mycout) << "." << flush; for (j = i; j <= n; j++) { x = m2.Get(i, j); const double * pik = &m2.Get(i, 1); const double * pjk = &m2.Get(j, 1); for (k = i-2; k >= 0; --k, ++pik, ++pjk) x -= (*pik) * (*pjk); // for (k = i-1; k >= 1; --k) // x -= m2.Get(j, k) * m2.Get(i, k); if (i == j) { if (x <= 0) { cerr << "Matrix indefinite 1" << endl; return; } p.Elem(i) = 1 / sqrt(x); } else { m2.Elem(j, i) = x * p.Get(i); } } } for (i = 1; i <= n; i++) m2.Elem(i, i) = 1 / p.Get(i); // check: A = L L^t // for (i = 1; i <= n; i++) // for (j = 1; j <= n; j++) // { // x = 0; // for (k = 1; k <= i && k <= j; k++) // x += m2.Get(i, k) * m2.Get(j, k); // (*testout) << "err " << i << "," << j << " = " << (m1.Get(i, j) - x) << endl; // } // calc L^{-1}, store upper triangle // DenseMatrix hm(n); // hm = m2; for (i = 1; i <= n; i++) { if (dots && i % 10 == 0) (*mycout) << "+" << flush; for (j = i; j <= n; j++) { x = 0; if (j == i) x = 1; const double * pjk = &m2.Get(j, i); const double * pik = &m2.Get(i, i); for (k = i; k < j; k++, ++pjk, ++pik) x -= *pik * *pjk; // for (k = i; k < j; k++) // x -= m2.Get(j, k) * m2.Get(i, k); m2.Elem(i, j) = x / m2.Get(j, j); } } // (*testout) << "check L^-1" << endl; // for (i = 1; i <= n; i++) // for (j = 1; j <= n; j++) // { // x = 0; // for (k = j; k <= i; k++) // x += hm.Get(i, k) * m2.Get(j, k); // (*testout) << "i, j = " << i << "," << j << " x = " << x << endl; // } // calc A^-1 = L^-T * L^-1 for (i = 1; i <= n; i++) { if (dots && i % 10 == 0) (*mycout) << "-" << flush; for (j = 1; j <= i; j++) { x = 0; k = i; if (j > i) k = j; const double * pik = &m2.Get(i, k); const double * pjk = &m2.Get(j, k); for ( ; k <= n; ++k, ++pik, ++pjk) x += *pik * *pjk; // for ( ; k <= n; k++) // x += m2.Get(i, k) * m2.Get(j, k); m2.Elem(i, j) = x; } } for (i = 1; i <= n; i++) for (j = 1; j < i; j++) m2.Elem(j, i) = m2.Get(i, j); if (dots) (*mycout) << endl; #endif // Gauss - Jordan - algorithm int r, hi; double max, hr; Array p(n); // pivot-permutation Vector hv(n); m2 = m1; /* if (m2.Symmetric()) for (i = 1; i <= n; i++) for (j = 1; j < i; j++) m2.Elem(j, i) = m2.Get(i, j); */ // Algorithm of Stoer, Einf. i. d. Num. Math, S 145 for (j = 1; j <= n; j++) p.Set(j, j); for (j = 1; j <= n; j++) { // pivot search max = fabs(m2.Get(j, j)); r = j; for (i = j+1; i <= n ;i++) if (fabs (m2.Get(i, j)) > max) { r = i; max = fabs (m2.Get(i, j)); } if (max < 1e-20) { cerr << "Inverse matrix: matrix singular" << endl; *testout << "Inverse matrix: matrix singular" << endl; return; } r = j; // exchange rows if (r > j) { for (k = 1; k <= n; k++) { hr = m2.Get(j, k); m2.Elem(j, k) = m2.Get(r, k); m2.Elem(r, k) = hr; } hi = p.Get(j); p.Elem(j) = p.Get(r); p.Elem(r) = hi; } // transformation hr = 1 / m2.Get(j, j); for (i = 1; i <= n; i++) m2.Elem(i, j) *= hr; m2.Elem(j, j) = hr; for (k = 1; k <= n; k++) if (k != j) { for (i = 1; i <= n; i++) if (i != j) m2.Elem(i, k) -= m2.Elem(i, j) * m2.Elem(j, k); m2.Elem(j, k) *= -hr; } } // col exchange for (i = 1; i <= n; i++) { for (k = 1; k <= n; k++) hv(p.Get(k)-1) = m2.Get(i, k); for (k = 1; k <= n; k++) m2.Elem(i, k) = hv(k-1); } /* if (m1.Symmetric()) for (i = 1; i <= n; i++) for (j = 1; j < i; j++) m1.Elem(j, i) = m1.Get(i, j); m2 = 0; for (i = 1; i <= n; i++) m2.Elem(i, i) = 1; for (i = 1; i <= n; i++) { // (*mycout) << '.' << flush; q = m1.Get(i, i); for (k = 1; k <= n; k++) { m1.Elem(i, k) /= q; m2.Elem(i, k) /= q; } for (j = i+1; j <= n; j++) { q = m1.Elem(j, i); double * m1pi = &m1.Elem(i, i); double * m1pj = &m1.Elem(j, i); for (k = n; k >= i; --k, ++m1pi, ++m1pj) *m1pj -= q * (*m1pi); double * m2pi = &m2.Elem(i, 1); double * m2pj = &m2.Elem(j, 1); for (k = i; k > 0; --k, ++m2pi, ++m2pj) *m2pj -= q * (*m2pi); // for (k = 1; k <= n; k++) // { // m1.Elem(j, k) -= q * m1.Elem(i, k); // m2.Elem(j, k) -= q * m2.Elem(i, k); // } } } for (i = n; i >= 1; i--) { // (*mycout) << "+" << flush; for (j = 1; j < i; j++) { q = m1.Elem(j, i); double * m2pi = &m2.Elem(i, 1); double * m2pj = &m2.Elem(j, 1); for (k = n; k > 0; --k, ++m2pi, ++m2pj) *m2pj -= q * (*m2pi); // for (k = 1; k <= n; k++) // { // m1.Elem(j, k) -= q * m1.Elem(i, k); // m2.Elem(j, k) -= q * m2.Elem(i, k); // } } } if (m2.Symmetric()) { for (i = 1; i <= n; i++) for (j = 1; j < i; j++) m2.Elem(i, j) = m2.Elem(j, i); } */ } } void CalcAAt (const DenseMatrix & a, DenseMatrix & m2) { int n1 = a.Height(); int n2 = a.Width(); int i, j, k; double sum; const double *p, *q, *p0; if (m2.Height() != n1 || m2.Width() != n1) { (*myerr) << "CalcAAt: sizes don't fit" << endl; return; } for (i = 1; i <= n1; i++) { sum = 0; p = &a.ConstElem(i, 1); for (k = 1; k <= n2; k++) { sum += *p * *p; p++; } m2.Set(i, i, sum); p0 = &a.ConstElem(i, 1); q = a.data; for (j = 1; j < i; j++) { sum = 0; p = p0; for (k = 1; k <= n2; k++) { sum += *p * *q; p++; q++; } m2.Set(i, j, sum); m2.Set(j, i, sum); } } } void CalcAtA (const DenseMatrix & a, DenseMatrix & m2) { int n1 = a.Height(); int n2 = a.Width(); int i, j, k; double sum; if (m2.Height() != n2 || m2.Width() != n2) { (*myerr) << "CalcAtA: sizes don't fit" << endl; return; } for (i = 1; i <= n2; i++) for (j = 1; j <= n2; j++) { sum = 0; for (k = 1; k <= n1; k++) sum += a.Get(k, i) * a.Get(k, j); m2.Elem(i, j) = sum; } } void CalcABt (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2) { int n1 = a.Height(); int n2 = a.Width(); int n3 = b.Height(); int i, j, k; double sum; if (m2.Height() != n1 || m2.Width() != n3 || b.Width() != n2) { (*myerr) << "CalcABt: sizes don't fit" << endl; return; } double * pm2 = &m2.Elem(1, 1); const double * pa1 = &a.Get(1, 1); for (i = 1; i <= n1; i++) { const double * pb = &b.Get(1, 1); for (j = 1; j <= n3; j++) { sum = 0; const double * pa = pa1; for (k = 1; k <= n2; k++) { sum += *pa * *pb; pa++; pb++; } *pm2 = sum; pm2++; } pa1 += n2; } } void CalcAtB (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2) { int n1 = a.Height(); int n2 = a.Width(); int n3 = b.Width(); int i, j, k; if (m2.Height() != n2 || m2.Width() != n3 || b.Height() != n1) { (*myerr) << "CalcAtB: sizes don't fit" << endl; return; } for (i = 1; i <= n2 * n3; i++) m2.data[i-1] = 0; for (i = 1; i <= n1; i++) for (j = 1; j <= n2; j++) { const double va = a.Get(i, j); double * pm2 = &m2.Elem(j, 1); const double * pb = &b.Get(i, 1); for (k = 1; k <= n3; ++k, ++pm2, ++pb) *pm2 += va * *pb; // for (k = 1; k <= n3; k++) // m2.Elem(j, k) += va * b.Get(i, k); } /* for (i = 1; i <= n2; i++) for (j = 1; j <= n3; j++) { sum = 0; for (k = 1; k <= n1; k++) sum += a.Get(k, i) * b.Get(k, j); m2.Elem(i, j) = sum; } */ } DenseMatrix operator* (const DenseMatrix & m1, const DenseMatrix & m2) { DenseMatrix temp (m1.Height(), m2.Width()); if (m1.Width() != m2.Height()) { (*myerr) << "DenseMatrix :: operator*: Matrix Size does not fit" << endl; } else if (temp.Height() != m1.Height()) { (*myerr) << "DenseMatrix :: operator*: temp not allocated" << endl; } else { Mult (m1, m2, temp); } return temp; } void Mult (const DenseMatrix & m1, const DenseMatrix & m2, DenseMatrix & m3) { double sum; double *p1, *p1s, *p1sn, *p1snn, *p2, *p2s, *p2sn, *p3; if (m1.Width() != m2.Height() || m1.Height() != m3.Height() || m2.Width() != m3.Width() ) { (*myerr) << "DenseMatrix :: Mult: Matrix Size does not fit" << endl; (*myerr) << "m1: " << m1.Height() << " x " << m1.Width() << endl; (*myerr) << "m2: " << m2.Height() << " x " << m2.Width() << endl; (*myerr) << "m3: " << m3.Height() << " x " << m3.Width() << endl; return; } /* else if (m1.Symmetric() || m2.Symmetric() || m3.Symmetric()) { (*myerr) << "DenseMatrix :: Mult: not implemented for symmetric matrices" << endl; return; } */ else { // int i, j, k; int n1 = m1.Height(); int n2 = m2.Width(); int n3 = m1.Width(); /* for (i = n1 * n2-1; i >= 0; --i) m3.data[i] = 0; const double * pm1 = &m1.Get(1, 1); for (i = 1; i <= n1; i++) { const double * pm2 = &m2.Get(1, 1); double * pm3i = &m3.Elem(i, 1); for (j = 1; j <= n3; j++) { const double vm1 = *pm1; ++pm1; // const double vm1 = m1.Get(i, j); double * pm3 = pm3i; // const double * pm2 = &m2.Get(j, 1); for (k = 0; k < n2; k++) { *pm3 += vm1 * *pm2; ++pm2; ++pm3; } // for (k = 1; k <= n2; k++) // m3.Elem(i, k) += m1.Get(i, j) * m2.Get(j, k); } } */ /* for (i = 1; i <= n1; i++) for (j = 1; j <= n2; j++) { sum = 0; for (k = 1; k <= n3; k++) sum += m1.Get(i, k) * m2.Get(k, j); m3.Set(i, j, sum); } */ /* for (i = 1; i <= n1; i++) { const double pm1i = &m1.Get(i, 1); const double pm2j = &m2.Get(1, 1); for (j = 1; j <= n2; j++) { double sum = 0; const double * pm1 = pm1i; const double * pm2 = pm2j; pm2j++; for (k = 1; k <= n3; k++) { sum += *pm1 * *pm2; ++pm1; pm2 += n2; } m3.Set (i, j, sum); } } */ p3 = m3.data; p1s = m1.data; p2sn = m2.data + n2; p1snn = p1s + n1 * n3; while (p1s != p1snn) { p1sn = p1s + n3; p2s = m2.data; while (p2s != p2sn) { sum = 0; p1 = p1s; p2 = p2s; p2s++; while (p1 != p1sn) { sum += *p1 * *p2; p1++; p2 += n2; } *p3++ = sum; } p1s = p1sn; } } } DenseMatrix operator+ (const DenseMatrix & m1, const DenseMatrix & m2) { DenseMatrix temp (m1.Height(), m1.Width()); int i, j; if (m1.Width() != m2.Width() || m1.Height() != m2.Height()) { (*myerr) << "BaseMatrix :: operator+: Matrix Size does not fit" << endl; } else if (temp.Height() != m1.Height()) { (*myerr) << "BaseMatrix :: operator+: temp not allocated" << endl; } else { for (i = 1; i <= m1.Height(); i++) for (j = 1; j <= m1.Width(); j++) { temp.Set(i, j, m1.Get(i, j) + m2.Get(i, j)); } } return temp; } void Transpose (const DenseMatrix & m1, DenseMatrix & m2) { int w = m1.Width(); int h = m1.Height(); int i, j; m2.SetSize (w, h); double * pm2 = &m2.Elem(1, 1); for (j = 1; j <= w; j++) { const double * pm1 = &m1.Get(1, j); for (i = 1; i <= h; i++) { *pm2 = *pm1; pm2 ++; pm1 += w; } } } /* void DenseMatrix :: Mult (const Vector & v, Vector & prod) const { double sum, val; const double * mp, * sp; double * dp; // const Vector & v = bv.CastToVector(); // Vector & prod = bprod.CastToVector(); int n = Height(); int m = Width(); if (prod.Size() != n) prod.SetSize (n); #ifdef DEVELOP if (!n) { cout << "DenseMatrix::Mult mheight = 0" << endl; } if (!m) { cout << "DenseMatrix::Mult mwidth = 0" << endl; } if (m != v.Size()) { (*myerr) << "\nMatrix and Vector don't fit" << endl; } else if (Height() != prod.Size()) { (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; } else #endif { if (Symmetric()) { int i, j; for (i = 1; i <= n; i++) { sp = &v.Get(1); dp = &prod.Elem(1); mp = &Get(i, 1); val = v.Get(i); sum = Get(i, i) * val; for (j = 1; j < i; ++j, ++mp, ++sp, ++dp) { sum += *mp * *sp; *dp += val * *mp; } prod.Elem(i) = sum; } } else { mp = data; dp = &prod.Elem(1); for (int i = 1; i <= n; i++) { sum = 0; sp = &v.Get(1); for (int j = 1; j <= m; j++) { // sum += Get(i,j) * v.Get(j); sum += *mp * *sp; mp++; sp++; } // prod.Set (i, sum); *dp = sum; dp++; } } } } */ void DenseMatrix :: MultTrans (const Vector & v, Vector & prod) const { // const Vector & v = (const Vector&)bv; // .CastToVector(); // Vector & prod = (Vector & )bprod; // .CastToVector(); /* if (Height() != v.Size()) { (*myerr) << "\nMatrix and Vector don't fit" << endl; } else if (Width() != prod.Size()) { (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; } else */ { int i, j; int w = Width(), h = Height(); if (prod.Size() != w) prod.SetSize (w); const double * pmat = &Get(1, 1); const double * pv = &v(0); prod = 0; for (i = 1; i <= h; i++) { double val = *pv; ++pv; double * pprod = &prod(0); for (j = w-1; j >= 0; --j, ++pmat, ++pprod) { *pprod += val * *pmat; } } /* double sum; for (i = 1; i <= Width(); i++) { sum = 0; for (int j = 1; j <= Height(); j++) sum += Get(j, i) * v.Get(j); prod.Set (i, sum); } */ } } void DenseMatrix :: Residuum (const Vector & x, const Vector & b, Vector & res) const { double sum; // const Vector & x = bx.CastToVector(); // const Vector & b = bb.CastToVector(); // Vector & res = bres.CastToVector(); res.SetSize (Height()); if (Width() != x.Size() || Height() != b.Size()) { (*myerr) << "\nMatrix and Vector don't fit" << endl; } else if (Height() != res.Size()) { (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; } else { int h = Height(); int w = Width(); const double * mp = &Get(1, 1); for (int i = 1; i <= h; i++) { sum = b(i-1); const double * xp = &x(0); for (int j = 1; j <= w; ++j, ++mp, ++xp) sum -= *mp * *xp; res(i-1) = sum; } } } #ifdef ABC double DenseMatrix :: EvaluateBilinearform (const Vector & hx) const { double sum = 0, hsum; // const Vector & hx = x.CastToVector(); int i, j; if (Width() != hx.Size() || Height() != hx.Size()) { (*myerr) << "Matrix::EvaluateBilinearForm: sizes don't fit" << endl; } else { for (i = 1; i <= Height(); i++) { hsum = 0; for (j = 1; j <= Height(); j++) { hsum += Get(i, j) * hx.Get(j); } sum += hsum * hx.Get(i); } } // testout << "sum = " << sum << endl; return sum; } void DenseMatrix :: MultElementMatrix (const Array & pnum, const Vector & hx, Vector & hy) { int i, j; // const Vector & hx = x.CastToVector(); // Vector & hy = y.CastToVector(); if (Symmetric()) { for (i = 1; i <= Height(); i++) { for (j = 1; j < i; j++) { hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j)); hy.Elem(pnum.Get(j)) += Get(i, j) * hx.Get(pnum.Get(i)); } hy.Elem(pnum.Get(j)) += Get(i, i) * hx.Get(pnum.Get(i)); } } else for (i = 1; i <= Height(); i++) for (j = 1; j <= Width(); j++) hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j)); } void DenseMatrix :: MultTransElementMatrix (const Array & pnum, const Vector & hx, Vector & hy) { int i, j; // const Vector & hx = x.CastToVector(); // Vector & hy = y.CastToVector(); if (Symmetric()) MultElementMatrix (pnum, hx, hy); else for (i = 1; i <= Height(); i++) for (j = 1; j <= Width(); j++) hy.Elem(pnum.Get(i)) += Get(j, i) * hx.Get(pnum.Get(j)); } #endif void DenseMatrix :: Solve (const Vector & v, Vector & sol) const { DenseMatrix temp (*this); temp.SolveDestroy (v, sol); } void DenseMatrix :: SolveDestroy (const Vector & v, Vector & sol) { double q; if (Width() != Height()) { (*myerr) << "SolveDestroy: Matrix not square"; return; } if (Width() != v.Size()) { (*myerr) << "SolveDestroy: Matrix and Vector don't fit"; return; } sol = v; if (Height() != sol.Size()) { (*myerr) << "SolveDestroy: Solution Vector not ok"; return; } if (0 /* Symmetric() */) { // Cholesky factorization int i, j, k, n; n = Height(); // Cholesky double x; Vector p(n); for (i = 1; i <= n; i++) for (j = 1; j < i; j++) Elem(j, i) = Get(i, j); for (i = 1; i <= n; i++) { // (*mycout) << "." << flush; for (j = i; j <= n; j++) { x = Get(i, j); const double * pik = &Get(i, 1); const double * pjk = &Get(j, 1); for (k = i-2; k >= 0; --k, ++pik, ++pjk) x -= (*pik) * (*pjk); // for (k = i-1; k >= 1; --k) // x -= Get(j, k) * Get(i, k); if (i == j) { if (x <= 0) { cerr << "Matrix indefinite" << endl; return; } p(i-1) = 1 / sqrt(x); } else { Elem(j, i) = x * p(i-1); } } } for (int i = 1; i <= n; i++) Elem(i, i) = 1 / p(i-1); // A = L L^t // L stored in left-lower triangle sol = v; // Solve L sol = sol for (int i = 1; i <= n; i++) { double val = sol(i-1); const double * pij = &Get(i, 1); const double * solj = &sol(0); for (int j = 1; j < i; j++, ++pij, ++solj) val -= *pij * *solj; // for (j = 1; j < i; j++) // val -= Get(i, j) * sol.Get(j); sol(i-1) = val / Get(i, i); } // Solve L^t sol = sol for (int i = n; i >= 1; i--) { double val = sol(i-1) / Get(i, i); sol(i-1) = val; double * solj = &sol(0); const double * pij = &Get(i, 1); for (j = 1; j < i; ++j, ++pij, ++solj) *solj -= val * *pij; // for (j = 1; j < i; j++) // sol.Elem(j) -= Get(i, j) * val; } } else { // (*mycout) << "gauss" << endl; int n = Height(); for (int i = 1; i <= n; i++) { for (int j = i+1; j <= n; j++) { q = Get(j,i) / Get(i,i); if (q) { const double * pik = &Get(i, i+1); double * pjk = &Elem(j, i+1); for (int k = i+1; k <= n; ++k, ++pik, ++pjk) *pjk -= q * *pik; // for (k = i+1; k <= Height(); k++) // Elem(j, k) -= q * Get(i,k); sol(j-1) -= q * sol(i-1); } } } for (int i = n; i >= 1; i--) { q = sol(i-1); for (int j = i+1; j <= n; j++) q -= Get(i,j) * sol(j-1); sol(i-1) = q / Get(i,i); } } } /* BaseMatrix * DenseMatrix :: Copy () const { return new DenseMatrix (*this); } */ ostream & operator<< (ostream & ost, const DenseMatrix & m) { for (int i = 0; i < m.Height(); i++) { for (int j = 0; j < m.Width(); j++) ost << m.Get(i+1,j+1) << " "; ost << endl; } return ost; } } netgen-6.2.1905/libsrc/linalg/CMakeLists.txt0000644000175000017500000000053713504650527017272 0ustar kurtkurtadd_library( la INTERFACE ) set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) target_sources( la INTERFACE ${sdir}/densemat.cpp ${sdir}/polynomial.cpp ${sdir}/bfgs.cpp ${sdir}/linopt.cpp ${sdir}/linsearch.cpp ) install(FILES densemat.hpp linalg.hpp opti.hpp polynomial.hpp vector.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/linalg COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/general/0000755000175000017500000000000013504650527014674 5ustar kurtkurtnetgen-6.2.1905/libsrc/general/sort.hpp0000644000175000017500000000200413504650527016370 0ustar kurtkurt#ifndef FILE_SORT #define FILE_SORT /**************************************************************************/ /* File: sort.hh */ /* Author: Joachim Schoeberl */ /* Date: 07. Jan. 00 */ /**************************************************************************/ namespace netgen { // order(i) is sorted index of element i extern void Sort (const Array & values, Array & order); extern void QuickSort (const Array & values, Array & order); template inline void BubbleSort (int size, T * data) { T hv; for (int i = 0; i < size; i++) for (int j = i+1; j < size; j++) if (data[i] > data[j]) { hv = data[i]; data[i] = data[j]; data[j] = hv; } } template inline void BubbleSort (Array & data) { if(data.Size() > 0) BubbleSort (data.Size(), &data[data.Begin()]); } } #endif netgen-6.2.1905/libsrc/general/mpi_interface.hpp0000644000175000017500000002617613504650527020226 0ustar kurtkurt#ifndef FILE_PARALLEL #define FILE_PARALLEL #ifdef VTRACE #include "vt_user.h" #else #define VT_USER_START(n) #define VT_USER_END(n) #define VT_TRACER(n) #endif namespace netgen { // using ngcore::id; // using ngcore::ntasks; #ifndef PARALLEL /** without MPI, we need a dummy typedef **/ // typedef int MPI_Comm; #endif /** This is the "standard" communicator that will be used for netgen-objects. **/ // extern DLL_HEADER NgMPI_Comm ng_comm; #ifdef OLD #ifdef PARALLEL inline int MyMPI_GetNTasks (MPI_Comm comm /* = ng_comm */) { int ntasks; MPI_Comm_size(comm, &ntasks); return ntasks; } inline int MyMPI_GetId (MPI_Comm comm /* = ng_comm */) { int id; MPI_Comm_rank(comm, &id); return id; } #else // enum { MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 0}; inline int MyMPI_GetNTasks (MPI_Comm comm /* = ng_comm */) { return 1; } inline int MyMPI_GetId (MPI_Comm comm /* = ng_comm */) { return 0; } #endif #endif /* #ifdef PARALLEL // For python wrapping of communicators struct PyMPI_Comm { MPI_Comm comm; bool owns_comm; PyMPI_Comm (MPI_Comm _comm, bool _owns_comm = false) : comm(_comm), owns_comm(_owns_comm) { } PyMPI_Comm (const PyMPI_Comm & c) = delete; ~PyMPI_Comm () { if (owns_comm) MPI_Comm_free(&comm); } inline int Rank() const { return MyMPI_GetId(comm); } inline int Size() const { return MyMPI_GetNTasks(comm); } }; #else // dummy without MPI struct PyMPI_Comm { MPI_Comm comm = 0; PyMPI_Comm (MPI_Comm _comm, bool _owns_comm = false) { } ~PyMPI_Comm () { } inline int Rank() const { return 0; } inline int Size() const { return 1; } }; #endif */ #ifdef PARALLEL template inline MPI_Datatype MyGetMPIType ( ) { cerr << "ERROR in GetMPIType() -- no type found" << endl;return 0; } template <> inline MPI_Datatype MyGetMPIType ( ) { return MPI_INT; } template <> inline MPI_Datatype MyGetMPIType ( ) { return MPI_DOUBLE; } template <> inline MPI_Datatype MyGetMPIType ( ) { return MPI_CHAR; } template<> inline MPI_Datatype MyGetMPIType ( ) { return MPI_UINT64_T; } #else typedef int MPI_Datatype; template inline MPI_Datatype MyGetMPIType ( ) { return 0; } #endif #ifdef PARALLEL inline MPI_Comm MyMPI_SubCommunicator(MPI_Comm comm, Array & procs) { MPI_Comm subcomm; MPI_Group gcomm, gsubcomm; MPI_Comm_group(comm, &gcomm); MPI_Group_incl(gcomm, procs.Size(), &(procs[0]), &gsubcomm); MPI_Comm_create_group(comm, gsubcomm, 6969, &subcomm); return subcomm; } #else inline MPI_Comm MyMPI_SubCommunicator(MPI_Comm comm, Array & procs) { return comm; } #endif #ifdef PARALLEL enum { MPI_TAG_CMD = 110 }; enum { MPI_TAG_MESH = 210 }; enum { MPI_TAG_VIS = 310 }; inline void MyMPI_Send (int i, int dest, int tag, MPI_Comm comm /* = ng_comm */) { int hi = i; MPI_Send( &hi, 1, MPI_INT, dest, tag, comm); } inline void MyMPI_Recv (int & i, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; MPI_Recv( &i, 1, MPI_INT, src, tag, comm, &status); } inline void MyMPI_Send (const string & s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Send( const_cast (s.c_str()), s.length(), MPI_CHAR, dest, tag, comm); } inline void MyMPI_Recv (string & s, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; int len; MPI_Probe (src, tag, MPI_COMM_WORLD, &status); MPI_Get_count (&status, MPI_CHAR, &len); s.assign (len, ' '); MPI_Recv( &s[0], len, MPI_CHAR, src, tag, comm, &status); } template inline void MyMPI_Send (FlatArray s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Send( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm); } template inline void MyMPI_Recv ( FlatArray s, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; MPI_Recv( &s.First(), s.Size(), MyGetMPIType(), src, tag, comm, &status); } template inline void MyMPI_Recv ( Array & s, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; int len; MPI_Probe (src, tag, comm, &status); MPI_Get_count (&status, MyGetMPIType(), &len); s.SetSize (len); MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, comm, &status); } template inline int MyMPI_Recv ( Array & s, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; int len; MPI_Probe (MPI_ANY_SOURCE, tag, comm, &status); int src = status.MPI_SOURCE; MPI_Get_count (&status, MyGetMPIType(), &len); s.SetSize (len); MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, comm, &status); return src; } /* template inline void MyMPI_ISend (FlatArray s, int dest, int tag, MPI_Request & request) { MPI_Isend( &s.First(), s.Size(), MyGetMPIType(), dest, tag, MPI_COMM_WORLD, & request); } template inline void MyMPI_IRecv (FlatArray s, int dest, int tag, MPI_Request & request) { MPI_Irecv( &s.First(), s.Size(), MyGetMPIType(), dest, tag, MPI_COMM_WORLD, & request); } */ template inline MPI_Request MyMPI_ISend (FlatArray s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Request request; MPI_Isend( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm, &request); return request; } template inline MPI_Request MyMPI_IRecv (FlatArray s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Request request; MPI_Irecv( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm, &request); return request; } /* template inline void MyMPI_ISend (FlatArray s, int dest, int tag) { MPI_Request request; MPI_Isend( &s.First(), s.Size(), MyGetMPIType(), dest, tag, MPI_COMM_WORLD, &request); MPI_Request_free (&request); } template inline void MyMPI_IRecv (FlatArray s, int dest, int tag) { MPI_Request request; MPI_Irecv( &s.First(), s.Size(), MyGetMPIType(), dest, tag, MPI_COMM_WORLD, &request); MPI_Request_free (&request); } */ /* send a table entry to each of the processes in the group ... receive-table entries will be set */ /* template inline void MyMPI_ExchangeTable (TABLE & send_data, TABLE & recv_data, int tag, MPI_Comm comm = MPI_COMM_WORLD) { int ntasks, rank; MPI_Comm_size(comm, &ntasks); MPI_Comm_rank(comm, &rank); Array requests; for (int dest = 0; dest < ntasks; dest++) if (dest != rank) requests.Append (MyMPI_ISend (send_data[dest], dest, tag, comm)); for (int i = 0; i < ntasks-1; i++) { MPI_Status status; MPI_Probe (MPI_ANY_SOURCE, tag, comm, &status); int size, src = status.MPI_SOURCE; MPI_Get_count (&status, MPI_INT, &size); recv_data.SetEntrySize (src, size, sizeof(T)); requests.Append (MyMPI_IRecv (recv_data[src], src, tag, comm)); } MPI_Barrier (comm); MPI_Waitall (requests.Size(), &requests[0], MPI_STATUS_IGNORE); } */ template inline void MyMPI_ExchangeTable (TABLE & send_data, TABLE & recv_data, int tag, const NgMPI_Comm & comm /* = ng_comm */) { /* int rank = MyMPI_GetId(comm); int ntasks = MyMPI_GetNTasks(comm); */ int rank = comm.Rank(); int ntasks = comm.Size(); Array send_sizes(ntasks); Array recv_sizes(ntasks); for (int i = 0; i < ntasks; i++) send_sizes[i] = send_data[i].Size(); MPI_Alltoall (&send_sizes[0], 1, MPI_INT, &recv_sizes[0], 1, MPI_INT, comm); // in-place is buggy ! // MPI_Alltoall (MPI_IN_PLACE, 1, MPI_INT, // &recv_sizes[0], 1, MPI_INT, comm); for (int i = 0; i < ntasks; i++) recv_data.SetEntrySize (i, recv_sizes[i], sizeof(T)); Array requests; for (int dest = 0; dest < ntasks; dest++) if (dest != rank && send_data[dest].Size()) requests.Append (MyMPI_ISend (send_data[dest], dest, tag, comm)); for (int dest = 0; dest < ntasks; dest++) if (dest != rank && recv_data[dest].Size()) requests.Append (MyMPI_IRecv (recv_data[dest], dest, tag, comm)); // MPI_Barrier (comm); MPI_Waitall (requests.Size(), &requests[0], MPI_STATUS_IGNORE); } extern void MyMPI_SendCmd (const char * cmd); extern string MyMPI_RecvCmd (); template inline void MyMPI_Bcast (T & s, MPI_Comm comm /* = ng_comm */) { MPI_Bcast (&s, 1, MyGetMPIType(), 0, comm); } template inline void MyMPI_Bcast (Array & s, NgMPI_Comm comm /* = ng_comm */) { int size = s.Size(); MyMPI_Bcast (size, comm); // if (MyMPI_GetId(comm) != 0) s.SetSize (size); if (comm.Rank() != 0) s.SetSize (size); MPI_Bcast (&s[0], size, MyGetMPIType(), 0, comm); } template inline void MyMPI_Bcast (Array & s, int root, MPI_Comm comm /* = ng_comm */) { int id; MPI_Comm_rank(comm, &id); int size = s.Size(); MPI_Bcast (&size, 1, MPI_INT, root, comm); if (id != root) s.SetSize (size); if ( !size ) return; MPI_Bcast (&s[0], size, MyGetMPIType(), root, comm); } template inline void MyMPI_Allgather (const T & send, FlatArray recv, MPI_Comm comm /* = ng_comm */) { MPI_Allgather( const_cast (&send), 1, MyGetMPIType(), &recv[0], 1, MyGetMPIType(), comm); } template inline void MyMPI_Alltoall (FlatArray send, FlatArray recv, MPI_Comm comm /* = ng_comm */) { MPI_Alltoall( &send[0], 1, MyGetMPIType(), &recv[0], 1, MyGetMPIType(), comm); } // template // inline void MyMPI_Alltoall_Block (FlatArray send, FlatArray recv, int blocklen, MPI_Comm comm = ng_comm) // { // MPI_Alltoall( &send[0], blocklen, MyGetMPIType(), &recv[0], blocklen, MyGetMPIType(), comm); // } /* inline void MyMPI_Send ( int *& s, int len, int dest, int tag) { int hlen = len; MPI_Send( &hlen, 1, MPI_INT, dest, tag, MPI_COMM_WORLD); MPI_Send( s, len, MPI_INT, dest, tag, MPI_COMM_WORLD); } inline void MyMPI_Recv ( int *& s, int & len, int src, int tag) { MPI_Status status; MPI_Recv( &len, 1, MPI_INT, src, tag, MPI_COMM_WORLD, &status); if ( s ) delete [] s; s = new int [len]; MPI_Recv( s, len, MPI_INT, src, tag, MPI_COMM_WORLD, &status); } inline void MyMPI_Send ( double * s, int len, int dest, int tag) { MPI_Send( &len, 1, MPI_INT, dest, tag, MPI_COMM_WORLD); MPI_Send( s, len, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD); } inline void MyMPI_Recv ( double *& s, int & len, int src, int tag) { MPI_Status status; MPI_Recv( &len, 1, MPI_INT, src, tag, MPI_COMM_WORLD, &status); if ( s ) delete [] s; s = new double [len]; MPI_Recv( s, len, MPI_DOUBLE, src, tag, MPI_COMM_WORLD, &status); } */ #endif // PARALLEL } #endif netgen-6.2.1905/libsrc/general/spbita2d.hpp0000644000175000017500000000233313504650527017116 0ustar kurtkurt#ifndef FILE_SPBITA2D #define FILE_SPBITA2D /**************************************************************************/ /* File: spbita2d.hh */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /** Implementation of sparse 2 dimensional bitarray */ namespace netgen { class SPARSE_BIT_Array_2D { class linestruct { public: INDEX size; INDEX maxsize; INDEX * col; }; /// linestruct * lines; /// INDEX height, width; public: /// SPARSE_BIT_Array_2D (INDEX ah = 0, INDEX aw = 0); /// ~SPARSE_BIT_Array_2D (); /// void SetSize (INDEX ah, INDEX aw = 0); /// void DeleteElements (); /// int Get (INDEX i, INDEX j) const; /// INDEX Height () const { return height; } /// INDEX Width () const { return width; } /// void Set (INDEX i, INDEX j); /// int Test (INDEX i, INDEX j) const; /// INDEX BitsInLine (INDEX i) const { return lines[i-1].size; } /// INDEX GetIndex (INDEX i, INDEX nr) const { return lines[i-1].col[nr-1]; } }; } #endif netgen-6.2.1905/libsrc/general/spbita2d.cpp0000644000175000017500000000557113504650527017120 0ustar kurtkurt/**************************************************************************/ /* File: spbita2d.cpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /* Implementation of sparse 2 dimensional bitarray */ #include #include namespace netgen { //using namespace netgen; SPARSE_BIT_Array_2D :: SPARSE_BIT_Array_2D (int ah, int aw) { lines = NULL; SetSize (ah, aw); } SPARSE_BIT_Array_2D :: ~SPARSE_BIT_Array_2D () { DeleteElements (); delete lines; } void SPARSE_BIT_Array_2D :: SetSize (int ah, int aw) { DeleteElements(); if (lines) { delete lines; lines = NULL; } if (!aw) aw = ah; height = ah; width = aw; if (!ah) return; lines = new linestruct[ah]; if (lines) { for (int i = 0; i < ah; i++) { lines[i].size = 0; lines[i].maxsize = 0; lines[i].col = NULL; } } else { height = width = 0; MyError ("SPARSE_Array::SetSize: Out of memory"); } } void SPARSE_BIT_Array_2D :: DeleteElements () { if (lines) { for (int i = 0; i < height; i++) { if (lines[i].col) { delete [] lines[i].col; lines[i].col = NULL; lines[i].size = 0; lines[i].maxsize = 0; } } } } int SPARSE_BIT_Array_2D :: Test (int i, int j) const { int k, max, *col; if (!lines) return 0; if (i < 1 || i > height) return 0; col = lines[i-1].col; max = lines[i-1].size; for (k = 0; k < max; k++, col++) if (*col == j) return 1; return 0; } void SPARSE_BIT_Array_2D :: Set(int i, int j) { int k, max, *col; i--; col = lines[i].col; max = lines[i].size; for (k = 0; k < max; k++, col++) if (*col == j) return; if (lines[i].size) { if (lines[i].size == lines[i].maxsize) { col = new int[lines[i].maxsize+2]; if (col) { lines[i].maxsize += 2; memcpy (col, lines[i].col, sizeof (int) * lines[i].size); delete [] lines[i].col; lines[i].col = col; } else { MyError ("SPARSE_BIT_Array::Set: Out of mem 1"); return; } } else col = lines[i].col; if (col) { k = lines[i].size-1; while (k >= 0 && col[k] > j) { col[k+1] = col[k]; k--; } k++; lines[i].size++; col[k] = j; return; } else { MyError ("SPARSE_Array::Set: Out of memory 2"); } } else { lines[i].col = new int[4]; if (lines[i].col) { lines[i].maxsize = 4; lines[i].size = 1; lines[i].col[0] = j; return; } else { MyError ("SparseMatrix::Elem: Out of memory 3"); } } } } netgen-6.2.1905/libsrc/general/mystring.cpp0000644000175000017500000002047213504650527017261 0ustar kurtkurt //************************************************************** // // filename: mystring.cpp // // project: doctoral thesis // // author: Dipl.-Ing. Gerstmayr Johannes // // generated: 20.12.98 // last change: 20.12.98 // description: implementation for strings // remarks: // //************************************************************** // string class #include #include #include #include namespace netgen { void ReadEnclString(istream & in, string & str, const char encl) { char currchar; str = ""; in.get(currchar); while(in && (currchar == ' ' || currchar == '\t' || currchar == '\n') ) in.get(currchar); if(currchar == encl) { in.get(currchar); while(in && currchar != encl) { str += currchar; in.get(currchar); } } else { in.putback(currchar); in >> str; } } void DefaultStringErrHandler() { cerr << "Error : string operation out of range\n" << flush; } void (*MyStr::ErrHandler)() = DefaultStringErrHandler; /* MyStr::MyStr() { length = 0; str = shortstr; str[0] = 0; } */ MyStr::MyStr(const char *s) { length = unsigned(strlen(s)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, s); } /* MyStr::MyStr(char s) { length = 1; str = shortstr; str[0] = s; str[1] = (char)0; } */ MyStr::MyStr(const MyStr& s) { length = s.length; if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, s.str); } MyStr::MyStr(int i) { char buffer[32]; sprintf(buffer, "%d", i); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } /* MyStr::MyStr(unsigned int i) { char buffer[32]; sprintf(buffer, "%d", i); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } */ MyStr::MyStr(void * p) { char buffer[32]; sprintf(buffer, "%p", p); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } /* MyStr::MyStr(long l) { char buffer[32]; sprintf(buffer, "%ld", l); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } */ MyStr::MyStr(size_t l) { char buffer[32]; sprintf(buffer, "%ld", l); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } MyStr::MyStr(double d) { char buffer[32]; //if (fabs(d) < 1E-100) {d = 0;} sprintf(buffer, "%g", d); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } MyStr::MyStr(const Point3d& p) { char buffer[80]; //if (fabs(d) < 1E-100) {d = 0;} sprintf(buffer, "[%g, %g, %g]", p.X(), p.Y(), p.Z()); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } MyStr::MyStr(const Vec3d& p) { char buffer[80]; //if (fabs(d) < 1E-100) {d = 0;} sprintf(buffer, "[%g, %g, %g]", p.X(), p.Y(), p.Z()); length = unsigned(strlen(buffer)); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, buffer); } MyStr::MyStr(unsigned n, int) { length = n; if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; str[n] = 0; } MyStr::MyStr(const string & st) { length = unsigned(st.length()); if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy (str, st.c_str()); } MyStr MyStr::Left(unsigned r) { if(r > length) { MyStr::ErrHandler(); MyStr s; return s; } else { MyStr tmp(r, 0); strncpy(tmp.str, str, r); return tmp; } } MyStr MyStr::Right(unsigned l) { if(l > length) { MyStr::ErrHandler(); MyStr s; return s; } else { MyStr tmp(l, 0); strncpy(tmp.str, str + length - l, l); return tmp; } } MyStr& MyStr::InsertAt(unsigned pos, const MyStr& s) { if(pos > length) { MyStr::ErrHandler(); return *this; } int newLength = length + s.length; char *tmp = new char[newLength + 1]; strncpy(tmp, str, pos); strcpy(tmp + pos, s.str); strcpy(tmp + pos + s.length, str + pos); if (length > SHORTLEN) delete [] str; length = newLength; if (length > SHORTLEN) str = tmp; else { strcpy (shortstr, tmp); delete [] tmp; str = shortstr; } return *this; } MyStr &MyStr::WriteAt(unsigned pos, const MyStr& s) { if(pos > length) { MyStr::ErrHandler(); return *this; } unsigned n = length - pos; if(s.length < n) n = s.length; strncpy(str + pos, s.str, n); return *this; } void MyStr::ConvertTextToExcel() { /* for (int i = 0; i < Length(); i++) { if ((*this)[i]==',') {(*this)[i] = ';';} else if ((*this)[i]=='.') {(*this)[i] = ',';} } */ } void MyStr::ConvertExcelToText() { /* for (int i = 0; i < Length(); i++) { if ((*this)[i]==',') {(*this)[i] = '.';} else if ((*this)[i]==';') {(*this)[i] = ',';} } */ } MyStr& MyStr::operator = (const MyStr& s) { if (length > SHORTLEN) delete [] str; length = s.length; if (length > SHORTLEN) str = new char[length + 1]; else str = shortstr; strcpy(str, s.str); return *this; } MyStr operator + (const MyStr& s1, const MyStr& s2) { MyStr tmp(s1.length + s2.length, 0); if (s1.length != 0) strcpy(tmp.str, s1.str); if (s2.length != 0) strcpy(tmp.str + s1.length, s2.str); return tmp; } void MyStr::operator += (const MyStr& s) { if (length+s.length <= SHORTLEN) { if (s.length != 0) strcpy(shortstr + length, s.str); } else { char *tmp = new char[length + s.length + 1]; if (length != 0) strcpy(tmp, str); if (s.length != 0) strcpy(tmp + length, s.str); if (length > SHORTLEN) delete [] str; length += s.length; str = tmp; } } char& MyStr::operator [] (unsigned n) { static char dummy; if(n < length) return str[n]; else { MyStr::ErrHandler(); return dummy; } } char MyStr::operator [] (unsigned n) const { static char dummy; if(n < length) return str[n]; else { MyStr::ErrHandler(); return dummy; } } MyStr MyStr::operator () (unsigned l, unsigned r) { if((l > r) || (r > length)) { MyStr::ErrHandler(); MyStr s; return s; } else { int n = r - l + 1; MyStr tmp(n, 0); strncpy(tmp.str, str + 1, n); return tmp; } } string MyStr::cpp_string(void) const { string aux(str,length); return aux; } /* istream& operator >> (istream& is, MyStr& s) { const int buflen = 1000; char buffer[buflen+1]; int end = 0; s = ""; MyStr str; while (!end) { is.get(buffer, buflen); str = MyStr(buffer); s += str; if (is.peek() == EOF) {end = 1;} } return is; } */ /* #ifdef __borland ::ifstream& operator >> (::ifstream& is, MyStr& s) // wb { // wb const int buflen = 1000; // wb char buffer[buflen+1]; // wb // wb int end = 0; // wb s = ""; // wb MyStr str; // wb // wb while (!end) // wb { // wb is.get(buffer, buflen); // wb str = MyStr(buffer); // wb s += str; // wb if (is.peek() == EOF) {end = 1;} // wb } // wb // wb return is; // wb } #endif */ } netgen-6.2.1905/libsrc/general/bitarray.cpp0000644000175000017500000000440713504650527017222 0ustar kurtkurt/**************************************************************************/ /* File: bitarray.cc */ /* Autho: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /* data type BitArray */ #include #include namespace netgen { //using namespace netgen; BitArray :: BitArray () { size = 0; data = NULL; } BitArray :: BitArray (int asize) { size = 0; data = NULL; SetSize (asize); } BitArray :: ~BitArray () { delete [] data; } void BitArray :: SetSize (int asize) { if (size == asize) return; delete [] data; size = asize; data = new unsigned char [Addr (size)+1]; } void BitArray :: Set () { if (!size) return; for (int i = 0; i <= Addr (size); i++) data[i] = UCHAR_MAX; } void BitArray :: Clear () { if (!size) return; for (int i = 0; i <= Addr (size); i++) data[i] = 0; } void BitArray :: Invert () { if (!size) return; for (int i = 0; i <= Addr (size); i++) data[i] ^= 255; } void BitArray :: And (const BitArray & ba2) { if (!size) return; for (int i = 0; i <= Addr (size); i++) data[i] &= ba2.data[i]; } void BitArray :: Or (const BitArray & ba2) { if (!size) return; for (int i = 0; i <= Addr (size); i++) data[i] |= ba2.data[i]; } template void BitArrayChar :: Set () { data = 1; } template void BitArrayChar :: Clear () { data = 0; } template void BitArrayChar :: Invert () { for (int i = BASE; i < data.Size()+BASE; i++) data[i] = 1 - data[i]; } template void BitArrayChar :: And (const BitArrayChar & ba2) { for (int i = BASE; i < data.Size()+BASE; i++) data[i] &= ba2.data[i]; } template void BitArrayChar :: Or (const BitArrayChar & ba2) { for (int i = BASE; i < data.Size()+BASE; i++) data[i] |= ba2.data[i]; } template class BitArrayChar<0>; template class BitArrayChar<1>; } netgen-6.2.1905/libsrc/general/mystring.hpp0000644000175000017500000001130213504650527017256 0ustar kurtkurt //************************************************************** // // filename: mystring.h // // project: doctoral thesis, program smart // // author: Dipl.-Ing. Gerstmayr Johannes // // generated: 20.12.98 // last change: 20.12.98 // description: base class for strings // remarks: string with n characters has // 0..n-1 characters and at pos n a 0 // //************************************************************** #ifndef MYSTRING__H #define MYSTRING__H namespace netgen { class Point3d; class Vec3d; // extract string str which is enclosed by the given character encl from a given string in void ReadEnclString(istream & in, string & str, const char encl); class MyStr; DLL_HEADER MyStr operator + (const MyStr &, const MyStr &); DLL_HEADER int operator == (const MyStr &, const MyStr &); DLL_HEADER int operator < (const MyStr &, const MyStr &); DLL_HEADER int operator <= (const MyStr &, const MyStr &); DLL_HEADER int operator > (const MyStr &, const MyStr &); DLL_HEADER int operator >= (const MyStr &, const MyStr &); DLL_HEADER int operator != (const MyStr &, const MyStr &); DLL_HEADER ostream& operator << (ostream &, const MyStr &); DLL_HEADER istream& operator >> (istream &, MyStr &); class DLL_HEADER MyStr { public: MyStr(); MyStr(const char *); MyStr(char); MyStr(const MyStr &); MyStr(int); MyStr(size_t); MyStr(void *); // MyStr(long); // MyStr(unsigned long); MyStr(double); MyStr(const Point3d& p); MyStr(const Vec3d& p); MyStr(const string & st); ~MyStr(); MyStr Left(unsigned); MyStr Right(unsigned); MyStr& InsertAt(unsigned, const MyStr &); MyStr& WriteAt(unsigned, const MyStr &); unsigned Length() const; int Find(const char); int Find(const char *); int Find(const MyStr &); MyStr& operator = (const MyStr &); DLL_HEADER friend MyStr operator + (const MyStr &, const MyStr &); void operator += (const MyStr &); char* c_str(); string cpp_string(void) const; //change every ',' -> ';', '.' -> ',' void ConvertTextToExcel(); //change every ','->'.', ';'->',' void ConvertExcelToText(); MyStr operator () (unsigned, unsigned); operator int(); operator double(); operator long(); operator char *(); char& operator [] (unsigned int); char operator [] (unsigned int) const; DLL_HEADER friend int operator == (const MyStr &, const MyStr &); DLL_HEADER friend int operator < (const MyStr &, const MyStr &); DLL_HEADER friend int operator <= (const MyStr &, const MyStr &); DLL_HEADER friend int operator > (const MyStr &, const MyStr &); DLL_HEADER friend int operator >= (const MyStr &, const MyStr &); DLL_HEADER friend int operator != (const MyStr &, const MyStr &); DLL_HEADER friend ostream& operator << (ostream &, const MyStr &); DLL_HEADER friend istream& operator >> (istream &, MyStr &); static void SetToErrHandler(void (*)()); private: MyStr(unsigned, int); char *str; unsigned length; enum { SHORTLEN = 24 }; char shortstr[SHORTLEN+1]; static void(*ErrHandler)(); }; inline MyStr::MyStr() { length = 0; str = shortstr; str[0] = 0; } inline MyStr::MyStr(char s) { length = 1; str = shortstr; str[0] = s; str[1] = (char)0; } inline MyStr::~MyStr() { if (length > SHORTLEN) delete [] str; } inline unsigned MyStr::Length() const { return length; } inline int MyStr::Find(const char c) { char *pos = strchr(str, int(c)); return pos ? int(pos - str) : -1; } inline int MyStr::Find(const MyStr &s) { char *pos = strstr(str, s.str); return pos ? int(pos - str) : -1; } inline int MyStr::Find(const char *s) { char *pos = strstr(str, s); return pos ? int(pos - str) : -1; } inline MyStr::operator int() { return atoi(str); } inline MyStr::operator double() { return atof(str); } inline MyStr::operator long() { return atol(str); } inline MyStr::operator char *() { return str; } inline char* MyStr::c_str() { return str; } inline int operator == (const MyStr &s1, const MyStr& s2) { return strcmp(s1.str, s2.str) == 0; } inline int operator < (const MyStr &s1, const MyStr& s2) { return strcmp(s1.str, s2.str) < 0; } inline int operator <= (const MyStr &s1, const MyStr& s2) { return strcmp(s1.str, s2.str) <= 0; } inline int operator > (const MyStr &s1, const MyStr& s2) { return strcmp(s1.str, s2.str) > 0; } inline int operator >= (const MyStr &s1, const MyStr& s2) { return strcmp(s1.str, s2.str) >= 0; } inline int operator != (const MyStr &s1, const MyStr& s2) { return !(s1 == s2); } inline ostream& operator << (ostream& os, const MyStr& s) { return os << s.str; } inline void MyStr::SetToErrHandler(void (*Handler)()) { ErrHandler = Handler; }; } #endif netgen-6.2.1905/libsrc/general/hashtabl.hpp0000644000175000017500000007347513504650527017213 0ustar kurtkurt#ifndef FILE_HASHTABL #define FILE_HASHTABL /**************************************************************************/ /* File: hashtabl.hh */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ namespace netgen { /** Abstract data type HASHTABLE. Hash is done by one INDEX */ class BASE_INDEX_HASHTABLE { protected: /// keys are stored in this table TABLE hash; public: /// BASE_INDEX_HASHTABLE (int size) : hash (size) { }; protected: /// int HashValue (const INDEX & ind) const { return ind % hash.Size() + 1; } /// int Position (int bnr, const INDEX & ind) const; }; /// template class INDEX_HASHTABLE : private BASE_INDEX_HASHTABLE { /// TABLE cont; public: /// inline INDEX_HASHTABLE (int size); /// inline void Set (const INDEX & hash, const T & acont); /// inline const T & Get (const INDEX & ahash) const; /// inline bool Used (const INDEX & ahash) const; /// inline int GetNBags () const; /// inline int GetBagSize (int bnr) const; /// inline void GetData (int bnr, int colnr, INDEX & ahash, T & acont) const; /// inline void PrintMemInfo (ostream & ost) const; }; /// class BASE_INDEX_2_HASHTABLE { protected: /// TABLE hash; public: /// BASE_INDEX_2_HASHTABLE () { ; } BASE_INDEX_2_HASHTABLE (int size) : hash (size) { }; /// void PrintStat (ostream & ost) const; void BaseSetSize(int s) {hash.SetSize(s);} //protected: /// int HashValue (const INDEX_2 & ind) const { return (ind.I1() + ind.I2()) % hash.Size() + 1; } /// int Position (int bnr, const INDEX_2 & ind) const { for (int i = 1; i <= hash.EntrySize (bnr); i++) if (hash.Get(bnr, i) == ind) return i; return 0; } }; /// template class INDEX_2_HASHTABLE : public BASE_INDEX_2_HASHTABLE { /// TABLE cont; public: /// INDEX_2_HASHTABLE () { ; } INDEX_2_HASHTABLE (int size) : BASE_INDEX_2_HASHTABLE (size), cont(size) { ; } /// void SetSize(int s) { cont.SetSize(s); BaseSetSize(s); } /// void Set (const INDEX_2 & ahash, const T & acont) { int bnr = HashValue (ahash); int pos = Position (bnr, ahash); if (pos) cont.Set (bnr, pos, acont); else { hash.Add1 (bnr, ahash); cont.Add1 (bnr, acont); } } /// const T & Get (const INDEX_2 & ahash) const { int bnr = HashValue (ahash); int pos = Position (bnr, ahash); return cont.Get (bnr, pos); } /// bool Used (const INDEX_2 & ahash) const { return Position (HashValue (ahash), ahash) > 0; } /// int GetNBags () const { return cont.Size(); } /// int GetBagSize (int bnr) const { return cont.EntrySize (bnr); } /// void GetData (int bnr, int colnr, INDEX_2 & ahash, T & acont) const { ahash = hash.Get(bnr, colnr); acont = cont.Get(bnr, colnr); } /// void SetData (int bnr, int colnr, const INDEX_2 & ahash, const T & acont) { hash.Set(bnr, colnr, ahash); cont.Set(bnr, colnr, acont); } /// void PrintMemInfo (ostream & ost) const { ost << "Hash: " << endl; hash.PrintMemInfo (ost); ost << "Cont: " << endl; cont.PrintMemInfo (ost); } void DeleteData () { int n = hash.Size(); hash.SetSize (n); cont.SetSize (n); } class Iterator { const INDEX_2_HASHTABLE & ht; int bagnr, pos; public: Iterator (const INDEX_2_HASHTABLE & aht, int abagnr, int apos) : ht(aht), bagnr(abagnr), pos(apos) { ; } int BagNr() const { return bagnr; } int Pos() const { return pos; } void operator++ (int) { // cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; pos++; while (bagnr < ht.GetNBags() && pos == ht.GetBagSize(bagnr+1)) { pos = 0; bagnr++; } // cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; } bool operator != (int i) const { return bagnr != i; } }; Iterator Begin () const { Iterator it(*this, 0, -1); it++; return it; } int End() const { return GetNBags(); } void GetData (const Iterator & it, INDEX_2 & ahash, T & acont) const { ahash = hash[it.BagNr()][it.Pos()]; acont = cont[it.BagNr()][it.Pos()]; } const INDEX_2 & GetHash (const Iterator & it) const { return hash[it.BagNr()][it.Pos()]; } const T & GetData (const Iterator & it) const { return cont[it.BagNr()][it.Pos()]; } void DoArchive (Archive & ar) { ar & hash & cont; } }; template inline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE & ht) { for (typename INDEX_2_HASHTABLE::Iterator it = ht.Begin(); it != ht.End(); it++) { ost << ht.GetHash(it) << ": " << ht.GetData(it) << endl; } return ost; } /// class BASE_INDEX_3_HASHTABLE { protected: /// TABLE hash; public: /// BASE_INDEX_3_HASHTABLE () { ; } BASE_INDEX_3_HASHTABLE (int size) : hash (size) { }; protected: /// int HashValue (const INDEX_3 & ind) const { return (ind.I1() + ind.I2() + ind.I3()) % hash.Size() + 1; } /// int Position (int bnr, const INDEX_3 & ind) const { const INDEX_3 * pi = &hash.Get(bnr, 1); int n = hash.EntrySize(bnr); for (int i = 1; i <= n; ++i, ++pi) { if (*pi == ind) return i; } return 0; } }; /// template class INDEX_3_HASHTABLE : private BASE_INDEX_3_HASHTABLE { /// TABLE cont; public: /// inline INDEX_3_HASHTABLE () { ; } inline INDEX_3_HASHTABLE (int size); /// inline void Set (const INDEX_3 & ahash, const T & acont); /// inline const T & Get (const INDEX_3 & ahash) const; /// inline bool Used (const INDEX_3 & ahash) const; /// inline int GetNBags () const; /// inline int GetBagSize (int bnr) const; /// inline void SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont); /// inline void GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const; /// returns position, if not existing, will create (create == return 1) inline int PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr); /// inline void SetSize (int size); /// inline void PrepareSet (const INDEX_3 & ahash); /// inline void AllocateElements (); /// inline void PrintMemInfo (ostream & ost) const; /// inline void DeleteData (); class Iterator { const INDEX_3_HASHTABLE & ht; int bagnr, pos; public: Iterator (const INDEX_3_HASHTABLE & aht, int abagnr, int apos) : ht(aht), bagnr(abagnr), pos(apos) { ; } int BagNr() const { return bagnr; } int Pos() const { return pos; } void operator++ (int) { // cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; pos++; while (bagnr < ht.GetNBags() && pos == ht.GetBagSize(bagnr+1)) { pos = 0; bagnr++; } // cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; } bool operator != (int i) const { return bagnr != i; } }; Iterator Begin () const { Iterator it(*this, 0, -1); it++; return it; } int End() const { return GetNBags(); } void GetData (const Iterator & it, INDEX_3 & ahash, T & acont) const { ahash = hash[it.BagNr()][it.Pos()]; acont = cont[it.BagNr()][it.Pos()]; } const INDEX_3 & GetHash (const Iterator & it) const { return hash[it.BagNr()][it.Pos()]; } const T & GetData (const Iterator & it) const { return cont[it.BagNr()][it.Pos()]; } void DoArchive (Archive & ar) { ar & hash & cont; } }; template inline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE & ht) { for (typename INDEX_3_HASHTABLE::Iterator it = ht.Begin(); it != ht.End(); it++) { ost << ht.GetHash(it) << ": " << ht.GetData(it) << endl; } return ost; } /// Closed Hashing HT class BASE_INDEX_CLOSED_HASHTABLE { protected: /// // MoveableArray hash; Array hash; /// int invalid; public: /// BASE_INDEX_CLOSED_HASHTABLE (int size); int Size() const { return hash.Size(); } int UsedPos (int pos) const { return ! (hash.Get(pos) == invalid); } int UsedElements () const; /// int HashValue (const INDEX & ind) const { return (3*ind) % hash.Size() + 1; } int Position (const INDEX & ind) const { int i = HashValue(ind); while (1) { if (hash.Get(i) == ind) return i; if (hash.Get(i) == invalid) return 0; i++; if (i > hash.Size()) i = 1; } } int CalcPositionCosts (const INDEX & ind) const { int i = HashValue(ind); int costs = 1; while (1) { if (hash.Get(i) == ind) return costs; if (hash.Get(i) == invalid) return costs; i++; if (i > hash.Size()) i = 1; costs++; } } // returns 1, if new position is created int PositionCreate (const INDEX & ind, int & apos) { int i = HashValue (ind); if (hash.Get(i) == ind) { apos = i; return 0; } if (hash.Get(i) == invalid) { hash.Elem(i) = ind; apos = i; return 1; } return PositionCreate2 (ind, apos); } protected: int Position2 (const INDEX & ind) const; int PositionCreate2 (const INDEX & ind, int & apos); void BaseSetSize (int asize); }; template class INDEX_CLOSED_HASHTABLE : public BASE_INDEX_CLOSED_HASHTABLE { /// // MoveableArray cont; Array cont; public: /// INDEX_CLOSED_HASHTABLE (int size) : BASE_INDEX_CLOSED_HASHTABLE(size), cont(size) { ; // cont.SetName ("ind-hashtable, contents"); } void Set (const INDEX & ahash, const T & acont) { int pos; PositionCreate (ahash, pos); hash.Elem(pos) = ahash; cont.Elem(pos) = acont; } const T & Get (const INDEX & ahash) const { int pos = Position (ahash); return cont.Get(pos); } /// bool Used (const INDEX & ahash) const { int pos = Position (ahash); return (pos != 0); } /// inline void SetData (int pos, const INDEX & ahash, const T & acont) { hash.Elem(pos) = ahash; cont.Elem(pos) = acont; } /// void GetData (int pos, INDEX & ahash, T & acont) const { ahash = hash.Get(pos); acont = cont.Get(pos); } /// inline void SetData (int pos, const T & acont) { cont.Elem(pos) = acont; } /// void GetData (int pos, T & acont) const { acont = cont.Get(pos); } /// const T & GetData (int pos) { return cont.Get(pos); } /// inline void SetSize (int size) { BaseSetSize(size); cont.SetSize(size); } /// inline void DeleteData () { SetSize (cont.Size()); } void SetName (const char * aname) { // cont.SetName(aname); // hash.SetName(aname); } }; inline size_t RoundUp2 (size_t i) { size_t res = 1; while (res < i) res *= 2; // hope it will never be too large return res; } /// Closed Hashing HT class BASE_INDEX_2_CLOSED_HASHTABLE { protected: /// // MoveableArray hash; Array hash; /// int invalid; size_t mask; public: /// BASE_INDEX_2_CLOSED_HASHTABLE (size_t size); int Size() const { return hash.Size(); } bool UsedPos0 (int pos) const { return ! (hash[pos].I1() == invalid); } int UsedElements () const; /// int HashValue (const INDEX_2 & ind) const { // return (ind.I1() + 71 * ind.I2()) % hash.Size() + 1; return (ind.I1() + 71 * ind.I2()) & mask; } int Position0 (const INDEX_2 & ind) const { int i = HashValue(ind); while (1) { if (hash[i] == ind) return i; if (hash[i].I1() == invalid) return -1; i = (i+1) & mask; /* i++; if (i > hash.Size()) i = 1; */ } } // returns 1, if new position is created bool PositionCreate0 (const INDEX_2 & ind, int & apos) { int i = HashValue (ind); if (hash[i] == ind) { apos = i; return false; } if (hash[i].I1() == invalid) { hash[i] = ind; apos = i; return true; } return PositionCreate2 (ind, apos); } protected: /// int Position2 (const INDEX_2 & ind) const; bool PositionCreate2 (const INDEX_2 & ind, int & apos); void BaseSetSize (int asize); }; template class INDEX_2_CLOSED_HASHTABLE : public BASE_INDEX_2_CLOSED_HASHTABLE { Array cont; public: INDEX_2_CLOSED_HASHTABLE (size_t size) : BASE_INDEX_2_CLOSED_HASHTABLE(size), cont(RoundUp2(size)) { ; } void Set (const INDEX_2 & ahash, const T & acont) { int pos; PositionCreate0 (ahash, pos); hash[pos] = ahash; cont[pos] = acont; } const T & Get (const INDEX_2 & ahash) const { int pos = Position0 (ahash); return cont[pos]; } inline bool Used (const INDEX_2 & ahash) const { int pos = Position0 (ahash); return (pos != -1); } inline void SetData0 (int pos, const INDEX_2 & ahash, const T & acont) { hash[pos] = ahash; cont[pos] = acont; } /// inline void GetData0 (int pos, INDEX_2 & ahash, T & acont) const { ahash = hash[pos]; acont = cont[pos]; } inline void SetData0 (int pos, const T & acont) { cont[pos] = acont; } inline void GetData0 (int pos, T & acont) const { acont = cont[pos]; } /// const T & GetData0 (int pos) { return cont[pos]; } /// inline void SetSize (size_t size) { BaseSetSize(size); cont.SetSize(RoundUp2(size)); } /// inline void PrintMemInfo (ostream & ost) const; /// inline void DeleteData () { SetSize (cont.Size()); } void SetName (const char * aname) { ; // cont.SetName(aname); // hash.SetName(aname); } }; template inline ostream & operator<< (ostream & ost, const INDEX_2_CLOSED_HASHTABLE & ht) { for (int i = 0; i < ht.Size(); i++) if (ht.UsedPos(i)) { INDEX_2 hash; T data; ht.GetData0 (i, hash, data); ost << "hash = " << hash << ", data = " << data << endl; } return ost; } class BASE_INDEX_3_CLOSED_HASHTABLE { protected: Array hash; int invalid; size_t mask; protected: BASE_INDEX_3_CLOSED_HASHTABLE (size_t size) : hash(RoundUp2(size)) { // cout << "orig size = " << size // << ", roundup size = " << hash.Size(); size = hash.Size(); mask = size-1; // cout << "mask = " << mask << endl; invalid = -1; for (size_t i = 0; i < size; i++) hash[i].I1() = invalid; } public: int Size() const { return hash.Size(); } bool UsedPos (int pos) const { return ! (hash[pos].I1() == invalid); } int UsedElements () const { int n = hash.Size(); int cnt = 0; for (int i = 0; i < n; i++) if (hash[i].I1() != invalid) cnt++; return cnt; } int HashValue (const INDEX_3 & ind) const { // return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) % hash.Size(); return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) & mask; } int Position (const INDEX_3 & ind) const { int i = HashValue(ind); while (1) { if (hash[i] == ind) return i; if (hash[i].I1() == invalid) return -1; // i = (i+1) % hash.Size(); i = (i+1) & mask; } } int Costs (const INDEX_3 & ind) const { int i = HashValue(ind); int c = 1; while (1) { if (hash[i] == ind) return c; if (hash[i].I1() == invalid) return c; // i = (i+1) % hash.Size(); i = (i+1) & mask; c++; } } // returns true, if new position is created bool PositionCreate (const INDEX_3 & ind, int & apos) { int i = HashValue (ind); if (hash[i] == ind) { apos = i; return false; } if (hash[i].I1() == invalid) { hash[i] = ind; apos = i; return true; } return PositionCreate2 (ind, apos); } void DeleteData() { size_t size = hash.Size(); for (size_t i = 0; i < size; i++) hash[i].I1() = invalid; } protected: bool PositionCreate2 (const INDEX_3 & ind, int & apos); void BaseSetSize (int asize); }; template class INDEX_3_CLOSED_HASHTABLE : public BASE_INDEX_3_CLOSED_HASHTABLE { // MoveableArray cont; Array cont; public: INDEX_3_CLOSED_HASHTABLE (int size) : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(RoundUp2(size)) { ; //cont.SetName ("i3-hashtable, contents"); } void Set (const INDEX_3 & ahash, const T & acont) { int pos; PositionCreate (ahash, pos); hash[pos] = ahash; cont[pos] = acont; } const T & Get (const INDEX_3 & ahash) const { return cont[Position (ahash)]; } bool Used (const INDEX_3 & ahash) const { return (Position (ahash) != -1); } void SetData (int pos, const INDEX_3 & ahash, const T & acont) { hash[pos] = ahash; cont[pos] = acont; } void GetData (int pos, INDEX_3 & ahash, T & acont) const { ahash = hash[pos]; acont = cont[pos]; } void SetData (int pos, const T & acont) { cont[pos] = acont; } void GetData (int pos, T & acont) const { acont = cont[pos]; } const T & GetData (int pos) const { return cont[pos]; } void SetSize (int size) { BaseSetSize(size); cont.SetSize(hash.Size()); } void PrintMemInfo (ostream & ost) const { cout << "Hashtable: " << Size() << " entries of size " << sizeof(INDEX_3) << " + " << sizeof(T) << " = " << Size() * (sizeof(INDEX_3) + sizeof(T)) << " bytes" << endl; } void DeleteData () { SetSize (cont.Size()); } void SetName (const char * aname) { ; // cont.SetName(aname); // hash.SetName(aname); } }; template inline ostream & operator<< (ostream & ost, const INDEX_3_CLOSED_HASHTABLE & ht) { for (int i = 0; i < ht.Size(); i++) if (ht.UsedPos(i)) { INDEX_3 hash; T data; ht.GetData (i, hash, data); ost << "hash = " << hash << ", data = " << data << endl; } return ost; } template inline INDEX_3_HASHTABLE :: INDEX_3_HASHTABLE (int size) : BASE_INDEX_3_HASHTABLE (size), cont(size) { ; } template inline int INDEX_3_HASHTABLE :: PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr) { bnr = HashValue (ahash); colnr = Position (bnr, ahash); if (!colnr) { hash.Add (bnr, ahash); cont.AddEmpty (bnr); colnr = cont.EntrySize (bnr); return 1; } return 0; } template inline void INDEX_3_HASHTABLE :: Set (const INDEX_3 & ahash, const T & acont) { int bnr = HashValue (ahash); int pos = Position (bnr, ahash); if (pos) cont.Set (bnr, pos, acont); else { hash.Add1 (bnr, ahash); cont.Add1 (bnr, acont); } } template inline const T & INDEX_3_HASHTABLE :: Get (const INDEX_3 & ahash) const { int bnr = HashValue (ahash); int pos = Position (bnr, ahash); return cont.Get (bnr, pos); } template inline bool INDEX_3_HASHTABLE :: Used (const INDEX_3 & ahash) const { return (Position (HashValue (ahash), ahash)) ? 1 : 0; } template inline int INDEX_3_HASHTABLE :: GetNBags () const { return cont.Size(); } template inline int INDEX_3_HASHTABLE :: GetBagSize (int bnr) const { return cont.EntrySize (bnr); } template inline void INDEX_3_HASHTABLE :: GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const { ahash = hash.Get(bnr, colnr); acont = cont.Get(bnr, colnr); } template inline void INDEX_3_HASHTABLE :: SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont) { hash.Set(bnr, colnr, ahash); cont.Set(bnr, colnr, acont); } template inline void INDEX_3_HASHTABLE :: SetSize (int size) { hash.SetSize (size); cont.SetSize (size); } template inline void INDEX_3_HASHTABLE :: DeleteData () { int n = hash.Size(); hash.SetSize (n); cont.SetSize (n); } template inline void INDEX_3_HASHTABLE :: PrepareSet (const INDEX_3 & ahash) { int bnr = HashValue (ahash); hash.IncSizePrepare (bnr-1); cont.IncSizePrepare (bnr-1); } template inline void INDEX_3_HASHTABLE :: AllocateElements () { hash.AllocateElementsOneBlock(); cont.AllocateElementsOneBlock(); } template inline void INDEX_3_HASHTABLE :: PrintMemInfo (ostream & ost) const { ost << "Hash: " << endl; hash.PrintMemInfo (ost); ost << "Cont: " << endl; cont.PrintMemInfo (ost); } template inline INDEX_HASHTABLE :: INDEX_HASHTABLE (int size) : BASE_INDEX_HASHTABLE (size), cont(size) { ; } template inline void INDEX_HASHTABLE :: Set (const INDEX & ahash, const T & acont) { int bnr = HashValue (ahash); int pos = Position (bnr, ahash); if (pos) cont.Set (bnr, pos, acont); else { hash.Add (bnr, ahash); cont.Add (bnr, acont); } } template inline const T & INDEX_HASHTABLE :: Get (const INDEX & ahash) const { int bnr = HashValue (ahash); int pos = Position (bnr, ahash); return cont.Get (bnr, pos); } template inline bool INDEX_HASHTABLE :: Used (const INDEX & ahash) const { return (Position (HashValue (ahash), ahash)) ? 1 : 0; } template inline int INDEX_HASHTABLE :: GetNBags () const { return hash.Size(); } template inline int INDEX_HASHTABLE :: GetBagSize (int bnr) const { return hash.EntrySize(bnr); } template inline void INDEX_HASHTABLE :: GetData (int bnr, int colnr, INDEX & ahash, T & acont) const { ahash = hash.Get(bnr, colnr); acont = cont.Get(bnr, colnr); } template inline void INDEX_HASHTABLE :: PrintMemInfo (ostream & ost) const { ost << "Hash: " << endl; hash.PrintMemInfo (ost); ost << "Cont: " << endl; cont.PrintMemInfo (ost); } /* *********** Closed Hashing ************************* */ template inline void INDEX_2_CLOSED_HASHTABLE :: PrintMemInfo (ostream & ost) const { cout << "Hashtable: " << Size() << " entries of size " << sizeof(INDEX_2) << " + " << sizeof(T) << " = " << Size() * (sizeof(INDEX_2) + sizeof(T)) << " bytes." << " Used els: " << UsedElements() << endl; } /* template inline INDEX_3_CLOSED_HASHTABLE :: INDEX_3_CLOSED_HASHTABLE (int size) : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(size) { cont.SetName ("i3-hashtable, contents"); } template inline void INDEX_3_CLOSED_HASHTABLE :: Set (const INDEX_3 & ahash, const T & acont) { int pos; PositionCreate (ahash, pos); hash.Elem(pos) = ahash; cont.Elem(pos) = acont; } template inline const T & INDEX_3_CLOSED_HASHTABLE :: Get (const INDEX_3 & ahash) const { int pos = Position (ahash); return cont[pos]; } template inline bool INDEX_3_CLOSED_HASHTABLE :: Used (const INDEX_3 & ahash) const { int pos = Position (ahash); return (pos != 0); } template inline void INDEX_3_CLOSED_HASHTABLE :: SetData (int pos, const INDEX_3 & ahash, const T & acont) { hash.Elem(pos) = ahash; cont.Elem(pos) = acont; } template inline void INDEX_3_CLOSED_HASHTABLE :: GetData (int pos, INDEX_3 & ahash, T & acont) const { ahash = hash.Get(pos); acont = cont.Get(pos); } template inline void INDEX_3_CLOSED_HASHTABLE :: SetData (int pos, const T & acont) { cont.Elem(pos) = acont; } template inline void INDEX_3_CLOSED_HASHTABLE :: GetData (int pos, T & acont) const { acont = cont.Get(pos); } template inline const T & INDEX_3_CLOSED_HASHTABLE :: GetData (int pos) const { return cont.Get(pos); } template inline void INDEX_3_CLOSED_HASHTABLE :: SetSize (int size) { BaseSetSize(size); cont.SetSize(size); } template inline void INDEX_3_CLOSED_HASHTABLE :: PrintMemInfo (ostream & ost) const { cout << "Hashtable: " << Size() << " entries of size " << sizeof(INDEX_3) << " + " << sizeof(T) << " = " << Size() * (sizeof(INDEX_3) + sizeof(T)) << " bytes" << endl; } */ inline void SetInvalid (INDEX & i) { i = -1; } inline bool IsInvalid (INDEX i) { return i == -1; } inline size_t HashValue (INDEX i, size_t size) { return (113*size_t(i)) % size; } inline void SetInvalid (INDEX_2 & i2) { i2[0] = -1; } inline bool IsInvalid (INDEX_2 i2) { return i2[0] == -1; } inline size_t HashValue (INDEX_2 i2, size_t size) { return (113*size_t(i2[0])+size_t(i2[1])) % size; } /** A closed hash-table. All information is stored in one fixed array. The array should be allocated with the double size of the expected number of entries. */ template class ClosedHashTable { protected: /// size_t size; /// size_t used; /// Array hash; /// Array cont; public: /// ClosedHashTable (size_t asize = 128) : size(asize), used(0), hash(asize), cont(asize) { for (auto & v : hash) SetInvalid(v); } ClosedHashTable (ClosedHashTable && ht2) = default; // who needs that ? ClosedHashTable (FlatArray _hash, FlatArray _cont) : size(_hash.Size()), used(0), hash(_hash.Size(), _hash.Addr(0)), cont(_cont.Size(), _cont.Addr(0)) { for (auto & v : hash) SetInvalid(v); } ClosedHashTable & operator= (ClosedHashTable && ht2) = default; /// size_t Size() const { return size; } /// is position used bool UsedPos (size_t pos) const { return ! (IsInvalid(hash[pos])); } /// number of used elements size_t UsedElements () const { return used; /* size_t cnt = 0; for (size_t i = 0; i < size; i++) if (hash[i] != invalid) cnt++; return cnt; */ } size_t Position (const T_HASH ind) const { size_t i = HashValue(ind, size); while (1) { if (hash[i] == ind) return i; if (IsInvalid(hash[i])) return size_t(-1); i++; if (i >= size) i = 0; } } void DoubleSize() { ClosedHashTable tmp(2*Size()); for (auto both : *this) tmp[both.first] = both.second; *this = move(tmp); } // returns true if new position is created bool PositionCreate (const T_HASH ind, size_t & apos) { if (UsedElements()*2 > Size()) DoubleSize(); size_t i = HashValue (ind, size); while (1) { if (IsInvalid(hash[i])) { hash[i] = ind; apos = i; used++; return true; } if (hash[i] == ind) { apos = i; return false; } i++; if (i >= size) i = 0; } } /// void Set (const T_HASH & ahash, const T & acont) { size_t pos; PositionCreate (ahash, pos); hash[pos] = ahash; cont[pos] = acont; } /// const T & Get (const T_HASH & ahash) const { size_t pos = Position (ahash); if (pos == size_t(-1)) throw Exception (string("illegal key: ") + ToString(ahash) ); return cont[pos]; } /// bool Used (const T_HASH & ahash) const { return (Position (ahash) != size_t(-1)); } void SetData (size_t pos, const T_HASH & ahash, const T & acont) { hash[pos] = ahash; cont[pos] = acont; } void GetData (size_t pos, T_HASH & ahash, T & acont) const { ahash = hash[pos]; acont = cont[pos]; } void SetData (size_t pos, const T & acont) { cont[pos] = acont; } void GetData (size_t pos, T & acont) const { acont = cont[pos]; } pair GetBoth (size_t pos) const { return pair (hash[pos], cont[pos]); } const T & operator[] (T_HASH key) const { return Get(key); } T & operator[] (T_HASH key) { size_t pos; PositionCreate(key, pos); return cont[pos]; } void SetSize (size_t asize) { size = asize; hash.Alloc(size); cont.Alloc(size); // for (size_t i = 0; i < size; i++) // hash[i] = invalid; // hash = T_HASH(invalid); for (auto & v : hash) SetInvalid(v); } void Delete (T_HASH key) { size_t pos = Position(key); if (pos == size_t(-1)) return; SetInvalid (hash[pos]); used--; while (1) { size_t nextpos = pos+1; if (nextpos == size) nextpos = 0; if (IsInvalid(hash[nextpos])) break; auto key = hash[nextpos]; auto val = cont[nextpos]; SetInvalid (hash[nextpos]); used--; Set (key, val); pos = nextpos; } } class Iterator { const ClosedHashTable & tab; size_t nr; public: Iterator (const ClosedHashTable & _tab, size_t _nr) : tab(_tab), nr(_nr) { while (nr < tab.Size() && !tab.UsedPos(nr)) nr++; } Iterator & operator++() { nr++; while (nr < tab.Size() && !tab.UsedPos(nr)) nr++; return *this; } bool operator!= (const Iterator & it2) { return nr != it2.nr; } auto operator* () const { T_HASH hash; T val; tab.GetData(nr, hash,val); return std::make_pair(hash,val); } }; Iterator begin() const { return Iterator(*this, 0); } Iterator end() const { return Iterator(*this, Size()); } }; template ostream & operator<< (ostream & ost, const ClosedHashTable & tab) { for (size_t i = 0; i < tab.Size(); i++) if (tab.UsedPos(i)) { T_HASH key; T val; tab.GetData (i, key, val); ost << key << ": " << val << ", "; } return ost; } } #endif netgen-6.2.1905/libsrc/general/hashtabl.cpp0000644000175000017500000001427413504650527017176 0ustar kurtkurt/**************************************************************************/ /* File: hashtabl.cpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /* Abstract data type HASHTABLE */ #include #include #include namespace netgen { //using namespace netgen; void INDEX_4 :: Sort () { if (i[0] > i[1]) Swap (i[0], i[1]); if (i[2] > i[3]) Swap (i[2], i[3]); if (i[0] > i[2]) Swap (i[0], i[2]); if (i[1] > i[3]) Swap (i[1], i[3]); if (i[1] > i[2]) Swap (i[1], i[2]); } void INDEX_4Q :: Sort () { if (min2 (i[1], i[2]) < min2 (i[0], i[3])) { Swap (i[0], i[1]); Swap (i[2], i[3]);} if (i[3] < i[0]) { Swap (i[0], i[3]); Swap (i[1], i[2]);} if (i[3] < i[1]) { Swap (i[1], i[3]); } } ostream & operator<<(ostream & s, const INDEX_2 & i2) { return s << i2.I1() << ", " << i2.I2(); } ostream & operator<<(ostream & s, const INDEX_3 & i3) { return s << i3.I1() << ", " << i3.I2() << ", " << i3.I3(); } ostream & operator<<(ostream & s, const INDEX_4 & i4) { return s << i4.I1() << ", " << i4.I2() << ", " << i4.I3() << ", " << i4.I4(); } ostream & operator<<(ostream & s, const INDEX_4Q & i4) { return s << i4.I1() << ", " << i4.I2() << ", " << i4.I3() << ", " << i4.I4(); } int BASE_INDEX_HASHTABLE :: Position (int bnr, const INDEX & ind) const { for (int i = 1; i <= hash.EntrySize (bnr); i++) if (hash.Get(bnr, i) == ind) return i; return 0; } /* int BASE_INDEX_2_HASHTABLE :: Position (int bnr, const INDEX_2 & ind) const { int i; for (i = 1; i <= hash.EntrySize (bnr); i++) if (hash.Get(bnr, i) == ind) return i; return 0; } */ void BASE_INDEX_2_HASHTABLE :: PrintStat (ostream & ost) const { int n = hash.Size(); int i; int sumn = 0, sumnn = 0; for (i = 1; i <= n; i++) { sumn += hash.EntrySize(i); sumnn += sqr (hash.EntrySize(i)); } ost << "Hashtable: " << endl << "size : " << n << endl << "elements per row : " << (double(sumn) / double(n)) << endl << "av. access time : " << (sumn ? (double (sumnn) / double(sumn)) : 0) << endl; } /* int BASE_INDEX_3_HASHTABLE :: Position (int bnr, const INDEX_3 & ind) const { int i; const INDEX_3 * pi = &hash.Get(bnr, 1); int n = hash.EntrySize(bnr); for (i = 1; i <= n; ++i, ++pi) { if (*pi == ind) return i; } return 0; } */ BASE_INDEX_CLOSED_HASHTABLE :: BASE_INDEX_CLOSED_HASHTABLE (int size) : hash(size) { // hash.SetName ("index-hashtable, hash"); invalid = -1; for (int i = 1; i <= size; i++) hash.Elem(i) = invalid; } void BASE_INDEX_CLOSED_HASHTABLE :: BaseSetSize (int size) { hash.SetSize(size); for (int i = 1; i <= size; i++) hash.Elem(i) = invalid; } int BASE_INDEX_CLOSED_HASHTABLE :: Position2 (const INDEX & ind) const { int i = HashValue(ind); while (1) { i++; if (i > hash.Size()) i = 1; if (hash.Get(i) == ind) return i; if (hash.Get(i) == invalid) return 0; } } int BASE_INDEX_CLOSED_HASHTABLE :: PositionCreate2 (const INDEX & ind, int & apos) { int i = HashValue(ind); int startpos = i; while (1) { i++; if (i > hash.Size()) i = 1; if (hash.Get(i) == ind) { apos = i; return 0; } if (hash.Get(i) == invalid) { hash.Elem(i) = ind; apos = i; return 1; } if (i == startpos) throw NgException ("Try to set new element in full closed hashtable"); } } int BASE_INDEX_CLOSED_HASHTABLE :: UsedElements () const { int n = hash.Size(); int cnt = 0; for (int i = 1; i <= n; i++) if (hash.Get(i) != invalid) cnt++; return cnt; } BASE_INDEX_2_CLOSED_HASHTABLE :: BASE_INDEX_2_CLOSED_HASHTABLE (size_t size) : hash(RoundUp2(size)) { size = hash.Size(); mask = size-1; // hash.SetName ("i2-hashtable, hash"); invalid = -1; for (size_t i = 0; i < size; i++) hash[i].I1() = invalid; } void BASE_INDEX_2_CLOSED_HASHTABLE :: BaseSetSize (int size) { size = RoundUp2 (size); mask = size-1; hash.SetSize(size); for (size_t i = 0; i < size; i++) hash[i].I1() = invalid; } int BASE_INDEX_2_CLOSED_HASHTABLE :: Position2 (const INDEX_2 & ind) const { int i = HashValue(ind); while (1) { i++; if (i > hash.Size()) i = 1; if (hash.Get(i) == ind) return i; if (hash.Get(i).I1() == invalid) return 0; } } bool BASE_INDEX_2_CLOSED_HASHTABLE :: PositionCreate2 (const INDEX_2 & ind, int & apos) { int i = HashValue(ind); int startpos = i; while (1) { /* i++; if (i > hash.Size()) i = 1; */ i = (i+1) % hash.Size(); if (hash[i] == ind) { apos = i; return false; } if (hash[i].I1() == invalid) { hash[i] = ind; apos = i; return true; } if (i == startpos) throw NgException ("Try to set new element in full closed hashtable"); } } int BASE_INDEX_2_CLOSED_HASHTABLE :: UsedElements () const { int n = hash.Size(); int cnt = 0; for (int i = 1; i <= n; i++) if (hash.Get(i).I1() != invalid) cnt++; return cnt; } void BASE_INDEX_3_CLOSED_HASHTABLE :: BaseSetSize (int size) { size = RoundUp2 (size); mask = size-1; hash.SetSize(size); for (int i = 0; i < size; i++) hash[i].I1() = invalid; } bool BASE_INDEX_3_CLOSED_HASHTABLE :: PositionCreate2 (const INDEX_3 & ind, int & apos) { int i = HashValue(ind); int startpos = i; while (1) { /* i++; if (i >= hash.Size()) i = 0; */ i = (i+1) % hash.Size(); if (hash[i] == ind) { apos = i; return false; } if (hash[i].I1() == invalid) { hash[i] = ind; apos = i; return true; } if (i == startpos) throw NgException ("Try to set new element in full closed hashtable"); } } } netgen-6.2.1905/libsrc/general/seti.cpp0000644000175000017500000000174313504650527016351 0ustar kurtkurt#include #include namespace netgen { //using namespace netgen; IndexSet :: IndexSet (int maxind) { SetMaxIndex (maxind); } IndexSet :: ~IndexSet () { Clear(); } void IndexSet :: SetMaxIndex (int maxind) { if (maxind > flags.Size()) { flags.SetSize (2 * maxind); flags.Clear(); } } /* int IndexSet :: IsIn (int ind) const { return flags.Test (ind); } */ /* void IndexSet :: Add (int ind) { if (ind > flags.Size()) { cerr << "out of range" << endl; exit (1); } if (!flags.Test(ind)) { set.Append (ind); flags.Set (ind); } } */ void IndexSet :: Del (int ind) { for (int i = 1; i <= set.Size(); i++) if (set.Get(i) == ind) { set.DeleteElement (ind); break; } flags.Clear (ind); } void IndexSet :: Clear () { for (int i = 1; i <= set.Size(); i++) flags.Clear (set.Get(i)); set.SetSize (0); } } netgen-6.2.1905/libsrc/general/seti.hpp0000644000175000017500000000163113504650527016352 0ustar kurtkurt#ifndef FILE_SETI #define FILE_SETI /**************************************************************************/ /* File: seti.hh */ /* Author: Joachim Schoeberl */ /* Date: 20. Mar. 98 */ /**************************************************************************/ namespace netgen { /** Set of Integers */ class IndexSet { Array set; BitArray flags; public: IndexSet (int maxind); ~IndexSet (); /// increase range to maxind void SetMaxIndex (int maxind); int IsIn (int ind) const { return flags.Test (ind); } void Add (int ind) { if (!flags.Test(ind)) { set.Append (ind); flags.Set (ind); } } void Del (int ind); void Clear (); const Array & GetArray() { return set; } }; } #endif netgen-6.2.1905/libsrc/general/flags.cpp0000644000175000017500000001526413504650527016504 0ustar kurtkurt/**************************************************************************/ /* File: flags.cc */ /* Author: Joachim Schoeberl */ /* Date: 10. Oct. 96 */ /**************************************************************************/ /* Datatype Flags */ #include #include namespace netgen { //using namespace netgen; Flags :: Flags () { ; } Flags :: ~Flags () { DeleteFlags (); } void Flags :: DeleteFlags () { for (int i = 0; i < strflags.Size(); i++) delete [] strflags[i]; for (int i = 0; i < numlistflags.Size(); i++) delete numlistflags[i]; strflags.DeleteAll(); numflags.DeleteAll(); defflags.DeleteAll(); strlistflags.DeleteAll(); numlistflags.DeleteAll(); } void Flags :: SetFlag (const char * name, const char * val) { char * hval = new char[strlen (val) + 1]; strcpy (hval, val); strflags.Set (name, hval); } void Flags :: SetFlag (const char * name, double val) { numflags.Set (name, val); } void Flags :: SetFlag (const char * name) { defflags.Set (name, 1); } void Flags :: SetFlag (const char * name, const Array & val) { Array * strarray = new Array; for (int i = 1; i <= val.Size(); i++) { strarray->Append (new char[strlen(val.Get(i))+1]); strcpy (strarray->Last(), val.Get(i)); } strlistflags.Set (name, strarray); } void Flags :: SetFlag (const char * name, const Array & val) { Array * numarray = new Array; for (int i = 1; i <= val.Size(); i++) numarray->Append (val.Get(i)); numlistflags.Set (name, numarray); } const char * Flags :: GetStringFlag (const char * name, const char * def) const { if (strflags.Used (name)) return strflags[name]; else return def; } double Flags :: GetNumFlag (const char * name, double def) const { if (numflags.Used (name)) return numflags[name]; else return def; } const double * Flags :: GetNumFlagPtr (const char * name) const { if (numflags.Used (name)) return & ((SymbolTable&)numflags)[name]; else return NULL; } double * Flags :: GetNumFlagPtr (const char * name) { if (numflags.Used (name)) return & ((SymbolTable&)numflags)[name]; else return NULL; } bool Flags :: GetDefineFlag (const char * name) const { return defflags.Used (name); } const Array & Flags :: GetStringListFlag (const char * name) const { if (strlistflags.Used (name)) return *strlistflags[name]; else { static Array dummy_array(0); return dummy_array; } } const Array & Flags ::GetNumListFlag (const char * name) const { if (numlistflags.Used (name)) return *numlistflags[name]; else { static Array dummy_array(0); return dummy_array; } } bool Flags :: StringFlagDefined (const char * name) const { return strflags.Used (name); } bool Flags :: NumFlagDefined (const char * name) const { return numflags.Used (name); } bool Flags :: StringListFlagDefined (const char * name) const { return strlistflags.Used (name); } bool Flags :: NumListFlagDefined (const char * name) const { return numlistflags.Used (name); } void Flags :: SaveFlags (const char * filename) const { int i; ofstream outfile (filename); for (i = 1; i <= strflags.Size(); i++) outfile << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) outfile << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) outfile << defflags.GetName(i) << endl; } void Flags :: PrintFlags (ostream & ost) const { int i; for (i = 1; i <= strflags.Size(); i++) ost << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) ost << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) ost << defflags.GetName(i) << endl; } void Flags :: LoadFlags (const char * filename) { char name[100], str[100]; char ch; double val; ifstream infile(filename); // (*logout) << "Load flags from " << filename << endl << endl; while (infile.good()) { infile >> name; if (strlen (name) == 0) break; if (name[0] == '/' && name[1] == '/') { // (*logout) << "comment: "; ch = 0; while (ch != '\n' && infile.good()) { ch = infile.get(); // (*logout) << ch; } continue; } // (*logout) << name; ch = 0; infile >> ch; if (ch != '=') { // (*logout) << endl; infile.putback (ch); SetFlag (name); } else { infile >> val; if (!infile.good()) { infile.clear(); infile >> str; SetFlag (name, str); // (*logout) << " = " << str << endl; } else { SetFlag (name, val); // (*logout) << " = " << val << endl; } } } // (*logout) << endl; } void Flags :: SetCommandLineFlag (const char * st) { // cout << "clflag = " << st << endl; istringstream inst( (char *)st); // istrstream defined with char * (not const char * ?????) char name[100]; double val; if (st[0] != '-') { cerr << "flag must start with '-'" << endl; return; } const char * pos = strchr (st, '='); if (!pos) { // (cout) << "Add def flag: " << st+1 << endl; SetFlag (st+1); } else { // cout << "pos = " << pos << endl; strncpy (name, st+1, (pos-st)-1); name[pos-st-1] = 0; // cout << "name = " << name << endl; pos++; char * endptr = NULL; val = strtod (pos, &endptr); // cout << "val = " << val << endl; if (endptr == pos) { // (cout) << "Add String Flag: " << name << " = " << pos << endl; SetFlag (name, pos); } else { // (cout) << "Add Num Flag: " << name << " = " << val << endl; SetFlag (name, val); } } /* inst >> name; (*mycout) << "name = " << name << endl; ch = 0; inst >> ch; if (ch != '=') { SetFlag (name); } else { inst >> val; if (!inst.good()) { inst.clear(); inst >> str; SetFlag (name, str); (*mycout) << "str = " << str << endl; } else { SetFlag (name, val); (*mycout) << "val = " << val << endl; } } */ } } netgen-6.2.1905/libsrc/general/autodiff.hpp0000644000175000017500000001714013504650527017211 0ustar kurtkurt#ifndef FILE_AUTODIFF #define FILE_AUTODIFF /**************************************************************************/ /* File: autodiff.hpp */ /* Author: Joachim Schoeberl */ /* Date: 24. Oct. 02 */ /**************************************************************************/ // Automatic differentiation datatype /** Datatype for automatic differentiation. Contains function value and D derivatives. Algebraic operations are overloaded by using product-rule etc. etc. **/ template class AutoDiff { SCAL val; SCAL dval[D]; public: typedef AutoDiff TELEM; typedef SCAL TSCAL; /// elements are undefined AutoDiff () throw() { }; // { val = 0; for (int i = 0; i < D; i++) dval[i] = 0; } // ! /// copy constructor AutoDiff (const AutoDiff & ad2) throw() { val = ad2.val; for (int i = 0; i < D; i++) dval[i] = ad2.dval[i]; } /// initial object with constant value AutoDiff (SCAL aval) throw() { val = aval; for (int i = 0; i < D; i++) dval[i] = 0; } /// init object with (val, e_diffindex) AutoDiff (SCAL aval, int diffindex) throw() { val = aval; for (int i = 0; i < D; i++) dval[i] = 0; dval[diffindex] = 1; } /// assign constant value AutoDiff & operator= (SCAL aval) throw() { val = aval; for (int i = 0; i < D; i++) dval[i] = 0; return *this; } /// returns value SCAL Value() const throw() { return val; } /// returns partial derivative SCAL DValue (int i) const throw() { return dval[i]; } /// access value SCAL & Value() throw() { return val; } /// accesses partial derivative SCAL & DValue (int i) throw() { return dval[i]; } /// AutoDiff & operator+= (const AutoDiff & y) throw() { val += y.val; for (int i = 0; i < D; i++) dval[i] += y.dval[i]; return *this; } /// AutoDiff & operator-= (const AutoDiff & y) throw() { val -= y.val; for (int i = 0; i < D; i++) dval[i] -= y.dval[i]; return *this; } /// AutoDiff & operator*= (const AutoDiff & y) throw() { for (int i = 0; i < D; i++) { // dval[i] *= y.val; // dval[i] += val * y.dval[i]; dval[i] = dval[i] * y.val + val * y.dval[i]; } val *= y.val; return *this; } /// AutoDiff & operator*= (const SCAL & y) throw() { val *= y; for (int i = 0; i < D; i++) dval[i] *= y; return *this; } /// AutoDiff & operator/= (const SCAL & y) throw() { SCAL iy = 1.0 / y; val *= iy; for (int i = 0; i < D; i++) dval[i] *= iy; return *this; } /// bool operator== (SCAL val2) throw() { return val == val2; } /// bool operator!= (SCAL val2) throw() { return val != val2; } /// bool operator< (SCAL val2) throw() { return val < val2; } /// bool operator> (SCAL val2) throw() { return val > val2; } }; //@{ AutoDiff helper functions. /// prints AutoDiff template inline ostream & operator<< (ostream & ost, const AutoDiff & x) { ost << x.Value() << ", D = "; for (int i = 0; i < D; i++) ost << x.DValue(i) << " "; return ost; } /// AutoDiff plus AutoDiff template inline AutoDiff operator+ (const AutoDiff & x, const AutoDiff & y) throw() { AutoDiff res; res.Value () = x.Value()+y.Value(); // AutoDiff res(x.Value()+y.Value()); for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i) + y.DValue(i); return res; } /// AutoDiff minus AutoDiff template inline AutoDiff operator- (const AutoDiff & x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x.Value()-y.Value(); // AutoDiff res (x.Value()-y.Value()); for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i) - y.DValue(i); return res; } /// double plus AutoDiff template inline AutoDiff operator+ (double x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x+y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = y.DValue(i); return res; } /// AutoDiff plus double template inline AutoDiff operator+ (const AutoDiff & y, double x) throw() { AutoDiff res; res.Value() = x+y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = y.DValue(i); return res; } /// minus AutoDiff template inline AutoDiff operator- (const AutoDiff & x) throw() { AutoDiff res; res.Value() = -x.Value(); for (int i = 0; i < D; i++) res.DValue(i) = -x.DValue(i); return res; } /// AutoDiff minus double template inline AutoDiff operator- (const AutoDiff & x, double y) throw() { AutoDiff res; res.Value() = x.Value()-y; for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i); return res; } /// template inline AutoDiff operator- (double x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x-y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = -y.DValue(i); return res; } /// double times AutoDiff template inline AutoDiff operator* (double x, const AutoDiff & y) throw() { AutoDiff res; res.Value() = x*y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x*y.DValue(i); return res; } /// AutoDiff times double template inline AutoDiff operator* (const AutoDiff & y, double x) throw() { AutoDiff res; res.Value() = x*y.Value(); for (int i = 0; i < D; i++) res.DValue(i) = x*y.DValue(i); return res; } /// AutoDiff times AutoDiff template inline AutoDiff operator* (const AutoDiff & x, const AutoDiff & y) throw() { AutoDiff res; SCAL hx = x.Value(); SCAL hy = y.Value(); res.Value() = hx*hy; for (int i = 0; i < D; i++) res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i); return res; } /// AutoDiff times AutoDiff template inline AutoDiff sqr (const AutoDiff & x) throw() { AutoDiff res; SCAL hx = x.Value(); res.Value() = hx*hx; hx *= 2; for (int i = 0; i < D; i++) res.DValue(i) = hx*x.DValue(i); return res; } /// Inverse of AutoDiff template inline AutoDiff Inv (const AutoDiff & x) { AutoDiff res(1.0 / x.Value()); for (int i = 0; i < D; i++) res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value()); return res; } /// AutoDiff div AutoDiff template inline AutoDiff operator/ (const AutoDiff & x, const AutoDiff & y) { return x * Inv (y); } /// AutoDiff div double template inline AutoDiff operator/ (const AutoDiff & x, double y) { return (1/y) * x; } /// double div AutoDiff template inline AutoDiff operator/ (double x, const AutoDiff & y) { return x * Inv(y); } template inline AutoDiff fabs (const AutoDiff & x) { double abs = fabs (x.Value()); AutoDiff res( abs ); if (abs != 0.0) for (int i = 0; i < D; i++) res.DValue(i) = x.DValue(i) / abs; else for (int i = 0; i < D; i++) res.DValue(i) = 0.0; return res; } //@} #endif netgen-6.2.1905/libsrc/general/netgenout.hpp0000644000175000017500000000632213504650527017420 0ustar kurtkurt#ifndef NETGEN_OUT_STREAM_HPP__ #define NETGEN_OUT_STREAM_HPP__ // #include // #include // #include #include "mpi_interface.hpp" namespace netgen { DLL_HEADER extern int printmessage_importance; DLL_HEADER extern int printdots; class Imp { int importance; public: Imp () : importance(0) { ; } Imp ( int aimportance ) : importance(aimportance) { ; } int GetImp () const { return importance; } }; class Proc { int proc; public: Proc () : proc(0) { ; } Proc ( int aproc ) : proc(aproc) { ; } int GetProc () const { return proc; } }; class Procs { const netgen::FlatArray procs; public: Procs ( const netgen::FlatArray & aprocs ) : procs (aprocs) { ; } const netgen::FlatArray & GetProcs () const { return procs; } }; class NetgenOutStream { ostream * out; bool print; bool printheader; public: NetgenOutStream() : out(&std::cout), print(1), printheader(1) { ; } NetgenOutStream(ostream * aout, Imp imp ) : out(aout), printheader(1) { if ( netgen::printmessage_importance >= imp.GetImp() ) print = true; else print = false; } NetgenOutStream(ostream * aout, Proc proc ) : out(aout), printheader(1) { #ifdef PARALLEL if ( netgen::id == proc.GetProc() ) print = true; else print = false; #else if ( 0 == proc.GetProc() ) print = true; else print = false; #endif } NetgenOutStream(ostream * aout, Procs & procs ) : out(aout), printheader(1) { #ifdef PARALLEL if ( procs.GetProcs().Contains(netgen::id) ) print = true; else print = false; #else if ( procs.GetProcs().Contains(0) ) print = true; else print = false; #endif } ostream & OStream () { return *out; } template NetgenOutStream & operator<< (T & var) { if ( print ) { #ifdef PARALLEL if ( printheader ) { *out << "proc " << netgen::id << ": "; printheader = false; } #endif *out << var; } return (*this); } NetgenOutStream& operator<< (ostream& ( *pf )(ostream&)) { if ( print ) *out << (*pf) ; return (*this); } NetgenOutStream& operator<< (ios& ( *pf )(ios&)) { if ( print) *out << (*pf) ; printheader = 1; return (*this); } NetgenOutStream& operator<< (ios_base& ( *pf )(ios_base&)) { if (print ) *out << (*pf) ; return (*this); } }; /* NetgenOutStream operator<< ( ostream & ost, Imp imp ); NetgenOutStream operator<< ( ostream & ost, Proc proc ); NetgenOutStream operator<< ( ostream & ost, Procs & procs ); */ inline NetgenOutStream operator<< ( ostream & ost, Imp imp ) { return ( NetgenOutStream ( &ost, imp ) ); } inline NetgenOutStream operator<< ( ostream & ost, Proc proc ) { return ( NetgenOutStream ( &ost, proc ) ); } inline NetgenOutStream operator<< ( ostream & ost, Procs & procs ) { return ( NetgenOutStream ( &ost, procs ) ); } // { // return ( NetgenOutStream ( &ost, imp.GetImp() ) ); // } // template // NetgenOutStream& operator<< (NetgenOutStream& out, T c ) // { // out.OStream() << c << endl; // return out; // } } #endif netgen-6.2.1905/libsrc/general/bitarray.hpp0000644000175000017500000000732413504650527017230 0ustar kurtkurt#ifndef FILE_BitArray #define FILE_BitArray /**************************************************************************/ /* File: bitarray.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ #include namespace netgen { /** data type BitArray BitArray is a compressed array of Boolean information. By Set and Clear the whole array or one bit can be set or reset, respectively. Test returns the state of the occurring bit. No range checking is done. index ranges from 0 to size-1 */ class BitArray { INDEX size; unsigned char * data; public: BitArray (); /// BitArray (INDEX asize); /// ~BitArray (); /// void SetSize (INDEX asize); /// INDEX Size () const { return size; } /// void Set (); /// void Set (INDEX i) { data[Addr(i)] |= Mask(i); } void Clear (); void Clear (INDEX i) { data[Addr(i)] &= ~Mask(i); } bool Test (INDEX i) const { return (data[i / CHAR_BIT] & (char(1) << (i % CHAR_BIT) ) ) ? true : false; } /// void Invert (); /// void And (const BitArray & ba2); /// void Or (const BitArray & ba2); private: /// inline unsigned char Mask (INDEX i) const { return char(1) << (i % CHAR_BIT); } /// inline INDEX Addr (INDEX i) const { return (i / CHAR_BIT); } /// BitArray & operator= (BitArray &); /// BitArray (const BitArray &); }; // print bitarray inline ostream & operator<< (ostream & s, const BitArray & a) { for (int i = 1; i <= a.Size(); i++) { s << int (a.Test(i)); if (i % 40 == 0) s << "\n"; } if (a.Size() % 40 != 0) s << "\n"; return s; } /* inline INDEX BitArray :: Size () const { return size; } inline unsigned char BitArray :: Mask (INDEX i) const { return char(1) << (i % CHAR_BIT); } inline INDEX BitArray :: Addr (INDEX i) const { return (i / CHAR_BIT); } inline void BitArray :: Set (INDEX i) { data[Addr(i)] |= Mask(i); } inline void BitArray :: Clear (INDEX i) { data[Addr(i)] &= ~Mask(i); } inline int BitArray :: Test (INDEX i) const { return (data[i / CHAR_BIT] & (char(1) << (i % CHAR_BIT) ) ) ? 1 : 0; } */ /** data type BitArrayChar BitArray is an array of Boolean information. By Set and Clear the whole array or one bit can be set or reset, respectively. Test returns the state of the occurring bit. No range checking is done. */ template class BitArrayChar { /// Array data; public: /// BitArrayChar () { ; } /// BitArrayChar (int asize) : data(asize) { ; } /// ~BitArrayChar () { ; } /// void SetSize (int asize) { data.SetSize(asize); } /// inline int Size () const { return data.Size(); } /// void Set (); /// inline void Set (int i) { data[i] = 1; } /// void Clear (); /// inline void Clear (int i) { data[i] = 0; } /// inline int Test (int i) const { return data[i]; } /// void Invert (); /// void And (const BitArrayChar & ba2); /// void Or (const BitArrayChar & ba2); private: /// copy bitarray is not supported BitArrayChar & operator= (BitArrayChar &) { return *this; } /// copy bitarray is not supported BitArrayChar (const BitArrayChar &) { ; } }; template inline ostream & operator<< (ostream & s, const BitArrayChar & a) { for (int i = BASE; i < a.Size()+BASE; i++) { s << a.Test(i); if ( (i-BASE) % 40 == 39) s << "\n"; } if (a.Size() % 40 != 0) s << "\n"; return s; } } #endif netgen-6.2.1905/libsrc/general/parthreads.hpp0000644000175000017500000000534013504650527017544 0ustar kurtkurt#ifndef FILE_PARTHREADS #define FILE_PARTHREADS /**************************************************************************/ /* File: parthreads.hh */ /* Author: Joachim Schoeberl */ /* Date: 22. Nov. 2000 */ /**************************************************************************/ /* Parallel thread, Mutex, */ #include namespace netgen { #ifdef NO_PARALLEL_THREADS class NgMutex { }; class NgLock { public: NgLock (NgMutex & mut, bool lock = 0) { ; } void Lock () { ; } void UnLock () { ; } }; #else typedef std::mutex NgMutex; class NgLock { NgMutex & mut; bool locked; public: NgLock (NgMutex & ngmut, bool lock = false) : mut (ngmut) { if (lock) mut.lock(); locked = lock; }; ~NgLock() { if (locked) mut.unlock(); } void Lock () { mut.lock(); locked = true; } void UnLock () { mut.unlock(); locked = false; } /* int TryLock () { return mut.try_lock(); } */ }; #endif // Simple ParallelFor function to replace OpenMP template void ParallelFor( int first, int next, const TFunc & f ) { int nthreads = thread::hardware_concurrency(); thread * threads = new thread[nthreads]; for (int i=0; i inline atomic & AsAtomic (T & d) { return reinterpret_cast&> (d); } typedef void (*TaskManager)(std::function); typedef void (*Tracer)(string, bool); // false .. start, true .. stop inline void DummyTaskManager (std::function func) { func(0,2); func(1,2); } inline void DummyTracer (string, bool) { ; } template inline void ParallelFor (TaskManager tm, size_t n, FUNC func) { (*tm) ([n,func] (size_t nr, size_t nums) { size_t begin = nr*n / nums; size_t end = (nr+1)*n / nums; for (size_t i = begin; i < end; i++) func(i); }); } template inline void ParallelForRange (TaskManager tm, size_t n, FUNC func) { (*tm) ([n,func] (size_t nr, size_t nums) { size_t begin = nr*n / nums; size_t end = (nr+1)*n / nums; func(begin, end); }); } } #endif netgen-6.2.1905/libsrc/general/template.hpp0000644000175000017500000002005513504650527017222 0ustar kurtkurt#ifndef FILE_TEMPLATE #define FILE_TEMPLATE /**************************************************************************/ /* File: template.hh */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ namespace netgen { /* templates, global types, defines and variables */ /// The following value may be adapted to the hardware ! #ifndef CLOCKS_PER_SEC #define CLOCKS_PER_SEC 1000000 #endif // #include /** output stream for testing. testout is opened by main */ /** use instead of cout */ DLL_HEADER extern ostream * mycout; /** error output stream */ DLL_HEADER extern ostream * myerr; /** Error messages display. Error messages are displayed by this function */ DLL_HEADER extern void MyError (const char * ch); /** Rings the bell. Produces nr beeps. */ DLL_HEADER extern void MyBeep (int nr = 1); template inline void Swap (T & a, T & b) { T temp = a; a = b; b = temp; } /* template inline void swap (T & a, T & b) { T temp = a; a = b; b = temp; } */ /** INDEX is a typedef for (at least) 4-byte integer */ typedef int INDEX; /** BOOL is a typedef for boolean variables */ // typedef int BOOL; typedef int ELIND; typedef int PIND; class twoint { public: /// int i1, i2; /// twoint() {}; /// twoint(int ii1, int ii2) {i1 = ii1; i2 = ii2;} friend int operator== (const twoint& t1, const twoint& t2); /// void Swap() {int x = i1; i1 = i2; i2 = x;} void Sort() {if (i1 > i2) {Swap();}} }; inline int operator== (const twoint& t1, const twoint& t2) { return t1.i1 == t2.i1 && t1.i2 == t2.i2; } class threeint { public: /// int i1, i2, i3; /// threeint() {}; /// threeint(int ii1, int ii2, int ii3) {i1 = ii1; i2 = ii2; i3 = ii3;} }; /// class twodouble { public: /// double d1, d2; /// twodouble() {d1 = 0; d2 = 0;}; /// twodouble(double id1, double id2) {d1 = id1; d2 = id2;} /// void Swap() {double x = d1; d1 = d2; d2 = x;} }; class fourint { public: int i1, i2, i3, i4; fourint() {}; }; /// class INDEX_2; ostream & operator<<(ostream & s, const INDEX_2 & i2); class INDEX_2 { /// INDEX i[2]; public: /// INDEX_2 () { } /// INDEX_2 (INDEX ai1, INDEX ai2) { i[0] = ai1; i[1] = ai2; } /// INDEX_2 (const INDEX_2 & in2) { i[0] = in2.i[0]; i[1] = in2.i[1]; } /// int operator== (const INDEX_2 & in2) const { return i[0] == in2.i[0] && i[1] == in2.i[1]; } /// INDEX_2 Sort () { if (i[0] > i[1]) { INDEX hi = i[0]; i[0] = i[1]; i[1] = hi; } return *this; } static INDEX_2 Sort (int i1, int i2) { if (i1 > i2) return INDEX_2 (i2,i1); else return INDEX_2 (i1,i2); } /// INDEX & I1 () { return i[0]; } /// INDEX & I2 () { return i[1]; } /// INDEX & I (int j) { return i[j-1]; } /// const INDEX & I1 () const { return i[0]; } /// const INDEX & I2 () const { return i[1]; } /// const INDEX & I (int j) const { return i[j-1]; } /// int & operator[] (int j) { return i[j]; } /// const int & operator[] (int j) const { return i[j]; } /// friend ostream & operator<<(ostream & s, const INDEX_2 & i2); }; inline INDEX_2 Sort (const INDEX_2 & i2) { INDEX_2 tmp = i2; tmp.Sort(); return tmp; } inline bool operator< (const INDEX_2 ia, const INDEX_2 ib) { if (ia[0] < ib[0]) return true; if (ia[0] > ib[0]) return false; if (ia[1] < ib[1]) return true; return false; } /// class INDEX_3 { /// INDEX i[3]; public: /// INDEX_3 () { } /// INDEX_3 (INDEX ai1, INDEX ai2, INDEX ai3) { i[0] = ai1; i[1] = ai2; i[2] = ai3; } /// INDEX_3 (const INDEX_3 & in2) { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; } static INDEX_3 Sort (INDEX_3 i3) { return i3.Sort(); } static INDEX_3 Sort (int i1, int i2, int i3) { if (i1 > i2) Swap (i1, i2); if (i2 > i3) Swap (i2, i3); if (i1 > i2) Swap (i1, i2); return INDEX_3 (i1, i2, i3); } INDEX_3 Sort () { if (i[0] > i[1]) Swap (i[0], i[1]); if (i[1] > i[2]) Swap (i[1], i[2]); if (i[0] > i[1]) Swap (i[0], i[1]); return *this; } int operator== (const INDEX_3 & in2) const { return i[0] == in2.i[0] && i[1] == in2.i[1] && i[2] == in2.i[2];} /// INDEX & I1 () { return i[0]; } /// INDEX & I2 () { return i[1]; } /// INDEX & I3 () { return i[2]; } /// INDEX & I (int j) { return i[j-1]; } /// const INDEX & I1 () const { return i[0]; } /// const INDEX & I2 () const { return i[1]; } /// const INDEX & I3 () const { return i[2]; } /// const INDEX & I (int j) const { return i[j-1]; } /// int & operator[] (int j) { return i[j]; } /// const int & operator[] (int j) const { return i[j]; } /// friend ostream & operator<<(ostream & s, const INDEX_3 & i3); }; /// class INDEX_4 { /// INDEX i[4]; public: /// INDEX_4 () { } /// INDEX_4 (INDEX ai1, INDEX ai2, INDEX ai3, INDEX ai4) { i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; } /// INDEX_4 (const INDEX_4 & in2) { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; i[3] = in2.i[3]; } /// void Sort (); /// int operator== (const INDEX_4 & in2) const { return i[0] == in2.i[0] && i[1] == in2.i[1] && i[2] == in2.i[2] && i[3] == in2.i[3]; } /// INDEX & I1 () { return i[0]; } /// INDEX & I2 () { return i[1]; } /// INDEX & I3 () { return i[2]; } /// INDEX & I4 () { return i[3]; } /// INDEX & I (int j) { return i[j-1]; } /// const INDEX & I1 () const { return i[0]; } /// const INDEX & I2 () const { return i[1]; } /// const INDEX & I3 () const { return i[2]; } /// const INDEX & I4 () const { return i[3]; } /// const INDEX & I (int j) const { return i[j-1]; } /// int & operator[] (int j) { return i[j]; } /// const int & operator[] (int j) const { return i[j]; } /// friend ostream & operator<<(ostream & s, const INDEX_4 & i4); }; /// The sort preserves quads !!! class INDEX_4Q { /// INDEX i[4]; public: /// INDEX_4Q () { } /// INDEX_4Q (INDEX ai1, INDEX ai2, INDEX ai3, INDEX ai4) { i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; } /// INDEX_4Q (const INDEX_4Q & in2) { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; i[3] = in2.i[3]; } /// void Sort (); /// int operator== (const INDEX_4Q & in2) const { return i[0] == in2.i[0] && i[1] == in2.i[1] && i[2] == in2.i[2] && i[3] == in2.i[3]; } /// INDEX & I1 () { return i[0]; } /// INDEX & I2 () { return i[1]; } /// INDEX & I3 () { return i[2]; } /// INDEX & I4 () { return i[3]; } /// INDEX & I (int j) { return i[j-1]; } /// const INDEX & I1 () const { return i[0]; } /// const INDEX & I2 () const { return i[1]; } /// const INDEX & I3 () const { return i[2]; } /// const INDEX & I4 () const { return i[3]; } /// const INDEX & I (int j) const { return i[j-1]; } /// friend ostream & operator<<(ostream & s, const INDEX_4Q & i4); }; inline bool operator< (const INDEX_4 & a, const INDEX_4 & b) { for (int j = 0; j < 4; j++) { if (a[j] < b[j]) return true; if (a[j] > b[j]) return false; } return false; } /// template inline T min2 (T a, T b) { /// return (a < b) ? a : b; } /// template inline T max2 (T a, T b) { /// return (a > b) ? a : b; } /// template inline T min3 (T a, T b, T c) { /// return (a < b) ? (a < c) ? a : c : (b < c) ? b : c; } /// template inline T max3 (T a, T b, T c) { /// return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c); } /// /// template inline int sgn (T a) { return (a > 0) ? 1 : ( ( a < 0) ? -1 : 0 ); } /// template inline T sqr (const T a) { return a * a; } /// template inline T pow3 (const T a) { return a * a * a; } /* template void BubbleSort (int size, T * data); template void MergeSort (int size, T * data, T * help); */ } #endif netgen-6.2.1905/libsrc/general/table.hpp0000644000175000017500000001351313504650527016477 0ustar kurtkurt#ifndef FILE_TABLE #define FILE_TABLE /**************************************************************************/ /* File: table.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ namespace netgen { /// Base class to generic class TABLE. class BASE_TABLE { protected: /// class linestruct { public: /// int size; /// int maxsize; /// void * col; }; /// Array data; char * oneblock; public: /// BASE_TABLE (BASE_TABLE && table2) : data(move(table2.data)), oneblock(table2.oneblock) { table2.oneblock = nullptr; } BASE_TABLE (int size); /// BASE_TABLE (const FlatArray & entrysizes, int elemsize); /// ~BASE_TABLE (); BASE_TABLE & operator= (BASE_TABLE && table2) { data = move(table2.data); Swap (oneblock, table2.oneblock); return *this; } /// void SetSize (int size); /// void ChangeSize (int size); /// increment size of entry i by one, i is 0-based void IncSize (int i, int elsize) { if (data[i].size < data[i].maxsize) data[i].size++; else IncSize2 (i, elsize); } void SetEntrySize (int i, int newsize, int elsize) { if (newsize < data[i].maxsize) data[i].size = newsize; else SetEntrySize2 (i, newsize, elsize); } /// void IncSize2 (int i, int elsize); void SetEntrySize2 (int i, int newsize, int elsize); // void DecSize (int i); /// void AllocateElementsOneBlock (int elemsize); size_t AllocatedElements () const; size_t UsedElements () const; void SetElementSizesToMaxSizes (); void DoArchive (Archive & ar, int elemsize); }; /** Abstract data type TABLE. To an integer i in the range from 1 to size a set of elements of the generic type T is associated. */ template class TABLE : public BASE_TABLE { public: /// Creates table. inline TABLE () : BASE_TABLE(0) { ; } /// Creates table of size size inline TABLE (int size) : BASE_TABLE (size) { ; } /// Creates fixed maximal element size table inline TABLE (const FlatArray & entrysizes) : BASE_TABLE (FlatArray (entrysizes.Size(), const_cast(&entrysizes[BASE])), sizeof(T)) { ; } /// Changes Size of table to size, deletes data inline void SetSize (int size) { BASE_TABLE::SetSize (size); } /// Changes Size of table to size, keep data inline void ChangeSize (int size) { BASE_TABLE::ChangeSize (size); } /// Inserts element acont into row i, BASE-based. Does not test if already used. inline void Add (int i, const T & acont) { IncSize (i-BASE, sizeof (T)); ((T*)data[i-BASE].col)[data[i-BASE].size-1] = acont; } /// Inserts element acont into row i, 1-based. Does not test if already used. inline void Add1 (int i, const T & acont) { IncSize (i-1, sizeof (T)); ((T*)data.Elem(i).col)[data.Elem(i).size-1] = acont; } /// void IncSizePrepare (int i) { data[i-BASE].maxsize++; } /// Inserts element acont into row i. BASE-based. Does not test if already used, assumes to have enough memory inline void AddSave (int i, const T & acont) { ((T*)data[i-BASE].col)[data[i-BASE].size] = acont; data[i-BASE].size++; } inline void ParallelAdd (int i, const T & acont) { auto oldval = AsAtomic (data[i-BASE].size)++; ((T*)data[i-BASE].col)[oldval] = acont; } /// Inserts element acont into row i. 1-based. Does not test if already used, assumes to have mem inline void AddSave1 (int i, const T & acont) { ((T*)data.Elem(i).col)[data.Elem(i).size] = acont; data.Elem(i).size++; } /// Inserts element acont into row i. Does not test if already used. inline void AddEmpty (int i) { IncSize (i-BASE, sizeof (T)); } /** Set the nr-th element in the i-th row to acont. Does not check for overflow. */ inline void Set (int i, int nr, const T & acont) { ((T*)data.Get(i).col)[nr-1] = acont; } /** Returns the nr-th element in the i-th row. Does not check for overflow. */ inline const T & Get (int i, int nr) const { return ((T*)data.Get(i).col)[nr-1]; } /** Returns pointer to the first element in row i. */ inline const T * GetLine (int i) const { return ((const T*)data.Get(i).col); } /// Returns size of the table. inline int Size () const { return data.Size(); } /// Returns size of the i-th row. inline int EntrySize (int i) const { return data.Get(i).size; } /* inline void DecEntrySize (int i) { DecSize(i); } */ void AllocateElementsOneBlock () { BASE_TABLE::AllocateElementsOneBlock (sizeof(T)); } inline void PrintMemInfo (ostream & ost) const { int els = AllocatedElements(); ost << "table: allocaed " << els << " a " << sizeof(T) << " Byts = " << els * sizeof(T) << " bytes in " << Size() << " bags." << " used: " << UsedElements() << endl; } /// Access entry. FlatArray operator[] (int i) const { #ifdef DEBUG if (i-BASE < 0 || i-BASE >= data.Size()) cout << "table out of range, i = " << i << ", s = " << data.Size() << endl; #endif return FlatArray (data[i-BASE].size, (T*)data[i-BASE].col); } void DoArchive (Archive & ar) { BASE_TABLE::DoArchive(ar, sizeof(T)); } }; template inline ostream & operator<< (ostream & ost, const TABLE & table) { for (int i = BASE; i < table.Size()+BASE; i++) { ost << i << ": "; FlatArray row = table[i]; ost << "(" << row.Size() << ") "; for (int j = 0; j < row.Size(); j++) ost << row[j] << " "; ost << endl; } return ost; } } #endif netgen-6.2.1905/libsrc/general/gzstream.cpp0000644000175000017500000001202613504650527017235 0ustar kurtkurt// ============================================================================ // gzstream, C++ iostream classes wrapping the zlib compression library. // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ============================================================================ // // File : gzstream.C // Revision : $Revision: 1.7 $ // Revision_date : $Date: 2003/01/08 14:41:27 $ // Author(s) : Deepak Bandyopadhyay, Lutz Kettner // // Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ #include #include //#include "gzstream.h" //#include //#include // for memcpy #ifdef GZSTREAM_NAMESPACE namespace GZSTREAM_NAMESPACE { #endif // ---------------------------------------------------------------------------- // Internal classes to implement gzstream. See header file for user classes. // ---------------------------------------------------------------------------- // -------------------------------------- // class gzstreambuf: // -------------------------------------- gzstreambuf* gzstreambuf::open( const char* name, int open_mode) { if ( is_open()) return (gzstreambuf*)0; mode = open_mode; // no append nor read/write mode if ((mode & std::ios::ate) || (mode & std::ios::app) || ((mode & std::ios::in) && (mode & std::ios::out))) return (gzstreambuf*)0; char fmode[10]; char* fmodeptr = fmode; if ( mode & std::ios::in) *fmodeptr++ = 'r'; else if ( mode & std::ios::out) *fmodeptr++ = 'w'; *fmodeptr++ = 'b'; *fmodeptr = '\0'; file = gzopen( name, fmode); if (file == 0) return (gzstreambuf*)0; opened = 1; return this; } gzstreambuf * gzstreambuf::close() { if ( is_open()) { sync(); opened = 0; if ( gzclose( file) == Z_OK) return this; } return (gzstreambuf*)0; } int gzstreambuf::underflow() { // used for input buffer only if ( gptr() && ( gptr() < egptr())) return * reinterpret_cast( gptr()); if ( ! (mode & std::ios::in) || ! opened) return EOF; // Josuttis' implementation of inbuf int n_putback = gptr() - eback(); if ( n_putback > 4) n_putback = 4; memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback); int num = gzread( file, buffer+4, bufferSize-4); if (num <= 0) // ERROR or EOF return EOF; // reset buffer pointers setg( buffer + (4 - n_putback), // beginning of putback area buffer + 4, // read position buffer + 4 + num); // end of buffer // return next character return * reinterpret_cast( gptr()); } int gzstreambuf::flush_buffer() { // Separate the writing of the buffer from overflow() and // sync() operation. int w = pptr() - pbase(); if ( gzwrite( file, pbase(), w) != w) return EOF; pbump( -w); return w; } int gzstreambuf::overflow( int c) { // used for output buffer only if ( ! ( mode & std::ios::out) || ! opened) return EOF; if (c != EOF) { *pptr() = c; pbump(1); } if ( flush_buffer() == EOF) return EOF; return c; } int gzstreambuf::sync() { // Changed to use flush_buffer() instead of overflow( EOF) // which caused improper behavior with std::endl and flush(), // bug reported by Vincent Ricard. if ( pptr() && pptr() > pbase()) { if ( flush_buffer() == EOF) return -1; } return 0; } // -------------------------------------- // class gzstreambase: // -------------------------------------- gzstreambase::gzstreambase( const char* name, int mode) { init( &buf); open( name, mode); } gzstreambase::~gzstreambase() { buf.close(); } void gzstreambase::open( const char* name, int open_mode) { if ( ! buf.open( name, open_mode)) clear( rdstate() | std::ios::badbit); } void gzstreambase::close() { if ( buf.is_open()) if ( ! buf.close()) clear( rdstate() | std::ios::badbit); } #ifdef GZSTREAM_NAMESPACE } // namespace GZSTREAM_NAMESPACE #endif // ============================================================================ // EOF // netgen-6.2.1905/libsrc/general/array.cpp0000644000175000017500000000311713504650527016520 0ustar kurtkurt#ifndef FILE_NGSTD_ArrayCPP #define FILE_NGSTD_ArrayCPP // necessary for SGI ???? /**************************************************************************/ /* File: array.cpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /* Abstract data type Array */ #include #include #include namespace netgen { //using namespace netgen; #ifdef NONE void BASE_Array :: ReSize (int minsize, int elementsize) { cout << "resize, minsize = " << minsize << endl; if (inc == -1) throw Exception ("Try to resize fixed size array"); void * p; int nsize = (inc) ? allocsize + inc : 2 * allocsize; if (nsize < minsize) nsize = minsize; if (data) { p = new char [nsize * elementsize]; int mins = (nsize < actsize) ? nsize : actsize; memcpy (p, data, mins * elementsize); delete [] static_cast (data); data = p; } else { data = new char[nsize * elementsize]; } allocsize = nsize; cout << "resize done" << endl; } void BASE_Array :: RangeCheck (int i) const { if (i < 0 || i >= actsize) throw ArrayRangeException (); } void BASE_Array :: CheckNonEmpty () const { if (!actsize) { throw Exception ("Array should not be empty"); // cerr << "Array souldn't be empty"; } } #endif } #endif netgen-6.2.1905/libsrc/general/mpi_interface.cpp0000644000175000017500000000234513504650527020211 0ustar kurtkurt/**************************************************************************/ /* File: mpi_interface.cpp */ /* Author: Joachim Schoeberl */ /* Date: 04. Apr. 97 */ /**************************************************************************/ #include #include namespace netgen { #ifdef PARALLEL void MyMPI_SendCmd (const char * cmd) { int ntasks; MPI_Comm_size(MPI_COMM_WORLD, &ntasks); if(ntasks==1) return; for (int dest = 1; dest < ntasks; dest++) MPI_Send( (void*)cmd, (strlen(cmd)+1), MPI_CHAR, dest, MPI_TAG_CMD, MPI_COMM_WORLD); } string MyMPI_RecvCmd () { MPI_Status status; int flag; int size_of_msg = -1; MPI_Probe(0, MPI_TAG_CMD, MPI_COMM_WORLD, &status); MPI_Get_count(&status, MPI_CHAR, &size_of_msg); //char* buf = (char*)malloc(size_of_msg*sizeof(char)); char buf[100000]; //1MB should be enough... MPI_Recv( &buf, size_of_msg, MPI_CHAR, 0, MPI_TAG_CMD, MPI_COMM_WORLD, &status); return string(buf); } // #else // MPI_Comm MPI_COMM_WORLD, MPI_COMM_NULL; #endif } netgen-6.2.1905/libsrc/general/array.hpp0000644000175000017500000004176013504650527016533 0ustar kurtkurt#ifndef FILE_Array #define FILE_Array /**************************************************************************/ /* File: array.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ namespace netgen { // template class IndirectArray; template class IndirectArray; template class ArrayRangeIterator { TSIZE ind; public: ArrayRangeIterator (TSIZE ai) : ind(ai) { ; } ArrayRangeIterator operator++ (int) { return ind++; } ArrayRangeIterator operator++ () { return ++ind; } TSIZE operator*() const { return ind; } bool operator != (ArrayRangeIterator d2) { return ind != d2.ind; } }; /// a range of integers template class T_Range { T first, next; public: T_Range (T f, T n) : first(f), next(n) {;} T Size() const { return next-first; } T operator[] (T i) const { return first+i; } bool Contains (T i) const { return ((i >= first) && (i < next)); } ArrayRangeIterator begin() const { return first; } ArrayRangeIterator end() const { return next; } }; template class FlatArray; template class ArrayIterator { FlatArray ar; TIND ind; public: ArrayIterator (FlatArray aar, TIND ai) : ar(aar), ind(ai) { ; } ArrayIterator operator++ (int) { return ArrayIterator(ar, ind++); } ArrayIterator operator++ () { return ArrayIterator(ar, ++ind); } T operator*() const { return ar[ind]; } T & operator*() { return ar[ind]; } bool operator != (ArrayIterator d2) { return ind != d2.ind; } bool operator == (ArrayIterator d2) { return ind == d2.ind; } }; /** A simple array container. Array represented by size and data-pointer. No memory allocation and deallocation, must be provided by user. Helper functions for printing. Optional range check by macro RANGE_CHECK */ template class FlatArray { protected: /// the size size_t size; /// the data T * data; public: typedef T TELEM; /// provide size and memory FlatArray (size_t asize, T * adata) : size(asize), data(adata) { ; } /// the size size_t Size() const { return size; } ArrayIterator begin() const { return ArrayIterator (*this, BASE); } ArrayIterator end() const { return ArrayIterator (*this, BASE+size); } TIND Begin() const { return TIND(BASE); } TIND End() const { return TIND(size+BASE); } T_Range Range() const { return T_Range(BASE, size+BASE); } /// Access array. BASE-based T & operator[] (TIND i) const { #ifdef DEBUG if (i-BASE < 0 || i-BASE >= size) cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl; #endif return data[i-BASE]; } template IndirectArray > operator[] (const FlatArray & ia) const { return IndirectArray > (*this, ia); } /// Access array, one-based (old fashioned) T & Elem (int i) { #ifdef DEBUG if (i < 1 || i > size) cout << "Array<" << typeid(T).name() << ">::Elem out of range, i = " << i << ", s = " << size << endl; #endif return ((T*)data)[i-1]; } /// Access array, one-based (old fashioned) const T & Get (int i) const { #ifdef DEBUG if (i < 1 || i > size) cout << "Array<" << typeid(T).name() << ">::Get out of range, i = " << i << ", s = " << size << endl; #endif return ((const T*)data)[i-1]; } /// Access array, one-based (old fashioned) void Set (int i, const T & el) { #ifdef DEBUG if (i < 1 || i > size) cout << "Array<" << typeid(T).name() << ">::Set out of range, i = " << i << ", s = " << size << endl; #endif ((T*)data)[i-1] = el; } /// access first element T & First () const { return data[0]; } /// access last element. check by macro CHECK_RANGE T & Last () const { return data[size-1]; } /// Fill array with value val FlatArray & operator= (const T & val) { for (int i = 0; i < size; i++) data[i] = val; return *this; } /// takes range starting from position start of end-start elements const FlatArray Range (TIND start, TIND end) { return FlatArray (end-start, data+start); } /// first position of element elem, returns -1 if element not contained in array TIND Pos(const T & elem) const { TIND pos = -1; for(TIND i=0; pos==-1 && i < this->size; i++) if(elem == data[i]) pos = i; return pos; } /// does the array contain element elem ? bool Contains(const T & elem) const { return ( Pos(elem) >= 0 ); } }; // print array template inline ostream & operator<< (ostream & s, const FlatArray & a) { for (TIND i = a.Begin(); i < a.End(); i++) s << i << ": " << a[i] << endl; return s; } /** Dynamic array container. Array is an automatically increasing array container. The allocated memory doubles on overflow. Either the container takes care of memory allocation and deallocation, or the user provides one block of data. */ template class Array : public FlatArray { protected: using FlatArray::size; using FlatArray::data; /// physical size of array size_t allocsize; /// memory is responsibility of container bool ownmem; public: /// Generate array of logical and physical size asize explicit Array() : FlatArray (0, NULL) { allocsize = 0; ownmem = 1; } explicit Array(size_t asize) : FlatArray (asize, asize ? new T[asize] : nullptr) { allocsize = asize; ownmem = (asize == 0) ? 0 : 1; } /// Generate array in user data Array(TIND asize, T* adata) : FlatArray (asize, adata) { allocsize = asize; ownmem = 0; } /// array copy explicit Array (const Array & a2) : FlatArray (a2.Size(), a2.Size() ? new T[a2.Size()] : 0) { allocsize = size; ownmem = 1; for (TIND i = BASE; i < size+BASE; i++) (*this)[i] = a2[i]; } /// array move Array (Array && a2) : FlatArray (a2.size, a2.data), allocsize(a2.allocsize), ownmem(a2.ownmem) { a2.size = 0; a2.data = nullptr; a2.allocsize = 0; a2.ownmem = false; } /// if responsible, deletes memory ~Array() { if (ownmem) delete [] data; } /// Change logical size. If necessary, do reallocation. Keeps contents. void SetSize(size_t nsize) { if (nsize > allocsize) ReSize (nsize); size = nsize; } /// Change physical size. Keeps logical size. Keeps contents. void SetAllocSize (size_t nallocsize) { if (nallocsize > allocsize) ReSize (nallocsize); } /// Add element at end of array. reallocation if necessary. void Append (const T & el) { if (size == allocsize) ReSize (size+1); data[size] = el; size++; // return size; } template void Append (FlatArray a2) { if (size+a2.Size() > allocsize) ReSize (size+a2.Size()); for (int i = 0; i < a2.Size(); i++) data[size+i] = a2[i+B2]; size += a2.Size(); } /// Delete element i (0-based). Move last element to position i. void Delete (TIND i) { #ifdef CHECK_Array_RANGE RangeCheck (i+1); #endif data[i] = std::move(data[size-1]); size--; // DeleteElement (i+1); } /// Delete element i (1-based). Move last element to position i. void DeleteElement (TIND i) { #ifdef CHECK_Array_RANGE RangeCheck (i); #endif data[i-1] = std::move(data[size-1]); size--; } /// Delete last element. void DeleteLast () { size--; } /// Deallocate memory void DeleteAll () { if (ownmem) delete [] data; data = 0; size = allocsize = 0; } /// Fill array with val Array & operator= (const T & val) { FlatArray::operator= (val); return *this; } /// array copy Array & operator= (const Array & a2) { SetSize (a2.Size()); for (TIND i (BASE); i < size+BASE; i++) (*this)[i] = a2[i]; return *this; } /// array copy Array & operator= (const FlatArray & a2) { SetSize (a2.Size()); for (TIND i = BASE; i < size+BASE; i++) (*this)[i] = a2[i]; return *this; } Array & operator= (Array && a2) { Swap (data, a2.data); Swap (size, a2.size); Swap (allocsize, a2.allocsize); Swap (ownmem, a2.ownmem); return *this; } T * Release() { ownmem = false; return data; } // Only provide this function if T is archivable template auto DoArchive(Archive& archive) -> typename std::enable_if, void>::type { if(archive.Output()) archive << size; else { size_t s; archive & s; SetSize(s); } archive.Do(data, size); } private: /// resize array, at least to size minsize. copy contents void ReSize (size_t minsize) { size_t nsize = 2 * allocsize; if (nsize < minsize) nsize = minsize; if (data) { T * p = new T[nsize]; size_t mins = (nsize < size) ? nsize : size; // memcpy (p, data, mins * sizeof(T)); #if defined(__GNUG__) && __GNUC__ < 5 && !defined(__clang__) for (size_t i = 0; i < mins; i++) p[i] = move(data[i]); #else if (std::is_trivially_copyable::value) memcpy (p, data, sizeof(T)*mins); else for (size_t i = 0; i < mins; i++) p[i] = move(data[i]); #endif if (ownmem) delete [] data; ownmem = 1; data = p; } else { data = new T[nsize]; ownmem = 1; } allocsize = nsize; } }; template class ArrayMem : public Array { using Array::size; using Array::data; using Array::ownmem; T mem[S]; // Intel C++ calls dummy constructor // char mem[S*sizeof(T)]; // double mem[(S*sizeof(T)+7) / 8]; public: /// Generate array of logical and physical size asize explicit ArrayMem(size_t asize = 0) : Array (S, static_cast (static_cast(&mem[0]))) { size = asize; if (asize > S) { data = new T[asize]; ownmem = 1; } // SetSize (asize); } ArrayMem & operator= (const T & val) { Array::operator= (val); return *this; } /// array copy ArrayMem & operator= (const FlatArray & a2) { this->SetSize (a2.Size()); for (size_t i = 0; i < size; i++) (*this)[i] = a2[i]; return *this; } }; /* template class IndirectArray { const FlatArray & array; const FlatArray & ia; public: IndirectArray (const FlatArray & aa, const FlatArray & aia) : array(aa), ia(aia) { ; } int Size() const { return ia.Size(); } const T & operator[] (int i) const { return array[ia[i]]; } }; */ template class IndirectArray { const TA1 & array; const TA2 & ia; public: IndirectArray (const TA1 & aa, const TA2 & aia) : array(aa), ia(aia) { ; } int Size() const { return ia.Size(); } int Begin() const { return ia.Begin(); } int End() const { return ia.End(); } const typename TA1::TELEM & operator[] (int i) const { return array[ia[i]]; } }; template inline ostream & operator<< (ostream & s, const IndirectArray & ia) { for (int i = ia.Begin(); i < ia.End(); i++) s << i << ": " << ia[i] << endl; return s; } /* /// template class MoveableArray { int size; int allocsize; DynamicMem data; public: MoveableArray() { size = allocsize = 0; data.SetName ("MoveableArray"); } MoveableArray(int asize) : size(asize), allocsize(asize), data(asize) { ; } ~MoveableArray () { ; } int Size() const { return size; } void SetSize(int nsize) { if (nsize > allocsize) { data.ReAlloc (nsize); allocsize = nsize; } size = nsize; } void SetAllocSize (int nallocsize) { data.ReAlloc (nallocsize); allocsize = nallocsize; } /// T & operator[] (int i) { return ((T*)data)[i-BASE]; } /// const T & operator[] (int i) const { return ((const T*)data)[i-BASE]; } /// T & Elem (int i) { return ((T*)data)[i-1]; } /// const T & Get (int i) const { return ((const T*)data)[i-1]; } /// void Set (int i, const T & el) { ((T*)data)[i-1] = el; } /// T & Last () { return ((T*)data)[size-1]; } /// const T & Last () const { return ((const T*)data)[size-1]; } /// int Append (const T & el) { if (size == allocsize) { SetAllocSize (2*allocsize+1); } ((T*)data)[size] = el; size++; return size; } /// void Delete (int i) { DeleteElement (i+1); } /// void DeleteElement (int i) { ((T*)data)[i-1] = ((T*)data)[size-1]; size--; } /// void DeleteLast () { size--; } /// void DeleteAll () { size = allocsize = 0; data.Free(); } /// void PrintMemInfo (ostream & ost) const { ost << Size() << " elements of size " << sizeof(T) << " = " << Size() * sizeof(T) << endl; } MoveableArray & operator= (const T & el) { for (int i = 0; i < size; i++) ((T*)data)[i] = el; return *this; } MoveableArray & Copy (const MoveableArray & a2) { SetSize (a2.Size()); for (int i = 0; i < this->size; i++) data[i] = a2.data[i]; return *this; } /// array copy MoveableArray & operator= (const MoveableArray & a2) { return Copy(a2); } void SetName (const char * aname) { data.SetName(aname); } private: /// //MoveableArray & operator= (MoveableArray &); //??? /// //MoveableArray (const MoveableArray &); //??? }; template inline ostream & operator<< (ostream & ost, MoveableArray & a) { for (int i = 0; i < a.Size(); i++) ost << i << ": " << a[i] << endl; return ost; } */ /// bubble sort array template inline void BubbleSort (const FlatArray & data) { for (int i = 0; i < data.Size(); i++) for (int j = i+1; j < data.Size(); j++) if (data[i] > data[j]) { T hv = data[i]; data[i] = data[j]; data[j] = hv; } } /// bubble sort array template inline void BubbleSort (FlatArray & data, FlatArray & slave) { for (int i = 0; i < data.Size(); i++) for (int j = i+1; j < data.Size(); j++) if (data[i] > data[j]) { T hv = data[i]; data[i] = data[j]; data[j] = hv; S hvs = slave[i]; slave[i] = slave[j]; slave[j] = hvs; } } template void QuickSortRec (FlatArray & data, FlatArray & slave, int left, int right) { int i = left; int j = right; T midval = data[(left+right)/2]; do { while (data[i] < midval) i++; while (midval < data[j]) j--; if (i <= j) { Swap (data[i], data[j]); Swap (slave[i], slave[j]); i++; j--; } } while (i <= j); if (left < j) QuickSortRec (data, slave, left, j); if (i < right) QuickSortRec (data, slave, i, right); } template void QuickSort (FlatArray & data, FlatArray & slave) { if (data.Size() > 1) QuickSortRec (data, slave, 0, data.Size()-1); } template void Intersection (const FlatArray & in1, const FlatArray & in2, Array & out) { out.SetSize(0); for(int i=0; i void Intersection (const FlatArray & in1, const FlatArray & in2, const FlatArray & in3, Array & out) { out.SetSize(0); for(int i=0; i bablocks; public: /// BlockAllocator (unsigned asize, unsigned ablocks = 100); /// ~BlockAllocator (); /// void * Alloc (); /* { if (!freelist) Alloc2(); void * p = freelist; // freelist = *(void**)freelist; freelist = *static_cast (freelist); return p; } */ /// void Free (void * p); /* { if (!bablocks.Size()) return; *(void**)p = freelist; freelist = p; } */ private: // void Alloc2 (); }; } #endif netgen-6.2.1905/libsrc/general/flags.hpp0000644000175000017500000000575613504650527016516 0ustar kurtkurt#ifndef FILE_FLAGS #define FILE_FLAGS /**************************************************************************/ /* File: flags.hh */ /* Author: Joachim Schoeberl */ /* Date: 10. Oct. 96 */ /**************************************************************************/ namespace netgen { /** Flag - Table. A flag table maintains string variables, numerical variables and boolean flags. */ class Flags { /// SymbolTable strflags; /// SymbolTable numflags; /// SymbolTable defflags; /// SymbolTable*> strlistflags; /// SymbolTable*> numlistflags; public: /// DLL_HEADER Flags (); /// DLL_HEADER ~Flags (); /// Deletes all flags DLL_HEADER void DeleteFlags (); /// Sets string flag, overwrite if exists DLL_HEADER void SetFlag (const char * name, const char * val); /// Sets numerical flag, overwrite if exists DLL_HEADER void SetFlag (const char * name, double val); /// Sets boolean flag DLL_HEADER void SetFlag (const char * name); /// Sets string arary flag DLL_HEADER void SetFlag (const char * name, const Array & val); /// Sets double array flag DLL_HEADER void SetFlag (const char * name, const Array & val); /// Save flags to file DLL_HEADER void SaveFlags (const char * filename) const; /// write flags to stream DLL_HEADER void PrintFlags (ostream & ost) const; /// Load flags from file DLL_HEADER void LoadFlags (const char * filename); /// set flag of form -name=hello -val=0.5 -defined DLL_HEADER void SetCommandLineFlag (const char * st); /// Returns string flag, default value if not exists DLL_HEADER const char * GetStringFlag (const char * name, const char * def) const; /// Returns numerical flag, default value if not exists DLL_HEADER double GetNumFlag (const char * name, double def) const; /// Returns address of numerical flag, null if not exists DLL_HEADER const double * GetNumFlagPtr (const char * name) const; /// Returns address of numerical flag, null if not exists DLL_HEADER double * GetNumFlagPtr (const char * name); /// Returns boolean flag DLL_HEADER bool GetDefineFlag (const char * name) const; /// Returns string list flag, empty array if not exist DLL_HEADER const Array & GetStringListFlag (const char * name) const; /// Returns num list flag, empty array if not exist DLL_HEADER const Array & GetNumListFlag (const char * name) const; /// Test, if string flag is defined DLL_HEADER bool StringFlagDefined (const char * name) const; /// Test, if num flag is defined DLL_HEADER bool NumFlagDefined (const char * name) const; /// Test, if string list flag is defined DLL_HEADER bool StringListFlagDefined (const char * name) const; /// Test, if num list flag is defined DLL_HEADER bool NumListFlagDefined (const char * name) const; }; } #endif netgen-6.2.1905/libsrc/general/autoptr.hpp0000644000175000017500000000170113504650527017102 0ustar kurtkurt#ifndef FILE_AUTOPTR #define FILE_AUTOPTR /**************************************************************************/ /* File: autoptr.hpp */ /* Author: STL, Joachim Schoeberl */ /* Date: 29. Dec. 02 */ /**************************************************************************/ namespace netgen { /* template class AutoPtr { private: T * ptr; public: typedef T* pT; explicit AutoPtr (T * p = 0) { ptr = p; } ~AutoPtr () { delete ptr; } T & operator*() const { return *ptr; } T* operator->() const { return ptr; } T *& Ptr() { return ptr; } T * Ptr() const { return ptr; } void Reset(T * p = 0) { if (p != ptr) { delete ptr; ptr = p; } } operator bool () { return ptr != 0; } private: AutoPtr (AutoPtr &) { ; } AutoPtr & operator= (AutoPtr &) { ; } }; */ } #endif netgen-6.2.1905/libsrc/general/table.cpp0000644000175000017500000001214413504650527016471 0ustar kurtkurt/**************************************************************************/ /* File: table.cpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /* Abstract data type TABLE */ #include #include namespace netgen { //using namespace netgen; BASE_TABLE :: BASE_TABLE (int size) : data(size) { for (int i = 0; i < size; i++) { data[i].maxsize = 0; data[i].size = 0; data[i].col = NULL; } oneblock = NULL; } BASE_TABLE :: BASE_TABLE (const FlatArray & entrysizes, int elemsize) : data(entrysizes.Size()) { size_t cnt = 0; size_t n = entrysizes.Size(); for (size_t i = 0; i < n; i++) cnt += entrysizes[i]; oneblock = new char[elemsize * cnt]; // mem_total_alloc_table += elemsize * cnt; cnt = 0; for (size_t i = 0; i < n; i++) { data[i].maxsize = entrysizes[i]; data[i].size = 0; data[i].col = &oneblock[elemsize * cnt]; cnt += entrysizes[i]; } } BASE_TABLE :: ~BASE_TABLE () { if (oneblock) delete [] oneblock; else { for (int i = 0; i < data.Size(); i++) delete [] (char*)data[i].col; } } void BASE_TABLE :: SetSize (int size) { for (int i = 0; i < data.Size(); i++) delete [] (char*)data[i].col; data.SetSize(size); for (int i = 0; i < size; i++) { data[i].maxsize = 0; data[i].size = 0; data[i].col = NULL; } } void BASE_TABLE :: ChangeSize (int size) { int oldsize = data.Size(); if (size == oldsize) return; if (size < oldsize) for (int i = size; i < oldsize; i++) delete [] (char*)data[i].col; data.SetSize(size); for (int i = oldsize; i < size; i++) { data[i].maxsize = 0; data[i].size = 0; data[i].col = NULL; } } void BASE_TABLE :: IncSize2 (int i, int elsize) { #ifdef DEBUG if (i < 0 || i >= data.Size()) { MyError ("BASE_TABLE::Inc: Out of range"); return; } #endif linestruct & line = data[i]; if (line.size == line.maxsize) { void * p = new char [(line.maxsize+5) * elsize]; memcpy (p, line.col, line.maxsize * elsize); delete [] (char*)line.col; line.col = p; line.maxsize += 5; } line.size++; } void BASE_TABLE :: SetEntrySize2 (int i, int newsize, int elsize) { linestruct & line = data[i]; if (newsize > line.maxsize) { void * p = new char [newsize * elsize]; memcpy (p, line.col, min2 (newsize, line.size) * elsize); delete [] (char*)line.col; line.col = p; } line.size = newsize; } /* void BASE_TABLE :: DecSize (int i) { #ifdef DEBUG if (i < 0 || i >= data.Size()) { MyError ("BASE_TABLE::Dec: Out of range"); return; } #endif linestruct & line = data[i]; #ifdef DEBUG if (line.size == 0) { MyError ("BASE_TABLE::Dec: EntrySize < 0"); return; } #endif line.size--; } */ void BASE_TABLE :: AllocateElementsOneBlock (int elemsize) { size_t cnt = 0; size_t n = data.Size(); for (size_t i = 0; i < n; i++) cnt += data[i].maxsize; oneblock = new char[elemsize * cnt]; cnt = 0; for (size_t i = 0; i < n; i++) { data[i].size = 0; data[i].col = &oneblock[elemsize * cnt]; cnt += data[i].maxsize; } } size_t BASE_TABLE :: AllocatedElements () const { size_t els = 0; for (size_t i = 0; i < data.Size(); i++) els += data[i].maxsize; return els; } size_t BASE_TABLE :: UsedElements () const { size_t els = 0; for (size_t i = 0; i < data.Size(); i++) els += data[i].size; return els; } void BASE_TABLE :: SetElementSizesToMaxSizes () { for (int i = 0; i < data.Size(); i++) data[i].size = data[i].maxsize; } void BASE_TABLE :: DoArchive (Archive & ar, int elemsize) { if (ar.Output()) { size_t entries = 0, size = data.Size(); for (size_t i = 0; i < data.Size(); i++) entries += data[i].size; ar & size & entries; for (size_t i = 0; i < data.Size(); i++) { ar & data[i].size; ar.Do ((unsigned char*)data[i].col, data[i].size*elemsize); /* for (size_t j = 0; j < data[i].size*elemsize; j++) ar & ((unsigned char*) data[i].col)[j]; cout << "write " << data[i].size*elemsize << " chars" << endl; */ } } else { size_t entries, size; ar & size & entries; data.SetSize(size); oneblock = new char [entries*elemsize]; size_t cnt = 0; for (size_t i = 0; i < size; i++) { ar & data[i].size; data[i].col = oneblock+cnt; data[i].maxsize = data[i].size; ar.Do ((unsigned char*)(oneblock+cnt), data[i].size*elemsize); cnt += data[i].size*elemsize; } } } } netgen-6.2.1905/libsrc/general/optmem.cpp0000644000175000017500000000353113504650527016703 0ustar kurtkurt/**************************************************************************/ /* File: optmem.cpp */ /* Author: Joachim Schoeberl */ /* Date: 04. Apr. 97 */ /**************************************************************************/ /* Abstract data type Array */ #include #include namespace netgen { static mutex block_allocator_mutex; BlockAllocator :: BlockAllocator (unsigned asize, unsigned ablocks) : bablocks (0) { if (asize < sizeof(void*)) asize = sizeof(void*); size = asize; blocks = ablocks; freelist = NULL; } BlockAllocator :: ~BlockAllocator () { // cout << "****************** delete BlockAllocator " << endl; for (int i = 0; i < bablocks.Size(); i++) delete [] bablocks[i]; bablocks.SetSize(0); } void * BlockAllocator :: Alloc () { void * p; { lock_guard guard(block_allocator_mutex); // return new char[size]; if (!freelist) { // cout << "freelist = " << freelist << endl; // cout << "BlockAlloc: " << size*blocks << endl; char * hcp = new char [size * blocks]; bablocks.Append (hcp); bablocks.Last() = hcp; for (unsigned i = 0; i < blocks-1; i++) *(void**)&(hcp[i * size]) = &(hcp[ (i+1) * size]); *(void**)&(hcp[(blocks-1)*size]) = NULL; freelist = hcp; } p = freelist; freelist = *(void**)freelist; } return p; } void BlockAllocator :: Free (void * p) { { lock_guard guard(block_allocator_mutex); if (bablocks.Size()) { *(void**)p = freelist; freelist = p; } } } } netgen-6.2.1905/libsrc/general/dynamicmem.cpp0000644000175000017500000000766313504650527017537 0ustar kurtkurt#include using namespace std; namespace netgen { BaseDynamicMem * BaseDynamicMem::first = 0; BaseDynamicMem * BaseDynamicMem::last = 0; BaseDynamicMem :: BaseDynamicMem () { prev = last; next = 0; if (last) last->next = this; last = this; if (!first) first = this; size = 0; ptr = 0; name = 0; } BaseDynamicMem :: ~BaseDynamicMem () { Free(); if (next) next->prev = prev; else last = prev; if (prev) prev->next = next; else first = next; delete [] name; } void BaseDynamicMem :: SetName (const char * aname) { delete [] name; name = NULL; if (aname) { name = new char[strlen(aname)+1]; strcpy (name, aname); } } void BaseDynamicMem :: Alloc (size_t s) { size = s; ptr = new char[s]; if (!ptr) { cerr << "BaseynamicMem, cannot allocate " << s << " bytes" << endl; Print (); throw ("BaseDynamicMem::Alloc: out of memory"); } // ptr = (char*)malloc (s); // ptr = (char*) _mm_malloc (s,16); } void BaseDynamicMem :: ReAlloc (size_t s) { if (size == s) return; char * old = ptr; ptr = new char[s]; if (!ptr) { cerr << "BaseynamicMem, cannot Reallocate " << s << " bytes" << endl; Print (); throw ("BaseDynamicMem::Alloc: out of memory"); } // ptr = (char*)malloc(s); // ptr = (char*) _mm_malloc (s,16); memmove (ptr, old, (s < size) ? s : size); delete [] old; // free (old); // _mm_free (old); size = s; } void BaseDynamicMem :: Free () { delete [] ptr; // free (ptr); // _mm_free (ptr); ptr = 0; } void BaseDynamicMem :: Swap (BaseDynamicMem & m2) { size_t hi; char * cp; hi = size; size = m2.size; m2.size = hi; cp = ptr; ptr = m2.ptr; m2.ptr = cp; cp = name; name = m2.name; m2.name = cp; } void BaseDynamicMem :: Print () { cout << "****************** Dynamic Mem Report ****************" << endl; BaseDynamicMem * p = first; size_t mem = 0; int cnt = 0; while (p) { mem += p->size; cnt++; cout << setw(10) << p->size << " Bytes"; cout << ", addr = " << (void*)p->ptr; if (p->name) cout << " in block " << p->name; cout << endl; p = p->next; } if (mem > 100000000) cout << "memory in dynamic memory: " << mem/1048576 << " MB" << endl; else if (mem > 100000) cout << "memory in dynamic memory: " << mem/1024 << " kB" << endl; else cout << "memory in dynamic memory: " << mem << " Bytes" << endl; cout << "number of blocks: " << cnt << endl; // cout << "******************************************************" << endl; } #ifdef __INTEL_COMPILER #pragma warning(push) #pragma warning(disable:1684) #endif void BaseDynamicMem :: GetUsed (int nr, char * ch) { BaseDynamicMem * p = first; for (int i = 0; i < nr; i++) ch[i] = '0'; while (p) { long unsigned hptr = (long unsigned) (p->ptr); // uintptr_t hptr = reinterpret_cast(p->ptr); //?? hptr /= (1024*1024); hptr /= (4096/nr); size_t blocks = p->size / (1024*1024); blocks /= (4096/nr); // cout << "ptr = " << (void*)(p->ptr) << ", size = " << p->size << ", hptr = " << hptr << " blocks = " << blocks << endl; for (size_t i = 0; i <= blocks; i++) ch[hptr+i] = '1'; p = p->next; } { /* BaseMoveableMem * pm = BaseMoveableMem::first; while (pm) { long unsigned hptr = (long unsigned) pm->ptr; // uintptr_t hptr = reinterpret_cast(pm->ptr); hptr /= (1024*1024); hptr /= (4096/nr); size_t blocks = pm->size / (1024*1024); blocks /= (4096/nr); // cout << "moveable, ptr = " << (void*)(pm->ptr) << ", size = " << pm->size << ", hptr = " << hptr << " blocks = " << blocks << endl; for (size_t i = 0; i <= blocks; i++) ch[hptr+i] = '1'; pm = pm->next; } */ } } #ifdef __INTEL_COMPILER #pragma warning(pop) #endif } netgen-6.2.1905/libsrc/general/stack.hpp0000644000175000017500000000317413504650527016517 0ustar kurtkurt#ifndef FILE_STACK #define FILE_STACK /*****************************************************************************/ /* File: stack.hh */ /* Author: Wolfram Muehlhuber */ /* Date: September 98 */ /*****************************************************************************/ /* Stack class, based on a resizable array */ // #include "array.hpp" namespace netgen { /// template class STACK { public: /// inline STACK (INDEX asize = 0, INDEX ainc = 0); /// inline ~STACK (); /// inline void Push (const T & el); /// inline T & Pop (); /// const inline T & Top () const; /// inline int IsEmpty () const; /// inline void MakeEmpty (); private: /// Array elems; /// INDEX size; }; /* Stack class, based on a resizable array */ template inline STACK :: STACK (INDEX asize, INDEX ainc) : elems(asize, ainc) { size = 0; } template inline STACK :: ~STACK () { ; } template inline void STACK :: Push (const T & el) { if (size < elems.Size()) elems.Elem(++size) = el; else { elems.Append(el); size++; } } template inline T & STACK :: Pop () { return elems.Elem(size--); } template const inline T & STACK :: Top () const { return elems.Get(size); } template inline int STACK :: IsEmpty () const { return (size == 0); } template inline void STACK :: MakeEmpty () { size = 0; } } #endif netgen-6.2.1905/libsrc/general/parthreads.cpp0000644000175000017500000000132513504650527017536 0ustar kurtkurt/**************************************************************************/ /* File: parthreads.cpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ #include #include /* namespace netgen { using namespace netgen; #ifdef WIN32 NgLock :: NgLock (NgMutex & mut) : sl(&mut.cs) { ; } void NgLock :: Lock () { sl.Lock(); } void NgLock :: UnLock () { sl.Unlock(); } #else #endif } */ netgen-6.2.1905/libsrc/general/sort.cpp0000644000175000017500000000321713504650527016372 0ustar kurtkurt/**************************************************************************/ /* File: sort.cc */ /* Author: Joachim Schoeberl */ /* Date: 07. Jan. 00 */ /**************************************************************************/ /* Sorting */ #include #include #include namespace netgen { void Sort (const Array & values, Array & order) { int n = values.Size(); int i, j; order.SetSize (n); for (i = 1; i <= n; i++) order.Elem(i) = i; for (i = 1; i <= n-1; i++) for (j = 1; j <= n-1; j++) if (values.Get(order.Elem(j)) > values.Get(order.Elem(j+1))) { Swap (order.Elem(j), order.Elem(j+1)); } } void QuickSortRec (const Array & values, Array & order, int left, int right) { int i, j; double midval; i = left; j = right; midval = values.Get(order.Get((i+j)/2)); do { while (values.Get(order.Get(i)) < midval) i++; while (midval < values.Get(order.Get(j))) j--; if (i <= j) { Swap (order.Elem(i), order.Elem(j)); i++; j--; } } while (i <= j); if (left < j) QuickSortRec (values, order, left, j); if (i < right) QuickSortRec (values, order, i, right); } void QuickSort (const Array & values, Array & order) { int i, n = values.Size(); order.SetSize (n); for (i = 1; i <= n; i++) order.Elem(i) = i; QuickSortRec (values, order, 1, order.Size()); } } netgen-6.2.1905/libsrc/general/myadt.hpp0000644000175000017500000000216013504650527016522 0ustar kurtkurt#ifndef FILE_MYADT #define FILE_MYADT /**************************************************************************/ /* File: myadt.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /* include for all abstract data types */ #include "../include/mystdlib.h" #include "../include/mydefs.hpp" #include "../core/ngcore.hpp" namespace netgen { using namespace ngcore; using NgException = Exception; } #include "parthreads.hpp" // #include "moveablemem.hpp" #include "dynamicmem.hpp" #include "template.hpp" #include "array.hpp" #include "table.hpp" #include "hashtabl.hpp" #include "bitarray.hpp" #include "flags.hpp" #include "spbita2d.hpp" #include "seti.hpp" #include "optmem.hpp" #include "autoptr.hpp" #include "sort.hpp" #include "stack.hpp" #include "mystring.hpp" #include "mpi_interface.hpp" #include "netgenout.hpp" #include "gzstream.h" #include "ngsimd.hpp" #endif netgen-6.2.1905/libsrc/general/ngpython.hpp0000644000175000017500000000320613504650527017254 0ustar kurtkurt#ifdef NG_PYTHON #include #include #include #include namespace py = pybind11; #include #include template py::array MoveToNumpy(std::vector& vec) { auto newvec = new std::vector(); std::swap(*newvec, vec); auto capsule = py::capsule(newvec, [](void *v) { delete reinterpret_cast*>(v); }); return py::array(newvec->size(), newvec->data(), capsule); } namespace PYBIND11_NAMESPACE { template bool CheckCast( py::handle obj ) { try{ obj.cast(); return true; } catch (py::cast_error &e) { return false; } } template struct extract { py::handle obj; extract( py::handle aobj ) : obj(aobj) {} bool check() { return CheckCast(obj); } T operator()() { return obj.cast(); } }; } struct NGDummyArgument {}; inline void NOOP_Deleter(void *) { ; } namespace netgen { ////////////////////////////////////////////////////////////////////// // Lambda to function pointer conversion template struct function_traits : public function_traits {}; template struct function_traits { typedef ReturnType (*pointer)(Args...); typedef ReturnType return_type; }; template typename function_traits::pointer FunctionPointer (const Function& lambda) { return static_cast::pointer>(lambda); } } // namespace netgen #endif netgen-6.2.1905/libsrc/general/dynamicmem.hpp0000644000175000017500000000360713504650527017536 0ustar kurtkurt#ifndef FILE_DYNAMICMEM #define FILE_DYNAMICMEM /**************************************************************************/ /* File: dynamicmem.hpp */ /* Author: Joachim Schoeberl */ /* Date: 12. Feb. 2003 */ /**************************************************************************/ namespace netgen { class BaseDynamicMem { private: static BaseDynamicMem *first, *last; BaseDynamicMem *prev, *next; size_t size; char * ptr; char * name; protected: BaseDynamicMem (); ~BaseDynamicMem (); void Alloc (size_t s); void ReAlloc (size_t s); void Free (); // char * Ptr() { return ptr; } char * Ptr() const { return ptr; } void Swap (BaseDynamicMem & m2); public: void SetName (const char * aname); static void Print (); static void GetUsed (int nr, char * ch); }; template class DynamicMem : public BaseDynamicMem { public: DynamicMem () : BaseDynamicMem () { ; } DynamicMem (size_t s) : BaseDynamicMem () { Alloc (s); } void Alloc (size_t s) { BaseDynamicMem::Alloc (sizeof(T) * s); } void ReAlloc (size_t s) { BaseDynamicMem::ReAlloc (sizeof(T) * s); } void Free () { BaseDynamicMem::Free (); } /* const T * Ptr() const { return reinterpret_cast (BaseDynamicMem::Ptr()); } */ const T * Ptr() { return reinterpret_cast (BaseDynamicMem::Ptr()); } /* operator const T* () const { return reinterpret_cast (BaseDynamicMem::Ptr()); } */ operator T* () const { return reinterpret_cast (BaseDynamicMem::Ptr()); } void Swap (DynamicMem & m2) { BaseDynamicMem::Swap (m2); } protected: DynamicMem (const DynamicMem & m); DynamicMem & operator= (const DynamicMem & m); }; } #endif netgen-6.2.1905/libsrc/general/gzstream.h0000644000175000017500000001104713504650527016704 0ustar kurtkurt// ============================================================================ // gzstream, C++ iostream classes wrapping the zlib compression library. // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ============================================================================ // // File : gzstream.h // Revision : $Revision: 1.5 $ // Revision_date : $Date: 2002/04/26 23:30:15 $ // Author(s) : Deepak Bandyopadhyay, Lutz Kettner // // Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ #ifndef GZSTREAM_H #define GZSTREAM_H 1 // standard C++ with new header file names and std:: namespace #include #include #include #ifdef GZSTREAM_NAMESPACE namespace GZSTREAM_NAMESPACE { #endif // ---------------------------------------------------------------------------- // Internal classes to implement gzstream. See below for user classes. // ---------------------------------------------------------------------------- class gzstreambuf : public std::streambuf { private: static const int bufferSize = 47+256; // size of data buff // totals 512 bytes under g++ for igzstream at the end. gzFile file; // file handle for compressed file char buffer[bufferSize]; // data buffer char opened; // open/close state of stream int mode; // I/O mode int flush_buffer(); public: gzstreambuf() : opened(0) { setp( buffer, buffer + (bufferSize-1)); setg( buffer + 4, // beginning of putback area buffer + 4, // read position buffer + 4); // end position // ASSERT: both input & output capabilities will not be used together } int is_open() { return opened; } gzstreambuf* open( const char* name, int open_mode); gzstreambuf* close(); ~gzstreambuf() { close(); } virtual int overflow( int c = EOF); virtual int underflow(); virtual int sync(); }; class gzstreambase : virtual public std::ios { protected: gzstreambuf buf; public: gzstreambase() { init(&buf); } DLL_HEADER gzstreambase( const char* name, int open_mode); DLL_HEADER ~gzstreambase(); void open( const char* name, int open_mode); void close(); gzstreambuf* rdbuf() { return &buf; } }; // ---------------------------------------------------------------------------- // User classes. Use igzstream and ogzstream analogously to ifstream and // ofstream respectively. They read and write files based on the gz* // function interface of the zlib. Files are compatible with gzip compression. // ---------------------------------------------------------------------------- class DLL_HEADER igzstream : public gzstreambase, public std::istream { public: igzstream() : std::istream( &buf) {} igzstream( const char* name, int open_mode = std::ios::in) : gzstreambase( name, open_mode), std::istream( &buf) {} gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } void open( const char* name, int open_mode = std::ios::in) { gzstreambase::open( name, open_mode); } }; class DLL_HEADER ogzstream : public gzstreambase, public std::ostream { public: ogzstream() : std::ostream( &buf) {} ogzstream( const char* name, int mode = std::ios::out) : gzstreambase( name, mode), std::ostream( &buf) {} gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } void open( const char* name, int open_mode = std::ios::out) { gzstreambase::open( name, open_mode); } }; #ifdef GZSTREAM_NAMESPACE } // namespace GZSTREAM_NAMESPACE #endif #endif // GZSTREAM_H // ============================================================================ // EOF // netgen-6.2.1905/libsrc/general/ngsimd.hpp0000644000175000017500000006766713504650527016714 0ustar kurtkurt#ifndef FILE_NGSIMD #define FILE_NGSIMD /**************************************************************************/ /* File: ngsimd.hpp */ /* Author: Joachim Schoeberl */ /* Date: 25. Mar. 16 */ /**************************************************************************/ #include #include #include #include #include #include #ifdef WIN32 #ifndef AVX_OPERATORS_DEFINED #define AVX_OPERATORS_DEFINED NG_INLINE __m128d operator- (__m128d a) { return _mm_xor_pd(a, _mm_set1_pd(-0.0)); } NG_INLINE __m128d operator+ (__m128d a, __m128d b) { return _mm_add_pd(a,b); } NG_INLINE __m128d operator- (__m128d a, __m128d b) { return _mm_sub_pd(a,b); } NG_INLINE __m128d operator* (__m128d a, __m128d b) { return _mm_mul_pd(a,b); } NG_INLINE __m128d operator/ (__m128d a, __m128d b) { return _mm_div_pd(a,b); } NG_INLINE __m128d operator* (double a, __m128d b) { return _mm_set1_pd(a)*b; } NG_INLINE __m128d operator* (__m128d b, double a) { return _mm_set1_pd(a)*b; } NG_INLINE __m128d operator+= (__m128d &a, __m128d b) { return a = a+b; } NG_INLINE __m128d operator-= (__m128d &a, __m128d b) { return a = a-b; } NG_INLINE __m128d operator*= (__m128d &a, __m128d b) { return a = a*b; } NG_INLINE __m128d operator/= (__m128d &a, __m128d b) { return a = a/b; } NG_INLINE __m256d operator- (__m256d a) { return _mm256_xor_pd(a, _mm256_set1_pd(-0.0)); } NG_INLINE __m256d operator+ (__m256d a, __m256d b) { return _mm256_add_pd(a,b); } NG_INLINE __m256d operator- (__m256d a, __m256d b) { return _mm256_sub_pd(a,b); } NG_INLINE __m256d operator* (__m256d a, __m256d b) { return _mm256_mul_pd(a,b); } NG_INLINE __m256d operator/ (__m256d a, __m256d b) { return _mm256_div_pd(a,b); } NG_INLINE __m256d operator* (double a, __m256d b) { return _mm256_set1_pd(a)*b; } NG_INLINE __m256d operator* (__m256d b, double a) { return _mm256_set1_pd(a)*b; } NG_INLINE __m256d operator+= (__m256d &a, __m256d b) { return a = a+b; } NG_INLINE __m256d operator-= (__m256d &a, __m256d b) { return a = a-b; } NG_INLINE __m256d operator*= (__m256d &a, __m256d b) { return a = a*b; } NG_INLINE __m256d operator/= (__m256d &a, __m256d b) { return a = a/b; } #endif #endif namespace ngsimd { // MSVC does not define SSE. It's always present on 64bit cpus #if (defined(_M_AMD64) || defined(_M_X64) || defined(__AVX__)) #ifndef __SSE__ #define __SSE__ #endif #ifndef __SSE2__ #define __SSE2__ #endif #endif constexpr int GetDefaultSIMDSize() { #if defined __AVX512F__ return 8; #elif defined __AVX__ return 4; #elif defined __SSE__ return 2; #else return 1; #endif } #if defined __AVX512F__ typedef __m512 tAVX; typedef __m512d tAVXd; #elif defined __AVX__ typedef __m256 tAVX; typedef __m256d tAVXd; #elif defined __SSE__ typedef __m128 tAVX; typedef __m128d tAVXd; #endif template class SIMD; template struct has_call_operator { template static std::true_type check( decltype( sizeof(&C::operator() )) ) { return std::true_type(); } template static std::false_type check(...) { return std::false_type(); } typedef decltype( check(sizeof(char)) ) type; static constexpr type value = type(); }; template // a*b+c NG_INLINE auto FMA(T1 a, T2 b, T3 c) { return a*b+c; } template::value, int>::type = 0> NG_INLINE SIMD operator+ (T a, SIMD b) { return SIMD(a) + b; } template::value, int>::type = 0> NG_INLINE SIMD operator- (T a, SIMD b) { return SIMD(a) - b; } template::value, int>::type = 0> NG_INLINE SIMD operator* (T a, SIMD b) { return SIMD(a) * b; } template::value, int>::type = 0> NG_INLINE SIMD operator/ (T a, SIMD b) { return SIMD(a) / b; } template::value, int>::type = 0> NG_INLINE SIMD operator+ (SIMD a, T b) { return a + SIMD(b); } template::value, int>::type = 0> NG_INLINE SIMD operator- (SIMD a, T b) { return a - SIMD(b); } template::value, int>::type = 0> NG_INLINE SIMD operator* (SIMD a, T b) { return a * SIMD(b); } template::value, int>::type = 0> NG_INLINE SIMD operator/ (SIMD a, T b) { return a / SIMD(b); } #ifdef __AVX__ template class AlignedAlloc { protected: static void * aligned_malloc(size_t s) { // Assume 16 byte alignment of standard library if(alignof(T)<=16) return malloc(s); else return _mm_malloc(s, alignof(T)); } static void aligned_free(void *p) { if(alignof(T)<=16) free(p); else _mm_free(p); } public: void * operator new (size_t s, void *p) { return p; } void * operator new (size_t s) { return aligned_malloc(s); } void * operator new[] (size_t s) { return aligned_malloc(s); } void operator delete (void * p) { aligned_free(p); } void operator delete[] (void * p) { aligned_free(p); } }; #else // it's only a dummy without AVX template class AlignedAlloc { ; }; #endif using std::sqrt; using std::fabs; class ExceptionNOSIMD : public std::runtime_error { public: using std::runtime_error::runtime_error; std::string What() { return what(); } }; using std::exp; template NG_INLINE SIMD exp (SIMD a) { return SIMD([&](int i)->double { return exp(a[i]); } ); } using std::log; template NG_INLINE SIMD log (SIMD a) { return SIMD([&](int i)->double { return log(a[i]); } ); } using std::pow; template NG_INLINE SIMD pow (SIMD a, double x) { return SIMD([&](int i)->double { return pow(a[i],x); } ); } using std::sin; template NG_INLINE SIMD sin (SIMD a) { return SIMD([&](int i)->double { return sin(a[i]); } ); } using std::cos; template NG_INLINE SIMD cos (SIMD a) { return SIMD([&](int i)->double { return cos(a[i]); } ); } using std::tan; template NG_INLINE SIMD tan (SIMD a) { return SIMD([&](int i)->double { return tan(a[i]); } ); } using std::atan; template NG_INLINE SIMD atan (SIMD a) { return SIMD([&](int i)->double { return atan(a[i]); } ); } ///////////////////////////////////////////////////////////////////////////// // SIMD width 1 (in case no AVX support is available) ///////////////////////////////////////////////////////////////////////////// template<> class SIMD { double data; public: static constexpr int Size() { return 1; } SIMD () = default; SIMD (const SIMD &) = default; SIMD & operator= (const SIMD &) = default; // only called if T has a call operator of appropriate type template>::value, int>::type = 0> SIMD (const T & func) { data = func(0); } // only called if T is arithmetic (integral or floating point types) template::value, int>::type = 0> SIMD (const T & val) { data = val; } SIMD (double const * p) { data = *p; } NG_INLINE operator double() const { return data; } NG_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; } NG_INLINE double Data() const { return data; } NG_INLINE double & Data() { return data; } NG_INLINE SIMD &operator+= (SIMD b) { data+=b.Data(); return *this; } NG_INLINE SIMD &operator-= (SIMD b) { data-=b.Data(); return *this; } NG_INLINE SIMD &operator*= (SIMD b) { data*=b.Data(); return *this; } NG_INLINE SIMD &operator/= (SIMD b) { data/=b.Data(); return *this; } }; NG_INLINE SIMD operator+ (SIMD a, SIMD b) { return a.Data()+b.Data(); } NG_INLINE SIMD operator- (SIMD a, SIMD b) { return a.Data()-b.Data(); } NG_INLINE SIMD operator- (SIMD a) { return -a.Data(); } NG_INLINE SIMD operator* (SIMD a, SIMD b) { return a.Data()*b.Data(); } NG_INLINE SIMD operator/ (SIMD a, SIMD b) { return a.Data()/b.Data(); } NG_INLINE SIMD sqrt (SIMD a) { return std::sqrt(a.Data()); } NG_INLINE SIMD floor (SIMD a) { return std::floor(a.Data()); } NG_INLINE SIMD ceil (SIMD a) { return std::ceil(a.Data()); } NG_INLINE SIMD fabs (SIMD a) { return std::fabs(a.Data()); } NG_INLINE SIMD L2Norm2 (SIMD a) { return a.Data()*a.Data(); } NG_INLINE SIMD Trans (SIMD a) { return a; } NG_INLINE SIMD IfPos (SIMD a, SIMD b, SIMD c) { return (a.Data() > 0) ? b : c; } NG_INLINE double HSum (SIMD sd) { return sd.Data(); } NG_INLINE auto HSum (SIMD sd1, SIMD sd2) { return std::make_tuple(sd1.Data(), sd2.Data()); } NG_INLINE auto HSum (SIMD sd1, SIMD sd2, SIMD sd3, SIMD sd4) { return std::make_tuple(sd1.Data(), sd2.Data(), sd3.Data(), sd4.Data()); } ///////////////////////////////////////////////////////////////////////////// // SSE - Simd width 2 ///////////////////////////////////////////////////////////////////////////// #ifdef __SSE__ template<> class alignas(16) SIMD // : public AlignedAlloc> { __m128d data; public: static constexpr int Size() { return 2; } SIMD () = default; SIMD (const SIMD &) = default; SIMD & operator= (const SIMD &) = default; SIMD (__m128d adata) : data(adata) { ; } // only called if T has a call operator of appropriate type template>::value, int>::type = 0> SIMD (const T & func) { data = _mm_set_pd(func(1), func(0)); } // only called if T is arithmetic (integral or floating point types) template::value, int>::type = 0> SIMD (const T & val) { data = _mm_set1_pd(val); } SIMD (double const * p) { data = _mm_loadu_pd(p); } NG_INLINE operator __m128d() const { return data; } NG_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; } NG_INLINE double& operator[] (int i) { return ((double*)(&data))[i]; } NG_INLINE __m128d Data() const { return data; } NG_INLINE __m128d & Data() { return data; } // NG_INLINE operator std::tuple () // { return std::tuple((*this)[0], (*this)[1], (*this)[2], (*this)[3]); } NG_INLINE SIMD &operator+= (SIMD b) { data+=b.Data(); return *this; } NG_INLINE SIMD &operator-= (SIMD b) { data-=b.Data(); return *this; } NG_INLINE SIMD &operator*= (SIMD b) { data*=b.Data(); return *this; } NG_INLINE SIMD &operator/= (SIMD b) { data/=b.Data(); return *this; } }; NG_INLINE SIMD operator+ (SIMD a, SIMD b) { return a.Data()+b.Data(); } NG_INLINE SIMD operator- (SIMD a, SIMD b) { return a.Data()-b.Data(); } NG_INLINE SIMD operator- (SIMD a) { return -a.Data(); } NG_INLINE SIMD operator* (SIMD a, SIMD b) { return a.Data()*b.Data(); } NG_INLINE SIMD operator/ (SIMD a, SIMD b) { return a.Data()/b.Data(); } /* NG_INLINE SIMD sqrt (SIMD a) { return _mm256_sqrt_pd(a.Data()); } NG_INLINE SIMD floor (SIMD a) { return _mm256_floor_pd(a.Data()); } NG_INLINE SIMD ceil (SIMD a) { return _mm256_ceil_pd(a.Data()); } NG_INLINE SIMD fabs (SIMD a) { return _mm256_max_pd(a.Data(), -a.Data()); } NG_INLINE SIMD L2Norm2 (SIMD a) { return a.Data()*a.Data(); } NG_INLINE SIMD Trans (SIMD a) { return a; } NG_INLINE SIMD IfPos (SIMD a, SIMD b, SIMD c) { auto cp = _mm256_cmp_pd (a.Data(), _mm256_setzero_pd(), _CMP_GT_OS); return _mm256_blendv_pd(c.Data(), b.Data(), cp); } NG_INLINE double HSum (SIMD sd) { __m128d hv = _mm_add_pd (_mm256_extractf128_pd(sd.Data(),0), _mm256_extractf128_pd(sd.Data(),1)); return _mm_cvtsd_f64 (_mm_hadd_pd (hv, hv)); } NG_INLINE auto HSum (SIMD sd1, SIMD sd2) { __m256d hv = _mm256_hadd_pd(sd1.Data(), sd2.Data()); __m128d hv2 = _mm_add_pd (_mm256_extractf128_pd(hv,0), _mm256_extractf128_pd(hv,1)); return std::make_tuple(_mm_cvtsd_f64 (hv2), _mm_cvtsd_f64(_mm_shuffle_pd (hv2, hv2, 3))); } NG_INLINE auto HSum (SIMD v1, SIMD v2, SIMD v3, SIMD v4) { __m256d hsum1 = _mm256_hadd_pd (v1.Data(), v2.Data()); __m256d hsum2 = _mm256_hadd_pd (v3.Data(), v4.Data()); __m256d hsum = _mm256_add_pd (_mm256_permute2f128_pd (hsum1, hsum2, 1+2*16), _mm256_blend_pd (hsum1, hsum2, 12)); return SIMD(hsum); } */ #endif // __SSE__ ///////////////////////////////////////////////////////////////////////////// // AVX - Simd width 4 ///////////////////////////////////////////////////////////////////////////// #ifdef __AVX__ template<> class alignas(32) SIMD : public AlignedAlloc> { __m256d data; public: static constexpr int Size() { return 4; } SIMD () = default; SIMD (const SIMD &) = default; SIMD & operator= (const SIMD &) = default; SIMD (__m256d adata) : data(adata) { ; } // only called if T has a call operator of appropriate type template>::value, int>::type = 0> SIMD (const T & func) { data = _mm256_set_pd(func(3), func(2), func(1), func(0)); } // only called if T is arithmetic (integral or floating point types) template::value, int>::type = 0> SIMD (const T & val) { data = _mm256_set1_pd(val); } SIMD (double const * p) { data = _mm256_loadu_pd(p); } NG_INLINE operator __m256d() const { return data; } NG_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; } NG_INLINE double& operator[] (int i) { return ((double*)(&data))[i]; } NG_INLINE __m256d Data() const { return data; } NG_INLINE __m256d & Data() { return data; } NG_INLINE operator std::tuple () { return std::tuple((*this)[0], (*this)[1], (*this)[2], (*this)[3]); } NG_INLINE SIMD &operator+= (SIMD b) { data+=b.Data(); return *this; } NG_INLINE SIMD &operator-= (SIMD b) { data-=b.Data(); return *this; } NG_INLINE SIMD &operator*= (SIMD b) { data*=b.Data(); return *this; } NG_INLINE SIMD &operator/= (SIMD b) { data/=b.Data(); return *this; } }; NG_INLINE SIMD operator+ (SIMD a, SIMD b) { return a.Data()+b.Data(); } NG_INLINE SIMD operator- (SIMD a, SIMD b) { return a.Data()-b.Data(); } NG_INLINE SIMD operator- (SIMD a) { return -a.Data(); } NG_INLINE SIMD operator* (SIMD a, SIMD b) { return a.Data()*b.Data(); } NG_INLINE SIMD operator/ (SIMD a, SIMD b) { return a.Data()/b.Data(); } NG_INLINE SIMD sqrt (SIMD a) { return _mm256_sqrt_pd(a.Data()); } NG_INLINE SIMD floor (SIMD a) { return _mm256_floor_pd(a.Data()); } NG_INLINE SIMD ceil (SIMD a) { return _mm256_ceil_pd(a.Data()); } NG_INLINE SIMD fabs (SIMD a) { return _mm256_max_pd(a.Data(), -a.Data()); } NG_INLINE SIMD L2Norm2 (SIMD a) { return a.Data()*a.Data(); } NG_INLINE SIMD Trans (SIMD a) { return a; } NG_INLINE SIMD IfPos (SIMD a, SIMD b, SIMD c) { auto cp = _mm256_cmp_pd (a.Data(), _mm256_setzero_pd(), _CMP_GT_OS); return _mm256_blendv_pd(c.Data(), b.Data(), cp); } NG_INLINE double HSum (SIMD sd) { __m128d hv = _mm_add_pd (_mm256_extractf128_pd(sd.Data(),0), _mm256_extractf128_pd(sd.Data(),1)); return _mm_cvtsd_f64 (_mm_hadd_pd (hv, hv)); } NG_INLINE auto HSum (SIMD sd1, SIMD sd2) { __m256d hv = _mm256_hadd_pd(sd1.Data(), sd2.Data()); __m128d hv2 = _mm_add_pd (_mm256_extractf128_pd(hv,0), _mm256_extractf128_pd(hv,1)); return std::make_tuple(_mm_cvtsd_f64 (hv2), _mm_cvtsd_f64(_mm_shuffle_pd (hv2, hv2, 3))); } NG_INLINE auto HSum (SIMD v1, SIMD v2, SIMD v3, SIMD v4) { __m256d hsum1 = _mm256_hadd_pd (v1.Data(), v2.Data()); __m256d hsum2 = _mm256_hadd_pd (v3.Data(), v4.Data()); __m256d hsum = _mm256_add_pd (_mm256_permute2f128_pd (hsum1, hsum2, 1+2*16), _mm256_blend_pd (hsum1, hsum2, 12)); return SIMD(hsum); } #endif // __AVX__ ///////////////////////////////////////////////////////////////////////////// // AVX512 - Simd width 8 ///////////////////////////////////////////////////////////////////////////// #ifdef __AVX512F__ template<> class alignas(64) SIMD : public AlignedAlloc> { __m512d data; public: static constexpr int Size() { return 8; } SIMD () = default; SIMD (const SIMD &) = default; SIMD & operator= (const SIMD &) = default; SIMD (__m512d adata) : data(adata) { ; } // only called if T has a call operator of appropriate type template>::value, int>::type = 0> SIMD (const T & func) { data = _mm512_set_pd(func(7), func(6), func(5), func(4), func(3), func(2), func(1), func(0)); } // only called if T is arithmetic (integral or floating point types) template::value, int>::type = 0> SIMD (const T & val) { data = _mm512_set1_pd(val); } SIMD (double const * p) { data = _mm512_loadu_pd(p); } NG_INLINE operator __m512d() const { return data; } NG_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; } NG_INLINE __m512d Data() const { return data; } NG_INLINE __m512d & Data() { return data; } NG_INLINE SIMD &operator+= (SIMD b) { data+=b.Data(); return *this; } NG_INLINE SIMD &operator-= (SIMD b) { data-=b.Data(); return *this; } NG_INLINE SIMD &operator*= (SIMD b) { data*=b.Data(); return *this; } NG_INLINE SIMD &operator/= (SIMD b) { data/=b.Data(); return *this; } }; NG_INLINE SIMD operator- (SIMD a) { return _mm512_sub_pd(_mm512_setzero_pd(), a.Data()); } NG_INLINE SIMD operator+ (SIMD a, SIMD b) { return _mm512_add_pd(a.Data(),b.Data()); } NG_INLINE SIMD operator- (SIMD a, SIMD b) { return _mm512_sub_pd(a.Data(),b.Data()); } NG_INLINE SIMD operator* (SIMD a, SIMD b) { return _mm512_mul_pd(a.Data(),b.Data()); } NG_INLINE SIMD operator/ (SIMD a, SIMD b) { return _mm512_div_pd(a.Data(),b.Data()); } NG_INLINE SIMD sqrt (SIMD a) { return _mm512_sqrt_pd(a.Data()); } NG_INLINE SIMD floor (SIMD a) { return _mm512_floor_pd(a.Data()); } NG_INLINE SIMD ceil (SIMD a) { return _mm512_ceil_pd(a.Data()); } NG_INLINE SIMD fabs (SIMD a) { return _mm512_max_pd(a.Data(), -a.Data()); } NG_INLINE SIMD L2Norm2 (SIMD a) { return a.Data()*a.Data(); } NG_INLINE SIMD Trans (SIMD a) { return a; } NG_INLINE SIMD IfPos (SIMD a, SIMD b, SIMD c) { auto cp = _mm512_cmp_pd_mask (a.Data(), _mm512_setzero_pd(), _MM_CMPINT_GT); return _mm512_mask_blend_pd(cp, c.Data(), b.Data()); } template<> NG_INLINE auto FMA (SIMD a, SIMD b, SIMD c) { return _mm512_fmadd_pd (a.Data(), b.Data(), c.Data()); } NG_INLINE double HSum (SIMD sd) { SIMD low = _mm512_extractf64x4_pd(sd.Data(),0); SIMD high = _mm512_extractf64x4_pd(sd.Data(),1); return HSum(low)+HSum(high); } NG_INLINE auto HSum (SIMD sd1, SIMD sd2) { return std::make_tuple(HSum(sd1), HSum(sd2)); } NG_INLINE SIMD HSum (SIMD v1, SIMD v2, SIMD v3, SIMD v4) { SIMD high1 = _mm512_extractf64x4_pd(v1.Data(),1); SIMD high2 = _mm512_extractf64x4_pd(v2.Data(),1); SIMD high3 = _mm512_extractf64x4_pd(v3.Data(),1); SIMD high4 = _mm512_extractf64x4_pd(v4.Data(),1); SIMD low1 = _mm512_extractf64x4_pd(v1.Data(),0); SIMD low2 = _mm512_extractf64x4_pd(v2.Data(),0); SIMD low3 = _mm512_extractf64x4_pd(v3.Data(),0); SIMD low4 = _mm512_extractf64x4_pd(v4.Data(),0); return HSum(low1,low2,low3,low4) + HSum(high1,high2,high3,high4); } #endif // __AVX512F__ //////////////////////////////////////////////////////////////////////////////// // MultiSIMD - Multiple SIMD values in one struct using head-tail implementation //////////////////////////////////////////////////////////////////////////////// template class MultiSIMD : public AlignedAlloc> { SIMD head; MultiSIMD tail; public: MultiSIMD () = default; MultiSIMD (const MultiSIMD & ) = default; MultiSIMD (T v) : head(v), tail(v) { ; } MultiSIMD (SIMD _head, MultiSIMD _tail) : head(_head), tail(_tail) { ; } SIMD Head() const { return head; } MultiSIMD Tail() const { return tail; } SIMD & Head() { return head; } MultiSIMD & Tail() { return tail; } template SIMD Get() const { return NR==0 ? head : tail.template Get(); } template SIMD & Get() { return NR==0 ? head : tail.template Get(); } auto MakeTuple() { return std::tuple_cat(std::tuple&> (head), tail.MakeTuple()); } // not yet possible for MSVC // operator auto () { return MakeTuple(); } }; template class MultiSIMD<2,T> : public AlignedAlloc> { SIMD v0, v1; public: MultiSIMD () = default; MultiSIMD (const MultiSIMD & ) = default; MultiSIMD (T v) : v0(v), v1(v) { ; } MultiSIMD (SIMD _v0, SIMD _v1) : v0(_v0), v1(_v1) { ; } SIMD Head() const { return v0; } SIMD Tail() const { return v1; } SIMD & Head() { return v0; } SIMD & Tail() { return v1; } template SIMD Get() const { return NR==0 ? v0 : v1; } template SIMD & Get() { return NR==0 ? v0 : v1; } auto MakeTuple() { return std::tuple&, SIMD&> (v0, v1); } operator std::tuple&, SIMD&>() { return MakeTuple(); } }; template NG_INLINE MultiSIMD operator+ (MultiSIMD a, MultiSIMD b) { return MultiSIMD (a.Head()+b.Head(), a.Tail()+b.Tail()); } template NG_INLINE MultiSIMD operator+ (double a, MultiSIMD b) { return MultiSIMD (a+b.Head(), a+b.Tail()); } template NG_INLINE MultiSIMD operator+ (MultiSIMD b, double a) { return MultiSIMD (a+b.Head(), a+b.Tail()); } template NG_INLINE MultiSIMD operator- (MultiSIMD a, MultiSIMD b) { return MultiSIMD (a.Head()-b.Head(), a.Tail()-b.Tail()); } template NG_INLINE MultiSIMD operator- (double a, MultiSIMD b) { return MultiSIMD (a-b.Head(), a-b.Tail()); } template NG_INLINE MultiSIMD operator- (MultiSIMD b, double a) { return MultiSIMD (b.Head()-a, b.Tail()-a); } template NG_INLINE MultiSIMD operator- (MultiSIMD a) { return MultiSIMD (-a.Head(), -a.Tail()); } template NG_INLINE MultiSIMD operator* (MultiSIMD a, MultiSIMD b) { return MultiSIMD (a.Head()*b.Head(), a.Tail()*b.Tail()); } template NG_INLINE MultiSIMD operator/ (MultiSIMD a, MultiSIMD b) { return MultiSIMD (a.Head()/b.Head(), a.Tail()/b.Tail()); } template NG_INLINE MultiSIMD operator* (double a, MultiSIMD b) { return MultiSIMD ( a*b.Head(), a*b.Tail()); } template NG_INLINE MultiSIMD operator* (MultiSIMD b, double a) { return MultiSIMD ( a*b.Head(), a*b.Tail()); } template NG_INLINE MultiSIMD & operator+= (MultiSIMD & a, MultiSIMD b) { a.Head()+=b.Head(); a.Tail()+=b.Tail(); return a; } template NG_INLINE MultiSIMD operator-= (MultiSIMD & a, double b) { a.Head()-=b; a.Tail()-=b; return a; } template NG_INLINE MultiSIMD operator-= (MultiSIMD & a, MultiSIMD b) { a.Head()-=b.Head(); a.Tail()-=b.Tail(); return a; } template NG_INLINE MultiSIMD & operator*= (MultiSIMD & a, MultiSIMD b) { a.Head()*=b.Head(); a.Tail()*=b.Tail(); return a; } template NG_INLINE MultiSIMD & operator*= (MultiSIMD & a, double b) { a.Head()*=b; a.Tail()*=b; return a; } // NG_INLINE MultiSIMD operator/= (MultiSIMD & a, MultiSIMD b) { return a.Data()/=b.Data(); } NG_INLINE SIMD HVSum (SIMD a) { return a; } template NG_INLINE SIMD HVSum (MultiSIMD a) { return a.Head() + HVSum(a.Tail()); } template NG_INLINE double HSum (MultiSIMD a) { return HSum(HVSum(a)); } template NG_INLINE auto HSum (MultiSIMD a, MultiSIMD b) { return HSum(HVSum(a), HVSum(b)); } template std::ostream & operator<< (std::ostream & ost, MultiSIMD multi) { ost << multi.Head() << " " << multi.Tail(); return ost; } template std::ostream & operator<< (std::ostream & ost, SIMD simd) { ost << simd[0]; for (int i = 1; i < simd.Size(); i++) ost << " " << simd[i]; return ost; } } namespace netgen { using namespace ngsimd; } #endif netgen-6.2.1905/libsrc/general/CMakeLists.txt0000644000175000017500000000146313504650527017440 0ustar kurtkurtadd_definitions(-DNGINTERFACE_EXPORTS) add_library(gen INTERFACE) set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) target_sources(gen INTERFACE ${sdir}/array.cpp ${sdir}/bitarray.cpp ${sdir}/dynamicmem.cpp ${sdir}/flags.cpp ${sdir}/hashtabl.cpp ${sdir}/mystring.cpp ${sdir}/optmem.cpp ${sdir}/parthreads.cpp ${sdir}/seti.cpp ${sdir}/sort.cpp ${sdir}/spbita2d.cpp ${sdir}/table.cpp ${sdir}/mpi_interface.cpp ${sdir}/gzstream.cpp ) install(FILES array.hpp autodiff.hpp autoptr.hpp bitarray.hpp dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp ngsimd.hpp mystring.hpp netgenout.hpp ngpython.hpp optmem.hpp parthreads.hpp seti.hpp sort.hpp spbita2d.hpp stack.hpp table.hpp template.hpp gzstream.h DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/visualization/0000755000175000017500000000000013504650527016160 5ustar kurtkurtnetgen-6.2.1905/libsrc/visualization/vsocc.cpp0000644000175000017500000004753213504650527020014 0ustar kurtkurt#ifndef NOTCL #ifdef OCCGEOMETRY #include #include #include #include #include "TopoDS_Shape.hxx" #include "TopoDS_Vertex.hxx" #include "TopExp_Explorer.hxx" #include "BRep_Tool.hxx" #include "TopoDS.hxx" #include "gp_Pnt.hxx" #include "Geom_Curve.hxx" #include "Poly_Triangulation.hxx" #include "Poly_Array1OfTriangle.hxx" #include "TColgp_Array1OfPnt2d.hxx" #include "Poly_Triangle.hxx" #include "Poly_Polygon3D.hxx" #include "Poly_PolygonOnTriangulation.hxx" #include namespace netgen { extern OCCGeometry * occgeometry; /* *********************** Draw OCC Geometry **************** */ VisualSceneOCCGeometry :: VisualSceneOCCGeometry () : VisualScene() { trilists.SetSize(0); linelists.SetSize(1); } VisualSceneOCCGeometry :: ~VisualSceneOCCGeometry () { ; } void VisualSceneOCCGeometry :: DrawScene () { if ( occgeometry->changed ) { BuildScene(); occgeometry -> changed = 0; } glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixf (transformationmat); glShadeModel (GL_SMOOTH); glDisable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glEnable (GL_LIGHTING); double shine = vispar.shininess; // double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); glEnable (GL_NORMALIZE); float mat_col[] = { 0.2f, 0.2f, 0.8f, 1.0f}; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); // Philippose - 30/01/2009 // Added clipping planes to Geometry view SetClippingPlane(); GLfloat matcoledge[] = { 0, 0, 1, 1}; GLfloat matcolhiedge[] = { 1, 0, 0, 1}; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcoledge); glLineWidth (1.0f); if (vispar.occshowedges) glCallList (linelists.Get(1)); if (vispar.occshowsurfaces) glCallList (trilists.Get(1)); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolhiedge); glLineWidth (5.0f); if (vispar.occshowedges) glCallList (linelists.Get(2)); for (int i = 1; i <= occgeometry->vmap.Extent(); i++) if (occgeometry->vvispar[i-1].IsHighlighted()) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolhiedge); glLineWidth (5.0f); glBegin (GL_LINES); gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(occgeometry->vmap(i))); double d = rad/100; glVertex3f (p.X()-d, p.Y(), p.Z()); glVertex3f (p.X()+d, p.Y(), p.Z()); glVertex3f (p.X(), p.Y()-d, p.Z()); glVertex3f (p.X(), p.Y()+d, p.Z()); glVertex3f (p.X(), p.Y(), p.Z()-d); glVertex3f (p.X(), p.Y(), p.Z()+d); glEnd(); } glDisable (GL_POLYGON_OFFSET_FILL); glPopMatrix(); // DrawCoordinateCross (); // DrawNetgenLogo (); glFinish(); glDisable (GL_POLYGON_OFFSET_FILL); } /* void VisualSceneOCCGeometry :: BuildScene (int zoomall) { int i = 0, j, k; TopExp_Explorer ex, ex_edge; if (vispar.occvisproblemfaces || (occgeometry -> changed != 2)) { Box<3> bb = occgeometry -> GetBoundingBox(); center = bb.Center(); rad = bb.Diam() / 2; if (vispar.occvisproblemfaces) { for (i = 1; i <= occgeometry->fmap.Extent(); i++) if (occgeometry->facemeshstatus[i-1] == -1) { GProp_GProps system; BRepGProp::LinearProperties(occgeometry->fmap(i), system); gp_Pnt pnt = system.CentreOfMass(); center = Point<3> (pnt.X(), pnt.Y(), pnt.Z()); cout << "Setting center to mid of face " << i << " = " << center << endl; } } CalcTransformationMatrices(); } for (i = 1; i <= linelists.Size(); i++) glDeleteLists (linelists.Elem(i), 1); linelists.SetSize(0); linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); i = 0; for (ex_edge.Init(occgeometry -> shape, TopAbs_EDGE); ex_edge.More(); ex_edge.Next()) { if (BRep_Tool::Degenerated(TopoDS::Edge(ex_edge.Current()))) continue; i++; TopoDS_Edge edge = TopoDS::Edge(ex_edge.Current()); Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { cout << "cannot visualize edge " << i << endl; continue; } glBegin (GL_LINE_STRIP); int nbnodes = aEdgePoly -> NbNodes(); for (j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); for (i = 1; i <= trilists.Size(); i++) glDeleteLists (trilists.Elem(i), 1); trilists.SetSize(0); trilists.Append (glGenLists (1)); glNewList (trilists.Last(), GL_COMPILE); i = 0; TopExp_Explorer exp0, exp1, exp2, exp3; int shapenr = 0; for (exp0.Init(occgeometry -> shape, TopAbs_SOLID); exp0.More(); exp0.Next()) { shapenr++; if (vispar.occshowvolumenr != 0 && vispar.occshowvolumenr != shapenr) continue; float mat_col[4]; mat_col[3] = 1; switch (shapenr) { case 1: mat_col[0] = 0.2; mat_col[1] = 0.2; mat_col[2] = 0.8; break; case 2: mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.8; break; case 3: mat_col[0] = 0.2; mat_col[1] = 0.8; mat_col[2] = 0.8; break; case 4: mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.2; break; case 5: mat_col[0] = 0.8; mat_col[1] = 0.8; mat_col[2] = 0.8; break; case 6: mat_col[0] = 0.6; mat_col[1] = 0.6; mat_col[2] = 0.6; break; case 7: mat_col[0] = 0.2; mat_col[1] = 0.8; mat_col[2] = 0.2; break; case 8: mat_col[0] = 0.8; mat_col[1] = 0.8; mat_col[2] = 0.2; break; default: // mat_col[0] = 1-(1.0/double(shapenr)); // mat_col[1] = 0.5; mat_col[0] = 0.5+double((shapenr*shapenr*shapenr*shapenr) % 10)/20.0; mat_col[1] = 0.5+double(int(shapenr*shapenr*shapenr*shapenr*sin(double(shapenr))) % 10)/20.0; mat_col[2] = 0.5+double((shapenr*shapenr*shapenr) % 10)/20.0; } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); for (exp1.Init(exp0.Current(), TopAbs_SHELL); exp1.More(); exp1.Next()) for (exp2.Init(exp1.Current().Composed(exp0.Current().Orientation()), TopAbs_FACE); exp2.More(); exp2.Next()) { TopoDS_Face face = TopoDS::Face (exp2.Current().Composed(exp1.Current().Orientation())); i = occgeometry->fmap.FindIndex(face); TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (face); BRepAdaptor_Surface sf(face, Standard_False); BRepLProp_SLProps prop(sf, 1, 1e-5); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) { cout << "cannot visualize face " << i << endl; continue; } if (vispar.occvisproblemfaces) { switch (occgeometry->facemeshstatus[i-1]) { case 0: mat_col[0] = 0.2; mat_col[1] = 0.2; mat_col[2] = 0.8; break; case 1: mat_col[0] = 0.2; mat_col[1] = 0.8; mat_col[2] = 0.2; break; case -1: mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.2; break; } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); } glBegin (GL_TRIANGLES); int ntriangles = triangulation -> NbTriangles(); for (j = 1; j <= ntriangles; j++) { Poly_Triangle triangle = (triangulation -> Triangles())(j); for (k = 1; k <= 3; k++) { gp_Pnt2d uv = (triangulation -> UVNodes())(triangle(k)); gp_Pnt pnt; gp_Vec du, dv; prop.SetParameters (uv.X(), uv.Y()); surf->D0 (uv.X(), uv.Y(), pnt); gp_Vec n; if (prop.IsNormalDefined()) n = prop.Normal(); else n = gp_Vec (0,0,0); if (face.Orientation() == TopAbs_REVERSED) n *= -1; glNormal3f (n.X(), n.Y(), n.Z()); glVertex3f (pnt.X(), pnt.Y(), pnt.Z()); } } glEnd (); } } glEndList (); } */ void VisualSceneOCCGeometry :: BuildScene (int zoomall) { if (occgeometry -> changed == OCCGEOMETRYVISUALIZATIONFULLCHANGE) { occgeometry -> BuildVisualizationMesh (vispar.occdeflection); center = occgeometry -> Center(); rad = occgeometry -> GetBoundingBox().Diam() / 2; if (vispar.occzoomtohighlightedentity) { bool hilite = false; bool hiliteonepoint = false; Bnd_Box bb; for (int i = 1; i <= occgeometry->fmap.Extent(); i++) if (occgeometry->fvispar[i-1].IsHighlighted()) { hilite = true; BRepBndLib::Add (occgeometry->fmap(i), bb); } for (int i = 1; i <= occgeometry->emap.Extent(); i++) if (occgeometry->evispar[i-1].IsHighlighted()) { hilite = true; BRepBndLib::Add (occgeometry->emap(i), bb); } for (int i = 1; i <= occgeometry->vmap.Extent(); i++) if (occgeometry->vvispar[i-1].IsHighlighted()) { hiliteonepoint = true; BRepBndLib::Add (occgeometry->vmap(i), bb); } if (hilite || hiliteonepoint) { double x1,y1,z1,x2,y2,z2; bb.Get (x1,y1,z1,x2,y2,z2); Point<3> p1 = Point<3> (x1,y1,z1); Point<3> p2 = Point<3> (x2,y2,z2); Box<3> boundingbox(p1,p2); center = boundingbox.Center(); if (hiliteonepoint) rad = occgeometry -> GetBoundingBox().Diam() / 100; else rad = boundingbox.Diam() / 2; } } CalcTransformationMatrices(); } // Clear lists for (int i = 1; i <= linelists.Size(); i++) glDeleteLists (linelists.Elem(i), 1); linelists.SetSize(0); for (int i = 1; i <= trilists.Size(); i++) glDeleteLists (trilists.Elem(i), 1); trilists.SetSize(0); // Total wireframe linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->emap.Extent(); i++) { TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i)); if (BRep_Tool::Degenerated(edge)) continue; if (occgeometry->evispar[i-1].IsHighlighted()) continue; Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge) << " without using the occ visualization triangulation" << endl; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); glBegin (GL_LINE_STRIP); for (int i = 0; i<=50; i++) { gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0); glVertex3f (p.X(),p.Y(),p.Z()); } glEnd (); continue; } int nbnodes = aEdgePoly -> NbNodes(); glBegin (GL_LINE_STRIP); for (int j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); // Highlighted edge list linelists.Append (glGenLists (1)); glNewList (linelists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->emap.Extent(); i++) if (occgeometry->evispar[i-1].IsHighlighted()) { TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i)); if (BRep_Tool::Degenerated(edge)) continue; Handle(Poly_PolygonOnTriangulation) aEdgePoly; Handle(Poly_Triangulation) T; TopLoc_Location aEdgeLoc; BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc); if(aEdgePoly.IsNull()) { (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge) << " without using the occ visualization triangulation" << endl; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); glBegin (GL_LINE_STRIP); for (int i = 0; i<=50; i++) { gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0); glVertex3f (p.X(),p.Y(),p.Z()); } glEnd (); continue; } int nbnodes = aEdgePoly -> NbNodes(); glBegin (GL_LINE_STRIP); for (int j = 1; j <= nbnodes; j++) { gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } glEndList (); // display faces trilists.Append (glGenLists (1)); glNewList (trilists.Last(), GL_COMPILE); for (int i = 1; i <= occgeometry->fmap.Extent(); i++) { if (!occgeometry->fvispar[i-1].IsVisible()) continue; glLoadName (i); float mat_col[4]; mat_col[3] = 1; TopoDS_Face face = TopoDS::Face(occgeometry->fmap(i)); if (!occgeometry->fvispar[i-1].IsHighlighted()) { // Philippose - 30/01/2009 // OpenCascade XDE Support Quantity_Color face_colour; // Philippose - 23/02/2009 // Check to see if colours have been extracted first!! // Forum bug-fox (Jean-Yves - 23/02/2009) if(!(occgeometry->face_colours.IsNull()) && (occgeometry->face_colours->GetColor(face,XCAFDoc_ColorSurf,face_colour))) { mat_col[0] = face_colour.Red(); mat_col[1] = face_colour.Green(); mat_col[2] = face_colour.Blue(); } else { mat_col[0] = 0.0; mat_col[1] = 1.0; mat_col[2] = 0.0; } } else { mat_col[0] = 0.8; mat_col[1] = 0.2; mat_col[2] = 0.2; } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (face); BRepAdaptor_Surface sf(face, Standard_False); BRepLProp_SLProps prop(sf, 1, 1e-5); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); if (triangulation.IsNull()) { cout << "cannot visualize face " << i << endl; occgeometry->fvispar[i-1].SetNotDrawable(); continue; } gp_Pnt2d uv; gp_Pnt pnt; gp_Vec n; glBegin (GL_TRIANGLES); int ntriangles = triangulation -> NbTriangles(); for (int j = 1; j <= ntriangles; j++) { Poly_Triangle triangle = (triangulation -> Triangles())(j); gp_Pnt p[3]; for (int k = 1; k <= 3; k++) p[k-1] = (triangulation -> Nodes())(triangle(k)).Transformed(loc); for (int k = 1; k <= 3; k++) { uv = (triangulation -> UVNodes())(triangle(k)); prop.SetParameters (uv.X(), uv.Y()); // surf->D0 (uv.X(), uv.Y(), pnt); if (prop.IsNormalDefined()) n = prop.Normal(); else { (*testout) << "Visualization of face " << i << ": Normal vector not defined" << endl; // n = gp_Vec (0,0,0); gp_Vec a(p[0],p[1]); gp_Vec b(p[0],p[2]); n = b^a; } if (face.Orientation() == TopAbs_REVERSED) n *= -1; glNormal3f (n.X(), n.Y(), n.Z()); glVertex3f (p[k-1].X(), p[k-1].Y(), p[k-1].Z()); } } glEnd (); } glEndList (); } void SelectFaceInOCCDialogTree (int facenr); void VisualSceneOCCGeometry :: MouseDblClick (int px, int py) { int hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixf (transformationmat); glInitNames(); glPushName (1); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glDisable(GL_CLIP_PLANE0); // Philippose - 30/01/2009 // Enable clipping planes for Selection mode in OCC Geometry if (vispar.clipenable) { Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); double len = Abs(n); double mu = -clipplane[3] / (len*len); Point<3> p (mu * n); n /= len; Vec<3> t1 = n.GetNormal (); Vec<3> t2 = Cross (n, t1); double xi1mid = (center - p) * t1; double xi2mid = (center - p) * t2; glLoadName (0); glBegin (GL_QUADS); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); glEnd (); } glCallList (trilists.Get(1)); glDisable (GL_POLYGON_OFFSET_FILL); glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); int minname = 0; GLuint mindepth = 0; // find clippingplane GLuint clipdepth = 0; // GLuint(-1); for (int i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; if (!curname) clipdepth = selbuf[4*i+1]; } for (int i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; if (curname && (curdepth> clipdepth) && (curdepth < mindepth || !minname)) { mindepth = curdepth; minname = curname; } } occgeometry->LowLightAll(); if (minname) { occgeometry->fvispar[minname-1].Highlight(); if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; cout << "Selected face: " << minname << endl; } else { occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } glDisable(GL_CLIP_PLANE0); SelectFaceInOCCDialogTree (minname); // Philippose - 30/01/2009 // Set the currently selected face in the array // for local face mesh size definition occgeometry->SetSelectedFace(minname); // selecttimestamp = NextTimeStamp(); } } #endif #endif // NOTCL netgen-6.2.1905/libsrc/visualization/importsolution.cpp0000644000175000017500000000601513504650527021775 0ustar kurtkurt// // Read solution file // #include #include #include #include #include #include namespace netgen { extern shared_ptr mesh; DLL_HEADER void ImportSolution2 (const char * filename) { ifstream inf (filename); char buf[100], name[1000]; int i, size, comps, order; bool iscomplex; const char * type; Flags flags; while (1) { buf[0] = 0; inf >> buf; if (strcmp (buf, "solution") == 0) { inf >> name; inf >> buf[0]; flags.DeleteFlags (); while (buf[0] == '-') { inf >> buf[1]; inf.putback (buf[1]); if (!isalpha (buf[1])) { break; } inf >> (buf+1); flags.SetCommandLineFlag (buf); buf[0] = 0; inf >> buf[0]; } inf.putback (buf[0]); (*testout) << "Flags: " << endl; flags.PrintFlags (*testout); (*testout) << "done" << endl; size = int(flags.GetNumFlag ("size", mesh->GetNP())); // Ng_GetNP())); comps = int(flags.GetNumFlag ("components", 1)); type = flags.GetStringFlag ("type", "nodal"); order = int(flags.GetNumFlag ("order", 1)); iscomplex = flags.GetDefineFlag ("complex"); double * sol = new double[size*comps]; (*testout) << "import solution " << name << " size = " << size << " comps = " << comps << " order = " << order << endl; for (i = 0; i < size*comps; i++) { inf >> sol[i]; // (*testout) << "sol: " << sol[i] << endl; } Ng_SolutionData soldata; Ng_InitSolutionData (&soldata); soldata.name = name; soldata.data = sol; soldata.dist = comps; soldata.components = comps; soldata.order = order; soldata.iscomplex = iscomplex; soldata.soltype = NG_SOLUTION_NODAL; soldata.draw_surface = 1; soldata.draw_volume = 1; if (strcmp (type, "element") == 0) { soldata.soltype = NG_SOLUTION_ELEMENT; soldata.draw_surface = 0; } if (strcmp (type, "surfaceelement") == 0) { soldata.soltype = NG_SOLUTION_SURFACE_ELEMENT; soldata.draw_volume = 0; } if (strcmp (type, "noncontinuous") == 0) soldata.soltype = NG_SOLUTION_NONCONTINUOUS; if (strcmp (type, "surfacenoncontinuous") == 0) soldata.soltype = NG_SOLUTION_SURFACE_NONCONTINUOUS; Ng_SetSolutionData (&soldata); } else { // cout << "kw = (" << buf << ")" << endl; (*testout) << "kw = (" << buf << ")" << endl; break; } } /* struct Ng_SolutionData { char * name; // name of gridfunction double * data; // solution values int components; // used components in solution vector int dist; // num of doubles per entry (alignment!) Ng_SolutionType soltype; // type of solution function }; // initialize solution data with default arguments void Ng_InitSolutionData (Ng_SolutionData * soldata); // set solution data void Ng_SetSolutionData (Ng_SolutionData * soldata); */ } } netgen-6.2.1905/libsrc/visualization/visual.hpp0000644000175000017500000000126213504650527020175 0ustar kurtkurt#ifndef FILE_VISUAL #define FILE_VISUAL /* *************************************************************************/ /* File: visual.hpp */ /* Author: Joachim Schoeberl */ /* Date: 02. Dec. 01 */ /* *************************************************************************/ /* Visualization */ // #ifdef PARALLEL // #define PARALLELGL // #endif #include "../include/incopengl.hpp" #include "vispar.hpp" #include "soldata.hpp" #include "mvdraw.hpp" #include #include "vssolution.hpp" #include "meshdoc.hpp" #endif netgen-6.2.1905/libsrc/visualization/meshdoc.hpp0000644000175000017500000000142613504650527020316 0ustar kurtkurtnamespace netgen { class VisualSceneMeshDoctor : public VisualScene { int filledlist; int outlinelist; int edgelist; int selelement, locpi; int selpoint, selpoint2; // for edgemarking: Array edgedist; int markedgedist; public: DLL_HEADER VisualSceneMeshDoctor (); DLL_HEADER virtual ~VisualSceneMeshDoctor (); DLL_HEADER virtual void BuildScene (int zoomall = 0); DLL_HEADER virtual void DrawScene (); DLL_HEADER virtual void MouseDblClick (int px, int py); DLL_HEADER void SetMarkEdgeDist (int dist); DLL_HEADER void ClickElement (int elnr); DLL_HEADER void UpdateTables (); DLL_HEADER int IsSegmentMarked (int segnr) const; }; class MeshDoctorParameters { public: int active; }; DLL_HEADER extern MeshDoctorParameters meshdoctor; } netgen-6.2.1905/libsrc/visualization/vispar.hpp0000644000175000017500000000412013504650527020172 0ustar kurtkurt#ifndef FILE_VISPAR #define FILE_VISPAR namespace netgen { class VisualizationParameters { public: double lightamb; double lightdiff; double lightspec; double shininess; double transp; int locviewer; char selectvisual[20]; int showstltrias; /* Vec3d clipnormal; double clipdist; int clipenable; int clipplanetimestamp; */ class Clipping { public: Vec3d normal; double dist; double dist2; int enable; int timestamp; bool operator== (Clipping & clip2) { return (normal == clip2.normal) && (dist == clip2.dist) && // (dist2 == clip2.dist2) && (enable == clip2.enable); } }; Clipping clipping; int colormeshsize; int drawfilledtrigs; int drawbadels; int drawoutline; int drawedges; int subdivisions; int drawprisms; int drawpyramids; int drawhexes; double shrink; int drawidentified; int drawpointnumbers; int drawedgenumbers; int drawfacenumbers; int drawelementnumbers; int drawdomainsurf; int drawtets; int drawtetsdomain; int clipdomain; int donotclipdomain; int drawededges; int drawedpoints; int drawedpointnrs; int drawedtangents; int drawededgenrs; int drawmetispartition; int drawcurveproj; int drawcurveprojedge; PointIndex centerpoint; int drawelement; // stl: int stlshowtrias; int stlshowfilledtrias; int stlshowedges; int stlshowmarktrias; int stlshowactivechart; int stlchartnumber; int stlchartnumberoffset; // occ: int occshowvolumenr; bool occshowsurfaces; bool occshowedges; bool occvisproblemfaces; bool occzoomtohighlightedentity; double occdeflection; // ACIS bool ACISshowfaces; bool ACISshowedges; int ACISshowsolidnr; int ACISshowsolidnr2; bool whitebackground; int stereo; bool usedispllists; bool drawcoordinatecross; bool drawcolorbar; bool drawnetgenlogo; bool use_center_coords; double centerx,centery,centerz; bool drawspecpoint; double specpointx,specpointy,specpointz; public: VisualizationParameters(); }; DLL_HEADER extern VisualizationParameters vispar; } #endif netgen-6.2.1905/libsrc/visualization/mvdraw.hpp0000644000175000017500000001315313504650527020174 0ustar kurtkurt#ifndef FILE_MVDRAW #define FILE_MVDRAW namespace netgen { class VisualScene { protected: static DLL_HEADER Point3d center; static DLL_HEADER double rad; static double lookatmat[16]; static double transmat[16]; static double rotmat[16]; static double centermat[16]; static DLL_HEADER double transformationmat[16]; GLdouble clipplane[4]; int changeval; static DLL_HEADER GLdouble backcolor; static int DLL_HEADER selface; static int selelement; static PointIndex DLL_HEADER selpoint; static PointIndex selpoint2; static int locpi; static int DLL_HEADER seledge; static int selecttimestamp; public: static int viewport[4]; static GLuint coltexname; static int ntexcols; int invcolor; public: DLL_HEADER VisualScene (); DLL_HEADER virtual ~VisualScene(); DLL_HEADER virtual void BuildScene (int zoomall = 0); DLL_HEADER virtual void DrawScene (); DLL_HEADER void CalcTransformationMatrices(); DLL_HEADER void StandardRotation (const char * dir); DLL_HEADER void ArbitraryRotation (const Array & alpha, const Array & vec); DLL_HEADER void ArbitraryRotation (const double alpha, const Vec3d & vec); DLL_HEADER void MouseMove(int oldx, int oldy, int newx, int newy, char mode); DLL_HEADER void LookAt (const Point<3> & cam, const Point<3> & obj, const Point<3> & camup); DLL_HEADER void SetClippingPlane (); DLL_HEADER virtual void MouseDblClick (int px, int py); DLL_HEADER void SetLight (); static void SetBackGroundColor (double col) { backcolor = col; } DLL_HEADER void CreateTexture (int ncols, int linear, double alpha, int typ); DLL_HEADER void DrawColorBar (double minval, double maxval, int logscale = 0, bool linear = 1); DLL_HEADER void DrawCoordinateCross (); DLL_HEADER void DrawNetgenLogo (); DLL_HEADER void SetOpenGlColor(double val, double valmin, double valmax, int logscale = 0); #ifdef PARALLELGL DLL_HEADER void InitParallelGL (); DLL_HEADER void Broadcast (); #endif }; DLL_HEADER extern void MyOpenGLText (const char * text); DLL_HEADER extern void Set_OpenGLText_Callback ( void (*fun) (const char * text) ); class VisualSceneSurfaceMeshing : public VisualScene { public: VisualSceneSurfaceMeshing (); virtual ~VisualSceneSurfaceMeshing (); virtual void BuildScene (int zoomall = 0); virtual void DrawScene (); }; class VisualSceneMesh : public VisualScene { int filledlist; int linelist; int edgelist; int pointnumberlist; int tetlist; int prismlist; int pyramidlist; int hexlist; int badellist; int identifiedlist; int domainsurflist; int vstimestamp;//, selecttimestamp; int filledtimestamp; int linetimestamp; int edgetimestamp; int pointnumbertimestamp; int tettimestamp; int prismtimestamp; int pyramidtimestamp; int hextimestamp; int badeltimestamp; int identifiedtimestamp; int domainsurftimestamp; #ifdef PARALLELGL Array par_linelists; Array par_filledlists; #endif MouseEventHandler * user_me_handler; NgLock *lock; // int selface, selelement; // int selpoint, selpoint2, locpi; // int seledge; double minh, maxh; // for meshsize coloring // weak_ptr wp_mesh; public: DLL_HEADER VisualSceneMesh (); DLL_HEADER virtual ~VisualSceneMesh (); DLL_HEADER virtual void BuildScene (int zoomall = 0); DLL_HEADER virtual void DrawScene (); DLL_HEADER virtual void MouseDblClick (int px, int py); // void SetMesh (shared_ptr mesh) { wp_mesh = mesh; } // shared_ptr GetMesh () { return shared_ptr(wp_mesh); } shared_ptr GetMesh () const { return shared_ptr(global_mesh); } void SetMouseEventHandler (MouseEventHandler * handler) { user_me_handler = handler; } DLL_HEADER int SelectedFace () const { return selface; } DLL_HEADER void SetSelectedFace (int asf); // { selface = asf; selecttimestamp = GetTimeStamp(); } DLL_HEADER int SelectedEdge () const { return seledge; } DLL_HEADER int SelectedElement () const { return selelement; } DLL_HEADER int SelectedPoint () const { return selpoint; } void BuildFilledList (bool names); // private: void BuildLineList(); void BuildEdgeList(); void BuildPointNumberList(); void BuildTetList(); void BuildPrismList(); void BuildPyramidList(); void BuildHexList(); void BuildBadelList(); void BuildIdentifiedList(); void BuildDomainSurfList(); }; DLL_HEADER extern VisualSceneMesh vsmesh; class DLL_HEADER VisualSceneSpecPoints : public VisualScene { public: VisualSceneSpecPoints (); virtual ~VisualSceneSpecPoints (); virtual void BuildScene (int zoomall = 0); virtual void DrawScene (); double len; }; // extern struct Tcl_Interp * hinterp; extern void AddVisualizationScene (const string & name, VisualScene * vs); void MouseDblClickSelect (const int px, const int py, const GLdouble * clipplane, const GLdouble backcolor, const double * transformationmat, const Point3d & center, const double rad, const int displaylist, int & selelement, int & selface, int & seledge, PointIndex & selpoint, PointIndex & selpoint2, int & locpi); } #endif netgen-6.2.1905/libsrc/visualization/soldata.hpp0000644000175000017500000000725013504650527020324 0ustar kurtkurt#ifndef FILE_SOLDATA #define FILE_SOLDATA #include // for tAVX namespace netgen { using namespace std; /* #if defined __AVX512F__ typedef __m512 tAVX; typedef __m512d tAVXd; #elif defined __AVX__ typedef __m256 tAVX; typedef __m256d tAVXd; #endif */ class SolutionData { protected: string name; int components; bool iscomplex; int multidimcomponent; public: SolutionData (const string & aname, int acomponents = 1, bool aiscomplex = 0) : name(aname), components(acomponents), iscomplex(aiscomplex) { ; } virtual ~SolutionData () { ; } int GetComponents() { return components; } bool IsComplex() { return iscomplex; } virtual bool GetValue (int /* elnr */, double /* lam1 */, double /* lam2 */, double /* lam3 */, double * /* values */) { return false; } virtual bool GetValue (int selnr, const double xref[], const double x[], const double dxdxref[], double * values) { return GetValue (selnr, xref[0], xref[1], xref[2], values); } virtual bool GetMultiValue (int elnr, int facetnr, int npts, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * values, int svalues) { bool res = false; for (int i = 0; i < npts; i++) res = GetValue (elnr, &xref[i*sxref], &x[i*sx], &dxdxref[i*sdxdxref], &values[i*svalues]); return res; } virtual bool GetSurfValue (int /* selnr */, int facetnr, double /* lam1 */, double /* lam2 */, double * /* values */) { return false; } virtual bool GetSurfValue (int selnr, int facetnr, const double xref[], const double x[], const double dxdxref[], double * values) { return GetSurfValue (selnr, facetnr, xref[0], xref[1], values); } virtual bool GetMultiSurfValue (int selnr, int facetnr, int npts, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * values, int svalues) { bool res = false; for (int i = 0; i < npts; i++) res = GetSurfValue (selnr, facetnr, &xref[i*sxref], &x[i*sx], &dxdxref[i*sdxdxref], &values[i*svalues]); return res; } #ifdef __SSE__ virtual bool GetMultiSurfValue (size_t selnr, size_t facetnr, size_t npts, const ngsimd::tAVXd * xref, const ngsimd::tAVXd * x, const ngsimd::tAVXd * dxdxref, ngsimd::tAVXd * values) { cerr << "GetMultiSurfVaue not overloaded for SIMD" << endl; return false; } #endif virtual bool GetSegmentValue (int segnr, double xref, double * values) { return false; } virtual int GetNumMultiDimComponents () { return 1; } virtual void SetMultiDimComponent (int mc) { if (mc >= GetNumMultiDimComponents()) mc = GetNumMultiDimComponents()-1; if (mc < 0) mc = 0; multidimcomponent = mc; } }; class DLL_HEADER MouseEventHandler { public: virtual void DblClick (int elnr, double x, double y, double z) = 0; }; class DLL_HEADER UserVisualizationObject { public: virtual void Draw () = 0; }; } #endif netgen-6.2.1905/libsrc/visualization/vssolution.hpp0000644000175000017500000002577013504650527021131 0ustar kurtkurt#ifndef FILE_VSSOLUTION #define FILE_VSSOLUTION typedef void * ClientData; struct Tcl_Interp; namespace netgen { DLL_HEADER extern void ImportSolution (const char * filename); class FieldLineCalc; extern int Ng_Vis_Set (ClientData clientData, Tcl_Interp * interp, int argc, const char *argv[]); class DLL_HEADER VisualSceneSolution : public VisualScene { friend class FieldLineCalc; class ClipPlaneTrig { public: struct ps { int pnr, locpnr; }; ps points[3]; ElementIndex elnr; }; class ClipPlanePoint { public: ElementIndex elnr; Point<3> lami; Point<3> p; }; #ifndef WIN32 // use OpenGL vertex buffers from OpenGL 2.x // not supported by some drivers on windows // try on your own responsibility #define USE_BUFFERS #endif #ifdef USE_BUFFERS bool has_surfel_vbo = false; GLuint surfel_vbo[4]; // size_t surfel_vbo_size; #endif int surfellist; int linelist; int element1dlist; int clipplanelist_scal; int clipplanelist_vec; int isolinelist; int clipplane_isolinelist; int surface_vector_list; // int cone_list; int isosurface_list; int pointcurvelist; bool draw_fieldlines; bool drawpointcurves; bool draw_isosurface; int num_fieldlines; bool fieldlines_randomstart; int fieldlineslist; int num_fieldlineslists; int fieldlines_startarea; Array fieldlines_startarea_parameter; int fieldlines_startface; string fieldlines_filename; double fieldlines_reltolerance; int fieldlines_rktype; double fieldlines_rellength; double fieldlines_relthickness; int fieldlines_vecfunction; bool fieldlines_fixedphase; float fieldlines_phase; int fieldlines_maxpoints; int surfeltimestamp, clipplanetimestamp, solutiontimestamp; int surfellinetimestamp; int fieldlinestimestamp, surface_vector_timestamp; int pointcurve_timestamp; int isosurface_timestamp; int subdivision_timestamp; int timetimestamp; double minval, maxval; NgLock *lock; #ifdef PARALLELGL Array par_linelists; Array par_surfellists; #endif Array user_vis; public: enum EvalFunc { FUNC_ABS = 1, FUNC_ABS_TENSOR = 2, FUNC_MISES = 3, FUNC_MAIN = 4 }; int evalfunc; enum SolType { SOL_NODAL = 1, SOL_ELEMENT = 2, SOL_SURFACE_ELEMENT = 3, SOL_NONCONTINUOUS = 4, SOL_SURFACE_NONCONTINUOUS = 5, SOL_VIRTUALFUNCTION = 6, SOL_MARKED_ELEMENTS = 10, SOL_ELEMENT_ORDER = 11, }; class SolData { public: SolData (); ~SolData (); string name; double * data; int components; int dist; int order; bool iscomplex; bool draw_volume; bool draw_surface; SolType soltype; SolutionData * solclass; // internal variables: int size; }; Array soldata; int usetexture; // 0..no, 1..1D texture (standard), 2..2D-texture (complex) int clipsolution; // 0..no, 1..scal, 2..vec int scalfunction, scalcomp, vecfunction; int gridsize; double xoffset, yoffset; int autoscale, logscale; double mminval, mmaxval; int numisolines; int subdivisions; bool showclipsolution; bool showsurfacesolution; bool lineartexture; int numtexturecols; int multidimcomponent; // bool fieldlineplot; double time; int deform; double scaledeform; bool imag_part; private: void BuildFieldLinesFromFile(Array & startpoints); void BuildFieldLinesFromFace(Array & startpoints); void BuildFieldLinesFromBox(Array & startpoints); void BuildFieldLinesFromLine(Array & startpoints); // weak_ptr wp_mesh; public: VisualSceneSolution (); virtual ~VisualSceneSolution (); virtual void BuildScene (int zoomall = 0); virtual void DrawScene (); virtual void MouseDblClick (int px, int py); // void SetMesh (shared_ptr amesh); // shared_ptr GetMesh () { return shared_ptr(wp_mesh); } shared_ptr GetMesh () const { return shared_ptr(global_mesh); } void BuildFieldLinesPlot (); void AddSolutionData (SolData * soldata); void ClearSolutionData (); void UpdateSolutionTimeStamp (); SolData * GetSolData (int i); int GetNSolData () { return soldata.Size(); } void SaveSolutionData (const char * filename); /* static void RealVec3d (const double * values, Vec3d & v, bool iscomplex, bool imag); */ static Vec<3> RealVec3d (const double * values, bool iscomplex, bool imag); static void RealVec3d (const double * values, Vec3d & v, bool iscomplex, double phaser, double phasei); void SetSubdivision (int sd) { subdivisions = sd; subdivision_timestamp = solutiontimestamp = NextTimeStamp(); } void GetMinMax (int funcnr, int comp, double & minv, double & maxv) const; void AddUserVisualizationObject (UserVisualizationObject * vis) { user_vis.Append (vis); } private: void GetClippingPlaneTrigs (Array & trigs, Array & pts); void GetClippingPlaneGrid (Array & pts); void DrawCone (const Point<3> & p1, const Point<3> & p2, double r); void DrawCylinder (const Point<3> & p1, const Point<3> & p2, double r); // Get Function Value, local coordinates lam1, lam2, lam3, bool GetValue (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, int comp, double & val) const; bool GetValue (const SolData * data, ElementIndex elnr, const double xref[], const double x[], const double dxdxref[], int comp, double & val) const; bool GetValueComplex (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, int comp, complex & val) const; bool GetValues (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, double * values) const; bool GetValues (const SolData * data, ElementIndex elnr, const double xref[], const double x[], const double dxdxref[], double * values) const; bool GetMultiValues (const SolData * data, ElementIndex elnr, int facetnr, int npt, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * val, int sval) const; bool GetSurfValue (const SolData * data, SurfaceElementIndex elnr, int facetnr, double lam1, double lam2, int comp, double & val) const; bool GetSurfValue (const SolData * data, SurfaceElementIndex elnr, int facetnr, const double xref[], const double x[], const double dxdxref[], int comp, double & val) const; bool GetSurfValueComplex (const SolData * data, SurfaceElementIndex elnr, int facetnr, double lam1, double lam2, int comp, complex & val) const; bool GetSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, double lam1, double lam2, double * values) const; bool GetSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, const double xref[], const double x[], const double dxdxref[], double * values) const; bool GetMultiSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, int npt, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * val, int sval) const; double ExtractValue (const SolData * data, int comp, double * values) const; complex ExtractValueComplex (const SolData * data, int comp, double * values) const; Vec<3> GetDeformation (ElementIndex elnr, const Point<3> & p) const; Vec<3> GetSurfDeformation (SurfaceElementIndex selnr, int facetnr, double lam1, double lam2) const; void GetPointDeformation (int pnum, Point<3> & p, SurfaceElementIndex elnr = -1) const; public: /// draw elements (build lists) void DrawSurfaceElements (); void DrawSurfaceElementLines (); void Draw1DElements(); void DrawSurfaceVectors (); void DrawTrigSurfaceVectors(const Array< Point<3> > & lp, const Point<3> & pmin, const Point<3> & pmax, const int sei, const SolData * vsol); void DrawIsoSurface(const SolData * sol, const SolData * grad, int comp); void DrawIsoLines (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, double val1, double val2, double val3); // draw isolines between lines (p1,p2) and (p3,p4) void DrawIsoLines2 (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, const Point<3> & p4, double val1, double val2, double val3, double val4); void DrawClipPlaneTrigs (); // const SolData * sol, int comp); void SetOpenGlColor(double val); // 0 .. non, 1 .. scalar, 2 .. complex void SetTextureMode (int texturemode) const; friend int Ng_Vis_Set (ClientData clientData, Tcl_Interp * interp, int argc, const char *argv[]); #ifdef PARALLELGL void Broadcast (); #endif }; class RKStepper { private: Array c,b; TABLE *a; int steps; int order; double tolerance; Array K; int stepcount; double h; double startt; double startt_bak; Point3d startval; Point3d startval_bak; bool adaptive; int adrun; Point3d valh; int notrestarted; public: ~RKStepper(); RKStepper(int type = 0); void SetTolerance(const double tol){tolerance = tol;} void StartNextValCalc(const Point3d & astartval, const double astartt, const double ah, const bool aadaptive = false); bool GetNextData(Point3d & val, double & t, double & ah); bool FeedNextF(const Vec3d & f); }; class FieldLineCalc { private: const Mesh & mesh; VisualSceneSolution & vss; const VisualSceneSolution::SolData * vsol; RKStepper stepper; double maxlength; int maxpoints; int direction; Point3d pmin, pmax; double rad; double phaser, phasei; double critical_value; bool randomized; double thickness; public: FieldLineCalc(const Mesh & amesh, VisualSceneSolution & avss, const VisualSceneSolution::SolData * solution, const double rel_length, const int amaxpoints = -1, const double rel_thickness = -1, const double rel_tolerance = -1, const int rk_type = 0, const int adirection = 0); void SetPhase(const double real, const double imag) { phaser = real; phasei = imag; } void SetCriticalValue(const double val) { critical_value = val; } void Randomized(void) { randomized = true; } void NotRandomized(void) { randomized = false; } void Calc(const Point3d & startpoint, Array & points, Array & vals, Array & drawelems, Array & dirstart); void GenerateFieldLines(Array & potential_startpoints, const int numlines, const int gllist, const double minval, const double maxval, const int logscale, double phaser, double phasei); }; // DLL_HEADER extern VisualSceneSolution vssolution; DLL_HEADER extern VisualSceneSolution & GetVSSolution(); } #endif netgen-6.2.1905/libsrc/visualization/stlmeshing.cpp0000644000175000017500000006650313504650527021053 0ustar kurtkurt#include #include #include #include #include #ifndef NOTCL #include #endif namespace netgen { /* //mmm #include "stlgeom/modeller.hpp" */ /* *********************** Draw STL Geometry **************** */ extern STLGeometry * stlgeometry; extern AutoPtr mesh; #ifdef OPENGL // #include "../../ngtcltk/mvdraw.hpp" VisualSceneSTLMeshing :: VisualSceneSTLMeshing () : VisualScene() { selecttrig = 0; nodeofseltrig = 1; stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); } VisualSceneSTLMeshing :: ~VisualSceneSTLMeshing () { ; } void VisualSceneSTLMeshing :: DrawScene () { int i, j, k; if (changeval != stlgeometry->GetNT()) BuildScene(); changeval = stlgeometry->GetNT(); int colormeshsize = vispar.colormeshsize; double hmin = 0.0, hmax = 1.0; if (colormeshsize) { hmax = -1E50; hmin = +1E50; double ms; for (i = 1; i <= stlgeometry->GetNP(); i++) { ms = mesh->GetH (stlgeometry->GetPoint(i)); hmin = min2(hmin,ms); hmax = max2(hmax,ms); } //hmax = mparam.maxh; //hmin = mesh->GetMinH (stlgeometry->GetBoundingBox().PMin(), // stlgeometry->GetBoundingBox().PMax()); if (hmin == 0) hmin = 0.1 * hmax; //hmax *= 1.1; } glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixf (transformationmat); SetClippingPlane (); glShadeModel (GL_SMOOTH); glDisable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float mat_spec_col[] = { 1, 1, 1, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col); double shine = vispar.shininess; // double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); float mat_colred[] = { 0.9f, 0.0f, 0.0f, 1.0f }; float mat_colgreen[] = { 0.0f, 0.9f, 0.0f, 1.0f }; float mat_colblue[] = { 0.1f, 0.1f, 1.0f, 1.0f }; float mat_colbluegreen[] = { 0.1f, 0.5f, 0.9f, 1.0f }; // float mat_colpink[] = { 1.0f, 0.1f, 0.5f, 1.0f }; float mat_colviolet[] = { 1.0f, 0.1f, 1.0f, 1.0f }; float mat_colbrown[] = { 0.8f, 0.6f, 0.1f, 1.0f }; // float mat_colorange[] = { 0.9f, 0.7f, 0.1f, 1.0f }; // float mat_colturquis[] = { 0.0f, 1.0f, 0.8f, 1.0f }; float mat_colgrey[] = { 0.3f, 0.3f, 0.3f, 1.0f }; float mat_collred[] = { 1.0f, 0.5f, 0.5f, 1.0f }; float mat_collgreen[] = { 0.2f, 1.9f, 0.2f, 1.0f }; float mat_collbrown[] = { 1.0f, 0.8f, 0.3f, 1.0f }; float mat_collgrey[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // float mat_colmgrey[] = { 0.4f, 0.4f, 0.4f, 1.0f }; float mat_colstlbody[] = { 0.0f, 0.0f, 0.8f, 1.0f }; float mat_colseltrig[] = { 0.7f, 0.7f, 0.3f, 1.0f }; float mat_colseledge[] = { 0.7f, 0.7f, 1.0f, 1.0f }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colblue); float pgoff = 0.5f; glPolygonOffset (pgoff*1, pgoff*1); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_NORMALIZE); /* { //mmm //test modeller Modeller model; //MoZylinder z1(Point3d(0,0,0),Vec3d(100,0,0),20,0.01); //model.Add(&z1); //MoZylinder z2(Point3d(50,50,0),Vec3d(0,-100,0),20,0.01); //model.Add(&z2); MoZylinder z1(Point3d(0,0,0),Vec3d(100,0,0),20,0.01); MoZylinder z2(Point3d(50,50,0),Vec3d(0,-100,0),20,0.01); MoCombine cb1(&z1,&z2); model.Add(&cb1); Array trigs; model.GetTriangles(trigs); int i, k; glBegin (GL_TRIANGLES); for (i = 1; i <= trigs.Size(); i++) { const MoTriangle & tria = trigs.Get(i); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); for (k = 0; k < 3; k++) { glVertex3f (tria.pts[k].X(), tria.pts[k].Y(), tria.pts[k].Z()); } } glEnd (); } */ if (!stlgeometry->trigsconverted) { glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { /* if (j % 10 == seltria) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); */ const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 1; k <= 3; k++) { const Point3d & tp = stlgeometry->GetPoint(stlgeometry->GetTriangle(j).PNum(k)); glVertex3f (tp.X(), tp.Y(), tp.Z()); } /* if (j%10 == seltria) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colblue); */ } glEnd (); glDisable (GL_POLYGON_OFFSET_FILL); int showtrias = vispar.stlshowtrias; if (showtrias) { float mat_coll[] = { 0.2f, 0.2f, 0.2f, 1.f }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_coll); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 1; k <= 3; k++) { const Point3d & tp = stlgeometry->GetPoint(stlgeometry->GetTriangle(j).PNum(k)); glVertex3f (tp.X(), tp.Y(), tp.Z()); } /* for (k = 0; k < 3; k++) { glVertex3f (tria.pts[k].X(), tria.pts[k].Y(), tria.pts[k].Z()); } */ } glEnd (); } } else { int showfilledtrias = vispar.stlshowfilledtrias; //(*mycout) << "in " << showfilledtrias << ", NT=" << stlgeometry -> GetNT() << endl; int chartnumber; if (vispar.stlshowmarktrias) chartnumber = vispar.stlchartnumber + vispar.stlchartnumberoffset; else chartnumber = stlgeometry->GetMeshChartNr(); if (showfilledtrias) { glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); if (colormeshsize) glEnable (GL_COLOR_MATERIAL); glPolygonOffset (pgoff*4, pgoff*4); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); int selt = stlgeometry -> GetSelectTrig(); if (stldoctor.selectmode != 0) {selt = 0; } //do not show selected triangle!!!! glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colstlbody); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} if (j == selt) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colseltrig); } else if (j == selt+1) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colstlbody); } const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { const Point3d & p = stlgeometry->GetPoint(st[k]); if (colormeshsize) { SetOpenGlColor (mesh->GetH (p), hmin, hmax, 1); } glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd (); } int foundseltrig = stlgeometry -> GetSelectTrig(); if (foundseltrig == 0 || foundseltrig > stlgeometry->GetNT() || (stldoctor.showvicinity && !stlgeometry->Vicinity(foundseltrig))) {foundseltrig = 0;} if (foundseltrig) { glPolygonOffset (pgoff*0, 0); glEnable (GL_POLYGON_OFFSET_FILL); //glDisable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colseledge); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glEnable (GL_NORMALIZE); if (stldoctor.selectmode == 2) { //point const STLTriangle& st = stlgeometry -> GetTriangle(foundseltrig); const Point3d & p1 = stlgeometry->GetPoint(st[0]); const Point3d & p2 = stlgeometry->GetPoint(st[1]); const Point3d & p3 = stlgeometry->GetPoint(st[2]); double cs = (Dist(p1,p2)+Dist(p2,p3)+Dist(p3,p1))/100.; const Point3d & p = stlgeometry->GetPoint(st[nodeofseltrig-1]); glLineWidth (4); glBegin (GL_LINES); glVertex3f(p.X()+cs, p.Y()+cs, p.Z()+cs); glVertex3f(p.X()-cs, p.Y()-cs, p.Z()-cs); glVertex3f(p.X()-cs, p.Y()+cs, p.Z()+cs); glVertex3f(p.X()+cs, p.Y()-cs, p.Z()-cs); glVertex3f(p.X()-cs, p.Y()+cs, p.Z()+cs); glVertex3f(p.X()+cs, p.Y()-cs, p.Z()-cs); glVertex3f(p.X()+cs, p.Y()-cs, p.Z()+cs); glVertex3f(p.X()-cs, p.Y()+cs, p.Z()-cs); glEnd (); glLineWidth (1); } else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { //multiedge const Array& me = stlgeometry->SelectedMultiEdge(); if (stlgeometry->GetSelectTrig() > 0 && stlgeometry->GetSelectTrig() <= stlgeometry->GetNT() && me.Size()) { int en = stlgeometry->EdgeDataList().GetEdgeNum(me.Get(1).i1,me.Get(1).i2); int status = stlgeometry->EdgeDataList().Get(en).GetStatus(); switch (status) { case ED_CONFIRMED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collgreen); break; case ED_CANDIDATE: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collbrown); break; case ED_EXCLUDED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collred); break; } glLineWidth (2); glBegin (GL_LINES); for (j = 1; j <= me.Size(); j++) { Point3d p1 = stlgeometry->GetPoint(me.Get(j).i1); Point3d p2 = stlgeometry->GetPoint(me.Get(j).i2); glVertex3f(p1.X(), p1.Y(), p1.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } glEnd (); glLineWidth (1); } } } int showmarktrias = vispar.stlshowmarktrias || vispar.stlshowactivechart; if (stldoctor.showmarkedtrigs) { //(*mycout) << "marked" << endl; glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); //GL_LINE glPolygonOffset (pgoff*1, pgoff*1); glEnable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbluegreen); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} if (!stlgeometry->IsMarkedTrig(j)) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { const Point3d & p = stlgeometry->GetPoint(st[k]); glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd (); //show OpenSegments on original geometry glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colviolet); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glPolygonOffset (pgoff*1, 1); glEnable (GL_NORMALIZE); glBegin (GL_LINES); if (stlgeometry->GetNMarkedSegs()) { Point<3> p1,p2; for (j = 1; j <= stlgeometry -> GetNMarkedSegs(); j++) { stlgeometry->GetMarkedSeg(j,p1,p2); glVertex3dv(&p1(0)); glVertex3dv(&p2(0)); } } glEnd (); } if (stldoctor.showfaces) { int facenumber = vispar.stlchartnumber + vispar.stlchartnumberoffset; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (pgoff*3, 3); glEnable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_collgrey); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} //(*mycout) << " facenum = " << stlgeometry->GetTriangle(j).GetFaceNum() << " "; if (stlgeometry->GetTriangle(j).GetFaceNum() != facenumber) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { Point3d p = stlgeometry->GetPoint(st[k]); glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd (); } if (showmarktrias && stlgeometry->AtlasMade()) { glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (pgoff*3, 3); glEnable (GL_POLYGON_OFFSET_FILL); glBegin (GL_TRIANGLES); if (chartnumber >= 1 && chartnumber <= stlgeometry->GetNOCharts()) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown); const STLChart& chart = stlgeometry->GetChart(chartnumber); for (j = 1; j <= chart.GetNChartT(); j++) { /* if (j == charttrignumber) {glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred);} else {glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown);} */ const STLTriangle& st = stlgeometry -> GetTriangle(chart.GetChartTrig(j)); const Vec3d & n = stlgeometry->GetTriangle(chart.GetChartTrig(j)).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(chart.GetChartTrig(j)); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { glVertex3f (stlgeometry->GetPoint(st[k])(0), stlgeometry->GetPoint(st[k])(1), stlgeometry->GetPoint(st[k])(2)); } } glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); for (j = 1; j <= chart.GetNOuterT(); j++) { const STLTriangle& st = stlgeometry -> GetTriangle(chart.GetOuterTrig(j)); const Vec3d & n = stlgeometry->GetTriangle(chart.GetOuterTrig(j)).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(chart.GetOuterTrig(j)); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { glVertex3f (stlgeometry->GetPoint(st[k])(0), stlgeometry->GetPoint(st[k])(1), stlgeometry->GetPoint(st[k])(2)); } } } glEnd (); } int showtrias = vispar.stlshowtrias; if (showtrias) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgrey); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glPolygonOffset (pgoff*2, 2); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_NORMALIZE); glBegin (GL_TRIANGLES); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); const Vec3d & n = stlgeometry->GetTriangle(j).Normal(); glNormal3f (n.X(), n.Y(), n.Z()); /* const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); */ for (k = 0; k < 3; k++) { glVertex3f (stlgeometry->GetPoint(st[k])(0), stlgeometry->GetPoint(st[k])(1), stlgeometry->GetPoint(st[k])(2)); } } glEnd (); } int showedges = vispar.stlshowedges; if (showedges) { glPolygonOffset (pgoff*1, 1); glEnable (GL_POLYGON_OFFSET_FILL); //glDisable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glEnable (GL_NORMALIZE); glBegin (GL_LINES); /* if (stldoctor.useexternaledges) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colorange); for (j = 1; j <= stlgeometry -> NOExternalEdges(); j++) { twoint v = stlgeometry->GetExternalEdge(j); Point3d p1 = stlgeometry->GetPoint(v.i1); Point3d p2 = stlgeometry->GetPoint(v.i2); Vec3d n1 = stlgeometry->GetNormal(v.i1); Vec3d n2 = stlgeometry->GetNormal(v.i2); glNormal3f(n1.X(), n1.Y(), n1.Z()); glVertex3f(p1.X(), p1.Y(), p1.Z()); glNormal3f(n2.X(), n2.Y(), n2.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } } */ if (!stlgeometry->meshlines.Size() || !stldoctor.drawmeshededges) { /* for (j = 1; j <= stlgeometry -> GetNE(); j++) { STLEdge v = stlgeometry->GetEdge(j); Point3d p1 = stlgeometry->GetPoint(v.pts[0]); Point3d p2 = stlgeometry->GetPoint(v.pts[1]); Vec3d n1 = stlgeometry->GetNormal(v.pts[0]); Vec3d n2 = stlgeometry->GetNormal(v.pts[1]); glNormal3f(n1.X(), n1.Y(), n1.Z()); glVertex3f(p1.X(), p1.Y(), p1.Z()); glNormal3f(n2.X(), n2.Y(), n2.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } */ const STLEdgeDataList& ed = stlgeometry->EdgeDataList(); for (i = 1; i <= ed.Size(); i++) { if (ed.Get(i).GetStatus() != ED_UNDEFINED) { switch (ed.Get(i).GetStatus()) { case ED_CONFIRMED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); break; case ED_CANDIDATE: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbrown); break; case ED_EXCLUDED: glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); break; } if (ed.Get(i).GetStatus() == ED_EXCLUDED && !stldoctor.showexcluded) continue; Point3d p1 = stlgeometry->GetPoint(ed.Get(i).PNum(1)); Point3d p2 = stlgeometry->GetPoint(ed.Get(i).PNum(2)); glVertex3f(p1.X(), p1.Y(), p1.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } } } /* else if (stlgeometry->meshlines.Size() == 0) { for (j = 1; j <= stlgeometry->GetNLines(); j++) { STLLine* line = stlgeometry->GetLine(j); int pn1, pn2; for (int k = 1; k <= line->NP()-1; k++) { pn1 = line->PNum(k); pn2 = line->PNum(k+1); Point3d p1 = stlgeometry->GetPoint(pn1); Point3d p2 = stlgeometry->GetPoint(pn2); Vec3d n1 = stlgeometry->GetNormal(pn1); Vec3d n2 = stlgeometry->GetNormal(pn2); glNormal3f(n1.X(), n1.Y(), n1.Z()); glVertex3f(p1.X(), p1.Y(), p1.Z()); glNormal3f(n2.X(), n2.Y(), n2.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); } } } */ else if (stlgeometry->meshlines.Size() != 0) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); for (j = 1; j <= stlgeometry->meshlines.Size(); j++) { STLLine* line = stlgeometry->meshlines.Get(j); int pn1, pn2; for (int k = 1; k <= line->NP()-1; k++) { pn1 = line->PNum(k); pn2 = line->PNum(k+1); Point3d p1 = stlgeometry->meshpoints.Get(pn1); Point3d p2 = stlgeometry->meshpoints.Get(pn2); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colgreen); glVertex3f(p1.X(), p1.Y(), p1.Z()); glVertex3f(p2.X(), p2.Y(), p2.Z()); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); double cs = 0.02*Dist(p1,p2); glVertex3f(p1.X()+cs, p1.Y()+cs, p1.Z()+cs); glVertex3f(p1.X()-cs, p1.Y()-cs, p1.Z()-cs); glVertex3f(p2.X()+cs, p2.Y()+cs, p2.Z()+cs); glVertex3f(p2.X()-cs, p2.Y()-cs, p2.Z()-cs); glVertex3f(p1.X()-cs, p1.Y()+cs, p1.Z()+cs); glVertex3f(p1.X()+cs, p1.Y()-cs, p1.Z()-cs); glVertex3f(p2.X()-cs, p2.Y()+cs, p2.Z()+cs); glVertex3f(p2.X()+cs, p2.Y()-cs, p2.Z()-cs); } } } glEnd (); } if (stldoctor.showedgecornerpoints && stlgeometry->LineEndPointsSet()) { glPointSize (5); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colred); glBegin (GL_POINTS); for (i = 1; i <= stlgeometry->GetNP(); i++) { if (stlgeometry->IsLineEndPoint(i)) { const Point3d p = stlgeometry->GetPoint(i); glVertex3f (p.X(), p.Y(), p.Z()); } } glEnd(); } } glPopMatrix(); if (vispar.colormeshsize) DrawColorBar (hmin, hmax, 1); glFinish(); } void VisualSceneSTLMeshing :: BuildScene (int zoomall) { if (selecttrig && zoomall == 2) center = stlgeometry -> GetPoint ( stlgeometry->GetTriangle(selecttrig).PNum(nodeofseltrig)); else center = stlgeometry -> GetBoundingBox().Center(); rad = stlgeometry -> GetBoundingBox().Diam() / 2; CalcTransformationMatrices(); } void VisualSceneSTLMeshing :: MouseDblClick (int px, int py) { // (*mycout) << "dblclick: " << px << " - " << py << endl; int i, j, k, hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); /* (*mycout) << "viewport = " << viewport[0] << " " << viewport[1] << " " << viewport[2] << " " << viewport[3] << endl; */ glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixf (transformationmat); glInitNames(); glPushName (1); glEnable (GL_POLYGON_OFFSET_FILL); for (j = 1; j <= stlgeometry -> GetNT(); j++) { if (stldoctor.showvicinity && !stlgeometry->Vicinity(j)) {continue;} const STLTriangle& st = stlgeometry -> GetTriangle(j); //const STLReadTriangle& tria = stlgeometry -> GetReadTriangle(j); //glNormal3f (tria.normal.X(), tria.normal.Y(), tria.normal.Z()); if (stldoctor.selectmode == 0) { glLoadName (j); glBegin (GL_TRIANGLES); for (k = 0; k < 3; k++) { Point3d p = stlgeometry->GetPoint(st[k]); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd (); } else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { Point3d pm = Center(stlgeometry->GetPoint(st[0]), stlgeometry->GetPoint(st[1]), stlgeometry->GetPoint(st[2])); for (k = 0; k < 3; k++) { glLoadName (j*3+k-2); glBegin (GL_TRIANGLES); Point3d p1 = stlgeometry->GetPoint(st[k]); Point3d p2 = stlgeometry->GetPoint(st[(k+1)%3]); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (p2.X(), p2.Y(), p2.Z()); glVertex3f (pm.X(), pm.Y(), pm.Z()); glEnd (); } } else { Point3d pm1 = Center(stlgeometry->GetPoint(st[0]), stlgeometry->GetPoint(st[1])); Point3d pm2 = Center(stlgeometry->GetPoint(st[1]), stlgeometry->GetPoint(st[2])); Point3d pm3 = Center(stlgeometry->GetPoint(st[2]), stlgeometry->GetPoint(st[0])); Point3d p1 = stlgeometry->GetPoint(st[0]); Point3d p2 = stlgeometry->GetPoint(st[1]); Point3d p3 = stlgeometry->GetPoint(st[2]); glLoadName (j*4-3); glBegin (GL_TRIANGLES); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (pm1.X(), pm1.Y(), pm1.Z()); glVertex3f (pm3.X(), pm3.Y(), pm3.Z()); glEnd (); glLoadName (j*4-2); glBegin (GL_TRIANGLES); glVertex3f (p2.X(), p2.Y(), p2.Z()); glVertex3f (pm2.X(), pm2.Y(), pm2.Z()); glVertex3f (pm1.X(), pm1.Y(), pm1.Z()); glEnd (); glLoadName (j*4-1); glBegin (GL_TRIANGLES); glVertex3f (p3.X(), p3.Y(), p3.Z()); glVertex3f (pm3.X(), pm3.Y(), pm3.Z()); glVertex3f (pm2.X(), pm2.Y(), pm2.Z()); glEnd (); glLoadName (j*4); glBegin (GL_TRIANGLES); glVertex3f (pm1.X(), pm1.Y(), pm1.Z()); glVertex3f (pm2.X(), pm2.Y(), pm2.Z()); glVertex3f (pm3.X(), pm3.Y(), pm3.Z()); glEnd (); } } glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); // (*mycout) << "hits = " << hits << endl; //int minrec = -1; int minname = 0; GLuint mindepth = 0; for (i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; /* (*mycout) << selbuf[4*i] << " " << selbuf[4*i+1] << " " << selbuf[4*i+2] << " " << selbuf[4*i+3] << endl; */ if (curname && (curdepth < mindepth || !minname)) { //minrec = i; mindepth = curdepth; minname = curname; } } if (!minname) {return;} if (stldoctor.selectmode == 0) { int oldtrig = selecttrig; selecttrig = minname; if (selecttrig == oldtrig) nodeofseltrig = (nodeofseltrig % 3) + 1; else nodeofseltrig = 1; stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); stlgeometry->PrintSelectInfo(); } else if (stldoctor.selectmode == 1 || stldoctor.selectmode == 3 || stldoctor.selectmode == 4) { selecttrig = (minname-1) / 3 + 1; nodeofseltrig = minname-selecttrig*3+3; stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); stlgeometry->PrintSelectInfo(); if (stldoctor.selectmode == 1) { stlgeometry->BuildSelectedEdge(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig), stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1))); } if (stldoctor.selectmode == 3) { stlgeometry->BuildSelectedMultiEdge(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig), stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1))); } else if (stldoctor.selectmode == 4) { stlgeometry->BuildSelectedCluster(twoint(stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig), stlgeometry->GetTriangle(selecttrig).PNumMod(nodeofseltrig+1))); } switch (stldoctor.edgeselectmode) { case 1: stlgeometry->STLDoctorUndefinedEdge(); break; case 2: stlgeometry->STLDoctorConfirmEdge(); break; case 3: stlgeometry->STLDoctorCandidateEdge(); break; case 4: stlgeometry->STLDoctorExcludeEdge(); break; default: break; } } else if (stldoctor.selectmode == 2) { selecttrig = (minname-1) / 4 + 1; nodeofseltrig = minname-selecttrig*4+4; if (nodeofseltrig == 4) {nodeofseltrig = 1;} stlgeometry->SetSelectTrig(selecttrig); stlgeometry->SetNodeOfSelTrig(nodeofseltrig); stlgeometry->PrintSelectInfo(); } if (stldoctor.showtouchedtrigchart && stlgeometry->AtlasMade() && stlgeometry->GetSelectTrig()) { vispar.stlchartnumber = stlgeometry->GetChartNr(stlgeometry->GetSelectTrig()); vispar.stlchartnumberoffset = 0; } } VisualSceneSTLMeshing vsstlmeshing; #endif } netgen-6.2.1905/libsrc/visualization/mvdraw.cpp0000644000175000017500000004632313504650527020174 0ustar kurtkurt#include #include #include #include // #include #ifndef WIN32 #define GLX_GLXEXT_LEGACY #include #include #include /* for XA_RGB_DEFAULT_MAP atom */ // #include // for parallel GL ??? #endif namespace netgen { DLL_HEADER Point3d VisualScene :: center; DLL_HEADER double VisualScene :: rad; DLL_HEADER GLdouble VisualScene :: backcolor; /* #if TOGL_MAJOR_VERSION!=2 GLuint VisualScene :: fontbase = 0; #else Tcl_Obj * VisualScene :: fontbase = NULL; Togl * VisualScene :: globtogl; #endif */ void (*opengl_text_function)(const char * text) = NULL; void Set_OpenGLText_Callback ( void (*fun) (const char * text) ) { opengl_text_function = fun; } void MyOpenGLText (const char * text) { if (opengl_text_function) (*opengl_text_function) (text); // cout << "MyOpenGLText: " << text << endl; } // texture for color decoding // GLubyte * VisualScene :: colortexture = NULL; GLuint VisualScene :: coltexname = 1; int VisualScene :: ntexcols = -1; double VisualScene :: lookatmat[16]; double VisualScene :: transmat[16]; double VisualScene :: rotmat[16]; double VisualScene :: centermat[16]; double VisualScene :: transformationmat[16]; int VisualScene :: selface; int VisualScene :: selelement; PointIndex VisualScene :: selpoint; PointIndex VisualScene :: selpoint2; int VisualScene :: locpi; int VisualScene :: seledge; int VisualScene :: selecttimestamp; int VisualScene :: viewport[4]; VisualizationParameters :: VisualizationParameters() { lightamb = 0.3; lightdiff = 0.7; lightspec = 1; shininess = 50; transp = 0.3; locviewer = 0; showstltrias = 0; centerpoint = 0; usedispllists = 1; strcpy (selectvisual, "cross"); use_center_coords = false; }; VisualizationParameters vispar; double dist = 0; // double dist = 6; // vorher: pnear = 2; // double pnear = 0.1; // double pfar = 10; VisualScene :: VisualScene () { changeval = -1; backcolor = 0; } VisualScene :: ~VisualScene() { ; } extern DLL_HEADER void Render(bool blocking); DLL_HEADER void Render (bool blocking) { if (blocking && multithread.running) { multithread.redraw = 2; while (multithread.redraw == 2) ; } else multithread.redraw = 1; } void VisualScene :: BuildScene (int zoomall) { center = Point3d (0,0,0); rad = 1; CalcTransformationMatrices(); glEnable(GL_DEPTH_TEST); glDisable (GL_DITHER); GLfloat ambvals[] = { 0.4f, 0.4f, 0.4f, 1.0f }; GLfloat diffvals[] = { 0.5f, 0.5f, 0.5f, 1.0f }; GLfloat specvals[] = { 0.7f, 0.7f, 0.7f, 1.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, ambvals); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffvals); glLightfv(GL_LIGHT0, GL_SPECULAR, specvals); GLfloat light_position[] = { 1, 3, 3, 0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, 0); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } void VisualScene :: DrawScene () { if (changeval == -1) BuildScene(); changeval = 0; glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable (GL_COLOR_MATERIAL); glColor3f (1.0f, 1.0f, 1.0f); glLineWidth (1.0f); DrawCoordinateCross (); DrawNetgenLogo (); glFinish(); } void VisualScene :: CalcTransformationMatrices() { // prepare model view matrix glPushMatrix(); glLoadIdentity(); gluLookAt (0, 0, 6, 0, 0, 0, 0, 1, 0); glGetDoublev (GL_MODELVIEW_MATRIX, lookatmat); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -dist); glGetDoublev (GL_MODELVIEW_MATRIX, transmat); glLoadIdentity(); glGetDoublev (GL_MODELVIEW_MATRIX, rotmat); glScaled (1/rad, 1/rad, 1/rad); glTranslated (-center.X(), -center.Y(), -center.Z()); glGetDoublev (GL_MODELVIEW_MATRIX, centermat); glLoadIdentity(); glMultMatrixd (lookatmat); glMultMatrixd (transmat); glMultMatrixd (rotmat); glMultMatrixd (centermat); glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat); glPopMatrix(); } void VisualScene :: ArbitraryRotation (const Array & alpha, const Array & vec) { glPushMatrix(); glLoadIdentity(); for(int i=0; i a(1); a[0] = alpha; Array v(1); v[0] = vec; ArbitraryRotation(a,v); } void VisualScene :: StandardRotation (const char * dir) { glPushMatrix(); glLoadIdentity(); if (strcmp (dir, "xy") == 0) ; else if (strcmp (dir, "yx") == 0) glRotatef(180.0, 1.0f, 1.0f, 0.0f); else if (strcmp (dir, "xz") == 0) glRotatef(-90.0, 1.0f, 0.0f, 0.0f); else if (strcmp (dir, "zx") == 0) { glRotatef(180.0, 1.0f, 1.0f, 0.0f); glRotatef(-90.0, 1.0f, 0.0f, 0.0f); } else if (strcmp (dir, "yz") == 0) { glRotatef(-90.0, 0.0f, 0.0f, 1.0f); glRotatef(-90.0, 0.0f, 1.0f, 0.0f); } else if (strcmp (dir, "zy") == 0) glRotatef(90.0, 0.0f, 1.0f, 0.0f); glGetDoublev (GL_MODELVIEW_MATRIX, rotmat); glLoadIdentity(); glMultMatrixd (lookatmat); glMultMatrixd (transmat); glMultMatrixd (rotmat); glMultMatrixd (centermat); glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat); glPopMatrix(); } void VisualScene :: MouseMove(int oldx, int oldy, int newx, int newy, char mode) { int deltax = newx - oldx; int deltay = newy - oldy; glPushMatrix(); glLoadIdentity (); switch (mode) { case 'r': { glRotatef(float(deltax)/2, 0.0f, 1.0f, 0.0f); glRotatef(float(deltay)/2, 1.0f, 0.0f, 0.0f); glMultMatrixd (rotmat); glGetDoublev (GL_MODELVIEW_MATRIX, rotmat); break; } case 'm': { GLdouble projmat[16], modelviewmat[16]; GLint viewport[4]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glGetDoublev (GL_MODELVIEW_MATRIX, modelviewmat); glGetIntegerv (GL_VIEWPORT, viewport); // vorher pvz1/2 = 0 GLdouble pvx1 = 0, pvy1 = 0, pvz1 = 0.99; // 0.95; GLdouble pvx2 = deltax, pvy2 = -deltay, pvz2 = 0.99; // 0.95; GLdouble px1, py1, pz1; GLdouble px2, py2, pz2; gluUnProject (pvx1, pvy1, pvz1, modelviewmat, projmat, viewport, &px1, &py1, &pz1); gluUnProject (pvx2, pvy2, pvz2, modelviewmat, projmat, viewport, &px2, &py2, &pz2); /* gluUnProject (oldx, oldy, 1, modelviewmat, projmat, viewport, &px1, &py1, &pz1); gluUnProject (newx, newy, 1, modelviewmat, projmat, viewport, &px2, &py2, &pz2); */ /* cout << "pv1 = " << pvx1 << ", " << pvy1 << ", " << pvz1 << endl; cout << "p1 = " << px1 << ", " << py1 << ", " << pz1 << endl; */ glTranslated (px2-px1, py2-py1, pz2-pz1); glMultMatrixd (transmat); glGetDoublev (GL_MODELVIEW_MATRIX, transmat); break; } case 'z': { // glTranslatef(0.0f, 0.0f, -dist); // cout << "deltay = " << deltay << endl; // cout << "float_bug = " << (float(deltay)/100) << endl; gives wrong result with icc 9.0.021 glScaled (exp (double (-deltay)/100), exp (double (-deltay)/100), exp (double (-deltay)/100)); // glTranslatef(0.0f, 0.0f, dist); glMultMatrixd (transmat); glGetDoublev (GL_MODELVIEW_MATRIX, transmat); break; } } glLoadIdentity(); glMultMatrixd (lookatmat); glMultMatrixd (transmat); glMultMatrixd (rotmat); glMultMatrixd (centermat); glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat); glPopMatrix(); } void VisualScene :: LookAt (const Point<3> & cam, const Point<3> & obj, const Point<3> & camup) { glPushMatrix(); glLoadIdentity (); gluLookAt (cam(0), cam(1), cam(2), obj(0), obj(1), obj(2), camup(0), camup(1), camup(2)); glMultMatrixd (centermat); glGetDoublev (GL_MODELVIEW_MATRIX, transformationmat); glPopMatrix(); } void VisualScene :: SetClippingPlane () { if (vispar.clipping.enable) { Vec3d n = vispar.clipping.normal; n /= (n.Length()+1e-10); clipplane[0] = n.X(); clipplane[1] = n.Y(); clipplane[2] = n.Z(); clipplane[3] = -(Vec3d(center) * n) + rad * vispar.clipping.dist; double clipplane2[4]; clipplane2[0] = n.X(); clipplane2[1] = n.Y(); clipplane2[2] = n.Z(); clipplane2[3] = -(Vec3d(center) * n) + rad * (vispar.clipping.dist + vispar.clipping.dist2); glClipPlane(GL_CLIP_PLANE0, clipplane2); glEnable(GL_CLIP_PLANE0); } else glDisable (GL_CLIP_PLANE0); } void VisualScene :: MouseDblClick (int /* px */, int /* py */) { ; } void VisualScene :: SetLight() { GLfloat vals[3]; double lightamb = vispar.lightamb; vals[0] = vals[1] = vals[2] = lightamb; glLightfv(GL_LIGHT0, GL_AMBIENT, vals); double lightdiff = vispar.lightdiff; vals[0] = vals[1] = vals[2] = lightdiff; glLightfv(GL_LIGHT0, GL_DIFFUSE, vals); double lightspec = vispar.lightspec; vals[0] = vals[1] = vals[2] = lightspec; glLightfv(GL_LIGHT0, GL_SPECULAR, vals); glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, vispar.shininess); glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, vispar.locviewer); float mat_spec_col[] = { 1, 1, 1, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); } void VisualScene :: SetOpenGlColor(double val, double valmin, double valmax, int logscale) { double value; if (!logscale) value = (val - valmin) / (valmax - valmin); else { if (valmax <= 0) valmax = 1; if (valmin <= 0) valmin = 1e-4 * valmax; value = (log(fabs(val)) - log(valmin)) / (log(valmax) - log(valmin)); } if (!invcolor) value = 1 - value; glTexCoord1f ( 0.998 * value + 0.001); // glTexCoord1f ( val ); glTexCoord2f ( 0.998 * value + 0.001, 1.5); // glTexCoord1f ( value ); if (value > 1) value = 1; if (value < 0) value = 0; value *= 4; static const double colp[][3] = { { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 0, 1 }, // { 1, 0, 1 }, // { 1, 0, 0 }, }; int i = int(value); double r = value - i; GLdouble col[3]; for (int j = 0; j < 3; j++) col[j] = (1-r) * colp[i][j] + r * colp[i+1][j]; glColor3d (col[0], col[1], col[2]); } void VisualScene :: CreateTexture (int ncols, int linear, double alpha, int typ) { if (linear) ncols = 32; else ncols = 8; if (ntexcols != ncols) { ntexcols = ncols; GLubyte colortexture[4*32]; const double colp[][3] = { { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 0, 1 }, }; for (int i = 0; i < ncols; i++) { double value = 4.0 * i / (ncols-1); int iv = int(value); double r = value - iv; GLdouble col[3]; if(r > 1e-3) for (int j = 0; j < 3; j++) col[j] = (1.-r) * colp[iv][j] + r * colp[iv+1][j]; else for (int j = 0; j < 3; j++) col[j] = colp[iv][j]; colortexture[4*i] = GLubyte (255 * col[0]); colortexture[4*i+1] = GLubyte (255 * col[1]); colortexture[4*i+2] = GLubyte (255 * col[2]); colortexture[4*i+3] = GLubyte(255*alpha); } // glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glTexImage1D (GL_TEXTURE_1D, 0, 4, ncols, 0, GL_RGBA, GL_UNSIGNED_BYTE, colortexture); glTexImage2D (GL_TEXTURE_2D, 0, 4, ncols, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colortexture); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, typ); // DECAL or MODULATE GLfloat bcol[] = { 1, 1, 1, 1.0 }; glTexParameterfv (GL_TEXTURE_1D, GL_TEXTURE_BORDER_COLOR, bcol); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bcol); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (linear) { glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } } } void VisualScene :: DrawColorBar (double minval, double maxval, int logscale, bool linear) { if (!vispar.drawcolorbar) return; CreateTexture (8, linear, 1, GL_DECAL); if (logscale && maxval <= 0) maxval = 1; if (logscale && minval <= 0) minval = 1e-4 * maxval; double minx = -1; double maxx = 1; double miny = 0.75; double maxy = 0.8; glDisable (GL_LIGHTING); glEnable (GL_COLOR_MATERIAL); glEnable (GL_TEXTURE_1D); glNormal3d (0, 0, 1); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glDisable (GL_DEPTH_TEST); glBegin (GL_QUAD_STRIP); for (double x = minx; x <= maxx; x += (maxx - minx) / 50) { SetOpenGlColor (x, minx, maxx); glVertex3d (x, miny, -5); glVertex3d (x, maxy, -5); } glEnd(); glDisable (GL_TEXTURE_1D); glEnable (GL_COLOR_MATERIAL); GLfloat textcol[3] = { GLfloat(1 - backcolor), GLfloat(1 - backcolor), GLfloat(1 - backcolor) }; glColor3fv (textcol); glPushAttrib (GL_LIST_BIT); // glListBase (fontbase); char buf[20]; for (int i = 0; i <= 4; i++) { double x = minx + i * (maxx-minx) / 4; glRasterPos3d (x, 0.7,-5); double val; if (logscale) val = minval * pow (maxval / minval, i / 4.0); else val = minval + i * (maxval-minval) / 4; sprintf (buf, "%8.3e", val); // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); } glPopAttrib (); glEnable (GL_DEPTH_TEST); } void VisualScene :: DrawCoordinateCross () { if (!vispar.drawcoordinatecross) return; glDisable (GL_DEPTH_TEST); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glTranslatef (-1, -1, 0.0); glScalef (40.0 / viewport[2], 40.0 / viewport[3], 1); glTranslatef (2.0, 2.0, 0.0); glMultMatrixd (rotmat); glEnable (GL_COLOR_MATERIAL); glDisable (GL_LIGHTING); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); GLfloat textcol[3] = { GLfloat(1 - backcolor), GLfloat(1 - backcolor), GLfloat(1 - backcolor) }; glColor3fv (textcol); glLineWidth (1.0f); double len = 1; glBegin(GL_LINES); glVertex3d (0, 0, 0); glVertex3d (len, 0, 0); glVertex3d (0.0f, 0.0f, 0.0f); glVertex3d (0.0f, len, 0.0f); glVertex3d (0.0f, 0.0f, 0.0f); glVertex3d (0.0f, 0.0f, len); glEnd (); glPushAttrib (GL_LIST_BIT); // glListBase (fontbase); char buf[20]; glRasterPos3d (len, 0.0f, 0.0f); sprintf (buf, "x"); // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); glRasterPos3d (0.0f, len, 0.0f); sprintf (buf, "y"); // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); glRasterPos3d (0.0f, 0.0f, len); sprintf (buf, "z"); // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); glPopAttrib (); glEnable (GL_LIGHTING); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glEnable (GL_DEPTH_TEST); } void VisualScene :: DrawNetgenLogo () { if (!vispar.drawnetgenlogo) return; glDisable (GL_DEPTH_TEST); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glTranslatef (1, -1, 0.0); glScalef (40.0 / viewport[2], 40.0 / viewport[3], 1); glTranslatef (-7.0, 2.0, 0.0); glDisable (GL_CLIP_PLANE0); glDisable (GL_LIGHTING); glEnable (GL_COLOR_MATERIAL); GLfloat textcol[3] = { GLfloat(1 - backcolor), GLfloat(1 - backcolor), GLfloat(1 - backcolor) }; glColor3fv (textcol); glLineWidth (1.0f); glPushAttrib (GL_LIST_BIT); // glListBase (fontbase); char buf[] = "Netgen " PACKAGE_VERSION; glRasterPos3d (0.0f, 0.0f, 0.0f); // glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); glPopAttrib (); glEnable (GL_LIGHTING); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glEnable (GL_DEPTH_TEST); } #ifdef PARALLELGL void VisualScene :: InitParallelGL () { static int init = 0; if (!init) { init = 1; if (id == 0) { string displname; Display * dpy = glXGetCurrentDisplay(); GLXDrawable drawable = glXGetCurrentDrawable(); GLXContext ctx = glXGetCurrentContext(); GLXContextID xid = glXGetContextIDEXT (ctx); displname = XDisplayName (0); if( glXIsDirect ( dpy, ctx ) ) cout << "WARNING: direct rendering enabled; this might break mpi-parallel netgen (especially if X-forwarding is used! (to disable, change -indirect to true in ng/drawing.tcl)" << endl; /* cout << "Init Parallel GL" << endl; cout << "DisplayName = " << displname << endl; cout << "current display = " << dpy << endl; cout << "current drawable = " << drawable << endl; cout << "current context = " << ctx << endl; cout << "contextid = " << xid << endl; cout << "isdirect = " << glXIsDirect ( dpy, ctx ) << endl; cout << "extensionstring = " << glXQueryExtensionsString( dpy, 0 ) << endl; */ MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("init"); for (int dest = 1; dest < ntasks; dest++) { MyMPI_Send (displname, dest, MPI_TAG_VIS); MyMPI_Send (int (drawable), dest, MPI_TAG_VIS); MyMPI_Send (int (xid), dest, MPI_TAG_VIS); } } } } void VisualScene :: Broadcast () { if (ntasks == 1) return; if (id == 0) { /* for (int dest = 1; dest < ntasks; dest++) { MyMPI_Send ("redraw", dest, MPI_TAG_CMD); MyMPI_Send ("broadcast", dest, MPI_TAG_VIS); } */ MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("broadcast"); } MyMPI_Bcast (selface); netgen::GetVSSolution().Broadcast (); } #endif } netgen-6.2.1905/libsrc/visualization/meshdoc.cpp0000644000175000017500000002756413504650527020324 0ustar kurtkurt#ifndef NOTCL #include #include // #include "incvis.hpp" #include #include namespace netgen { // #include "meshdoc.hpp" MeshDoctorParameters meshdoctor; DLL_HEADER extern shared_ptr mesh; VisualSceneMeshDoctor :: VisualSceneMeshDoctor () : VisualScene() { filledlist = 0; outlinelist = 0; edgelist = 0; selelement = 0; locpi = 1; selpoint = 0; selpoint2 = 0; markedgedist = 1; UpdateTables (); } VisualSceneMeshDoctor :: ~VisualSceneMeshDoctor () { ; } void VisualSceneMeshDoctor :: DrawScene () { if (!mesh) return; int hchval = mesh->GetNP() + mesh->GetNE() + mesh->GetNSE(); if (changeval != hchval) { changeval = hchval; BuildScene(); } glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable (GL_COLOR_MATERIAL); glColor3f (1.0f, 1.0f, 1.0f); glLineWidth (1.0f); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); glInitNames (); glPushName (0); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); SetClippingPlane (); if (vispar.drawfilledtrigs) glCallList (filledlist); glDisable (GL_POLYGON_OFFSET_FILL); if (vispar.drawoutline) glCallList (outlinelist); glPolygonOffset (-1, -1); glEnable (GL_POLYGON_OFFSET_LINE); if (vispar.drawedges) glCallList (edgelist); glDisable (GL_POLYGON_OFFSET_LINE); glPopName(); if (selpoint > 0 && selpoint <= mesh->GetNP()) { GLfloat matcolblue[] = { 0, 0, 1, 1 }; glPointSize (10); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolblue); glBegin (GL_POINTS); const Point3d p = mesh->Point(selpoint); glVertex3f (p.X(), p.Y(), p.Z()); glEnd(); } glDisable(GL_CLIP_PLANE0); glPopMatrix(); glFinish(); } void VisualSceneMeshDoctor :: BuildScene (int zoomall) { int i, j; if (zoomall) { Point3d pmin, pmax; mesh->GetBox (pmin, pmax, -1); if (vispar.centerpoint) center = mesh->Point (vispar.centerpoint); else center = Center (pmin, pmax); rad = 0.5 * Dist (pmin, pmax); glEnable (GL_NORMALIZE); CalcTransformationMatrices(); } if (filledlist) { glDeleteLists (filledlist, 1); glDeleteLists (outlinelist, 1); glDeleteLists (edgelist, 1); } filledlist = glGenLists (1); glNewList (filledlist, GL_COMPILE); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glLineWidth (1.0f); glDisable (GL_COLOR_MATERIAL); for (i = 1; i <= mesh->GetNSE(); i++) { glLoadName (i); // copy to be thread-safe Element2d el = mesh->SurfaceElement (i); int drawel = 1; for (j = 1; j <= el.GetNP(); j++) { if (!el.PNum(j)) drawel = 0; } if (!drawel) continue; GLfloat matcol[] = { 0, 1, 0, 1 }; GLfloat matcolsel[] = { 1, 0, 0, 1 }; if (i == selelement) glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcolsel); else glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcol); if (el.GetNP() == 3) { glBegin (GL_TRIANGLES); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length()+1e-12); glNormal3d (n.X(), n.Y(), n.Z()); if (!vispar.colormeshsize) { glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } else { double h1 = mesh->GetH (lp1); double h2 = mesh->GetH (lp2); double h3 = mesh->GetH (lp3); SetOpenGlColor (h1, 0.1, 10); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); SetOpenGlColor (h2, 0.1, 10); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); SetOpenGlColor (h3, 0.1, 10); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } glEnd(); } else if (el.GetNP() == 4) { glBegin (GL_QUADS); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(4)); const Point3d & lp4 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, Center (lp3, lp4))); n /= (n.Length()+1e-12); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp4.X(), lp4.Y(), lp4.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glEnd(); } else if (el.GetNP() == 6) { glBegin (GL_TRIANGLES); static int trigs[4][3] = { { 1, 6, 5 }, { 2, 4, 6 }, { 3, 5, 4 }, { 4, 5, 6 } }; for (j = 0; j < 4; j++) { const Point3d & lp1 = mesh->Point (el.PNum(trigs[j][0])); const Point3d & lp2 = mesh->Point (el.PNum(trigs[j][1])); const Point3d & lp3 = mesh->Point (el.PNum(trigs[j][2])); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length() + 1e-12); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } glEnd(); } } glLoadName (0); glEndList (); outlinelist = glGenLists (1); glNewList (outlinelist, GL_COMPILE); glLineWidth (1.0f); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glColor3f (0.0f, 0.0f, 0.0f); glEnable (GL_COLOR_MATERIAL); for (i = 1; i <= mesh->GetNSE(); i++) { Element2d el = mesh->SurfaceElement(i); int drawel = 1; for (j = 1; j <= el.GetNP(); j++) { if (!el.PNum(j)) drawel = 0; } if (!drawel) continue; if (el.GetNP() == 3) { glBegin (GL_TRIANGLES); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length() + 1e-12); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glEnd(); } else if (el.GetNP() == 4) { glBegin (GL_QUADS); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(4)); const Point3d & lp4 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, Center (lp3, lp4))); n /= (n.Length() + 1e-12); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp4.X(), lp4.Y(), lp4.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glEnd(); } else if (el.GetNP() == 6) { glBegin (GL_LINES); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(3)); const Point3d & lp4 = mesh->Point (el.PNum(4)); const Point3d & lp5 = mesh->Point (el.PNum(5)); const Point3d & lp6 = mesh->Point (el.PNum(6)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length()+1e-12); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp6.X(), lp6.Y(), lp6.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp6.X(), lp6.Y(), lp6.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp5.X(), lp5.Y(), lp5.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glVertex3d (lp5.X(), lp5.Y(), lp5.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp4.X(), lp4.Y(), lp4.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glVertex3d (lp4.X(), lp4.Y(), lp4.Z()); glEnd(); } } glLoadName (0); glEndList (); edgelist = glGenLists (1); glNewList (edgelist, GL_COMPILE); glDisable (GL_COLOR_MATERIAL); GLfloat matcoledge[] = { 0, 0, 1, 1 }; GLfloat matcolseledge[] = { 1, 0, 1, 1 }; glLineWidth (2.0f); for (i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh->LineSegment(i); const Point3d & p1 = mesh->Point(seg[0]); const Point3d & p2 = mesh->Point(seg[1]); if (edgedist.Get(seg[0]) <= markedgedist && edgedist.Get(seg[1]) <= markedgedist) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolseledge); glLineWidth (4.0f); } else { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcoledge); glLineWidth (2.0f); } glBegin (GL_LINES); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (p2.X(), p2.Y(), p2.Z()); glEnd(); } glLineWidth (1.0f); glEndList (); } void VisualSceneMeshDoctor :: MouseDblClick (int px, int py) { cout << "dblclick: " << px << " - " << py << endl; int i, hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixd (transformationmat); glInitNames(); glPushName (1); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glCallList (filledlist); glDisable (GL_POLYGON_OFFSET_FILL); glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); cout << "hits = " << hits << endl; int minname = 0; GLuint mindepth = 0; for (i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; if (curname && (curdepth < mindepth || !minname)) { mindepth = curdepth; minname = curname; } } cout << "clicked element: " << minname << endl; ClickElement (minname); BuildScene (); } void VisualSceneMeshDoctor :: SetMarkEdgeDist (int dist) { markedgedist = dist; BuildScene(); } void VisualSceneMeshDoctor :: ClickElement (int elnr) { selelement = elnr; int oldlocpi = locpi; locpi = locpi % 3 + 1; if (selelement > 0 && selelement <= mesh->GetNSE()) { selpoint = mesh->SurfaceElement(selelement).PNum(locpi); selpoint2 = mesh->SurfaceElement(selelement).PNum(oldlocpi); cout << "selpts = " << selpoint << ", " << selpoint2 << endl; } UpdateTables(); } void VisualSceneMeshDoctor :: UpdateTables () { if (!mesh) return; edgedist.SetSize(mesh->GetNP()); int i, changed; for (i = 1; i <= mesh->GetNP(); i++) edgedist.Elem(i) = 10000; for (i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh->LineSegment(i); if ( (seg[0] == selpoint && seg[1] == selpoint2) || (seg[1] == selpoint && seg[0] == selpoint2) ) { edgedist.Elem(selpoint) = 1; edgedist.Elem(selpoint2) = 1; } } do { changed = 0; for (i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh->LineSegment(i); int edist = min2 (edgedist.Get(seg[0]), edgedist.Get(seg[1])); edist++; if (edgedist.Get(seg[0]) > edist) { edgedist.Elem(seg[0]) = edist; changed = 1; } if (edgedist.Get(seg[1]) > edist) { edgedist.Elem(seg[1]) = edist; changed = 1; } } } while (changed); } int VisualSceneMeshDoctor :: IsSegmentMarked (int segnr) const { const Segment & seg = mesh->LineSegment(segnr); return (edgedist.Get(seg[0]) <= markedgedist && edgedist.Get(seg[1]) <= markedgedist); } } #endif // NOTCL netgen-6.2.1905/libsrc/visualization/vsmesh.cpp0000644000175000017500000024600413504650527020177 0ustar kurtkurt#include #include #include // #include #ifdef STLGEOM #include #endif // #include #include namespace netgen { // extern shared_ptr mesh; extern NetgenGeometry * ng_geometry; VisualSceneMesh vsmesh; VisualSceneMesh :: VisualSceneMesh () : VisualScene() { filledlist = 0; linelist = 0; edgelist = 0; badellist = 0; tetlist = 0; prismlist = 0; hexlist = 0; pyramidlist = 0; identifiedlist = 0; pointnumberlist = 0; domainsurflist = 0; vstimestamp = -1; // GetTimeStamp(); selecttimestamp = -1; // GetTimeStamp(); filledtimestamp = -1; // GetTimeStamp(); linetimestamp = -1; // GetTimeStamp(); edgetimestamp = -1; // GetTimeStamp(); pointnumbertimestamp = -1; // GetTimeStamp(); tettimestamp = -1; // GetTimeStamp(); prismtimestamp = -1; // GetTimeStamp(); hextimestamp = -1; // GetTimeStamp(); pyramidtimestamp = -1; // GetTimeStamp(); badeltimestamp = -1; // GetTimeStamp(); identifiedtimestamp = -1; // GetTimeStamp(); domainsurftimestamp = -1; // GetTimeStamp(); selface = -1; selelement = -1; locpi = 1; selpoint = -1; selpoint2 = -1; seledge = -1; minh = 0.0; maxh = 0.0; user_me_handler = NULL; } VisualSceneMesh :: ~VisualSceneMesh () { ; } void VisualSceneMesh :: DrawScene () { try { shared_ptr mesh = GetMesh(); if (!mesh) { VisualScene::DrawScene(); return; } lock = NULL; static int timer = NgProfiler::CreateTimer ("VSMesh::DrawScene"); NgProfiler::RegionTimer reg (timer); BuildScene(); glEnable(GL_DEPTH_TEST); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable (GL_COLOR_MATERIAL); glColor3f (1.0f, 1.0f, 1.0f); glLineWidth (1.0f); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); GLdouble projmat[16]; // brauchen wir das ? glGetDoublev (GL_PROJECTION_MATRIX, projmat); #ifdef PARALLEL glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #endif glInitNames (); glPushName (0); // glEnable (GL_LINE_SMOOTH); // glEnable (GL_BLEND); // glEnable (GL_POLYGON_SMOOTH); // glDisable (GL_DEPTH_TEST); // glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); glDisable (GL_COLOR_MATERIAL); GLfloat matcol0[] = { 0, 0, 0, 1 }; GLfloat matcol1[] = { 1, 1, 1, 1 }; GLfloat matcolf[] = { 0, 1, 0, 1 }; GLfloat matcolb[] = { 0.5, 0, 0, 1 }; // GLfloat matcolblue[] = { 0, 0, 1, 1 }; glMatrixMode (GL_MODELVIEW); glMaterialfv(GL_FRONT, GL_EMISSION, matcol0); glMaterialfv(GL_BACK, GL_EMISSION, matcol0); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matcol1); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcolf); glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, matcolb); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // glPolygonOffset (1,10); glPolygonOffset (2,2); glEnable (GL_POLYGON_OFFSET_FILL); SetClippingPlane (); if (vispar.drawfilledtrigs) { if (filledtimestamp < mesh->GetTimeStamp () || filledtimestamp < selecttimestamp) { BuildFilledList (false); } #ifdef PARALLELGL if (ntasks > 1 && vispar.drawtetsdomain > 0 && vispar.drawtetsdomain < ntasks) glCallList (par_filledlists[vispar.drawtetsdomain]); else #endif glCallList (filledlist); } if (vispar.drawbadels) glCallList (badellist); if (vispar.drawprisms) { BuildPrismList (); glCallList (prismlist); } if (vispar.drawpyramids) { BuildPyramidList (); glCallList (pyramidlist); } if (vispar.drawhexes) { BuildHexList (); glCallList (hexlist); } if (vispar.drawtets) { BuildTetList (); glCallList (tetlist); } if (vispar.drawdomainsurf) { BuildDomainSurfList(); glCallList (domainsurflist); } glDisable (GL_POLYGON_OFFSET_FILL); // draw lines glMatrixMode (GL_MODELVIEW); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol0); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matcol0); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matcol0); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glLineWidth (1.0f); glColor3f (0.0f, 0.0f, 0.0f); glDisable (GL_LINE_SMOOTH); if (vispar.drawoutline) { glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_LINE); if (linetimestamp < mesh->GetTimeStamp ()) BuildLineList (); #ifdef PARALLELGL if (ntasks > 1 && vispar.drawtetsdomain > 0 && vispar.drawtetsdomain < ntasks) glCallList (par_linelists[vispar.drawtetsdomain]); else #endif glCallList (linelist); glDisable (GL_POLYGON_OFFSET_LINE); } if (vispar.drawidentified) { glPolygonOffset (1, -1); glEnable (GL_POLYGON_OFFSET_LINE); glCallList (identifiedlist); glDisable (GL_POLYGON_OFFSET_LINE); } if (vispar.drawpointnumbers || vispar.drawedgenumbers || vispar.drawfacenumbers || vispar.drawelementnumbers) glCallList (pointnumberlist); glPopName(); if (vispar.drawedges) { BuildEdgeList(); glCallList (edgelist); } if (selpoint > 0 && selpoint <= mesh->GetNP()) { /* glPointSize (3.0); glColor3d (0, 0, 1); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolblue); glBegin (GL_POINTS); const Point3d p = mesh->Point(selpoint); glVertex3f (p.X(), p.Y(), p.Z()); glEnd(); */ glColor3d (0, 0, 1); static GLubyte cross[] = { 0xc6, 0xee, 0x7c, 0x38, 0x7c, 0xee, 0xc6 }; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDisable (GL_COLOR_MATERIAL); glDisable (GL_LIGHTING); glDisable (GL_CLIP_PLANE0); const Point3d p = mesh->Point(selpoint); glRasterPos3d (p.X(), p.Y(), p.Z()); glBitmap (7, 7, 3, 3, 0, 0, &cross[0]); } glDisable(GL_CLIP_PLANE0); glPopMatrix(); if (vispar.colormeshsize) DrawColorBar (minh, maxh, 1); DrawCoordinateCross (); DrawNetgenLogo (); if (lock) { lock -> UnLock(); delete lock; lock = NULL; } glFinish(); } catch (bad_weak_ptr e) { // cout << "don't have a mesh to visualize" << endl; VisualScene::DrawScene(); } } void VisualSceneMesh :: BuildScene (int zoomall) { try { shared_ptr mesh = GetMesh(); if (!mesh) { VisualScene::BuildScene (zoomall); return; } if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } static int timer = NgProfiler::CreateTimer ("VSMesh::BuildScene"); NgProfiler::RegionTimer reg (timer); Point3d pmin, pmax; static double oldrad = 0; Array faces; int meshtimestamp = mesh->GetTimeStamp(); if (meshtimestamp > vstimestamp || zoomall) { if (mesh->GetDimension() == 2) { // works in NGSolve, mesh view mesh->GetBox (pmin, pmax); } else { // otherwise strange zooms douring mesh generation mesh->GetBox (pmin, pmax, SURFACEPOINT); } if (vispar.use_center_coords && zoomall == 2) { center.X() = vispar.centerx; center.Y() = vispar.centery; center.Z() = vispar.centerz; } else if (selpoint >= 1 && zoomall == 2) center = mesh->Point (selpoint); else if (vispar.centerpoint >= 1 && zoomall == 2) center = mesh->Point (vispar.centerpoint); else center = Center (pmin, pmax); rad = 0.5 * Dist (pmin, pmax); if(rad == 0) rad = 1e-6; if (rad > 1.2 * oldrad || mesh->GetMajorTimeStamp() > vstimestamp || zoomall) { CalcTransformationMatrices(); oldrad = rad; } } glEnable (GL_NORMALIZE); if (pointnumberlist) { glDeleteLists (pointnumberlist, 1); pointnumberlist = 0; } if (badellist) { glDeleteLists (badellist, 1); badellist = 0; } /* if (prismlist) { glDeleteLists (prismlist, 1); prismlist = 0; } if (pyramidlist) { glDeleteLists (pyramidlist, 1); pyramidlist = 0; } if (hexlist) { glDeleteLists (hexlist, 1); hexlist = 0; } */ if (identifiedlist) { glDeleteLists (identifiedlist, 1); identifiedlist = 0; } pointnumberlist = glGenLists (1); glNewList (pointnumberlist, GL_COMPILE); if (vispar.drawpointnumbers || vispar.drawedgenumbers || vispar.drawfacenumbers || vispar.drawelementnumbers) { // glEnable (GL_COLOR_MATERIAL); GLfloat textcol[3] = { float(1-backcolor), float(1-backcolor), float(1-backcolor) }; glColor3fv (textcol); glNormal3d (0, 0, 1); glPushAttrib (GL_LIST_BIT); // glListBase (fontbase); char buf[30]; if (vispar.drawpointnumbers) for (PointIndex pi : mesh->Points().Range()) { const Point3d & p = mesh->Point(pi); glRasterPos3d (p.X(), p.Y(), p.Z()); sprintf (buf, "%d", int(pi)); // glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); } if (vispar.drawedgenumbers) { /* for (SegmentIndex i = 0; i < mesh->GetNSeg(); i++) { const Segment & seg = (*mesh)[i]; const Point3d & p1 = mesh->Point(seg[0]); const Point3d & p2 = mesh->Point(seg[1]); const Point3d p = Center (p1, p2); glRasterPos3d (p.X(), p.Y(), p.Z()); sprintf (buf, "%d", seg.edgenr); glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); } */ const MeshTopology & top = mesh->GetTopology(); for (int i = 1; i <= top.GetNEdges(); i++) { int v1, v2; top.GetEdgeVertices (i, v1, v2); const Point3d & p1 = mesh->Point(v1); const Point3d & p2 = mesh->Point(v2); const Point3d p = Center (p1, p2); glRasterPos3d (p.X(), p.Y(), p.Z()); sprintf (buf, "%d", i); // glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); } } if (vispar.drawfacenumbers) { const MeshTopology & top = mesh->GetTopology(); Array v; for (int i = 1; i <= top.GetNFaces(); i++) { top.GetFaceVertices (i, v); const Point3d & p1 = mesh->Point(v.Elem(1)); const Point3d & p2 = mesh->Point(v.Elem(2)); const Point3d & p3 = mesh->Point(v.Elem(3)); Point3d p; if (v.Elem(4) == 0) { p = Center (p1, p2, p3); } else { const Point3d & p4 = mesh->Point(v.Elem(4)); Point3d hp1 = Center (p1, p2); Point3d hp2 = Center (p3, p4); p = Center (hp1, hp2); } glRasterPos3d (p.X(), p.Y(), p.Z()); sprintf (buf, "%d", i); // glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); } } if (vispar.drawelementnumbers) { Array v; for (int i = 1; i <= mesh->GetNE(); i++) { // const ELEMENTTYPE & eltype = mesh->ElementType(i); Array pnums; Point3d p; const Element & el = mesh->VolumeElement (i); if ( ! el.PNum(5)) // eltype == TET ) { pnums.SetSize(4); for( int j = 0; j < pnums.Size(); j++) pnums[j] = mesh->VolumeElement(i).PNum(j+1); const Point3d & p1 = mesh->Point(pnums[0]); const Point3d & p2 = mesh->Point(pnums[1]); const Point3d & p3 = mesh->Point(pnums[2]); const Point3d & p4 = mesh->Point(pnums[3]); p = Center (p1, p2, p3, p4); } else if ( ! el.PNum(6)) // eltype == PYRAMID { pnums.SetSize(5); for( int j = 0; j < pnums.Size(); j++) pnums[j] = mesh->VolumeElement(i).PNum(j+1); const Point3d & p1 = mesh->Point(pnums[0]); const Point3d & p2 = mesh->Point(pnums[1]); const Point3d & p3 = mesh->Point(pnums[2]); const Point3d & p4 = mesh->Point(pnums[3]); const Point3d & p5 = mesh->Point(pnums[4]); p.X() = 0.3 * p5.X() + 0.7 * Center ( Center(p1, p3) , Center(p2, p4) ) . X(); p.Y() = 0.3 * p5.Y() + 0.7 * Center ( Center(p1, p3) , Center(p2, p4) ) . Y(); p.Z() = 0.3 * p5.Z() + 0.7 * Center ( Center(p1, p3) , Center(p2, p4) ) . Z(); } else if ( ! el.PNum(7) ) // eltype == PRISM { pnums.SetSize(6); for( int j = 0; j < pnums.Size(); j++) pnums[j] = mesh->VolumeElement(i).PNum(j+1); const Point3d & p1 = mesh->Point(pnums[0]); const Point3d & p2 = mesh->Point(pnums[1]); const Point3d & p3 = mesh->Point(pnums[2]); const Point3d & p11 = mesh->Point(pnums[3]); const Point3d & p12 = mesh->Point(pnums[4]); const Point3d & p13 = mesh->Point(pnums[5]); p = Center ( Center (p1, p2, p3) , Center(p11, p12, p13) ) ; } else if (! el.PNum(9) ) // eltype == HEX { pnums.SetSize(8); for( int j = 0; j < pnums.Size(); j++) pnums[j] = mesh->VolumeElement(i).PNum(j+1); const Point3d & p1 = mesh->Point(pnums[0]); const Point3d & p2 = mesh->Point(pnums[1]); const Point3d & p3 = mesh->Point(pnums[2]); const Point3d & p4 = mesh->Point(pnums[3]); const Point3d & p5 = mesh->Point(pnums[4]); const Point3d & p6 = mesh->Point(pnums[5]); const Point3d & p7 = mesh->Point(pnums[6]); const Point3d & p8 = mesh->Point(pnums[7]); p = Center ( Center ( Center(p1, p3), Center(p2, p4) ) , Center( Center(p5, p7) , Center(p6, p8 ) ) ); } glRasterPos3d (p.X(), p.Y(), p.Z()); sprintf (buf, "%d", i); // glCallLists (strlen (buf), GL_UNSIGNED_BYTE, buf); MyOpenGLText (buf); } } glPopAttrib (); // glDisable (GL_COLOR_MATERIAL); } glEndList (); badellist = glGenLists (1); glNewList (badellist, GL_COMPILE); if (vispar.drawbadels) { // SetClippingPlane (); static float badelcol[] = { 1.0f, 0.0f, 1.0f, 1.0f }; glLineWidth (1.0f); for (int i = 1; i <= mesh->GetNE(); i++) { if (mesh->VolumeElement(i).flags.badel || mesh->VolumeElement(i).flags.illegal || (i == vispar.drawelement)) { // copy to be thread-safe Element el = mesh->VolumeElement (i); el.GetSurfaceTriangles (faces); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, badelcol); // if ( (el.GetNP() == 4) || (el.GetNP() == 10)) if (el.PNum(1)) { glBegin (GL_TRIANGLES); for (int j = 1; j <= faces.Size(); j++) { Element2d & face = faces.Elem(j); const Point3d & lp1 = mesh->Point (el.PNum(face.PNum(1))); const Point3d & lp2 = mesh->Point (el.PNum(face.PNum(2))); const Point3d & lp3 = mesh->Point (el.PNum(face.PNum(3))); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length()+1e-12); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } glEnd(); } } } for (ElementIndex ei : mesh->VolumeElements().Range()) { if (mesh->VolumeElement(ei).flags.badel) { // copy to be thread-safe Element el = mesh->VolumeElement (ei); if ( (el.GetNP() == 4) || (el.GetNP() == 10)) { glBegin (GL_LINES); glVertex3d (0,0,0); const Point3d & p = mesh->Point(el.PNum(1)); glVertex3d (p.X(), p.Y(), p.Z()); glEnd(); } } } for (int i = 1; i <= mesh->GetNE(); i++) { Element el = mesh->VolumeElement (i); int hascp = 0; for (int j = 1; j <= el.GetNP(); j++) if (el.PNum(j) == vispar.centerpoint) hascp = 1; if (hascp) { (*testout) << "draw el " << i << " : "; for (int j = 1; j <= el.GetNP(); j++) (*testout) << el.PNum(j) << " "; (*testout) << endl; if (el.GetNP() == 4) { int et[6][2] = { { 1, 2 }, { 1, 3 }, { 1, 4 }, { 2, 3 }, { 2, 4 }, { 3, 4 } } ; for (int j = 0; j < 6; j++) { glBegin (GL_LINES); const Point3d & p1 = mesh->Point (el.PNum(et[j][0])); const Point3d & p2 = mesh->Point (el.PNum(et[j][1])); glVertex3d (p1.X(), p1.Y(), p1.Z()); glVertex3d (p2.X(), p2.Y(), p2.Z()); glEnd (); } } if (el.GetNP() == 10) { int et[12][2] = { { 1, 5 }, { 2, 5 }, { 1, 6 }, { 3, 6 }, { 1, 7 }, { 4, 7 }, { 2, 8 }, { 3, 8 }, { 2, 9 }, { 4, 9 }, { 3, 10 }, { 4, 10 } }; for (int j = 0; j < 12; j++) { glBegin (GL_LINES); const Point3d & p1 = mesh->Point (el.PNum(et[j][0])); const Point3d & p2 = mesh->Point (el.PNum(et[j][1])); glVertex3d (p1.X(), p1.Y(), p1.Z()); glVertex3d (p2.X(), p2.Y(), p2.Z()); glEnd (); } } } } for (SurfaceElementIndex sei : mesh->SurfaceElements().Range()) { Element2d el = mesh->SurfaceElement(sei); // copy to be thread-safe if (!el.BadElement()) continue; bool drawel = true; for (int j = 1; j <= el.GetNP(); j++) if (!el.PNum(j).IsValid()) drawel = false; if (!drawel) continue; // cout << int (el.GetType()) << " " << flush; switch (el.GetType()) { case TRIG: { glBegin (GL_TRIANGLES); Point3d lp1 = mesh->Point (el.PNum(1)); Point3d lp2 = mesh->Point (el.PNum(2)); Point3d lp3 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length() + 1e-12); glNormal3dv (&n.X()); glVertex3dv (&lp1.X()); glVertex3dv (&lp2.X()); glVertex3dv (&lp3.X()); glEnd(); break; } case QUAD: { glBegin (GL_QUADS); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(4)); const Point3d & lp4 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, Center (lp3, lp4))); n /= (n.Length() + 1e-12); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp4.X(), lp4.Y(), lp4.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glEnd(); break; } case TRIG6: { int lines[6][2] = { { 1, 6 }, { 2, 6 }, { 1, 5 }, { 3, 5 }, { 2, 4 }, { 3, 4 } }; glBegin (GL_LINES); for (int j = 0; j < 6; j++) { glVertex3dv ( mesh->Point (el.PNum(lines[j][0])) ); glVertex3dv ( mesh->Point (el.PNum(lines[j][0])) ); } glEnd(); break; } case QUAD6: { int lines[6][2] = { { 1, 5 }, { 2, 5 }, { 3, 6 }, { 4, 6 }, { 1, 4 }, { 2, 3 } }; glBegin (GL_LINES); for (int j = 0; j < 6; j++) { const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0])); const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1])); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); } glEnd (); break; } default: PrintSysError ("Cannot draw surface element of type ", int(el.GetType())); } } glLoadName (0); } glEndList (); if (1) { identifiedlist = glGenLists (1); glNewList (identifiedlist, GL_COMPILE); GLfloat identifiedcol[] = { 1, 0, 1, 1 }; glLineWidth (3); // for (i = 1; i <= mesh->GetNSeg(); i++) if (mesh -> HasIdentifications() ) { // if (mesh->GetIdentifications().HasIdentifiedPoints()) { INDEX_2_HASHTABLE & idpts = mesh->GetIdentifications().GetIdentifiedPoints(); for (int i = 1; i <= idpts.GetNBags(); i++) for (int j = 1; j <= idpts.GetBagSize(i); j++) { INDEX_2 pts; int val; idpts.GetData (i, j, pts, val); const Point3d & p1 = mesh->Point(pts.I1()); const Point3d & p2 = mesh->Point(pts.I2()); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, identifiedcol); glBegin (GL_LINES); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (p2.X(), p2.Y(), p2.Z()); glEnd(); } } } glEndList (); } if (lock) { lock -> UnLock(); delete lock; lock = NULL; } vstimestamp = meshtimestamp; } catch (bad_weak_ptr e) { PrintMessage (3, "vsmesh::buildscene: don't have a mesh to visualize"); VisualScene::BuildScene (zoomall); } } void VisualSceneMesh :: BuildFilledList (bool names) { shared_ptr mesh = GetMesh(); static int timer = NgProfiler::CreateTimer ("Mesh::BuildFilledList"); NgProfiler::RegionTimer reg (timer); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); par_filledlists.SetSize (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("filledlist"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (par_filledlists[dest], dest, MPI_TAG_VIS); if (filledlist) glDeleteLists (filledlist, 1); filledlist = glGenLists (1); glNewList (filledlist, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (par_filledlists[dest]); glEndList(); filledtimestamp = NextTimeStamp(); return; } #endif if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } filledtimestamp = NextTimeStamp(); if (filledlist) glDeleteLists (filledlist, 1); filledlist = glGenLists (1); glNewList (filledlist, GL_COMPILE); #ifdef STLGEOM STLGeometry * stlgeometry = dynamic_cast (ng_geometry); bool checkvicinity = (stlgeometry != NULL) && stldoctor.showvicinity; #endif glEnable (GL_NORMALIZE); glLineWidth (1.0f); Vector locms; if (vispar.colormeshsize) { glEnable (GL_COLOR_MATERIAL); glShadeModel (GL_SMOOTH); locms.SetSize (mesh->GetNP()); maxh = -1; minh = 1e99; for (int i = 1; i <= locms.Size(); i++) { Point3d p = mesh->Point(i); locms(i-1) = mesh->GetH (p); if (locms(i-1) > maxh) maxh = locms(i-1); if (locms(i-1) < minh) minh = locms(i-1); } if (!locms.Size()) { minh = 1; maxh = 10; } } else glDisable (GL_COLOR_MATERIAL); GLfloat matcol[] = { 0, 1, 0, 1 }; GLfloat matcolsel[] = { 1, 0, 0, 1 }; GLint rendermode; glGetIntegerv (GL_RENDER_MODE, &rendermode); CurvedElements & curv = mesh->GetCurvedElements(); int hoplotn = 1 << vispar.subdivisions; Array seia; for (int faceindex = 1; faceindex <= mesh->GetNFD(); faceindex++) { mesh->GetSurfaceElementsOfFace (faceindex, seia); // Philippose - 06/07/2009 // Modified the colour system to integrate the face colours into // the mesh data structure, rather than limit it to the OCC geometry // structure... allows other geometry types to use face colours too matcol[0] = mesh->GetFaceDescriptor(faceindex).SurfColour().X(); matcol[1] = mesh->GetFaceDescriptor(faceindex).SurfColour().Y(); matcol[2] = mesh->GetFaceDescriptor(faceindex).SurfColour().Z(); matcol[3] = 1.0; if (faceindex == selface) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolsel); else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol); for (int hi = 0; hi < seia.Size(); hi++) { SurfaceElementIndex sei = seia[hi]; const Element2d & el = (*mesh)[sei]; bool drawel = (!el.IsDeleted() & el.IsVisible()); #ifdef STLGEOM if (checkvicinity) for (int j = 0; j < el.GetNP(); j++) if (!stlgeometry->Vicinity(el.GeomInfoPi(j+1).trignum)) drawel = 0; #endif if (!drawel) continue; if (names) glLoadName (sei+1); switch (el.GetType()) { case TRIG: { if (curv.IsHighOrder()) // && curv.IsSurfaceElementCurved(sei)) { if (hoplotn > 128) hoplotn = 128; Point<3> xa[129]; Vec<3> na[129]; for (int i = 0; i < hoplotn; i++) { glBegin (GL_TRIANGLE_STRIP); for (int j = 0; j <= hoplotn-i; j++) for (int k = 0; k < 2; k++) { if (j == hoplotn-i && k == 1) continue; if (i > 0 && k == 0) { glNormal3dv (na[j]); glVertex3dv (xa[j]); continue; } Point<2> xref (double(j) / hoplotn, double(i+k) / hoplotn); Point<3> xglob; Mat<3,2> dxdxi; Vec<3> dx, dy, n; curv.CalcSurfaceTransformation (xref, sei, xglob, dxdxi); for (int i = 0; i < 3; i++) { dx(i) = dxdxi(i,0); dy(i) = dxdxi(i,1); } n = Cross (dx, dy); glNormal3dv (n); glVertex3dv (xglob); if (k == 1) { na[j] = n; xa[j] = xglob; } } glEnd(); } } else // not high order { glBegin (GL_TRIANGLES); const Point<3> & lp0 = (*mesh) [el[0]]; const Point<3> & lp1 = (*mesh) [el[1]]; const Point<3> & lp2 = (*mesh) [el[2]]; Vec<3> n = Cross (lp1-lp0, lp2-lp0).Normalize(); glNormal3dv (n); for (int j = 0; j < 3; j++) { if (vispar.colormeshsize) SetOpenGlColor (locms(el[0]-1), minh, maxh, 0); glVertex3dv ( (*mesh)[el[j]] ); } glEnd(); } break; } case QUAD: { if (curv.IsHighOrder()) // && curv.IsSurfaceElementCurved(sei)) { Point<2> xr[4]; Point<3> xg; Vec<3> dx, dy, n; glBegin (GL_QUADS); for (int i = 0; i < hoplotn; i++) for (int j = 0; j < hoplotn; j++) { xr[0](0) = (double) i/hoplotn; xr[0](1) = (double) j/hoplotn; xr[1](0) = (double)(i+1)/hoplotn; xr[1](1) = (double) j/hoplotn; xr[2](0) = (double)(i+1)/hoplotn; xr[2](1) = (double)(j+1)/hoplotn; xr[3](0) = (double) i/hoplotn; xr[3](1) = (double)(j+1)/hoplotn; for (int l=0; l<4; l++) { Mat<3,2> dxdxi; curv.CalcSurfaceTransformation (xr[l], sei, xg, dxdxi); for (int i = 0; i < 3; i++) { dx(i) = dxdxi(i,0); dy(i) = dxdxi(i,1); } n = Cross (dx, dy); n.Normalize(); glNormal3d (n(0), n(1), n(2)); glVertex3d (xg(0), xg(1), xg(2)); } } glEnd(); } else // not high order { glBegin (GL_QUADS); const Point<3> & lp1 = mesh->Point (el.PNum(1)); const Point<3> & lp2 = mesh->Point (el.PNum(2)); const Point<3> & lp3 = mesh->Point (el.PNum(4)); const Point<3> & lp4 = mesh->Point (el.PNum(3)); Vec<3> n = Cross (lp2-lp1, Center (lp3, lp4)-lp1); n.Normalize(); glNormal3dv (n); glVertex3dv (lp1); glVertex3dv (lp2); glVertex3dv (lp4); glVertex3dv (lp3); glEnd (); } break; } case TRIG6: { glBegin (GL_TRIANGLES); static int trigs[4][3] = { { 1, 6, 5 }, { 2, 4, 6 }, { 3, 5, 4 }, { 4, 5, 6 } }; for (int j = 0; j < 4; j++) { const Point<3> & lp1 = mesh->Point (el.PNum(trigs[j][0])); const Point<3> & lp2 = mesh->Point (el.PNum(trigs[j][1])); const Point<3> & lp3 = mesh->Point (el.PNum(trigs[j][2])); // Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); Vec<3> n = Cross (lp2-lp1, lp3-lp1); glNormal3dv (n); glVertex3dv (lp1); glVertex3dv (lp2); glVertex3dv (lp3); } glEnd(); break; } case QUAD6: { glBegin (GL_QUADS); static int quads[2][4] = { { 1, 5, 6, 4 }, { 5, 2, 3, 6 } }; for (int j = 0; j < 2; j++) { Point3d lp1 = mesh->Point (el.PNum(quads[j][0])); Point3d lp2 = mesh->Point (el.PNum(quads[j][1])); Point3d lp3 = mesh->Point (el.PNum(quads[j][2])); Point3d lp4 = mesh->Point (el.PNum(quads[j][3])); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length() + 1e-12); glNormal3dv (&n.X()); glVertex3dv (&lp1.X()); glVertex3dv (&lp2.X()); glVertex3dv (&lp3.X()); glVertex3dv (&lp4.X()); } glEnd(); break; } case QUAD8: { glBegin (GL_TRIANGLES); static int boundary[] = { 1, 5, 2, 8, 3, 6, 4, 7, 1 }; Point3d c(0,0,0); for (int j = 0; j < 4; j++) { const Point3d & hp = mesh->Point (el[j]); c.X() -= 0.25 * hp.X(); c.Y() -= 0.25 * hp.Y(); c.Z() -= 0.25 * hp.Z(); } for (int j = 4; j < 8; j++) { const Point3d & hp = mesh->Point (el[j]); c.X() += 0.5 * hp.X(); c.Y() += 0.5 * hp.Y(); c.Z() += 0.5 * hp.Z(); } for (int j = 0; j < 8; j++) { Point3d lp1 = mesh->Point (el.PNum(boundary[j])); Point3d lp2 = mesh->Point (el.PNum(boundary[j+1])); Vec3d n = Cross (Vec3d (c, lp1), Vec3d (c, lp2)); n /= (n.Length() + 1e-12); glNormal3dv (&n.X()); glVertex3dv (&lp1.X()); glVertex3dv (&lp2.X()); glVertex3dv (&c.X()); } glEnd(); break; } default: PrintSysError ("Cannot draw (2) surface element of type ", int(el.GetType())); } } } glLoadName (0); glEndList (); #ifdef PARALLELGL glFinish(); if (id > 0) MyMPI_Send (filledlist, 0, MPI_TAG_VIS); #endif } void VisualSceneMesh :: BuildLineList() { shared_ptr mesh = GetMesh(); static int timer = NgProfiler::CreateTimer ("Mesh::BuildLineList"); NgProfiler::RegionTimer reg (timer); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); par_linelists.SetSize (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("linelist"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (par_linelists[dest], dest, MPI_TAG_VIS); if (linelist) glDeleteLists (linelist, 1); linelist = glGenLists (1); glNewList (linelist, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (par_linelists[dest]); glEndList(); linetimestamp = NextTimeStamp(); return; } #endif if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } linetimestamp = NextTimeStamp(); #ifdef STLGEOM STLGeometry * stlgeometry = dynamic_cast (ng_geometry); bool checkvicinity = (stlgeometry != NULL) && stldoctor.showvicinity; #endif if (linelist) glDeleteLists (linelist, 1); linelist = glGenLists (1); glNewList (linelist, GL_COMPILE); // cout << "linelist = " << linelist << endl; glLineWidth (1.0f); int hoplotn = 1 << vispar.subdivisions; // PrintMessage (3, "nse = ", mesh->GetNSE()); for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) { const Element2d & el = (*mesh)[sei]; bool drawel = (!el.IsDeleted() & el.IsVisible()); #ifdef STLGEOM if (checkvicinity) for (int j = 0; j < el.GetNP(); j++) if (!stlgeometry->Vicinity(el.GeomInfoPi(j+1).trignum)) drawel = 0; #endif if (!drawel) continue; switch (el.GetType()) { case TRIG: { CurvedElements & curv = mesh->GetCurvedElements(); if (curv.IsHighOrder()) // && curv.IsSurfaceElementCurved(sei)) { Point<3> xg; glBegin (GL_LINE_LOOP); for (int i = 0; i < hoplotn; i++) { Point<2> xr (double(i) / hoplotn, 0); curv.CalcSurfaceTransformation (xr, sei, xg); glVertex3dv (xg); } for (int i = 0; i < hoplotn; i++) { Point<2> xr (double(hoplotn-i) / hoplotn, double(i)/hoplotn); curv.CalcSurfaceTransformation (xr, sei, xg); glVertex3dv (xg); } for (int i = 0; i < hoplotn; i++) { Point<2> xr (0, double(hoplotn-i) / hoplotn); curv.CalcSurfaceTransformation (xr, sei, xg); glVertex3dv (xg); } glEnd(); } else { glBegin (GL_TRIANGLES); for (int j = 0; j < 3; j++) glVertex3dv ( (*mesh) [el[j]] ); /* const Point<3> & lp0 = (*mesh) [el[0]]; const Point<3> & lp1 = (*mesh) [el[1]]; const Point<3> & lp2 = (*mesh) [el[2]]; glVertex3dv (lp0); glVertex3dv (lp1); glVertex3dv (lp2); */ glEnd(); } break; } case QUAD: { CurvedElements & curv = mesh->GetCurvedElements(); if (curv.IsHighOrder()) // && curv.IsSurfaceElementCurved(sei)) { Point<2> xr; Point<3> xg; glBegin (GL_LINE_STRIP); for (int side = 0; side < 4; side++) { for (int i = 0; i <= hoplotn; i++) { switch (side) { case 0: xr(0) = (double) i/hoplotn; xr(1) = 0.; break; case 1: xr(0) = 1.; xr(1) = (double) i/hoplotn; break; case 2: xr(0) = (double) (hoplotn-i)/hoplotn; xr(1) = 1.; break; case 3: xr(0) = 0.; xr(1) = (double) (hoplotn-i)/hoplotn; break; } curv.CalcSurfaceTransformation (xr, sei, xg); glVertex3d (xg(0), xg(1), xg(2)); } } glEnd(); } else { glBegin (GL_QUADS); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(4)); const Point3d & lp4 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, Center (lp3, lp4))); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp4.X(), lp4.Y(), lp4.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glEnd(); } break; } case TRIG6: { int lines[6][2] = { { 1, 6 }, { 2, 6 }, { 1, 5 }, { 3, 5 }, { 2, 4 }, { 3, 4 } }; glBegin (GL_LINES); for (int j = 0; j < 6; j++) { const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0])); const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1])); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); } glEnd(); break; } case QUAD6: { int lines[6][2] = { { 1, 5 }, { 2, 5 }, { 3, 6 }, { 4, 6 }, { 1, 4 }, { 2, 3 } }; glBegin (GL_LINES); for (int j = 0; j < 6; j++) { const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0])); const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1])); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); } glEnd (); break; } case QUAD8: { int lines[8][2] = { { 1, 5 }, { 2, 5 }, { 3, 6 }, { 4, 6 }, { 1, 7 }, { 4, 7 }, { 2, 8 }, { 3, 8 } }; glBegin (GL_LINES); for (int j = 0; j < 8; j++) { const Point3d & lp1 = mesh->Point (el.PNum(lines[j][0])); const Point3d & lp2 = mesh->Point (el.PNum(lines[j][1])); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); } glEnd (); break; } default: PrintSysError ("Cannot draw (4) surface element of type ", int(el.GetType())); } } glEndList (); #ifdef PARALLELGL glFinish(); if (id > 0) MyMPI_Send (linelist, 0, MPI_TAG_VIS); #endif } void VisualSceneMesh :: BuildEdgeList() { shared_ptr mesh = GetMesh(); if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } if (edgetimestamp > mesh->GetTimeStamp () && vispar.drawtetsdomain == 0 && vispar.shrink == 1) return; edgetimestamp = NextTimeStamp(); if (edgelist) glDeleteLists (edgelist, 1); edgelist = glGenLists (1); glNewList (edgelist, GL_COMPILE); GLfloat matcoledge[] = { 0, 0, 1, 1 }; GLfloat matcolsingedge[] = { 1, 0, 1, 1 }; glEnable (GL_POLYGON_OFFSET_LINE); glPolygonOffset (1, -1); glEnable (GL_COLOR_MATERIAL); glDisable (GL_LIGHTING); for (int i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh->LineSegment(i); /* #ifdef PARALLEL if (ntasks > 1 && vispar.drawtetsdomain && // (vispar.drawtetsdomain != seg.GetPartition())) continue; (vispar.drawtetsdomain != mesh->seg_partition[i-1]) continue; #endif */ const Point3d & p1 = (*mesh)[seg[0]]; const Point3d & p2 = (*mesh)[seg[1]]; if (seg.singedge_left || seg.singedge_right) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcolsingedge); else glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcoledge); if (seg.singedge_left || seg.singedge_right) glColor3fv (matcolsingedge); else glColor3fv (matcoledge); if (seg.edgenr == seledge) glLineWidth(5); else glLineWidth(2); if (mesh->GetCurvedElements().IsHighOrder()) { int hoplotn = 1 << vispar.subdivisions; // mesh->GetCurvedElements().GetNVisualSubsecs(); Point<3> x; glBegin (GL_LINE_STRIP); for (int j = 0; j <= hoplotn; j++) { mesh->GetCurvedElements().CalcSegmentTransformation ((double) j/hoplotn, i-1, x); glVertex3d (x(0), x(1), x(2)); /* cout << "x = " << x(0) << ", " << x(1) << ", " << x(2) << ", norm = 1+" << sqrt(x(0)*x(0)+x(1)*x(1))-1 << ", phi = " << atan2(x(1), x(0))/M_PI << endl; */ } glEnd(); } else { glBegin (GL_LINES); Point<3> hp1 = p1; Point<3> hp2 = p2; Point<3> c = Center(p1, p2); if (vispar.shrink < 1) { hp1 = c + vispar.shrink * (hp1 - c); hp2 = c + vispar.shrink * (hp2 - c); } glVertex3dv (hp1); glVertex3dv (hp2); // p2.X(), p2.Y(), p2.Z()); glEnd(); } } glLineWidth (2); glDisable (GL_POLYGON_OFFSET_LINE); glDisable (GL_COLOR_MATERIAL); glEnable (GL_LIGHTING); glEndList(); } void VisualSceneMesh :: BuildPointNumberList() { ; } // Bernstein Pol B_{n,i}(x) = n! / i! / (n-i)! (1-x)^{n-i} x^i static inline double Bernstein (int n, int i, double x) { double val = 1; for (int j = 1; j <= i; j++) val *= x; for (int j = 1; j <= n-i; j++) val *= (1-x) * (j+i) / j; return val; } void ToBernstein (int order, Point<3> * pts, int stride) { static DenseMatrix mat, inv; static Vector vec1, vec2; if (mat.Height () != order+1) { mat.SetSize (order+1); inv.SetSize (order+1); vec1.SetSize (order+1); vec2.SetSize (order+1); for (int i = 0; i <= order; i++) { double x = double(i) / order; for (int j = 0; j <= order; j++) mat(i,j) = Bernstein (order, j, x); } CalcInverse (mat, inv); } for (int i = 0; i < 3; i++) { for (int j = 0; j <= order; j++) vec1(j) = pts[j*stride](i); inv.Mult (vec1, vec2); for (int j = 0; j <= order; j++) pts[j*stride](i) = vec2(j); } } void VisualSceneMesh :: BuildTetList() { shared_ptr mesh = GetMesh(); if (tettimestamp > mesh->GetTimeStamp () && tettimestamp > vispar.clipping.timestamp ) return; if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } tettimestamp = NextTimeStamp(); if (tetlist) glDeleteLists (tetlist, 1); tetlist = glGenLists (1); glNewList (tetlist, GL_COMPILE); Vector locms; // Philippose - 16/02/2010 // Add Mesh size based coloring of // meshes also for the volume elements if (vispar.colormeshsize) { glEnable (GL_COLOR_MATERIAL); locms.SetSize (mesh->GetNP()); maxh = -1; minh = 1e99; for (int i = 1; i <= locms.Size(); i++) { Point3d p = mesh->Point(i); locms(i-1) = mesh->GetH (p); if (locms(i-1) > maxh) maxh = locms(i-1); if (locms(i-1) < minh) minh = locms(i-1); } if (!locms.Size()) { minh = 1; maxh = 10; } } else glDisable (GL_COLOR_MATERIAL); Array faces; BitArray shownode(mesh->GetNP()); if (vispar.clipping.enable) { shownode.Clear(); for (int i = 1; i <= shownode.Size(); i++) { Point<3> p = mesh->Point(i); double val = p[0] * clipplane[0] + p[1] * clipplane[1] + p[2] * clipplane[2] + clipplane[3]; if (val > 0) shownode.Set (i); } } else shownode.Set(); static float tetcols[][4] = { { 1.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } /* { 1.0f, 1.0f, 0.0f, 0.3f }, { 1.0f, 0.0f, 0.0f, 0.3f }, { 0.0f, 1.0f, 0.0f, 0.3f }, { 0.0f, 0.0f, 1.0f, 0.3f } */ }; CurvedElements & curv = mesh->GetCurvedElements(); if (!curv.IsHighOrder()) glShadeModel (GL_FLAT); else glShadeModel (GL_SMOOTH); int hoplotn = max (2, 1 << vispar.subdivisions); for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { if (vispar.drawtetsdomain > 0) { /* int tetid = vispar.drawmetispartition ? (*mesh)[ei].GetPartition() : (*mesh)[ei].GetIndex(); */ int tetid = (*mesh)[ei].GetIndex(); if (vispar.drawtetsdomain != tetid) continue; } const Element & el = (*mesh)[ei]; if ((el.GetType() == TET || el.GetType() == TET10) && !el.IsDeleted()) { bool drawtet = 1; for (int j = 0; j < 4; j++) if (!shownode.Test(el[j])) drawtet = 0; if (!drawtet) continue; int ind = el.GetIndex() % 4; // if (vispar.drawmetispartition && el.GetPartition()!=-1) // ind = el.GetPartition() % 4; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tetcols[ind]); if (curv.IsHighOrder()) // && curv.IsElementCurved(ei)) { const ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (TET); const Point3d * vertices = MeshTopology :: GetVertices (TET); /* Point<3> grid[11][11]; Point<3> fpts[3]; int order = vispar.subdivisions+1; for (int trig = 0; trig < 4; trig++) { for (int j = 0; j < 3; j++) fpts[j] = vertices[faces[trig][j]-1]; static Point<3> c(0.25, 0.25, 0.25); if (vispar.shrink < 1) for (int j = 0; j < 3; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); for (int ix = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++) { double lami[3] = { (1-double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * (1-double(iy)/order), double(iy)/order }; Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l); curv.CalcElementTransformation (xl, i-1, grid[ix][iy]); } for (int j = 0; j <= order; j++) ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]); for (int j = 0; j <= order; j++) ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1, 0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1, &grid[0][0](0)); glEnable(GL_MAP2_VERTEX_3); glEnable(GL_AUTO_NORMAL); glMapGrid2f(8, 0.0, 0.999, 8, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, 8, 0, 8); glDisable (GL_AUTO_NORMAL); glDisable (GL_MAP2_VERTEX_3); } */ int order = curv.GetOrder(); Array > ploc ( (order+1)*(order+1) ); Array > pglob ( (order+1)*(order+1) ); Point<3> fpts[3]; for (int trig = 0; trig < 4; trig++) { for (int j = 0; j < 3; j++) fpts[j] = vertices[faces[trig][j]-1]; static Point<3> c(0.25, 0.25, 0.25); if (vispar.shrink < 1) for (int j = 0; j < 3; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); for (int ix = 0, ii = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++, ii++) { double lami[3] = { (1-double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * (1-double(iy)/order), double(iy)/order }; Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l); ploc[ii] = xl; } curv.CalcMultiPointElementTransformation (&ploc, ei, &pglob, 0); Point<3> grid[11][11]; for (int ix = 0, ii = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++, ii++) grid[ix][iy] = pglob[ii]; for (int j = 0; j <= order; j++) ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]); for (int j = 0; j <= order; j++) ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1, 0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1, &grid[0][0](0)); glEnable(GL_MAP2_VERTEX_3); glEnable(GL_AUTO_NORMAL); glMapGrid2f(hoplotn, 0.0, 0.9999f, hoplotn, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, hoplotn, 0, hoplotn); glDisable (GL_AUTO_NORMAL); glDisable (GL_MAP2_VERTEX_3); } } else // Not High Order { Point<3> pts[4]; for (int j = 0; j < 4; j++) pts[j] = (*mesh)[el[j]]; if (vispar.shrink < 1) { Point<3> c = Center (pts[0], pts[1], pts[2], pts[3]); for (int j = 0; j < 4; j++) pts[j] = c + vispar.shrink * (pts[j]-c); } Vec<3> n; // Philippose - 16/02/2010 // Add Mesh size based coloring of // meshes also for the volume elements if(vispar.colormeshsize) { glBegin (GL_TRIANGLE_STRIP); n = Cross (pts[1]-pts[0], pts[2]-pts[0]); glNormal3dv (n); SetOpenGlColor (locms(el[0]-1), minh, maxh, 0); glVertex3dv (pts[0]); SetOpenGlColor (locms(el[1]-1), minh, maxh, 0); glVertex3dv (pts[1]); SetOpenGlColor (locms(el[2]-1), minh, maxh, 0); glVertex3dv (pts[2]); n = Cross (pts[3]-pts[1], pts[2]-pts[1]); glNormal3dv (n); SetOpenGlColor (locms(el[3]-1), minh, maxh, 0); glVertex3dv (pts[3]); n = Cross (pts[3]-pts[2], pts[0]-pts[2]); glNormal3dv (n); SetOpenGlColor (locms(el[0]-1), minh, maxh, 0); glVertex3dv (pts[0]); n = Cross (pts[1]-pts[3], pts[0]-pts[3]); glNormal3dv (n); SetOpenGlColor (locms(el[1]-1), minh, maxh, 0); glVertex3dv (pts[1]); glEnd(); } else // Do not color mesh based on mesh size { GLubyte ind[4][3] = { { 0,1,2 }, { 3,1,0 }, { 1,3,2 }, { 2,3,0 } }; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_DOUBLE, 0, &pts[0](0)); for (int j = 0; j < 4; j++) { glNormal3dv (Cross (pts[ind[j][1]]-pts[ind[j][0]], pts[ind[j][2]]-pts[ind[j][0]])); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &ind[j][0]); } glDisableClientState(GL_VERTEX_ARRAY); /* glBegin (GL_TRIANGLE_STRIP); glNormal3dv (Cross (pts[1]-pts[0], pts[2]-pts[0])); glVertex3dv (pts[0]); glVertex3dv (pts[1]); glVertex3dv (pts[2]); glNormal3dv (Cross (pts[3]-pts[1], pts[2]-pts[1])); glVertex3dv (pts[3]); glNormal3dv (Cross (pts[3]-pts[2], pts[0]-pts[2])); glVertex3dv (pts[0]); glNormal3dv (Cross (pts[1]-pts[3], pts[0]-pts[3])); glVertex3dv (pts[1]); glEnd(); */ } } } } glEndList (); } void VisualSceneMesh :: BuildPrismList() { shared_ptr mesh = GetMesh(); if (prismtimestamp > mesh->GetTimeStamp () && prismtimestamp > vispar.clipping.timestamp ) return; if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } prismtimestamp = NextTimeStamp(); if (prismlist) glDeleteLists (prismlist, 1); prismlist = glGenLists (1); glNewList (prismlist, GL_COMPILE); static float prismcol[] = { 0.0f, 1.0f, 1.0f, 1.0f }; glLineWidth (1.0f); Array faces; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, prismcol); for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; if (el.GetType() == PRISM && !el.IsDeleted()) { int j; int i = ei + 1; CurvedElements & curv = mesh->GetCurvedElements(); if (curv.IsHighOrder()) // && curv.IsElementCurved(ei)) { const ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (PRISM); const Point3d * vertices = MeshTopology :: GetVertices (PRISM); Point<3> grid[11][11]; Point<3> fpts[4]; int order = vispar.subdivisions+1; for (int trig = 0; trig < 2; trig++) { for (int j = 0; j < 3; j++) fpts[j] = vertices[faces[trig][j]-1]; static Point<3> c(1.0/3.0, 1.0/3.0, 0.5); if (vispar.shrink < 1) for (int j = 0; j < 3; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); for (int ix = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++) { double lami[3] = { (1-double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * (1-double(iy)/order), double(iy)/order }; Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l); curv.CalcElementTransformation (xl, i-1, grid[ix][iy]); } for (int j = 0; j <= order; j++) ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]); for (int j = 0; j <= order; j++) ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1, 0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1, &grid[0][0](0)); glEnable(GL_MAP2_VERTEX_3); glEnable(GL_AUTO_NORMAL); glMapGrid2f(8, 0.0, 0.999f, 8, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, 8, 0, 8); glDisable (GL_AUTO_NORMAL); glDisable (GL_MAP2_VERTEX_3); } for (int quad = 2; quad < 5; quad++) { for (int j = 0; j < 4; j++) fpts[j] = vertices[faces[quad][j]-1]; static Point<3> c(1.0/3.0, 1.0/3.0, 0.5); if (vispar.shrink < 1) for (int j = 0; j < 4; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); for (int ix = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++) { double lami[4] = { (1-double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * ( double(iy)/order), (1-double(ix)/order) * ( double(iy)/order) }; Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l) + lami[3] * fpts[3](l); curv.CalcElementTransformation (xl, ei, grid[ix][iy]); } for (int j = 0; j <= order; j++) ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]); for (int j = 0; j <= order; j++) ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1, 0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1, &grid[0][0](0)); glEnable(GL_MAP2_VERTEX_3); glEnable(GL_AUTO_NORMAL); glMapGrid2f(8, 0.0, 1.0, 8, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, 8, 0, 8); glDisable (GL_AUTO_NORMAL); glDisable (GL_MAP2_VERTEX_3); } /* int hoplotn = 1 << vispar.subdivisions; // int hoplotn = curv.GetNVisualSubsecs(); const Point3d * facepoint = MeshTopology :: GetVertices (TRIG); const ELEMENT_FACE * elface = MeshTopology :: GetFaces(TRIG); glBegin (GL_TRIANGLES); for (int trig = 0; trig<2; trig++) { Vec<3> x0,x1,d0,d1; x0 = facepoint[1] - facepoint[2]; x1 = facepoint[0] - facepoint[2]; x0.Normalize(); x1.Normalize(); if (trig == 1) swap (x0,x1); Point<3> xr[3]; Point<3> xg; Vec<3> dx, dy, dz, n; for (int i1 = 0; i1 < hoplotn; i1++) for (int j1 = 0; j1 < hoplotn-i1; j1++) for (int k = 0; k < 2; k++) { if (k == 0) { xr[0](0) = (double) i1/hoplotn; xr[0](1) = (double) j1/hoplotn; xr[1](0) = (double)(i1+1)/hoplotn; xr[1](1) = (double) j1/hoplotn; xr[2](0) = (double) i1/hoplotn; xr[2](1) = (double)(j1+1)/hoplotn; } else { if (j1 == hoplotn-i1-1) continue; xr[0](0) = (double)(i1+1)/hoplotn; xr[0](1) = (double) j1/hoplotn; xr[1](0) = (double)(i1+1)/hoplotn; xr[1](1) = (double)(j1+1)/hoplotn; xr[2](0) = (double) i1/hoplotn; xr[2](1) = (double)(j1+1)/hoplotn; }; for (int l=0; l<3; l++) { Mat<3,3> dxdxi; xr[l](2) = (double) trig; curv.CalcElementTransformation (xr[l], i-1, xg, dxdxi); for (int i = 0; i < 3; i++) { dx(i) = dxdxi(i,0); dy(i) = dxdxi(i,1); dz(i) = dxdxi(i,2); } Vec<3> d0 = x0(0)*dx + x0(1)*dy + x0(2)*dz; Vec<3> d1 = x1(0)*dx + x1(1)*dy + x1(2)*dz; n = Cross (d1, d0); glNormal3d (n(0), n(1), n(2)); glVertex3d (xg(0), xg(1), xg(2)); } } } glEnd (); glBegin (GL_QUADS); for (int quad = 0; quad<3; quad++) { const Point3d * facepoint = MeshTopology :: GetVertices (PRISM); Vec<3> x0,x1; int xyz; switch (quad) { case 0: x0 = facepoint[5] - facepoint[2]; x1 = facepoint[0] - facepoint[2]; xyz = 0; break; case 1: x0 = facepoint[4] - facepoint[0]; x1 = facepoint[1] - facepoint[0]; xyz = 0; break; case 2: x0 = facepoint[1] - facepoint[2]; x1 = facepoint[5] - facepoint[2]; xyz = 1; break; } x0.Normalize(); x1.Normalize(); swap (x0,x1); Point<3> xr[4]; Point<3> xg; Vec<3> dx, dy, dz, n; for (int i1 = 0; i1 < hoplotn; i1++) for (int j1 = 0; j1 < hoplotn; j1++) { xr[0](xyz) = (double) i1/hoplotn; xr[0](2) = (double) j1/hoplotn; xr[1](xyz) = (double)(i1+1)/hoplotn; xr[1](2) = (double) j1/hoplotn; xr[2](xyz) = (double)(i1+1)/hoplotn; xr[2](2) = (double)(j1+1)/hoplotn; xr[3](xyz) = (double) i1/hoplotn; xr[3](2) = (double)(j1+1)/hoplotn; for (int l=0; l<4; l++) { switch (quad) { case 0: xr[l](1) = 0; break; case 1: xr[l](1) = 1-xr[l](0); break; case 2: xr[l](0) = 0; break; } Mat<3,3> dxdxi; curv.CalcElementTransformation (xr[l], i-1, xg, dxdxi); for (int i = 0; i < 3; i++) { dx(i) = dxdxi(i,0); dy(i) = dxdxi(i,1); dz(i) = dxdxi(i,2); } Vec<3> d0 = x0(0)*dx + x0(1)*dy + x0(2)*dz; Vec<3> d1 = x1(0)*dx + x1(1)*dy + x1(2)*dz; n = Cross (d1, d0); glNormal3d (n(0), n(1), n(2)); glVertex3d (xg(0), xg(1), xg(2)); } } } glEnd (); */ } else { Point3d c(0,0,0); if (vispar.shrink < 1) { for (j = 1; j <= 6; j++) { Point3d p = mesh->Point(el.PNum(j)); c.X() += p.X() / 6; c.Y() += p.Y() / 6; c.Z() += p.Z() / 6; } } el.GetSurfaceTriangles (faces); glBegin (GL_TRIANGLES); for (j = 1; j <= faces.Size(); j++) { Element2d & face = faces.Elem(j); Point3d lp1 = mesh->Point (el.PNum(face.PNum(1))); Point3d lp2 = mesh->Point (el.PNum(face.PNum(2))); Point3d lp3 = mesh->Point (el.PNum(face.PNum(3))); Vec3d n = Cross (Vec3d (lp1, lp3), Vec3d (lp1, lp2)); n /= (n.Length()+1e-12); glNormal3d (n.X(), n.Y(), n.Z()); if (vispar.shrink < 1) { lp1 = c + vispar.shrink * (lp1 - c); lp2 = c + vispar.shrink * (lp2 - c); lp3 = c + vispar.shrink * (lp3 - c); } glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } glEnd(); } } } glEndList (); } void VisualSceneMesh :: BuildHexList() { shared_ptr mesh = GetMesh(); if (hextimestamp > mesh->GetTimeStamp () && hextimestamp > vispar.clipping.timestamp ) return; if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } hextimestamp = NextTimeStamp(); if (hexlist) glDeleteLists (hexlist, 1); hexlist = glGenLists (1); glNewList (hexlist, GL_COMPILE); static float hexcol[] = { 1.0f, 1.0f, 0.0f, 1.0f }; glLineWidth (1.0f); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, hexcol); Array faces; // int hoplotn = 1 << vispar.subdivisions; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; if (el.GetType() == HEX && !el.IsDeleted()) { CurvedElements & curv = mesh->GetCurvedElements(); if (curv.IsHighOrder()) // && curv.IsElementCurved(ei)) { /* // classical glBegin (GL_QUADS); const ELEMENT_FACE * faces = MeshTopology :: GetFaces (HEX); const Point3d * vertices = MeshTopology :: GetVertices (HEX); Point<3> grid[33][33]; Vec<3> gridn[33][33]; Point<3> fpts[4]; for (int quad = 0; quad<6; quad++) { for (int j = 0; j < 4; j++) fpts[j] = vertices[faces[quad][j]-1]; static Point<3> c(0.5, 0.5, 0.5); if (vispar.shrink < 1) for (int j = 0; j < 4; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); Vec<3> taux = fpts[1]-fpts[0]; Vec<3> tauy = fpts[3]-fpts[0]; for (int ix = 0; ix <= hoplotn; ix++) for (int iy = 0; iy <= hoplotn; iy++) { Point<3> xl; Mat<3,3> dxdxi; double lami[4] = { (1-double(ix)/hoplotn) * (1-double(iy)/hoplotn), ( double(ix)/hoplotn) * (1-double(iy)/hoplotn), ( double(ix)/hoplotn) * ( double(iy)/hoplotn), (1-double(ix)/hoplotn) * ( double(iy)/hoplotn) }; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l) + lami[3] * fpts[3](l); curv.CalcElementTransformation (xl, ei, grid[ix][iy], dxdxi); Vec<3> gtaux = dxdxi * taux; Vec<3> gtauy = dxdxi * tauy; gridn[ix][iy] = Cross (gtauy, gtaux).Normalize(); } for (int ix = 0; ix < hoplotn; ix++) for (int iy = 0; iy < hoplotn; iy++) { glNormal3dv (gridn[ix][iy]); glVertex3dv (grid[ix][iy]); glNormal3dv (gridn[ix+1][iy]); glVertex3dv (grid[ix+1][iy]); glNormal3dv (gridn[ix+1][iy+1]); glVertex3dv (grid[ix+1][iy+1]); glNormal3dv (gridn[ix][iy+1]); glVertex3dv (grid[ix][iy+1]); } } glEnd (); */ const ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (HEX); const Point3d * vertices = MeshTopology :: GetVertices (HEX); Point<3> grid[11][11]; Point<3> fpts[4]; int order = vispar.subdivisions+1; for (int quad = 0; quad<6; quad++) { for (int j = 0; j < 4; j++) fpts[j] = vertices[faces[quad][j]-1]; static Point<3> c(0.5, 0.5, 0.5); if (vispar.shrink < 1) for (int j = 0; j < 4; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); for (int ix = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++) { double lami[4] = { (1-double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * ( double(iy)/order), (1-double(ix)/order) * ( double(iy)/order) }; Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l) + lami[3] * fpts[3](l); curv.CalcElementTransformation (xl, ei, grid[ix][iy]); } for (int j = 0; j <= order; j++) ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]); for (int j = 0; j <= order; j++) ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1, 0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1, &grid[0][0](0)); glEnable(GL_MAP2_VERTEX_3); glEnable(GL_AUTO_NORMAL); glMapGrid2f(8, 0.0, 1.0, 8, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, 8, 0, 8); glDisable (GL_AUTO_NORMAL); glDisable (GL_MAP2_VERTEX_3); } } else { Point3d c(0,0,0); if (vispar.shrink < 1) { for (int j = 1; j <= 8; j++) { Point3d p = mesh->Point(el.PNum(j)); c.X() += p.X(); c.Y() += p.Y(); c.Z() += p.Z(); } c.X() /= 8; c.Y() /= 8; c.Z() /= 8; } glBegin (GL_TRIANGLES); el.GetSurfaceTriangles (faces); for (int j = 1; j <= faces.Size(); j++) { Element2d & face = faces.Elem(j); Point<3> lp1 = mesh->Point (el.PNum(face.PNum(1))); Point<3> lp2 = mesh->Point (el.PNum(face.PNum(2))); Point<3> lp3 = mesh->Point (el.PNum(face.PNum(3))); Vec<3> n = Cross (lp3-lp1, lp2-lp1); n.Normalize(); glNormal3dv (n); if (vispar.shrink < 1) { lp1 = c + vispar.shrink * (lp1 - c); lp2 = c + vispar.shrink * (lp2 - c); lp3 = c + vispar.shrink * (lp3 - c); } glVertex3dv (lp1); glVertex3dv (lp2); glVertex3dv (lp3); } glEnd(); } } } glEndList (); } void VisualSceneMesh :: BuildPyramidList() { shared_ptr mesh = GetMesh(); if (pyramidtimestamp > mesh->GetTimeStamp () && pyramidtimestamp > vispar.clipping.timestamp ) return; if (!lock) { lock = new NgLock (mesh->Mutex()); lock -> Lock(); } pyramidtimestamp = NextTimeStamp(); if (pyramidlist) glDeleteLists (pyramidlist, 1); pyramidlist = glGenLists (1); glNewList (pyramidlist, GL_COMPILE); static float pyramidcol[] = { 1.0f, 0.0f, 1.0f, 1.0f }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, pyramidcol); glLineWidth (1.0f); Array faces; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; if ((el.GetType() == PYRAMID || el.GetType() == PYRAMID13) && !el.IsDeleted()) { int i = ei + 1; CurvedElements & curv = mesh->GetCurvedElements(); if (curv.IsHighOrder()) // && curv.IsElementCurved(ei)) { const ELEMENT_FACE * faces = MeshTopology :: GetFaces1 (PYRAMID); const Point3d * vertices = MeshTopology :: GetVertices (PYRAMID); Point<3> grid[11][11]; Point<3> fpts[4]; int order = vispar.subdivisions+1; for (int trig = 0; trig < 4; trig++) { for (int j = 0; j < 3; j++) fpts[j] = vertices[faces[trig][j]-1]; static Point<3> c(0.375, 0.375, 0.25); if (vispar.shrink < 1) for (int j = 0; j < 3; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); for (int ix = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++) { double lami[3] = { (1-double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * (1-double(iy)/order), double(iy)/order }; Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l); curv.CalcElementTransformation (xl, i-1, grid[ix][iy]); } for (int j = 0; j <= order; j++) ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]); for (int j = 0; j <= order; j++) ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1, 0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1, &grid[0][0](0)); glEnable(GL_MAP2_VERTEX_3); glEnable(GL_AUTO_NORMAL); glMapGrid2f(8, 0.0, 0.999f, 8, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, 8, 0, 8); glDisable (GL_AUTO_NORMAL); glDisable (GL_MAP2_VERTEX_3); } for (int quad = 4; quad < 5; quad++) { for (int j = 0; j < 4; j++) fpts[j] = vertices[faces[quad][j]-1]; static Point<3> c(0.375, 0.375, 0.25); if (vispar.shrink < 1) for (int j = 0; j < 4; j++) fpts[j] += (1-vispar.shrink) * (c-fpts[j]); for (int ix = 0; ix <= order; ix++) for (int iy = 0; iy <= order; iy++) { double lami[4] = { (1-double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * (1-double(iy)/order), ( double(ix)/order) * ( double(iy)/order), (1-double(ix)/order) * ( double(iy)/order) }; Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = lami[0] * fpts[0](l) + lami[1] * fpts[1](l) + lami[2] * fpts[2](l) + lami[3] * fpts[3](l); curv.CalcElementTransformation (xl, ei, grid[ix][iy]); } for (int j = 0; j <= order; j++) ToBernstein (order, &grid[j][0], &grid[0][1]-&grid[0][0]); for (int j = 0; j <= order; j++) ToBernstein (order, &grid[0][j], &grid[1][0]-&grid[0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, &grid[0][1](0)-&grid[0][0](0), order+1, 0.0, 1.0, &grid[1][0](0)-&grid[0][0](0), order+1, &grid[0][0](0)); glEnable(GL_MAP2_VERTEX_3); glEnable(GL_AUTO_NORMAL); glMapGrid2f(8, 0.0, 1.0, 8, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, 8, 0, 8); glDisable (GL_AUTO_NORMAL); glDisable (GL_MAP2_VERTEX_3); } /* int hoplotn = 1 << vispar.subdivisions; const ELEMENT_FACE * faces = MeshTopology :: GetFaces (PYRAMID); const Point3d * vertices = MeshTopology :: GetVertices (PYRAMID); Point<3> grid[33][33]; Vec<3> gridn[33][33]; glBegin (GL_TRIANGLES); for (int trig = 0; trig < 4; trig++) { Point<3> p0 = vertices[faces[trig][0]-1]; Point<3> p1 = vertices[faces[trig][1]-1]; Point<3> p2 = vertices[faces[trig][2]-1]; if (vispar.shrink < 1) { static Point<3> c(0.375, 0.375, 0.25); p0 = c + vispar.shrink * (p0 - c); p1 = c + vispar.shrink * (p1 - c); p2 = c + vispar.shrink * (p2 - c); } Vec<3> taux = p0-p2; Vec<3> tauy = p1-p2; Vec<3> gtaux, gtauy; Point<3> xl; Mat<3,3> dxdxi; for (int ix = 0; ix <= hoplotn; ix++) for (int iy = 0; iy <= hoplotn-ix; iy++) { for (int l = 0; l < 3; l++) xl(l) = (1-double(ix+iy)/hoplotn) * p2(l) + (double(ix)/hoplotn) * p0(l) + (double(iy)/hoplotn) * p1(l); curv.CalcElementTransformation (xl, i-1, grid[ix][iy], dxdxi); gtaux = dxdxi * taux; gtauy = dxdxi * tauy; gridn[ix][iy] = Cross (gtauy, gtaux).Normalize(); } for (int ix = 0; ix < hoplotn; ix++) for (int iy = 0; iy < hoplotn-ix; iy++) { glNormal3dv (gridn[ix][iy]); glVertex3dv (grid[ix][iy]); glNormal3dv (gridn[ix+1][iy]); glVertex3dv (grid[ix+1][iy]); glNormal3dv (gridn[ix][iy+1]); glVertex3dv (grid[ix][iy+1]); if (iy < hoplotn-ix-1) { glNormal3dv (gridn[ix][iy+1]); glVertex3dv (grid[ix][iy+1]); glNormal3dv (gridn[ix+1][iy]); glVertex3dv (grid[ix+1][iy]); glNormal3dv (gridn[ix+1][iy+1]); glVertex3dv (grid[ix+1][iy+1]); } } } glEnd (); glBegin (GL_QUADS); for (int quad = 4; quad < 5; quad++) { Point<3> p0 = vertices[faces[quad][0]-1]; Point<3> p1 = vertices[faces[quad][1]-1]; Point<3> p2 = vertices[faces[quad][2]-1]; Point<3> p3 = vertices[faces[quad][3]-1]; if (vispar.shrink < 1) { static Point<3> c(0.375, 0.375, 0.25); p0 = c + vispar.shrink * (p0 - c); p1 = c + vispar.shrink * (p1 - c); p2 = c + vispar.shrink * (p2 - c); p3 = c + vispar.shrink * (p3 - c); } Vec<3> taux = p1-p0; Vec<3> tauy = p3-p0; Vec<3> gtaux, gtauy; Point<3> xl, xg; Mat<3,3> dxdxi; for (int ix = 0; ix <= hoplotn; ix++) for (int iy = 0; iy <= hoplotn; iy++) { Point<3> xl; for (int l = 0; l < 3; l++) xl(l) = (1-double(ix)/hoplotn)*(1-double(iy)/hoplotn) * p0(l) + ( double(ix)/hoplotn)*(1-double(iy)/hoplotn) * p1(l) + ( double(ix)/hoplotn)*( double(iy)/hoplotn) * p2(l) + (1-double(ix)/hoplotn)*( double(iy)/hoplotn) * p3(l); curv.CalcElementTransformation (xl, i-1, grid[ix][iy], dxdxi); gtaux = dxdxi * taux; gtauy = dxdxi * tauy; gridn[ix][iy] = Cross (gtauy, gtaux).Normalize(); } for (int ix = 0; ix < hoplotn; ix++) for (int iy = 0; iy < hoplotn; iy++) { glNormal3dv (gridn[ix][iy]); glVertex3dv (grid[ix][iy]); glNormal3dv (gridn[ix+1][iy]); glVertex3dv (grid[ix+1][iy]); glNormal3dv (gridn[ix+1][iy+1]); glVertex3dv (grid[ix+1][iy+1]); glNormal3dv (gridn[ix][iy+1]); glVertex3dv (grid[ix][iy+1]); } } glEnd (); */ } else { Point3d c(0,0,0); if (vispar.shrink < 1) { for (int j = 1; j <= 5; j++) { Point3d p = mesh->Point(el.PNum(j)); c.X() += p.X() / 5; c.Y() += p.Y() / 5; c.Z() += p.Z() / 5; } } el.GetSurfaceTriangles (faces); if (el.PNum(1)) { glBegin (GL_TRIANGLES); for (int j = 1; j <= faces.Size(); j++) { Element2d & face = faces.Elem(j); Point3d lp1 = mesh->Point (el.PNum(face.PNum(1))); Point3d lp2 = mesh->Point (el.PNum(face.PNum(2))); Point3d lp3 = mesh->Point (el.PNum(face.PNum(3))); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (n.Length()+1e-12); n *= -1; glNormal3d (n.X(), n.Y(), n.Z()); if (vispar.shrink < 1) { lp1 = c + vispar.shrink * (lp1 - c); lp2 = c + vispar.shrink * (lp2 - c); lp3 = c + vispar.shrink * (lp3 - c); } glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } glEnd(); } } } } glEndList (); } void VisualSceneMesh :: BuildBadelList() { ; } void VisualSceneMesh :: BuildIdentifiedList() { ; } void VisualSceneMesh :: BuildDomainSurfList() { shared_ptr mesh = GetMesh(); if (domainsurflist) glDeleteLists (domainsurflist, 1); domainsurflist = glGenLists (1); glNewList (domainsurflist, GL_COMPILE); int i, j; glLineWidth (1.0f); glDisable (GL_COLOR_MATERIAL); for (i = 1; i <= mesh->GetNSE(); i++) { Element2d el = mesh->SurfaceElement (i); int drawel = 1; for (j = 1; j <= el.GetNP(); j++) { if (!el.PNum(j)) drawel = 0; } if (!drawel) continue; if (el.GetIndex() < 1 || el.GetIndex() > mesh->GetNFD()) continue; int domin = mesh->GetFaceDescriptor(el.GetIndex()).DomainIn(); int domout = mesh->GetFaceDescriptor(el.GetIndex()).DomainOut(); int fac; if (domin == vispar.drawdomainsurf) fac = 1; else if (domout == vispar.drawdomainsurf) fac = -1; else continue; GLfloat matcol[] = { 1, 0, 0, 1 }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matcol); if (el.GetNP() == 3) { glBegin (GL_TRIANGLES); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= ( fac * (n.Length()+1e-12)); glNormal3d (n.X(), n.Y(), n.Z()); if (!vispar.colormeshsize) { glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } glEnd(); } else if (el.GetNP() == 4) { glBegin (GL_QUADS); const Point3d & lp1 = mesh->Point (el.PNum(1)); const Point3d & lp2 = mesh->Point (el.PNum(2)); const Point3d & lp3 = mesh->Point (el.PNum(4)); const Point3d & lp4 = mesh->Point (el.PNum(3)); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, Center (lp3, lp4))); n /= (fac * (n.Length()+1e-12)); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp4.X(), lp4.Y(), lp4.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); glEnd(); } else if (el.GetNP() == 6) { glBegin (GL_TRIANGLES); static int trigs[4][3] = { { 1, 6, 5 }, { 2, 4, 6 }, { 3, 5, 4 }, { 4, 5, 6 } }; for (j = 0; j < 4; j++) { const Point3d & lp1 = mesh->Point (el.PNum(trigs[j][0])); const Point3d & lp2 = mesh->Point (el.PNum(trigs[j][1])); const Point3d & lp3 = mesh->Point (el.PNum(trigs[j][2])); Vec3d n = Cross (Vec3d (lp1, lp2), Vec3d (lp1, lp3)); n /= (fac * (n.Length() + 1e-12)); glNormal3d (n.X(), n.Y(), n.Z()); glVertex3d (lp1.X(), lp1.Y(), lp1.Z()); glVertex3d (lp2.X(), lp2.Y(), lp2.Z()); glVertex3d (lp3.X(), lp3.Y(), lp3.Z()); } glEnd(); } } glEndList (); } void VisualSceneMesh :: MouseDblClick (int px, int py) { shared_ptr mesh = GetMesh(); BuildFilledList (true); MouseDblClickSelect(px,py,clipplane,backcolor,transformationmat,center,rad, filledlist,selelement,selface,seledge,selpoint,selpoint2,locpi); GLdouble /* modelview[16], */ projection[16]; GLint viewport[4]; GLdouble result[3]; glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]); glGetIntegerv(GL_VIEWPORT, &viewport[0]); int hy = viewport[3]-py; GLfloat pz; // cout << "x, y = " << px << ", " << hy << endl; glReadPixels (px, hy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pz); cout << "pz = " << pz << endl; gluUnProject(px, hy, pz, transformationmat, projection, viewport, &result[0], &result[1], &result[2]); if (pz < 1.0) cout << "point : " << result[0] << ", " << result[1] << ", " << result[2] << endl; if (user_me_handler && pz < 1.0) { if (selelement != -1) user_me_handler -> DblClick (selelement-1, result[0], result[1], result[2]); } selecttimestamp = NextTimeStamp(); if(lock) { lock->UnLock(); delete lock; lock = NULL; } /* int i, hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixf (transformationmat); // SetClippingPlane(); glInitNames(); glPushName (1); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glDisable(GL_CLIP_PLANE0); if (vispar.clipenable) { Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); double len = Abs(n); double mu = -clipplane[3] / (len*len); Point<3> p (mu * n); n /= len; Vec<3> t1 = n.GetNormal (); Vec<3> t2 = Cross (n, t1); double xi1mid = (center - p) * t1; double xi2mid = (center - p) * t2; glLoadName (0); glBegin (GL_QUADS); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); glEnd (); } // SetClippingPlane(); glCallList (filledlist); glDisable (GL_POLYGON_OFFSET_FILL); glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); // cout << "hits = " << hits << endl; int minname = 0; GLuint mindepth = 0; // find clippingplane GLuint clipdepth = 0; // GLuint(-1); for (i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; if (!curname) clipdepth = selbuf[4*i+1]; } for (i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; if (curname && (curdepth > clipdepth) && (curdepth < mindepth || !minname)) { mindepth = curdepth; minname = curname; } } seledge = -1; if (minname) { const Element2d & sel = mesh->SurfaceElement(minname); cout << "select element " << minname << " on face " << sel.GetIndex() << endl; cout << "Nodes: "; for (i = 1; i <= sel.GetNP(); i++) cout << sel.PNum(i) << " "; cout << endl; selelement = minname; selface = mesh->SurfaceElement(minname).GetIndex(); locpi = (locpi % sel.GetNP()) + 1; selpoint2 = selpoint; selpoint = sel.PNum(locpi); cout << "selected point " << selpoint << ", pos = " << mesh->Point (selpoint) << endl; for (i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh->LineSegment(i); if (seg[0] == selpoint && seg[1] == selpoint2 || seg[1] == selpoint && seg[0] == selpoint2) { seledge = seg.edgenr; cout << "seledge = " << seledge << endl; } } } else { selface = -1; selelement = -1; selpoint = -1; selpoint2 = -1; } glDisable(GL_CLIP_PLANE0); selecttimestamp = NextTimeStamp(); */ } void MouseDblClickSelect (const int px, const int py, const GLdouble * clipplane, const GLdouble backcolor, const double * transformationmat, const Point3d & center, const double rad, const int displaylist, int & selelement, int & selface, int & seledge, PointIndex & selpoint, PointIndex & selpoint2, int & locpi) { auto mesh = vsmesh.GetMesh(); int i, hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixd (transformationmat); // SetClippingPlane(); glInitNames(); glPushName (1); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glDisable(GL_CLIP_PLANE0); if (vispar.clipping.enable) { Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); double len = Abs(n); double mu = -clipplane[3] / (len*len); Point<3> p (mu * n); n /= len; Vec<3> t1 = n.GetNormal (); Vec<3> t2 = Cross (n, t1); double xi1mid = (center - p) * t1; double xi2mid = (center - p) * t2; glLoadName (0); glBegin (GL_QUADS); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); glEnd (); } // SetClippingPlane(); glCallList (displaylist); glDisable (GL_POLYGON_OFFSET_FILL); glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); //cout << "hits = " << hits << endl; int minname = 0; GLuint mindepth = 0; // find clippingplane GLuint clipdepth = 0; // GLuint(-1); for (i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; if (!curname) clipdepth = selbuf[4*i+1]; } for (i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; /* cout << selbuf[4*i] << " " << selbuf[4*i+1] << " " << selbuf[4*i+2] << " " << selbuf[4*i+3] << endl; */ if (curname && (curdepth > clipdepth) && (curdepth < mindepth || !minname)) { mindepth = curdepth; minname = curname; } } seledge = -1; if (minname) { const Element2d & sel = mesh->SurfaceElement(minname); cout << "select element " << minname << " on face " << sel.GetIndex() << endl; cout << "Nodes: "; for (i = 1; i <= sel.GetNP(); i++) cout << sel.PNum(i) << " "; cout << endl; selelement = minname; selface = mesh->SurfaceElement(minname).GetIndex(); locpi = (locpi % sel.GetNP()) + 1; selpoint2 = selpoint; selpoint = sel.PNum(locpi); cout << "selected point " << selpoint << ", pos = " << mesh->Point (selpoint) << endl; for (i = 1; i <= mesh->GetNSeg(); i++) { const Segment & seg = mesh->LineSegment(i); if ( (seg[0] == selpoint && seg[1] == selpoint2) || (seg[1] == selpoint && seg[0] == selpoint2) ) { seledge = seg.edgenr; cout << "seledge = " << seledge << endl; } } } else { selface = -1; selelement = -1; selpoint = -1; selpoint2 = -1; } glDisable(GL_CLIP_PLANE0); #ifdef PARALLELGL vsmesh.Broadcast (); #endif } void VisualSceneMesh :: SetSelectedFace (int asf) { selface = asf; selecttimestamp = NextTimeStamp(); } } #ifdef NG_PYTHON #include <../general/ngpython.hpp> DLL_HEADER void ExportMeshVis(py::module &m) { using namespace netgen; vispar.drawcolorbar = true; vispar.drawnetgenlogo = true; vispar.drawcoordinatecross = true; vispar.drawfilledtrigs = true; vispar.drawdomainsurf = true; vispar.drawhexes = true; vispar.drawtets = true; vispar.drawprisms = true; vispar.drawoutline = true; py::class_> (m, "VisualSceneMesh") .def("Draw", &VisualSceneMesh::DrawScene) ; m.def("VS", FunctionPointer ([](shared_ptr mesh) { auto vs = make_shared(); // vs->SetMesh(mesh); SetGlobalMesh (mesh); return vs; })); m.def("MouseMove", FunctionPointer ([](VisualSceneMesh &vsmesh, int oldx, int oldy, int newx, int newy, char mode) { vsmesh.MouseMove(oldx, oldy, newx, newy, mode); })); m.def("SelectFace", FunctionPointer ([] (int facenr) { vsmesh.SetSelectedFace(facenr); })); m.def("GetGlobalMesh", FunctionPointer ([] () { return vsmesh.GetMesh(); })); } // BOOST_PYTHON_MODULE(libvisual) // { // ExportMeshVis(); // } #endif netgen-6.2.1905/libsrc/visualization/visualpkg.cpp0000644000175000017500000004021013504650527020666 0ustar kurtkurt#include // #include #include #include #include #include #include // #include #include #include namespace netgen { /* */ int Ng_Vis_Set (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { auto & vssolution = netgen::GetVSSolution(); if (argc >= 2) { if (strcmp (argv[1], "parameters") == 0) { vssolution.imag_part = atoi (Tcl_GetVar (interp, "::visoptions.imaginary", TCL_GLOBAL_ONLY)); vssolution.usetexture = atoi (Tcl_GetVar (interp, "::visoptions.usetexture", TCL_GLOBAL_ONLY)); if (atoi (Tcl_GetVar (interp, "::visoptions.redrawperiodic", TCL_GLOBAL_ONLY))) vssolution.usetexture = 2; vssolution.invcolor = atoi (Tcl_GetVar (interp, "::visoptions.invcolor", TCL_GLOBAL_ONLY)); vssolution.clipsolution = 0; if (strcmp (Tcl_GetVar (interp, "::visoptions.clipsolution", TCL_GLOBAL_ONLY), "scal") == 0) vssolution.clipsolution = 1; if (strcmp (Tcl_GetVar (interp, "::visoptions.clipsolution", TCL_GLOBAL_ONLY), "vec") == 0) vssolution.clipsolution = 2; tcl_const char * scalname = Tcl_GetVar (interp, "::visoptions.scalfunction", TCL_GLOBAL_ONLY); tcl_const char * vecname = Tcl_GetVar (interp, "::visoptions.vecfunction", TCL_GLOBAL_ONLY); tcl_const char * fieldlines_vecname = Tcl_GetVar (interp, "::visoptions.fieldlinesvecfunction", TCL_GLOBAL_ONLY); vssolution.scalfunction = -1; vssolution.vecfunction = -1; vssolution.fieldlines_vecfunction = -1; int pointpos; // SZ const char * pch = strchr(scalname,':'); pointpos = int(pch-scalname+1); for (int i = 0; i < vssolution.soldata.Size(); i++) { if ( (strlen (vssolution.soldata[i]->name.c_str()) == size_t(pointpos-1)) && (strncmp (vssolution.soldata[i]->name.c_str(), scalname, pointpos-1) == 0) ) { vssolution.scalfunction = i; vssolution.scalcomp = atoi (scalname + pointpos); if ( vssolution.scalcomp > vssolution.soldata[i]->components ) vssolution.scalcomp = 1; char newscalname[100]; for ( int ii = 0; ii < pointpos; ii++ ) newscalname[ii] = scalname[ii]; newscalname[pointpos] = ':'; sprintf (newscalname+pointpos, "%i", vssolution.scalcomp); if (strcmp (scalname, newscalname) != 0) Tcl_SetVar ( interp, "::visoptions.scalfunction", newscalname, TCL_GLOBAL_ONLY ); scalname = Tcl_GetVar (interp, "::visoptions.scalfunction", TCL_GLOBAL_ONLY); } if (strcmp (vssolution.soldata[i]->name.c_str(), vecname) == 0) vssolution.vecfunction = i; if (strcmp (vssolution.soldata[i]->name.c_str(), fieldlines_vecname) == 0) vssolution.fieldlines_vecfunction = i; } if(vssolution.fieldlines_vecfunction != -1 && vssolution.vecfunction == -1) { //cout << "WARNING: Setting vector function in Visualization toolbox to value from Fieldlines toolbox!" << endl; vssolution.vecfunction = vssolution.fieldlines_vecfunction; } // reset visoptions.scalfunction and visoptions.vecfunction if not avialable if ( vssolution.scalfunction == -1 && strcmp (scalname, "none") != 0) Tcl_SetVar ( interp, "::visoptions.scalfunction", "none", TCL_GLOBAL_ONLY ); if ( vssolution.vecfunction == -1 && strcmp (vecname, "none") != 0) Tcl_SetVar ( interp, "::visoptions.vecfunction", "none", TCL_GLOBAL_ONLY ); tcl_const char * evalname = Tcl_GetVar (interp, "::visoptions.evaluate", TCL_GLOBAL_ONLY); if (strcmp(evalname, "abs") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_ABS; if (strcmp(evalname, "abstens") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_ABS_TENSOR; if (strcmp(evalname, "mises") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_MISES; if (strcmp(evalname, "main") == 0) vssolution.evalfunc = VisualSceneSolution::FUNC_MAIN; vssolution.gridsize = atoi (Tcl_GetVar (interp, "::visoptions.gridsize", TCL_GLOBAL_ONLY)); vssolution.xoffset = atof (Tcl_GetVar (interp, "::visoptions.xoffset", TCL_GLOBAL_ONLY)); // cout << "x-offset:" << vssolution.xoffset << endl; vssolution.yoffset = atof (Tcl_GetVar (interp, "::visoptions.yoffset", TCL_GLOBAL_ONLY)); vssolution.autoscale = atoi (Tcl_GetVar (interp, "::visoptions.autoscale", TCL_GLOBAL_ONLY)); /* vssolution.linear_colors = atoi (Tcl_GetVar (interp, "::visoptions.lineartexture", TCL_GLOBAL_ONLY)); */ vssolution.logscale = atoi (Tcl_GetVar (interp, "::visoptions.logscale", TCL_GLOBAL_ONLY)); vssolution.mminval = atof (Tcl_GetVar (interp, "::visoptions.mminval", TCL_GLOBAL_ONLY)); vssolution.mmaxval = atof (Tcl_GetVar (interp, "::visoptions.mmaxval", TCL_GLOBAL_ONLY)); vssolution.showclipsolution = atoi (Tcl_GetVar (interp, "::visoptions.showclipsolution", TCL_GLOBAL_ONLY)); vssolution.showsurfacesolution = atoi (Tcl_GetVar (interp, "::visoptions.showsurfacesolution", TCL_GLOBAL_ONLY)); vssolution.lineartexture = atoi (Tcl_GetVar (interp, "::visoptions.lineartexture", TCL_GLOBAL_ONLY)); vssolution.numtexturecols = atoi (Tcl_GetVar (interp, "::visoptions.numtexturecols", TCL_GLOBAL_ONLY)); vssolution.multidimcomponent = atoi (Tcl_GetVar (interp, "::visoptions.multidimcomponent", TCL_GLOBAL_ONLY)); vssolution.drawpointcurves = atoi (Tcl_GetVar (interp, "::visoptions.drawpointcurves", TCL_GLOBAL_ONLY)); vssolution.draw_fieldlines = atoi (Tcl_GetVar (interp, "::visoptions.drawfieldlines", TCL_GLOBAL_ONLY)); vssolution.num_fieldlines = atoi (Tcl_GetVar (interp, "::visoptions.numfieldlines", TCL_GLOBAL_ONLY)); vssolution.fieldlines_randomstart = atoi (Tcl_GetVar (interp, "::visoptions.fieldlinesrandomstart", TCL_GLOBAL_ONLY)); vssolution.fieldlines_reltolerance = atof (Tcl_GetVar (interp, "::visoptions.fieldlinestolerance", TCL_GLOBAL_ONLY)); if (strcmp (Tcl_GetVar (interp, "::visoptions.fieldlinesrktype", TCL_GLOBAL_ONLY), "euler") == 0) vssolution.fieldlines_rktype = 0; else if (strcmp (Tcl_GetVar (interp, "::visoptions.fieldlinesrktype", TCL_GLOBAL_ONLY), "eulercauchy") == 0) vssolution.fieldlines_rktype = 1; else if (strcmp (Tcl_GetVar (interp, "::visoptions.fieldlinesrktype", TCL_GLOBAL_ONLY), "simpson") == 0) vssolution.fieldlines_rktype = 2; else if (strcmp (Tcl_GetVar (interp, "::visoptions.fieldlinesrktype", TCL_GLOBAL_ONLY), "crungekutta") == 0) vssolution.fieldlines_rktype = 3; vssolution.fieldlines_rellength = atof (Tcl_GetVar (interp, "::visoptions.fieldlineslength", TCL_GLOBAL_ONLY)); vssolution.fieldlines_maxpoints = atoi (Tcl_GetVar (interp, "::visoptions.fieldlinesmaxpoints", TCL_GLOBAL_ONLY)); vssolution.fieldlines_relthickness = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesthickness", TCL_GLOBAL_ONLY)); vssolution.fieldlines_fixedphase = (atoi (Tcl_GetVar (interp, "::visoptions.fieldlinesonlyonephase", TCL_GLOBAL_ONLY)) != 0); if(vssolution.fieldlines_fixedphase) vssolution.fieldlines_phase = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesphase", TCL_GLOBAL_ONLY)); if (strcmp (Tcl_GetVar (interp, "::visoptions.fieldlinesstartarea", TCL_GLOBAL_ONLY), "box") == 0) vssolution.fieldlines_startarea = 0; else if (strcmp (Tcl_GetVar (interp, "::visoptions.fieldlinesstartarea", TCL_GLOBAL_ONLY), "file") == 0) vssolution.fieldlines_startarea = 1; else if (strcmp (Tcl_GetVar (interp, "::visoptions.fieldlinesstartarea", TCL_GLOBAL_ONLY), "face") == 0) vssolution.fieldlines_startarea = 2; if (vssolution.fieldlines_startarea == 0) { vssolution.fieldlines_startarea_parameter.SetSize(6); vssolution.fieldlines_startarea_parameter[0] = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesstartareap1x", TCL_GLOBAL_ONLY)); vssolution.fieldlines_startarea_parameter[1] = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesstartareap1y", TCL_GLOBAL_ONLY)); vssolution.fieldlines_startarea_parameter[2] = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesstartareap1z", TCL_GLOBAL_ONLY)); vssolution.fieldlines_startarea_parameter[3] = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesstartareap2x", TCL_GLOBAL_ONLY)); vssolution.fieldlines_startarea_parameter[4] = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesstartareap2y", TCL_GLOBAL_ONLY)); vssolution.fieldlines_startarea_parameter[5] = atof (Tcl_GetVar (interp, "::visoptions.fieldlinesstartareap2z", TCL_GLOBAL_ONLY)); } else if (vssolution.fieldlines_startarea == 1) { vssolution.fieldlines_filename = Tcl_GetVar (interp, "::visoptions.fieldlinesfilename", TCL_GLOBAL_ONLY); } else if (vssolution.fieldlines_startarea == 2) { vssolution.fieldlines_startface = atoi (Tcl_GetVar (interp, "::visoptions.fieldlinesstartface", TCL_GLOBAL_ONLY)); } vssolution.deform = atoi (Tcl_GetVar (interp, "::visoptions.deformation", TCL_GLOBAL_ONLY)); vssolution.scaledeform = atof (Tcl_GetVar (interp, "::visoptions.scaledeform1", TCL_GLOBAL_ONLY)) * atof (Tcl_GetVar (interp, "::visoptions.scaledeform2", TCL_GLOBAL_ONLY)); if (atoi (Tcl_GetVar (interp, "::visoptions.isolines", TCL_GLOBAL_ONLY))) vssolution.numisolines = atoi (Tcl_GetVar (interp, "::visoptions.numiso", TCL_GLOBAL_ONLY)); else vssolution.numisolines = 0; vssolution.draw_isosurface = atoi (Tcl_GetVar (interp, "::visoptions.isosurf", TCL_GLOBAL_ONLY)); vssolution.SetSubdivision(atoi (Tcl_GetVar (interp, "::visoptions.subdivisions", TCL_GLOBAL_ONLY))); vssolution.UpdateSolutionTimeStamp(); } if (strcmp (argv[1], "parametersrange") == 0) { vssolution.invcolor = atoi (Tcl_GetVar (interp, "::visoptions.invcolor", TCL_GLOBAL_ONLY)); vssolution.mminval = atof (Tcl_GetVar (interp, "::visoptions.mminval", TCL_GLOBAL_ONLY)); vssolution.mmaxval = atof (Tcl_GetVar (interp, "::visoptions.mmaxval", TCL_GLOBAL_ONLY)); vssolution.lineartexture = atoi (Tcl_GetVar (interp, "::visoptions.lineartexture", TCL_GLOBAL_ONLY)); vssolution.numtexturecols = atoi (Tcl_GetVar (interp, "::visoptions.numtexturecols", TCL_GLOBAL_ONLY)); if (vssolution.usetexture == 0 || vssolution.logscale) vssolution.UpdateSolutionTimeStamp(); } if (argc >= 3 && strcmp (argv[1], "time") == 0) { vssolution.time = double (atoi (argv[2])) / 1000; vssolution.timetimestamp = NextTimeStamp(); cout << "\rtime = " << vssolution.time << " " << flush; } } vsmesh.SetClippingPlane (); // for computing parameters vssolution.SetClippingPlane (); // for computing parameters glDisable(GL_CLIP_PLANE0); #ifdef PARALLELGL vsmesh.Broadcast (); #endif return TCL_OK; } int Ng_Vis_Field (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { int i; char buf[1000]; buf[0] = 0; auto & vssolution = netgen::GetVSSolution(); if (argc >= 2) { if (strcmp (argv[1], "setfield") == 0) { if (argc < 3) return TCL_ERROR; for (i = 0; i < vssolution.GetNSolData(); i++) if (strcmp (vssolution.GetSolData(i)->name.c_str(), argv[2]) == 0) { cout << "found soldata " << i << endl; } } if (strcmp (argv[1], "getnfieldnames") == 0) { sprintf (buf, "%d", vssolution.GetNSolData()); } if (strcmp (argv[1], "getfieldname") == 0) { sprintf (buf, "%s", vssolution.GetSolData(atoi(argv[2])-1)->name.c_str()); } if (strcmp (argv[1], "iscomplex") == 0) { sprintf (buf, "%d", vssolution.GetSolData(atoi(argv[2])-1)->iscomplex); } if (strcmp (argv[1], "getfieldcomponents") == 0) { sprintf (buf, "%d", vssolution.GetSolData(atoi(argv[2])-1)->components); } if (strcmp (argv[1], "getfieldnames") == 0) { for (i = 0; i < vssolution.GetNSolData(); i++) { strcat (buf, vssolution.GetSolData(i)->name.c_str()); strcat (buf, " "); } strcat (buf, "var1 var2 var3"); Tcl_SetResult (interp, buf, TCL_STATIC); } if (strcmp (argv[1], "setcomponent") == 0) { cout << "set component " << argv[2] << endl; } if (strcmp (argv[1], "getactivefield") == 0) { sprintf (buf, "1"); } if (strcmp (argv[1], "getdimension") == 0) { auto mesh = vssolution.GetMesh(); sprintf (buf, "%d", mesh->GetDimension()); } } Tcl_SetResult (interp, buf, TCL_STATIC); return TCL_OK; } VisualSceneMeshDoctor vsmeshdoc; DLL_HEADER extern shared_ptr mesh; int Ng_MeshDoctor(ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { cout << "Mesh Doctor:" << endl; int i; for (i = 0; i < argc; i++) cout << argv[i] << " "; cout << endl; meshdoctor.active = atoi(Tcl_GetVar(interp, "::meshdoctor.active", 0)); if (argc >= 2) { if (strcmp(argv[1], "markedgedist") == 0) { vsmeshdoc.SetMarkEdgeDist(atoi(argv[2])); } if (strcmp(argv[1], "deletemarkedsegments") == 0) { for (i = 1; i <= mesh->GetNSeg(); i++) if (vsmeshdoc.IsSegmentMarked(i)) mesh->DeleteSegment(i); // for (i = 1; i <= mesh->GetNSE(); i++) // mesh->SurfaceElement(i).SetIndex (1); mesh->Compress(); } } vsmeshdoc.UpdateTables(); vsmeshdoc.BuildScene(); return TCL_OK; } extern "C" int Ng_Vis_Init (Tcl_Interp * interp); int Ng_Vis_Init (Tcl_Interp * interp) { Tcl_CreateCommand (interp, "Ng_Vis_Set", Ng_Vis_Set, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Vis_Field", Ng_Vis_Field, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); return TCL_OK; } } netgen-6.2.1905/libsrc/visualization/vssolution.cpp0000644000175000017500000043504113504650527021120 0ustar kurtkurt#include #include #include #include #include // #include #include #include namespace netgen { DLL_HEADER VisualSceneSolution & GetVSSolution() { static VisualSceneSolution vssolution; return vssolution; } // extern shared_ptr mesh; extern VisualSceneMesh vsmesh; void AddUserVisualizationObject (UserVisualizationObject * vis) { // vssolution.AddUserVisualizationObject (vis); GetVSSolution().AddUserVisualizationObject (vis); } VisualSceneSolution :: SolData :: SolData () : data (0), solclass(0) { ; } VisualSceneSolution :: SolData :: ~SolData () { // delete [] name; delete data; delete solclass; } VisualSceneSolution :: VisualSceneSolution () : VisualScene() { // cout << "init VisualSceneSolution" << endl; surfellist = 0; linelist = 0; element1dlist = 0; clipplanelist_scal = 0; clipplanelist_vec = 0; isolinelist = 0; clipplane_isolinelist = 0; surface_vector_list = 0; isosurface_list = 0; fieldlineslist = 0; pointcurvelist = 0; num_fieldlineslists = 0; surfeltimestamp = GetTimeStamp(); surfellinetimestamp = GetTimeStamp(); clipplanetimestamp = GetTimeStamp(); solutiontimestamp = GetTimeStamp(); fieldlinestimestamp = GetTimeStamp(); pointcurve_timestamp = GetTimeStamp(); surface_vector_timestamp = GetTimeStamp(); isosurface_timestamp = GetTimeStamp(); timetimestamp = GetTimeStamp(); // AddVisualizationScene ("solution", &vssolution); } VisualSceneSolution :: ~VisualSceneSolution () { // cout << "exit VisualSceneSolution" << endl; ClearSolutionData(); } /* void VisualSceneSolution :: SetMesh (shared_ptr amesh) { wp_mesh = amesh; } */ void VisualSceneSolution :: AddSolutionData (SolData * sd) { shared_ptr mesh = GetMesh(); NgLock meshlock1 (mesh->MajorMutex(), 1); int funcnr = -1; for (int i = 0; i < soldata.Size(); i++) { // if (strcmp (soldata[i]->name, sd->name) == 0) if (soldata[i]->name == sd->name) { delete soldata[i]; soldata[i] = sd; funcnr = i; break; } } if (funcnr == -1) { soldata.Append (sd); funcnr = soldata.Size()-1; } SolData * nsd = soldata[funcnr]; nsd->size = 0; if (mesh) { switch (nsd->soltype) { case SOL_NODAL: nsd->size = mesh->GetNV(); break; case SOL_ELEMENT: nsd->size = mesh->GetNE(); break; case SOL_SURFACE_ELEMENT: nsd->size = mesh->GetNSE(); break; case SOL_NONCONTINUOUS: { switch (nsd->order) { case 0: nsd->size = mesh->GetNE(); break; case 1: nsd->size = 6 * mesh->GetNE(); break; case 2: nsd->size = 18 * mesh->GetNE(); break; } break; } case SOL_SURFACE_NONCONTINUOUS: { switch (nsd->order) { case 0: nsd->size = mesh->GetNSE(); break; case 1: nsd->size = 4 * mesh->GetNSE(); break; case 2: nsd->size = 9 * mesh->GetNSE(); break; } break; } default: nsd->size = 0; } solutiontimestamp = NextTimeStamp(); } } void VisualSceneSolution :: ClearSolutionData () { for (int i = 0; i < soldata.Size(); i++) delete soldata[i]; soldata.SetSize (0); } void VisualSceneSolution :: UpdateSolutionTimeStamp () { solutiontimestamp = NextTimeStamp(); } VisualSceneSolution::SolData * VisualSceneSolution :: GetSolData (int i) { if (i >= 0 && i < soldata.Size()) return soldata[i]; else return NULL; } void VisualSceneSolution :: SaveSolutionData (const char * filename) { shared_ptr mesh = GetMesh(); PrintMessage (1, "Write solution data to file ", filename); if (strcmp (&filename[strlen(filename)-3], "sol") == 0) { ofstream ost(filename); for (int i = 0; i < soldata.Size(); i++) { const SolData & sol = *soldata[i]; ost << "solution " << sol.name << " -size=" << sol.size << " -components=" << sol.components << " -order=" << sol.order; if (sol.iscomplex) ost << " -complex"; switch (sol.soltype) { case SOL_NODAL: ost << " -type=nodal"; break; case SOL_ELEMENT: ost << " -type=element"; break; case SOL_SURFACE_ELEMENT: ost << " -type=surfaceelement"; break; case SOL_NONCONTINUOUS: ost << " -type=noncontinuous"; break; case SOL_SURFACE_NONCONTINUOUS: ost << " -type=surfacenoncontinuous"; break; default: cerr << "save solution data, case not handeld" << endl; } ost << endl; for (int j = 0; j < sol.size; j++) { for (int k = 0; k < sol.components; k++) ost << sol.data[j*sol.dist+k] << " "; ost << "\n"; } } } if (strcmp (&filename[strlen(filename)-3], "vtk") == 0) { string surf_fn = filename; surf_fn.erase (strlen(filename)-4); surf_fn += "_surf.vtk"; cout << "surface mesh = " << surf_fn << endl; ofstream surf_ost(surf_fn.c_str()); surf_ost << "# vtk DataFile Version 1.0\n" << "NGSolve surface mesh\n" << "ASCII\n" << "DATASET UNSTRUCTURED_GRID\n\n"; surf_ost << "POINTS " << mesh->GetNP() << " float\n"; for (PointIndex pi = PointIndex::BASE; pi < mesh->GetNP()+PointIndex::BASE; pi++) { const MeshPoint & mp = (*mesh)[pi]; surf_ost << mp(0) << " " << mp(1) << " " << mp(2) << "\n"; } int cntverts = 0; for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) cntverts += 1 + (*mesh)[sei].GetNP(); surf_ost << "\nCELLS " << mesh->GetNSE() << " " << cntverts << "\n"; for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) { const Element2d & el = (*mesh)[sei]; surf_ost << el.GetNP(); for (int j = 0; j < el.GetNP(); j++) surf_ost << " " << el[j] - PointIndex::BASE; surf_ost << "\n"; } surf_ost << "\nCELL_TYPES " << mesh->GetNSE() << "\n"; for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) { const Element2d & el = (*mesh)[sei]; switch (el.GetType()) { case QUAD: surf_ost << 9; break; case TRIG: surf_ost << 5; break; default: cerr << "not implemented 2378" << endl; } surf_ost << "\n"; } ofstream ost(filename); ost << "# vtk DataFile Version 1.0\n" << "NGSolve solution\n" << "ASCII\n" << "DATASET UNSTRUCTURED_GRID\n\n"; ost << "POINTS " << mesh->GetNP() << " float\n"; for (PointIndex pi = PointIndex::BASE; pi < mesh->GetNP()+PointIndex::BASE; pi++) { const MeshPoint & mp = (*mesh)[pi]; ost << mp(0) << " " << mp(1) << " " << mp(2) << "\n"; } cntverts = 0; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) cntverts += 1 + (*mesh)[ei].GetNP(); ost << "\nCELLS " << mesh->GetNE() << " " << cntverts << "\n"; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; ost << el.GetNP(); for (int j = 0; j < el.GetNP(); j++) ost << " " << el[j] - PointIndex::BASE; ost << "\n"; } ost << "\nCELL_TYPES " << mesh->GetNE() << "\n"; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; switch (el.GetType()) { case TET: ost << 10; break; default: cerr << "not implemented 67324" << endl; } ost << "\n"; } ost << "CELL_DATA " << mesh->GetNE() << "\n"; for (int i = 0; i < soldata.Size(); i++) { ost << "VECTORS bfield float\n"; SolutionData & sol = *(soldata[i] -> solclass); double values[3]; for (int elnr = 0; elnr < mesh->GetNE(); elnr++) { sol.GetValue (elnr, 0.25, 0.25, 0.25, values); ost << values[0] << " " << values[1] << " " << values[2] << "\n"; } } /* ost << "POINT_DATA " << mesh->GetNP() << "\n"; for (int i = 0; i < soldata.Size(); i++) { ost << "VECTORS bfield float\n"; SolutionData & sol = *(soldata[i] -> solclass); for (PointIndex pi = PointIndex::BASE; pi < mesh->GetNP()+PointIndex::BASE; pi++) { double values[3], sumvalues[3] = { 0, 0, 0 }; FlatArray els = mesh->GetTopology().GetVertexElements(pi); for (int j = 0; j < els.Size(); j++) { sol.GetValue (els[j]-1, 0.25, 0.25, 0.25, values); for (int k = 0; k < 3; k++) sumvalues[k] += values[k]; } for (int k = 0; k < 3; k++) sumvalues[k] /= els.Size(); ost << sumvalues[0] << " " << sumvalues[1] << " " << sumvalues[2] << "\n"; } } */ } } void VisualSceneSolution :: DrawScene () { try { shared_ptr mesh = GetMesh(); if (!mesh) { VisualScene::DrawScene(); return; } // static NgLock mem_lock(mem_mutex); // mem_lock.Lock(); NgLock meshlock1 (mesh->MajorMutex(), true); NgLock meshlock (mesh->Mutex(), true); BuildScene(); CreateTexture (numtexturecols, lineartexture, 0.5, GL_MODULATE); glClearColor(backcolor, backcolor, backcolor, 1); // glClearColor(backcolor, backcolor, backcolor, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); glMatrixMode (GL_MODELVIEW); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_COLOR_MATERIAL); if (usetexture) { SetTextureMode (usetexture); glMatrixMode (GL_TEXTURE); glLoadIdentity(); if (usetexture == 1) { double hmax = maxval; double hmin = minval; if (invcolor) Swap (hmax, hmin); if (fabs (hmax - hmin) > 1e-30) glScaled (1.0 / (hmin - hmax), 0, 0); else glScaled (1e30, 0, 0); glTranslatef (-hmax, 0, 0); } else { glTranslatef (0.5, 0, 0); glRotatef(360 * netgen::GetVSSolution().time, 0, 0, -1); if (fabs (maxval) > 1e-10) glScalef(0.5/maxval, 0.5/maxval, 0.5/maxval); else glScalef (1e10, 1e10, 1e10); } glMatrixMode (GL_MODELVIEW); } if (vispar.drawfilledtrigs || vispar.drawtetsdomain > 0 || vispar.drawdomainsurf > 0) { // Change for Martin: // orig: SetClippingPlane (); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // glEnable(GL_BLEND); glDisable(GL_BLEND); glCallList (surfellist); #ifdef USE_BUFFERS // static int timer = NgProfiler::CreateTimer ("Solution::drawing - DrawSurfaceElements VBO"); // NgProfiler::StartTimer(timer); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glDrawElements(GL_TRIANGLES, surfel_vbo_size, GL_UNSIGNED_INT, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // NgProfiler::StopTimer(timer); #endif glDisable(GL_BLEND); /* // transparent test ... glColor4f (1, 0, 0, 0.1); glEnable (GL_COLOR_MATERIAL); glDepthFunc(GL_GREATER); glDepthMask(GL_FALSE); // glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_DST_ALPHA); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA); glCallList (surfellist); glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); glDepthMask(GL_TRUE); glCallList (surfellist); // end test ... */ glCallList (surface_vector_list); glDisable(GL_CLIP_PLANE0); } if (showclipsolution) { if (clipsolution == 1) { // Martin // orig: glCallList (clipplanelist_scal); // transparent experiments // see http://wiki.delphigl.com/index.php/Blenden /* glColor4f (1, 1, 1, 0.5); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_COLOR); glDepthFunc(GL_GREATER); glDepthMask(GL_FALSE); glCallList (clipplanelist_scal); glDepthFunc(GL_LEQUAL); glDepthMask(GL_TRUE); glCallList (clipplanelist_scal); glDisable(GL_BLEND); */ /* // latest transparent version ... glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_DEPTH_TEST); // CreateTexture (numtexturecols, lineartexture, 0.25, GL_MODULATE); // glCallList (clipplanelist_scal); glEnable(GL_BLEND); // glDisable(GL_DEPTH_TEST); // CreateTexture (numtexturecols, lineartexture, 0.25, GL_MODULATE); glCallList (clipplanelist_scal); // glDepthFunc(GL_LEQUAL); // glDepthMask(GL_TRUE); // glCallList (clipplanelist_scal); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); */ // end test } if (clipsolution == 2) { // glDisable(GL_DEPTH_TEST); glCallList (clipplanelist_vec); // glEnable(GL_DEPTH_TEST); } } if (draw_fieldlines) { SetClippingPlane(); if (num_fieldlineslists <= 1) glCallList (fieldlineslist); else { // animated int start = int (time / 10 * num_fieldlineslists); for (int ln = 0; ln < 10; ln++) { int nr = fieldlineslist + (start + ln) % num_fieldlineslists; glCallList (nr); } } glDisable(GL_CLIP_PLANE0); } if(drawpointcurves) { glCallList(pointcurvelist); } glMatrixMode (GL_TEXTURE); glLoadIdentity(); glMatrixMode (GL_MODELVIEW); glDisable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_2D); glDisable (GL_POLYGON_OFFSET_FILL); glDisable (GL_COLOR_MATERIAL); if (draw_isosurface) glCallList (isosurface_list); GLfloat matcol0[] = { 0, 0, 0, 1 }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol0); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matcol0); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matcol0); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glLineWidth (1.0f); glColor3f (0.0f, 0.0f, 0.0f); glDisable (GL_LINE_SMOOTH); if (vispar.drawedges) { glCallList (element1dlist); } if (vispar.drawoutline && !numisolines) { SetClippingPlane (); glDepthMask(GL_FALSE); glCallList (linelist); glDepthMask(GL_TRUE); glDisable(GL_CLIP_PLANE0); } if (numisolines) { SetClippingPlane (); glCallList (isolinelist); glDisable(GL_CLIP_PLANE0); glCallList (clipplane_isolinelist); } // user visualization for (int i = 0; i < user_vis.Size(); i++) user_vis[i] -> Draw(); glPopMatrix(); glDisable(GL_CLIP_PLANE0); DrawColorBar (minval, maxval, logscale, lineartexture); if (vispar.drawcoordinatecross) DrawCoordinateCross (); DrawNetgenLogo (); glFinish(); // delete lock; // mem_lock.UnLock(); } catch (bad_weak_ptr e) { // cout << "don't have a mesh to visualize" << endl; VisualScene::DrawScene(); } } /* void VisualSceneSolution :: RealVec3d (const double * values, Vec3d & v, bool iscomplex, bool imag) { if (!iscomplex) { v.X() = values[0]; v.Y() = values[1]; v.Z() = values[2]; } else { if (!imag) { v.X() = values[0]; v.Y() = values[2]; v.Z() = values[4]; } else { v.X() = values[1]; v.Y() = values[3]; v.Z() = values[5]; } } } */ Vec<3> VisualSceneSolution :: RealVec3d (const double * values, bool iscomplex, bool imag) { Vec<3> v; if (!iscomplex) { for (int j = 0; j < 3; j++) v(j) = values[j]; } else { if (!imag) { for (int j = 0; j < 3; j++) v(j) = values[2*j]; } else { for (int j = 0; j < 3; j++) v(j) = values[2*j+1]; } } return v; } void VisualSceneSolution :: RealVec3d (const double * values, Vec3d & v, bool iscomplex, double phaser, double phasei) { if (!iscomplex) { v.X() = values[0]; v.Y() = values[1]; v.Z() = values[2]; } else { for (int i = 0; i < 3; i++) v.X(i+1) = phaser * values[2*i] + phasei * values[2*i+1]; } } void VisualSceneSolution :: BuildScene (int zoomall) { try { shared_ptr mesh = GetMesh(); if (!mesh) { VisualScene::BuildScene (zoomall); return; } /* if (!cone_list) { cone_list = glGenLists (1); glNewList (cone_list, GL_COMPILE); DrawCone (Point<3> (0,0,0), Point<3> (0,0,1), 0.4); glEndList(); } */ // vispar.colormeshsize = 1; // recalc clipping plane SetClippingPlane (); glDisable(GL_CLIP_PLANE0); SolData * sol = NULL; SolData * vsol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; if (vecfunction != -1) vsol = soldata[vecfunction]; if (mesh->GetTimeStamp () > solutiontimestamp) { sol = NULL; vsol = NULL; } if (sol && sol->solclass) sol->solclass->SetMultiDimComponent (multidimcomponent); if (vsol && vsol->solclass) vsol->solclass->SetMultiDimComponent (multidimcomponent); if (!autoscale || (!sol && !vsol) ) { minval = mminval; maxval = mmaxval; } else { if (mesh->GetTimeStamp () > surfeltimestamp || vispar.clipping.timestamp > clipplanetimestamp || solutiontimestamp > surfeltimestamp) { GetMinMax (scalfunction, scalcomp, minval, maxval); } } if (mesh->GetTimeStamp() > surfeltimestamp || solutiontimestamp > surfeltimestamp || zoomall) { if (mesh->GetTimeStamp() > surfeltimestamp || zoomall) { // mesh has changed Point3d pmin, pmax; static double oldrad = 0; mesh->GetBox (pmin, pmax, -1); center = Center (pmin, pmax); rad = 0.5 * Dist (pmin, pmax); glEnable (GL_NORMALIZE); if (rad > 1.5 * oldrad || mesh->GetMajorTimeStamp() > surfeltimestamp || zoomall) { CalcTransformationMatrices(); oldrad = rad; } } DrawSurfaceElements(); surfeltimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp()); } if (mesh->GetTimeStamp() > surfellinetimestamp || subdivision_timestamp > surfellinetimestamp || (deform && solutiontimestamp > surfellinetimestamp) || zoomall) { DrawSurfaceElementLines(); surfellinetimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp()); } if (vispar.drawedges) Draw1DElements(); if (mesh->GetTimeStamp() > surface_vector_timestamp || solutiontimestamp > surface_vector_timestamp || zoomall) { if (surface_vector_list) glDeleteLists (surface_vector_list, 1); surface_vector_list = glGenLists (1); glNewList (surface_vector_list, GL_COMPILE); glEnable (GL_NORMALIZE); DrawSurfaceVectors(); glEndList (); surface_vector_timestamp = max2 (mesh->GetTimeStamp(), solutiontimestamp); } if (clipplanetimestamp < vispar.clipping.timestamp || clipplanetimestamp < solutiontimestamp) { // cout << "clipsolution = " << clipsolution << endl; if (vispar.clipping.enable && clipsolution == 2) { mesh->Mutex().unlock(); mesh->BuildElementSearchTree(); mesh->Mutex().lock(); } if (vispar.clipping.enable && clipsolution == 1 && sol) DrawClipPlaneTrigs (); if (clipplanelist_vec) glDeleteLists (clipplanelist_vec, 1); clipplanelist_vec = glGenLists (1); glNewList (clipplanelist_vec, GL_COMPILE); if (vispar.clipping.enable && clipsolution == 2 && vsol) { SetTextureMode (usetexture); if (autoscale) GetMinMax (vecfunction, 0, minval, maxval); Array cpp; GetClippingPlaneGrid (cpp); for (int i = 0; i < cpp.Size(); i++) { const ClipPlanePoint & p = cpp[i]; double values[6]; Vec3d v; bool drawelem = GetValues (vsol, p.elnr, p.lami(0), p.lami(1), p.lami(2), values); // RealVec3d (values, v, vsol->iscomplex, imag_part); v = RealVec3d (values, vsol->iscomplex, imag_part); double val = v.Length(); if (drawelem && val > 1e-10 * maxval) { v *= (rad / val / gridsize * 0.5); SetOpenGlColor (val); DrawCone (p.p, p.p+v, rad / gridsize * 0.2); } } } glEndList (); } if (mesh->GetTimeStamp() > isosurface_timestamp || solutiontimestamp > isosurface_timestamp || zoomall) { if (isosurface_list) glDeleteLists (isosurface_list, 1); isosurface_list = glGenLists (1); glNewList (isosurface_list, GL_COMPILE); glEnable (GL_NORMALIZE); DrawIsoSurface(sol, vsol, scalcomp); glEndList (); isosurface_timestamp = max2 (mesh->GetTimeStamp(), solutiontimestamp); } if(mesh->GetTimeStamp() > pointcurve_timestamp || solutiontimestamp > pointcurve_timestamp) { if(pointcurvelist) glDeleteLists(pointcurvelist,1); if(mesh->GetNumPointCurves() > 0) { pointcurvelist = glGenLists(1); glNewList(pointcurvelist,GL_COMPILE); //glColor3f (1.0f, 0.f, 0.f); for(int i=0; iGetNumPointCurves(); i++) { Box3d box; box.SetPoint(mesh->GetPointCurvePoint(i,0)); for(int j=1; jGetNumPointsOfPointCurve(i); j++) box.AddPoint(mesh->GetPointCurvePoint(i,j)); double diam = box.CalcDiam(); double thick = min2(0.1*diam, 0.001*rad); double red,green,blue; mesh->GetPointCurveColor(i,red,green,blue); glColor3f (red, green, blue); for(int j=0; jGetNumPointsOfPointCurve(i)-1; j++) { DrawCylinder(mesh->GetPointCurvePoint(i,j), mesh->GetPointCurvePoint(i,j+1), thick); } } glEndList(); } } if ( numisolines && (clipplanetimestamp < vispar.clipping.timestamp || clipplanetimestamp < solutiontimestamp) ) { if (isolinelist) glDeleteLists (isolinelist, 1); isolinelist = glGenLists (1); glNewList (isolinelist, GL_COMPILE); Point<3> points[1100]; double values[1100]; int nse = mesh->GetNSE(); CurvedElements & curv = mesh->GetCurvedElements(); if (sol) { glBegin (GL_LINES); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; bool curved = curv.IsHighOrder(); // && curv.IsSurfaceElementCurved(sei); if (el.GetType() == TRIG || el.GetType() == TRIG6) { Point<3> lp1, lp2, lp3; if (!curved) { GetPointDeformation (el[0]-1, lp1); GetPointDeformation (el[1]-1, lp2); GetPointDeformation (el[2]-1, lp3); } int n = 1 << subdivisions; int ii = 0; int ix, iy; for (iy = 0; iy <= n; iy++) for (ix = 0; ix <= n-iy; ix++) { double x = double(ix) / n; double y = double(iy) / n; // TODO: consider return value (bool: draw/don't draw element) GetSurfValue (sol, sei, -1, x, y, scalcomp, values[ii]); Point<2> xref(x,y); if (curved) mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, points[ii]); else points[ii] = lp3 + x * (lp1-lp3) + y * (lp2-lp3); if (deform) { points[ii] += GetSurfDeformation (sei, -1, x, y); } ii++; } ii = 0; for (iy = 0; iy < n; iy++, ii++) for (ix = 0; ix < n-iy; ix++, ii++) { int index[] = { ii, ii+1, ii+n-iy+1, ii+1, ii+n-iy+2, ii+n-iy+1 }; DrawIsoLines (points[index[0]], points[index[1]], points[index[2]], values[index[0]], values[index[1]], values[index[2]]); if (ix < n-iy-1) DrawIsoLines (points[index[3]], points[index[4]], points[index[5]], values[index[3]], values[index[4]], values[index[5]]); } } if (el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 ) { Point<3> lpi[4]; Vec<3> vx = 0.0, vy = 0.0, vtwist = 0.0, def; if (!curved) { for (int j = 0; j < 4; j++) GetPointDeformation (el[j]-1, lpi[j]); vx = lpi[1]-lpi[0]; vy = lpi[3]-lpi[0]; vtwist = (lpi[0]-lpi[1]) + (lpi[2]-lpi[3]); } int n = 1 << subdivisions; int ix, iy, ii = 0; for (iy = 0; iy <= n; iy++) for (ix = 0; ix <= n; ix++, ii++) { double x = double(ix) / n; double y = double(iy) / n; // TODO: consider return value (bool: draw/don't draw element) GetSurfValue (sol, sei, -1, x, y, scalcomp, values[ii]); Point<2> xref(x,y); if (curved) mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, points[ii]); else points[ii] = lpi[0] + x * vx + y * vy + x*y * vtwist; if (deform) points[ii] += GetSurfDeformation (sei, -1, x, y); } ii = 0; for (iy = 0; iy < n; iy++, ii++) for (ix = 0; ix < n; ix++, ii++) { DrawIsoLines (points[ii], points[ii+1], points[ii+n+1], values[ii], values[ii+1], values[ii+n+1]); DrawIsoLines (points[ii+1], points[ii+n+2], points[ii+n+1], values[ii+1], values[ii+n+2], values[ii+n+1]); } } } glEnd(); } glEndList (); if (clipplane_isolinelist) glDeleteLists (clipplane_isolinelist, 1); if (vispar.clipping.enable && clipsolution == 1 && sol) { clipplane_isolinelist = glGenLists (1); glNewList (clipplane_isolinelist, GL_COMPILE); Array cpt; Array pts; GetClippingPlaneTrigs (cpt, pts); bool drawelem; glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); glBegin (GL_LINES); if (numisolines) for (int i = 0; i < cpt.Size(); i++) { const ClipPlaneTrig & trig = cpt[i]; double vali[3]; for (int j = 0; j < 3; j++) { Point<3> lami = pts[trig.points[j].pnr].lami; drawelem = GetValue (sol, trig.elnr, lami(0), lami(1), lami(2), scalcomp, vali[j]); } if ( drawelem ) DrawIsoLines (pts[trig.points[0].pnr].p, pts[trig.points[1].pnr].p, pts[trig.points[2].pnr].p, vali[0], vali[1], vali[2]); } glEnd(); glEndList (); } } clipplanetimestamp = max2 (vispar.clipping.timestamp, solutiontimestamp); } catch (bad_weak_ptr e) { PrintMessage (3, "vssolution::buildscene: don't have a mesh to visualize"); VisualScene::BuildScene (zoomall); } } void VisualSceneSolution :: Draw1DElements () { shared_ptr mesh = GetMesh(); if (element1dlist) glDeleteLists (element1dlist, 1); element1dlist = glGenLists (1); glNewList (element1dlist, GL_COMPILE); int npt = (1 << subdivisions) + 1; Array pref(npt), values(npt); Array > points(npt); const SolData * sol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; const SolData * vsol = NULL; if (deform && vecfunction != -1) vsol = soldata[vecfunction]; int ncomp = 0; if (sol) ncomp = sol->components; if (vsol) ncomp = vsol->components; Array mvalues(ncomp); for (int i = 0; i < npt; i++) pref[i] = double(i) / (npt-1); int meshdim = mesh->GetDimension(); for (SegmentIndex i = 0; i < mesh -> GetNSeg(); i++) { // mesh->GetCurvedElements(). // CalcMultiPointSegmentTransformation (&pref, i, &points, NULL); // const Segment & seg = mesh -> LineSegment(i); for (int j = 0; j < npt; j++) mesh->GetCurvedElements(). CalcSegmentTransformation (pref[j], i, points[j]); if (vsol) { for (int j = 0; j < npt; j++) { vsol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]); // values[j] = ExtractValue (sol, scalcomp, &mvalues[0]); for (int k = 0; k < min(ncomp, 3); k++) points[j](k) += scaledeform * mvalues[k]; // points[j](0) += scaledeform * mvalues[0]; // points[j](1) += scaledeform * mvalues[1]; } } else if (sol) { for (int j = 0; j < npt; j++) { sol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]); values[j] = ExtractValue (sol, scalcomp, &mvalues[0]); if (meshdim <= 2) points[j](meshdim) += scaledeform * values[j]; } } glBegin (GL_LINE_STRIP); for (int i = 0; i < npt; i++) glVertex3dv (points[i]); glEnd(); } glEndList (); } void VisualSceneSolution :: DrawSurfaceElements () { shared_ptr mesh = GetMesh(); static int timer = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements"); /* static int timerstart = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements start"); static int timerloops = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements loops"); static int timerlist = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements list"); static int timerbuffer = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements buffer"); static int timer1 = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1"); static int timer1a = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1a"); static int timer1b = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1b"); static int timer1c = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1c"); static int timer2 = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2"); static int timer2a = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2a"); static int timer2b = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2b"); */ NgProfiler::RegionTimer reg (timer); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); par_surfellists.SetSize (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("solsurfellist"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (par_surfellists[dest], dest, MPI_TAG_VIS); if (surfellist) glDeleteLists (surfellist, 1); surfellist = glGenLists (1); glNewList (surfellist, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (par_surfellists[dest]); glEndList(); return; } #endif // NgProfiler::StartTimer(timerstart); if (surfellist) glDeleteLists (surfellist, 1); surfellist = glGenLists (1); glNewList (surfellist, GL_COMPILE); const SolData * sol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; if (mesh->GetTimeStamp () > solutiontimestamp) sol = NULL; if (sol && sol->solclass) sol->solclass->SetMultiDimComponent (multidimcomponent); glLineWidth (1.0f); GLfloat col_grey[] = { 0.6f, 0.6f, 0.6f, 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col_grey); int nse = mesh->GetNSE(); SetTextureMode (usetexture); CurvedElements & curv = mesh->GetCurvedElements(); int n = 1 << subdivisions; int npt = sqr(n+1); Array > pref (npt); Array > points (npt); Array > dxdxis (npt); Array > nvs(npt); Array values(npt); Array mvalues(npt); int sol_comp = (sol && sol->draw_surface) ? sol->components : 0; Array> > simd_pref ( (npt+SIMD::Size()-1)/SIMD::Size() ); Array> > simd_points ( (npt+SIMD::Size()-1)/SIMD::Size() ); Array> > simd_dxdxis ( (npt+SIMD::Size()-1)/SIMD::Size() ); Array> > simd_nvs( (npt+SIMD::Size()-1)/SIMD::Size() ); Array> simd_values( (npt+SIMD::Size()-1)/SIMD::Size() * sol_comp); // Array> glob_pnts; // Array> glob_nvs; // Array glob_values; if (sol && sol->draw_surface) mvalues.SetSize (npt * sol->components); Array > valuesc(npt); #ifdef USE_BUFFERS if (has_surfel_vbo) glDeleteBuffers (4, &surfel_vbo[0]); glGenBuffers (4, &surfel_vbo[0]); has_surfel_vbo = true; glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[0]); glBufferData (GL_ARRAY_BUFFER, nse*npt*sizeof(Point<3,double>), NULL, GL_STATIC_DRAW); glVertexPointer(3, GL_DOUBLE, 0, 0); // glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[1]); glBufferData (GL_ARRAY_BUFFER, nse*npt*sizeof(Vec<3,double>), NULL, GL_STATIC_DRAW); // glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_DOUBLE, 0, 0); // glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[2]); glBufferData (GL_ARRAY_BUFFER, nse*npt*sizeof(double), NULL, GL_STATIC_DRAW); glTexCoordPointer(1, GL_DOUBLE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, nse*npt*6*sizeof(int), NULL, GL_STATIC_DRAW); surfel_vbo_size = 0; #endif // NgProfiler::StopTimer(timerstart); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; if (vispar.drawdomainsurf > 0) { if (mesh->GetDimension() == 3) { if (vispar.drawdomainsurf != mesh->GetFaceDescriptor(el.GetIndex()).DomainIn() && vispar.drawdomainsurf != mesh->GetFaceDescriptor(el.GetIndex()).DomainOut()) continue; } else { if (el.GetIndex() != vispar.drawdomainsurf) continue; } } if ( el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 ) { bool curved = curv.IsSurfaceElementCurved (sei); for (int iy = 0, ii = 0; iy <= n; iy++) for (int ix = 0; ix <= n; ix++, ii++) pref[ii] = Point<2> (double(ix)/n, double(iy)/n); int npt = (n+1)*(n+1); if (curved) { for (int ii = 0; ii < npt; ii++) { Point<2> xref = pref[ii]; mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, points[ii], dxdxis[ii]); nvs[ii] = Cross (dxdxis[ii].Col(0), dxdxis[ii].Col(1)); nvs[ii].Normalize(); } } else { Point<3> lpi[4]; Vec<3> vx, vy, vtwist; for (int k = 0; k < 4; k++) GetPointDeformation (el[k]-1, lpi[k]); vx = lpi[1]-lpi[0]; vy = lpi[3]-lpi[0]; vtwist = (lpi[0]-lpi[1]) + (lpi[2]-lpi[3]); for (int ii = 0; ii < npt; ii++) { double x = pref[ii](0); double y = pref[ii](1); points[ii] = lpi[0] + x * vx + y * vy + x*y * vtwist; for (int j = 0; j < 3; j++) { dxdxis[ii](j,0) = vx(j) + y*vtwist(j); dxdxis[ii](j,1) = vy(j) + x*vtwist(j); } } Vec<3> nv = Cross (vx, vy); nv.Normalize(); for (int ii = 0; ii < npt; ii++) nvs[ii] = nv; } bool drawelem = false; /* if (sol && sol->draw_surface) { if (usetexture == 2) for (int ii = 0; ii < npt; ii++) drawelem = GetSurfValueComplex (sol, sei, -1, pref[ii](0), pref[ii](1), scalcomp, valuesc[ii]); else for (int ii = 0; ii < npt; ii++) drawelem = GetSurfValue (sol, sei, -1, pref[ii](0), pref[ii](1), scalcomp, values[ii]); } */ if (sol && sol->draw_surface) { drawelem = GetMultiSurfValues (sol, sei, -1, npt, &pref[0](0), &pref[1](0)-&pref[0](0), &points[0](0), &points[1](0)-&points[0](0), &dxdxis[0](0), &dxdxis[1](0)-&dxdxis[0](0), &mvalues[0], sol->components); if (usetexture == 2) for (int ii = 0; ii < npt; ii++) valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < npt; ii++) values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); } if (deform) for (int ii = 0; ii < npt; ii++) points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1)); int save_usetexture = usetexture; if (!drawelem) { usetexture = 0; SetTextureMode (0); } int ii = 0; glBegin (GL_QUADS); for (int iy = 0; iy < n; iy++, ii++) for (int ix = 0; ix < n; ix++, ii++) { int index[] = { ii, ii+1, ii+n+2, ii+n+1 }; for (int j = 0; j < 4; j++) { if (drawelem) { if (usetexture != 2) SetOpenGlColor (values[index[j]]); else glTexCoord2f ( valuesc[index[j]].real(), valuesc[index[j]].imag() ); } else glColor4fv (col_grey); glNormal3dv (nvs[index[j]]); glVertex3dv (points[index[j]]); } } glEnd(); if (!drawelem && (usetexture != save_usetexture)) { usetexture = save_usetexture; SetTextureMode (usetexture); } } } n = 1 << subdivisions; double invn = 1.0 / n; npt = (n+1)*(n+2)/2; // NgProfiler::StartTimer(timerloops); size_t base_pi = 0; for (int iy = 0, ii = 0; iy <= n; iy++) for (int ix = 0; ix <= n-iy; ix++, ii++) pref[ii] = Point<2> (ix*invn, iy*invn); constexpr size_t simd_size = SIMD::Size(); size_t simd_npt = (npt+simd_size-1)/simd_size; for (size_t i = 0; i < simd_npt; i++) { simd_pref[i](0) = [&] (size_t j) { size_t ii = i*simd_size+j; return (ii < npt) ? pref[ii](0) : 0; }; simd_pref[i](1) = [&] (size_t j) { size_t ii = i*simd_size+j; return (ii < npt) ? pref[ii](1) : 0; }; } Array ind_reftrig; for (int iy = 0, ii = 0; iy < n; iy++,ii++) for (int ix = 0; ix < n-iy; ix++, ii++) { int nv = (ix+iy+1 < n) ? 6 : 3; int ind[] = { ii, ii+1, ii+n-iy+1, ii+n-iy+1, ii+1, ii+n-iy+2 }; for (int j = 0; j < nv; j++) ind_reftrig.Append (ind[j]); } Array glob_ind; glob_ind.SetSize(ind_reftrig.Size()); for(SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; // if (el.GetIndex() <= 1) continue; if(vispar.drawdomainsurf > 0) { if (mesh->GetDimension() == 3) { if (vispar.drawdomainsurf != mesh->GetFaceDescriptor(el.GetIndex()).DomainIn() && vispar.drawdomainsurf != mesh->GetFaceDescriptor(el.GetIndex()).DomainOut()) continue; } else { if (el.GetIndex() != vispar.drawdomainsurf) continue; } } if ( el.GetType() == TRIG || el.GetType() == TRIG6 ) { // NgProfiler::StartTimer(timer1); #ifdef __AVX_try_it_out__ // NgProfiler::StartTimer(timer1a); bool curved = curv.IsSurfaceElementCurved(sei); if (curved) { mesh->GetCurvedElements(). CalcMultiPointSurfaceTransformation<3> (sei, simd_npt, &simd_pref[0](0), 2, &simd_points[0](0), 3, &simd_dxdxis[0](0,0), 6); for (size_t ii = 0; ii < simd_npt; ii++) simd_nvs[ii] = Cross (simd_dxdxis[ii].Col(0), simd_dxdxis[ii].Col(1)).Normalize(); } else { Point<3,SIMD> p1 = mesh->Point (el[0]); Point<3,SIMD> p2 = mesh->Point (el[1]); Point<3,SIMD> p3 = mesh->Point (el[2]); Vec<3,SIMD> vx = p1-p3; Vec<3,SIMD> vy = p2-p3; for (size_t ii = 0; ii < simd_npt; ii++) { simd_points[ii] = p3 + simd_pref[ii](0) * vx + simd_pref[ii](1) * vy; for (size_t j = 0; j < 3; j++) { simd_dxdxis[ii](j,0) = vx(j); simd_dxdxis[ii](j,1) = vy(j); } } Vec<3,SIMD> nv = Cross (vx, vy).Normalize(); for (size_t ii = 0; ii < simd_npt; ii++) simd_nvs[ii] = nv; } bool drawelem = false; if (sol && sol->draw_surface) { // NgProfiler::StopTimer(timer1a); // NgProfiler::StartTimer(timer1b); drawelem = sol->solclass->GetMultiSurfValue (sei, -1, simd_npt, &simd_pref[0](0).Data(), &simd_points[0](0).Data(), &simd_dxdxis[0](0).Data(), &simd_values[0].Data()); // NgProfiler::StopTimer(timer1b); // NgProfiler::StartTimer(timer1c); for (size_t j = 0; j < sol->components; j++) for (size_t i = 0; i < npt; i++) mvalues[i*sol->components+j] = ((double*)&simd_values[j*simd_npt])[i]; if (usetexture == 2) for (int ii = 0; ii < npt; ii++) valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < npt; ii++) values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); } for (size_t i = 0; i < npt; i++) { size_t ii = i/4; size_t r = i%4; for (int j = 0; j < 2; j++) pref[i](j) = simd_pref[ii](j)[r]; for (int j = 0; j < 3; j++) points[i](j) = simd_points[ii](j)[r]; for (int j = 0; j < 3; j++) nvs[i](j) = simd_nvs[ii](j)[r]; } if (deform) for (int ii = 0; ii < npt; ii++) points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1)); // NgProfiler::StopTimer(timer1c); #else bool curved = curv.IsSurfaceElementCurved(sei); for (int iy = 0, ii = 0; iy <= n; iy++) for (int ix = 0; ix <= n-iy; ix++, ii++) pref[ii] = Point<2> (ix*invn, iy*invn); if (curved) { mesh->GetCurvedElements(). CalcMultiPointSurfaceTransformation (&pref, sei, &points, &dxdxis); for (int ii = 0; ii < npt; ii++) nvs[ii] = Cross (dxdxis[ii].Col(0), dxdxis[ii].Col(1)).Normalize(); } else { Point<3> p1 = mesh->Point (el[0]); Point<3> p2 = mesh->Point (el[1]); Point<3> p3 = mesh->Point (el[2]); Vec<3> vx = p1-p3; Vec<3> vy = p2-p3; for (int ii = 0; ii < npt; ii++) { points[ii] = p3 + pref[ii](0) * vx + pref[ii](1) * vy; for (int j = 0; j < 3; j++) { dxdxis[ii](j,0) = vx(j); dxdxis[ii](j,1) = vy(j); } } Vec<3> nv = Cross (vx, vy).Normalize(); for (int ii = 0; ii < npt; ii++) nvs[ii] = nv; } bool drawelem = false; if (sol && sol->draw_surface) { drawelem = GetMultiSurfValues (sol, sei, -1, npt, &pref[0](0), &pref[1](0)-&pref[0](0), &points[0](0), &points[1](0)-&points[0](0), &dxdxis[0](0), &dxdxis[1](0)-&dxdxis[0](0), &mvalues[0], sol->components); if (usetexture == 2) for (int ii = 0; ii < npt; ii++) valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < npt; ii++) values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); } if (deform) for (int ii = 0; ii < npt; ii++) points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1)); #endif // NgProfiler::StopTimer(timer1); int save_usetexture = usetexture; if (!drawelem) { usetexture = 0; SetTextureMode (usetexture); } // NgProfiler::StartTimer(timer2); #ifdef USE_BUFFERS if (drawelem && usetexture == 1 && !logscale) { glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[0]); glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(Point<3,double>), npt*sizeof(Point<3,double>), &points[0][0]); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[1]); glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(Vec<3,double>), npt*sizeof(Vec<3,double>), &nvs[0][0]); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[2]); glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(double), npt*sizeof(double), &values[0]); for (size_t i = 0; i < ind_reftrig.Size(); i++) glob_ind[i] = base_pi+ind_reftrig[i]; glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]); glBufferSubData (GL_ELEMENT_ARRAY_BUFFER, surfel_vbo_size*sizeof(int), ind_reftrig.Size()*sizeof(int), &glob_ind[0]); surfel_vbo_size += ind_reftrig.Size(); base_pi += npt; } else #endif for (int iy = 0, ii = 0; iy < n; iy++) { glBegin (GL_TRIANGLE_STRIP); for (int ix = 0; ix <= n-iy; ix++, ii++) for (int k = 0; k < 2; k++) { if (ix+iy+k > n) continue; int hi = (k == 0) ? ii : ii+n-iy+1; if (drawelem) { if (usetexture != 2) SetOpenGlColor (values[hi]); else glTexCoord2f ( valuesc[hi].real(), valuesc[hi].imag() ); } else glColor4fv (col_grey); glNormal3dv (nvs[hi]); glVertex3dv (points[hi]); } glEnd(); } // NgProfiler::StopTimer(timer2); if (!drawelem && (usetexture != save_usetexture)) { usetexture = save_usetexture; SetTextureMode (usetexture); } } } // NgProfiler::StopTimer(timerloops); // NgProfiler::StartTimer(timerbuffer); // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]); // glBufferData(GL_ELEMENT_ARRAY_BUFFER, glob_ind.Size()*sizeof(int), &glob_ind[0], GL_STATIC_DRAW); // surfel_vbo_size = glob_ind.Size(); // NgProfiler::StopTimer(timerbuffer); // glDrawElements(GL_TRIANGLES, surfel_vbo_size, GL_UNSIGNED_INT, 0); // glDrawElements(GL_TRIANGLES, glob_ind.Size(), GL_UNSIGNED_INT, &glob_ind[0]); // glDisableClientState(GL_VERTEX_ARRAY); // glDisableClientState(GL_NORMAL_ARRAY); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); // glDeleteBuffers (1, &IndexVBOID); // glDeleteBuffers (4, &vboId[0]); // NgProfiler::StartTimer(timerlist); glEndList (); // NgProfiler::StopTimer(timerlist); #ifdef PARALLELGL glFinish(); if (id > 0) MyMPI_Send (surfellist, 0, MPI_TAG_VIS); #endif } void VisualSceneSolution :: DrawSurfaceElementLines () { shared_ptr mesh = GetMesh(); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); par_surfellists.SetSize (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("solsurfellinelist"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (par_surfellists[dest], dest, MPI_TAG_VIS); if (linelist) glDeleteLists (linelist, 1); linelist = glGenLists (1); glNewList (linelist, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (par_surfellists[dest]); glEndList(); return; } #endif if (linelist) glDeleteLists (linelist, 1); linelist = glGenLists (1); glNewList (linelist, GL_COMPILE); glLineWidth (1.0f); int nse = mesh->GetNSE(); CurvedElements & curv = mesh->GetCurvedElements(); int n = 1 << subdivisions; ArrayMem, 65> ptsloc(n+1); ArrayMem, 65> ptsglob(n+1); double trigpts[3][2] = { { 0, 0 }, { 0, 1 }, { 1, 0} }; double trigvecs[3][2] = { { 1, 0 }, { 0, -1 }, { -1, 1} }; double quadpts[4][2] = { { 0, 0 }, { 1, 1 }, { 0, 1}, { 1, 0 } }; double quadvecs[4][2] = { { 1, 0 }, { -1, 0}, { 0, -1}, { 0, 1 } }; for (SurfaceElementIndex sei = 0; sei < nse; sei++) { Element2d & el = (*mesh)[sei]; int nv = (el.GetType() == TRIG || el.GetType() == TRIG6) ? 3 : 4; for (int k = 0; k < nv; k++) { Point<2> p0; Vec<2> vtau; if (nv == 3) { p0 = Point<2>(trigpts[k][0], trigpts[k][1]); vtau = Vec<2>(trigvecs[k][0], trigvecs[k][1]); } else { p0 = Point<2>(quadpts[k][0], quadpts[k][1]); vtau = Vec<2>(quadvecs[k][0], quadvecs[k][1]); } glBegin (GL_LINE_STRIP); for (int ix = 0; ix <= n; ix++) ptsloc[ix] = p0 + (double(ix) / n) * vtau; curv.CalcMultiPointSurfaceTransformation (&ptsloc, sei, &ptsglob, 0); for (int ix = 0; ix <= n; ix++) { if (deform) ptsglob[ix] += GetSurfDeformation (sei, k, ptsloc[ix](0), ptsloc[ix](1)); glVertex3dv (ptsglob[ix]); } glEnd (); } } glEndList (); #ifdef PARALLELGL glFinish(); if (id > 0) MyMPI_Send (linelist, 0, MPI_TAG_VIS); #endif } void VisualSceneSolution :: DrawIsoSurface(const SolData * sol, const SolData * vsol, int comp) { shared_ptr mesh = GetMesh(); if (!draw_isosurface) return; if (!sol) return; SetTextureMode (0); glColor3d (1.0, 0, 0); glEnable (GL_COLOR_MATERIAL); glBegin (GL_TRIANGLES); int ne = mesh->GetNE(); const int edgei[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; double edgelam[6]; Point<3> edgep[6]; Vec<3> normp[6]; double nodevali[4]; int cntce; int cpe1 = 0, cpe2 = 0, cpe3 = 0; int n = 1 << subdivisions; int n3 = (n+1)*(n+1)*(n+1); Array > grid(n3); Array > locgrid(n3); Array > trans(n3); Array val1(n3*sol->components); Array > grads1(n3); Array compress(n3); MatrixFixWidth<3> pointmat(8); grads1 = Vec<3> (0.0); for (ElementIndex ei = 0; ei < ne; ei++) { // if(vispar.clipdomain > 0 && vispar.clipdomain != (*mesh)[ei].GetIndex()) continue; // if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue; ELEMENT_TYPE type = (*mesh)[ei].GetType(); if (type == HEX || type == PRISM || type == TET || type == PYRAMID) { const Element & el = (*mesh)[ei]; int ii = 0; int cnt_valid = 0; for (int ix = 0; ix <= n; ix++) for (int iy = 0; iy <= n; iy++) for (int iz = 0; iz <= n; iz++, ii++) { Point<3> ploc; compress[ii] = ii; switch (type) { case PRISM: if (ix+iy <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); compress[ii] = cnt_valid; cnt_valid++; } else compress[ii] = -1; break; case TET: if (ix+iy+iz <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); compress[ii] = cnt_valid; cnt_valid++; } else compress[ii] = -1; break; case HEX: ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); break; case PYRAMID: ploc = Point<3> (double(ix) / n * (1-double(iz)/n), double(iy) / n * (1-double(iz)/n), double(iz)/n); break; default: cerr << "case not implementd 878234" << endl; ploc = 0.0; } if (compress[ii] != -1) locgrid[compress[ii]] = ploc; } if (type != TET && type != PRISM) cnt_valid = n3; if (mesh->GetCurvedElements().IsHighOrder() || 1) { mesh->GetCurvedElements(). CalcMultiPointElementTransformation (&locgrid, ei, &grid, &trans); } else { Vector shape(el.GetNP()); for (int k = 0; k < el.GetNP(); k++) for (int j = 0; j < 3; j++) pointmat(k,j) = (*mesh)[el[k]](j); for (int i = 0; i < cnt_valid; i++) { el.GetShapeNew (locgrid[i], shape); Point<3> pglob; for (int j = 0; j < 3; j++) { pglob(j) = 0; for (int k = 0; k < el.GetNP(); k++) pglob(j) += shape(k) * pointmat(k,j); } grid[i] = pglob; } } bool has_pos = 0, has_neg = 0; GetMultiValues( sol, ei, -1, n3, &locgrid[0](0), &locgrid[1](0)-&locgrid[0](0), &grid[0](0), &grid[1](0)-&grid[0](0), &trans[0](0), &trans[1](0)-&trans[0](0), &val1[0], sol->components); for (int i = 0; i < cnt_valid; i++) { // GetValue (sol, ei, &locgrid[i](0), &grid[i](0), &trans[i](0), comp, val[i]); // val[i] -= minval; val1[sol->components*i+comp-1] -= minval; // if (vsol) // GetValues (vsol, ei, &locgrid[i](0), &grid[i](0), &trans[i](0), &grads[i](0)); // grads[i] *= -1; if (val1[i*sol->components+comp-1] > 0) has_pos = 1; else has_neg = 1; // if (val[i] > 0) // has_pos = 1; // else // has_neg = 1; } if (!has_pos || !has_neg) continue; if (vsol) { GetMultiValues(vsol, ei, -1, n3, &locgrid[0](0), &locgrid[1](0)-&locgrid[0](0), &grid[0](0), &grid[1](0)-&grid[0](0), &trans[0](0), &trans[1](0)-&trans[0](0), &grads1[0](0), vsol->components); // for (int i = 0; i < cnt_valid; i++) // grads1[i*sol->components+comp-1] *= -1; for (int i = 0; i < cnt_valid; i++) grads1[i] *= -1; } for (int ix = 0; ix < n; ix++) for (int iy = 0; iy < n; iy++) for (int iz = 0; iz < n; iz++) { int base = iz + (n+1)*iy + (n+1)*(n+1)*ix; int pi[8] = { base, base+(n+1)*(n+1), base+(n+1)*(n+1)+(n+1), base+(n+1), base+1, base+(n+1)*(n+1)+1, base+(n+1)*(n+1)+(n+1)+1, base+(n+1)+1 }; for (int j = 0; j < 8; j++) pi[j] = compress[pi[j]]; int tets[6][4] = { { 1, 2, 4, 5 }, { 4, 5, 2, 8 }, { 2, 8, 5, 6 }, { 2, 3, 4, 8 }, { 2, 3, 8, 6 }, { 3, 8, 6, 7 } }; for (int ii = 0; ii < 6; ii++) { int teti[4]; for (int k = 0; k < 4; k++) teti[k] = pi[tets[ii][k]-1]; bool is_valid = 1; for (int j = 0; j < 4; j++) if (teti[j] == -1) is_valid = 0; if (!is_valid) continue; // for (int j = 0; j < 4; j++) // nodevali[j] = val[teti[j]]; for (int j = 0; j < 4; j++) nodevali[j] = val1[sol->components*teti[j]+comp-1]; cntce = 0; for (int j = 0; j < 6; j++) { int lpi1 = edgei[j][0]; int lpi2 = edgei[j][1]; if ( (nodevali[lpi1] > 0) != (nodevali[lpi2] > 0) ) { Point<3> p1 = grid[teti[lpi1]]; Point<3> p2 = grid[teti[lpi2]]; edgelam[j] = nodevali[lpi2] / (nodevali[lpi2] - nodevali[lpi1]); edgep[j] = grid[teti[lpi1]] + (1-edgelam[j]) * (grid[teti[lpi2]]-grid[teti[lpi1]]); // normp[j] = grads[teti[lpi1]] + (1-edgelam[j]) * (grads[teti[lpi2]]-grads[teti[lpi1]]); normp[j] = grads1[teti[lpi1]] + (1-edgelam[j]) * (grads1[teti[lpi2]]-grads1[teti[lpi1]]); // normp[j] = grads1[sol->components*teti[lpi1]+comp-1] + (1-edgelam[j]) * (grads1[sol->components*teti[lpi2]+comp-1]-grads1[sol->components*teti[lpi1]+comp-1]); cntce++; cpe3 = cpe2; cpe2 = cpe1; cpe1 = j; if (cntce >= 3) { if (!vsol) { Point<3> points[3]; points[0] = edgep[cpe1]; points[1] = edgep[cpe2]; points[2] = edgep[cpe3]; Vec<3> normal = Cross (points[2]-points[0], points[1]-points[0]); if ( ( (normal * (p2-p1)) > 0 ) == ( nodevali[lpi1] < 0) ) normal *= -1; glNormal3dv (normal); glVertex3dv (points[0]); glVertex3dv (points[1]); glVertex3dv (points[2]); } else { glNormal3dv (normp[cpe1]); glVertex3dv (edgep[cpe1]); glNormal3dv (normp[cpe2]); glVertex3dv (edgep[cpe2]); glNormal3dv (normp[cpe3]); glVertex3dv (edgep[cpe3]); } } } } } } } } glEnd(); } void VisualSceneSolution :: DrawTrigSurfaceVectors(const Array< Point<3> > & lp, const Point<3> & pmin, const Point<3> & pmax, const int sei, const SolData * vsol) { shared_ptr mesh = GetMesh(); int dir,dir1,dir2; double s,t; Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]); Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2))); if (na(0) > na(1) && na(0) > na(2)) dir = 1; else if (na(1) > na(2)) dir = 2; else dir = 3; dir1 = (dir % 3) + 1; dir2 = (dir1 % 3) + 1; Point<2> p2d[3]; int k; for (k = 0; k < 3; k++) { p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad), (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad)); } double minx2d, maxx2d, miny2d, maxy2d; minx2d = maxx2d = p2d[0](0); miny2d = maxy2d = p2d[0](1); for (k = 1; k < 3; k++) { minx2d = min2 (minx2d, p2d[k](0)); maxx2d = max2 (maxx2d, p2d[k](0)); miny2d = min2 (miny2d, p2d[k](1)); maxy2d = max2 (maxy2d, p2d[k](1)); } double mat11 = p2d[1](0) - p2d[0](0); double mat21 = p2d[1](1) - p2d[0](1); double mat12 = p2d[2](0) - p2d[0](0); double mat22 = p2d[2](1) - p2d[0](1); double det = mat11*mat22-mat21*mat12; double inv11 = mat22/det; double inv21 = -mat21/det; double inv12 = -mat12/det; double inv22 = mat11/det; // cout << "drawsurfacevectors. xoffset = " << xoffset << ", yoffset = "; // cout << yoffset << endl; for (s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize) if (s >= minx2d && s <= maxx2d) for (t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize) if (t >= miny2d && t <= maxy2d) { double lam1 = inv11 * (s - p2d[0](0)) + inv12 * (t-p2d[0](1)); double lam2 = inv21 * (s - p2d[0](0)) + inv22 * (t-p2d[0](1)); if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1) { Point<3> cp; for (k = 0; k < 3; k++) cp(k) = lp[0](k) + lam1 * (lp[1](k)-lp[0](k)) + lam2 * (lp[2](k)-lp[0](k)); Point<2> xref(lam1, lam2); if (mesh->GetCurvedElements().IsHighOrder()) mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, cp); Vec<3> v; double values[6]; bool drawelem = GetSurfValues (vsol, sei, -1, lam1, lam2, values); if (!vsol->iscomplex) for (k = 0; k < 3; k++) v(k) = values[k]; else { if (!imag_part) for (k = 0; k < 3; k++) v(k) = values[2*k]; else for (k = 0; k < 3; k++) v(k) = values[2*k+1]; } if (mesh->GetDimension() == 2) if ( (!vsol->iscomplex && vsol->components != 3) || (vsol->iscomplex && vsol->components != 6) ) v(2) = 0; double val = v.Length(); SetOpenGlColor (val); // (val, minval, maxval, logscale); // change JS if (val > 1e-10 * maxval) v *= (rad / val / gridsize * 0.5); else drawelem = 0; if ( drawelem ) DrawCone (cp, cp+4*v, 0.8*rad / gridsize); } } } void VisualSceneSolution :: DrawSurfaceVectors () { shared_ptr mesh = GetMesh(); SurfaceElementIndex sei; const SolData * vsol = NULL; // bool drawelem; if (vecfunction != -1) vsol = soldata[vecfunction]; if (mesh->GetTimeStamp () > solutiontimestamp) vsol = NULL; if (!vsol) return; Point<3> pmin = center - Vec3d (rad, rad, rad); Point<3> pmax = center - Vec3d (rad, rad, rad); // glColor3d (1.0, 1.0, 1.0); // glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); if (vsol->draw_surface && showsurfacesolution) { int nse = mesh->GetNSE(); for (sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; if (el.GetType() == TRIG || el.GetType() == TRIG6) { Array< Point<3> > lp(3); lp[0] = mesh->Point(el[2]); lp[1] = mesh->Point(el[0]); lp[2] = mesh->Point(el[1]); DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol); /* Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]); Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2))); if (na(0) > na(1) && na(0) > na(2)) dir = 1; else if (na(1) > na(2)) dir = 2; else dir = 3; dir1 = (dir % 3) + 1; dir2 = (dir1 % 3) + 1; for (k = 0; k < 3; k++) { p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad), (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad)); } double minx2d, maxx2d, miny2d, maxy2d; minx2d = maxx2d = p2d[0](0); miny2d = maxy2d = p2d[0](1); for (k = 1; k < 3; k++) { minx2d = min2 (minx2d, p2d[k](0)); maxx2d = max2 (maxx2d, p2d[k](0)); miny2d = min2 (miny2d, p2d[k](1)); maxy2d = max2 (maxy2d, p2d[k](1)); } double mat11 = p2d[1](0) - p2d[0](0); double mat21 = p2d[1](1) - p2d[0](1); double mat12 = p2d[2](0) - p2d[0](0); double mat22 = p2d[2](1) - p2d[0](1); double det = mat11*mat22-mat21*mat12; double inv11 = mat22/det; double inv21 = -mat21/det; double inv12 = -mat12/det; double inv22 = mat11/det; // cout << "drawsurfacevectors. xoffset = " << xoffset << ", yoffset = "; // cout << yoffset << endl; for (s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize) if (s >= minx2d && s <= maxx2d) for (t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize) if (t >= miny2d && t <= maxy2d) { double lam1 = inv11 * (s - p2d[0](0)) + inv12 * (t-p2d[0](1)); double lam2 = inv21 * (s - p2d[0](0)) + inv22 * (t-p2d[0](1)); if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1) { Point<3> cp; for (k = 0; k < 3; k++) cp(k) = lp[0](k) + lam1 * (lp[1](k)-lp[0](k)) + lam2 * (lp[2](k)-lp[0](k)); Vec<3> v; double values[6]; drawelem = GetSurfValues (vsol, sei, lam1, lam2, values); if (!vsol->iscomplex) for (k = 0; k < 3; k++) v(k) = values[k]; else { if (!imag_part) for (k = 0; k < 3; k++) v(k) = values[2*k]; else for (k = 0; k < 3; k++) v(k) = values[2*k+1]; } if (mesh->GetDimension() == 2) if ( (!vsol->iscomplex && vsol->components != 3) || (vsol->iscomplex && vsol->components != 6) ) v(2) = 0; double val = v.Length(); SetOpenGlColor (val, minval, maxval, logscale); if (val > 1e-10 * maxval) v *= (rad / val / gridsize * 0.5); else drawelem = 0; // "drawelem": added 07.04.2004 (FB) if ( drawelem ) DrawCone (cp, cp+4*v, 0.8*rad / gridsize); } } */ } else if (el.GetType() == QUAD) { /* Array < Point<3> > lp(3); lp[0] = mesh->Point(el[0]); lp[1] = mesh->Point(el[1]); lp[2] = mesh->Point(el[2]); DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol); lp[0] = mesh->Point(el[0]); lp[1] = mesh->Point(el[2]); lp[2] = mesh->Point(el[3]); DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol); */ Point<3> lp[4]; Point<2> p2d[4]; for (int k = 0; k < 4; k++) lp[k] = mesh->Point (el[k]); Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]); Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2))); int dir, dir1, dir2; if (na(0) > na(1) && na(0) > na(2)) dir = 1; else if (na(1) > na(2)) dir = 2; else dir = 3; dir1 = (dir % 3) + 1; dir2 = (dir1 % 3) + 1; for (int k = 0; k < 4; k++) { p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad), (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad)); } double minx2d, maxx2d, miny2d, maxy2d; minx2d = maxx2d = p2d[0](0); miny2d = maxy2d = p2d[0](1); for (int k = 1; k < 4; k++) { minx2d = min2 (minx2d, p2d[k](0)); maxx2d = max2 (maxx2d, p2d[k](0)); miny2d = min2 (miny2d, p2d[k](1)); maxy2d = max2 (maxy2d, p2d[k](1)); } for (double s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize) if (s >= minx2d && s <= maxx2d) for (double t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize) if (t >= miny2d && t <= maxy2d) { double lami[3]; Point3d p3d(2*rad*s+pmin(0), 2*rad*t+pmin(1),0); if (mesh->PointContainedIn2DElement (p3d, lami, sei+1)) { Point<3> cp = p3d; double lam1 = lami[0]; double lam2 = lami[1]; //for (k = 0; k < 3; k++) //cp(k) = lp[0](k) + //lam1 * (lp[1](k)-lp[0](k)) + //lam2 * (lp[2](k)-lp[0](k)); Vec<3> v; double values[6]; bool drawelem = GetSurfValues (vsol, sei, -1, lam1, lam2, values); (*testout) << "sei " << sei << " lam1 " << lam1 << " lam2 " << lam2 << " drawelem " << drawelem << endl; if (!vsol->iscomplex) for (int k = 0; k < 3; k++) v(k) = values[k]; else { if (!imag_part) for (int k = 0; k < 3; k++) v(k) = values[2*k]; else for (int k = 0; k < 3; k++) v(k) = values[2*k+1]; } if (mesh->GetDimension() == 2) if ( (!vsol->iscomplex && vsol->components != 3) || (vsol->iscomplex && vsol->components != 6) ) v(2) = 0; double val = v.Length(); SetOpenGlColor (val); // , minval, maxval, logscale); july 09 (*testout) << "v " << v << endl; if (val > 1e-10 * maxval) v *= (rad / val / gridsize * 0.5); (*testout) << "v " << v << endl; if ( drawelem ) { DrawCone (cp, cp+4*v, 0.8*rad / gridsize); (*testout) << "cp " << cp << " rad " << rad << " gridsize " << gridsize << endl; } } } } } } } void VisualSceneSolution :: DrawIsoLines (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, double val1, double val2, double val3) { DrawIsoLines2 (p1, p2, p1, p3, val1, val2, val1, val3); // , minval, maxval, n); DrawIsoLines2 (p2, p1, p2, p3, val2, val1, val2, val3); // , minval, maxval, n); DrawIsoLines2 (p3, p1, p3, p2, val3, val1, val3, val2); // , minval, maxval, n); } void VisualSceneSolution :: DrawIsoLines2 (const Point<3> & hp1, const Point<3> & hp2, const Point<3> & hp3, const Point<3> & hp4, double val1, double val2, double val3, double val4) { int n = numisolines; Point<3> p1, p2, p3, p4; if (val1 < val2) { p1 = hp1; p2 = hp2; } else { p1 = hp2; p2 = hp1; swap (val1, val2); } if (val3 < val4) { p3 = hp3; p4 = hp4; } else { p3 = hp4; p4 = hp3; swap (val3, val4); } val2 += 1e-10; val4 += 1e-10; double fac = (maxval-minval) / n; double idelta1 = 1.0 / (val2 - val1); double idelta2 = 1.0 / (val4 - val3); int mini = int ((max2 (val1, val3) - minval) / fac); int maxi = int ((min2 (val2, val4) - minval) / fac); if (mini < 0) mini = 0; if (maxi > n-1) maxi = n-1; for (int i = mini; i <= maxi; i++) { double val = minval + i * fac; double lam1 = (val - val1) * idelta1; double lam2 = (val - val3) * idelta2; if (lam1 >= 0 && lam1 <= 1 && lam2 >= 0 && lam2 <= 1) { Point<3> lp1 = p1 + lam1 * (p2-p1); Point<3> lp2 = p3 + lam2 * (p4-p3); glVertex3dv (lp1 ); glVertex3dv (lp2 ); // glVertex3dv (lp2 ); // better ? // glVertex3dv (lp1 ); } } } void VisualSceneSolution :: GetMinMax (int funcnr, int comp, double & minv, double & maxv) const { shared_ptr mesh = GetMesh(); // static int timer1 = NgProfiler::CreateTimer ("getminmax, vol"); // static int timer2 = NgProfiler::CreateTimer ("getminmax, surf"); #ifdef PARALLEL auto comm = mesh->GetCommunicator(); if (comm.Size() > 1) { if (id == 0) { MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("getminmax"); } MyMPI_Bcast (funcnr, mesh->GetCommunicator()); MyMPI_Bcast (comp, mesh->GetCommunicator()); } #endif // double val; // bool considerElem; bool hasit = false; #ifdef max #undef max #endif minv = numeric_limits::max(); maxv = -numeric_limits::max(); if ((ntasks == 1) || (id > 0)) if (funcnr != -1) { const SolData * sol = soldata[funcnr]; if (sol->draw_volume) { // NgProfiler::RegionTimer reg1 (timer1); int ne = mesh->GetNE(); mutex min_mutex; mutex max_mutex; ParallelFor(0, ne, [&] (int first, int next) { double minv_local = numeric_limits::max(); double maxv_local = -numeric_limits::max(); for (int i=first; i maxv_local) maxv_local = val; if (val < minv_local) minv_local = val; hasit = true; } } if(minv_local < minv) { lock_guard guard(min_mutex); if(minv_local < minv) minv = minv_local; } if(maxv_local > maxv) { lock_guard guard(max_mutex); if(maxv_local > maxv) maxv = maxv_local; } }); } if (sol->draw_surface) { // NgProfiler::RegionTimer reg2 (timer2); int nse = mesh->GetNSE(); for (int i = 0; i < nse; i++) { ELEMENT_TYPE type = mesh->SurfaceElement(i+1).GetType(); double val; bool considerElem = (type == QUAD) ? GetSurfValue (sol, i, -1, 0.5, 0.5, comp, val) : GetSurfValue (sol, i, -1, 0.3333333, 0.3333333, comp, val); if (considerElem) { if (val > maxv) maxv = val; if (val < minv) minv = val; hasit = true; } } } } if (minv == maxv) maxv = minv+1e-6; if (!hasit) { minv = 0; maxv = 1; } #ifdef PARALLEL if ((ntasks > 1) && (id == 0)) { minv = 1e99; maxv = -1e99; } if (ntasks > 1) { double hmin, hmax; MPI_Reduce (&minv, &hmin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); MPI_Reduce (&maxv, &hmax, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); minv = hmin; maxv = hmax; } #endif } bool VisualSceneSolution :: GetValues (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values); break; } default: { for (int i = 0; i < data->components; i++) ok = GetValue (data, elnr, lam1, lam2, lam3, i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetValues (const SolData * data, ElementIndex elnr, const double xref[], const double x[], const double dxdxref[], double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetValue (elnr, xref, x, dxdxref, values); break; } default: { for (int i = 0; i < data->components; i++) ok = GetValue (data, elnr, xref[0], xref[1], xref[2], i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetValue (const SolData * data, ElementIndex elnr, const double xref[], const double x[], const double dxdxref[], int comp, double & val) const { shared_ptr mesh = GetMesh(); double lam1 = xref[0]; double lam2 = xref[1]; double lam3 = xref[2]; val = 0; bool ok = 0; if (comp == 0) { ArrayMem values(data->components); ok = GetValues (data, elnr, xref, x, dxdxref, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { double values[20]; ok = data->solclass->GetValue (elnr, xref, x, dxdxref, values); val = values[comp-1]; return ok; } case SOL_NODAL: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } default: cerr << "case not implementd 23523" << endl; } for (int i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { val = data->data[elnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_ELEMENT: return 0; case SOL_NONCONTINUOUS: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } case PYRAMID: case PYRAMID13: { if (lam3 > 1-1e-5) { lami[0] = lami[1] = lami[2] = lami[3] = 0; lami[4] = 1; } else { double x0 = lam1 / (1-lam3); double y0 = lam2 / (1-lam3); lami[0] = (1-x0) * (1-y0) * (1-lam3); lami[1] = ( x0) * (1-y0) * (1-lam3); lami[2] = ( x0) * ( y0) * (1-lam3); lami[3] = (1-x0) * ( y0) * (1-lam3); lami[4] = lam3; np = 5; } break; } default: np = 0; } int base; if (data->order == 1) base = 6 * elnr; else base = 10 * elnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { val = (*mesh)[elnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { val = (*mesh)[elnr].GetOrder(); return 1; } default: cerr << "case not handled 7234" << endl; } return 0; } bool VisualSceneSolution :: GetValue (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, int comp, double & val) const { shared_ptr mesh = GetMesh(); val = 0; bool ok = 0; if (comp == 0) { ArrayMem values(data->components); ok = GetValues (data, elnr, lam1, lam2, lam3, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { val = 0.0; double values[20]; ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values); val = values[comp-1]; return ok; } case SOL_NODAL: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } default: cerr << "case not implemented 234324" << endl; } for (int i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { val = data->data[elnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_ELEMENT: return 0; case SOL_NONCONTINUOUS: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } case PYRAMID: { if (lam3 > 1-1e-5) { lami[0] = lami[1] = lami[2] = lami[3] = 0; lami[4] = 1; } else { double x0 = lam1 / (1-lam3); double y0 = lam2 / (1-lam3); lami[0] = (1-x0) * (1-y0) * (1-lam3); lami[1] = ( x0) * (1-y0) * (1-lam3); lami[2] = ( x0) * ( y0) * (1-lam3); lami[3] = (1-x0) * ( y0) * (1-lam3); lami[4] = lam3; np = 5; } break; } default: np = 0; } int base; if (data->order == 1) base = 6 * elnr; else base = 10 * elnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { val = (*mesh)[elnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { val = (*mesh)[elnr].GetOrder(); return 1; } default: cerr << "case not implemented 234234" << endl; } return 0; } bool VisualSceneSolution :: GetValueComplex (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, int comp, complex & val) const { shared_ptr mesh = GetMesh(); val = 0.0; bool ok = 0; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { double values[20]; ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values); val = complex (values[comp-1], values[comp]); return ok; } default: cerr << "case not handled 234234" << endl; } return 0; } bool VisualSceneSolution :: GetMultiValues (const SolData * data, ElementIndex elnr, int facetnr, int npt, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * val, int sval) const { bool drawelem = false; if (data->soltype == SOL_VIRTUALFUNCTION) drawelem = data->solclass->GetMultiValue(elnr, facetnr, npt, xref, sxref, x, sx, dxdxref, sdxdxref, val, sval); else for (int i = 0; i < npt; i++) drawelem = GetValues (data, elnr, xref+i*sxref, x+i*sx, dxdxref+i*sdxdxref, val+i*sval); return drawelem; } bool VisualSceneSolution :: GetSurfValues (const SolData * data, SurfaceElementIndex selnr, int facetnr, double lam1, double lam2, double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, values); // ok = 1; // values[0] = 1.0; break; } default: { for (int i = 0; i < data->components; i++) ok = GetSurfValue (data, selnr, facetnr, lam1, lam2, i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetSurfValues (const SolData * data, SurfaceElementIndex selnr, int facetnr, const double xref[], const double x[], const double dxdxref[], double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetSurfValue (selnr, facetnr, xref, x, dxdxref, values); break; } default: { for (int i = 0; i < data->components; i++) ok = GetSurfValue (data, selnr, facetnr, xref[0], xref[1], i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetMultiSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, int npt, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * val, int sval) const { bool drawelem = false; if (data->soltype == SOL_VIRTUALFUNCTION) drawelem = data->solclass->GetMultiSurfValue(elnr, facetnr, npt, xref, sxref, x, sx, dxdxref, sdxdxref, val, sval); else for (int i = 0; i < npt; i++) drawelem = GetSurfValues (data, elnr, facetnr, xref+i*sxref, x+i*sx, dxdxref+i*sdxdxref, val+i*sval); return drawelem; } double VisualSceneSolution :: ExtractValue (const SolData * data, int comp, double * values) const { double val = 0; if (comp == 0) { switch (evalfunc) { case FUNC_ABS: { for (int ci = 0; ci < data->components; ci++) val += sqr (values[ci]); val = sqrt (val); break; } case FUNC_ABS_TENSOR: { int d = 0; switch (data->components) { case 1: d = 1; break; case 3: d = 2; break; case 6: d = 3; break; } for (int ci = 0; ci < d; ci++) val += sqr (values[ci]); for (int ci = d; ci < data->components; ci++) val += 2*sqr (values[ci]); val = sqrt (val); break; } case FUNC_MISES: { int d = 0; switch(data->components) { case 1: d = 1; break; case 3: d = 2; break; case 6: d = 3; break; } int ci; double trace = 0.; for (ci = 0; ci < d; ci++) trace += 1./3.*(values[ci]); for (ci = 0; ci < d; ci++) val += sqr (values[ci]-trace); for (ci = d; ci < data->components; ci++) val += 2.*sqr (values[ci]); val = sqrt (val); break; } case FUNC_MAIN: { int d = 0; switch(data->components) { case 1: d = 1; break; case 3: d = 2; break; case 6: d = 3; break; } Mat<3,3> m ; Vec<3> ev; int ci; for (ci = 0; ci < d; ci++) m(ci,ci) = (values[ci]); m(0,1) = m(1,0) = values[3]; m(0,2) = m(2,0) = values[4]; m(1,2) = m(2,1) = values[5]; EigenValues (m, ev); double help; for (int i=0; i abs(ev(j-1)) ) { help = ev(j); ev(j) = ev(j-1); ev(j-1) = help; } } } val = (ev(0)); break; } } return val; } return values[comp-1]; } complex VisualSceneSolution :: ExtractValueComplex (const SolData * data, int comp, double * values) const { if (!data->iscomplex) return values[comp-1]; else return complex (values[comp-1], values[comp]); } bool VisualSceneSolution :: GetSurfValueComplex (const SolData * data, SurfaceElementIndex selnr, int facetnr, double lam1, double lam2, int comp, complex & val) const { switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ArrayMem values(data->components); bool ok; ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, &values[0]); if (ok) { if (!data->iscomplex) val = values[comp-1]; else val = complex (values[comp-1], values[comp]); } return ok; } default: cerr << "case not implementd 6565" << endl; } return 0; } bool VisualSceneSolution :: GetSurfValue (const SolData * data, SurfaceElementIndex selnr, int facetnr, double lam1, double lam2, int comp, double & val) const { bool ok; if (comp == 0) { val = 0; ArrayMem values(data->components); ok = GetSurfValues (data, selnr, facetnr, lam1, lam2, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ArrayMem values(data->components); bool ok; ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, &values[0]); if (ok) { if (!data->iscomplex) val = values[comp-1]; else { // cout << "time = " << time << ", cos = " << cos(time) << endl; // old version: val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); // SZ: Sept 06 if(comp%2==0) val = values[comp-1]*cos(3*time) - values[comp-2]*sin(3*time); else val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); } } return ok; } case SOL_NODAL: { shared_ptr mesh = GetMesh(); const Element2d & el = (*mesh)[selnr]; double lami[8]; int np, i; val = 0; double lam3 = 1-lam1-lam2; switch (el.GetType()) { case TRIG: /* lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; */ lami[0] = lam1; lami[1] = lam2; lami[2] = lam3; np = 3; break; case TRIG6: /* lami[0] = lam3*(2*lam3-1); lami[1] = lam1*(2*lam1-1); lami[2] = lam2*(2*lam2-1); */ // hierarchical basis: lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; case QUAD: case QUAD6: case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; lami[3] = (1-lam1) * lam2; np = 4; break; default: np = 0; } for (i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { shared_ptr mesh = GetMesh(); int el1, el2; mesh->GetTopology().GetSurface2VolumeElement (selnr+1, el1, el2); el1--; val = data->data[el1 * data->dist+comp-1]; return 1; } case SOL_NONCONTINUOUS: { val = 0; // ????? return 0; } case SOL_SURFACE_ELEMENT: { val = data->data[selnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_NONCONTINUOUS: { shared_ptr mesh = GetMesh(); const Element2d & el = (*mesh)[selnr]; double lami[8]; int np = 0; val = 0; int order = data->order; switch (order) { case 0: return data->data[selnr * data->dist + comp-1]; case 1: { switch (el.GetType()) { case TRIG: case TRIG6: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } default: cerr << "case not implementd 2342" << endl; } break; } case 2: { switch (el.GetType()) { case TRIG: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } case TRIG6: { double lam3 = 1-lam1-lam2; lami[1] = 2*lam1 * (lam1-0.5); lami[2] = 2*lam2 * (lam2-0.5); lami[0] = 2*lam3 * (lam3-0.5); lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; } default: cerr << "case not implemented 8712" << endl; } break; } } int base; if (order == 1) base = 4 * selnr; else base = 9 * selnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { shared_ptr mesh = GetMesh(); val = (*mesh)[selnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { shared_ptr mesh = GetMesh(); val = (*mesh)[selnr].GetOrder(); return 1; } } return 0; } bool VisualSceneSolution :: GetSurfValue (const SolData * data, SurfaceElementIndex selnr, int facetnr, const double xref[], const double x[], const double dxdxref[], int comp, double & val) const { shared_ptr mesh = GetMesh(); double lam1 = xref[0], lam2 = xref[1]; bool ok; if (comp == 0) { val = 0; ArrayMem values(data->components); ok = GetSurfValues (data, selnr, facetnr, xref, x, dxdxref, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ArrayMem values(data->components); bool ok; // ok = data->solclass->GetSurfValue (selnr, lam1, lam2, &values[0]); // cout << "data->solclass = " << flush << data->solclass << endl; ok = data->solclass->GetSurfValue (selnr, facetnr, xref, x, dxdxref, &values[0]); // ok = 1; // values[0] = 1.0; if (ok) { if (!data->iscomplex) val = values[comp-1]; else { // cout << "time = " << time << ", cos = " << cos(time) << endl; // old version: val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); // SZ: Sept 06 if(comp%2==0) val = values[comp-1]*cos(3*time) - values[comp-2]*sin(3*time); else val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); } } return ok; } case SOL_NODAL: { const Element2d & el = (*mesh)[selnr]; double lami[8]; int np, i; val = 0; double lam3 = 1-lam1-lam2; switch (el.GetType()) { case TRIG: /* lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; */ lami[0] = lam1; lami[1] = lam2; lami[2] = lam3; np = 3; break; case TRIG6: /* lami[0] = lam3*(2*lam3-1); lami[1] = lam1*(2*lam1-1); lami[2] = lam2*(2*lam2-1); */ // hierarchical basis: lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; case QUAD: case QUAD6: case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; lami[3] = (1-lam1) * lam2; np = 4; break; default: np = 0; } for (i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { int el1, el2; mesh->GetTopology().GetSurface2VolumeElement (selnr+1, el1, el2); el1--; val = data->data[el1 * data->dist+comp-1]; return 1; } case SOL_NONCONTINUOUS: { val = 0; // ????? return 0; } case SOL_SURFACE_ELEMENT: { val = data->data[selnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_NONCONTINUOUS: { const Element2d & el = (*mesh)[selnr]; double lami[8] = { 0.0 }; int np = 0; val = 0; int order = data->order; switch (order) { case 0: return data->data[selnr * data->dist + comp-1]; case 1: { switch (el.GetType()) { case TRIG: case TRIG6: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } default: cerr << "case not impl 234234" << endl; } break; } case 2: { switch (el.GetType()) { case TRIG: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } case TRIG6: { double lam3 = 1-lam1-lam2; lami[1] = 2*lam1 * (lam1-0.5); lami[2] = 2*lam2 * (lam2-0.5); lami[0] = 2*lam3 * (lam3-0.5); lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; } default: cerr << "case not implented 3234" << endl; } break; } } int base; if (order == 1) base = 4 * selnr; else base = 9 * selnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { val = (*mesh)[selnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { val = (*mesh)[selnr].GetOrder(); return 1; } } return 0; } Vec<3> VisualSceneSolution :: GetDeformation (ElementIndex elnr, const Point<3> & p) const { Vec<3> def; if (deform && vecfunction != -1) { GetValues (soldata[vecfunction], elnr, p(0), p(1), p(2), &def(0)); def *= scaledeform; if (soldata[vecfunction]->components == 2) def(2) = 0; } else def = 0; return def; } Vec<3> VisualSceneSolution :: GetSurfDeformation (SurfaceElementIndex elnr, int facetnr, double lam1, double lam2) const { shared_ptr mesh = GetMesh(); Vec<3> def; if (deform && vecfunction != -1) { // GetSurfValues (soldata[vecfunction], elnr, facetnr, lam1, lam2, &def(0)); double values[6]; GetSurfValues (soldata[vecfunction], elnr, facetnr, lam1, lam2, values); def = RealVec3d (values, soldata[vecfunction]->iscomplex, imag_part); def *= scaledeform; if (soldata[vecfunction]->components == 2) def(2) = 0; } else if (deform && scalfunction != -1 && mesh->GetDimension()==2) { // he: allow for 3d plots of 2d surfaces: usage: turn deformation on def = 0; GetSurfValue (soldata[scalfunction], elnr, facetnr, lam1, lam2, scalcomp, def(2)); def *= scaledeform; } else def = 0; return def; } void VisualSceneSolution :: GetPointDeformation (int pnum, Point<3> & p, SurfaceElementIndex elnr) const { shared_ptr mesh = GetMesh(); p = mesh->Point (pnum+1); if (deform && vecfunction != -1) { const SolData * vsol = soldata[vecfunction]; Vec<3> v(0,0,0); if (vsol->soltype == SOL_NODAL) { v = Vec3d(vsol->data[pnum * vsol->dist], vsol->data[pnum * vsol->dist+1], vsol->data[pnum * vsol->dist+2]); } else if (vsol->soltype == SOL_SURFACE_NONCONTINUOUS) { const Element2d & el = (*mesh)[elnr]; for (int j = 0; j < el.GetNP(); j++) if (el[j] == pnum+1) { int base = (4*elnr+j-1) * vsol->dist; v = Vec3d(vsol->data[base], vsol->data[base+1], vsol->data[base+2]); } } if (vsol->dist == 2) v(2) = 0; v *= scaledeform; p += v; } } void VisualSceneSolution :: GetClippingPlaneTrigs (Array & trigs, Array & pts) { shared_ptr mesh = GetMesh(); // static int timer_vals = NgProfiler::CreateTimer ("ClipPlaneTrigs - vertex values"); static int timer1 = NgProfiler::CreateTimer ("ClipPlaneTrigs1"); // static int timer1a = NgProfiler::CreateTimer ("ClipPlaneTrigs1a"); // static int timer2 = NgProfiler::CreateTimer ("ClipPlaneTrigs2"); // static int timer3 = NgProfiler::CreateTimer ("ClipPlaneTrigs3"); // static int timer4 = NgProfiler::CreateTimer ("ClipPlaneTrigs4"); // static int timer4b = NgProfiler::CreateTimer ("ClipPlaneTrigs4b"); NgProfiler::RegionTimer reg1 (timer1); int ne = mesh->GetNE(); const int edgei[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; double edgelam[6]; // Point<3> edgep[6]; double nodevali[4]; int cntce; int cpe1 = 0, cpe2 = 0, cpe3 = 0; // Array loctets; // Array loctetsloc; // Array > pointsloc; int n = 1 << subdivisions; int n3 = (n+1)*(n+1)*(n+1); Array > grid(n3); Array > locgrid(n3); Array > trans(n3); Array val(n3); Array locposval(n3); Array compress(n3); // NgProfiler::StartTimer (timer_vals); Array vertval(mesh->GetNP()); Array posval(mesh->GetNP()); for (PointIndex pi = vertval.Begin(); pi < vertval.End(); pi++) { Point<3> vert = (*mesh)[pi]; vertval[pi] = vert(0) * clipplane[0] + vert(1) * clipplane[1] + vert(2) * clipplane[2] + clipplane[3]; posval[pi] = vertval[pi] > 0; } // NgProfiler::StopTimer (timer_vals); INDEX_2_CLOSED_HASHTABLE edges(8*n3); // point nr of edge for (ElementIndex ei = 0; ei < ne; ei++) { // NgProfiler::RegionTimer reg1a (timer1a); int first_point_of_element = pts.Size(); locgrid.SetSize(n3); if(vispar.clipdomain > 0 && vispar.clipdomain != (*mesh)[ei].GetIndex()) continue; if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue; ELEMENT_TYPE type = (*mesh)[ei].GetType(); if (type == HEX || type == PRISM || type == TET || type == TET10 || type == PYRAMID || type == PYRAMID13 || type == PRISM15 || type == HEX20) { const Element & el = (*mesh)[ei]; int ii = 0; int cnt_valid = 0; // NgProfiler::StartTimer (timer2); if (!mesh->GetCurvedElements().IsElementHighOrder(ei)) { bool has_pos = 0, has_neg = 0; for (int i = 0; i < el.GetNP(); i++) if (posval[el[i]]) has_pos = 1; else has_neg = 1; if (!has_pos || !has_neg) { // NgProfiler::StopTimer (timer2); continue; } } if (type == TET || type == TET10) { for (int ix = 0; ix <= n; ix++) for (int iy = 0; iy <= n; iy++) for (int iz = 0; iz <= n; iz++, ii++) { if (ix+iy+iz <= n) { compress[ii] = cnt_valid; locgrid[cnt_valid] = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); cnt_valid++; } else compress[ii] = -1; } } else for (int ix = 0; ix <= n; ix++) for (int iy = 0; iy <= n; iy++) for (int iz = 0; iz <= n; iz++, ii++) { Point<3> ploc; compress[ii] = ii; switch (type) { case PRISM: case PRISM12: case PRISM15: if (ix+iy <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); compress[ii] = cnt_valid; cnt_valid++; } else compress[ii] = -1; break; case HEX: case HEX20: ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); break; case PYRAMID: case PYRAMID13: ploc = Point<3> (double(ix) / n * (1-double(iz)/n), double(iy) / n * (1-double(iz)/n), double(iz)/n); if (iz == n) ploc = Point<3> (0,0,1-1e-8); break; default: cerr << "clip plane trigs not implemented" << endl; ploc = Point<3> (0,0,0); } if (compress[ii] != -1) locgrid[compress[ii]] = ploc; } if (type != TET && type != TET10 && type != PRISM && type != PRISM12 && type != PRISM15) cnt_valid = n3; locgrid.SetSize(cnt_valid); // NgProfiler::StopTimer (timer2); // NgProfiler::RegionTimer reg4(timer4); if (mesh->GetCurvedElements().IsHighOrder()) { // NgProfiler::RegionTimer reg4(timer4); mesh->GetCurvedElements(). CalcMultiPointElementTransformation (&locgrid, ei, &grid, 0); } else { // NgProfiler::RegionTimer reg4(timer4b); Vector shape(el.GetNP()); MatrixFixWidth<3> pointmat(el.GetNP()); for (int k = 0; k < el.GetNP(); k++) for (int j = 0; j < 3; j++) pointmat(k,j) = (*mesh)[el[k]](j); for (int i = 0; i < cnt_valid; i++) { el.GetShapeNew (locgrid[i], shape); Point<3> pglob; for (int j = 0; j < 3; j++) { pglob(j) = 0; for (int k = 0; k < el.GetNP(); k++) pglob(j) += shape(k) * pointmat(k,j); } grid[i] = pglob; } } // NgProfiler::RegionTimer reg3(timer3); bool has_pos = false, all_pos = true; for (int i = 0; i < cnt_valid; i++) { val[i] = grid[i](0) * clipplane[0] + grid[i](1) * clipplane[1] + grid[i](2) * clipplane[2] + clipplane[3]; locposval[i] = val[i] > 0; has_pos |= locposval[i]; all_pos &= locposval[i]; // if (val[i] > 0) has_pos = 1; else has_neg = 1; } // if (!has_pos || !has_neg) continue; if (!has_pos || all_pos) continue; edges.DeleteData(); for (int ix = 0; ix < n; ix++) for (int iy = 0; iy < n; iy++) for (int iz = 0; iz < n; iz++) { int base = iz + (n+1)*iy + (n+1)*(n+1)*ix; int pi[8] = { base, base+(n+1)*(n+1), base+(n+1)*(n+1)+(n+1), base+(n+1), base+1, base+(n+1)*(n+1)+1, base+(n+1)*(n+1)+(n+1)+1, base+(n+1)+1 }; for (int j = 0; j < 8; j++) pi[j] = compress[pi[j]]; bool has_pos = false, all_pos = true; for (int j = 0; j < 8; j++) if (pi[j] != -1) { has_pos |= locposval[pi[j]]; all_pos &= locposval[pi[j]]; } if (!has_pos || all_pos) continue; const int tets[6][4] = { { 1, 2, 4, 5 }, { 4, 5, 2, 8 }, { 2, 8, 5, 6 }, { 2, 3, 4, 8 }, { 2, 3, 8, 6 }, { 3, 8, 6, 7 } }; for (int ii = 0; ii < 6; ii++) { int teti[4]; for (int k = 0; k < 4; k++) teti[k] = pi[tets[ii][k]-1]; bool is_valid = true; for (int j = 0; j < 4; j++) is_valid &= (teti[j] != -1); if (!is_valid) continue; bool has_pos = false, all_pos = true; for (int j = 0; j < 4; j++) { has_pos |= locposval[teti[j]]; all_pos &= locposval[teti[j]]; } if (!has_pos || all_pos) continue; for (int j = 0; j < 4; j++) nodevali[j] = val[teti[j]]; cntce = 0; for (int j = 0; j < 6; j++) { int lpi1 = edgei[j][0]; int lpi2 = edgei[j][1]; if ( (nodevali[lpi1] > 0) != (nodevali[lpi2] > 0) ) { cntce++; cpe3 = cpe2; cpe2 = cpe1; cpe1 = j; if (cntce >= 3) { ClipPlaneTrig cpt; cpt.elnr = ei; for (int k = 0; k < 3; k++) { int ednr; switch (k) { case 0: ednr = cpe1; break; case 1: ednr = cpe2; break; case 2: ednr = cpe3; break; } int pi1 = edgei[ednr][0]; int pi2 = edgei[ednr][1]; int pnr = -1; INDEX_2 pair (teti[pi1], teti[pi2]); pair.Sort(); if (edges.Used(pair)) pnr = edges.Get(pair); else { ClipPlanePoint cppt; cppt.elnr = ei; edgelam[ednr] = nodevali[pi2] / (nodevali[pi2] - nodevali[pi1]); Point<3> gp1 = grid[teti[pi1]]; Point<3> gp2 = grid[teti[pi2]]; cppt.p = gp2 + edgelam[ednr] * (gp1-gp2); Point<3> p1 = locgrid[teti[pi1]]; Point<3> p2 = locgrid[teti[pi2]]; cppt.lami = p2 + edgelam[ednr] * (p1-p2); pts.Append (cppt); pnr = pts.Size()-1; edges.Set (pair, pnr); } cpt.points[k].pnr = pnr; cpt.points[k].locpnr = pnr-first_point_of_element; } trigs.Append (cpt); } } } } } } else { // other elements not supported (JS, June 2007) continue; // return; } } } void VisualSceneSolution :: GetClippingPlaneGrid (Array & pts) { shared_ptr mesh = GetMesh(); Vec3d n(clipplane[0], clipplane[1], clipplane[2]); double mu = -clipplane[3] / n.Length2(); Point3d p(mu*n.X(), mu * n.Y(), mu * n.Z()); // n /= n.Length(); n.Normalize(); Vec3d t1, t2; n.GetNormal (t1); t2 = Cross (n, t1); double xi1, xi2; double xi1mid = (center - p) * t1; double xi2mid = (center - p) * t2; pts.SetSize(0); for (xi1 = xi1mid-rad+xoffset/gridsize; xi1 <= xi1mid+rad+xoffset/gridsize; xi1 += rad / gridsize) for (xi2 = xi2mid-rad+yoffset/gridsize; xi2 <= xi2mid+rad+yoffset/gridsize; xi2 += rad / gridsize) { Point3d hp = p + xi1 * t1 + xi2 * t2; int cindex(-1); bool allowindex(true); if(vispar.clipdomain > 0) { cindex = vispar.clipdomain; } else if(vispar.donotclipdomain > 0) { allowindex = false; cindex = vispar.donotclipdomain; } double lami[3]; int elnr = mesh->GetElementOfPoint (hp, lami,0,cindex,allowindex)-1; if (elnr != -1) { ClipPlanePoint cpp; cpp.p = hp; cpp.elnr = elnr; cpp.lami(0) = lami[0]; cpp.lami(1) = lami[1]; cpp.lami(2) = lami[2]; pts.Append (cpp); } } }; void VisualSceneSolution :: DrawClipPlaneTrigs () { shared_ptr mesh = GetMesh(); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); Array parlists (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("clipplanetrigs"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (parlists[dest], dest, MPI_TAG_VIS); if (clipplanelist_scal) glDeleteLists (clipplanelist_scal, 1); clipplanelist_scal = glGenLists (1); glNewList (clipplanelist_scal, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (parlists[dest]); glEndList(); return; } #endif if (clipplanelist_scal) glDeleteLists (clipplanelist_scal, 1); clipplanelist_scal = glGenLists (1); glNewList (clipplanelist_scal, GL_COMPILE); Array trigs; Array points; GetClippingPlaneTrigs (trigs, points); glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); glColor3d (1.0, 1.0, 1.0); SetTextureMode (usetexture); SolData * sol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; if (sol -> draw_volume) { glBegin (GL_TRIANGLES); int maxlpnr = 0; for (int i = 0; i < trigs.Size(); i++) for (int j = 0; j < 3; j++) maxlpnr = max2 (maxlpnr, trigs[i].points[j].locpnr); Array vals(maxlpnr+1); Array > valsc(maxlpnr+1); Array elnrs(maxlpnr+1); Array trigok(maxlpnr+1); Array > locpoints(maxlpnr+1); Array > globpoints(maxlpnr+1); Array > jacobi(maxlpnr+1); Array mvalues( (maxlpnr+1) * sol->components); trigok = false; elnrs = -1; Point<3> p[3]; // double val[3]; // complex valc[3]; int lastelnr = -1; int nlp = -1; bool ok = false; for (int i = 0; i < trigs.Size(); i++) { const ClipPlaneTrig & trig = trigs[i]; if (trig.elnr != lastelnr) { lastelnr = trig.elnr; nlp = -1; for (int ii = i; ii < trigs.Size(); ii++) { if (trigs[ii].elnr != trig.elnr) break; for (int j = 0; j < 3; j++) nlp = max (nlp, trigs[ii].points[j].locpnr); } nlp++; locpoints.SetSize (nlp); for (int ii = i; ii < trigs.Size(); ii++) { if (trigs[ii].elnr != trig.elnr) break; for (int j = 0; j < 3; j++) locpoints[trigs[ii].points[j].locpnr] = points[trigs[ii].points[j].pnr].lami; } mesh->GetCurvedElements(). CalcMultiPointElementTransformation (&locpoints, trig.elnr, &globpoints, &jacobi); bool drawelem = GetMultiValues (sol, trig.elnr, -1, nlp, &locpoints[0](0), &locpoints[1](0)-&locpoints[0](0), &globpoints[0](0), &globpoints[1](0)-&globpoints[0](0), &jacobi[0](0), &jacobi[1](0)-&jacobi[0](0), &mvalues[0], sol->components); // cout << "have multivalues, comps = " << sol->components << endl; // if (!drawelem) ok = false; ok = drawelem; if (usetexture != 2 || !sol->iscomplex) for (int ii = 0; ii < nlp; ii++) vals[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < nlp; ii++) valsc[ii] = complex (mvalues[ii*sol->components + scalcomp-1], mvalues[ii*sol->components + scalcomp]); } if(ok) for(int j=0; j<3; j++) { if (usetexture != 2 || !sol->iscomplex) SetOpenGlColor (vals[trig.points[j].locpnr]); else glTexCoord2f ( valsc[trig.points[j].locpnr].real(), valsc[trig.points[j].locpnr].imag() ); p[j] = points[trig.points[j].pnr].p; if (deform) { Point<3> ploc = points[trig.points[j].pnr].lami; p[j] += GetDeformation (trig.elnr, ploc); } glVertex3dv (p[j]); } } glEnd(); } glEndList (); #ifdef PARALLELGL glFinish(); if (id > 0) MyMPI_Send (clipplanelist_scal, 0, MPI_TAG_VIS); #endif } void VisualSceneSolution :: SetOpenGlColor(double val) { if (usetexture == 1 && !logscale) { glTexCoord1f ( val ); return; } double valmin = minval; double valmax = maxval; double value; if (!logscale) value = (val - valmin) / (valmax - valmin); else { if (valmax <= 0) valmax = 1; if (valmin <= 0) valmin = 1e-4 * valmax; value = (log(fabs(val)) - log(valmin)) / (log(valmax) - log(valmin)); } if (!invcolor) value = 1 - value; if (value > 1) value = 1; if (value < 0) value = 0; value *= 4; static const double colp[][3] = { { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 0, 0 }, }; int i = int(value); double r = value - i; GLdouble col[3]; for (int j = 0; j < 3; j++) col[j] = (1-r) * colp[i][j] + r * colp[i+1][j]; glColor3dv (col); } void VisualSceneSolution :: SetTextureMode (int texturemode) const { switch (texturemode) { case 0: glDisable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_2D); break; case 1: glEnable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_2D); glColor3d (1.0, 1.0, 1.0); break; case 2: glDisable (GL_TEXTURE_1D); glEnable (GL_TEXTURE_2D); glColor3d (1.0, 1.0, 1.0); break; } } void VisualSceneSolution :: DrawCone (const Point<3> & p1, const Point<3> & p2, double r) { int n = 10, i; Vec<3> p1p2 = p2 - p1; p1p2.Normalize(); Vec<3> p2p1 = -p1p2; Vec<3> t1 = p1p2.GetNormal(); Vec<3> t2 = Cross (p1p2, t1); Point<3> oldp = p1 + r * t1; Vec<3> oldn = t1; Point<3> p; Vec<3> normal; Mat<2> rotmat; Vec<2> cs, newcs; cs(0) = 1; cs(1) = 0; rotmat(0,0) = rotmat(1,1) = cos(2*M_PI/n); rotmat(1,0) = sin(2*M_PI/n); rotmat(0,1) = -rotmat(1,0); glBegin (GL_TRIANGLES); for (i = 1; i <= n; i++) { /* phi = 2 * M_PI * i / n; normal = cos(phi) * t1 + sin(phi) * t2; */ newcs = rotmat * cs; cs = newcs; normal = cs(0) * t1 + cs(1) * t2; p = p1 + r * normal; // cone glNormal3dv (normal); glVertex3dv (p); glVertex3dv (p2); glNormal3dv (oldn); glVertex3dv (oldp); // base-circle glNormal3dv (p2p1); glVertex3dv (p); glVertex3dv (p1); glVertex3dv (oldp); oldp = p; oldn = normal; } glEnd (); } void VisualSceneSolution :: DrawCylinder (const Point<3> & p1, const Point<3> & p2, double r) { int n = 10, i; Vec<3> p1p2 = p2 - p1; p1p2.Normalize(); // Vec<3> p2p1 = -p1p2; Vec<3> t1 = p1p2.GetNormal(); Vec<3> t2 = Cross (p1p2, t1); Point<3> oldhp1 = p1 + r * t1; Point<3> oldhp2 = p2 + r * t1; Vec<3> oldn = t1; Point<3> hp1, hp2; Vec<3> normal; Mat<2> rotmat; Vec<2> cs, newcs; cs(0) = 1; cs(1) = 0; rotmat(0,0) = rotmat(1,1) = cos(2*M_PI/n); rotmat(1,0) = sin(2*M_PI/n); rotmat(0,1) = -rotmat(1,0); glBegin (GL_QUADS); for (i = 1; i <= n; i++) { newcs = rotmat * cs; cs = newcs; normal = cs(0) * t1 + cs(1) * t2; hp1 = p1 + r * normal; hp2 = p2 + r * normal; // cylinder glNormal3dv (normal); glVertex3dv (hp1); glVertex3dv (hp2); glVertex3dv (oldhp2); glVertex3dv (oldhp1); oldhp1 = hp1; oldhp2 = hp2; oldn = normal; } glEnd (); } void VisualSceneSolution :: MouseDblClick (int px, int py) { vsmesh.SetClippingPlane(); // vsmesh.BuildFilledList(); vsmesh.MouseDblClick(px,py); } #ifdef PARALLELGL void VisualSceneSolution :: Broadcast () { MPI_Datatype type; int blocklen[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1 }; MPI_Aint displ[] = { (char*)&usetexture - (char*)this, (char*)&clipsolution - (char*)this, (char*)&scalfunction - (char*)this, (char*)&scalcomp - (char*)this, (char*)&vecfunction - (char*)this, (char*)&gridsize - (char*)this, (char*)&autoscale - (char*)this, (char*)&logscale - (char*)this, (char*)&minval - (char*)this, (char*)&maxval - (char*)this, (char*)&numisolines - (char*)this, (char*)&subdivisions - (char*)this, (char*)&evalfunc - (char*)this, (char*)&clipplane[0] - (char*)this, (char*)&multidimcomponent - (char*)this, (char*)&deform - (char*)this, (char*)&scaledeform - (char*)this }; MPI_Datatype types[] = { MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_DOUBLE, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_INT, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_DOUBLE }; MPI_Type_create_struct (17, blocklen, displ, types, &type); MPI_Type_commit ( &type ); MPI_Bcast (this, 1, type, 0, MPI_COMM_WORLD); MPI_Type_free (&type); } #endif } #include "../include/nginterface.h" void Ng_ClearSolutionData () { #ifdef OPENGL // if (nodisplay) return; // netgen::vssolution.ClearSolutionData(); netgen::GetVSSolution().ClearSolutionData(); #endif } void Ng_InitSolutionData (Ng_SolutionData * soldata) { // soldata -> name = NULL; soldata -> data = NULL; soldata -> components = 1; soldata -> dist = 1; soldata -> order = 1; soldata -> iscomplex = 0; soldata -> draw_surface = 1; soldata -> draw_volume = 1; soldata -> soltype = NG_SOLUTION_NODAL; soldata -> solclass = 0; } void Ng_SetSolutionData (Ng_SolutionData * soldata) { #ifdef OPENGL // if (nodisplay) return; // vssolution.ClearSolutionData (); netgen::VisualSceneSolution::SolData * vss = new netgen::VisualSceneSolution::SolData; // vss->name = new char[strlen (soldata->name)+1]; // strcpy (vss->name, soldata->name); vss->name = soldata->name; vss->data = soldata->data; vss->components = soldata->components; vss->dist = soldata->dist; vss->order = soldata->order; vss->iscomplex = bool(soldata->iscomplex); vss->draw_surface = soldata->draw_surface; vss->draw_volume = soldata->draw_volume; vss->soltype = netgen::VisualSceneSolution::SolType (soldata->soltype); vss->solclass = soldata->solclass; // netgen::vssolution.AddSolutionData (vss); netgen::GetVSSolution().AddSolutionData (vss); #endif } namespace netgen { extern void Render (bool blocking); } void Ng_Redraw (bool blocking) { #ifdef OPENGL //netgen::vssolution.UpdateSolutionTimeStamp(); netgen::GetVSSolution().UpdateSolutionTimeStamp(); netgen::Render(blocking); #endif } #ifdef OPENGL #ifdef WIN32 void (*glBindBuffer) (GLenum a, GLuint b); void (*glDeleteBuffers) (GLsizei a, const GLuint *b); void (*glGenBuffers) (GLsizei a, GLuint *b); void (*glBufferData) (GLenum a, GLsizeiptr b, const GLvoid *c, GLenum d); void (*glBufferSubData) (GLenum a, GLintptr b, GLsizeiptr c, const GLvoid *d); DLL_HEADER void LoadOpenGLFunctionPointers() { #ifdef USE_BUFFERS glBindBuffer = (decltype(glBindBuffer)) wglGetProcAddress("glBindBuffer"); glBufferSubData = (decltype(glBufferSubData)) wglGetProcAddress("glBufferSubData"); glBufferData = (decltype(glBufferData)) wglGetProcAddress("glBufferData"); glDeleteBuffers = (decltype(glDeleteBuffers)) wglGetProcAddress("glDeleteBuffers"); glGenBuffers = (decltype(glGenBuffers)) wglGetProcAddress("glGenBuffers"); if(!glBindBuffer) throw std::runtime_error("Could not load OpenGL functions!"); #endif } #else // WIN32 DLL_HEADER void LoadOpenGLFunctionPointers() { } #endif // WIN32 #endif // OPENGL netgen-6.2.1905/libsrc/visualization/visual_dummy.cpp0000644000175000017500000000042613504650527021404 0ustar kurtkurt#include #include #include "../include/nginterface.h" void Ng_ClearSolutionData () { ; } void Ng_InitSolutionData (Ng_SolutionData * soldata) { ; } void Ng_SetSolutionData (Ng_SolutionData * soldata) { ; } void Ng_Redraw (bool blocking) { ; } netgen-6.2.1905/libsrc/visualization/vsfieldlines.cpp0000644000175000017500000004305713504650527021364 0ustar kurtkurt#ifndef NOTCL #include #include #include #include #include #include #include namespace netgen { // extern shared_ptr mesh; RKStepper :: ~RKStepper() { delete a; } RKStepper :: RKStepper(int type) : a(NULL), tolerance(1e100) { notrestarted = 0; if (type == 0) // explicit Euler { c.SetSize(1); c[0] = 0; b.SetSize(1); b[0] = 1; steps = order = 1; } else if (type == 1) // Euler-Cauchy { c.SetSize(2); c[0] = 0; c[1] = 0.5; b.SetSize(2); b[0] = 0; b[1] = 1; Array size(2); size[0] = 0; size[1] = 1; a = new TABLE(size); a->Set(2,1,0.5); // Set, Get: 1-based! steps = order = 2; } else if (type == 2) // Simpson { c.SetSize(3); c[0] = 0; c[1] = 1; c[2] = 0.5; b.SetSize(3); b[0] = b[1] = 1./6.; b[2] = 2./3.; Array size(3); size[0] = 0; size[1] = 1; size[2] = 2; a = new TABLE(size); a->Set(2,1,1); a->Set(3,1,0.25); a->Set(3,2,0.25); steps = order = 3; } else if (type == 3) // classical Runge-Kutta { c.SetSize(4); c[0] = 0; c[1] = c[2] = 0.5; c[3] = 1; b.SetSize(4); b[0] = b[3] = 1./6.; b[1] = b[2] = 1./3.; Array size(4); size[0] = 0; size[1] = 1; size[2] = 2; size[3] = 3; a = new TABLE(size); a->Set(2,1,0.5); a->Set(3,1,0); a->Set(3,2,0.5); a->Set(4,1,0); a->Set(4,2,0); a->Set(4,3,1); steps = order = 4; } K.SetSize(steps); } void RKStepper :: StartNextValCalc(const Point3d & astartval, const double astartt, const double ah, const bool aadaptive) { //cout << "Starting RK-Step with h=" << ah << endl; stepcount = 0; h = ah; startt = astartt; startval = astartval; adaptive = aadaptive; adrun = 0; } bool RKStepper :: GetNextData(Point3d & val, double & t, double & ah) { bool finished(false); //cout << "stepcount " << stepcount << endl; if(stepcount <= steps) { t = startt + c[stepcount-1]*h; val = startval; for(int i=0; iGet(stepcount,i+1) * K[i]; } if(stepcount == steps) { val = startval; for(int i=0; i 1.3) fac = 1.3; if(fac < 1 || notrestarted >= 2) ah = 2.*h * fac; if(err < tolerance) { finished = true; notrestarted++; //(*testout) << "finished RK-Step, new h=" << ah << " tolerance " << tolerance << " err " << err << endl; } else { //ah *= 0.9; notrestarted = 0; //(*testout) << "restarting h " << 2.*h << " ah " << ah << " tolerance " << tolerance << " err " << err << endl; StartNextValCalc(startval_bak,startt_bak, ah, adaptive); } } } else { t = startt + h; finished = true; } } if(stepcount == 0) { t = startt + c[stepcount]*h; val = startval; for(int i=0; iGet(stepcount,i) * K[i]; } return finished; } bool RKStepper :: FeedNextF(const Vec3d & f) { K[stepcount] = f; stepcount++; return true; } void FieldLineCalc :: GenerateFieldLines(Array & potential_startpoints, const int numlines, const int gllist, const double minval, const double maxval, const int logscale, double phaser, double phasei) { Array points; Array values; Array drawelems; Array dirstart; if(vsol -> iscomplex) SetPhase(phaser,phasei); double crit = 1.0; if(randomized) { double sum = 0; double lami[3]; double values[6]; Vec3d v; for(int i=0; iiscomplex, phaser, phasei); sum += v.Length(); } crit = sum/double(numlines); } int calculated = 0; cout << endl; for(int i=0; i= numlines) break; Calc(potential_startpoints[i],points,values,drawelems,dirstart); bool usable = false; for(int j=1; j 0) ? rel_length : 0.5; maxlength *= 2.*rad; thickness = (rel_thickness > 0) ? rel_thickness : 0.0015; thickness *= 2.*rad; double auxtolerance = (rel_tolerance > 0) ? rel_tolerance : 1.5e-3; auxtolerance *= 2.*rad; stepper.SetTolerance(auxtolerance); direction = adirection; maxpoints = amaxpoints; if(direction == 0) { maxlength *= 0.5; maxpoints /= 2; } phaser = 1; phasei = 0; critical_value = -1; randomized = false; } void FieldLineCalc :: Calc(const Point3d & startpoint, Array & points, Array & vals, Array & drawelems, Array & dirstart) { double lami[3], startlami[3]; double values[6]; double dummyt(0); Vec3d v; Vec3d startv; Point3d newp; double h; double startval; bool startdraw; bool drawelem = false; int elnr; for (int i=0; i<6; i++) values[i]=0.0; for (int i=0; i<3; i++) lami[i]=0.0; for (int i=0; i<3; i++) startlami[i]=0.0; points.SetSize(0); vals.SetSize(0); drawelems.SetSize(0); dirstart.SetSize(0); dirstart.Append(0); int startelnr = mesh.GetElementOfPoint(startpoint,startlami,true) - 1; (*testout) << "p = " << startpoint << "; elnr = " << startelnr << endl; if (startelnr == -1) return; mesh.SetPointSearchStartElement(startelnr); if (mesh.GetDimension()==3) startdraw = vss.GetValues ( vsol, startelnr, startlami[0], startlami[1], startlami[2], values); else startdraw = vss.GetSurfValues ( vsol, startelnr, -1, startlami[0], startlami[1], values); VisualSceneSolution::RealVec3d ( values, startv, vsol->iscomplex, phaser, phasei); startval = startv.Length(); if(critical_value > 0 && fabs(startval) < critical_value) return; //cout << "p = " << startpoint << "; elnr = " << startelnr << endl; for(int dir = 1; dir >= -1; dir -= 2) { if(dir*direction < 0) continue; points.Append(startpoint); vals.Append(startval); drawelems.Append(startdraw); h = 0.001*rad/startval; // otherwise no nice lines; should be made accessible from outside v = startv; if(dir == -1) v *= -1.; elnr = startelnr; lami[0] = startlami[0]; lami[1] = startlami[1]; lami[2] = startlami[2]; for(double length = 0; length < maxlength; length += h*vals.Last()) { if(v.Length() < 1e-12*rad) { (*testout) << "Current fieldlinecalculation came to a stillstand at " << points.Last() << endl; break; } stepper.StartNextValCalc(points.Last(),dummyt,h,true); stepper.FeedNextF(v); while(!stepper.GetNextData(newp,dummyt,h) && elnr != -1) { elnr = mesh.GetElementOfPoint(newp,lami,true) - 1; if(elnr != -1) { mesh.SetPointSearchStartElement(elnr); if (mesh.GetDimension()==3) drawelem = vss.GetValues (vsol, elnr, lami[0], lami[1], lami[2], values); else drawelem = vss.GetSurfValues (vsol, elnr, -1, lami[0], lami[1], values); VisualSceneSolution::RealVec3d (values, v, vsol->iscomplex, phaser, phasei); if(dir == -1) v *= -1.; stepper.FeedNextF(v); } } if (elnr == -1) { //cout << "direction " < 1) (*testout) << "Points in current fieldline: " << points.Size() << ", current position: " << newp << endl; if(maxpoints > 0 && points.Size() >= maxpoints) { break; } //cout << "length " << length << " h " << h << " vals.Last() " << vals.Last() << " maxlength " << maxlength << endl; } dirstart.Append(points.Size()); } } void VisualSceneSolution :: BuildFieldLinesFromBox(Array & startpoints) { shared_ptr mesh = GetMesh(); if (!mesh) return; if(fieldlines_startarea_parameter[0] > fieldlines_startarea_parameter[3] || fieldlines_startarea_parameter[1] > fieldlines_startarea_parameter[4] || fieldlines_startarea_parameter[2] > fieldlines_startarea_parameter[5]) { Point3d pmin, pmax; mesh->GetBox (pmin, pmax); fieldlines_startarea_parameter[0] = pmin.X(); fieldlines_startarea_parameter[1] = pmin.Y(); fieldlines_startarea_parameter[2] = pmin.Z(); fieldlines_startarea_parameter[3] = pmax.X(); fieldlines_startarea_parameter[4] = pmax.Y(); fieldlines_startarea_parameter[5] = pmax.Z(); } for (int i = 1; i <= startpoints.Size(); i++) { Point3d p (fieldlines_startarea_parameter[0] + double (rand()) / RAND_MAX * (fieldlines_startarea_parameter[3]-fieldlines_startarea_parameter[0]), fieldlines_startarea_parameter[1] + double (rand()) / RAND_MAX * (fieldlines_startarea_parameter[4]-fieldlines_startarea_parameter[1]), fieldlines_startarea_parameter[2] + double (rand()) / RAND_MAX * (fieldlines_startarea_parameter[5]-fieldlines_startarea_parameter[2])); startpoints[i-1] = p; } } void VisualSceneSolution :: BuildFieldLinesFromLine(Array & startpoints) { shared_ptr mesh = GetMesh(); if (!mesh) return; for (int i = 1; i <= startpoints.Size(); i++) { double s = double (rand()) / RAND_MAX; Point3d p (fieldlines_startarea_parameter[0] + s * (fieldlines_startarea_parameter[3]-fieldlines_startarea_parameter[0]), fieldlines_startarea_parameter[1] + s * (fieldlines_startarea_parameter[4]-fieldlines_startarea_parameter[1]), fieldlines_startarea_parameter[2] + s * (fieldlines_startarea_parameter[5]-fieldlines_startarea_parameter[2])); startpoints[i-1] = p; } } void VisualSceneSolution :: BuildFieldLinesFromFile(Array & startpoints) { shared_ptr mesh = GetMesh(); if (!mesh) return; ifstream * infile; infile = new ifstream(fieldlines_filename.c_str()); //cout << "reading from file " << fieldlines_filename << endl; int numpoints = 0; string keyword; double dparam; int iparam; while(infile->good()) { (*infile) >> keyword; if(keyword == "point") numpoints++; else if(keyword == "line" || keyword == "box") { for(int i=0; i<6; i++) (*infile) >> dparam; (*infile) >> iparam; numpoints += iparam; } } delete infile; //cout << numpoints << " startpoints" << endl; startpoints.SetSize(numpoints); infile = new ifstream(fieldlines_filename.c_str()); numpoints = 0; while(infile->good()) { (*infile) >> keyword; if (keyword == "point") { (*infile) >> startpoints[numpoints].X(); (*infile) >> startpoints[numpoints].Y(); (*infile) >> startpoints[numpoints].Z(); numpoints++; } else if (keyword == "line" || keyword == "box") { for(int i=0; i<6; i++) (*infile) >> fieldlines_startarea_parameter[i]; (*infile) >> iparam; Array auxpoints(iparam); if (keyword == "box") BuildFieldLinesFromBox(auxpoints); else if (keyword == "line") BuildFieldLinesFromLine(auxpoints); for(int i=0; i & startpoints) { shared_ptr mesh = GetMesh(); if (!mesh) return; Array elements_2d; //cout << "fieldlines_startface " << fieldlines_startface << endl; mesh->GetSurfaceElementsOfFace(fieldlines_startface,elements_2d); if(elements_2d.Size() == 0) { cerr << "No Elements on selected face (?)" << endl; return; } Vec3d v1,v2,cross; double area = 0; int i; for(i=0; iSurfaceElement(elements_2d[i]); v1 = mesh->Point(elem[1]) - mesh->Point(elem[0]); v2 = mesh->Point(elem[2]) - mesh->Point(elem[0]); cross = Cross(v1,v2); area += cross.Length(); if(elem.GetNV() == 4) { v1 = mesh->Point(elem[2]) - mesh->Point(elem[0]); v2 = mesh->Point(elem[3]) - mesh->Point(elem[0]); cross = Cross(v1,v2); area += cross.Length(); } } int startpointsp = 0; i = 0; while(startpointsp < startpoints.Size()) { const Element2d & elem = mesh->SurfaceElement(elements_2d[i]); int numtri = (elem.GetNV() == 3) ? 1 : 2; for(int tri = 0; startpointsp < startpoints.Size() && triPoint(elem[1]) - mesh->Point(elem[0]); v2 = mesh->Point(elem[2]) - mesh->Point(elem[0]); cross = Cross(v1,v2); } else if(tri == 1) { v1 = mesh->Point(elem[2]) - mesh->Point(elem[0]); v2 = mesh->Point(elem[3]) - mesh->Point(elem[0]); cross = Cross(v1,v2); } double thisarea = cross.Length(); int numloc = int(startpoints.Size()*thisarea/area); if(double (rand()) / RAND_MAX < startpoints.Size()*thisarea/area - numloc) numloc++; for(int j=0; startpointsp < startpoints.Size() && j 1) { s = 1.-s; t = 1.-t; } startpoints[startpointsp] = mesh->Point(elem[0]) + s*v1 +t*v2; startpointsp++; } } i++; if(i == elements_2d.Size()) i = 0; } } void VisualSceneSolution :: BuildFieldLinesPlot () { shared_ptr mesh = GetMesh(); if (!mesh) return; if (fieldlinestimestamp >= solutiontimestamp) return; fieldlinestimestamp = solutiontimestamp; if (fieldlineslist) glDeleteLists (fieldlineslist, num_fieldlineslists); if (vecfunction == -1) return; const SolData * vsol = soldata[fieldlines_vecfunction]; num_fieldlineslists = (vsol -> iscomplex && !fieldlines_fixedphase) ? 100 : 1; FieldLineCalc linecalc(*mesh,*this,vsol, fieldlines_rellength,fieldlines_maxpoints,fieldlines_relthickness,fieldlines_reltolerance,fieldlines_rktype); if(fieldlines_randomstart) linecalc.Randomized(); fieldlineslist = glGenLists (num_fieldlineslists); int num_startpoints = num_fieldlines / num_fieldlineslists; if (num_fieldlines % num_fieldlineslists != 0) num_startpoints++; if(fieldlines_randomstart) num_startpoints *= 10; Array startpoints(num_startpoints); for (int ln = 0; ln < num_fieldlineslists; ln++) { if(fieldlines_startarea == 0) BuildFieldLinesFromBox(startpoints); else if(fieldlines_startarea == 1) BuildFieldLinesFromFile(startpoints); else if(fieldlines_startarea == 2) BuildFieldLinesFromFace(startpoints); double phi; if(vsol -> iscomplex) { if(fieldlines_fixedphase) phi = fieldlines_phase; else phi = 2*M_PI*ln / num_fieldlineslists; } else phi = 0; cout << "phi = " << phi << endl; double phaser = cos(phi), phasei = sin(phi); glNewList(fieldlineslist+ln, GL_COMPILE); SetTextureMode (usetexture); linecalc.GenerateFieldLines(startpoints,num_fieldlines / num_fieldlineslists+1, fieldlineslist+ln,minval,maxval,logscale,phaser,phasei); glEndList (); } } } #endif // NOTCL netgen-6.2.1905/libsrc/visualization/CMakeLists.txt0000644000175000017500000000126413504650527020723 0ustar kurtkurtadd_definitions(-DNGINTERFACE_EXPORTS) install(FILES soldata.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel ) if(USE_GUI) set( LIB_VISUAL_SOURCES meshdoc.cpp mvdraw.cpp vsfieldlines.cpp vsmesh.cpp vssolution.cpp importsolution.cpp ) else(USE_GUI) set( LIB_VISUAL_SOURCES visual_dummy.cpp ) endif(USE_GUI) add_library(visual ${NG_LIB_TYPE} ${LIB_VISUAL_SOURCES}) target_link_libraries( visual ngcore ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ) install( TARGETS visual ${NG_INSTALL_DIR}) install(FILES meshdoc.hpp mvdraw.hpp vispar.hpp visual.hpp vssolution.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/visualization COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/meshing/0000755000175000017500000000000013504650527014711 5ustar kurtkurtnetgen-6.2.1905/libsrc/meshing/delaunay.cpp0000644000175000017500000010555713504650527017234 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { static const int deltetfaces[][3] = { { 1, 2, 3 }, { 2, 0, 3 }, { 0, 1, 3 }, { 1, 0, 2 } }; class DelaunayTet { PointIndex pnums[4]; int nb[4]; public: DelaunayTet () { ; } DelaunayTet (const DelaunayTet & el) { for (int i = 0; i < 4; i++) pnums[i] = el[i]; } DelaunayTet (const Element & el) { for (int i = 0; i < 4; i++) pnums[i] = el[i]; } PointIndex & operator[] (int i) { return pnums[i]; } PointIndex operator[] (int i) const { return pnums[i]; } int & NB(int i) { return nb[i]; } int NB(int i) const { return nb[i]; } int FaceNr (INDEX_3 & face) const // which face nr is it ? { for (int i = 0; i < 3; i++) if (pnums[i] != face.I1() && pnums[i] != face.I2() && pnums[i] != face.I3()) return i; return 3; } INDEX_3 GetFace (int i) const { return INDEX_3 (pnums[deltetfaces[i][0]], pnums[deltetfaces[i][1]], pnums[deltetfaces[i][2]]); } void GetFace (int i, Element2d & face) const { // face.SetType(TRIG); face[0] = pnums[deltetfaces[i][0]]; face[1] = pnums[deltetfaces[i][1]]; face[2] = pnums[deltetfaces[i][2]]; } }; /* Table to maintain neighbour elements */ class MeshNB { // face nodes -> one element INDEX_3_CLOSED_HASHTABLE faces; // Array & tets; public: // estimated number of points MeshNB (Array & atets, int np) : faces(200), tets(atets) { ; } // add element with 4 nodes void Add (int elnr); // delete element with 4 nodes void Delete (int elnr) { DelaunayTet & el = tets.Elem(elnr); for (int i = 0; i < 4; i++) faces.Set (el.GetFace(i).Sort(), el.NB(i)); } // get neighbour of element elnr in direction fnr int GetNB (int elnr, int fnr) { return tets.Get(elnr).NB(fnr); } // void ResetFaceHT (int size) { faces.SetSize (size); } }; void MeshNB :: Add (int elnr) { DelaunayTet & el = tets.Elem(elnr); for (int i = 0; i < 4; i++) { INDEX_3 i3 = INDEX_3::Sort (el.GetFace(i)); int posnr; if (!faces.PositionCreate (i3, posnr)) { // face already in use int othertet = faces.GetData (posnr); el.NB(i) = othertet; if (othertet) { int fnr = tets.Get(othertet).FaceNr (i3); tets.Elem(othertet).NB(fnr) = elnr; } } else { faces.SetData (posnr, elnr); el.NB(i) = 0; } } } /* connected lists of cosphereical elements */ class SphereList { Array links; public: SphereList () { ; } void AddElement (int elnr) { if (elnr > links.Size()) links.Append (1); links.Elem(elnr) = elnr; } void DeleteElement (int elnr) { links.Elem(elnr) = 0; } void ConnectElement (int eli, int toi) { links.Elem (eli) = links.Get (toi); links.Elem (toi) = eli; } void GetList (int eli, Array & linked) const; }; void SphereList :: GetList (int eli, Array & linked) const { linked.SetSize (0); int pi = eli; do { if (pi <= 0 || pi > links.Size()) { cerr << "link, error " << endl; cerr << "pi = " << pi << " linked.s = " << linked.Size() << endl; exit(1); } if (linked.Size() > links.Size()) { cerr << "links have loop" << endl; exit(1); } linked.Append (pi); pi = links.Get(pi); } while (pi != eli); } void AddDelaunayPoint (PointIndex newpi, const Point3d & newp, Array & tempels, Mesh & mesh, BoxTree<3> & tettree, MeshNB & meshnb, Array > & centers, Array & radi2, Array & connected, Array & treesearch, Array & freelist, SphereList & list, IndexSet & insphere, IndexSet & closesphere) { // static Timer t("Meshing3::AddDelaunayPoint"); RegionTimer reg(t); /* find any sphere, such that newp is contained in */ DelaunayTet el; int cfelind = -1; const Point<3> * pp[4]; Point<3> pc; Point3d tpmin, tpmax; tettree.GetIntersecting (newp, newp, treesearch); double quot,minquot(1e20); for (auto jjj : treesearch) { quot = Dist2 (centers.Get(jjj), newp) / radi2.Get(jjj); if((cfelind == -1 || quot < 0.99*minquot) && quot < 1) { minquot = quot; el = tempels.Get(jjj); cfelind = jjj; if(minquot < 0.917632) break; } } if (cfelind == -1) { PrintWarning ("Delaunay, point not in any sphere"); return; } /* insphere: point is in sphere -> delete element closesphere: point is close to sphere -> considered for same center */ // save overestimate insphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP()); closesphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP()); insphere.Clear(); closesphere.Clear(); insphere.Add (cfelind); int changed = 1; int nstarti = 1, starti; while (changed) { changed = 0; starti = nstarti; nstarti = insphere.GetArray().Size()+1; // if point in sphere, then it is also closesphere for (int j = starti; j < nstarti; j++) { int helind = insphere.GetArray().Get(j); if (!closesphere.IsIn (helind)) closesphere.Add (helind); } // add connected spheres to insphere - list for (int j = starti; j < nstarti; j++) { list.GetList (insphere.GetArray().Get(j), connected); for (int k = 0; k < connected.Size(); k++) { int celind = connected[k]; if (tempels.Get(celind)[0] != -1 && !insphere.IsIn (celind)) { changed = 1; insphere.Add (celind); } } } // check neighbour-tets for (int j = starti; j < nstarti; j++) for (int k = 0; k < 4; k++) { int helind = insphere.GetArray().Get(j); int nbind = meshnb.GetNB (helind, k); if (nbind && !insphere.IsIn (nbind) ) { //changed //int prec = testout->precision(); //testout->precision(12); //(*testout) << "val1 " << Dist2 (centers.Get(nbind), newp) // << " val2 " << radi2.Get(nbind) * (1+1e-8) // << " val3 " << radi2.Get(nbind) // << " val1 / val3 " << Dist2 (centers.Get(nbind), newp)/radi2.Get(nbind) << endl; //testout->precision(prec); if (Dist2 (centers.Get(nbind), newp) < radi2.Get(nbind) * (1+1e-8) ) closesphere.Add (nbind); if (Dist2 (centers.Get(nbind), newp) < radi2.Get(nbind) * (1 + 1e-12)) { // point is in sphere -> remove tet insphere.Add (nbind); changed = 1; } else { INDEX_3 i3 = tempels.Get(helind).GetFace (k); const Point<3> & p1 = mesh.Point ( PointIndex (i3.I1()) ); const Point<3> & p2 = mesh.Point ( PointIndex (i3.I2()) ); const Point<3> & p3 = mesh.Point ( PointIndex (i3.I3()) ); Vec<3> v1 = p2-p1; Vec<3> v2 = p3-p1; Vec<3> n = Cross (v1, v2); n /= n.Length(); if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k])) > 0) n *= -1; double dist = n * Vec3d (p1, newp); if (dist > -1e-10) // 1e-10 { insphere.Add (nbind); changed = 1; } } } } } // while (changed) // Array newels; Array newels; Element2d face(TRIG); for (int celind : insphere.GetArray()) for (int k = 0; k < 4; k++) { int nbind = meshnb.GetNB (celind, k); if (!nbind || !insphere.IsIn (nbind)) { tempels.Get (celind).GetFace (k, face); // Element newel(TET); DelaunayTet newel; for (int l = 0; l < 3; l++) newel[l] = face[l]; newel[3] = newpi; newels.Append (newel); Vec<3> v1 = mesh[face[1]] - mesh[face[0]]; Vec<3> v2 = mesh[face[2]] - mesh[face[0]]; Vec<3> n = Cross (v1, v2); n.Normalize(); if (n * Vec3d(mesh.Point (face[0]), mesh.Point (tempels.Get(celind)[k])) > 0) n *= -1; double hval = n * ( newp - mesh[face[0]]); if (hval > -1e-12) { cerr << "vec to outer" << endl; (*testout) << "vec to outer, hval = " << hval << endl; (*testout) << "v1 x v2 = " << Cross (v1, v2) << endl; (*testout) << "facep: " << mesh.Point (face[0]) << " " << mesh.Point (face[1]) << " " << mesh.Point (face[2]) << endl; } } } meshnb.ResetFaceHT (10*insphere.GetArray().Size()+1); for (auto celind : insphere.GetArray()) { meshnb.Delete (celind); list.DeleteElement (celind); for (int k = 0; k < 4; k++) tempels.Elem(celind)[k] = -1; tettree.DeleteElement (celind); freelist.Append (celind); } bool hasclose = false; for (int ind : closesphere.GetArray()) { if (!insphere.IsIn(ind) && fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 ) hasclose = true; } for (int j = 1; j <= newels.Size(); j++) { const auto & newel = newels.Get(j); int nelind; if (!freelist.Size()) { tempels.Append (newel); nelind = tempels.Size(); } else { nelind = freelist.Last(); freelist.DeleteLast(); tempels.Elem(nelind) = newel; } meshnb.Add (nelind); list.AddElement (nelind); for (int k = 0; k < 4; k++) pp[k] = &mesh.Point (newel[k]); if (CalcSphereCenter (&pp[0], pc) ) { PrintSysError ("Delaunay: New tet is flat"); (*testout) << "new tet is flat" << endl; for (int k = 0; k < 4; k++) (*testout) << newel[k] << " "; (*testout) << endl; for (int k = 0; k < 4; k++) (*testout) << *pp[k-1] << " "; (*testout) << endl; } double r2 = Dist2 (*pp[0], pc); if (hasclose) for (int k = 1; k <= closesphere.GetArray().Size(); k++) { int csameind = closesphere.GetArray().Get(k); if (!insphere.IsIn(csameind) && fabs (r2 - radi2.Get(csameind)) < 1e-10 && Dist (pc, centers.Get(csameind)) < 1e-10) { pc = centers.Get(csameind); r2 = radi2.Get(csameind); list.ConnectElement (nelind, csameind); break; } } if (centers.Size() < nelind) { centers.Append (pc); radi2.Append (r2); } else { centers.Elem(nelind) = pc; radi2.Elem(nelind) = r2; } closesphere.Add (nelind); tpmax = tpmin = *pp[0]; for (int k = 1; k <= 3; k++) { tpmin.SetToMin (*pp[k]); tpmax.SetToMax (*pp[k]); } tpmax = tpmax + 0.01 * (tpmax - tpmin); tettree.Insert (tpmin, tpmax, nelind); } } void Delaunay1 (Mesh & mesh, const MeshingParameters & mp, AdFront3 * adfront, Array & tempels, int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax) { static Timer t("Meshing3::Delaunay1"); RegionTimer reg(t); Array> centers; Array radi2; Box<3> bbox(Box<3>::EMPTY_BOX); for (auto & face : adfront->Faces()) for (PointIndex pi : face.Face().PNums()) bbox.Add (mesh.Point(pi)); for (PointIndex pi : mesh.LockedPoints()) bbox.Add (mesh.Point (pi)); pmin = bbox.PMin(); pmax = bbox.PMax(); Vec<3> vdiag = pmax-pmin; // double r1 = vdiag.Length(); double r1 = sqrt (3.0) * max3(vdiag(0), vdiag(1), vdiag(2)); vdiag = Vec<3> (r1, r1, r1); //double r2; Point<3> pmin2 = pmin - 8 * vdiag; Point<3> pmax2 = pmax + 8 * vdiag; Point<3> cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2); cp2(0) = pmin2(0); cp3(1) = pmin2(1); cp4(2) = pmin2(2); size_t np = mesh.GetNP(); startel[0] = mesh.AddPoint (cp1); startel[1] = mesh.AddPoint (cp2); startel[2] = mesh.AddPoint (cp3); startel[3] = mesh.AddPoint (cp4); // flag points to use for Delaunay: BitArrayChar usep(np); usep.Clear(); for (auto & face : adfront->Faces()) for (PointIndex pi : face.Face().PNums()) usep.Set (pi); for (size_t i = oldnp + PointIndex::BASE; i < np + PointIndex::BASE; i++) usep.Set (i); for (PointIndex pi : mesh.LockedPoints()) usep.Set (pi); Array freelist; int cntp = 0; MeshNB meshnb (tempels, mesh.GetNP() + 5); SphereList list; pmin2 = pmin2 + 0.1 * (pmin2 - pmax2); pmax2 = pmax2 + 0.1 * (pmax2 - pmin2); BoxTree<3> tettree(pmin2, pmax2); tempels.Append (startel); meshnb.Add (1); list.AddElement (1); Array connected, treesearch; Box<3> tbox(Box<3>::EMPTY_BOX); for (size_t k = 0; k < 4; k++) tbox.Add (mesh.Point(startel[k])); Point<3> tpmin = tbox.PMin(); Point<3> tpmax = tbox.PMax(); tpmax = tpmax + 0.01 * (tpmax - tpmin); tettree.Insert (tpmin, tpmax, 1); Point<3> pc; const Point<3> * pp[4]; for (int k = 0; k < 4; k++) pp[k] = &mesh.Point (startel[k]); CalcSphereCenter (&pp[0], pc); centers.Append (pc); radi2.Append (Dist2 (*pp[0], pc)); IndexSet insphere(mesh.GetNP()); IndexSet closesphere(mesh.GetNP()); // "random" reordering of points (speeds a factor 3 - 5 !!!) Array mixed(np); int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 }; int prim; { int i = 0; while (np % prims[i] == 0) i++; prim = prims[i]; } for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++) mixed[pi] = PointIndex ( (prim * pi) % np + PointIndex::BASE ); for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++) { if (pi % 1000 == 0) { if (pi % 10000 == 0) PrintDot ('+'); else PrintDot ('.'); } multithread.percent = 100.0 * pi / np; if (multithread.terminate) break; PointIndex newpi = mixed[pi]; if (!usep.Test(newpi)) continue; cntp++; const MeshPoint & newp = mesh[newpi]; AddDelaunayPoint (newpi, newp, tempels, mesh, tettree, meshnb, centers, radi2, connected, treesearch, freelist, list, insphere, closesphere); } for (int i = tempels.Size(); i >= 1; i--) if (tempels.Get(i)[0] <= 0) tempels.DeleteElement (i); PrintDot ('\n'); PrintMessage (3, "Points: ", cntp); PrintMessage (3, "Elements: ", tempels.Size()); // (*mycout) << cntp << " / " << tempels.Size() << " points/elements" << endl; /* cout << "tempels: "; tempels.PrintMemInfo(cout); cout << "Searchtree: "; tettree.Tree().PrintMemInfo(cout); cout << "MeshNB: "; meshnb.PrintMemInfo(cout); */ } void Meshing3 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp) { static Timer t("Meshing3::Delaunay"); RegionTimer reg(t); int np, ne; PrintMessage (1, "Delaunay meshing"); PrintMessage (3, "number of points: ", mesh.GetNP()); PushStatus ("Delaunay meshing"); Array tempels; Point3d pmin, pmax; DelaunayTet startel; int oldnp = mesh.GetNP(); if (mp.blockfill) { BlockFillLocalH (mesh, mp); PrintMessage (3, "number of points: ", mesh.GetNP()); } np = mesh.GetNP(); Delaunay1 (mesh, mp, adfront, tempels, oldnp, startel, pmin, pmax); { // improve delaunay - mesh by swapping !!!! Mesh tempmesh; for (auto & meshpoint : mesh.Points()) tempmesh.AddPoint (meshpoint); for (auto & tempel : tempels) { Element el(4); for (int j = 0; j < 4; j++) el[j] = tempel[j]; el.SetIndex (1); const Point<3> & lp1 = mesh.Point (el[0]); const Point<3> & lp2 = mesh.Point (el[1]); const Point<3> & lp3 = mesh.Point (el[2]); const Point<3> & lp4 = mesh.Point (el[3]); Vec<3> v1 = lp2-lp1; Vec<3> v2 = lp3-lp1; Vec<3> v3 = lp4-lp1; Vec<3> n = Cross (v1, v2); double vol = n * v3; if (vol > 0) swap (el[2], el[3]); tempmesh.AddVolumeElement (el); } MeshQuality3d (tempmesh); tempmesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0)); tempmesh.AddFaceDescriptor (FaceDescriptor (2, 1, 0, 0)); for (int i = 1; i <= mesh.GetNOpenElements(); i++) { Element2d sel = mesh.OpenElement(i); sel.SetIndex(1); tempmesh.AddSurfaceElement (sel); swap (sel[1], sel[2]); tempmesh.AddSurfaceElement (sel); } for (int i = 1; i <= 4; i++) { Element2d self(TRIG); self.SetIndex (1); startel.GetFace (i-1, self); tempmesh.AddSurfaceElement (self); } // for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++) // tempmesh.AddLockedPoint (i); for (auto pi : tempmesh.Points().Range()) tempmesh.AddLockedPoint (pi); // tempmesh.PrintMemInfo(cout); // tempmesh.Save ("tempmesh.vol"); for (int i = 1; i <= 4; i++) { tempmesh.FindOpenElements (); PrintMessage (5, "Num open: ", tempmesh.GetNOpenElements()); tempmesh.CalcSurfacesOfNode (); tempmesh.FreeOpenElementsEnvironment (1); MeshOptimize3d meshopt(mp); // tempmesh.CalcSurfacesOfNode(); meshopt.SwapImprove(tempmesh, OPT_CONFORM); } MeshQuality3d (tempmesh); tempels.SetSize(0); for (auto & el : tempmesh.VolumeElements()) tempels.Append (el); } // remove degenerated BitArray badnode(mesh.GetNP()); badnode.Clear(); int ndeg = 0; for (int i = 1; i <= tempels.Size(); i++) { Element el(4); for (int j = 0; j < 4; j++) el[j] = tempels.Elem(i)[j]; // Element & el = tempels.Elem(i); const Point3d & lp1 = mesh.Point (el[0]); const Point3d & lp2 = mesh.Point (el[1]); const Point3d & lp3 = mesh.Point (el[2]); const Point3d & lp4 = mesh.Point (el[3]); Vec3d v1(lp1, lp2); Vec3d v2(lp1, lp3); Vec3d v3(lp1, lp4); Vec3d n = Cross (v1, v2); double vol = n * v3; double h = v1.Length() + v2.Length() + v3.Length(); if (fabs (vol) < 1e-8 * (h * h * h) && (el[0] <= np && el[1] <= np && el[2] <= np && el[3] <= np) ) // old: 1e-12 { badnode.Set(el[0]); badnode.Set(el[1]); badnode.Set(el[2]); badnode.Set(el[3]); ndeg++; (*testout) << "vol = " << vol << " h = " << h << endl; } if (vol > 0) Swap (el[2], el[3]); } ne = tempels.Size(); for (int i = ne; i >= 1; i--) { const DelaunayTet & el = tempels.Get(i); if (badnode.Test(el[0]) || badnode.Test(el[1]) || badnode.Test(el[2]) || badnode.Test(el[3]) ) tempels.DeleteElement(i); } PrintMessage (3, ndeg, " degenerated elements removed"); // find surface triangles which are no face of any tet INDEX_3_HASHTABLE openeltab(mesh.GetNOpenElements()+3); Array openels; for (int i = 1; i <= mesh.GetNOpenElements(); i++) { const Element2d & tri = mesh.OpenElement(i); INDEX_3 i3(tri[0], tri[1], tri[2]); i3.Sort(); openeltab.Set (i3, i); } for (int i = 1; i <= tempels.Size(); i++) { for (int j = 0; j < 4; j++) { INDEX_3 i3 = tempels.Get(i).GetFace (j); i3.Sort(); if (openeltab.Used(i3)) openeltab.Set (i3, 0); } } // and store them in openels for (int i = 1; i <= openeltab.GetNBags(); i++) for (int j = 1; j <= openeltab.GetBagSize(i); j++) { INDEX_3 i3; int fnr; openeltab.GetData (i, j, i3, fnr); if (fnr) openels.Append (fnr); } // find open triangle with close edge (from halfening of surface squares) INDEX_2_HASHTABLE twotrias(mesh.GetNOpenElements()+5); // for (i = 1; i <= mesh.GetNOpenElements(); i++) for (int ii = 1; ii <= openels.Size(); ii++) { int i = openels.Get(ii); const Element2d & el = mesh.OpenElement(i); for (int j = 1; j <= 3; j++) { INDEX_2 hi2 (el.PNumMod (j), el.PNumMod(j+1)); hi2.Sort(); if (twotrias.Used(hi2)) { INDEX_2 hi3; hi3 = twotrias.Get (hi2); hi3.I2() = el.PNumMod (j+2); twotrias.Set (hi2, hi3); } else { INDEX_2 hi3(el.PNumMod (j+2), 0); twotrias.Set (hi2, hi3); } } } INDEX_2_HASHTABLE tetedges(tempels.Size() + 5); for (int i = 1; i <= tempels.Size(); i++) { const DelaunayTet & el = tempels.Get(i); INDEX_2 i2; for (int j = 1; j <= 6; j++) { switch (j) { case 1: i2.I1()=el[0]; i2.I2()=el[1]; break; case 2: i2.I1()=el[0]; i2.I2()=el[2]; break; case 3: i2.I1()=el[0]; i2.I2()=el[3]; break; case 4: i2.I1()=el[1]; i2.I2()=el[2]; break; case 5: i2.I1()=el[1]; i2.I2()=el[3]; break; case 6: i2.I1()=el[2]; i2.I2()=el[3]; break; default: i2.I1()=i2.I2()=0; break; } i2.Sort(); tetedges.Set (i2, 1); } } // cout << "tetedges:"; // tetedges.PrintMemInfo (cout); for (INDEX_2_HASHTABLE::Iterator it = twotrias.Begin(); it != twotrias.End(); it++) { INDEX_2 hi2, hi3; twotrias.GetData (it, hi2, hi3); hi3.Sort(); if (tetedges.Used (hi3)) { const Point3d & p1 = mesh.Point ( PointIndex (hi2.I1())); const Point3d & p2 = mesh.Point ( PointIndex (hi2.I2())); const Point3d & p3 = mesh.Point ( PointIndex (hi3.I1())); const Point3d & p4 = mesh.Point ( PointIndex (hi3.I2())); Vec3d v1(p1, p2); Vec3d v2(p1, p3); Vec3d v3(p1, p4); Vec3d n = Cross (v1, v2); double vol = n * v3; double h = v1.Length() + v2.Length() + v3.Length(); if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12 { badnode.Set(hi3.I1()); badnode.Set(hi3.I2()); } } } /* for (i = 1; i <= twotrias.GetNBags(); i++) for (j = 1; j <= twotrias.GetBagSize (i); j++) { INDEX_2 hi2, hi3; twotrias.GetData (i, j, hi2, hi3); hi3.Sort(); if (tetedges.Used (hi3)) { const Point3d & p1 = mesh.Point (hi2.I1()); const Point3d & p2 = mesh.Point (hi2.I2()); const Point3d & p3 = mesh.Point (hi3.I1()); const Point3d & p4 = mesh.Point (hi3.I2()); Vec3d v1(p1, p2); Vec3d v2(p1, p3); Vec3d v3(p1, p4); Vec3d n = Cross (v1, v2); double vol = n * v3; double h = v1.Length() + v2.Length() + v3.Length(); if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12 { badnode.Set(hi3.I1()); badnode.Set(hi3.I2()); } } } */ ne = tempels.Size(); for (int i = ne; i >= 1; i--) { const DelaunayTet & el = tempels.Get(i); if (badnode.Test(el[0]) || badnode.Test(el[1]) || badnode.Test(el[2]) || badnode.Test(el[3]) ) tempels.DeleteElement(i); } // find intersecting: PrintMessage (3, "Remove intersecting"); if (openels.Size()) { BoxTree<3> setree(pmin, pmax); /* cout << "open elements in search tree: " << openels.Size() << endl; cout << "pmin, pmax = " << pmin << " - " << pmax << endl; */ for (int i = 1; i <= openels.Size(); i++) { int fnr; fnr = openels.Get(i); if (fnr) { const Element2d & tri = mesh.OpenElement(fnr); Point3d ltpmin (mesh.Point(tri[0])); Point3d ltpmax (ltpmin); for (int k = 2; k <= 3; k++) { ltpmin.SetToMin (mesh.Point (tri.PNum(k))); ltpmax.SetToMax (mesh.Point (tri.PNum(k))); } setree.Insert (ltpmin, ltpmax, fnr); } } Array neartrias; for (int i = 1; i <= tempels.Size(); i++) { const Point<3> *pp[4]; int tetpi[4]; DelaunayTet & el = tempels.Elem(i); int intersect = 0; for (int j = 0; j < 4; j++) { pp[j] = &mesh.Point(el[j]); tetpi[j] = el[j]; } Point3d tetpmin(*pp[0]); Point3d tetpmax(tetpmin); for (int j = 1; j < 4; j++) { tetpmin.SetToMin (*pp[j]); tetpmax.SetToMax (*pp[j]); } tetpmin = tetpmin + 0.01 * (tetpmin - tetpmax); tetpmax = tetpmax + 0.01 * (tetpmax - tetpmin); setree.GetIntersecting (tetpmin, tetpmax, neartrias); // for (j = 1; j <= mesh.GetNSE(); j++) // { for (int jj = 1; jj <= neartrias.Size(); jj++) { int j = neartrias.Get(jj); const Element2d & tri = mesh.OpenElement(j); const Point<3> *tripp[3]; int tripi[3]; for (int k = 1; k <= 3; k++) { tripp[k-1] = &mesh.Point (tri.PNum(k)); tripi[k-1] = tri.PNum(k); } if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi)) { /* int il1, il2; (*testout) << "intersect !" << endl; (*testout) << "triind: "; for (il1 = 0; il1 < 3; il1++) (*testout) << " " << tripi[il1]; (*testout) << endl; (*testout) << "tetind: "; for (il2 = 0; il2 < 4; il2++) (*testout) << " " << tetpi[il2]; (*testout) << endl; (*testout) << "trip: "; for (il1 = 0; il1 < 3; il1++) (*testout) << " " << *tripp[il1]; (*testout) << endl; (*testout) << "tetp: "; for (il2 = 0; il2 < 4; il2++) (*testout) << " " << *pp[il2]; (*testout) << endl; */ intersect = 1; break; } } if (intersect) { tempels.DeleteElement(i); i--; } } } PrintMessage (3, "Remove outer"); // find connected tets (with no face between, and no hole due // to removed intersecting tets. // INDEX_3_HASHTABLE innerfaces(np); INDEX_3_HASHTABLE boundaryfaces(mesh.GetNOpenElements()/3+1); /* for (int i = 1; i <= mesh.GetNOpenElements(); i++) { const Element2d & tri = mesh.OpenElement(i); INDEX_3 i3 (tri[0], tri[1], tri[2]); i3.Sort(); boundaryfaces.PrepareSet (i3); } */ for (const Element2d & tri : mesh.OpenElements()) { INDEX_3 i3 (tri[0], tri[1], tri[2]); i3.Sort(); boundaryfaces.PrepareSet (i3); } boundaryfaces.AllocateElements(); for (int i = 1; i <= mesh.GetNOpenElements(); i++) { const Element2d & tri = mesh.OpenElement(i); INDEX_3 i3 (tri[0], tri[1], tri[2]); i3.Sort(); boundaryfaces.Set (i3, 1); } /* for (int i = 0; i < tempels.Size(); i++) for (int j = 0; j < 4; j++) tempels[i].NB(j) = 0; */ for (auto & el : tempels) for (int j = 0; j < 4; j++) el.NB(j) = 0; TABLE elsonpoint(mesh.GetNP()); /* for (int i = 0; i < tempels.Size(); i++) { const DelaunayTet & el = tempels[i]; */ for (const DelaunayTet & el : tempels) { INDEX_4 i4(el[0], el[1], el[2], el[3]); i4.Sort(); elsonpoint.IncSizePrepare (i4.I1()); elsonpoint.IncSizePrepare (i4.I2()); } elsonpoint.AllocateElementsOneBlock(); for (int i = 0; i < tempels.Size(); i++) { const DelaunayTet & el = tempels[i]; INDEX_4 i4(el[0], el[1], el[2], el[3]); i4.Sort(); elsonpoint.Add (i4.I1(), i+1); elsonpoint.Add (i4.I2(), i+1); } // cout << "elsonpoint mem: "; // elsonpoint.PrintMemInfo(cout); INDEX_3_CLOSED_HASHTABLE faceht(100); Element2d hel(TRIG); // for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) for (PointIndex pi : mesh.Points().Range()) { faceht.SetSize (4 * elsonpoint[pi].Size()); for (int ii = 0; ii < elsonpoint[pi].Size(); ii++) { int i = elsonpoint[pi][ii]; const DelaunayTet & el = tempels.Get(i); for (int j = 1; j <= 4; j++) { el.GetFace (j-1, hel); hel.Invert(); hel.NormalizeNumbering(); if (hel[0] == pi) { INDEX_3 i3(hel[0], hel[1], hel[2]); if (!boundaryfaces.Used (i3)) { if (faceht.Used (i3)) { INDEX_2 i2 = faceht.Get(i3); tempels.Elem(i).NB(j-1) = i2.I1(); tempels.Elem(i2.I1()).NB(i2.I2()-1) = i; } else { hel.Invert(); hel.NormalizeNumbering(); INDEX_3 i3i(hel[0], hel[1], hel[2]); INDEX_2 i2(i, j); faceht.Set (i3i, i2); } } } } } } /* for (i = 1; i <= tempels.Size(); i++) { const DelaunayTet & el = tempels.Get(i); for (j = 1; j <= 4; j++) { INDEX_3 i3; Element2d face; el.GetFace1 (j, face); for (int kk = 1; kk <= 3; kk++) i3.I(kk) = face.PNum(kk); i3.Sort(); if (!boundaryfaces.Used (i3)) { if (innerfaces.Used(i3)) { INDEX_2 i2; i2 = innerfaces.Get(i3); i2.I2() = i; innerfaces.Set (i3, i2); } else { INDEX_2 i2; i2.I1() = i; i2.I2() = 0; innerfaces.Set (i3, i2); } } } } */ /* (*testout) << "nb elements:" << endl; for (i = 1; i <= tempels.Size(); i++) { (*testout) << i << " "; for (j = 1; j <= 4; j++) (*testout) << tempels.Get(i).NB1(j) << " "; (*testout) << endl; } (*testout) << "pairs:" << endl; for (i = 1; i <= innerfaces.GetNBags(); i++) for (j = 1; j <= innerfaces.GetBagSize(i); j++) { INDEX_3 i3; INDEX_2 i2; innerfaces.GetData (i, j, i3, i2); (*testout) << i2 << endl; } */ /* cout << "innerfaces: "; innerfaces.PrintMemInfo (cout); */ // cout << "boundaryfaces: "; // boundaryfaces.PrintMemInfo (cout); PrintMessage (5, "tables filled"); ne = tempels.Size(); BitArray inner(ne), outer(ne); inner.Clear(); outer.Clear(); Array elstack; /* int starti = 0; for (i = 1; i <= ne; i++) { const Element & el = tempels.Get(i); for (j = 1; j <= 4; j++) for (k = 1; k <= 4; k++) if (el.PNum(j) == startel.PNum(k)) { outer.Set(i); starti = i; } } */ while (1) { int inside; bool done = 1; int i; for (i = 1; i <= ne; i++) if (!inner.Test(i) && !outer.Test(i)) { done = 0; break; } if (done) break; const DelaunayTet & el = tempels.Get(i); const Point3d & p1 = mesh.Point (el[0]); const Point3d & p2 = mesh.Point (el[1]); const Point3d & p3 = mesh.Point (el[2]); const Point3d & p4 = mesh.Point (el[3]); Point3d ci = Center (p1, p2, p3, p4); inside = adfront->Inside (ci); /* cout << "startel: " << i << endl; cout << "inside = " << inside << endl; cout << "ins2 = " << adfront->Inside (Center (ci, p1)) << endl; cout << "ins3 = " << adfront->Inside (Center (ci, p2)) << endl; */ elstack.SetSize(0); elstack.Append (i); while (elstack.Size()) { int ei = elstack.Last(); elstack.DeleteLast(); if (!inner.Test(ei) && !outer.Test(ei)) { if (inside) inner.Set(ei); else outer.Set(ei); for (int j = 1; j <= 4; j++) { INDEX_3 i3 = tempels.Get(ei).GetFace(j-1); /* Element2d face; tempels.Get(ei).GetFace(j, face); for (int kk = 1; kk <= 3; kk++) i3.I(kk) = face.PNum(kk); */ i3.Sort(); if (tempels.Get(ei).NB(j-1)) elstack.Append (tempels.Get(ei).NB(j-1)); /* if (innerfaces.Used(i3)) { INDEX_2 i2 = innerfaces.Get(i3); int other = i2.I1() + i2.I2() - ei; if (other != tempels.Get(ei).NB1(j)) cerr << "different1 !!" << endl; if (other) { elstack.Append (other); } } else if (tempels.Get(ei).NB1(j)) cerr << "different2 !!" << endl; */ } } } } // check outer elements if (debugparam.slowchecks) { for (int i = 1; i <= ne; i++) { const DelaunayTet & el = tempels.Get(i); const Point3d & p1 = mesh.Point (el[0]); const Point3d & p2 = mesh.Point (el[1]); const Point3d & p3 = mesh.Point (el[2]); const Point3d & p4 = mesh.Point (el[3]); Point3d ci = Center (p1, p2, p3, p4); // if (adfront->Inside (ci) != adfront->Inside (Center (ci, p1))) // cout << "ERROR: outer test unclear !!!" << endl; if (inner.Test(i) != adfront->Inside (ci)) { /* cout << "ERROR: outer test wrong !!!" << "inner = " << int(inner.Test(i)) << "outer = " << int(outer.Test(i)) << endl; cout << "Vol = " << Determinant(Vec3d(p1, p2), Vec3d(p1, p3), Vec3d(p1, p4)) << endl; */ for (int j = 1; j <= 4; j++) { Point3d hp; switch (j) { case 1: hp = Center (ci, p1); break; case 2: hp = Center (ci, p2); break; case 3: hp = Center (ci, p3); break; case 4: hp = Center (ci, p4); break; } // cout << "inside(" << hp << ") = " << adfront->Inside(hp) << endl; } } if (adfront->Inside(ci)) outer.Clear(i); else outer.Set(i); } } /* // find bug in innerfaces tempmesh.DeleteVolumeElements(); for (i = 1; i <= innerfaces.GetNBags(); i++) for (j = 1; j <= innerfaces.GetBagSize(i); j++) { INDEX_3 i3; INDEX_2 i2; innerfaces.GetData (i, j, i3, i2); if (i2.I2()) { if (outer.Test(i2.I1()) != outer.Test(i2.I2())) { tempmesh.AddVolumeElement (tempels.Get(i2.I1())); tempmesh.AddVolumeElement (tempels.Get(i2.I2())); cerr << "outer flag different for connected els" << endl; } } } cout << "Check intersectiong once more" << endl; for (i = 1; i <= openels.Size(); i++) { tempmesh.SurfaceElement(2*openels.Get(i)).SetIndex(2); tempmesh.SurfaceElement(2*openels.Get(i)-1).SetIndex(2); } // for (i = 1; i <= tempmesh.GetNE(); i++) // for (j = 1; j <= tempmesh.GetNSE(); j++) i = 6; j = 403; if (i <= tempmesh.GetNE() && j <= tempmesh.GetNSE()) if (tempmesh.SurfaceElement(j).GetIndex()==2) { const Element & el = tempmesh.VolumeElement(i); const Element2d & sel = tempmesh.SurfaceElement(j); const Point3d *tripp[3]; const Point3d *pp[4]; int tetpi[4], tripi[3]; for (k = 1; k <= 4; k++) { pp[k-1] = &tempmesh.Point(el.PNum(k)); tetpi[k-1] = el.PNum(k); } for (k = 1; k <= 3; k++) { tripp[k-1] = &tempmesh.Point (sel.PNum(k)); tripi[k-1] = sel.PNum(k); } (*testout) << "Check Triangle " << j << ":"; for (k = 1; k <= 3; k++) (*testout) << " " << sel.PNum(k); for (k = 1; k <= 3; k++) (*testout) << " " << tempmesh.Point(sel.PNum(k)); (*testout) << endl; (*testout) << "Check Tet " << i << ":"; for (k = 1; k <= 4; k++) (*testout) << " " << el.PNum(k); for (k = 1; k <= 4; k++) (*testout) << " " << tempmesh.Point(el.PNum(k)); (*testout) << endl; if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi)) { cout << "Intesection detected !!" << endl; } } tempmesh.Save ("temp.vol"); // end bug search */ for (int i = ne; i >= 1; i--) { if (outer.Test(i)) tempels.DeleteElement(i); } // mesh.points.SetSize(mesh.points.Size()-4); for (int i = 0; i < tempels.Size(); i++) { Element el(4); for (int j = 0; j < 4; j++) el[j] = tempels[i][j]; mesh.AddVolumeElement (el); } PrintMessage (5, "outer removed"); mesh.FindOpenElements(domainnr); mesh.Compress(); PopStatus (); } } netgen-6.2.1905/libsrc/meshing/hprefinement.cpp0000644000175000017500000015177213504650527020116 0ustar kurtkurt#include #include "meshing.hpp" #include "hprefinement.hpp" namespace netgen { #include "hpref_segm.hpp" #include "hpref_trig.hpp" #include "hpref_quad.hpp" #include "hpref_tet.hpp" #include "hpref_prism.hpp" #include "hpref_hex.hpp" #include "hpref_pyramid.hpp" #include "classifyhpel.hpp" void HPRefElement :: Reset(void) { np = 8; for (int i = 0; i < 8; i++) { pnums[i] = -1; param[i][0] = param[i][1] = param[i][2] = 0; } domin=-1; domout=-1; // he: levelx = 0; levely = 0; levelz = 0; } HPRefElement :: HPRefElement () { Reset(); } HPRefElement :: HPRefElement(Element & el) : np(el.GetNV()), index(el.GetIndex()), levelx(0), levely(0), levelz(0), type(HP_NONE), domin(-1), domout(-1) //domin,out for segements { //Reset(); for (int i=0; igeom == HP_TET) hps = &reftet; if (hps->geom == HP_TRIG) hps = &reftrig; } */ if (!hps) { cout << "Attention hps : hp-refinement not implemented for case " << type << endl; PrintSysError ("hp-refinement not implemented for case ", type); } return hps; } bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoiclt_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint, int & levels, int & act_ref); bool ClassifyHPElements (Mesh & mesh, Array & elements, int & act_ref, int & levels); void InitHPElements(Mesh & mesh, Array & elements) { for(ElementIndex i = 0; i < mesh.GetNE(); i++) { HPRefElement hpel(mesh[i]); hpel.coarse_elnr = i; switch (mesh[i].GetType()) { case PRISM: hpel.type = HP_PRISM; break; case HEX: hpel.type = HP_HEX; break; case TET: hpel.type = HP_TET; break; case PYRAMID: hpel.type = HP_PYRAMID; break; default: cerr << "HPRefElement: illegal elementtype (1) " << mesh[i].GetType() << endl; throw NgException ("HPRefElement: illegal elementtype (1)"); } elements.Append(hpel); } for(SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) { HPRefElement hpel(mesh[i]); hpel.coarse_elnr = i; switch(mesh[i].GetType()) { case TRIG: hpel.type = HP_TRIG; break; case QUAD: hpel.type = HP_QUAD; break; default: cerr << "HPRefElement: illegal elementtype (1b) " << mesh[i].GetType() << endl; throw NgException ("HPRefElement: illegal elementtype (1b)"); } elements.Append(hpel); } for(SegmentIndex i = 0; i < mesh.GetNSeg(); i++) { Segment & seg = mesh[i]; HPRefElement hpel(mesh[i]); hpel.coarse_elnr = i; hpel.type = HP_SEGM; hpel.index = seg.edgenr + 10000*seg.si; if(seg.edgenr >= 10000) { throw NgException("assumption that seg.edgenr < 10000 is wrong"); } elements.Append(hpel); } } /* ******************************* DoRefinement *************************************** */ void DoRefinement (Mesh & mesh, Array & elements, Refinement * ref, double fac1) { elements.SetAllocSize (5 * elements.Size()); INDEX_2_HASHTABLE newpts(elements.Size()+1); INDEX_3_HASHTABLE newfacepts(elements.Size()+1); // prepare new points fac1 = max(0.001,min(0.33,fac1)); cout << " in HP-REFINEMENT with fac1 " << fac1 << endl; *testout << " in HP-REFINEMENT with fac1 " << fac1 << endl; int oldelsize = elements.Size(); for (int i = 0; i < oldelsize; i++) { HPRefElement & el = elements[i]; HPRef_Struct * hprs = Get_HPRef_Struct (el.type); if (!hprs) { cout << "Refinementstruct not defined for element " << el.type << endl; continue; } int j = 0; while (hprs->splitedges[j][0]) { INDEX_2 i2(el.pnums[hprs->splitedges[j][0]-1], el.pnums[hprs->splitedges[j][1]-1]); if (!newpts.Used (i2)) { Point<3> np; for( int l=0;l<3;l++) np(l) = (1-fac1)*mesh.Point(i2.I1())(l) + fac1 * mesh.Point(i2.I2())(l); int npi = mesh.AddPoint (np); newpts.Set (i2, npi); } j++; } j = 0; if (hprs->splitfaces) while (hprs->splitfaces[j][0]) { INDEX_3 i3(el.pnums[hprs->splitfaces[j][0]-1], el.pnums[hprs->splitfaces[j][1]-1], el.pnums[hprs->splitfaces[j][2]-1]); if (i3.I2() > i3.I3()) Swap (i3.I2(), i3.I3()); if (!newfacepts.Used (i3)) { Point<3> np; for( int l=0;l<3;l++) np(l) = (1-2*fac1)*mesh.Point(i3.I1())(l) + fac1*mesh.Point(i3.I2())(l) + fac1*mesh.Point(i3.I3())(l); int npi = mesh.AddPoint (np); newfacepts.Set (i3, npi); } j++; } } for (int i = 0; i < oldelsize; i++) { HPRefElement el = elements[i]; HPRef_Struct * hprs = Get_HPRef_Struct (el.type); int newlevel = el.levelx; int oldnp = 0; switch (hprs->geom) { case HP_SEGM: oldnp = 2; break; case HP_TRIG: oldnp = 3; break; case HP_QUAD: oldnp = 4; break; case HP_TET: oldnp = 4; break; case HP_PYRAMID: oldnp = 5; break; case HP_PRISM: oldnp = 6; break; case HP_HEX: oldnp = 8; break; default: cerr << "HPRefElement: illegal type (3) " << hprs->geom << endl; throw NgException ("HPRefElement::SetType: illegal type (3)"); } if (el.type == HP_SEGM || el.type == HP_TRIG || el.type == HP_QUAD || el.type == HP_TET || el.type == HP_PRISM || el.type == HP_HEX || el.type == HP_PYRAMID) newlevel = el.levelx; if (!hprs) continue; int newpnums[64]; double newparam[64][3]; int j; for (j = 0; j < oldnp; j++) { newpnums[j] = el.pnums[j]; for (int l = 0; l < 3; l++) newparam[j][l] = el.param[j][l]; } // split edges, incl. transferring curvature j = 0; while (hprs->splitedges[j][0]) { INDEX_2 i2(el.pnums[hprs->splitedges[j][0]-1], el.pnums[hprs->splitedges[j][1]-1]); int npi = newpts.Get(i2); newpnums[hprs->splitedges[j][2]-1] = npi; for (int l = 0; l < 3; l++) newparam[hprs->splitedges[j][2]-1][l] = (1-fac1) * el.param[hprs->splitedges[j][0]-1][l] + fac1 * el.param[hprs->splitedges[j][1]-1][l]; j++; } // split faces j = 0; if (hprs->splitfaces) while (hprs->splitfaces[j][0]) { INDEX_3 i3(el.pnums[hprs->splitfaces[j][0]-1], el.pnums[hprs->splitfaces[j][1]-1], el.pnums[hprs->splitfaces[j][2]-1]); if (i3.I2() > i3.I3()) Swap (i3.I2(), i3.I3()); int npi = newfacepts.Get(i3); newpnums[hprs->splitfaces[j][3]-1] = npi; for (int l = 0; l < 3; l++) newparam[hprs->splitfaces[j][3]-1][l] = (1-2*fac1) * el.param[hprs->splitfaces[j][0]-1][l] + fac1 * el.param[hprs->splitfaces[j][1]-1][l] + fac1 * el.param[hprs->splitfaces[j][2]-1][l]; j++; } // split elements j = 0; if (hprs->splitelements) while (hprs->splitelements[j][0]) { //int pi1 = el.pnums[hprs->splitelements[j][0]-1]; Point<3> np; for( int l=0;l<3;l++) np(l) = (1-3*fac1)* mesh.Point(el.pnums[hprs->splitelements[j][0]-1])(l) + fac1* mesh.Point(el.pnums[hprs->splitelements[j][1]-1])(l) + fac1* mesh.Point(el.pnums[hprs->splitelements[j][2]-1])(l) + fac1* mesh.Point(el.pnums[hprs->splitelements[j][3]-1])(l); int npi = mesh.AddPoint (np); newpnums[hprs->splitelements[j][4]-1] = npi; for (int l = 0; l < 3; l++) newparam[hprs->splitelements[j][4]-1][l] = (1-3*fac1) * el.param[hprs->splitelements[j][0]-1][l] + fac1 * el.param[hprs->splitelements[j][1]-1][l] + fac1 * el.param[hprs->splitelements[j][2]-1][l] + fac1 * el.param[hprs->splitelements[j][3]-1][l]; j++; } j = 0; /* *testout << " newpnums = "; for (int hi = 0; hi < 64; hi++) *testout << newpnums[hi] << " "; *testout << endl; */ while (hprs->neweltypes[j]) { HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]); HPRefElement newel(el); newel.type = hprs->neweltypes[j]; // newel.index = elements[i].index; // newel.coarse_elnr = elements[i].coarse_elnr; if (newel.type == HP_SEGM || newel.type == HP_TRIG || newel.type == HP_QUAD || newel.type == HP_TET || newel.type == HP_PRISM || newel.type == HP_HEX || newel.type == HP_PYRAMID) newel.levelx = newel.levely = newel.levelz = newlevel; else newel.levelx = newel.levely = newel.levelz = newlevel+1; switch(hprsnew->geom) { case HP_SEGM: newel.np=2; break; case HP_QUAD: newel.np=4; break; case HP_TRIG: newel.np=3; break; case HP_HEX: newel.np=8; break; case HP_PRISM: newel.np=6; break; case HP_TET: newel.np=4; break; case HP_PYRAMID: newel.np=5; break; default: throw NgException (string("hprefinement.cpp: illegal type")); } for (int k = 0; k < newel.np; k++) newel.pnums[k] = newpnums[hprs->newels[j][k]-1]; /* *testout << " newel pnums " ; for (int k = 0; k < newel.np; k++) *testout << newel.pnums[k] << "\t"; *testout << endl; */ for (int k = 0; k < newel.np; k++) { for (int l = 0; l < 3; l++) { newel.param[k][l] = newparam[hprs->newels[j][k]-1][l]; // *testout << newel.param[k][l] << " \t "; } // *testout << endl; } if (j == 0) elements[i] = newel; // overwrite old element else elements.Append (newel); j++; } } } /* ************************** DoRefineDummies ******************************** */ void DoRefineDummies (Mesh & mesh, Array & elements, Refinement * ref) { int oldelsize = elements.Size(); for (int i = 0; i < oldelsize; i++) { HPRefElement el = elements[i]; HPRef_Struct * hprs = Get_HPRef_Struct (el.type); if (!hprs) continue; if (el.type != HP_DUMMY_QUAD_SINGCORNER && el.type != HP_PYRAMID_EDGES && el.type != HP_PYRAMID_0E_1V && el.type != HP_HEX_0E_1V && el.type != HP_HEX_1E_1V && el.type != HP_HEX_1E_0V && el.type != HP_HEX_3E_0V ) continue; int newlevel = el.levelx; int newpnums[8]; int j; for (j = 0; j < 8; j++) newpnums[j] = el.pnums[j]; double newparam[8][3]; for (j = 0; j < 8; j++) for (int k = 0; k < 3; k++) newparam[j][k] = el.param[j][k]; j = 0; while (hprs->neweltypes[j]) { HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]); HPRefElement newel(el); switch(hprsnew->geom) { case HP_SEGM: newel.np=2; break; case HP_QUAD: newel.np=4; break; case HP_TRIG: newel.np=3; break; case HP_HEX: newel.np=8; break; case HP_PRISM: newel.np=6; break; case HP_TET: newel.np=4; break; case HP_PYRAMID: newel.np=5; break; default: cerr << "HPRefElement: illegal type (4) " << hprsnew->geom << endl; throw NgException ("HPRefElement: illegal type (4)"); } newel.type = hprs->neweltypes[j]; for (int k = 0; k < 8; k++) newel.pnums[k] = newpnums[hprs->newels[j][k]-1]; newel.index = el.index; newel.coarse_elnr = el.coarse_elnr; newel.levelx = newel.levely = newel.levelz = newlevel; for (int k = 0; k < 8; k++) for (int l = 0; l < 3; l++) newel.param[k][l] = newparam[hprs->newels[j][k]-1][l]; if (j == 0) elements[i] = newel; else elements.Append (newel); j++; } } } void SubdivideDegeneratedHexes (Mesh & mesh, Array & elements, double fac1) { int oldne = elements.Size(); for (int i = 0; i < oldne; i++) if (Get_HPRef_Struct (elements[i].type)->geom == HP_HEX) { bool common = 0; for (int j = 0; j < 8; j++) for (int k = 0; k < j; k++) if (elements[i].pnums[j] == elements[i].pnums[k]) common = 1; if (common) { cout << " Degenerate Hex found " << endl; *testout << " Degenerate Hex found " << endl; HPRefElement el = elements[i]; HPRefElement newel = el; Point<3> center(0,0,0); double newparam[3] = { 0, 0, 0 }; for (int j = 0; j < 8; j++) { center += 0.125 * Vec<3>(mesh[el.pnums[j]]); // 0.125 originates form 8 points not from fac1; for (int l = 0; l < 3; l++) newparam[l] += 0.125 * el.param[j][l]; } int npi = mesh.AddPoint (center); const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (HEX); for (int j = 0; j < 6; j++) { Array pts; for (int k = 0; k < 4; k++) { bool same = 0; for (int l = 0; l < pts.Size(); l++) if (el.pnums[pts[l]] == el.pnums[faces[j][k]-1]) same = 1; if (!same) pts.Append (faces[j][k]-1); } if (pts.Size() == 3) // TrigFace -> TET { for (int k = 0; k < 3; k++) { newel.pnums[k] = el.pnums[pts[2-k]]; for (int l = 0; l < 3; l++) newel.param[k][l] = el.param[pts[2-k]][l]; } newel.pnums[3] = npi; for (int l = 0; l < 3; l++) newel.param[3][l] = newparam[l]; newel.type = HP_TET; newel.np = 4; } else { for (int k = 0; k < 4; k++) { newel.pnums[k] = el.pnums[pts[3-k]]; for (int l = 0; l < 3; l++) newel.param[k][l] = el.param[pts[3-k]][l]; } newel.pnums[4] = npi; for (int l = 0; l < 3; l++) newel.param[4][l] = newparam[l]; newel.type = HP_PYRAMID; newel.np = 5; } if (j == 0) elements[i] = newel; else elements.Append (newel); } /* const ELEMENT_EDGE * edges = MeshTopology::GetEdges (HEX); for(int k=0;k<12;k++) { int e[2]; for(int l=0;l<2;l++) e[l] = edges[k][l]-1; if(el.PNum(e[0]+1)!=el.PNum(e[1]+1)) { newel.SetType(HP_SEGM); for(int l=0;l<2;l++) { newel.pnums[0] = el.PNum(e[l]+1); newel.pnums[1] = npi; for(int j=0;j<3;j++) { // newel.param[0][j] = el.param[e[l]][j]; // newel.param[1][j] = newparam[j]; } elements.Append(newel); } newel.SetType(HP_TRIG); newel.pnums[0] = el.PNum(e[0]+1); newel.pnums[1] = el.PNum(e[1]+1); newel.pnums[2] = npi; *testout << "DEGHEX TRIG :: newpnums " << newel.pnums[0] << "\t" << newel.pnums[1] << "\t" << newel.pnums[2] << endl; cout << "DEGHEX TRIG :: newpnums " << newel.pnums[0] << "\t" << newel.pnums[1] << "\t" << newel.pnums[2] << endl; for(int j=0;j<3;j++) { // newel.param[0][j] = el.param[e[0]][j]; // newel.param[1][j] = el.param[e[1]][j]; // newel.param[2][j] = newparam[j]; } elements.Append(newel); } }*/ } } } void CalcStatistics (Array & elements) { return; #ifdef ABC int i, p; int nsegm = 0, ntrig = 0, nquad = 0; int nhex = 0, nprism = 0, npyramid = 0, ntet = 0; int maxlevel = 0; for (i = 1; i <= elements.Size(); i++) { const HPRefElement & el = elements.Get(i); maxlevel = max2 (el.level, maxlevel); switch (Get_HPRef_Struct (el.type)->geom) { case HP_SEGM: { nsegm++; break; } case HP_TRIG: { ntrig ++; break; } case HP_QUAD: { nquad++; break; } case HP_TET: { ntet++; break; } case HP_PRISM: { nprism++; break; } case HP_PYRAMID: { npyramid++; break; } case HP_HEX: { nhex++; break; } default: { cerr << "statistics error, unknown element type" << endl; } } } cout << "level = " << maxlevel << endl; cout << "nsegm = " << nsegm << endl; cout << "ntrig = " << ntrig << ", nquad = " << nquad << endl; cout << "ntet = " << ntet << ", npyr = " << npyramid << ", nprism = " << nprism << ", nhex = " << nhex << endl; return; double memcost = 0, cpucost = 0; for (p = 1; p <= 20; p++) { memcost = (ntet + nprism + nhex) * pow (static_cast(p), 6.0); cpucost = (ntet + nprism + nhex) * pow (static_cast(p), 9.0); cout << "costs for p = " << p << ": mem = " << memcost << ", cpu = " << cpucost << endl; } double memcosttet = 0; double memcostprism = 0; double memcosthex = 0; double memcostsctet = 0; double memcostscprism = 0; double memcostschex = 0; double cpucosttet = 0; double cpucostprism = 0; double cpucosthex = 0; for (i = 1; i <= elements.Size(); i++) { const HPRefElement & el = elements.Get(i); switch (el.type) { case HP_TET: case HP_TET_0E_1V: case HP_TET_1E_0V: case HP_TET_1E_1VA: { int p1 = maxlevel - el.level + 1; (*testout) << "p1 = " << p1 << ", P1^6 = " << pow (static_cast(p1), 6.0) << " (p1-3)^6 = " << pow ( static_cast(max2(p1-3, 0)), 6.0) << " p1^3 = " << pow ( static_cast(p1), 3.0) << " (p1-3)^3 = " << pow ( static_cast(p1-3), 3.0) << " [p1^3-(p1-3)^3]^2 = " << sqr (pow (static_cast(p1),3.0) - pow ( static_cast(p1-3), 3.0)) << endl; p1 /= 2 +1; memcosttet += pow (static_cast(p1), 6.0); memcostsctet += pow (static_cast(p1), 6.0) - pow ( static_cast(max2(p1-3, 1)), 6.0); cpucosttet += pow (static_cast(p1), 9.0); break; } case HP_PRISM: case HP_PRISM_SINGEDGE: { int p1 = maxlevel - el.level + 1; p1 /= 2 +1; memcostprism += pow (static_cast(p1), 6.0); memcostscprism += pow (static_cast(p1), 6.0) - pow ( static_cast(max2(p1-3, 1)), 6.0); cpucostprism += pow (static_cast(p1), 9.0); break; } case HP_HEX: { int p1 = maxlevel - el.level + 1; int p2 = maxlevel; p1 /= 2 +1; p2 /= 2 +1; memcosthex += pow (static_cast(p1), 4.0) * pow (static_cast(p2), 2.0); memcostschex += pow (static_cast(p1), 6.0) - pow ( static_cast(max2(p1-2, 0)), 6.0); cpucosthex += pow (static_cast(p1), 6.0) * pow (static_cast(p2), 3.0); break; } default: ; } } cout << "TET: hp-memcost = " << memcosttet << ", scmemcost = " << memcostsctet << ", cpucost = " << cpucosttet << endl; cout << "PRI: hp-memcost = " << memcostprism << ", scmemcost = " << memcostscprism << ", cpucost = " << cpucostprism << endl; cout << "HEX: hp-memcost = " << memcosthex << ", scmemcost = " << memcostschex << ", cpucost = " << cpucosthex << endl; #endif } void ReorderPoints (Mesh & mesh, Array & hpelements) { Array map (mesh.GetNP()); for (int i = 1; i <= mesh.GetNP(); i++) map[i] = i; int nwrong(0), nright(0); for (int k = 0; k < 5; k++) { nwrong = nright = 0; for (int i = 0; i < hpelements.Size(); i++) { const HPRefElement & hpel = hpelements[i]; if (Get_HPRef_Struct (hpel.type) -> geom == HP_PRISM) { int minbot = 0, mintop = 0; for (int j = 0; j < 3; j++) { if (map[hpel.pnums[j]] < map[hpel.pnums[minbot]]) minbot = j; if (map[hpel.pnums[j+3]] < map[hpel.pnums[mintop+3]]) mintop = j; } if (minbot != mintop) nwrong++; else nright++; if (minbot != mintop) { if (map[hpel.pnums[minbot]] < map[hpel.pnums[mintop+3]]) swap (map[hpel.pnums[3+minbot]], map[hpel.pnums[3+mintop]]); else swap (map[hpel.pnums[minbot]], map[hpel.pnums[mintop]]); } } } // cout << nwrong << " wrong prisms, " << nright << " right prisms" << endl; } cout << nwrong << " wrong prisms, " << nright << " right prisms" << endl; Array hpts(mesh.GetNP()); for (int i = 1; i <= mesh.GetNP(); i++) hpts[map[i]] = mesh.Point(i); for (int i = 1; i <= mesh.GetNP(); i++) mesh.Point(i) = hpts[i]; for (int i = 0; i < hpelements.Size(); i++) { HPRefElement & hpel = hpelements[i]; for (int j = 0; j < hpel.np; j++) hpel.pnums[j] = map[hpel.pnums[j]]; } } /* ***************************** HPRefinement ********************************** */ void HPRefinement (Mesh & mesh, Refinement * ref, int levels, double fac1, bool setorders, bool reflevels) { PrintMessage (1, "HP Refinement called, levels = ", levels); // NgLock mem_lock (mem_mutex,1); mesh.coarsemesh = new Mesh; *mesh.coarsemesh = mesh; // #ifdef CURVEDELEMS_NEW const_cast (mesh.coarsemesh->GetCurvedElements() ). BuildCurvedElements (ref, mesh.GetCurvedElements().GetOrder()); // #endif delete mesh.hpelements; mesh.hpelements = new Array; Array & hpelements = *mesh.hpelements; InitHPElements(mesh,hpelements); Array nplevel; nplevel.Append (mesh.GetNP()); int act_ref=1; bool sing = ClassifyHPElements (mesh,hpelements, act_ref, levels); sing = true; // iterate at least once while(sing) { cout << " Start new hp-refinement: step " << act_ref << endl; DoRefinement (mesh, hpelements, ref, fac1); DoRefineDummies (mesh, hpelements, ref); nplevel.Append (mesh.GetNP()); CalcStatistics (hpelements); SubdivideDegeneratedHexes (mesh, hpelements,fac1); ReorderPoints (mesh, hpelements); mesh.ClearSegments(); mesh.ClearSurfaceElements(); mesh.ClearVolumeElements(); for (int i = 0; i < hpelements.Size(); i++) { HPRefElement & hpel = hpelements[i]; if (Get_HPRef_Struct (hpel.type)) switch (Get_HPRef_Struct (hpel.type) -> geom) { case HP_SEGM: { Segment seg; seg[0] = hpel.pnums[0]; seg[1] = hpel.pnums[1]; // NOTE: only for less than 10000 elements (HACK) !!! seg.edgenr = hpel.index % 10000; seg.si = hpel.index / 10000; /* seg.epgeominfo[0].dist = hpel.param[0][0]; // he: war hpel.param[0][0] seg.epgeominfo[1].dist = hpel.param[1][0]; // he: war hpel.param[1][0] */ const Segment & coarseseg = mesh.coarsemesh->LineSegment(hpel.coarse_elnr+1); double d1 = coarseseg.epgeominfo[0].dist; double d2 = coarseseg.epgeominfo[1].dist; // seg.epgeominfo[0].dist = hpel.param[0][0]; // he: war hpel.param[0][0] // seg.epgeominfo[1].dist = hpel.param[1][0]; // he: war hpel.param[1][0] seg.epgeominfo[0].dist = d1 + hpel.param[0][0] * (d2-d1); // JS, June 08 seg.epgeominfo[1].dist = d1 + hpel.param[1][0] * (d2-d1); seg.epgeominfo[0].edgenr = seg.edgenr; seg.epgeominfo[1].edgenr = seg.edgenr; seg.domin = hpel.domin; seg.domout=hpel.domout; // he: needed for segments! seg.hp_elnr = i; seg.singedge_left = hpel.singedge_left; seg.singedge_right = hpel.singedge_right; mesh.AddSegment (seg); break; } case HP_TRIG: case HP_QUAD: { Element2d el(hpel.np); for(int j=0;j geom)); } } cout << " Start with Update Topology " << endl; mesh.UpdateTopology(); cout << " Mesh Update Topology done " << endl; act_ref++; sing = ClassifyHPElements(mesh,hpelements, act_ref, levels); } cout << " HP-Refinement done with " << --act_ref << " refinement steps." << endl; if(act_ref>=1) { for(ElementIndex i=0;i v(hpel.param[edges[j][0]-1][0]-hpel.param[edges[j][1]-1][0], hpel.param[edges[j][0]-1][1]-hpel.param[edges[j][1]-1][1], hpel.param[edges[j][0]-1][2]-hpel.param[edges[j][1]-1][2]); dist[edge_dir[j]] = max(v.Length(),dist[edge_dir[j]]); } int refi[3]; for(int j=0;j<3;j++) refi[j] = int(max(double(floor(log(dist[ord_dir[j]]/sqrt(2.))/log(fac1))),0.)); // cout << " ref " << refi[0] << "\t" << refi[1] << "\t" << refi[2] << endl; // cout << " order " << act_ref +1 - refi[0] << "\t" << act_ref +1 - refi[1] << "\t" << act_ref +1 - refi[2] << endl; if(setorders) mesh[i].SetOrder(act_ref+1-refi[0],act_ref+1-refi[1],act_ref+1-refi[2]); } for(SurfaceElementIndex i=0;i v(hpel.param[edges[j][0]-1][0]-hpel.param[edges[j][1]-1][0], hpel.param[edges[j][0]-1][1]-hpel.param[edges[j][1]-1][1], hpel.param[edges[j][0]-1][2]-hpel.param[edges[j][1]-1][2]); dist[edge_dir[j]] = max(v.Length(),dist[edge_dir[j]]); } int refi[3]; for(int j=0;j<3;j++) refi[j] = int(max(double(floor(log(dist[ord_dir[j]]/sqrt(2.))/log(fac1))),0.)); if(setorders) mesh[i].SetOrder(act_ref+1-refi[0],act_ref+1-refi[1],act_ref+1-refi[2]); // cout << " ref " << refi[0] << "\t" << refi[1] << endl; // cout << " order " << act_ref +1 - refi[0] << "\t" << act_ref +1 - refi[1] << endl; } } } bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint, int & levels, int & act_ref) { bool sing = 0; if (mesh.GetDimension() == 3) { /* // check, if point has as least 3 different surfs: Array surfonpoint(mesh.GetNP()); surfonpoint = INDEX_3(0,0,0); for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el = mesh[sei]; int ind = el.GetIndex(); for (int j = 0; j < el.GetNP(); j++) { INDEX_3 & i3 = surfonpoint[el[j]]; if (ind != i3.I1() && ind != i3.I2() && ind != i3.I3()) { i3.I1() = i3.I2(); i3.I2() = i3.I3(); i3.I3() = ind; } } } for (int i = 1; i <= mesh.GetNP(); i++) if (surfonpoint.Get(i).I1()) cornerpoint.Set(i); */ cornerpoint.Clear(); for (int i = 1; i <= mesh.GetNP(); i++) { if (mesh.Point(i).Singularity() * levels >= act_ref) { cornerpoint.Set(i); sing = 1; } } cout << endl; for (int i = 1; i <= mesh.GetNSeg(); i++) if (mesh.LineSegment(i).singedge_left * levels >= act_ref) { INDEX_2 i2 (mesh.LineSegment(i)[0], mesh.LineSegment(i)[1]); /* // before edges.Set (i2, 1); i2.Sort(); INDEX_2 i2s(i2.I2(), i2.I1()); edges.Set (i2s, 1); */ edges.Set (i2, 1); INDEX_2 i2s(i2.I2(), i2.I1()); edges.Set (i2s, 1); edgepoint.Set (i2.I1()); edgepoint.Set (i2.I2()); sing = 1; } // if 2 adjacent edges of an element are singular, the // commen point must be a singular point for (int i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement(i); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (el.GetType()); int nedges = MeshTopology::GetNEdges (el.GetType()); for (int j = 0; j < nedges; j++) for (int k = 0; k < nedges; k++) if (j != k) { INDEX_2 ej(el.PNum(eledges[j][0]), el.PNum(eledges[j][1])); ej.Sort(); INDEX_2 ek(el.PNum(eledges[k][0]), el.PNum(eledges[k][1])); ek.Sort(); if (edges.Used(ej) && edges.Used(ek)) { if (ej.I1() == ek.I1()) cornerpoint.Set (ek.I1()); if (ej.I1() == ek.I2()) cornerpoint.Set (ek.I2()); if (ej.I2() == ek.I1()) cornerpoint.Set (ek.I1()); if (ej.I2() == ek.I2()) cornerpoint.Set (ek.I2()); } } } edgepoint.Or (cornerpoint); (*testout) << "cornerpoint = " << endl << cornerpoint << endl; (*testout) << "edgepoint = " << endl << edgepoint << endl; facepoint = 0; for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el = mesh[sei]; const FaceDescriptor & fd = mesh.GetFaceDescriptor (el.GetIndex()); int domnr = 0; if (fd.DomainInSingular() * levels < act_ref && fd.DomainOutSingular() * levels < act_ref) { domnr=0; continue;} if (fd.DomainInSingular() * levels >= act_ref) { domnr = fd.DomainIn(); sing = 1; } if (fd.DomainOutSingular() * levels >= act_ref) { domnr = fd.DomainOut(); sing = 1; } if (fd.DomainInSingular() * levels >= act_ref && fd.DomainOutSingular() * levels >= act_ref) { domnr = -1; sing = 1; } INDEX_3 i3; if (el.GetNP() == 3) i3 = INDEX_3::Sort (el[0], el[1], el[2]); else { INDEX_4 i4 (el[0], el[1], el[2], el[3]); i4.Sort(); i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); } faces.Set (i3, domnr); for (int j = 0; j < el.GetNP(); j++) { face_edges.Set (INDEX_2::Sort (el[j], el[(j+1)%el.GetNP()]), domnr); surf_edges.Set (INDEX_2::Sort (el[j], el[(j+1)%el.GetNP()]), fd.SurfNr()+1); facepoint[el[j]] = domnr; } } (*testout) << "singular faces = " << faces << endl; (*testout) << "singular faces_edges = " << face_edges << endl; } else { // 2D case // check, if point has as least 3 different surfs: Array surfonpoint(mesh.GetNP()); for (int i = 1; i <= mesh.GetNP(); i++) surfonpoint.Elem(i) = INDEX_3(0,0,0); for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); int ind = seg.edgenr; if (seg.singedge_left * levels >= act_ref) { INDEX_2 i2 (mesh.LineSegment(i)[0], mesh.LineSegment(i)[1]); edges.Set(i2,1); edgepoint.Set(i2.I1()); edgepoint.Set(i2.I2()); *testout << " singleft " << endl; *testout << " mesh.LineSegment(i).domout " << mesh.LineSegment(i).domout << endl; *testout << " mesh.LineSegment(i).domin " << mesh.LineSegment(i).domin << endl; edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domin, i2.I1()), 1); edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domin, i2.I2()), 1); sing = 1; } if (seg.singedge_right * levels >= act_ref) { INDEX_2 i2 (mesh.LineSegment(i)[1], mesh.LineSegment(i)[0]); edges.Set (i2, 1); edgepoint.Set(i2.I1()); edgepoint.Set(i2.I2()); *testout << " singright " << endl; *testout << " mesh.LineSegment(i).domout " << mesh.LineSegment(i).domout << endl; *testout << " mesh.LineSegment(i).domin " << mesh.LineSegment(i).domin << endl; edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domout, i2.I1()), 1); edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domout, i2.I2()), 1); sing = 1; } // (*testout) << "seg = " << ind << ", " << seg[0] << "-" << seg[1] << endl; if (seg.singedge_left * levels >= act_ref || seg.singedge_right* levels >= act_ref) { for (int j = 0; j < 2; j++) { int pi = (j == 0) ? seg[0] : seg[1]; INDEX_3 & i3 = surfonpoint.Elem(pi); if (ind != i3.I1() && ind != i3.I2()) { i3.I1() = i3.I2(); i3.I2() = ind; } } } } for (int i = 1; i <= mesh.GetNP(); i++) { // mark points for refinement that are in corners between two anisotropic edges if (surfonpoint.Get(i).I1()) { // cornerpoint.Set(i); // disabled by JS, Aug 2009 edgepoint.Set(i); } // mark points for refinement that are explicitly specified in input file if (mesh.Point(i).Singularity()*levels >= act_ref) { cornerpoint.Set(i); edgepoint.Set(i); sing = 1; } } edgepoint.Or (cornerpoint); (*testout) << "2d sing edges: " << endl << edges << endl; (*testout) << "2d cornerpoints: " << endl << cornerpoint << endl << "2d edgepoints: " << endl << edgepoint << endl; facepoint = 0; } if (!sing) cout << "PrepareElements no more to do for actual refinement " << act_ref << endl; return(sing); } bool ClassifyHPElements (Mesh & mesh, Array & elements, int & act_ref, int & levels) { INDEX_2_HASHTABLE edges(mesh.GetNSeg()+1); BitArray edgepoint(mesh.GetNP()); INDEX_2_HASHTABLE edgepoint_dom(mesh.GetNSeg()+1); edgepoint.Clear(); BitArray cornerpoint(mesh.GetNP()); cornerpoint.Clear(); // value = nr > 0 ... refine elements in domain nr // value = -1 ..... refine elements in any domain INDEX_3_HASHTABLE faces(mesh.GetNSE()+1); INDEX_2_HASHTABLE face_edges(mesh.GetNSE()+1); INDEX_2_HASHTABLE surf_edges(mesh.GetNSE()+1); Array facepoint(mesh.GetNP()); bool sing = CheckSingularities(mesh, edges, edgepoint_dom, cornerpoint, edgepoint, faces, face_edges, surf_edges, facepoint, levels, act_ref); if(sing==0) return(sing); int cnt_undef = 0, cnt_nonimplement = 0; Array misses(10000); misses = 0; (*testout) << "edgepoint_dom = " << endl << edgepoint_dom << endl; for( int i = 0; igeom) { case HP_TET: { hpel.type = ClassifyTet(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces,face_edges, surf_edges, facepoint); break; } case HP_PRISM: { hpel.type = ClassifyPrism(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, face_edges, surf_edges, facepoint); break; } case HP_HEX: { hpel.type = ClassifyHex(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, face_edges, surf_edges, facepoint); break; } case HP_TRIG: { int dim = mesh.GetDimension(); const FaceDescriptor & fd = mesh.GetFaceDescriptor (hpel.GetIndex()); hpel.type = ClassifyTrig(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, face_edges, surf_edges, facepoint, dim, fd); dd = 2; break; } case HP_QUAD: { int dim = mesh.GetDimension(); const FaceDescriptor & fd = mesh.GetFaceDescriptor (hpel.GetIndex()); hpel.type = ClassifyQuad(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, face_edges, surf_edges, facepoint, dim, fd); dd = 2; break; } case HP_SEGM: { hpel.type = ClassifySegm(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, face_edges, surf_edges, facepoint); dd = 1; break; } case HP_PYRAMID: { hpel.type = ClassifyPyramid(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, face_edges, surf_edges, facepoint); cout << " ** Pyramid classified " << hpel.type << endl; break; } default: { cout << "illegal element type for hp-prepare elements " << hpel.type << endl; throw NgException ("hprefinement.cpp: don't know how to set parameters"); } } if(hpel.type == HP_NONE) cnt_undef++; //else //cout << "elem " << i << " classified type " << hpel.type << endl; if (!Get_HPRef_Struct (hpel.type)) { (*testout) << "hp-element-type " << hpel.type << " not implemented " << endl; (*testout) << " elType " << hprs->geom << endl; (cout) << " elType " << hprs->geom << endl; cnt_nonimplement++; misses[hpel.type]++; } for(int j=0; j #include "meshing.hpp" namespace netgen { netrule :: netrule () { name = new char[1]; name[0] = char(0); quality = 0; } netrule :: ~netrule() { delete [] name; for(int i = 0; i < oldutofreearea_i.Size(); i++) delete oldutofreearea_i[i]; for(int i = 0; i < freezone_i.Size(); i++) delete freezone_i[i]; } void netrule :: SetFreeZoneTransformation (const Vector & devp, int tolclass) { double lam1 = 1.0/tolclass; double lam2 = 1.-lam1; double mem1[100], mem2[100], mem3[100]; int vs = oldutofreearea.Height(); FlatVector devfree(vs, mem1); int fzs = freezone.Size(); transfreezone.SetSize (fzs); if (tolclass <= oldutofreearea_i.Size()) { oldutofreearea_i[tolclass-1] -> Mult (devp, devfree); Array & fzi = *freezone_i[tolclass-1]; for (int i = 0; i < fzs; i++) { transfreezone[i].X() = fzi[i].X() + devfree[2*i]; transfreezone[i].Y() = fzi[i].Y() + devfree[2*i+1]; } } else { FlatVector devfree1(vs, mem2); FlatVector devfree2(vs, mem3); oldutofreearea.Mult (devp, devfree1); oldutofreearealimit.Mult (devp, devfree2); devfree.Set2 (lam1, devfree1, lam2, devfree2); for (int i = 0; i < fzs; i++) { transfreezone[i].X() = lam1 * freezone[i].X() + lam2 * freezonelimit[i].X() + devfree[2*i]; transfreezone[i].Y() = lam1 * freezone[i].Y() + lam2 * freezonelimit[i].Y() + devfree[2*i+1]; } } if (fzs > 0) { fzmaxx = fzminx = transfreezone[0].X(); fzmaxy = fzminy = transfreezone[0].Y(); } for (int i = 1; i < fzs; i++) { if (transfreezone[i].X() > fzmaxx) fzmaxx = transfreezone[i].X(); if (transfreezone[i].X() < fzminx) fzminx = transfreezone[i].X(); if (transfreezone[i].Y() > fzmaxy) fzmaxy = transfreezone[i].Y(); if (transfreezone[i].Y() < fzminy) fzminy = transfreezone[i].Y(); } for (int i = 0; i < fzs; i++) { Point2d p1 = transfreezone[i]; Point2d p2 = transfreezone[(i+1) % fzs]; Vec2d vn (p2.Y() - p1.Y(), p1.X() - p2.X()); double len2 = vn.Length2(); if (len2 < 1e-10) { freesetinequ(i, 0) = 0; freesetinequ(i, 1) = 0; freesetinequ(i, 2) = -1; } else { vn /= sqrt (len2); // scaling necessary ? freesetinequ(i,0) = vn.X(); freesetinequ(i,1) = vn.Y(); freesetinequ(i,2) = -(p1.X() * vn.X() + p1.Y() * vn.Y()); } } } /* int netrule :: IsInFreeZone2 (const Point2d & p) const { for (int i = 0; i < transfreezone.Size(); i++) { if (freesetinequ(i, 0) * p.X() + freesetinequ(i, 1) * p.Y() + freesetinequ(i, 2) > 0) return 0; } return 1; } */ int netrule :: IsLineInFreeZone2 (const Point2d & p1, const Point2d & p2) const { if ( (p1.X() > fzmaxx && p2.X() > fzmaxx) || (p1.X() < fzminx && p2.X() < fzminx) || (p1.Y() > fzmaxy && p2.Y() > fzmaxy) || (p1.Y() < fzminy && p2.Y() < fzminy) ) return 0; for (int i = 1; i <= transfreezone.Size(); i++) { if (freesetinequ.Get(i, 1) * p1.X() + freesetinequ.Get(i, 2) * p1.Y() + freesetinequ.Get(i, 3) > -1e-8 && // -1e-6 freesetinequ.Get(i, 1) * p2.X() + freesetinequ.Get(i, 2) * p2.Y() + freesetinequ.Get(i, 3) > -1e-8 // -1e-6 ) return 0; } double nx = (p2.Y() - p1.Y()); double ny = -(p2.X() - p1.X()); double nl = sqrt (nx * nx + ny * ny); if (nl > 1e-8) { nx /= nl; ny /= nl; double c = - (p1.X() * nx + p1.Y() * ny); bool allleft = true; bool allright = true; for (int i = 1; i <= transfreezone.Size(); i++) { bool left = transfreezone.Get(i).X() * nx + transfreezone.Get(i).Y() * ny + c < 1e-7; bool right = transfreezone.Get(i).X() * nx + transfreezone.Get(i).Y() * ny + c > -1e-7; if (!left) allleft = false; if (!right) allright = false; } if (allleft || allright) return false; } return true; } int netrule :: ConvexFreeZone () const { int n = transfreezone.Size(); for (int i = 1; i <= n; i++) { const bool counterclockwise = CCW (transfreezone.Get(i), transfreezone.Get(i % n + 1), transfreezone.Get( (i+1) % n + 1 ), 1e-7); //(*testout) << "ccw " << counterclockwise << endl << " p1 " << transfreezone.Get(i) << " p2 " << transfreezone.Get(i % n + 1) // << " p3 " << transfreezone.Get( (i+1) % n + 1 ) << endl; if (!counterclockwise ) return 0; } return 1; } /* float netrule :: CalcPointDist (int pi, const Point2d & p) const { float dx = p.X() - points.Get(pi).X(); float dy = p.Y() - points.Get(pi).Y(); const threefloat * tf = &tolerances.Get(pi); return tf->f1 * dx * dx + tf->f2 * dx * dy + tf->f3 * dy * dy; } */ float netrule :: CalcLineError (int li, const Vec2d & v) const { float dx = v.X() - linevecs.Get(li).X(); float dy = v.Y() - linevecs.Get(li).Y(); const threefloat * ltf = &linetolerances.Get(li); return ltf->f1 * dx * dx + ltf->f2 * dx * dy + ltf->f3 * dy * dy; } /* int GetNRules () { return rules.Size(); } */ } netgen-6.2.1905/libsrc/meshing/triarls.cpp0000644000175000017500000001737313504650527017110 0ustar kurtkurtnamespace netgen { const char * triarules[] = { "rule \"Free Triangle (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0) { 1.0, 0, 1.0 };\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 0.5 X2 } { };\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.7) { 0.5 X2 } { };\n",\ "(0.5, 1.5) { 0.5 X2 } { };\n",\ "(-0.5, 0.7) { 0.5 X2 } { };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.866) { 0.5 X2 } { };\n",\ "(0.5, 0.866) { 0.5 X2 } { };\n",\ "(0.5, 0.866) { 0.5 X2 } { };\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "rule \"Free Triangle (5)\"\n",\ "\n",\ "quality 5\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0) { 1.0, 0, 1.0 };\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.5) { 0.5 X2 } { };\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.7) { 1 X2 } { };\n",\ "(0, 0.7) { } { };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.5) { 0.5 X2 } { };\n",\ "(0.5, 0.5) { 0.5 X2 } { };\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Free Triangle (10)\"\n",\ "\n",\ "quality 10\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0) { 1.0, 0, 1.0 };\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.3) { 0.5 X2 } { };\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.5) { 1 X2 } { };\n",\ "(0, 0.5) { } { };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.3) { 0.5 X2 } { };\n",\ "(0.5, 0.3) { 0.5 X2 } { };\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Free Triangle (20)\"\n",\ "\n",\ "quality 20\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0) { 1.0, 0, 1.0 };\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.1) { 0.5 X2 } { };\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.2) { 1 X2 } { };\n",\ "(0, 0.2) { } { };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.1) { 0.5 X2 } { };\n",\ "(0.5, 0.1) { 0.5 X2 } { };\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Right 60 (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0) { 0.5, 0, 1.0 };\n",\ "(0.5, 0.866) { 0.6, 0, 0.8 };\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left 60 (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 1) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.125, 0.6495) { 0.75 X2, 0.75 X3 } { 0.75 Y3 };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Right 120 (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(1, 4);\n",\ "(4, 3);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(1, 1.732) { -2 X2, 2 X3 } { 2 Y3 };\n",\ "(0, 1.732) { -3 X2, 2 X3 } { 2 Y3 };\n",\ "(-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4);\n",\ "(2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left 120 (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(-0.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 1) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(3, 4);\n",\ "(4, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 };\n",\ "(1, 1.732) { 2 X2, 2 X3 } { 2 Y3 };\n",\ "(0, 1.732) { 1 X2, 2 X3 } { 2 Y3 };\n",\ "(-0.5, 0.866) { 1 X3 } {1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4);\n",\ "(1, 4, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left Right 120 (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(-0.5, 0.866);\n",\ "(1.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 1) del;\n",\ "(2, 4) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ "\n",\ "newlines\n",\ "(3, 5);\n",\ "(5, 4);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.866) { 1 X4 } { 1 Y4 };\n",\ "(1, 1.299) { -0.5 X2, 0.375 X3, 1.125 X4 } { -0.5 Y2, 0.375 Y3, 1.125 Y4 };\n",\ "(0, 1.299) { 1.125 X3, 0.375 X4 } { 1.125 Y3, 0.375 Y4 };\n",\ "(-0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 5);\n",\ "(3, 1, 5);\n",\ "(2, 4, 5);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "rule \"Fill Triangle\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "(3, 1) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { 1 Y2 };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Vis A Vis (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.2, 0.693) { 0.8 X2, 0.8 X3 } { 0.8 Y2, 0.8 Y3 };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(-0.2, 0.693) { -0.6 X2, 0.8 X3 } { -0.6 Y2, 0.8 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"2 h Vis A Vis (1)\"\n",\ "\n",\ "quality 3\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1.732);\n",\ "(0, 1.732);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 4) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 };\n",\ "\n",\ "newlines\n",\ "(1, 5);\n",\ "(5, 4);\n",\ "(3, 5);\n",\ "(5, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { 1 Y2 };\n",\ "(1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 };\n",\ "(1, 1.732) { 1 X3 } { 1 Y3 };\n",\ "(0, 1.732) { 1 X4 } { 1 Y4 };\n",\ "(-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 5);\n",\ "(3, 4, 5);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ 0}; } netgen-6.2.1905/libsrc/meshing/meshtype.cpp0000644000175000017500000020565713504650527017272 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { int MultiPointGeomInfo :: AddPointGeomInfo (const PointGeomInfo & gi) { for (int k = 0; k < cnt; k++) if (mgi[k].trignum == gi.trignum) return 0; if (cnt < MULTIPOINTGEOMINFO_MAX) { mgi[cnt] = gi; cnt++; return 0; } throw NgException ("Please report error: MPGI Size too small\n"); } #ifdef PARALLEL MPI_Datatype MeshPoint :: MyGetMPIType ( ) { static MPI_Datatype type = NULL; static MPI_Datatype htype = NULL; if (!type) { MeshPoint hp; int blocklen[] = { 3, 1, 1 }; MPI_Aint displ[] = { (char*)&hp.x[0] - (char*)&hp, (char*)&hp.layer - (char*)&hp, (char*)&hp.singular - (char*)&hp }; MPI_Datatype types[] = { MPI_DOUBLE, MPI_INT, MPI_DOUBLE }; *testout << "displ = " << displ[0] << ", " << displ[1] << ", " << displ[2] << endl; *testout << "sizeof = " << sizeof (MeshPoint) << endl; MPI_Type_create_struct (3, blocklen, displ, types, &htype); MPI_Type_commit ( &htype ); MPI_Aint lb, ext; MPI_Type_get_extent (htype, &lb, &ext); *testout << "lb = " << lb << endl; *testout << "ext = " << ext << endl; ext = sizeof (MeshPoint); MPI_Type_create_resized (htype, lb, ext, &type); MPI_Type_commit ( &type ); } return type; } #endif Segment :: Segment() : is_curved(false) { pnums[0] = -1; pnums[1] = -1; edgenr = -1; singedge_left = 0.; singedge_right = 0.; seginfo = 0; si = -1; domin = -1; domout = -1; tlosurf = -1; surfnr1 = -1; surfnr2 = -1; pnums[2] = -1; meshdocval = 0; /* geominfo[0].trignum=-1; geominfo[1].trignum=-1; epgeominfo[0].edgenr = 1; epgeominfo[0].dist = 0; epgeominfo[1].edgenr = 1; epgeominfo[1].dist = 0; */ bcname = nullptr; } Segment::Segment (const Segment & other) : edgenr(other.edgenr), singedge_left(other.singedge_left), singedge_right(other.singedge_right), seginfo(other.seginfo), si(other.si), domin(other.domin), domout(other.domout), tlosurf(other.tlosurf), geominfo(), surfnr1(other.surfnr1), surfnr2(other.surfnr2), epgeominfo(), meshdocval(other.meshdocval), is_curved(other.is_curved), hp_elnr(other.hp_elnr) { for (int j = 0; j < 3; j++) pnums[j] = other.pnums[j]; geominfo[0] = other.geominfo[0]; geominfo[1] = other.geominfo[1]; epgeominfo[0] = other.epgeominfo[0]; epgeominfo[1] = other.epgeominfo[1]; bcname = other.bcname; } Segment& Segment::operator=(const Segment & other) { if (&other != this) { pnums[0] = other[0]; pnums[1] = other[1]; edgenr = other.edgenr; singedge_left = other.singedge_left; singedge_right = other.singedge_right; seginfo = other.seginfo; si = other.si; domin = other.domin; domout = other.domout; tlosurf = other.tlosurf; geominfo[0] = other.geominfo[0]; geominfo[1] = other.geominfo[1]; surfnr1 = other.surfnr1; surfnr2 = other.surfnr2; epgeominfo[0] = other.epgeominfo[0]; epgeominfo[1] = other.epgeominfo[1]; pnums[2] = other.pnums[2]; meshdocval = other.meshdocval; hp_elnr = other.hp_elnr; bcname = other.bcname; is_curved = other.is_curved; } return *this; } void Segment :: DoArchive (Archive & ar) { ar & pnums[0] & pnums[1] & pnums[2] & edgenr & singedge_left & singedge_right & si & cd2i & domin & domout & tlosurf & surfnr1 & surfnr2 & bcname & epgeominfo[0].edgenr & epgeominfo[1].edgenr; } ostream & operator<<(ostream & s, const Segment & seg) { s << seg[0] << "(gi=" << seg.geominfo[0].trignum << ") - " << seg[1] << "(gi=" << seg.geominfo[1].trignum << ")" << " domin = " << seg.domin << ", domout = " << seg.domout << " si = " << seg.si << ", edgenr = " << seg.edgenr; return s; } /* Element2d :: Element2d () { for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) { pnum[i] = 0; geominfo[i].trignum = 0; } np = 3; index = 0; badel = 0; deleted = 0; visible = 1; typ = TRIG; orderx = ordery = 1; refflag = 1; strongrefflag = false; is_curved = false; } */ Element2d :: Element2d (int anp) { for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) { pnum[i] = 0; geominfo[i].trignum = 0; } np = anp; index = 0; badel = 0; deleted = 0; visible = 1; switch (np) { case 3: typ = TRIG; break; case 4: typ = QUAD; break; case 6: typ = TRIG6; break; case 8: typ = QUAD8; break; } orderx = ordery = 1; refflag = 1; strongrefflag = false; is_curved = (np >= 4); // false; } Element2d :: Element2d (ELEMENT_TYPE atyp) { for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) { pnum[i] = 0; geominfo[i].trignum = 0; } SetType (atyp); index = 0; badel = 0; deleted = 0; visible = 1; orderx = ordery = 1; refflag = 1; strongrefflag = false; is_curved = (np >= 4); // false; } Element2d :: Element2d (int pi1, int pi2, int pi3) { pnum[0] = pi1; pnum[1] = pi2; pnum[2] = pi3; np = 3; typ = TRIG; pnum[3] = 0; pnum[4] = 0; pnum[5] = 0; for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) geominfo[i].trignum = 0; index = 0; badel = 0; refflag = 1; strongrefflag = false; deleted = 0; visible = 1; orderx = ordery = 1; is_curved = false; } Element2d :: Element2d (int pi1, int pi2, int pi3, int pi4) { pnum[0] = pi1; pnum[1] = pi2; pnum[2] = pi3; pnum[3] = pi4; np = 4; typ = QUAD; pnum[4] = 0; pnum[5] = 0; for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) geominfo[i].trignum = 0; index = 0; badel = 0; refflag = 1; strongrefflag = false; deleted = 0; visible = 1; orderx = ordery = 1; is_curved = true; } /* void Element2d :: SetType (ELEMENT_TYPE atyp) { typ = atyp; switch (typ) { case TRIG: np = 3; break; case QUAD: np = 4; break; case TRIG6: np = 6; break; case QUAD6: np = 6; break; default: PrintSysError ("Element2d::SetType, illegal type ", typ); } } */ void Element2d :: GetBox (const T_POINTS & points, Box3d & box) const { box.SetPoint (points.Get(pnum[0])); for (unsigned i = 1; i < np; i++) box.AddPoint (points.Get(pnum[i])); } bool Element2d :: operator==(const Element2d & el2) const { bool retval = (el2.GetNP() == np); for(int i= 0; retval && i ipdtrig; Array ipdquad; int Element2d :: GetNIP () const { int nip; switch (np) { case 3: nip = 1; break; case 4: nip = 4; break; default: nip = 0; break; } return nip; } void Element2d :: GetIntegrationPoint (int ip, Point2d & p, double & weight) const { static double eltriqp[1][3] = { { 1.0/3.0, 1.0/3.0, 0.5 } }; static double elquadqp[4][3] = { { 0, 0, 0.25 }, { 0, 1, 0.25 }, { 1, 0, 0.25 }, { 1, 1, 0.25 } }; double * pp = 0; switch (typ) { case TRIG: pp = &eltriqp[0][0]; break; case QUAD: pp = &elquadqp[ip-1][0]; break; default: PrintSysError ("Element2d::GetIntegrationPoint, illegal type ", int(typ)); } p.X() = pp[0]; p.Y() = pp[1]; weight = pp[2]; } void Element2d :: GetTransformation (int ip, const Array & points, DenseMatrix & trans) const { int np = GetNP(); DenseMatrix pmat(2, np), dshape(2, np); pmat.SetSize (2, np); dshape.SetSize (2, np); Point2d p; double w; GetPointMatrix (points, pmat); GetIntegrationPoint (ip, p, w); GetDShape (p, dshape); CalcABt (pmat, dshape, trans); /* (*testout) << "p = " << p << endl << "pmat = " << pmat << endl << "dshape = " << dshape << endl << "tans = " << trans << endl; */ } void Element2d :: GetTransformation (int ip, class DenseMatrix & pmat, class DenseMatrix & trans) const { // int np = GetNP(); #ifdef DEBUG if (pmat.Width() != np || pmat.Height() != 2) { (*testout) << "GetTransofrmation: pmat doesn't fit" << endl; return; } #endif ComputeIntegrationPointData (); DenseMatrix * dshapep = NULL; switch (typ) { case TRIG: dshapep = &ipdtrig.Get(ip)->dshape; break; case QUAD: dshapep = &ipdquad.Get(ip)->dshape; break; default: PrintSysError ("Element2d::GetTransformation, illegal type ", int(typ)); } CalcABt (pmat, *dshapep, trans); } void Element2d :: GetShape (const Point2d & p, Vector & shape) const { if (shape.Size() != GetNP()) { cerr << "Element::GetShape: Length not fitting" << endl; return; } switch (typ) { case TRIG: shape(0) = 1 - p.X() - p.Y(); shape(1) = p.X(); shape(2) = p.Y(); break; case QUAD: shape(0) = (1-p.X()) * (1-p.Y()); shape(1) = p.X() * (1-p.Y()); shape(2) = p.X() * p.Y(); shape(3) = (1-p.X()) * p.Y(); break; default: PrintSysError ("Element2d::GetShape, illegal type ", int(typ)); } } void Element2d :: GetShapeNew (const Point<2> & p, FlatVector & shape) const { switch (typ) { case TRIG: { shape(0) = p(0); shape(1) = p(1); shape(2) = 1-p(0)-p(1); break; } case QUAD: { shape(0) = (1-p(0))*(1-p(1)); shape(1) = p(0) *(1-p(1)); shape(2) = p(0) * p(1) ; shape(3) = (1-p(0))* p(1) ; break; } default: throw NgException ("illegal element type in GetShapeNew"); } } template void Element2d :: GetShapeNew (const Point<2,T> & p, TFlatVector shape) const { switch (typ) { case TRIG: { shape(0) = p(0); shape(1) = p(1); shape(2) = 1-p(0)-p(1); break; } case QUAD: { shape(0) = (1-p(0))*(1-p(1)); shape(1) = p(0) *(1-p(1)); shape(2) = p(0) * p(1) ; shape(3) = (1-p(0))* p(1) ; break; } default: throw NgException ("illegal element type in GetShapeNew"); } } void Element2d :: GetDShape (const Point2d & p, DenseMatrix & dshape) const { #ifdef DEBUG if (dshape.Height() != 2 || dshape.Width() != np) { PrintSysError ("Element::DShape: Sizes don't fit"); return; } #endif switch (typ) { case TRIG: dshape.Elem(1, 1) = -1; dshape.Elem(1, 2) = 1; dshape.Elem(1, 3) = 0; dshape.Elem(2, 1) = -1; dshape.Elem(2, 2) = 0; dshape.Elem(2, 3) = 1; break; case QUAD: dshape.Elem(1, 1) = -(1-p.Y()); dshape.Elem(1, 2) = (1-p.Y()); dshape.Elem(1, 3) = p.Y(); dshape.Elem(1, 4) = -p.Y(); dshape.Elem(2, 1) = -(1-p.X()); dshape.Elem(2, 2) = -p.X(); dshape.Elem(2, 3) = p.X(); dshape.Elem(2, 4) = (1-p.X()); break; default: PrintSysError ("Element2d::GetDShape, illegal type ", int(typ)); } } template void Element2d :: GetDShapeNew (const Point<2,T> & p, MatrixFixWidth<2,T> & dshape) const { switch (typ) { case TRIG: { dshape = T(0.0); dshape(0,0) = 1; dshape(1,1) = 1; dshape(2,0) = -1; dshape(2,1) = -1; break; } case QUAD: { dshape(0,0) = -(1-p(1)); dshape(0,1) = -(1-p(0)); dshape(1,0) = (1-p(1)); dshape(1,1) = -p(0); dshape(2,0) = p(1); dshape(2,1) = p(0); dshape(3,0) = -p(1); dshape(3,1) = (1-p(0)); break; } default: throw NgException ("illegal element type in GetDShapeNew"); } } void Element2d :: GetPointMatrix (const Array & points, DenseMatrix & pmat) const { int np = GetNP(); #ifdef DEBUG if (pmat.Width() != np || pmat.Height() != 2) { cerr << "Element::GetPointMatrix: sizes don't fit" << endl; return; } #endif for (int i = 1; i <= np; i++) { const Point2d & p = points.Get(PNum(i)); pmat.Elem(1, i) = p.X(); pmat.Elem(2, i) = p.Y(); } } double Element2d :: CalcJacobianBadness (const Array & points) const { int i, j; int nip = GetNIP(); DenseMatrix trans(2,2); DenseMatrix pmat; pmat.SetSize (2, GetNP()); GetPointMatrix (points, pmat); double err = 0; for (i = 1; i <= nip; i++) { GetTransformation (i, pmat, trans); // Frobenius norm double frob = 0; for (j = 1; j <= 4; j++) frob += sqr (trans.Get(j)); frob = sqrt (frob); frob /= 2; double det = trans.Det(); if (det <= 0) err += 1e12; else err += frob * frob / det; } err /= nip; return err; } static const int qip_table[4][4] = { { 0, 1, 0, 3 }, { 0, 1, 1, 2 }, { 3, 2, 0, 3 }, { 3, 2, 1, 2 } }; double Element2d :: CalcJacobianBadnessDirDeriv (const Array & points, int pi, Vec2d & dir, double & dd) const { if (typ == QUAD) { Mat<2,2> trans, dtrans; Mat<2,4> vmat, pmat; for (int j = 0; j < 4; j++) { const Point2d & p = points.Get( (*this)[j] ); pmat(0, j) = p.X(); pmat(1, j) = p.Y(); } vmat = 0.0; vmat(0, pi-1) = dir.X(); vmat(1, pi-1) = dir.Y(); double err = 0; dd = 0; for (int i = 0; i < 4; i++) { int ix1 = qip_table[i][0]; int ix2 = qip_table[i][1]; int iy1 = qip_table[i][2]; int iy2 = qip_table[i][3]; trans(0,0) = pmat(0, ix2) - pmat(0,ix1); trans(1,0) = pmat(1, ix2) - pmat(1,ix1); trans(0,1) = pmat(0, iy2) - pmat(0,iy1); trans(1,1) = pmat(1, iy2) - pmat(1,iy1); double det = trans(0,0)*trans(1,1)-trans(1,0)*trans(0,1); if (det <= 0) { dd = 0; return 1e12; } dtrans(0,0) = vmat(0, ix2) - vmat(0,ix1); dtrans(1,0) = vmat(1, ix2) - vmat(1,ix1); dtrans(0,1) = vmat(0, iy2) - vmat(0,iy1); dtrans(1,1) = vmat(1, iy2) - vmat(1,iy1); // Frobenius norm double frob = 0; for (int j = 0; j < 4; j++) frob += sqr (trans(j)); frob = sqrt (frob); double dfrob = 0; for (int j = 0; j < 4; j++) dfrob += trans(j) * dtrans(j); dfrob = dfrob / frob; frob /= 2; dfrob /= 2; // ddet = \sum_j det (m_j) with m_j = trans, except col j = dtrans double ddet = dtrans(0,0) * trans(1,1) - trans(0,1) * dtrans(1,0) + trans(0,0) * dtrans(1,1) - dtrans(0,1) * trans(1,0); err += frob * frob / det; dd += (2 * frob * dfrob * det - frob * frob * ddet) / (det * det); } err /= 4; dd /= 4; return err; } int nip = GetNIP(); DenseMatrix trans(2,2), dtrans(2,2); DenseMatrix pmat, vmat; pmat.SetSize (2, GetNP()); vmat.SetSize (2, GetNP()); GetPointMatrix (points, pmat); vmat = 0.0; vmat.Elem(1, pi) = dir.X(); vmat.Elem(2, pi) = dir.Y(); double err = 0; dd = 0; for (int i = 1; i <= nip; i++) { GetTransformation (i, pmat, trans); GetTransformation (i, vmat, dtrans); // Frobenius norm double frob = 0; for (int j = 1; j <= 4; j++) frob += sqr (trans.Get(j)); frob = sqrt (frob); double dfrob = 0; for (int j = 1; j <= 4; j++) dfrob += trans.Get(j) * dtrans.Get(j); dfrob = dfrob / frob; frob /= 2; dfrob /= 2; double det = trans(0,0)*trans(1,1)-trans(1,0)*trans(0,1); // ddet = \sum_j det (m_j) with m_j = trans, except col j = dtrans double ddet = dtrans(0,0) * trans(1,1) - trans(0,1) * dtrans(1,0) + trans(0,0) * dtrans(1,1) - dtrans(0,1) * trans(1,0); if (det <= 0) err += 1e12; else { err += frob * frob / det; dd += (2 * frob * dfrob * det - frob * frob * ddet) / (det * det); } } err /= nip; dd /= nip; return err; } double Element2d :: CalcJacobianBadness (const T_POINTS & points, const Vec<3> & n) const { int i, j; int nip = GetNIP(); DenseMatrix trans(2,2); DenseMatrix pmat; pmat.SetSize (2, GetNP()); Vec<3> t1, t2; t1 = n.GetNormal(); t2 = Cross (n, t1); for (i = 1; i <= GetNP(); i++) { Point3d p = points.Get(PNum(i)); pmat.Elem(1, i) = p.X() * t1(0) + p.Y() * t1(1) + p.Z() * t1(2); pmat.Elem(2, i) = p.X() * t2(0) + p.Y() * t2(1) + p.Z() * t2(2); } double err = 0; for (i = 1; i <= nip; i++) { GetTransformation (i, pmat, trans); // Frobenius norm double frob = 0; for (j = 1; j <= 4; j++) frob += sqr (trans.Get(j)); frob = sqrt (frob); frob /= 2; double det = trans.Det(); if (det <= 0) err += 1e12; else err += frob * frob / det; } err /= nip; return err; } void Element2d :: ComputeIntegrationPointData () const { switch (np) { case 3: if (ipdtrig.Size()) return; break; case 4: if (ipdquad.Size()) return; break; } for (int i = 1; i <= GetNIP(); i++) { IntegrationPointData * ipd = new IntegrationPointData; Point2d hp; GetIntegrationPoint (i, hp, ipd->weight); ipd->p(0) = hp.X(); ipd->p(1) = hp.Y(); ipd->p(2) = 0; ipd->shape.SetSize(GetNP()); ipd->dshape.SetSize(2, GetNP()); GetShape (hp, ipd->shape); GetDShape (hp, ipd->dshape); switch (np) { case 3: ipdtrig.Append (ipd); break; case 4: ipdquad.Append (ipd); break; } } } ostream & operator<<(ostream & s, const Element0d & el) { s << el.pnum << ", index = " << el.index; return s; } ostream & operator<<(ostream & s, const Element2d & el) { s << "np = " << el.GetNP(); for (int j = 1; j <= el.GetNP(); j++) s << " " << el.PNum(j); return s; } ostream & operator<<(ostream & s, const Element & el) { s << "np = " << el.GetNP(); for (int j = 0; j < el.GetNP(); j++) s << " " << int(el[j]); return s; } /* Element :: Element () { typ = TET; np = 4; for (int i = 0; i < ELEMENT_MAXPOINTS; i++) pnum[i] = 0; index = 0; flags.marked = 1; flags.badel = 0; flags.reverse = 0; flags.illegal = 0; flags.illegal_valid = 0; flags.badness_valid = 0; flags.refflag = 1; flags.strongrefflag = false; flags.deleted = 0; flags.fixed = 0; orderx = ordery = orderz = 1; is_curved = false; #ifdef PARALLEL partitionNumber = -1; #endif } */ Element :: Element (int anp) { np = anp; int i; for (i = 0; i < ELEMENT_MAXPOINTS; i++) pnum[i] = 0; index = 0; flags.marked = 1; flags.badel = 0; flags.reverse = 0; flags.illegal = 0; flags.illegal_valid = 0; flags.badness_valid = 0; flags.refflag = 1; flags.strongrefflag = false; flags.deleted = 0; flags.fixed = 0; switch (np) { case 4: typ = TET; break; case 5: typ = PYRAMID; break; case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; case 13: typ = PYRAMID13; break; case 15: typ = PRISM15; break; case 20: typ = HEX20; break; default: cerr << "Element::Element: unknown element with " << np << " points" << endl; } orderx = ordery = orderz = 1; is_curved = typ != TET; // false; } void Element :: SetOrder (const int aorder) { orderx = aorder; ordery = aorder; orderz = aorder; } void Element :: SetOrder (const int ox, const int oy, const int oz) { orderx = ox; ordery = oy; orderz = oz; } Element :: Element (ELEMENT_TYPE type) { SetType (type); int i; for (i = 0; i < ELEMENT_MAXPOINTS; i++) pnum[i] = 0; index = 0; flags.marked = 1; flags.badel = 0; flags.reverse = 0; flags.illegal = 0; flags.illegal_valid = 0; flags.badness_valid = 0; flags.refflag = 1; flags.strongrefflag = false; flags.deleted = 0; flags.fixed = 0; orderx = ordery = orderz = 1; is_curved = typ != TET; // false; // #ifdef PARALLEL // partitionNumber = -1; // #endif } /* Element & Element :: operator= (const Element & el2) { typ = el2.typ; np = el2.np; for (int i = 0; i < ELEMENT_MAXPOINTS; i++) pnum[i] = el2.pnum[i]; index = el2.index; flags = el2.flags; orderx = el2.orderx; ordery = el2.ordery; orderz = el2.orderz; hp_elnr = el2.hp_elnr; flags = el2.flags; is_curved = el2.is_curved; return *this; } */ void Element :: SetNP (int anp) { np = anp; switch (np) { case 4: typ = TET; break; case 5: typ = PYRAMID; break; case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; case 13: typ = PYRAMID13; break; case 15: typ = PRISM15; break; case 20: typ = HEX20; break; // default: break; cerr << "Element::SetNP unknown element with " << np << " points" << endl; } } void Element :: SetType (ELEMENT_TYPE atyp) { typ = atyp; switch (atyp) { case TET: np = 4; break; case PYRAMID: np = 5; break; case PRISM: np = 6; break; case HEX: np = 8; break; case TET10: np = 10; break; case PYRAMID13: np = 13; break; case PRISM12: np = 12; break; case PRISM15: np = 15; break; case HEX20: np = 20; break; default: break; cerr << "Element::SetType unknown type " << int(typ) << endl; } is_curved = (np > 4); } void Element :: Invert() { switch (GetNP()) { case 4: { Swap (PNum(3), PNum(4)); break; } case 5: { Swap (PNum(1), PNum(4)); Swap (PNum(2), PNum(3)); break; } case 6: { Swap (PNum(1), PNum(4)); Swap (PNum(2), PNum(5)); Swap (PNum(3), PNum(6)); break; } } } void Element :: Print (ostream & ost) const { ost << np << " Points: "; for (int i = 1; i <= np; i++) ost << pnum[i-1] << " " << endl; } void Element :: GetBox (const T_POINTS & points, Box3d & box) const { box.SetPoint (points.Get(PNum(1))); box.AddPoint (points.Get(PNum(2))); box.AddPoint (points.Get(PNum(3))); box.AddPoint (points.Get(PNum(4))); } double Element :: Volume (const T_POINTS & points) const { Vec<3> v1 = points.Get(PNum(2)) - points.Get(PNum(1)); Vec<3> v2 = points.Get(PNum(3)) - points.Get(PNum(1)); Vec<3> v3 = points.Get(PNum(4)) - points.Get(PNum(1)); return -(Cross (v1, v2) * v3) / 6; } void Element :: GetFace2 (int i, Element2d & face) const { static const int tetfaces[][5] = { { 3, 2, 3, 4, 0 }, { 3, 3, 1, 4, 0 }, { 3, 1, 2, 4, 0 }, { 3, 2, 1, 3, 0 } }; static const int tet10faces[][7] = { { 3, 2, 3, 4, 10, 9, 8 }, { 3, 3, 1, 4, 7, 10, 6 }, { 3, 1, 2, 4, 9, 7, 5 }, { 3, 2, 1, 3, 6, 8, 5 } }; static const int pyramidfaces[][5] = { { 4, 1, 4, 3, 2 }, { 3, 1, 2, 5, 0 }, { 3, 2, 3, 5, 0 }, { 3, 3, 4, 5, 0 }, { 3, 4, 1, 5, 0 } }; static const int prismfaces[][5] = { { 3, 1, 3, 2, 0 }, { 3, 4, 5, 6, 0 }, { 4, 1, 2, 5, 4 }, { 4, 2, 3, 6, 5 }, { 4, 3, 1, 4, 6 } }; static const int hexfaces[][5] = { { 4, 4, 3, 2, 1 }, { 4, 3, 7, 6, 2 }, { 4, 7, 8, 5, 6 }, { 4, 8, 4, 1, 5 }, { 4, 1, 2, 6, 5 }, { 4, 3, 4, 8, 7 } }; switch (np) { case 4: // tet { face.SetType(TRIG); for (int j = 1; j <= 3; j++) face.PNum(j) = PNum(tetfaces[i-1][j]); break; } case 10: // tet10 { face.SetType(TRIG6); for (int j = 1; j <= 6; j++) face.PNum(j) = PNum(tet10faces[i-1][j]); break; } case 5: // pyramid { // face.SetNP(pyramidfaces[i-1][0]); face.SetType ( (i == 1) ? QUAD : TRIG); for (int j = 1; j <= face.GetNP(); j++) face.PNum(j) = PNum(pyramidfaces[i-1][j]); break; } case 6: // prism { // face.SetNP(prismfaces[i-1][0]); face.SetType ( (i >= 3) ? QUAD : TRIG); for (int j = 1; j <= face.GetNP(); j++) face.PNum(j) = PNum(prismfaces[i-1][j]); break; } case 8: { face.SetType(QUAD); for (int j = 1; j <= 4; j++) face.PNum(j) = PNum(hexfaces[i-1][j]); break; } } } void Element :: GetTets (Array & locels) const { GetTetsLocal (locels); int i, j; for (i = 1; i <= locels.Size(); i++) for (j = 1; j <= 4; j++) locels.Elem(i).PNum(j) = PNum ( locels.Elem(i).PNum(j) ); } void Element :: GetTetsLocal (Array & locels) const { int i, j; locels.SetSize(0); switch (GetType()) { case TET: { int linels[1][4] = { { 1, 2, 3, 4 }, }; for (i = 0; i < 1; i++) { Element tet(4); for (j = 1; j <= 4; j++) tet.PNum(j) = linels[i][j-1]; locels.Append (tet); } break; } case TET10: { int linels[8][4] = { { 1, 5, 6, 7 }, { 5, 2, 8, 9 }, { 6, 8, 3, 10 }, { 7, 9, 10, 4 }, { 5, 6, 7, 9 }, { 5, 6, 9, 8 }, { 6, 7, 9, 10 }, { 6, 8, 10, 9 } }; for (i = 0; i < 8; i++) { Element tet(4); for (j = 1; j <= 4; j++) tet.PNum(j) = linels[i][j-1]; locels.Append (tet); } break; } case PYRAMID: { int linels[2][4] = { { 1, 2, 3, 5 }, { 1, 3, 4, 5 } }; for (i = 0; i < 2; i++) { Element tet(4); for (j = 1; j <= 4; j++) tet.PNum(j) = linels[i][j-1]; locels.Append (tet); } break; } case PRISM: case PRISM12: { int linels[3][4] = { { 1, 2, 3, 4 }, { 4, 2, 3, 5 }, { 6, 5, 4, 3 } }; for (i = 0; i < 3; i++) { Element tet(4); for (j = 0; j < 4; j++) tet[j] = linels[i][j]; locels.Append (tet); } break; } case HEX: { int linels[6][4] = { { 1, 7, 2, 3 }, { 1, 7, 3, 4 }, { 1, 7, 4, 8 }, { 1, 7, 8, 5 }, { 1, 7, 5, 6 }, { 1, 7, 6, 2 } }; for (i = 0; i < 6; i++) { Element tet(4); for (j = 0; j < 4; j++) tet[j] = linels[i][j]; locels.Append (tet); } break; } default: { cerr << "GetTetsLocal not implemented for el with " << GetNP() << " nodes" << endl; } } } bool Element :: operator==(const Element & el2) const { bool retval = (el2.GetNP() == np); for(int i= 0; retval && i & points) const { const static double tetpoints[4][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }}; const static double prismpoints[6][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 0, 1 }, { 0, 1, 1 } }; const static double pyramidpoints[6][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; const static double tet10points[10][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 0.5, 0, 0 }, { 0, 0.5, 0 }, { 0, 0, 0.5 }, { 0.5, 0.5, 0 }, { 0.5, 0, 0.5 }, { 0, 0.5, 0.5 } }; const static double hexpoints[8][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 } }; int np, i; const double (*pp)[3]; switch (GetType()) { case TET: { np = 4; pp = tetpoints; break; } case PRISM: case PRISM12: { np = 6; pp = prismpoints; break; } case TET10: { np = 10; pp = tet10points; break; } case PYRAMID: { np = 5; pp = pyramidpoints; break; } case HEX: { np = 8; pp = hexpoints; break; } default: { cout << "GetNodesLocal not impelemented for element " << GetType() << endl; np = 0; } } points.SetSize(0); for (i = 0; i < np; i++) points.Append (Point3d (pp[i][0], pp[i][1], pp[i][2])); } #endif void Element :: GetNodesLocalNew (Array > & points) const { const static double tetpoints[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 0, 0, 0 } }; const static double prismpoints[6][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 }, { 1, 0, 1 }, { 0, 1, 1 }, { 0, 0, 1 } }; const static double pyramidpoints[6][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; const static double tet10points[10][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 0.5, 0, 0 }, { 0, 0.5, 0 }, { 0, 0, 0.5 }, { 0.5, 0.5, 0 }, { 0.5, 0, 0.5 }, { 0, 0.5, 0.5 } }; const static double hexpoints[8][3] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 } }; int np, i; const double (*pp)[3]; switch (GetType()) { case TET: { np = 4; pp = tetpoints; break; } case PRISM: case PRISM12: { np = 6; pp = prismpoints; break; } case TET10: { np = 10; pp = tet10points; break; } case PYRAMID: { np = 5; pp = pyramidpoints; break; } case HEX: { np = 8; pp = hexpoints; break; } default: { cout << "GetNodesLocal not impelemented for element " << GetType() << endl; np = 0; pp = NULL; } } points.SetSize(0); for (i = 0; i < np; i++) points.Append (Point<3> (pp[i][0], pp[i][1], pp[i][2])); } void Element :: GetSurfaceTriangles (Array & surftrigs) const { static int tet4trigs[][3] = { { 2, 3, 4 }, { 3, 1, 4 }, { 1, 2, 4 }, { 2, 1, 3 } }; static int tet10trigs[][3] = { { 2, 8, 9 }, { 3, 10, 8}, { 4, 9, 10 }, { 9, 8, 10 }, { 3, 6, 10 }, { 1, 7, 6 }, { 4, 10, 7 }, { 6, 7, 10 }, { 1, 5, 7 }, { 2, 9, 5 }, { 4, 7, 9 }, { 5, 9, 7 }, { 1, 6, 5 }, { 2, 5, 8 }, { 3, 8, 6 }, { 5, 6, 8 } }; static int pyramidtrigs[][3] = { { 1, 3, 2 }, { 1, 4, 3 }, { 1, 2, 5 }, { 2, 3, 5 }, { 3, 4, 5 }, { 4, 1, 5 } }; static int prismtrigs[][3] = { { 1, 3, 2 }, { 4, 5, 6 }, { 1, 2, 4 }, { 4, 2, 5 }, { 2, 3, 5 }, { 5, 3, 6 }, { 3, 1, 6 }, { 6, 1, 4 } }; static int hextrigs[][3] = { { 1, 3, 2 }, { 1, 4, 3 }, { 5, 6, 7 }, { 5, 7, 8 }, { 1, 2, 6 }, { 1, 6, 5 }, { 2, 3, 7 }, { 2, 7, 6 }, { 3, 4, 8 }, { 3, 8, 7 }, { 4, 1, 8 }, { 1, 5, 8 } }; int j; int nf; int (*fp)[3]; switch (GetType()) { case TET: { nf = 4; fp = tet4trigs; break; } case PYRAMID: { nf = 6; fp = pyramidtrigs; break; } case PRISM: case PRISM12: { nf = 8; fp = prismtrigs; break; } case TET10: { nf = 16; fp = tet10trigs; break; } case HEX: { nf = 12; fp = hextrigs; break; } default: { nf = 0; fp = NULL; } } surftrigs.SetSize (nf); for (j = 0; j < nf; j++) { surftrigs.Elem(j+1) = Element2d(TRIG); surftrigs.Elem(j+1).PNum(1) = fp[j][0]; surftrigs.Elem(j+1).PNum(2) = fp[j][1]; surftrigs.Elem(j+1).PNum(3) = fp[j][2]; } } Array< shared_ptr < IntegrationPointData > > ipdtet; Array< shared_ptr < IntegrationPointData > > ipdtet10; int Element :: GetNIP () const { int nip; switch (typ) { case TET: nip = 1; break; case TET10: nip = 8; break; default: nip = 0; break; } return nip; } void Element :: GetIntegrationPoint (int ip, Point<3> & p, double & weight) const { static double eltetqp[1][4] = { { 0.25, 0.25, 0.25, 1.0/6.0 } }; static double eltet10qp[8][4] = { { 0.585410196624969, 0.138196601125011, 0.138196601125011, 1.0/24.0 }, { 0.138196601125011, 0.585410196624969, 0.138196601125011, 1.0/24.0 }, { 0.138196601125011, 0.138196601125011, 0.585410196624969, 1.0/24.0 }, { 0.138196601125011, 0.138196601125011, 0.138196601125011, 1.0/24.0 }, { 1, 0, 0, 1 }, { 0, 1, 0, 1 }, { 0, 0, 1, 1 }, { 0, 0, 0, 1 }, }; double * pp = NULL; switch (typ) { case TET: pp = &eltetqp[0][0]; break; case TET10: pp = &eltet10qp[ip-1][0]; break; default: throw NgException ("illegal element shape in GetIntegrationPoint"); } p(0) = pp[0]; p(1) = pp[1]; p(2) = pp[2]; weight = pp[3]; } void Element :: GetTransformation (int ip, const T_POINTS & points, DenseMatrix & trans) const { int np = GetNP(); DenseMatrix pmat(3, np), dshape(3, np); pmat.SetSize (3, np); dshape.SetSize (3, np); Point<3> p; double w; GetPointMatrix (points, pmat); GetIntegrationPoint (ip, p, w); GetDShape (p, dshape); CalcABt (pmat, dshape, trans); /* (*testout) << "p = " << p << endl << "pmat = " << pmat << endl << "dshape = " << dshape << endl << "tans = " << trans << endl; */ } void Element :: GetTransformation (int ip, class DenseMatrix & pmat, class DenseMatrix & trans) const { int np = GetNP(); if (pmat.Width() != np || pmat.Height() != 3) { (*testout) << "GetTransofrmation: pmat doesn't fit" << endl; return; } ComputeIntegrationPointData (); DenseMatrix * dshapep = 0; switch (GetType()) { case TET: dshapep = &ipdtet.Get(ip)->dshape; break; case TET10: dshapep = &ipdtet10.Get(ip)->dshape; break; default: PrintSysError ("Element::GetTransformation, illegal type ", int(typ)); } CalcABt (pmat, *dshapep, trans); } void Element :: GetShape (const Point<3> & hp, Vector & shape) const { Point3d p = hp; if (shape.Size() != GetNP()) { cerr << "Element::GetShape: Length not fitting" << endl; return; } switch (typ) { case TET: { shape(0) = 1 - p.X() - p.Y() - p.Z(); shape(1) = p.X(); shape(2) = p.Y(); shape(3) = p.Z(); break; } case TET10: { double lam1 = 1 - p.X() - p.Y() - p.Z(); double lam2 = p.X(); double lam3 = p.Y(); double lam4 = p.Z(); shape(4) = 4 * lam1 * lam2; shape(5) = 4 * lam1 * lam3; shape(6) = 4 * lam1 * lam4; shape(7) = 4 * lam2 * lam3; shape(8) = 4 * lam2 * lam4; shape(9) = 4 * lam3 * lam4; shape(0) = lam1 - 0.5 * (shape(4) + shape(5) + shape(6)); shape(1) = lam2 - 0.5 * (shape(4) + shape(7) + shape(8)); shape(2) = lam3 - 0.5 * (shape(5) + shape(7) + shape(9)); shape(3) = lam4 - 0.5 * (shape(6) + shape(8) + shape(9)); break; } case PRISM: { Point<3> hp = p; shape(0) = hp(0) * (1-hp(2)); shape(1) = hp(1) * (1-hp(2)); shape(2) = (1-hp(0)-hp(1)) * (1-hp(2)); shape(3) = hp(0) * hp(2); shape(4) = hp(1) * hp(2); shape(5) = (1-hp(0)-hp(1)) * hp(2); break; } case HEX: { Point<3> hp = p; shape(0) = (1-hp(0))*(1-hp(1))*(1-hp(2)); shape(1) = ( hp(0))*(1-hp(1))*(1-hp(2)); shape(2) = ( hp(0))*( hp(1))*(1-hp(2)); shape(3) = (1-hp(0))*( hp(1))*(1-hp(2)); shape(4) = (1-hp(0))*(1-hp(1))*( hp(2)); shape(5) = ( hp(0))*(1-hp(1))*( hp(2)); shape(6) = ( hp(0))*( hp(1))*( hp(2)); shape(7) = (1-hp(0))*( hp(1))*( hp(2)); break; } default: throw NgException("Element :: GetShape not implemented for that element"); } } template void Element :: GetShapeNew (const Point<3,T> & p, TFlatVector shape) const { /* if (shape.Size() < GetNP()) { cerr << "Element::GetShape: Length not fitting" << endl; return; } */ switch (typ) { case TET: { shape(0) = p(0); shape(1) = p(1); shape(2) = p(2); shape(3) = 1-p(0)-p(1)-p(2); break; } case TET10: { T lam1 = p(0); T lam2 = p(1); T lam3 = p(2); T lam4 = 1-p(0)-p(1)-p(2); shape(0) = 2 * lam1 * (lam1-0.5); shape(1) = 2 * lam2 * (lam2-0.5); shape(2) = 2 * lam3 * (lam3-0.5); shape(3) = 2 * lam4 * (lam4-0.5); shape(4) = 4 * lam1 * lam2; shape(5) = 4 * lam1 * lam3; shape(6) = 4 * lam1 * lam4; shape(7) = 4 * lam2 * lam3; shape(8) = 4 * lam2 * lam4; shape(9) = 4 * lam3 * lam4; break; } case PYRAMID: { T noz = 1-p(2); // if (noz == 0.0) noz = 1e-10; noz += T(1e-12); T xi = p(0) / noz; T eta = p(1) / noz; shape(0) = (1-xi)*(1-eta) * (noz); shape(1) = ( xi)*(1-eta) * (noz); shape(2) = ( xi)*( eta) * (noz); shape(3) = (1-xi)*( eta) * (noz); shape(4) = p(2); break; } case PYRAMID13: { T x = p(0); T y = p(1); T z = p(2); z *= 1-1e-12; shape[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25); shape[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2)); shape[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75); shape[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2)); shape[4] = z*(2*z - 1); shape[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); shape[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2); shape[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); shape[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2); shape[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); shape[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1); shape[11] = 4*x*y*z/(-z + 1); shape[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1); break; } case PRISM: { shape(0) = p(0) * (1-p(2)); shape(1) = p(1) * (1-p(2)); shape(2) = (1-p(0)-p(1)) * (1-p(2)); shape(3) = p(0) * p(2); shape(4) = p(1) * p(2); shape(5) = (1-p(0)-p(1)) * p(2); break; } case PRISM15: { T x = p(0); T y = p(1); T z = p(2); T lam = 1-x-y; T lamz = 1-z; shape[0] = (2*x*x-x) * (2*lamz*lamz-lamz); shape[1] = (2*y*y-y) * (2*lamz*lamz-lamz); shape[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); shape[3] = (2*x*x-x) * (2*z*z-z); shape[4] = (2*y*y-y) * (2*z*z-z); shape[5] = (2*lam*lam-lam) * (2*z*z-z); shape[6] = 4 * x * y * (2*lamz*lamz-lamz); shape[7] = 4 * x * lam * (2*lamz*lamz-lamz); shape[8] = 4 * y * lam * (2*lamz*lamz-lamz); shape[9] = x * 4 * z * (1-z); shape[10] = y * 4 * z * (1-z); shape[11] = lam * 4 * z * (1-z); shape[12] = 4 * x * y * (2*z*z-z); shape[13] = 4 * x * lam * (2*z*z-z); shape[14] = 4 * y * lam * (2*z*z-z); break; } case HEX: { shape(0) = (1-p(0))*(1-p(1))*(1-p(2)); shape(1) = ( p(0))*(1-p(1))*(1-p(2)); shape(2) = ( p(0))*( p(1))*(1-p(2)); shape(3) = (1-p(0))*( p(1))*(1-p(2)); shape(4) = (1-p(0))*(1-p(1))*( p(2)); shape(5) = ( p(0))*(1-p(1))*( p(2)); shape(6) = ( p(0))*( p(1))*( p(2)); shape(7) = (1-p(0))*( p(1))*( p(2)); break; } case HEX20: { T x = p(0); T y = p(1); T z = p(2); shape[0] = (1-x)*(1-y)*(1-z); shape[1] = x *(1-y)*(1-z); shape[2] = x * y *(1-z); shape[3] = (1-x)* y *(1-z); shape[4] = (1-x)*(1-y)*(z); shape[5] = x *(1-y)*(z); shape[6] = x * y *(z); shape[7] = (1-x)* y *(z); T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; static const int e[12][2] = { { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, }; for (int i = 0; i < 12; i++) { T lame = shape[e[i][0]]+shape[e[i][1]]; T xi = sigma[e[i][1]]-sigma[e[i][0]]; shape[8+i] = (1-xi*xi)*lame; } for (int i = 0; i < 12; i++) { shape[e[i][0]] -= 0.5 * shape[8+i]; shape[e[i][1]] -= 0.5 * shape[8+i]; } break; } default: throw NgException("Element :: GetNewShape not implemented for that element"); } } void Element :: GetDShape (const Point<3> & hp, DenseMatrix & dshape) const { Point3d p = hp; int np = GetNP(); if (dshape.Height() != 3 || dshape.Width() != np) { cerr << "Element::DShape: Sizes don't fit" << endl; return; } double eps = 1e-6; Vector shaper(np), shapel(np); for (int i = 1; i <= 3; i++) { Point3d pr(p), pl(p); pr.X(i) += eps; pl.X(i) -= eps; GetShape (pr, shaper); GetShape (pl, shapel); for (int j = 0; j < np; j++) dshape(i-1, j) = (shaper(j) - shapel(j)) / (2 * eps); } } template void Element :: GetDShapeNew (const Point<3,T> & p, MatrixFixWidth<3,T> & dshape) const { switch (typ) { case TET: { dshape = T(0.0); dshape(0,0) = 1; dshape(1,1) = 1; dshape(2,2) = 1; dshape(3,0) = -1; dshape(3,1) = -1; dshape(3,2) = -1; break; } case PRISM: { dshape = T(0.0); dshape(0,0) = 1-p(2); dshape(0,2) = -p(0); dshape(1,1) = 1-p(2); dshape(1,2) = -p(1); dshape(2,0) = -(1-p(2)); dshape(2,1) = -(1-p(2)); dshape(2,2) = -(1-p(0)-p(1)); dshape(3,0) = p(2); dshape(3,2) = p(0); dshape(4,1) = p(2); dshape(4,2) = p(1); dshape(5,0) = -p(2); dshape(5,1) = -p(2); dshape(5,2) = 1-p(0)-p(1); break; } default: { int np = GetNP(); double eps = 1e-6; ArrayMem mem(2*np); TFlatVector shaper(np, &mem[0]); TFlatVector shapel(np, &mem[np]); // Vector shaper(np), shapel(np); for (int i = 0; i < 3; i++) { Point<3,T> pr(p), pl(p); pr(i) += eps; pl(i) -= eps; GetShapeNew (pr, shaper); GetShapeNew (pl, shapel); for (int j = 0; j < np; j++) dshape(j, i) = (shaper(j) - shapel(j)) / (2 * eps); } } } } template void Element2d :: GetShapeNew (const Point<2,double> & p, TFlatVector shape) const; template void Element2d :: GetShapeNew (const Point<2,SIMD> & p, TFlatVector> shape) const; template void Element2d::GetDShapeNew (const Point<2> &, MatrixFixWidth<2> &) const; template void Element2d::GetDShapeNew> (const Point<2,SIMD> &, MatrixFixWidth<2,SIMD> &) const; template void Element :: GetShapeNew (const Point<3,double> & p, TFlatVector shape) const; template void Element :: GetShapeNew (const Point<3,SIMD> & p, TFlatVector> shape) const; template void Element::GetDShapeNew (const Point<3> &, MatrixFixWidth<3> &) const; template void Element::GetDShapeNew> (const Point<3,SIMD> &, MatrixFixWidth<3,SIMD> &) const; void Element :: GetPointMatrix (const T_POINTS & points, DenseMatrix & pmat) const { int np = GetNP(); for (int i = 1; i <= np; i++) { const Point3d & p = points.Get(PNum(i)); pmat.Elem(1, i) = p.X(); pmat.Elem(2, i) = p.Y(); pmat.Elem(3, i) = p.Z(); } } double Element :: CalcJacobianBadness (const T_POINTS & points) const { int nip = GetNIP(); DenseMatrix trans(3,3); DenseMatrix pmat; pmat.SetSize (3, GetNP()); GetPointMatrix (points, pmat); double err = 0; for (int i = 1; i <= nip; i++) { GetTransformation (i, pmat, trans); // Frobenius norm double frob = 0; for (int j = 1; j <= 9; j++) frob += sqr (trans.Get(j)); frob = sqrt (frob); frob /= 3; double det = -trans.Det(); if (det <= 0) err += 1e12; else err += frob * frob * frob / det; } err /= nip; return err; } double Element :: CalcJacobianBadnessDirDeriv (const T_POINTS & points, int pi, Vec<3> & dir, double & dd) const { int i, j, k; int nip = GetNIP(); DenseMatrix trans(3,3), dtrans(3,3), hmat(3,3); DenseMatrix pmat, vmat; pmat.SetSize (3, GetNP()); vmat.SetSize (3, GetNP()); GetPointMatrix (points, pmat); for (i = 1; i <= np; i++) for (j = 1; j <= 3; j++) vmat.Elem(j, i) = 0; for (j = 1; j <= 3; j++) vmat.Elem(j, pi) = dir(j-1); double err = 0; dd = 0; for (i = 1; i <= nip; i++) { GetTransformation (i, pmat, trans); GetTransformation (i, vmat, dtrans); // Frobenius norm double frob = 0; for (j = 1; j <= 9; j++) frob += sqr (trans.Get(j)); frob = sqrt (frob); double dfrob = 0; for (j = 1; j <= 9; j++) dfrob += trans.Get(j) * dtrans.Get(j); dfrob = dfrob / frob; frob /= 3; dfrob /= 3; double det = trans.Det(); double ddet = 0; for (j = 1; j <= 3; j++) { hmat = trans; for (k = 1; k <= 3; k++) hmat.Elem(k, j) = dtrans.Get(k, j); ddet += hmat.Det(); } det *= -1; ddet *= -1; if (det <= 0) err += 1e12; else { err += frob * frob * frob / det; dd += (3 * frob * frob * dfrob * det - frob * frob * frob * ddet) / (det * det); } } err /= nip; dd /= nip; return err; } double Element :: CalcJacobianBadnessGradient (const T_POINTS & points, int pi, Vec<3> & grad) const { int nip = GetNIP(); DenseMatrix trans(3,3), dtrans(3,3), hmat(3,3); DenseMatrix pmat, vmat; pmat.SetSize (3, GetNP()); vmat.SetSize (3, GetNP()); GetPointMatrix (points, pmat); for (int i = 1; i <= np; i++) for (int j = 1; j <= 3; j++) vmat.Elem(j, i) = 0; for (int j = 1; j <= 3; j++) vmat.Elem(j, pi) = 1.; double err = 0; double dfrob[3]; grad = 0; for (int i = 1; i <= nip; i++) { GetTransformation (i, pmat, trans); GetTransformation (i, vmat, dtrans); // Frobenius norm double frob = 0; for (int j = 1; j <= 9; j++) frob += sqr (trans.Get(j)); frob = sqrt (frob); for(int k = 0; k<3; k++) { dfrob[k] = 0; for (int j = 1; j <= 3; j++) dfrob[k] += trans.Get(k+1,j) * dtrans.Get(k+1,j); dfrob[k] = dfrob[k] / (3.*frob); } frob /= 3; double det = trans.Det(); double ddet[3]; // = 0; for(int k=1; k<=3; k++) { int km1 = (k > 1) ? (k-1) : 3; int kp1 = (k < 3) ? (k+1) : 1; ddet[k-1] = 0; for(int j=1; j<=3; j++) { int jm1 = (j > 1) ? (j-1) : 3; int jp1 = (j < 3) ? (j+1) : 1; ddet[k-1] += (-1.)* dtrans.Get(k,j) * ( trans.Get(km1,jm1)*trans.Get(kp1,jp1) - trans.Get(km1,jp1)*trans.Get(kp1,jm1) ); } } det *= -1; if (det <= 0) err += 1e12; else { err += frob * frob * frob / det; double fac = (frob * frob)/(det * det); for(int j=0; j<3; j++) grad(j) += fac * (3 * dfrob[j] * det - frob * ddet[j]); } } err /= nip; grad *= 1./nip; return err; } void Element :: ComputeIntegrationPointData () const { switch (GetType()) { case TET: if (ipdtet.Size()) return; break; case TET10: if (ipdtet10.Size()) return; break; default: PrintSysError ("Element::ComputeIntegrationPoint, illegal type ", int(typ)); } switch (GetType()) { case TET: ipdtet.SetSize(GetNIP()); break; case TET10: ipdtet10.SetSize(GetNIP()); break; default: PrintSysError ("Element::ComputeIntegrationPoint, illegal type2 ", int(typ)); } for (int i = 1; i <= GetNIP(); i++) { IntegrationPointData * ipd = new IntegrationPointData; GetIntegrationPoint (i, ipd->p, ipd->weight); ipd->shape.SetSize(GetNP()); ipd->dshape.SetSize(3, GetNP()); GetShape (ipd->p, ipd->shape); GetDShape (ipd->p, ipd->dshape); switch (GetType()) { case TET: ipdtet.Elem(i).reset(ipd); break; case TET10: ipdtet10.Elem(i).reset(ipd); break; default: PrintSysError ("Element::ComputeIntegrationPoint(2), illegal type ", int(typ)); } } } FaceDescriptor :: FaceDescriptor() { surfnr = domin = domout = bcprop = 0; domin_singular = domout_singular = 0.; // Philippose - 06/07/2009 // Initialise surface colour surfcolour = Vec3d(0.0,1.0,0.0); tlosurf = -1; // bcname = 0; firstelement = -1; } FaceDescriptor :: FaceDescriptor(const FaceDescriptor& other) : surfnr(other.surfnr), domin(other.domin), domout(other.domout), tlosurf(other.tlosurf), bcprop(other.bcprop), surfcolour(other.surfcolour), bcname(other.bcname), domin_singular(other.domin_singular), domout_singular(other.domout_singular) { firstelement = -1; } FaceDescriptor :: FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi) { surfnr = surfnri; domin = domini; domout = domouti; // Philippose - 06/07/2009 // Initialise surface colour surfcolour = Vec3d(0.0,1.0,0.0); tlosurf = tlosurfi; bcprop = surfnri; domin_singular = domout_singular = 0.; // bcname = 0; firstelement = -1; } FaceDescriptor :: FaceDescriptor(const Segment & seg) { surfnr = seg.si; domin = seg.domin+1; domout = seg.domout+1; // Philippose - 06/07/2009 // Initialise surface colour surfcolour = Vec3d(0.0,1.0,0.0); tlosurf = seg.tlosurf+1; bcprop = 0; domin_singular = domout_singular = 0.; // bcname = 0; firstelement = -1; } int FaceDescriptor :: SegmentFits (const Segment & seg) { return surfnr == seg.si && domin == seg.domin+1 && domout == seg.domout+1 && tlosurf == seg.tlosurf+1; } string FaceDescriptor :: default_bcname = "default"; /* const string & FaceDescriptor :: GetBCName () const { static string defaultstring = "default"; if (bcname) return *bcname; return defaultstring; } */ void FaceDescriptor :: SetBCName (string * bcn) { if (bcn) bcname = bcn; else bcn = &default_bcname; } void FaceDescriptor :: DoArchive (Archive & ar) { ar & surfnr & domin & domout & tlosurf & bcprop & surfcolour.X() & surfcolour.Y() & surfcolour.Z() & bcname & domin_singular & domout_singular ; // don't need: firstelement } ostream & operator<<(ostream & s, const FaceDescriptor & fd) { s << "surfnr = " << fd.SurfNr() << ", domin = " << fd.DomainIn() << ", domout = " << fd.DomainOut() << ", tlosurf = " << fd.TLOSurface() << ", bcprop = " << fd.BCProperty() << ", bcname = " << fd.GetBCName() << ", domin_sing = " << fd.DomainInSingular() << ", domout_sing = " << fd.DomainOutSingular() << ", colour = " << fd.SurfColour(); return s; } Identifications :: Identifications (Mesh & amesh) : mesh(amesh), identifiedpoints(100), identifiedpoints_nr(100) { // identifiedpoints = new INDEX_2_HASHTABLE(100); // identifiedpoints_nr = new INDEX_3_HASHTABLE(100); maxidentnr = 0; } Identifications :: ~Identifications () { ; // delete identifiedpoints; // delete identifiedpoints_nr; } void Identifications :: Delete () { identifiedpoints.DeleteData(); identifiedpoints_nr.DeleteData(); /* delete identifiedpoints; identifiedpoints = new INDEX_2_HASHTABLE(100); delete identifiedpoints_nr; identifiedpoints_nr = new INDEX_3_HASHTABLE(100); */ maxidentnr = 0; } void Identifications :: DoArchive (Archive & ar) { ar & maxidentnr; ar & identifiedpoints & identifiedpoints_nr; ar & idpoints_table; if (ar.Output()) { size_t s = type.Size(); ar & s; for (auto & t : type) ar & (unsigned char&)(t); } else { size_t s; ar & s; type.SetSize(s); for (auto & t : type) ar & (unsigned char&)(t); } } void Identifications :: Add (PointIndex pi1, PointIndex pi2, int identnr) { // (*testout) << "Identification::Add, pi1 = " << pi1 << ", pi2 = " << pi2 << ", identnr = " << identnr << endl; INDEX_2 pair (pi1, pi2); identifiedpoints.Set (pair, identnr); INDEX_3 tripl (pi1, pi2, identnr); identifiedpoints_nr.Set (tripl, 1); if (identnr > maxidentnr) maxidentnr = identnr; if (identnr+1 > idpoints_table.Size()) idpoints_table.ChangeSize (identnr+1); idpoints_table.Add (identnr, pair); // timestamp = NextTimeStamp(); } int Identifications :: Get (PointIndex pi1, PointIndex pi2) const { INDEX_2 pair(pi1, pi2); if (identifiedpoints.Used (pair)) return identifiedpoints.Get(pair); else return 0; } bool Identifications :: Get (PointIndex pi1, PointIndex pi2, int nr) const { INDEX_3 tripl(pi1, pi2, nr); if (identifiedpoints_nr.Used (tripl)) return 1; else return 0; } int Identifications :: GetSymmetric (PointIndex pi1, PointIndex pi2) const { INDEX_2 pair(pi1, pi2); if (identifiedpoints.Used (pair)) return identifiedpoints.Get(pair); pair = INDEX_2 (pi2, pi1); if (identifiedpoints.Used (pair)) return identifiedpoints.Get(pair); return 0; } void Identifications :: GetMap (int identnr, Array & identmap, bool symmetric) const { identmap.SetSize (mesh.GetNP()); identmap = 0; if (identnr) for (int i = 0; i < idpoints_table[identnr].Size(); i++) { INDEX_2 pair = idpoints_table[identnr][i]; identmap[pair.I1()] = pair.I2(); if(symmetric) identmap[pair.I2()] = pair.I1(); } else { cout << "getmap, identnr = " << identnr << endl; for (int i = 1; i <= identifiedpoints_nr.GetNBags(); i++) for (int j = 1; j <= identifiedpoints_nr.GetBagSize(i); j++) { INDEX_3 i3; int dummy; identifiedpoints_nr.GetData (i, j, i3, dummy); if (i3.I3() == identnr || !identnr) { identmap.Elem(i3.I1()) = i3.I2(); if(symmetric) identmap.Elem(i3.I2()) = i3.I1(); } } } } void Identifications :: GetPairs (int identnr, Array & identpairs) const { identpairs.SetSize(0); if (identnr == 0) for (int i = 1; i <= identifiedpoints.GetNBags(); i++) for (int j = 1; j <= identifiedpoints.GetBagSize(i); j++) { INDEX_2 i2; int nr; identifiedpoints.GetData (i, j, i2, nr); identpairs.Append (i2); } else for (int i = 1; i <= identifiedpoints_nr.GetNBags(); i++) for (int j = 1; j <= identifiedpoints_nr.GetBagSize(i); j++) { INDEX_3 i3; int dummy; identifiedpoints_nr.GetData (i, j, i3 , dummy); if (i3.I3() == identnr) identpairs.Append (INDEX_2(i3.I1(), i3.I2())); } } void Identifications :: SetMaxPointNr (int maxpnum) { for (int i = 1; i <= identifiedpoints.GetNBags(); i++) for (int j = 1; j <= identifiedpoints.GetBagSize(i); j++) { INDEX_2 i2; int nr; identifiedpoints.GetData (i, j, i2, nr); if (i2.I1() > maxpnum || i2.I2() > maxpnum) { i2.I1() = i2.I2() = -1; identifiedpoints.SetData (i, j, i2, -1); } } } void Identifications :: Print (ostream & ost) const { ost << "Identifications:" << endl; ost << "pairs: " << endl << identifiedpoints << endl; ost << "pairs and nr: " << endl << identifiedpoints_nr << endl; ost << "table: " << endl << idpoints_table << endl; } MeshingParameters :: MeshingParameters () { // optimize3d = "cmdmustm"; //optimize3d = "cmdmstm"; // optsteps3d = 3; // optimize2d = "smsmsmSmSmSm"; // optsteps2d = 3; // opterrpow = 2; // blockfill = 1; // filldist = 0.1; // safety = 5; // relinnersafety = 3; // uselocalh = 1; // grading = 0.3; // delaunay = 1; // maxh = 1e10; // minh = 0; // meshsizefilename = NULL; // startinsurface = 0; // checkoverlap = 1; // checkoverlappingboundary = 1; // checkchartboundary = 1; // curvaturesafety = 2; // segmentsperedge = 1; // parthread = 0; // elsizeweight = 0.2; // giveuptol2d = 200; // giveuptol = 10; // maxoutersteps = 10; // starshapeclass = 5; // baseelnp = 0; // sloppy = 1; // badellimit = 175; // check_impossible = 0; // secondorder = 0; } void MeshingParameters :: Print (ostream & ost) const { ost << "Meshing parameters: " << endl << "optimize3d = " << optimize3d << endl << "optsteps3d = " << optsteps3d << endl << " optimize2d = " << optimize2d << endl << " optsteps2d = " << optsteps2d << endl << " opterrpow = " << opterrpow << endl << " blockfill = " << blockfill << endl << " filldist = " << filldist << endl << " safety = " << safety << endl << " relinnersafety = " << relinnersafety << endl << " uselocalh = " << uselocalh << endl << " grading = " << grading << endl << " delaunay = " << delaunay << endl << " maxh = " << maxh << endl << " meshsizefilename = " << meshsizefilename << endl << " startinsurface = " << startinsurface << endl << " checkoverlap = " << checkoverlap << endl << " checkchartboundary = " << checkchartboundary << endl << " curvaturesafety = " << curvaturesafety << endl << " segmentsperedge = " << segmentsperedge << endl << " parthread = " << parthread << endl << " elsizeweight = " << elsizeweight << endl << " giveuptol2d = " << giveuptol2d << endl << " giveuptol = " << giveuptol << endl << " maxoutersteps = " << maxoutersteps << endl << " starshapeclass = " << starshapeclass << endl << " baseelnp = " << baseelnp << endl << " sloppy = " << sloppy << endl << " badellimit = " << badellimit << endl << " secondorder = " << secondorder << endl << " elementorder = " << elementorder << endl << " quad = " << quad << endl << " inverttets = " << inverttets << endl << " inverttrigs = " << inverttrigs << endl; } /* void MeshingParameters :: CopyFrom(const MeshingParameters & other) { //strcpy(optimize3d,other.optimize3d); optimize3d = other.optimize3d; optsteps3d = other.optsteps3d; //strcpy(optimize2d,other.optimize2d); optimize2d = other.optimize2d; optsteps2d = other.optsteps2d; opterrpow = other.opterrpow; blockfill = other.blockfill; filldist = other.filldist; safety = other.safety; relinnersafety = other.relinnersafety; uselocalh = other.uselocalh; grading = other.grading; delaunay = other.delaunay; maxh = other.maxh; //strcpy(const_cast(meshsizefilename), other.meshsizefilename); //const_cast(meshsizefilename) = other.meshsizefilename; //??? meshsizefilename = other.meshsizefilename; startinsurface = other.startinsurface; checkoverlap = other.checkoverlap; checkoverlappingboundary = other.checkoverlappingboundary; checkchartboundary = other.checkchartboundary; curvaturesafety = other.curvaturesafety; segmentsperedge = other.segmentsperedge; parthread = other.parthread; elsizeweight = other.elsizeweight; giveuptol2d = other.giveuptol2d; giveuptol = other.giveuptol; maxoutersteps = other.maxoutersteps; starshapeclass = other.starshapeclass; baseelnp = other.baseelnp; sloppy = other.sloppy; badellimit = other.badellimit; secondorder = other.secondorder; elementorder = other.elementorder; quad = other.quad; inverttets = other.inverttets; inverttrigs = other.inverttrigs; } */ DebugParameters :: DebugParameters () { slowchecks = 0; haltsuccess = 0; haltnosuccess = 0; haltlargequalclass = 0; haltsegment = 0; haltsegmentp1 = 0; haltsegmentp2 = 0; }; } netgen-6.2.1905/libsrc/meshing/meshfunc.hpp0000644000175000017500000000215013504650527017230 0ustar kurtkurt#ifndef FILE_MESHFUNC #define FILE_MESHFUNC /**************************************************************************/ /* File: meshfunc.hpp */ /* Author: Johannes Gerstmayr, Joachim Schoeberl */ /* Date: 26. Jan. 98 */ /**************************************************************************/ /* Functions for mesh-generations strategies */ class Mesh; // class CSGeometry; /// Build tet-mesh DLL_HEADER MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d); /// Build mixed-element mesh // MESHING3_RESULT MeshMixedVolume (MeshingParameters & mp, Mesh& mesh3d); /// Optimize tet-mesh DLL_HEADER MESHING3_RESULT OptimizeVolume (MeshingParameters & mp, Mesh& mesh3d); // const CSGeometry * geometry = NULL); DLL_HEADER void RemoveIllegalElements (Mesh & mesh3d); enum MESHING_STEP { MESHCONST_ANALYSE = 1, MESHCONST_MESHEDGES = 2, MESHCONST_MESHSURFACE = 3, MESHCONST_OPTSURFACE = 4, MESHCONST_MESHVOLUME = 5, MESHCONST_OPTVOLUME = 6 }; #endif netgen-6.2.1905/libsrc/meshing/meshing2.hpp0000644000175000017500000000751513504650527017146 0ustar kurtkurt#ifndef FILE_MESHING2 #define FILE_MESHING2 /**************************************************************************/ /* File: meshing2.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Okt. 95 */ /**************************************************************************/ enum MESHING2_RESULT { MESHING2_OK = 0, MESHING2_GIVEUP = 1 }; /* The basis class for 2D mesh generation. Has the method GenerateMesh For surface mesh generation, or non-Euklidean meshing, derive from Meshing2, and replace transformation. */ class Meshing2 { /// the current advancing front AdFront2 * adfront; /// rules for mesh generation Array rules; /// statistics Array ruleused, canuse, foundmap; /// Box<3> boundingbox; /// double starttime; /// double maxarea; Vec3d ex, ey; Point3d globp1; public: /// DLL_HEADER Meshing2 (const MeshingParameters & mp, const Box<3> & aboundingbox); /// DLL_HEADER virtual ~Meshing2 (); /// Load rules, either from file, or compiled rules void LoadRules (const char * filename, bool quad); /// DLL_HEADER MESHING2_RESULT GenerateMesh (Mesh & mesh, const MeshingParameters & mp, double gh, int facenr); DLL_HEADER void Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp); DLL_HEADER void BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp); /// DLL_HEADER void AddPoint (const Point3d & p, PointIndex globind, MultiPointGeomInfo * mgi = NULL, bool pointonsurface = true); /// DLL_HEADER void AddBoundaryElement (INDEX i1, INDEX i2, const PointGeomInfo & gi1, const PointGeomInfo & gi2); /// void SetStartTime (double astarttime); /// void SetMaxArea (double amaxarea); protected: /// virtual void StartMesh (); /// virtual void EndMesh (); /// virtual double CalcLocalH (const Point3d & p, double gh) const; /// virtual void DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo1, const PointGeomInfo * geominfo2); /// virtual void TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominfo, Point2d & plainpoint, double h, int & zone); /// return 0 .. ok /// return >0 .. cannot transform point to true surface virtual int TransformFromPlain (Point2d & plainpoint, Point3d & locpoint, PointGeomInfo & geominfo, double h); /// projects to surface /// return 0 .. ok virtual int BelongsToActiveChart (const Point3d & p, const PointGeomInfo & gi); /// computes geoinfo data for line with respect to /// selected chart virtual int ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi); /// Tries to select unique geominfo on active chart /// return 0: success /// return 1: failed virtual int ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, PointGeomInfo & pgi); /* tests, whether endpoint (= 1 or 2) of line segment p1-p2 is inside of the selected chart. The endpoint must be on the chart */ virtual int IsLineVertexOnChart (const Point3d & p1, const Point3d & p2, int endpoint, const PointGeomInfo & geominfo); /* get (projected) boundary of current chart */ virtual void GetChartBoundary (Array & points, Array & points3d, Array & lines, double p) const; virtual double Area () const; /** Applies 2D rules. Tests all 2D rules */ int ApplyRules (Array & lpoints, Array & legalpoints, int maxlegalpoint, Array & llines, int maxlegelline, Array & elements, Array & dellines, int tolerance, const MeshingParameters & mp); }; #endif netgen-6.2.1905/libsrc/meshing/quadrls.cpp0000644000175000017500000003534213504650527017077 0ustar kurtkurtnamespace netgen { const char * quadrules[] = { "rule \"Free Quad (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(1, 1) { 1 X2 } { };\n",\ "(0, 1) { } { };\n",\ "\n",\ "newlines\n",\ "(3, 2);\n",\ "(4, 3);\n",\ "(1, 4);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 1.5) { 1.5 X2 } { };\n",\ "(-0.5, 1.5) { -0.5 X2 } { };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Free Quad (5)\"\n",\ "\n",\ "quality 5\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(1, 1) { 1 X2 } { };\n",\ "(0, 1) { } { };\n",\ "\n",\ "newlines\n",\ "(3, 2);\n",\ "(4, 3);\n",\ "(1, 4);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 1.5) { 1.5 X2 } { };\n",\ "(-0.5, 1.5) { -0.5 X2 } { };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X2 } { };\n",\ "(0, 1) { } { };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Quad Right (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "\n",\ "newpoints\n",\ "(0, 1) { } { 1 y3 };\n",\ "\n",\ "newlines\n",\ "(1, 4);\n",\ "(4, 3);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(-0.5, 1.5) { } { 1.5 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "rule \"Quad P Right (2)\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(0, 1) { -1 X2, 1 X3 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(1, 4);\n",\ "(4, 3);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.2, 0.5) { 0.7 X2, 0.5 X3 } { 0.5 Y3 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(-0.5, 1.5) { -2 X2, 1.5 X3 } { 1.5 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { -1 X2, 1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "\n",\ "orientations\n",\ "(1, 2, 3);\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "rule \"Quad P Right (150)\"\n",\ "\n",\ "quality 150\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(0, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(1, 4)\n;",\ "(4, 3)\n;",\ "(3, 2)\n;",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.2, 0.5) { 0.7 X2, 0.5 X3 } { 0.5 Y3 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(-0.5, 1.5) { -2 X2, 1.5 X3 } { 1.5 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "orientations\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "rule \"Quad Right PL (2)\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(1, 4);\n",\ "(4, 3);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "(-0.2, 0.5) { -0.1 X2, -0.1 X3, 0.6 X4 } { -0.1 Y2, -0.1 Y3, 0.6 Y4 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "orientations\n",\ "(1, 2, 3);\n",\ "(1, 3, 4);\n",\ "(1, 2, 4);\n",\ "(4, 2, 3);\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left Quad (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 1) del;\n",\ "\n",\ "newpoints\n",\ "(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(3, 4);\n",\ "(4, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left P Quad (2)\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 4);\n",\ "(4, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "(-0.2, 0.6) { -0.2 X2, 0.6 X3 } { 0.6 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 0.5) { 0.5 X3 } { 0.5 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left P Quad (150)\"\n",\ "\n",\ "quality 150\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "(1, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 4);\n",\ "(4, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "(-0.2, 0.6) { -0.2 X2, 0.6 X3 } { 0.6 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 0.5) { 0.5 X3 } { 0.5 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left Quad RP (2)\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0, 1);\n",\ "(1, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 1) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(3, 4);\n",\ "(4, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.2, 0.5) { 0.6 X2, 0.6 X4, -0.1 X3 } { 0.6 Y2, 0.6 Y4, -0.1 Y3 };\n",\ "(1, 1) { 1 X4 } { 1 Y4 };\n",\ "(0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.5) { 0.5 X2, 0.5 X4 } { 0.5 Y2, 0.5 Y4 };\n",\ "(1, 1) { 1 X4 } { 1 Y4 };\n",\ "(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ "(0, 1) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4, 3);\n",\ "\n",\ "orientations\n",\ "(1, 2, 4);\n",\ "(1, 4, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Two left (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 4) del;\n",\ "(4, 1) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Two Right (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "(3, 4) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(1, 4);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "(-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Right 120 (1)\"\n",\ "\n",\ "quality 1000\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(1, 4);\n",\ "(4, 3);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(1, 1.732) { -2 X2, 2 X3 } { 2 Y3 };\n",\ "(0, 1.732) { -3 X2, 2 X3 } { 2 Y3 };\n",\ "(-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4);\n",\ "(2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left 120 (1)\"\n",\ "\n",\ "quality 1000\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(-0.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 1) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 };\n",\ "\n",\ "newlines\n",\ "(3, 4);\n",\ "(4, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 };\n",\ "(1, 1.732) { 2 X2, 2 X3 } { 2 Y3 };\n",\ "(0, 1.732) { -1 X2, 2 X3 } { 2 Y3 };\n",\ "(-0.5, 0.866) { 1 X3 } {1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 4);\n",\ "(2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Left Right (1)\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "(4, 1) del;\n",\ "\n",\ "\n",\ "newlines\n",\ "(4, 3);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0.5, 1.5) { -0.25 X2, 0.75 X3, 0.75 X4 } { 0.75 Y3, 0.75 Y4 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Fill Quad\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "(3, 4) del;\n",\ "(4, 1) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { 1 Y2 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Fill Triangle\"\n",\ "\n",\ "quality 10\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0.5, 0.86);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "(3, 1) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { 1 Y2 };\n",\ "(0.5, 0.86) { 1 X3 } { 1 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "rule \"Right 60 (1)\"\n",\ "\n",\ "quality 10\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0) { 0.5, 0, 1.0 };\n",\ "(0.5, 0.866) { 0.6, 0, 0.8 };\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(2, 3) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Vis A Vis (2)\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1);\n",\ "(0, 1);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 4) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(1, 4);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "(-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ "(1, 1) { 1 X3 } { 1 Y3 };\n",\ "(0, 1) { 1 X4 } { 1 Y4 };\n",\ "(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4);\n",\ "\n",\ "orientations\n",\ "(1, 3, 4);\n",\ "(2, 3, 4);\n",\ "(1, 2, 3);\n",\ "(1, 2, 4);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Triangle Vis A Vis (200)\"\n",\ "\n",\ "quality 200\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(0.5, 0.866);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newlines\n",\ "(1, 3);\n",\ "(3, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(1.2, 0.693) { 0.8 X2, 0.8 X3 } { 0.8 Y2, 0.8 Y3 };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(-0.2, 0.693) { -0.6 X2, 0.8 X3 } { -0.6 Y2, 0.8 Y3 };\n",\ "\n",\ "freearea2\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { };\n",\ "(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n",\ "(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ "(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 3);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "rule \"2 h Vis A Vis (1)\"\n",\ "\n",\ "quality 3000\n",\ "\n",\ "mappoints\n",\ "(0, 0);\n",\ "(1, 0);\n",\ "(1, 1.732);\n",\ "(0, 1.732);\n",\ "\n",\ "maplines\n",\ "(1, 2) del;\n",\ "(3, 4) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.866) { 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 };\n",\ "\n",\ "newlines\n",\ "(1, 5);\n",\ "(5, 4);\n",\ "(3, 5);\n",\ "(5, 2);\n",\ "\n",\ "freearea\n",\ "(0, 0);\n",\ "(1, 0) { 1 X2 } { 1 Y2 };\n",\ "(1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 };\n",\ "(1, 1.732) { 1 X3 } { 1 Y3 };\n",\ "(0, 1.732) { 1 X4 } { 1 Y4 };\n",\ "(-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 };\n",\ "\n",\ "elements\n",\ "(1, 2, 5);\n",\ "(3, 4, 5);\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ 0}; } netgen-6.2.1905/libsrc/meshing/validate.hpp0000644000175000017500000000132013504650527017207 0ustar kurtkurt#ifndef VALIDATE_HPP #define VALIDATE_HPP namespace netgen { void GetPureBadness(Mesh & mesh, Array & pure_badness, const BitArray & isnewpoint); double Validate(const Mesh & mesh, Array & bad_elements, const Array & pure_badness, double max_worsening, const bool uselocalworsening, Array * quality_loss = NULL); void RepairBisection(Mesh & mesh, Array & bad_elements, const BitArray & isnewpoint, const Refinement & refinement, const Array & pure_badness, double max_worsening, const bool uselocalworsening, const Array< Array* > & idmaps); } #endif // VALIDATE_HPP netgen-6.2.1905/libsrc/meshing/smoothing2.5.cpp0000644000175000017500000001202213504650527017646 0ustar kurtkurt#include #include "meshing.hpp" #include namespace netgen { void MeshOptimize2d :: ProjectBoundaryPoints(Array & surfaceindex, const Array* > & from, Array* > & dest) { for(int i=0; i= 0) { *dest[i] = *from[i]; ProjectPoint(surfaceindex[i],*dest[i]); } } } void MeshOptimize2d :: ImproveVolumeMesh (Mesh & mesh) { if (!faceindex) { PrintMessage (3, "Smoothing"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) { ImproveVolumeMesh (mesh); if (multithread.terminate) throw NgException ("Meshing stopped"); } faceindex = 0; return; } static int timer = NgProfiler::CreateTimer ("MeshSmoothing 2D"); NgProfiler::RegionTimer reg (timer); CheckMeshApproximation (mesh); int i, j, k; SurfaceElementIndex sei; Array seia; mesh.GetSurfaceElementsOfFace (faceindex, seia); /* bool mixed = 0; for (i = 0; i < seia.Size(); i++) if (mesh[seia[i]].GetNP() != 3) { mixed = 1; break; } */ int loci; double fact; bool moveisok; PointGeomInfo ngi; Point<3> origp; Vector x(3); Array savepoints(mesh.GetNP()); Array nelementsonpoint(mesh.GetNP()); nelementsonpoint = 0; for (i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (j = 0; j < el.GetNP(); j++) nelementsonpoint[el[j]]++; } TABLE elementsonpoint(nelementsonpoint); for (i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (j = 0; j < el.GetNP(); j++) elementsonpoint.Add (el[j], seia[i]); } JacobianPointFunction pf(mesh.Points(),mesh.VolumeElements()); // Opti2SurfaceMinFunction surfminf(mesh); // Opti2EdgeMinFunction edgeminf(mesh); // Opti2SurfaceMinFunctionJacobian surfminfj(mesh); OptiParameters par; par.maxit_linsearch = 8; par.maxit_bfgs = 5; int np = mesh.GetNP(); int ne = mesh.GetNE(); BitArray badnodes(np); badnodes.Clear(); for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); double bad = el.CalcJacobianBadness (mesh.Points()); if (bad > 1) for (j = 1; j <= el.GetNP(); j++) badnodes.Set (el.PNum(j)); } bool printeddot = 0; char plotchar = '.'; int modplot = 1; if (mesh.GetNP() > 1000) { plotchar = '+'; modplot = 10; } if (mesh.GetNP() > 10000) { plotchar = 'o'; modplot = 100; } int cnt = 0; Array locelements(0); Array locrots(0); for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) { if (mesh[pi].Type() != SURFACEPOINT) continue; if (multithread.terminate) throw NgException ("Meshing stopped"); int surfi(-1); if(elementsonpoint[pi].Size() == 0) continue; Element2d & hel = mesh[elementsonpoint[pi][0]]; if(hel.GetIndex() != faceindex) continue; cnt++; if (cnt % modplot == 0 && writestatus) { printeddot = 1; PrintDot (plotchar); } int hpi = 0; for (j = 1; j <= hel.GetNP(); j++) if (hel.PNum(j) == pi) { hpi = j; break; } PointGeomInfo gi1 = hel.GeomInfoPi(hpi); locelements.SetSize(0); locrots.SetSize (0); for (j = 0; j < elementsonpoint[pi].Size(); j++) { sei = elementsonpoint[pi][j]; const Element2d & bel = mesh[sei]; surfi = mesh.GetFaceDescriptor(bel.GetIndex()).SurfNr(); locelements.Append (sei); for (k = 1; k <= bel.GetNP(); k++) if (bel.PNum(k) == pi) { locrots.Append (k); break; } } double lh = mesh.GetH(mesh.Point(pi)); par.typx = lh; pf.SetPointIndex(pi); x = 0; bool pok = (pf.Func (x) < 1e10); if (pok) { BFGS (x, pf, par); origp = mesh[pi]; loci = 1; fact = 1; moveisok = false; //optimizer loop (if whole distance is not possible, move only a bit!!!!) while (loci <= 5 && !moveisok) { loci ++; mesh[pi](0) = origp(0) + x(0)*fact; mesh[pi](1) = origp(1) + x(1)*fact; mesh[pi](2) = origp(2) + x(2)*fact; fact = fact/2.; //cout << "origp " << origp << " newp " << mesh[pi]; ngi = gi1; moveisok = (ProjectPointGI (surfi, mesh[pi], ngi) != 0); //cout << " projected " << mesh[pi] << endl; // point lies on same chart in stlsurface if (moveisok) { for (j = 0; j < locelements.Size(); j++) mesh[locelements[j]].GeomInfoPi(locrots[j]) = ngi; //cout << "moved " << origp << " to " << mesh[pi] << endl; } else { mesh[pi] = origp; } } } else { cout << "el not ok (point " << pi << ": " << mesh[pi] << ")" << endl; } } if (printeddot) PrintDot ('\n'); CheckMeshApproximation (mesh); mesh.SetNextTimeStamp(); } } netgen-6.2.1905/libsrc/meshing/curvedelems.hpp0000644000175000017500000001736613504650527017755 0ustar kurtkurt#ifndef CURVEDELEMS #define CURVEDELEMS /**************************************************************************/ /* File: curvedelems.hpp */ /* Author: Robert Gaisbauer (first version) */ /* redesign by Joachim Schoeberl */ /* Date: 27. Sep. 02, Feb 2006 */ /**************************************************************************/ class Refinement; class CurvedElements { const Mesh & mesh; Array edgeorder; Array faceorder; Array edgecoeffsindex; Array facecoeffsindex; Array< Vec<3> > edgecoeffs; Array< Vec<3> > facecoeffs; Array< double > edgeweight; // for rational 2nd order splines int order; bool rational; bool ishighorder; void buildJacPols(); public: DLL_HEADER CurvedElements (const Mesh & amesh); DLL_HEADER ~CurvedElements(); // bool IsHighOrder() const { return order > 1; } bool IsHighOrder() const { return ishighorder; } // void SetHighOrder (int aorder) { order=aorder; } void SetIsHighOrder (bool ho) { ishighorder = ho; } DLL_HEADER void BuildCurvedElements(const Refinement * ref, int aorder, bool arational = false); int GetOrder () { return order; } virtual void DoArchive(Archive& ar) { if(ar.Input()) buildJacPols(); ar & edgeorder & faceorder & edgecoeffsindex & facecoeffsindex & edgecoeffs & facecoeffs & edgeweight & order & rational & ishighorder; } bool IsSegmentCurved (SegmentIndex segnr) const; bool IsSurfaceElementCurved (SurfaceElementIndex sei) const; bool IsElementCurved (ElementIndex ei) const; bool IsElementHighOrder (ElementIndex ei) const; void CalcSegmentTransformation (double xi, SegmentIndex segnr, Point<3> & x) { CalcSegmentTransformation (xi, segnr, &x, NULL); }; void CalcSegmentTransformation (double xi, SegmentIndex segnr, Vec<3> & dxdxi) { CalcSegmentTransformation (xi, segnr, NULL, &dxdxi); }; void CalcSegmentTransformation (double xi, SegmentIndex segnr, Point<3> & x, Vec<3> & dxdxi) { CalcSegmentTransformation (xi, segnr, &x, &dxdxi, NULL); }; void CalcSegmentTransformation (double xi, SegmentIndex segnr, Point<3> & x, Vec<3> & dxdxi, bool & curved) { CalcSegmentTransformation (xi, segnr, &x, &dxdxi, &curved); }; void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, Point<3> & x) { CalcSurfaceTransformation (xi, elnr, &x, NULL); }; void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, Mat<3,2> & dxdxi) { CalcSurfaceTransformation (xi, elnr, NULL, &dxdxi); }; void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, Point<3> & x, Mat<3,2> & dxdxi) { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi, NULL); }; void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, Point<3> & x, Mat<3,2> & dxdxi, bool & curved) { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi, &curved); }; void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, Point<3> & x) { CalcElementTransformation (xi, elnr, &x, NULL); }; void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, Mat<3,3> & dxdxi) { CalcElementTransformation (xi, elnr, NULL, &dxdxi); }; void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, Point<3> & x, Mat<3,3> & dxdxi) { CalcElementTransformation (xi, elnr, &x, &dxdxi /* , NULL */ ); }; void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, Point<3> & x, Mat<3,3> & dxdxi, void * buffer, bool valid) { CalcElementTransformation (xi, elnr, &x, &dxdxi, /* NULL, */ buffer, valid ); }; // void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, // Point<3> & x, Mat<3,3> & dxdxi) // , bool & curved) // { CalcElementTransformation (xi, elnr, &x, &dxdxi /* , &curved * ); } /* void CalcMultiPointSegmentTransformation (Array * xi, SegmentIndex segnr, Array > * x, Array > * dxdxi); */ template void CalcMultiPointSegmentTransformation (SegmentIndex elnr, int n, const T * xi, size_t sxi, T * x, size_t sx, T * dxdxi, size_t sdxdxi); void CalcMultiPointSurfaceTransformation (Array< Point<2> > * xi, SurfaceElementIndex elnr, Array< Point<3> > * x, Array< Mat<3,2> > * dxdxi); template void CalcMultiPointSurfaceTransformation (SurfaceElementIndex elnr, int n, const T * xi, size_t sxi, T * x, size_t sx, T * dxdxi, size_t sdxdxi); void CalcMultiPointElementTransformation (Array< Point<3> > * xi, ElementIndex elnr, Array< Point<3> > * x, Array< Mat<3,3> > * dxdxi); template void CalcMultiPointElementTransformation (ElementIndex elnr, int n, const T * xi, size_t sxi, T * x, size_t sx, T * dxdxi, size_t sdxdxi); private: template void CalcSegmentTransformation (T xi, SegmentIndex segnr, Point<3,T> * x = NULL, Vec<3,T> * dxdxi = NULL, bool * curved = NULL); void CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr, Point<3> * x = NULL, Mat<3,2> * dxdxi = NULL, bool * curved = NULL); void CalcElementTransformation (Point<3> xi, ElementIndex elnr, Point<3> * x = NULL, Mat<3,3> * dxdxi = NULL, // bool * curved = NULL, void * buffer = NULL, bool valid = 0); class SegmentInfo { public: SegmentIndex elnr; int order; int nv; int ndof; int edgenr; }; template void CalcElementShapes (SegmentInfo & elnr, T xi, TFlatVector shapes) const; void GetCoefficients (SegmentInfo & elnr, Array > & coefs) const; template void CalcElementDShapes (SegmentInfo & elnr, T xi, TFlatVector dshapes) const; class ElementInfo { public: ElementIndex elnr; int order; int nv; int ndof; int nedges; int nfaces; int edgenrs[12]; int facenrs[6]; Mat<3> hdxdxi; Vec<3> hcoefs[10]; // enough for second order tets }; template void CalcElementShapes (ElementInfo & info, Point<3,T> xi, TFlatVector shapes) const; void GetCoefficients (ElementInfo & info, Vec<3> * coefs) const; template void CalcElementDShapes (ElementInfo & info, const Point<3,T> xi, MatrixFixWidth<3,T> dshapes) const; template bool EvaluateMapping (ElementInfo & info, const Point<3,T> xi, Point<3,T> & x, Mat<3,3,T> & jac) const; class SurfaceElementInfo { public: SurfaceElementIndex elnr; int order; int nv; int ndof; ArrayMem edgenrs; int facenr; }; template void CalcElementShapes (SurfaceElementInfo & elinfo, const Point<2,T> xi, TFlatVector shapes) const; template void GetCoefficients (SurfaceElementInfo & elinfo, Array > & coefs) const; template void CalcElementDShapes (SurfaceElementInfo & elinfo, const Point<2,T> xi, MatrixFixWidth<2,T> dshapes) const; template bool EvaluateMapping (SurfaceElementInfo & info, const Point<2,T> xi, Point & x, Mat & jac) const; }; #endif netgen-6.2.1905/libsrc/meshing/hpref_quad.hpp0000644000175000017500000007554513504650527017560 0ustar kurtkurt// HP_QUAD int refquad_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_newelstypes[] = { HP_QUAD, HP_NONE, }; int refquad_newels[][8] = { { 1, 2, 3, 4 }, }; HPRef_Struct refquad = { HP_QUAD, refquad_splitedges, 0, 0, refquad_newelstypes, refquad_newels }; // HP_QUAD_SINGCORNER int refquad_singcorner_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_singcorner_newelstypes[] = { HP_TRIG_SINGCORNER, HP_QUAD, HP_TRIG, HP_NONE, }; int refquad_singcorner_newels[][8] = { { 1, 5, 6 }, { 2, 4, 6, 5 }, { 2, 3, 4 }, }; HPRef_Struct refquad_singcorner = { HP_QUAD, refquad_singcorner_splitedges, 0, 0, refquad_singcorner_newelstypes, refquad_singcorner_newels }; // HP_DUMMY_QUAD_SINGCORNER int refdummyquad_singcorner_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refdummyquad_singcorner_newelstypes[] = { HP_TRIG_SINGCORNER, HP_TRIG, HP_NONE, }; int refdummyquad_singcorner_newels[][8] = { { 1, 2, 4 }, { 4, 2, 3 }, }; HPRef_Struct refdummyquad_singcorner = { HP_QUAD, refdummyquad_singcorner_splitedges, 0, 0, refdummyquad_singcorner_newelstypes, refdummyquad_singcorner_newels }; // HP_QUAD_SINGEDGE int refquad_singedge_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_singedge_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_singedge_newels[][8] = { { 1, 2, 6, 5 }, { 5, 6, 3, 4 }, }; HPRef_Struct refquad_singedge = { HP_QUAD, refquad_singedge_splitedges, 0, 0, refquad_singedge_newelstypes, refquad_singedge_newels }; // HP_QUAD_0E_2VA int refquad_0e_2va_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_0e_2va_newelstypes[] = { HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD, HP_QUAD, HP_NONE, }; int refquad_0e_2va_newels[][8] = { { 1, 5, 6 }, { 2, 8, 7 }, { 5, 7, 8, 6 }, { 6, 8, 3, 4 }, }; HPRef_Struct refquad_0e_2va = { HP_QUAD, refquad_0e_2va_splitedges, 0, 0, refquad_0e_2va_newelstypes, refquad_0e_2va_newels }; // HP_QUAD_0E_2VB int refquad_0e_2vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 3, 4, 7 }, { 3, 2, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_0e_2vb_newelstypes[] = { HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD, HP_QUAD, HP_NONE, }; int refquad_0e_2vb_newels[][8] = { { 1, 5, 6 }, { 3, 7, 8 }, { 5, 2, 4, 6 }, { 2, 8, 7, 4 }, }; HPRef_Struct refquad_0e_2vb = { HP_QUAD, refquad_0e_2vb_splitedges, 0, 0, refquad_0e_2vb_newelstypes, refquad_0e_2vb_newels }; // HP_QUAD_0E_3V int refquad_0e_3v_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 3, 2, 9 }, { 3, 4, 10 }, { 0, 0, 0 } }; int refquad_0e_3v_splitfaces[][4] = { { 2, 3, 1, 14 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_0e_3v_newelstypes[] = { HP_TRIG_SINGCORNER, HP_DUMMY_QUAD_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD, HP_QUAD, HP_QUAD, HP_NONE, }; int refquad_0e_3v_newels[][8] = { { 1, 5, 6 }, { 2, 8, 14, 7 }, { 3, 10, 9 }, { 5, 7, 14, 6 }, { 8, 9, 10, 14 }, { 6, 14, 10, 4 }, }; HPRef_Struct refquad_0e_3v = { HP_QUAD, refquad_0e_3v_splitedges, refquad_0e_3v_splitfaces, 0, refquad_0e_3v_newelstypes, refquad_0e_3v_newels }; // HP_QUAD_0E_4V int refquad_0e_4v_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 3, 2, 9 }, { 3, 4, 10 }, { 4, 1, 11 }, { 4, 3, 12 }, { 0, 0, 0 } }; int refquad_0e_4v_splitfaces[][4] = { { 1, 2, 4, 13 }, { 2, 3, 1, 14 }, { 3, 4, 2, 15 }, { 4, 1, 3, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_0e_4v_newelstypes[] = { HP_DUMMY_QUAD_SINGCORNER, HP_DUMMY_QUAD_SINGCORNER, HP_DUMMY_QUAD_SINGCORNER, HP_DUMMY_QUAD_SINGCORNER, HP_QUAD, HP_QUAD, HP_QUAD, HP_QUAD, HP_QUAD, HP_NONE, }; int refquad_0e_4v_newels[][8] = { { 1, 5, 13, 6 }, { 2, 8, 14, 7 }, { 3, 10, 15, 9 }, { 4, 11, 16, 12 }, { 5, 7, 14, 13 }, { 8, 9, 15, 14 }, { 10, 12, 16, 15 }, { 11, 6, 13, 16 }, { 13, 14, 15, 16 } }; HPRef_Struct refquad_0e_4v = { HP_QUAD, refquad_0e_4v_splitedges, refquad_0e_4v_splitfaces, 0, refquad_0e_4v_newelstypes, refquad_0e_4v_newels }; // HP_QUAD_1E_1VA int refquad_1e_1va_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_1va_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGEDGECORNER1, HP_NONE, }; int refquad_1e_1va_newels[][8] = { { 7, 2, 6, 5 }, { 5, 6, 3, 4 }, { 1, 7, 5 }, }; HPRef_Struct refquad_1e_1va = { HP_QUAD, refquad_1e_1va_splitedges, 0, 0, refquad_1e_1va_newelstypes, refquad_1e_1va_newels }; // HP_QUAD_1E_1VB int refquad_1e_1vb_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 2, 1, 7 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_1vb_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGEDGECORNER2, HP_NONE, }; int refquad_1e_1vb_newels[][8] = { { 1, 7, 6, 5 }, { 5, 6, 3, 4 }, { 7, 2, 6 }, }; HPRef_Struct refquad_1e_1vb = { HP_QUAD, refquad_1e_1vb_splitedges, 0, 0, refquad_1e_1vb_newelstypes, refquad_1e_1vb_newels }; // HP_QUAD_1E_1VC int refquad_1e_1vc_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 3, 4, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_1vc_newelstypes[] = { HP_QUAD_SINGEDGE, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_1e_1vc_newels[][8] = { { 1, 2, 6, 5 }, { 5, 6, 4 }, { 4, 6, 7, 8 }, { 3, 8, 7 } }; HPRef_Struct refquad_1e_1vc = { HP_QUAD, refquad_1e_1vc_splitedges, 0, 0, refquad_1e_1vc_newelstypes, refquad_1e_1vc_newels }; // HP_QUAD_1E_1VD int refquad_1e_1vd_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 4, 1, 7 }, { 4, 3, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_1vd_newelstypes[] = { HP_QUAD_SINGEDGE, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_1e_1vd_newels[][8] = { { 1, 2, 6, 5 }, { 5, 6, 3 }, { 5, 3, 8, 7 }, { 4, 7, 8 } }; HPRef_Struct refquad_1e_1vd = { HP_QUAD, refquad_1e_1vd_splitedges, 0, 0, refquad_1e_1vd_newelstypes, refquad_1e_1vd_newels }; // HP_QUAD_1E_2VA int refquad_1e_2va_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 2, 1, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_2va_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_NONE, }; int refquad_1e_2va_newels[][8] = { { 7, 8, 6, 5 }, { 5, 6, 3, 4 }, { 1, 7, 5 }, { 8, 2, 6 } }; HPRef_Struct refquad_1e_2va = { HP_QUAD, refquad_1e_2va_splitedges, 0, 0, refquad_1e_2va_newelstypes, refquad_1e_2va_newels }; // HP_QUAD_1E_2VB int refquad_1e_2vb_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 3, 2, 8 }, { 3, 4, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_2vb_newelstypes[] = { HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_1e_2vb_newels[][8] = { { 7, 2, 6, 5 }, { 1, 7, 5 }, { 5, 6, 4 }, { 4, 6, 8, 9 }, { 3, 9, 8 } }; HPRef_Struct refquad_1e_2vb = { HP_QUAD, refquad_1e_2vb_splitedges, 0, 0, refquad_1e_2vb_newelstypes, refquad_1e_2vb_newels }; // HP_QUAD_1E_2VC int refquad_1e_2vc_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 4, 1, 8 }, { 4, 3, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_2vc_newelstypes[] = { HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_1e_2vc_newels[][8] = { { 7, 2, 6, 5 }, { 1, 7, 5 }, { 5, 6, 3 }, { 5, 3, 9, 8 }, { 4, 8, 9 } }; HPRef_Struct refquad_1e_2vc = { HP_QUAD, refquad_1e_2vc_splitedges, 0, 0, refquad_1e_2vc_newelstypes, refquad_1e_2vc_newels }; // HP_QUAD_1E_2VD int refquad_1e_2vd_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 2, 1, 7 }, { 3, 2, 8 }, { 3, 4, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_2vd_newelstypes[] = { HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER2, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_1e_2vd_newels[][8] = { { 1, 7, 6, 5 }, { 7, 2, 6 }, { 5, 6, 4 }, { 4, 6, 8, 9 }, { 3, 9, 8 } }; HPRef_Struct refquad_1e_2vd = { HP_QUAD, refquad_1e_2vd_splitedges, 0, 0, refquad_1e_2vd_newelstypes, refquad_1e_2vd_newels }; // HP_QUAD_1E_2VE int refquad_1e_2ve_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 2, 1, 7 }, { 4, 1, 8 }, { 4, 3, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_2ve_newelstypes[] = { HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER2, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_1e_2ve_newels[][8] = { { 1, 7, 6, 5 }, { 7, 2, 6 }, { 5, 6, 3 }, { 5, 3, 9, 8 }, { 4, 8, 9 } }; HPRef_Struct refquad_1e_2ve = { HP_QUAD, refquad_1e_2ve_splitedges, 0, 0, refquad_1e_2ve_newelstypes, refquad_1e_2ve_newels }; // HP_QUAD_1E_2VF int refquad_1e_2vf_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 4, 1, 7 }, { 4, 3, 8 }, { 3, 2, 9 }, { 3, 4, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_2vf_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD, HP_QUAD, HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_1e_2vf_newels[][8] = { { 1, 2, 6, 5 }, { 5, 6, 9, 7 }, { 7, 9, 10, 8 }, { 4, 7, 8 }, { 3, 10, 9 }, }; HPRef_Struct refquad_1e_2vf = { HP_QUAD, refquad_1e_2vf_splitedges, 0, 0, refquad_1e_2vf_newelstypes, refquad_1e_2vf_newels }; // HP_QUAD_1E_3VA int refquad_1e_3va_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 2, 1, 8 }, { 3, 2, 9 }, { 3, 4, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_3va_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGCORNER, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG, HP_NONE, }; int refquad_1e_3va_newels[][8] = { { 1, 7, 5 }, { 8, 2, 6 }, { 3, 10, 9 }, { 7, 8, 6, 5 }, { 4, 6, 9, 10 }, { 5, 6, 4 } }; HPRef_Struct refquad_1e_3va = { HP_QUAD, refquad_1e_3va_splitedges, 0, 0, refquad_1e_3va_newelstypes, refquad_1e_3va_newels }; // HP_QUAD_1E_3VB int refquad_1e_3vb_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 2, 1, 8 }, { 4, 1, 9 }, { 4, 3, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_3vb_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGCORNER, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG, HP_NONE, }; int refquad_1e_3vb_newels[][8] = { { 1, 7, 5 }, { 8, 2, 6 }, { 4, 9, 10 }, { 7, 8, 6, 5 }, { 5, 3, 10, 9 }, { 5, 6, 3 } }; HPRef_Struct refquad_1e_3vb = { HP_QUAD, refquad_1e_3vb_splitedges, 0, 0, refquad_1e_3vb_newelstypes, refquad_1e_3vb_newels }; // HP_QUAD_1E_3VC int refquad_1e_3vc_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 3, 2, 8 }, { 3, 4, 9 }, { 4, 3, 10 }, { 4, 1, 11 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_3vc_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD_SINGEDGE, HP_QUAD, HP_QUAD, HP_NONE, }; int refquad_1e_3vc_newels[][8] = { { 1, 7, 5 }, { 3, 9, 8 }, { 4, 11, 10 }, { 7, 2, 6, 5 }, { 5, 6, 8, 11 }, { 11, 8, 9, 10 } }; HPRef_Struct refquad_1e_3vc = { HP_QUAD, refquad_1e_3vc_splitedges, 0, 0, refquad_1e_3vc_newelstypes, refquad_1e_3vc_newels }; // HP_QUAD_1E_3VD int refquad_1e_3vd_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 2, 1, 7 }, { 3, 2, 8 }, { 3, 4, 9 }, { 4, 3, 10 }, { 4, 1, 11 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_3vd_newelstypes[] = { HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD_SINGEDGE, HP_QUAD, HP_QUAD, HP_NONE, }; int refquad_1e_3vd_newels[][8] = { { 7, 2, 6 }, { 3, 9, 8 }, { 4, 11, 10 }, { 1, 7, 6, 5 }, { 5, 6, 8, 11 }, { 11, 8, 9, 10 } }; HPRef_Struct refquad_1e_3vd = { HP_QUAD, refquad_1e_3vd_splitedges, 0, 0, refquad_1e_3vd_newelstypes, refquad_1e_3vd_newels }; // HP_QUAD_1E_4V int refquad_1e_4v_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 2, 1, 8 }, { 4, 1, 9 }, { 3, 2, 10 }, { 4, 3, 11 }, { 3, 4, 12 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_1e_4v_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD_SINGEDGE, HP_QUAD, HP_QUAD, HP_NONE, }; int refquad_1e_4v_newels[][8] = { { 1, 7, 5 }, { 8, 2, 6 }, { 3, 12, 10 }, { 4, 9, 11 }, { 7, 8, 6, 5 }, { 5, 6, 10, 9 }, { 9, 10, 12, 11 } }; HPRef_Struct refquad_1e_4v = { HP_QUAD, refquad_1e_4v_splitedges, 0, 0, refquad_1e_4v_newelstypes, refquad_1e_4v_newels }; //////////////////////////////////////////////////////////////////////////////// // HP_QUAD_2E int refquad_2e_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 4, 3, 8 }, { 0, 0, 0 } }; int refquad_2e_splitfaces[][4] = { { 1, 2, 4, 9 }, { 0, 0, 0, 0 }, }; /* HPREF_ELEMENT_TYPE refquad_2e_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_2e_newels[][8] = { { 1, 5, 9 }, { 6, 1, 9 }, { 5, 2, 7, 9 }, { 4, 6, 9, 8 }, { 9, 7, 3, 8 }, }; */ // SZ refine to 4 quads HPREF_ELEMENT_TYPE refquad_2e_newelstypes[] = { HP_QUAD_2E, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_2e_newels[][8] = { { 1, 5, 9, 6 }, { 5, 2, 7, 9 }, { 4, 6, 9, 8 }, { 9, 7, 3, 8 }, }; HPRef_Struct refquad_2e = { HP_QUAD, refquad_2e_splitedges, refquad_2e_splitfaces, 0, refquad_2e_newelstypes, refquad_2e_newels }; // HP_QUAD_2E_1VA int refquad_2e_1va_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 4, 3, 8 }, { 2, 1, 10 }, { 0, 0, 0 } }; int refquad_2e_1va_splitfaces[][4] = { { 1, 2, 4, 9 }, { 0, 0, 0, 0 }, }; /* HPREF_ELEMENT_TYPE refquad_2e_1va_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGEDGECORNER2, HP_NONE, }; int refquad_2e_1va_newels[][8] = { { 1, 5, 9 }, { 6, 1, 9 }, { 5, 10, 7, 9 }, { 4, 6, 9, 8 }, { 9, 7, 3, 8 }, { 10, 2, 7 }, }; */ // SZ Quad_2e refinement HPREF_ELEMENT_TYPE refquad_2e_1va_newelstypes[] = { HP_QUAD_2E, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGEDGECORNER2, HP_NONE, }; int refquad_2e_1va_newels[][8] = { { 1, 5, 9, 6 }, { 5, 10, 7, 9 }, { 4, 6, 9, 8 }, { 9, 7, 3, 8 }, { 10, 2, 7 }, }; HPRef_Struct refquad_2e_1va = { HP_QUAD, refquad_2e_1va_splitedges, refquad_2e_1va_splitfaces, 0, refquad_2e_1va_newelstypes, refquad_2e_1va_newels }; // HP_QUAD_2E_1VB int refquad_2e_1vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 4, 3, 8 }, { 3, 2, 10 }, { 3, 4, 11 }, { 0, 0, 0 } }; int refquad_2e_1vb_splitfaces[][4] = { { 1, 2, 4, 9 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2e_1vb_newelstypes[] = { // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, // SZ QUAD_2E HP_QUAD_2E, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int refquad_2e_1vb_newels[][8] = { //{ 1, 5, 9 }, //{ 6, 1, 9 }, { 1, 5, 9, 6 }, { 5, 2, 7, 9 }, { 4, 6, 9, 8 }, { 7, 8, 9 }, { 8, 7, 10, 11 }, { 3, 11, 10 } }; HPRef_Struct refquad_2e_1vb = { HP_QUAD, refquad_2e_1vb_splitedges, refquad_2e_1vb_splitfaces, 0, refquad_2e_1vb_newelstypes, refquad_2e_1vb_newels } ; // HP_QUAD_2E_1VC int refquad_2e_1vc_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 4, 1, 8 }, { 4, 3, 9 }, { 0, 0, 0 } }; int refquad_2e_1vc_splitfaces[][4] = { { 1, 2, 4, 10 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2e_1vc_newelstypes[] = { // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, HP_QUAD_2E, HP_TRIG_SINGEDGECORNER1, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_2e_1vc_newels[][8] = { //{ 1, 5, 10 }, //{ 6, 1, 10 }, { 1, 5, 10, 6}, { 4, 8, 9 }, { 5, 2, 7, 10 }, { 8, 6, 10, 9 }, { 10, 7, 3, 9 }, }; HPRef_Struct refquad_2e_1vc = { HP_QUAD, refquad_2e_1vc_splitedges, refquad_2e_1vc_splitfaces, 0, refquad_2e_1vc_newelstypes, refquad_2e_1vc_newels }; // HP_QUAD_2E_2VA int refquad_2e_2va_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 4, 3, 8 }, { 3, 2, 10 }, { 3, 4, 11 }, { 2, 1, 12 }, { 0, 0, 0 } }; int refquad_2e_2va_splitfaces[][4] = { { 1, 2, 4, 9 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2e_2va_newelstypes[] = { //HP_TRIG_SINGEDGECORNER1, //HP_TRIG_SINGEDGECORNER2, HP_QUAD_2E, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_TRIG_SINGEDGECORNER2, HP_NONE, }; int refquad_2e_2va_newels[][8] = { // { 1, 5, 9 }, // { 6, 1, 9 }, { 1, 5, 9, 6 }, { 5, 12, 7, 9 }, { 4, 6, 9, 8 }, { 7, 8, 9 }, { 8, 7, 10, 11 }, { 3, 11, 10 }, { 12, 2, 7 } }; HPRef_Struct refquad_2e_2va = { HP_QUAD, refquad_2e_2va_splitedges, refquad_2e_2va_splitfaces, 0, refquad_2e_2va_newelstypes, refquad_2e_2va_newels }; // HP_QUAD_2E_2VB int refquad_2e_2vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 4, 1, 9 }, { 4, 3, 10 }, { 0, 0, 0 } }; int refquad_2e_2vb_splitfaces[][4] = { { 1, 2, 4, 11 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2e_2vb_newelstypes[] = { // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, HP_QUAD_2E, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_2e_2vb_newels[][8] = { //{ 1, 5, 11 }, //{ 6, 1, 11 }, { 1, 5, 11, 6 }, { 4, 9, 10 }, { 7, 2, 8 }, { 5, 7, 8, 11 }, { 9, 6, 11, 10 }, { 3, 10, 11, 8 }, }; HPRef_Struct refquad_2e_2vb = { HP_QUAD, refquad_2e_2vb_splitedges, refquad_2e_2vb_splitfaces, 0, refquad_2e_2vb_newelstypes, refquad_2e_2vb_newels }; // HP_QUAD_2E_2VC int refquad_2e_2vc_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 4, 3, 8 }, { 3, 2, 10 }, { 3, 4, 11 }, { 4, 1, 12 }, { 0, 0, 0 } }; int refquad_2e_2vc_splitfaces[][4] = { { 1, 2, 4, 9 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2e_2vc_newelstypes[] = { // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, HP_QUAD_2E, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_TRIG_SINGEDGECORNER1, //SZ (vorher: SINGEDGECORNER2) HP_NONE, }; int refquad_2e_2vc_newels[][8] = { { 1, 5, 9 }, { 6, 1, 9 }, { 5, 2, 7, 9 }, { 12, 6, 9, 8 }, { 7, 8, 9 }, { 8, 7, 10, 11 }, { 3, 11, 10 }, { 4, 12, 8 } }; HPRef_Struct refquad_2e_2vc = { HP_QUAD, refquad_2e_2vc_splitedges, refquad_2e_2vc_splitfaces, 0, refquad_2e_2vc_newelstypes, refquad_2e_2vc_newels }; // HP_QUAD_2E_3V int refquad_2e_3v_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 4, 3, 8 }, { 3, 2, 10 }, { 3, 4, 11 }, { 2, 1, 12 }, { 4, 1, 13 }, { 0, 0, 0 } }; int refquad_2e_3v_splitfaces[][4] = { { 1, 2, 4, 9 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2e_3v_newelstypes[] = { // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, HP_QUAD_2E, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG, HP_QUAD, HP_TRIG_SINGCORNER, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER1, HP_NONE, }; int refquad_2e_3v_newels[][8] = { //{ 1, 5, 9 }, //{ 6, 1, 9 }, { 1, 5, 9, 6 }, { 5, 12, 7, 9 }, { 13, 6, 9, 8 }, { 7, 8, 9 }, { 8, 7, 10, 11 }, { 3, 11, 10 }, { 12, 2, 7 }, { 4, 13, 8 } }; HPRef_Struct refquad_2e_3v = { HP_QUAD, refquad_2e_3v_splitedges, refquad_2e_3v_splitfaces, 0, refquad_2e_3v_newelstypes, refquad_2e_3v_newels }; // HP_QUAD_2EB_0V int refquad_2eb_0v_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 0, 0, 0 } }; int refquad_2eb_0v_splitfaces[][4] = { { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2eb_0v_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_2eb_0v_newels[][8] = { { 1, 2, 6, 5 }, { 3, 4, 8, 7 }, { 5, 6, 7, 8 } }; HPRef_Struct refquad_2eb_0v = { HP_QUAD, refquad_2eb_0v_splitedges, refquad_2eb_0v_splitfaces, 0, refquad_2eb_0v_newelstypes, refquad_2eb_0v_newels }; // HP_QUAD_2EB_1VA int refquad_2eb_1va_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 1, 2, 9 }, { 0, 0, 0 } }; int refquad_2eb_1va_splitfaces[][4] = { { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2eb_1va_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_QUAD, HP_NONE, }; int refquad_2eb_1va_newels[][8] = { { 9, 2, 6, 5 }, { 3, 4, 8, 7 }, { 1, 9, 5 }, { 5, 6, 7, 8 } }; HPRef_Struct refquad_2eb_1va = { HP_QUAD, refquad_2eb_1va_splitedges, refquad_2eb_1va_splitfaces, 0, refquad_2eb_1va_newelstypes, refquad_2eb_1va_newels }; // HP_QUAD_2EB_1VB int refquad_2eb_1vb_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 2, 1, 9 }, { 0, 0, 0 } }; int refquad_2eb_1vb_splitfaces[][4] = { { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2eb_1vb_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER2, HP_QUAD, HP_NONE, }; int refquad_2eb_1vb_newels[][8] = { { 1, 9, 6, 5 }, { 3, 4, 8, 7 }, { 9, 2, 6 }, { 5, 6, 7, 8 } }; HPRef_Struct refquad_2eb_1vb = { HP_QUAD, refquad_2eb_1vb_splitedges, refquad_2eb_1vb_splitfaces, 0, refquad_2eb_1vb_newelstypes, refquad_2eb_1vb_newels }; // HP_QUAD_2EB_2VA int refquad_2eb_2va_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 1, 2, 9 }, { 2, 1, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_2eb_2va_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD, HP_NONE, }; int refquad_2eb_2va_newels[][8] = { { 9, 10, 6, 5 }, { 3, 4, 8, 7 }, { 1, 9, 5 }, { 10, 2, 6 }, { 5, 6, 7, 8 } }; HPRef_Struct refquad_2eb_2va = { HP_QUAD, refquad_2eb_2va_splitedges, 0, 0, refquad_2eb_2va_newelstypes, refquad_2eb_2va_newels }; // HP_QUAD_2EB_2VB int refquad_2eb_2vb_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 1, 2, 9 }, { 3, 4, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_2eb_2vb_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER1, HP_QUAD, HP_NONE, }; int refquad_2eb_2vb_newels[][8] = { { 9, 2, 6, 5 }, { 10, 4, 8, 7 }, { 1, 9, 5 }, { 3, 10, 7 }, { 5, 6, 7, 8 } }; HPRef_Struct refquad_2eb_2vb = { HP_QUAD, refquad_2eb_2vb_splitedges, 0, 0, refquad_2eb_2vb_newelstypes, refquad_2eb_2vb_newels }; // HP_QUAD_2EB_2VC int refquad_2eb_2vc_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 1, 2, 9 }, { 4, 3, 10 }, { 0, 0, 0 } }; int refquad_2eb_2vc_splitfaces[][4] = { { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2eb_2vc_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD, HP_NONE, }; int refquad_2eb_2vc_newels[][8] = { { 9, 2, 6, 5 }, { 3, 10, 8, 7 }, { 1, 9, 5 }, { 10, 4, 8 }, { 5, 6, 7, 8 } }; HPRef_Struct refquad_2eb_2vc = { HP_QUAD, refquad_2eb_2vc_splitedges, refquad_2eb_2vc_splitfaces, 0, refquad_2eb_2vc_newelstypes, refquad_2eb_2vc_newels }; // HP_QUAD_2EB_2VD int refquad_2eb_2vd_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 2, 1, 9 }, { 4, 3, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_2eb_2vd_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER2, HP_QUAD, HP_NONE, }; int refquad_2eb_2vd_newels[][8] = { { 1, 9, 6, 5 }, { 3, 10, 8, 7 }, { 9, 2, 6 }, { 10, 4, 8 }, { 5, 6, 7, 8 } }; HPRef_Struct refquad_2eb_2vd = { HP_QUAD, refquad_2eb_2vd_splitedges, 0, 0, refquad_2eb_2vd_newelstypes, refquad_2eb_2vd_newels }; // HP_QUAD_2EB_3VA int refquad_2eb_3va_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 2, 1, 8 }, { 3, 2, 9 }, { 4, 1, 10 }, { 3, 4, 11 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_2eb_3va_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER1, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_2eb_3va_newels[][8] = { { 1, 7, 5 }, { 8, 2, 6 }, { 3, 11, 9}, { 7, 8, 6, 5 }, { 11, 4, 10, 9 }, { 5, 6, 9, 10 } }; HPRef_Struct refquad_2eb_3va = { HP_QUAD, refquad_2eb_3va_splitedges, 0, 0, refquad_2eb_3va_newelstypes, refquad_2eb_3va_newels }; // HP_QUAD_2EB_3VB int refquad_2eb_3vb_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 1, 2, 7 }, { 2, 1, 8 }, { 3, 2, 9 }, { 4, 1, 10 }, { 4, 3, 11 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refquad_2eb_3vb_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_2eb_3vb_newels[][8] = { { 1, 7, 5 }, { 8, 2, 6 }, { 11, 4, 10 }, { 7, 8, 6, 5 }, { 3, 11, 10, 9 }, { 5, 6, 9, 10 } }; HPRef_Struct refquad_2eb_3vb = { HP_QUAD, refquad_2eb_3vb_splitedges, 0, 0, refquad_2eb_3vb_newelstypes, refquad_2eb_3vb_newels }; // HP_QUAD_2EB_4V int refquad_2eb_4v_splitedges[][3] = { { 1, 4, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 4, 1, 8 }, { 1, 2, 9 }, { 2, 1, 10 }, { 3, 4, 11 }, { 4, 3, 12 }, { 0, 0, 0 } }; int refquad_2eb_4v_splitfaces[][4] = { { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_2eb_4v_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_NONE, }; int refquad_2eb_4v_newels[][8] = { { 9, 10, 6, 5 }, { 11, 12, 8, 7 }, { 5, 6, 7, 8 }, { 1, 9, 5 }, { 10, 2, 6 }, { 3, 11, 7 }, { 12, 4, 8 }, }; HPRef_Struct refquad_2eb_4v = { HP_QUAD, refquad_2eb_4v_splitedges, refquad_2eb_4v_splitfaces, 0, refquad_2eb_4v_newelstypes, refquad_2eb_4v_newels }; // HP_QUAD_3E int refquad_3e_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 3, 4, 10 }, { 4, 3, 12 }, { 0, 0, 0 } }; int refquad_3e_splitfaces[][4] = { { 1, 2, 4, 13 }, { 2, 3, 1, 14 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_3e_newelstypes[] = { HP_QUAD_2E, HP_QUAD_2E, // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER1, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_3e_newels[][8] = { // { 1, 5, 13 }, // { 6, 1, 13 }, // { 7, 2, 14 }, // { 2, 8, 14 }, { 1, 5, 13, 6 }, { 2, 8, 14, 7 }, { 5, 7, 14, 13 }, { 8, 3, 10, 14 }, { 4, 6, 13, 12 }, { 13, 14, 10, 12 } }; HPRef_Struct refquad_3e = { HP_QUAD, refquad_3e_splitedges, refquad_3e_splitfaces, 0, refquad_3e_newelstypes, refquad_3e_newels }; // HP_QUAD_3E_3VA int refquad_3e_3va_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 3, 4, 10 }, { 3, 2, 11 }, { 4, 3, 12 }, { 0, 0, 0 } }; int refquad_3e_3va_splitfaces[][4] = { { 1, 2, 4, 13 }, { 2, 3, 1, 14 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_3e_3va_newelstypes[] = { HP_QUAD_2E, HP_QUAD_2E, // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_3e_3va_newels[][8] = { // { 1, 5, 13 }, // { 6, 1, 13 }, // { 7, 2, 14 }, // { 2, 8, 14 }, { 1, 5, 13, 6 }, { 2, 8, 14, 7 }, { 11, 3, 10 }, { 5, 7, 14, 13 }, { 8, 11, 10, 14 }, { 4, 6, 13, 12 }, { 13, 14, 10, 12 } }; HPRef_Struct refquad_3e_3va = { HP_QUAD, refquad_3e_3va_splitedges, refquad_3e_3va_splitfaces, 0, refquad_3e_3va_newelstypes, refquad_3e_3va_newels }; // HP_QUAD_3E_3VB int refquad_3e_3vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 3, 4, 10 }, { 4, 1, 11 }, { 4, 3, 12 }, { 0, 0, 0 } }; int refquad_3e_3vb_splitfaces[][4] = { { 1, 2, 4, 13 }, { 2, 3, 1, 14 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_3e_3vb_newelstypes[] = { HP_QUAD_2E, HP_QUAD_2E, // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER1, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_3e_3vb_newels[][8] = { // { 1, 5, 13 }, // { 6, 1, 13 }, // { 7, 2, 14 }, // { 2, 8, 14 }, { 1, 5, 13, 6 }, { 2, 8, 14, 7 }, { 4, 11, 12 }, { 5, 7, 14, 13 }, { 8, 3, 10, 14 }, { 11, 6, 13, 12 }, { 13, 14, 10, 12 } }; HPRef_Struct refquad_3e_3vb = { HP_QUAD, refquad_3e_3vb_splitedges, refquad_3e_3vb_splitfaces, 0, refquad_3e_3vb_newelstypes, refquad_3e_3vb_newels }; // HP_QUAD_3E_4V int refquad_3e_4v_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 3, 4, 10 }, { 3, 2, 11 }, { 4, 3, 12 }, { 4, 1, 15 }, { 0, 0, 0 } }; int refquad_3e_4v_splitfaces[][4] = { { 1, 2, 4, 13 }, { 2, 3, 1, 14 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_3e_4v_newelstypes[] = { HP_QUAD_2E, HP_QUAD_2E, // HP_TRIG_SINGEDGECORNER1, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER2, // HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER1, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_3e_4v_newels[][8] = { // { 1, 5, 13 }, // { 6, 1, 13 }, // { 7, 2, 14 }, // { 2, 8, 14 }, { 1, 5, 13, 6 }, { 2, 8, 14, 7 }, { 11, 3, 10 }, { 4, 15, 12 }, { 5, 7, 14, 13 }, { 8, 11, 10, 14 }, { 15, 6, 13, 12 }, { 13, 14, 10, 12 } }; HPRef_Struct refquad_3e_4v = { HP_QUAD, refquad_3e_4v_splitedges, refquad_3e_4v_splitfaces, 0, refquad_3e_4v_newelstypes, refquad_3e_4v_newels }; // HP_QUAD_4E int refquad_4e_splitedges[][3] = { { 1, 2, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 3, 2, 9 }, { 3, 4, 10 }, { 4, 1, 11 }, { 4, 3, 12 }, { 0, 0, 0 } }; int refquad_4e_splitfaces[][4] = { { 1, 2, 4, 13 }, { 2, 3, 1, 14 }, { 3, 4, 2, 15 }, { 4, 1, 3, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refquad_4e_newelstypes[] = { HP_QUAD_2E, HP_QUAD_2E, HP_QUAD_2E, HP_QUAD_2E, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD, HP_NONE, }; int refquad_4e_newels[][8] = { { 1, 5, 13, 6 }, { 2, 8, 14, 7 }, { 3, 10, 15, 9 }, { 4, 11, 16, 12 }, { 5, 7, 14, 13 }, { 8, 9, 15, 14 }, { 10, 12, 16, 15 }, { 11, 6, 13, 16 }, { 13, 14, 15, 16 } }; HPRef_Struct refquad_4e = { HP_QUAD, refquad_4e_splitedges, refquad_4e_splitfaces, 0, refquad_4e_newelstypes, refquad_4e_newels }; netgen-6.2.1905/libsrc/meshing/smoothing2.cpp0000644000175000017500000006353113504650527017516 0ustar kurtkurt#include #include "meshing.hpp" #include namespace netgen { static const double c_trig = 0.14433756; // sqrt(3.0) / 12 static const double c_trig4 = 0.57735026; // sqrt(3.0) / 3 inline double CalcTriangleBadness (double x2, double x3, double y3, double metricweight, double h) { // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); double cir_2 = (x2*x2 + x3*x3 + y3*y3 - x2*x3); double area = x2 * y3; if (area <= 1e-24 * cir_2) return 1e10; double badness = c_trig4 * cir_2 / area - 1; if (metricweight > 0) { // add: metricweight * (area / h^2 + h^2 / area - 2) double areahh = area / (h * h); badness += metricweight * (areahh + 1 / areahh - 2); } return badness; } inline void CalcTriangleBadness (double x2, double x3, double y3, double metricweight, double h, double & badness, double & g1x, double & g1y) { // old: badness = sqrt(3.0) /36 * circumference^2 / area - 1 // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); double cir_2 = 2* (x2*x2 + x3*x3 + y3*y3 - x2*x3); double area = 0.5 * x2 * y3; if (area <= 1e-24 * cir_2) { g1x = 0; g1y = 0; badness = 1e10; return; } badness = c_trig * cir_2 / area - 1; double c1 = -2 * c_trig / area; double c2 = 0.5 * c_trig * cir_2 / (area * area); g1x = c1 * (x2 + x3) + c2 * y3; g1y = c1 * (y3) + c2 * (x2-x3); if (metricweight > 0) { // area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); // add: metricweight * (area / h^2 + h^2 / area - 2) area = x2 * y3; double dareax1 = -y3; double dareay1 = x3 - x2; double areahh = area / (h * h); double fac = metricweight * (areahh - 1 / areahh) / area; badness += metricweight * (areahh + 1 / areahh - 2); g1x += fac * dareax1; g1y += fac * dareay1; } } double CalcTriangleBadness (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, double metricweight, double h) { // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 Vec<3> e12 = p2-p1; Vec<3> e13 = p3-p1; Vec<3> e23 = p3-p2; double cir_2 = e12.Length2() + e13.Length2() + e23.Length2(); double area = 0.5 * Cross (e12, e13).Length(); if (area <= 1e-24 * cir_2) return 1e10; double badness = c_trig * cir_2 / area - 1; if (metricweight > 0) { // add: metricweight * (area / h^2 + h^2 / area - 2) area *= 2; // optimum for (2 area) is h^2 double areahh = area / (h * h); badness += metricweight * (areahh + 1 / areahh - 2); } return badness; } double CalcTriangleBadnessGrad (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, Vec<3> & gradp1, double metricweight, double h) { // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 Vec<3> e12 = p2-p1; Vec<3> e13 = p3-p1; Vec<3> e23 = p3-p2; double cir_2 = e12.Length2() + e13.Length2() + e23.Length2(); Vec<3> varea = Cross(e12, e13); double area = 0.5 * varea.Length(); Vec<3> dcir_2 = (-2) * (e12+e13); Vec<3> darea = (0.25/area) * Cross (p2-p3, varea); if (area <= 1e-24 * cir_2) { gradp1 = 0; return 1e10; } double badness = c_trig * cir_2 / area - 1; gradp1 = c_trig * (1.0/area * dcir_2 - cir_2 / (area*area) * darea); if (metricweight > 0) { // add: metricweight * (area / h^2 + h^2 / area - 2) area *= 2; // optimum for (2 area) is h^2 double areahh = area / (h * h); badness += metricweight * (areahh + 1 / areahh - 2); gradp1 += (2*metricweight * (1/(h*h) - (h*h)/(area*area))) * darea; } return badness; } double CalcTriangleBadness (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, const Vec<3> & n, double metricweight, double h) { Vec<3> v1 = p2-p1; Vec<3> v2 = p3-p1; Vec<3> e1 = v1; Vec<3> e2 = v2; e1 -= (e1 * n) * n; e1 /= (e1.Length() + 1e-24); e2 = Cross (n, e1); return CalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), metricweight, h); } class Opti2dLocalData { public: const MeshOptimize2d * meshthis; MeshPoint sp1; PointGeomInfo gi1; Vec<3> normal, t1, t2; Array locelements; Array locrots; Array lochs; Array > loc_pnts2, loc_pnts3; // static int locerr2; double locmetricweight; double loch; int surfi, surfi2; int uselocalh; public: Opti2dLocalData () { locmetricweight = 0; } }; class Opti2SurfaceMinFunction : public MinFunction { const Mesh & mesh; Opti2dLocalData & ld; public: Opti2SurfaceMinFunction (const Mesh & amesh, Opti2dLocalData & ald) : mesh(amesh), ld(ald) { } ; virtual double Func (const Vector & x) const { Vec<3> n; double badness = 0; ld.meshthis -> GetNormalVector (ld.surfi, ld.sp1, ld.gi1, n); Point<3> pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2; for (int j = 0; j < ld.locelements.Size(); j++) { Vec<3> e1 = ld.loc_pnts2[j] - pp1; Vec<3> e2 = ld.loc_pnts3[j] - pp1; if (ld.uselocalh) ld.loch = ld.lochs[j]; if (Determinant(e1, e2, n) > 1e-8 * ld.loch * ld.loch) { badness += CalcTriangleBadness (pp1, ld.loc_pnts2[j], ld.loc_pnts3[j], ld.locmetricweight, ld.loch); } else { badness += 1e8; } } return badness; } virtual double FuncGrad (const Vector & x, Vector & g) const { Vec<3> vgrad; Point<3> pp1; vgrad = 0; double badness = 0; pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2; for (int j = 0; j < ld.locelements.Size(); j++) { Vec<3> e1 = ld.loc_pnts2[j] - pp1; Vec<3> e2 = ld.loc_pnts3[j] - pp1; if (ld.uselocalh) ld.loch = ld.lochs[j]; if (Determinant(e1, e2, ld.normal) > 1e-8 * ld.loch * ld.loch) { Vec<3> hgrad; badness += CalcTriangleBadnessGrad (pp1, ld.loc_pnts2[j], ld.loc_pnts3[j], hgrad, ld.locmetricweight, ld.loch); vgrad += hgrad; } else { badness += 1e8; } } g(0) = ld.t1 * vgrad; g(1) = ld.t2 * vgrad; return badness; } virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const { deriv = 0; double badness = 0; Point<3> pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2; Vec<3> dir3d = dir(0) * ld.t1 + dir(1) * ld.t2; for (int j = 0; j < ld.locelements.Size(); j++) { Vec<3> e1 = ld.loc_pnts2[j] - pp1; Vec<3> e2 = ld.loc_pnts3[j] - pp1; if (ld.uselocalh) ld.loch = ld.lochs[j]; if (Determinant(e1, e2, ld.normal) > 1e-8 * ld.loch * ld.loch) { Vec<3> hgrad; badness += CalcTriangleBadnessGrad (pp1, ld.loc_pnts2[j], ld.loc_pnts3[j], hgrad, ld.locmetricweight, ld.loch); deriv += dir3d * hgrad; } else { badness += 1e8; } } // cout << "deriv = " << deriv << " =?= "; return badness; /* static int timer = NgProfiler::CreateTimer ("opti2surface - deriv"); NgProfiler::RegionTimer reg (timer); double eps = 1e-6; Vector xr(2), xl(2); xr = x; xl = x; for (int i = 0; i < 2; i++) { xr(i) = x(i) + eps * dir(i); xl(i) = x(i) - eps * dir(i); } deriv = (Func (xr) - Func(xl) ) / (2*eps); cout << deriv << endl; return Func(x); */ } virtual double XXFuncGrad (const Vector & x, Vector & g) const; virtual double XXFuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; }; /* double Opti2SurfaceMinFunction :: Func (const Vector & x) const { static int timer = NgProfiler::CreateTimer ("opti2surface - func"); NgProfiler::RegionTimer reg (timer); Vector g(x.Size()); return FuncGrad (x, g); } */ double Opti2SurfaceMinFunction :: XXFuncGrad (const Vector & x, Vector & grad) const { // static int timer = NgProfiler::CreateTimer ("opti2surface - funcgrad"); // NgProfiler::RegionTimer reg (timer); Vec<3> n, vgrad; Point<3> pp1; vgrad = 0; double badness = 0; ld.meshthis -> GetNormalVector (ld.surfi, ld.sp1, ld.gi1, n); pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2; // meshthis -> ProjectPoint (surfi, pp1); // meshthis -> GetNormalVector (surfi, pp1, n); for (int j = 0; j < ld.locelements.Size(); j++) { double g1x, g1y, hbadness; Vec<3> e1 = ld.loc_pnts2[j] - pp1; Vec<3> e2 = ld.loc_pnts3[j] - pp1; if (ld.uselocalh) ld.loch = ld.lochs[j]; double e1l = e1.Length(); if (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length()) { e1 /= e1l; double e1e2 = e1 * e2; e2 -= e1e2 * e1; double e2l = e2.Length(); CalcTriangleBadness ( e1l, e1e2, e2l, ld.locmetricweight, ld.loch, hbadness, g1x, g1y); badness += hbadness; vgrad += g1x * e1 + (g1y/e2l) * e2; } else { // (*testout) << "very very bad badness" << endl; badness += 1e8; } } // vgrad -= (vgrad * n) * n; grad(0) = vgrad * ld.t1; grad(1) = vgrad * ld.t2; return badness; } double Opti2SurfaceMinFunction :: XXFuncDeriv (const Vector & x, const Vector & dir, double & deriv) const { // static int timer = NgProfiler::CreateTimer ("opti2surface - funcderiv"); // NgProfiler::RegionTimer reg (timer); Vec<3> n, vgrad; Point<3> pp1; vgrad = 0; double badness = 0; ld.meshthis -> GetNormalVector (ld.surfi, ld.sp1, ld.gi1, n); pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2; for (int j = 0; j < ld.locelements.Size(); j++) { double g1x, g1y, hbadness; /* int roti = ld.locrots[j]; const Element2d & bel = mesh[ld.locelements[j]]; Vec<3> e1 = mesh[bel.PNumMod(roti + 1)] - pp1; Vec<3> e2 = mesh[bel.PNumMod(roti + 2)] - pp1; */ Vec<3> e1 = ld.loc_pnts2[j] - pp1; Vec<3> e2 = ld.loc_pnts3[j] - pp1; if (ld.uselocalh) ld.loch = ld.lochs[j]; double e1l = e1.Length(); if (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length()) { e1 /= e1l; double e1e2 = e1 * e2; e2 -= e1e2 * e1; double e2l = e2.Length(); CalcTriangleBadness ( e1l, e1e2, e2l, ld.locmetricweight, ld.loch, hbadness, g1x, g1y); badness += hbadness; vgrad += g1x * e1 + (g1y / e2l) * e2; } else { // (*testout) << "very very bad badness" << endl; badness += 1e8; } } // vgrad -= (vgrad * n) * n; deriv = dir(0) * (vgrad*ld.t1) + dir(1) * (vgrad*ld.t2); return badness; } class Opti2EdgeMinFunction : public MinFunction { const Mesh & mesh; Opti2dLocalData & ld; public: Opti2EdgeMinFunction (const Mesh & amesh, Opti2dLocalData & ald) : mesh(amesh), ld(ald) { } ; virtual double FuncGrad (const Vector & x, Vector & g) const; virtual double Func (const Vector & x) const; }; double Opti2EdgeMinFunction :: Func (const Vector & x) const { Vector g(x.Size()); return FuncGrad (x, g); } double Opti2EdgeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const { int j, rot; Vec<3> n1, n2, v1, v2, e1, e2, vgrad; Point<3> pp1; Vec<2> g1; double badness, hbadness; vgrad = 0.0; badness = 0; pp1 = ld.sp1 + x(0) * ld.t1; ld.meshthis -> ProjectPoint2 (ld.surfi, ld.surfi2, pp1); for (j = 0; j < ld.locelements.Size(); j++) { rot = ld.locrots[j]; const Element2d & bel = mesh[ld.locelements[j]]; v1 = mesh[bel.PNumMod(rot + 1)] - pp1; v2 = mesh[bel.PNumMod(rot + 2)] - pp1; e1 = v1; e2 = v2; e1 /= e1.Length(); e2 -= (e1 * e2) * e1; e2 /= e2.Length(); if (ld.uselocalh) ld.loch = ld.lochs[j]; CalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), ld.locmetricweight, ld.loch, hbadness, g1(0), g1(1)); badness += hbadness; vgrad += g1(0) * e1 + g1(1) * e2; } ld.meshthis -> GetNormalVector (ld.surfi, pp1, n1); ld.meshthis -> GetNormalVector (ld.surfi2, pp1, n2); v1 = Cross (n1, n2); v1.Normalize(); grad(0) = (vgrad * v1) * (ld.t1 * v1); return badness; } class Opti2SurfaceMinFunctionJacobian : public MinFunction { const Mesh & mesh; Opti2dLocalData & ld; public: Opti2SurfaceMinFunctionJacobian (const Mesh & amesh, Opti2dLocalData & ald) : mesh(amesh), ld(ald) { } ; virtual double FuncGrad (const Vector & x, Vector & g) const; virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; virtual double Func (const Vector & x) const; }; double Opti2SurfaceMinFunctionJacobian :: Func (const Vector & x) const { Vector g(x.Size()); return FuncGrad (x, g); } double Opti2SurfaceMinFunctionJacobian :: FuncGrad (const Vector & x, Vector & grad) const { // from 2d: int lpi, gpi; Vec<3> n, vgrad; Point<3> pp1; Vec2d g1, vdir; double badness, hbad, hderiv; vgrad = 0; badness = 0; ld.meshthis -> GetNormalVector (ld.surfi, ld.sp1, ld.gi1, n); pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2; // meshthis -> ProjectPoint (surfi, pp1); // meshthis -> GetNormalVector (surfi, pp1, n); static Array pts2d; pts2d.SetSize(mesh.GetNP()); grad = 0; for (int j = 1; j <= ld.locelements.Size(); j++) { lpi = ld.locrots.Get(j); const Element2d & bel = mesh[ld.locelements.Get(j)]; gpi = bel.PNum(lpi); for (int k = 1; k <= bel.GetNP(); k++) { PointIndex pi = bel.PNum(k); pts2d.Elem(pi) = Point2d (ld.t1 * (mesh.Point(pi) - ld.sp1), ld.t2 * (mesh.Point(pi) - ld.sp1)); } pts2d.Elem(gpi) = Point2d (x(0), x(1)); for (int k = 1; k <= 2; k++) { if (k == 1) vdir = Vec2d (1, 0); else vdir = Vec2d (0, 1); hbad = bel. CalcJacobianBadnessDirDeriv (pts2d, lpi, vdir, hderiv); grad(k-1) += hderiv; if (k == 1) badness += hbad; } } /* vgrad.Add (-(vgrad * n), n); grad.Elem(1) = vgrad * t1; grad.Elem(2) = vgrad * t2; */ return badness; } double Opti2SurfaceMinFunctionJacobian :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const { // from 2d: int j, k, lpi, gpi; Vec<3> n, vgrad; Point<3> pp1; Vec2d g1, vdir; double badness, hbad, hderiv; vgrad = 0; badness = 0; ld.meshthis -> GetNormalVector (ld.surfi, ld.sp1, ld.gi1, n); // pp1 = sp1; // pp1.Add2 (x.Get(1), t1, x.Get(2), t2); pp1 = ld.sp1 + x(0) * ld.t1 + x(1) * ld.t2; static Array pts2d; pts2d.SetSize(mesh.GetNP()); deriv = 0; for (j = 1; j <= ld.locelements.Size(); j++) { lpi = ld.locrots.Get(j); const Element2d & bel = mesh[ld.locelements.Get(j)]; gpi = bel.PNum(lpi); for (k = 1; k <= bel.GetNP(); k++) { PointIndex pi = bel.PNum(k); pts2d.Elem(pi) = Point2d (ld.t1 * (mesh.Point(pi) - ld.sp1), ld.t2 * (mesh.Point(pi) - ld.sp1)); } pts2d.Elem(gpi) = Point2d (x(0), x(1)); vdir = Vec2d (dir(0), dir(1)); hbad = bel. CalcJacobianBadnessDirDeriv (pts2d, lpi, vdir, hderiv); deriv += hderiv; badness += hbad; } return badness; } MeshOptimize2d dummy; MeshOptimize2d :: MeshOptimize2d () { SetFaceIndex (0); SetImproveEdges (0); SetMetricWeight (0); SetWriteStatus (1); } void MeshOptimize2d :: SelectSurfaceOfPoint (const Point<3> & p, const PointGeomInfo & gi) { ; } void MeshOptimize2d :: ImproveMesh (Mesh & mesh, const MeshingParameters & mp) { if (!faceindex) { PrintMessage (3, "Smoothing"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) { ImproveMesh (mesh, mp); if (multithread.terminate) throw NgException ("Meshing stopped"); } faceindex = 0; return; } static Timer timer("MeshSmoothing 2D"); static int timer1 = NgProfiler::CreateTimer ("MeshSmoothing 2D start"); static int timer2 = NgProfiler::CreateTimer ("MeshSmoothing 2D - BFGS"); RegionTimer reg (timer); NgProfiler::StartTimer (timer1); CheckMeshApproximation (mesh); Opti2dLocalData ld; Array seia; mesh.GetSurfaceElementsOfFace (faceindex, seia); bool mixed = 0; for (int i = 0; i < seia.Size(); i++) if (mesh[seia[i]].GetNP() != 3) { mixed = 1; break; } Vector x(2); Array savepoints(mesh.GetNP()); ld.uselocalh = mp.uselocalh; Array compress(mesh.GetNP()); Array icompress; for (int i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) compress[el[j]] = -1; } for (int i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) if (compress[el[j]] == -1) { compress[el[j]] = icompress.Size(); icompress.Append(el[j]); } } Array cnta(icompress.Size()); cnta = 0; for (int i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) cnta[compress[el[j]]]++; } TABLE elementsonpoint(cnta); for (int i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) elementsonpoint.Add (compress[el[j]], seia[i]); } /* Array nelementsonpoint(mesh.GetNP()); nelementsonpoint = 0; for (int i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) nelementsonpoint[el[j]]++; } TABLE elementsonpoint(nelementsonpoint); for (int i = 0; i < seia.Size(); i++) { const Element2d & el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) elementsonpoint.Add (el[j], seia[i]); } */ ld.loch = mp.maxh; ld.locmetricweight = metricweight; ld.meshthis = this; Opti2SurfaceMinFunction surfminf(mesh, ld); Opti2EdgeMinFunction edgeminf(mesh, ld); Opti2SurfaceMinFunctionJacobian surfminfj(mesh, ld); OptiParameters par; par.maxit_linsearch = 8; par.maxit_bfgs = 5; /* int i, j, k; Vector xedge(1); if (improveedges) for (i = 1; i <= mesh.GetNP(); i++) if (mesh.PointType(i) == EDGEPOINT) { continue; PrintDot (); sp1 = mesh.Point(i); locelements.SetSize(0); locrots.SetSize (0); lochs.SetSize (0); surfi = surfi2 = surfi3 = 0; for (j = 0; j < elementsonpoint[i].Size(); j++) { sei = elementsonpoint[i][j]; const Element2d * bel = &mesh[sei]; if (!surfi) surfi = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr(); else if (surfi != mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr()) { if (surfi2 != 0 && surfi2 != mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr()) surfi3 = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr(); else surfi2 = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr(); } locelements.Append (sei); if (bel->PNum(1) == i) locrots.Append (1); else if (bel->PNum(2) == i) locrots.Append (2); else locrots.Append (3); if (uselocalh) { Point3d pmid = Center (mesh.Point(bel->PNum(1)), mesh.Point(bel->PNum(2)), mesh.Point(bel->PNum(3))); lochs.Append (mesh.GetH(pmid)); } } if (surfi2 && !surfi3) { Vec3d n1, n2; GetNormalVector (surfi, sp1, n1); GetNormalVector (surfi2, sp1, n2); t1 = Cross (n1, n2); xedge = 0; BFGS (xedge, edgeminf, par, 1e-6); mesh.Point(i).X() += xedge.Get(1) * t1.X(); mesh.Point(i).Y() += xedge.Get(1) * t1.Y(); mesh.Point(i).Z() += xedge.Get(1) * t1.Z(); ProjectPoint2 (surfi, surfi2, mesh.Point(i)); } } */ bool printeddot = 0; char plotchar = '.'; int modplot = 1; if (mesh.GetNP() > 1000) { plotchar = '+'; modplot = 100; } if (mesh.GetNP() > 10000) { plotchar = 'o'; modplot = 1000; } if (mesh.GetNP() > 100000) { plotchar = 'O'; modplot = 10000; } int cnt = 0; NgProfiler::StopTimer (timer1); /* for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) if (mesh[pi].Type() == SURFACEPOINT) */ for (int hi = 0; hi < icompress.Size(); hi++) { PointIndex pi = icompress[hi]; if (mesh[pi].Type() == SURFACEPOINT) { if (multithread.terminate) throw NgException ("Meshing stopped"); cnt++; if (cnt % modplot == 0 && writestatus) { printeddot = 1; PrintDot (plotchar); } // if (elementsonpoint[pi].Size() == 0) continue; if (elementsonpoint[hi].Size() == 0) continue; ld.sp1 = mesh[pi]; // Element2d & hel = mesh[elementsonpoint[pi][0]]; Element2d & hel = mesh[elementsonpoint[hi][0]]; int hpi = 0; for (int j = 1; j <= hel.GetNP(); j++) if (hel.PNum(j) == pi) { hpi = j; break; } ld.gi1 = hel.GeomInfoPi(hpi); SelectSurfaceOfPoint (ld.sp1, ld.gi1); ld.locelements.SetSize(0); ld.locrots.SetSize (0); ld.lochs.SetSize (0); ld.loc_pnts2.SetSize (0); ld.loc_pnts3.SetSize (0); for (int j = 0; j < elementsonpoint[hi].Size(); j++) { SurfaceElementIndex sei = elementsonpoint[hi][j]; const Element2d & bel = mesh[sei]; ld.surfi = mesh.GetFaceDescriptor(bel.GetIndex()).SurfNr(); ld.locelements.Append (sei); for (int k = 1; k <= bel.GetNP(); k++) if (bel.PNum(k) == pi) { ld.locrots.Append (k); ld.loc_pnts2.Append (mesh[bel.PNumMod(k + 1)]); ld.loc_pnts3.Append (mesh[bel.PNumMod(k + 2)]); break; } if (ld.uselocalh) { Point3d pmid = Center (mesh[bel[0]], mesh[bel[1]], mesh[bel[2]]); ld.lochs.Append (mesh.GetH(pmid)); } } GetNormalVector (ld.surfi, ld.sp1, ld.gi1, ld.normal); ld.t1 = ld.normal.GetNormal (); ld.t2 = Cross (ld.normal, ld.t1); // save points, and project to tangential plane for (int j = 0; j < ld.locelements.Size(); j++) { const Element2d & el = mesh[ld.locelements[j]]; for (int k = 0; k < el.GetNP(); k++) savepoints[el[k]] = mesh[el[k]]; } for (int j = 0; j < ld.locelements.Size(); j++) { const Element2d & el = mesh[ld.locelements[j]]; for (int k = 0; k < el.GetNP(); k++) { PointIndex hhpi = el[k]; double lam = ld.normal * (mesh[hhpi] - ld.sp1); mesh[hhpi] -= lam * ld.normal; } } x = 0; par.typx = 0.3*ld.lochs[0]; NgProfiler::StartTimer (timer2); if (mixed) { BFGS (x, surfminfj, par, 1e-6); } else { BFGS (x, surfminf, par, 1e-6); } NgProfiler::StopTimer (timer2); Point3d origp = mesh[pi]; int loci = 1; double fact = 1; int moveisok = 0; // restore other points for (int j = 0; j < ld.locelements.Size(); j++) { const Element2d & el = mesh[ld.locelements[j]]; for (int k = 0; k < el.GetNP(); k++) { PointIndex hhpi = el[k]; if (hhpi != pi) mesh[hhpi] = savepoints[hhpi]; } } //optimizer loop (if whole distance is not possible, move only a bit!!!!) while (loci <= 5 && !moveisok) { loci ++; /* mesh[pi].X() = origp.X() + (x.Get(1) * t1.X() + x.Get(2) * t2.X())*fact; mesh[pi].Y() = origp.Y() + (x.Get(1) * t1.Y() + x.Get(2) * t2.Y())*fact; mesh[pi].Z() = origp.Z() + (x.Get(1) * t1.Z() + x.Get(2) * t2.Z())*fact; */ Vec<3> hv = x(0) * ld.t1 + x(1) * ld.t2; Point3d hnp = origp + Vec3d (hv); mesh[pi](0) = hnp.X(); mesh[pi](1) = hnp.Y(); mesh[pi](2) = hnp.Z(); fact = fact/2.; // ProjectPoint (surfi, mesh[pi]); // moveisok = CalcPointGeomInfo(surfi, ngi, mesh[pi]); PointGeomInfo ngi; ngi = ld.gi1; moveisok = ProjectPointGI (ld.surfi, mesh[pi], ngi); // point lies on same chart in stlsurface if (moveisok) { for (int j = 0; j < ld.locelements.Size(); j++) mesh[ld.locelements[j]].GeomInfoPi(ld.locrots[j]) = ngi; } else { mesh[pi] = Point<3> (origp); } } } } if (printeddot) PrintDot ('\n'); CheckMeshApproximation (mesh); mesh.SetNextTimeStamp(); } void MeshOptimize2d :: GetNormalVector(INDEX /* surfind */, const Point<3> & p, Vec<3> & nv) const { nv = Vec<3> (0, 0, 1); } void MeshOptimize2d :: GetNormalVector(INDEX surfind, const Point<3> & p, PointGeomInfo & gi, Vec<3> & n) const { GetNormalVector (surfind, p, n); } } netgen-6.2.1905/libsrc/meshing/parallelmesh.cpp0000644000175000017500000015064113504650527020075 0ustar kurtkurt#ifdef PARALLEL #include #include "paralleltop.hpp" // #define METIS4 #ifdef METIS namespace metis { extern "C" { #include #if METIS_VER_MAJOR >= 5 #define METIS5 typedef idx_t idxtype; #else #define METIS4 typedef idxtype idx_t; #endif } } using namespace metis; #endif namespace netgen { template <> inline MPI_Datatype MyGetMPIType ( ) { return MPI_INT; } void Mesh :: SendRecvMesh () { int id = GetCommunicator().Rank(); int np = GetCommunicator().Size(); if (np == 1) { throw NgException("SendRecvMesh called, but only one rank in communicator!!"); } if (id == 0) PrintMessage (1, "Send/Receive mesh"); // Why is this here?? if (id == 0) { paralleltop -> SetNV (GetNV()); paralleltop -> SetNE (GetNE()); paralleltop -> SetNSegm (GetNSeg()); paralleltop -> SetNSE (GetNSE()); } if (id == 0) SendMesh (); else ReceiveParallelMesh(); paralleltop -> UpdateCoarseGrid(); } void Mesh :: SendMesh () const { Array sendrequests; NgMPI_Comm comm = GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); int dim = GetDimension(); MyMPI_Bcast(dim, comm); // If the topology is not already updated, we do not need to // build edges/faces. auto & top = const_cast(GetTopology()); if(top.NeedsUpdate()) { top.SetBuildEdges(false); top.SetBuildFaces(false); top.Update(); } PrintMessage ( 3, "Sending nr of elements"); Array num_els_on_proc(ntasks); num_els_on_proc = 0; for (ElementIndex ei = 0; ei < GetNE(); ei++) // num_els_on_proc[(*this)[ei].GetPartition()]++; num_els_on_proc[vol_partition[ei]]++; MPI_Scatter (&num_els_on_proc[0], 1, MPI_INT, MPI_IN_PLACE, -1, MPI_INT, 0, comm); TABLE els_of_proc (num_els_on_proc); for (ElementIndex ei = 0; ei < GetNE(); ei++) // els_of_proc.Add ( (*this)[ei].GetPartition(), ei); els_of_proc.Add (vol_partition[ei], ei); PrintMessage ( 3, "Building vertex/proc mapping"); Array num_sels_on_proc(ntasks); num_sels_on_proc = 0; for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) // num_sels_on_proc[(*this)[ei].GetPartition()]++; num_sels_on_proc[surf_partition[ei]]++; TABLE sels_of_proc (num_sels_on_proc); for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) // sels_of_proc.Add ( (*this)[ei].GetPartition(), ei); sels_of_proc.Add (surf_partition[ei], ei); Array num_segs_on_proc(ntasks); num_segs_on_proc = 0; for (SegmentIndex ei = 0; ei < GetNSeg(); ei++) // num_segs_on_proc[(*this)[ei].GetPartition()]++; num_segs_on_proc[seg_partition[ei]]++; TABLE segs_of_proc (num_segs_on_proc); for (SegmentIndex ei = 0; ei < GetNSeg(); ei++) segs_of_proc.Add (seg_partition[ei], ei); /** ----- STRATEGY FOR PERIODIC MESHES ----- Whenever two vertices are identified by periodicity, any proc that gets one of the vertices actually gets both of them. This has to be transitive, that is, if a <-> b and b <-> c, then any proc that has vertex a also has vertices b and c! Surfaceelements and Segments that are identified by periodicity are treated the same way. We need to duplicate these so we have containers to hold the edges/facets. Afaik, a mesh cannot have nodes that are not part of some sort of element. **/ /** First, we build tables for vertex identification. **/ Array per_pairs; Array pp2; auto & idents = GetIdentifications(); bool has_periodic = false; for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) { if(idents.GetType(idnr)!=Identifications::PERIODIC) continue; has_periodic = true; idents.GetPairs(idnr, pp2); per_pairs.Append(pp2); } Array npvs(GetNV()); npvs = 0; for (int k = 0; k < per_pairs.Size(); k++) { npvs[per_pairs[k].I1()]++; npvs[per_pairs[k].I2()]++; } /** for each vertex, gives us all identified vertices **/ TABLE per_verts(npvs); for (int k = 0; k < per_pairs.Size(); k++) { per_verts.Add(per_pairs[k].I1(), per_pairs[k].I2()); per_verts.Add(per_pairs[k].I2(), per_pairs[k].I1()); } for (int k = PointIndex::BASE; k < GetNV()+PointIndex::BASE; k++) { BubbleSort(per_verts[k]); } /** The same table as per_verts, but TRANSITIVE!! **/ auto iterate_per_verts_trans = [&](auto f){ Array allvs; for (int k = PointIndex::BASE; k < GetNV()+PointIndex::BASE; k++) { allvs.SetSize(0); allvs.Append(per_verts[k]); bool changed = true; while(changed) { changed = false; for (int j = 0; j per_verts_trans(npvs); iterate_per_verts_trans([&](auto k, auto & allvs) { for (int j = 0; j vert_flag (GetNV()); Array num_procs_on_vert (GetNV()); Array num_verts_on_proc (ntasks); num_verts_on_proc = 0; num_procs_on_vert = 0; auto iterate_vertices = [&](auto f) { vert_flag = -1; for (int dest = 1; dest < ntasks; dest++) { FlatArray els = els_of_proc[dest]; for (int hi = 0; hi < els.Size(); hi++) { const Element & el = (*this) [ els[hi] ]; for (int i = 0; i < el.GetNP(); i++) f(el[i], dest); } FlatArray sels = sels_of_proc[dest]; for (int hi = 0; hi < sels.Size(); hi++) { const Element2d & el = (*this) [ sels[hi] ]; for (int i = 0; i < el.GetNP(); i++) f(el[i], dest); } FlatArray segs = segs_of_proc[dest]; for (int hi = 0; hi < segs.Size(); hi++) { const Segment & el = (*this) [segs[hi]]; for (int i = 0; i < 2; i++) f(el[i], dest); } } }; /** count vertices per proc and procs per vertex **/ iterate_vertices([&](auto vertex, auto dest){ auto countit = [&] (auto vertex, auto dest) { if (vert_flag[vertex] < dest) { vert_flag[vertex] = dest; num_verts_on_proc[dest]++; num_procs_on_vert[vertex]++; GetParallelTopology().SetDistantPNum (dest, vertex); } }; countit(vertex, dest); auto pers = per_verts_trans[vertex]; for(int j = 0; j < pers.Size(); j++) countit(pers[j], dest); }); TABLE verts_of_proc (num_verts_on_proc); TABLE procs_of_vert (num_procs_on_vert); TABLE loc_num_of_vert (num_procs_on_vert); /** Write vertex/proc mappingfs to tables **/ iterate_vertices([&](auto vertex, auto dest) { auto addit = [&] (auto vertex, auto dest) { if (vert_flag[vertex] < dest) { vert_flag[vertex] = dest; procs_of_vert.Add (vertex, dest); } }; addit(vertex, dest); auto pers = per_verts_trans[vertex]; for(int j = 0; j < pers.Size(); j++) addit(pers[j], dest); }); /** local vertex numbers on distant procs (I think this was only used for debugging??) **/ for (int vert = 1; vert <= GetNP(); vert++ ) { FlatArray procs = procs_of_vert[vert]; for (int j = 0; j < procs.Size(); j++) { int dest = procs[j]; verts_of_proc.Add (dest, vert); loc_num_of_vert.Add (vert, verts_of_proc[dest].Size()); } } PrintMessage ( 3, "Sending Vertices - vertices"); for (int dest = 1; dest < ntasks; dest++) { FlatArray verts = verts_of_proc[dest]; sendrequests.Append (MyMPI_ISend (verts, dest, MPI_TAG_MESH+1, comm)); MPI_Datatype mptype = MeshPoint::MyGetMPIType(); int numv = verts.Size(); MPI_Datatype newtype; Array blocklen (numv); blocklen = 1; MPI_Type_indexed (numv, &blocklen[0], reinterpret_cast (&verts[0]), mptype, &newtype); MPI_Type_commit (&newtype); MPI_Request request; MPI_Isend( &points[0], 1, newtype, dest, MPI_TAG_MESH+1, comm, &request); sendrequests.Append (request); } Array num_distpnums(ntasks); num_distpnums = 0; /** Next, we send the identifications themselfs. Info about periodic identifications sent to each proc is an array of integers. - maxidentnr - type for each identification - nr of pairs for each identification (each pair is local!) - pairs for each periodic ident (global numbers) **/ PrintMessage ( 3, "Sending Vertices - identifications"); int maxidentnr = idents.GetMaxNr(); Array ppd_sizes(ntasks); ppd_sizes = 1 + 2*maxidentnr; for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) { if(idents.GetType(idnr)!=Identifications::PERIODIC) continue; idents.GetPairs(idnr, pp2); for(int j = 0; j pp_data(ppd_sizes); for(int dest = 0; dest < ntasks; dest++) pp_data.Add(dest, maxidentnr); for (int dest = 0; dest < ntasks; dest++) { for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) pp_data.Add(dest, idents.GetType(idnr)); for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) pp_data.Add(dest, 0); } for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) { if(idents.GetType(idnr)!=Identifications::PERIODIC) continue; idents.GetPairs(idnr, pp2); for(int j = 0; j req_per; for(int dest = 1; dest < ntasks; dest++) req_per.Append(MyMPI_ISend(pp_data[dest], dest, MPI_TAG_MESH+1, comm)); MPI_Waitall(req_per.Size(), &req_per[0], MPI_STATUS_IGNORE); PrintMessage ( 3, "Sending Vertices - distprocs"); for (int vert = 1; vert <= GetNP(); vert++) { FlatArray procs = procs_of_vert[vert]; for (int j = 0; j < procs.Size(); j++) num_distpnums[procs[j]] += 3 * (procs.Size()-1); } TABLE distpnums (num_distpnums); for (int vert = 1; vert <= GetNP(); vert++) { FlatArray procs = procs_of_vert[vert]; for (int j = 0; j < procs.Size(); j++) for (int k = 0; k < procs.Size(); k++) if (j != k) { distpnums.Add (procs[j], loc_num_of_vert[vert][j]); distpnums.Add (procs[j], procs_of_vert[vert][k]); distpnums.Add (procs[j], loc_num_of_vert[vert][k]); } } for ( int dest = 1; dest < ntasks; dest ++ ) sendrequests.Append (MyMPI_ISend (distpnums[dest], dest, MPI_TAG_MESH+1, comm)); PrintMessage ( 3, "Sending elements" ); Array elarraysize (ntasks); elarraysize = 0; for ( int ei = 1; ei <= GetNE(); ei++) { const Element & el = VolumeElement (ei); // int dest = el.GetPartition(); int dest = vol_partition[ei-1]; elarraysize[dest] += 3 + el.GetNP(); } TABLE elementarrays(elarraysize); for (int ei = 1; ei <= GetNE(); ei++) { const Element & el = VolumeElement (ei); // int dest = el.GetPartition(); int dest = vol_partition[ei-1]; elementarrays.Add (dest, ei); elementarrays.Add (dest, el.GetIndex()); elementarrays.Add (dest, el.GetNP()); for (int i = 0; i < el.GetNP(); i++) elementarrays.Add (dest, el[i]); } for (int dest = 1; dest < ntasks; dest ++ ) sendrequests.Append (MyMPI_ISend (elementarrays[dest], dest, MPI_TAG_MESH+2, comm)); PrintMessage ( 3, "Sending Face Descriptors" ); Array fddata (6 * GetNFD()); for (int fdi = 1; fdi <= GetNFD(); fdi++) { fddata[6*fdi-6] = GetFaceDescriptor(fdi).SurfNr(); fddata[6*fdi-5] = GetFaceDescriptor(fdi).DomainIn(); fddata[6*fdi-4] = GetFaceDescriptor(fdi).DomainOut(); fddata[6*fdi-3] = GetFaceDescriptor(fdi).BCProperty(); fddata[6*fdi-2] = GetFaceDescriptor(fdi).domin_singular; fddata[6*fdi-1] = GetFaceDescriptor(fdi).domout_singular; } for (int dest = 1; dest < ntasks; dest++) sendrequests.Append (MyMPI_ISend (fddata, dest, MPI_TAG_MESH+3, comm)); /** Surface Elements **/ PrintMessage ( 3, "Sending Surface elements" ); // build sel-identification size_t nse = GetNSE(); Array ided_sel(nse); ided_sel = -1; bool has_ided_sels = false; if(GetNE() && has_periodic) //we can only have identified surf-els if we have vol-els (right?) { Array os1, os2; for(SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { if(ided_sel[sei]!=-1) continue; const Element2d & sel = (*this)[sei]; FlatArray points = sel.PNums(); auto ided1 = per_verts[points[0]]; os1.SetSize(0); for (int j = 0; j < ided1.Size(); j++) os1.Append(GetTopology().GetVertexSurfaceElements(ided1[j])); for (int j = 1; j < points.Size(); j++) { os2.SetSize(0); auto p2 = points[j]; auto ided2 = per_verts[p2]; for (int l = 0; l < ided2.Size(); l++) os2.Append(GetTopology().GetVertexSurfaceElements(ided2[l])); for (int m = 0; m1) { throw NgException("SurfaceElement identified with more than one other??"); } const Element2d & sel2 = (*this)[sei]; FlatArray points2 = sel2.PNums(); has_ided_sels = true; ided_sel[sei] = os1[0]; ided_sel[os1[0]] = sei; } } // build sel data to send auto iterate_sels = [&](auto f) { for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++ ) { const Element2d & sel = (*this)[sei]; // int dest = (*this)[sei].GetPartition(); int dest = surf_partition[sei]; f(sei, sel, dest); if(ided_sel[sei]!=-1) { // int dest2 = (*this)[ided_sel[sei]].GetPartition(); int dest2 = surf_partition[ided_sel[sei]]; f(sei, sel, dest2); } } }; Array nlocsel(ntasks), bufsize(ntasks); nlocsel = 0; bufsize = 1; iterate_sels([&](SurfaceElementIndex sei, const Element2d & sel, int dest){ nlocsel[dest]++; bufsize[dest] += 4 + 2*sel.GetNP(); }); TABLE selbuf(bufsize); for (int dest = 1; dest < ntasks; dest++ ) selbuf.Add (dest, nlocsel[dest]); iterate_sels([&](SurfaceElementIndex sei, const auto & sel, int dest) { selbuf.Add (dest, sei); selbuf.Add (dest, sel.GetIndex()); // selbuf.Add (dest, 0); selbuf.Add (dest, sel.GetNP()); for ( int ii = 1; ii <= sel.GetNP(); ii++) { selbuf.Add (dest, sel.PNum(ii)); selbuf.Add (dest, sel.GeomInfoPi(ii).trignum); } }); // distribute sel data for (int dest = 1; dest < ntasks; dest++) sendrequests.Append (MyMPI_ISend(selbuf[dest], dest, MPI_TAG_MESH+4, comm)); /** Segments **/ PrintMessage ( 3, "Sending Edge Segments"); auto iterate_segs1 = [&](auto f) { Array osegs1, osegs2, osegs_both; Array type1, type2; for(SegmentIndex segi = 0; segi < GetNSeg(); segi++) { const Segment & seg = (*this)[segi]; int segnp = seg.GetNP(); PointIndex pi1 = seg[0]; auto ided1 = per_verts[pi1]; PointIndex pi2 = seg[1]; auto ided2 = per_verts[pi2]; if (!(ided1.Size() && ided2.Size())) continue; osegs1.SetSize(0); type1.SetSize(0); for (int l = 0; l per_seg_size(GetNSeg()); per_seg_size = 0; iterate_segs1([&](SegmentIndex segi1, SegmentIndex segi2) { per_seg_size[segi1]++; }); TABLE per_seg(per_seg_size); iterate_segs1([&](SegmentIndex segi1, SegmentIndex segi2) { per_seg.Add(segi1, segi2); }); // make per_seg transitive auto iterate_per_seg_trans = [&](auto f){ Array allsegs; for (SegmentIndex segi = 0; segi < GetNSeg(); segi++) { allsegs.SetSize(0); allsegs.Append(per_seg[segi]); bool changed = true; while (changed) { changed = false; for (int j = 0; j & segs){ for (int j = 0; j < segs.Size(); j++) per_seg_size[segi] = segs.Size(); }); TABLE per_seg_trans(per_seg_size); iterate_per_seg_trans([&](SegmentIndex segi, Array & segs){ for (int j = 0; j < segs.Size(); j++) per_seg_trans.Add(segi, segs[j]); }); // build segment data Array dests; auto iterate_segs2 = [&](auto f) { for (SegmentIndex segi = 0; segi nloc_seg(ntasks); // bufsize = 1; //was originally this - why?? bufsize = 0; nloc_seg = 0; iterate_segs2([&](auto segi, const auto & seg, int dest) { nloc_seg[dest]++; bufsize[dest] += 14; }); TABLE segm_buf(bufsize); iterate_segs2([&](auto segi, const auto & seg, int dest) { segm_buf.Add (dest, segi); segm_buf.Add (dest, seg.si); segm_buf.Add (dest, seg.pnums[0]); segm_buf.Add (dest, seg.pnums[1]); segm_buf.Add (dest, seg.geominfo[0].trignum); segm_buf.Add (dest, seg.geominfo[1].trignum); segm_buf.Add (dest, seg.surfnr1); segm_buf.Add (dest, seg.surfnr2); segm_buf.Add (dest, seg.edgenr); segm_buf.Add (dest, seg.epgeominfo[0].dist); segm_buf.Add (dest, seg.epgeominfo[1].edgenr); segm_buf.Add (dest, seg.epgeominfo[1].dist); segm_buf.Add (dest, seg.singedge_right); segm_buf.Add (dest, seg.singedge_left); }); // distrubute segment data for (int dest = 1; dest < ntasks; dest++) sendrequests.Append (MyMPI_ISend(segm_buf[dest], dest, MPI_TAG_MESH+5, comm)); PrintMessage ( 3, "now wait ..."); MPI_Waitall (sendrequests.Size(), &sendrequests[0], MPI_STATUS_IGNORE); PrintMessage ( 3, "Sending names"); sendrequests.SetSize(3*ntasks); /** Send bc/mat/cd*-names **/ // nr of names int nnames[4] = {0,0,0,0}; nnames[0] = materials.Size(); nnames[1] = bcnames.Size(); nnames[2] = GetNCD2Names(); nnames[3] = GetNCD3Names(); int tot_nn = nnames[0] + nnames[1] + nnames[2] + nnames[3]; for( int k = 1; k < ntasks; k++) (void) MPI_Isend(nnames, 4, MPI_INT, k, MPI_TAG_MESH+6, comm, &sendrequests[k]); auto iterate_names = [&](auto func) { for (int k = 0; k < nnames[0]; k++) func(materials[k]); for (int k = 0; k < nnames[1]; k++) func(bcnames[k]); for (int k = 0; k < nnames[2]; k++) func(cd2names[k]); for (int k = 0; k < nnames[3]; k++) func(cd3names[k]); }; // sizes of names Array name_sizes(tot_nn); tot_nn = 0; iterate_names([&](auto ptr) { name_sizes[tot_nn++] = (ptr==NULL) ? 0 : ptr->size(); }); for( int k = 1; k < ntasks; k++) (void) MPI_Isend(&name_sizes[0], tot_nn, MPI_INT, k, MPI_TAG_MESH+6, comm, &sendrequests[ntasks+k]); // names int strs = 0; iterate_names([&](auto ptr) { strs += (ptr==NULL) ? 0 : ptr->size(); }); Array compiled_names(strs); strs = 0; iterate_names([&](auto ptr) { if (ptr==NULL) return; auto& name = *ptr; for (int j=0; j < name.size(); j++) compiled_names[strs++] = name[j]; }); for( int k = 1; k < ntasks; k++) (void) MPI_Isend(&(compiled_names[0]), strs, MPI_CHAR, k, MPI_TAG_MESH+6, comm, &sendrequests[2*ntasks+k]); PrintMessage ( 3, "wait for names"); MPI_Waitall (sendrequests.Size(), &sendrequests[0], MPI_STATUS_IGNORE); MPI_Barrier(comm); PrintMessage( 3, "Clean up local memory"); auto & self = const_cast(*this); self.points = T_POINTS(0); self.surfelements = T_SURFELEMENTS(0); self.volelements = T_VOLELEMENTS(0); self.segments = Array(0); self.lockedpoints = Array(0); auto cleanup_ptr = [](auto & ptr) { if (ptr != nullptr) { delete ptr; ptr = nullptr; } }; cleanup_ptr(self.boundaryedges); cleanup_ptr(self.boundaryedges); cleanup_ptr(self.segmentht); cleanup_ptr(self.surfelementht); self.openelements = Array(0); self.opensegments = Array(0); self.numvertices = 0; self.mlbetweennodes = Array,PointIndex::BASE> (0); self.mlparentelement = Array(0); self.mlparentsurfaceelement = Array(0); self.curvedelems = new CurvedElements (self); self.clusters = new AnisotropicClusters (self); self.ident = new Identifications (self); self.topology = MeshTopology(*this); self.topology.Update(); self.BuildElementSearchTree(); // const_cast(*this).DeleteMesh(); PrintMessage( 3, "send mesh complete"); } // slaves receive the mesh from the master void Mesh :: ReceiveParallelMesh ( ) { int timer = NgProfiler::CreateTimer ("ReceiveParallelMesh"); int timer_pts = NgProfiler::CreateTimer ("Receive points"); int timer_els = NgProfiler::CreateTimer ("Receive elements"); int timer_sels = NgProfiler::CreateTimer ("Receive surface elements"); NgProfiler::RegionTimer reg(timer); NgMPI_Comm comm = GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); int dim; MyMPI_Bcast(dim, comm); SetDimension(dim); // Receive number of local elements int nelloc; MPI_Scatter (NULL, 0, MPI_INT, &nelloc, 1, MPI_INT, 0, comm); paralleltop -> SetNE (nelloc); // string st; // receive vertices NgProfiler::StartTimer (timer_pts); Array verts; MyMPI_Recv (verts, 0, MPI_TAG_MESH+1, comm); int numvert = verts.Size(); paralleltop -> SetNV (numvert); // INDEX_CLOSED_HASHTABLE glob2loc_vert_ht (3*numvert+1); INDEX_HASHTABLE glob2loc_vert_ht (3*numvert+1); for (int vert = 0; vert < numvert; vert++) { int globvert = verts[vert]; paralleltop->SetLoc2Glob_Vert ( vert+1, globvert ); glob2loc_vert_ht.Set (globvert, vert+1); } for (int i = 0; i < numvert; i++) AddPoint (netgen::Point<3> (0,0,0)); MPI_Datatype mptype = MeshPoint::MyGetMPIType(); MPI_Status status; MPI_Recv( &points[1], numvert, mptype, 0, MPI_TAG_MESH+1, comm, &status); Array pp_data; MyMPI_Recv(pp_data, 0, MPI_TAG_MESH+1, comm); int maxidentnr = pp_data[0]; auto & idents = GetIdentifications(); for (int idnr = 1; idnr < maxidentnr+1; idnr++) { idents.SetType(idnr, (Identifications::ID_TYPE)pp_data[idnr]); } int offset = 2*maxidentnr+1; for(int idnr = 1; idnr < maxidentnr+1; idnr++) { int npairs = pp_data[maxidentnr+idnr]; FlatArray pairdata(2*npairs, &pp_data[offset]); offset += 2*npairs; for (int k = 0; k dist_pnums; MyMPI_Recv (dist_pnums, 0, MPI_TAG_MESH+1, comm); for (int hi = 0; hi < dist_pnums.Size(); hi += 3) paralleltop -> SetDistantPNum (dist_pnums[hi+1], dist_pnums[hi]); // , dist_pnums[hi+2]); NgProfiler::StopTimer (timer_pts); *testout << "got " << numvert << " vertices" << endl; { Array elarray; MyMPI_Recv (elarray, 0, MPI_TAG_MESH+2, comm); NgProfiler::RegionTimer reg(timer_els); for (int ind = 0, elnum = 1; ind < elarray.Size(); elnum++) { paralleltop->SetLoc2Glob_VolEl ( elnum, elarray[ind++]); int index = elarray[ind++]; Element el(elarray[ind++]); el.SetIndex(index); for ( int j = 0; j < el.GetNP(); j++) el[j] = glob2loc_vert_ht.Get (elarray[ind++]); AddVolumeElement (el); } } { Array fddata; MyMPI_Recv (fddata, 0, MPI_TAG_MESH+3, comm); for (int i = 0; i < fddata.Size(); i += 6) { int faceind = AddFaceDescriptor (FaceDescriptor(int(fddata[i]), int(fddata[i+1]), int(fddata[i+2]), 0)); GetFaceDescriptor(faceind).SetBCProperty (int(fddata[i+3])); GetFaceDescriptor(faceind).domin_singular = fddata[i+4]; GetFaceDescriptor(faceind).domout_singular = fddata[i+5]; } } { NgProfiler::RegionTimer reg(timer_sels); Array selbuf; MyMPI_Recv ( selbuf, 0, MPI_TAG_MESH+4, comm); int ii = 0; int sel = 0; int nlocsel = selbuf[ii++]; paralleltop -> SetNSE ( nlocsel ); while (ii < selbuf.Size()-1) { int globsel = selbuf[ii++]; int faceind = selbuf[ii++]; //bool isghost = selbuf[ii++]; int nep = selbuf[ii++]; Element2d tri(nep); tri.SetIndex(faceind); for(int j = 1; j <= nep; j++) { tri.PNum(j) = glob2loc_vert_ht.Get (selbuf[ii++]); tri.GeomInfoPi(j).trignum = selbuf[ii++]; } paralleltop->SetLoc2Glob_SurfEl ( sel+1, globsel ); AddSurfaceElement (tri); sel ++; } } { Array segmbuf; MyMPI_Recv ( segmbuf, 0, MPI_TAG_MESH+5, comm); Segment seg; int globsegi; int ii = 0; int segi = 1; int nsegloc = int ( segmbuf.Size() / 14 ) ; paralleltop -> SetNSegm ( nsegloc ); while ( ii < segmbuf.Size() ) { globsegi = int (segmbuf[ii++]); seg.si = int (segmbuf[ii++]); seg.pnums[0] = glob2loc_vert_ht.Get (int(segmbuf[ii++])); seg.pnums[1] = glob2loc_vert_ht.Get (int(segmbuf[ii++])); seg.geominfo[0].trignum = int( segmbuf[ii++] ); seg.geominfo[1].trignum = int ( segmbuf[ii++]); seg.surfnr1 = int ( segmbuf[ii++]); seg.surfnr2 = int ( segmbuf[ii++]); seg.edgenr = int ( segmbuf[ii++]); seg.epgeominfo[0].dist = segmbuf[ii++]; seg.epgeominfo[1].edgenr = int (segmbuf[ii++]); seg.epgeominfo[1].dist = segmbuf[ii++]; seg.singedge_left = segmbuf[ii++]; seg.singedge_right = segmbuf[ii++]; seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr; seg.domin = seg.surfnr1; seg.domout = seg.surfnr2; if ( seg.pnums[0] >0 && seg.pnums[1] > 0 ) { paralleltop-> SetLoc2Glob_Segm ( segi, globsegi ); AddSegment (seg); segi++; } } } /** Recv bc-names **/ int nnames[4] = {0,0,0,0}; MPI_Recv(nnames, 4, MPI_INT, 0, MPI_TAG_MESH+6, comm, MPI_STATUS_IGNORE); materials.SetSize(nnames[0]); bcnames.SetSize(nnames[1]); cd2names.SetSize(nnames[2]); cd3names.SetSize(nnames[3]); int tot_nn = nnames[0] + nnames[1] + nnames[2] + nnames[3]; Array name_sizes(tot_nn); MPI_Recv(&name_sizes[0], tot_nn, MPI_INT, 0, MPI_TAG_MESH+6, comm, MPI_STATUS_IGNORE); int tot_size = 0; for (int k = 0; k < tot_nn; k++) tot_size += name_sizes[k]; Array compiled_names(tot_size); MPI_Recv(&(compiled_names[0]), tot_size, MPI_CHAR, 0, MPI_TAG_MESH+6, comm, MPI_STATUS_IGNORE); tot_nn = tot_size = 0; auto write_names = [&] (auto & array) { for (int k = 0; k < array.Size(); k++) { int s = name_sizes[tot_nn]; array[k] = new string(&compiled_names[tot_size], s); tot_nn++; tot_size += s; } }; write_names(materials); write_names(bcnames); write_names(cd2names); write_names(cd3names); MPI_Barrier(comm); int timerloc = NgProfiler::CreateTimer ("Update local mesh"); int timerloc2 = NgProfiler::CreateTimer ("CalcSurfacesOfNode"); NgProfiler::RegionTimer regloc(timerloc); stringstream str; str << "p" << id << ": got " << GetNE() << " elements and " << GetNSE() << " surface elements"; PrintMessage(2, str.str()); // cout << str.str() << endl; // PrintMessage (2, "Got ", GetNE(), " elements and ", GetNSE(), " surface elements"); // PrintMessage (2, "Got ", GetNSE(), " surface elements"); NgProfiler::StartTimer (timerloc2); CalcSurfacesOfNode (); NgProfiler::StopTimer (timerloc2); topology.Update(); clusters -> Update(); // paralleltop -> UpdateCoarseGrid(); SetNextMajorTimeStamp(); } // distribute the mesh to the slave processors // call it only for the master ! void Mesh :: Distribute () { NgMPI_Comm comm = GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); if (id != 0 || ntasks == 1 ) return; #ifdef METIS ParallelMetis (); #else for (ElementIndex ei = 0; ei < GetNE(); ei++) (*this)[ei].SetPartition(ntasks * ei/GetNE() + 1); #endif /* for (ElementIndex ei = 0; ei < GetNE(); ei++) *testout << "el(" << ei << ") is in part " << (*this)[ei].GetPartition() << endl; for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) *testout << "sel(" << int(ei) << ") is in part " << (*this)[ei].GetPartition() << endl; */ // MyMPI_SendCmd ("mesh"); SendRecvMesh (); } #ifdef METIS5 void Mesh :: ParallelMetis ( ) { PrintMessage (3, "call metis 5 ..."); int timer = NgProfiler::CreateTimer ("Mesh::Partition"); NgProfiler::RegionTimer reg(timer); idx_t ne = GetNE() + GetNSE() + GetNSeg(); idx_t nn = GetNP(); Array eptr, eind; for (int i = 0; i < GetNE(); i++) { eptr.Append (eind.Size()); const Element & el = VolumeElement(i+1); for (int j = 0; j < el.GetNP(); j++) eind.Append (el[j]-1); } for (int i = 0; i < GetNSE(); i++) { eptr.Append (eind.Size()); const Element2d & el = SurfaceElement(i+1); for (int j = 0; j < el.GetNP(); j++) eind.Append (el[j]-1); } for (int i = 0; i < GetNSeg(); i++) { eptr.Append (eind.Size()); const Segment & el = LineSegment(i+1); eind.Append (el[0]-1); eind.Append (el[1]-1); } eptr.Append (eind.Size()); Array epart(ne), npart(nn); idxtype nparts = GetCommunicator().Size()-1; vol_partition.SetSize(GetNE()); surf_partition.SetSize(GetNSE()); seg_partition.SetSize(GetNSeg()); if (nparts == 1) { for (int i = 0; i < GetNE(); i++) // VolumeElement(i+1).SetPartition(1); vol_partition[i]= 1; for (int i = 0; i < GetNSE(); i++) // SurfaceElement(i+1).SetPartition(1); surf_partition[i] = 1; for (int i = 0; i < GetNSeg(); i++) // LineSegment(i+1).SetPartition(1); seg_partition[i] = 1; } else { idxtype edgecut; idxtype ncommon = 3; METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &ncommon, &nparts, NULL, NULL, &edgecut, &epart[0], &npart[0]); /* METIS_PartMeshNodal (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &nparts, NULL, NULL, &edgecut, &epart[0], &npart[0]); */ PrintMessage (3, "metis complete"); // cout << "done" << endl; for (int i = 0; i < GetNE(); i++) // VolumeElement(i+1).SetPartition(epart[i] + 1); vol_partition[i]= epart[i] + 1; for (int i = 0; i < GetNSE(); i++) // SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); surf_partition[i] = epart[i+GetNE()] + 1; for (int i = 0; i < GetNSeg(); i++) // LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); seg_partition[i] = epart[i+GetNE()+GetNSE()] + 1; } // surface elements attached to volume elements Array boundarypoints (GetNP()); boundarypoints = false; if(GetDimension() == 3) for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & el = (*this)[sei]; for (int j = 0; j < el.GetNP(); j++) boundarypoints[el[j]] = true; } else for (SegmentIndex segi = 0; segi < GetNSeg(); segi++) { const Segment & seg = (*this)[segi]; for (int j = 0; j < 2; j++) boundarypoints[seg[j]] = true; } // Build Pnt2Element table, boundary points only Array cnt(GetNP()); cnt = 0; auto loop_els_2d = [&](auto f) { for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & el = (*this)[sei]; for (int j = 0; j < el.GetNP(); j++) { f(el[j], sei); } } }; auto loop_els_3d = [&](auto f) { for (ElementIndex ei = 0; ei < GetNE(); ei++) { const Element & el = (*this)[ei]; for (int j = 0; j < el.GetNP(); j++) f(el[j], ei); } }; auto loop_els = [&](auto f) { if (GetDimension() == 3 ) loop_els_3d(f); else loop_els_2d(f); }; loop_els([&](auto vertex, int index) { if(boundarypoints[vertex]) cnt[vertex]++; }); TABLE pnt2el(cnt); loop_els([&](auto vertex, int index) { if(boundarypoints[vertex]) pnt2el.Add(vertex, index); }); if (GetDimension() == 3) { for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { Element2d & sel = (*this)[sei]; PointIndex pi1 = sel[0]; // FlatArray els = pnt2el[pi1]; FlatArray els = pnt2el[pi1]; // sel.SetPartition (-1); surf_partition[sei] = -1; for (int j = 0; j < els.Size(); j++) { const Element & el = (*this)[ElementIndex(els[j])]; bool hasall = true; for (int k = 0; k < sel.GetNP(); k++) { bool haspi = false; for (int l = 0; l < el.GetNP(); l++) if (sel[k] == el[l]) haspi = true; if (!haspi) hasall = false; } if (hasall) { // sel.SetPartition (el.GetPartition()); surf_partition[sei] = vol_partition[ElementIndex(els[j])]; break; } } // if (sel.GetPartition() == -1) if (surf_partition[sei] == -1) cerr << "no volume element found" << endl; } for (SegmentIndex si = 0; si < GetNSeg(); si++) { Segment & sel = (*this)[si]; PointIndex pi1 = sel[0]; FlatArray els = pnt2el[pi1]; // sel.SetPartition (-1); seg_partition[si] = -1; for (int j = 0; j < els.Size(); j++) { const Element & el = (*this)[ElementIndex(els[j])]; bool haspi[9] = { false }; // max surfnp for (int k = 0; k < 2; k++) for (int l = 0; l < el.GetNP(); l++) if (sel[k] == el[l]) haspi[k] = true; bool hasall = true; for (int k = 0; k < sel.GetNP(); k++) if (!haspi[k]) hasall = false; if (hasall) { // sel.SetPartition (el.GetPartition()); seg_partition[si] = vol_partition[ElementIndex(els[j])]; break; } } // if (sel.GetPartition() == -1) if (seg_partition[si] == -1) cerr << "no volume element found" << endl; } } else { for (SegmentIndex segi = 0; segi < GetNSeg(); segi++) { Segment & seg = (*this)[segi]; // seg.SetPartition(-1); seg_partition[segi] = -1; PointIndex pi1 = seg[0]; FlatArray sels = pnt2el[pi1]; for (int j = 0; j < sels.Size(); j++) { SurfaceElementIndex sei = sels[j]; Element2d & se = (*this)[sei]; bool found = false; for (int l = 0; l < se.GetNP(); l++ && !found) found |= (se[l]==seg[1]); if(found) { // seg.SetPartition(se.GetPartition()); seg_partition[segi] = surf_partition[sei]; break; } } // if (seg.GetPartition() == -1) { if (seg_partition[segi] == -1) { cout << endl << "segi: " << segi << endl; cout << "points: " << seg[0] << " " << seg[1] << endl; cout << "surfels: " << endl << sels << endl; throw NgException("no surface element found"); } } } } #endif //========================== weights ================================================================= // distribute the mesh to the slave processors // call it only for the master ! void Mesh :: Distribute (Array & volume_weights , Array & surface_weights, Array & segment_weights) { NgMPI_Comm comm = GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); if (id != 0 || ntasks == 1 ) return; #ifdef METIS ParallelMetis (volume_weights, surface_weights, segment_weights); #else for (ElementIndex ei = 0; ei < GetNE(); ei++) (*this)[ei].SetPartition(ntasks * ei/GetNE() + 1); #endif /* for (ElementIndex ei = 0; ei < GetNE(); ei++) *testout << "el(" << ei << ") is in part " << (*this)[ei].GetPartition() << endl; for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) *testout << "sel(" << int(ei) << ") is in part " << (*this)[ei].GetPartition() << endl; */ // MyMPI_SendCmd ("mesh"); SendRecvMesh (); } #ifdef METIS5 void Mesh :: ParallelMetis (Array & volume_weights , Array & surface_weights, Array & segment_weights) { PrintMessage (3, "call metis 5 with weights ..."); // cout << "segment_weights " << segment_weights << endl; // cout << "surface_weights " << surface_weights << endl; // cout << "volume_weights " << volume_weights << endl; int timer = NgProfiler::CreateTimer ("Mesh::Partition"); NgProfiler::RegionTimer reg(timer); idx_t ne = GetNE() + GetNSE() + GetNSeg(); idx_t nn = GetNP(); Array eptr, eind , nwgt; for (int i = 0; i < GetNE(); i++) { eptr.Append (eind.Size()); const Element & el = VolumeElement(i+1); int ind = el.GetIndex(); if (volume_weights.Size() epart(ne), npart(nn); idxtype nparts = GetCommunicator().Size()-1; vol_partition.SetSize(GetNE()); surf_partition.SetSize(GetNSE()); seg_partition.SetSize(GetNSeg()); if (nparts == 1) { for (int i = 0; i < GetNE(); i++) // VolumeElement(i+1).SetPartition(1); vol_partition[i] = 1; for (int i = 0; i < GetNSE(); i++) // SurfaceElement(i+1).SetPartition(1); surf_partition[i] = 1; for (int i = 0; i < GetNSeg(); i++) // LineSegment(i+1).SetPartition(1); seg_partition[i] = 1; return; } idxtype edgecut; idxtype ncommon = 3; METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], &nwgt[0], NULL, &ncommon, &nparts, NULL, NULL, &edgecut, &epart[0], &npart[0]); /* METIS_PartMeshNodal (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &nparts, NULL, NULL, &edgecut, &epart[0], &npart[0]); */ PrintMessage (3, "metis complete"); // cout << "done" << endl; for (int i = 0; i < GetNE(); i++) // VolumeElement(i+1).SetPartition(epart[i] + 1); vol_partition[i] = epart[i] + 1; for (int i = 0; i < GetNSE(); i++) // SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); surf_partition[i] = epart[i+GetNE()] + 1; for (int i = 0; i < GetNSeg(); i++) // LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); seg_partition[i] = epart[i+GetNE()+GetNSE()] + 1; } #endif //=========================================================================================== #ifdef METIS4 void Mesh :: ParallelMetis ( ) { int timer = NgProfiler::CreateTimer ("Mesh::Partition"); NgProfiler::RegionTimer reg(timer); PrintMessage (3, "Metis called"); if (GetDimension() == 2) { PartDualHybridMesh2D ( ); // neloc ); return; } idx_t ne = GetNE(); idx_t nn = GetNP(); if (ntasks <= 2 || ne <= 1) { if (ntasks == 1) return; for (int i=1; i<=ne; i++) VolumeElement(i).SetPartition(1); for (int i=1; i<=GetNSE(); i++) SurfaceElement(i).SetPartition(1); return; } bool uniform_els = true; ELEMENT_TYPE elementtype = TET; for (int el = 1; el <= GetNE(); el++) if (VolumeElement(el).GetType() != elementtype) { uniform_els = false; break; } if (!uniform_els) { PartHybridMesh (); } else { // uniform (TET) mesh, JS int npe = VolumeElement(1).GetNP(); Array elmnts(ne*npe); int etype; if (elementtype == TET) etype = 2; else if (elementtype == HEX) etype = 3; for (int i=1; i<=ne; i++) for (int j=1; j<=npe; j++) elmnts[(i-1)*npe+(j-1)] = VolumeElement(i).PNum(j)-1; int numflag = 0; int nparts = ntasks-1; int ncommon = 3; int edgecut; Array epart(ne), npart(nn); // if ( ntasks == 1 ) // { // (*this) = *mastermesh; // nparts = 4; // metis :: METIS_PartMeshDual (&ne, &nn, elmnts, &etype, &numflag, &nparts, // &edgecut, epart, npart); // cout << "done" << endl; // cout << "edge-cut: " << edgecut << ", balance: " << metis :: ComputeElementBalance(ne, nparts, epart) << endl; // for (int i=1; i<=ne; i++) // { // mastermesh->VolumeElement(i).SetPartition(epart[i-1]); // } // return; // } int timermetis = NgProfiler::CreateTimer ("Metis itself"); NgProfiler::StartTimer (timermetis); #ifdef METIS4 cout << "call metis(4)_PartMeshDual ... " << flush; METIS_PartMeshDual (&ne, &nn, &elmnts[0], &etype, &numflag, &nparts, &edgecut, &epart[0], &npart[0]); #else cout << "call metis(5)_PartMeshDual ... " << endl; // idx_t options[METIS_NOPTIONS]; Array eptr(ne+1); for (int j = 0; j < ne+1; j++) eptr[j] = 4*j; METIS_PartMeshDual (&ne, &nn, &eptr[0], &elmnts[0], NULL, NULL, &ncommon, &nparts, NULL, NULL, &edgecut, &epart[0], &npart[0]); #endif NgProfiler::StopTimer (timermetis); cout << "complete" << endl; #ifdef METIS4 cout << "edge-cut: " << edgecut << ", balance: " << ComputeElementBalance(ne, nparts, &epart[0]) << endl; #endif // partition numbering by metis : 0 ... ntasks - 1 // we want: 1 ... ntasks for (int i=1; i<=ne; i++) VolumeElement(i).SetPartition(epart[i-1] + 1); } for (int sei = 1; sei <= GetNSE(); sei++ ) { int ei1, ei2; GetTopology().GetSurface2VolumeElement (sei, ei1, ei2); Element2d & sel = SurfaceElement (sei); for (int j = 0; j < 2; j++) { int ei = (j == 0) ? ei1 : ei2; if ( ei > 0 && ei <= GetNE() ) { sel.SetPartition (VolumeElement(ei).GetPartition()); break; } } } } #endif void Mesh :: PartHybridMesh () { #ifdef METIS int ne = GetNE(); int nn = GetNP(); int nedges = topology.GetNEdges(); idxtype *xadj, * adjacency, *v_weights = NULL, *e_weights = NULL; int weightflag = 0; int numflag = 0; int nparts = ntasks - 1; int options[5]; options[0] = 0; int edgecut; idxtype * part; xadj = new idxtype[nn+1]; part = new idxtype[nn]; Array cnt(nn+1); cnt = 0; for ( int edge = 1; edge <= nedges; edge++ ) { int v1, v2; topology.GetEdgeVertices ( edge, v1, v2); cnt[v1-1] ++; cnt[v2-1] ++; } xadj[0] = 0; for ( int n = 1; n <= nn; n++ ) { xadj[n] = idxtype(xadj[n-1] + cnt[n-1]); } adjacency = new idxtype[xadj[nn]]; cnt = 0; for ( int edge = 1; edge <= nedges; edge++ ) { int v1, v2; topology.GetEdgeVertices ( edge, v1, v2); adjacency[ xadj[v1-1] + cnt[v1-1] ] = v2-1; adjacency[ xadj[v2-1] + cnt[v2-1] ] = v1-1; cnt[v1-1]++; cnt[v2-1]++; } for ( int vert = 0; vert < nn; vert++ ) { FlatArray array ( cnt[vert], &adjacency[ xadj[vert] ] ); BubbleSort(array); } #ifdef METIS4 METIS_PartGraphKway ( &nn, xadj, adjacency, v_weights, e_weights, &weightflag, &numflag, &nparts, options, &edgecut, part ); #else cout << "currently not supported (metis5), A" << endl; #endif Array nodesinpart(ntasks); vol_partition.SetSize(ne); for ( int el = 1; el <= ne; el++ ) { Element & volel = VolumeElement(el); nodesinpart = 0; int el_np = volel.GetNP(); int partition = 0; for ( int i = 0; i < el_np; i++ ) nodesinpart[ part[volel[i]-1]+1 ] ++; for ( int i = 1; i < ntasks; i++ ) if ( nodesinpart[i] > nodesinpart[partition] ) partition = i; // volel.SetPartition(partition); vol_partition[el-1] = partition; } delete [] xadj; delete [] part; delete [] adjacency; #else cout << "parthybridmesh not available" << endl; #endif } void Mesh :: PartDualHybridMesh ( ) // Array & neloc ) { #ifdef METIS int ne = GetNE(); // int nn = GetNP(); // int nedges = topology->GetNEdges(); int nfaces = topology.GetNFaces(); idxtype *xadj, * adjacency, *v_weights = NULL, *e_weights = NULL; int weightflag = 0; // int numflag = 0; int nparts = ntasks - 1; int options[5]; options[0] = 0; int edgecut; idxtype * part; Array facevolels1(nfaces), facevolels2(nfaces); facevolels1 = -1; facevolels2 = -1; Array elfaces; xadj = new idxtype[ne+1]; part = new idxtype[ne]; Array cnt(ne+1); cnt = 0; for ( int el=1; el <= ne; el++ ) { Element volel = VolumeElement(el); topology.GetElementFaces(el, elfaces); for ( int i = 0; i < elfaces.Size(); i++ ) { if ( facevolels1[elfaces[i]-1] == -1 ) facevolels1[elfaces[i]-1] = el; else { facevolels2[elfaces[i]-1] = el; cnt[facevolels1[elfaces[i]-1]-1]++; cnt[facevolels2[elfaces[i]-1]-1]++; } } } xadj[0] = 0; for ( int n = 1; n <= ne; n++ ) { xadj[n] = idxtype(xadj[n-1] + cnt[n-1]); } adjacency = new idxtype[xadj[ne]]; cnt = 0; for ( int face = 1; face <= nfaces; face++ ) { int e1, e2; e1 = facevolels1[face-1]; e2 = facevolels2[face-1]; if ( e2 == -1 ) continue; adjacency[ xadj[e1-1] + cnt[e1-1] ] = e2-1; adjacency[ xadj[e2-1] + cnt[e2-1] ] = e1-1; cnt[e1-1]++; cnt[e2-1]++; } for ( int el = 0; el < ne; el++ ) { FlatArray array ( cnt[el], &adjacency[ xadj[el] ] ); BubbleSort(array); } int timermetis = NgProfiler::CreateTimer ("Metis itself"); NgProfiler::StartTimer (timermetis); #ifdef METIS4 METIS_PartGraphKway ( &ne, xadj, adjacency, v_weights, e_weights, &weightflag, &numflag, &nparts, options, &edgecut, part ); #else cout << "currently not supported (metis5), B" << endl; #endif NgProfiler::StopTimer (timermetis); Array nodesinpart(ntasks); vol_partition.SetSize(ne); for ( int el = 1; el <= ne; el++ ) { // Element & volel = VolumeElement(el); nodesinpart = 0; // VolumeElement(el).SetPartition(part[el-1 ] + 1); vol_partition[el-1] = part[el-1 ] + 1; } /* for ( int i=1; i<=ne; i++) { neloc[ VolumeElement(i).GetPartition() ] ++; } */ delete [] xadj; delete [] part; delete [] adjacency; #else cout << "partdualmesh not available" << endl; #endif } void Mesh :: PartDualHybridMesh2D ( ) { #ifdef METIS idxtype ne = GetNSE(); int nv = GetNV(); Array xadj(ne+1); Array adjacency(ne*4); // first, build the vertex 2 element table: Array cnt(nv); cnt = 0; for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) for (int j = 0; j < (*this)[sei].GetNP(); j++) cnt[ (*this)[sei][j] ] ++; TABLE vert2els(cnt); for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) for (int j = 0; j < (*this)[sei].GetNP(); j++) vert2els.Add ((*this)[sei][j], sei); // find all neighbour elements int cntnb = 0; Array marks(ne); // to visit each neighbour just once marks = -1; for (SurfaceElementIndex sei = 0; sei < ne; sei++) { xadj[sei] = cntnb; for (int j = 0; j < (*this)[sei].GetNP(); j++) { PointIndex vnr = (*this)[sei][j]; // all elements with at least one common vertex for (int k = 0; k < vert2els[vnr].Size(); k++) { SurfaceElementIndex sei2 = vert2els[vnr][k]; if (sei == sei2) continue; if (marks[sei2] == sei) continue; // neighbour, if two common vertices int common = 0; for (int m1 = 0; m1 < (*this)[sei].GetNP(); m1++) for (int m2 = 0; m2 < (*this)[sei2].GetNP(); m2++) if ( (*this)[sei][m1] == (*this)[sei2][m2]) common++; if (common >= 2) { marks[sei2] = sei; // mark as visited adjacency[cntnb++] = sei2; } } } } xadj[ne] = cntnb; idxtype *v_weights = NULL, *e_weights = NULL; idxtype weightflag = 0; // int numflag = 0; idxtype nparts = ntasks - 1; idxtype edgecut; Array part(ne); for ( int el = 0; el < ne; el++ ) BubbleSort (adjacency.Range (xadj[el], xadj[el+1])); #ifdef METIS4 int options[5]; options[0] = 0; METIS_PartGraphKway ( &ne, &xadj[0], &adjacency[0], v_weights, e_weights, &weightflag, &numflag, &nparts, options, &edgecut, &part[0] ); #else idx_t ncon = 1; METIS_PartGraphKway ( &ne, &ncon, &xadj[0], &adjacency[0], v_weights, NULL, e_weights, &nparts, NULL, NULL, NULL, &edgecut, &part[0] ); #endif surf_partition.SetSize(ne); for (SurfaceElementIndex sei = 0; sei < ne; sei++) // (*this) [sei].SetPartition (part[sei]+1); surf_partition[sei] = part[sei]+1; #else cout << "partdualmesh not available" << endl; #endif } } #endif netgen-6.2.1905/libsrc/meshing/findip2.hpp0000644000175000017500000000420213504650527016753 0ustar kurtkurt// find inner point template inline int FindInnerPoint2 (POINTArray & points, FACEArray & faces, Point3d & p) { static int timer = NgProfiler::CreateTimer ("FindInnerPoint2"); NgProfiler::RegionTimer reg (timer); Array a; Array c; Mat<3> m, inv; Vec<3> rs, x, pmin; int nf = faces.Size(); a.SetSize (nf); c.SetSize (nf); for (int i = 0; i < nf; i++) { Point3d p1 = points.Get(faces[i][0]); a[i] = Cross (points.Get(faces[i][1]) - p1, points.Get(faces[i][2]) - p1); a[i] /= a[i].Length(); c[i] = - (a[i].X() * p1.X() + a[i].Y() * p1.Y() + a[i].Z() * p1.Z()); } x = 0; double hmax = 0; for (int i = 0; i < nf; i++) { const Element2d & el = faces[i]; for (int j = 1; j <= 3; j++) { double hi = Dist (points.Get(el.PNumMod(j)), points.Get(el.PNumMod(j+1))); if (hi > hmax) hmax = hi; } } double fmin = 0; for (int i1 = 1; i1 <= nf; i1++) for (int i2 = i1+1; i2 <= nf; i2++) for (int i3 = i2+1; i3 <= nf; i3++) for (int i4 = i3+1; i4 <= nf; i4++) { m(0, 0) = a.Get(i1).X() - a.Get(i2).X(); m(0, 1) = a.Get(i1).Y() - a.Get(i2).Y(); m(0, 2) = a.Get(i1).Z() - a.Get(i2).Z(); rs(0) = c.Get(i2) - c.Get(i1); m(1, 0) = a.Get(i1).X() - a.Get(i3).X(); m(1, 1) = a.Get(i1).Y() - a.Get(i3).Y(); m(1, 2) = a.Get(i1).Z() - a.Get(i3).Z(); rs(1) = c.Get(i3) - c.Get(i1); m(2, 0) = a.Get(i1).X() - a.Get(i4).X(); m(2, 1) = a.Get(i1).Y() - a.Get(i4).Y(); m(2, 2) = a.Get(i1).Z() - a.Get(i4).Z(); rs(2) = c.Get(i4) - c.Get(i1); if (fabs (Det (m)) > 1e-10) { CalcInverse (m, inv); x = inv * rs; double f = -1e10; for (int i = 0; i < nf; i++) { double hd = x(0) * a[i].X() + x(1) * a[i].Y() + x(2) * a[i].Z() + c[i]; if (hd > f) f = hd; if (hd > fmin) break; } if (f < fmin) { fmin = f; pmin = x; } } } p = Point3d (pmin(0), pmin(1), pmin(2)); (*testout) << "fmin = " << fmin << endl; return (fmin < -1e-3 * hmax); } netgen-6.2.1905/libsrc/meshing/clusters.cpp0000644000175000017500000002356013504650527017267 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { AnisotropicClusters :: AnisotropicClusters (const Mesh & amesh) : mesh(amesh) { ; } AnisotropicClusters :: ~AnisotropicClusters () { ; } void AnisotropicClusters :: Update(TaskManager tm, Tracer tracer) { static int timer = NgProfiler::CreateTimer ("clusters"); // static int timer1 = NgProfiler::CreateTimer ("clusters1"); // static int timer2 = NgProfiler::CreateTimer ("clusters2"); // static int timer3 = NgProfiler::CreateTimer ("clusters3"); NgProfiler::RegionTimer reg (timer); const MeshTopology & top = mesh.GetTopology(); auto id = this->mesh.GetCommunicator().Rank(); auto ntasks = this->mesh.GetCommunicator().Size(); bool hasedges = top.HasEdges(); bool hasfaces = top.HasFaces(); if (!hasedges || !hasfaces) return; if (id == 0) PrintMessage (3, "Update clusters"); nv = mesh.GetNV(); ned = top.GetNEdges(); nfa = top.GetNFaces(); ne = mesh.GetNE(); int nse = mesh.GetNSE(); cluster_reps.SetSize (nv+ned+nfa+ne); cluster_reps = -1; Array llist (nv+ned+nfa+ne); llist = 0; Array nnums, ednums, fanums; int changed; // NgProfiler::StartTimer(timer1); /* for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); ELEMENT_TYPE typ = el.GetType(); top.GetElementEdges (i, ednums); top.GetElementFaces (i, fanums); int elnv = top.GetNVertices (typ); int elned = ednums.Size(); int elnfa = fanums.Size(); nnums.SetSize(elnv+elned+elnfa+1); for (int j = 1; j <= elnv; j++) nnums.Elem(j) = el.PNum(j); for (int j = 1; j <= elned; j++) nnums.Elem(elnv+j) = nv+ednums.Elem(j); for (int j = 1; j <= elnfa; j++) nnums.Elem(elnv+elned+j) = nv+ned+fanums.Elem(j); nnums.Elem(elnv+elned+elnfa+1) = nv+ned+nfa+i; for (int j = 0; j < nnums.Size(); j++) cluster_reps.Elem(nnums[j]) = nnums[j]; } */ ParallelForRange (tm, ne, [&] (size_t begin, size_t end) { Array nnums, ednums, fanums; for (int i = begin+1; i <= end; i++) { const Element & el = mesh.VolumeElement(i); ELEMENT_TYPE typ = el.GetType(); top.GetElementEdges (i, ednums); top.GetElementFaces (i, fanums); int elnv = top.GetNVertices (typ); int elned = ednums.Size(); int elnfa = fanums.Size(); nnums.SetSize(elnv+elned+elnfa+1); for (int j = 1; j <= elnv; j++) nnums.Elem(j) = el.PNum(j)+1-PointIndex::BASE; for (int j = 1; j <= elned; j++) nnums.Elem(elnv+j) = nv+ednums.Elem(j); for (int j = 1; j <= elnfa; j++) nnums.Elem(elnv+elned+j) = nv+ned+fanums.Elem(j); nnums.Elem(elnv+elned+elnfa+1) = nv+ned+nfa+i; for (int j = 0; j < nnums.Size(); j++) cluster_reps.Elem(nnums[j]) = nnums[j]; } }); // NgProfiler::StopTimer(timer1); // NgProfiler::StartTimer(timer2); /* for (int i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); ELEMENT_TYPE typ = el.GetType(); top.GetSurfaceElementEdges (i, ednums); int fanum = top.GetSurfaceElementFace (i); int elnv = top.GetNVertices (typ); int elned = ednums.Size(); nnums.SetSize(elnv+elned+1); for (int j = 1; j <= elnv; j++) nnums.Elem(j) = el.PNum(j)+1-PointIndex::BASE; for (int j = 1; j <= elned; j++) nnums.Elem(elnv+j) = nv+ednums.Elem(j); nnums.Elem(elnv+elned+1) = fanum; for (int j = 0; j < nnums.Size(); j++) cluster_reps.Elem(nnums[j]) = nnums[j]; } */ ParallelForRange (tm, nse, [&] (size_t begin, size_t end) { ArrayMem nnums, ednums; for (int i = begin+1; i <= end; i++) { const Element2d & el = mesh.SurfaceElement(i); ELEMENT_TYPE typ = el.GetType(); top.GetSurfaceElementEdges (i, ednums); int fanum = top.GetSurfaceElementFace (i); int elnv = top.GetNVertices (typ); int elned = ednums.Size(); nnums.SetSize(elnv+elned+1); for (int j = 1; j <= elnv; j++) nnums.Elem(j) = el.PNum(j)+1-PointIndex::BASE; for (int j = 1; j <= elned; j++) nnums.Elem(elnv+j) = nv+ednums.Elem(j); nnums.Elem(elnv+elned+1) = fanum; for (int j = 0; j < nnums.Size(); j++) cluster_reps.Elem(nnums[j]) = nnums[j]; } }); // NgProfiler::StopTimer(timer2); // NgProfiler::StartTimer(timer3); static const int hex_cluster[] = { 1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 7, 8, 5, 6, 7, 8, 1, 2, 3, 4, 9, 9, 5, 8, 6, 7, 9 }; static const int prism_cluster[] = { 1, 2, 3, 1, 2, 3, 4, 5, 6, 4, 5, 6, 3, 1, 2, 7, 7, 4, 5, 6, 7 }; static const int pyramid_cluster[] = { 1, 2, 2, 1, 3, 4, 2, 1, 4, 6, 5, 5, 6, 7, 5, 7, 6, 4, 7 }; static const int tet_cluster14[] = { 1, 2, 3, 1, 1, 4, 5, 4, 5, 6, 7, 5, 4, 7, 7 }; static const int tet_cluster12[] = { 1, 1, 2, 3, 4, 4, 5, 1, 6, 6, 7, 7, 4, 6, 7 }; static const int tet_cluster13[] = { 1, 2, 1, 3, 4, 6, 4, 5, 1, 5, 7, 4, 7, 5, 7 }; static const int tet_cluster23[] = { 2, 1, 1, 3, 6, 5, 5, 4, 4, 1, 5, 7, 7, 4, 7 }; static const int tet_cluster24[] = { 2, 1, 3, 1, 4, 1, 5, 4, 6, 5, 5, 7, 4, 7, 7 }; static const int tet_cluster34[] = { 2, 3, 1, 1, 4, 5, 1, 6, 4, 5, 5, 4, 7, 7, 7 }; int cnt = 0; do { (*tracer) ("update cluster, identify", false); cnt++; changed = 0; for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); ELEMENT_TYPE typ = el.GetType(); const int * clustertab = NULL; switch (typ) { case PRISM: case PRISM12: clustertab = prism_cluster; break; case HEX: clustertab = hex_cluster; break; case PYRAMID: clustertab = pyramid_cluster; break; case TET: case TET10: if (cluster_reps.Get(el.PNum(1)+1-PointIndex::BASE) == cluster_reps.Get(el.PNum(2)+1-PointIndex::BASE)) clustertab = tet_cluster12; else if (cluster_reps.Get(el.PNum(1)+1-PointIndex::BASE) == cluster_reps.Get(el.PNum(3)+1-PointIndex::BASE)) clustertab = tet_cluster13; else if (cluster_reps.Get(el.PNum(1)+1-PointIndex::BASE) == cluster_reps.Get(el.PNum(4)+1-PointIndex::BASE)) clustertab = tet_cluster14; else if (cluster_reps.Get(el.PNum(2)+1-PointIndex::BASE) == cluster_reps.Get(el.PNum(3)+1-PointIndex::BASE)) clustertab = tet_cluster23; else if (cluster_reps.Get(el.PNum(2)+1-PointIndex::BASE) == cluster_reps.Get(el.PNum(4)+1-PointIndex::BASE)) clustertab = tet_cluster24; else if (cluster_reps.Get(el.PNum(3)+1-PointIndex::BASE) == cluster_reps.Get(el.PNum(4)+1-PointIndex::BASE)) clustertab = tet_cluster34; else clustertab = NULL; break; default: clustertab = NULL; } if (clustertab) { top.GetElementEdges (i, ednums); top.GetElementFaces (i, fanums); int elnv = top.GetNVertices (typ); int elned = ednums.Size(); int elnfa = fanums.Size(); nnums.SetSize(elnv+elned+elnfa+1); for (int j = 1; j <= elnv; j++) nnums.Elem(j) = el.PNum(j)+1-PointIndex::BASE; for (int j = 1; j <= elned; j++) nnums.Elem(elnv+j) = nv+ednums.Elem(j); for (int j = 1; j <= elnfa; j++) nnums.Elem(elnv+elned+j) = nv+ned+fanums.Elem(j); nnums.Elem(elnv+elned+elnfa+1) = nv+ned+nfa+i; for (int j = 0; j < nnums.Size(); j++) for (int k = 0; k < j; k++) if (clustertab[j] == clustertab[k]) { int jj = nnums[j]; int kk = nnums[k]; if (cluster_reps.Get(kk) < cluster_reps.Get(jj)) swap (jj,kk); if (cluster_reps.Get(jj) < cluster_reps.Get(kk)) { /* cluster_reps.Elem(kk) = cluster_reps.Get(jj); changed = 1; */ int rep = cluster_reps.Get(jj); int next = cluster_reps.Get(kk); do { int cur = next; next = llist.Elem(next); cluster_reps.Elem(cur) = rep; llist.Elem(cur) = llist.Elem(rep); llist.Elem(rep) = cur; } while (next); changed = 1; } } } /* if (clustertab) { if (typ == PYRAMID) (*testout) << "pyramid"; else if (typ == PRISM || typ == PRISM12) (*testout) << "prism"; else if (typ == TET || typ == TET10) (*testout) << "tet"; else (*testout) << "unknown type" << endl; (*testout) << ", nnums = "; for (j = 0; j < nnums.Size(); j++) (*testout) << "node " << j << " = " << nnums[j] << ", rep = " << cluster_reps.Get(nnums[j]) << endl; } */ } (*tracer) ("update cluster, identify", true); } while (changed); // NgProfiler::StopTimer(timer3); /* (*testout) << "cluster reps:" << endl; for (i = 1; i <= cluster_reps.Size(); i++) { (*testout) << i << ": "; if (i <= nv) (*testout) << "v" << i << " "; else if (i <= nv+ned) (*testout) << "e" << i-nv << " "; else if (i <= nv+ned+nfa) (*testout) << "f" << i-nv-ned << " "; else (*testout) << "c" << i-nv-ned-nfa << " "; (*testout) << cluster_reps.Get(i) << endl; } */ } } netgen-6.2.1905/libsrc/meshing/meshfunc2d.cpp0000644000175000017500000000321613504650527017455 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { DLL_HEADER void Optimize2d (Mesh & mesh, MeshingParameters & mp) { static Timer timer("optimize2d"); RegionTimer reg(timer); mesh.CalcSurfacesOfNode(); bool secondorder = mesh.GetNP() > mesh.GetNV(); if (secondorder) { for (SurfaceElementIndex ei = 0; ei < mesh.GetNSE(); ei++) mesh[ei].SetType(TRIG); } mesh.Compress(); const char * optstr = mp.optimize2d.c_str(); int optsteps = mp.optsteps2d; for (int i = 1; i <= optsteps; i++) for (size_t j = 1; j <= strlen(optstr); j++) { if (multithread.terminate) break; switch (optstr[j-1]) { case 's': { // topological swap MeshOptimize2d meshopt; meshopt.SetMetricWeight (mp.elsizeweight); meshopt.EdgeSwapping (mesh, 0); break; } case 'S': { // metric swap MeshOptimize2d meshopt; meshopt.SetMetricWeight (mp.elsizeweight); meshopt.EdgeSwapping (mesh, 1); break; } case 'm': { MeshOptimize2d meshopt; meshopt.SetMetricWeight (mp.elsizeweight); meshopt.ImproveMesh(mesh, mp); break; } case 'c': { MeshOptimize2d meshopt; meshopt.SetMetricWeight (mp.elsizeweight); meshopt.CombineImprove(mesh); break; } default: cerr << "Optimization code " << optstr[j-1] << " not defined" << endl; } } if (secondorder) { if (mesh.GetGeometry()) mesh.GetGeometry()->GetRefinement().MakeSecondOrder(mesh); else Refinement().MakeSecondOrder(mesh); } } } netgen-6.2.1905/libsrc/meshing/refine.cpp0000644000175000017500000005144113504650527016672 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { void Refinement :: Refine (Mesh & mesh) const { const_cast (*this).Refine(mesh); } void Refinement :: Refine (Mesh & mesh) { PrintMessage (3, "Refine mesh"); mesh.SetNextMajorTimeStamp(); if (ntasks > 1 && id == 0) return; // reduce 2nd order mesh.ComputeNVertices(); mesh.SetNP(mesh.GetNV()); if (mesh.mlbetweennodes.Size() < mesh.GetNV()) { mesh.mlbetweennodes.SetSize(mesh.GetNV()); mesh.mlbetweennodes = INDEX_2(PointIndex::BASE-1,PointIndex::BASE-1); } INDEX_2_HASHTABLE between(mesh.GetNP() + 5); // new version with consistent ordering across sub-domains Array parents; for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { const Segment & el = mesh[si]; INDEX_2 i2 = INDEX_2::Sort(el[0], el[1]); if (!between.Used(i2)) { between.Set (i2, 0); parents.Append(i2); } } for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el = mesh[sei]; switch (el.GetType()) { case TRIG: case TRIG6: { static int betw[3][3] = { { 1, 2, 3 }, { 0, 2, 4 }, { 0, 1, 5 } }; for (int j = 0; j < 3; j++) { auto i2 = PointIndices<2>::Sort(el[betw[j][0]],el[betw[j][1]]); if (!between.Used(i2)) { between.Set (i2, 0); parents.Append(i2); } } break; } default: throw NgException ("currently refinement for quad-elements is not supported"); } } for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; switch (el.GetType()) { case TET: case TET10: { static int betw[6][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 4, 10 } }; for (int j = 0; j < 6; j++) { INDEX_2 i2 = INDEX_2::Sort(el.PNum(betw[j][0]),el.PNum(betw[j][1])); if (!between.Used(i2)) { between.Set (i2, 0); parents.Append(i2); } } break; } default: throw NgException ("currently refinement for non-tet elements is not supported"); } } PrintMessage (5, "have points"); Array par_nr(parents.Size()); for (int i = 0; i < par_nr.Size(); i++) par_nr[i] = i; QuickSort (parents, par_nr); mesh.mlbetweennodes.SetSize(mesh.GetNV()+parents.Size()); for (int i = 0; i < parents.Size(); i++) { between.Set (parents[i], mesh.GetNV()+i+PointIndex::BASE); mesh.mlbetweennodes[mesh.GetNV()+i+PointIndex::BASE] = parents[i]; } mesh.SetNP(mesh.GetNV() + parents.Size()); Array pointset(mesh.GetNP()); pointset = false; PrintMessage (5, "sorting complete"); // refine edges Array epgi; int oldns = mesh.GetNSeg(); for (SegmentIndex si = 0; si < oldns; si++) { const Segment & el = mesh.LineSegment(si); INDEX_2 i2 = INDEX_2::Sort(el[0], el[1]); PointIndex pinew = between.Get(i2); EdgePointGeomInfo ngi; if (pointset[pinew]) { // pinew = between.Get(i2); ngi = epgi[pinew]; } else { pointset[pinew] = true; Point<3> pnew; PointBetween (mesh.Point (el[0]), mesh.Point (el[1]), 0.5, el.surfnr1, el.surfnr2, el.epgeominfo[0], el.epgeominfo[1], pnew, ngi); // pinew = mesh.AddPoint (pnew); mesh.Point(pinew) = pnew; // between.Set (i2, pinew); if (pinew >= epgi.Size()+PointIndex::BASE) epgi.SetSize (pinew+1-PointIndex::BASE); epgi[pinew] = ngi; } Segment ns1 = el; Segment ns2 = el; ns1[1] = pinew; ns1.epgeominfo[1] = ngi; ns2[0] = pinew; ns2.epgeominfo[0] = ngi; mesh.LineSegment(si) = ns1; mesh.AddSegment (ns2); } PrintMessage (5, "have 1d elements"); // refine surface elements Array surfgi (8*mesh.GetNP()); for (int i = PointIndex::BASE; i < surfgi.Size()+PointIndex::BASE; i++) surfgi[i].trignum = -1; int oldnf = mesh.GetNSE(); for (SurfaceElementIndex sei = 0; sei < oldnf; sei++) { const Element2d & el = mesh.SurfaceElement(sei); switch (el.GetType()) { case TRIG: case TRIG6: { ArrayMem pnums(6); ArrayMem pgis(6); static int betw[3][3] = { { 2, 3, 4 }, { 1, 3, 5 }, { 1, 2, 6 } }; for (int j = 1; j <= 3; j++) { pnums.Elem(j) = el.PNum(j); pgis.Elem(j) = el.GeomInfoPi(j); } for (int j = 0; j < 3; j++) { PointIndex pi1 = pnums.Elem(betw[j][0]); PointIndex pi2 = pnums.Elem(betw[j][1]); INDEX_2 i2 (pi1, pi2); i2.Sort(); Point<3> pb; PointGeomInfo pgi; PointBetween (mesh.Point (pi1), mesh.Point (pi2), 0.5, mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(), el.GeomInfoPi (betw[j][0]), el.GeomInfoPi (betw[j][1]), pb, pgi); pgis.Elem(4+j) = pgi; PointIndex pinew = between.Get(i2); pnums.Elem(4+j) = pinew; if (!pointset[pinew]) { pointset[pinew] = true; mesh.Point(pinew) = pb; } /* if (between.Used(i2)) pnums.Elem(4+j) = between.Get(i2); else { pnums.Elem(4+j) = mesh.AddPoint (pb); between.Set (i2, pnums.Get(4+j)); } */ if (surfgi.Size() < pnums.Elem(4+j)) surfgi.SetSize (pnums.Elem(4+j)); surfgi.Elem(pnums.Elem(4+j)) = pgis.Elem(4+j); } static int reftab[4][3] = { { 1, 6, 5 }, { 2, 4, 6 }, { 3, 5, 4 }, { 6, 4, 5 } }; int ind = el.GetIndex(); for (int j = 0; j < 4; j++) { Element2d nel(TRIG); for (int k = 1; k <= 3; k++) { nel.PNum(k) = pnums.Get(reftab[j][k-1]); nel.GeomInfoPi(k) = pgis.Get(reftab[j][k-1]); } nel.SetIndex(ind); if (j == 0) mesh.SurfaceElement(sei) = nel; else mesh.AddSurfaceElement(nel); } break; } case QUAD: case QUAD6: case QUAD8: { ArrayMem pnums(9); ArrayMem pgis(9); static int betw[5][3] = { { 1, 2, 5 }, { 2, 3, 6 }, { 3, 4, 7 }, { 1, 4, 8 }, { 5, 7, 9 } }; for (int j = 1; j <= 4; j++) { pnums.Elem(j) = el.PNum(j); pgis.Elem(j) = el.GeomInfoPi(j); } for (int j = 0; j < 5; j++) { int pi1 = pnums.Elem(betw[j][0]); int pi2 = pnums.Elem(betw[j][1]); INDEX_2 i2 (pi1, pi2); i2.Sort(); if (between.Used(i2)) { pnums.Elem(5+j) = between.Get(i2); pgis.Elem(5+j) = surfgi.Get(pnums.Elem(4+j)); } else { Point<3> pb; PointBetween (mesh.Point (pi1), mesh.Point (pi2), 0.5, mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(), el.GeomInfoPi (betw[j][0]), el.GeomInfoPi (betw[j][1]), pb, pgis.Elem(5+j)); pnums.Elem(5+j) = mesh.AddPoint (pb); between.Set (i2, pnums.Get(5+j)); if (surfgi.Size() < pnums.Elem(5+j)) surfgi.SetSize (pnums.Elem(5+j)); surfgi.Elem(pnums.Elem(5+j)) = pgis.Elem(5+j); } } static int reftab[4][4] = { { 1, 5, 9, 8 }, { 5, 2, 6, 9 }, { 8, 9, 7, 4 }, { 9, 6, 3, 7 } }; int ind = el.GetIndex(); for (int j = 0; j < 4; j++) { Element2d nel(QUAD); for (int k = 1; k <= 4; k++) { nel.PNum(k) = pnums.Get(reftab[j][k-1]); nel.GeomInfoPi(k) = pgis.Get(reftab[j][k-1]); } nel.SetIndex(ind); if (j == 0) mesh.SurfaceElement(sei) = nel; else mesh.AddSurfaceElement(nel); } break; } default: PrintSysError ("Refine: undefined surface element type ", int(el.GetType())); } } PrintMessage (5, "have 2d elements"); // cout << "id = " << id << ", ne = " << mesh.GetNE() << endl; // refine volume elements int oldne = mesh.GetNE(); mesh.VolumeElements().SetAllocSize(8*oldne); for (ElementIndex ei = 0; ei < oldne; ei++) { const Element & el = mesh.VolumeElement(ei); switch (el.GetType()) { case TET: case TET10: { ArrayMem pnums(10); static int betw[6][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 4, 10 } }; int elrev = el.flags.reverse; for (int j = 1; j <= 4; j++) pnums.Elem(j) = el.PNum(j); if (elrev) swap (pnums.Elem(3), pnums.Elem(4)); for (int j = 0; j < 6; j++) { PointIndex pi1 = pnums.Get(betw[j][0]); PointIndex pi2 = pnums.Get(betw[j][1]); INDEX_2 i2 (pi1, pi2); i2.Sort(); /* if (between.Used(i2)) pnums.Elem(5+j) = between.Get(i2); else { pnums.Elem(5+j) = mesh.AddPoint (Center (mesh.Point(i2.I1()), mesh.Point(i2.I2()))); between.Set (i2, pnums.Elem(5+j)); } */ PointIndex pinew = between.Get(i2); pnums.Elem(j+5) = pinew; if (!pointset[pinew]) { pointset[pinew] = true; mesh.Point(pinew) = Center(mesh.Point(pi1), mesh.Point(pi2)); } } static int reftab[8][4] = { { 1, 5, 6, 7 }, { 5, 2, 8, 9 }, { 6, 8, 3, 10 }, { 7, 9, 10, 4 }, { 5, 6, 7, 9 }, { 5, 6, 9, 8 }, { 6, 7, 9, 10 }, { 6, 8, 10, 9 } }; /* { { 1, 5, 6, 7 }, { 5, 2, 8, 9 }, { 6, 8, 3, 10 }, { 7, 9, 10, 4 }, { 5, 6, 7, 9 }, { 5, 6, 8, 9 }, { 6, 7, 9, 10 }, { 6, 8, 9, 10 } }; */ static bool reverse[8] = { false, false, false, false, false, true, false, true }; int ind = el.GetIndex(); for (int j = 0; j < 8; j++) { Element nel(TET); for (int k = 1; k <= 4; k++) nel.PNum(k) = pnums.Get(reftab[j][k-1]); nel.SetIndex(ind); nel.flags.reverse = reverse[j]; if (elrev) { nel.flags.reverse = !nel.flags.reverse; swap (nel.PNum(3), nel.PNum(4)); } if (j == 0) mesh.VolumeElement(ei) = nel; else mesh.AddVolumeElement (nel); } break; } case HEX: { ArrayMem pnums(27); static int betw[13][3] = { { 1, 2, 9 }, { 3, 4, 10 }, { 4, 1, 11 }, { 2, 3, 12 }, { 5, 6, 13 }, { 7, 8, 14 }, { 8, 5, 15 }, { 6, 7, 16 }, { 1, 5, 17 }, { 2, 6, 18 }, { 3, 7, 19 }, { 4, 8, 20 }, { 2, 8, 21 }, }; /* static int fbetw[12][3] = { { 1, 3, 22 }, { 2, 4, 22 }, { 5, 7, 23 }, { 6, 8, 23 }, { 1, 6, 24 }, { 2, 5, 24 }, { 2, 7, 25 }, { 3, 6, 25 }, { 3, 8, 26 }, { 4, 7, 26 }, { 1, 8, 27 }, { 4, 5, 27 }, }; */ // updated by anonymous supporter, donations please to Karo W. static int fbetw[12][3] = { { 11, 12, 22 }, { 9, 10, 22 }, { 13, 14, 23 }, { 15, 16, 23 }, { 9, 13, 24 }, { 17, 18, 24 }, { 12, 16, 25 }, { 18, 19, 25 }, { 19, 20, 26 }, { 10, 14, 26 }, { 11, 15, 27 }, { 17, 20, 27 }, }; pnums = PointIndex(-1); for (int j = 1; j <= 8; j++) pnums.Elem(j) = el.PNum(j); for (int j = 0; j < 13; j++) { INDEX_2 i2; i2.I1() = pnums.Get(betw[j][0]); i2.I2() = pnums.Get(betw[j][1]); i2.Sort(); if (between.Used(i2)) pnums.Elem(9+j) = between.Get(i2); else { pnums.Elem(9+j) = mesh.AddPoint (Center (mesh.Point(i2.I1()), mesh.Point(i2.I2()))); between.Set (i2, pnums.Elem(9+j)); } } for (int j = 0; j < 6; j++) { INDEX_2 i2a, i2b; i2a.I1() = pnums.Get(fbetw[2*j][0]); i2a.I2() = pnums.Get(fbetw[2*j][1]); i2a.Sort(); i2b.I1() = pnums.Get(fbetw[2*j+1][0]); i2b.I2() = pnums.Get(fbetw[2*j+1][1]); i2b.Sort(); if (between.Used(i2a)) pnums.Elem(22+j) = between.Get(i2a); else if (between.Used(i2b)) pnums.Elem(22+j) = between.Get(i2b); else { pnums.Elem(22+j) = mesh.AddPoint (Center (mesh.Point(i2a.I1()), mesh.Point(i2a.I2()))); between.Set (i2a, pnums.Elem(22+j)); } } static int reftab[8][8] = { { 1, 9, 22, 11, 17, 24, 21, 27 }, { 9, 2, 12, 22, 24, 18, 25, 21 }, { 11, 22, 10, 4, 27, 21, 26, 20}, { 22, 12, 3, 10, 21, 25, 19, 26}, { 17, 24, 21, 27, 5, 13, 23, 15}, { 24, 18, 25, 21, 13, 6, 16, 23}, { 27, 21, 26, 20, 15, 23, 14, 8}, { 21, 25, 19, 26, 23, 16, 7, 14} }; int ind = el.GetIndex(); for (int j = 0; j < 8; j++) { Element nel(HEX); for (int k = 1; k <= 8; k++) nel.PNum(k) = pnums.Get(reftab[j][k-1]); nel.SetIndex(ind); if (j == 0) mesh.VolumeElement(ei) = nel; else mesh.AddVolumeElement (nel); } break; } case PRISM: { ArrayMem pnums(18); static int betw[9][3] = { { 3, 1, 7 }, { 1, 2, 8 }, { 3, 2, 9 }, { 6, 4, 10 }, { 4, 5, 11 }, { 6, 5, 12 }, { 1, 4, 13 }, { 3, 6, 14 }, { 2, 5, 15 }, }; // he: 15.jul 08, old version is wrong // produces double points ad quad faces and inconsistent mesh // static int fbetw[6][3] = // { { 1, 6, 16 }, // { 3, 4, 16 }, // { 1, 5, 17 }, // { 2, 4, 17 }, // { 2, 6, 18 }, // { 3, 5, 18 }, // }; static int fbetw[6][3] = { { 7, 10, 16 }, { 14, 13, 16 }, { 11, 8, 17 }, { 13, 15, 17 }, { 12, 9, 18 }, { 14, 15, 18 }, }; //int elrev = el.flags.reverse; pnums = PointIndex(-1); for (int j = 1; j <= 6; j++) pnums.Elem(j) = el.PNum(j); // if (elrev) // swap (pnums.Elem(3), pnums.Elem(4)); for (int j = 0; j < 9; j++) { INDEX_2 i2; i2.I1() = pnums.Get(betw[j][0]); i2.I2() = pnums.Get(betw[j][1]); i2.Sort(); if (between.Used(i2)) pnums.Elem(7+j) = between.Get(i2); else { pnums.Elem(7+j) = mesh.AddPoint (Center (mesh.Point(i2.I1()), mesh.Point(i2.I2()))); between.Set (i2, pnums.Elem(7+j)); } } for (int j = 0; j < 3; j++) { INDEX_2 i2a, i2b; i2a.I1() = pnums.Get(fbetw[2*j][0]); i2a.I2() = pnums.Get(fbetw[2*j][1]); i2a.Sort(); i2b.I1() = pnums.Get(fbetw[2*j+1][0]); i2b.I2() = pnums.Get(fbetw[2*j+1][1]); i2b.Sort(); if (between.Used(i2a)) pnums.Elem(16+j) = between.Get(i2a); else if (between.Used(i2b)) pnums.Elem(16+j) = between.Get(i2b); else { pnums.Elem(16+j) = mesh.AddPoint (Center (mesh.Point(i2a.I1()), mesh.Point(i2a.I2()))); between.Set (i2a, pnums.Elem(16+j)); } } static int reftab[8][6] = { { 1, 8, 7, 13, 17, 16 }, { 7, 8, 9, 16, 17, 18 }, { 7, 9, 3, 16, 18, 14 }, { 8, 2, 9, 17, 15, 18 }, { 13, 17, 16, 4, 11, 10 }, { 16, 17, 18, 10, 11, 12 }, { 16, 18, 14, 10, 12, 6 }, { 17, 15, 18, 11, 5, 12 } }; int ind = el.GetIndex(); for (int j = 0; j < 8; j++) { Element nel(PRISM); for (int k = 1; k <= 6; k++) nel.PNum(k) = pnums.Get(reftab[j][k-1]); nel.SetIndex(ind); //nel.flags.reverse = reverse[j]; //if (elrev) // { //nel.flags.reverse = 1 - nel.flags.reverse; //swap (nel.PNum(3), nel.PNum(4)); if (j == 0) mesh.VolumeElement(ei) = nel; else mesh.AddVolumeElement (nel); } break; } default: PrintSysError ("Refine: undefined volume element type ", int(el.GetType())); } } // update identification tables for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) { Array identmap; mesh.GetIdentifications().GetMap (i, identmap); for (int j = 1; j <= between.GetNBags(); j++) for (int k = 1; k <= between.GetBagSize(j); k++) { INDEX_2 i2; PointIndex newpi; between.GetData (j, k, i2, newpi); INDEX_2 oi2(identmap.Get(i2.I1()), identmap.Get(i2.I2())); oi2.Sort(); if (between.Used (oi2)) { PointIndex onewpi = between.Get(oi2); mesh.GetIdentifications().Add (newpi, onewpi, i); } } } PrintMessage (5, "have 3d elements"); mesh.ComputeNVertices(); mesh.RebuildSurfaceElementLists(); PrintMessage (5, "mesh updates complete"); return; int cnttrials = 10; int wrongels = 0; for (int i = 1; i <= mesh.GetNE(); i++) if (mesh.VolumeElement(i).Volume(mesh.Points()) < 0) { wrongels++; mesh.VolumeElement(i).flags.badel = 1; } else mesh.VolumeElement(i).flags.badel = 0; if (wrongels) { cout << "WARNING: " << wrongels << " with wrong orientation found" << endl; int np = mesh.GetNP(); Array > should(np); Array > can(np); for (int i = 1; i <= np; i++) { should.Elem(i) = can.Elem(i) = mesh.Point(i); } for (int i = 1; i <= between.GetNBags(); i++) for (int j = 1; j <= between.GetBagSize(i); j++) { INDEX_2 parent; PointIndex child; between.GetData (i, j, parent, child); can.Elem(child) = Center (can.Elem(parent.I1()), can.Elem(parent.I2())); } BitArray boundp(np); boundp.Clear(); for (auto & sel : mesh.SurfaceElements()) for (auto pi : sel.PNums()) boundp.Set(pi); double lam = 0.5; while (lam < 0.9 && cnttrials > 0) { lam = 2; do { lam *= 0.5; cnttrials--; cout << "lam = " << lam << endl; for (int i = 1; i <= np; i++) if (boundp.Test(i)) { for (int j = 0; j < 3; j++) mesh.Point(i)(j) = lam * should.Get(i)(j) + (1-lam) * can.Get(i)(j); } else mesh.Point(i) = can.Get(i); BitArray free (mesh.GetNP()), fhelp(mesh.GetNP()); free.Clear(); for (int i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement(i); if (el.Volume(mesh.Points()) < 0) for (int j = 1; j <= el.GetNP(); j++) free.Set (el.PNum(j)); } for (int k = 1; k <= 3; k++) { fhelp.Clear(); for (int i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement(i); int freeel = 0; for (int j = 1; j <= el.GetNP(); j++) if (free.Test(el.PNum(j))) freeel = 1; if (freeel) for (int j = 1; j <= el.GetNP(); j++) fhelp.Set (el.PNum(j)); } free.Or (fhelp); } (*testout) << "smooth points: " << endl; for (int i = 1; i <= free.Size(); i++) if (free.Test(i)) (*testout) << "p " << i << endl; (*testout) << "surf points: " << endl; for (auto & sel : mesh.SurfaceElements()) for (auto pi : sel.PNums()) (*testout) << pi << endl; mesh.CalcSurfacesOfNode(); free.Invert(); mesh.FixPoints (free); MeshingParameters dummymp; mesh.ImproveMesh (dummymp, OPT_REST); wrongels = 0; for (int i = 1; i <= mesh.GetNE(); i++) { if (mesh.VolumeElement(i).Volume(mesh.Points()) < 0) { wrongels++; mesh.VolumeElement(i).flags.badel = 1; (*testout) << "wrong el: "; for (int j = 1; j <= 4; j++) (*testout) << mesh.VolumeElement(i).PNum(j) << " "; (*testout) << endl; } else mesh.VolumeElement(i).flags.badel = 0; } cout << "wrongels = " << wrongels << endl; } while (wrongels && cnttrials > 0); for (int i = 1; i <= np; i++) can.Elem(i) = mesh.Point(i); } } if (cnttrials <= 0) { cerr << "ERROR: Sorry, reverted elements" << endl; } mesh.ComputeNVertices(); } } netgen-6.2.1905/libsrc/meshing/adfront3.cpp0000644000175000017500000004435313504650527017146 0ustar kurtkurt#include #include "meshing.hpp" /* ********************** FrontPoint ********************** */ namespace netgen { FrontPoint3 :: FrontPoint3 () { globalindex.Invalidate(); // = -1; nfacetopoint = 0; frontnr = 1000; cluster = 0; } FrontPoint3 :: FrontPoint3 (const Point<3> & ap, PointIndex agi) { p = ap; globalindex = agi; nfacetopoint = 0; frontnr = 1000; cluster = 0; } /* ********************** FrontFace ********************** */ FrontFace :: FrontFace () { qualclass = 1; oldfront = 0; hashvalue = 0; cluster = 0; } FrontFace :: FrontFace (const MiniElement2d & af) { f = af; oldfront = 0; qualclass = 1; hashvalue = 0; } void FrontFace :: Invalidate () { f.Delete(); oldfront = 0; qualclass = 1000; } /* ********************** AddFront ********************** */ AdFront3 :: AdFront3 () { nff = 0; nff4 = 0; vol = 0; hashon = 1; hashcreated = 0; if (hashon) hashtable.Init(&points, &faces); facetree = NULL; connectedpairs = NULL; rebuildcounter = -1; lasti = 0; minval = -1; } AdFront3 :: ~AdFront3 () { delete facetree; delete connectedpairs; } void AdFront3 :: GetPoints (Array > & apoints) const { for (PointIndex pi = points.Begin(); pi < points.End(); pi++) apoints.Append (points[pi].P()); } PointIndex AdFront3 :: AddPoint (const Point<3> & p, PointIndex globind) { if (delpointl.Size()) { PointIndex pi = delpointl.Last(); delpointl.DeleteLast (); points[pi] = FrontPoint3 (p, globind); return pi; } else { points.Append (FrontPoint3 (p, globind)); return --points.End(); // return points.Size()-1+PointIndex::BASE; } } INDEX AdFront3 :: AddFace (const MiniElement2d & aface) { int i, minfn; nff++; for (i = 0; i < aface.GetNP(); i++) points[aface[i]].AddFace(); const Point3d & p1 = points[aface[0]].P(); const Point3d & p2 = points[aface[1]].P(); const Point3d & p3 = points[aface[2]].P(); vol += 1.0/6.0 * (p1.X() + p2.X() + p3.X()) * ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) - (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) ); if (aface.GetNP() == 4) { nff4++; const Point3d & p4 = points[aface[3]].P(); vol += 1.0/6.0 * (p1.X() + p3.X() + p4.X()) * ( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) - (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) ); } minfn = 1000; for (i = 0; i < aface.GetNP(); i++) { int fpn = points[aface[i]].FrontNr(); if (i == 0 || fpn < minfn) minfn = fpn; } int cluster = 0; for (i = 1; i <= aface.GetNP(); i++) { if (points[aface.PNum(i)].cluster) cluster = points[aface.PNum(i)].cluster; } for (i = 1; i <= aface.GetNP(); i++) points[aface.PNum(i)].cluster = cluster; for (i = 1; i <= aface.GetNP(); i++) points[aface.PNum(i)].DecFrontNr (minfn+1); faces.Append(FrontFace (aface)); int nfn = faces.Size(); faces.Elem(nfn).cluster = cluster; if (hashon && hashcreated) hashtable.AddElem(aface, nfn); return nfn; } void AdFront3 :: DeleteFace (INDEX fi) { nff--; for (int i = 1; i <= faces.Get(fi).Face().GetNP(); i++) { PointIndex pi = faces.Get(fi).Face().PNum(i); points[pi].RemoveFace(); if (!points[pi].Valid()) delpointl.Append (pi); } const MiniElement2d & face = faces.Get(fi).Face(); const Point3d & p1 = points[face.PNum(1)].P(); const Point3d & p2 = points[face.PNum(2)].P(); const Point3d & p3 = points[face.PNum(3)].P(); vol -= 1.0/6.0 * (p1.X() + p2.X() + p3.X()) * ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) - (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) ); if (face.GetNP() == 4) { const Point3d & p4 = points[face.PNum(4)].P(); vol -= 1.0/6.0 * (p1.X() + p3.X() + p4.X()) * ( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) - (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) ); nff4--; } faces.Elem(fi).Invalidate(); } INDEX AdFront3 :: AddConnectedPair (const INDEX_2 & apair) { if (!connectedpairs) connectedpairs = new TABLE (GetNP()); connectedpairs->Add (apair.I1(), apair.I2()); connectedpairs->Add (apair.I2(), apair.I1()); return 0; } void AdFront3 :: CreateTrees () { int i, j; PointIndex pi; Point3d pmin, pmax; for (pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++) { const Point<3> & p = GetPoint(pi); if (pi == PointIndex::BASE) { pmin = p; pmax = p; } else { pmin.SetToMin (p); pmax.SetToMax (p); } } pmax = pmax + 0.5 * (pmax - pmin); pmin = pmin + 0.5 * (pmin - pmax); delete facetree; facetree = new BoxTree<3> (pmin, pmax); for (i = 1; i <= GetNF(); i++) { const MiniElement2d & el = GetFace(i); pmin = GetPoint (el[0]); pmax = pmin; for (j = 1; j < 3; j++) { const Point<3> & p = GetPoint (el[j]); pmin.SetToMin (p); pmax.SetToMax (p); } pmax = pmax + 0.01 * (pmax - pmin); pmin = pmin + 0.01 * (pmin - pmax); // (*testout) << "insert " << i << ": " << pmin << " - " << pmax << "\n"; facetree -> Insert (pmin, pmax, i); } } void AdFront3 :: GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax, Array & ifaces) const { facetree -> GetIntersecting (pmin, pmax, ifaces); } void AdFront3 :: GetFaceBoundingBox (int i, Box3d & box) const { const FrontFace & face = faces.Get(i); box.SetPoint (points[face.f[0]].p); box.AddPoint (points[face.f[1]].p); box.AddPoint (points[face.f[2]].p); } void AdFront3 :: RebuildInternalTables () { static int timer_a = NgProfiler::CreateTimer ("Adfront3::RebuildInternal A"); static int timer_b = NgProfiler::CreateTimer ("Adfront3::RebuildInternal B"); static int timer_c = NgProfiler::CreateTimer ("Adfront3::RebuildInternal C"); static int timer_d = NgProfiler::CreateTimer ("Adfront3::RebuildInternal D"); NgProfiler::StartTimer (timer_a); int hi = 0; for (int i = 1; i <= faces.Size(); i++) if (faces.Get(i).Valid()) { hi++; if (hi < i) faces.Elem(hi) = faces.Get(i); } faces.SetSize (nff); int np = points.Size(); for (PointIndex pi = points.Begin(); pi < points.End(); pi++) points[pi].cluster = pi; NgProfiler::StopTimer (timer_a); NgProfiler::StartTimer (timer_b); int change; do { change = 0; for (int i = 1; i <= faces.Size(); i++) { const MiniElement2d & el = faces.Get(i).Face(); int mini = points[el.PNum(1)].cluster; int maxi = mini; for (int j = 2; j <= 3; j++) { int ci = points[el.PNum(j)].cluster; if (ci < mini) mini = ci; if (ci > maxi) maxi = ci; } if (mini < maxi) { change = 1; for (int j = 1; j <= 3; j++) points[el.PNum(j)].cluster = mini; } } } while (change); NgProfiler::StopTimer (timer_b); NgProfiler::StartTimer (timer_c); BitArrayChar usecl(np); usecl.Clear(); for (int i = 1; i <= faces.Size(); i++) { usecl.Set (points[faces.Get(i).Face().PNum(1)].cluster); faces.Elem(i).cluster = points[faces.Get(i).Face().PNum(1)].cluster; } int cntcl = 0; for (int i = PointIndex::BASE; i < np+PointIndex::BASE; i++) if (usecl.Test(i)) cntcl++; Array clvol (np); clvol = 0.0; for (int i = 1; i <= faces.Size(); i++) { const MiniElement2d & face = faces.Get(i).Face(); const Point3d p1 = points[face.PNum(1)].P(); const Point3d p2 = points[face.PNum(2)].P(); const Point3d p3 = points[face.PNum(3)].P(); double vi = 1.0/6.0 * (p1.X() + p2.X() + p3.X()) * ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) - (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) ); if (face.GetNP() == 4) { const Point3d p4 = points[face.PNum(4)].P(); vi += 1.0/6.0 * (p1.X() + p3.X() + p4.X()) * ( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) - (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) ); } clvol[faces.Get(i).cluster] += vi; } NgProfiler::StopTimer (timer_c); NgProfiler::StartTimer (timer_d); int negvol = 0; for (int i = PointIndex::BASE; i < clvol.Size()+PointIndex::BASE; i++) { if (clvol[i] < 0) negvol = 1; } if (negvol) { for (int i = 1; i <= faces.Size(); i++) faces.Elem(i).cluster = 1; for (PointIndex pi = points.Begin(); pi < points.End(); pi++) points[pi].cluster = 1; } if (hashon) hashtable.Create(); NgProfiler::StopTimer (timer_d); } int AdFront3 :: SelectBaseElement () { int i, hi, fstind; /* static int minval = -1; static int lasti = 0; static int counter = 0; */ if (rebuildcounter <= 0) { RebuildInternalTables(); rebuildcounter = nff / 10 + 1; lasti = 0; } rebuildcounter--; /* if (faces.Size() > 2 * nff) { // compress facelist RebuildInternalTables (); lasti = 0; } */ fstind = 0; for (i = lasti+1; i <= faces.Size() && !fstind; i++) if (faces.Elem(i).Valid()) { hi = faces.Get(i).QualClass() + points[faces.Get(i).Face().PNum(1)].FrontNr() + points[faces.Get(i).Face().PNum(2)].FrontNr() + points[faces.Get(i).Face().PNum(3)].FrontNr(); if (hi <= minval) { minval = hi; fstind = i; lasti = fstind; } } if (!fstind) { minval = INT_MAX; for (i = 1; i <= faces.Size(); i++) if (faces.Elem(i).Valid()) { hi = faces.Get(i).QualClass() + points[faces.Get(i).Face().PNum(1)].FrontNr() + points[faces.Get(i).Face().PNum(2)].FrontNr() + points[faces.Get(i).Face().PNum(3)].FrontNr(); if (hi <= minval) { minval = hi; fstind = i; lasti = 0; } } } return fstind; } int AdFront3 :: GetLocals (int fstind, Array & locpoints, Array & locfaces, // local index Array & pindex, Array & findex, INDEX_2_HASHTABLE & getconnectedpairs, float xh, float relh, INDEX& facesplit) { // static int timer = NgProfiler::CreateTimer ("AdFront3::GetLocals"); // NgProfiler::RegionTimer reg (timer); if (hashon && faces.Size() < 500) { hashon=0; } if (hashon && !hashcreated) { hashtable.Create(); hashcreated=1; } INDEX i, j; PointIndex pstind; Point3d midp, p0; // static Array invpindex; Array locfaces2; //all local faces in radius xh Array locfaces3; // all faces in outer radius relh Array findex2; locfaces2.SetSize(0); locfaces3.SetSize(0); findex2.SetSize(0); int cluster = faces.Get(fstind).cluster; pstind = faces.Get(fstind).Face().PNum(1); p0 = points[pstind].P(); locfaces2.Append(faces.Get(fstind).Face()); findex2.Append(fstind); Box3d b1 (p0 - Vec3d(xh, xh, xh), p0 + Vec3d (xh, xh, xh)); if (hashon) { hashtable.GetLocals(locfaces2, findex2, fstind, p0, xh); } else { for (i = 1; i <= faces.Size(); i++) { const MiniElement2d & face = faces.Get(i).Face(); if (faces.Get(i).cluster == cluster && faces.Get(i).Valid() && i != fstind) { Box3d b2; b2.SetPoint (points[face[0]].P()); b2.AddPoint (points[face[1]].P()); b2.AddPoint (points[face[2]].P()); if (b1.Intersect (b2)) { locfaces2.Append(faces.Get(i).Face()); findex2.Append(i); } } } } //local faces for inner radius: for (i = 1; i <= locfaces2.Size(); i++) { const MiniElement2d & face = locfaces2.Get(i); const Point3d & p1 = points[face[0]].P(); const Point3d & p2 = points[face[1]].P(); const Point3d & p3 = points[face[2]].P(); midp = Center (p1, p2, p3); if (Dist2 (midp, p0) <= relh * relh || i == 1) { locfaces.Append(locfaces2.Get(i)); findex.Append(findex2.Get(i)); } else locfaces3.Append (i); } facesplit=locfaces.Size(); //local faces for outer radius: for (i = 1; i <= locfaces3.Size(); i++) { locfaces.Append (locfaces2.Get(locfaces3.Get(i))); findex.Append (findex2.Get(locfaces3.Get(i))); } invpindex.SetSize (points.Size()); for (i = 1; i <= locfaces.Size(); i++) for (j = 1; j <= locfaces.Get(i).GetNP(); j++) { PointIndex pi = locfaces.Get(i).PNum(j); invpindex[pi] = -1; } for (i = 1; i <= locfaces.Size(); i++) { for (j = 1; j <= locfaces.Get(i).GetNP(); j++) { PointIndex pi = locfaces.Get(i).PNum(j); if (invpindex[pi] == -1) { pindex.Append (pi); locpoints.Append (points[pi].P()); invpindex[pi] = pindex.Size()-1+PointIndex::BASE; } // locfaces.Elem(i).PNum(j) = locpoints.Append (points[pi].P()); // } // else locfaces.Elem(i).PNum(j) = invpindex[pi]; } } if (connectedpairs) { for (i = 1; i <= locpoints.Size(); i++) { int pind = pindex.Get(i); if (pind >= 1 && pind <= connectedpairs->Size ()) { for (j = 1; j <= connectedpairs->EntrySize(pind); j++) { int oi = connectedpairs->Get(pind, j); int other = invpindex.Get(oi); if (other >= 1 && other <= pindex.Size() && pindex.Get(other) == oi) { // INDEX_2 coned(i, other); // coned.Sort(); // (*testout) << "connected: " << locpoints.Get(i) << "-" << locpoints.Get(other) << endl; getconnectedpairs.Set (INDEX_2::Sort (i, other), 1); } } } } } /* // add isolated points for (i = 1; i <= points.Size(); i++) if (points.Elem(i).Valid() && Dist (points.Elem(i).P(), p0) <= xh) { if (!invpindex.Get(i)) { locpoints.Append (points.Get(i).P()); pindex.Append (i); invpindex.Elem(i) = pindex.Size(); } } */ return faces.Get(fstind).QualClass(); } // returns all points connected with fi void AdFront3 :: GetGroup (int fi, Array & grouppoints, Array & groupelements, Array & pindex, Array & findex) { // static Array pingroup; int changed; pingroup.SetSize(points.Size()); pingroup = 0; for (int j = 1; j <= 3; j++) pingroup.Elem (faces.Get(fi).Face().PNum(j)) = 1; do { changed = 0; /* for (i = 1; i <= faces.Size(); i++) if (faces.Get(i).Valid()) { const MiniElement2d & face = faces.Get(i).Face(); int fused = 0; for (j = 1; j <= 3; j++) if (pingroup.Elem(face.PNum(j))) fused++; if (fused >= 2) for (j = 1; j <= 3; j++) if (!pingroup.Elem(face.PNum(j))) { pingroup.Elem(face.PNum(j)) = 1; changed = 1; } } */ for (auto & f : faces) if (f.Valid()) { const MiniElement2d & face = f.Face(); int fused = 0; for (int j = 1; j <= 3; j++) if (pingroup.Elem(face.PNum(j))) fused++; if (fused >= 2) for (int j = 1; j <= 3; j++) if (!pingroup.Elem(face.PNum(j))) { pingroup.Elem(face.PNum(j)) = 1; changed = 1; } } } while (changed); invpindex.SetSize (points.Size()); // for (PointIndex pi = points.Begin(); pi < points.End(); pi++) for (PointIndex pi : points.Range()) if (points[pi].Valid()) { grouppoints.Append (points[pi].P()); pindex.Append (pi); invpindex[pi] = pindex.Size(); } for (int i = 1; i <= faces.Size(); i++) if (faces.Get(i).Valid()) { int fused = 0; for (int j = 1; j <= 3; j++) if (pingroup.Get(faces.Get(i).Face().PNum(j))) fused++; if (fused >= 2) { groupelements.Append (faces.Get(i).Face()); findex.Append (i); } } /* for (int i = 1; i <= groupelements.Size(); i++) for (int j = 1; j <= 3; j++) { groupelements.Elem(i).PNum(j) = invpindex.Get(groupelements.Elem(i).PNum(j)); } */ for (auto & e : groupelements) for (int j = 1; j <= 3; j++) e.PNum(j) = invpindex.Get(e.PNum(j)); } void AdFront3 :: SetStartFront (int /* baseelnp */) { for (INDEX i = 1; i <= faces.Size(); i++) if (faces.Get(i).Valid()) { const MiniElement2d & face = faces.Get(i).Face(); for (int j = 1; j <= 3; j++) points[face.PNum(j)].DecFrontNr(0); } /* if (baseelnp) { for (i = 1; i <= faces.Size(); i++) if (faces.Get(i).Valid() && faces.Get(i).Face().GetNP() != baseelnp) faces.Elem(i).qualclass = 1000; } */ } bool AdFront3 :: Inside (const Point<3> & p) const { int cnt; Vec3d n, v1, v2; DenseMatrix a(3), ainv(3); Vector b(3), u(3); // random numbers: n.X() = 0.123871; n.Y() = 0.15432; n.Z() = -0.43989; cnt = 0; for (int i = 1; i <= faces.Size(); i++) if (faces.Get(i).Valid()) { const Point<3> & p1 = points[faces.Get(i).Face().PNum(1)].P(); const Point<3> & p2 = points[faces.Get(i).Face().PNum(2)].P(); const Point<3> & p3 = points[faces.Get(i).Face().PNum(3)].P(); v1 = p2 - p1; v2 = p3 - p1; a(0, 0) = v1.X(); a(1, 0) = v1.Y(); a(2, 0) = v1.Z(); a(0, 1) = v2.X(); a(1, 1) = v2.Y(); a(2, 1) = v2.Z(); a(0, 2) = -n.X(); a(1, 2) = -n.Y(); a(2, 2) = -n.Z(); b(0) = p(0) - p1(0); b(1) = p(1) - p1(1); b(2) = p(2) - p1(2); CalcInverse (a, ainv); ainv.Mult (b, u); if (u(0) >= 0 && u(1) >= 0 && u(0)+u(1) <= 1 && u(2) > 0) { cnt++; } } return ((cnt % 2) != 0); } int AdFront3 :: SameSide (const Point<3> & lp1, const Point<3> & lp2, const Array * testfaces) const { const Point<3> *line[2]; line[0] = &lp1; line[1] = &lp2; Point3d pmin(lp1); Point3d pmax(lp1); pmin.SetToMin (lp2); pmax.SetToMax (lp2); ArrayMem aprif; aprif.SetSize(0); if (!testfaces) facetree->GetIntersecting (pmin, pmax, aprif); else for (int i = 1; i <= testfaces->Size(); i++) aprif.Append (testfaces->Get(i)); int cnt = 0; for (int ii = 1; ii <= aprif.Size(); ii++) { int i = aprif.Get(ii); if (faces.Get(i).Valid()) { const Point<3> *tri[3]; tri[0] = &points[faces.Get(i).Face().PNum(1)].P(); tri[1] = &points[faces.Get(i).Face().PNum(2)].P(); tri[2] = &points[faces.Get(i).Face().PNum(3)].P(); if (IntersectTriangleLine (&tri[0], &line[0])) cnt++; } } return ((cnt+1) % 2); } } netgen-6.2.1905/libsrc/meshing/meshfunc.cpp0000644000175000017500000004466113504650527017240 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { extern const char * tetrules[]; // extern const char * tetrules2[]; extern const char * prismrules2[]; extern const char * pyramidrules[]; extern const char * pyramidrules2[]; extern const char * hexrules[]; // extern double teterrpow; MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d) { static Timer t("MeshVolume"); RegionTimer reg(t); int oldne; int meshed; Array connectednodes; if (!mesh3d.HasLocalHFunction()) mesh3d.CalcLocalH(mp.grading); mesh3d.Compress(); // mesh3d.PrintMemInfo (cout); if (mp.checkoverlappingboundary) if (mesh3d.CheckOverlappingBoundary()) throw NgException ("Stop meshing since boundary mesh is overlapping"); int nonconsist = 0; for (int k = 1; k <= mesh3d.GetNDomains(); k++) { if(mp.only3D_domain_nr && mp.only3D_domain_nr !=k) continue; PrintMessage (3, "Check subdomain ", k, " / ", mesh3d.GetNDomains()); mesh3d.FindOpenElements(k); /* bool res = mesh3d.CheckOverlappingBoundary(); if (res) { PrintError ("Surface is overlapping !!"); nonconsist = 1; } */ bool res = (mesh3d.CheckConsistentBoundary() != 0); if (res) { PrintError ("Surface mesh not consistent"); nonconsist = 1; } } if (nonconsist) { PrintError ("Stop meshing since surface mesh not consistent"); throw NgException ("Stop meshing since surface mesh not consistent"); } double globmaxh = mp.maxh; for (int k = 1; k <= mesh3d.GetNDomains(); k++) { if(mp.only3D_domain_nr && mp.only3D_domain_nr !=k) continue; if (multithread.terminate) break; PrintMessage (2, ""); PrintMessage (1, "Meshing subdomain ", k, " of ", mesh3d.GetNDomains()); (*testout) << "Meshing subdomain " << k << endl; mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k)); mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(k); if (!mesh3d.GetNOpenElements()) continue; Box<3> domain_bbox( Box<3>::EMPTY_BOX ); for (SurfaceElementIndex sei = 0; sei < mesh3d.GetNSE(); sei++) { const Element2d & el = mesh3d[sei]; if (el.IsDeleted() ) continue; if (mesh3d.GetFaceDescriptor(el.GetIndex()).DomainIn() == k || mesh3d.GetFaceDescriptor(el.GetIndex()).DomainOut() == k) for (int j = 0; j < el.GetNP(); j++) domain_bbox.Add (mesh3d[el[j]]); } domain_bbox.Increase (0.01 * domain_bbox.Diam()); for (int qstep = 0; qstep <= 3; qstep++) // for (int qstep = 0; qstep <= 0; qstep++) // for hex-filling { if (qstep == 0 && !mp.try_hexes) continue; // cout << "openquads = " << mesh3d.HasOpenQuads() << endl; if (mesh3d.HasOpenQuads()) { string rulefile = ngdir; const char ** rulep = NULL; switch (qstep) { case 0: rulefile = "/Users/joachim/gitlab/netgen/rules/hexa.rls"; rulep = hexrules; break; case 1: rulefile += "/rules/prisms2.rls"; rulep = prismrules2; break; case 2: // connect pyramid to triangle rulefile += "/rules/pyramids2.rls"; rulep = pyramidrules2; break; case 3: // connect to vis-a-vis point rulefile += "/rules/pyramids.rls"; rulep = pyramidrules; break; } // Meshing3 meshing(rulefile); Meshing3 meshing(rulep); MeshingParameters mpquad = mp; mpquad.giveuptol = 15; mpquad.baseelnp = 4; mpquad.starshapeclass = 1000; mpquad.check_impossible = qstep == 1; // for prisms only (air domain in trafo) for (PointIndex pi = mesh3d.Points().Begin(); pi < mesh3d.Points().End(); pi++) meshing.AddPoint (mesh3d[pi], pi); /* mesh3d.GetIdentifications().GetPairs (0, connectednodes); for (int i = 1; i <= connectednodes.Size(); i++) meshing.AddConnectedPair (connectednodes.Get(i)); */ for (int nr = 1; nr <= mesh3d.GetIdentifications().GetMaxNr(); nr++) if (mesh3d.GetIdentifications().GetType(nr) != Identifications::PERIODIC) { mesh3d.GetIdentifications().GetPairs (nr, connectednodes); for (auto pair : connectednodes) meshing.AddConnectedPair (pair); } for (int i = 1; i <= mesh3d.GetNOpenElements(); i++) { Element2d hel = mesh3d.OpenElement(i); meshing.AddBoundaryElement (hel); } oldne = mesh3d.GetNE(); meshing.GenerateMesh (mesh3d, mpquad); for (int i = oldne + 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (k); (*testout) << "mesh has " << mesh3d.GetNE() << " prism/pyramid elements" << endl; mesh3d.FindOpenElements(k); } } if (mesh3d.HasOpenQuads()) { PrintSysError ("mesh has still open quads"); throw NgException ("Stop meshing since too many attempts"); // return MESHING3_GIVEUP; } if (mp.delaunay && mesh3d.GetNOpenElements()) { Meshing3 meshing((const char**)NULL); mesh3d.FindOpenElements(k); /* for (PointIndex pi = mesh3d.Points().Begin(); pi < mesh3d.Points().End(); pi++) meshing.AddPoint (mesh3d[pi], pi); */ for (PointIndex pi : mesh3d.Points().Range()) meshing.AddPoint (mesh3d[pi], pi); for (int i = 1; i <= mesh3d.GetNOpenElements(); i++) meshing.AddBoundaryElement (mesh3d.OpenElement(i)); oldne = mesh3d.GetNE(); meshing.Delaunay (mesh3d, k, mp); for (int i = oldne + 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (k); PrintMessage (3, mesh3d.GetNP(), " points, ", mesh3d.GetNE(), " elements"); } int cntsteps = 0; if (mesh3d.GetNOpenElements()) do { if (multithread.terminate) break; mesh3d.FindOpenElements(k); PrintMessage (5, mesh3d.GetNOpenElements(), " open faces"); cntsteps++; if (cntsteps > mp.maxoutersteps) throw NgException ("Stop meshing since too many attempts"); string rulefile = ngdir + "/tetra.rls"; PrintMessage (1, "start tetmeshing"); // Meshing3 meshing(rulefile); Meshing3 meshing(tetrules); Array glob2loc(mesh3d.GetNP()); glob2loc = -1; for (PointIndex pi = mesh3d.Points().Begin(); pi < mesh3d.Points().End(); pi++) if (domain_bbox.IsIn (mesh3d[pi])) glob2loc[pi] = meshing.AddPoint (mesh3d[pi], pi); for (int i = 1; i <= mesh3d.GetNOpenElements(); i++) { Element2d hel = mesh3d.OpenElement(i); for (int j = 0; j < hel.GetNP(); j++) hel[j] = glob2loc[hel[j]]; meshing.AddBoundaryElement (hel); // meshing.AddBoundaryElement (mesh3d.OpenElement(i)); } oldne = mesh3d.GetNE(); mp.giveuptol = 15 + 10 * cntsteps; mp.sloppy = 5; meshing.GenerateMesh (mesh3d, mp); for (ElementIndex ei = oldne; ei < mesh3d.GetNE(); ei++) mesh3d[ei].SetIndex (k); mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(k); // teterrpow = 2; if (mesh3d.GetNOpenElements() != 0) { meshed = 0; PrintMessage (5, mesh3d.GetNOpenElements(), " open faces found"); MeshOptimize3d optmesh(mp); const char * optstr = "mcmstmcmstmcmstmcm"; for (size_t j = 1; j <= strlen(optstr); j++) { mesh3d.CalcSurfacesOfNode(); mesh3d.FreeOpenElementsEnvironment(2); mesh3d.CalcSurfacesOfNode(); switch (optstr[j-1]) { case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; case 'd': optmesh.SplitImprove(mesh3d, OPT_REST); break; case 's': optmesh.SwapImprove(mesh3d, OPT_REST); break; case 't': optmesh.SwapImprove2(mesh3d, OPT_REST); break; case 'm': mesh3d.ImproveMesh(mp, OPT_REST); break; } } mesh3d.FindOpenElements(k); PrintMessage (3, "Call remove problem"); RemoveProblem (mesh3d, k); mesh3d.FindOpenElements(k); } else { meshed = 1; PrintMessage (1, "Success !"); } } while (!meshed); PrintMessage (1, mesh3d.GetNP(), " points, ", mesh3d.GetNE(), " elements"); } mp.maxh = globmaxh; MeshQuality3d (mesh3d); return MESHING3_OK; } /* MESHING3_RESULT MeshVolumeOld (MeshingParameters & mp, Mesh& mesh3d) { int i, k, oldne; int meshed; int cntsteps; PlotStatistics3d * pstat; if (globflags.GetNumFlag("silentflag", 1) <= 2) pstat = new XPlotStatistics3d; else pstat = new TerminalPlotStatistics3d; cntsteps = 0; do { cntsteps++; if (cntsteps > mp.maxoutersteps) { return MESHING3_OUTERSTEPSEXCEEDED; } int noldp = mesh3d.GetNP(); if ( (cntsteps == 1) && globflags.GetDefineFlag ("delaunay")) { cntsteps ++; mesh3d.CalcSurfacesOfNode(); for (k = 1; k <= mesh3d.GetNDomains(); k++) { Meshing3 meshing(NULL, pstat); mesh3d.FindOpenElements(k); for (i = 1; i <= noldp; i++) meshing.AddPoint (mesh3d.Point(i), i); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) { if (mesh3d.OpenElement(i).GetIndex() == k) meshing.AddBoundaryElement (mesh3d.OpenElement(i)); } oldne = mesh3d.GetNE(); if (globflags.GetDefineFlag ("blockfill")) { if (!globflags.GetDefineFlag ("localh")) meshing.BlockFill (mesh3d, mp.h * globflags.GetNumFlag ("relblockfillh", 1)); else meshing.BlockFillLocalH (mesh3d); } MeshingParameters mpd; meshing.Delaunay (mesh3d, mpd); for (i = oldne + 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (k); } } noldp = mesh3d.GetNP(); mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(); for (k = 1; k <= mesh3d.GetNDomains(); k++) { Meshing3 meshing(globflags.GetStringFlag ("rules3d", NULL), pstat); Point3d pmin, pmax; mesh3d.GetBox (pmin, pmax, k); rot.SetCenter (Center (pmin, pmax)); for (i = 1; i <= noldp; i++) meshing.AddPoint (mesh3d.Point(i), i); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) { if (mesh3d.OpenElement(i).GetIndex() == k) meshing.AddBoundaryElement (mesh3d.OpenElement(i)); } oldne = mesh3d.GetNE(); if ( (cntsteps == 1) && globflags.GetDefineFlag ("blockfill")) { if (!globflags.GetDefineFlag ("localh")) { meshing.BlockFill (mesh3d, mp.h * globflags.GetNumFlag ("relblockfillh", 1)); } else { meshing.BlockFillLocalH (mesh3d); } } mp.giveuptol = int(globflags.GetNumFlag ("giveuptol", 15)); meshing.GenerateMesh (mesh3d, mp); for (i = oldne + 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (k); } mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(); teterrpow = 2; if (mesh3d.GetNOpenElements() != 0) { meshed = 0; (*mycout) << "Open elements found, old" << endl; const char * optstr = "mcmcmcmcm"; int j; for (j = 1; j <= strlen(optstr); j++) switch (optstr[j-1]) { case 'c': mesh3d.CombineImprove(); break; case 'd': mesh3d.SplitImprove(); break; case 's': mesh3d.SwapImprove(); break; case 'm': mesh3d.ImproveMesh(2); break; } (*mycout) << "Call remove" << endl; RemoveProblem (mesh3d); (*mycout) << "Problem removed" << endl; } else meshed = 1; } while (!meshed); MeshQuality3d (mesh3d); return MESHING3_OK; } */ /* MESHING3_RESULT MeshMixedVolume(MeshingParameters & mp, Mesh& mesh3d) { int i, j; MESHING3_RESULT res; Point3d pmin, pmax; mp.giveuptol = 10; mp.baseelnp = 4; mp.starshapeclass = 100; // TerminalPlotStatistics3d pstat; Meshing3 meshing1("pyramids.rls"); for (i = 1; i <= mesh3d.GetNP(); i++) meshing1.AddPoint (mesh3d.Point(i), i); mesh3d.FindOpenElements(); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) if (mesh3d.OpenElement(i).GetIndex() == 1) meshing1.AddBoundaryElement (mesh3d.OpenElement(i)); res = meshing1.GenerateMesh (mesh3d, mp); mesh3d.GetBox (pmin, pmax); PrintMessage (1, "Mesh pyramids, res = ", res); if (res) exit (1); for (i = 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (1); // do delaunay mp.baseelnp = 0; mp.starshapeclass = 5; Meshing3 meshing2(NULL); for (i = 1; i <= mesh3d.GetNP(); i++) meshing2.AddPoint (mesh3d.Point(i), i); mesh3d.FindOpenElements(); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) if (mesh3d.OpenElement(i).GetIndex() == 1) meshing2.AddBoundaryElement (mesh3d.OpenElement(i)); MeshingParameters mpd; meshing2.Delaunay (mesh3d, mpd); for (i = 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (1); mp.baseelnp = 0; mp.giveuptol = 10; for (int trials = 1; trials <= 50; trials++) { if (multithread.terminate) return MESHING3_TERMINATE; Meshing3 meshing3("tetra.rls"); for (i = 1; i <= mesh3d.GetNP(); i++) meshing3.AddPoint (mesh3d.Point(i), i); mesh3d.FindOpenElements(); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) if (mesh3d.OpenElement(i).GetIndex() == 1) meshing3.AddBoundaryElement (mesh3d.OpenElement(i)); if (trials > 1) CheckSurfaceMesh2 (mesh3d); res = meshing3.GenerateMesh (mesh3d, mp); for (i = 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (1); if (res == 0) break; for (i = 1; i <= mesh3d.GetNE(); i++) { const Element & el = mesh3d.VolumeElement(i); if (el.GetNP() != 4) { for (j = 1; j <= el.GetNP(); j++) mesh3d.AddLockedPoint (el.PNum(j)); } } mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(); MeshOptimize3d optmesh; teterrpow = 2; const char * optstr = "mcmcmcmcm"; for (j = 1; j <= strlen(optstr); j++) switch (optstr[j-1]) { case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; case 'd': optmesh.SplitImprove(mesh3d); break; case 's': optmesh.SwapImprove(mesh3d); break; case 'm': mesh3d.ImproveMesh(); break; } RemoveProblem (mesh3d); } PrintMessage (1, "Meshing tets, res = ", res); if (res) { mesh3d.FindOpenElements(); PrintSysError (1, "Open elements: ", mesh3d.GetNOpenElements()); exit (1); } for (i = 1; i <= mesh3d.GetNE(); i++) { const Element & el = mesh3d.VolumeElement(i); if (el.GetNP() != 4) { for (j = 1; j <= el.GetNP(); j++) mesh3d.AddLockedPoint (el.PNum(j)); } } mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(); MeshOptimize3d optmesh; teterrpow = 2; const char * optstr = "mcmcmcmcm"; for (j = 1; j <= strlen(optstr); j++) switch (optstr[j-1]) { case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; case 'd': optmesh.SplitImprove(mesh3d); break; case 's': optmesh.SwapImprove(mesh3d); break; case 'm': mesh3d.ImproveMesh(); break; } return MESHING3_OK; } */ MESHING3_RESULT OptimizeVolume (MeshingParameters & mp, Mesh & mesh3d) // const CSGeometry * geometry) { static Timer t("OptimizeVolume"); RegionTimer reg(t); int i; PrintMessage (1, "Volume Optimization"); /* if (!mesh3d.PureTetMesh()) return MESHING3_OK; */ // (*mycout) << "optstring = " << mp.optimize3d << endl; /* const char * optstr = globflags.GetStringFlag ("optimize3d", "cmh"); int optsteps = int (globflags.GetNumFlag ("optsteps3d", 2)); */ mesh3d.CalcSurfacesOfNode(); for (i = 1; i <= mp.optsteps3d; i++) { if (multithread.terminate) break; MeshOptimize3d optmesh(mp); // teterrpow = mp.opterrpow; // for (size_t j = 1; j <= strlen(mp.optimize3d); j++) for (size_t j = 1; j <= mp.optimize3d.length(); j++) { if (multithread.terminate) break; switch (mp.optimize3d[j-1]) { case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; case 'd': optmesh.SplitImprove(mesh3d); break; case 's': optmesh.SwapImprove(mesh3d); break; // case 'u': optmesh.SwapImproveSurface(mesh3d); break; case 't': optmesh.SwapImprove2(mesh3d); break; #ifdef SOLIDGEOM case 'm': mesh3d.ImproveMesh(*geometry); break; case 'M': mesh3d.ImproveMesh(*geometry); break; #else case 'm': mesh3d.ImproveMesh(mp); break; case 'M': mesh3d.ImproveMesh(mp); break; #endif case 'j': mesh3d.ImproveMeshJacobian(mp); break; } } mesh3d.mglevels = 1; MeshQuality3d (mesh3d); } return MESHING3_OK; } void RemoveIllegalElements (Mesh & mesh3d) { static Timer t("RemoveIllegalElements"); RegionTimer reg(t); int it = 10; int nillegal, oldn; PrintMessage (1, "Remove Illegal Elements"); // return, if non-pure tet-mesh /* if (!mesh3d.PureTetMesh()) return; */ mesh3d.CalcSurfacesOfNode(); nillegal = mesh3d.MarkIllegalElements(); MeshingParameters dummymp; MeshOptimize3d optmesh(dummymp); while (nillegal && (it--) > 0) { if (multithread.terminate) break; PrintMessage (5, nillegal, " illegal tets"); optmesh.SplitImprove (mesh3d, OPT_LEGAL); mesh3d.MarkIllegalElements(); // test optmesh.SwapImprove (mesh3d, OPT_LEGAL); mesh3d.MarkIllegalElements(); // test optmesh.SwapImprove2 (mesh3d, OPT_LEGAL); oldn = nillegal; nillegal = mesh3d.MarkIllegalElements(); if (oldn != nillegal) it = 10; } PrintMessage (5, nillegal, " illegal tets"); } } netgen-6.2.1905/libsrc/meshing/classifyhpel.hpp0000644000175000017500000014342413504650527020120 0ustar kurtkurtHPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint) { int ep1(0), ep2(0), ep3(0), ep4(0), cp1(0), cp2(0), cp3(0), cp4(0), fp1, fp2, fp3, fp4; int isedge1(0), isedge2(0), isedge3(0), isedge4(0), isedge5(0), isedge6(0); int isfedge1, isfedge2, isfedge3, isfedge4, isfedge5, isfedge6; int isface1(0), isface2(0), isface3(0), isface4(0); HPREF_ELEMENT_TYPE type = HP_NONE; int debug = 0; for (int j = 0;j < 4; j++) { if (el.pnums[j] == 444) debug++; if (el.pnums[j] == 115) debug++; if (el.pnums[j] == 382) debug++; if (el.pnums[j] == 281) debug++; } if (debug < 4) debug = 0; for (int j = 0; j < 4; j++) for (int k = 0; k < 4; k++) { if (j == k) continue; if (type) break; int pi3 = 0; while (pi3 == j || pi3 == k) pi3++; int pi4 = 6 - j - k - pi3; // preserve orientation int sort[4]; sort[0] = j; sort[1] = k; sort[2] = pi3; sort[3] = pi4; int cnt = 0; for (int jj = 0; jj < 4; jj++) for (int kk = 0; kk < 3; kk++) if (sort[kk] > sort[kk+1]) { cnt++; Swap (sort[kk], sort[kk+1]); } if (cnt % 2 == 1) Swap (pi3, pi4); ep1 = edgepoint.Test (el.pnums[j]); ep2 = edgepoint.Test (el.pnums[k]); ep3 = edgepoint.Test (el.pnums[pi3]); ep4 = edgepoint.Test (el.pnums[pi4]); cp1 = cornerpoint.Test (el.pnums[j]); cp2 = cornerpoint.Test (el.pnums[k]); cp3 = cornerpoint.Test (el.pnums[pi3]); cp4 = cornerpoint.Test (el.pnums[pi4]); isedge1 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[k])); isedge2 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi3])); isedge3 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi4])); isedge4 = edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi3])); isedge5 = edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi4])); isedge6 = edges.Used (INDEX_2::Sort (el.pnums[pi3], el.pnums[pi4])); if (debug) { cout << "debug" << endl; *testout << "debug" << endl; *testout << "ep = " << ep1 << ep2 << ep3 << ep4 << endl; *testout << "cp = " << cp1 << cp2 << cp3 << cp4 << endl; *testout << "edge = " << isedge1 << isedge2 << isedge3 << isedge4 << isedge5 << isedge6 << endl; } isface1 = isface2 = isface3 = isface4 = 0; for (int l = 0; l < 4; l++) { INDEX_3 i3(0,0,0); switch (l) { case 0: i3.I1() = el.pnums[k]; i3.I1() = el.pnums[pi3]; i3.I1() = el.pnums[pi4]; break; case 1: i3.I1() = el.pnums[j]; i3.I1() = el.pnums[pi3]; i3.I1() = el.pnums[pi4]; break; case 2: i3.I1() = el.pnums[j]; i3.I1() = el.pnums[k]; i3.I1() = el.pnums[pi4]; break; case 3: i3.I1() = el.pnums[j]; i3.I1() = el.pnums[k]; i3.I1() = el.pnums[pi3]; break; } i3.Sort(); if (faces.Used (i3)) { int domnr = faces.Get(i3); if (domnr == -1 || domnr == el.GetIndex()) { switch (l) { case 0: isface1 = 1; break; case 1: isface2 = 1; break; case 2: isface3 = 1; break; case 3: isface4 = 1; break; } } } } /* isface1 = faces.Used (INDEX_3::Sort (el.pnums[k], el.pnums[pi3], el.pnums[pi4])); isface2 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[pi3], el.pnums[pi4])); isface3 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[k], el.pnums[pi4])); isface4 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[k], el.pnums[pi3])); */ isfedge1 = isfedge2 = isfedge3 = isfedge4 = isfedge5 = isfedge6 = 0; for (int l = 0; l < 6; l++) { INDEX_2 i2(0,0); switch (l) { case 0: i2.I1() = el.pnums[j]; i2.I2() = el[k]; break; case 1: i2.I1() = el.pnums[j]; i2.I2() = el.pnums[pi3]; break; case 2: i2.I1() = el.pnums[j]; i2.I2() = el.pnums[pi4]; break; case 3: i2.I1() = el.pnums[k]; i2.I2() = el.pnums[pi3]; break; case 4: i2.I1() = el.pnums[k]; i2.I2() = el.pnums[pi4]; break; case 5: i2.I1() = el.pnums[pi3]; i2.I2() = el.pnums[pi4]; break; } i2.Sort(); if (face_edges.Used (i2)) { int domnr = face_edges.Get(i2); if (domnr == -1 || domnr == el.GetIndex()) { switch (l) { case 0: isfedge1 = 1; break; case 1: isfedge2 = 1; break; case 2: isfedge3 = 1; break; case 3: isfedge4 = 1; break; case 4: isfedge5 = 1; break; case 5: isfedge6 = 1; break; } } } } /* isfedge1 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[k])); isfedge2 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi3])); isfedge3 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi4])); isfedge4 = face_edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi3])); isfedge5 = face_edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi4])); isfedge6 = face_edges.Used (INDEX_2::Sort (el.pnums[pi3], el.pnums[pi4])); */ fp1 = fp2 = fp3 = fp4 = 0; for (int l = 0; l < 4; l++) { int pti(0); switch (l) { case 0: pti = el.pnums[j]; break; case 1: pti = el.pnums[k]; break; case 2: pti = el.pnums[pi3]; break; case 3: pti = el.pnums[pi4]; break; } int domnr = facepoint[pti]; if (domnr == -1 || domnr == el.GetIndex()) { switch (l) { case 0: fp1 = 1; break; case 1: fp2 = 1; break; case 2: fp3 = 1; break; case 3: fp4 = 1; break; } } } /* fp1 = facepoint[el.pnums[j]] != 0; fp2 = facepoint[el.pnums[k]] != 0; fp3 = facepoint[el.pnums[pi3]] != 0; fp4 = facepoint[el.pnums[pi4]] != 0; */ switch (isface1+isface2+isface3+isface4) { case 0: { isedge1 |= isfedge1; isedge2 |= isfedge2; isedge3 |= isfedge3; isedge4 |= isfedge4; isedge5 |= isfedge5; isedge6 |= isfedge6; ep1 |= fp1; ep2 |= fp2; ep3 |= fp3; ep4 |= fp4; switch (isedge1+isedge2+isedge3+isedge4+isedge5+isedge6) { case 0: { if (!ep1 && !ep2 && !ep3 && !ep4) type = HP_TET; if (ep1 && !ep2 && !ep3 && !ep4) type = HP_TET_0E_1V; if (ep1 && ep2 && !ep3 && !ep4) type = HP_TET_0E_2V; if (ep1 && ep2 && ep3 && !ep4) type = HP_TET_0E_3V; if (ep1 && ep2 && ep3 && ep4) type = HP_TET_0E_4V; break; } case 1: { if (!isedge1) break; if (!cp1 && !cp2 && !ep3 && !ep4) type = HP_TET_1E_0V; if (cp1 && !cp2 && !ep3 && !ep4) type = HP_TET_1E_1VA; if (!cp1 && !cp2 && !ep3 && ep4) type = HP_TET_1E_1VB; if (cp1 && cp2 && !ep3 && !ep4) type = HP_TET_1E_2VA; if (cp1 && !cp2 && ep3 && !ep4) type = HP_TET_1E_2VB; if (cp1 && !cp2 && !ep3 && ep4) type = HP_TET_1E_2VC; if (!cp1 && !cp2 && ep3 && ep4) type = HP_TET_1E_2VD; if (cp1 && cp2 && ep3 && !ep4) type = HP_TET_1E_3VA; if (cp1 && !cp2 && ep3 && ep4) type = HP_TET_1E_3VB; if (cp1 && cp2 && ep3 && ep4) type = HP_TET_1E_4V; break; } case 2: { if (isedge1 && isedge2) { if (!cp2 && !cp3 && !ep4) type = HP_TET_2EA_0V; if (cp2 && !cp3 && !ep4) type = HP_TET_2EA_1VA; if (!cp2 && cp3 && !ep4) type = HP_TET_2EA_1VB; if (!cp2 && !cp3 && ep4) type = HP_TET_2EA_1VC; if (cp2 && cp3 && !ep4) type = HP_TET_2EA_2VA; if (cp2 && !cp3 && ep4) type = HP_TET_2EA_2VB; if (!cp2 && cp3 && ep4) type = HP_TET_2EA_2VC; if (cp2 && cp3 && ep4) type = HP_TET_2EA_3V; } if (isedge1 && isedge6) { if (!cp1 && !cp2 && !cp3 && !cp4) type = HP_TET_2EB_0V; if (cp1 && !cp2 && !cp3 && !cp4) type = HP_TET_2EB_1V; if (cp1 && cp2 && !cp3 && !cp4) type = HP_TET_2EB_2VA; if (cp1 && !cp2 && cp3 && !cp4) type = HP_TET_2EB_2VB; if (cp1 && !cp2 && !cp3 && cp4) type = HP_TET_2EB_2VC; if (cp1 && cp2 && cp3 && !cp4) type = HP_TET_2EB_3V; if (cp1 && cp2 && cp3 && cp4) type = HP_TET_2EB_4V; } break; } case 3: { if (isedge1 && isedge2 && isedge3) { if (!cp2 && !cp3 && !cp4) type = HP_TET_3EA_0V; if (cp2 && !cp3 && !cp4) type = HP_TET_3EA_1V; if (cp2 && cp3 && !cp4) type = HP_TET_3EA_2V; if (cp2 && cp3 && cp4) type = HP_TET_3EA_3V; } if (isedge1 && isedge3 && isedge4) { if (!cp3 && !cp4) type = HP_TET_3EB_0V; if (cp3 && !cp4) type = HP_TET_3EB_1V; if (cp3 && cp4) type = HP_TET_3EB_2V; } if (isedge1 && isedge2 && isedge5) { if (!cp3 && !cp4) type = HP_TET_3EC_0V; if (cp3 && !cp4) type = HP_TET_3EC_1V; if (cp3 && cp4) type = HP_TET_3EC_2V; } break; } } break; } case 1: // one singular face { if (!isface1) break; switch (isfedge1+isfedge2+isfedge3+isedge4+isedge5+isedge6) { case 0: { if (!fp1 && !ep2 && !ep3 && !ep4) type = HP_TET_1F_0E_0V; if (fp1 && !ep2 && !ep3 && !ep4) type = HP_TET_1F_0E_1VB; if (!fp1 && ep2 && !ep3 & !ep4) type = HP_TET_1F_0E_1VA; break; } case 1: { if (isfedge1) { if (!ep1 && !ep3 && !ep4) type = HP_TET_1F_1EA_0V; } if (isedge4) // V1-V3 { if (!ep1 && !cp2 && !cp3 && !ep4) type = HP_TET_1F_1EB_0V; } break; } } break; } case 2: // two singular faces { if (!isface1 || !isface2) break; switch (isfedge1+isedge2+isedge3+isedge4+isedge5) { case 0: { if (!ep1 && !ep2 && !cp3 && !cp4) type = HP_TET_2F_0E_0V; break; } } break; } } if (type != HP_NONE) { int pnums[4]; pnums[0] = el.pnums[j]; pnums[1] = el.pnums[k]; pnums[2] = el.pnums[pi3]; pnums[3] = el.pnums[pi4]; for(k=0;k<4;k++) el.pnums[k] = pnums[k]; break; } } if (debug) cout << "type = " << type << endl; if (type == HP_NONE) { // cnt_undef++; (*testout) << "undefined element" << endl << "cp = " << cp1 << cp2 << cp3 << cp4 << endl << "ep = " << ep1 << ep2 << ep3 << ep4 << endl << "isedge = " << isedge1 << isedge2 << isedge3 << isedge4 << isedge5 << isedge6 << endl << "isface = " << isface1 << isface2 << isface3 << isface4 << endl; cout << "undefined element !!! " << endl; } return(type); } HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint) { HPREF_ELEMENT_TYPE type = HP_NONE; int p[6]; for(int m=1;m<=6;m++) { int point_sing[6]={0,0,0,0,0,0}; int face_sing[5]={0,0,0,0,0}; int edge_sing[9]={0,0,0,0,0,0,0,0,0}; if(m<4) { p[0]= m; p[1]=m%3+1; p[2]=(m%3+1)%3+1; for(int l=3;l<6;l++) p[l]=p[l-3]+3; } else { p[0] = m; p[1]=(m%3+1)%3+4; p[2]=m%3+4; for(int l=3;l<6;l++) p[l]=p[l-3]-3; } for(int j=0;j<6;j++) { if(cornerpoint.Test(el.PNum(p[j]))) { point_sing[p[j]-1]=3;} else if(edgepoint.Test(el.PNum(p[j]))) point_sing[p[j]-1]=2; else if (facepoint[el.PNum(p[j])] == -1 || facepoint[el.PNum(p[j])] == el.GetIndex()) point_sing[p[j]-1] = 1; } const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (PRISM); for(int k=0;k<9;k++) { INDEX_2 i2 = INDEX_2 :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1])); if (edges.Used(i2)) edge_sing[k] = 2; else edge_sing[k] = face_edges.Used(i2); } const ELEMENT_FACE * elfaces = MeshTopology::GetFaces1 (PRISM); for (int k=0;k<5;k++) { INDEX_3 i3; if(k<2) i3 = INDEX_3::Sort(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], el.pnums[p[elfaces[k][2]-1]-1]); else { INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]); i4.Sort(); i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); } if (faces.Used (i3)) { int domnr = faces.Get(i3); if (domnr == -1 || domnr == el.GetIndex()) face_sing[k] = 1; } } if (face_sing[1] > face_sing[0]) {m=m+2; continue;} //int cp = 0; int qfsing = face_sing[2] + face_sing[3] + face_sing[4]; int tfsing = face_sing[0] + face_sing[1]; int evsing = edge_sing[6] + edge_sing[7] + edge_sing[8]; int ehsing = edge_sing[0] + edge_sing[1] + edge_sing[2] + edge_sing[3] + edge_sing[4] + edge_sing[5]; if (qfsing + tfsing + evsing + ehsing == 0) { type = HP_PRISM; break;} HPREF_ELEMENT_TYPE types[] = {HP_NONE,HP_NONE,HP_NONE}; int fb = (1-face_sing[4])* face_sing[3] * (face_sing[2] + face_sing[3]) + 3*face_sing[4]*face_sing[3]*face_sing[2]; int sve[3] = {edge_sing[7] , edge_sing[8], edge_sing[6]}; if(fb!=qfsing) continue; switch(fb) { case 0: if (evsing == 0 && ehsing==3*tfsing) { types[0] = HP_PRISM; types[1] = HP_PRISM_1FA_0E_0V; types[2] = HP_PRISM_2FA_0E_0V; } if(evsing > 0 && sve[0] == evsing) // 1 vertical edge 1-4 { types[0] = HP_PRISM_SINGEDGE; types[1] = HP_PRISM_1FA_1E_0V; types[2] = HP_PRISM_2FA_1E_0V; } if(sve[0] > 0 && sve[1] > 0 && sve[2] == 0) { types[0] = HP_PRISM_SINGEDGE_V12; types[1] = HP_PRISM_1FA_2E_0V; types[2] = HP_PRISM_2FA_2E_0V; } if(sve[0] > 0 && sve[1] > 0 && sve[2] > 0) { types[0] = HP_PRISM_3E_0V; types[1] = HP_PRISM_1FA_3E_0V; types[2] = HP_PRISM_2FA_3E_0V; if ( edge_sing[0] > 1 && edge_sing[2] > 1 && edge_sing[4] > 1 && edge_sing[5] > 1 && tfsing==0) types[0] = HP_PRISM_3E_4EH; } break; case 1: if(sve[0] <= 1 && sve[1] <= 1) { if(sve[2]==0) { types[0] = HP_PRISM_1FB_0E_0V; types[1] = HP_PRISM_1FA_1FB_0E_0V; types[2] = HP_PRISM_2FA_1FB_0E_0V; } else { types[0] = HP_PRISM_1FB_1EC_0V; types[1] = HP_PRISM_1FA_1FB_1EC_0V; types[2] = HP_PRISM_2FA_1FB_1EC_0V; } } if(sve[0] > 1 && sve[2] >= 1 && sve[1] <= 1) { types[0] = HP_PRISM_1FB_2EB_0V; types[1] = HP_PRISM_1FA_1FB_2EB_0V; types[2] = HP_PRISM_2FA_1FB_2EB_0V; } if(sve[0] > 1 && sve[1] <= 1 && sve[2] == 0) // ea && !eb { types[0] = HP_PRISM_1FB_1EA_0V; types[1] = HP_PRISM_1FA_1FB_1EA_0V; types[2] = HP_PRISM_2FA_1FB_1EA_0V; } if(sve[0] <= 1 && sve[1] > 1 && sve[2] == 0) types[1] = HP_PRISM_1FA_1FB_1EB_0V; if(sve[0] > 1 && sve[1]>1) if(sve[2] == 0) // ea && eb { types[0] = HP_PRISM_1FB_2EA_0V; types[1] = HP_PRISM_1FA_1FB_2EA_0V; types[2] = HP_PRISM_2FA_1FB_2EA_0V; } if(sve[0] <= 1 && sve[1] > 1 && sve[2] >0) types[1] = HP_PRISM_1FA_1FB_2EC_0V; if(sve[0] > 1 && sve[1] > 1 && sve[2] >= 1) //sve[2] can also be a face-edge { types[0] = HP_PRISM_1FB_3E_0V; types[1] = HP_PRISM_1FA_1FB_3E_0V; types[2] = HP_PRISM_2FA_1FB_3E_0V; } break; case 2: if(sve[0] <= 1) cout << " **** WARNING: Edge between to different singular faces should be marked singular " << endl; if(sve[1] <= 1) if(sve[2] <=1) { types[0] = HP_PRISM_2FB_0E_0V; types[1] = HP_PRISM_1FA_2FB_0E_0V; types[2] = HP_PRISM_2FA_2FB_0E_0V; } else { types[0] = HP_PRISM_2FB_1EC_0V; types[1] = HP_PRISM_1FA_2FB_1EC_0V; types[2] = HP_PRISM_2FA_2FB_1EC_0V; } else if(sve[2] <= 1) types[1] = HP_PRISM_1FA_2FB_1EB_0V; else { types[0] = HP_PRISM_2FB_3E_0V; types[1] = HP_PRISM_1FA_2FB_3E_0V; types[2] = HP_PRISM_2FA_2FB_3E_0V; } break; case 3: types[0] = HP_PRISM_3FB_0V; types[1] = HP_PRISM_1FA_3FB_0V; types[2] = HP_PRISM_2FA_3FB_0V; break; } type = types[tfsing]; if(type != HP_NONE) break; } /* *testout << " Prism with pnums " << endl; for(int j=0;j<6;j++) *testout << el.pnums[j] << "\t"; *testout << endl; */ if(type != HP_NONE) { int pnums[6]; for(int j=0;j<6;j++) pnums[j] = el.PNum (p[j]); for(int k=0;k<6;k++) el.pnums[k] = pnums[k]; } /* *testout << " Classified Prism with pnums " << endl; for(int j=0;j<6;j++) *testout << el.pnums[j] << "\t"; *testout << endl; */ return(type); } // #ifdef SABINE HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int pnums[3]; int p[3]; INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); i3.Sort(); bool sing_face = faces.Used (i3); // *testout << " facepoint " << facepoint << endl; // Try all rotations of the trig for (int j=0;j<3;j++) { int point_sing[3] = {0,0,0}; int edge_sing[3] = {0,0,0}; // *testout << " actual rotation of trig points " ; for(int m=0;m<3;m++) { p[m] = (j+m)%3 +1; // local vertex number pnums[m] = el.PNum(p[m]); // global vertex number // *testout << pnums[m] << " \t "; } // *testout << endl ; if(dim == 3) { // face point for(int k=0;k<3;k++) if(!sing_face) { // *testout << " fp [" << k << "] = " << facepoint[pnums[k]] << endl; // *testout << " fd.DomainIn()" << fd.DomainIn() << endl; // *testout << " fd.DomainOut()" << fd.DomainOut() << endl; if( facepoint[pnums[k]] && (facepoint[pnums[k]] ==-1 || facepoint[pnums[k]] == fd.DomainIn() || facepoint[pnums[k]] == fd.DomainOut())) point_sing[p[k]-1] = 1; } // if point is on face_edge in next step sing = 2 /* *testout << " pointsing NACH FACEPOints ... FALLS EDGEPOINT UMSETZEN" ; for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; *testout << endl; */ } const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1(TRIG); if(dim==3) { for(int k=0;k<3;k++) { int ep1=p[eledges[k][0]-1]; int ep2=p[eledges[k][1]-1]; INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); if(edges.Used(i2)) { edge_sing[k]=2; point_sing[ep1-1] = 2; point_sing[ep2-1] = 2; } else // face_edge? { i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1) // edge not face_edge acc. to surface in which trig lies { if(face_edges.Get(i2)==-1 ||face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut() ) { edge_sing[k]=1; } else { point_sing[ep1-1] = 0; // set to edge_point point_sing[ep2-1] = 0; // set to edge_point } } } /* *testout << " pointsing NACH edges UND FACEEDGES UMSETZEN ... " ; for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; *testout << endl; */ } } /* *testout << " dim " << dim << endl; *testout << " edgepoint_dom " << edgepoint_dom << endl; */ if(dim==2) { for(int k=0;k<3;k++) { int ep1=p[eledges[k][0]-1]; int ep2=p[eledges[k][1]-1]; INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); if(edges.Used(i2)) { if(edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep1-1])) || edgepoint_dom.Used(INDEX_2(-1,pnums[ep1-1])) || edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep2-1])) || edgepoint_dom.Used(INDEX_2(-1,pnums[ep2-1]))) { edge_sing[k]=2; point_sing[ep1-1] = 2; point_sing[ep2-1] = 2; } } } } for(int k=0;k<3;k++) if(edgepoint.Test(pnums[k])) //edgepoint, but not member of sing_edge on trig -> cp { INDEX_2 i2a=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+1)%3])); INDEX_2 i2b=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+2)%3])); if(!edges.Used(i2a) && !edges.Used(i2b)) point_sing[p[k]-1] = 3; } for(int k=0;k<3;k++) if(cornerpoint.Test(el.PNum(p[k]))) point_sing[p[k]-1] = 3; *testout << "point_sing = " << point_sing[0] << point_sing[1] << point_sing[2] << endl; if(edge_sing[0] + edge_sing[1] + edge_sing[2] == 0) { int ps = point_sing[0] + point_sing[1] + point_sing[2]; if(ps==0) type = HP_TRIG; else if(point_sing[p[0]-1] && !point_sing[p[1]-1] && !point_sing[p[2]-1]) type = HP_TRIG_SINGCORNER; else if(point_sing[p[0]-1] && point_sing[p[1]-1] && !point_sing[p[2]-1]) type = HP_TRIG_SINGCORNER12; else if(point_sing[p[0]-1] && point_sing[p[1]-1] && point_sing[p[2]-1]) { if(dim==2) type = HP_TRIG_SINGCORNER123_2D; else type = HP_TRIG_SINGCORNER123; } } else if (edge_sing[2] && !edge_sing[0] && !edge_sing[1]) //E[2]=(1,2) { int code = 0; if(point_sing[p[0]-1] > edge_sing[2]) code+=1; if(point_sing[p[1]-1] > edge_sing[2]) code+=2; if(point_sing[p[2]-1]) code+=4; HPREF_ELEMENT_TYPE types[] = { HP_TRIG_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER12, HP_TRIG_SINGEDGECORNER3, HP_TRIG_SINGEDGECORNER13, HP_TRIG_SINGEDGECORNER23, HP_TRIG_SINGEDGECORNER123, }; type = types[code]; } // E[0] = [0,2], E[1] =[1,2], E[2] = [0,1] else if(edge_sing[2] && !edge_sing[1] && edge_sing[0]) { if(point_sing[p[2]-1] <= edge_sing[0] ) { if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES; else type = HP_TRIG_SINGEDGES2; } else { if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES3; else type = HP_TRIG_SINGEDGES23; } } else if (edge_sing[2] && edge_sing[1] && edge_sing[0]) type = HP_TRIG_3SINGEDGES; // cout << " run for " << j << " gives type " << type << endl; //*testout << " run for " << j << " gives type " << type << endl; if(type!=HP_NONE) break; } *testout << "type = " << type << endl; for(int k=0;k<3;k++) el[k] = pnums[k]; /*if(type != HP_NONE) { cout << " TRIG with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << endl; cout << " type " << type << endl; } */ return(type); } #ifdef HPREF_OLD HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int pnums[3]; INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); i3.Sort(); bool sing_face = faces.Used (i3); for (int j = 1; j <= 3; j++) { int ep1 = edgepoint.Test (el.PNumMod (j)); int ep2 = edgepoint.Test (el.PNumMod (j+1)); int ep3 = edgepoint.Test (el.PNumMod (j+2)); if (dim == 2) { // JS, Dec 11 ep1 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+1))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+2))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+2))); /* ep1 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+2))); */ // ep3 = edgepoint_dom.Used (INDEX_2 (mesh.SurfaceElement(i).GetIndex(), el.PNumMod(j+2))); } int cp1 = cornerpoint.Test (el.PNumMod (j)); int cp2 = cornerpoint.Test (el.PNumMod (j+1)); int cp3 = cornerpoint.Test (el.PNumMod (j+2)); ep1 |= cp1; ep2 |= cp2; ep3 |= cp3; // (*testout) << "cp = " << cp1 << cp2 << cp3 << ", ep = " << ep1 << ep2 << ep3 << endl; int p[3] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2)}; if(ep1) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[0], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp1 = 1; } if(ep2) { INDEX_2 i2a=INDEX_2::Sort(p[1], p[0]); INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp2 = 1; } if(ep3) { INDEX_2 i2a=INDEX_2::Sort(p[2], p[0]); INDEX_2 i2b=INDEX_2::Sort(p[2], p[1]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp3= 1; } int isedge1=0, isedge2=0, isedge3=0; if(dim == 3 ) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); isedge1 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge1=1; ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); isedge2 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge2=1; ep2 = 1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); isedge3 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge3=1; ep1 = 1; ep3=1; } // cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; if (!sing_face) { /* if (!isedge1) { cp1 |= ep1; cp2 |= ep2; } if (!isedge2) { cp2 |= ep2; cp3 |= ep3; } if (!isedge3) { cp3 |= ep3; cp1 |= ep1; } */ ep1 |= facepoint [el.PNumMod(j)] != 0; ep2 |= facepoint [el.PNumMod(j+1)] != 0; ep3 |= facepoint [el.PNumMod(j+2)] != 0; isedge1 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))); isedge2 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+1), el.PNumMod(j+2))); isedge3 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+2), el.PNumMod(j+3))); } } if(dim ==2) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); i2.Sort(); isedge1 = edges.Used (i2); if(isedge1) { ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); i2.Sort(); isedge2 = edges.Used (i2); if(isedge2) { ep2 = 1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); i2.Sort(); isedge3 = edges.Used (i2); if(isedge3) { ep1 = 1; ep3=1; } } /* cout << " used " << face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))) << endl; cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; cout << " ep " << ep1 << "\t" << ep2 << " \t " << ep3 << endl; cout << " cp " << cp1 << "\t" << cp2 << " \t " << cp3 << endl; */ if (isedge1 + isedge2 + isedge3 == 0) { if (!ep1 && !ep2 && !ep3) type = HP_TRIG; if (ep1 && !ep2 && !ep3) type = HP_TRIG_SINGCORNER; if (ep1 && ep2 && !ep3) type = HP_TRIG_SINGCORNER12; if (ep1 && ep2 && ep3) { if (dim == 2) type = HP_TRIG_SINGCORNER123_2D; else type = HP_TRIG_SINGCORNER123; } if (type != HP_NONE) { pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } } if (isedge1 && !isedge2 && !isedge3) { int code = 0; if (cp1) code += 1; if (cp2) code += 2; if (ep3) code += 4; HPREF_ELEMENT_TYPE types[] = { HP_TRIG_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER12, HP_TRIG_SINGEDGECORNER3, HP_TRIG_SINGEDGECORNER13, HP_TRIG_SINGEDGECORNER23, HP_TRIG_SINGEDGECORNER123, }; type = types[code]; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } if (isedge1 && !isedge2 && isedge3) { if (!cp3) { if (!cp2) type = HP_TRIG_SINGEDGES; else type = HP_TRIG_SINGEDGES2; } else { if (!cp2) type = HP_TRIG_SINGEDGES3; else type = HP_TRIG_SINGEDGES23; } pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } if (isedge1 && isedge2 && isedge3) { type = HP_TRIG_3SINGEDGES; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } } for(int k=0;k<3;k++) el[k] = pnums[k]; /*if(type != HP_NONE) { cout << " TRIG with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << endl; cout << " type " << type << endl; } */ return(type); } #endif HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int ep1(-1), ep2(-1), ep3(-1), ep4(-1), cp1(-1), cp2(-1), cp3(-1), cp4(-1); int isedge1, isedge2, isedge3, isedge4; *testout << "edges = " << edges << endl; for (int j = 1; j <= 4; j++) { ep1 = edgepoint.Test (el.PNumMod (j)); ep2 = edgepoint.Test (el.PNumMod (j+1)); ep3 = edgepoint.Test (el.PNumMod (j+2)); ep4 = edgepoint.Test (el.PNumMod (j+3)); if (dim == 2) { ep1 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+2))); ep4 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+3))); } cp1 = cornerpoint.Test (el.PNumMod (j)); cp2 = cornerpoint.Test (el.PNumMod (j+1)); cp3 = cornerpoint.Test (el.PNumMod (j+2)); cp4 = cornerpoint.Test (el.PNumMod (j+3)); ep1 |= cp1; ep2 |= cp2; ep3 |= cp3; ep4 |= cp4; int p[4] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2), el.PNumMod(j+4)}; //int epp[4] = { ep1, ep2, ep3, ep4}; int cpp[4] = { cp1, cp2, cp3, cp4}; for(int k=0;k<0;k++) { INDEX_2 i2a=INDEX_2::Sort(p[k], p[(k+1)%4]); INDEX_2 i2b=INDEX_2::Sort(p[k], p[(k-1)%4]); if(!edges.Used(i2a) && !edges.Used(i2b)) cpp[k] = 1; } cp1= cpp[0]; cp2=cpp[1]; cp3=cpp[2]; cp4=cpp[3]; if(dim ==3) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); // i2.Sort(); isedge1 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge1=1; ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); // i2.Sort(); isedge2 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge2=1; ep2=1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); // i2.Sort(); isedge3 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge3=1; ep3=1; ep4=1; } i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); // i2.Sort(); isedge4 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge4=1; ep4=1; ep1=1; } //MH*********************************************************************************************************** if(ep1) if(edgepoint.Test(p[0])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[0], p[3]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp1 = 1; } if(ep2) if(edgepoint.Test(p[1])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp2 = 1; } if(ep3) if(edgepoint.Test(p[2])) { INDEX_2 i2a=INDEX_2::Sort(p[2], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp3 = 1; } if(ep4) if(edgepoint.Test(p[3])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[3]); INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp4 = 1; } //MH***************************************************************************************************************************** } else { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); i2.Sort(); isedge1 = edges.Used (i2); if(isedge1) { ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); i2.Sort(); isedge2 = edges.Used (i2); if(isedge2) { ep2=1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); i2.Sort(); isedge3 = edges.Used (i2); if(isedge3) { ep3=1; ep4=1; } i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); i2.Sort(); isedge4 = edges.Used (i2); if(isedge4) { ep4=1; ep1=1; } } int sumcp = cp1 + cp2 + cp3 + cp4; int sumep = ep1 + ep2 + ep3 + ep4; int sumedge = isedge1 + isedge2 + isedge3 + isedge4; *testout << "isedge = " << isedge1 << isedge2 << isedge3 << isedge4 << endl; *testout << "iscp = " << cp1 << cp2 << cp3 << cp4 << endl; *testout << "isep = " << ep1 << ep2 << ep3 << ep4 << endl; switch (sumedge) { case 0: { switch (sumep) { case 0: type = HP_QUAD; break; case 1: if (ep1) type = HP_QUAD_SINGCORNER; break; case 2: { if (ep1 && ep2) type = HP_QUAD_0E_2VA; if (ep1 && ep3) type = HP_QUAD_0E_2VB; break; } case 3: if (!ep4) type = HP_QUAD_0E_3V; break; case 4: type = HP_QUAD_0E_4V; break; } break; } case 1: { if (isedge1) { switch (cp1+cp2+ep3+ep4) { case 0: type = HP_QUAD_SINGEDGE; break; case 1: { if (cp1) type = HP_QUAD_1E_1VA; if (cp2) type = HP_QUAD_1E_1VB; if (ep3) type = HP_QUAD_1E_1VC; if (ep4) type = HP_QUAD_1E_1VD; break; } case 2: { if (cp1 && cp2) type = HP_QUAD_1E_2VA; if (cp1 && ep3) type = HP_QUAD_1E_2VB; if (cp1 && ep4) type = HP_QUAD_1E_2VC; if (cp2 && ep3) type = HP_QUAD_1E_2VD; if (cp2 && ep4) type = HP_QUAD_1E_2VE; if (ep3 && ep4) type = HP_QUAD_1E_2VF; break; } case 3: { if (cp1 && cp2 && ep3) type = HP_QUAD_1E_3VA; if (cp1 && cp2 && ep4) type = HP_QUAD_1E_3VB; if (cp1 && ep3 && ep4) type = HP_QUAD_1E_3VC; if (cp2 && ep3 && ep4) type = HP_QUAD_1E_3VD; break; } case 4: { type = HP_QUAD_1E_4V; break; } } } break; } case 2: { if (isedge1 && isedge4) { if (!cp2 && !ep3 && !cp4) type = HP_QUAD_2E; if (cp2 && !ep3 && !cp4) type = HP_QUAD_2E_1VA; if (!cp2 && ep3 && !cp4) type = HP_QUAD_2E_1VB; if (!cp2 && !ep3 && cp4) type = HP_QUAD_2E_1VC; if (cp2 && ep3 && !cp4) type = HP_QUAD_2E_2VA; if (cp2 && !ep3 && cp4) type = HP_QUAD_2E_2VB; if (!cp2 && ep3 && cp4) type = HP_QUAD_2E_2VC; if (cp2 && ep3 && cp4) type = HP_QUAD_2E_3V; } if (isedge1 && isedge3) { switch (sumcp) { case 0: type = HP_QUAD_2EB_0V; break; case 1: { if (cp1) type = HP_QUAD_2EB_1VA; if (cp2) type = HP_QUAD_2EB_1VB; break; } case 2: { if (cp1 && cp2) { type = HP_QUAD_2EB_2VA; } if (cp1 && cp3) { type = HP_QUAD_2EB_2VB; } if (cp1 && cp4) { type = HP_QUAD_2EB_2VC; } if (cp2 && cp4) { type = HP_QUAD_2EB_2VD; } break; } case 3: { if (cp1 && cp2 && cp3) { type = HP_QUAD_2EB_3VA; } if (cp1 && cp2 && cp4) { type = HP_QUAD_2EB_3VB; } break; } case 4: { type = HP_QUAD_2EB_4V; break; } } } break; } case 3: { if (isedge1 && isedge2 && isedge4) { if (!cp3 && !cp4) type = HP_QUAD_3E; if (cp3 && !cp4) type = HP_QUAD_3E_3VA; if (!cp3 && cp4) type = HP_QUAD_3E_3VB; if (cp3 && cp4) type = HP_QUAD_3E_4V; } break; } case 4: { type = HP_QUAD_4E; break; } } if (type != HP_NONE) { int pnums[4]; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); pnums[3] = el.PNumMod (j+3); for (int k=0;k<4;k++) el[k] = pnums[k]; /* cout << " QUAD with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << "\t" << pnums[3] << endl << " of type " << type << endl; */ break; } } if (type == HP_NONE) { (*testout) << "undefined element" << endl << "cp = " << cp1 << cp2 << cp3 << cp4 << endl << "ep = " << ep1 << ep2 << ep3 << ep4 << endl << "isedge = " << isedge1 << isedge2 << isedge3 << isedge4 << endl; } *testout << "quad type = " << type << endl; return type; } HPREF_ELEMENT_TYPE ClassifyHex(HPRefElement & el, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint) { HPREF_ELEMENT_TYPE type = HP_NONE; // implementation only for HP_HEX_1F_0E_0V // HP_HEX_1FA_1FB_0E_0V // HP_HEX // up to now other cases are refine dummies // indices of bot,top-faces combinations int index[6][2] = {{0,1},{1,0},{2,4},{4,2},{3,5},{5,3}}; int p[8]; const ELEMENT_FACE * elfaces = MeshTopology::GetFaces1 (HEX); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (HEX); for(int m=0;m<6 && type == HP_NONE;m++) for(int j=0;j<4 && type == HP_NONE;j++) { int point_sing[8]={0,0,0,0,0,0,0,0}; int face_sing[6] = {0,0,0,0,0,0}; int edge_sing[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; int spoint=0, sface=0, sedge=0; for(int l=0;l<4;l++) { p[l] = elfaces[index[m][0]][(4-j-l)%4]; p[l+4] = elfaces[index[m][1]][(j+l)%4]; } for(int l=0;l<8;l++) if(cornerpoint.Test(el.PNum(p[l]))) { point_sing[p[l]-1]=3; spoint++; } else if(edgepoint.Test(el.PNum(p[l]))) point_sing[p[l]-1]=2; else if (facepoint[el.PNum(p[l])] == -1 || facepoint[el.PNum(p[l])] == el.GetIndex()) point_sing[p[l]-1] = 1; for(int k=0;k<12;k++) { INDEX_2 i2 = INDEX_2 :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1])); if (edges.Used(i2)) { edge_sing[k] = 2; sedge++; } else edge_sing[k] = face_edges.Used(i2); } for (int k=0;k<6;k++) { INDEX_3 i3; INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]); i4.Sort(); i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); if (faces.Used (i3)) { int domnr = faces.Get(i3); if (domnr == -1 || domnr == el.GetIndex()) { face_sing[k] = 1; sface++; } } } if(!sface && !sedge && !spoint) type = HP_HEX; if(!sedge && !spoint) { if(face_sing[0] && face_sing[2] && sface==2) type = HP_HEX_1FA_1FB_0E_0V; if (face_sing[0] && sface==1) type = HP_HEX_1F_0E_0V; } el.type=type; if(type != HP_NONE) { int pnums[8]; for(int l=0;l<8;l++) pnums[l] = el[p[l]-1]; for(int l=0;l<8;l++) el[l] = pnums[l]; /* cout << " HEX with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << "\t" << pnums[3] << "\t" << pnums[4] << "\t" << pnums[5] << endl << " of type " << type << endl; */ break; } } return (type); } HPREF_ELEMENT_TYPE ClassifySegm(HPRefElement & hpel, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint) { int cp1 = cornerpoint.Test (hpel[0]); int cp2 = cornerpoint.Test (hpel[1]); INDEX_2 i2; i2 = INDEX_2(hpel[0], hpel[1]); i2.Sort(); if (!edges.Used (i2)) { cp1 = edgepoint.Test (hpel[0]); cp2 = edgepoint.Test (hpel[1]); } if(!edges.Used(i2) && !face_edges.Used(i2)) { if(facepoint[hpel[0]]!=0) cp1=1; if(facepoint[hpel[1]]!=0) cp2=1; } if(edges.Used(i2) && !face_edges.Used(i2)) { if(facepoint[hpel[0]]) cp1 = 1; if(facepoint[hpel[1]]) cp2 = 1; } if (!cp1 && !cp2) hpel.type = HP_SEGM; else if (cp1 && !cp2) hpel.type = HP_SEGM_SINGCORNERL; else if (!cp1 && cp2) hpel.type = HP_SEGM_SINGCORNERR; else hpel.type = HP_SEGM_SINGCORNERS; // cout << " SEGM found with " << hpel[0] << " \t" << hpel[1] << endl << " of type " << hpel.type << endl; return(hpel.type) ; } HPREF_ELEMENT_TYPE ClassifyPyramid(HPRefElement & el, INDEX_2_HASHTABLE & edges, INDEX_2_HASHTABLE & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE & faces, INDEX_2_HASHTABLE & face_edges, INDEX_2_HASHTABLE & surf_edges, Array & facepoint) { HPREF_ELEMENT_TYPE type = HP_NONE; // implementation only for HP_PYRAMID // HP_PYRAMID_0E_1V // HP_PYRAMID_EDGES // HP_PYRAMID_1FB_0E_1VA // up to now other cases are refine dummies // indices of bot,top-faces combinations // int index[6][2] = {{0,1},{1,0},{2,4},{4,2},{3,5},{5,3}}; const ELEMENT_FACE * elfaces = MeshTopology::GetFaces1 (PYRAMID); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (PYRAMID); int point_sing[5]={0,0,0,0,0}; int face_sing[5] = {0,0,0,0,0}; int edge_sing[8] = {0,0,0,0,0,0,0,0}; int spoint=0, sedge=0, sface=0; for(int m=0;m<4 && type == HP_NONE;m++) { int p[5] = {m%4, m%4+1, m%4+2, m%4+3, 4}; for(int l=0;l<5;l++) { if(cornerpoint.Test(el.pnums[p[l]])) point_sing[l]=3; else if(edgepoint.Test(el.pnums[p[l]])) point_sing[l]=2; else if (facepoint[el.pnums[p[l]]] == -1 || facepoint[el.pnums[p[l]]] == el.GetIndex()) point_sing[l] = 1; spoint += point_sing[l]; } for(int k=0;k<8;k++) { INDEX_2 i2 = INDEX_2 :: Sort(el.pnums[p[eledges[k][0]-1]], el.pnums[p[eledges[k][1]-1]]); if (edges.Used(i2)) edge_sing[k] = 2; else edge_sing[k] = face_edges.Used(i2); sedge += edge_sing[k]; } for (int k=0;k<5;k++) { INDEX_3 i3; INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]], el.pnums[p[elfaces[k][1]-1]], el.pnums[p[elfaces[k][2]-1]], el.pnums[p[elfaces[k][3]-1]]); i4.Sort(); i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); if (faces.Used (i3)) { int domnr = faces.Get(i3); if (domnr == -1 || domnr == el.GetIndex()) face_sing[k] = 1; } sface +=face_sing[k]; } if(!sface && !spoint && !sedge) return(HP_PYRAMID); if(!sface && !sedge && point_sing[p[0]] == spoint) type = HP_PYRAMID_0E_1V; if(!sface && edge_sing[0] + edge_sing[2] == sedge && spoint == point_sing[0] + point_sing[1] + point_sing[3]) type = HP_PYRAMID_EDGES; if(sface && sface == face_sing[0] && spoint == point_sing[4] + 2) type = HP_PYRAMID_1FB_0E_1VA; if(type != HP_NONE) { int pnums[8]; for(int l=0;l<5;l++) pnums[l] = el[p[l]]; for(int l=0;l<5;l++) el[l] = pnums[l]; el.type=type; break; } } return (type); } netgen-6.2.1905/libsrc/meshing/improve3.cpp0000644000175000017500000020711313504650527017165 0ustar kurtkurt#include #include "meshing.hpp" #ifdef SOLIDGEOM #include #endif #include namespace netgen { /* Combine two points to one. Set new point into the center, if both are inner points. Connect inner point to boundary point, if one point is inner point. */ void MeshOptimize3d :: CombineImprove (Mesh & mesh, OPTIMIZEGOAL goal) { static Timer t("MeshOptimize3d::CombineImprove"); RegionTimer reg(t); int np = mesh.GetNP(); int ne = mesh.GetNE(); TABLE elementsonnode(np); Array hasonepi, hasbothpi; Array oneperr; Array elerrs (ne); PrintMessage (3, "CombineImprove"); (*testout) << "Start CombineImprove" << "\n"; // mesh.CalcSurfacesOfNode (); const char * savetask = multithread.task; multithread.task = "Combine Improve"; double totalbad = 0; for (ElementIndex ei = 0; ei < ne; ei++) { if(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex()) continue; double elerr = CalcBad (mesh.Points(), mesh[ei], 0); totalbad += elerr; elerrs[ei] = elerr; } if (goal == OPT_QUALITY) { totalbad = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); (*testout) << "Total badness = " << totalbad << endl; PrintMessage (5, "Total badness = ", totalbad); } for (ElementIndex ei = 0; ei < ne; ei++) if (!mesh[ei].IsDeleted()) for (int j = 0; j < mesh[ei].GetNP(); j++) elementsonnode.Add (mesh[ei][j], ei); INDEX_2_HASHTABLE edgetested (np+1); int cnt = 0; for (ElementIndex ei = 0; ei < ne; ei++) { if(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex()) continue; if (multithread.terminate) break; multithread.percent = 100.0 * (ei+1) / ne; if (mesh.ElementType(ei) == FIXEDELEMENT) continue; for (int j = 0; j < 6; j++) { Element & elemi = mesh[ei]; if (elemi.IsDeleted()) continue; static const int tetedges[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; PointIndex pi1 = elemi[tetedges[j][0]]; PointIndex pi2 = elemi[tetedges[j][1]]; if (pi2 < pi1) Swap (pi1, pi2); INDEX_2 si2 (pi1, pi2); si2.Sort(); if (edgetested.Used (si2)) continue; edgetested.Set (si2, 1); // hasonepoint.SetSize(0); // hasbothpoints.SetSize(0); hasonepi.SetSize(0); hasbothpi.SetSize(0); FlatArray row1 = elementsonnode[pi1]; for (int k = 0; k < row1.Size(); k++) { Element & elem = mesh[row1[k]]; if (elem.IsDeleted()) continue; if (elem[0] == pi2 || elem[1] == pi2 || elem[2] == pi2 || elem[3] == pi2) { hasbothpi.Append (row1[k]); } else { hasonepi.Append (row1[k]); } } FlatArray row2 = elementsonnode[pi2]; for (int k = 0; k < row2.Size(); k++) { Element & elem = mesh[row2[k]]; if (elem.IsDeleted()) continue; if (elem[0] == pi1 || elem[1] == pi1 || elem[2] == pi1 || elem[3] == pi1) ; else { hasonepi.Append (row2[k]); } } double bad1 = 0; for (int k = 0; k < hasonepi.Size(); k++) bad1 += elerrs[hasonepi[k]]; for (int k = 0; k < hasbothpi.Size(); k++) bad1 += elerrs[hasbothpi[k]]; MeshPoint p1 = mesh[pi1]; MeshPoint p2 = mesh[pi2]; // if (mesh.PointType(pi2) != INNERPOINT) if (p2.Type() != INNERPOINT) continue; MeshPoint pnew; // if (mesh.PointType(pi1) != INNERPOINT) if (p1.Type() != INNERPOINT) pnew = p1; else pnew = Center (p1, p2); mesh[pi1] = pnew; mesh[pi2] = pnew; oneperr.SetSize (hasonepi.Size()); double bad2 = 0; for (int k = 0; k < hasonepi.Size(); k++) { const Element & elem = mesh[hasonepi[k]]; double err = CalcBad (mesh.Points(), elem, 0); // CalcTetBadness (mesh[elem[0]], mesh[elem[1]], // mesh[elem[2]], mesh[elem[3]], 0, mparam); bad2 += err; oneperr[k] = err; } mesh[pi1] = p1; mesh[pi2] = p2; // if (mesh.PointType(pi1) != INNERPOINT) if (p1.Type() != INNERPOINT) { for (int k = 0; k < hasonepi.Size(); k++) { Element & elem = mesh[hasonepi[k]]; int l; for (l = 0; l < 4; l++) if (elem[l] == pi2) { elem[l] = pi1; break; } elem.flags.illegal_valid = 0; if (!mesh.LegalTet(elem)) bad2 += 1e4; if (l < 4) { elem.flags.illegal_valid = 0; elem[l] = pi2; } } } if (bad2 / hasonepi.Size() < bad1 / (hasonepi.Size()+hasbothpi.Size())) { mesh[pi1] = pnew; cnt++; FlatArray row = elementsonnode[pi2]; for (int k = 0; k < row.Size(); k++) { Element & elem = mesh[row[k]]; if (elem.IsDeleted()) continue; elementsonnode.Add (pi1, row[k]); for (int l = 0; l < elem.GetNP(); l++) if (elem[l] == pi2) elem[l] = pi1; elem.flags.illegal_valid = 0; if (!mesh.LegalTet (elem)) (*testout) << "illegal tet " << elementsonnode[pi2][k] << endl; } for (int k = 0; k < hasonepi.Size(); k++) elerrs[hasonepi[k]] = oneperr[k]; for (int k = 0; k < hasbothpi.Size(); k++) { mesh[hasbothpi[k]].flags.illegal_valid = 0; mesh[hasbothpi[k]].Delete(); } } } } mesh.Compress(); mesh.MarkIllegalElements(); PrintMessage (5, cnt, " elements combined"); (*testout) << "CombineImprove done" << "\n"; totalbad = 0; for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) if(!(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex())) totalbad += CalcBad (mesh.Points(), mesh[ei], 0); if (goal == OPT_QUALITY) { totalbad = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); (*testout) << "Total badness = " << totalbad << endl; int cntill = 0; for (ElementIndex ei = 0; ei < ne; ei++) if(!(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex())) if (!mesh.LegalTet (mesh[ei])) cntill++; PrintMessage (5, cntill, " illegal tets"); } multithread.task = savetask; } /* Mesh improvement by edge splitting. If mesh quality is improved by inserting a node into an inner edge, the edge is split into two parts. */ void MeshOptimize3d :: SplitImprove (Mesh & mesh, OPTIMIZEGOAL goal) { static Timer t("MeshOptimize3d::SplitImprove"); RegionTimer reg(t); static Timer tloop("MeshOptimize3d::SplitImprove loop"); double bad1, bad2, badmax, badlimit; int cnt = 0; int np = mesh.GetNP(); int ne = mesh.GetNE(); TABLE elementsonnode(np); Array hasbothpoints; BitArray origpoint(np+1), boundp(np+1); // big enough for 0 and 1-based origpoint.Set(); Array elerrs(ne); BitArray illegaltet(ne); illegaltet.Clear(); const char * savetask = multithread.task; multithread.task = "Split Improve"; PrintMessage (3, "SplitImprove"); (*testout) << "start SplitImprove" << "\n"; Array locfaces; INDEX_2_HASHTABLE edgetested (np); bad1 = 0; badmax = 0; for (ElementIndex ei = 0; ei < ne; ei++) { if(mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex()) continue; elerrs[ei] = CalcBad (mesh.Points(), mesh[ei], 0); bad1 += elerrs[ei]; if (elerrs[ei] > badmax) badmax = elerrs[ei]; } PrintMessage (5, "badmax = ", badmax); badlimit = 0.5 * badmax; boundp.Clear(); for (auto & el : mesh.SurfaceElements()) for (PointIndex pi : el.PNums()) boundp.Set (pi); if (goal == OPT_QUALITY) { bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); (*testout) << "Total badness = " << bad1 << endl; } for (ElementIndex ei : mesh.VolumeElements().Range()) for (PointIndex pi : mesh[ei].PNums()) elementsonnode.Add (pi, ei); mesh.MarkIllegalElements(); if (goal == OPT_QUALITY || goal == OPT_LEGAL) { int cntill = 0; for (ElementIndex ei = 0; ei < ne; ei++) { // if (!LegalTet (volelements.Get(i))) if (mesh[ei].flags.illegal) { cntill++; illegaltet.Set (ei); } } } tloop.Start(); for (ElementIndex ei : mesh.VolumeElements().Range()) { Element & elem = mesh[ei]; if(mp.only3D_domain_nr && mp.only3D_domain_nr != elem.GetIndex()) continue; if (multithread.terminate) break; multithread.percent = 100.0 * (ei+1) / ne; bool ltestmode = 0; if (elerrs[ei] < badlimit && !illegaltet.Test(ei)) continue; if ((goal == OPT_LEGAL) && !illegaltet.Test(ei) && CalcBad (mesh.Points(), elem, 0) < 1e3) continue; if (ltestmode) { (*testout) << "test el " << ei << endl; for (int j = 0; j < 4; j++) (*testout) << elem[j] << " "; (*testout) << endl; } for (int j = 0; j < 6; j++) { static const int tetedges[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; PointIndex pi1 = elem[tetedges[j][0]]; PointIndex pi2 = elem[tetedges[j][1]]; if (pi2 < pi1) Swap (pi1, pi2); if (pi2 >= elementsonnode.Size()+PointIndex::BASE) continue; // old number of points if (!origpoint.Test(pi1) || !origpoint.Test(pi2)) continue; INDEX_2 i2(pi1, pi2); i2.Sort(); if (mesh.BoundaryEdge (pi1, pi2)) continue; if (edgetested.Used (i2) && !illegaltet.Test(ei)) continue; edgetested.Set (i2, 1); hasbothpoints.SetSize (0); /* for (int k = 1; k <= elementsonnode.EntrySize(pi1); k++) { ElementIndex elnr = elementsonnode.Get(pi1, k); */ for (ElementIndex ei : elementsonnode[pi1]) { Element & el = mesh[ei]; bool has1 = el.PNums().Contains(pi1); bool has2 = el.PNums().Contains(pi2); if (has1 && has2) if (!hasbothpoints.Contains (ei)) hasbothpoints.Append (ei); } bad1 = 0; for (ElementIndex ei : hasbothpoints) bad1 += CalcBad (mesh.Points(), mesh[ei], 0); bool puretet = 1; for (ElementIndex ei : hasbothpoints) if (mesh[ei].GetType() != TET) puretet = 0; if (!puretet) continue; Point3d p1 = mesh[pi1]; Point3d p2 = mesh[pi2]; /* pnew = Center (p1, p2); points.Elem(pi1) = pnew; bad2 = 0; for (k = 1; k <= hasbothpoints.Size(); k++) bad2 += CalcBad (points, volelements.Get(hasbothpoints.Get(k)), 0); points.Elem(pi1) = p1; points.Elem(pi2) = pnew; for (k = 1; k <= hasbothpoints.Size(); k++) bad2 += CalcBad (points, volelements.Get(hasbothpoints.Get(k)), 0); points.Elem(pi2) = p2; */ locfaces.SetSize (0); for (ElementIndex ei : hasbothpoints) { const Element & el = mesh[ei]; for (int l = 0; l < 4; l++) if (el[l] == pi1 || el[l] == pi2) { INDEX_3 i3; Element2d face(TRIG); el.GetFace (l+1, face); for (int kk = 1; kk <= 3; kk++) i3.I(kk) = face.PNum(kk); locfaces.Append (i3); } } PointFunction1 pf (mesh.Points(), locfaces, mp, -1); OptiParameters par; par.maxit_linsearch = 50; par.maxit_bfgs = 20; Point3d pnew = Center (p1, p2); Vector px(3); px(0) = pnew.X(); px(1) = pnew.Y(); px(2) = pnew.Z(); if (elerrs[ei] > 0.1 * badmax) BFGS (px, pf, par); bad2 = pf.Func (px); pnew.X() = px(0); pnew.Y() = px(1); pnew.Z() = px(2); PointIndex hpinew = mesh.AddPoint (pnew); // ptyps.Append (INNERPOINT); for (int k = 0; k < hasbothpoints.Size(); k++) { Element & oldel = mesh[hasbothpoints[k]]; Element newel1 = oldel; Element newel2 = oldel; oldel.flags.illegal_valid = 0; newel1.flags.illegal_valid = 0; newel2.flags.illegal_valid = 0; for (int l = 0; l < 4; l++) { if (newel1[l] == pi2) newel1[l] = hpinew; if (newel2[l] == pi1) newel2[l] = hpinew; } if (!mesh.LegalTet (oldel)) bad1 += 1e6; if (!mesh.LegalTet (newel1)) bad2 += 1e6; if (!mesh.LegalTet (newel2)) bad2 += 1e6; } // mesh.PointTypes().DeleteLast(); mesh.Points().DeleteLast(); if (bad2 < bad1) /* (bad1 > 1e4 && boundp.Test(pi1) && boundp.Test(pi2)) */ { cnt++; PointIndex pinew = mesh.AddPoint (pnew); for (ElementIndex ei : hasbothpoints) { Element & oldel = mesh[ei]; Element newel = oldel; newel.flags.illegal_valid = 0; oldel.flags.illegal_valid = 0; for (int l = 0; l < 4; l++) { origpoint.Clear (oldel[l]); if (oldel[l] == pi2) oldel[l] = pinew; if (newel[l] == pi1) newel[l] = pinew; } mesh.AddVolumeElement (newel); } j = 10; // end j-loop } } } tloop.Stop(); mesh.Compress(); PrintMessage (5, cnt, " splits performed"); (*testout) << "Splitt - Improve done" << "\n"; if (goal == OPT_QUALITY) { bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); (*testout) << "Total badness = " << bad1 << endl; int cntill = 0; ne = mesh.GetNE(); for (ElementIndex ei = 0; ei < ne; ei++) if (!mesh.LegalTet (mesh[ei])) cntill++; // cout << cntill << " illegal tets" << endl; } multithread.task = savetask; } void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal, const BitArray * working_elements) { static Timer t("MeshOptimize3d::SwapImprove"); RegionTimer reg(t); static Timer tloop("MeshOptimize3d::SwapImprove loop"); PointIndex pi3(0), pi4(0), pi5(0), pi6(0); int cnt = 0; Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET); Element el1(TET), el2(TET), el3(TET), el4(TET); Element el1b(TET), el2b(TET), el3b(TET), el4b(TET); double bad1, bad2, bad3; int np = mesh.GetNP(); int ne = mesh.GetNE(); // contains at least all elements at node TABLE elementsonnode(np); Array hasbothpoints; PrintMessage (3, "SwapImprove "); (*testout) << "\n" << "Start SwapImprove" << endl; const char * savetask = multithread.task; multithread.task = "Swap Improve"; // mesh.CalcSurfacesOfNode (); INDEX_3_HASHTABLE faces(mesh.GetNOpenElements()/3 + 2); if (goal == OPT_CONFORM) { for (int i = 1; i <= mesh.GetNOpenElements(); i++) { const Element2d & hel = mesh.OpenElement(i); INDEX_3 face(hel[0], hel[1], hel[2]); face.Sort(); faces.Set (face, 1); } } // Calculate total badness if (goal == OPT_QUALITY) { bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); (*testout) << "Total badness = " << bad1 << endl; } // find elements on node for (ElementIndex ei = 0; ei < ne; ei++) for (PointIndex pi : mesh[ei].PNums()) elementsonnode.Add (pi, ei); /* for (int j = 0; j < mesh[ei].GetNP(); j++) elementsonnode.Add (mesh[ei][j], ei); */ // INDEX_2_HASHTABLE edgeused(2 * ne + 5); INDEX_2_CLOSED_HASHTABLE edgeused(12 * ne + 5); tloop.Start(); for (ElementIndex ei = 0; ei < ne; ei++) { if (multithread.terminate) break; if (mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex()) continue; multithread.percent = 100.0 * (ei+1) / ne; if ((mesh.ElementType(ei)) == FIXEDELEMENT) continue; if(working_elements && ei < working_elements->Size() && !working_elements->Test(ei)) continue; if (mesh[ei].IsDeleted()) continue; if ((goal == OPT_LEGAL) && mesh.LegalTet (mesh[ei]) && CalcBad (mesh.Points(), mesh[ei], 0) < 1e3) continue; // int onlybedges = 1; for (int j = 0; j < 6; j++) { // loop over edges const Element & elemi = mesh[ei]; if (elemi.IsDeleted()) continue; int mattyp = elemi.GetIndex(); static const int tetedges[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; PointIndex pi1 = elemi[tetedges[j][0]]; PointIndex pi2 = elemi[tetedges[j][1]]; if (pi2 < pi1) Swap (pi1, pi2); if (mesh.BoundaryEdge (pi1, pi2)) continue; INDEX_2 i2 (pi1, pi2); i2.Sort(); if (edgeused.Used(i2)) continue; edgeused.Set (i2, 1); hasbothpoints.SetSize (0); for (int k = 0; k < elementsonnode[pi1].Size(); k++) { bool has1 = 0, has2 = 0; ElementIndex elnr = elementsonnode[pi1][k]; const Element & elem = mesh[elnr]; if (elem.IsDeleted()) continue; for (int l = 0; l < elem.GetNP(); l++) { if (elem[l] == pi1) has1 = 1; if (elem[l] == pi2) has2 = 1; } if (has1 && has2) { // only once if (hasbothpoints.Contains (elnr)) has1 = false; if (has1) { hasbothpoints.Append (elnr); } } } bool puretet = true; for (ElementIndex ei : hasbothpoints) if (mesh[ei].GetType () != TET) puretet = false; if (!puretet) continue; int nsuround = hasbothpoints.Size(); if ( nsuround == 3 ) { Element & elem = mesh[hasbothpoints[0]]; for (int l = 0; l < 4; l++) if (elem[l] != pi1 && elem[l] != pi2) { pi4 = pi3; pi3 = elem[l]; } el31[0] = pi1; el31[1] = pi2; el31[2] = pi3; el31[3] = pi4; el31.SetIndex (mattyp); if (WrongOrientation (mesh.Points(), el31)) { Swap (pi3, pi4); el31[2] = pi3; el31[3] = pi4; } pi5 = 0; for (int k = 0; k < 3; k++) // JS, 201212 { const Element & elemk = mesh[hasbothpoints[k]]; bool has1 = false; for (int l = 0; l < 4; l++) if (elemk[l] == pi4) has1 = true; if (has1) { for (int l = 0; l < 4; l++) if (elemk[l] != pi1 && elemk[l] != pi2 && elemk[l] != pi4) pi5 = elemk[l]; } } if (!pi5.IsValid()) throw NgException("Illegal state observed in SwapImprove"); el32[0] = pi1; el32[1] = pi2; el32[2] = pi4; el32[3] = pi5; el32.SetIndex (mattyp); el33[0] = pi1; el33[1] = pi2; el33[2] = pi5; el33[3] = pi3; el33.SetIndex (mattyp); elementsonnode.Add (pi4, hasbothpoints[1]); elementsonnode.Add (pi3, hasbothpoints[2]); bad1 = CalcBad (mesh.Points(), el31, 0) + CalcBad (mesh.Points(), el32, 0) + CalcBad (mesh.Points(), el33, 0); el31.flags.illegal_valid = 0; el32.flags.illegal_valid = 0; el33.flags.illegal_valid = 0; if (!mesh.LegalTet(el31) || !mesh.LegalTet(el32) || !mesh.LegalTet(el33)) bad1 += 1e4; el21[0] = pi3; el21[1] = pi4; el21[2] = pi5; el21[3] = pi2; el21.SetIndex (mattyp); el22[0] = pi5; el22[1] = pi4; el22[2] = pi3; el22[3] = pi1; el22.SetIndex (mattyp); bad2 = CalcBad (mesh.Points(), el21, 0) + CalcBad (mesh.Points(), el22, 0); el21.flags.illegal_valid = 0; el22.flags.illegal_valid = 0; if (!mesh.LegalTet(el21) || !mesh.LegalTet(el22)) bad2 += 1e4; if (goal == OPT_CONFORM && bad2 < 1e4) { INDEX_3 face(pi3, pi4, pi5); face.Sort(); if (faces.Used(face)) { // (*testout) << "3->2 swap, could improve conformity, bad1 = " << bad1 // << ", bad2 = " << bad2 << endl; if (bad2 < 1e4) bad1 = 2 * bad2; } /* else { INDEX_2 hi1(pi3, pi4); hi1.Sort(); INDEX_2 hi2(pi3, pi5); hi2.Sort(); INDEX_2 hi3(pi4, pi5); hi3.Sort(); if (boundaryedges->Used (hi1) || boundaryedges->Used (hi2) || boundaryedges->Used (hi3) ) bad1 = 2 * bad2; } */ } if (bad2 < bad1) { // (*mycout) << "3->2 " << flush; // (*testout) << "3->2 conversion" << endl; cnt++; /* (*testout) << "3->2 swap, old els = " << endl << mesh[hasbothpoints[0]] << endl << mesh[hasbothpoints[1]] << endl << mesh[hasbothpoints[2]] << endl << "new els = " << endl << el21 << endl << el22 << endl; */ el21.flags.illegal_valid = 0; el22.flags.illegal_valid = 0; mesh[hasbothpoints[0]] = el21; mesh[hasbothpoints[1]] = el22; for (int l = 0; l < 4; l++) mesh[hasbothpoints[2]][l].Invalidate(); mesh[hasbothpoints[2]].Delete(); for (int k = 0; k < 2; k++) for (int l = 0; l < 4; l++) elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]); } } if (nsuround == 4) { const Element & elem1 = mesh[hasbothpoints[0]]; for (int l = 0; l < 4; l++) if (elem1[l] != pi1 && elem1[l] != pi2) { pi4 = pi3; pi3 = elem1[l]; } el1[0] = pi1; el1[1] = pi2; el1[2] = pi3; el1[3] = pi4; el1.SetIndex (mattyp); if (WrongOrientation (mesh.Points(), el1)) { Swap (pi3, pi4); el1[2] = pi3; el1[3] = pi4; } pi5.Invalidate(); for (int k = 0; k < 4; k++) { const Element & elem = mesh[hasbothpoints[k]]; bool has1 = elem.PNums().Contains(pi4); if (has1) { for (int l = 0; l < 4; l++) if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi4) pi5 = elem[l]; } } pi6.Invalidate(); for (int k = 0; k < 4; k++) { const Element & elem = mesh[hasbothpoints[k]]; bool has1 = elem.PNums().Contains(pi3); if (has1) { for (int l = 0; l < 4; l++) if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi3) pi6 = elem[l]; } } /* INDEX_2 i22(pi3, pi5); i22.Sort(); INDEX_2 i23(pi4, pi6); i23.Sort(); */ el1[0] = pi1; el1[1] = pi2; el1[2] = pi3; el1[3] = pi4; el1.SetIndex (mattyp); el2[0] = pi1; el2[1] = pi2; el2[2] = pi4; el2[3] = pi5; el2.SetIndex (mattyp); el3[0] = pi1; el3[1] = pi2; el3[2] = pi5; el3[3] = pi6; el3.SetIndex (mattyp); el4[0] = pi1; el4[1] = pi2; el4[2] = pi6; el4[3] = pi3; el4.SetIndex (mattyp); // elementsonnode.Add (pi4, hasbothpoints.Elem(2)); // elementsonnode.Add (pi3, hasbothpoints.Elem(3)); bad1 = CalcBad (mesh.Points(), el1, 0) + CalcBad (mesh.Points(), el2, 0) + CalcBad (mesh.Points(), el3, 0) + CalcBad (mesh.Points(), el4, 0); el1.flags.illegal_valid = 0; el2.flags.illegal_valid = 0; el3.flags.illegal_valid = 0; el4.flags.illegal_valid = 0; if (goal != OPT_CONFORM) { if (!mesh.LegalTet(el1) || !mesh.LegalTet(el2) || !mesh.LegalTet(el3) || !mesh.LegalTet(el4)) bad1 += 1e4; } el1[0] = pi3; el1[1] = pi5; el1[2] = pi2; el1[3] = pi4; el1.SetIndex (mattyp); el2[0] = pi3; el2[1] = pi5; el2[2] = pi4; el2[3] = pi1; el2.SetIndex (mattyp); el3[0] = pi3; el3[1] = pi5; el3[2] = pi1; el3[3] = pi6; el3.SetIndex (mattyp); el4[0] = pi3; el4[1] = pi5; el4[2] = pi6; el4[3] = pi2; el4.SetIndex (mattyp); bad2 = CalcBad (mesh.Points(), el1, 0) + CalcBad (mesh.Points(), el2, 0) + CalcBad (mesh.Points(), el3, 0) + CalcBad (mesh.Points(), el4, 0); el1.flags.illegal_valid = 0; el2.flags.illegal_valid = 0; el3.flags.illegal_valid = 0; el4.flags.illegal_valid = 0; if (goal != OPT_CONFORM) { if (!mesh.LegalTet(el1) || !mesh.LegalTet(el2) || !mesh.LegalTet(el3) || !mesh.LegalTet(el4)) bad2 += 1e4; } el1b[0] = pi4; el1b[1] = pi6; el1b[2] = pi3; el1b[3] = pi2; el1b.SetIndex (mattyp); el2b[0] = pi4; el2b[1] = pi6; el2b[2] = pi2; el2b[3] = pi5; el2b.SetIndex (mattyp); el3b[0] = pi4; el3b[1] = pi6; el3b[2] = pi5; el3b[3] = pi1; el3b.SetIndex (mattyp); el4b[0] = pi4; el4b[1] = pi6; el4b[2] = pi1; el4b[3] = pi3; el4b.SetIndex (mattyp); bad3 = CalcBad (mesh.Points(), el1b, 0) + CalcBad (mesh.Points(), el2b, 0) + CalcBad (mesh.Points(), el3b, 0) + CalcBad (mesh.Points(), el4b, 0); el1b.flags.illegal_valid = 0; el2b.flags.illegal_valid = 0; el3b.flags.illegal_valid = 0; el4b.flags.illegal_valid = 0; if (goal != OPT_CONFORM) { if (!mesh.LegalTet(el1b) || !mesh.LegalTet(el2b) || !mesh.LegalTet(el3b) || !mesh.LegalTet(el4b)) bad3 += 1e4; } /* int swap2 = (bad2 < bad1) && (bad2 < bad3); int swap3 = !swap2 && (bad3 < bad1); if ( ((bad2 < 10 * bad1) || (bad2 < 1e6)) && mesh.BoundaryEdge (pi3, pi5)) swap2 = 1; else if ( ((bad3 < 10 * bad1) || (bad3 < 1e6)) && mesh.BoundaryEdge (pi4, pi6)) { swap3 = 1; swap2 = 0; } */ bool swap2, swap3; if (goal != OPT_CONFORM) { swap2 = (bad2 < bad1) && (bad2 < bad3); swap3 = !swap2 && (bad3 < bad1); } else { if (mesh.BoundaryEdge (pi3, pi5)) bad2 /= 1e6; if (mesh.BoundaryEdge (pi4, pi6)) bad3 /= 1e6; swap2 = (bad2 < bad1) && (bad2 < bad3); swap3 = !swap2 && (bad3 < bad1); } if (swap2 || swap3) { // (*mycout) << "4->4 " << flush; cnt++; // (*testout) << "4->4 conversion" << "\n"; /* (*testout) << "bad1 = " << bad1 << " bad2 = " << bad2 << " bad3 = " << bad3 << "\n"; (*testout) << "Points: " << pi1 << " " << pi2 << " " << pi3 << " " << pi4 << " " << pi5 << " " << pi6 << "\n"; (*testout) << "Elements: " << hasbothpoints.Get(1) << " " << hasbothpoints.Get(2) << " " << hasbothpoints.Get(3) << " " << hasbothpoints.Get(4) << " " << "\n"; */ /* { int i1, j1; for (i1 = 1; i1 <= 4; i1++) { for (j1 = 1; j1 <= 4; j1++) (*testout) << volelements.Get(hasbothpoints.Get(i1)).PNum(j1) << " "; (*testout) << "\n"; } } */ } if (swap2) { // (*mycout) << "bad1 = " << bad1 << " bad2 = " << bad2 << "\n"; /* (*testout) << "4->4 swap A, old els = " << endl << mesh[hasbothpoints[0]] << endl << mesh[hasbothpoints[1]] << endl << mesh[hasbothpoints[2]] << endl << mesh[hasbothpoints[3]] << endl << "new els = " << endl << el1 << endl << el2 << endl << el3 << endl << el4 << endl; */ el1.flags.illegal_valid = 0; el2.flags.illegal_valid = 0; el3.flags.illegal_valid = 0; el4.flags.illegal_valid = 0; mesh[hasbothpoints[0]] = el1; mesh[hasbothpoints[1]] = el2; mesh[hasbothpoints[2]] = el3; mesh[hasbothpoints[3]] = el4; for (int k = 0; k < 4; k++) for (int l = 0; l < 4; l++) elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]); } else if (swap3) { // (*mycout) << "bad1 = " << bad1 << " bad3 = " << bad3 << "\n"; el1b.flags.illegal_valid = 0; el2b.flags.illegal_valid = 0; el3b.flags.illegal_valid = 0; el4b.flags.illegal_valid = 0; /* (*testout) << "4->4 swap A, old els = " << endl << mesh[hasbothpoints[0]] << endl << mesh[hasbothpoints[1]] << endl << mesh[hasbothpoints[2]] << endl << mesh[hasbothpoints[3]] << endl << "new els = " << endl << el1b << endl << el2b << endl << el3b << endl << el4b << endl; */ mesh[hasbothpoints[0]] = el1b; mesh[hasbothpoints[1]] = el2b; mesh[hasbothpoints[2]] = el3b; mesh[hasbothpoints[3]] = el4b; for (int k = 0; k < 4; k++) for (int l = 0; l < 4; l++) elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]); } } if (nsuround >= 5) { Element hel(TET); ArrayMem suroundpts(nsuround); ArrayMem tetused(nsuround); Element & elem = mesh[hasbothpoints[0]]; for (int l = 0; l < 4; l++) if (elem[l] != pi1 && elem[l] != pi2) { pi4 = pi3; pi3 = elem[l]; } hel[0] = pi1; hel[1] = pi2; hel[2] = pi3; hel[3] = pi4; hel.SetIndex (mattyp); if (WrongOrientation (mesh.Points(), hel)) { Swap (pi3, pi4); hel[2] = pi3; hel[3] = pi4; } // suroundpts.SetSize (nsuround); suroundpts = -17; suroundpts[0] = pi3; suroundpts[1] = pi4; tetused = false; tetused[0] = true; for (int l = 2; l < nsuround; l++) { PointIndex oldpi = suroundpts[l-1]; PointIndex newpi; newpi.Invalidate(); for (int k = 0; k < nsuround && !newpi.IsValid(); k++) if (!tetused[k]) { const Element & nel = mesh[hasbothpoints[k]]; for (int k2 = 0; k2 < 4 && !newpi.IsValid(); k2++) if (nel[k2] == oldpi) { newpi = nel[0] + nel[1] + nel[2] + nel[3] - pi1 - pi2 - oldpi; tetused[k] = true; suroundpts[l] = newpi; } } } bad1 = 0; for (int k = 0; k < nsuround; k++) { hel[0] = pi1; hel[1] = pi2; hel[2] = suroundpts[k]; hel[3] = suroundpts[(k+1) % nsuround]; hel.SetIndex (mattyp); bad1 += CalcBad (mesh.Points(), hel, 0); } // (*testout) << "nsuround = " << nsuround << " bad1 = " << bad1 << endl; int bestl = -1; int confface = -1; int confedge = -1; double badopt = bad1; for (int l = 0; l < nsuround; l++) { bad2 = 0; for (int k = l+1; k <= nsuround + l - 2; k++) { hel[0] = suroundpts[l]; hel[1] = suroundpts[k % nsuround]; hel[2] = suroundpts[(k+1) % nsuround]; hel[3] = pi2; bad2 += CalcBad (mesh.Points(), hel, 0); hel.flags.illegal_valid = 0; if (!mesh.LegalTet(hel)) bad2 += 1e4; hel[2] = suroundpts[k % nsuround]; hel[1] = suroundpts[(k+1) % nsuround]; hel[3] = pi1; bad2 += CalcBad (mesh.Points(), hel, 0); hel.flags.illegal_valid = 0; if (!mesh.LegalTet(hel)) bad2 += 1e4; } // (*testout) << "bad2," << l << " = " << bad2 << endl; if ( bad2 < badopt ) { bestl = l; badopt = bad2; } if (goal == OPT_CONFORM) // (bad2 <= 100 * bad1 || bad2 <= 1e6)) { bool nottoobad = (bad2 <= bad1) || (bad2 <= 100 * bad1 && bad2 <= 1e18) || (bad2 <= 1e8); for (int k = l+1; k <= nsuround + l - 2; k++) { INDEX_3 hi3(suroundpts[l], suroundpts[k % nsuround], suroundpts[(k+1) % nsuround]); hi3.Sort(); if (faces.Used(hi3)) { // (*testout) << "could improve face conformity, bad1 = " << bad1 // << ", bad 2 = " << bad2 << ", nottoobad = " << nottoobad << endl; if (nottoobad) confface = l; } } for (int k = l+2; k <= nsuround+l-2; k++) { if (mesh.BoundaryEdge (suroundpts[l], suroundpts[k % nsuround])) { /* *testout << "could improve edge conformity, bad1 = " << bad1 << ", bad 2 = " << bad2 << ", nottoobad = " << nottoobad << endl; */ if (nottoobad) confedge = l; } } } } if (confedge != -1) bestl = confedge; if (confface != -1) bestl = confface; if (bestl != -1) { // (*mycout) << nsuround << "->" << 2 * (nsuround-2) << " " << flush; cnt++; for (int k = bestl+1; k <= nsuround + bestl - 2; k++) { int k1; hel[0] = suroundpts[bestl]; hel[1] = suroundpts[k % nsuround]; hel[2] = suroundpts[(k+1) % nsuround]; hel[3] = pi2; hel.flags.illegal_valid = 0; /* (*testout) << nsuround << "-swap, new el,top = " << hel << endl; */ mesh.AddVolumeElement (hel); for (k1 = 0; k1 < 4; k1++) elementsonnode.Add (hel[k1], mesh.GetNE()-1); hel[2] = suroundpts[k % nsuround]; hel[1] = suroundpts[(k+1) % nsuround]; hel[3] = pi1; /* (*testout) << nsuround << "-swap, new el,bot = " << hel << endl; */ mesh.AddVolumeElement (hel); for (k1 = 0; k1 < 4; k1++) elementsonnode.Add (hel[k1], mesh.GetNE()-1); } for (int k = 0; k < nsuround; k++) { Element & rel = mesh[hasbothpoints[k]]; /* (*testout) << nsuround << "-swap, old el = " << rel << endl; */ rel.Delete(); for (int k1 = 0; k1 < 4; k1++) rel[k1].Invalidate(); } } } } /* if (onlybedges) { (*testout) << "bad tet: " << volelements.Get(i)[0] << volelements.Get(i)[1] << volelements.Get(i)[2] << volelements.Get(i)[3] << "\n"; if (!mesh.LegalTet (volelements.Get(i))) cerr << "Illegal tet" << "\n"; } */ } // (*mycout) << endl; tloop.Stop(); /* cout << "edgeused: "; edgeused.PrintMemInfo(cout); */ PrintMessage (5, cnt, " swaps performed"); mesh.Compress (); /* if (goal == OPT_QUALITY) { bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); // (*testout) << "Total badness = " << bad1 << endl; } */ /* for (i = 1; i <= GetNE(); i++) if (volelements.Get(i)[0]) if (!mesh.LegalTet (volelements.Get(i))) { cout << "detected illegal tet, 2" << endl; (*testout) << "detected illegal tet1: " << i << endl; } */ multithread.task = savetask; } void MeshOptimize3d :: SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal, const BitArray * working_elements, const Array< Array* > * idmaps) { Array< Array* > locidmaps; const Array< Array* > * used_idmaps; if(idmaps) used_idmaps = idmaps; else { used_idmaps = &locidmaps; for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) { if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) { locidmaps.Append(new Array); mesh.GetIdentifications().GetMap(i,*locidmaps.Last(),true); } } } PointIndex pi1, pi2, pi3, pi4, pi5, pi6; PointIndex pi1other, pi2other; int cnt = 0; //double bad1, bad2, bad3, sbad; double bad1, sbad; double h; int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int mattype, othermattype; // contains at least all elements at node TABLE elementsonnode(np); TABLE surfaceelementsonnode(np); TABLE surfaceindicesonnode(np); Array hasbothpoints; Array hasbothpointsother; PrintMessage (3, "SwapImproveSurface "); (*testout) << "\n" << "Start SwapImproveSurface" << endl; const char * savetask = multithread.task; multithread.task = "Swap Improve Surface"; // find elements on node for (ElementIndex ei = 0; ei < ne; ei++) for (int j = 0; j < mesh[ei].GetNP(); j++) elementsonnode.Add (mesh[ei][j], ei); for (SurfaceElementIndex sei = 0; sei < nse; sei++) for(int j=0; j edgeused(2 * ne + 5); INDEX_2_CLOSED_HASHTABLE edgeused(12 * ne + 5); for (ElementIndex ei = 0; ei < ne; ei++) { if (multithread.terminate) break; multithread.percent = 100.0 * (ei+1) / ne; if (mesh.ElementType(ei) == FIXEDELEMENT) continue; if(working_elements && ei < working_elements->Size() && !working_elements->Test(ei)) continue; if (mesh[ei].IsDeleted()) continue; if ((goal == OPT_LEGAL) && mesh.LegalTet (mesh[ei]) && CalcBad (mesh.Points(), mesh[ei], 0) < 1e3) continue; const Element & elemi = mesh[ei]; //Element elemi = mesh[ei]; if (elemi.IsDeleted()) continue; mattype = elemi.GetIndex(); bool swapped = false; for (int j = 0; !swapped && j < 6; j++) { // loop over edges static const int tetedges[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; pi1 = elemi[tetedges[j][0]]; pi2 = elemi[tetedges[j][1]]; if (pi2 < pi1) Swap (pi1, pi2); bool found = false; for(int k=0; !found && kSize(); k++) { if(pi2 < (*used_idmaps)[k]->Size() + PointIndex::BASE) { pi1other = (*(*used_idmaps)[k])[pi1]; pi2other = (*(*used_idmaps)[k])[pi2]; found = (pi1other != 0 && pi2other != 0 && pi1other != pi1 && pi2other != pi2); if(found) idnum = k; } } if(found) periodic = true; else { periodic = false; pi1other = pi1; pi2other = pi2; } if (!mesh.BoundaryEdge (pi1, pi2) || mesh.IsSegment(pi1, pi2)) continue; othermattype = -1; INDEX_2 i2 (pi1, pi2); i2.Sort(); if (edgeused.Used(i2)) continue; edgeused.Set (i2, 1); if(periodic) { i2.I1() = pi1other; i2.I2() = pi2other; i2.Sort(); edgeused.Set(i2,1); } hasbothpoints.SetSize (0); hasbothpointsother.SetSize (0); for (int k = 0; k < elementsonnode[pi1].Size(); k++) { bool has1 = false, has2 = false; ElementIndex elnr = elementsonnode[pi1][k]; const Element & elem = mesh[elnr]; if (elem.IsDeleted()) continue; for (int l = 0; l < elem.GetNP(); l++) { if (elem[l] == pi1) has1 = true; if (elem[l] == pi2) has2 = true; } if (has1 && has2) { if(othermattype == -1 && elem.GetIndex() != mattype) othermattype = elem.GetIndex(); if(elem.GetIndex() == mattype) { // only once for (int l = 0; l < hasbothpoints.Size(); l++) if (hasbothpoints[l] == elnr) has1 = 0; if (has1) hasbothpoints.Append (elnr); } else if(elem.GetIndex() == othermattype) { // only once for (int l = 0; l < hasbothpointsother.Size(); l++) if (hasbothpointsother[l] == elnr) has1 = 0; if (has1) hasbothpointsother.Append (elnr); } else { cout << "problem with domain indices" << endl; (*testout) << "problem: mattype = " << mattype << ", othermattype = " << othermattype << " elem " << elem << " mt " << elem.GetIndex() << endl << " pi1 " << pi1 << " pi2 " << pi2 << endl; (*testout) << "hasbothpoints:" << endl; for(int ii=0; ii < hasbothpoints.Size(); ii++) (*testout) << mesh[hasbothpoints[ii]] << endl; (*testout) << "hasbothpointsother:" << endl; for(int ii=0; ii < hasbothpointsother.Size(); ii++) (*testout) << mesh[hasbothpointsother[ii]] << endl; } } } if(hasbothpointsother.Size() > 0 && periodic) throw NgException("SwapImproveSurface: Assumption about interface/periodicity wrong!"); if(periodic) { for (int k = 0; k < elementsonnode[pi1other].Size(); k++) { bool has1 = false, has2 = false; ElementIndex elnr = elementsonnode[pi1other][k]; const Element & elem = mesh[elnr]; if (elem.IsDeleted()) continue; for (int l = 0; l < elem.GetNP(); l++) { if (elem[l] == pi1other) has1 = true; if (elem[l] == pi2other) has2 = true; } if (has1 && has2) { if(othermattype == -1) othermattype = elem.GetIndex(); // only once for (int l = 0; l < hasbothpointsother.Size(); l++) if (hasbothpointsother[l] == elnr) has1 = 0; if (has1) hasbothpointsother.Append (elnr); } } } //for(k=0; k v1 = mesh[sp1]-mesh[pi1], v2 = mesh[sp2]-mesh[pi1], v3 = mesh[sp1]-mesh[pi2], v4 = mesh[sp2]-mesh[pi2]; double vol = 0.5*(Cross(v1,v2).Length() + Cross(v3,v4).Length()); h = sqrt(vol); h = 0; sbad = CalcTriangleBadness (mesh[pi1],mesh[pi2],mesh[sp1],0,0) + CalcTriangleBadness (mesh[pi2],mesh[pi1],mesh[sp2],0,0); bool puretet = true; for (int k = 0; puretet && k < hasbothpoints.Size(); k++) if (mesh[hasbothpoints[k]].GetType () != TET) puretet = false; for (int k = 0; puretet && k < hasbothpointsother.Size(); k++) if (mesh[hasbothpointsother[k]].GetType () != TET) puretet = false; if (!puretet) continue; int nsuround = hasbothpoints.Size(); int nsuroundother = hasbothpointsother.Size(); Array < int > outerpoints(nsuround+1); outerpoints[0] = sp1; for(int i=0; i 0) (*testout) << mesh[hasbothpoints[ii]][jj] << " between " << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and " << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl; } (*testout) << "outerpoints: " << outerpoints << endl; (*testout) << "sel1 " << mesh[sel1] << endl << "sel2 " << mesh[sel2] << endl; for(int ii=0; ii<3; ii++) { if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0) (*testout) << mesh[sel1][ii] << " between " << mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and " << mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl; if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0) (*testout) << mesh[sel2][ii] << " between " << mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and " << mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl; } } Array < int > outerpointsother; if(nsuroundother > 0) { outerpointsother.SetSize(nsuroundother+1); outerpointsother[0] = sp2other; } for(int i=0; i 0 && outerpointsother[nsuroundother] != sp1other) { cerr << "OJE OJE OJE (other)" << endl; (*testout) << "OJE OJE OJE (other)" << endl; (*testout) << "pi1 " << pi1 << " pi2 " << pi2 << " sp1 " << sp1 << " sp2 " << sp2 << endl; (*testout) << "hasbothpoints: " << endl; for(int ii=0; ii < hasbothpoints.Size(); ii++) { (*testout) << mesh[hasbothpoints[ii]] << endl; for(int jj=0; jj 0) (*testout) << mesh[hasbothpoints[ii]][jj] << " between " << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and " << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl; } (*testout) << "outerpoints: " << outerpoints << endl; (*testout) << "sel1 " << mesh[sel1] << endl << "sel2 " << mesh[sel2] << endl; for(int ii=0; ii<3; ii++) { if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0) (*testout) << mesh[sel1][ii] << " between " << mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and " << mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl; if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0) (*testout) << mesh[sel2][ii] << " between " << mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and " << mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl; } (*testout) << "pi1other " << pi1other << " pi2other " << pi2other << " sp1other " << sp1other << " sp2other " << sp2other << endl; (*testout) << "hasbothpointsother: " << endl; for(int ii=0; ii < hasbothpointsother.Size(); ii++) { (*testout) << mesh[hasbothpointsother[ii]] << endl; for(int jj=0; jj 0) (*testout) << mesh[hasbothpointsother[ii]][jj] << " between " << mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] << " and " << mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][1] << endl; } (*testout) << "outerpoints: " << outerpointsother << endl; (*testout) << "sel1other " << mesh[sel1other] << endl << "sel2other " << mesh[sel2other] << endl; for(int ii=0; ii<3; ii++) { if(mesh.mlbetweennodes[mesh[sel1other][ii]][0] > 0) (*testout) << mesh[sel1other][ii] << " between " << mesh.mlbetweennodes[mesh[sel1other][ii]][0] << " and " << mesh.mlbetweennodes[mesh[sel1other][ii]][1] << endl; if(mesh.mlbetweennodes[mesh[sel2other][ii]][0] > 0) (*testout) << mesh[sel2other][ii] << " between " << mesh.mlbetweennodes[mesh[sel2other][ii]][0] << " and " << mesh.mlbetweennodes[mesh[sel2other][ii]][1] << endl; } } bad1=0; for(int i=0; i * > newelts(startpoints); Array < Array < Element* > * > neweltsother(startpointsother); double minbad = 1e50, minbadother = 1e50, currbad; int minpos = -1, minposother = -1; //(*testout) << "pi1 " << pi1 << " pi2 " << pi2 << " outerpoints " << outerpoints << endl; for(int i=0; i(2*(nsuround-1)); for(int jj=0; jjSize(); jj++) wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*newelts[i])[jj]); currbad = 0; for(int jj=0; jjSize(); jj++) { if(wrongorientation) Swap((*(*newelts[i])[jj])[2],(*(*newelts[i])[jj])[3]); // not two new faces on same surface Array face_index; for(int k = 0; kSize()); if(currbad < minbad) { minbad = currbad; minpos = i; } } if(startpointsother == 0) minbadother = 0; for(int i=0; i(2*(nsuroundother)); for(int jj=0; jjSize(); jj++) wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*neweltsother[i])[jj]); currbad = 0; for(int jj=0; jjSize(); jj++) { if(wrongorientation) Swap((*(*neweltsother[i])[jj])[2],(*(*neweltsother[i])[jj])[3]); currbad += CalcBad(mesh.Points(),*(*neweltsother[i])[jj],h); } //currbad /= double(neweltsother[i]->Size()); if(currbad < minbadother) { minbadother = currbad; minposother = i; } } //(*testout) << "minbad " << minbad << " bad1 " << bad1 << endl; double sbadnew = CalcTriangleBadness (mesh[pi1],mesh[sp2],mesh[sp1],0,0) + CalcTriangleBadness (mesh[pi2],mesh[sp1],mesh[sp2],0,0); int denom = newelts[minpos]->Size(); if(minposother >= 0) denom += neweltsother[minposother]->Size(); if((minbad+minbadother)/double(denom) < bad1 && sbadnew < sbad) { cnt++; swapped = true; int start1 = -1; for(int l=0; l<3; l++) if(mesh[sel1][l] == pi1) start1 = l; if(mesh[sel1][(start1+1)%3] == pi2) { mesh[sel1][0] = pi1; mesh[sel1][1] = sp2; mesh[sel1][2] = sp1; mesh[sel2][0] = pi2; mesh[sel2][1] = sp1; mesh[sel2][2] = sp2; } else { mesh[sel1][0] = pi2; mesh[sel1][1] = sp2; mesh[sel1][2] = sp1; mesh[sel2][0] = pi1; mesh[sel2][1] = sp1; mesh[sel2][2] = sp2; } //(*testout) << "changed surface element " << sel1 << " to " << mesh[sel1] << ", " << sel2 << " to " << mesh[sel2] << endl; for(int l=0; l<3; l++) { surfaceelementsonnode.Add(mesh[sel1][l],sel1); surfaceelementsonnode.Add(mesh[sel2][l],sel2); } if(periodic) { start1 = -1; for(int l=0; l<3; l++) if(mesh[sel1other][l] == pi1other) start1 = l; //(*testout) << "changed surface elements " << mesh[sel1other] << " and " << mesh[sel2other] << endl; if(mesh[sel1other][(start1+1)%3] == pi2other) { mesh[sel1other][0] = pi1other; mesh[sel1other][1] = sp2other; mesh[sel1other][2] = sp1other; mesh[sel2other][0] = pi2other; mesh[sel2other][1] = sp1other; mesh[sel2other][2] = sp2other; //(*testout) << " with rule 1" << endl; } else { mesh[sel1other][0] = pi2other; mesh[sel1other][1] = sp2other; mesh[sel1other][2] = sp1other; mesh[sel2other][0] = pi1other; mesh[sel2other][1] = sp1other; mesh[sel2other][2] = sp2other; //(*testout) << " with rule 2" << endl; } //(*testout) << " to " << mesh[sel1other] << " and " << mesh[sel2other] << endl; //(*testout) << " and surface element " << sel1other << " to " << mesh[sel1other] << ", " << sel2other << " to " << mesh[sel2other] << endl; for(int l=0; l<3; l++) { surfaceelementsonnode.Add(mesh[sel1other][l],sel1other); surfaceelementsonnode.Add(mesh[sel2other][l],sel2other); } } for(int i=0; i 0) { for(int i=0; iSize(); jj++) delete (*newelts[i])[jj]; delete newelts[i]; } for(int i=0; iSize(); jj++) delete (*neweltsother[i])[jj]; delete neweltsother[i]; } } } PrintMessage (5, cnt, " swaps performed"); for(int i=0; i 3 conversion */ void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal) { static Timer t("MeshOptimize3d::SwapImprove2"); RegionTimer reg(t); PointIndex pi1(0), pi2(0), pi3(0), pi4(0), pi5(0); Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET); int cnt = 0; double bad1, bad2; int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); if (goal == OPT_CONFORM) return; // contains at least all elements at node TABLE elementsonnode(np); TABLE belementsonnode(np); PrintMessage (3, "SwapImprove2 "); (*testout) << "\n" << "Start SwapImprove2" << "\n"; // TestOk(); /* CalcSurfacesOfNode (); for (i = 1; i <= GetNE(); i++) if (volelements.Get(i)[0]) if (!mesh.LegalTet (volelements.Get(i))) { cout << "detected illegal tet, 1" << endl; (*testout) << "detected illegal tet1: " << i << endl; } */ // Calculate total badness bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); (*testout) << "Total badness = " << bad1 << endl; // cout << "tot bad = " << bad1 << endl; // find elements on node for (ElementIndex ei = 0; ei < ne; ei++) for (int j = 0; j < mesh[ei].GetNP(); j++) elementsonnode.Add (mesh[ei][j], ei); for (SurfaceElementIndex sei = 0; sei < nse; sei++) for (int j = 0; j < 3; j++) belementsonnode.Add (mesh[sei][j], sei); for (ElementIndex eli1 = 0; eli1 < ne; eli1++) { if (multithread.terminate) break; if (mesh.ElementType (eli1) == FIXEDELEMENT) continue; if (mesh[eli1].GetType() != TET) continue; if ((goal == OPT_LEGAL) && mesh.LegalTet (mesh[eli1]) && CalcBad (mesh.Points(), mesh[eli1], 0) < 1e3) continue; if(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(eli1).GetIndex()) continue; // cout << "eli = " << eli1 << endl; // (*testout) << "swapimp2, eli = " << eli1 << "; el = " << mesh[eli1] << endl; for (int j = 0; j < 4; j++) { // loop over faces Element & elem = mesh[eli1]; // if (elem[0] < PointIndex::BASE) continue; if (elem.IsDeleted()) continue; int mattyp = elem.GetIndex(); switch (j) { case 0: pi1 = elem.PNum(1); pi2 = elem.PNum(2); pi3 = elem.PNum(3); pi4 = elem.PNum(4); break; case 1: pi1 = elem.PNum(1); pi2 = elem.PNum(4); pi3 = elem.PNum(2); pi4 = elem.PNum(3); break; case 2: pi1 = elem.PNum(1); pi2 = elem.PNum(3); pi3 = elem.PNum(4); pi4 = elem.PNum(2); break; case 3: pi1 = elem.PNum(2); pi2 = elem.PNum(4); pi3 = elem.PNum(3); pi4 = elem.PNum(1); break; } bool bface = 0; for (int k = 0; k < belementsonnode[pi1].Size(); k++) { const Element2d & bel = mesh[belementsonnode[pi1][k]]; bool bface1 = 1; for (int l = 0; l < 3; l++) if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3) { bface1 = 0; break; } if (bface1) { bface = 1; break; } } if (bface) continue; FlatArray row = elementsonnode[pi1]; for (int k = 0; k < row.Size(); k++) { ElementIndex eli2 = row[k]; // cout << "\rei1 = " << eli1 << ", pi1 = " << pi1 << ", k = " << k << ", ei2 = " << eli2 // << ", getne = " << mesh.GetNE(); if ( eli1 != eli2 ) { Element & elem2 = mesh[eli2]; if (elem2.IsDeleted()) continue; if (elem2.GetType() != TET) continue; int comnodes=0; for (int l = 1; l <= 4; l++) if (elem2.PNum(l) == pi1 || elem2.PNum(l) == pi2 || elem2.PNum(l) == pi3) { comnodes++; } else { pi5 = elem2.PNum(l); } if (comnodes == 3) { bad1 = CalcBad (mesh.Points(), elem, 0) + CalcBad (mesh.Points(), elem2, 0); if (!mesh.LegalTet(elem) || !mesh.LegalTet(elem2)) bad1 += 1e4; el31.PNum(1) = pi1; el31.PNum(2) = pi2; el31.PNum(3) = pi5; el31.PNum(4) = pi4; el31.SetIndex (mattyp); el32.PNum(1) = pi2; el32.PNum(2) = pi3; el32.PNum(3) = pi5; el32.PNum(4) = pi4; el32.SetIndex (mattyp); el33.PNum(1) = pi3; el33.PNum(2) = pi1; el33.PNum(3) = pi5; el33.PNum(4) = pi4; el33.SetIndex (mattyp); bad2 = CalcBad (mesh.Points(), el31, 0) + CalcBad (mesh.Points(), el32, 0) + CalcBad (mesh.Points(), el33, 0); el31.flags.illegal_valid = 0; el32.flags.illegal_valid = 0; el33.flags.illegal_valid = 0; if (!mesh.LegalTet(el31) || !mesh.LegalTet(el32) || !mesh.LegalTet(el33)) bad2 += 1e4; bool do_swap = (bad2 < bad1); if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) && mesh.BoundaryEdge (pi4, pi5)) do_swap = 1; if (do_swap) { // cout << "do swap, eli1 = " << eli1 << "; eli2 = " << eli2 << endl; // (*mycout) << "2->3 " << flush; cnt++; el31.flags.illegal_valid = 0; el32.flags.illegal_valid = 0; el33.flags.illegal_valid = 0; mesh[eli1] = el31; mesh[eli2] = el32; ElementIndex neli = mesh.AddVolumeElement (el33); /* if (!LegalTet(el31) || !LegalTet(el32) || !LegalTet(el33)) { cout << "Swap to illegal tets !!!" << endl; } */ // cout << "neli = " << neli << endl; for (int l = 0; l < 4; l++) { elementsonnode.Add (el31[l], eli1); elementsonnode.Add (el32[l], eli2); elementsonnode.Add (el33[l], neli); } break; } } } } } } PrintMessage (5, cnt, " swaps performed"); /* CalcSurfacesOfNode (); for (i = 1; i <= GetNE(); i++) if (volelements.Get(i).PNum(1)) if (!LegalTet (volelements.Get(i))) { cout << "detected illegal tet, 2" << endl; (*testout) << "detected illegal tet2: " << i << endl; } */ bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); (*testout) << "Total badness = " << bad1 << endl; (*testout) << "swapimprove2 done" << "\n"; // (*mycout) << "Vol = " << CalcVolume (points, volelements) << "\n"; } /* void Mesh :: SwapImprove2 (OPTIMIZEGOAL goal) { int i, j; int eli1, eli2; int mattyp; Element el31(4), el32(4), el33(4); double bad1, bad2; INDEX_3_HASHTABLE elsonface (GetNE()); (*mycout) << "SwapImprove2 " << endl; (*testout) << "\n" << "Start SwapImprove2" << "\n"; // Calculate total badness if (goal == OPT_QUALITY) { double bad1 = CalcTotalBad (points, volelements); (*testout) << "Total badness = " << bad1 << endl; } // find elements on node Element2d face; for (i = 1; i <= GetNE(); i++) if ( (i > eltyps.Size()) || (eltyps.Get(i) != FIXEDELEMENT) ) { const Element & el = VolumeElement(i); if (!el.PNum(1)) continue; for (j = 1; j <= 4; j++) { el.GetFace (j, face); INDEX_3 i3 (face.PNum(1), face.PNum(2), face.PNum(3)); i3.Sort(); int bnr, posnr; if (!elsonface.PositionCreate (i3, bnr, posnr)) { INDEX_2 i2; elsonface.GetData (bnr, posnr, i3, i2); i2.I2() = i; elsonface.SetData (bnr, posnr, i3, i2); } else { INDEX_2 i2 (i, 0); elsonface.SetData (bnr, posnr, i3, i2); } // if (elsonface.Used (i3)) // { // INDEX_2 i2 = elsonface.Get(i3); // i2.I2() = i; // elsonface.Set (i3, i2); // } // else // { // INDEX_2 i2 (i, 0); // elsonface.Set (i3, i2); // } } } BitArray original(GetNE()); original.Set(); for (i = 1; i <= GetNSE(); i++) { const Element2d & sface = SurfaceElement(i); INDEX_3 i3 (sface.PNum(1), sface.PNum(2), sface.PNum(3)); i3.Sort(); INDEX_2 i2(0,0); elsonface.Set (i3, i2); } for (i = 1; i <= elsonface.GetNBags(); i++) for (j = 1; j <= elsonface.GetBagSize(i); j++) { INDEX_3 i3; INDEX_2 i2; elsonface.GetData (i, j, i3, i2); int eli1 = i2.I1(); int eli2 = i2.I2(); if (eli1 && eli2 && original.Test(eli1) && original.Test(eli2) ) { Element & elem = volelements.Elem(eli1); Element & elem2 = volelements.Elem(eli2); int pi1 = i3.I1(); int pi2 = i3.I2(); int pi3 = i3.I3(); int pi4 = elem.PNum(1) + elem.PNum(2) + elem.PNum(3) + elem.PNum(4) - pi1 - pi2 - pi3; int pi5 = elem2.PNum(1) + elem2.PNum(2) + elem2.PNum(3) + elem2.PNum(4) - pi1 - pi2 - pi3; el31.PNum(1) = pi1; el31.PNum(2) = pi2; el31.PNum(3) = pi3; el31.PNum(4) = pi4; el31.SetIndex (mattyp); if (WrongOrientation (points, el31)) swap (pi1, pi2); bad1 = CalcBad (points, elem, 0) + CalcBad (points, elem2, 0); // if (!LegalTet(elem) || !LegalTet(elem2)) // bad1 += 1e4; el31.PNum(1) = pi1; el31.PNum(2) = pi2; el31.PNum(3) = pi5; el31.PNum(4) = pi4; el31.SetIndex (mattyp); el32.PNum(1) = pi2; el32.PNum(2) = pi3; el32.PNum(3) = pi5; el32.PNum(4) = pi4; el32.SetIndex (mattyp); el33.PNum(1) = pi3; el33.PNum(2) = pi1; el33.PNum(3) = pi5; el33.PNum(4) = pi4; el33.SetIndex (mattyp); bad2 = CalcBad (points, el31, 0) + CalcBad (points, el32, 0) + CalcBad (points, el33, 0); // if (!LegalTet(el31) || !LegalTet(el32) || // !LegalTet(el33)) // bad2 += 1e4; int swap = (bad2 < bad1); INDEX_2 hi2b(pi4, pi5); hi2b.Sort(); if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) && boundaryedges->Used (hi2b) ) swap = 1; if (swap) { (*mycout) << "2->3 " << flush; volelements.Elem(eli1) = el31; volelements.Elem(eli2) = el32; volelements.Append (el33); original.Clear (eli1); original.Clear (eli2); } } } (*mycout) << endl; if (goal == OPT_QUALITY) { bad1 = CalcTotalBad (points, volelements); (*testout) << "Total badness = " << bad1 << endl; } // FindOpenElements (); (*testout) << "swapimprove2 done" << "\n"; } */ } netgen-6.2.1905/libsrc/meshing/hpref_trig.hpp0000644000175000017500000003027013504650527017555 0ustar kurtkurt // HP_TRIG int reftrig_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_newelstypes[] = { HP_TRIG, HP_NONE, }; int reftrig_newels[][8] = { { 1, 2, 3 }, }; HPRef_Struct reftrig = { HP_TRIG, reftrig_splitedges, 0, 0, reftrig_newelstypes, reftrig_newels }; // HP_TRIG_SINGCORNER int reftrig_singcorner_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singcorner_newelstypes[] = { HP_TRIG_SINGCORNER, HP_QUAD, HP_NONE, }; int reftrig_singcorner_newels[][8] = { { 1, 4, 5 }, { 2, 3, 5, 4 }, }; HPRef_Struct reftrig_singcorner = { HP_TRIG, reftrig_singcorner_splitedges, 0, 0, reftrig_singcorner_newelstypes, reftrig_singcorner_newels }; /* // HP_TRIG_SINGCORNER, trigs only int reftrig_singcorner_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singcorner_newelstypes[] = { HP_TRIG_SINGCORNER, HP_TRIG, HP_TRIG, HP_NONE, }; int reftrig_singcorner_newels[][8] = { { 1, 4, 5 }, { 4, 2, 5 }, { 5, 2, 3 }, }; HPRef_Struct reftrig_singcorner = { HP_TRIG, reftrig_singcorner_splitedges, 0, 0, reftrig_singcorner_newelstypes, reftrig_singcorner_newels }; */ // HP_TRIG_SINGCORNER12 int reftrig_singcorner12_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 1, 6 }, { 2, 3, 7 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singcorner12_newelstypes[] = { HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD, HP_TRIG, HP_NONE, }; int reftrig_singcorner12_newels[][8] = { { 1, 4, 5 }, { 2, 7, 6 }, { 4, 6, 7, 5 }, { 5, 7, 3 }, }; HPRef_Struct reftrig_singcorner12 = { HP_TRIG, reftrig_singcorner12_splitedges, 0, 0, reftrig_singcorner12_newelstypes, reftrig_singcorner12_newels }; // HP_TRIG_SINGCORNER123_2D int reftrig_singcorner123_2D_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 1, 6 }, { 2, 3, 7 }, { 3, 1, 8 }, { 3, 2, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singcorner123_2D_newelstypes[] = { HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER, HP_QUAD, HP_QUAD, HP_NONE, }; int reftrig_singcorner123_2D_newels[][8] = { { 1, 4, 5 }, { 2, 7, 6 }, { 3, 8, 9 }, { 4, 6, 8, 5 }, { 6, 7, 9, 8 }, }; HPRef_Struct reftrig_singcorner123_2D = { HP_TRIG, reftrig_singcorner123_2D_splitedges, 0, 0, reftrig_singcorner123_2D_newelstypes, reftrig_singcorner123_2D_newels }; // HP_TRIG_SINGCORNER123 int reftrig_singcorner123_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 1, 6 }, { 2, 3, 7 }, { 3, 1, 8 }, { 3, 2, 9 }, { 0, 0, 0 } }; int reftrig_singcorner123_splitfaces[][4] = { { 1, 2, 3, 10 }, { 2, 3, 1, 11 }, { 3, 1, 2, 12 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singcorner123_newelstypes[] = { HP_DUMMY_QUAD_SINGCORNER, HP_DUMMY_QUAD_SINGCORNER, HP_DUMMY_QUAD_SINGCORNER, // HP_TRIG_SINGCORNER, // HP_TRIG, // HP_TRIG_SINGCORNER, // HP_TRIG, // HP_TRIG_SINGCORNER, // HP_TRIG, HP_QUAD, HP_QUAD, HP_QUAD, HP_TRIG, HP_NONE, }; int reftrig_singcorner123_newels[][8] = { { 1, 4, 10, 5 }, { 2, 7, 11, 6 }, { 3, 8, 12, 9 }, // { 1, 4, 5 }, // { 5, 4, 10 }, // { 2, 7, 6 }, // { 6, 7, 11 }, // { 3, 8, 9 }, // { 8, 12, 9 }, { 4, 6, 11, 10 }, { 7, 9, 12, 11 }, { 8, 5, 10, 12 }, { 10, 11, 12 }, }; HPRef_Struct reftrig_singcorner123 = { HP_TRIG, reftrig_singcorner123_splitedges, reftrig_singcorner123_splitfaces, 0, reftrig_singcorner123_newelstypes, reftrig_singcorner123_newels }; // HP_TRIG_SINGEDGE int reftrig_singedge_splitedges[][3] = { { 2, 3, 4 }, { 1, 3, 5 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedge_newelstypes[] = { HP_TRIG, HP_QUAD_SINGEDGE, HP_NONE, }; int reftrig_singedge_newels[][8] = { { 4, 3, 5 }, { 1, 2, 4, 5 }, }; HPRef_Struct reftrig_singedge = { HP_TRIG, reftrig_singedge_splitedges, 0, 0, reftrig_singedge_newelstypes, reftrig_singedge_newels }; // HP_TRIG_SINGEDGECORNER1 int reftrig_singedgecorner1_splitedges[][3] = { { 1, 2, 6 }, { 1, 3, 5 }, { 2, 3, 4 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedgecorner1_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_QUAD_SINGEDGE, HP_TRIG, HP_NONE, }; int reftrig_singedgecorner1_newels[][8] = { { 1, 6, 5 }, { 6, 2, 4, 5 }, { 5, 4, 3 }, }; HPRef_Struct reftrig_singedgecorner1 = { HP_TRIG, reftrig_singedgecorner1_splitedges, 0, 0, reftrig_singedgecorner1_newelstypes, reftrig_singedgecorner1_newels }; // HP_TRIG_SINGEDGECORNER2 int reftrig_singedgecorner2_splitedges[][3] = { { 2, 1, 6 }, { 1, 3, 5 }, { 2, 3, 4 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedgecorner2_newelstypes[] = { HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_TRIG, HP_NONE, }; int reftrig_singedgecorner2_newels[][8] = { { 6, 2, 4}, { 1, 6, 4, 5 }, { 5, 4, 3 }, }; HPRef_Struct reftrig_singedgecorner2 = { HP_TRIG, reftrig_singedgecorner2_splitedges, 0, 0, reftrig_singedgecorner2_newelstypes, reftrig_singedgecorner2_newels }; // HP_TRIG_SINGEDGECORNER12 int reftrig_singedgecorner12_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 1, 6 }, { 2, 3, 7 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedgecorner12_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_TRIG, HP_NONE, }; int reftrig_singedgecorner12_newels[][8] = { { 1, 4, 5 }, { 6, 2, 7 }, { 4, 6, 7, 5 }, { 5, 7, 3 }, }; HPRef_Struct reftrig_singedgecorner12 = { HP_TRIG, reftrig_singedgecorner12_splitedges, 0, 0, reftrig_singedgecorner12_newelstypes, reftrig_singedgecorner12_newels }; // HP_TRIG_SINGEDGECORNER3 int reftrig_singedgecorner3_splitedges[][3] = { { 1, 3, 4 }, { 3, 1, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedgecorner3_newelstypes[] = { HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int reftrig_singedgecorner3_newels[][8] = { { 1, 2, 6, 4 }, { 4, 6, 7, 5 }, { 3, 5, 7 }, }; HPRef_Struct reftrig_singedgecorner3 = { HP_TRIG, reftrig_singedgecorner3_splitedges, 0, 0, reftrig_singedgecorner3_newelstypes, reftrig_singedgecorner3_newels }; // HP_TRIG_SINGEDGECORNER13 int reftrig_singedgecorner13_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 3, 6 }, { 3, 1, 7 }, { 3, 2, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedgecorner13_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int reftrig_singedgecorner13_newels[][8] = { { 1, 4, 5 }, { 4, 2, 6, 5 }, { 5, 6, 8, 7 }, { 3, 7, 8 }, }; HPRef_Struct reftrig_singedgecorner13 = { HP_TRIG, reftrig_singedgecorner13_splitedges, 0, 0, reftrig_singedgecorner13_newelstypes, reftrig_singedgecorner13_newels }; // HP_TRIG_SINGEDGECORNER23 int reftrig_singedgecorner23_splitedges[][3] = { { 1, 3, 4 }, { 2, 1, 5 }, { 2, 3, 6 }, { 3, 1, 7 }, { 3, 2, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedgecorner23_newelstypes[] = { HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int reftrig_singedgecorner23_newels[][8] = { { 5, 2, 6 }, { 1, 5, 6, 4 }, { 4, 6, 8, 7 }, { 3, 7, 8 }, }; HPRef_Struct reftrig_singedgecorner23 = { HP_TRIG, reftrig_singedgecorner23_splitedges, 0, 0, reftrig_singedgecorner23_newelstypes, reftrig_singedgecorner23_newels }; // HP_TRIG_SINGEDGECORNER123 int reftrig_singedgecorner123_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 1, 6 }, { 2, 3, 7 }, { 3, 1, 8 }, { 3, 2, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedgecorner123_newelstypes[] = { HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD, HP_TRIG_SINGCORNER, HP_NONE, }; int reftrig_singedgecorner123_newels[][8] = { { 1, 4, 5 }, { 6, 2, 7 }, { 4, 6, 7, 5 }, { 5, 7, 9, 8 }, { 3, 8, 9 }, }; HPRef_Struct reftrig_singedgecorner123 = { HP_TRIG, reftrig_singedgecorner123_splitedges, 0, 0, reftrig_singedgecorner123_newelstypes, reftrig_singedgecorner123_newels }; // HP_TRIG_SINGEDGES int reftrig_singedges_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 0, 0, 0 } }; int reftrig_singedges_splitfaces[][4] = { { 1, 2, 3, 8 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedges_newelstypes[] = { // HP_QUAD_2E, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG, HP_NONE, }; int reftrig_singedges_newels[][8] = { // { 1, 4, 8, 5 }, { 1, 4, 8 }, { 5, 1, 8 }, { 4, 2, 6, 8 }, { 3, 5, 8, 7 }, { 6, 7, 8 }, }; HPRef_Struct reftrig_singedges = { HP_TRIG, reftrig_singedges_splitedges, reftrig_singedges_splitfaces, 0, reftrig_singedges_newelstypes, reftrig_singedges_newels }; // HP_TRIG_SINGEDGES2 int reftrig_singedges2_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 1, 6 }, { 2, 3, 7 }, { 3, 2, 8 }, { 0, 0, 0 } }; int reftrig_singedges2_splitfaces[][4] = { { 1, 2, 3, 9 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedges2_newelstypes[] = { // HP_QUAD_2E, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER2, HP_TRIG, HP_NONE, }; int reftrig_singedges2_newels[][8] = { // { 1, 4, 9, 5 }, { 1, 4, 9 }, { 5, 1, 9 }, { 4, 6, 7, 9 }, { 3, 5, 9, 8 }, { 6, 2, 7 }, { 7, 8, 9 }, }; HPRef_Struct reftrig_singedges2 = { HP_TRIG, reftrig_singedges2_splitedges, reftrig_singedges2_splitfaces, 0, reftrig_singedges2_newelstypes, reftrig_singedges2_newels }; // HP_TRIG_SINGEDGES3 int reftrig_singedges3_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 3, 6 }, { 3, 1, 7 }, { 3, 2, 8 }, { 0, 0, 0 } }; int reftrig_singedges3_splitfaces[][4] = { { 1, 2, 3, 9 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedges3_newelstypes[] = { // HP_QUAD_2E, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG, HP_NONE, }; int reftrig_singedges3_newels[][8] = { // { 1, 4, 9, 5 }, { 1, 4, 9 }, { 5, 1, 9 }, { 4, 2, 6, 9 }, { 7, 5, 9, 8 }, { 3, 7, 8 }, { 6, 8, 9 }, }; HPRef_Struct reftrig_singedges3 = { HP_TRIG, reftrig_singedges3_splitedges, reftrig_singedges3_splitfaces, 0, reftrig_singedges3_newelstypes, reftrig_singedges3_newels }; // HP_TRIG_SINGEDGES23 int reftrig_singedges23_splitedges[][3] = { { 1, 2, 4 }, { 1, 3, 5 }, { 2, 1, 6 }, { 2, 3, 7 }, { 3, 1, 8 }, { 3, 2, 9 }, { 0, 0, 0 } }; int reftrig_singedges23_splitfaces[][4] = { { 1, 2, 3, 10 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_singedges23_newelstypes[] = { // HP_QUAD_2E, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER1, HP_TRIG, HP_NONE, }; int reftrig_singedges23_newels[][8] = { // { 1, 4, 10, 5 }, { 1 , 4, 10 }, { 5, 1, 10 }, { 4, 6, 7, 10 }, { 8, 5, 10, 9 }, { 6, 2, 7 }, { 3, 8, 9 }, { 7, 9, 10 }, }; HPRef_Struct reftrig_singedges23 = { HP_TRIG, reftrig_singedges23_splitedges, reftrig_singedges23_splitfaces, 0, reftrig_singedges23_newelstypes, reftrig_singedges23_newels }; // HP_TRIG_3SINGEDGES int reftrig_3singedges_splitedges[][3] = { { 1, 2, 4 }, { 2, 1, 5 }, { 2, 3, 6 }, { 3, 2, 7 }, { 3, 1, 8 }, { 1, 3, 9 }, { 0, 0, 0 } }; int reftrig_3singedges_splitfaces[][4] = { { 1, 2, 3, 10 }, { 2, 3, 1, 11 }, { 3, 1, 2, 12 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftrig_3singedges_newelstypes[] = { HP_TRIG, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_QUAD_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_NONE, }; int reftrig_3singedges_newels[][8] = { { 10, 11, 12 }, { 4, 5, 11, 10 }, { 6, 7, 12, 11 }, { 8, 9, 10, 12 }, { 1, 4, 10 }, { 9, 1, 10 }, { 2, 6, 11 }, { 5, 2, 11 }, { 3, 8, 12 }, { 7, 3, 12 }, }; HPRef_Struct reftrig_3singedges = { HP_TRIG, reftrig_3singedges_splitedges, reftrig_3singedges_splitfaces, 0, reftrig_3singedges_newelstypes, reftrig_3singedges_newels }; netgen-6.2.1905/libsrc/meshing/hpref_segm.hpp0000644000175000017500000000355413504650527017550 0ustar kurtkurt // HP_SEGM int refsegm_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refsegm_newelstypes[] = { HP_SEGM, HP_NONE, }; int refsegm_newels[][8] = { { 1, 2 }, }; HPRef_Struct refsegm = { HP_SEGM, refsegm_splitedges, 0, 0, refsegm_newelstypes, refsegm_newels }; // HP_SEGM_SINGCORNERL = 2, int refsegm_scl_splitedges[][3] = { { 1, 2, 3 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refsegm_scl_newelstypes[] = { HP_SEGM_SINGCORNERL, HP_SEGM, HP_NONE, }; int refsegm_scl_newels[][8] = { { 1, 3 }, { 3, 2 }, { 0, 0 }, }; HPRef_Struct refsegm_scl = { HP_SEGM, refsegm_scl_splitedges, 0, 0, refsegm_scl_newelstypes, refsegm_scl_newels }; // HP_SEGM_SINGCORNERR int refsegm_scr_splitedges[][3] = { { 2, 1, 3 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refsegm_scr_newelstypes[] = { HP_SEGM, HP_SEGM_SINGCORNERR, HP_NONE, }; int refsegm_scr_newels[][8] = { { 1, 3 }, { 3, 2 }, { 0, 0 }, }; HPRef_Struct refsegm_scr = { HP_SEGM, refsegm_scr_splitedges, 0, 0, refsegm_scr_newelstypes, refsegm_scr_newels }; // HP_SEGM_SINGCORNERS = 3, int refsegm_sc2_splitedges[][3] = { { 1, 2, 3 }, { 2, 1, 4 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refsegm_sc2_newelstypes[] = { HP_SEGM_SINGCORNERL, HP_SEGM_SINGCORNERR, HP_SEGM, HP_NONE, }; int refsegm_sc2_newels[][8] = { { 1, 3 }, { 4, 2 }, { 3, 4 }, { 0, 0 }, }; HPRef_Struct refsegm_sc2 = { HP_SEGM, refsegm_sc2_splitedges, 0, 0, refsegm_sc2_newelstypes, refsegm_sc2_newels }; netgen-6.2.1905/libsrc/meshing/secondorder.cpp0000644000175000017500000003160313504650527017727 0ustar kurtkurt #include #include "meshing.hpp" namespace netgen { void Refinement :: MakeSecondOrder (Mesh & mesh) const { const_cast (*this).MakeSecondOrder(mesh); } void Refinement :: MakeSecondOrder (Mesh & mesh) { /* Berlin, 2014: if we have curved surface elements, keep them ! */ mesh.ComputeNVertices(); // mesh.SetNP(mesh.GetNV()); mesh.SetNP(mesh.GetNP()); // setup multilevel-table INDEX_2_HASHTABLE between(mesh.GetNP() + 5); for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { auto & seg = mesh[si]; if (seg.GetType() == SEGMENT3) between.Set(INDEX_2::Sort(seg[0],seg[1]), seg[2]); } for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el = mesh[sei]; static int betw_trig[3][3] = { { 1, 2, 3 }, { 0, 2, 4 }, { 0, 1, 5 } }; static int betw_quad6[2][3] = { { 0, 1, 4 }, { 3, 2, 5 } }; static int betw_quad8[4][3] = { { 0, 1, 4 }, { 3, 2, 5 }, { 0, 3, 6 }, { 1, 2, 7 } }; int onp = 0; int (*betw)[3] = NULL; switch (el.GetType()) { case TRIG6: { betw = betw_trig; onp = 3; break; } case QUAD6: { betw = betw_quad6; onp = 4; break; } case QUAD8: { betw = betw_quad8; onp = 4; break; } default: ; } if (betw) for (int j = 0; j < el.GetNP()-onp; j++) { int pi1 = el[betw[j][0]]; int pi2 = el[betw[j][1]]; INDEX_2 i2 = INDEX_2::Sort (pi1, pi2); between.Set (i2, el[onp+j]); } } bool thinlayers = 0; for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) if (mesh[ei].GetType() == PRISM || mesh[ei].GetType() == PRISM12) thinlayers = 1; int nseg = mesh.GetNSeg(); for (SegmentIndex si = 0; si < nseg; si++) { Segment & el = mesh.LineSegment(si); INDEX_2 i2 = INDEX_2::Sort (el[0], el[1]); if (between.Used(i2)) el[2] = between.Get(i2); else { Point<3> pb; EdgePointGeomInfo ngi; PointBetween (mesh.Point (el[0]), mesh.Point (el[1]), 0.5, el.surfnr1, el.surfnr2, el.epgeominfo[0], el.epgeominfo[1], pb, ngi); el[2] = mesh.AddPoint (pb, mesh.Point(el[0]).GetLayer(), EDGEPOINT); between.Set (i2, el[2]); } } // refine surface elements for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { int j; const Element2d & el = mesh.SurfaceElement(sei); int onp(0); Element2d newel(TRIG); newel.SetIndex (el.GetIndex()); static int betw_trig[3][3] = { { 1, 2, 3 }, { 0, 2, 4 }, { 0, 1, 5 } }; static int betw_quad6[2][3] = { { 0, 1, 4 }, { 3, 2, 5 } }; static int betw_quad8[4][3] = { { 0, 1, 4 }, { 3, 2, 5 }, { 0, 3, 6 }, { 1, 2, 7 } }; int (*betw)[3] = NULL; switch (el.GetType()) { case TRIG: case TRIG6: { betw = betw_trig; newel.SetType (TRIG6); onp = 3; break; } case QUAD: case QUAD6: case QUAD8: { if (thinlayers) { betw = betw_quad6; newel.SetType (QUAD6); } else { betw = betw_quad8; newel.SetType (QUAD8); } onp = 4; break; } default: PrintSysError ("Unhandled element in secondorder:", int(el.GetType())); } for (j = 0; j < onp; j++) newel[j] = el[j]; int nnp = newel.GetNP(); for (j = 0; j < nnp-onp; j++) { int pi1 = newel[betw[j][0]]; int pi2 = newel[betw[j][1]]; INDEX_2 i2 = INDEX_2::Sort (pi1, pi2); if (between.Used(i2)) newel[onp+j] = between.Get(i2); else { Point<3> pb; PointGeomInfo newgi; PointBetween (mesh.Point (pi1), mesh.Point (pi2), 0.5, mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(), el.GeomInfoPi (betw[j][0]+1), el.GeomInfoPi (betw[j][1]+1), pb, newgi); newel[onp+j] = mesh.AddPoint (pb, mesh.Point(pi1).GetLayer(), SURFACEPOINT); between.Set (i2, newel[onp+j]); } } mesh.SurfaceElement(sei) = newel; } // int i, j; // refine volume elements for (int i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement(i); int onp = 0; Element newel(TET); newel.SetIndex (el.GetIndex()); static int betw_tet[6][3] = { { 0, 1, 4 }, { 0, 2, 5 }, { 0, 3, 6 }, { 1, 2, 7 }, { 1, 3, 8 }, { 2, 3, 9 } }; static int betw_prism[6][3] = { { 0, 2, 6 }, { 0, 1, 7 }, { 1, 2, 8 }, { 3, 5, 9 }, { 3, 4, 10 }, { 4, 5, 11 }, }; static int betw_prism15[9][3] = { { 0, 1, 6 }, { 0, 2, 7 }, { 1, 2, 8 }, { 0, 3, 9 }, { 1, 4, 10 }, { 2, 5, 11 }, { 3, 4, 12 }, { 3, 5, 13 }, { 4, 5, 14 } }; static int betw_pyramid[8][3] = { { 0, 1, 5 }, { 3, 2, 6 }, { 3, 0, 7 }, { 1, 2, 8 }, { 0, 4, 9 }, { 1, 4, 10 }, { 2, 4, 11 }, { 3, 4, 12 } }; static int betw_hex[12][3] = { { 0, 1, 8 }, { 2, 3, 9 }, { 3, 0, 10 }, { 1, 2, 11 }, { 4, 5, 12 }, { 6, 7, 13 }, { 7, 4, 14 }, { 5, 6, 15 }, { 0, 4, 16 }, { 1, 5, 17 }, { 2, 6, 18 }, { 3, 7, 19 }, }; int (*betw)[3] = NULL; switch (el.GetType()) { case TET: case TET10: { betw = betw_tet; newel.SetType (TET10); onp = 4; break; } case PRISM: case PRISM12: { betw = betw_prism; newel.SetType (PRISM12); onp = 6; break; } case PRISM15: { betw = betw_prism15; newel.SetType(PRISM15); onp = 6; break; } case PYRAMID: case PYRAMID13: { betw = betw_pyramid; newel.SetType(PYRAMID13); onp = 5; break; } case HEX: case HEX20: { betw = betw_hex; newel.SetType (HEX20); onp = 8; break; } default: PrintSysError ("MakeSecondOrder, illegal vol type ", int(el.GetType())); } for (int j = 1; j <= onp; j++) newel.PNum(j) = el.PNum(j); int nnp = newel.GetNP(); for (int j = 0; j < nnp-onp; j++) { INDEX_2 i2(newel[betw[j][0]], newel[betw[j][1]]); i2.Sort(); if (between.Used(i2)) newel.PNum(onp+1+j) = between.Get(i2); else { newel.PNum(onp+1+j) = mesh.AddPoint (Center (mesh.Point(i2.I1()), mesh.Point(i2.I2())), mesh.Point(i2.I1()).GetLayer(), INNERPOINT); between.Set (i2, newel.PNum(onp+1+j)); } } mesh.VolumeElement (i) = newel; } // makes problems after linear mesh refinement, since // 2nd order identifications are not removed // update identification tables for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) { Array identmap; mesh.GetIdentifications().GetMap (i, identmap); for (INDEX_2_HASHTABLE::Iterator it = between.Begin(); it != between.End(); it++) { INDEX_2 i2; PointIndex newpi; between.GetData (it, i2, newpi); INDEX_2 oi2(identmap.Get(i2.I1()), identmap.Get(i2.I2())); oi2.Sort(); if (between.Used (oi2)) { PointIndex onewpi = between.Get(oi2); mesh.GetIdentifications().Add (newpi, onewpi, i); } } /* for (int j = 1; j <= between.GetNBags(); j++) for (int k = 1; k <= between.GetBagSize(j); k++) { INDEX_2 i2; int newpi; between.GetData (j, k, i2, newpi); INDEX_2 oi2(identmap.Get(i2.I1()), identmap.Get(i2.I2())); oi2.Sort(); if (between.Used (oi2)) { int onewpi = between.Get(oi2); mesh.GetIdentifications().Add (newpi, onewpi, i); } } */ } // mesh.mglevels++; int oldsize = mesh.mlbetweennodes.Size(); mesh.mlbetweennodes.SetSize(mesh.GetNP()); for (int i = oldsize; i < mesh.GetNP(); i++) mesh.mlbetweennodes[i] = INDEX_2(0,0); /* for (i = 1; i <= between.GetNBags(); i++) for (j = 1; j <= between.GetBagSize(i); j++) { INDEX_2 oldp; int newp; between.GetData (i, j, oldp, newp); mesh.mlbetweennodes.Elem(newp) = oldp; } */ for (INDEX_2_HASHTABLE::Iterator it = between.Begin(); it != between.End(); it++) { mesh.mlbetweennodes[between.GetData (it)] = between.GetHash(it); } mesh.ComputeNVertices(); mesh.RebuildSurfaceElementLists(); // ValidateSecondOrder (mesh); } void Refinement :: ValidateSecondOrder (Mesh & mesh) { PrintMessage (3, "Validate mesh"); int np = mesh.GetNP(); int ne = mesh.GetNE(); // int i, j; Array parents(np); for (int i = 1; i <= np; i++) parents.Elem(i) = INDEX_2(0,0); for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); if (el.GetType() == TET10) { static int betweentab[6][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 4, 10 } }; for (int j = 0; j < 6; j++) { int f1 = el.PNum (betweentab[j][0]); int f2 = el.PNum (betweentab[j][1]); int son = el.PNum (betweentab[j][2]); parents.Elem(son).I1() = f1; parents.Elem(son).I2() = f2; } } } ValidateRefinedMesh (mesh, parents); } void Refinement :: ValidateRefinedMesh (Mesh & mesh, Array & parents) { // int i, j, k; // homotopy method int ne = mesh.GetNE(); int cnttrials = 100; int wrongels = 0; for (int i = 1; i <= ne; i++) if (mesh.VolumeElement(i).CalcJacobianBadness (mesh.Points()) > 1e10) { wrongels++; mesh.VolumeElement(i).flags.badel = 1; } else mesh.VolumeElement(i).flags.badel = 0; double facok = 0; double factry; BitArray illegalels(ne); illegalels.Clear(); if (wrongels) { cout << "WARNING: " << wrongels << " illegal element(s) found" << endl; int np = mesh.GetNP(); Array > should(np); Array > can(np); for (int i = 1; i <= np; i++) { should.Elem(i) = can.Elem(i) = mesh.Point(i); } for (int i = 1; i <= parents.Size(); i++) { if (parents.Get(i).I1()) can.Elem(i) = Center (can.Elem(parents.Get(i).I1()), can.Elem(parents.Get(i).I2())); } BitArray boundp(np); boundp.Clear(); for (int i = 1; i <= mesh.GetNSE(); i++) { const Element2d & sel = mesh.SurfaceElement(i); for (int j = 1; j <= sel.GetNP(); j++) boundp.Set(sel.PNum(j)); } (*testout) << "bpoints:" << endl; for (int i = 1; i <= np; i++) if (boundp.Test(i)) (*testout) << i << endl; double lam = 0.5; while (facok < 1-1e-8 && cnttrials > 0) { lam *= 4; if (lam > 2) lam = 2; do { // cout << "trials: " << cnttrials << endl; lam *= 0.5; cnttrials--; cout << "lam = " << lam << endl; factry = lam + (1-lam) * facok; cout << "trying: " << factry << endl; for (int i = 1; i <= np; i++) if (boundp.Test(i)) { for (int j = 0; j < 3; j++) mesh.Point(i)(j) = lam * should.Get(i)(j) + (1-lam) * can.Get(i)(j); } else mesh.Point(i) = Point<3> (can.Get(i)); // (*testout) << "bad els: " << endl; wrongels = 0; for (int i = 1; i <= ne; i++) { if (!illegalels.Test(i) && mesh.VolumeElement(i). CalcJacobianBadness(mesh.Points()) > 1e10) { wrongels++; Element & el = mesh.VolumeElement(i); el.flags.badel = 1; if (lam < 1e-4) illegalels.Set(i); /* (*testout) << i << ": "; for (j = 1; j <= el.GetNP(); j++) (*testout) << el.PNum(j) << " "; (*testout) << endl; */ } else mesh.VolumeElement(i).flags.badel = 0; } cout << "wrongels = " << wrongels << endl; } while (wrongels && cnttrials > 0); mesh.CalcSurfacesOfNode(); MeshingParameters dummymp; mesh.ImproveMeshJacobian (dummymp, OPT_WORSTCASE); facok = factry; for (int i = 1; i <= np; i++) can.Elem(i) = mesh.Point(i); } } for (int i = 1; i <= ne; i++) { if (illegalels.Test(i)) { cout << "illegal element: " << i << endl; mesh.VolumeElement(i).flags.badel = 1; } else mesh.VolumeElement(i).flags.badel = 0; } /* if (cnttrials <= 0) { cerr << "ERROR: Sorry, illegal elements:" << endl; } */ } } netgen-6.2.1905/libsrc/meshing/meshclass.hpp0000644000175000017500000006361713504650527017421 0ustar kurtkurt#ifndef MESHCLASS #define MESHCLASS /**************************************************************************/ /* File: meshclass.hpp */ /* Author: Joachim Schoeberl */ /* Date: 20. Nov. 99 */ /**************************************************************************/ /* The mesh class */ namespace netgen { enum resthtype { RESTRICTH_FACE, RESTRICTH_EDGE, RESTRICTH_SURFACEELEMENT, RESTRICTH_POINT, RESTRICTH_SEGMENT }; class HPRefElement; /// 2d/3d mesh class Mesh { public: typedef ::netgen::T_POINTS T_POINTS; typedef Array T_VOLELEMENTS; // typedef Array T_SURFELEMENTS; typedef Array T_SURFELEMENTS; private: /// point coordinates T_POINTS points; // The communicator for this mesh. Just a dummy if compiled without MPI. NgMPI_Comm comm; /// line-segments at edges Array segments; /// surface elements, 2d-inner elements T_SURFELEMENTS surfelements; /// volume elements T_VOLELEMENTS volelements; /// points will be fixed forever Array lockedpoints; /// surface indices at boundary nodes // TABLE surfacesonnode; /// boundary edges (1..normal bedge, 2..segment) INDEX_2_CLOSED_HASHTABLE * boundaryedges; /// INDEX_2_CLOSED_HASHTABLE * segmentht; /// INDEX_3_CLOSED_HASHTABLE * surfelementht; /// faces of rest-solid Array openelements; /// open segmenets for surface meshing Array opensegments; /** Representation of local mesh-size h */ LocalH * lochfunc; /// double hglob; /// double hmin; /// Array maxhdomain; /** the face-index of the surface element maps into this table. */ Array facedecoding; /** the edge-index of the line element maps into this table. */ Array edgedecoding; /// sub-domain materials Array materials; /// labels for boundary conditions Array bcnames; /// labels for co dim 2 bboundary conditions Array cd2names; /// labels for co dim 3 bbboundary conditions Array cd3names; /// Periodic surface, close surface, etc. identifications Identifications * ident; /// number of vertices (if < 0, use np) int numvertices; /// geometric search tree for interval intersection search BoxTree<3> * elementsearchtree; /// time stamp for tree mutable int elementsearchtreets; /// element -> face, element -> edge etc ... MeshTopology topology; /// methods for high order elements class CurvedElements * curvedelems; /// nodes identified by close points class AnisotropicClusters * clusters; /// space dimension (2 or 3) int dimension; /// changed by every minor modification (addpoint, ...) int timestamp; /// changed after finishing global algorithm (improve, ...) int majortimestamp; /// mesh access semaphors. NgMutex mutex; /// mesh access semaphors. NgMutex majormutex; SymbolTable< Array* > userdata_int; SymbolTable< Array* > userdata_double; mutable Array< Point3d > pointcurves; mutable Array pointcurves_startpoint; mutable Array pointcurves_red,pointcurves_green,pointcurves_blue; /// start element for point search (GetElementOfPoint) mutable int ps_startelement; #ifdef PARALLEL /// connection to parallel meshes class ParallelMeshTopology * paralleltop; #endif shared_ptr geometry; private: void BuildBoundaryEdges(void); public: bool PointContainedIn2DElement(const Point3d & p, double lami[3], const int element, bool consider3D = false) const; bool PointContainedIn3DElement(const Point3d & p, double lami[3], const int element) const; bool PointContainedIn3DElementOld(const Point3d & p, double lami[3], const int element) const; public: // store coarse mesh before hp-refinement Array * hpelements; Mesh * coarsemesh; /// number of refinement levels int mglevels; /// refinement hierarchy Array,PointIndex::BASE> mlbetweennodes; /// parent element of volume element Array mlparentelement; /// parent element of surface element Array mlparentsurfaceelement; /// DLL_HEADER Mesh(); /// DLL_HEADER ~Mesh(); Mesh & operator= (const Mesh & mesh2); /// DLL_HEADER void DeleteMesh(); /// void ClearSurfaceElements(); /// DLL_HEADER void ClearVolumeElements() { volelements.SetSize(0); timestamp = NextTimeStamp(); } /// DLL_HEADER void ClearSegments() { segments.SetSize(0); timestamp = NextTimeStamp(); } /// bool TestOk () const; void SetAllocSize(int nnodes, int nsegs, int nsel, int nel); DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer = 1); DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer, POINTTYPE type); auto GetNP () const { return points.Size(); } // [[deprecated("Use Point(PointIndex) instead of int !")]] MeshPoint & Point(int i) { return points.Elem(i); } MeshPoint & Point(PointIndex pi) { return points[pi]; } // [[deprecated("Use Point(PointIndex) instead of int !")]] const MeshPoint & Point(int i) const { return points.Get(i); } const MeshPoint & Point(PointIndex pi) const { return points[pi]; } const MeshPoint & operator[] (PointIndex pi) const { return points[pi]; } MeshPoint & operator[] (PointIndex pi) { return points[pi]; } const T_POINTS & Points() const { return points; } T_POINTS & Points() { return points; } DLL_HEADER SegmentIndex AddSegment (const Segment & s); void DeleteSegment (int segnr) { segments.Elem(segnr)[0].Invalidate(); segments.Elem(segnr)[1].Invalidate(); } /* void FullDeleteSegment (int segnr) // von wem ist das ??? { segments.Delete(segnr-PointIndex::BASE); } */ int GetNSeg () const { return segments.Size(); } // [[deprecated("Use LineSegment(SegmentIndex) instead of int !")]] Segment & LineSegment(int i) { return segments.Elem(i); } // [[deprecated("Use LineSegment(SegmentIndex) instead of int !")]] const Segment & LineSegment(int i) const { return segments.Get(i); } Segment & LineSegment(SegmentIndex si) { return segments[si]; } const Segment & LineSegment(SegmentIndex si) const { return segments[si]; } const Segment & operator[] (SegmentIndex si) const { return segments[si]; } Segment & operator[] (SegmentIndex si) { return segments[si]; } /* const Array & LineSegments() const { return segments; } Array & LineSegments() { return segments; } */ const auto & LineSegments() const { return segments; } auto & LineSegments() { return segments; } Array pointelements; // only via python interface DLL_HEADER SurfaceElementIndex AddSurfaceElement (const Element2d & el); // write to pre-allocated container, thread-safe DLL_HEADER void SetSurfaceElement (SurfaceElementIndex sei, const Element2d & el); // [[deprecated("Use DeleteSurfaceElement(SurfaceElementIndex) instead of int !")]] void DeleteSurfaceElement (int eli) { surfelements.Elem(eli).Delete(); surfelements.Elem(eli).PNum(1).Invalidate(); surfelements.Elem(eli).PNum(2).Invalidate(); surfelements.Elem(eli).PNum(3).Invalidate(); timestamp = NextTimeStamp(); } void DeleteSurfaceElement (SurfaceElementIndex eli) { for (auto & p : surfelements[eli].PNums()) p.Invalidate(); surfelements[eli].Delete(); timestamp = NextTimeStamp(); } auto GetNSE () const { return surfelements.Size(); } // [[deprecated("Use SurfaceElement(SurfaceElementIndex) instead of int !")]] Element2d & SurfaceElement(int i) { return surfelements.Elem(i); } // [[deprecated("Use SurfaceElement(SurfaceElementIndex) instead of int !")]] const Element2d & SurfaceElement(int i) const { return surfelements.Get(i); } Element2d & SurfaceElement(SurfaceElementIndex i) { return surfelements[i]; } const Element2d & SurfaceElement(SurfaceElementIndex i) const { return surfelements[i]; } const Element2d & operator[] (SurfaceElementIndex ei) const { return surfelements[ei]; } Element2d & operator[] (SurfaceElementIndex ei) { return surfelements[ei]; } const T_SURFELEMENTS & SurfaceElements() const { return surfelements; } T_SURFELEMENTS & SurfaceElements() { return surfelements; } DLL_HEADER void RebuildSurfaceElementLists (); DLL_HEADER void GetSurfaceElementsOfFace (int facenr, Array & sei) const; DLL_HEADER ElementIndex AddVolumeElement (const Element & el); // write to pre-allocated container, thread-safe DLL_HEADER void SetVolumeElement (ElementIndex sei, const Element & el); auto GetNE () const { return volelements.Size(); } // [[deprecated("Use VolumeElement(ElementIndex) instead of int !")]] Element & VolumeElement(int i) { return volelements.Elem(i); } // [[deprecated("Use VolumeElement(ElementIndex) instead of int !")]] const Element & VolumeElement(int i) const { return volelements.Get(i); } Element & VolumeElement(ElementIndex i) { return volelements[i]; } const Element & VolumeElement(ElementIndex i) const { return volelements[i]; } const Element & operator[] (ElementIndex ei) const { return volelements[ei]; } Element & operator[] (ElementIndex ei) { return volelements[ei]; } ELEMENTTYPE ElementType (ElementIndex i) const { return (volelements[i].flags.fixed) ? FIXEDELEMENT : FREEELEMENT; } const auto & VolumeElements() const { return volelements; } auto & VolumeElements() { return volelements; } /// DLL_HEADER double ElementError (int eli, const MeshingParameters & mp) const; /// DLL_HEADER void AddLockedPoint (PointIndex pi); /// void ClearLockedPoints (); const auto & LockedPoints() const { return lockedpoints; } /// Returns number of domains DLL_HEADER int GetNDomains() const; /// int GetDimension() const { return dimension; } void SetDimension (int dim) { dimension = dim; } /// sets internal tables DLL_HEADER void CalcSurfacesOfNode (); /// additional (temporarily) fix points void FixPoints (const BitArray & fixpoints); /** finds elements without neighbour and boundary elements without inner element. Results are stored in openelements. if dom == 0, all sub-domains, else subdomain dom */ DLL_HEADER void FindOpenElements (int dom = 0); /** finds segments without surface element, and surface elements without neighbours. store in opensegmentsy */ DLL_HEADER void FindOpenSegments (int surfnr = 0); /** remove one layer of surface elements */ DLL_HEADER void RemoveOneLayerSurfaceElements (); int GetNOpenSegments () { return opensegments.Size(); } const Segment & GetOpenSegment (int nr) { return opensegments.Get(nr); } /** Checks overlap of boundary return == 1, iff overlap */ DLL_HEADER int CheckOverlappingBoundary (); /** Checks consistent boundary return == 0, everything ok */ DLL_HEADER int CheckConsistentBoundary () const; /* checks element orientation */ DLL_HEADER int CheckVolumeMesh () const; /** finds average h of surface surfnr if surfnr > 0, else of all surfaces. */ DLL_HEADER double AverageH (int surfnr = 0) const; /// Calculates localh DLL_HEADER void CalcLocalH (double grading); /// DLL_HEADER void SetLocalH (netgen::Point<3> pmin, netgen::Point<3> pmax, double grading); /// DLL_HEADER void RestrictLocalH (const Point3d & p, double hloc); /// DLL_HEADER void RestrictLocalHLine (const Point3d & p1, const Point3d & p2, double hloc); /// number of elements per radius DLL_HEADER void CalcLocalHFromSurfaceCurvature(double grading, double elperr); /// DLL_HEADER void CalcLocalHFromPointDistances(double grading); /// DLL_HEADER void RestrictLocalH (resthtype rht, int nr, double loch); /// DLL_HEADER void LoadLocalMeshSize (const string & meshsizefilename); /// DLL_HEADER void SetGlobalH (double h); /// DLL_HEADER void SetMinimalH (double h); /// DLL_HEADER double MaxHDomain (int dom) const; /// DLL_HEADER void SetMaxHDomain (const Array & mhd); /// DLL_HEADER double GetH (const Point3d & p) const; /// double GetMinH (const Point3d & pmin, const Point3d & pmax); /// bool HasLocalHFunction () { return lochfunc != nullptr; } /// LocalH & LocalHFunction () { return * lochfunc; } /// bool LocalHFunctionGenerated(void) const { return (lochfunc != NULL); } /// Find bounding box DLL_HEADER void GetBox (Point3d & pmin, Point3d & pmax, int dom = -1) const; /// Find bounding box of points of typ ptyp or less DLL_HEADER void GetBox (Point3d & pmin, Point3d & pmax, POINTTYPE ptyp ) const; /// int GetNOpenElements() const { return openelements.Size(); } /// const Element2d & OpenElement(int i) const { return openelements.Get(i); } auto & OpenElements() const { return openelements; } /// are also quads open elements bool HasOpenQuads () const; /// split into connected pieces DLL_HEADER void SplitIntoParts (); /// DLL_HEADER void SplitSeparatedFaces (); /// Refines mesh and projects points to true surface // void Refine (int levels, const CSGeometry * geom); bool BoundaryEdge (PointIndex pi1, PointIndex pi2) const { if(!boundaryedges) const_cast(this)->BuildBoundaryEdges(); INDEX_2 i2 (pi1, pi2); i2.Sort(); return boundaryedges->Used (i2); } bool IsSegment (PointIndex pi1, PointIndex pi2) const { INDEX_2 i2 (pi1, pi2); i2.Sort(); return segmentht->Used (i2); } SegmentIndex SegmentNr (PointIndex pi1, PointIndex pi2) const { INDEX_2 i2 (pi1, pi2); i2.Sort(); return segmentht->Get (i2); } /** Remove unused points. etc. */ DLL_HEADER void Compress (); /// first vertex has lowest index void OrderElements(); /// DLL_HEADER void Save (ostream & outfile) const; /// DLL_HEADER void Load (istream & infile); /// DLL_HEADER void Merge (istream & infile, const int surfindex_offset = 0); /// DLL_HEADER void Save (const string & filename) const; /// DLL_HEADER void Load (const string & filename); /// DLL_HEADER void Merge (const string & filename, const int surfindex_offset = 0); DLL_HEADER void DoArchive (Archive & archive); /// DLL_HEADER void ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY); /// void ImproveMeshJacobian (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY, const BitArray * usepoint = NULL); /// void ImproveMeshJacobianOnSurface (const MeshingParameters & mp, const BitArray & usepoint, const Array< Vec<3>* > & nv, OPTIMIZEGOAL goal = OPT_QUALITY, const Array< Array* > * idmaps = NULL); /** free nodes in environment of openelements for optimiztion */ void FreeOpenElementsEnvironment (int layers); /// bool LegalTet (Element & el) const { if (el.IllegalValid()) return !el.Illegal(); return LegalTet2 (el); } /// bool LegalTet2 (Element & el) const; /// bool LegalTrig (const Element2d & el) const; /** if values non-null, return values in 4-double array: triangle angles min/max, tetangles min/max if null, output results on cout */ DLL_HEADER void CalcMinMaxAngle (double badellimit, double * retvalues = NULL); /* Marks elements which are dangerous to refine return: number of illegal elements */ DLL_HEADER int MarkIllegalElements (); /// orient surface mesh, for one sub-domain only DLL_HEADER void SurfaceMeshOrientation (); /// convert mixed element mesh to tet-mesh DLL_HEADER void Split2Tets(); /// build box-search tree DLL_HEADER void BuildElementSearchTree (); void SetPointSearchStartElement(const int el) const {ps_startelement = el;} /// gives element of point, barycentric coordinates int GetElementOfPoint (const netgen::Point<3> & p, double * lami, bool build_searchtree = 0, const int index = -1, const bool allowindex = true) const; int GetElementOfPoint (const netgen::Point<3> & p, double * lami, const Array * const indices, bool build_searchtree = 0, const bool allowindex = true) const; int GetSurfaceElementOfPoint (const netgen::Point<3> & p, double * lami, bool build_searchtree = 0, const int index = -1, const bool allowindex = true) const; int GetSurfaceElementOfPoint (const netgen::Point<3> & p, double * lami, const Array * const indices, bool build_searchtree = 0, const bool allowindex = true) const; /// give list of vol elements which are int the box(p1,p2) void GetIntersectingVolEls(const Point3d& p1, const Point3d& p2, Array & locels) const; /// int AddFaceDescriptor(const FaceDescriptor& fd) { facedecoding.Append(fd); return facedecoding.Size(); } int AddEdgeDescriptor(const EdgeDescriptor & fd) { edgedecoding.Append(fd); return edgedecoding.Size() - 1; } auto GetCommunicator() const { return this->comm; } void SetCommunicator(NgMPI_Comm acomm); /// DLL_HEADER void SetMaterial (int domnr, const string & mat); /// DLL_HEADER const string & GetMaterial (int domnr) const; DLL_HEADER static string defaultmat; const string * GetMaterialPtr (int domnr) const // 1-based { return domnr <= materials.Size() ? materials.Get(domnr) : &defaultmat; } DLL_HEADER void SetNBCNames ( int nbcn ); DLL_HEADER void SetBCName ( int bcnr, const string & abcname ); DLL_HEADER const string & GetBCName ( int bcnr ) const; DLL_HEADER void SetNCD2Names (int ncd2n); DLL_HEADER void SetCD2Name (int cd2nr, const string & abcname); DLL_HEADER const string & GetCD2Name (int cd2nr ) const; DLL_HEADER static string cd2_default_name; string * GetCD2NamePtr (int cd2nr ) const { if (cd2nr < cd2names.Size() && cd2names[cd2nr]) return cd2names[cd2nr]; return &cd2_default_name; } size_t GetNCD2Names() const { return cd2names.Size(); } DLL_HEADER void SetNCD3Names (int ncd3n); DLL_HEADER void SetCD3Name (int cd3nr, const string & abcname); DLL_HEADER const string & GetCD3Name (int cd3nr ) const; DLL_HEADER static string cd3_default_name; string * GetCD3NamePtr (int cd3nr ) const { if (cd3nr < cd3names.Size() && cd3names[cd3nr]) return cd3names[cd3nr]; return &cd3_default_name; } size_t GetNCD3Names() const { return cd3names.Size(); } DLL_HEADER static string default_bc; string * GetBCNamePtr (int bcnr) const { return (bcnr < bcnames.Size() && bcnames[bcnr]) ? bcnames[bcnr] : &default_bc; } /// void ClearFaceDescriptors() { facedecoding.SetSize(0); } /// int GetNFD () const { return facedecoding.Size(); } const FaceDescriptor & GetFaceDescriptor (int i) const { return facedecoding.Get(i); } const EdgeDescriptor & GetEdgeDescriptor (int i) const { return edgedecoding[i]; } /// FaceDescriptor & GetFaceDescriptor (int i) { return facedecoding.Elem(i); } // #ifdef NONE // /* // Identify points pi1 and pi2, due to // identification nr identnr // */ // void AddIdentification (int pi1, int pi2, int identnr); // int GetIdentification (int pi1, int pi2) const; // int GetIdentificationSym (int pi1, int pi2) const; // /// // INDEX_2_HASHTABLE & GetIdentifiedPoints () // { // return *identifiedpoints; // } // /// // void GetIdentificationMap (int identnr, Array & identmap) const; // /// // void GetIdentificationPairs (int identnr, Array & identpairs) const; // /// // int GetMaxIdentificationNr () const // { // return maxidentnr; // } // #endif /// return periodic, close surface etc. identifications Identifications & GetIdentifications () { return *ident; } /// return periodic, close surface etc. identifications const Identifications & GetIdentifications () const { return *ident; } /// bool HasIdentifications() const { return ident != nullptr; } void InitPointCurve(double red = 1, double green = 0, double blue = 0) const; void AddPointCurvePoint(const Point3d & pt) const; int GetNumPointCurves(void) const; int GetNumPointsOfPointCurve(int curve) const; Point3d & GetPointCurvePoint(int curve, int n) const; void GetPointCurveColor(int curve, double & red, double & green, double & blue) const; /// find number of vertices void ComputeNVertices (); /// number of vertices (no edge-midpoints) int GetNV () const; /// remove edge points void SetNP (int np); DLL_HEADER bool PureTrigMesh (int faceindex = 0) const; DLL_HEADER bool PureTetMesh () const; const MeshTopology & GetTopology () const { return topology; } DLL_HEADER void UpdateTopology (TaskManager tm = &DummyTaskManager, Tracer tracer = &DummyTracer); class CurvedElements & GetCurvedElements () const { return *curvedelems; } DLL_HEADER void BuildCurvedElements (const class Refinement * ref, int aorder, bool arational = false); DLL_HEADER void BuildCurvedElements (int aorder); const class AnisotropicClusters & GetClusters () const { return *clusters; } class CSurfaceArea { const Mesh & mesh; bool valid; double area; public: CSurfaceArea (const Mesh & amesh) : mesh(amesh), valid(false) { ; } void Add (const Element2d & sel) { if (sel.GetNP() == 3) area += Cross ( mesh[sel[1]]-mesh[sel[0]], mesh[sel[2]]-mesh[sel[0]] ).Length() / 2; else area += Cross (Vec3d (mesh[sel.PNum(1)], mesh[sel.PNum(3)]), Vec3d (mesh[sel.PNum(1)], mesh[sel.PNum(4)])).Length() / 2;; } void ReCalc () { area = 0; for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) Add (mesh[sei]); valid = true; } operator double () const { return area; } bool Valid() const { return valid; } }; CSurfaceArea surfarea; CSurfaceArea & SurfaceArea() { return surfarea; } const CSurfaceArea & SurfaceArea() const { return surfarea; } int GetTimeStamp() const { return timestamp; } void SetNextTimeStamp() { timestamp = NextTimeStamp(); } int GetMajorTimeStamp() const { return majortimestamp; } void SetNextMajorTimeStamp() { majortimestamp = timestamp = NextTimeStamp(); } /// return mutex NgMutex & Mutex () { return mutex; } NgMutex & MajorMutex () { return majormutex; } shared_ptr GetGeometry() const { return geometry; } void SetGeometry (shared_ptr geom) { geometry = geom; } /// void SetUserData(const char * id, Array & data); /// bool GetUserData(const char * id, Array & data, int shift = 0) const; /// void SetUserData(const char * id, Array & data); /// bool GetUserData(const char * id, Array & data, int shift = 0) const; /// friend void OptimizeRestart (Mesh & mesh3d); /// void PrintMemInfo (ostream & ost) const; /// friend class Meshing3; enum GEOM_TYPE { NO_GEOM = 0, GEOM_2D = 1, GEOM_CSG = 10, GEOM_STL = 11, GEOM_OCC = 12, GEOM_ACIS = 13 }; GEOM_TYPE geomtype; #ifdef PARALLEL /// returns parallel topology class ParallelMeshTopology & GetParallelTopology () const { return *paralleltop; } /// distributes the master-mesh to local meshes void Distribute (); void Distribute (Array & volume_weights, Array & surface_weights, Array & segment_weights); /// find connection to parallel meshes // void FindExchangePoints () ; // void FindExchangeEdges (); // void FindExchangeFaces (); /// use metis to decompose master mesh void ParallelMetis (); // Array & neloc ); void ParallelMetis (Array & volume_weights, Array & surface_weights, Array & segment_weights); void PartHybridMesh (); // Array & neloc ); void PartDualHybridMesh (); // Array & neloc ); void PartDualHybridMesh2D (); // ( Array & neloc ); /// send mesh from master to local procs void SendRecvMesh (); /// send mesh to parallel machine, keep global mesh at master void SendMesh ( ) const; // Mesh * mastermesh, Array & neloc) const; /// loads a mesh sent from master processor void ReceiveParallelMesh (); Array vol_partition; Array surf_partition; Array seg_partition; #else void Distribute () {} void SendRecvMesh () {} void Distribute (Array & volume_weights, Array & surface_weights, Array & segment_weights){ } #endif }; inline ostream& operator<<(ostream& ost, const Mesh& mesh) { ost << "mesh: " << endl; mesh.Save(ost); return ost; } } #endif netgen-6.2.1905/libsrc/meshing/localh.hpp0000644000175000017500000001072613504650527016672 0ustar kurtkurt#ifndef LOCALH #define LOCALH /**************************************************************************/ /* File: localh.hh */ /* Author: Joachim Schoeberl */ /* Date: 29. Jan. 97 */ /**************************************************************************/ namespace netgen { /// box for grading class GradingBox { /// xmid float xmid[3]; /// half edgelength float h2; /// GradingBox * childs[8]; /// GradingBox * father; /// double hopt; /// public: struct { unsigned int cutboundary:1; unsigned int isinner:1; unsigned int oldcell:1; unsigned int pinner:1; } flags; /// GradingBox (const double * ax1, const double * ax2); /// void DeleteChilds(); /// Point<3> PMid() const { return Point<3> (xmid[0], xmid[1], xmid[2]); } double H2() const { return h2; } bool HasChilds() const { for (int i = 0; i < 8; i++) if (childs[i]) return true; return false; } friend class LocalH; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; /** Control of 3D mesh grading */ class LocalH { /// GradingBox * root; /// double grading; /// Array boxes; /// Box<3> boundingbox; /// octree or quadtree int dimension; public: /// LocalH (Point<3> pmin, Point<3> pmax, double grading, int adimension = 3); /// LocalH (const Box<3> & box, double grading, int adimension = 3) : LocalH (box.PMin(), box.PMax(), grading, adimension) { ; } /// ~LocalH(); /// void Delete(); /// void SetGrading (double agrading) { grading = agrading; } /// void SetH (Point<3> x, double h); /// double GetH (Point<3> x) const; /// minimal h in box (pmin, pmax) double GetMinH (Point<3> pmin, Point<3> pmax) const; /// mark boxes intersecting with boundary-box // void CutBoundary (const Point3d & pmin, const Point3d & pmax) // { CutBoundaryRec (pmin, pmax, root); } void CutBoundary (const Box<3> & box) { CutBoundaryRec (box.PMin(), box.PMax(), root); } /// find inner boxes void FindInnerBoxes (class AdFront3 * adfront, int (*testinner)(const Point3d & p1)); void FindInnerBoxes (class AdFront2 * adfront, int (*testinner)(const Point<2> & p1)); /// clears all flags void ClearFlags () { ClearFlagsRec(root); } /// widen refinement zone void WidenRefinement (); /// get points in inner elements void GetInnerPoints (Array > & points); /// get points in outer closure void GetOuterPoints (Array > & points); /// void Convexify (); /// int GetNBoxes () { return boxes.Size(); } const Box<3> & GetBoundingBox () const { return boundingbox; } /// void PrintMemInfo (ostream & ost) const; private: /// double GetMinHRec (const Point3d & pmin, const Point3d & pmax, const GradingBox * box) const; /// void CutBoundaryRec (const Point3d & pmin, const Point3d & pmax, GradingBox * box); /// void FindInnerBoxesRec ( int (*inner)(const Point3d & p), GradingBox * box); /// void FindInnerBoxesRec2 (GradingBox * box, class AdFront3 * adfront, Array & faceboxes, Array & finds, int nfinbox); void FindInnerBoxesRec ( int (*inner)(const Point<2> & p), GradingBox * box); /// void FindInnerBoxesRec2 (GradingBox * box, class AdFront2 * adfront, Array > & faceboxes, Array & finds, int nfinbox); /// void SetInnerBoxesRec (GradingBox * box); /// void ClearFlagsRec (GradingBox * box); /// void ConvexifyRec (GradingBox * box); friend ostream & operator<< (ostream & ost, const LocalH & loch); }; inline ostream & operator<< (ostream & ost, const GradingBox & box) { ost << "gradbox, pmid = " << box.PMid() << ", h2 = " << box.H2() << " cutbound = " << box.flags.cutboundary << " isinner = " << box.flags.isinner << endl; return ost; } inline ostream & operator<< (ostream & ost, const LocalH & loch) { for (int i = 0; i < loch.boxes.Size(); i++) ost << "box[" << i << "] = " << *(loch.boxes[i]); return ost; } } #endif netgen-6.2.1905/libsrc/meshing/improve3.hpp0000644000175000017500000000671213504650527017174 0ustar kurtkurt#ifndef FILE_IMPROVE3 #define FILE_IMPROVE3 extern double CalcTotalBad (const Mesh::T_POINTS & points, const Mesh::T_VOLELEMENTS & elements, const MeshingParameters & mp); /// class MeshOptimize3d { const MeshingParameters & mp; public: MeshOptimize3d (const MeshingParameters & amp) : mp(amp) { ; } void CombineImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); void SplitImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); void SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY, const BitArray * working_elements = NULL); void SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY, const BitArray * working_elements = NULL, const Array< Array* > * idmaps = NULL); void SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); double CalcBad (const Mesh::T_POINTS & points, const Element & elem, double h) { if (elem.GetType() == TET) return CalcTetBadness (points[elem[0]], points[elem[1]], points[elem[2]], points[elem[3]], h, mp); return 0; } double CalcTotalBad (const Mesh::T_POINTS & points, const Mesh::T_VOLELEMENTS & elements) { return netgen::CalcTotalBad (points, elements, mp); } }; inline double CalcBad (const Mesh::T_POINTS & points, const Element & elem, double h, const MeshingParameters & mp) { if (elem.GetType() == TET) return CalcTetBadness (points[elem[0]], points[elem[1]], points[elem[2]], points[elem[3]], h, mp); return 0; } extern int WrongOrientation (const Mesh::T_POINTS & points, const Element & el); /* Functional depending of inner point inside triangular surface */ class MinFunctionSum : public MinFunction { protected: Array functions; public: virtual double Func (const Vector & x) const; virtual void Grad (const Vector & x, Vector & g) const; virtual double FuncGrad (const Vector & x, Vector & g) const; virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; virtual double GradStopping (const Vector & x) const; void AddFunction(MinFunction & fun); const MinFunction & Function(int i) const; MinFunction & Function(int i); }; class PointFunction1 : public MinFunction { Mesh::T_POINTS & points; const Array & faces; const MeshingParameters & mp; double h; public: PointFunction1 (Mesh::T_POINTS & apoints, const Array & afaces, const MeshingParameters & amp, double ah); virtual double Func (const Vector & x) const; virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; virtual double FuncGrad (const Vector & x, Vector & g) const; virtual double GradStopping (const Vector & x) const; }; class JacobianPointFunction : public MinFunction { public: Mesh::T_POINTS & points; const Mesh::T_VOLELEMENTS & elements; TABLE elementsonpoint; PointIndex actpind; bool onplane; Vec<3> nv; public: JacobianPointFunction (Mesh::T_POINTS & apoints, const Mesh::T_VOLELEMENTS & aelements); virtual ~JacobianPointFunction () { ; } virtual void SetPointIndex (PointIndex aactpind); virtual double Func (const Vector & x) const; virtual double FuncGrad (const Vector & x, Vector & g) const; virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; inline void SetNV(const Vec<3> & anv) {nv = anv; onplane = true;} inline void UnSetNV(void) {onplane = false;} }; #endif netgen-6.2.1905/libsrc/meshing/bisect.cpp0000644000175000017500000030232613504650527016674 0ustar kurtkurt#include #include "meshing.hpp" #define noDEBUG namespace netgen { class MarkedTet; class MarkedPrism; class MarkedIdentification; class MarkedTri; class MarkedQuad; typedef Array T_MTETS; typedef Array T_MPRISMS; typedef Array T_MIDS; typedef Array T_MTRIS; typedef Array T_MQUADS; class MarkedTet { public: /// pnums of tet PointIndex pnums[4]; /// material number int matindex; /// element marked for refinement /// marked = 1: marked by element marker, marked = 2 due to closure unsigned int marked:2; /// flag of Arnold-Mukherjee algorithm unsigned int flagged:1; /// tetedge (local coordinates 0..3) unsigned int tetedge1:3; unsigned int tetedge2:3; // marked edge of faces // face_j : face without node j, // mark_k : edge without node k char faceedges[4]; // unsigned char faceedges[4]; bool incorder; unsigned int order:6; MarkedTet() = default; /* { for (int i = 0; i < 4; i++) { faceedges[i] = 127; } } */ MarkedTet (const MarkedTet&) = default; MarkedTet (MarkedTet &&) = default; MarkedTet & operator= (const MarkedTet&) = default; MarkedTet & operator= (MarkedTet&&) = default; }; ostream & operator<< (ostream & ost, const MarkedTet & mt) { for(int i=0; i<4; i++) ost << mt.pnums[i] << " "; ost << mt.matindex << " " << int(mt.marked) << " " << int(mt.flagged) << " " << int(mt.tetedge1) << " " << int(mt.tetedge2) << " "; ost << "faceedges = "; for(int i=0; i<4; i++) ost << int(mt.faceedges[i]) << " "; ost << " order = "; ost << mt.incorder << " " << int(mt.order) << "\n"; return ost; } istream & operator>> (istream & ost, MarkedTet & mt) { for(int i=0; i<4; i++) ost >> mt.pnums[i]; ost >> mt.matindex; int auxint; ost >> auxint; mt.marked = auxint; ost >> auxint; mt.flagged = auxint; ost >> auxint; mt.tetedge1 = auxint; ost >> auxint; mt.tetedge2 = auxint; char auxchar; for(int i=0; i<4; i++) { ost >> auxchar; mt.faceedges[i] = auxchar; } ost >> mt.incorder; ost >> auxint; mt.order = auxint; return ost; } class MarkedPrism { public: /// 6 point numbers PointIndex pnums[6]; /// material number int matindex; /// marked for refinement int marked; /// edge without node k (0,1,2) int markededge; bool incorder; unsigned int order:6; }; ostream & operator<< (ostream & ost, const MarkedPrism & mp) { for(int i=0; i<6; i++) ost << mp.pnums[i] << " "; ost << mp.matindex << " " << mp.marked << " " << mp.markededge << " " << mp.incorder << " " << int(mp.order) << "\n"; return ost; } istream & operator>> (istream & ist, MarkedPrism & mp) { for(int i=0; i<6; i++) ist >> mp.pnums[i]; ist >> mp.matindex >> mp.marked >> mp.markededge >> mp.incorder; int auxint; ist >> auxint; mp.order = auxint; return ist; } class MarkedIdentification { public: // number of points of one face (3 or 4) - or edge (in 2d) int np; /// 6 or 8 point numbers - or 4 in 2d PointIndex pnums[8]; /// marked for refinement int marked; /// edge starting with node k (0,1,2, or 3) int markededge; bool incorder; unsigned int order:6; }; ostream & operator<< (ostream & ost, const MarkedIdentification & mi) { ost << mi.np << " "; for(int i=0; i<2*mi.np; i++) ost << mi.pnums[i] << " "; ost << mi.marked << " " << mi.markededge << " " << mi.incorder << " " << int(mi.order) << "\n"; return ost; } istream & operator>> (istream & ist, MarkedIdentification & mi) { ist >> mi.np; for(int i=0; i<2*mi.np; i++) ist >> mi.pnums[i]; ist >> mi.marked >> mi.markededge >> mi.incorder; int auxint; ist >> auxint; mi.order = auxint; return ist; } class MarkedTri { public: MarkedTri () = default; MarkedTri (const MarkedTri&) = default; MarkedTri (MarkedTri &&) = default; MarkedTri & operator= (const MarkedTri&) = default; MarkedTri & operator= (MarkedTri&&) = default; /// three point numbers PointIndex pnums[3]; /// three geominfos PointGeomInfo pgeominfo[3]; /// marked for refinement int marked; /// edge without node k int markededge; /// surface id int surfid; bool incorder; unsigned int order:6; }; ostream & operator<< (ostream & ost, const MarkedTri & mt) { for(int i=0; i<3; i++) ost << mt.pnums[i] << " "; for(int i=0; i<3; i++) ost << mt.pgeominfo[i] << " "; ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n"; return ost; } istream & operator>> (istream & ist, MarkedTri & mt) { for(int i=0; i<3; i++) ist >> mt.pnums[i]; for(int i=0; i<3; i++) ist >> mt.pgeominfo[i]; ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder; int auxint; ist >> auxint; mt.order = auxint; return ist; } class MarkedQuad { public: /// point numbers PointIndex pnums[4]; /// PointGeomInfo pgeominfo[4]; /// marked for refinement int marked; /// marked edge: 0/2 = vertical, 1/3 = horizontal int markededge; /// surface id int surfid; bool incorder; unsigned int order:6; }; ostream & operator<< (ostream & ost, const MarkedQuad & mt) { for(int i=0; i<4; i++) ost << mt.pnums[i] << " "; for(int i=0; i<4; i++) ost << mt.pgeominfo[i] << " "; ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n"; return ost; } istream & operator>> (istream & ist, MarkedQuad & mt) { for(int i=0; i<4; i++) ist >> mt.pnums[i]; for(int i=0; i<4; i++) ist >> mt.pgeominfo[i]; ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder; int auxint; ist >> auxint; mt.order = auxint; return ist; } void PrettyPrint(ostream & ost, const MarkedTet & mt) { int te1 = mt.tetedge1; int te2 = mt.tetedge2; int order = mt.order; ost << "MT: " << mt.pnums[0] << " - " << mt.pnums[1] << " - " << mt.pnums[2] << " - " << mt.pnums[3] << endl << "marked edge: " << te1 << " - " << te2 << ", order = " << order << endl; //for (int k = 0; k < 4; k++) // ost << int(mt.faceedges[k]) << " "; for (int k = 0; k < 4; k++) { ost << "face"; for (int j=0; j<4; j++) if(j != k) ost << " " << mt.pnums[j]; for(int i=0; i<3; i++) for(int j=i+1; j<4; j++) if(i != k && j != k && int(mt.faceedges[k]) == 6-k-i-j) ost << " marked edge " << mt.pnums[i] << " " << mt.pnums[j] << endl; } ost << endl; } int BTSortEdges (const Mesh & mesh, const Array< Array* > & idmaps, INDEX_2_CLOSED_HASHTABLE & edgenumber) { PrintMessage(4,"sorting ... "); // if (mesh.PureTetMesh()) if (1) { // new, fast version Array edges; Array eclasses; int i, j, k; int cntedges = 0; int go_on; int ned(0); // enumerate edges: for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement (i); static int tetedges[6][2] = { { 1, 2 }, { 1, 3 }, { 1, 4 }, { 2, 3 }, { 2, 4 }, { 3, 4 } } ; static int prismedges[9][2] = { { 1, 2 }, { 1, 3 }, { 2, 3 }, { 4, 5 }, { 4, 6 }, { 5, 6 }, { 1, 4 }, { 2, 5 }, { 3, 6 } }; int pyramidedges[6][2] = { { 1, 2 }, { 3, 4 }, { 1, 5 }, { 2, 5 }, { 3, 5 }, { 4, 5 } }; int (*tip)[2] = NULL; switch (el.GetType()) { case TET: case TET10: { tip = tetedges; ned = 6; break; } case PRISM: case PRISM12: { tip = prismedges; ned = 6; break; } case PYRAMID: { tip = pyramidedges; ned = 6; break; } default: throw NgException("Bisect, element type not handled in switch"); } for (j = 0; j < ned; j++) { INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1])); i2.Sort(); //(*testout) << "edge " << i2 << endl; if (!edgenumber.Used(i2)) { cntedges++; edges.Append (i2); edgenumber.Set(i2, cntedges); } } } // additional surface edges: for (i = 1; i <= mesh.GetNSE(); i++) { const Element2d & el = mesh.SurfaceElement (i); static int trigedges[3][2] = { { 1, 2 }, { 2, 3 }, { 3, 1 } }; static int quadedges[4][2] = { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 1 } }; int (*tip)[2] = NULL; switch (el.GetType()) { case TRIG: case TRIG6: { tip = trigedges; ned = 3; break; } case QUAD: case QUAD6: { tip = quadedges; ned = 4; break; } default: { cerr << "Error: Sort for Bisect, SE has " << el.GetNP() << " points" << endl; ned = 0; } } for (j = 0; j < ned; j++) { INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1])); i2.Sort(); if (!edgenumber.Used(i2)) { cntedges++; edges.Append (i2); edgenumber.Set(i2, cntedges); } } } eclasses.SetSize (cntedges); for (i = 1; i <= cntedges; i++) eclasses.Elem(i) = i; // identify edges in element stack do { go_on = 0; for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement (i); if (el.GetType() != PRISM && el.GetType() != PRISM12 && el.GetType() != PYRAMID) continue; int prismpairs[3][4] = { { 1, 2, 4, 5 }, { 2, 3, 5, 6 }, { 1, 3, 4, 6 } }; int pyramidpairs[3][4] = { { 1, 2, 4, 3 }, { 1, 5, 4, 5 }, { 2, 5, 3, 5 } }; int (*pairs)[4] = NULL; switch (el.GetType()) { case PRISM: case PRISM12: { pairs = prismpairs; break; } case PYRAMID: { pairs = pyramidpairs; break; } default: throw NgException("Bisect, element type not handled in switch, 2"); } for (j = 0; j < 3; j++) { INDEX_2 e1 (el.PNum(pairs[j][0]), el.PNum(pairs[j][1])); INDEX_2 e2 (el.PNum(pairs[j][2]), el.PNum(pairs[j][3])); e1.Sort(); e2.Sort(); int eclass1 = edgenumber.Get (e1); int eclass2 = edgenumber.Get (e2); // (*testout) << "identify edges " << eclass1 << "-" << eclass2 << endl; if (eclasses.Get(eclass1) > eclasses.Get(eclass2)) { eclasses.Elem(eclass1) = eclasses.Get(eclass2); go_on = 1; } else if (eclasses.Get(eclass2) > eclasses.Get(eclass1)) { eclasses.Elem(eclass2) = eclasses.Get(eclass1); go_on = 1; } } } for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el2d = mesh[sei]; for(i = 0; i < el2d.GetNP(); i++) { INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]); e1.Sort(); INDEX_2 e2; for(k = 0; k < idmaps.Size(); k++) { e2.I1() = (*idmaps[k])[e1.I1()]; e2.I2() = (*idmaps[k])[e1.I2()]; if(e2.I1() == 0 || e2.I2() == 0 || e1.I1() == e2.I1() || e1.I2() == e2.I2()) continue; e2.Sort(); if(!edgenumber.Used(e2)) continue; int eclass1 = edgenumber.Get (e1); int eclass2 = edgenumber.Get (e2); if (eclasses.Get(eclass1) > eclasses.Get(eclass2)) { eclasses.Elem(eclass1) = eclasses.Get(eclass2); go_on = 1; } else if (eclasses.Get(eclass2) > eclasses.Get(eclass1)) { eclasses.Elem(eclass2) = eclasses.Get(eclass1); go_on = 1; } } } } } while (go_on); // for (i = 1; i <= cntedges; i++) // { // (*testout) << "edge " << i << ": " // << edges.Get(i).I1() << "-" << edges.Get(i).I2() // << ", class = " << eclasses.Get(i) << endl; // } // compute classlength: Array edgelength(cntedges); /* for (i = 1; i <= cntedges; i++) edgelength.Elem(i) = 1e20; */ for (i = 1; i <= cntedges; i++) { INDEX_2 edge = edges.Get(i); double elen = Dist (mesh.Point(edge.I1()), mesh.Point(edge.I2())); edgelength.Elem (i) = elen; } /* for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement (i); if (el.GetType() == TET) { for (j = 1; j <= 3; j++) for (k = j+1; k <= 4; k++) { INDEX_2 i2(el.PNum(j), el.PNum(k)); i2.Sort(); int enr = edgenumber.Get(i2); double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); if (elen < edgelength.Get(enr)) edgelength.Set (enr, elen); } } else if (el.GetType() == PRISM) { for (j = 1; j <= 3; j++) { k = (j % 3) + 1; INDEX_2 i2(el.PNum(j), el.PNum(k)); i2.Sort(); int enr = edgenumber.Get(i2); double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); if (elen < edgelength.Get(enr)) edgelength.Set (enr, elen); i2 = INDEX_2(el.PNum(j+3), el.PNum(k+3)); i2.Sort(); enr = edgenumber.Get(i2); elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); if (elen < edgelength.Get(enr)) edgelength.Set (enr, elen); if (!edgenumber.Used(i2)) { cntedges++; edgenumber.Set(i2, cntedges); } i2 = INDEX_2(el.PNum(j), el.PNum(j+3)); i2.Sort(); enr = edgenumber.Get(i2); elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); if (elen < edgelength.Get(enr)) edgelength.Set (enr, elen); } } } */ for (i = 1; i <= cntedges; i++) { if (eclasses.Get(i) != i) { if (edgelength.Get(i) < edgelength.Get(eclasses.Get(i))) edgelength.Elem(eclasses.Get(i)) = edgelength.Get(i); edgelength.Elem(i) = 1e20; } } TABLE eclasstab(cntedges); for (i = 1; i <= cntedges; i++) eclasstab.Add1 (eclasses.Get(i), i); // sort edges: Array sorted(cntedges); QuickSort (edgelength, sorted); int cnt = 0; for (i = 1; i <= cntedges; i++) { int ii = sorted.Get(i); for (j = 1; j <= eclasstab.EntrySize(ii); j++) { cnt++; edgenumber.Set (edges.Get(eclasstab.Get(ii, j)), cnt); } } return cnt; } else { // old version int i, j; int cnt = 0; int found; double len2, maxlen2; INDEX_2 ep; // sort edges by length, parallel edges (on prisms) // are added in blocks do { found = 0; maxlen2 = 1e30; for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement (i); int ned; int tetedges[6][2] = { { 1, 2 }, { 1, 3 }, { 1, 4 }, { 2, 3 }, { 2, 4 }, { 3, 4 } }; int prismedges[6][2] = { { 1, 2 }, { 1, 3 }, { 2, 4 }, { 4, 5 }, { 4, 6 }, { 5, 6 } }; int pyramidedges[6][2] = { { 1, 2 }, { 3, 4 }, { 1, 5 }, { 2, 5 }, { 3, 5 }, { 4, 5 } }; int (*tip)[2]; switch (el.GetType()) { case TET: { tip = tetedges; ned = 6; break; } case PRISM: { tip = prismedges; ned = 6; break; } case PYRAMID: { tip = pyramidedges; ned = 6; break; } default: throw NgException("Bisect, element type not handled in switch, 3"); } for (j = 0; j < ned; j++) { INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1])); i2.Sort(); if (!edgenumber.Used(i2)) { len2 = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); if (len2 < maxlen2) { maxlen2 = len2; ep = i2; found = 1; } } } } if (found) { cnt++; edgenumber.Set (ep, cnt); // find connected edges: int go_on = 0; do { go_on = 0; for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement (i); if (el.GetNP() != 6) continue; int prismpairs[3][4] = { { 1, 2, 4, 5 }, { 2, 3, 5, 6 }, { 1, 3, 4, 6 } }; int pyramidpairs[3][4] = { { 1, 2, 4, 3 }, { 1, 5, 4, 5 }, { 2, 5, 3, 5 } }; int (*pairs)[4]; switch (el.GetType()) { case PRISM: { pairs = prismpairs; break; } case PYRAMID: { pairs = pyramidpairs; break; } default: throw NgException("Bisect, element type not handled in switch, 3a"); } for (j = 0; j < 3; j++) { INDEX_2 e1 (el.PNum(pairs[j][0]), el.PNum(pairs[j][1])); INDEX_2 e2 (el.PNum(pairs[j][2]), el.PNum(pairs[j][3])); e1.Sort(); e2.Sort(); int used1 = edgenumber.Used (e1); int used2 = edgenumber.Used (e2); if (used1 && !used2) { cnt++; edgenumber.Set (e2, cnt); go_on = 1; } if (used2 && !used1) { cnt++; edgenumber.Set (e1, cnt); go_on = 1; } } } } while (go_on); } } while (found); return cnt; } } void BTDefineMarkedTet (const Element & el, INDEX_2_CLOSED_HASHTABLE & edgenumber, MarkedTet & mt) { for (int i = 0; i < 4; i++) mt.pnums[i] = el[i]; mt.marked = 0; mt.flagged = 0; mt.incorder = 0; mt.order = 1; int val = 0; // find marked edge of tet: for (int i = 0; i < 3; i++) for (int j = i+1; j < 4; j++) { INDEX_2 i2(mt.pnums[i], mt.pnums[j]); i2.Sort(); int hval = edgenumber.Get(i2); if (hval > val) { val = hval; mt.tetedge1 = i; mt.tetedge2 = j; } } // find marked edges of faces: for (int k = 0; k < 4; k++) { val = 0; for (int i = 0; i < 3; i++) for (int j = i+1; j < 4; j++) if (i != k && j != k) { INDEX_2 i2(mt.pnums[i], mt.pnums[j]); i2.Sort(); int hval = edgenumber.Get(i2); if (hval > val) { val = hval; int hi = 6 - k - i - j; mt.faceedges[k] = char(hi); } } } } void BTDefineMarkedPrism (const Element & el, INDEX_2_CLOSED_HASHTABLE & edgenumber, MarkedPrism & mp) { if (el.GetType() == PRISM || el.GetType() == PRISM12) { for (int i = 0; i < 6; i++) mp.pnums[i] = el[i]; } else if (el.GetType() == PYRAMID) { static int map[6] = { 1, 2, 5, 4, 3, 5 }; for (int i = 0; i < 6; i++) mp.pnums[i] = el.PNum(map[i]); } else if (el.GetType() == TET || el.GetType() == TET10) { static int map[6] = { 1, 4, 3, 2, 4, 3 }; for (int i = 0; i < 6; i++) mp.pnums[i] = el.PNum(map[i]); } else { PrintSysError ("Define marked prism called for non-prism and non-pyramid"); } mp.marked = 0; mp.incorder = 0; mp.order = 1; int val = 0; for (int i = 0; i < 2; i++) for (int j = i+1; j < 3; j++) { INDEX_2 i2(mp.pnums[i], mp.pnums[j]); i2.Sort(); int hval = edgenumber.Get(i2); if (hval > val) { val = hval; mp.markededge = 3 - i - j; } } } bool BTDefineMarkedId(const Element2d & el, INDEX_2_CLOSED_HASHTABLE & edgenumber, const Array & idmap, MarkedIdentification & mi) { bool identified = true; mi.np = el.GetNP(); int min1(0),min2(0); for(int j = 0; identified && j < mi.np; j++) { mi.pnums[j] = el[j]; mi.pnums[j+mi.np] = idmap[el[j]]; if(j == 0 || el[j] < min1) min1 = el[j]; if(j == 0 || mi.pnums[j+mi.np] < min2) min2 = mi.pnums[j+mi.np]; identified = (mi.pnums[j+mi.np] != 0 && mi.pnums[j+mi.np] != mi.pnums[j]); } identified = identified && (min1 < min2); if(identified) { mi.marked = 0; mi.incorder = 0; mi.order = 1; int val = 0; for (int i = 0; i < mi.np; i++) { INDEX_2 i2(mi.pnums[i], mi.pnums[(i+1)%mi.np]); i2.Sort(); int hval = edgenumber.Get(i2); if (hval > val) { val = hval; mi.markededge = i; } } } return identified; } void BTDefineMarkedTri (const Element2d & el, INDEX_2_CLOSED_HASHTABLE & edgenumber, MarkedTri & mt) { for (int i = 0; i < 3; i++) { mt.pnums[i] = el[i]; mt.pgeominfo[i] = el.GeomInfoPi (i+1); } mt.marked = 0; mt.surfid = el.GetIndex(); mt.incorder = 0; mt.order = 1; int val = 0; for (int i = 0; i < 2; i++) for (int j = i+1; j < 3; j++) { INDEX_2 i2(mt.pnums[i], mt.pnums[j]); i2.Sort(); int hval = edgenumber.Get(i2); if (hval > val) { val = hval; mt.markededge = 3 - i - j; } } } void PrettyPrint(ostream & ost, const MarkedTri & mt) { ost << "MarkedTrig: " << endl; ost << " pnums = "; for (int i=0; i<3; i++) ost << mt.pnums[i] << " "; ost << endl; ost << " marked = " << mt.marked << ", markededge=" << mt.markededge << endl; for(int i=0; i<2; i++) for(int j=i+1; j<3; j++) if(mt.markededge == 3-i-j) ost << " marked edge pnums = " << mt.pnums[i] << " " << mt.pnums[j] << endl; } void PrettyPrint(ostream & ost, const MarkedQuad & mq) { ost << "MarkedQuad: " << endl; ost << " pnums = "; for (int i=0; i<4; i++) ost << mq.pnums[i] << " "; ost << endl; ost << " marked = " << mq.marked << ", markededge=" << mq.markededge << endl; } void BTDefineMarkedQuad (const Element2d & el, INDEX_2_CLOSED_HASHTABLE & edgenumber, MarkedQuad & mq) { for (int i = 0; i < 4; i++) mq.pnums[i] = el[i]; Swap (mq.pnums[2], mq.pnums[3]); mq.marked = 0; mq.markededge = 0; mq.surfid = el.GetIndex(); } // mark elements due to local h int BTMarkTets (T_MTETS & mtets, T_MPRISMS & mprisms, const Mesh & mesh) { int marked = 0; int np = mesh.GetNP(); Vector hv(np); for (int i = 0; i < np; i++) hv(i) = mesh.GetH (mesh.Point(i+1)); double hfac = 1; for (int step = 1; step <= 2; step++) { for (int i = 1; i <= mtets.Size(); i++) { double h = 0; for (int j = 0; j < 3; j++) for (int k = j+1; k < 4; k++) { const Point<3> & p1 = mesh.Point (mtets.Get(i).pnums[j]); const Point<3> & p2 = mesh.Point (mtets.Get(i).pnums[k]); double hh = Dist2 (p1, p2); if (hh > h) h = hh; } h = sqrt (h); double hshould = 1e10; for (int j = 0; j < 4; j++) { double hi = hv (mtets.Get(i).pnums[j]-1); if (hi < hshould) hshould = hi; } if (step == 1) { if (h / hshould > hfac) hfac = h / hshould; } else { if (h > hshould * hfac) { mtets.Elem(i).marked = 1; marked = 1; } else mtets.Elem(i).marked = 0; } } for (int i = 1; i <= mprisms.Size(); i++) { double h = 0; for (int j = 0; j < 2; j++) for (int k = j+1; k < 3; k++) { const Point<3> & p1 = mesh.Point (mprisms.Get(i).pnums[j]); const Point<3> & p2 = mesh.Point (mprisms.Get(i).pnums[k]); double hh = Dist2 (p1, p2); if (hh > h) h = hh; } h = sqrt (h); double hshould = 1e10; for (int j = 0; j < 6; j++) { double hi = hv (mprisms.Get(i).pnums[j]-1); if (hi < hshould) hshould = hi; } if (step == 1) { if (h / hshould > hfac) hfac = h / hshould; } else { if (h > hshould * hfac) { mprisms.Elem(i).marked = 1; marked = 1; } else mprisms.Elem(i).marked = 0; } } if (step == 1) { if (hfac > 2) hfac /= 2; else hfac = 1; } } return marked; } void BTBisectTet (const MarkedTet & oldtet, int newp, MarkedTet & newtet1, MarkedTet & newtet2) { #ifdef DEBUG *testout << "bisect tet " << oldtet << endl; #endif // points vis a vis from tet-edge int vis1, vis2; vis1 = 0; while (vis1 == oldtet.tetedge1 || vis1 == oldtet.tetedge2) vis1++; vis2 = 6 - vis1 - oldtet.tetedge1 - oldtet.tetedge2; // is tet of type P ? int istypep = 0; for (int i = 0; i < 4; i++) { int cnt = 0; for (int j = 0; j < 4; j++) if (oldtet.faceedges[j] == i) cnt++; if (cnt == 3) istypep = 1; } for (int i = 0; i < 4; i++) { newtet1.pnums[i] = oldtet.pnums[i]; newtet2.pnums[i] = oldtet.pnums[i]; } newtet1.flagged = istypep && !oldtet.flagged; newtet2.flagged = istypep && !oldtet.flagged; int nm = oldtet.marked - 1; if (nm < 0) nm = 0; newtet1.marked = nm; newtet2.marked = nm; #ifdef DEBUG *testout << "newtet1,before = " << newtet1 << endl; *testout << "newtet2,before = " << newtet2 << endl; #endif for (int i = 0; i < 4; i++) { if (i == oldtet.tetedge1) { newtet2.pnums[i] = newp; newtet2.faceedges[i] = oldtet.faceedges[i]; // inherited face newtet2.faceedges[vis1] = i; // cut faces newtet2.faceedges[vis2] = i; int j = 0; while (j == i || j == oldtet.faceedges[i]) j++; int k = 6 - i - oldtet.faceedges[i] - j; newtet2.tetedge1 = j; // tet-edge newtet2.tetedge2 = k; // new face: if (istypep && oldtet.flagged) { int hi = 6 - oldtet.tetedge1 - j - k; newtet2.faceedges[oldtet.tetedge2] = char(hi); } else newtet2.faceedges[oldtet.tetedge2] = oldtet.tetedge1; #ifdef DEBUG *testout << "i = " << i << ", j = " << j << " k = " << k << " oldtet.tetedge1 = " << oldtet.tetedge1 << " oldtet.tetedge2 = " << oldtet.tetedge2 << " 6-oldtet.tetedge1-j-k = " << 6 - oldtet.tetedge1 - j - k << " 6-oldtet.tetedge1-j-k = " << short(6 - oldtet.tetedge1 - j - k) << endl; *testout << "vis1 = " << vis1 << ", vis2 = " << vis2 << endl; for (int j = 0; j < 4; j++) if (newtet2.faceedges[j] > 3) { *testout << "ERROR1" << endl; } #endif } if (i == oldtet.tetedge2) { newtet1.pnums[i] = newp; newtet1.faceedges[i] = oldtet.faceedges[i]; // inherited face newtet1.faceedges[vis1] = i; newtet1.faceedges[vis2] = i; int j = 0; while (j == i || j == oldtet.faceedges[i]) j++; int k = 6 - i - oldtet.faceedges[i] - j; newtet1.tetedge1 = j; newtet1.tetedge2 = k; // new face: if (istypep && oldtet.flagged) { int hi = 6 - oldtet.tetedge2 - j - k; newtet1.faceedges[oldtet.tetedge1] = char(hi); } else newtet1.faceedges[oldtet.tetedge1] = oldtet.tetedge2; #ifdef DEBUG for (int j = 0; j < 4; j++) if (newtet2.faceedges[j] > 3) { *testout << "ERROR2" << endl; } #endif } } newtet1.matindex = oldtet.matindex; newtet2.matindex = oldtet.matindex; newtet1.incorder = 0; newtet1.order = oldtet.order; newtet2.incorder = 0; newtet2.order = oldtet.order; // *testout << "newtet1 = " << newtet1 << endl; // *testout << "newtet2 = " << newtet2 << endl; } void BTBisectPrism (const MarkedPrism & oldprism, int newp1, int newp2, MarkedPrism & newprism1, MarkedPrism & newprism2) { for (int i = 0; i < 6; i++) { newprism1.pnums[i] = oldprism.pnums[i]; newprism2.pnums[i] = oldprism.pnums[i]; } int pe1 = 0; if (pe1 == oldprism.markededge) pe1++; int pe2 = 3 - oldprism.markededge - pe1; newprism1.pnums[pe2] = newp1; newprism1.pnums[pe2+3] = newp2; newprism1.markededge = pe2; newprism2.pnums[pe1] = newp1; newprism2.pnums[pe1+3] = newp2; newprism2.markededge = pe1; newprism1.matindex = oldprism.matindex; newprism2.matindex = oldprism.matindex; int nm = oldprism.marked - 1; if (nm < 0) nm = 0; newprism1.marked = nm; newprism2.marked = nm; newprism1.incorder = 0; newprism1.order = oldprism.order; newprism2.incorder = 0; newprism2.order = oldprism.order; } void BTBisectIdentification (const MarkedIdentification & oldid, Array & newp, MarkedIdentification & newid1, MarkedIdentification & newid2) { for(int i=0; i<2*oldid.np; i++) { newid1.pnums[i] = oldid.pnums[i]; newid2.pnums[i] = oldid.pnums[i]; } newid1.np = newid2.np = oldid.np; if(oldid.np == 2) { newid1.pnums[1] = newp[0]; newid2.pnums[0] = newp[0]; newid1.pnums[3] = newp[1]; newid2.pnums[2] = newp[1]; newid1.markededge = 0; newid2.markededge = 0; } if(oldid.np == 3) { newid1.pnums[(oldid.markededge+1)%3] = newp[0]; newid1.pnums[(oldid.markededge+1)%3+3] = newp[1]; newid1.markededge = (oldid.markededge+2)%3; newid2.pnums[oldid.markededge] = newp[0]; newid2.pnums[oldid.markededge+3] = newp[1]; newid2.markededge = (oldid.markededge+1)%3; } else if(oldid.np == 4) { newid1.pnums[(oldid.markededge+1)%4] = newp[0]; newid1.pnums[(oldid.markededge+2)%4] = newp[2]; newid1.pnums[(oldid.markededge+1)%4+4] = newp[1]; newid1.pnums[(oldid.markededge+2)%4+4] = newp[3]; newid1.markededge = (oldid.markededge+3)%4; newid2.pnums[oldid.markededge] = newp[0]; newid2.pnums[(oldid.markededge+3)%4] = newp[2]; newid2.pnums[oldid.markededge+4] = newp[1]; newid2.pnums[(oldid.markededge+3)%4+4] = newp[3]; newid2.markededge = (oldid.markededge+1)%4; } int nm = oldid.marked - 1; if (nm < 0) nm = 0; newid1.marked = newid2.marked = nm; newid1.incorder = newid2.incorder = 0; newid1.order = newid2.order = oldid.order; } void BTBisectTri (const MarkedTri & oldtri, int newp, const PointGeomInfo & newpgi, MarkedTri & newtri1, MarkedTri & newtri2) { for (int i = 0; i < 3; i++) { newtri1.pnums[i] = oldtri.pnums[i]; newtri1.pgeominfo[i] = oldtri.pgeominfo[i]; newtri2.pnums[i] = oldtri.pnums[i]; newtri2.pgeominfo[i] = oldtri.pgeominfo[i]; } int pe1 = 0; if (pe1 == oldtri.markededge) pe1++; int pe2 = 3 - oldtri.markededge - pe1; newtri1.pnums[pe2] = newp; newtri1.pgeominfo[pe2] = newpgi; newtri1.markededge = pe2; newtri2.pnums[pe1] = newp; newtri2.pgeominfo[pe1] = newpgi; newtri2.markededge = pe1; newtri1.surfid = oldtri.surfid; newtri2.surfid = oldtri.surfid; int nm = oldtri.marked - 1; if (nm < 0) nm = 0; newtri1.marked = nm; newtri2.marked = nm; newtri1.incorder = 0; newtri1.order = oldtri.order; newtri2.incorder = 0; newtri2.order = oldtri.order; } void BTBisectQuad (const MarkedQuad & oldquad, int newp1, const PointGeomInfo & npgi1, int newp2, const PointGeomInfo & npgi2, MarkedQuad & newquad1, MarkedQuad & newquad2) { for (int i = 0; i < 4; i++) { newquad1.pnums[i] = oldquad.pnums[i]; newquad1.pgeominfo[i] = oldquad.pgeominfo[i]; newquad2.pnums[i] = oldquad.pnums[i]; newquad2.pgeominfo[i] = oldquad.pgeominfo[i]; } /* if (oldquad.marked==1) // he/sz: 2d quads or 3d prism { newquad1.pnums[1] = newp1; newquad1.pgeominfo[1] = npgi1; newquad1.pnums[3] = newp2; newquad1.pgeominfo[3] = npgi2; newquad2.pnums[0] = newp1; newquad2.pgeominfo[0] = npgi1; newquad2.pnums[2] = newp2; newquad2.pgeominfo[2] = npgi2; } else if (oldquad.marked==2) // he/sz: 2d quads only { newquad1.pnums[0] = newp1; newquad1.pnums[1] = newp2; newquad1.pnums[3] = oldquad.pnums[2]; newquad1.pnums[2] = oldquad.pnums[0]; newquad1.pgeominfo[0] = npgi1; newquad1.pgeominfo[1] = npgi2; newquad1.pgeominfo[3] = oldquad.pgeominfo[2]; newquad1.pgeominfo[2] = oldquad.pgeominfo[0]; newquad2.pnums[0] = newp2; newquad2.pnums[1] = newp1; newquad2.pnums[3] = oldquad.pnums[1]; newquad2.pnums[2] = oldquad.pnums[3]; newquad2.pgeominfo[0] = npgi2; newquad2.pgeominfo[1] = npgi1; newquad2.pgeominfo[3] = oldquad.pgeominfo[1]; newquad2.pgeominfo[2] = oldquad.pgeominfo[3]; } */ if (oldquad.markededge==0 || oldquad.markededge==2) { newquad1.pnums[1] = newp1; newquad1.pgeominfo[1] = npgi1; newquad1.pnums[3] = newp2; newquad1.pgeominfo[3] = npgi2; newquad2.pnums[0] = newp1; newquad2.pgeominfo[0] = npgi1; newquad2.pnums[2] = newp2; newquad2.pgeominfo[2] = npgi2; } else // 1 || 3 { newquad1.pnums[2] = newp1; newquad1.pgeominfo[2] = npgi1; newquad1.pnums[3] = newp2; newquad1.pgeominfo[3] = npgi2; newquad2.pnums[0] = newp1; newquad2.pgeominfo[0] = npgi1; newquad2.pnums[1] = newp2; newquad2.pgeominfo[1] = npgi2; } newquad1.surfid = oldquad.surfid; newquad2.surfid = oldquad.surfid; int nm = oldquad.marked - 1; if (nm < 0) nm = 0; newquad1.marked = nm; newquad2.marked = nm; if (nm==1) { newquad1.markededge=1; newquad2.markededge=1; } else { newquad1.markededge=0; newquad2.markededge=0; } } int MarkHangingIdentifications(T_MIDS & mids, const INDEX_2_CLOSED_HASHTABLE & cutedges) { int hanging = 0; for (int i = 1; i <= mids.Size(); i++) { if (mids.Elem(i).marked) { hanging = 1; continue; } const int np = mids.Get(i).np; for(int j = 0; j < np; j++) { INDEX_2 edge1(mids.Get(i).pnums[j], mids.Get(i).pnums[(j+1) % np]); INDEX_2 edge2(mids.Get(i).pnums[j+np], mids.Get(i).pnums[((j+1) % np) + np]); edge1.Sort(); edge2.Sort(); if (cutedges.Used (edge1) || cutedges.Used (edge2)) { mids.Elem(i).marked = 1; hanging = 1; } } } return hanging; } /* void IdentifyCutEdges(Mesh & mesh, INDEX_2_CLOSED_HASHTABLE & cutedges) { int i,j,k; Array< Array* > idmaps; for(i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) { idmaps.Append(new Array); mesh.GetIdentifications().GetMap(i,*idmaps.Last()); } for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el2d = mesh[sei]; for(i = 0; i < el2d.GetNP(); i++) { INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]); e1.Sort(); if(!cutedges.Used(e1)) continue; for(k = 0; k < idmaps.Size(); k++) { INDEX_2 e2((*idmaps[k])[e1.I1()], (*idmaps[k])[e1.I2()]); if(e2.I1() == 0 || e2.I2() == 0 || e1.I1() == e2.I1() || e1.I2() == e2.I2()) continue; e2.Sort(); if(cutedges.Used(e2)) continue; Point3d np = Center(mesh.Point(e2.I1()), mesh.Point(e2.I2())); int newp = mesh.AddPoint(np); cutedges.Set(e2,newp); (*testout) << "DAAA" << endl; } } } for(i=0; i & cutedges, TaskManager tm) { static int timer = NgProfiler::CreateTimer ("MarkHangingTets"); NgProfiler::RegionTimer reg (timer); int hanging = 0; // for (int i = 1; i <= mtets.Size(); i++) ParallelForRange (tm, mtets.Size(), [&] (size_t begin, size_t end) { bool my_hanging = false; for (size_t i = begin; i < end; i++) { MarkedTet & teti = mtets[i]; if (teti.marked) { my_hanging = true; continue; } for (int j = 0; j < 3; j++) for (int k = j+1; k < 4; k++) { INDEX_2 edge(teti.pnums[j], teti.pnums[k]); edge.Sort(); if (cutedges.Used (edge)) { teti.marked = 1; my_hanging = true; } } } if (my_hanging) hanging = true; }); return hanging; } int MarkHangingPrisms (T_MPRISMS & mprisms, const INDEX_2_CLOSED_HASHTABLE & cutedges) { int hanging = 0; for (int i = 1; i <= mprisms.Size(); i++) { if (mprisms.Elem(i).marked) { hanging = 1; continue; } for (int j = 0; j < 2; j++) for (int k = j+1; k < 3; k++) { INDEX_2 edge1(mprisms.Get(i).pnums[j], mprisms.Get(i).pnums[k]); INDEX_2 edge2(mprisms.Get(i).pnums[j+3], mprisms.Get(i).pnums[k+3]); edge1.Sort(); edge2.Sort(); if (cutedges.Used (edge1) || cutedges.Used (edge2)) { mprisms.Elem(i).marked = 1; hanging = 1; } } } return hanging; } bool MarkHangingTris (T_MTRIS & mtris, const INDEX_2_CLOSED_HASHTABLE & cutedges, TaskManager tm) { bool hanging = false; // for (int i = 1; i <= mtris.Size(); i++) // for (auto & tri : mtris) ParallelForRange (tm, mtris.Size(), [&] (size_t begin, size_t end) { bool my_hanging = false; for (size_t i = begin; i < end; i++) { auto & tri = mtris[i]; if (tri.marked) { my_hanging = true; continue; } for (int j = 0; j < 2; j++) for (int k = j+1; k < 3; k++) { INDEX_2 edge(tri.pnums[j], tri.pnums[k]); edge.Sort(); if (cutedges.Used (edge)) { tri.marked = 1; my_hanging = true; } } } if (my_hanging) hanging = true; }); return hanging; } int MarkHangingQuads (T_MQUADS & mquads, const INDEX_2_CLOSED_HASHTABLE & cutedges) { int hanging = 0; for (int i = 1; i <= mquads.Size(); i++) { if (mquads.Elem(i).marked) { hanging = 1; continue; } INDEX_2 edge1(mquads.Get(i).pnums[0], mquads.Get(i).pnums[1]); INDEX_2 edge2(mquads.Get(i).pnums[2], mquads.Get(i).pnums[3]); edge1.Sort(); edge2.Sort(); if (cutedges.Used (edge1) || cutedges.Used (edge2)) { mquads.Elem(i).marked = 1; mquads.Elem(i).markededge = 0; hanging = 1; continue; } // he/sz: second case: split horizontally INDEX_2 edge3(mquads.Get(i).pnums[1], mquads.Get(i).pnums[3]); INDEX_2 edge4(mquads.Get(i).pnums[2], mquads.Get(i).pnums[0]); edge3.Sort(); edge4.Sort(); if (cutedges.Used (edge3) || cutedges.Used (edge4)) { mquads.Elem(i).marked = 1; mquads.Elem(i).markededge = 1; hanging = 1; continue; } } return hanging; } void ConnectToNodeRec (int node, int tonode, const TABLE & conto, Array & connecttonode) { // (*testout) << "connect " << node << " to " << tonode << endl; for (int i = 1; i <= conto.EntrySize(node); i++) { int n2 = conto.Get(node, i); if (!connecttonode.Get(n2)) { connecttonode.Elem(n2) = tonode; ConnectToNodeRec (n2, tonode, conto, connecttonode); } } } T_MTETS mtets; T_MPRISMS mprisms; T_MIDS mids; T_MTRIS mtris; T_MQUADS mquads; void WriteMarkedElements(ostream & ost) { ost << "Marked Elements\n"; ost << mtets.Size() << "\n"; for(int i=0; i> auxstring; if(auxstring != "Marked") return false; if(ist) ist >> auxstring; if(auxstring != "Elements") return false; int size; ist >> size; mtets.SetSize(size); for(int i=0; i> mtets[i]; if(mtets[i].pnums[0] > mesh.GetNV() || mtets[i].pnums[1] > mesh.GetNV() || mtets[i].pnums[2] > mesh.GetNV() || mtets[i].pnums[3] > mesh.GetNV()) return false; } ist >> size; mprisms.SetSize(size); for(int i=0; i> mprisms[i]; ist >> size; mids.SetSize(size); for(int i=0; i> mids[i]; ist >> size; mtris.SetSize(size); for(int i=0; i> mtris[i]; ist >> size; mquads.SetSize(size); for(int i=0; i> mquads[i]; return true; } void BisectTetsCopyMesh (Mesh & mesh, const NetgenGeometry *, BisectionOptions & opt, const Array< Array* > & idmaps, const string & refinfofile) { // mtets.SetName ("bisection, tets"); // mprisms.SetName ("bisection, prisms"); // mtris.SetName ("bisection, trigs"); // nmquads.SetName ("bisection, quads"); // mids.SetName ("bisection, identifications"); //int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); /* if (mtets.Size() + mprisms.Size() == mesh.GetNE()) return; */ bool readok = false; if(refinfofile != "") { PrintMessage(3,"Reading marked-element information from \"",refinfofile,"\""); ifstream ist(refinfofile.c_str()); readok = ReadMarkedElements(ist,mesh); ist.close(); } if(!readok) { PrintMessage(3,"resetting marked-element information"); mtets.SetSize(0); mprisms.SetSize(0); mids.SetSize(0); mtris.SetSize(0); mquads.SetSize(0); INDEX_2_HASHTABLE shortedges(100); for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); if (el.GetType() == PRISM || el.GetType() == PRISM12) { for (int j = 1; j <= 3; j++) { INDEX_2 se(el.PNum(j), el.PNum(j+3)); se.Sort(); shortedges.Set (se, 1); } } } // INDEX_2_HASHTABLE edgenumber(np); INDEX_2_CLOSED_HASHTABLE edgenumber(9*ne+4*nse); BTSortEdges (mesh, idmaps, edgenumber); for (int i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); switch (el.GetType()) { case TET: case TET10: { // if tet has short edge, it is handled as degenerated prism int foundse = 0; for (int j = 1; j <= 3; j++) for (int k = j+1; k <= 4; k++) { INDEX_2 se(el.PNum(j), el.PNum(k)); se.Sort(); if (shortedges.Used (se)) { // cout << "tet converted to prism" << endl; foundse = 1; int p3 = 1; while (p3 == j || p3 == k) p3++; int p4 = 10 - j - k - p3; // even permutation ? int pi[4]; pi[0] = j; pi[1] = k; pi[2] = p3; pi[3] = p4; int cnt = 0; for (int l = 1; l <= 4; l++) for (int m = 0; m < 3; m++) if (pi[m] > pi[m+1]) { Swap (pi[m], pi[m+1]); cnt++; } if (cnt % 2) Swap (p3, p4); Element hel = el; hel.PNum(1) = el.PNum(j); hel.PNum(2) = el.PNum(k); hel.PNum(3) = el.PNum(p3); hel.PNum(4) = el.PNum(p4); MarkedPrism mp; BTDefineMarkedPrism (hel, edgenumber, mp); mp.matindex = el.GetIndex(); mprisms.Append (mp); } } if (!foundse) { MarkedTet mt; BTDefineMarkedTet (el, edgenumber, mt); mt.matindex = el.GetIndex(); mtets.Append (mt); } break; } case PYRAMID: { // eventually rotate MarkedPrism mp; INDEX_2 se(el.PNum(1), el.PNum(2)); se.Sort(); if (shortedges.Used (se)) { Element hel = el; hel.PNum(1) = el.PNum(2); hel.PNum(2) = el.PNum(3); hel.PNum(3) = el.PNum(4); hel.PNum(4) = el.PNum(1); BTDefineMarkedPrism (hel, edgenumber, mp); } else { BTDefineMarkedPrism (el, edgenumber, mp); } mp.matindex = el.GetIndex(); mprisms.Append (mp); break; } case PRISM: case PRISM12: { MarkedPrism mp; BTDefineMarkedPrism (el, edgenumber, mp); mp.matindex = el.GetIndex(); mprisms.Append (mp); break; } default: throw NgException("Bisect, element type not handled in switch, 4"); } } for (int i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (el.GetType() == TRIG || el.GetType() == TRIG6) { MarkedTri mt; BTDefineMarkedTri (el, edgenumber, mt); mtris.Append (mt); } else { MarkedQuad mq; BTDefineMarkedQuad (el, edgenumber, mq); mquads.Append (mq); } if(mesh.GetDimension() == 3) { MarkedIdentification mi; for(int j=0; j 0 && seg[1] > 0 && (*map)[seg[0]] && (*map)[seg[1]]) { MarkedIdentification mi; mi.np = 2; mi.pnums[0] = seg[0]; mi.pnums[1] = seg[1]; mi.pnums[2] = (*map)[seg[0]]; mi.pnums[3] = (*map)[seg[1]]; auto min1 = mi.pnums[0] < mi.pnums[1] ? mi.pnums[0] : mi.pnums[1]; auto min2 = mi.pnums[2] < mi.pnums[3] ? mi.pnums[2] : mi.pnums[3]; if (min1 > min2) continue; mi.marked = 0; mi.markededge = 0; mi.incorder = 0; mids.Append(mi); } } } } } mesh.mlparentelement.SetSize(ne); for (int i = 1; i <= ne; i++) mesh.mlparentelement.Elem(i) = 0; mesh.mlparentsurfaceelement.SetSize(nse); for (int i = 1; i <= nse; i++) mesh.mlparentsurfaceelement.Elem(i) = 0; if (printmessage_importance>0) { ostringstream str1,str2; str1 << "copied " << mtets.Size() << " tets, " << mprisms.Size() << " prisms"; str2 << " " << mtris.Size() << " trigs, " << mquads.Size() << " quads"; PrintMessage(4,str1.str()); PrintMessage(4,str2.str()); } } /* void UpdateEdgeMarks2(Mesh & mesh, const Array< Array* > & idmaps) { Array< Array*,PointIndex::BASE > mtets_old(mesh.GetNP()); Array< Array*,PointIndex::BASE > mprisms_old(mesh.GetNP()); Array< Array*,PointIndex::BASE > mids_old(mesh.GetNP()); Array< Array*,PointIndex::BASE > mtris_old(mesh.GetNP()); Array< Array*,PointIndex::BASE > mquads_old(mesh.GetNP()); for(int i=PointIndex::BASE; i; for(int i=PointIndex::BASE; i; for(int i=PointIndex::BASE; i; for(int i=PointIndex::BASE; i; for(int i=PointIndex::BASE; i; for(int i=0; iAppend(mtets[i]); for(int i=0; iAppend(mprisms[i]); for(int i=0; iAppend(mids[i]); for(int i=0; iAppend(mtris[i]); } for(int i=0; iAppend(mquads[i]); int np = mesh.GetNP(); int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int i, j, k, l, m; // if (mtets.Size() + mprisms.Size() == mesh.GetNE()) // return; mtets.SetSize(0); mprisms.SetSize(0); mids.SetSize(0); mtris.SetSize(0); mquads.SetSize(0); INDEX_2_HASHTABLE shortedges(100); for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); if (el.GetType() == PRISM || el.GetType() == PRISM12) { for (j = 1; j <= 3; j++) { INDEX_2 se(el.PNum(j), el.PNum(j+3)); se.Sort(); shortedges.Set (se, 1); } } } // INDEX_2_HASHTABLE edgenumber(np); INDEX_2_CLOSED_HASHTABLE edgenumber(9*ne+4*nse); BTSortEdges (mesh, idmaps, edgenumber); for (i = 1; i <= ne; i++) { const Element & el = mesh.VolumeElement(i); switch (el.GetType()) { case TET: case TET10: { // if tet has short edge, it is handled as degenerated prism int foundse = 0; for (j = 1; j <= 3; j++) for (k = j+1; k <= 4; k++) { INDEX_2 se(el.PNum(j), el.PNum(k)); se.Sort(); if (shortedges.Used (se)) { // cout << "tet converted to prism" << endl; foundse = 1; int p3 = 1; while (p3 == j || p3 == k) p3++; int p4 = 10 - j - k - p3; // even permutation ? int pi[4]; pi[0] = j; pi[1] = k; pi[2] = p3; pi[3] = p4; int cnt = 0; for (l = 1; l <= 4; l++) for (m = 0; m < 3; m++) if (pi[m] > pi[m+1]) { Swap (pi[m], pi[m+1]); cnt++; } if (cnt % 2) Swap (p3, p4); Element hel = el; hel.PNum(1) = el.PNum(j); hel.PNum(2) = el.PNum(k); hel.PNum(3) = el.PNum(p3); hel.PNum(4) = el.PNum(p4); MarkedPrism mp; BTDefineMarkedPrism (hel, edgenumber, mp); mp.matindex = el.GetIndex(); mprisms.Append (mp); } } if (!foundse) { MarkedTet mt; int oldind = -1; for(l = 0; oldind < 0 && lSize(); l++) if(el[1] == (*mtets_old[el[0]])[l].pnums[1] && el[2] == (*mtets_old[el[0]])[l].pnums[2] && el[3] == (*mtets_old[el[0]])[l].pnums[3]) oldind = l; if(oldind >= 0) mtets.Append((*mtets_old[el[0]])[oldind]); else { BTDefineMarkedTet (el, edgenumber, mt); mt.matindex = el.GetIndex(); mtets.Append (mt); } } break; } case PYRAMID: { // eventually rotate MarkedPrism mp; INDEX_2 se(el.PNum(1), el.PNum(2)); se.Sort(); if (shortedges.Used (se)) { Element hel = el; hel.PNum(1) = el.PNum(2); hel.PNum(2) = el.PNum(3); hel.PNum(3) = el.PNum(4); hel.PNum(4) = el.PNum(1); BTDefineMarkedPrism (hel, edgenumber, mp); } else { BTDefineMarkedPrism (el, edgenumber, mp); } mp.matindex = el.GetIndex(); mprisms.Append (mp); break; } case PRISM: case PRISM12: { MarkedPrism mp; BTDefineMarkedPrism (el, edgenumber, mp); mp.matindex = el.GetIndex(); mprisms.Append (mp); break; } } } for (i = 1; i <= nse; i++) { const Element2d & el = mesh.SurfaceElement(i); if (el.GetType() == TRIG || el.GetType() == TRIG6) { MarkedTri mt; BTDefineMarkedTri (el, edgenumber, mt); mtris.Append (mt); } else { MarkedQuad mq; BTDefineMarkedQuad (el, edgenumber, mq); mquads.Append (mq); } MarkedIdentification mi; for(j=0; jSize(); l++) { bool equal = true; for(int m = 1; equal && m < mi.np; m++) equal = (mi.pnums[m] == (*mids_old[el[0]])[l].pnums[m]); if(equal) oldind = l; } if(oldind >= 0) mids.Last() = (*mids_old[mi.pnums[0]])[oldind]; } } for(int i=PointIndex::BASE; i* > & idmaps) //const Array < Array* > & elements_before, //const Array < Array* > & markedelts_num, // const Array < Array* > & surfelements_before, // const Array < Array* > & markedsurfelts_num) { /* T_MTETS mtets_old; mtets_old.Copy(mtets); T_MPRISMS mprisms_old; mprisms_old.Copy(mprisms); T_MIDS mids_old; mids_old.Copy(mids); T_MTRIS mtris_old; mtris_old.Copy(mtris); T_MQUADS mquads_old; mquads_old.Copy(mquads); */ T_MTETS mtets_old (mtets); T_MPRISMS mprisms_old (mprisms); T_MIDS mids_old (mids); T_MTRIS mtris_old (mtris); T_MQUADS mquads_old (mquads); mtets.SetSize(0); mprisms.SetSize(0); mids.SetSize(0); mtris.SetSize(0); mquads.SetSize(0); //int nv = mesh.GetNV(); INDEX_2_CLOSED_HASHTABLE edgenumber(9*mesh.GetNE()+4*mesh.GetNSE()); int maxnum = BTSortEdges (mesh, idmaps, edgenumber); for(int m = 0; m < mtets_old.Size(); m++) { MarkedTet & mt = mtets_old[m]; //(*testout) << "old mt " << mt; INDEX_2 edge (mt.pnums[mt.tetedge1],mt.pnums[mt.tetedge2]); edge.Sort(); if(edgenumber.Used(edge)) { int val = edgenumber.Get(edge); //(*testout) << "set voledge " << edge << " from " << val; if(val <= maxnum) { val += 2*maxnum; edgenumber.Set(edge,val); } else if(val <= 2*maxnum) { val += maxnum; edgenumber.Set(edge,val); } //(*testout) << " to " << val << endl; } for(int k=0; k<4; k++) for(int i=0; i<3; i++) for(int j=i+1; i != k && j<4; j++) if(j != k && int(mt.faceedges[k]) == 6-k-i-j) { edge[0] = mt.pnums[i]; edge[1] = mt.pnums[j]; edge.Sort(); if(edgenumber.Used(edge)) { int val = edgenumber.Get(edge); //(*testout) << "set faceedge " << edge << " from " << val; if(val <= maxnum) { val += maxnum; edgenumber.Set(edge,val); } //(*testout) << " to " << val << endl; } } } for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; //int pos = elements_before[el[0]]->Pos(el); //int elnum = (pos >= 0) ? (*markedelts_num[el[0]])[pos] : -1; switch (el.GetType()) { case TET: case TET10: { //if(elnum >= 0) // { // mtets.Append(mtets_old[elnum]); // } //else // { MarkedTet mt; BTDefineMarkedTet (el, edgenumber, mt); mt.matindex = el.GetIndex(); mtets.Append (mt); //(*testout) << "mtet " << mtets.Last() << endl; break; } case PYRAMID: { cerr << "Refinement :: UpdateEdgeMarks not yet implemented for pyramids" << endl; break; } case PRISM: case PRISM12: { cerr << "Refinement :: UpdateEdgeMarks not yet implemented for prisms" << endl; break; } default: throw NgException("Bisect, element type not handled in switch, 6"); } } for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el = mesh[sei]; /* for(int k=0; k<3; k++) auxind3[k] = el[k]; auxind3.Sort(); int pos = oldfaces[auxind3[0]]->Pos(auxind3); if(pos < 0) cout << "UIUIUI" << endl; */ switch (el.GetType()) { case TRIG: case TRIG6: { MarkedTri mt; BTDefineMarkedTri (el, edgenumber, mt); mtris.Append (mt); break; } case QUAD: case QUAD6: { MarkedQuad mt; BTDefineMarkedQuad (el, edgenumber, mt); mquads.Append (mt); break; } default: throw NgException("Bisect, element type not handled in switch, 5"); } MarkedIdentification mi; for(int j=0; jPos(el); int elnum = (pos >= 0) ? (*markedsurfelts_num[el[0]])[pos] : -1; switch (el.GetType()) { case TRIG: case TRIG6: { if(elnum >= 0) mtris.Append(mtris_old[elnum]); else { MarkedTri mt; BTDefineMarkedTri (el, edgenumber, mt); mtris.Append (mt); (*testout) << "(new) "; } (*testout) << "mtri " << mtris.Last(); break; } case QUAD: case QUAD6: { if(elnum >= 0) mquads.Append(mquads_old[elnum]); else { MarkedQuad mt; BTDefineMarkedQuad (el, edgenumber, mt); mquads.Append (mt); } break; } } */ } /* for(int i=0; i * quality_loss) const { PrintMessage(1,"Mesh bisection"); PushStatus("Mesh bisection"); static int timer = NgProfiler::CreateTimer ("Bisect"); static int timer1 = NgProfiler::CreateTimer ("Bisect 1"); static int timer1a = NgProfiler::CreateTimer ("Bisect 1a"); static int timer1b = NgProfiler::CreateTimer ("Bisect 1b"); static int timer2 = NgProfiler::CreateTimer ("Bisect 2"); static int timer2a = NgProfiler::CreateTimer ("Bisect 2a"); static int timer2b = NgProfiler::CreateTimer ("Bisect 2b"); // static int timer2c = NgProfiler::CreateTimer ("Bisect 2c"); static int timer3 = NgProfiler::CreateTimer ("Bisect 3"); static int timer3a = NgProfiler::CreateTimer ("Bisect 3a"); static int timer3b = NgProfiler::CreateTimer ("Bisect 3b"); static int timer_bisecttet = NgProfiler::CreateTimer ("Bisect tets"); static int timer_bisecttrig = NgProfiler::CreateTimer ("Bisect trigs"); static int timer_bisectsegms = NgProfiler::CreateTimer ("Bisect segms"); NgProfiler::RegionTimer reg1 (timer); (*opt.tracer)("Bisect", false); NgProfiler::StartTimer (timer1); NgProfiler::StartTimer (timer1a); static int localizetimer = NgProfiler::CreateTimer("localize edgepoints"); NgProfiler::RegionTimer * loct = new NgProfiler::RegionTimer(localizetimer); LocalizeEdgePoints(mesh); delete loct; Array< Array* > idmaps; for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) { if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) { idmaps.Append(new Array); mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true); } } string refelementinfofileread = ""; string refelementinfofilewrite = ""; if(opt.refinementfilename) { ifstream inf(opt.refinementfilename); string st; inf >> st; if(st == "refinementinfo") { while(inf) { while(inf && st != "markedelementsfile") inf >> st; if(inf) inf >> st; if(st == "read" && inf) ReadEnclString(inf,refelementinfofileread,'\"'); else if(st == "write" && inf) ReadEnclString(inf,refelementinfofilewrite,'\"'); } } inf.close(); } if (mesh.mglevels == 1 || idmaps.Size() > 0) BisectTetsCopyMesh(mesh, NULL, opt, idmaps, refelementinfofileread); mesh.ComputeNVertices(); int np = mesh.GetNV(); mesh.SetNP(np); // int ne = mesh.GetNE(); // int nse = mesh.GetNSE(); // int i, j, l; // int initnp = np; // int maxsteps = 3; mesh.mglevels++; /* if (opt.refinementfilename || opt.usemarkedelements) maxsteps = 3; */ if (opt.refine_p) { int ne = mesh.GetNE(); int nse = mesh.GetNSE(); int ox,oy,oz; for (ElementIndex ei = 0; ei < ne; ei++) if (mesh[ei].TestRefinementFlag()) { mesh[ei].GetOrder(ox,oy,oz); mesh[ei].SetOrder (ox+1,oy+1,oz+1); if (mesh[ei].TestStrongRefinementFlag()) mesh[ei].SetOrder (ox+2,oy+2,oz+2); } for (SurfaceElementIndex sei = 0; sei < nse; sei++) if (mesh[sei].TestRefinementFlag()) { mesh[sei].GetOrder(ox,oy); mesh[sei].SetOrder(ox+1,oy+1); if (mesh[sei].TestStrongRefinementFlag()) mesh[sei].SetOrder(ox+2,oy+2); } #ifndef SABINE //Nachbarelemente mit ordx,ordy,ordz Array v_order (mesh.GetNP()); v_order = 0; for (ElementIndex ei = 0; ei < ne; ei++) for (int j = 0; j < mesh[ei].GetNP(); j++) if (mesh[ei].GetOrder() > v_order[mesh[ei][j]]) v_order[mesh[ei][j]] = mesh[ei].GetOrder(); for (SurfaceElementIndex sei = 0; sei < nse; sei++) for (int j = 0; j < mesh[sei].GetNP(); j++) if (mesh[sei].GetOrder() > v_order[mesh[sei][j]]) v_order[mesh[sei][j]] = mesh[sei].GetOrder(); for (ElementIndex ei = 0; ei < ne; ei++) for (int j = 0; j < mesh[ei].GetNP(); j++) if (mesh[ei].GetOrder() < v_order[mesh[ei][j]]-1) mesh[ei].SetOrder(v_order[mesh[ei][j]]-1); for (SurfaceElementIndex sei = 0; sei < nse; sei++) for (int j = 0; j < mesh[sei].GetNP(); j++) if (mesh[sei].GetOrder() < v_order[mesh[sei][j]]-1) mesh[sei].SetOrder(v_order[mesh[sei][j]]-1); #endif PopStatus(); return; } // INDEX_2_HASHTABLE cutedges(10 + 5 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size())); INDEX_2_CLOSED_HASHTABLE cutedges(10 + 9 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size())); bool noprojection = false; NgProfiler::StopTimer (timer1a); for (int l = 1; l <= 1; l++) { int marked = 0; if (opt.refinementfilename) { ifstream inf(opt.refinementfilename); PrintMessage(3,"load refinementinfo from file ",opt.refinementfilename); string st; inf >> st; if(st == "refinementinfo") // new version { for(int i=1; i<=mtets.Size(); i++) mtets.Elem(i).marked = 0; for(int i=1; i<=mprisms.Size(); i++) mprisms.Elem(i).marked = 0; for(int i=1; i<=mtris.Size(); i++) mtris.Elem(i).marked = 0; for(int i=1; i<=mquads.Size(); i++) mquads.Elem(i).marked = 0; for(int i=1; i<=mprisms.Size(); i++) mids.Elem(i).marked = 0; inf >> st; while(inf) { if(st[0] == '#') { inf.ignore(10000,'\n'); inf >> st; } else if(st == "markedelementsfile") { inf >> st; ReadEnclString(inf,st,'\"'); inf >> st; } else if(st == "noprojection") { noprojection = true; inf >> st; } else if(st == "refine") { inf >> st; if(st == "elements") { inf >> st; bool isint = true; for(string::size_type ii=0; isint && ii> st; isint = true; for(string::size_type ii=0; isint && ii> bounds[i]; int cnt = 0; for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; // Point<3> center(0,0,0); for(int i=0; i 0) marked = 1; inf >> st; } else { throw NgException("something wrong with refinementinfo file"); } } } } else { inf.close(); inf.open(opt.refinementfilename); char ch; for (int i = 1; i <= mtets.Size(); i++) { inf >> ch; if(!inf) throw NgException("something wrong with refinementinfo file (old format)"); mtets.Elem(i).marked = (ch == '1'); } marked = 1; } inf.close(); } else if (opt.usemarkedelements) { int cntm = 0; // all in one ! if (mprisms.Size()) { int cnttet = 0; int cntprism = 0; for (int i = 1; i <= mesh.GetNE(); i++) { if (mesh.VolumeElement(i).GetType() == TET || mesh.VolumeElement(i).GetType() == TET10) { cnttet++; mtets.Elem(cnttet).marked = 3 * mesh.VolumeElement(i).TestRefinementFlag(); if (mtets.Elem(cnttet).marked) cntm++; } else { cntprism++; mprisms.Elem(cntprism).marked = 2 * mesh.VolumeElement(i).TestRefinementFlag(); if (mprisms.Elem(cntprism).marked) cntm++; } } } else for (int i = 1; i <= mtets.Size(); i++) { mtets.Elem(i).marked = 3 * mesh.VolumeElement(i).TestRefinementFlag(); if (mtets.Elem(i).marked) cntm++; } // (*testout) << "mtets = " << mtets << endl; /* for (i = 1; i <= mtris.Size(); i++) mtris.Elem(i).marked = 0; for (i = 1; i <= mquads.Size(); i++) mquads.Elem(i).marked = 0; */ if (printmessage_importance>0) { ostringstream str; str << "marked elements: " << cntm; PrintMessage(4,str.str()); } int cnttrig = 0; int cntquad = 0; for (int i = 1; i <= mesh.GetNSE(); i++) { if (mesh.SurfaceElement(i).GetType() == TRIG || mesh.SurfaceElement(i).GetType() == TRIG6) { cnttrig++; mtris.Elem(cnttrig).marked = mesh.SurfaceElement(i).TestRefinementFlag() ? 2 : 0; // mtris.Elem(cnttrig).marked = 0; if (mtris.Elem(cnttrig).marked) cntm++; } else { cntquad++; // 2d: marked=2, 3d prisms: marked=1 mquads.Elem(cntquad).marked = mesh.SurfaceElement(i).TestRefinementFlag() ? 4-mesh.GetDimension() : 0 ; // mquads.Elem(cntquad).marked = 0; if (mquads.Elem(cntquad).marked) cntm++; } } if (printmessage_importance>0) { ostringstream str; str << "with surface-elements: " << cntm; PrintMessage(4,str.str()); } // he/sz: das wird oben schon richtig gemacht. // hier sind die quads vergessen! /* if (mesh.GetDimension() == 2) { cntm = 0; for (i = 1; i <= mtris.Size(); i++) { mtris.Elem(i).marked = 2 * mesh.SurfaceElement(i).TestRefinementFlag(); // mtris.Elem(i).marked = 2; if (mtris.Elem(i).marked) cntm++; } if (!cntm) { for (i = 1; i <= mtris.Size(); i++) { mtris.Elem(i).marked = 2; cntm++; } } cout << "trigs: " << mtris.Size() << " "; cout << "marked: " << cntm << endl; } */ marked = (cntm > 0); } else { marked = BTMarkTets (mtets, mprisms, mesh); } if (!marked) break; //(*testout) << "mtets " << mtets << endl; if (opt.refine_p) { PrintMessage(3,"refine p"); for (int i = 1; i <= mtets.Size(); i++) mtets.Elem(i).incorder = mtets.Elem(i).marked ? 1 : 0; for (int i = 1; i <= mtets.Size(); i++) if (mtets.Elem(i).incorder) mtets.Elem(i).marked = 0; for (int i = 1; i <= mprisms.Size(); i++) mprisms.Elem(i).incorder = mprisms.Elem(i).marked ? 1 : 0; for (int i = 1; i <= mprisms.Size(); i++) if (mprisms.Elem(i).incorder) mprisms.Elem(i).marked = 0; for (int i = 1; i <= mtris.Size(); i++) mtris.Elem(i).incorder = mtris.Elem(i).marked ? 1 : 0; for (int i = 1; i <= mtris.Size(); i++) { if (mtris.Elem(i).incorder) mtris.Elem(i).marked = 0; } } if (opt.refine_hp) { PrintMessage(3,"refine hp"); BitArray singv(np); singv.Clear(); if (mesh.GetDimension() == 3) { for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); singv.Set (seg[0]); singv.Set (seg[1]); } /* for ( i=1; i<= mesh.GetNSE(); i++) { const Element2d & sel = mesh.SurfaceElement(i); for(int j=1; j<=sel.GetNP(); j++) singv.Set(sel.PNum(j)); } */ } else { // vertices with 2 different bnds Array bndind(np); bndind = 0; for (int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); for (int j = 0; j < 2; j++) { int pi = (j == 0) ? seg[0] : seg[1]; if (bndind.Elem(pi) == 0) bndind.Elem(pi) = seg.edgenr; else if (bndind.Elem(pi) != seg.edgenr) singv.Set (pi); } } } for (int i = 1; i <= mtets.Size(); i++) mtets.Elem(i).incorder = 1; for (int i = 1; i <= mtets.Size(); i++) { if (!mtets.Elem(i).marked) mtets.Elem(i).incorder = 0; for (int j = 0; j < 4; j++) if (singv.Test (mtets.Elem(i).pnums[j])) mtets.Elem(i).incorder = 0; } for (int i = 1; i <= mtets.Size(); i++) if (mtets.Elem(i).incorder) mtets.Elem(i).marked = 0; for (int i = 1; i <= mprisms.Size(); i++) mprisms.Elem(i).incorder = 1; for (int i = 1; i <= mprisms.Size(); i++) { if (!mprisms.Elem(i).marked) mprisms.Elem(i).incorder = 0; for (int j = 0; j < 6; j++) if (singv.Test (mprisms.Elem(i).pnums[j])) mprisms.Elem(i).incorder = 0; } for (int i = 1; i <= mprisms.Size(); i++) if (mprisms.Elem(i).incorder) mprisms.Elem(i).marked = 0; for (int i = 1; i <= mtris.Size(); i++) mtris.Elem(i).incorder = 1; for (int i = 1; i <= mtris.Size(); i++) { if (!mtris.Elem(i).marked) mtris.Elem(i).incorder = 0; for (int j = 0; j < 3; j++) if (singv.Test (mtris.Elem(i).pnums[j])) mtris.Elem(i).incorder = 0; } for (int i = 1; i <= mtris.Size(); i++) { if (mtris.Elem(i).incorder) mtris.Elem(i).marked = 0; } } int hangingvol, hangingsurf, hangingedge; //cout << "write?" << endl; //string yn; //cin >> yn; (*testout) << "refine volume elements" << endl; do { // refine volume elements NgProfiler::StartTimer (timer_bisecttet); (*opt.tracer)("bisecttet", false); int nel = mtets.Size(); for (int i = 1; i <= nel; i++) if (mtets.Elem(i).marked) { MarkedTet oldtet = mtets.Get(i); INDEX_2 edge(oldtet.pnums[oldtet.tetedge1], oldtet.pnums[oldtet.tetedge2]); edge.Sort(); PointIndex newp; if (cutedges.Used (edge)) { newp = cutedges.Get(edge); } else { Point<3> npt = Center (mesh.Point (edge.I1()), mesh.Point (edge.I2())); newp = mesh.AddPoint (npt); cutedges.Set (edge, newp); } MarkedTet newtet1, newtet2; BTBisectTet (oldtet, newp, newtet1, newtet2); mtets.Elem(i) = newtet1; mtets.Append (newtet2); mesh.mlparentelement.Append (i); } NgProfiler::StopTimer (timer_bisecttet); (*opt.tracer)("bisecttet", true); int npr = mprisms.Size(); for (int i = 1; i <= npr; i++) if (mprisms.Elem(i).marked) { MarkedPrism oldprism; MarkedPrism newprism1, newprism2; PointIndex newp1, newp2; oldprism = mprisms.Get(i); int pi1 = 0; if (pi1 == oldprism.markededge) pi1++; int pi2 = 3-pi1-oldprism.markededge; INDEX_2 edge1(oldprism.pnums[pi1], oldprism.pnums[pi2]); INDEX_2 edge2(oldprism.pnums[pi1+3], oldprism.pnums[pi2+3]); edge1.Sort(); edge2.Sort(); if (cutedges.Used (edge1)) newp1 = cutedges.Get(edge1); else { Point<3> npt = Center (mesh.Point (edge1.I1()), mesh.Point (edge1.I2())); newp1 = mesh.AddPoint (npt); cutedges.Set (edge1, newp1); } if (cutedges.Used (edge2)) newp2 = cutedges.Get(edge2); else { Point<3> npt = Center (mesh.Point (edge2.I1()), mesh.Point (edge2.I2())); newp2 = mesh.AddPoint (npt); cutedges.Set (edge2, newp2); } BTBisectPrism (oldprism, newp1, newp2, newprism1, newprism2); //if(yn == "y") // (*testout) << "bisected prism " << oldprism << "and got " << newprism1 << "and " << newprism2 << endl; mprisms.Elem(i) = newprism1; mprisms.Append (newprism2); } int nid = mids.Size(); for (int i = 1; i <= nid; i++) if (mids.Elem(i).marked) { MarkedIdentification oldid,newid1,newid2; Array newp; oldid = mids.Get(i); Array edges; edges.Append(INDEX_2(oldid.pnums[oldid.markededge], oldid.pnums[(oldid.markededge+1)%oldid.np])); edges.Append(INDEX_2(oldid.pnums[oldid.markededge + oldid.np], oldid.pnums[(oldid.markededge+1)%oldid.np + oldid.np])); if(oldid.np == 4) { edges.Append(INDEX_2(oldid.pnums[(oldid.markededge+2)%oldid.np], oldid.pnums[(oldid.markededge+3)%oldid.np])); edges.Append(INDEX_2(oldid.pnums[(oldid.markededge+2)%oldid.np + oldid.np], oldid.pnums[(oldid.markededge+3)%oldid.np + oldid.np])); } for (int j = 0; j < edges.Size(); j++) { edges[j].Sort(); if(cutedges.Used(edges[j])) newp.Append(cutedges.Get(edges[j])); else { Point<3> npt = Center (mesh.Point (edges[j].I1()), mesh.Point (edges[j].I2())); newp.Append(mesh.AddPoint(npt)); cutedges.Set(edges[j],newp[j]); } } BTBisectIdentification(oldid,newp,newid1,newid2); mids.Elem(i) = newid1; mids.Append(newid2); } //IdentifyCutEdges(mesh, cutedges); (*opt.tracer)("mark elements", false); hangingvol = MarkHangingTets (mtets, cutedges, opt.task_manager) + MarkHangingPrisms (mprisms, cutedges) + MarkHangingIdentifications (mids, cutedges); (*opt.tracer)("mark elements", true); size_t nsel = mtris.Size(); NgProfiler::StartTimer (timer_bisecttrig); (*opt.tracer)("Bisect trigs", false); for (size_t i = 0; i < nsel; i++) if (mtris[i].marked) { MarkedTri newtri1, newtri2; PointIndex newp; MarkedTri oldtri = mtris[i]; PointIndex oldpi1 = oldtri.pnums[(oldtri.markededge+1)%3]; PointIndex oldpi2 = oldtri.pnums[(oldtri.markededge+2)%3]; INDEX_2 edge(oldpi1, oldpi2); edge.Sort(); if (cutedges.Used (edge)) { newp = cutedges.Get(edge); } else { Point<3> npt = Center (mesh.Point (edge.I1()), mesh.Point (edge.I2())); newp = mesh.AddPoint (npt); cutedges.Set (edge, newp); } int si = mesh.GetFaceDescriptor (oldtri.surfid).SurfNr(); PointGeomInfo npgi; if (mesh[newp].Type() != EDGEPOINT) PointBetween (mesh.Point (oldpi1), mesh.Point (oldpi2), 0.5, si, oldtri.pgeominfo[(oldtri.markededge+1)%3], oldtri.pgeominfo[(oldtri.markededge+2)%3], mesh.Point (newp), npgi); BTBisectTri (oldtri, newp, npgi, newtri1, newtri2); mtris[i] = newtri1; mtris.Append (newtri2); mesh.mlparentsurfaceelement.Append (i+1); } NgProfiler::StopTimer (timer_bisecttrig); (*opt.tracer)("Bisect trigs", true); int nquad = mquads.Size(); for (int i = 1; i <= nquad; i++) if (mquads.Elem(i).marked) { MarkedQuad oldquad; MarkedQuad newquad1, newquad2; PointIndex newp1, newp2; oldquad = mquads.Get(i); /* INDEX_2 edge1(oldquad.pnums[0], oldquad.pnums[1]); INDEX_2 edge2(oldquad.pnums[2], oldquad.pnums[3]); */ INDEX_2 edge1, edge2; PointGeomInfo pgi11, pgi12, pgi21, pgi22; if (oldquad.markededge==0 || oldquad.markededge==2) { edge1.I1()=oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0]; edge1.I2()=oldquad.pnums[1]; pgi12=oldquad.pgeominfo[1]; edge2.I1()=oldquad.pnums[2]; pgi21=oldquad.pgeominfo[2]; edge2.I2()=oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3]; } else // 3 || 1 { edge1.I1()=oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0]; edge1.I2()=oldquad.pnums[2]; pgi12=oldquad.pgeominfo[2]; edge2.I1()=oldquad.pnums[1]; pgi21=oldquad.pgeominfo[1]; edge2.I2()=oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3]; } edge1.Sort(); edge2.Sort(); if (cutedges.Used (edge1)) { newp1 = cutedges.Get(edge1); } else { Point<3> np1 = Center (mesh.Point (edge1.I1()), mesh.Point (edge1.I2())); newp1 = mesh.AddPoint (np1); cutedges.Set (edge1, newp1); } if (cutedges.Used (edge2)) { newp2 = cutedges.Get(edge2); } else { Point<3> np2 = Center (mesh.Point (edge2.I1()), mesh.Point (edge2.I2())); newp2 = mesh.AddPoint (np2); cutedges.Set (edge2, newp2); } PointGeomInfo npgi1, npgi2; int si = mesh.GetFaceDescriptor (oldquad.surfid).SurfNr(); // geom->GetSurface(si)->Project (mesh.Point(newp1)); // geom->GetSurface(si)->Project (mesh.Point(newp2)); // (*testout) // cerr << "project point 1 " << newp1 << " old: " << mesh.Point(newp1); PointBetween (mesh.Point (edge1.I1()), mesh.Point (edge1.I2()), 0.5, si, pgi11, pgi12, mesh.Point (newp1), npgi1); // (*testout) // cerr << " new: " << mesh.Point(newp1) << endl; // cerr << "project point 2 " << newp2 << " old: " << mesh.Point(newp2); PointBetween (mesh.Point (edge2.I1()), mesh.Point (edge2.I2()), 0.5, si, pgi21, pgi22, mesh.Point (newp2), npgi2); // cerr << " new: " << mesh.Point(newp2) << endl; BTBisectQuad (oldquad, newp1, npgi1, newp2, npgi2, newquad1, newquad2); mquads.Elem(i) = newquad1; mquads.Append (newquad2); } NgProfiler::StartTimer (timer1b); hangingsurf = MarkHangingTris (mtris, cutedges, opt.task_manager) + MarkHangingQuads (mquads, cutedges); hangingedge = mesh.GetDimension() == 3 ? 0 : MarkHangingIdentifications(mids, cutedges); NgProfiler::StopTimer (timer1b); NgProfiler::StartTimer (timer_bisectsegms); int nseg = mesh.GetNSeg (); for (int i = 1; i <= nseg; i++) { Segment & seg = mesh.LineSegment (i); INDEX_2 edge(seg[0], seg[1]); edge.Sort(); if (cutedges.Used (edge)) { hangingedge = 1; Segment nseg1 = seg; Segment nseg2 = seg; int newpi = cutedges.Get(edge); nseg1[1] = newpi; nseg2[0] = newpi; EdgePointGeomInfo newepgi; // // cerr << "move edgepoint " << newpi << " from " << mesh.Point(newpi); PointBetween (mesh.Point (seg[0]), mesh.Point (seg[1]), 0.5, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0], seg.epgeominfo[1], mesh.Point (newpi), newepgi); // cerr << " to " << mesh.Point (newpi) << endl; nseg1.epgeominfo[1] = newepgi; nseg2.epgeominfo[0] = newepgi; mesh.LineSegment (i) = nseg1; mesh.AddSegment (nseg2); } } NgProfiler::StopTimer (timer_bisectsegms); } while (hangingvol || hangingsurf || hangingedge); /* if (printmessage_importance>0) { ostringstream strstr; strstr << mtets.Size() << " tets" << endl << mtris.Size() << " trigs" << endl; if (mprisms.Size()) { strstr << mprisms.Size() << " prisms" << endl << mquads.Size() << " quads" << endl; } strstr << mesh.GetNP() << " points"; PrintMessage(4,strstr.str()); } */ PrintMessage (4, mtets.Size(), " tets"); PrintMessage (4, mtris.Size(), " trigs"); if (mprisms.Size()) { PrintMessage (4, mprisms.Size(), " prisms"); PrintMessage (4, mquads.Size(), " quads"); } PrintMessage (4, mesh.GetNP(), " points"); } NgProfiler::StopTimer (timer1); // (*testout) << "mtets = " << mtets << endl; if (opt.refine_hp) { // Array v_order (mesh.GetNP()); v_order = 0; if (mesh.GetDimension() == 3) { for (int i = 1; i <= mtets.Size(); i++) if (mtets.Elem(i).incorder) mtets.Elem(i).order++; for (int i = 0; i < mtets.Size(); i++) for (int j = 0; j < 4; j++) if (int(mtets[i].order) > v_order.Elem(mtets[i].pnums[j])) v_order.Elem(mtets[i].pnums[j]) = mtets[i].order; for (int i = 0; i < mtets.Size(); i++) for (int j = 0; j < 4; j++) if (int(mtets[i].order) < v_order.Elem(mtets[i].pnums[j])-1) mtets[i].order = v_order.Elem(mtets[i].pnums[j])-1; } else { for (int i = 1; i <= mtris.Size(); i++) if (mtris.Elem(i).incorder) { mtris.Elem(i).order++; } for (int i = 0; i < mtris.Size(); i++) for (int j = 0; j < 3; j++) if (int(mtris[i].order) > v_order.Elem(mtris[i].pnums[j])) v_order.Elem(mtris[i].pnums[j]) = mtris[i].order; for (int i = 0; i < mtris.Size(); i++) { for (int j = 0; j < 3; j++) if (int(mtris[i].order) < v_order.Elem(mtris[i].pnums[j])-1) mtris[i].order = v_order.Elem(mtris[i].pnums[j])-1; } } } NgProfiler::StartTimer (timer2); NgProfiler::StartTimer (timer2a); mtets.SetAllocSize (mtets.Size()); mprisms.SetAllocSize (mprisms.Size()); mids.SetAllocSize (mids.Size()); mtris.SetAllocSize (mtris.Size()); mquads.SetAllocSize (mquads.Size()); (*opt.tracer)("copy tets", false); mesh.ClearVolumeElements(); mesh.VolumeElements().SetAllocSize (mtets.Size()+mprisms.Size()); mesh.VolumeElements().SetSize(mtets.Size()); /* for (int i = 1; i <= mtets.Size(); i++) { Element el(TET); el.SetIndex (mtets.Get(i).matindex); for (int j = 1; j <= 4; j++) el.PNum(j) = mtets.Get(i).pnums[j-1]; el.SetOrder (mtets.Get(i).order); mesh.AddVolumeElement (el); } */ ParallelForRange (opt.task_manager, mtets.Size(), [&] (size_t begin, size_t end) { for (size_t i = begin; i < end; i++) { Element el(TET); auto & tet = mtets[i]; el.SetIndex (tet.matindex); el.SetOrder (tet.order); for (int j = 0; j < 4; j++) el[j] = tet.pnums[j]; mesh.SetVolumeElement (ElementIndex(i), el); } }); (*opt.tracer)("copy tets", true); for (int i = 1; i <= mprisms.Size(); i++) { Element el(PRISM); el.SetIndex (mprisms.Get(i).matindex); for (int j = 1; j <= 6; j++) el.PNum(j) = mprisms.Get(i).pnums[j-1]; el.SetOrder (mprisms.Get(i).order); // degenerated prism ? static const int map1[] = { 3, 2, 5, 6, 1 }; static const int map2[] = { 1, 3, 6, 4, 2 }; static const int map3[] = { 2, 1, 4, 5, 3 }; const int * map = NULL; int deg1 = 0, deg2 = 0, deg3 = 0; // int deg = 0; if (el.PNum(1) == el.PNum(4)) { map = map1; deg1 = 1; } if (el.PNum(2) == el.PNum(5)) { map = map2; deg2 = 1; } if (el.PNum(3) == el.PNum(6)) { map = map3; deg3 = 1; } switch (deg1+deg2+deg3) { case 1: { for (int j = 1; j <= 5; j++) el.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1]; el.SetType (PYRAMID); break; } case 2: { static const int tetmap1[] = { 1, 2, 3, 4 }; static const int tetmap2[] = { 2, 3, 1, 5 }; static const int tetmap3[] = { 3, 1, 2, 6 }; if (!deg1) map = tetmap1; if (!deg2) map = tetmap2; if (!deg3) map = tetmap3; for (int j = 1; j <= 4; j++) el.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1]; /* if (!deg1) el.PNum(4) = el.PNum(4); if (!deg2) el.PNum(4) = el.PNum(5); if (!deg3) el.PNum(4) = el.PNum(6); */ el.SetType(TET); break; } default: ; } mesh.AddVolumeElement (el); } mesh.ClearSurfaceElements(); mesh.SurfaceElements().SetAllocSize (mtris.Size()+mquads.Size()); NgProfiler::StopTimer (timer2a); NgProfiler::StartTimer (timer2b); /* for (auto & trig : mtris) { Element2d el(TRIG); el.SetIndex (trig.surfid); el.SetOrder (trig.order); for (int j = 0; j < 3; j++) { el[j] = trig.pnums[j]; el.GeomInfoPi(j+1) = trig.pgeominfo[j]; } mesh.AddSurfaceElement (el); } */ mesh.SurfaceElements().SetSize(mtris.Size()); // for (size_t i = 0; i < mtris.Size(); i++) ParallelForRange (opt.task_manager, mtris.Size(), [&] (size_t begin, size_t end) { for (size_t i = begin; i < end; i++) { Element2d el(TRIG); auto & trig = mtris[i]; el.SetIndex (trig.surfid); el.SetOrder (trig.order); for (int j = 0; j < 3; j++) { el[j] = trig.pnums[j]; el.GeomInfoPi(j+1) = trig.pgeominfo[j]; } mesh.SetSurfaceElement (SurfaceElementIndex(i), el); } }); mesh.RebuildSurfaceElementLists(); for (int i = 1; i <= mquads.Size(); i++) { Element2d el(QUAD); el.SetIndex (mquads.Get(i).surfid); for (int j = 1; j <= 4; j++) el.PNum(j) = mquads.Get(i).pnums[j-1]; Swap (el.PNum(3), el.PNum(4)); mesh.AddSurfaceElement (el); } NgProfiler::StopTimer (timer2b); // write multilevel hierarchy to mesh: np = mesh.GetNP(); mesh.mlbetweennodes.SetSize(np); if (mesh.mglevels <= 2) { PrintMessage(4,"RESETTING mlbetweennodes"); for (int i = 1; i <= np; i++) { mesh.mlbetweennodes.Elem(i).I1() = 0; mesh.mlbetweennodes.Elem(i).I2() = 0; } } /* for (i = 1; i <= cutedges.GetNBags(); i++) for (j = 1; j <= cutedges.GetBagSize(i); j++) { INDEX_2 edge; int newpi; cutedges.GetData (i, j, edge, newpi); mesh.mlbetweennodes.Elem(newpi) = edge; } */ BitArray isnewpoint(np); isnewpoint.Clear(); for (int i = 0; i < cutedges.Size(); i++) if (cutedges.UsedPos0(i)) { INDEX_2 edge; PointIndex newpi; cutedges.GetData0 (i, edge, newpi); isnewpoint.Set(newpi); mesh.mlbetweennodes.Elem(newpi) = edge; } /* mesh.PrintMemInfo (cout); cout << "tets "; mtets.PrintMemInfo (cout); cout << "prims "; mprisms.PrintMemInfo (cout); cout << "tris "; mtris.PrintMemInfo (cout); cout << "quads "; mquads.PrintMemInfo (cout); cout << "cutedges "; cutedges.PrintMemInfo (cout); */ /* // find connected nodes (close nodes) TABLE conto(np); for (i = 1; i <= mprisms.Size(); i++) for (j = 1; j <= 6; j++) { int n1 = mprisms.Get(i).pnums[j-1]; int n2 = mprisms.Get(i).pnums[(j+2)%6]; // if (n1 != n2) { int found = 0; for (k = 1; k <= conto.EntrySize(n1); k++) if (conto.Get(n1, k) == n2) { found = 1; break; } if (!found) conto.Add (n1, n2); } } mesh.connectedtonode.SetSize(np); for (i = 1; i <= np; i++) mesh.connectedtonode.Elem(i) = 0; // (*testout) << "connection table: " << endl; // for (i = 1; i <= np; i++) // { // (*testout) << "node " << i << ": "; // for (j = 1; j <= conto.EntrySize(i); j++) // (*testout) << conto.Get(i, j) << " "; // (*testout) << endl; // } for (i = 1; i <= np; i++) if (mesh.connectedtonode.Elem(i) == 0) { mesh.connectedtonode.Elem(i) = i; ConnectToNodeRec (i, i, conto, mesh.connectedtonode); } */ // mesh.BuildConnectedNodes(); mesh.ComputeNVertices(); (*opt.tracer)("call RebuildSurfElList", false); mesh.RebuildSurfaceElementLists(); (*opt.tracer)("call RebuildSurfElList", true); // update identification tables for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) { Array identmap; mesh.GetIdentifications().GetMap (i, identmap); /* for (j = 1; j <= cutedges.GetNBags(); j++) for (k = 1; k <= cutedges.GetBagSize(j); k++) { INDEX_2 i2; int newpi; cutedges.GetData (j, k, i2, newpi); INDEX_2 oi2(identmap.Get(i2.I1()), identmap.Get(i2.I2())); oi2.Sort(); if (cutedges.Used (oi2)) { int onewpi = cutedges.Get(oi2); mesh.GetIdentifications().Add (newpi, onewpi, i); } } */ for (int j = 0; j < cutedges.Size(); j++) if (cutedges.UsedPos0(j)) { INDEX_2 i2; PointIndex newpi; cutedges.GetData0 (j, i2, newpi); INDEX_2 oi2(identmap.Get(i2.I1()), identmap.Get(i2.I2())); oi2.Sort(); if (cutedges.Used (oi2)) { PointIndex onewpi = cutedges.Get(oi2); mesh.GetIdentifications().Add (newpi, onewpi, i); } } } (*opt.tracer)("Bisect", true); // Repair works only for tets! bool do_repair = mesh.PureTetMesh (); do_repair = false; // JS, March 2009: multigrid crashes //if(mesh.mglevels == 3) // noprojection = true; //noprojection = true; if(noprojection) { do_repair = false; for(int ii=1; ii<=mesh.GetNP(); ii++) { if(isnewpoint.Test(ii) && mesh.mlbetweennodes[ii][0] > 0) { mesh.Point(ii) = Center(mesh.Point(mesh.mlbetweennodes[ii][0]), mesh.Point(mesh.mlbetweennodes[ii][1])); } } } // Check/Repair static bool repaired_once; if(mesh.mglevels == 1) repaired_once = false; //mesh.Save("before.vol"); static int reptimer = NgProfiler::CreateTimer("check/repair"); NgProfiler::RegionTimer * regt(NULL); regt = new NgProfiler::RegionTimer(reptimer); Array bad_elts; Array pure_badness; if(do_repair || quality_loss != NULL) { pure_badness.SetSize(mesh.GetNP()+2); GetPureBadness(mesh,pure_badness,isnewpoint); } if(do_repair) // by Markus W { const double max_worsening = 1; const bool uselocalworsening = false; // bool repaired = false; Validate(mesh,bad_elts,pure_badness,max_worsening,uselocalworsening); if (printmessage_importance>0) { ostringstream strstr; for(int ii=0; ii 0) { clock_t t1(clock()); // update id-maps int j=0; for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) { if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) { mesh.GetIdentifications().GetMap(i,*idmaps[j],true); j++; } } // do the repair try { RepairBisection(mesh,bad_elts,isnewpoint,*this, pure_badness, max_worsening,uselocalworsening, idmaps); // repaired = true; repaired_once = true; } catch(NgException & ex) { PrintMessage(1,string("Problem: ") + ex.What()); } if (printmessage_importance>0) { ostringstream strstr; strstr << "Time for Repair: " << double(clock() - t1)/double(CLOCKS_PER_SEC) << endl << "bad elements after repair: " << bad_elts << endl; PrintMessage(1,strstr.str()); } if(quality_loss != NULL) Validate(mesh,bad_elts,pure_badness,1e100,uselocalworsening,quality_loss); if(idmaps.Size() == 0) UpdateEdgeMarks(mesh,idmaps); /* if(1==1) UpdateEdgeMarks(mesh,idmaps); else mesh.mglevels = 1; */ //mesh.ImproveMesh(); } } delete regt; for(int i=0; i & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const { newp = p1+secpoint*(p2-p1); } void Refinement :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const { //cout << "base class edge point between" << endl; newp = p1+secpoint*(p2-p1); } Vec<3> Refinement :: GetTangent (const Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & ap1) const { cerr << "Refinement::GetTangent not overloaded" << endl; return Vec<3> (0,0,0); } Vec<3> Refinement :: GetNormal (const Point<3> & p, int surfi1, const PointGeomInfo & gi) const { cerr << "Refinement::GetNormal not overloaded" << endl; return Vec<3> (0,0,0); } void Refinement :: ProjectToSurface (Point<3> & p, int surfi) const { if (printmessage_importance>0) cerr << "Refinement :: ProjectToSurface ERROR: no geometry set" << endl; }; void Refinement :: ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const { cerr << "Refinement::ProjectToEdge not overloaded" << endl; } } netgen-6.2.1905/libsrc/meshing/specials.hpp0000644000175000017500000000035413504650527017227 0ustar kurtkurt#ifndef FILE_SPECIALS #define FILE_SPECIALS /* Very special implementations .. */ /// DLL_HEADER extern void CutOffAndCombine (Mesh & mesh, const Mesh & othermesh); DLL_HEADER extern void HelmholtzMesh (Mesh & mesh); #endif netgen-6.2.1905/libsrc/meshing/topology.hpp0000644000175000017500000003566313504650527017313 0ustar kurtkurt#ifndef TOPOLOGY #define TOPOLOGY /**************************************************************************/ /* File: topology.hh */ /* Author: Joachim Schoeberl */ /* Date: 27. Apr. 01 */ /**************************************************************************/ /* Mesh topology (Elements, Faces, Edges, Vertices */ namespace netgen { struct T_EDGE { // int orient:1; int nr; // 0-based }; struct T_FACE { // int forient:3; int fnr; // 0-based }; template struct FixArray { T vals[S]; T & operator[] (size_t i) { return vals[i]; } T operator[] (size_t i) const { return vals[i]; } }; class MeshTopology { const Mesh * mesh; bool buildedges; bool buildfaces; Array edge2vert; Array face2vert; /* Array edges; Array faces; Array surfedges; */ Array> edges; Array> faces; Array> surfedges; Array segedges; Array surffaces; Array surf2volelement; Array face2surfel; TABLE vert2element; TABLE vert2surfelement; TABLE vert2segment; TABLE vert2pointelement; int timestamp; public: int GetNSurfedges() const {return surfedges.Size();} MeshTopology () = default; MeshTopology (MeshTopology && top) = default; MeshTopology (const Mesh & amesh); ~MeshTopology (); MeshTopology & operator= (MeshTopology && top) = default; void SetBuildEdges (bool be) { buildedges = be; } void SetBuildFaces (bool bf) { buildfaces = bf; } bool HasEdges () const { return buildedges; } bool HasFaces () const { return buildfaces; } void Update(TaskManager tm = &DummyTaskManager, Tracer tracer = &DummyTracer); bool NeedsUpdate() const; int GetNEdges () const { return edge2vert.Size(); } int GetNFaces () const { return face2vert.Size(); } static inline short int GetNVertices (ELEMENT_TYPE et); static inline short int GetNPoints (ELEMENT_TYPE et); static inline short int GetNEdges (ELEMENT_TYPE et); static inline short int GetNFaces (ELEMENT_TYPE et); static const Point3d * GetVertices (ELEMENT_TYPE et); inline static const ELEMENT_EDGE * GetEdges1 (ELEMENT_TYPE et); inline static const ELEMENT_EDGE * GetEdges0 (ELEMENT_TYPE et); inline static const ELEMENT_FACE * GetFaces1 (ELEMENT_TYPE et); inline static const ELEMENT_FACE * GetFaces0 (ELEMENT_TYPE et); int GetSegmentEdge (int segnr) const { return segedges[segnr-1].nr+1; } int GetEdge (SegmentIndex segnr) const { return segedges[segnr].nr; } void GetSegmentEdge (int segnr, int & enr, int & orient) const { enr = segedges.Get(segnr).nr+1; // orient = segedges.Get(segnr).orient; orient = GetSegmentEdgeOrientation(segnr); } void GetElementEdges (int elnr, Array & edges) const; void GetElementFaces (int elnr, Array & faces, bool withorientation = false) const; void GetElementEdgeOrientations (int elnr, Array & eorient) const; void GetElementFaceOrientations (int elnr, Array & forient) const; int GetElementEdges (int elnr, int * edges, int * orient) const; int GetElementFaces (int elnr, int * faces, int * orient) const; int GetElementEdgeOrientation (int elnr, int locedgenr) const; // old style int GetElementFaceOrientation (int elnr, int locfacenr) const; // old style int GetSurfaceElementEdgeOrientation (int elnr, int locedgenr) const; // old style int GetSurfaceElementFaceOrientation2 (int elnr) const; // old style int GetSegmentEdgeOrientation (int elnr) const; // old style void GetFaceVertices (int fnr, Array & vertices) const; void GetFaceVertices (int fnr, int * vertices) const; void GetEdgeVertices (int enr, int & v1, int & v2) const; void GetEdgeVertices (int enr, PointIndex & v1, PointIndex & v2) const; const int * GetEdgeVerticesPtr (int enr) const { return &edge2vert[enr][0]; } const int * GetFaceVerticesPtr (int fnr) const { return &face2vert[fnr][0]; } void GetFaceEdges (int fnr, Array & edges, bool withorientation = false) const; ELEMENT_TYPE GetFaceType (int fnr) const { return (face2vert.Get(fnr)[3] == 0) ? TRIG : QUAD; } void GetSurfaceElementEdges (int elnr, Array & edges) const; int GetSurfaceElementFace (int elnr) const; void GetSurfaceElementEdgeOrientations (int elnr, Array & eorient) const; int GetSurfaceElementFaceOrientation (int elnr) const; void GetEdges (SurfaceElementIndex elnr, Array & edges) const; int GetFace (SurfaceElementIndex elnr) const { return surffaces[elnr].fnr; } int GetSurfaceElementEdges (int elnr, int * edges, int * orient) const; const T_EDGE * GetElementEdgesPtr (int elnr) const { return &edges[elnr][0]; } const T_EDGE * GetSurfaceElementEdgesPtr (int selnr) const { return &surfedges[selnr][0]; } const T_EDGE * GetSegmentElementEdgesPtr (int selnr) const { return &segedges[selnr]; } const T_FACE * GetElementFacesPtr (int elnr) const { return &faces[elnr][0]; } const T_FACE * GetSurfaceElementFacesPtr (int selnr) const { return &surffaces[selnr]; } void GetSurface2VolumeElement (int selnr, int & elnr1, int & elnr2) const { elnr1 = surf2volelement.Get(selnr)[0]; elnr2 = surf2volelement.Get(selnr)[1]; } int GetFace2SurfaceElement (int fnr) const { return face2surfel[fnr-1]; } void GetVertexElements (int vnr, Array & elements) const; FlatArray GetVertexElements (int vnr) const { return vert2element[vnr]; } void GetVertexSurfaceElements( int vnr, Array& elements ) const; FlatArray GetVertexSurfaceElements (int vnr) const { return vert2surfelement[vnr]; } FlatArray GetVertexSegments (int vnr) const { return vert2segment[vnr]; } FlatArray GetVertexPointElements (int vnr) const { return vert2pointelement[vnr]; } int GetVerticesEdge ( int v1, int v2) const; void GetSegmentVolumeElements ( int segnr, Array & els ) const; void GetSegmentSurfaceElements ( int segnr, Array & els ) const; }; inline short int MeshTopology :: GetNVertices (ELEMENT_TYPE et) { switch (et) { case SEGMENT: case SEGMENT3: return 2; case TRIG: case TRIG6: return 3; case QUAD: case QUAD6: case QUAD8: return 4; case TET: case TET10: return 4; case PYRAMID: case PYRAMID13: return 5; case PRISM: case PRISM12: case PRISM15: return 6; case HEX: case HEX20: return 8; // default: // cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; } return 0; } inline short int MeshTopology :: GetNPoints (ELEMENT_TYPE et) { switch (et) { case SEGMENT: return 2; case SEGMENT3: return 3; case TRIG: return 3; case TRIG6: return 6; case QUAD: case QUAD6: return 4; case QUAD8: return 8; case TET: return 4; case TET10: return 10; case PYRAMID: return 5; case PYRAMID13: return 13; case PRISM: return 6; case PRISM12: return 12; case PRISM15: return 15; case HEX: return 8; case HEX20: return 20; // default: // cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; } return 0; } inline short int MeshTopology :: GetNEdges (ELEMENT_TYPE et) { __assume(et >= SEGMENT && et <= PYRAMID13); switch (et) { case SEGMENT: case SEGMENT3: return 1; case TRIG: case TRIG6: return 3; case QUAD: case QUAD6: case QUAD8: return 4; case TET: case TET10: return 6; case PYRAMID: case PYRAMID13: return 8; case PRISM: case PRISM12: case PRISM15: return 9; case HEX: case HEX20: return 12; default: return 0; // default: // cerr << "Ng_ME_GetNEdges, illegal element type " << et << endl; } // return 0; } inline short int MeshTopology :: GetNFaces (ELEMENT_TYPE et) { __assume(et >= SEGMENT && et <= PYRAMID13); switch (et) { case SEGMENT: case SEGMENT3: return 0; case TRIG: case TRIG6: return 1; case QUAD: case QUAD6: case QUAD8: return 1; case TET: case TET10: return 4; case PYRAMID: case PYRAMID13: return 5; case PRISM: case PRISM12: case PRISM15: return 5; case HEX: case HEX20: return 6; default: return -99; // default: // cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; } } const ELEMENT_EDGE * MeshTopology :: GetEdges1 (ELEMENT_TYPE et) { static ELEMENT_EDGE segm_edges[1] = { { 1, 2 }}; static ELEMENT_EDGE trig_edges[3] = { { 3, 1 }, { 2, 3 }, { 1, 2 }}; static ELEMENT_EDGE quad_edges[4] = { { 1, 2 }, { 3, 4 }, { 4, 1 }, { 2, 3 }}; static ELEMENT_EDGE tet_edges[6] = { { 4, 1 }, { 4, 2 }, { 4, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 }}; static ELEMENT_EDGE prism_edges[9] = { { 3, 1 }, { 1, 2 }, { 3, 2 }, { 6, 4 }, { 4, 5 }, { 6, 5 }, { 3, 6 }, { 1, 4 }, { 2, 5 }}; static ELEMENT_EDGE pyramid_edges[8] = { { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 3 }, { 1, 5 }, { 2, 5 }, { 3, 5 }, { 4, 5 }}; static ELEMENT_EDGE hex_edges[12] = { { 1, 2 }, { 3, 4 }, { 4, 1 }, { 2, 3 }, { 5, 6 }, { 7, 8 }, { 8, 5 }, { 6, 7 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, { 4, 8 }, }; switch (et) { case SEGMENT: case SEGMENT3: return segm_edges; case TRIG: case TRIG6: return trig_edges; case QUAD: case QUAD6: case QUAD8: return quad_edges; case TET: case TET10: return tet_edges; case PYRAMID: case PYRAMID13: return pyramid_edges; case PRISM: case PRISM12: case PRISM15: return prism_edges; case HEX: case HEX20: return hex_edges; // default: // cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; } return 0; } const ELEMENT_EDGE * MeshTopology :: GetEdges0 (ELEMENT_TYPE et) { static ELEMENT_EDGE segm_edges[1] = { { 0, 1 }}; static ELEMENT_EDGE trig_edges[3] = { { 2, 0 }, { 1, 2 }, { 0, 1 }}; static ELEMENT_EDGE quad_edges[4] = { { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }}; static ELEMENT_EDGE tet_edges[6] = { { 3, 0 }, { 3, 1 }, { 3, 2 }, { 0, 1 }, { 0, 2 }, { 1, 2 }}; static ELEMENT_EDGE prism_edges[9] = { { 2, 0 }, { 0, 1 }, { 2, 1 }, { 5, 3 }, { 3, 4 }, { 5, 4 }, { 2, 5 }, { 0, 3 }, { 1, 4 }}; static ELEMENT_EDGE pyramid_edges[8] = { { 0, 1 }, { 1, 2 }, { 0, 3 }, { 3, 2 }, { 0, 4 }, { 1, 4 }, { 2, 4 }, { 3, 4 }}; static ELEMENT_EDGE hex_edges[12] = { { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, }; switch (et) { case SEGMENT: case SEGMENT3: return segm_edges; case TRIG: case TRIG6: return trig_edges; case QUAD: case QUAD6: case QUAD8: return quad_edges; case TET: case TET10: return tet_edges; case PYRAMID: case PYRAMID13: return pyramid_edges; case PRISM: case PRISM12: case PRISM15: return prism_edges; case HEX: case HEX20: return hex_edges; // default: // cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; } return 0; } inline const ELEMENT_FACE * MeshTopology :: GetFaces1 (ELEMENT_TYPE et) { static const ELEMENT_FACE trig_faces[1] = { { 1, 2, 3, 0 } }; static const ELEMENT_FACE quad_faces[1] = { { 1, 2, 3, 4 } }; static const ELEMENT_FACE tet_faces[4] = { { 4, 2, 3, 0 }, { 4, 3, 1, 0 }, { 4, 1, 2, 0 }, { 1, 3, 2, 0 } }; static const ELEMENT_FACE prism_faces[5] = { { 1, 3, 2, 0 }, { 4, 5, 6, 0 }, { 3, 1, 4, 6 }, { 1, 2, 5, 4 }, { 2, 3, 6, 5 } }; static const ELEMENT_FACE pyramid_faces[5] = { { 1, 2, 5, 0 }, { 2, 3, 5, 0 }, { 3, 4, 5, 0 }, { 4, 1, 5, 0 }, { 1, 4, 3, 2 } }; static const ELEMENT_FACE hex_faces[6] = { { 1, 4, 3, 2 }, { 5, 6, 7, 8 }, { 1, 2, 6, 5 }, { 2, 3, 7, 6 }, { 3, 4, 8, 7 }, { 4, 1, 5, 8 } }; switch (et) { case TRIG: case TRIG6: return trig_faces; case QUAD: case QUAD6: case QUAD8: return quad_faces; case TET: case TET10: return tet_faces; case PRISM: case PRISM12: case PRISM15: return prism_faces; case PYRAMID: case PYRAMID13: return pyramid_faces; case SEGMENT: case SEGMENT3: case HEX: case HEX20: return hex_faces; // default: // cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; } return 0; } inline const ELEMENT_FACE * MeshTopology :: GetFaces0 (ELEMENT_TYPE et) { static const ELEMENT_FACE trig_faces[1] = { { 0, 1, 2, -1 } }; static const ELEMENT_FACE quad_faces[1] = { { 0, 1, 2, 3 } }; static const ELEMENT_FACE tet_faces[4] = { { 3, 1, 2, -1 }, { 3, 2, 0, -1 }, { 3, 0, 1, -1 }, { 0, 2, 1, -1 } }; static const ELEMENT_FACE prism_faces[5] = { { 0, 2, 1, -1 }, { 3, 4, 5, -1 }, { 2, 0, 3, 5 }, { 0, 1, 4, 3 }, { 1, 2, 5, 4 } }; static const ELEMENT_FACE pyramid_faces[5] = { { 0, 1, 4, -1 }, { 1, 2, 4, -1 }, { 2, 3, 4, -1 }, { 3, 0, 4, -1 }, { 0, 3, 2, 1 } }; static const ELEMENT_FACE hex_faces[6] = { { 0, 3, 2, 1 }, { 4, 5, 6, 7 }, { 0, 1, 5, 4 }, { 1, 2, 6, 5 }, { 2, 3, 7, 6 }, { 3, 0, 4, 7 } }; switch (et) { case TRIG: case TRIG6: return trig_faces; case QUAD: case QUAD6: case QUAD8: return quad_faces; case TET: case TET10: return tet_faces; case PRISM: case PRISM12: case PRISM15: return prism_faces; case PYRAMID: case PYRAMID13: return pyramid_faces; case SEGMENT: case SEGMENT3: case HEX: case HEX20: return hex_faces; // default: // cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; } return 0; } } #endif netgen-6.2.1905/libsrc/meshing/hpref_prism.hpp0000644000175000017500000022075213504650527017750 0ustar kurtkurt // HP_PRISM ... no refinement int refprism_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_newelstypes[] = { HP_PRISM, HP_NONE, }; int refprism_newels[][8] = { { 1, 2, 3, 4, 5, 6 } }; HPRef_Struct refprism = { HP_PRISM, refprism_splitedges, 0, 0, refprism_newelstypes, refprism_newels }; // HP_PRISM_SINGEDGE ... vertical edge 1-4 is singular int refprism_singedge_splitedges[][3] = { { 1, 2, 7 }, { 1, 3, 8 }, { 4, 5, 9 }, { 4, 6, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_singedge_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_NONE, }; int refprism_singedge_newels[][8] = { { 1, 7, 8, 4, 9, 10 }, { 3, 8, 7, 2, 6, 10, 9, 5 } }; HPRef_Struct refprism_singedge = { HP_PRISM, refprism_singedge_splitedges, 0, 0, refprism_singedge_newelstypes, refprism_singedge_newels }; // HP_PRISM_SINGEDGE_V12 vertical edges 1-4 and 2-5 are singular int refprism_singedge_v12_splitedges[][3] = { { 1, 2, 7 }, { 1, 3, 8 }, { 2, 1, 9 }, { 2, 3, 10 }, { 4, 5, 11 }, { 4, 6, 12 }, { 5, 4, 13 }, { 5, 6, 14}, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_singedge_v12_newelstypes[] = { HP_HEX, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM, HP_NONE, }; int refprism_singedge_v12_newels[][8] = { { 7, 9, 10, 8, 11, 13, 14, 12 }, { 1, 7, 8, 4, 11, 12 }, { 2, 10, 9, 5, 14, 13 }, { 3, 8, 10, 6, 12, 14 }, }; HPRef_Struct refprism_singedge_v12 = { HP_PRISM, refprism_singedge_v12_splitedges, 0, 0, refprism_singedge_v12_newelstypes, refprism_singedge_v12_newels }; // HP_PRISM_SINGEDGE_H12 int refprism_singedge_h12_splitedges[][3] = { { 1, 3, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 3, 1, 10 }, { 4, 6, 12 }, { 5, 4, 13 }, { 5, 6, 14 }, { 6, 4, 15 }, { 0, 0, 0 } }; int refprism_singedge_h12_splitfaces[][4] = { { 2, 1, 3, 11 }, { 5, 4, 6, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refprism_singedge_h12_newelstypes[] = { HP_HEX, HP_HEX, HP_PRISM, HP_PRISM, HP_PRISM, HP_NONE, }; int refprism_singedge_h12_newels[][8] = { { 1, 8, 11, 7, 4, 13, 16, 12 }, { 9, 3, 10, 11, 14, 6, 15, 16 }, { 7, 11, 10, 12, 16, 15 }, { 2, 9, 11, 5, 14, 16 }, { 8, 2, 11, 13, 5, 16 } }; HPRef_Struct refprism_singedge_h12 = { HP_PRISM, refprism_singedge_h12_splitedges, refprism_singedge_h12_splitfaces, 0, refprism_singedge_h12_newelstypes, refprism_singedge_h12_newels }; // HP_PRISM_SINGEDGE_H1 int refprism_singedge_h1_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 4, 6, 9 }, { 5, 6, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_singedge_h1_newelstypes[] = { HP_HEX, HP_PRISM, HP_NONE, }; int refprism_singedge_h1_newels[][8] = { { 1, 2, 8, 7, 4, 5, 10, 9 }, { 3, 7, 8, 6, 9, 10 } }; HPRef_Struct refprism_singedge_h1 = { HP_PRISM, refprism_singedge_h1_splitedges, 0, 0, refprism_singedge_h1_newelstypes, refprism_singedge_h1_newels }; // HP_PRISM_1FA_0E_0V int refprism_1fa_0e_0v_splitedges[][3] = { { 1, 4, 16 }, { 2, 5, 17 }, { 3, 6, 18 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fa_0e_0v_newelstypes[] = { HP_PRISM, HP_PRISM_1FA_0E_0V, HP_NONE, }; int refprism_1fa_0e_0v_newels[][8] = { { 16, 17, 18, 4, 5, 6 }, { 1, 2, 3, 16, 17, 18 } }; HPRef_Struct refprism_1fa_0e_0v = { HP_PRISM, refprism_1fa_0e_0v_splitedges, 0, 0, refprism_1fa_0e_0v_newelstypes, refprism_1fa_0e_0v_newels }; // HP_PRISM_1FA_1E_0V int refprism_1fa_1e_0v_splitedges[][3] = { { 1, 4, 16 }, { 2, 5, 17 }, { 3, 6, 18 }, { 1, 2, 7}, { 1, 3, 12}, { 4, 6, 45}, { 4, 5, 40}, { 0, 0, 0 } }; int refprism_1fa_1e_0v_splitfaces[][4] = { {1,2,4,19}, {1,3,4,24}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_1e_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_NONE, }; int refprism_1fa_1e_0v_newels[][8] = { { 16, 19, 24, 4, 40, 45 }, { 24, 19, 17, 18, 45 , 40, 5, 6 }, { 1, 7 , 12 , 16, 19, 24 }, { 7, 2, 3, 12, 19, 17, 18, 24 } }; HPRef_Struct refprism_1fa_1e_0v = { HP_PRISM, refprism_1fa_1e_0v_splitedges, refprism_1fa_1e_0v_splitfaces, 0, refprism_1fa_1e_0v_newelstypes, refprism_1fa_1e_0v_newels }; // HP_PRISM_2FA_1E_0V int refprism_2fa_1e_0v_splitedges[][3] = { { 1, 4, 16 }, { 2, 5, 17 }, { 3, 6, 18 }, { 1, 2, 7}, { 1, 3, 12}, { 4, 6, 45}, { 4, 5, 40}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 0, 0, 0 } }; int refprism_2fa_1e_0v_splitfaces[][4] = { {1,2,4,19}, {1,3,4,24}, {4,1,5,31}, {4,1,6,36}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_1e_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_NONE, }; int refprism_2fa_1e_0v_newels[][8] = { { 16, 19, 24, 28, 31, 36 }, { 24, 19, 17, 18, 36, 31, 29, 30 }, { 1, 7 , 12 , 16, 19, 24 }, { 12, 7, 2, 3, 24, 19, 17, 18 }, { 4, 45, 40, 28, 36, 31 }, { 40, 45, 6, 5, 31, 36, 30, 29,} }; HPRef_Struct refprism_2fa_1e_0v = { HP_PRISM, refprism_2fa_1e_0v_splitedges, refprism_2fa_1e_0v_splitfaces, 0, refprism_2fa_1e_0v_newelstypes, refprism_2fa_1e_0v_newels }; // HP_PRISM_1FB_0E_0V ... quad face 1-2-4-5 int refprism_1fb_0e_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 4, 6, 9 }, { 5, 6, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fb_0e_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PRISM, HP_NONE, }; int refprism_1fb_0e_0v_newels[][8] = { { 1, 4, 5, 2, 7, 9, 10, 8 }, { 7, 8, 3, 9, 10, 6 } }; HPRef_Struct refprism_1fb_0e_0v = { HP_PRISM, refprism_1fb_0e_0v_splitedges, 0, 0, refprism_1fb_0e_0v_newelstypes, refprism_1fb_0e_0v_newels }; // HP_PRISM_1FB_1EA_0V ... quad face 1-2-4-5 int refprism_1fb_1ea_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 4, 6, 9 }, { 5, 6, 10 }, { 1, 2, 11 }, { 4, 5, 12 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fb_1ea_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM, HP_NONE, }; int refprism_1fb_1ea_0v_newels[][8] = { { 11, 12, 5, 2, 7, 9, 10, 8 }, { 1, 11, 7, 4, 12, 9 }, { 7, 8, 3, 9, 10, 6 } }; HPRef_Struct refprism_1fb_1ea_0v = { HP_PRISM, refprism_1fb_1ea_0v_splitedges, 0, 0, refprism_1fb_1ea_0v_newelstypes, refprism_1fb_1ea_0v_newels }; // HP_PRISM_1FB_1EC_0V ... quad face 1-2-4-5 with singular edge 3-6 int refprism_1fb_1ec_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {3,2,10}, {3,1,11}, {5,6,42}, {4,6,45}, {6,5,43}, {6,4,44}, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fb_1ec_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_HEX_1F_0E_0V, HP_NONE, }; int refprism_1fb_1ec_0v_newels[][8] = { { 3, 11, 10, 6, 44, 43}, { 12, 9, 10, 11, 45, 42, 43, 44}, { 4, 5, 2, 1, 45, 42, 9, 12 } }; HPRef_Struct refprism_1fb_1ec_0v = { HP_PRISM, refprism_1fb_1ec_0v_splitedges, 0, 0, refprism_1fb_1ec_0v_newelstypes, refprism_1fb_1ec_0v_newels }; // HP_PRISM_1FA_1FB_1EC_0V ... bot-trig face, quad face 1-2-4-5 with singular edge 3-6 int refprism_1fa_1fb_1ec_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {3,2,10}, {3,1,11}, {5,6,42}, {4,6,45}, {6,5,43}, {6,4,44}, {1,4,16}, {2,5,17}, {3,6,18}, { 0, 0, 0 } }; int refprism_1fa_1fb_1ec_0v_splitfaces[][4] = { {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ec_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_NONE, }; int refprism_1fa_1fb_1ec_0v_newels[][8] = { { 18, 23, 22, 6, 44, 43}, { 24, 21, 22, 23, 45, 42, 43, 44}, { 4, 5, 17, 16, 45, 42, 21, 24}, { 3, 11, 10, 18, 23, 22}, { 12, 9, 10, 11, 24, 21, 22, 23}, { 1, 2, 9, 12, 16, 17, 21, 24} }; HPRef_Struct refprism_1fa_1fb_1ec_0v = { HP_PRISM, refprism_1fa_1fb_1ec_0v_splitedges, refprism_1fa_1fb_1ec_0v_splitfaces, 0, refprism_1fa_1fb_1ec_0v_newelstypes, refprism_1fa_1fb_1ec_0v_newels }; // HP_PRISM_1FA_1FB_2EB_0V int refprism_1fa_1fb_2eb_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {3,2,10}, {3,1,11}, {5,6,42}, {4,6,45}, {6,5,43}, {6,4,44}, {1,4,16}, {2,5,17}, {3,6,18}, { 4, 5, 40}, { 4, 6, 45}, { 1, 2, 7}, { 0, 0, 0 } }; int refprism_1fa_1fb_2eb_0v_splitfaces[][4] = { {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {1,2,4,19}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_2eb_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE, }; int refprism_1fa_1fb_2eb_0v_newels[][8] = { { 18, 23, 22, 6, 44, 43}, { 24, 21, 22, 23, 45, 42, 43, 44}, { 40, 5, 17, 19, 45, 42, 21, 24}, { 3, 11, 10, 18, 23, 22}, { 12, 9, 10, 11, 24, 21, 22, 23}, { 7, 2, 9, 12, 19, 17, 21, 24}, {16,19,24,4,40,45}, {1,7,12,16,19,24} }; HPRef_Struct refprism_1fa_1fb_2eb_0v = { HP_PRISM, refprism_1fa_1fb_2eb_0v_splitedges, refprism_1fa_1fb_2eb_0v_splitfaces, 0, refprism_1fa_1fb_2eb_0v_newelstypes, refprism_1fa_1fb_2eb_0v_newels }; // HP_PRISM_1FA_1FB_2EC_0V int refprism_1fa_1fb_2ec_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {3,2,10}, {3,1,11}, {5,6,42}, {4,6,45}, {6,5,43}, {6,4,44}, {1,4,16}, {2,5,17}, {3,6,18}, {5,4,41}, {2,1,8}, { 0, 0, 0 } }; int refprism_1fa_1fb_2ec_0v_splitfaces[][4] = { {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {2,1,5,20}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_2ec_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FB_1EA_0V, HP_NONE, }; int refprism_1fa_1fb_2ec_0v_newels[][8] = { { 18, 23, 22, 6, 44, 43}, { 24, 21, 22, 23, 45, 42, 43, 44}, { 4, 41, 20, 16, 45, 42, 21, 24}, { 3, 11, 10, 18, 23, 22}, { 12, 9, 10, 11, 24, 21, 22, 23}, { 1, 8, 9, 12, 16, 20, 21, 24}, {8,2,9,20,17,21}, {5,41,42,17,20,21} }; HPRef_Struct refprism_1fa_1fb_2ec_0v = { HP_PRISM, refprism_1fa_1fb_2ec_0v_splitedges, refprism_1fa_1fb_2ec_0v_splitfaces, 0, refprism_1fa_1fb_2ec_0v_newelstypes, refprism_1fa_1fb_2ec_0v_newels }; // HP_PRISM_2FA_1FB_1EC_0V ... trig faces, quad face 1-2-4-5 with singular edge 3-6 int refprism_2fa_1fb_1ec_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {3,2,10}, {3,1,11}, {5,6,42}, {4,6,45}, {6,5,43}, {6,4,44}, {1,4,16}, {2,5,17}, {3,6,18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 0, 0, 0 } }; int refprism_2fa_1fb_1ec_0v_splitfaces[][4] = { {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {5,2,6,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_1fb_1ec_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_NONE, }; int refprism_2fa_1fb_1ec_0v_newels[][8] = { { 18, 23, 22, 30, 35, 34}, { 24, 21, 22, 23, 36, 33, 34, 35}, { 28, 29, 17, 16, 36, 33, 21, 24}, { 3, 11, 10, 18, 23, 22}, { 12, 9, 10, 11, 24, 21, 22, 23}, { 1, 2, 9, 12, 16, 17, 21, 24}, { 6, 43, 44, 30, 34, 35}, { 44, 43, 42, 45, 35, 34, 33, 36}, { 5, 4, 45, 42, 29, 28, 36, 33 }, }; HPRef_Struct refprism_2fa_1fb_1ec_0v = { HP_PRISM, refprism_2fa_1fb_1ec_0v_splitedges, refprism_2fa_1fb_1ec_0v_splitfaces, 0, refprism_2fa_1fb_1ec_0v_newelstypes, refprism_2fa_1fb_1ec_0v_newels }; // HP_PRISM_2FA_1FB_2EB_0V int refprism_2fa_1fb_2eb_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {3,2,10}, {3,1,11}, {5,6,42}, {4,6,45}, {6,5,43}, {6,4,44}, {1,4,16}, {2,5,17}, {3,6,18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, {4,5,40}, {1,2,7}, { 0, 0, 0 } }; int refprism_2fa_1fb_2eb_0v_splitfaces[][4] = { {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {5,6,2,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, {4,1,5,31}, {1,2,4,19}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_1fb_2eb_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE, }; int refprism_2fa_1fb_2eb_0v_newels[][8] = { { 18, 23, 22, 30, 35, 34}, { 24, 21, 22, 23, 36, 33, 34, 35}, { 31, 29, 17, 19, 36, 33, 21, 24}, { 3, 11, 10, 18, 23, 22}, { 12, 9, 10, 11, 24, 21, 22, 23}, { 7, 2, 9, 12, 19, 17, 21, 24}, { 6, 43, 44, 30, 34, 35}, { 44, 43, 42, 45, 35, 34, 33, 36}, { 5, 40, 45, 42, 29, 31, 36, 33 }, { 1, 7, 12, 16, 19, 24 }, { 16, 19, 24, 28, 31, 36 }, { 40, 4, 45, 31, 28, 36 }, }; HPRef_Struct refprism_2fa_1fb_2eb_0v = { HP_PRISM, refprism_2fa_1fb_2eb_0v_splitedges, refprism_2fa_1fb_2eb_0v_splitfaces, 0, refprism_2fa_1fb_2eb_0v_newelstypes, refprism_2fa_1fb_2eb_0v_newels }; // HP_PRISM_1FB_2EA_0V ... quad face 1-2-4-5 with singular edges 1-4, 2-5 int refprism_1fb_2ea_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 1, 2, 9 }, { 2, 1, 10 }, { 4, 6, 11 }, { 5, 6, 12 }, { 4, 5, 13 }, { 5, 4, 14 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fb_2ea_0v_newelstypes[] = { HP_PRISM, HP_PRISM_1FB_1EA_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_NONE, }; int refprism_1fb_2ea_0v_newels[][8] = { { 7, 8, 3, 11, 12, 6 }, { 1, 9, 7, 4, 13, 11 }, { 13, 14, 10, 9, 11, 12, 8, 7 }, { 5, 14, 12, 2, 10, 8 }, }; HPRef_Struct refprism_1fb_2ea_0v = { HP_PRISM, refprism_1fb_2ea_0v_splitedges, 0, 0, refprism_1fb_2ea_0v_newelstypes, refprism_1fb_2ea_0v_newels }; // HP_PRISM_1FB_2EB_0V ... quad face 1-2-4-5 with singular edges 1-4, 3-6 int refprism_1fb_2eb_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 4, 5, 40}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fb_2eb_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_PRISM_1FB_1EA_0V, HP_HEX_1F_0E_0V, HP_NONE, }; int refprism_1fb_2eb_0v_newels[][8] = { { 3, 11, 10, 6, 44, 43 }, { 12, 9, 10, 11, 45, 42, 43, 44}, { 1, 7, 12, 4, 40, 45}, { 40, 5, 2, 7, 45, 42, 9, 12} }; HPRef_Struct refprism_1fb_2eb_0v = { HP_PRISM, refprism_1fb_2eb_0v_splitedges, 0, 0, refprism_1fb_2eb_0v_newelstypes, refprism_1fb_2eb_0v_newels }; // HP_PRISM_1FB_3E_0V ... quad face 1-2-4-5 with singular edges 1-4, 3-6 int refprism_1fb_3e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fb_3e_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_HEX, HP_PRISM_1FB_1EA_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_NONE, }; int refprism_1fb_3e_0v_newels[][8] = { { 3, 11, 10, 6, 44, 43 }, { 12, 9, 10, 11, 45, 42, 43, 44}, { 1, 7, 12, 4, 40, 45 }, { 40, 41, 8, 7, 45, 42, 9, 12}, { 5, 41, 42, 2, 8, 9}, }; HPRef_Struct refprism_1fb_3e_0v = { HP_PRISM, refprism_1fb_3e_0v_splitedges, 0, 0, refprism_1fb_3e_0v_newelstypes, refprism_1fb_3e_0v_newels }; // HP_PRISM_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 int refprism_2fb_0e_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 1, 2, 9 }, { 3, 2, 10 }, { 4, 6, 11 }, { 5, 6, 12 }, { 4, 5, 13 }, { 6, 5, 14 }, { 0, 0, 0 } }; int refprism_2fb_0e_0v_splitfaces[][4] = { { 1, 2, 3, 15 }, { 4, 5, 6, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refprism_2fb_0e_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_NONE, }; int refprism_2fb_0e_0v_newels[][8] = { { 15, 8, 10, 16, 12, 14 }, { 13, 5, 2, 9, 16, 12, 8, 15}, { 11, 7, 3, 6, 16, 15, 10, 14 }, { 1, 9, 15, 4, 13, 16 }, { 4, 11, 16, 1,7, 15 } }; HPRef_Struct refprism_2fb_0e_0v = { HP_PRISM, refprism_2fb_0e_0v_splitedges, refprism_2fb_0e_0v_splitfaces, 0, refprism_2fb_0e_0v_newelstypes, refprism_2fb_0e_0v_newels }; // HP_PRISM_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 and sing edge 3-6 int refprism_2fb_1ec_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 1, 2, 9 }, { 3, 2, 10 }, { 4, 6, 11 }, { 5, 6, 12 }, { 4, 5, 13 }, { 6, 5, 14 }, { 3, 1, 17}, { 6, 4, 18}, { 0, 0, 0 } }; int refprism_2fb_1ec_0v_splitfaces[][4] = { { 1, 2, 3, 15 }, { 4, 5, 6, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refprism_2fb_1ec_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_NONE, }; int refprism_2fb_1ec_0v_newels[][8] = { { 15, 8, 10, 16, 12, 14 }, { 13, 5, 2, 9, 16, 12, 8, 15}, { 11, 7, 17, 18, 16, 15, 10, 14 }, { 1, 9, 15, 4, 13, 16 }, { 4, 11, 16, 1,7, 15 }, { 3, 17, 10, 6, 18, 14 } }; HPRef_Struct refprism_2fb_1ec_0v = { HP_PRISM, refprism_2fb_1ec_0v_splitedges, refprism_2fb_1ec_0v_splitfaces, 0, refprism_2fb_1ec_0v_newelstypes, refprism_2fb_1ec_0v_newels }; // HP_PRISM_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 and 3 sing edges int refprism_2fb_3e_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 1, 2, 9 }, { 3, 2, 10 }, { 4, 6, 11 }, { 5, 6, 12 }, { 4, 5, 13 }, { 6, 5, 14 }, { 3, 1, 17}, { 6, 4, 18}, { 2, 1, 19}, { 5, 4, 20}, { 0, 0, 0 } }; int refprism_2fb_3e_0v_splitfaces[][4] = { { 1, 2, 3, 15 }, { 4, 5, 6, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refprism_2fb_3e_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_NONE, }; int refprism_2fb_3e_0v_newels[][8] = { { 15, 8, 10, 16, 12, 14 }, { 13, 20, 19, 9, 16, 12, 8, 15}, { 11, 7, 17, 18, 16, 15, 10, 14 }, { 1, 9, 15, 4, 13, 16 }, { 4, 11, 16, 1,7, 15 }, { 3, 17, 10, 6, 18, 14 }, { 5, 20, 12, 2, 19, 8 } }; HPRef_Struct refprism_2fb_3e_0v = { HP_PRISM, refprism_2fb_3e_0v_splitedges, refprism_2fb_3e_0v_splitfaces, 0, refprism_2fb_3e_0v_newelstypes, refprism_2fb_3e_0v_newels }; // HP_PRISM_1FA_1FB_0E_0V ... quad face 1-2-4-5 and trig face 1-2-3 int refprism_1fa_1fb_0e_0v_splitedges[][3] = { {1,4,16}, {2,5,17}, {3,6,18}, {2,3,9}, {1,3,12}, {5,6,42}, {4,6,45}, {0,0,0} }; int refprism_1fa_1fb_0e_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_0e_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_NONE, }; int refprism_1fa_1fb_0e_0v_newels[][8] = { { 24, 21, 18, 45, 42, 6 }, { 4, 5, 17, 16, 45, 42, 21, 24 }, { 12, 9, 3, 24, 21, 18 }, { 1, 2, 9, 12, 16, 17, 21, 24 } }; HPRef_Struct refprism_1fa_1fb_0e_0v = { HP_PRISM, refprism_1fa_1fb_0e_0v_splitedges, refprism_1fa_1fb_0e_0v_splitfaces, 0, refprism_1fa_1fb_0e_0v_newelstypes, refprism_1fa_1fb_0e_0v_newels }; /* // HP_PRISM_1FA_1FB_1EC_0V ... quad face 1-2-4-5 and trig face 1-2-3 int refprism_1fa_1fb_1ec_0v_splitedges[][3] = { {1,4,16}, {2,5,17}, {3,6,18}, {2,3,9}, {1,3,12}, {5,6,42}, {4,6,45}, {6,5,43}, {6,4,44}, {3,2,10}, {3,1,11}, {0,0,0} }; int refprism_1fa_1fb_1ec_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ec_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_SINGEDGE, HP_PRISM_1FA_1E_0V, HP_PRISM_ HP_NONE, }; int refprism_1fa_1fb_0e_0v_newels[][8] = { { 24, 21, 18, 45, 42, 6 }, { 4, 5, 17, 16, 45, 42, 21, 24 }, { 12, 9, 3, 24, 21, 18 }, { 1, 2, 9, 12, 16, 17, 21, 24 } }; HPRef_Struct refprism_1fa_1fb_0e_0v = { HP_PRISM, refprism_1fa_1fb_1ec_0v_splitedges, refprism_1fa_1fb_1ec_0v_splitfaces, 0, refprism_1fa_1fb_1ec_0v_newelstypes, refprism_1fa_1fb_1ec_0v_newels }; */ // HP_PRISM_2FA_1FB_0E_0V ... quad face 1-2-4-5 and trig face 1-2-3 int refprism_2fa_1fb_0e_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {4,1,28}, {5,2,29}, {6,3,30}, {0,0,0} }; int refprism_2fa_1fb_0e_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {5,6,2,33}, {4,1,6,36}, {0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_1fb_0e_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PRISM, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_NONE, }; int refprism_2fa_1fb_0e_0v_newels[][8] = { {28,29,17,16,36,33,21,24}, {24,21,18, 36, 33, 30}, {12,9,3,24,21,18}, {1,2,9,12,16,17,21,24}, {6,42,45,30,33,36}, {4,5,29,28,45,42,33,36} }; HPRef_Struct refprism_2fa_1fb_0e_0v = { HP_PRISM, refprism_2fa_1fb_0e_0v_splitedges, refprism_2fa_1fb_0e_0v_splitfaces, 0, refprism_2fa_1fb_0e_0v_newelstypes, refprism_2fa_1fb_0e_0v_newels }; // HP_PRISM_1FA_1FB_1EA_0V ... quad face 1-2-4-5 and trig face 1-2-3 int refprism_1fa_1fb_1ea_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {4,5,40}, {1,2,7}, {0,0,0}, }; int refprism_1fa_1fb_1ea_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {1,2,4,19}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ea_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PRISM, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE }; int refprism_1fa_1fb_1ea_0v_newels[][8] = { {40,5,17,19,45,42,21,24}, {24,21,18,45,42,6}, {12,9,3,24,21,18}, {7,2,9,12,19,17,21,24}, {16,19,24,4,40,45}, {1,7,12,16,19,24} }; HPRef_Struct refprism_1fa_1fb_1ea_0v = { HP_PRISM, refprism_1fa_1fb_1ea_0v_splitedges, refprism_1fa_1fb_1ea_0v_splitfaces, 0, refprism_1fa_1fb_1ea_0v_newelstypes, refprism_1fa_1fb_1ea_0v_newels }; // HP_PRISM_2FA_1FB_1EA_0V int refprism_2fa_1fb_1ea_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {4,1,28}, {5,2,29}, {6,3,30}, {4,5,40}, {1,2,7}, {0,0,0}, }; int refprism_2fa_1fb_1ea_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {1,2,4,19}, {4,1,6,36}, {4,1,5,31}, {5,6,2,33}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_1fb_1ea_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE }; int refprism_2fa_1fb_1ea_0v_newels[][8] = { { 18, 24, 21, 30, 36, 33}, { 31, 29, 17, 19, 36, 33, 21, 24}, { 16,19, 24, 28, 31, 36 }, { 3, 12, 9, 18, 24, 21 }, { 7, 2, 9, 12, 19, 17, 21, 24}, { 1, 7, 12, 16, 19, 24 }, { 6, 42, 45, 30, 33, 36 }, { 40, 5, 29, 31, 45, 42, 33, 36 }, { 40, 4, 45, 31, 28, 36} }; HPRef_Struct refprism_2fa_1fb_1ea_0v = { HP_PRISM, refprism_2fa_1fb_1ea_0v_splitedges, refprism_2fa_1fb_1ea_0v_splitfaces, 0, refprism_2fa_1fb_1ea_0v_newelstypes, refprism_2fa_1fb_1ea_0v_newels }; // HP_PRISM_2FA_1FB_2EA_0V int refprism_2fa_1fb_2ea_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {4,1,28}, {5,2,29}, {6,3,30}, {4,5,40}, {1,2,7}, { 5, 4, 41}, { 2, 1, 8}, {0,0,0}, }; int refprism_2fa_1fb_2ea_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {1,2,4,19}, {4,1,6,36}, {4,1,5,31}, {5,6,2,33}, {5,4,2,32}, {2,1,5,20}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_1fb_2ea_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE }; int refprism_2fa_1fb_2ea_0v_newels[][8] = { { 18, 24, 21, 30, 36, 33}, { 31, 32, 20, 19, 36, 33, 21, 24}, { 16,19, 24, 28, 31, 36 }, { 3, 12, 9, 18, 24, 21 }, {7,8,9,12,19,20,21,24}, { 1, 7, 12, 16, 19, 24 }, { 6, 42, 45, 30, 33, 36 }, { 40, 41, 32, 31, 45, 42, 33, 36}, { 40, 4, 45, 31, 28, 36}, { 8, 2, 9, 20, 17, 21 }, { 29, 32, 33, 17, 20, 21 }, { 5, 41, 42, 29, 32, 33 }, }; HPRef_Struct refprism_2fa_1fb_2ea_0v = { HP_PRISM, refprism_2fa_1fb_2ea_0v_splitedges, refprism_2fa_1fb_2ea_0v_splitfaces, 0, refprism_2fa_1fb_2ea_0v_newelstypes, refprism_2fa_1fb_2ea_0v_newels }; // HP_PRISM_2FA_1FB_3E_0V int refprism_2fa_1fb_3e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, {0,0,0}, }; int refprism_2fa_1fb_3e_0v_splitfaces[][4] = { {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,1,5,31}, {5,4,2,32}, {5,6,2,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_1fb_3e_0v_newelstypes[] = { HP_HEX, HP_PRISM_SINGEDGE, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_HEX_1FA_1FB_0E_0V, HP_NONE }; int refprism_2fa_1fb_3e_0v_newels[][8] = { {24, 21, 22, 23, 36, 33, 34, 35}, {18, 23, 22, 30, 35, 34}, { 31, 32, 20, 19, 36, 33, 21, 24}, { 16,19, 24, 28, 31, 36 }, { 29, 32, 33, 17, 20, 21}, { 12, 9,10,11, 24, 21, 22, 23 }, { 3, 11, 10, 18,23,22}, { 1, 7, 12 , 16, 19, 24}, { 8,2,9, 20, 17,21}, { 7,8,9,12,19, 20, 21, 24}, { 44, 43, 42, 45, 35, 34, 33, 36}, { 6, 43, 44, 30, 34, 35}, { 40, 4, 45, 31,28, 36}, { 5, 41,42, 29, 32, 33}, { 40, 41, 32, 31, 45, 42, 33, 36}, }; HPRef_Struct refprism_2fa_1fb_3e_0v = { HP_PRISM, refprism_2fa_1fb_3e_0v_splitedges, refprism_2fa_1fb_3e_0v_splitfaces, 0, refprism_2fa_1fb_3e_0v_newelstypes, refprism_2fa_1fb_3e_0v_newels }; // HP_PRISM_1FA_1FB_1EB_0V ... quad face 1-2-4-5 and trig face 1-2-3 int refprism_1fa_1fb_1eb_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {5,4,41}, {2,1,8}, {0,0,0}, }; int refprism_1fa_1fb_1eb_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {2,1,5,20}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_1eb_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PRISM, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V , HP_NONE }; int refprism_1fa_1fb_1eb_0v_newels[][8] = { {4,41,20,16,45,42,21,24}, {24,21,18,45,42,6}, {12,9,3,24,21,18}, {1,8,9,12,16,20,21,24}, {5,41,42,17,20,21}, {8,2,9,20,17,21} }; HPRef_Struct refprism_1fa_1fb_1eb_0v = { HP_PRISM, refprism_1fa_1fb_1eb_0v_splitedges, refprism_1fa_1fb_1eb_0v_splitfaces, 0, refprism_1fa_1fb_1eb_0v_newelstypes, refprism_1fa_1fb_1eb_0v_newels }; // HP_PRISM_1FA_1FB_2EA_0V ... quad face 1-2-4-5 and trig face 1-2-3 int refprism_1fa_1fb_2ea_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {5,4,41}, {2,1,8}, {4,5,40}, {1,2,7}, {0,0,0}, }; int refprism_1fa_1fb_2ea_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {2,1,5,20}, {1,2,4,19}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_2ea_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PRISM, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V , HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE }; int refprism_1fa_1fb_2ea_0v_newels[][8] = { {40,41,20,19,45,42,21,24}, {24,21,18,45,42,6}, {12,9,3,24,21,18}, {7,8,9,12,19,20,21,24}, {5,41,42,17,20,21}, {8,2,9,20,17,21}, {16,19,24,4,40,45}, {1,7,12,16,19,24} }; HPRef_Struct refprism_1fa_1fb_2ea_0v = { HP_PRISM, refprism_1fa_1fb_2ea_0v_splitedges, refprism_1fa_1fb_2ea_0v_splitfaces, 0, refprism_1fa_1fb_2ea_0v_newelstypes, refprism_1fa_1fb_2ea_0v_newels }; // HP_PRISM_1FA_1FB_3E_0V int refprism_1fa_1fb_3e_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {5,4,41}, {2,1,8}, {4,5,40}, {1,2,7}, { 3, 2, 10}, { 3, 1, 11}, { 6, 5, 43}, { 6, 4, 44}, {0,0,0}, }; int refprism_1fa_1fb_3e_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {2,1,5,20}, {1,2,4,19}, {3,2,6,22}, {3,1,6,23}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_1fa_1fb_3e_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_HEX, HP_PRISM_SINGEDGE, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V , HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE }; int refprism_1fa_1fb_3e_0v_newels[][8] = { {40,41,20,19,45,42,21,24}, {24, 21, 22, 23, 45, 42, 43, 44}, {18, 23, 22, 6, 44, 43}, {12, 9, 10, 11, 24, 21, 22, 23}, {3, 11, 10, 18, 23, 22}, {7,8,9,12,19,20,21,24}, {5,41,42,17,20,21}, {8,2,9,20,17,21}, {16,19,24,4,40,45}, {1,7,12,16,19,24} }; HPRef_Struct refprism_1fa_1fb_3e_0v = { HP_PRISM, refprism_1fa_1fb_3e_0v_splitedges, refprism_1fa_1fb_3e_0v_splitfaces, 0, refprism_1fa_1fb_3e_0v_newelstypes, refprism_1fa_1fb_3e_0v_newels }; // HP_PRISM_2FA_0E_0V singular trig faces int refprism_2fa_0e_0v_splitedges[][3] = { {1,4,16}, {2,5,17}, {3,6,18}, {4,1,28}, {5,2,29}, {6,3,30}, {0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_0e_0v_newelstypes[] = { HP_PRISM, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_NONE }; int refprism_2fa_0e_0v_newels[][8] = { {16,17,18,28,29,30}, {1,2,3,16,17,18}, {4,6,5,28,30,29}, }; HPRef_Struct refprism_2fa_0e_0v = { HP_PRISM, refprism_2fa_0e_0v_splitedges, 0, 0, refprism_2fa_0e_0v_newelstypes, refprism_2fa_0e_0v_newels }; // HP_PRISM_1FA_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 int refprism_1fa_2fb_0e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 3, 9}, { 3, 2, 10}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 5, 40}, { 5, 6, 42}, { 6, 5, 43}, { 4, 6, 45}, { 0, 0, 0 } }; int refprism_1fa_2fb_0e_0v_splitfaces[][4] = { {1,2,3,13}, {1,2,4,19}, {2,3,5,21}, {3,2,6,22}, {1,3,4,24}, {4,5,6,46}, { 0, 0, 0, 0 } }; int refprism_1fa_2fb_0e_0v_splitelement[][5] = { {1,2,3,4,25}, {0,0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_2fb_0e_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE, }; int refprism_1fa_2fb_0e_0v_newels[][8] = { { 25, 21, 22, 46, 42, 43 }, { 40, 5, 17, 19, 46, 42, 21, 25 }, { 24, 18, 6, 45, 25, 22, 43, 46}, { 16, 19, 25, 4, 40, 46 }, { 4, 45, 46, 16, 24, 25 }, { 13, 9, 10, 25, 21, 22 }, { 7, 2, 9, 13, 19, 17, 21, 25 }, { 3, 12, 13, 10, 18, 24, 25, 22 }, { 1, 7, 13, 16, 19, 25 }, { 12, 1, 13, 24, 16, 25 } }; HPRef_Struct refprism_1fa_2fb_0e_0v = { HP_PRISM, refprism_1fa_2fb_0e_0v_splitedges, refprism_1fa_2fb_0e_0v_splitfaces, refprism_1fa_2fb_0e_0v_splitelement, refprism_1fa_2fb_0e_0v_newelstypes, refprism_1fa_2fb_0e_0v_newels }; // HP_PRISM_1FA_2FB_1EC ... quad face 1-2-4-5 and quad face 1-4-6-3 int refprism_1fa_2fb_1ec_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 5, 40}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0 } }; int refprism_1fa_2fb_1ec_0v_splitfaces[][4] = { {1,2,3,13}, {1,2,4,19}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,5,6,46}, { 0, 0, 0, 0 } }; int refprism_1fa_2fb_1ec_0v_splitelement[][5] = { {1,2,3,4,25}, {0,0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_2fb_1ec_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE, }; int refprism_1fa_2fb_1ec_0v_newels[][8] = { { 25, 21, 22, 46, 42, 43 }, { 40, 5, 17, 19, 46, 42, 21, 25 }, { 24, 23, 44, 45, 25, 22, 43, 46}, { 16, 19, 25, 4, 40, 46 }, { 4, 45, 46, 16, 24, 25 }, { 18, 23, 22, 6, 44, 43}, { 13, 9, 10, 25, 21, 22 }, { 7, 2, 9, 13, 19, 17, 21, 25 }, { 11, 12, 13, 10, 23, 24, 25, 22 }, { 1, 7, 13, 16, 19, 25 }, { 12, 1, 13, 24, 16, 25 }, { 3, 11, 10, 18, 23, 22}, }; HPRef_Struct refprism_1fa_2fb_1ec_0v = { HP_PRISM, refprism_1fa_2fb_1ec_0v_splitedges, refprism_1fa_2fb_1ec_0v_splitfaces, refprism_1fa_2fb_1ec_0v_splitelement, refprism_1fa_2fb_1ec_0v_newelstypes, refprism_1fa_2fb_1ec_0v_newels }; // HP_PRISM_1FA_2FB_3E ... quad face 1-2-4-5 and quad face 1-4-6-3 int refprism_1fa_2fb_3e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0 } }; int refprism_1fa_2fb_3e_0v_splitfaces[][4] = { {1,2,3,13}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,5,6,46}, { 0, 0, 0, 0 } }; int refprism_1fa_2fb_3e_0v_splitelement[][5] = { {1,2,3,4,25}, {0,0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_2fb_3e_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE, }; int refprism_1fa_2fb_3e_0v_newels[][8] = { { 25, 21, 22, 46, 42, 43 }, { 40, 41, 20, 19, 46, 42, 21, 25 }, { 24, 23, 44, 45, 25, 22, 43, 46}, { 16, 19, 25, 4, 40, 46 }, { 4, 45, 46, 16, 24, 25 }, { 18, 23, 22, 6, 44, 43}, { 5, 41, 42, 17, 20, 21}, { 13, 9, 10, 25, 21, 22 }, { 7, 8, 9, 13, 19, 20, 21, 25 }, { 11, 12, 13, 10, 23, 24, 25, 22 }, { 1, 7, 13, 16, 19, 25 }, { 12, 1, 13, 24, 16, 25 }, { 3, 11, 10, 18, 23, 22}, { 8, 2, 9, 20, 17, 21}, }; HPRef_Struct refprism_1fa_2fb_3e_0v = { HP_PRISM, refprism_1fa_2fb_3e_0v_splitedges, refprism_1fa_2fb_3e_0v_splitfaces, refprism_1fa_2fb_3e_0v_splitelement, refprism_1fa_2fb_3e_0v_newelstypes, refprism_1fa_2fb_3e_0v_newels }; // HP_PRISM_1FA_2FB_1eb ... quad face 1-2-4-5 and quad face 1-4-6-3 int refprism_1fa_2fb_1eb_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 4, 6, 45}, { 0, 0, 0 } }; int refprism_1fa_2fb_1eb_0v_splitfaces[][4] = { {1,2,3,13}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {1,3,4,24}, {4,5,6,46}, { 0, 0, 0, 0 } }; int refprism_1fa_2fb_1eb_0v_splitelement[][5] = { {1,2,3,4,25}, {0,0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_1fa_2fb_1eb_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE, }; int refprism_1fa_2fb_1eb_0v_newels[][8] = { { 25, 21, 22, 46, 42, 43 }, { 40, 41, 20, 19, 46, 42, 21, 25 }, { 24, 18, 6, 45, 25, 22, 43, 46}, { 16, 19, 25, 4, 40, 46 }, { 4, 45, 46, 16, 24, 25 }, { 5, 41, 42, 17, 20, 21 }, { 13, 9, 10, 25, 21, 22 }, { 7, 8, 9, 13, 19, 20, 21, 25 }, { 3, 12, 13, 10, 18, 24, 25, 22 }, { 1, 7, 13, 16, 19, 25 }, { 12, 1, 13, 24, 16, 25 }, { 8, 2, 9, 20, 17, 21}, }; HPRef_Struct refprism_1fa_2fb_1eb_0v = { HP_PRISM, refprism_1fa_2fb_1eb_0v_splitedges, refprism_1fa_2fb_1eb_0v_splitfaces, refprism_1fa_2fb_1eb_0v_splitelement, refprism_1fa_2fb_1eb_0v_newelstypes, refprism_1fa_2fb_1eb_0v_newels }; // HP_PRISM_2FA_2FB int refprism_2fa_2fb_0e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 3, 9}, { 3, 2, 10}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 5, 40}, { 5, 6, 42}, { 6, 5, 43}, { 4, 6, 45}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 0, 0, 0 } }; int refprism_2fa_2fb_0e_0v_splitfaces[][4] = { {1,2,3,13}, {1,2,4,19}, {2,3,5,21}, {3,2,6,22}, {1,3,4,24}, {4,5,6,46}, {4,1,5,31}, {5,6,2,33}, {6,5,3,34}, {4,1,6,36}, { 0, 0, 0, 0 } }; int refprism_2fa_2fb_0e_0v_splitelement[][5] = { {1,2,3,4,25}, {4,1,6,5,37}, {0,0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_2fb_0e_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE, }; int refprism_2fa_2fb_0e_0v_newels[][8] = { { 25, 21, 22, 37, 33, 34}, { 31, 29, 17, 19, 37, 33, 21, 25}, { 36, 24, 18, 30, 37, 25, 22, 34}, { 16, 19, 25, 28, 31, 37}, { 28, 36, 37, 16, 24, 25}, { 13, 9, 10, 25, 21, 22 }, { 7, 2, 9, 13, 19, 17, 21, 25 }, { 3, 12, 13, 10, 18, 24, 25, 22 }, { 1, 7, 13, 16, 19, 25 }, { 12, 1, 13, 24, 16, 25 }, { 46, 43, 42 ,37, 34, 33}, { 40, 5, 29, 31, 46, 42, 33, 37 }, { 6, 45, 36, 30, 43, 46, 37, 34 }, { 40, 4, 46, 31, 28, 37 }, { 4, 45, 46, 28, 36, 37}, }; HPRef_Struct refprism_2fa_2fb_0e_0v = { HP_PRISM, refprism_2fa_2fb_0e_0v_splitedges, refprism_2fa_2fb_0e_0v_splitfaces, refprism_2fa_2fb_0e_0v_splitelement, refprism_2fa_2fb_0e_0v_newelstypes, refprism_2fa_2fb_0e_0v_newels }; // HP_PRISM_2FA_2FB_1EC int refprism_2fa_2fb_1ec_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 4, 5, 40}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0 } }; int refprism_2fa_2fb_1ec_0v_splitfaces[][4] = { {1,2,3,13}, {1,2,4,19}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,5,6,46}, {4,1,5,31}, {5,6,2,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, { 0, 0, 0, 0 } }; int refprism_2fa_2fb_1ec_0v_splitelement[][5] = { {1,2,3,4,25}, {4,1,6,5,37}, {0,0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_2fb_1ec_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE, }; int refprism_2fa_2fb_1ec_0v_newels[][8] = { { 25, 21, 22, 37, 33, 34}, { 31, 29, 17, 19, 37, 33, 21, 25}, { 36, 24, 23, 35, 37, 25, 22, 34}, { 16, 19, 25, 28, 31, 37}, { 28, 36, 37, 16, 24, 25}, { 18, 23, 22, 30, 35, 34}, { 13, 9, 10, 25, 21, 22 }, { 7, 2, 9, 13, 19, 17, 21, 25 }, { 11, 12, 13, 10, 23, 24, 25, 22 }, { 1, 7, 13, 16, 19, 25 }, { 12, 1, 13, 24, 16, 25 }, { 3, 11, 10, 18, 23, 22 }, { 46, 43, 42 ,37, 34, 33}, { 40, 5, 29, 31, 46, 42, 33, 37 }, { 44, 45, 36, 35, 43, 46, 37, 34 }, { 40, 4, 46, 31, 28, 37 }, { 4, 45, 46, 28, 36, 37}, { 44, 6, 43, 35, 30, 34}, }; HPRef_Struct refprism_2fa_2fb_1ec_0v = { HP_PRISM, refprism_2fa_2fb_1ec_0v_splitedges, refprism_2fa_2fb_1ec_0v_splitfaces, refprism_2fa_2fb_1ec_0v_splitelement, refprism_2fa_2fb_1ec_0v_newelstypes, refprism_2fa_2fb_1ec_0v_newels }; // HP_PRISM_2FA_2FB_3E int refprism_2fa_2fb_3e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0 } }; int refprism_2fa_2fb_3e_0v_splitfaces[][4] = { {1,2,3,13}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,5,6,46}, {4,1,5,31}, {5,4,2,32}, {5,6,2,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, { 0, 0, 0, 0 } }; int refprism_2fa_2fb_3e_0v_splitelement[][5] = { {1,2,3,4,25}, {4,1,6,5,37}, {0,0,0,0,0} }; HPREF_ELEMENT_TYPE refprism_2fa_2fb_3e_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_NONE, }; int refprism_2fa_2fb_3e_0v_newels[][8] = { { 25, 21, 22, 37, 33, 34}, { 31, 32, 20, 19, 37, 33, 21, 25}, { 36, 24, 23, 35, 37, 25, 22, 34}, { 16, 19, 25, 28, 31, 37}, { 28, 36, 37, 16, 24, 25}, { 18, 23, 22, 30, 35, 34}, { 29, 32, 33, 17, 20, 21}, { 13, 9, 10, 25, 21, 22 }, { 7, 8, 9, 13, 19, 20, 21, 25 }, { 11, 12, 13, 10, 23, 24, 25, 22 }, { 1, 7, 13, 16, 19, 25 }, { 12, 1, 13, 24, 16, 25 }, { 3, 11, 10, 18, 23, 22 }, { 8, 2, 9, 20, 17, 21 }, { 46, 43, 42 ,37, 34, 33}, { 40, 41, 32, 31, 46, 42, 33, 37 }, { 44, 45, 36, 35, 43, 46, 37, 34 }, { 40, 4, 46, 31, 28, 37 }, { 4, 45, 46, 28, 36, 37}, { 44, 6, 43, 35, 30, 34}, { 5, 41, 42, 29, 32, 33}, }; HPRef_Struct refprism_2fa_2fb_3e_0v = { HP_PRISM, refprism_2fa_2fb_3e_0v_splitedges, refprism_2fa_2fb_3e_0v_splitfaces, refprism_2fa_2fb_3e_0v_splitelement, refprism_2fa_2fb_3e_0v_newelstypes, refprism_2fa_2fb_3e_0v_newels }; // HP_PRISM_1FA_2E_0V int refprism_1fa_2e_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {5,4,41}, {2,1,8}, {4,5,40}, {1,2,7}, {0,0,0}, }; int refprism_1fa_2e_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {2,1,5,20}, {1,2,4,19}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_1fa_2e_0v_newelstypes[] = { HP_HEX, HP_PRISM, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_SINGEDGE, HP_PRISM_1FA_1E_0V, HP_PRISM_SINGEDGE, HP_PRISM_1FA_1E_0V, HP_NONE }; int refprism_1fa_2e_0v_newels[][8] = { {40,41,20,19,45,42,21,24}, {24,21,18,45,42,6}, {12,9,3,24,21,18}, {9, 12, 7, 8, 21, 24, 19, 20}, { 17, 21, 20, 5, 42, 41}, {2, 9, 8, 17, 21, 20}, {16,19,24,4,40,45}, {1,7,12,16,19,24} }; HPRef_Struct refprism_1fa_2e_0v = { HP_PRISM, refprism_1fa_2e_0v_splitedges, refprism_1fa_2e_0v_splitfaces, 0, refprism_1fa_2e_0v_newelstypes, refprism_1fa_2e_0v_newels }; // HP_PRISM_2FA_2E_0V int refprism_2fa_2e_0v_splitedges[][3] = { {2,3,9}, {1,3,12}, {1,4,16}, {2,5,17}, {3,6,18}, {5,6,42}, {4,6,45}, {4,1,28}, {5,2,29}, {6,3,30}, {4,5,40}, {1,2,7}, { 5, 4, 41}, { 2, 1, 8}, {0,0,0}, }; int refprism_2fa_2e_0v_splitfaces[][4] = { {2,3,5,21}, {1,3,4,24}, {1,2,4,19}, {4,1,6,36}, {4,1,5,31}, {5,6,2,33}, {5,4,2,32}, {2,1,5,20}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_2e_0v_newelstypes[] = { HP_PRISM, HP_HEX, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_NONE, }; int refprism_2fa_2e_0v_newels[][8] = { { 24, 21, 18, 36, 33, 30}, { 19, 20, 21, 24, 31, 32, 33, 36}, { 16, 19, 24, 28, 31, 36}, { 17, 21, 20, 29, 33, 32}, { 12, 9, 3, 24, 21, 18}, { 7, 8, 9, 12, 19, 20, 21, 24}, { 1, 7, 12, 16, 19, 24}, { 2, 9, 8, 17, 21, 20}, { 45, 6, 42, 36, 30, 33}, { 40, 45, 42, 41, 31, 36, 33, 32}, { 4, 45, 40, 28, 36, 31 }, { 5, 41, 42, 29, 32, 33 }, }; HPRef_Struct refprism_2fa_2e_0v = { HP_PRISM, refprism_2fa_2e_0v_splitedges, refprism_2fa_2e_0v_splitfaces, 0, refprism_2fa_2e_0v_newelstypes, refprism_2fa_2e_0v_newels }; // HP_PRISM_3E_0V int refprism_3e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_3e_0v_splitfaces[][4] = { {1,2,3,13}, {2,3,1,14}, {3,1,2,15}, {4,5,6,46}, {5,4,6,47}, {6,4,5,48}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_3e_0v_newelstypes[] = { HP_PRISM, HP_HEX, HP_HEX, HP_HEX, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_NONE }; int refprism_3e_0v_newels[][8] = { { 13, 14, 15, 46, 47, 48}, { 7, 8, 14, 13, 40, 41, 47, 46}, { 15, 14, 9, 10, 48, 47, 42, 43}, { 12, 13, 15, 11, 45, 46, 48, 44}, { 14, 8, 9, 47, 41, 42 }, { 11, 15, 10, 44, 48, 43 }, { 7, 13, 12, 40, 46, 45}, { 1, 7, 12, 4, 40, 45}, { 2, 9, 8, 5, 42, 41 }, { 3, 11, 10, 6, 44, 43 } }; HPRef_Struct refprism_3e_0v = { HP_PRISM, refprism_3e_0v_splitedges, refprism_3e_0v_splitfaces, 0, refprism_3e_0v_newelstypes, refprism_3e_0v_newels }; // HP_PRISM_3E_0V int refprism_1fa_3e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_1fa_3e_0v_splitfaces[][4] = { {1,2,3,13}, {2,3,1,14}, {3,1,2,15}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,5,6,46}, {5,4,6,47}, {6,4,5,48}, {0,0,0,0}, }; int refprism_1fa_3e_0v_splitelements[][5] = { {1,2,3,4,25}, {2,1,3,5,26}, {3,1,2,6,27}, {0,0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_1fa_3e_0v_newelstypes[] = { HP_PRISM, HP_HEX, HP_HEX, HP_HEX, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_NONE }; int refprism_1fa_3e_0v_newels[][8] = { { 25, 26, 27, 46, 47, 48}, { 19, 20, 26, 25, 40, 41, 47, 46}, { 27, 26, 21, 22, 48, 47, 42, 43}, { 23, 24, 25, 27, 44, 45, 46, 48}, { 19, 25, 24, 40, 46, 45}, { 26, 20, 21, 47, 41, 42}, { 23, 27, 22, 44, 48, 43}, { 16, 19, 24, 4, 40, 45}, { 17, 21, 20, 5, 42, 41}, { 18, 23, 22, 6, 44, 43}, { 13, 14, 15, 25, 26, 27}, { 7, 8, 14, 13, 19, 20, 26, 25}, { 15, 14, 9, 10, 27, 26, 21, 22}, { 12, 13, 15, 11, 24, 25, 27, 23}, { 14, 8, 9, 26, 20, 21}, { 11, 15, 10, 23, 27, 22}, { 7, 13 , 12, 19, 25, 24}, { 2, 9, 8, 17, 21, 20}, { 3, 11, 10, 18, 23, 22}, { 1, 7, 12, 16, 19, 24}, }; HPRef_Struct refprism_1fa_3e_0v = { HP_PRISM, refprism_1fa_3e_0v_splitedges, refprism_1fa_3e_0v_splitfaces, refprism_1fa_3e_0v_splitelements, refprism_1fa_3e_0v_newelstypes, refprism_1fa_3e_0v_newels }; // HP_PRISM_2FA_3E_0V int refprism_2fa_3e_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_2fa_3e_0v_splitfaces[][4] = { {1,2,3,13}, {2,3,1,14}, {3,1,2,15}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,1,5,31}, {5,4,2,32}, {5,6,2,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, {4,5,6,46}, {5,4,6,47}, {6,4,5,48}, {0,0,0,0}, }; int refprism_2fa_3e_0v_splitelements[][5] = { {1,2,3,4,25}, {2,1,3,5,26}, {3,1,2,6,27}, {4,1,6,5,37}, {5,2,4,6,38}, {6,4,5,3,39}, {0,0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_3e_0v_newelstypes[] = { HP_PRISM, HP_HEX, HP_HEX, HP_HEX, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_NONE }; int refprism_2fa_3e_0v_newels[][8] = { { 25, 26, 27, 37, 38, 39}, { 19, 20, 26, 25, 31, 32, 38, 37}, { 27, 26, 21, 22, 39, 38, 33, 34}, { 23, 24, 25, 27, 35, 36, 37, 39}, { 19, 25, 24, 31, 37, 36}, { 26, 20, 21, 38, 32, 33}, { 23, 27, 22, 35, 39, 34}, { 16, 19, 24, 28, 31, 36}, { 17, 21, 20, 29, 33, 32}, { 18, 23, 22, 30, 35, 34}, { 13, 14, 15, 25, 26, 27}, { 7, 8, 14, 13, 19, 20, 26, 25}, { 15, 14, 9, 10, 27, 26, 21, 22}, { 12, 13, 15, 11, 24, 25, 27, 23}, { 14, 8, 9, 26, 20, 21}, { 11, 15, 10, 23, 27, 22}, { 7, 13 , 12, 19, 25, 24}, { 2, 9, 8, 17, 21, 20}, { 3, 11, 10, 18, 23, 22}, { 1, 7, 12, 16, 19, 24}, { 48, 47, 46, 39, 38, 37 }, { 48, 43, 42, 47, 39, 34, 33, 38}, { 45, 44, 48, 46, 36, 35, 39, 37}, { 46, 47, 41, 40, 37, 38, 32, 31}, { 47, 42, 41, 38, 33, 32}, { 45, 46, 40, 36, 37, 31}, { 44, 43, 48, 35, 34, 39}, { 6, 43, 44, 30, 34, 35}, { 5, 41, 42, 29, 32, 33}, { 4, 45, 40, 28, 36, 31}, }; HPRef_Struct refprism_2fa_3e_0v = { HP_PRISM, refprism_2fa_3e_0v_splitedges, refprism_2fa_3e_0v_splitfaces, refprism_2fa_3e_0v_splitelements, refprism_2fa_3e_0v_newelstypes, refprism_2fa_3e_0v_newels }; // HP_PRISM_3FB_0V int refprism_3fb_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_3fb_0v_splitfaces[][4] = { {1,2,3,13}, {2,3,1,14}, {3,1,2,15}, {4,5,6,46}, {5,4,6,47}, {6,4,5,48}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_3fb_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_NONE }; int refprism_3fb_0v_newels[][8] = { { 13, 14, 15, 46, 47, 48}, { 8, 7, 40, 41, 14,13, 46, 47 }, { 10, 9, 42, 43, 15, 14, 47, 48 }, { 44, 45, 12, 11, 48, 46, 13, 15}, { 1, 7, 13, 4, 40, 46 }, { 4, 45, 46, 1, 12, 13}, { 2, 9, 14, 5, 42, 47 }, { 5, 41, 47, 2, 8, 14 }, { 3, 11, 15, 6, 44, 48}, { 6, 43, 48, 3, 10, 15}, }; HPRef_Struct refprism_3fb_0v = { HP_PRISM, refprism_3fb_0v_splitedges, refprism_3fb_0v_splitfaces, 0, refprism_3fb_0v_newelstypes, refprism_3fb_0v_newels }; // HP_PRISM_3FB_0V int refprism_1fa_3fb_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_1fa_3fb_0v_splitfaces[][4] = { {1,2,3,13}, {2,3,1,14}, {3,1,2,15}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,5,6,46}, {5,4,6,47}, {6,4,5,48}, {0,0,0,0}, }; int refprism_1fa_3fb_0v_splitelements[][5] = { {1,2,3,4,25}, {2,1,3,5,26}, {3,1,2,6,27}, {0,0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_1fa_3fb_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE }; int refprism_1fa_3fb_0v_newels[][8] = { { 25, 26, 27, 46, 47, 48}, { 19, 40, 41, 20, 25, 46, 47, 26}, { 22, 21, 42, 43, 27, 26, 47, 48}, { 24, 23, 44, 45, 25, 27, 48, 46}, { 16, 19, 25, 4, 40, 46 }, { 4, 45, 46, 16, 24, 25 }, { 17, 21, 26, 5, 42, 47 }, { 5, 41, 47, 17, 20, 26}, { 18, 23, 27, 6, 44, 48}, { 6, 43, 48, 18, 22, 27}, { 13, 14, 15, 25, 26, 27}, { 7, 8, 14, 13, 19, 20, 26, 25}, { 9, 10, 15, 14, 21, 22, 27, 26}, { 11, 12, 13, 15, 23, 24, 25, 27}, { 2, 9, 14, 17, 21, 26}, { 8, 2, 14, 20, 17, 26}, { 1, 7, 13, 16, 19, 25}, { 12, 1, 13, 24, 16, 25 }, { 3, 11, 15, 18, 23, 27 }, { 10, 3, 15, 22, 18, 27}, }; HPRef_Struct refprism_1fa_3fb_0v = { HP_PRISM, refprism_1fa_3fb_0v_splitedges, refprism_1fa_3fb_0v_splitfaces, refprism_1fa_3fb_0v_splitelements, refprism_1fa_3fb_0v_newelstypes, refprism_1fa_3fb_0v_newels }; // HP_PRISM_2FA_3E_0V int refprism_2fa_3fb_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_2fa_3fb_0v_splitfaces[][4] = { {1,2,3,13}, {2,3,1,14}, {3,1,2,15}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,1,5,31}, {5,4,2,32}, {5,6,2,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, {4,5,6,46}, {5,4,6,47}, {6,4,5,48}, {0,0,0,0}, }; int refprism_2fa_3fb_0v_splitelements[][5] = { {1,2,3,4,25}, {2,1,3,5,26}, {3,1,2,6,27}, {4,1,6,5,37}, {5,2,4,6,38}, {6,4,5,3,39}, {0,0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_3fb_0v_newelstypes[] = { HP_PRISM, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_NONE }; int refprism_2fa_3fb_0v_newels[][8] = { { 25, 26, 27, 37, 38, 39}, { 19, 31, 32, 20, 25, 37, 38, 26}, { 33, 34, 22, 21, 38, 39, 27, 26}, { 35, 36, 24, 23, 39, 37, 25, 27}, { 16, 19, 25, 28, 31, 37}, { 28, 36, 37, 16, 24, 25 }, { 17, 21, 26, 29, 33, 38 }, { 29, 32, 38, 17, 20, 26}, { 18, 23, 27, 30, 35, 39}, { 30, 34, 39, 18, 22, 27}, { 13, 14, 15, 25, 26, 27}, { 7, 8, 14, 13, 19, 20, 26, 25}, { 9, 10, 15, 14, 21, 22, 27, 26}, { 11, 12, 13, 15, 23, 24, 25, 27}, { 2, 9, 14, 17, 21, 26}, { 8, 2, 14, 20, 17, 26}, { 1, 7, 13, 16, 19, 25}, { 12, 1, 13, 24, 16, 25 }, { 3, 11, 15, 18, 23, 27 }, { 10, 3, 15, 22, 18, 27}, { 48, 47, 46, 39, 38, 37 }, { 44, 45, 36, 35, 48, 46, 37, 39}, { 40, 41, 32, 31, 46, 47, 38, 37}, { 42, 43, 34, 33, 47, 48, 39, 38}, { 6, 43, 48, 30, 34, 39}, { 44, 6, 48, 35, 30, 39}, { 4, 45, 46, 28, 36, 37}, { 40, 4, 46, 31, 28, 37}, { 5, 41, 47, 29, 32, 38}, { 42, 5, 47, 33, 29, 38}, }; HPRef_Struct refprism_2fa_3fb_0v = { HP_PRISM, refprism_2fa_3fb_0v_splitedges, refprism_2fa_3fb_0v_splitfaces, refprism_2fa_3fb_0v_splitelements, refprism_2fa_3fb_0v_newelstypes, refprism_2fa_3fb_0v_newels }; /* // HP_PRISM_3E_4EH int refprism_3e_4eh_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_3e_4eh_splitfaces[][4] = { {3,1,2,15}, {6,4,5,48}, {0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_3fb_0v_newelstypes[] = { HP_PRISM, HP_HEX_2EH_0V, HP_HEX_2EH_0V, HP_TET_2E, HP_TET_2E, HP_PRISM_1E_2EH_0V, HP_PRISM_1E_2EH_0V, HP_NONE }; int refprism_2fa_3fb_0v_newels[][8] = { {15, 7, 8, 48, 40, 41 }, }; HPRef_Struct refprism_2fa_3fb_0v = { HP_PRISM, refprism_2fa_3fb_0v_splitedges, refprism_2fa_3fb_0v_splitfaces, refprism_2fa_3fb_0v_splitelements, refprism_2fa_3fb_0v_newelstypes, refprism_2fa_3fb_0v_newels }; */ /* // HP_PRISM_2FA_3E_0V int refprism_3e_4_0v_splitedges[][3] = { { 1, 2, 7}, { 2, 1, 8}, { 2, 3, 9}, { 3, 2, 10}, { 3, 1, 11}, { 1, 3, 12}, { 1, 4, 16}, { 2, 5, 17}, { 3, 6, 18}, { 4, 1, 28}, { 5, 2, 29}, { 6, 3, 30}, { 4, 5, 40}, { 5, 4, 41}, { 5, 6, 42}, { 6, 5, 43}, { 6, 4, 44}, { 4, 6, 45}, { 0, 0, 0}, }; int refprism_2fa_3e_0v_splitfaces[][4] = { {1,2,3,13}, {2,3,1,14}, {3,1,2,15}, {1,2,4,19}, {2,1,5,20}, {2,3,5,21}, {3,2,6,22}, {3,1,6,23}, {1,3,4,24}, {4,1,5,31}, {5,4,2,32}, {5,6,2,33}, {6,5,3,34}, {6,4,3,35}, {4,1,6,36}, {4,5,6,46}, {5,4,6,47}, {6,4,5,48}, {0,0,0,0}, }; int refprism_2fa_3e_0v_splitelements[][5] = { {1,2,3,4,25}, {2,1,3,5,26}, {3,1,2,6,27}, {4,1,6,5,37}, {5,2,4,6,38}, {6,4,5,3,39}, {0,0,0,0,0}, }; HPREF_ELEMENT_TYPE refprism_2fa_3e_0v_newelstypes[] = { HP_PRISM, HP_HEX, HP_HEX, HP_HEX, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_PRISM_1FA_1E_0V, HP_NONE }; int refprism_2fa_3e_0v_newels[][8] = { { 25, 26, 27, 37, 38, 39}, { 19, 20, 26, 25, 31, 32, 38, 37}, { 27, 26, 21, 22, 39, 38, 33, 34}, { 23, 24, 25, 27, 35, 36, 37, 39}, { 19, 25, 24, 31, 37, 36}, { 26, 20, 21, 38, 32, 33}, { 23, 27, 22, 35, 39, 34}, { 16, 19, 24, 28, 31, 36}, { 17, 21, 20, 29, 33, 32}, { 18, 23, 22, 30, 35, 34}, { 13, 14, 15, 25, 26, 27}, { 7, 8, 14, 13, 19, 20, 26, 25}, { 15, 14, 9, 10, 27, 26, 21, 22}, { 12, 13, 15, 11, 24, 25, 27, 23}, { 14, 8, 9, 26, 20, 21}, { 11, 15, 10, 23, 27, 22}, { 7, 13 , 12, 19, 25, 24}, { 2, 9, 8, 17, 21, 20}, { 3, 11, 10, 18, 23, 22}, { 1, 7, 12, 16, 19, 24}, { 48, 47, 46, 39, 38, 37 }, { 48, 43, 42, 47, 39, 34, 33, 38}, { 45, 44, 48, 46, 36, 35, 39, 37}, { 46, 47, 41, 40, 37, 38, 32, 31}, { 47, 42, 41, 38, 33, 32}, { 45, 46, 40, 36, 37, 31}, { 44, 43, 48, 35, 34, 39}, { 6, 43, 44, 30, 34, 35}, { 5, 41, 42, 29, 32, 33}, { 4, 45, 40, 28, 36, 31}, }; HPRef_Struct refprism_2fa_3e_0v = { HP_PRISM, refprism_2fa_3e_0v_splitedges, refprism_2fa_3e_0v_splitfaces, refprism_2fa_3e_0v_splitelements, refprism_2fa_3e_0v_newelstypes, refprism_2fa_3e_0v_newels }; */ /* // HP_PRISM_1FB_1EB_0V ... quad face 1-2-4-5 int refprism_1fb_1eb_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 3, 8 }, { 4, 6, 9 }, { 5, 6, 10 }, { 2, 1, 11 }, { 5, 4, 12 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refprism_1fb_1eb_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EB_0V, HP_PRISM, HP_NONE, }; int refprism_1fb_1eb_0v_newels[][8] = { { 1, 4, 12, 11, 7, 9, 10, 8 }, { 11, 2, 8, 12, 5, 10 }, { 7, 8, 3, 9, 10, 6 } }; HPRef_Struct refprism_1fb_1eb_0v = { HP_PRISM, refprism_1fb_1eb_0v_splitedges, 0, 0, refprism_1fb_1eb_0v_newelstypes, refprism_1fb_1eb_0v_newels }; // HP_PRISM_2F_0E_0V int refprism_2f_0e_0v_splitedges[][3] = { { 1, 3, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 3, 1, 10 }, { 4, 6, 12 }, { 5, 4, 13 }, { 5, 6, 14 }, { 6, 4, 15 }, { 0, 0, 0 } }; int refprism_2f_0e_0v_splitfaces[][4] = { { 2, 1, 3, 11 }, { 5, 4, 6, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refprism_2f_0e_0v_newelstypes[] = { HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM, HP_NONE, }; int refprism_2f_0e_0v_newels[][8] = { //{ 1, 8, 11, 7, 4, 13, 16, 12 }, // { 9, 3, 10, 11, 14, 6, 15, 16 }, { 1, 4, 13, 8, 7, 12, 16, 11 }, { 9, 14, 6, 3, 11, 16, 15, 10 }, { 2, 9, 11, 5, 14, 16 }, // { 8, 2, 11, 13, 5, 16 }, { 5, 13, 16, 2, 8, 11 }, { 7, 11, 10, 12, 16, 15 } }; HPRef_Struct refprism_2f_0e_0v = { HP_PRISM, refprism_2f_0e_0v_splitedges, refprism_2f_0e_0v_splitfaces, 0, refprism_2f_0e_0v_newelstypes, refprism_2f_0e_0v_newels }; */ netgen-6.2.1905/libsrc/meshing/basegeom.cpp0000644000175000017500000000313413504650527017200 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { DLL_HEADER GeometryRegisterArray geometryregister; //DLL_HEADER Array geometryregister; GeometryRegister :: ~GeometryRegister() { ; } shared_ptr GeometryRegisterArray :: LoadFromMeshFile (istream & ist) const { for (int i = 0; i < Size(); i++) { NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist); if (hgeom) return shared_ptr(hgeom); } return nullptr; } int NetgenGeometry :: GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam) { if (!mesh) return 1; if (mparam.perfstepsstart <= MESHCONST_MESHVOLUME) { multithread.task = "Volume meshing"; MESHING3_RESULT res = MeshVolume (mparam, *mesh); if (res != MESHING3_OK) return 1; if (multithread.terminate) return 0; RemoveIllegalElements (*mesh); if (multithread.terminate) return 0; MeshQuality3d (*mesh); } if (multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHVOLUME) return 0; if (mparam.perfstepsstart <= MESHCONST_OPTVOLUME) { multithread.task = "Volume optimization"; OptimizeVolume (mparam, *mesh); if (multithread.terminate) return 0; } return 0; } const Refinement & NetgenGeometry :: GetRefinement () const { return *new Refinement;; } void NetgenGeometry :: Save (string filename) const { throw NgException("Cannot save geometry - no geometry available"); } static RegisterClassForArchive regnggeo; } netgen-6.2.1905/libsrc/meshing/pyramid2rls.cpp0000644000175000017500000001124013504650527017663 0ustar kurtkurtnamespace netgen { const char * pyramidrules2[] = { "tolfak 0.5\n",\ "\n",\ "rule \"Pyramid on quad\"\n",\ "\n",\ "quality 100\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.5, -0.5) \n",\ " { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ " { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ "\n",\ "newfaces\n",\ "(1, 2, 5);\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "rule \"small Pyramid on quad\"\n",\ "\n",\ "quality 100\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.5, -0.1 )\n",\ " { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ " { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ "\n",\ "newfaces\n",\ "(1, 2, 5);\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"connect pyramid\"\n",\ "\n",\ "quality 100\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0.5, -0.5);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 2, 5);\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"pyramid with one trig\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0.5, -0.5);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 1, 5) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 };\n",\ "{ 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 };\n",\ "{ 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P2 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 };\n",\ "{ 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 };\n",\ "{ 0.333 P1, 0.333 P4, 0.334 P5, 0 P2 };\n",\ "\n",\ "orientations\n",\ "(1, 2, 3, 5);\n",\ "(1, 3, 4, 5);\n",\ "\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "freeset\n",\ "1 3 4 5;\n",\ "freeset\n",\ "2 3 5 6;\n",\ "freeset\n",\ "3 4 5 7;\n",\ "freeset \n",\ "1 4 5 8;\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"pyramid with two trig\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0.5, -0.5);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 1, 5) del;\n",\ "(3, 2, 5) del;\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"pyramid with two trig, left\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0.5, -0.5);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 1, 5) del;\n",\ "(1, 4, 5) del;\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(3, 4, 5);\n",\ "(2, 3, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ 0}; } netgen-6.2.1905/libsrc/meshing/python_mesh.cpp0000644000175000017500000012164313504650527017761 0ustar kurtkurt#ifdef NG_PYTHON #include <../general/ngpython.hpp> #include #include "meshing.hpp" // #include // #include #include <../interface/writeuser.hpp> using namespace netgen; extern const char *ngscript[]; namespace netgen { extern bool netgen_executable_started; extern shared_ptr ng_geometry; extern void Optimize2d (Mesh & mesh, MeshingParameters & mp); #ifdef PARALLEL /** we need allreduce in python-wrapped communicators **/ template inline T MyMPI_AllReduceNG (T d, const MPI_Op & op /* = MPI_SUM */, MPI_Comm comm) { T global_d; MPI_Allreduce ( &d, &global_d, 1, MyGetMPIType(), op, comm); return global_d; } #else // enum { MPI_SUM = 0, MPI_MIN = 1, MPI_MAX = 2 }; // typedef int MPI_Op; template inline T MyMPI_AllReduceNG (T d, const MPI_Op & op /* = MPI_SUM */, MPI_Comm comm) { return d; } #endif } template void ExportArray (py::module &m) { using TA = Array; string name = string("Array_") + typeid(T).name(); py::class_>(m, name.c_str()) .def ("__len__", [] ( Array &self ) { return self.Size(); } ) .def ("__getitem__", FunctionPointer ([](Array & self, TIND i) -> T& { if (i < BASE || i >= BASE+self.Size()) throw py::index_error(); return self[i]; }), py::return_value_policy::reference) .def("__iter__", [] ( TA & self) { return py::make_iterator (self.begin(),self.end()); }, py::keep_alive<0,1>()) // keep array alive while iterator is used ; } void TranslateException (const NgException & ex) { string err = string("Netgen exception: ")+ex.What(); PyErr_SetString(PyExc_RuntimeError, err.c_str()); } static Transformation<3> global_trafo(Vec<3> (0,0,0)); DLL_HEADER void ExportNetgenMeshing(py::module &m) { py::register_exception(m, "NgException"); m.attr("_netgen_executable_started") = py::cast(netgen::netgen_executable_started); string script; const char ** hcp = ngscript; while (*hcp) script += *hcp++; m.attr("_ngscript") = py::cast(script); m.def("_GetStatus", []() { MyStr s; double percent; GetStatus(s, percent); return py::make_tuple(s.c_str(), percent); }); m.def("_PushStatus", [](string s) { PushStatus(MyStr(s)); }); m.def("_SetThreadPercentage", [](double percent) { SetThreadPercent(percent); }); py::class_ (m, "MPI_Comm") .def_property_readonly ("rank", &NgMPI_Comm::Rank) .def_property_readonly ("size", &NgMPI_Comm::Size) .def("Barrier", &NgMPI_Comm::Barrier) #ifdef PARALLEL .def("WTime", [](NgMPI_Comm & c) { return MPI_Wtime(); }) #else .def("WTime", [](NgMPI_Comm & c) { return -1.0; }) #endif .def("Sum", [](NgMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_SUM, c); }) .def("Min", [](NgMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_MIN, c); }) .def("Max", [](NgMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_MAX, c); }) .def("Sum", [](NgMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_SUM, c); }) .def("Min", [](NgMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_MIN, c); }) .def("Max", [](NgMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_MAX, c); }) .def("Sum", [](NgMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_SUM, c); }) .def("Min", [](NgMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MIN, c); }) .def("Max", [](NgMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MAX, c); }) .def("SubComm", [](NgMPI_Comm & c, std::vector proc_list) { Array procs(proc_list.size()); for (int i = 0; i < procs.Size(); i++) procs[i] = proc_list[i]; if (!procs.Contains(c.Rank())) throw Exception("rank "+ToString(c.Rank())+" not in subcomm"); MPI_Comm subcomm = MyMPI_SubCommunicator(c, procs); return NgMPI_Comm(subcomm, true); }, py::arg("procs")); ; py::class_(m, "NGDummyArgument") .def("__bool__", []( NGDummyArgument &self ) { return false; } ) ; py::class_> (m, "Point2d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self-py::self) .def(py::self+Vec<2>()) .def(py::self-Vec<2>()) .def("__getitem__", [](Point<2>& self, int index) { return self[index]; }) ; py::class_> (m, "Point3d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self-py::self) .def(py::self+Vec<3>()) .def(py::self-Vec<3>()) .def("__getitem__", [](Point<2>& self, int index) { return self[index]; }) ; m.def ("Pnt", FunctionPointer ([](double x, double y, double z) { return global_trafo(Point<3>(x,y,z)); })); m.def ("Pnt", FunctionPointer ([](double x, double y) { return Point<2>(x,y); })); /* // duplicated functions ???? m.def ("Pnt", FunctionPointer ([](double x, double y, double z) { return Point<3>(x,y,z); })); m.def ("Pnt", FunctionPointer ([](double x, double y) { return Point<2>(x,y); })); */ py::class_> (m, "Vec2d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self+py::self) .def(py::self-py::self) .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<2>::Length) .def("__getitem__", [](Vec<2>& vec, int index) { return vec[index]; }) .def("__len__", [](Vec<2>& /*unused*/) { return 2; }) ; py::class_> (m, "Vec3d") .def(py::init()) .def ("__str__", &ToString>) .def(py::self+py::self) .def(py::self-py::self) .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<3>::Length) .def("__getitem__", [](Vec<3>& vec, int index) { return vec[index]; }) .def("__len__", [](Vec<3>& /*unused*/) { return 3; }) ; m.def ("Vec", FunctionPointer ([] (double x, double y, double z) { return global_trafo(Vec<3>(x,y,z)); })); m.def ("Vec", FunctionPointer ([] (double x, double y) { return Vec<2>(x,y); })); py::class_> (m, "Trafo") .def(py::init>(), "a translation") .def(py::init,Vec<3>,double>(), "a rotation given by point on axes, direction of axes, angle") .def("__mul__", [](Transformation<3> a, Transformation<3> b)->Transformation<3> { Transformation<3> res; res.Combine(a,b); return res; }) .def("__call__", [] (Transformation<3> trafo, Point<3> p) { return trafo(p); }) ; m.def ("GetTransformation", [] () { return global_trafo; }); m.def ("SetTransformation", [] (Transformation<3> trafo) { global_trafo = trafo; }); m.def ("SetTransformation", [](int dir, double angle) { if (dir > 0) global_trafo.SetAxisRotation (dir, angle*M_PI/180); else global_trafo = Transformation<3> (Vec<3>(0,0,0)); }, py::arg("dir")=int(0), py::arg("angle")=int(0)); m.def ("SetTransformation", [](Point<3> p0, Vec<3> ex, Vec<3> ey, Vec<3> ez) { Point<3> pnts[4]; pnts[0] = p0; pnts[1] = p0 + ex; pnts[2] = p0 + ey; pnts[3] = p0 + ez; global_trafo = Transformation<3> (pnts); }, py::arg("p0"), py::arg("ex"), py::arg("ey"), py::arg("ez")); py::class_(m, "PointId") .def(py::init()) .def("__repr__", &ToString) .def("__str__", &ToString) .def_property_readonly("nr", &PointIndex::operator int) .def("__eq__" , FunctionPointer( [](PointIndex &self, PointIndex &other) { return static_cast(self)==static_cast(other); }) ) .def("__hash__" , FunctionPointer( [](PointIndex &self ) { return static_cast(self); }) ) ; py::class_(m, "ElementId3D") .def(py::init()) .def("__repr__", &ToString) .def("__str__", &ToString) .def_property_readonly("nr", &ElementIndex::operator int) .def("__eq__" , FunctionPointer( [](ElementIndex &self, ElementIndex &other) { return static_cast(self)==static_cast(other); }) ) .def("__hash__" , FunctionPointer( [](ElementIndex &self ) { return static_cast(self); }) ) ; py::class_(m, "ElementId2D") .def(py::init()) .def("__repr__", &ToString) .def("__str__", &ToString) .def_property_readonly("nr", &SurfaceElementIndex::operator int) .def("__eq__" , FunctionPointer( [](SurfaceElementIndex &self, SurfaceElementIndex &other) { return static_cast(self)==static_cast(other); }) ) .def("__hash__" , FunctionPointer( [](SurfaceElementIndex &self ) { return static_cast(self); }) ) ; py::class_(m, "ElementId1D") .def(py::init()) .def("__repr__", &ToString) .def("__str__", &ToString) .def_property_readonly("nr", &SegmentIndex::operator int) .def("__eq__" , FunctionPointer( [](SegmentIndex &self, SegmentIndex &other) { return static_cast(self)==static_cast(other); }) ) .def("__hash__" , FunctionPointer( [](SegmentIndex &self ) { return static_cast(self); }) ) ; /* py::class_> ("Point") .def(py::init()) ; */ py::class_> */ >(m, "MeshPoint") .def(py::init>()) .def("__str__", &ToString) .def("__repr__", &ToString) .def_property_readonly("p", FunctionPointer([](const MeshPoint & self) { py::list l; l.append ( py::cast(self[0]) ); l.append ( py::cast(self[1]) ); l.append ( py::cast(self[2]) ); return py::tuple(l); })) .def("__getitem__", FunctionPointer([](const MeshPoint & self, int index) { if(index<0 || index>2) throw py::index_error(); return self[index]; })) .def("__setitem__", FunctionPointer([](MeshPoint & self, int index, double val) { if(index<0 || index>2) throw py::index_error(); self(index) = val; })) ; py::class_(m, "Element3D") .def(py::init([](int index, std::vector vertices) { int np = vertices.size(); ELEMENT_TYPE et; switch (np) { case 4: et = TET; break; case 5: et = PYRAMID; break; case 6: et = PRISM; break; case 8: et = HEX; break; case 10: et = TET10; break; case 13: et = PYRAMID13; break; case 15: et = PRISM15; break; case 20: et = HEX20; break; default: throw Exception ("no Element3D with " + ToString(np) + " points"); } auto newel = new Element(et); for(int i=0; iSetIndex(index); return newel; }), py::arg("index")=1,py::arg("vertices"), "create volume element" ) .def("__repr__", &ToString) .def_property("index", &Element::GetIndex, &Element::SetIndex) .def_property("curved", &Element::IsCurved, &Element::SetCurved) .def_property_readonly("vertices", FunctionPointer ([](const Element & self) -> py::list { py::list li; for (int i = 0; i < self.GetNV(); i++) li.append (py::cast(self[i])); return li; })) .def_property_readonly("points", FunctionPointer ([](const Element & self) -> py::list { py::list li; for (int i = 0; i < self.GetNP(); i++) li.append (py::cast(self[i])); return li; })) ; py::class_(m, "Element2D") .def(py::init ([](int index, py::list vertices) { Element2d * newel = nullptr; if (py::len(vertices) == 3) { newel = new Element2d(TRIG); for (int i = 0; i < 3; i++) (*newel)[i] = py::extract(vertices[i])(); newel->SetIndex(index); } else if (py::len(vertices) == 4) { newel = new Element2d(QUAD); for (int i = 0; i < 4; i++) (*newel)[i] = py::extract(vertices[i])(); newel->SetIndex(index); } else if (py::len(vertices) == 6) { newel = new Element2d(TRIG6); for(int i = 0; i<6; i++) (*newel)[i] = py::extract(vertices[i])(); newel->SetIndex(index); } else if (py::len(vertices) == 8) { newel = new Element2d(QUAD8); for(int i = 0; i<8; i++) (*newel)[i] = py::extract(vertices[i])(); newel->SetIndex(index); } else throw NgException("Inconsistent number of vertices in Element2D"); return newel; }), py::arg("index")=1,py::arg("vertices"), "create surface element" ) .def_property("index", &Element2d::GetIndex, &Element2d::SetIndex) .def_property("curved", &Element2d::IsCurved, &Element2d::SetCurved) .def_property_readonly("vertices", FunctionPointer([](const Element2d & self) -> py::list { py::list li; for (int i = 0; i < self.GetNV(); i++) li.append(py::cast(self[i])); return li; })) .def_property_readonly("points", FunctionPointer ([](const Element2d & self) -> py::list { py::list li; for (int i = 0; i < self.GetNP(); i++) li.append (py::cast(self[i])); return li; })) ; py::class_(m, "Element1D") .def(py::init([](py::list vertices, py::list surfaces, int index, int edgenr) { Segment * newel = new Segment(); for (int i = 0; i < 2; i++) (*newel)[i] = py::extract(vertices[i])(); newel -> si = index; newel -> edgenr = edgenr; newel -> epgeominfo[0].edgenr = edgenr; newel -> epgeominfo[1].edgenr = edgenr; // needed for codim2 in 3d newel -> edgenr = index; if (len(surfaces)) { newel->surfnr1 = py::extract(surfaces[0])(); newel->surfnr2 = py::extract(surfaces[1])(); } return newel; }), py::arg("vertices"), py::arg("surfaces")=py::list(), py::arg("index")=1, py::arg("edgenr")=1, "create segment element" ) .def("__repr__", &ToString) .def_property_readonly("vertices", FunctionPointer ([](const Segment & self) -> py::list { py::list li; for (int i = 0; i < 2; i++) li.append (py::cast(self[i])); return li; })) .def_property_readonly("points", FunctionPointer ([](const Segment & self) -> py::list { py::list li; for (int i = 0; i < self.GetNP(); i++) li.append (py::cast(self[i])); return li; })) .def_property_readonly("surfaces", FunctionPointer ([](const Segment & self) -> py::list { py::list li; li.append (py::cast(self.surfnr1)); li.append (py::cast(self.surfnr2)); return li; })) .def_property_readonly("index", FunctionPointer([](const Segment &self) -> size_t { return self.si; })) .def_property_readonly("edgenr", FunctionPointer([](const Segment & self) -> size_t { return self.edgenr; })) ; py::class_(m, "Element0D") .def(py::init([](PointIndex vertex, int index) { Element0d * instance = new Element0d; instance->pnum = vertex; instance->index = index; return instance; }), py::arg("vertex"), py::arg("index")=1, "create point element" ) .def("__repr__", &ToString) .def_property_readonly("vertices", FunctionPointer ([](const Element0d & self) -> py::list { py::list li; li.append (py::cast(self.pnum)); return li; })) ; py::class_(m, "FaceDescriptor") .def(py::init()) .def(py::init([](int surfnr, int domin, int domout, int bc) { FaceDescriptor * instance = new FaceDescriptor(); instance->SetSurfNr(surfnr); instance->SetDomainIn(domin); instance->SetDomainOut(domout); instance->SetBCProperty(bc); return instance; }), py::arg("surfnr")=1, py::arg("domin")=1, py::arg("domout")=py::int_(0), py::arg("bc")=py::int_(0), "create facedescriptor") .def("__str__", &ToString) .def("__repr__", &ToString) .def_property("surfnr", &FaceDescriptor::SurfNr, &FaceDescriptor::SetSurfNr) .def_property("domin", &FaceDescriptor::DomainIn, &FaceDescriptor::SetDomainIn) .def_property("domout", &FaceDescriptor::DomainOut, &FaceDescriptor::SetDomainOut) .def_property("bc", &FaceDescriptor::BCProperty, &FaceDescriptor::SetBCProperty) .def_property("bcname", [](FaceDescriptor & self) -> string { return self.GetBCName(); }, [](FaceDescriptor & self, string name) { self.SetBCName(new string(name)); } // memleak ) .def("SetSurfaceColor", [](FaceDescriptor & self, py::list color ) { Vec3d c; c.X() = py::extract(color[0])(); c.Y() = py::extract(color[1])(); c.Z() = py::extract(color[2])(); self.SetSurfColour(c); }) ; ExportArray(m); ExportArray(m); ExportArray(m); ExportArray(m); ExportArray(m); ExportArray(m); py::implicitly_convertible< int, PointIndex>(); py::class_> (m, "NetgenGeometry", py::dynamic_attr()) ; py::class_>(m, "Mesh") // .def(py::init<>("create empty mesh")) .def(py::init( [] (int dim, NgMPI_Comm comm) { auto mesh = make_shared(); mesh->SetCommunicator(comm); mesh -> SetDimension(dim); SetGlobalMesh(mesh); // for visualization mesh -> SetGeometry (nullptr); return mesh; } ), py::arg("dim")=3, py::arg("comm")=NgMPI_Comm{} ) .def(NGSPickle()) .def_property_readonly("comm", [](const Mesh & amesh) -> NgMPI_Comm { return amesh.GetCommunicator(); }, "MPI-communicator the Mesh lives in") /* .def("__init__", [](Mesh *instance, int dim) { new (instance) Mesh(); instance->SetDimension(dim); }, py::arg("dim")=3 ) */ .def_property_readonly("_timestamp", &Mesh::GetTimeStamp) .def("Distribute", [](shared_ptr self, NgMPI_Comm comm) { self->SetCommunicator(comm); if(comm.Size()==1) return self; // if(MyMPI_GetNTasks(comm)==2) throw NgException("Sorry, cannot handle communicators with NP=2!"); // cout << " rank " << MyMPI_GetId(comm) << " of " << MyMPI_GetNTasks(comm) << " called Distribute " << endl; if(comm.Rank()==0) self->Distribute(); else self->SendRecvMesh(); return self; }, py::arg("comm")) .def_static("Receive", [](NgMPI_Comm comm) -> shared_ptr { auto mesh = make_shared(); mesh->SetCommunicator(comm); mesh->SendRecvMesh(); return mesh; }, py::arg("comm")) .def("Load", FunctionPointer ([](shared_ptr self, const string & filename) { auto comm = self->GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); auto & mesh = self; { ifstream infile(filename.c_str()); if(!infile.good()) throw NgException(string("Error opening file ") + filename); } if ( filename.find(".vol") == string::npos ) { if(ntasks>1) throw NgException("Not sure what to do with this?? Does this work with MPI??"); mesh->SetCommunicator(comm); ReadFile(*mesh,filename.c_str()); //mesh->SetGlobalH (mparam.maxh); //mesh->CalcLocalH(); return; } istream * infile; Array buf; // for distributing geometry! int strs; if( id == 0) { if (filename.substr (filename.length()-3, 3) == ".gz") infile = new igzstream (filename.c_str()); else infile = new ifstream (filename.c_str()); mesh -> Load(*infile); // make string from rest of file (for geometry info!) // (this might be empty, in which case we take the global ng_geometry) stringstream geom_part; geom_part << infile->rdbuf(); string geom_part_string = geom_part.str(); strs = geom_part_string.size(); // buf = new char[strs]; buf.SetSize(strs); memcpy(&buf[0], geom_part_string.c_str(), strs*sizeof(char)); delete infile; if (ntasks > 1) { char * weightsfilename = new char [filename.size()+1]; strcpy (weightsfilename, filename.c_str()); weightsfilename[strlen (weightsfilename)-3] = 'w'; weightsfilename[strlen (weightsfilename)-2] = 'e'; weightsfilename[strlen (weightsfilename)-1] = 'i'; ifstream weightsfile(weightsfilename); delete [] weightsfilename; if (!(weightsfile.good())) { // cout << "regular distribute" << endl; mesh -> Distribute(); } else { char str[20]; bool endfile = false; int n, dummy; Array segment_weights; Array surface_weights; Array volume_weights; while (weightsfile.good() && !endfile) { weightsfile >> str; if (strcmp (str, "edgeweights") == 0) { weightsfile >> n; segment_weights.SetSize(n); for (int i = 0; i < n; i++) weightsfile >> dummy >> segment_weights[i]; } if (strcmp (str, "surfaceweights") == 0) { weightsfile >> n; surface_weights.SetSize(n); for (int i=0; i> dummy >> surface_weights[i]; } if (strcmp (str, "volumeweights") == 0) { weightsfile >> n; volume_weights.SetSize(n); for (int i=0; i> dummy >> volume_weights[i]; } if (strcmp (str, "endfile") == 0) endfile = true; } mesh -> Distribute(volume_weights, surface_weights, segment_weights); } } // ntasks>1 end } // id==0 end else { mesh->SendRecvMesh(); } if(ntasks>1) { #ifdef PARALLEL /** Scatter the geometry-string (no dummy-implementation in mpi_interface) **/ int strs = buf.Size(); MyMPI_Bcast(strs, comm); if(strs>0) MyMPI_Bcast(buf, comm); #endif } shared_ptr geo; if(buf.Size()) { // if we had geom-info in the file, take it istringstream geom_infile(string((const char*)&buf[0], buf.Size())); geo = geometryregister.LoadFromMeshFile(geom_infile); } if(geo!=nullptr) mesh->SetGeometry(geo); else if(ng_geometry!=nullptr) mesh->SetGeometry(ng_geometry); }),py::call_guard()) // static_cast(&Mesh::Load)) .def("Save", static_cast(&Mesh::Save),py::call_guard()) .def("Export", [] (Mesh & self, string filename, string format) { if (WriteUserFormat (format, self, /* *self.GetGeometry(), */ filename)) { string err = string ("nothing known about format")+format; Array names, extensions; RegisterUserFormats (names, extensions); err += "\navailable formats are:\n"; for (auto name : names) err += string("'") + name + "'\n"; throw NgException (err); } }, py::arg("filename"), py::arg("format"),py::call_guard()) .def_property("dim", &Mesh::GetDimension, &Mesh::SetDimension) .def("Elements3D", static_cast&(Mesh::*)()> (&Mesh::VolumeElements), py::return_value_policy::reference) .def("Elements2D", static_cast&(Mesh::*)()> (&Mesh::SurfaceElements), py::return_value_policy::reference) .def("Elements1D", static_cast&(Mesh::*)()> (&Mesh::LineSegments), py::return_value_policy::reference) .def("Elements0D", FunctionPointer([] (Mesh & self) -> Array& { return self.pointelements; } ), py::return_value_policy::reference) .def("Points", static_cast (&Mesh::Points), py::return_value_policy::reference) .def("FaceDescriptor", static_cast (&Mesh::GetFaceDescriptor), py::return_value_policy::reference) .def("GetNFaceDescriptors", &Mesh::GetNFD) .def("GetVolumeNeighboursOfSurfaceElement", [](Mesh & self, size_t sel) { int elnr1, elnr2; self.GetTopology().GetSurface2VolumeElement(sel+1, elnr1, elnr2); return py::make_tuple(elnr1, elnr2); }, "Returns element nrs of volume element connected to surface element, -1 if no volume element") .def("GetNCD2Names", &Mesh::GetNCD2Names) .def("__getitem__", FunctionPointer ([](const Mesh & self, PointIndex pi) { return self[pi]; })) .def ("Add", FunctionPointer ([](Mesh & self, MeshPoint p) { return self.AddPoint (Point3d(p)); })) .def ("Add", FunctionPointer ([](Mesh & self, const Element & el) { return self.AddVolumeElement (el); })) .def ("Add", FunctionPointer ([](Mesh & self, const Element2d & el) { return self.AddSurfaceElement (el); })) .def ("Add", FunctionPointer ([](Mesh & self, const Segment & el) { return self.AddSegment (el); })) .def ("Add", FunctionPointer ([](Mesh & self, const Element0d & el) { return self.pointelements.Append (el); })) .def ("Add", FunctionPointer ([](Mesh & self, const FaceDescriptor & fd) { return self.AddFaceDescriptor (fd); })) .def ("DeleteSurfaceElement", FunctionPointer ([](Mesh & self, SurfaceElementIndex i) { return self.DeleteSurfaceElement (i); })) .def ("Compress", FunctionPointer ([](Mesh & self) { return self.Compress (); }),py::call_guard()) .def ("SetBCName", &Mesh::SetBCName) .def ("GetBCName", FunctionPointer([](Mesh & self, int bc)->string { return self.GetBCName(bc); })) .def ("SetMaterial", &Mesh::SetMaterial) .def ("GetMaterial", FunctionPointer([](Mesh & self, int domnr) { return string(self.GetMaterial(domnr)); })) .def ("GetCD2Name", &Mesh::GetCD2Name) .def ("SetCD2Name", &Mesh::SetCD2Name) .def ("GetCD3Name", &Mesh::GetCD3Name) .def ("SetCD3Name", &Mesh::SetCD3Name) .def ("AddPointIdentification", [](Mesh & self, py::object pindex1, py::object pindex2, int identnr, int type) { if(py::extract(pindex1).check() && py::extract(pindex2).check()) { self.GetIdentifications().Add (py::extract(pindex1)(), py::extract(pindex2)(), identnr); self.GetIdentifications().SetType(identnr, Identifications::ID_TYPE(type)); // type = 2 ... periodic } }, //py::default_call_policies(), py::arg("pid1"), py::arg("pid2"), py::arg("identnr"), py::arg("type")) .def ("CalcLocalH", &Mesh::CalcLocalH) .def ("SetMaxHDomain", [] (Mesh& self, py::list maxhlist) { Array maxh; for(auto el : maxhlist) maxh.Append(py::cast(el)); self.SetMaxHDomain(maxh); }) .def ("GenerateVolumeMesh", [](Mesh & self, py::object pymp) { cout << "generate vol mesh" << endl; MeshingParameters mp; { py::gil_scoped_acquire acquire; if (py::extract(pymp).check()) mp = py::extract(pymp)(); else { mp.optsteps3d = 5; } } MeshVolume (mp, self); OptimizeVolume (mp, self); }, py::arg("mp")=NGDummyArgument(),py::call_guard()) .def ("OptimizeVolumeMesh", [](Mesh & self) { MeshingParameters mp; mp.optsteps3d = 5; OptimizeVolume (mp, self); },py::call_guard()) .def ("OptimizeMesh2d", [](Mesh & self) { self.CalcLocalH(0.5); MeshingParameters mp; mp.optsteps2d = 5; Optimize2d (self, mp); },py::call_guard()) .def ("Refine", FunctionPointer ([](Mesh & self) { if (self.GetGeometry()) self.GetGeometry()->GetRefinement().Refine(self); else Refinement().Refine(self); self.UpdateTopology(); }),py::call_guard()) .def ("SecondOrder", FunctionPointer ([](Mesh & self) { if (self.GetGeometry()) self.GetGeometry()->GetRefinement().MakeSecondOrder(self); else Refinement().MakeSecondOrder(self); })) .def ("GetGeometry", [] (Mesh& self) { return self.GetGeometry(); }) .def ("SetGeometry", [](Mesh & self, shared_ptr geo) { self.SetGeometry(geo); }) /* .def ("SetGeometry", FunctionPointer ([](Mesh & self, shared_ptr geo) { self.SetGeometry(geo); })) */ .def ("BuildSearchTree", &Mesh::BuildElementSearchTree,py::call_guard()) .def ("BoundaryLayer", FunctionPointer ([](Mesh & self, int bc, py::list thicknesses, int volnr, py::list materials) { int n = py::len(thicknesses); BoundaryLayerParameters blp; for (int i = 1; i <= self.GetNFD(); i++) if (self.GetFaceDescriptor(i).BCProperty() == bc) blp.surfid.Append (i); cout << "add layer at surfaces: " << blp.surfid << endl; blp.prismlayers = n; blp.growthfactor = 1.0; // find max domain nr int maxind = 0; for (ElementIndex ei = 0; ei < self.GetNE(); ei++) maxind = max (maxind, self[ei].GetIndex()); cout << "maxind = " << maxind << endl; for ( int i=0; i(thicknesses[i])()) ; blp.new_matnrs.Append( maxind+1+i ); self.SetMaterial (maxind+1+i, py::extract(materials[i])().c_str()); } blp.bulk_matnr = volnr; GenerateBoundaryLayer (self, blp); } )) .def ("BoundaryLayer", FunctionPointer ([](Mesh & self, int bc, double thickness, int volnr, string material) { BoundaryLayerParameters blp; for (int i = 1; i <= self.GetNFD(); i++) if (self.GetFaceDescriptor(i).BCProperty() == bc) blp.surfid.Append (i); cout << "add layer at surfaces: " << blp.surfid << endl; blp.prismlayers = 1; blp.hfirst = thickness; blp.growthfactor = 1.0; // find max domain nr int maxind = 0; for (ElementIndex ei = 0; ei < self.GetNE(); ei++) maxind = max (maxind, self[ei].GetIndex()); cout << "maxind = " << maxind << endl; self.SetMaterial (maxind+1, material.c_str()); blp.new_matnr = maxind+1; blp.bulk_matnr = volnr; GenerateBoundaryLayer (self, blp); } )) .def ("EnableTable", [] (Mesh & self, string name, bool set) { if (name == "edges") const_cast(self.GetTopology()).SetBuildEdges(set); if (name == "faces") const_cast(self.GetTopology()).SetBuildFaces(set); }, py::arg("name"), py::arg("set")=true) .def ("Scale", [](Mesh & self, double factor) { for(auto i = 0; i (); *m2 = self; return m2; }) ; m.def("ImportMesh", [](const string& filename) { auto mesh = make_shared(); ReadFile(*mesh, filename); return mesh; }, py::arg("filename"), R"delimiter(Import mesh from other file format, supported file formats are: Neutral format (*.mesh, *.emt) Surface file (*.surf) Universal format (*.unv) Olaf format (*.emt) Tet format (*.tet) Pro/ENGINEER format (*.fnf) )delimiter"); py::enum_(m,"MeshingStep") .value("MESHEDGES",MESHCONST_MESHEDGES) .value("MESHSURFACE",MESHCONST_OPTSURFACE) .value("MESHVOLUME",MESHCONST_OPTVOLUME) ; typedef MeshingParameters MP; py::class_ (m, "MeshingParameters") .def(py::init<>()) .def(py::init([](double maxh, bool quad_dominated, int optsteps2d, int optsteps3d, MESHING_STEP perfstepsend, int only3D_domain, const string & meshsizefilename, double grading, double curvaturesafety, double segmentsperedge) { MP * instance = new MeshingParameters; instance->maxh = maxh; instance->quad = int(quad_dominated); instance->optsteps2d = optsteps2d; instance->optsteps3d = optsteps3d; instance->only3D_domain_nr = only3D_domain; instance->perfstepsend = perfstepsend; instance->meshsizefilename = meshsizefilename; instance->grading = grading; instance->curvaturesafety = curvaturesafety; instance->segmentsperedge = segmentsperedge; return instance; }), py::arg("maxh")=1000, py::arg("quad_dominated")=false, py::arg("optsteps2d") = 3, py::arg("optsteps3d") = 3, py::arg("perfstepsend") = MESHCONST_OPTVOLUME, py::arg("only3D_domain") = 0, py::arg("meshsizefilename") = "", py::arg("grading")=0.3, py::arg("curvaturesafety")=2, py::arg("segmentsperedge")=1, "create meshing parameters" ) .def("__str__", &ToString) .def_property("maxh", FunctionPointer ([](const MP & mp ) { return mp.maxh; }), FunctionPointer ([](MP & mp, double maxh) { return mp.maxh = maxh; })) .def("RestrictH", FunctionPointer ([](MP & mp, double x, double y, double z, double h) { mp.meshsize_points.Append ( MeshingParameters::MeshSizePoint (Point<3> (x,y,z), h)); }), py::arg("x"), py::arg("y"), py::arg("z"), py::arg("h") ) ; m.def("SetTestoutFile", FunctionPointer ([] (const string & filename) { delete testout; testout = new ofstream (filename); })); m.def("SetMessageImportance", FunctionPointer ([] (int importance) { int old = printmessage_importance; printmessage_importance = importance; return old; })); } PYBIND11_MODULE(libmesh, m) { ExportNetgenMeshing(m); } #endif netgen-6.2.1905/libsrc/meshing/meshing3.cpp0000644000175000017500000007373313504650527017147 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { double minother; double minwithoutother; MeshingStat3d :: MeshingStat3d () { cntsucc = cnttrials = cntelem = qualclass = 0; vol0 = h = 1; problemindex = 1; } Meshing3 :: Meshing3 (const string & rulefilename) { tolfak = 1; LoadRules (rulefilename.c_str(), NULL); adfront = new AdFront3; problems.SetSize (rules.Size()); foundmap.SetSize (rules.Size()); canuse.SetSize (rules.Size()); ruleused.SetSize (rules.Size()); for (int i = 1; i <= rules.Size(); i++) { problems.Elem(i) = new char[255]; foundmap.Elem(i) = 0; canuse.Elem(i) = 0; ruleused.Elem(i) = 0; } } Meshing3 :: Meshing3 (const char ** rulep) { tolfak = 1; LoadRules (NULL, rulep); adfront = new AdFront3; problems.SetSize (rules.Size()); foundmap.SetSize (rules.Size()); canuse.SetSize (rules.Size()); ruleused.SetSize (rules.Size()); for (int i = 0; i < rules.Size(); i++) { problems[i] = new char[255]; foundmap[i] = 0; canuse[i] = 0; ruleused[i] = 0; } } Meshing3 :: ~Meshing3 () { delete adfront; for (int i = 0; i < rules.Size(); i++) { delete [] problems[i]; delete rules[i]; } } /* // was war das ???? static double CalcLocH (const Array & locpoints, const Array & locfaces, double h) { return h; int i, j; double hi, h1, d, dn, sum, weight, wi; Point3d p0, pc; Vec3d n, v1, v2; p0.X() = p0.Y() = p0.Z() = 0; for (j = 1; j <= 3; j++) { p0.X() += locpoints.Get(locfaces.Get(1).PNum(j)).X(); p0.Y() += locpoints.Get(locfaces.Get(1).PNum(j)).Y(); p0.Z() += locpoints.Get(locfaces.Get(1).PNum(j)).Z(); } p0.X() /= 3; p0.Y() /= 3; p0.Z() /= 3; v1 = locpoints.Get(locfaces.Get(1).PNum(2)) - locpoints.Get(locfaces.Get(1).PNum(1)); v2 = locpoints.Get(locfaces.Get(1).PNum(3)) - locpoints.Get(locfaces.Get(1).PNum(1)); h1 = v1.Length(); n = Cross (v2, v1); n /= n.Length(); sum = 0; weight = 0; for(int i = 1; i <= locfaces.Size(); i++) { pc.X() = pc.Y() = pc.Z() = 0; for (j = 1; j <= 3; j++) { pc.X() += locpoints.Get(locfaces.Get(i).PNum(j)).X(); pc.Y() += locpoints.Get(locfaces.Get(i).PNum(j)).Y(); pc.Z() += locpoints.Get(locfaces.Get(i).PNum(j)).Z(); } pc.X() /= 3; pc.Y() /= 3; pc.Z() /= 3; d = Dist (p0, pc); dn = n * (pc - p0); hi = Dist (locpoints.Get(locfaces.Get(i).PNum(1)), locpoints.Get(locfaces.Get(i).PNum(2))); if (dn > -0.2 * h1) { wi = 1 / (h1 + d); wi *= wi; } else wi = 0; sum += hi * wi; weight += wi; } return sum/weight; } */ PointIndex Meshing3 :: AddPoint (const Point3d & p, PointIndex globind) { return adfront -> AddPoint (p, globind); } void Meshing3 :: AddBoundaryElement (const Element2d & elem) { MiniElement2d mini(elem.GetNP()); for (int j = 0; j < elem.GetNP(); j++) mini[j] = elem[j]; adfront -> AddFace(mini); } void Meshing3 :: AddBoundaryElement (const MiniElement2d & elem) { adfront -> AddFace(elem); } int Meshing3 :: AddConnectedPair (const INDEX_2 & apair) { return adfront -> AddConnectedPair (apair); } MESHING3_RESULT Meshing3 :: GenerateMesh (Mesh & mesh, const MeshingParameters & mp) { static Timer t("Meshing3::GenerateMesh"); RegionTimer reg(t); static Timer meshing3_timer_a("Meshing3::GenerateMesh a", 2); static Timer meshing3_timer_b("Meshing3::GenerateMesh b", 2); static Timer meshing3_timer_c("Meshing3::GenerateMesh c", 1); static Timer meshing3_timer_d("Meshing3::GenerateMesh d", 2); // static int meshing3_timer = NgProfiler::CreateTimer ("Meshing3::GenerateMesh"); // static int meshing3_timer_a = NgProfiler::CreateTimer ("Meshing3::GenerateMesh a"); // static int meshing3_timer_b = NgProfiler::CreateTimer ("Meshing3::GenerateMesh b"); // static int meshing3_timer_c = NgProfiler::CreateTimer ("Meshing3::GenerateMesh c"); // static int meshing3_timer_d = NgProfiler::CreateTimer ("Meshing3::GenerateMesh d"); // NgProfiler::RegionTimer reg (meshing3_timer); Array locpoints; // local points Array locfaces; // local faces Array pindex; // mapping from local to front point numbering Array allowpoint; // point is allowed ? Array findex; // mapping from local to front face numbering //INDEX_2_HASHTABLE connectedpairs(100); // connecgted pairs for prism meshing Array plainpoints; // points in reference coordinates Array delpoints, delfaces; // points and lines to be deleted Array locelements; // new generated elements int j, oldnp, oldnf; int found; referencetransform trans; int rotind; Point3d inp; float err; INDEX locfacesplit; //index for faces in outer area bool loktestmode = false; int uselocalh = mp.uselocalh; // int giveuptol = mp.giveuptol; // MeshingStat3d stat; // statistics int plotstat_oldne = -1; // for star-shaped domain meshing Array grouppoints; Array groupfaces; Array grouppindex; Array groupfindex; float minerr; int hasfound; double tetvol; // int giveup = 0; Array tempnewpoints; Array tempnewfaces; Array tempdelfaces; Array templocelements; stat.h = mp.maxh; adfront->SetStartFront (mp.baseelnp); found = 0; stat.vol0 = adfront -> Volume(); tetvol = 0; stat.qualclass = 1; while (1) { if (multithread.terminate) throw NgException ("Meshing stopped"); // break if advancing front is empty if (!mp.baseelnp && adfront->Empty()) break; // break, if advancing front has no elements with // mp.baseelnp nodes if (mp.baseelnp && adfront->Empty (mp.baseelnp)) break; locpoints.SetSize(0); locfaces.SetSize(0); locelements.SetSize(0); pindex.SetSize(0); findex.SetSize(0); INDEX_2_HASHTABLE connectedpairs(100); // connected pairs for prism meshing // select base-element (will be locface[1]) // and get local environment of radius (safety * h) int baseelem = adfront -> SelectBaseElement (); if (mp.baseelnp && adfront->GetFace (baseelem).GetNP() != mp.baseelnp) { adfront->IncrementClass (baseelem); continue; } const MiniElement2d & bel = adfront->GetFace (baseelem); const Point<3> p1 = adfront->GetPoint (bel[0]); const Point<3> p2 = adfront->GetPoint (bel[1]); const Point<3> p3 = adfront->GetPoint (bel[2]); Point<3> pmid = Center (p1, p2, p3); double his = (Dist (p1, p2) + Dist(p1, p3) + Dist(p2, p3)) / 3; double hshould = mesh.GetH (pmid); if (adfront->GetFace (baseelem).GetNP() == 4) hshould = max2 (his, hshould); double hmax = (his > hshould) ? his : hshould; // qualclass should come from baseelem !!!!! double hinner = hmax * (1 + stat.qualclass); double houter = hmax * (1 + 2 * stat.qualclass); meshing3_timer_a.Start(); stat.qualclass = adfront -> GetLocals (baseelem, locpoints, locfaces, pindex, findex, connectedpairs, houter, hinner, locfacesplit); meshing3_timer_a.Stop(); // (*testout) << "locfaces = " << endl << locfaces << endl; //loktestmode = 1; testmode = loktestmode; //changed // loktestmode = testmode = (adfront->GetFace (baseelem).GetNP() == 4) && (rules.Size() == 5); loktestmode = stat.qualclass > 5; if (loktestmode) { (*testout) << "baseel = " << baseelem << ", ind = " << findex.Get(1) << endl; int pi1 = pindex[locfaces[0].PNum(1)]; int pi2 = pindex[locfaces[0].PNum(2)]; int pi3 = pindex[locfaces[0].PNum(3)]; (*testout) << "pi = " << pi1 << ", " << pi2 << ", " << pi3 << endl; } if (testmode) { (*testout) << "baseelem = " << baseelem << " qualclass = " << stat.qualclass << endl; (*testout) << "locpoints = " << endl << locpoints << endl; (*testout) << "connected = " << endl << connectedpairs << endl; } // loch = CalcLocH (locpoints, locfaces, h); stat.nff = adfront->GetNF(); stat.vol = adfront->Volume(); if (stat.vol < 0) break; oldnp = locpoints.Size(); oldnf = locfaces.Size(); allowpoint.SetSize(locpoints.Size()); if (uselocalh && stat.qualclass <= 3) for(int i = 1; i <= allowpoint.Size(); i++) { allowpoint.Elem(i) = (mesh.GetH (locpoints.Get(i)) > 0.4 * hshould / mp.sloppy) ? 2 : 1; } else allowpoint = 2; if (stat.qualclass >= mp.starshapeclass && mp.baseelnp != 4) { NgProfiler::RegionTimer reg1 (meshing3_timer_b); // star-shaped domain removing grouppoints.SetSize (0); groupfaces.SetSize (0); grouppindex.SetSize (0); groupfindex.SetSize (0); adfront -> GetGroup (findex[0], grouppoints, groupfaces, grouppindex, groupfindex); bool onlytri = 1; for (auto i : groupfaces.Range()) if (groupfaces[i].GetNP() != 3) onlytri = 0; if (onlytri && groupfaces.Size() <= 20 + 2*stat.qualclass && FindInnerPoint (grouppoints, groupfaces, inp)) { (*testout) << "inner point found" << endl; for(int i = 1; i <= groupfaces.Size(); i++) adfront -> DeleteFace (groupfindex.Get(i)); for(int i = 1; i <= groupfaces.Size(); i++) for (j = 1; j <= locfaces.Size(); j++) if (findex.Get(j) == groupfindex.Get(i)) delfaces.Append (j); delfaces.SetSize (0); INDEX npi; Element newel(TET); npi = mesh.AddPoint (inp); newel.SetNP(4); newel.PNum(4) = npi; for(int i = 1; i <= groupfaces.Size(); i++) { for (j = 1; j <= 3; j++) { newel.PNum(j) = adfront->GetGlobalIndex (grouppindex.Get(groupfaces.Get(i).PNum(j))); } mesh.AddVolumeElement (newel); } continue; } } found = 0; hasfound = 0; minerr = 1e6; // int optother = 0; /* for(int i = 1; i <= locfaces.Size(); i++) { (*testout) << "Face " << i << ": "; for (j = 1; j <= locfaces.Get(i).GetNP(); j++) (*testout) << pindex.Get(locfaces.Get(i).PNum(j)) << " "; (*testout) << endl; } for(int i = 1; i <= locpoints.Size(); i++) { (*testout) << "p" << i << ", gi = " << pindex.Get(i) << " = " << locpoints.Get(i) << endl; } */ minother = 1e10; minwithoutother = 1e10; bool impossible = 1; for (rotind = 1; rotind <= locfaces[0].GetNP(); rotind++) { // set transformatino to reference coordinates if (locfaces[0].GetNP() == 3) { trans.Set (locpoints[locfaces[0].PNumMod(1+rotind)], locpoints[locfaces[0].PNumMod(2+rotind)], locpoints[locfaces[0].PNumMod(3+rotind)], hshould); } else { trans.Set (locpoints[locfaces[0].PNumMod(1+rotind)], locpoints[locfaces[0].PNumMod(2+rotind)], locpoints[locfaces[0].PNumMod(4+rotind)], hshould); } // trans.ToPlain (locpoints, plainpoints); plainpoints.SetSize (locpoints.Size()); for (auto i : locpoints.Range()) trans.ToPlain (locpoints[i], plainpoints[i]); for (auto i : allowpoint.Range()) if (plainpoints[i].Z() > 0) allowpoint[i] = false; stat.cnttrials++; if (stat.cnttrials % 100 == 0) { (*testout) << "\n"; for(int i = 1; i <= canuse.Size(); i++) { (*testout) << foundmap.Get(i) << "/" << canuse.Get(i) << "/" << ruleused.Get(i) << " map/can/use rule " << rules.Get(i)->Name() << "\n"; } (*testout) << endl; } // NgProfiler::StartTimer (meshing3_timer_c); meshing3_timer_c.Start(); found = ApplyRules (plainpoints, allowpoint, locfaces, locfacesplit, connectedpairs, locelements, delfaces, stat.qualclass, mp.sloppy, rotind, err); if (found >= 0) impossible = 0; if (found < 0) found = 0; meshing3_timer_c.Stop(); // NgProfiler::StopTimer (meshing3_timer_c); if (!found) loktestmode = 0; NgProfiler::RegionTimer reg2 (meshing3_timer_d); if (loktestmode) { (*testout) << "plainpoints = " << endl << plainpoints << endl; (*testout) << "Applyrules found " << found << endl; } if (found) stat.cntsucc++; locpoints.SetSize (plainpoints.Size()); for (int i = oldnp+1; i <= plainpoints.Size(); i++) trans.FromPlain (plainpoints.Elem(i), locpoints.Elem(i)); // avoid meshing from large to small mesh-size if (uselocalh && found && stat.qualclass <= 3) { for (int i = 1; i <= locelements.Size(); i++) { Point3d pmin = locpoints[locelements.Get(i).PNum(1)]; Point3d pmax = pmin; for (j = 2; j <= 4; j++) { const Point3d & hp = locpoints[locelements.Get(i).PNum(j)]; pmin.SetToMin (hp); pmax.SetToMax (hp); } if (mesh.GetMinH (pmin, pmax) < 0.4 * hshould / mp.sloppy) found = 0; } } if (found) { for (int i = 1; i <= locelements.Size(); i++) for (int j = 1; j <= 4; j++) { const Point3d & hp = locpoints[locelements.Get(i).PNum(j)]; if (Dist (hp, pmid) > hinner) found = 0; } } if (found) ruleused.Elem(found)++; // plotstat->Plot(stat); if (stat.cntelem != plotstat_oldne) { plotstat_oldne = stat.cntelem; PrintMessageCR (5, "El: ", stat.cntelem, // << " trials: " << stat.cnttrials " faces: ", stat.nff, " vol = ", float(100 * stat.vol / stat.vol0)); multithread.percent = 100 - 100.0 * stat.vol / stat.vol0; } if (found && (!hasfound || err < minerr) ) { if (testmode) { (*testout) << "found is active, 3" << endl; for(int i = 1; i <= plainpoints.Size(); i++) { (*testout) << "p"; if (i <= pindex.Size()) (*testout) << pindex.Get(i) << ": "; else (*testout) << "new: "; (*testout) << plainpoints.Get(i) << endl; } } hasfound = found; minerr = err; tempnewpoints.SetSize (0); for(int i = oldnp+1; i <= locpoints.Size(); i++) tempnewpoints.Append (locpoints.Get(i)); tempnewfaces.SetSize (0); for(int i = oldnf+1; i <= locfaces.Size(); i++) tempnewfaces.Append (locfaces.Get(i)); tempdelfaces.SetSize (0); for(int i = 1; i <= delfaces.Size(); i++) tempdelfaces.Append (delfaces.Get(i)); templocelements.SetSize (0); for(int i = 1; i <= locelements.Size(); i++) templocelements.Append (locelements.Get(i)); /* optother = strcmp (problems[found], "other") == 0; */ } locpoints.SetSize (oldnp); locfaces.SetSize (oldnf); delfaces.SetSize (0); locelements.SetSize (0); } if (hasfound) { /* if (optother) (*testout) << "Other is optimal" << endl; if (minother < minwithoutother) { (*testout) << "Other is better, " << minother << " less " << minwithoutother << endl; } */ for(int i = 1; i <= tempnewpoints.Size(); i++) locpoints.Append (tempnewpoints.Get(i)); for(int i = 1; i <= tempnewfaces.Size(); i++) locfaces.Append (tempnewfaces.Get(i)); for(int i = 1; i <= tempdelfaces.Size(); i++) delfaces.Append (tempdelfaces.Get(i)); for(int i = 1; i <= templocelements.Size(); i++) locelements.Append (templocelements.Get(i)); if (loktestmode) { (*testout) << "apply rule" << endl; for(int i = 1; i <= locpoints.Size(); i++) { (*testout) << "p"; if (i <= pindex.Size()) (*testout) << pindex.Get(i) << ": "; else (*testout) << "new: "; (*testout) << locpoints.Get(i) << endl; } } pindex.SetSize(locpoints.Size()); for (int i = oldnp+1; i <= locpoints.Size(); i++) { PointIndex globind = mesh.AddPoint (locpoints.Get(i)); pindex.Elem(i) = adfront -> AddPoint (locpoints.Get(i), globind); } for (int i = 1; i <= locelements.Size(); i++) { Point3d * hp1, * hp2, * hp3, * hp4; hp1 = &locpoints[locelements.Get(i).PNum(1)]; hp2 = &locpoints[locelements.Get(i).PNum(2)]; hp3 = &locpoints[locelements.Get(i).PNum(3)]; hp4 = &locpoints[locelements.Get(i).PNum(4)]; tetvol += (1.0 / 6.0) * ( Cross ( *hp2 - *hp1, *hp3 - *hp1) * (*hp4 - *hp1) ); for (j = 1; j <= locelements.Get(i).NP(); j++) locelements.Elem(i).PNum(j) = adfront -> GetGlobalIndex (pindex[locelements.Get(i).PNum(j)]); mesh.AddVolumeElement (locelements.Get(i)); stat.cntelem++; } for(int i = oldnf+1; i <= locfaces.Size(); i++) { for (j = 1; j <= locfaces.Get(i).GetNP(); j++) locfaces.Elem(i).PNum(j) = pindex[locfaces.Get(i).PNum(j)]; // (*testout) << "add face " << locfaces.Get(i) << endl; adfront->AddFace (locfaces.Get(i)); } for(int i = 1; i <= delfaces.Size(); i++) adfront->DeleteFace (findex.Get(delfaces.Get(i))); } else { adfront->IncrementClass (findex.Get(1)); if (impossible && mp.check_impossible) { (*testout) << "skip face since it is impossible" << endl; for (j = 0; j < 100; j++) adfront->IncrementClass (findex.Get(1)); } } locelements.SetSize (0); delpoints.SetSize(0); delfaces.SetSize(0); if (stat.qualclass >= mp.giveuptol) break; } PrintMessage (5, ""); // line feed after statistics for(int i = 1; i <= ruleused.Size(); i++) (*testout) << setw(4) << ruleused.Get(i) << " times used rule " << rules.Get(i) -> Name() << endl; if (!mp.baseelnp && adfront->Empty()) return MESHING3_OK; if (mp.baseelnp && adfront->Empty (mp.baseelnp)) return MESHING3_OK; if (stat.vol < -1e-15) return MESHING3_NEGVOL; return MESHING3_NEGVOL; } enum blocktyp { BLOCKUNDEF, BLOCKINNER, BLOCKBOUND, BLOCKOUTER }; void Meshing3 :: BlockFill (Mesh & mesh, double gh) { static Timer t("Mesing3::BlockFill"); RegionTimer reg(t); PrintMessage (3, "Block-filling called (obsolete) "); int i, j(0), i1, i2, i3, j1, j2, j3; int n1, n2, n3, n, min1, min2, min3, max1, max2, max3; int changed, filled; double xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0); double xminb, xmaxb, yminb, ymaxb, zminb, zmaxb; //double rad = 0.7 * gh; for(int i = 1; i <= adfront->GetNP(); i++) { const Point3d & p = adfront->GetPoint(PointIndex(i)); if (i == 1) { xmin = xmax = p.X(); ymin = ymax = p.Y(); zmin = zmax = p.Z(); } else { if (p.X() < xmin) xmin = p.X(); if (p.X() > xmax) xmax = p.X(); if (p.Y() < ymin) ymin = p.Y(); if (p.Y() > ymax) ymax = p.Y(); if (p.Z() < zmin) zmin = p.Z(); if (p.Z() > zmax) zmax = p.Z(); } } xmin -= 5 * gh; ymin -= 5 * gh; zmin -= 5 * gh; n1 = int ((xmax-xmin) / gh + 5); n2 = int ((ymax-ymin) / gh + 5); n3 = int ((zmax-zmin) / gh + 5); n = n1 * n2 * n3; PrintMessage (5, "n1 = ", n1, " n2 = ", n2, " n3 = ", n3); Array inner(n); Array pointnr(n); Array frontpointnr(n); // initialize inner to 1 for(int i = 1; i <= n; i++) inner.Elem(i) = BLOCKUNDEF; // set blocks cutting surfaces to 0 for(int i = 1; i <= adfront->GetNF(); i++) { const MiniElement2d & el = adfront->GetFace(i); xminb = xmax; xmaxb = xmin; yminb = ymax; ymaxb = ymin; zminb = zmax; zmaxb = zmin; for (j = 1; j <= 3; j++) { const Point3d & p = adfront->GetPoint (el.PNum(j)); if (p.X() < xminb) xminb = p.X(); if (p.X() > xmaxb) xmaxb = p.X(); if (p.Y() < yminb) yminb = p.Y(); if (p.Y() > ymaxb) ymaxb = p.Y(); if (p.Z() < zminb) zminb = p.Z(); if (p.Z() > zmaxb) zmaxb = p.Z(); } double filldist = 0.2; // globflags.GetNumFlag ("filldist", 0.4); xminb -= filldist * gh; xmaxb += filldist * gh; yminb -= filldist * gh; ymaxb += filldist * gh; zminb -= filldist * gh; zmaxb += filldist * gh; min1 = int ((xminb - xmin) / gh) + 1; max1 = int ((xmaxb - xmin) / gh) + 1; min2 = int ((yminb - ymin) / gh) + 1; max2 = int ((ymaxb - ymin) / gh) + 1; min3 = int ((zminb - zmin) / gh) + 1; max3 = int ((zmaxb - zmin) / gh) + 1; for (i1 = min1; i1 <= max1; i1++) for (i2 = min2; i2 <= max2; i2++) for (i3 = min3; i3 <= max3; i3++) inner.Elem(i3 + (i2-1) * n3 + (i1-1) * n2 * n3) = BLOCKBOUND; } while (1) { int undefi = 0; Point3d undefp; for (i1 = 1; i1 <= n1 && !undefi; i1++) for (i2 = 1; i2 <= n2 && !undefi; i2++) for (i3 = 1; i3 <= n3 && !undefi; i3++) { i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; if (inner.Elem(i) == BLOCKUNDEF) { undefi = i; undefp.X() = xmin + (i1-0.5) * gh; undefp.Y() = ymin + (i2-0.5) * gh; undefp.Z() = zmin + (i3-0.5) * gh; } } if (!undefi) break; // PrintMessage (5, "Test point: ", undefp); if (adfront -> Inside (undefp)) { // (*mycout) << "inner" << endl; inner.Elem(undefi) = BLOCKINNER; } else { // (*mycout) << "outer" << endl; inner.Elem(undefi) = BLOCKOUTER; } do { changed = 0; for (i1 = 1; i1 <= n1; i1++) for (i2 = 1; i2 <= n2; i2++) for (i3 = 1; i3 <= n3; i3++) { i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; for (int k = 1; k <= 3; k++) { switch (k) { case 1: j = i + n2 * n3; break; case 2: j = i + n3; break; case 3: j = i + 1; break; } if (j > n1 * n2 * n3) continue; if (inner.Elem(i) == BLOCKOUTER && inner.Elem(j) == BLOCKUNDEF) { changed = 1; inner.Elem(j) = BLOCKOUTER; } if (inner.Elem(j) == BLOCKOUTER && inner.Elem(i) == BLOCKUNDEF) { changed = 1; inner.Elem(i) = BLOCKOUTER; } if (inner.Elem(i) == BLOCKINNER && inner.Elem(j) == BLOCKUNDEF) { changed = 1; inner.Elem(j) = BLOCKINNER; } if (inner.Elem(j) == BLOCKINNER && inner.Elem(i) == BLOCKUNDEF) { changed = 1; inner.Elem(i) = BLOCKINNER; } } } } while (changed); } filled = 0; for(int i = 1; i <= n; i++) if (inner.Elem(i) == BLOCKINNER) { filled++; } PrintMessage (5, "Filled blocks: ", filled); for(int i = 1; i <= n; i++) { pointnr.Elem(i) = 0; frontpointnr.Elem(i) = 0; } for (i1 = 1; i1 <= n1-1; i1++) for (i2 = 1; i2 <= n2-1; i2++) for (i3 = 1; i3 <= n3-1; i3++) { i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; if (inner.Elem(i) == BLOCKINNER) { for (j1 = i1; j1 <= i1+1; j1++) for (j2 = i2; j2 <= i2+1; j2++) for (j3 = i3; j3 <= i3+1; j3++) { j = j3 + (j2-1) * n3 + (j1-1) * n2 * n3; if (pointnr.Get(j) == 0) { Point3d hp(xmin + (j1-1) * gh, ymin + (j2-1) * gh, zmin + (j3-1) * gh); pointnr.Elem(j) = mesh.AddPoint (hp); frontpointnr.Elem(j) = AddPoint (hp, pointnr.Elem(j)); } } } } for (i1 = 2; i1 <= n1-1; i1++) for (i2 = 2; i2 <= n2-1; i2++) for (i3 = 2; i3 <= n3-1; i3++) { i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; if (inner.Elem(i) == BLOCKINNER) { int pn[9]; pn[1] = pointnr.Get(i); pn[2] = pointnr.Get(i+1); pn[3] = pointnr.Get(i+n3); pn[4] = pointnr.Get(i+n3+1); pn[5] = pointnr.Get(i+n2*n3); pn[6] = pointnr.Get(i+n2*n3+1); pn[7] = pointnr.Get(i+n2*n3+n3); pn[8] = pointnr.Get(i+n2*n3+n3+1); static int elind[][4] = { { 1, 8, 2, 4 }, { 1, 8, 4, 3 }, { 1, 8, 3, 7 }, { 1, 8, 7, 5 }, { 1, 8, 5, 6 }, { 1, 8, 6, 2 } }; for (j = 1; j <= 6; j++) { Element el(4); for (int k = 1; k <= 4; k++) el.PNum(k) = pn[elind[j-1][k-1]]; mesh.AddVolumeElement (el); } } } for (i1 = 2; i1 <= n1-1; i1++) for (i2 = 2; i2 <= n2-1; i2++) for (i3 = 2; i3 <= n3-1; i3++) { i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; if (inner.Elem(i) == BLOCKINNER) { int pi1(0), pi2(0), pi3(0), pi4(0); int pn1 = frontpointnr.Get(i); int pn2 = frontpointnr.Get(i+1); int pn3 = frontpointnr.Get(i+n3); int pn4 = frontpointnr.Get(i+n3+1); int pn5 = frontpointnr.Get(i+n2*n3); int pn6 = frontpointnr.Get(i+n2*n3+1); int pn7 = frontpointnr.Get(i+n2*n3+n3); int pn8 = frontpointnr.Get(i+n2*n3+n3+1); for (int k = 1; k <= 6; k++) { switch (k) { case 1: // j3 = i3+1 j = i + 1; pi1 = pn2; pi2 = pn6; pi3 = pn4; pi4 = pn8; break; case 2: // j3 = i3-1 j = i - 1; pi1 = pn1; pi2 = pn3; pi3 = pn5; pi4 = pn7; break; case 3: // j2 = i2+1 j = i + n3; pi1 = pn3; pi2 = pn4; pi3 = pn7; pi4 = pn8; break; case 4: // j2 = i2-1 j = i - n3; pi1 = pn1; pi2 = pn5; pi3 = pn2; pi4 = pn6; break; case 5: // j1 = i1+1 j = i + n3*n2; pi1 = pn5; pi2 = pn7; pi3 = pn6; pi4 = pn8; break; case 6: // j1 = i1-1 j = i - n3*n2; pi1 = pn1; pi2 = pn2; pi3 = pn3; pi4 = pn4; break; } if (inner.Get(j) == BLOCKBOUND) { MiniElement2d face; face.PNum(1) = pi4; face.PNum(2) = pi1; face.PNum(3) = pi3; AddBoundaryElement (face); face.PNum(1) = pi1; face.PNum(2) = pi4; face.PNum(3) = pi2; AddBoundaryElement (face); } } } } } /* static const AdFront3 * locadfront; static int TestInner (const Point3d & p) { return locadfront->Inside (p); } static int TestSameSide (const Point3d & p1, const Point3d & p2) { return locadfront->SameSide (p1, p2); } */ void Meshing3 :: BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp) { static Timer t("Mesing3::BlockFillLocalH"); RegionTimer reg(t); double filldist = mp.filldist; // (*testout) << "blockfill local h" << endl; // (*testout) << "rel filldist = " << filldist << endl; PrintMessage (3, "blockfill local h"); Array > npoints; adfront -> CreateTrees(); Box<3> bbox ( Box<3>::EMPTY_BOX ); double maxh = 0; for (int i = 1; i <= adfront->GetNF(); i++) { const MiniElement2d & el = adfront->GetFace(i); for (int j = 1; j <= 3; j++) { const Point3d & p1 = adfront->GetPoint (el.PNumMod(j)); const Point3d & p2 = adfront->GetPoint (el.PNumMod(j+1)); double hi = Dist (p1, p2); if (hi > maxh) maxh = hi; bbox.Add (p1); } } Point3d mpmin = bbox.PMin(); Point3d mpmax = bbox.PMax(); Point3d mpc = Center (mpmin, mpmax); double d = max3(mpmax.X()-mpmin.X(), mpmax.Y()-mpmin.Y(), mpmax.Z()-mpmin.Z()) / 2; mpmin = mpc - Vec3d (d, d, d); mpmax = mpc + Vec3d (d, d, d); Box3d meshbox (mpmin, mpmax); LocalH loch2 (mpmin, mpmax, 1); if (mp.maxh < maxh) maxh = mp.maxh; bool changed; do { mesh.LocalHFunction().ClearFlags(); for (int i = 1; i <= adfront->GetNF(); i++) { const MiniElement2d & el = adfront->GetFace(i); Box<3> bbox (adfront->GetPoint (el[0])); bbox.Add (adfront->GetPoint (el[1])); bbox.Add (adfront->GetPoint (el[2])); double filld = filldist * bbox.Diam(); bbox.Increase (filld); mesh.LocalHFunction().CutBoundary (bbox); // .PMin(), bbox.PMax()); } // locadfront = adfront; mesh.LocalHFunction().FindInnerBoxes (adfront, NULL); npoints.SetSize(0); mesh.LocalHFunction().GetInnerPoints (npoints); changed = false; for (int i = 1; i <= npoints.Size(); i++) { if (mesh.LocalHFunction().GetH(npoints.Get(i)) > 1.5 * maxh) { mesh.LocalHFunction().SetH (npoints.Get(i), maxh); changed = true; } } } while (changed); if (debugparam.slowchecks) (*testout) << "Blockfill with points: " << endl; for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn (npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint (npoints.Get(i)); adfront->AddPoint (npoints.Get(i), gpnum); if (debugparam.slowchecks) { (*testout) << npoints.Get(i) << endl; if (!adfront->Inside(npoints.Get(i))) { cout << "add outside point" << endl; (*testout) << "outside" << endl; } } } } // find outer points loch2.ClearFlags(); for (int i = 1; i <= adfront->GetNF(); i++) { const MiniElement2d & el = adfront->GetFace(i); Point3d pmin = adfront->GetPoint (el.PNum(1)); Point3d pmax = pmin; for (int j = 2; j <= 3; j++) { const Point3d & p = adfront->GetPoint (el.PNum(j)); pmin.SetToMin (p); pmax.SetToMax (p); } loch2.SetH (Center (pmin, pmax), Dist (pmin, pmax)); } for (int i = 1; i <= adfront->GetNF(); i++) { const MiniElement2d & el = adfront->GetFace(i); Point3d pmin = adfront->GetPoint (el.PNum(1)); Point3d pmax = pmin; for (int j = 2; j <= 3; j++) { const Point3d & p = adfront->GetPoint (el.PNum(j)); pmin.SetToMin (p); pmax.SetToMax (p); } double filld = filldist * Dist (pmin, pmax); pmin = pmin - Vec3d (filld, filld, filld); pmax = pmax + Vec3d (filld, filld, filld); // loch2.CutBoundary (pmin, pmax); loch2.CutBoundary (Box<3> (pmin, pmax)); // pmin, pmax); } // locadfront = adfront; loch2.FindInnerBoxes (adfront, NULL); npoints.SetSize(0); loch2.GetOuterPoints (npoints); for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn (npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint (npoints.Get(i)); adfront->AddPoint (npoints.Get(i), gpnum); } } } } netgen-6.2.1905/libsrc/meshing/hpref_pyramid.hpp0000644000175000017500000000425613504650527020262 0ustar kurtkurt // HP_PYRAMID int refpyramid_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refpyramid_newelstypes[] = { HP_PYRAMID, HP_NONE, }; int refpyramid_newels[][8] = { { 1, 2, 3, 4, 5 } }; HPRef_Struct refpyramid = { HP_PYRAMID, refpyramid_splitedges, 0, 0, refpyramid_newelstypes, refpyramid_newels }; // singular point 1 // HP_PYRAMID_0E_1V int refpyramid_0e_1v_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refpyramid_0e_1v_newelstypes[] = { HP_TET_0E_1V, HP_TET, HP_NONE, }; int refpyramid_0e_1v_newels[][8] = { { 1, 2, 4, 5 }, { 2, 3, 4, 5 }, }; HPRef_Struct refpyramid_0e_1v = { HP_PYRAMID, refpyramid_0e_1v_splitedges, 0, 0, refpyramid_0e_1v_newelstypes, refpyramid_0e_1v_newels }; // singular edges 1-2 1-4 singular point 1 // HP_PYRAMID_EDGES int refpyramid_edges_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refpyramid_edges_newelstypes[] = { HP_TET_1E_1VA, HP_TET_1E_1VA, HP_NONE, }; int refpyramid_edges_newels[][8] = { { 1, 2, 3, 5 }, { 1, 4, 5, 3 }, }; HPRef_Struct refpyramid_edges = { HP_PYRAMID, refpyramid_edges_splitedges, 0, 0, refpyramid_edges_newelstypes, refpyramid_edges_newels }; // singular face 1-2-5 singular point 5 // HP_PYRAMID_1FB_0E_1VA int refpyramid_1fb_0e_1va_splitedges[][3] = { { 1, 4, 6 }, { 2, 3, 7 }, { 5, 1, 8 }, { 5, 2, 9 }, { 5, 3, 10 }, { 5, 4, 11 }, { 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refpyramid_1fb_0e_1va_newelstypes[] = { HP_HEX_1F_0E_0V, HP_PYRAMID_1FB_0E_1VA, HP_PRISM, HP_NONE, }; int refpyramid_1fb_0e_1va_newels[][8] = { { 1, 8, 9, 2, 6, 11, 10, 7 }, { 8, 9, 10, 11, 5 }, { 3, 7, 10, 4, 6, 11 } }; HPRef_Struct refpyramid_1fb_0e_1va = { HP_PYRAMID, refpyramid_1fb_0e_1va_splitedges, 0, 0, refpyramid_1fb_0e_1va_newelstypes, refpyramid_1fb_0e_1va_newels }; netgen-6.2.1905/libsrc/meshing/improve2.cpp0000644000175000017500000004566413504650527017177 0ustar kurtkurt#include #include "meshing.hpp" #include #ifndef SMALLLIB //#ifndef NOTCL //#include //#endif #endif namespace netgen { class Neighbour { int nr[3]; int orient[3]; public: Neighbour () { ; } void SetNr (int side, int anr) { nr[side] = anr; } int GetNr (int side) { return nr[side]; } void SetOrientation (int side, int aorient) { orient[side] = aorient; } int GetOrientation (int side) { return orient[side]; } /* void SetNr1 (int side, int anr) { nr[side-1] = anr; } int GetNr1 (int side) { return nr[side-1]; } void SetOrientation1 (int side, int aorient) { orient[side-1] = aorient; } int GetOrientation1 (int side) { return orient[side-1]; } */ }; class trionedge { public: int tnr; int sidenr; trionedge () { tnr = 0; sidenr = 0; } trionedge (int atnr, int asidenr) { tnr = atnr; sidenr = asidenr; } }; void MeshOptimize2d :: EdgeSwapping (Mesh & mesh, int usemetric) { if (!faceindex) { if (usemetric) PrintMessage (3, "Edgeswapping, metric"); else PrintMessage (3, "Edgeswapping, topological"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) { EdgeSwapping (mesh, usemetric); if (multithread.terminate) throw NgException ("Meshing stopped"); } faceindex = 0; mesh.CalcSurfacesOfNode(); return; } static int timer = NgProfiler::CreateTimer ("EdgeSwapping 2D"); NgProfiler::RegionTimer reg1 (timer); static int timerstart = NgProfiler::CreateTimer ("EdgeSwapping 2D start"); NgProfiler::StartTimer (timerstart); Array seia; mesh.GetSurfaceElementsOfFace (faceindex, seia); for (int i = 0; i < seia.Size(); i++) if (mesh[seia[i]].GetNP() != 3) { GenericImprove (mesh); return; } int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); Array neighbors(mesh.GetNSE()); INDEX_2_HASHTABLE other(seia.Size() + 2); Array swapped(mesh.GetNSE()); Array pdef(mesh.GetNP()); Array pangle(mesh.GetNP()); // int e; // double d; // Vec3d nv1, nv2; // double loch(-1); static const double minangle[] = { 0, 1.481, 2.565, 3.627, 4.683, 5.736, 7, 9 }; for (int i = 0; i < seia.Size(); i++) { const Element2d & sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) pangle[sel[j]] = 0.0; } // pangle = 0; for (int i = 0; i < seia.Size(); i++) { const Element2d & sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { POINTTYPE typ = mesh[sel[j]].Type(); if (typ == FIXEDPOINT || typ == EDGEPOINT) { pangle[sel[j]] += Angle (mesh[sel[(j+1)%3]] - mesh[sel[j]], mesh[sel[(j+2)%3]] - mesh[sel[j]]); } } } // for (PointIndex pi = PointIndex::BASE; // pi < mesh.GetNP()+PointIndex::BASE; pi++) // pdef = 0; for (int i = 0; i < seia.Size(); i++) { const Element2d & sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { PointIndex pi = sel[j]; if (mesh[pi].Type() == INNERPOINT || mesh[pi].Type() == SURFACEPOINT) pdef[pi] = -6; else for (int j = 0; j < 8; j++) if (pangle[pi] >= minangle[j]) pdef[pi] = -1-j; } } for (int i = 0; i < seia.Size(); i++) { const Element2d & sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) pdef[sel[j]]++; } for (int i = 0; i < seia.Size(); i++) { for (int j = 0; j < 3; j++) { neighbors[seia[i]].SetNr (j, -1); neighbors[seia[i]].SetOrientation (j, 0); } } /* Array normals(mesh.GetNP()); for (i = 1; i <= mesh.GetNSE(); i++) { Element2d & hel = mesh.SurfaceElement(i); if (hel.GetIndex() == faceindex) for (k = 1; k <= 3; k++) { int pi = hel.PNum(k); SelectSurfaceOfPoint (mesh.Point(pi), hel.GeomInfoPi(k)); int surfi = mesh.GetFaceDescriptor(faceindex).SurfNr(); GetNormalVector (surfi, mesh.Point(pi), normals.Elem(pi)); normals.Elem(pi) /= normals.Elem(pi).Length(); } } */ for (int i = 0; i < seia.Size(); i++) { const Element2d & sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { PointIndex pi1 = sel.PNumMod(j+2); PointIndex pi2 = sel.PNumMod(j+3); // double loch = mesh.GetH(mesh[pi1]); INDEX_2 edge(pi1, pi2); edge.Sort(); if (mesh.IsSegment (pi1, pi2)) continue; /* if (segments.Used (edge)) continue; */ INDEX_2 ii2 (pi1, pi2); if (other.Used (ii2)) { // INDEX_2 i2s(ii2); // i2s.Sort(); int i2 = other.Get(ii2).tnr; int j2 = other.Get(ii2).sidenr; neighbors[seia[i]].SetNr (j, i2); neighbors[seia[i]].SetOrientation (j, j2); neighbors[i2].SetNr (j2, seia[i]); neighbors[i2].SetOrientation (j2, j); } else { other.Set (INDEX_2 (pi2, pi1), trionedge (seia[i], j)); } } } for (int i = 0; i < seia.Size(); i++) swapped[seia[i]] = 0; NgProfiler::StopTimer (timerstart); int t = 4; int done = 0; while (!done && t >= 2) { for (int i = 0; i < seia.Size(); i++) { SurfaceElementIndex t1 = seia[i]; if (mesh[t1].IsDeleted()) continue; if (mesh[t1].GetIndex() != faceindex) continue; if (multithread.terminate) throw NgException ("Meshing stopped"); for (int o1 = 0; o1 < 3; o1++) { bool should; SurfaceElementIndex t2 = neighbors[t1].GetNr (o1); int o2 = neighbors[t1].GetOrientation (o1); if (t2 == -1) continue; if (swapped[t1] || swapped[t2]) continue; PointIndex pi1 = mesh[t1].PNumMod(o1+1+1); PointIndex pi2 = mesh[t1].PNumMod(o1+1+2); PointIndex pi3 = mesh[t1].PNumMod(o1+1); PointIndex pi4 = mesh[t2].PNumMod(o2+1); PointGeomInfo gi1 = mesh[t1].GeomInfoPiMod(o1+1+1); PointGeomInfo gi2 = mesh[t1].GeomInfoPiMod(o1+1+2); PointGeomInfo gi3 = mesh[t1].GeomInfoPiMod(o1+1); PointGeomInfo gi4 = mesh[t2].GeomInfoPiMod(o2+1); bool allowswap = true; Vec<3> auxvec1 = mesh[pi3]-mesh[pi4]; Vec<3> auxvec2 = mesh[pi1]-mesh[pi4]; allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4; if(!allowswap) continue; // normal of new Vec<3> nv1 = Cross (auxvec1, auxvec2); auxvec1 = mesh.Point(pi4)-mesh.Point(pi3); auxvec2 = mesh.Point(pi2)-mesh.Point(pi3); allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4; if(!allowswap) continue; Vec<3> nv2 = Cross (auxvec1, auxvec2); // normals of original Vec<3> nv3 = Cross (mesh[pi1]-mesh[pi4], mesh[pi2]-mesh[pi4]); Vec<3> nv4 = Cross (mesh[pi2]-mesh[pi3], mesh[pi1]-mesh[pi3]); nv3 *= -1; nv4 *= -1; nv3.Normalize(); nv4.Normalize(); nv1.Normalize(); nv2.Normalize(); Vec<3> nvp3, nvp4; SelectSurfaceOfPoint (mesh.Point(pi3), gi3); GetNormalVector (surfnr, mesh.Point(pi3), gi3, nvp3); nvp3.Normalize(); SelectSurfaceOfPoint (mesh.Point(pi4), gi4); GetNormalVector (surfnr, mesh.Point(pi4), gi4, nvp4); nvp4.Normalize(); double critval = cos (M_PI / 6); // 30 degree allowswap = allowswap && (nv1 * nvp3 > critval) && (nv1 * nvp4 > critval) && (nv2 * nvp3 > critval) && (nv2 * nvp4 > critval) && (nvp3 * nv3 > critval) && (nvp4 * nv4 > critval); double horder = Dist (mesh.Point(pi1), mesh.Point(pi2)); if ( // nv1 * nv2 >= 0 && nv1.Length() > 1e-3 * horder * horder && nv2.Length() > 1e-3 * horder * horder && allowswap ) { if (!usemetric) { int e = pdef[pi1] + pdef[pi2] - pdef[pi3] - pdef[pi4]; double d = Dist2 (mesh.Point(pi1), mesh.Point(pi2)) - Dist2 (mesh.Point(pi3), mesh.Point(pi4)); should = e >= t && (e > 2 || d > 0); } else { double loch = mesh.GetH(mesh[pi1]); should = CalcTriangleBadness (mesh.Point(pi4), mesh.Point(pi3), mesh.Point(pi1), metricweight, loch) + CalcTriangleBadness (mesh.Point(pi3), mesh.Point(pi4), mesh.Point(pi2), metricweight, loch) < CalcTriangleBadness (mesh.Point(pi1), mesh.Point(pi2), mesh.Point(pi3), metricweight, loch) + CalcTriangleBadness (mesh.Point(pi2), mesh.Point(pi1), mesh.Point(pi4), metricweight, loch); } if (allowswap) { Element2d sw1 (pi4, pi3, pi1); Element2d sw2 (pi3, pi4, pi2); int legal1 = mesh.LegalTrig (mesh.SurfaceElement (t1)) + mesh.LegalTrig (mesh.SurfaceElement (t2)); int legal2 = mesh.LegalTrig (sw1) + mesh.LegalTrig (sw2); if (legal1 < legal2) should = 1; if (legal2 < legal1) should = 0; } if (should) { // do swapping ! done = 1; mesh[t1].PNum(1) = pi1; mesh[t1].PNum(2) = pi4; mesh[t1].PNum(3) = pi3; mesh[t2].PNum(1) = pi2; mesh[t2].PNum(2) = pi3; mesh[t2].PNum(3) = pi4; mesh[t1].GeomInfoPi(1) = gi1; mesh[t1].GeomInfoPi(2) = gi4; mesh[t1].GeomInfoPi(3) = gi3; mesh[t2].GeomInfoPi(1) = gi2; mesh[t2].GeomInfoPi(2) = gi3; mesh[t2].GeomInfoPi(3) = gi4; pdef[pi1]--; pdef[pi2]--; pdef[pi3]++; pdef[pi4]++; swapped[t1] = 1; swapped[t2] = 1; } } } } t--; } mesh.SetNextTimeStamp(); } void MeshOptimize2d :: CombineImprove (Mesh & mesh) { if (!faceindex) { PrintMessage (3, "Combine improve"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) { CombineImprove (mesh); if (multithread.terminate) throw NgException ("Meshing stopped"); } faceindex = 0; return; } static int timer = NgProfiler::CreateTimer ("Combineimprove 2D"); NgProfiler::RegionTimer reg (timer); static int timerstart = NgProfiler::CreateTimer ("Combineimprove 2D start"); NgProfiler::StartTimer (timerstart); static int timerstart1 = NgProfiler::CreateTimer ("Combineimprove 2D start1"); NgProfiler::StartTimer (timerstart1); // int i, j, k, l; // PointIndex pi; // SurfaceElementIndex sei; Array seia; mesh.GetSurfaceElementsOfFace (faceindex, seia); for (int i = 0; i < seia.Size(); i++) if (mesh[seia[i]].GetNP() != 3) return; int surfnr = 0; if (faceindex) surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); // PointIndex pi1, pi2; // MeshPoint p1, p2, pnew; double bad1, bad2; Vec<3> nv; int np = mesh.GetNP(); //int nse = mesh.GetNSE(); TABLE elementsonnode(np); Array hasonepi, hasbothpi; for (int i = 0; i < seia.Size(); i++) { Element2d & el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) elementsonnode.Add (el[j], seia[i]); } Array fixed(np); fixed = false; NgProfiler::StopTimer (timerstart1); /* for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) { INDEX_2 i2(mesh[si][0], mesh[si][1]); fixed[i2.I1()] = true; fixed[i2.I2()] = true; } */ for (int i = 0; i < seia.Size(); i++) { Element2d & sel = mesh[seia[i]]; for (int j = 0; j < sel.GetNP(); j++) { PointIndex pi1 = sel.PNumMod(j+2); PointIndex pi2 = sel.PNumMod(j+3); if (mesh.IsSegment (pi1, pi2)) { fixed[pi1] = true; fixed[pi2] = true; } } } for(int i = 0; i < mesh.LockedPoints().Size(); i++) fixed[mesh.LockedPoints()[i]] = true; Array,PointIndex::BASE> normals(np); for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) { if (elementsonnode[pi].Size()) { Element2d & hel = mesh[elementsonnode[pi][0]]; for (int k = 0; k < 3; k++) if (hel[k] == pi) { SelectSurfaceOfPoint (mesh[pi], hel.GeomInfoPi(k+1)); GetNormalVector (surfnr, mesh[pi], hel.GeomInfoPi(k+1), normals[pi]); break; } } } NgProfiler::StopTimer (timerstart); for (int i = 0; i < seia.Size(); i++) { SurfaceElementIndex sei = seia[i]; Element2d & elem = mesh[sei]; if (elem.IsDeleted()) continue; for (int j = 0; j < 3; j++) { PointIndex pi1 = elem[j]; PointIndex pi2 = elem[(j+1) % 3]; if (pi1 < PointIndex::BASE || pi2 < PointIndex::BASE) continue; /* INDEX_2 i2(pi1, pi2); i2.Sort(); if (segmentht.Used(i2)) continue; */ bool debugflag = 0; if (debugflag) { (*testout) << "Combineimprove, face = " << faceindex << "pi1 = " << pi1 << " pi2 = " << pi2 << endl; } /* // save version: if (fixed.Get(pi1) || fixed.Get(pi2)) continue; if (pi2 < pi1) swap (pi1, pi2); */ // more general if (fixed[pi2]) Swap (pi1, pi2); if (fixed[pi2]) continue; double loch = mesh.GetH (mesh[pi1]); INDEX_2 si2 (pi1, pi2); si2.Sort(); /* if (edgetested.Used (si2)) continue; edgetested.Set (si2, 1); */ hasonepi.SetSize(0); hasbothpi.SetSize(0); for (int k = 0; k < elementsonnode[pi1].Size(); k++) { const Element2d & el2 = mesh[elementsonnode[pi1][k]]; if (el2.IsDeleted()) continue; if (el2[0] == pi2 || el2[1] == pi2 || el2[2] == pi2) { hasbothpi.Append (elementsonnode[pi1][k]); nv = Cross (Vec3d (mesh[el2[0]], mesh[el2[1]]), Vec3d (mesh[el2[0]], mesh[el2[2]])); } else { hasonepi.Append (elementsonnode[pi1][k]); } } Element2d & hel = mesh[hasbothpi[0]]; for (int k = 0; k < 3; k++) if (hel[k] == pi1) { SelectSurfaceOfPoint (mesh[pi1], hel.GeomInfoPi(k+1)); GetNormalVector (surfnr, mesh[pi1], hel.GeomInfoPi(k+1), nv); break; } // nv = normals.Get(pi1); for (int k = 0; k < elementsonnode[pi2].Size(); k++) { const Element2d & el2 = mesh[elementsonnode[pi2][k]]; if (el2.IsDeleted()) continue; if (el2[0] == pi1 || el2[1] == pi1 || el2[2] == pi1) ; else hasonepi.Append (elementsonnode[pi2][k]); } bad1 = 0; int illegal1 = 0, illegal2 = 0; for (int k = 0; k < hasonepi.Size(); k++) { const Element2d & el = mesh[hasonepi[k]]; bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch); illegal1 += 1-mesh.LegalTrig(el); } for (int k = 0; k < hasbothpi.Size(); k++) { const Element2d & el = mesh[hasbothpi[k]]; bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch); illegal1 += 1-mesh.LegalTrig(el); } bad1 /= (hasonepi.Size()+hasbothpi.Size()); MeshPoint p1 = mesh[pi1]; MeshPoint p2 = mesh[pi2]; MeshPoint pnew = p1; mesh[pi1] = pnew; mesh[pi2] = pnew; bad2 = 0; for (int k = 0; k < hasonepi.Size(); k++) { Element2d & el = mesh[hasonepi[k]]; double err = CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch); bad2 += err; Vec<3> hnv = Cross (Vec3d (mesh[el[0]], mesh[el[1]]), Vec3d (mesh[el[0]], mesh[el[2]])); if (hnv * nv < 0) bad2 += 1e10; for (int l = 0; l < 3; l++) if ( (normals[el[l]] * nv) < 0.5) bad2 += 1e10; illegal2 += 1-mesh.LegalTrig(el); } bad2 /= hasonepi.Size(); mesh[pi1] = p1; mesh[pi2] = p2; if (debugflag) { (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl; } bool should = (bad2 < bad1 && bad2 < 1e4); if (bad2 < 1e4) { if (illegal1 > illegal2) should = 1; if (illegal2 > illegal1) should = 0; } if (should) { /* (*testout) << "combine !" << endl; (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl; (*testout) << "illegal1 = " << illegal1 << ", illegal2 = " << illegal2 << endl; (*testout) << "loch = " << loch << endl; */ mesh[pi1] = pnew; PointGeomInfo gi; // bool gi_set(false); Element2d *el1p(NULL); int l = 0; while(mesh[elementsonnode[pi1][l]].IsDeleted() && lGetNP(); l++) if ((*el1p)[l] == pi1) { gi = el1p->GeomInfoPi (l+1); // gi_set = true; } // (*testout) << "Connect point " << pi2 << " to " << pi1 << "\n"; for (int k = 0; k < elementsonnode[pi2].Size(); k++) { Element2d & el = mesh[elementsonnode[pi2][k]]; if(el.IsDeleted()) continue; elementsonnode.Add (pi1, elementsonnode[pi2][k]); bool haspi1 = 0; for (l = 0; l < el.GetNP(); l++) if (el[l] == pi1) haspi1 = 1; if (haspi1) continue; for (int l = 0; l < el.GetNP(); l++) { if (el[l] == pi2) { el[l] = pi1; el.GeomInfoPi (l+1) = gi; } fixed[el[l]] = true; } } /* for (k = 0; k < hasbothpi.Size(); k++) { cout << mesh[hasbothpi[k]] << endl; for (l = 0; l < 3; l++) cout << mesh[mesh[hasbothpi[k]][l]] << " "; cout << endl; } */ for (int k = 0; k < hasbothpi.Size(); k++) { mesh[hasbothpi[k]].Delete(); /* for (l = 0; l < 4; l++) mesh[hasbothpi[k]][l] = PointIndex::BASE-1; */ } } } } // mesh.Compress(); mesh.SetNextTimeStamp(); } void MeshOptimize2d :: CheckMeshApproximation (Mesh & mesh) { // Check angles between elements and normals at corners /* int i, j; int ne = mesh.GetNSE(); int surfnr; Vec3d n, ng; Array ngs(3); (*mycout) << "Check Surface Approximation" << endl; (*testout) << "Check Surface Approximation" << endl; for (i = 1; i <= ne; i++) { const Element2d & el = mesh.SurfaceElement(i); surfnr = mesh.GetFaceDescriptor (el.GetIndex()).SurfNr(); Vec3d n = Cross (mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(2)), mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(3))); n /= n.Length(); for (j = 1; j <= el.GetNP(); j++) { SelectSurfaceOfPoint (mesh.Point(el.PNum(j)), el.GeomInfoPi(j)); GetNormalVector (surfnr, mesh.Point(el.PNum(j)), ng); ng /= ng.Length(); ngs.Elem(j) = ng; double angle = (180.0 / M_PI) * Angle (n, ng); if (angle > 60) { (*testout) << "el " << i << " node " << el.PNum(j) << "has angle = " << angle << endl; } } for (j = 1; j <= 3; j++) { double angle = (180.0 / M_PI) * Angle (ngs.Get(j), ngs.Get(j%3+1)); if (angle > 60) { (*testout) << "el " << i << " node-node " << ngs.Get(j) << " - " << ngs.Get(j%3+1) << " has angle = " << angle << endl; } } } */ } } netgen-6.2.1905/libsrc/meshing/netrule3.cpp0000644000175000017500000005764413504650527017176 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { vnetrule :: vnetrule () { name = new char[1]; name[0] = char(0); quality = 0; } vnetrule :: ~vnetrule () { // if (strlen(name)) delete [] name; for (int i = 1; i <= freefaces.Size(); i++) delete freefaces.Elem(i); for (int i = 1; i <= freesets.Size(); i++) delete freesets.Elem(i); for (int i = 1; i <= freeedges.Size(); i++) delete freeedges.Elem(i); for (int i = 1; i <= freefaceinequ.Size(); i++) delete freefaceinequ.Elem(i); delete oldutofreezone; delete oldutofreezonelimit; } int vnetrule :: TestFlag (char flag) const { for (int i = 1; i <= flags.Size(); i++) if (flags.Get(i) == flag) return 1; return 0; } void vnetrule :: SetFreeZoneTransformation (const Vector & allp, int tolclass) { int i, j; // double nx, ny, nz, v1x, v1y, v1z, v2x, v2y, v2z; double nl; const threeint * ti; int fs; double lam1 = 1.0/(2 * tolclass - 1); double lam2 = 1-lam1; transfreezone.SetSize (freezone.Size()); int np = points.Size(); int nfp = freezone.Size(); Vector vp(np), vfp1(nfp), vfp2(nfp); for (i = 1; i <= 3; i++) { for (j = 1; j <= np; j++) vp(j-1) = allp(i+3*j-3-1); oldutofreezone->Mult (vp, vfp1); oldutofreezonelimit->Mult (vp, vfp2); vfp1 *= lam1; vfp1.Add (lam2, vfp2); for (j = 1; j <= nfp; j++) transfreezone.Elem(j).X(i) = vfp1(j-1); } // MARK(setfz2); fzbox.SetPoint (transfreezone.Elem(1)); for (i = 2; i <= freezone.Size(); i++) fzbox.AddPoint (transfreezone.Elem(i)); // MARK(setfz3); for (fs = 1; fs <= freesets.Size(); fs++) { Array & freesetfaces = *freefaces.Get(fs); DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); for (i = 1; i <= freesetfaces.Size(); i++) { ti = &freesetfaces.Get(i); const Point3d & p1 = transfreezone.Get(ti->i1); const Point3d & p2 = transfreezone.Get(ti->i2); const Point3d & p3 = transfreezone.Get(ti->i3); Vec3d v1(p1, p2); Vec3d v2(p1, p3); Vec3d n; Cross (v1, v2, n); nl = n.Length(); if (nl < 1e-10) { freesetinequ.Set(1, 1, 0); freesetinequ.Set(1, 2, 0); freesetinequ.Set(1, 3, 0); freesetinequ.Set(1, 4, -1); } else { // n /= nl; freesetinequ.Set(i, 1, n.X()/nl); freesetinequ.Set(i, 2, n.Y()/nl); freesetinequ.Set(i, 3, n.Z()/nl); freesetinequ.Set(i, 4, -(p1.X() * n.X() + p1.Y() * n.Y() + p1.Z() * n.Z()) / nl); } } } /* (*testout) << "Transformed freezone: " << endl; for (i = 1; i <= transfreezone.Size(); i++) (*testout) << transfreezone.Get(i) << " "; (*testout) << endl; */ } int vnetrule :: ConvexFreeZone () const { int i, j, k, fs; // (*mycout) << "Convex free zone...\n"; int ret1=1; // int ret2=1; for (fs = 1; fs <= freesets.Size(); fs++) { const DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); // const Array & freeset = *freesets.Get(fs); const Array & freesetedges = *freeedges.Get(fs); // const Array & freesetfaces = *freefaces.Get(fs); for (i = 1; i <= freesetedges.Size(); i++) { j = freesetedges.Get(i).i1; //triangle j with opposite point k k = freesetedges.Get(i).i2; if ( freesetinequ.Get(j, 1) * transfreezone.Get(k).X() + freesetinequ.Get(j, 2) * transfreezone.Get(k).Y() + freesetinequ.Get(j, 3) * transfreezone.Get(k).Z() + freesetinequ.Get(j, 4) > 0 ) { ret1=0; } } } return ret1; } int vnetrule :: IsInFreeZone (const Point3d & p) const { int i, fs; char inthis; for (fs = 1; fs <= freesets.Size(); fs++) { inthis = 1; Array & freesetfaces = *freefaces.Get(fs); DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); for (i = 1; i <= freesetfaces.Size() && inthis; i++) { if (freesetinequ.Get(i, 1) * p.X() + freesetinequ.Get(i, 2) * p.Y() + freesetinequ.Get(i, 3) * p.Z() + freesetinequ.Get(i, 4) > 0) inthis = 0; } if (inthis) return 1; } return 0; } int vnetrule :: IsTriangleInFreeZone (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Array & pi, int newone) { int fs; int infreeset, cannot = 0; ArrayMem pfi(3), pfi2(3); // convert from local index to freeset index int i, j; for (i = 1; i <= 3; i++) { pfi.Elem(i) = 0; if (pi.Get(i)) { for (j = 1; j <= freezonepi.Size(); j++) if (freezonepi.Get(j) == pi.Get(i)) pfi.Elem(i) = j; } } for (fs = 1; fs <= freesets.Size(); fs++) { const Array & freeseti = *freesets.Get(fs); for (i = 1; i <= 3; i++) { pfi2.Elem(i) = 0; for (j = 1; j <= freeseti.Size(); j++) if (pfi.Get(i) == freeseti.Get(j)) pfi2.Elem(i) = pfi.Get(i); } infreeset = IsTriangleInFreeSet(p1, p2, p3, fs, pfi2, newone); if (infreeset == 1) return 1; if (infreeset == -1) cannot = -1; } return cannot; } int vnetrule :: IsTriangleInFreeSet (const Point3d & p1, const Point3d & p2, const Point3d & p3, int fs, const Array & pi, int newone) { int i, ii; Vec3d n; int allleft, allright; int hos1, hos2, hos3, os1, os2, os3; double hf, lam1, lam2, f, c1, c2, alpha; double v1n, v2n, h11, h12, h22, dflam1, dflam2; double lam1old, lam2old, fold; double hpx, hpy, hpz, v1x, v1y, v1z, v2x, v2y, v2z; int act1, act2, act3, it; int cntout; Array activefaces; int isin; // MARK(triinfz); Array & freesetfaces = *freefaces.Get(fs); DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); int cnt = 0; for (i = 1; i <= 3; i++) if (pi.Get(i)) cnt++; /* (*testout) << "trig in free set : " << p1 << " - " << p2 << " - " << p3 << endl; (*testout) << "common points: " << cnt << endl; */ if (!newone) cnt = 0; if (cnt == 1) { // MARK(triinfz1); int upi = 0, lpiu = 0; for (i = 1; i <= 3; i++) if (pi.Get(i)) { upi = i; lpiu = pi.Get(i); } Vec3d v1, v2; switch (upi) { case 1: { v1 = p2 - p1; v2 = p3 - p1; break; } case 2: { v1 = p3 - p2; v2 = p1 - p2; break; } case 3: { v1 = p1 - p3; v2 = p2 - p3; break; } } v1 /= v1.Length(); v2 /= v2.Length(); Cross (v1, v2, n); n /= n.Length(); // (*testout) << "Test new: " << endl; for (i = 1; i <= freesetfaces.Size(); i++) { if ( (freesetfaces.Get(i).i1 == lpiu) || (freesetfaces.Get(i).i2 == lpiu) || (freesetfaces.Get(i).i3 == lpiu) ) { // freeface has point Vec3d a (freesetinequ.Get(i, 1), freesetinequ.Get(i, 2), freesetinequ.Get(i, 3)); // if (1 - fabs (a * n) < 1e-8 ) // continue; Vec3d an; Cross (a, n, an); double lan = an.Length(); if (lan < 1e-10) continue; an /= lan; int out1 = (a * v1) > 0; int out2 = (a * v2) > 0; // (*testout) << "out1, out2 = " << out1 << ", " << out2 << endl; if (out1 && out2) return 0; if (!out1 && !out2) continue; // if ( ( (an * v1) < 0) && ( (an * v2) < 0) ) // falsch !!!! // an *= -1; // solve an = lam1 v1 + lam2 v2 double vii11 = v1 * v1; double vii12 = v1 * v2; double vii22 = v2 * v2; double det = vii11 * vii22 - vii12 * vii12; if ( fabs (det) < 1e-10 ) continue; double rs1 = an * v1; double rs2 = an * v2; double lambda1 = rs1 * vii22 - rs2 * vii12; double lambda2 = rs2 * vii11 - rs1 * vii12; if (fabs (lambda1) > fabs (lambda2)) { if (lambda1 < 0) an *= -1; } else { if (lambda2 < 0) an *= -1; } if (lambda1 * lambda2 < 0 && 0) { if (fabs (lambda1) > 1e-14 && fabs (lambda2) > 1e-14) { // (*mycout) << "lambda1 lambda2 < 0" << endl; (*testout) << "lambdai different" << endl; (*testout) << "v1 = " << v1 << endl; (*testout) << "v2 = " << v2 << endl; (*testout) << "n = " << n << endl; (*testout) << "a = " << a << endl; (*testout) << "an = " << an << endl; (*testout) << "a * v1 = " << (a * v1) << endl; (*testout) << "a * v2 = " << (a * v2) << endl; (*testout) << "an * v1 = " << (an * v1) << endl; (*testout) << "an * v2 = " << (an * v2) << endl; (*testout) << "vii = " << vii11 << ", " << vii12 << ", " << vii22 << endl; (*testout) << "lambdai = " << lambda1 << ", " << lambda2 << endl; (*testout) << "rs = " << rs1 << ", " << rs2 << endl; continue; } } if (out1) v1 = an; else v2 = an; } } return 1; /* (*testout) << "overlap trig " << p1 << p2 << p3 << endl; (*testout) << "upi = " << upi << endl; (*testout) << "v1 = " << v1 << " v2 = " << v2 << endl; */ switch (upi) { case 1: { v1 = p2 - p1; v2 = p3 - p1; break; } case 2: { v1 = p3 - p2; v2 = p1 - p2; break; } case 3: { v1 = p1 - p3; v2 = p2 - p3; break; } } v1 /= v1.Length(); v2 /= v2.Length(); Cross (v1, v2, n); n /= n.Length(); // (*testout) << "orig v1, v2 = " << v1 << ", " << v2 << endl; for (i = 1; i <= freesetfaces.Size(); i++) { if ( (freesetfaces.Get(i).i1 == lpiu) || (freesetfaces.Get(i).i2 == lpiu) || (freesetfaces.Get(i).i3 == lpiu) ) { /* (*testout) << "v1, v2, now = " << v1 << ", " << v2 << endl; // freeface has point (*testout) << "freesetface: " << freesetfaces.Get(i).i1 << " " << freesetfaces.Get(i).i2 << " " << freesetfaces.Get(i).i3 << " "; */ Vec3d a (freesetinequ.Get(i, 1), freesetinequ.Get(i, 2), freesetinequ.Get(i, 3)); // (*testout) << "a = " << a << endl; Vec3d an; Cross (a, n, an); double lan = an.Length(); // (*testout) << "an = " << an << endl; if (lan < 1e-10) continue; an /= lan; // (*testout) << "a*v1 = " << (a*v1) << " a*v2 = " << (a*v2) << endl; int out1 = (a * v1) > 0; // int out2 = (a * v2) > 0; // (*testout) << "out1, 2 = " << out1 << ", " << out2 << endl; double vii11 = v1 * v1; double vii12 = v1 * v2; double vii22 = v2 * v2; double det = vii11 * vii22 - vii12 * vii12; if ( fabs (det) < 1e-10 ) continue; double rs1 = an * v1; double rs2 = an * v2; double lambda1 = rs1 * vii22 - rs2 * vii12; double lambda2 = rs2 * vii11 - rs1 * vii12; // (*testout) << "lambda1, lambda2 = " << lambda1 << ", " << lambda2 << endl; if (fabs (lambda1) > fabs (lambda2)) { if (lambda1 < 0) an *= -1; } else { if (lambda2 < 0) an *= -1; } if (lambda1 * lambda2 < 0) { if (fabs (lambda1) > 1e-14 && fabs (lambda2) > 1e-14) { // (*mycout) << "lambda1 lambda2 < 0" << endl; (*testout) << "lambdai different" << endl; (*testout) << "v1 = " << v1 << endl; (*testout) << "v2 = " << v2 << endl; (*testout) << "n = " << n << endl; (*testout) << "a = " << a << endl; (*testout) << "an = " << an << endl; (*testout) << "a * v1 = " << (a * v1) << endl; (*testout) << "a * v2 = " << (a * v2) << endl; (*testout) << "an * v1 = " << (an * v1) << endl; (*testout) << "an * v2 = " << (an * v2) << endl; (*testout) << "vii = " << vii11 << ", " << vii12 << ", " << vii22 << endl; (*testout) << "lambdai = " << lambda1 << ", " << lambda2 << endl; (*testout) << "rs = " << rs1 << ", " << rs2 << endl; continue; } } if (out1) v1 = an; else v2 = an; } } return 1; } if (cnt == 2) { // (*testout) << "tripoitns: " << p1 << " " << p2 << " " << p3 << endl; // MARK(triinfz2); int pi1 = 0, pi2 = 0, pi3 = 0; Vec3d a1, a2; // outer normals Vec3d trivec; // vector from common edge to third point of triangle for (i = 1; i <= 3; i++) if (pi.Get(i)) { pi2 = pi1; pi1 = pi.Get(i); } else pi3 = i; switch (pi3) { case 1: trivec = (p1 - p2); break; case 2: trivec = (p2 - p3); break; case 3: trivec = (p3 - p2); break; } Array lpi(freezonepi.Size()); for (i = 1; i <= lpi.Size(); i++) lpi.Elem(i) = 0; lpi.Elem(pi1) = 1; lpi.Elem(pi2) = 1; int ff1 = 0, ff2 = 0; for (i = 1; i <= freesetfaces.Size(); i++) { if (lpi.Get(freesetfaces.Get(i).i1) + lpi.Get(freesetfaces.Get(i).i2) + lpi.Get(freesetfaces.Get(i).i3) == 2) { ff2 = ff1; ff1 = i; } } if (ff2 == 0) return 1; a1 = Vec3d (freesetinequ.Get(ff1, 1), freesetinequ.Get(ff1, 2), freesetinequ.Get(ff1, 3)); a2 = Vec3d (freesetinequ.Get(ff2, 1), freesetinequ.Get(ff2, 2), freesetinequ.Get(ff2, 3)); if ( ( (a1 * trivec) > 0) || ( (a2 * trivec) > 0)) return 0; return 1; } if (cnt == 3) { // MARK(triinfz3); Array lpi(freezonepi.Size()); for (i = 1; i <= lpi.Size(); i++) lpi.Elem(i) = 0; for (i = 1; i <= 3; i++) lpi.Elem(pi.Get(i)) = 1; for (i = 1; i <= freesetfaces.Size(); i++) { if (lpi.Get(freesetfaces.Get(i).i1) + lpi.Get(freesetfaces.Get(i).i2) + lpi.Get(freesetfaces.Get(i).i3) == 3) { return 0; } } return 1; } // MARK(triinfz0); os1 = os2 = os3 = 0; activefaces.SetSize(0); // is point inside ? for (i = 1; i <= freesetfaces.Size(); i++) { hos1 = freesetinequ.Get(i, 1) * p1.X() + freesetinequ.Get(i, 2) * p1.Y() + freesetinequ.Get(i, 3) * p1.Z() + freesetinequ.Get(i, 4) > -1E-5; hos2 = freesetinequ.Get(i, 1) * p2.X() + freesetinequ.Get(i, 2) * p2.Y() + freesetinequ.Get(i, 3) * p2.Z() + freesetinequ.Get(i, 4) > -1E-5; hos3 = freesetinequ.Get(i, 1) * p3.X() + freesetinequ.Get(i, 2) * p3.Y() + freesetinequ.Get(i, 3) * p3.Z() + freesetinequ.Get(i, 4) > -1E-5; if (hos1 && hos2 && hos3) return 0; if (hos1) os1 = 1; if (hos2) os2 = 1; if (hos3) os3 = 1; if (hos1 || hos2 || hos3) activefaces.Append (i); } if (!os1 || !os2 || !os3) return 1; v1x = p2.X() - p1.X(); v1y = p2.Y() - p1.Y(); v1z = p2.Z() - p1.Z(); v2x = p3.X() - p1.X(); v2y = p3.Y() - p1.Y(); v2z = p3.Z() - p1.Z(); n.X() = v1y * v2z - v1z * v2y; n.Y() = v1z * v2x - v1x * v2z; n.Z() = v1x * v2y - v1y * v2x; n /= n.Length(); allleft = allright = 1; for (i = 1; i <= transfreezone.Size() && (allleft || allright); i++) { const Point3d & p = transfreezone.Get(i); float scal = (p.X() - p1.X()) * n.X() + (p.Y() - p1.Y()) * n.Y() + (p.Z() - p1.Z()) * n.Z(); if ( scal > 1E-8 ) allleft = 0; if ( scal < -1E-8 ) allright = 0; } if (allleft || allright) return 0; lam1old = lam2old = lam1 = lam2 = 1.0 / 3.0; // testout << endl << endl << "Start minimizing" << endl; it = 0; int minit; minit = 1000; fold = 1E10; while (1) { it++; if (it > 1000) return -1; if (lam1 < 0) lam1 = 0; if (lam2 < 0) lam2 = 0; if (lam1 + lam2 > 1) lam1 = 1 - lam2; if (it > minit) { (*testout) << "it = " << it << endl; (*testout) << "lam1/2 = " << lam1 << " " << lam2 << endl; } hpx = p1.X() + lam1 * v1x + lam2 * v2x; hpy = p1.Y() + lam1 * v1y + lam2 * v2y; hpz = p1.Z() + lam1 * v1z + lam2 * v2z; f = 0; h11 = h12 = h22 = dflam1 = dflam2 = 0; cntout = 0; isin = 1; for (i = 1; i <= activefaces.Size(); i++) { ii = activefaces.Get(i); hf = freesetinequ.Get(ii, 1) * hpx + freesetinequ.Get(ii, 2) * hpy + freesetinequ.Get(ii, 3) * hpz + freesetinequ.Get(ii, 4); if (hf > -1E-7) isin = 0; hf += 1E-4; if (hf > 0) { f += hf * hf; v1n = freesetinequ.Get(ii, 1) * v1x + freesetinequ.Get(ii, 2) * v1y + freesetinequ.Get(ii, 3) * v1z; v2n = freesetinequ.Get(ii, 1) * v2x + freesetinequ.Get(ii, 2) * v2y + freesetinequ.Get(ii, 3) * v2z; h11 += 2 * v1n * v1n; h12 += 2 * v1n * v2n; h22 += 2 * v2n * v2n; dflam1 += 2 * hf * v1n; dflam2 += 2 * hf * v2n; cntout++; } } if (isin) return 1; if (it > minit) { (*testout) << "f = " << f << " dfdlam = " << dflam1 << " " << dflam2 << endl; (*testout) << "h = " << h11 << " " << h12 << " " << h22 << endl; (*testout) << "active: " << cntout << endl; (*testout) << "lam1-lam1old = " << (lam1 - lam1old) << endl; (*testout) << "lam2-lam2old = " << (lam2 - lam2old) << endl; } if (f >= fold) { lam1 = 0.100000000000000 * lam1 + 0.9000000000000000 * lam1old; lam2 = 0.100000000000000 * lam2 + 0.9000000000000000 * lam2old; } else { lam1old = lam1; lam2old = lam2; fold = f; if (f < 1E-9) return 1; h11 += 1E-10; h22 += 1E-10; c1 = - ( h22 * dflam1 - h12 * dflam2) / (h11 * h22 - h12 * h12); c2 = - (-h12 * dflam1 + h11 * dflam2) / (h11 * h22 - h12 * h12); alpha = 1; if (it > minit) (*testout) << "c1/2 = " << c1 << " " << c2 << endl; act1 = lam1 <= 1E-6 && c1 <= 0; act2 = lam2 <= 1E-6 && c2 <= 0; act3 = lam1 + lam2 >= 1 - 1E-6 && c1 + c2 >= 0; if (it > minit) (*testout) << "act1,2,3 = " << act1 << act2 << act3 << endl; if ( (act1 && act2) || (act1 && act3) || (act2 && act3) ) return 0; if (act1) { c1 = 0; c2 = - dflam2 / h22; } if (act2) { c1 = - dflam1 / h11; c2 = 0; } if (act3) { c1 = - (dflam1 - dflam2) / (h11 + h22 - 2 * h12); c2 = -c1; } if (it > minit) (*testout) << "c1/2 now = " << c1 << " " << c2 << endl; if (f > 100 * sqrt (sqr (c1) + sqr (c2))) return 0; if (lam1 + alpha * c1 < 0 && !act1) alpha = -lam1 / c1; if (lam2 + alpha * c2 < 0 && !act2) alpha = -lam2 / c2; if (lam1 + lam2 + alpha * (c1 + c2) > 1 && !act3) alpha = (1 - lam1 - lam2) / (c1 + c2); if (it > minit) (*testout) << "alpha = " << alpha << endl; lam1 += alpha * c1; lam2 += alpha * c2; } } } int vnetrule :: IsQuadInFreeZone (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, const Array & pi, int newone) { int fs; int infreeset, cannot = 0; ArrayMem pfi(4), pfi2(4); // convert from local index to freeset index int i, j; for (i = 1; i <= 4; i++) { pfi.Elem(i) = 0; if (pi.Get(i)) { for (j = 1; j <= freezonepi.Size(); j++) if (freezonepi.Get(j) == pi.Get(i)) pfi.Elem(i) = j; } } for (fs = 1; fs <= freesets.Size(); fs++) { const Array & freeseti = *freesets.Get(fs); for (i = 1; i <= 4; i++) { pfi2.Elem(i) = 0; for (j = 1; j <= freeseti.Size(); j++) if (pfi.Get(i) == freeseti.Get(j)) pfi2.Elem(i) = pfi.Get(i); } infreeset = IsQuadInFreeSet(p1, p2, p3, p4, fs, pfi2, newone); if (infreeset == 1) return 1; if (infreeset == -1) cannot = -1; } return cannot; } int vnetrule :: IsQuadInFreeSet (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, int fs, const Array & pi, int newone) { int i; int cnt = 0; for (i = 1; i <= 4; i++) if (pi.Get(i)) cnt++; /* (*testout) << "test quad in freeset: " << p1 << " - " << p2 << " - " << p3 << " - " << p4 << endl; (*testout) << "pi = "; for (i = 1; i <= pi.Size(); i++) (*testout) << pi.Get(i) << " "; (*testout) << endl; (*testout) << "cnt = " << cnt << endl; */ if (cnt == 4) { return 1; } if (cnt == 3) { return 1; } ArrayMem pi3(3); int res; pi3.Elem(1) = pi.Get(1); pi3.Elem(2) = pi.Get(2); pi3.Elem(3) = pi.Get(3); res = IsTriangleInFreeSet (p1, p2, p3, fs, pi3, newone); if (res) return res; pi3.Elem(1) = pi.Get(2); pi3.Elem(2) = pi.Get(3); pi3.Elem(3) = pi.Get(4); res = IsTriangleInFreeSet (p2, p3, p4, fs, pi3, newone); if (res) return res; pi3.Elem(1) = pi.Get(3); pi3.Elem(2) = pi.Get(4); pi3.Elem(3) = pi.Get(1); res = IsTriangleInFreeSet (p3, p4, p1, fs, pi3, newone); if (res) return res; pi3.Elem(1) = pi.Get(4); pi3.Elem(2) = pi.Get(1); pi3.Elem(3) = pi.Get(2); res = IsTriangleInFreeSet (p4, p1, p2, fs, pi3, newone); return res; } float vnetrule :: CalcPointDist (int pi, const Point3d & p) const { float dx = p.X() - points.Get(pi).X(); float dy = p.Y() - points.Get(pi).Y(); float dz = p.Z() - points.Get(pi).Z(); // const threefloat * tf = &tolerances.Get(pi); // return tf->f1 * dx * dx + tf->f2 * dx * dy + tf->f3 * dy * dy; return tolerances.Get(pi) * (dx * dx + dy * dy + dz * dz); } int vnetrule :: TestOk () const { Array cntpused(points.Size()); Array edge1, edge2; Array delf(faces.Size()); int i, j, k; int pi1, pi2; int found; for (i = 1; i <= cntpused.Size(); i++) cntpused.Elem(i) = 0; for (i = 1; i <= faces.Size(); i++) delf.Elem(i) = 0; for (i = 1; i <= delfaces.Size(); i++) delf.Elem(delfaces.Get(i)) = 1; for (i = 1; i <= faces.Size(); i++) if (delf.Get(i) || i > noldf) for (j = 1; j <= faces.Get(i).GetNP(); j++) cntpused.Elem(faces.Get(i).PNum(j))++; for (i = 1; i <= cntpused.Size(); i++) if (cntpused.Get(i) > 0 && cntpused.Get(i) < 2) { return 0; } // (*testout) << endl; for (i = 1; i <= faces.Size(); i++) { // (*testout) << "face " << i << endl; for (j = 1; j <= faces.Get(i).GetNP(); j++) { pi1 = 0; pi2 = 0; if (delf.Get(i)) { pi1 = faces.Get(i).PNumMod(j); pi2 = faces.Get(i).PNumMod(j+1); } if (i > noldf) { pi1 = faces.Get(i).PNumMod(j+1); pi2 = faces.Get(i).PNumMod(j); } found = 0; if (pi1) { for (k = 1; k <= edge1.Size(); k++) if (edge1.Get(k) == pi1 && edge2.Get(k) == pi2) { found = 1; edge1.DeleteElement(k); edge2.DeleteElement(k); k--; // (*testout) << "Del edge " << pi1 << "-" << pi2 << endl; } if (!found) { edge1.Append (pi2); edge2.Append (pi1); // (*testout) << "Add edge " << pi1 << "-" << pi2 << endl; } } } } if (edge1.Size() > 0) { return 0; } /* cntpused.SetSize(freezone.Size()); for (i = 1; i <= cntpused.Size(); i++) cntpused[i] = 0; for (i = 1; i <= freefaces.Size(); i++) { cntpused[freefaces[i].i1]++; cntpused[freefaces[i].i2]++; cntpused[freefaces[i].i3]++; } for (i = 1; i <= cntpused.Size(); i++) if (cntpused[i] < 3) { (*mycout) << "Fall 3" << endl; return 0; } for (i = 1; i <= freefaces.Size(); i++) { for (j = 1; j <= 3; j++) { if (j == 1) { pi1 = freefaces[i].i1; pi2 = freefaces[i].i2; } if (j == 2) { pi1 = freefaces[i].i2; pi2 = freefaces[i].i3; } if (j == 3) { pi1 = freefaces[i].i3; pi2 = freefaces[i].i1; } found = 0; for (k = 1; k <= edge1.Size(); k++) if (edge1[k] == pi1 && edge2[k] == pi2) { found = 1; edge1.DeleteElement(k); edge2.DeleteElement(k); k--; } if (!found) { edge1.Append (pi2); edge2.Append (pi1); } } } if (edge1.Size() > 0) { (*mycout) << "Fall 4" << endl; return 0; } */ return 1; } int vnetrule :: IsDelFace (int fn) const { int i; for (i = 1; i <= GetNDelF(); i++) if (GetDelFace(i) == fn) return 1; return 0; } } netgen-6.2.1905/libsrc/meshing/curvedelems.cpp0000644000175000017500000037243313504650527017747 0ustar kurtkurt#include #include "meshing.hpp" #include "../general/autodiff.hpp" namespace netgen { // bool rational = true; static void ComputeGaussRule (int n, Array & xi, Array & wi) { xi.SetSize (n); wi.SetSize (n); int m = (n+1)/2; double p1, p2, p3; double pp, z, z1; for (int i = 1; i <= m; i++) { z = cos ( M_PI * (i - 0.25) / (n + 0.5)); while(1) { p1 = 1; p2 = 0; for (int j = 1; j <= n; j++) { p3 = p2; p2 = p1; p1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j; } // p1 is legendre polynomial pp = n * (z*p1-p2) / (z*z - 1); z1 = z; z = z1-p1/pp; if (fabs (z - z1) < 1e-14) break; } xi[i-1] = 0.5 * (1 - z); xi[n-i] = 0.5 * (1 + z); wi[i-1] = wi[n-i] = 1.0 / ( (1 - z * z) * pp * pp); } } // compute edge bubbles up to order n, x \in (-1, 1) template static void CalcEdgeShape (int n, T x, T * shape) { T p1 = x, p2 = -1, p3 = 0; for (int j=2; j<=n; j++) { p3=p2; p2=p1; p1=( (2*j-3) * x * p2 - (j-3) * p3) / j; shape[j-2] = p1; } } template static void CalcEdgeShapeLambda (int n, T x, FUNC func) { T p1(x), p2(-1.0), p3(0.0); for (int j=2; j<=n; j++) { p3=p2; p2=p1; p1=( (2*j-3) * x * p2 - (j-3) * p3) / j; func(j-2, p1); } } template static void CalcEdgeDx (int n, T x, T * dshape) { T p1 = x, p2 = -1, p3 = 0; T p1dx = 1, p2dx = 0, p3dx = 0; for (int j=2; j<=n; j++) { p3=p2; p2=p1; p3dx = p2dx; p2dx = p1dx; p1=( (2*j-3) * x * p2 - (j-3) * p3) / j; p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j; dshape[j-2] = p1dx; } } template static void CalcEdgeShapeDx (int n, T x, T * shape, T * dshape) { T p1 = x, p2 = -1, p3 = 0; T p1dx = 1, p2dx = 0, p3dx = 0; for (int j=2; j<=n; j++) { p3=p2; p2=p1; p3dx = p2dx; p2dx = p1dx; p1=( (2*j-3) * x * p2 - (j-3) * p3) / j; p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j; shape[j-2] = p1; dshape[j-2] = p1dx; } } // compute L_i(x/t) * t^i template static void CalcScaledEdgeShape (int n, T x, T t, T * shape) { static bool init = false; static double coefs[100][2]; if (!init) { for (int j = 0; j < 100; j++) { coefs[j][0] = double(2*j+1)/(j+2); coefs[j][1] = -double(j-1)/(j+2); } init = true; } T p1 = x, p2 = -1, p3 = 0; T tt = t*t; for (int j=0; j<=n-2; j++) { p3=p2; p2=p1; p1= coefs[j][0] * x * p2 + coefs[j][1] * tt*p3; // p1=( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2); shape[j] = p1; } } template static void CalcScaledEdgeShapeLambda (int n, T x, T t, FUNC func) { static bool init = false; static double coefs[100][2]; if (!init) { for (int j = 0; j < 100; j++) { coefs[j][0] = double(2*j+1)/(j+2); coefs[j][1] = -double(j-1)/(j+2); } init = true; } T p1(x), p2(-1.0), p3(0.0); T tt = t*t; for (int j=0; j<=n-2; j++) { p3=p2; p2=p1; p1= coefs[j][0] * x * p2 + coefs[j][1] * tt*p3; // p1=( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2); func(j, p1); } } template static void CalcScaledEdgeShapeDxDt (int n, T x, T t, T * dshape) { T p1 = x, p2 = -1, p3 = 0; T p1dx = 1, p1dt = 0; T p2dx = 0, p2dt = 0; T p3dx = 0, p3dt = 0; for (int j=0; j<=n-2; j++) { p3=p2; p3dx=p2dx; p3dt = p2dt; p2=p1; p2dx=p1dx; p2dt = p1dt; p1 = ( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2); p1dx = ( (2*j+1) * (x * p2dx + p2) - t*t*(j-1) * p3dx) / (j+2); p1dt = ( (2*j+1) * x * p2dt - (j-1)* (t*t*p3dt+2*t*p3)) / (j+2); // shape[j] = p1; dshape[DIST*j ] = p1dx; dshape[DIST*j+1] = p1dt; } } template static void LegendrePolynomial (int n, Tx x, Tres * values) { switch (n) { case 0: values[0] = 1; break; case 1: values[0] = 1; values[1] = x; break; default: if (n < 0) return; Tx p1 = 1.0, p2 = 0.0, p3; values[0] = 1.0; for (int j=1; j<=n; j++) { p3 = p2; p2 = p1; p1 = ((2.0*j-1.0)*x*p2 - (j-1.0)*p3) / j; values[j] = p1; } } } template static void ScaledLegendrePolynomial (int n, Tx x, Tt t, Tres * values) { switch (n) { case 0: values[0] = 1.0; break; case 1: values[0] = 1.0; values[1] = x; break; default: if (n < 0) return; Tx p1 = 1.0, p2 = 0.0, p3; values[0] = 1.0; for (int j=1; j<=n; j++) { p3 = p2; p2 = p1; p1 = ((2.0*j-1.0)*x*p2 - t*t*(j-1.0)*p3) / j; values[j] = p1; } } } class RecPol { protected: int maxorder; double *a, *b, *c; public: RecPol (int amaxorder) { maxorder = amaxorder; a = new double[maxorder+1]; b = new double[maxorder+1]; c = new double[maxorder+1]; } ~RecPol () { delete [] a; delete [] b; delete [] c; } template void Evaluate (int n, S x, T * values) { S p1(1.0), p2(0.0), p3; if (n >= 0) p2 = values[0] = 1.0; if (n >= 1) p1 = values[1] = a[0]+b[0]*x; for (int i = 1; i < n; i++) { p3 = p2; p2=p1; p1 = (a[i]+b[i]*x)*p2-c[i]*p3; values[i+1] = p1; } } template void EvaluateScaled (int n, S x, S y, T * values) { S p1(1.0), p2(0.0), p3; if (n >= 0) p2 = values[0] = 1.0; if (n >= 1) p1 = values[1] = a[0]*y+b[0]*x; for (int i = 1; i < n; i++) { p3 = p2; p2=p1; p1 = (a[i]*y+b[i]*x)*p2-c[i]*y*y*p3; values[i+1] = p1; } } template void EvaluateScaledLambda (int n, S x, S y, FUNC func) { S p1(1.0), p2(0.0), p3; if (n >= 0) { p2 = 1.0; func(0, p2); } if (n >= 1) { p1 = a[0]*y+b[0]*x; func(1, p1); } for (int i = 1; i < n; i++) { p3 = p2; p2=p1; p1 = (a[i]*y+b[i]*x)*p2-c[i]*y*y*p3; func(i+1, p1); } } }; class JacobiRecPol : public RecPol { public: JacobiRecPol (int amo, double al, double be) : RecPol (amo) { for (int i = 0; i <= maxorder; i++) { double den = 2*(i+1)*(i+al+be+1)*(2*i+al+be); a[i] = (2*i+al+be+1)*(al*al-be*be) / den; b[i] = (2*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) / den; c[i] = 2*(i+al)*(i+be)*(2*i+al+be+2) / den; } } }; template inline void JacobiPolynomial (int n, S x, double alpha, double beta, T * values) { S p1 = 1.0, p2 = 0.0, p3; if (n >= 0) p2 = values[0] = 1.0; if (n >= 1) p1 = values[1] = 0.5 * (2*(alpha+1)+(alpha+beta+2)*(x-1)); for (int i = 1; i < n; i++) { p3 = p2; p2=p1; p1 = 1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) * ( ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) + (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x) * p2 - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * p3 ); values[i+1] = p1; } } template inline void ScaledJacobiPolynomial (int n, S x, St t, double alpha, double beta, T * values) { /* S p1 = 1.0, p2 = 0.0, p3; if (n >= 0) values[0] = 1.0; */ S p1(1.0), p2(0.0), p3; if (n >= 0) p2 = values[0] = 1.0; if (n >= 1) p1 = values[1] = 0.5 * (2*(alpha+1)*t+(alpha+beta+2)*(x-t)); for (int i=1; i < n; i++) { p3 = p2; p2=p1; p1 = 1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) * ( ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) * t + (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x) * p2 - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * t * t * p3 ); values[i+1] = p1; } } static Array> jacpols2; void CurvedElements::buildJacPols() { if (!jacpols2.Size()) { jacpols2.SetSize (100); for (int i = 0; i < 100; i++) jacpols2[i] = make_shared (100, i, 2); } } // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 template static void CalcTrigShape (int n, Tx x, Ty y, Ts * shape) { // cout << "calc trig shape" << endl; if (n < 3) return; Tx hx[50], hy[50*50]; jacpols2[2] -> EvaluateScaled (n-3, x, 1-y, hx); for (int ix = 0; ix <= n-3; ix++) jacpols2[2*ix+5] -> Evaluate (n-3, 2*y-1, hy+50*ix); int ii = 0; Tx bub = (1+x-y)*y*(1-x-y); for (int ix = 0; ix <= n-3; ix++) hx[ix] *= bub; /* for (int iy = 0; iy <= n-3; iy++) for (int ix = 0; ix <= n-3-iy; ix++) shape[ii++] = hx[ix]*hy[iy+50*ix]; */ // change loops: for (int ix = 0; ix <= n-3; ix++) for (int iy = 0; iy <= n-3-ix; iy++) shape[ii++] = hx[ix]*hy[iy+50*ix]; } template static void CalcTrigShapeDxDy (int n, T x, T y, T * dshape) { if (n < 3) return; AutoDiff<2,T> adx(x, 0); AutoDiff<2,T> ady(y, 1); AutoDiff<2,T> res[2000]; CalcTrigShape (n, adx, ady, &res[0]); int ndof = (n-1)*(n-2)/2; for (int i = 0; i < ndof; i++) { dshape[2*i] = res[i].DValue(0); dshape[2*i+1] = res[i].DValue(1); } } // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 template static void CalcScaledTrigShape (int n, Tx x, Ty y, Tt t, Tr * shape) { if (n < 3) return; Tx hx[50], hy[50]; ScaledJacobiPolynomial (n-3, x, t-y, 2, 2, hx); int ii = 0; Tx bub = (t+x-y)*y*(t-x-y); for (int ix = 0; ix <= n-3; ix++) { jacpols2[2*ix+5] -> EvaluateScaled (n-3, 2*y-1, t, hy); for (int iy = 0; iy <= n-3-ix; iy++) shape[ii++] = bub * hx[ix]*hy[iy]; } } template static void CalcScaledTrigShapeLambda (int n, Tx x, Ty y, Tt t, FUNC func) { if (n < 3) return; int ii = 0; Tx bub = (t+x-y)*y*(t-x-y); jacpols2[2]->EvaluateScaledLambda (n-3, x, t-y, [&](int ix, Tx valx) { jacpols2[2*ix+5] -> EvaluateScaledLambda (n-3-ix, 2*y-1, t, [&](int iy, Ty valy) { func(ii++, bub*valx*valy); }); }); } // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 template static void CalcScaledTrigShapeDxDyDt (int n, T x, T y, T t, T * dshape) { /* if (n < 3) return; AutoDiff<3,T> adx(x, 0); AutoDiff<3,T> ady(y, 1); AutoDiff<3,T> adt(t, 2); AutoDiff<3,T> res[2000]; CalcScaledTrigShape (n, adx, ady, adt, &res[0]); int ndof = (n-1)*(n-2)/2; for (int i = 0; i < ndof; i++) { dshape[3*i] = res[i].DValue(0); dshape[3*i+1] = res[i].DValue(1); dshape[3*i+2] = res[i].DValue(2); } */ if (n < 3) return; AutoDiff<3,T> adx(x, 0); AutoDiff<3,T> ady(y, 1); AutoDiff<3,T> adt(t, 2); CalcScaledTrigShapeLambda (n, adx, ady, adt, [&] (int i, AutoDiff<3,T> shape) { dshape[3*i] = shape.DValue(0); dshape[3*i+1] = shape.DValue(1); dshape[3*i+2] = shape.DValue(2); }); } CurvedElements :: CurvedElements (const Mesh & amesh) : mesh (amesh) { order = 1; rational = 0; ishighorder = 0; } CurvedElements :: ~CurvedElements() { } void CurvedElements :: BuildCurvedElements(const Refinement * ref, int aorder, bool arational) { ishighorder = 0; order = 1; // MPI_Comm curve_comm; const auto & curve_comm = mesh.GetCommunicator(); #ifdef PARALLEL enum { MPI_TAG_CURVE = MPI_TAG_MESH+20 }; const ParallelMeshTopology & partop = mesh.GetParallelTopology (); // MPI_Comm_dup (mesh.GetCommunicator(), &curve_comm); Array procs; #else // curve_comm = mesh.GetCommunicator(); #endif int id = curve_comm.Rank(); int ntasks = curve_comm.Size(); bool working = (ntasks == 1) || (id > 0); if (working) order = aorder; if (mesh.coarsemesh) { mesh.coarsemesh->GetCurvedElements().BuildCurvedElements (ref, aorder, arational); order = aorder; rational = arational; ishighorder = (order > 1); return; } PrintMessage (1, "Curve elements, order = ", aorder); if (rational) PrintMessage (1, "curved elements with rational splines"); // if (working) const_cast (mesh).UpdateTopology(); const MeshTopology & top = mesh.GetTopology(); rational = arational; Array edgenrs; int nedges = top.GetNEdges(); int nfaces = top.GetNFaces(); edgeorder.SetSize (nedges); faceorder.SetSize (nfaces); edgeorder = 1; faceorder = 1; if (rational) { edgeweight.SetSize (nedges); edgeweight = 1.0; } if (aorder <= 1) { for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) if (mesh[ei].GetType() == TET10) ishighorder = 1; return; } if (rational) aorder = 2; if (working) { if (mesh.GetDimension() == 3) for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) { top.GetEdges (i, edgenrs); for (int j = 0; j < edgenrs.Size(); j++) edgeorder[edgenrs[j]] = aorder; faceorder[top.GetFace (i)] = aorder; } for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++) edgeorder[top.GetEdge (i)] = aorder; } if (rational) { edgeorder = 2; faceorder = 1; } #ifdef PARALLEL TABLE send_orders(ntasks), recv_orders(ntasks); if (ntasks > 1 && working) { for (int e = 0; e < edgeorder.Size(); e++) { partop.GetDistantEdgeNums (e+1, procs); for (int j = 0; j < procs.Size(); j++) send_orders.Add (procs[j], edgeorder[e]); } for (int f = 0; f < faceorder.Size(); f++) { partop.GetDistantFaceNums (f+1, procs); for (int j = 0; j < procs.Size(); j++) send_orders.Add (procs[j], faceorder[f]); } } if (ntasks > 1) MyMPI_ExchangeTable (send_orders, recv_orders, MPI_TAG_CURVE, curve_comm); if (ntasks > 1 && working) { Array cnt(ntasks); cnt = 0; for (int e = 0; e < edgeorder.Size(); e++) { partop.GetDistantEdgeNums (e+1, procs); for (int j = 0; j < procs.Size(); j++) edgeorder[e] = max(edgeorder[e], recv_orders[procs[j]][cnt[procs[j]]++]); } for (int f = 0; f < faceorder.Size(); f++) { partop.GetDistantFaceNums (f+1, procs); for (int j = 0; j < procs.Size(); j++) faceorder[f] = max(faceorder[f], recv_orders[procs[j]][cnt[procs[j]]++]); } } #endif edgecoeffsindex.SetSize (nedges+1); int nd = 0; for (int i = 0; i < nedges; i++) { edgecoeffsindex[i] = nd; nd += max (0, edgeorder[i]-1); } edgecoeffsindex[nedges] = nd; edgecoeffs.SetSize (nd); edgecoeffs = Vec<3> (0,0,0); facecoeffsindex.SetSize (nfaces+1); nd = 0; for (int i = 0; i < nfaces; i++) { facecoeffsindex[i] = nd; if (top.GetFaceType(i+1) == TRIG) nd += max2 (0, (faceorder[i]-1)*(faceorder[i]-2)/2); else nd += max2 (0, sqr(faceorder[i]-1)); } facecoeffsindex[nfaces] = nd; facecoeffs.SetSize (nd); facecoeffs = Vec<3> (0,0,0); if (!ref || aorder <= 1) { order = aorder; return; } Array xi, weight; ComputeGaussRule (aorder+4, xi, weight); // on (0,1) buildJacPols(); PrintMessage (3, "Curving edges"); if (mesh.GetDimension() == 3 || rational) { static Timer tce("curve edges"); RegionTimer reg(tce); Array surfnr(nedges); Array gi0(nedges); Array gi1(nedges); surfnr = -1; if (working) for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) { top.GetEdges (i, edgenrs); const Element2d & el = mesh[i]; const ELEMENT_EDGE * edges = MeshTopology::GetEdges0 (el.GetType()); for (int i2 = 0; i2 < edgenrs.Size(); i2++) { // PointIndex pi1 = el[edges[i2][0]]; // PointIndex pi2 = el[edges[i2][1]]; // bool swap = pi1 > pi2; // Point<3> p1 = mesh[pi1]; // Point<3> p2 = mesh[pi2]; // int order1 = edgeorder[edgenrs[i2]]; // int ndof = max (0, order1-1); surfnr[edgenrs[i2]] = mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(); gi0[edgenrs[i2]] = el.GeomInfoPi(edges[i2][0]+1); gi1[edgenrs[i2]] = el.GeomInfoPi(edges[i2][1]+1); } } #ifdef PARALLEL if (ntasks > 1) { // distribute it ... TABLE senddata(ntasks), recvdata(ntasks); if (working) for (int e = 0; e < nedges; e++) { partop.GetDistantEdgeNums (e+1, procs); for (int j = 0; j < procs.Size(); j++) { senddata.Add (procs[j], surfnr[e]); if (surfnr[e] != -1) { senddata.Add (procs[j], gi0[e].trignum); senddata.Add (procs[j], gi0[e].u); senddata.Add (procs[j], gi0[e].v); senddata.Add (procs[j], gi1[e].trignum); senddata.Add (procs[j], gi1[e].u); senddata.Add (procs[j], gi1[e].v); } } } MyMPI_ExchangeTable (senddata, recvdata, MPI_TAG_CURVE, curve_comm); Array cnt(ntasks); cnt = 0; if (working) for (int e = 0; e < nedges; e++) { partop.GetDistantEdgeNums (e+1, procs); for (int j = 0; j < procs.Size(); j++) { int surfnr1 = recvdata[procs[j]][cnt[procs[j]]++]; if (surfnr1 != -1) { surfnr[e] = surfnr1; gi0[e].trignum = int (recvdata[procs[j]][cnt[procs[j]]++]); gi0[e].u = recvdata[procs[j]][cnt[procs[j]]++]; gi0[e].v = recvdata[procs[j]][cnt[procs[j]]++]; gi1[e].trignum = int (recvdata[procs[j]][cnt[procs[j]]++]); gi1[e].u = recvdata[procs[j]][cnt[procs[j]]++]; gi1[e].v = recvdata[procs[j]][cnt[procs[j]]++]; } } } } #endif if (working) for (int e = 0; e < surfnr.Size(); e++) { if (surfnr[e] == -1) continue; SetThreadPercent(double(e)/surfnr.Size()*100.); PointIndex pi1, pi2; top.GetEdgeVertices (e+1, pi1, pi2); bool swap = (pi1 > pi2); Point<3> p1 = mesh[pi1]; Point<3> p2 = mesh[pi2]; int order1 = edgeorder[e]; int ndof = max (0, order1-1); if (rational && order1 >= 2) { Point<3> pm = Center (p1, p2); Vec<3> n1 = ref -> GetNormal (p1, surfnr[e], gi0[e]); Vec<3> n2 = ref -> GetNormal (p2, surfnr[e], gi1[e]); // p3 = pm + alpha1 n1 + alpha2 n2 Mat<2> mat, inv; Vec<2> rhs, sol; mat(0,0) = n1*n1; mat(0,1) = mat(1,0) = n1*n2; mat(1,1) = n2*n2; rhs(0) = n1 * (p1-pm); rhs(1) = n2 * (p2-pm); Point<3> p3; if (fabs (Det (mat)) > 1e-10) { CalcInverse (mat, inv); sol = inv * rhs; p3 = pm + sol(0) * n1 + sol(1) * n2; } else p3 = pm; edgecoeffs[edgecoeffsindex[e]] = Vec<3> (p3); double wold = 1, w = 1, dw = 0.1; double dold = 1e99; while (fabs (dw) > 1e-12) { Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2); v05 /= 1 + (w-1) * 0.5; Point<3> p05 (v05), pp05(v05); ref -> ProjectToSurface (pp05, surfnr[e], gi0[e]); double d = Dist (pp05, p05); if (d < dold) { dold = d; wold = w; w += dw; } else { dw *= -0.7; w = wold + dw; } } edgeweight[e] = w; continue; } Vector shape(ndof); DenseMatrix mat(ndof, ndof), inv(ndof, ndof), rhs(ndof, 3), sol(ndof, 3); rhs = 0.0; mat = 0.0; for (int j = 0; j < xi.Size(); j++) { Point<3> p; Point<3> pp; PointGeomInfo ppgi; if (swap) { p = p1 + xi[j] * (p2-p1); ref -> PointBetween (p1, p2, xi[j], surfnr[e], gi0[e], gi1[e], pp, ppgi); } else { p = p2 + xi[j] * (p1-p2); ref -> PointBetween (p2, p1, xi[j], surfnr[e], gi1[e], gi0[e], pp, ppgi); } Vec<3> dist = pp - p; CalcEdgeShape (order1, 2*xi[j]-1, &shape(0)); for (int k = 0; k < ndof; k++) for (int l = 0; l < ndof; l++) mat(k,l) += weight[j] * shape(k) * shape(l); for (int k = 0; k < ndof; k++) for (int l = 0; l < 3; l++) rhs(k,l) += weight[j] * shape(k) * dist(l); } CalcInverse (mat, inv); Mult (inv, rhs, sol); int first = edgecoeffsindex[e]; for (int j = 0; j < ndof; j++) for (int k = 0; k < 3; k++) edgecoeffs[first+j](k) = sol(j,k); } } Array use_edge(nedges); Array edge_surfnr1(nedges); Array edge_surfnr2(nedges); Array swap_edge(nedges); Array edge_gi0(nedges); Array edge_gi1(nedges); use_edge = 0; if (working) for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++) { const Segment & seg = mesh[i]; int edgenr = top.GetEdge (i); use_edge[edgenr] = 1; edge_surfnr1[edgenr] = seg.surfnr1; edge_surfnr2[edgenr] = seg.surfnr2; edge_gi0[edgenr] = seg.epgeominfo[0]; edge_gi1[edgenr] = seg.epgeominfo[1]; swap_edge[edgenr] = int (seg[0] > seg[1]); } #ifdef PARALLEL if (ntasks > 1) { // distribute it ... TABLE senddata(ntasks), recvdata(ntasks); if (working) for (int e = 0; e < nedges; e++) { partop.GetDistantEdgeNums (e+1, procs); for (int j = 0; j < procs.Size(); j++) { senddata.Add (procs[j], use_edge[e]); if (use_edge[e]) { senddata.Add (procs[j], edge_surfnr1[e]); senddata.Add (procs[j], edge_surfnr2[e]); senddata.Add (procs[j], edge_gi0[e].edgenr); senddata.Add (procs[j], edge_gi0[e].body); senddata.Add (procs[j], edge_gi0[e].dist); senddata.Add (procs[j], edge_gi0[e].u); senddata.Add (procs[j], edge_gi0[e].v); senddata.Add (procs[j], edge_gi1[e].edgenr); senddata.Add (procs[j], edge_gi1[e].body); senddata.Add (procs[j], edge_gi1[e].dist); senddata.Add (procs[j], edge_gi1[e].u); senddata.Add (procs[j], edge_gi1[e].v); senddata.Add (procs[j], swap_edge[e]); } } } MyMPI_ExchangeTable (senddata, recvdata, MPI_TAG_CURVE, curve_comm); Array cnt(ntasks); cnt = 0; if (working) for (int e = 0; e < edge_surfnr1.Size(); e++) { partop.GetDistantEdgeNums (e+1, procs); for (int j = 0; j < procs.Size(); j++) { int get_edge = int(recvdata[procs[j]][cnt[procs[j]]++]); if (get_edge) { use_edge[e] = 1; edge_surfnr1[e] = int (recvdata[procs[j]][cnt[procs[j]]++]); edge_surfnr2[e] = int (recvdata[procs[j]][cnt[procs[j]]++]); edge_gi0[e].edgenr = int (recvdata[procs[j]][cnt[procs[j]]++]); edge_gi0[e].body = int (recvdata[procs[j]][cnt[procs[j]]++]); edge_gi0[e].dist = recvdata[procs[j]][cnt[procs[j]]++]; edge_gi0[e].u = recvdata[procs[j]][cnt[procs[j]]++]; edge_gi0[e].v = recvdata[procs[j]][cnt[procs[j]]++]; edge_gi1[e].edgenr = int (recvdata[procs[j]][cnt[procs[j]]++]); edge_gi1[e].body = int (recvdata[procs[j]][cnt[procs[j]]++]); edge_gi1[e].dist = recvdata[procs[j]][cnt[procs[j]]++]; edge_gi1[e].u = recvdata[procs[j]][cnt[procs[j]]++]; edge_gi1[e].v = recvdata[procs[j]][cnt[procs[j]]++]; swap_edge[e] = recvdata[procs[j]][cnt[procs[j]]++]; } } } } #endif if (working) for (int edgenr = 0; edgenr < use_edge.Size(); edgenr++) { int segnr = edgenr; if (!use_edge[edgenr]) continue; SetThreadPercent(double(edgenr)/edge_surfnr1.Size()*100.); PointIndex pi1, pi2; top.GetEdgeVertices (edgenr+1, pi1, pi2); bool swap = swap_edge[edgenr]; // (pi1 > pi2); if (swap) Swap (pi1, pi2); Point<3> p1 = mesh[pi1]; Point<3> p2 = mesh[pi2]; int order1 = edgeorder[segnr]; int ndof = max (0, order1-1); if (rational) { Vec<3> tau1 = ref -> GetTangent (p1, edge_surfnr2[edgenr], edge_surfnr1[edgenr], edge_gi0[edgenr]); Vec<3> tau2 = ref -> GetTangent (p2, edge_surfnr2[edgenr], edge_surfnr1[edgenr], edge_gi1[edgenr]); // p1 + alpha1 tau1 = p2 + alpha2 tau2; Mat<3,2> mat; Mat<2,3> inv; Vec<3> rhs; Vec<2> sol; for (int j = 0; j < 3; j++) { mat(j,0) = tau1(j); mat(j,1) = -tau2(j); rhs(j) = p2(j)-p1(j); } CalcInverse (mat, inv); sol = inv * rhs; Point<3> p3 = p1+sol(0) * tau1; edgecoeffs[edgecoeffsindex[segnr]] = Vec<3> (p3); double wold = 1, w = 1, dw = 0.1; double dold = 1e99; while (fabs (dw) > 1e-12) { Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2); v05 /= 1 + (w-1) * 0.5; Point<3> p05 (v05), pp05(v05); ref -> ProjectToEdge (pp05, edge_surfnr1[edgenr], edge_surfnr2[edgenr], edge_gi0[edgenr]); double d = Dist (pp05, p05); if (d < dold) { dold = d; wold = w; w += dw; } else { dw *= -0.7; w = wold + dw; } // *testout << "w = " << w << ", dw = " << dw << endl; } // cout << "wopt = " << w << ", dopt = " << dold << endl; edgeweight[segnr] = w; // cout << "p1 = " << p1 << ", tau1 = " << tau1 << ", alpha1 = " << sol(0) << endl; // cout << "p2 = " << p2 << ", tau2 = " << tau2 << ", alpha2 = " << -sol(1) << endl; // cout << "p+alpha tau = " << p1 + sol(0) * tau1 // << " =?= " << p2 +sol(1) * tau2 << endl; } else { Vector shape(ndof); DenseMatrix mat(ndof, ndof), inv(ndof, ndof), rhs(ndof, 3), sol(ndof, 3); rhs = 0.0; mat = 0.0; for (int j = 0; j < xi.Size(); j++) { Point<3> p, pp; EdgePointGeomInfo ppgi; if (swap) { p = p1 + xi[j] * (p2-p1); ref -> PointBetween (p1, p2, xi[j], edge_surfnr2[edgenr], edge_surfnr1[edgenr], edge_gi0[edgenr], edge_gi1[edgenr], pp, ppgi); } else { p = p2 + xi[j] * (p1-p2); ref -> PointBetween (p2, p1, xi[j], edge_surfnr2[edgenr], edge_surfnr1[edgenr], edge_gi1[edgenr], edge_gi0[edgenr], pp, ppgi); } Vec<3> dist = pp - p; CalcEdgeShape (order1, 2*xi[j]-1, &shape(0)); for (int k = 0; k < ndof; k++) for (int l = 0; l < ndof; l++) mat(k,l) += weight[j] * shape(k) * shape(l); for (int k = 0; k < ndof; k++) for (int l = 0; l < 3; l++) rhs(k,l) += weight[j] * shape(k) * dist(l); } CalcInverse (mat, inv); Mult (inv, rhs, sol); int first = edgecoeffsindex[segnr]; for (int j = 0; j < ndof; j++) for (int k = 0; k < 3; k++) edgecoeffs[first+j](k) = sol(j,k); } } PrintMessage (3, "Curving faces"); Array surfnr(nfaces); surfnr = -1; if (working) for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) surfnr[top.GetFace(i)] = mesh.GetFaceDescriptor(mesh[i].GetIndex()).SurfNr(); #ifdef PARALLEL TABLE send_surfnr(ntasks), recv_surfnr(ntasks); if (ntasks > 1 && working) { for (int f = 0; f < nfaces; f++) { partop.GetDistantFaceNums (f+1, procs); for (int j = 0; j < procs.Size(); j++) send_surfnr.Add (procs[j], surfnr[f]); } } if (ntasks > 1) MyMPI_ExchangeTable (send_surfnr, recv_surfnr, MPI_TAG_CURVE, curve_comm); if (ntasks > 1 && working) { Array cnt(ntasks); cnt = 0; for (int f = 0; f < nfaces; f++) { partop.GetDistantFaceNums (f+1, procs); for (int j = 0; j < procs.Size(); j++) surfnr[f] = max(surfnr[f], recv_surfnr[procs[j]][cnt[procs[j]]++]); } } #endif if (mesh.GetDimension() == 3 && working) { static Timer tcf("curve faces"); RegionTimer reg(tcf); for (int f = 0; f < nfaces; f++) { int facenr = f; if (surfnr[f] == -1) continue; // if (el.GetType() == TRIG && order >= 3) if (top.GetFaceType(facenr+1) == TRIG && order >= 3) { ArrayMem verts(3); top.GetFaceVertices (facenr+1, verts); int fnums[] = { 0, 1, 2 }; /* if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); */ if (verts[fnums[0]] > verts[fnums[1]]) swap (fnums[0], fnums[1]); if (verts[fnums[1]] > verts[fnums[2]]) swap (fnums[1], fnums[2]); if (verts[fnums[0]] > verts[fnums[1]]) swap (fnums[0], fnums[1]); int order1 = faceorder[facenr]; int ndof = max (0, (order1-1)*(order1-2)/2); Vector shape(ndof), dmat(ndof); MatrixFixWidth<3> rhs(ndof), sol(ndof); rhs = 0.0; dmat = 0.0; int np = sqr(xi.Size()); Array > xia(np); Array > xa(np); for (int jx = 0, jj = 0; jx < xi.Size(); jx++) for (int jy = 0; jy < xi.Size(); jy++, jj++) xia[jj] = Point<2> ((1-xi[jy])*xi[jx], xi[jy]); // CalcMultiPointSurfaceTransformation (&xia, i, &xa, NULL); Array edgenrs; top.GetFaceEdges (facenr+1, edgenrs); for (int k = 0; k < edgenrs.Size(); k++) edgenrs[k]--; for (int jj = 0; jj < np; jj++) { Point<3> pp(0,0,0); double lami[] = { xia[jj](0), xia[jj](1), 1-xia[jj](0)-xia[jj](1)}; for (int k = 0; k < verts.Size(); k++) pp += lami[k] * Vec<3> (mesh.Point(verts[k])); // const ELEMENT_EDGE * edges = MeshTopology::GetEdges0 (TRIG); for (int k = 0; k < edgenrs.Size(); k++) { int eorder = edgeorder[edgenrs[k]]; if (eorder < 2) continue; int first = edgecoeffsindex[edgenrs[k]]; Vector eshape(eorder-1); int vi1, vi2; top.GetEdgeVertices (edgenrs[k]+1, vi1, vi2); if (vi1 > vi2) swap (vi1, vi2); int v1 = -1, v2 = -1; for (int j = 0; j < 3; j++) { if (verts[j] == vi1) v1 = j; if (verts[j] == vi2) v2 = j; } CalcScaledEdgeShape (eorder, lami[v1]-lami[v2], lami[v1]+lami[v2], &eshape(0)); for (int n = 0; n < eshape.Size(); n++) pp += eshape(n) * edgecoeffs[first+n]; } xa[jj] = pp; } for (int jx = 0, jj = 0; jx < xi.Size(); jx++) for (int jy = 0; jy < xi.Size(); jy++, jj++) { double y = xi[jy]; double x = (1-y) * xi[jx]; double lami[] = { x, y, 1-x-y }; double wi = weight[jx]*weight[jy]*(1-y); Point<3> pp = xa[jj]; // ref -> ProjectToSurface (pp, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr()); SurfaceElementIndex sei = top.GetFace2SurfaceElement (f+1)-1; PointGeomInfo gi = mesh[sei].GeomInfoPi(1); ref -> ProjectToSurface (pp, surfnr[facenr], gi); Vec<3> dist = pp-xa[jj]; CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]], 1-lami[fnums[1]]-lami[fnums[0]], &shape(0)); for (int k = 0; k < ndof; k++) dmat(k) += wi * shape(k) * shape(k); dist *= wi; for (int k = 0; k < ndof; k++) for (int l = 0; l < 3; l++) rhs(k,l) += shape(k) * dist(l); } for (int i = 0; i < ndof; i++) for (int j = 0; j < 3; j++) sol(i,j) = rhs(i,j) / dmat(i); // Orthogonal basis ! int first = facecoeffsindex[facenr]; for (int j = 0; j < ndof; j++) for (int k = 0; k < 3; k++) facecoeffs[first+j](k) = sol(j,k); } } } // compress edge and face tables int newbase = 0; for (int i = 0; i < edgeorder.Size(); i++) { bool curved = 0; int oldbase = edgecoeffsindex[i]; int nd = edgecoeffsindex[i+1] - edgecoeffsindex[i]; for (int j = 0; j < nd; j++) if (edgecoeffs[oldbase+j].Length() > 1e-12) curved = 1; if (rational) curved = 1; if (curved && newbase != oldbase) for (int j = 0; j < nd; j++) edgecoeffs[newbase+j] = edgecoeffs[oldbase+j]; edgecoeffsindex[i] = newbase; if (!curved) edgeorder[i] = 1; if (curved) newbase += nd; } edgecoeffsindex.Last() = newbase; newbase = 0; for (int i = 0; i < faceorder.Size(); i++) { bool curved = 0; int oldbase = facecoeffsindex[i]; int nd = facecoeffsindex[i+1] - facecoeffsindex[i]; for (int j = 0; j < nd; j++) if (facecoeffs[oldbase+j].Length() > 1e-12) curved = 1; if (curved && newbase != oldbase) for (int j = 0; j < nd; j++) facecoeffs[newbase+j] = facecoeffs[oldbase+j]; facecoeffsindex[i] = newbase; if (!curved) faceorder[i] = 1; if (curved) newbase += nd; } facecoeffsindex.Last() = newbase; if (working) ishighorder = (order > 1); // (*testout) << "edgecoeffs = " << endl << edgecoeffs << endl; // (*testout) << "facecoeffs = " << endl << facecoeffs << endl; #ifdef PARALLEL curve_comm.Barrier(); // MPI_Comm_free (&curve_comm); #endif } // *********************** Transform edges ***************************** bool CurvedElements :: IsSegmentCurved (SegmentIndex elnr) const { if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; return mesh.coarsemesh->GetCurvedElements().IsSegmentCurved (hpref_el.coarse_elnr); } SegmentInfo info; info.elnr = elnr; info.order = order; info.ndof = info.nv = 2; if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); info.edgenr = top.GetSegmentEdge (elnr+1)-1; info.ndof += edgeorder[info.edgenr]-1; } return (info.ndof > info.nv); } template void CurvedElements :: CalcSegmentTransformation (T xi, SegmentIndex elnr, Point<3,T> * x, Vec<3,T> * dxdxi, bool * curved) { if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; // xi umrechnen T lami[2] = { xi, 1-xi }; T dlami[2] = { 1, -1 }; T coarse_xi = 0; T trans = 0; for (int i = 0; i < 2; i++) { coarse_xi += hpref_el.param[i][0] * lami[i]; trans += hpref_el.param[i][0] * dlami[i]; } mesh.coarsemesh->GetCurvedElements().CalcSegmentTransformation (coarse_xi, hpref_el.coarse_elnr, x, dxdxi, curved); if (dxdxi) *dxdxi *= trans; return; } // TVector shapes, dshapes; // Array > coefs; SegmentInfo info; info.elnr = elnr; info.order = order; info.ndof = info.nv = 2; if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); info.edgenr = top.GetSegmentEdge (elnr+1)-1; info.ndof += edgeorder[info.edgenr]-1; } ArrayMem,100> coefs(info.ndof); ArrayMem shapes_mem(info.ndof); TFlatVector shapes(info.ndof, &shapes_mem[0]); ArrayMem dshapes_mem(info.ndof); TFlatVector dshapes(info.ndof, &dshapes_mem[0]); CalcElementShapes (info, xi, shapes); GetCoefficients (info, coefs); *x = 0; for (int i = 0; i < shapes.Size(); i++) // *x += shapes(i) * coefs[i]; for (int j = 0; j < 3; j++) (*x)(j) += shapes(i) * coefs[i](j); if (dxdxi) { CalcElementDShapes (info, xi, dshapes); *dxdxi = 0; for (int i = 0; i < shapes.Size(); i++) for (int j = 0; j < 3; j++) (*dxdxi)(j) += dshapes(i) * coefs[i](j); } if (curved) *curved = (info.order > 1); // cout << "Segment, |x| = " << Abs2(Vec<3> (*x) ) << endl; } template void CurvedElements :: CalcElementShapes (SegmentInfo & info, T xi, TFlatVector shapes) const { /* if (rational && info.order == 2) { shapes.SetSize(3); double w = edgeweight[info.edgenr]; shapes(0) = xi*xi; shapes(1) = (1-xi)*(1-xi); shapes(2) = 2*w*xi*(1-xi); shapes *= 1.0 / (1 + (w-1) *2*xi*(1-xi)); return; } */ // shapes.SetSize(info.ndof); shapes(0) = xi; shapes(1) = 1-xi; if (info.order >= 2) { if (mesh[info.elnr][0] > mesh[info.elnr][1]) xi = 1-xi; CalcEdgeShape (edgeorder[info.edgenr], 2*xi-1, &shapes(2)); } } template void CurvedElements :: CalcElementDShapes (SegmentInfo & info, T xi, TFlatVector dshapes) const { /* if (rational && info.order == 2) { dshapes.SetSize(3); double wi = edgeweight[info.edgenr]; double shapes[3]; shapes[0] = xi*xi; shapes[1] = (1-xi)*(1-xi); shapes[2] = 2*wi*xi*(1-xi); double w = 1 + (wi-1) *2*xi*(1-xi); double dw = (wi-1) * (2 - 4*xi); dshapes(0) = 2*xi; dshapes(1) = 2*(xi-1); dshapes(2) = 2*wi*(1-2*xi); for (int j = 0;j < 3; j++) dshapes(j) = dshapes(j) / w - shapes[j] * dw / (w*w); return; } */ // dshapes.SetSize(info.ndof); dshapes = 0; dshapes(0) = 1; dshapes(1) = -1; // int order = edgeorder[info.edgenr]; if (info.order >= 2) { T fac = 2; if (mesh[info.elnr][0] > mesh[info.elnr][1]) { xi = 1-xi; fac *= -1; } CalcEdgeDx (edgeorder[info.edgenr], 2*xi-1, &dshapes(2)); for (int i = 2; i < dshapes.Size(); i++) dshapes(i) *= fac; } // ??? not implemented ???? } void CurvedElements :: GetCoefficients (SegmentInfo & info, Array > & coefs) const { const Segment & el = mesh[info.elnr]; coefs.SetSize(info.ndof); coefs[0] = Vec<3> (mesh[el[0]]); coefs[1] = Vec<3> (mesh[el[1]]); if (info.order >= 2) { int first = edgecoeffsindex[info.edgenr]; int next = edgecoeffsindex[info.edgenr+1]; for (int i = 0; i < next-first; i++) coefs[i+2] = edgecoeffs[first+i]; } } // ********************** Transform surface elements ******************* bool CurvedElements :: IsSurfaceElementCurved (SurfaceElementIndex elnr) const { if (mesh[elnr].GetType() != TRIG) return true; if (!IsHighOrder()) return false; if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; return mesh.coarsemesh->GetCurvedElements().IsSurfaceElementCurved (hpref_el.coarse_elnr); } const Element2d & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); SurfaceElementInfo info; info.elnr = elnr; info.order = order; switch (type) { case TRIG : info.nv = 3; break; case QUAD : info.nv = 4; break; case TRIG6: return true; default: cerr << "undef element in CalcSurfaceTrafo" << endl; } info.ndof = info.nv; // info.ndof = info.nv = ( (type == TRIG) || (type == TRIG6) ) ? 3 : 4; if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); top.GetSurfaceElementEdges (elnr+1, info.edgenrs); for (int i = 0; i < info.edgenrs.Size(); i++) info.edgenrs[i]--; info.facenr = top.GetSurfaceElementFace (elnr+1)-1; for (int i = 0; i < info.edgenrs.Size(); i++) info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; } return (info.ndof > info.nv); } void CurvedElements :: CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr, Point<3> * x, Mat<3,2> * dxdxi, bool * curved) { if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; // xi umrechnen double lami[4]; FlatVector vlami(4, lami); vlami = 0; mesh[elnr].GetShapeNew (xi, vlami); Mat<2,2> trans; Mat<3,2> dxdxic; if (dxdxi) { MatrixFixWidth<2> dlami(4); dlami = 0; mesh[elnr].GetDShapeNew (xi, dlami); trans = 0; for (int k = 0; k < 2; k++) for (int l = 0; l < 2; l++) for (int i = 0; i < hpref_el.np; i++) trans(l,k) += hpref_el.param[i][l] * dlami(i, k); } Point<2> coarse_xi(0,0); for (int i = 0; i < hpref_el.np; i++) for (int j = 0; j < 2; j++) coarse_xi(j) += hpref_el.param[i][j] * lami[i]; mesh.coarsemesh->GetCurvedElements().CalcSurfaceTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic, curved); if (dxdxi) *dxdxi = dxdxic * trans; return; } const Element2d & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); SurfaceElementInfo info; info.elnr = elnr; info.order = order; switch (type) { case TRIG : info.nv = 3; break; case QUAD : info.nv = 4; break; case TRIG6: info.nv = 6; break; case QUAD8 : info.nv = 8; break; default: cerr << "undef element in CalcSurfaceTrafo" << endl; } info.ndof = info.nv; if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); top.GetSurfaceElementEdges (elnr+1, info.edgenrs); for (int i = 0; i < info.edgenrs.Size(); i++) info.edgenrs[i]--; info.facenr = top.GetSurfaceElementFace (elnr+1)-1; bool firsttry = true; bool problem = false; while(firsttry || problem) { problem = false; for (int i = 0; !problem && i < info.edgenrs.Size(); i++) { if(info.edgenrs[i]+1 >= edgecoeffsindex.Size()) problem = true; else info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; } if(info.facenr+1 >= facecoeffsindex.Size()) problem = true; else info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; if(problem && !firsttry) throw NgException("something wrong with curved elements"); if(problem) BuildCurvedElements(NULL,order,rational); firsttry = false; } } Point<2> _xi(xi); Point<3> _x; Mat<3,2> _dxdxi; if (EvaluateMapping (info, _xi, _x, _dxdxi)) { if (x) *x = _x; if (dxdxi) *dxdxi = _dxdxi; return; } ArrayMem,100> coefs(info.ndof); ArrayMem shapes_mem(info.ndof); TFlatVector shapes(info.ndof, &shapes_mem[0]); ArrayMem dshapes_mem(2*info.ndof); MatrixFixWidth<2> dshapes(info.ndof, &dshapes_mem[0]); CalcElementShapes (info, xi, shapes); GetCoefficients (info, coefs); *x = 0; for (int i = 0; i < coefs.Size(); i++) *x += shapes(i) * coefs[i]; if (dxdxi) { CalcElementDShapes (info, xi, dshapes); *dxdxi = 0; for (int i = 0; i < coefs.Size(); i++) for (int j = 0; j < 3; j++) for (int k = 0; k < 2; k++) (*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j); } if (curved) *curved = (info.ndof > info.nv); } template void CurvedElements :: CalcElementShapes (SurfaceElementInfo & info, const Point<2,T> xi, TFlatVector shapes) const { const Element2d & el = mesh[info.elnr]; // shapes.SetSize(info.ndof); if (rational && info.order >= 2) { // shapes.SetSize(6); T w(1); T lami[3] = { xi(0), xi(1), 1-xi(0)-xi(1) }; for (int j = 0; j < 3; j++) shapes(j) = lami[j] * lami[j]; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG); for (int j = 0; j < 3; j++) { T wi = edgeweight[info.edgenrs[j]]; shapes(j+3) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; } shapes *= 1.0 / w; return; } switch (el.GetType()) { case TRIG: { shapes(0) = xi(0); shapes(1) = xi(1); shapes(2) = 1-xi(0)-xi(1); if (info.order == 1) return; int ii = 3; const ELEMENT_EDGE * edges = MeshTopology::GetEdges0 (TRIG); for (int i = 0; i < 3; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0], vi2 = edges[i][1]; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii)); ii += eorder-1; } } int forder = faceorder[info.facenr]; if (forder >= 3) { int fnums[] = { 0, 1, 2 }; if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); CalcTrigShape (forder, shapes(fnums[1])-shapes(fnums[0]), 1-shapes(fnums[1])-shapes(fnums[0]), &shapes(ii)); } break; } case TRIG6: { if (shapes.Size() == 3) { shapes(0) = xi(0); shapes(1) = xi(1); shapes(2) = 1-xi(0)-xi(1); } else { T x = xi(0); T y = xi(1); T lam3 = 1-x-y; shapes(0) = x * (2*x-1); shapes(1) = y * (2*y-1); shapes(2) = lam3 * (2*lam3-1); shapes(3) = 4 * y * lam3; shapes(4) = 4 * x * lam3; shapes(5) = 4 * x * y; } break; } case QUAD: { shapes(0) = (1-xi(0))*(1-xi(1)); shapes(1) = xi(0) *(1-xi(1)); shapes(2) = xi(0) * xi(1) ; shapes(3) = (1-xi(0))* xi(1) ; if (info.order == 1) return; T mu[4] = { 1 - xi(0) + 1 - xi(1), xi(0) + 1 - xi(1), xi(0) + xi(1), 1 - xi(0) + xi(1), }; int ii = 4; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (QUAD); for (int i = 0; i < 4; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcEdgeShape (eorder, mu[vi1]-mu[vi2], &shapes(ii)); T lame = shapes(vi1)+shapes(vi2); for (int j = 0; j < order-1; j++) shapes(ii+j) *= lame; ii += eorder-1; } } for (int i = ii; i < info.ndof; i++) shapes(i) = 0; break; } case QUAD8: { auto x = xi(0), y = xi(1); shapes(0) = (1-x)*(1-y); shapes(1) = x*(1-y); shapes(2) = x*y; shapes(3) = (1-x)*y; shapes(4) = 4*(1-x)*x*(1-y); shapes(5) = 4*(1-x)*x*y; shapes(6) = 4*(1-y)*y*(1-x); shapes(7) = 4*(1-y)*y*x; shapes(0) -= 0.5*(shapes(4)+shapes(6)); shapes(1) -= 0.5*(shapes(4)+shapes(7)); shapes(2) -= 0.5*(shapes(5)+shapes(7)); shapes(3) -= 0.5*(shapes(5)+shapes(6)); break; } default: throw NgException("CurvedElements::CalcShape 2d, element type not handled"); }; } template void CurvedElements :: CalcElementDShapes (SurfaceElementInfo & info, const Point<2,T> xi, MatrixFixWidth<2,T> dshapes) const { const Element2d & el = mesh[info.elnr]; ELEMENT_TYPE type = el.GetType(); T lami[4]; dshapes.SetSize(info.ndof); // dshapes = 0; // *testout << "calcelementdshapes, info.ndof = " << info.ndof << endl; if (rational && info.order >= 2) { T w = 1; T dw[2] = { 0, 0 }; lami[0] = xi(0); lami[1] = xi(1); lami[2] = 1-xi(0)-xi(1); T dlami[3][2] = { { 1, 0 }, { 0, 1 }, { -1, -1 }}; T shapes[6]; for (int j = 0; j < 3; j++) { shapes[j] = lami[j] * lami[j]; dshapes(j,0) = 2 * lami[j] * dlami[j][0]; dshapes(j,1) = 2 * lami[j] * dlami[j][1]; } const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG); for (int j = 0; j < 3; j++) { T wi = edgeweight[info.edgenrs[j]]; shapes[j+3] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; for (int k = 0; k < 2; k++) dshapes(j+3,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; for (int k = 0; k < 2; k++) dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); } // shapes *= 1.0 / w; dshapes *= 1.0 / w; for (int i = 0; i < 6; i++) for (int j = 0; j < 2; j++) dshapes(i,j) -= shapes[i] * dw[j] / (w*w); return; } switch (type) { case TRIG: { dshapes(0,0) = 1; dshapes(0,1) = 0.0; dshapes(1,0) = 0.0; dshapes(1,1) = 1; dshapes(2,0) = -1; dshapes(2,1) = -1; if (info.order == 1) return; // *testout << "info.order = " << info.order << endl; lami[0] = xi(0); lami[1] = xi(1); lami[2] = 1-xi(0)-xi(1); int ii = 3; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG); for (int i = 0; i < 3; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShapeDxDt<2> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0)); Mat<2,2,T> trans; for (int j = 0; j < 2; j++) { trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j); trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j); } for (int j = 0; j < eorder-1; j++) { T ddx = dshapes(ii+j,0); T ddt = dshapes(ii+j,1); dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); } ii += eorder-1; } } int forder = faceorder[info.facenr]; // *testout << "forder = " << forder << endl; if (forder >= 3) { int fnums[] = { 0, 1, 2 }; if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); CalcTrigShapeDxDy (forder, lami[fnums[1]]-lami[fnums[0]], 1-lami[fnums[1]]-lami[fnums[0]], &dshapes(ii,0)); int nd = (forder-1)*(forder-2)/2; Mat<2,2,T> trans; for (int j = 0; j < 2; j++) { trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j); trans(1,j) = -dshapes(fnums[1],j)-dshapes(fnums[0],j); } for (int j = 0; j < nd; j++) { T ddx = dshapes(ii+j,0); T ddt = dshapes(ii+j,1); dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); } } break; } case TRIG6: { if (dshapes.Height() == 3) { dshapes = T(0.0); dshapes(0,0) = 1; dshapes(1,1) = 1; dshapes(2,0) = -1; dshapes(2,1) = -1; } else { AutoDiff<2,T> x(xi(0), 0); AutoDiff<2,T> y(xi(1), 1); AutoDiff<2,T> lam3 = 1-x-y; AutoDiff<2,T> shapes[6]; shapes[0] = x * (2*x-1); shapes[1] = y * (2*y-1); shapes[2] = lam3 * (2*lam3-1); shapes[3] = 4 * y * lam3; shapes[4] = 4 * x * lam3; shapes[5] = 4 * x * y; for (int i = 0; i < 6; i++) { dshapes(i,0) = shapes[i].DValue(0); dshapes(i,1) = shapes[i].DValue(1); } } break; } case QUAD: { dshapes(0,0) = -(1-xi(1)); dshapes(0,1) = -(1-xi(0)); dshapes(1,0) = (1-xi(1)); dshapes(1,1) = -xi(0); dshapes(2,0) = xi(1); dshapes(2,1) = xi(0); dshapes(3,0) = -xi(1); dshapes(3,1) = (1-xi(0)); if (info.order == 1) return; T shapes[4] = { (1-xi(0))*(1-xi(1)), xi(0) *(1-xi(1)), xi(0) * xi(1) , (1-xi(0))* xi(1) }; T mu[4] = { 1 - xi(0) + 1 - xi(1), xi(0) + 1 - xi(1), xi(0) + xi(1), 1 - xi(0) + xi(1), }; T dmu[4][2] = { { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } }; // double hshapes[20], hdshapes[20]; ArrayMem hshapes(order+1), hdshapes(order+1); int ii = 4; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (QUAD); for (int i = 0; i < 4; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcEdgeShapeDx (eorder, mu[vi1]-mu[vi2], &hshapes[0], &hdshapes[0]); T lame = shapes[vi1]+shapes[vi2]; T dlame[2] = { dshapes(vi1, 0) + dshapes(vi2, 0), dshapes(vi1, 1) + dshapes(vi2, 1) }; for (int j = 0; j < eorder-1; j++) for (int k = 0; k < 2; k++) dshapes(ii+j, k) = lame * hdshapes[j] * (dmu[vi1][k]-dmu[vi2][k]) + dlame[k] * hshapes[j]; ii += eorder-1; } } /* *testout << "quad, dshape = " << endl << dshapes << endl; for (int i = 0; i < 2; i++) { Point<2> xil = xi, xir = xi; Vector shapesl(dshapes.Height()), shapesr(dshapes.Height()); xil(i) -= 1e-6; xir(i) += 1e-6; CalcElementShapes (info, xil, shapesl); CalcElementShapes (info, xir, shapesr); for (int j = 0; j < dshapes.Height(); j++) dshapes(j,i) = 1.0 / 2e-6 * (shapesr(j)-shapesl(j)); } *testout << "quad, num dshape = " << endl << dshapes << endl; */ break; } default: throw NgException("CurvedElements::CalcDShape 2d, element type not handled"); }; } template bool CurvedElements :: EvaluateMapping (SurfaceElementInfo & info, const Point<2,T> xi, Point & mx, Mat & jac) const { const Element2d & el = mesh[info.elnr]; if (rational && info.order >= 2) return false; // not supported AutoDiff<2,T> x(xi(0), 0); AutoDiff<2,T> y(xi(1), 1); AutoDiff<2,T> mapped_x[DIM_SPACE]; for (int i = 0; i < DIM_SPACE; i++) mapped_x[i] = AutoDiff<2,T>(0.0); switch (el.GetType()) { case TRIG6: { AutoDiff<2,T> lam3 = 1-x-y; AutoDiff<2,T> lami[6] = { x * (2*x-1), y * (2*y-1), lam3 * (2*lam3-1), 4 * y * lam3, 4 * x * lam3, 4 * x * y }; for (int j = 0; j < 6; j++) { Point<3> p = mesh[el[j]]; for (int k = 0; k < DIM_SPACE; k++) mapped_x[k] += p(k) * lami[j]; } break; } case TRIG: { // if (info.order >= 2) return false; // not yet supported AutoDiff<2,T> lami[4] = { x, y, 1-x-y }; for (int j = 0; j < 3; j++) { Point<3> p = mesh[el[j]]; for (int k = 0; k < DIM_SPACE; k++) mapped_x[k] += p(k) * lami[j]; } if (info.order == 1) break; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TRIG); for (int i = 0; i < 3; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int first = edgecoeffsindex[info.edgenrs[i]]; int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShapeLambda (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], [&](int i, AutoDiff<2,T> shape) { for (int k = 0; k < DIM_SPACE; k++) mapped_x[k] += edgecoeffs[first+i](k) * shape; }); } } int forder = faceorder[info.facenr]; if (forder >= 3) { int first = facecoeffsindex[info.facenr]; int fnums[] = { 0, 1, 2 }; if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); CalcScaledTrigShapeLambda (forder, lami[fnums[1]]-lami[fnums[0]], lami[fnums[2]], AutoDiff<2,T>(1.0), [&](int i, AutoDiff<2,T> shape) { for (int k = 0; k < DIM_SPACE; k++) mapped_x[k] += facecoeffs[first+i](k) * shape; }); } break; } case QUAD: { if (info.order >= 2) return false; // not yet supported AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; for (int j = 0; j < 4; j++) { Point<3> p = mesh[el[j]]; for (int k = 0; k < DIM_SPACE; k++) mapped_x[k] += p(k) * lami[j]; } break; } case QUAD8: { // AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; AutoDiff<2,T> lami[8] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y, 4*(1-x)*x*(1-y), 4*(1-x)*x*y, 4*(1-y)*y*(1-x), 4*(1-y)*y*x }; lami[0] -= 0.5*(lami[4]+lami[6]); lami[1] -= 0.5*(lami[4]+lami[7]); lami[2] -= 0.5*(lami[5]+lami[7]); lami[3] -= 0.5*(lami[5]+lami[6]); for (int j = 0; j < 8; j++) { Point<3> p = mesh[el[j]]; for (int k = 0; k < DIM_SPACE; k++) mapped_x[k] += p(k) * lami[j]; } break; } default: return false; } for (int i = 0; i < DIM_SPACE; i++) { mx(i) = mapped_x[i].Value(); for (int j = 0; j < 2; j++) jac(i,j) = mapped_x[i].DValue(j); } return true; } template void CurvedElements :: GetCoefficients (SurfaceElementInfo & info, Array > & coefs) const { const Element2d & el = mesh[info.elnr]; coefs.SetSize (info.ndof); for (int i = 0; i < info.nv; i++) { Point<3> hv = mesh[el[i]]; for (int j = 0; j < DIM_SPACE; j++) coefs[i](j) = hv(j); } if (info.order == 1) return; int ii = info.nv; for (int i = 0; i < info.edgenrs.Size(); i++) { int first = edgecoeffsindex[info.edgenrs[i]]; int next = edgecoeffsindex[info.edgenrs[i]+1]; for (int j = first; j < next; j++, ii++) for (int k = 0; k < DIM_SPACE; k++) coefs[ii](k) = edgecoeffs[j](k); } int first = facecoeffsindex[info.facenr]; int next = facecoeffsindex[info.facenr+1]; for (int j = first; j < next; j++, ii++) for (int k = 0; k < DIM_SPACE; k++) coefs[ii](k) = facecoeffs[j](k); } template void CurvedElements :: GetCoefficients<2> (SurfaceElementInfo & info, Array > & coefs) const; template void CurvedElements :: GetCoefficients<3> (SurfaceElementInfo & info, Array > & coefs) const; // ********************** Transform volume elements ******************* bool CurvedElements :: IsElementCurved (ElementIndex elnr) const { if (mesh[elnr].GetType() != TET) return true; if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; return mesh.coarsemesh->GetCurvedElements().IsElementCurved (hpref_el.coarse_elnr); } const Element & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); int nfaces = MeshTopology::GetNFaces (type); if (nfaces > 4) { // not a tet const ELEMENT_FACE * faces = MeshTopology::GetFaces0 (type); for (int j = 0; j < nfaces; j++) { if (faces[j][3] != -1) { // a quad face Point<3> pts[4]; for (int k = 0; k < 4; k++) pts[k] = mesh.Point(el[faces[j][k]]); Vec<3> twist = (pts[1] - pts[0]) - (pts[2]-pts[3]); if (twist.Length() > 1e-8 * (pts[1]-pts[0]).Length()) return true; } } } ElementInfo info; info.elnr = elnr; info.order = order; info.ndof = info.nv = MeshTopology::GetNPoints (type); if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); for (int i = 0; i < info.nedges; i++) info.edgenrs[i]--; info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); for (int i = 0; i < info.nfaces; i++) info.facenrs[i]--; for (int i = 0; i < info.nedges; i++) info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; for (int i = 0; i < info.nfaces; i++) info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; } return (info.ndof > info.nv); } bool CurvedElements :: IsElementHighOrder (ElementIndex elnr) const { if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; return mesh.coarsemesh->GetCurvedElements().IsElementHighOrder (hpref_el.coarse_elnr); } const Element & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); ElementInfo info; info.elnr = elnr; info.order = order; info.ndof = info.nv = MeshTopology::GetNPoints (type); if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); for (int i = 0; i < info.nedges; i++) info.edgenrs[i]--; info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); for (int i = 0; i < info.nfaces; i++) info.facenrs[i]--; for (int i = 0; i < info.nedges; i++) if (edgecoeffsindex[info.edgenrs[i]+1] > edgecoeffsindex[info.edgenrs[i]]) return true; for (int i = 0; i < info.nfaces; i++) if (facecoeffsindex[info.facenrs[i]+1] > facecoeffsindex[info.facenrs[i]]) return true; } return false; } void CurvedElements :: CalcElementTransformation (Point<3> xi, ElementIndex elnr, Point<3> * x, Mat<3,3> * dxdxi, // bool * curved, void * buffer, bool valid) { if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; // xi umrechnen double lami[8]; FlatVector vlami(8, lami); vlami = 0; mesh[elnr].GetShapeNew (xi, vlami); Mat<3,3> trans, dxdxic; if (dxdxi) { MatrixFixWidth<3> dlami(8); dlami = 0; mesh[elnr].GetDShapeNew (xi, dlami); trans = 0; for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) for (int i = 0; i < hpref_el.np; i++) trans(l,k) += hpref_el.param[i][l] * dlami(i, k); } Point<3> coarse_xi(0,0,0); for (int i = 0; i < hpref_el.np; i++) for (int j = 0; j < 3; j++) coarse_xi(j) += hpref_el.param[i][j] * lami[i]; mesh.coarsemesh->GetCurvedElements().CalcElementTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic /* , curved */); if (dxdxi) *dxdxi = dxdxic * trans; return; } const Element & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); ElementInfo hinfo; ElementInfo & info = (buffer) ? *static_cast (buffer) : hinfo; if (!valid) { info.elnr = elnr; info.order = order; info.ndof = info.nv = MeshTopology::GetNPoints (type); if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); for (int i = 0; i < info.nedges; i++) info.edgenrs[i]--; info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); for (int i = 0; i < info.nfaces; i++) info.facenrs[i]--; for (int i = 0; i < info.nedges; i++) info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; for (int i = 0; i < info.nfaces; i++) info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; } } ArrayMem mem(info.ndof); TFlatVector shapes(info.ndof, &mem[0]); ArrayMem dshapes_mem(info.ndof*3); MatrixFixWidth<3> dshapes(info.ndof, &dshapes_mem[0]); CalcElementShapes (info, xi, shapes); Vec<3> * coefs = (info.ndof <= 10) ? &info.hcoefs[0] : new Vec<3> [info.ndof]; if (info.ndof > 10 || !valid) GetCoefficients (info, coefs); if (x) { *x = 0; for (int i = 0; i < shapes.Size(); i++) *x += shapes(i) * coefs[i]; } if (dxdxi) { if (valid && info.order == 1 && info.nv == 4) // a linear tet { *dxdxi = info.hdxdxi; } else { CalcElementDShapes (info, xi, dshapes); *dxdxi = 0; for (int i = 0; i < shapes.Size(); i++) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) (*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j); info.hdxdxi = *dxdxi; } } // *testout << "curved_elements, dshapes = " << endl << dshapes << endl; // if (curved) *curved = (info.ndof > info.nv); if (info.ndof > 10) delete [] coefs; } template void CurvedElements :: CalcElementShapes (ElementInfo & info, Point<3,T> xi, TFlatVector shapes) const { const Element & el = mesh[info.elnr]; if (rational && info.order >= 2) { // shapes.SetSize(10); T w = 1; T lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) }; for (int j = 0; j < 4; j++) shapes(j) = lami[j] * lami[j]; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET); for (int j = 0; j < 6; j++) { double wi = edgeweight[info.edgenrs[j]]; shapes(j+4) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; } shapes *= 1.0 / w; return; } // shapes.SetSize(info.ndof); switch (el.GetType()) { case TET: { shapes(0) = xi(0); shapes(1) = xi(1); shapes(2) = xi(2); shapes(3) = 1-xi(0)-xi(1)-xi(2); if (info.order == 1) return; int ii = 4; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET); for (int i = 0; i < 6; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii)); ii += eorder-1; } } const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (TET); for (int i = 0; i < 4; i++) { int forder = faceorder[info.facenrs[i]]; if (forder >= 3) { int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); CalcScaledTrigShape (forder, shapes(fnums[1])-shapes(fnums[0]), shapes(fnums[2]), shapes(fnums[0])+shapes(fnums[1])+shapes(fnums[2]), &shapes(ii)); ii += (forder-1)*(forder-2)/2; } } break; } case TET10: { T x = xi(0); T y = xi(1); T z = xi(2); T lam4 = 1 - x - y - z; /* shapes(0) = xi(0); shapes(1) = xi(1); shapes(2) = xi(2); shapes(3) = 1-xi(0)-xi(1)-xi(2); */ shapes(0) = 2 * x * x - x; shapes(1) = 2 * y * y - y; shapes(2) = 2 * z * z - z; shapes(3) = 2 * lam4 * lam4 - lam4; shapes(4) = 4 * x * y; shapes(5) = 4 * x * z; shapes(6) = 4 * x * lam4; shapes(7) = 4 * y * z; shapes(8) = 4 * y * lam4; shapes(9) = 4 * z * lam4; break; } case PRISM: { T lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) }; T lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) }; for (int i = 0; i < 6; i++) shapes(i) = lami[i] * lamiz[i]; for (int i = 6; i < info.ndof; i++) shapes(i) = 0; if (info.order == 1) return; int ii = 6; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PRISM); for (int i = 0; i < 6; i++) // horizontal edges { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShape (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapes(ii)); T facz = (i < 3) ? (1-xi(2)) : xi(2); for (int j = 0; j < eorder-1; j++) shapes(ii+j) *= facz; ii += eorder-1; } } for (int i = 6; i < 9; i++) // vertical edges { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); T bubz = lamiz[vi1]*lamiz[vi2]; T polyz = lamiz[vi1] - lamiz[vi2]; T bubxy = lami[vi1]; for (int j = 0; j < eorder-1; j++) { shapes(ii+j) = bubxy * bubz; bubz *= polyz; } ii += eorder-1; } } // FACE SHAPES const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (PRISM); for (int i = 0; i < 2; i++) { int forder = faceorder[info.facenrs[i]]; if ( forder < 3 ) continue; int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]); if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); CalcTrigShape (forder, lami[fav[2]]-lami[fav[1]], lami[fav[0]], &shapes(ii)); int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1); for ( int j = 0; j < ndf; j++ ) shapes(ii+j) *= lamiz[fav[1]]; ii += ndf; } break; } case PRISM15: { shapes = 0.0; T x = xi(0); T y = xi(1); T z = xi(2); T lam = 1-x-y; T lamz = 1-z; shapes[0] = (2*x*x-x) * (2*lamz*lamz-lamz); shapes[1] = (2*y*y-y) * (2*lamz*lamz-lamz); shapes[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); shapes[3] = (2*x*x-x) * (2*z*z-z); shapes[4] = (2*y*y-y) * (2*z*z-z); shapes[5] = (2*lam*lam-lam) * (2*z*z-z); shapes[6] = 4 * x * y * (2*lamz*lamz-lamz); shapes[7] = 4 * x * lam * (2*lamz*lamz-lamz); shapes[8] = 4 * y * lam * (2*lamz*lamz-lamz); shapes[9] = x * 4 * z * (1-z); shapes[10] = y * 4 * z * (1-z); shapes[11] = lam * 4 * z * (1-z); shapes[12] = 4 * x * y * (2*z*z-z); shapes[13] = 4 * x * lam * (2*z*z-z); shapes[14] = 4 * y * lam * (2*z*z-z); break; } case PYRAMID: { shapes = 0.0; T x = xi(0); T y = xi(1); T z = xi(2); // if (z == 1.) z = 1-1e-10; z *= (1-1e-12); shapes[0] = (1-z-x)*(1-z-y) / (1-z); shapes[1] = x*(1-z-y) / (1-z); shapes[2] = x*y / (1-z); shapes[3] = (1-z-x)*y / (1-z); shapes[4] = z; if (info.order == 1) return; T sigma[4] = { sigma[0] = ( (1-z-x) + (1-z-y) ), sigma[1] = ( x + (1-z-y) ), sigma[2] = ( x + y ), sigma[3] = ( (1-z-x) + y ), }; int ii = 5; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PYRAMID); for (int i = 0; i < 4; i++) // horizontal edges { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1); if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShape (eorder, sigma[vi1]-sigma[vi2], 1-z, &shapes(ii)); T fac = (shapes[vi1]+shapes[vi2]) / (1-z); for (int j = 0; j < eorder-1; j++) shapes(ii+j) *= fac; ii += eorder-1; } } break; } case PYRAMID13: { shapes = 0.0; T x = xi(0); T y = xi(1); T z = xi(2); z *= 1-1e-12; shapes[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25); shapes[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2)); shapes[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75); shapes[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2)); shapes[4] = z*(2*z - 1); shapes[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); shapes[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2); shapes[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); shapes[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2); shapes[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); shapes[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1); shapes[11] = 4*x*y*z/(-z + 1); shapes[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1); break; } case HEX: { shapes = 0.0; T x = xi(0); T y = xi(1); T z = xi(2); shapes[0] = (1-x)*(1-y)*(1-z); shapes[1] = x *(1-y)*(1-z); shapes[2] = x * y *(1-z); shapes[3] = (1-x)* y *(1-z); shapes[4] = (1-x)*(1-y)*(z); shapes[5] = x *(1-y)*(z); shapes[6] = x * y *(z); shapes[7] = (1-x)* y *(z); if (info.order == 1) return; T mu[8] = { (1-x)+(1-y)+(1-z), x +(1-y)+(1-z), x + y +(1-z), (1-x)+ y +(1-z), (1-x)+(1-y)+(z), x +(1-y)+(z), x + y +(z), (1-x)+ y +(z), }; int ii = 8; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (HEX); for (int i = 0; i < 8; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcEdgeShape (eorder, mu[vi1]-mu[vi2], &shapes(ii)); T lame = shapes(vi1)+shapes(vi2); for (int j = 0; j < order-1; j++) shapes(ii+j) *= lame; ii += eorder-1; } } break; } case HEX20: { shapes = 0.0; T x = xi(0); T y = xi(1); T z = xi(2); shapes[0] = (1-x)*(1-y)*(1-z); shapes[1] = x *(1-y)*(1-z); shapes[2] = x * y *(1-z); shapes[3] = (1-x)* y *(1-z); shapes[4] = (1-x)*(1-y)*(z); shapes[5] = x *(1-y)*(z); shapes[6] = x * y *(z); shapes[7] = (1-x)* y *(z); T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; static const int e[12][2] = { { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, }; for (int i = 0; i < 12; i++) { T lame = shapes[e[i][0]]+shapes[e[i][1]]; T xi = sigma[e[i][1]]-sigma[e[i][0]]; shapes[8+i] = (1-xi*xi)*lame; } for (int i = 0; i < 12; i++) { shapes[e[i][0]] -= 0.5 * shapes[8+i]; shapes[e[i][1]] -= 0.5 * shapes[8+i]; } break; } default: throw NgException("CurvedElements::CalcShape 3d, element type not handled"); }; } template void CurvedElements :: CalcElementDShapes (ElementInfo & info, const Point<3,T> xi, MatrixFixWidth<3,T> dshapes) const { // static int timer = NgProfiler::CreateTimer ("calcelementdshapes"); const Element & el = mesh[info.elnr]; // dshapes.SetSize(info.ndof); if ( (long int)(&dshapes(0,0)) % alignof(T) != 0) throw NgException ("alignment problem"); if (dshapes.Height() != info.ndof) throw NgException ("wrong height"); if (rational && info.order >= 2) { T w = 1; T dw[3] = { 0, 0, 0 }; T lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) }; T dlami[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, -1, -1 }}; T shapes[10]; for (int j = 0; j < 4; j++) { shapes[j] = lami[j] * lami[j]; dshapes(j,0) = 2 * lami[j] * dlami[j][0]; dshapes(j,1) = 2 * lami[j] * dlami[j][1]; dshapes(j,2) = 2 * lami[j] * dlami[j][2]; } const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET); for (int j = 0; j < 6; j++) { T wi = edgeweight[info.edgenrs[j]]; shapes[j+4] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; for (int k = 0; k < 3; k++) dshapes(j+4,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; for (int k = 0; k < 3; k++) dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); } // shapes *= 1.0 / w; dshapes *= 1.0 / w; for (int i = 0; i < 10; i++) for (int j = 0; j < 3; j++) dshapes(i,j) -= shapes[i] * dw[j] / (w*w); return; } /* if (typeid(T) == typeid(SIMD)) { if (el.GetType() == HEX) dshapes = T(0.0); return; } */ switch (el.GetType()) { case TET: { // if (typeid(T) == typeid(SIMD)) return; dshapes = T(0.0); dshapes(0,0) = 1; dshapes(1,1) = 1; dshapes(2,2) = 1; dshapes(3,0) = -1; dshapes(3,1) = -1; dshapes(3,2) = -1; if (info.order == 1) return; T lami[] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) }; int ii = 4; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET); for (int i = 0; i < 6; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShapeDxDt<3> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0)); Mat<2,3,T> trans; for (int j = 0; j < 3; j++) { trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j); trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j); } for (int j = 0; j < order-1; j++) { T ddx = dshapes(ii+j,0); T ddt = dshapes(ii+j,1); dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); dshapes(ii+j,2) = ddx * trans(0,2) + ddt * trans(1,2); } ii += eorder-1; } } const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (TET); for (int i = 0; i < 4; i++) { int forder = faceorder[info.facenrs[i]]; if (forder >= 3) { int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); CalcScaledTrigShapeDxDyDt (forder, lami[fnums[1]]-lami[fnums[0]], lami[fnums[2]], lami[fnums[0]]+lami[fnums[1]]+lami[fnums[2]], &dshapes(ii,0)); Mat<3,3,T> trans; for (int j = 0; j < 3; j++) { trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j); trans(1,j) = dshapes(fnums[2],j); trans(2,j) = dshapes(fnums[0],j)+dshapes(fnums[1],j)+dshapes(fnums[2],j); } int nfd = (forder-1)*(forder-2)/2; for (int j = 0; j < nfd; j++) { T ddx = dshapes(ii+j,0); T ddy = dshapes(ii+j,1); T ddt = dshapes(ii+j,2); dshapes(ii+j,0) = ddx * trans(0,0) + ddy * trans(1,0) + ddt * trans(2,0); dshapes(ii+j,1) = ddx * trans(0,1) + ddy * trans(1,1) + ddt * trans(2,1); dshapes(ii+j,2) = ddx * trans(0,2) + ddy * trans(1,2) + ddt * trans(2,2); } ii += nfd; } } break; } case TET10: { // if (typeid(T) == typeid(SIMD)) return; if (dshapes.Height() == 4) { dshapes = T(0.0); dshapes(0,0) = 1; dshapes(1,1) = 1; dshapes(2,2) = 1; dshapes(3,0) = -1; dshapes(3,1) = -1; dshapes(3,2) = -1; } else { AutoDiff<3,T> x(xi(0), 0); AutoDiff<3,T> y(xi(1), 1); AutoDiff<3,T> z(xi(2), 2); AutoDiff<3,T> lam4 = 1-x-y-z; AutoDiff<3,T> shapes[10]; shapes[0] = 2 * x * x - x; shapes[1] = 2 * y * y - y; shapes[2] = 2 * z * z - z; shapes[3] = 2 * lam4 * lam4 - lam4; shapes[4] = 4 * x * y; shapes[5] = 4 * x * z; shapes[6] = 4 * x * lam4; shapes[7] = 4 * y * z; shapes[8] = 4 * y * lam4; shapes[9] = 4 * z * lam4; for (int i = 0; i < 10; i++) { dshapes(i,0) = shapes[i].DValue(0); dshapes(i,1) = shapes[i].DValue(1); dshapes(i,2) = shapes[i].DValue(2); } } break; break; } case PRISM: { T lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) }; T lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) }; T dlamiz[6] = { -1, -1, -1, 1, 1, 1 }; T dlami[6][2] = { { 1, 0, }, { 0, 1, }, { -1, -1 }, { 1, 0, }, { 0, 1, }, { -1, -1 } }; for (int i = 0; i < 6; i++) { // shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) ); dshapes(i,0) = dlami[i%3][0] * ( (i < 3) ? (1-xi(2)) : xi(2) ); dshapes(i,1) = dlami[i%3][1] * ( (i < 3) ? (1-xi(2)) : xi(2) ); dshapes(i,2) = lami[i%3] * ( (i < 3) ? -1 : 1 ); } int ii = 6; if (info.order == 1) return; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PRISM); for (int i = 0; i < 6; i++) // horizontal edges { int order = edgeorder[info.edgenrs[i]]; if (order >= 2) { int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1); if (el[vi1] > el[vi2]) swap (vi1, vi2); vi1 = vi1 % 3; vi2 = vi2 % 3; ArrayMem shapei_mem(order+1); TFlatVector shapei(order+1, &shapei_mem[0]); CalcScaledEdgeShapeDxDt<3> (order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0) ); CalcScaledEdgeShape(order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapei(0) ); Mat<2,2,T> trans; for (int j = 0; j < 2; j++) { trans(0,j) = dlami[vi1][j]-dlami[vi2][j]; trans(1,j) = dlami[vi1][j]+dlami[vi2][j]; } for (int j = 0; j < order-1; j++) { T ddx = dshapes(ii+j,0); T ddt = dshapes(ii+j,1); dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); } T facz = (i < 3) ? (1-xi(2)) : xi(2); T dfacz = (i < 3) ? (-1) : 1; for (int j = 0; j < order-1; j++) { dshapes(ii+j,0) *= facz; dshapes(ii+j,1) *= facz; dshapes(ii+j,2) = shapei(j) * dfacz; } ii += order-1; } } // if (typeid(T) == typeid(SIMD)) return; for (int i = 6; i < 9; i++) // vertical edges { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1); if (el[vi1] > el[vi2]) swap (vi1, vi2); T bubz = lamiz[vi1] * lamiz[vi2]; T dbubz = dlamiz[vi1]*lamiz[vi2] + lamiz[vi1]*dlamiz[vi2]; T polyz = lamiz[vi1] - lamiz[vi2]; T dpolyz = dlamiz[vi1] - dlamiz[vi2]; T bubxy = lami[(vi1)%3]; T dbubxydx = dlami[(vi1)%3][0]; T dbubxydy = dlami[(vi1)%3][1]; for (int j = 0; j < eorder-1; j++) { dshapes(ii+j,0) = dbubxydx * bubz; dshapes(ii+j,1) = dbubxydy * bubz; dshapes(ii+j,2) = bubxy * dbubz; dbubz = bubz * dpolyz + dbubz * polyz; bubz *= polyz; } ii += eorder-1; } } if (info.order == 2) return; // FACE SHAPES const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (PRISM); for (int i = 0; i < 2; i++) { int forder = faceorder[info.facenrs[i]]; if ( forder < 3 ) continue; int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1); int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]); if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); ArrayMem dshapei_mem(ndf); ArrayMem shapei_mem(ndf); MatrixFixWidth<2,T> dshapei(ndf, &dshapei_mem[0]); TFlatVector shapei(ndf, &shapei_mem[0]); CalcTrigShapeDxDy (forder, lami[fav[2]]-lami[fav[1]], lami[fav[0]], &dshapei(0,0)); CalcTrigShape (forder, lami[fav[2]]-lami[fav[1]], lami[fav[0]], &shapei(0)); Mat<2,2,T> trans; for (int j = 0; j < 2; j++) { trans(0,j) = dlami[fav[2]][j]-dlami[fav[1]][j]; trans(1,j) = dlami[fav[0]][j]; } for (int j = 0; j < ndf; j++) { // double ddx = dshapes(ii+j,0); // double ddt = dshapes(ii+j,1); T ddx = dshapei(j,0); T ddt = dshapei(j,1); dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); } for ( int j = 0; j < ndf; j++ ) { dshapes(ii+j,0) *= lamiz[fav[1]]; dshapes(ii+j,1) *= lamiz[fav[1]]; dshapes(ii+j,2) = shapei(j) * dlamiz[fav[1]]; } ii += ndf; } break; } case PRISM15: { AutoDiff<3,T> x(xi(0), 0); AutoDiff<3,T> y(xi(1), 1); AutoDiff<3,T> z(xi(2), 2); AutoDiff<3,T> ad[15]; AutoDiff<3,T> lam = 1-x-y; AutoDiff<3,T> lamz = 1-z; ad[0] = (2*x*x-x) * (2*lamz*lamz-lamz); ad[1] = (2*y*y-y) * (2*lamz*lamz-lamz); ad[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); ad[3] = (2*x*x-x) * (2*z*z-z); ad[4] = (2*y*y-y) * (2*z*z-z); ad[5] = (2*lam*lam-lam) * (2*z*z-z); ad[6] = 4 * x * y * (2*lamz*lamz-lamz); ad[7] = 4 * x * lam * (2*lamz*lamz-lamz); ad[8] = 4 * y * lam * (2*lamz*lamz-lamz); ad[9] = x * 4 * z * (1-z); ad[10] = y * 4 * z * (1-z); ad[11] = lam * 4 * z * (1-z); ad[12] = 4 * x * y * (2*z*z-z); ad[13] = 4 * x * lam * (2*z*z-z); ad[14] = 4 * y * lam * (2*z*z-z); for(int i=0; i<15; i++) for(int j=0; j<3; j++) dshapes(i,j) = ad[i].DValue(j); break; } case PYRAMID: { // if (typeid(T) == typeid(SIMD)) return; dshapes = T(0.0); T x = xi(0); T y = xi(1); T z = xi(2); // if (z == 1.) z = 1-1e-10; z *= 1-1e-12; T z1 = 1-z; T z2 = z1*z1; dshapes(0,0) = -(z1-y)/z1; dshapes(0,1) = -(z1-x)/z1; dshapes(0,2) = ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2; dshapes(1,0) = (z1-y)/z1; dshapes(1,1) = -x/z1; dshapes(1,2) = (-x*z1+x*(z1-y))/z2; dshapes(2,0) = y/z1; dshapes(2,1) = x/z1; dshapes(2,2) = x*y/z2; dshapes(3,0) = -y/z1; dshapes(3,1) = (z1-x)/z1; dshapes(3,2) = (-y*z1+y*(z1-x))/z2; dshapes(4,0) = 0; dshapes(4,1) = 0; dshapes(4,2) = 1; if (info.order == 1) return; int ii = 5; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (PYRAMID); // if (z == 1.) z = 1-1e-10; z *= 1-1e-12; T shapes[5]; shapes[0] = (1-z-x)*(1-z-y) / (1-z); shapes[1] = x*(1-z-y) / (1-z); shapes[2] = x*y / (1-z); shapes[3] = (1-z-x)*y / (1-z); shapes[4] = z; T sigma[4] = { ( (1-z-x) + (1-z-y) ), ( x + (1-z-y) ), ( x + y ), ( (1-z-x) + y ), }; T dsigma[4][3] = { { -1, -1, -2 }, { 1, -1, -1 }, { 1, 1, 0 }, { -1, 1, -1 } }; T dz[3] = { 0, 0, 1 }; for (int i = 0; i < 4; i++) // horizontal edges { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1); if (el[vi1] > el[vi2]) swap (vi1, vi2); ArrayMem shapei_mem(eorder+1); TFlatVector shapei(eorder+1,&shapei_mem[0]); CalcScaledEdgeShapeDxDt<3> (eorder, sigma[vi1]-sigma[vi2], 1-z, &dshapes(ii,0) ); CalcScaledEdgeShape(eorder, sigma[vi1]-sigma[vi2], 1-z, &shapei(0) ); T fac = (shapes[vi1]+shapes[vi2]) / (1-z); T dfac[3]; for (int k = 0; k < 3; k++) dfac[k] = ( (dshapes(vi1,k)+dshapes(vi2,k)) * (1-z) - (shapes[vi1]+shapes[vi2]) *(-dshapes(4,k)) ) / sqr(1-z); for (int j = 0; j < eorder-1; j++) { T ddx = dshapes(ii+j,0); T ddt = dshapes(ii+j,1); for (int k = 0; k < 3; k++) dshapes(ii+j,k) = fac * (ddx * (dsigma[vi1][k]-dsigma[vi2][k]) - ddt*dz[k]) + dfac[k] * shapei(j); } ii += eorder-1; } } break; } case PYRAMID13: { T x = xi(0); T y = xi(1); T z = xi(2); z *= 1-1e-12; dshapes(0,0) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1) - 4); dshapes(0,1) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1) - 4); dshapes(0,2) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 5 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); dshapes(1,0) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(-2*y - z + 2) + (0.5*x - 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1) + 4); dshapes(1,1) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*x + z)*(-2*y - z + 2) + (-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x - 0.5*y - 0.25); dshapes(1,2) = (0.5*x - 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); dshapes(2,0) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75); dshapes(2,1) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75); dshapes(2,2) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (0.5*x + 0.5*y + 0.5*z - 0.75)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 1 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); dshapes(3,0) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1)); dshapes(3,1) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1) + 4); dshapes(3,2) = (-0.5*x + 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); dshapes(4,0) = 0; dshapes(4,1) = 0; dshapes(4,2) = 4*z - 1; dshapes(5,0) = -4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); dshapes(5,1) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2); dshapes(5,2) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2) - 4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 4*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); dshapes(6,0) = -8*x*y/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)/(-2*z + 2); dshapes(6,1) = 4*x*(-2*x - 2*z + 2)/(-2*z + 2); dshapes(6,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*x - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); dshapes(7,0) = -4*y*(-2*y - 2*z + 2)/(-2*z + 2); dshapes(7,1) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); dshapes(7,2) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) - 4*y*(-2*y - 2*z + 2)/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); dshapes(8,0) = 4*y*(-2*y - 2*z + 2)/(-2*z + 2); dshapes(8,1) = -8*x*y/(-2*z + 2) + 4*x*(-2*y - 2*z + 2)/(-2*z + 2); dshapes(8,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); dshapes(9,0) = -2*z*(-2*y - 2*z + 2)/(-z + 1); dshapes(9,1) = -2*z*(-2*x - 2*z + 2)/(-z + 1); dshapes(9,2) = -2*z*(-2*x - 2*z + 2)/(-z + 1) - 2*z*(-2*y - 2*z + 2)/(-z + 1) + z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + (-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); dshapes(10,0) = 2*z*(-2*y - 2*z + 2)/(-z + 1); dshapes(10,1) = -4*x*z/(-z + 1); dshapes(10,2) = -4*x*z/(-z + 1) + 2*x*z*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*x*(-2*y - 2*z + 2)/(-z + 1); dshapes(11,0) = 4*y*z/(-z + 1); dshapes(11,1) = 4*x*z/(-z + 1); dshapes(11,2) = 4*x*y*z/((-z + 1)*(-z + 1)) + 4*x*y/(-z + 1); dshapes(12,0) = -4*y*z/(-z + 1); dshapes(12,1) = 2*z*(-2*x - 2*z + 2)/(-z + 1); dshapes(12,2) = -4*y*z/(-z + 1) + 2*y*z*(-2*x - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*y*(-2*x - 2*z + 2)/(-z + 1); break; } case HEX: { // if (typeid(T) == typeid(SIMD)) return; // NgProfiler::StartTimer(timer); T x = xi(0); T y = xi(1); T z = xi(2); // shapes[0] = (1-x)*(1-y)*(1-z); dshapes(0,0) = - (1-y)*(1-z); dshapes(0,1) = (1-x) * (-1) * (1-z); dshapes(0,2) = (1-x) * (1-y) * (-1); // shapes[1] = x *(1-y)*(1-z); dshapes(1,0) = (1-y)*(1-z); dshapes(1,1) = -x * (1-z); dshapes(1,2) = -x * (1-y); // shapes[2] = x * y *(1-z); dshapes(2,0) = y * (1-z); dshapes(2,1) = x * (1-z); dshapes(2,2) = -x * y; // shapes[3] = (1-x)* y *(1-z); dshapes(3,0) = -y * (1-z); dshapes(3,1) = (1-x) * (1-z); dshapes(3,2) = -(1-x) * y; // shapes[4] = (1-x)*(1-y)*z; dshapes(4,0) = - (1-y)*z; dshapes(4,1) = (1-x) * (-1) * z; dshapes(4,2) = (1-x) * (1-y) * 1; // shapes[5] = x *(1-y)*z; dshapes(5,0) = (1-y)*z; dshapes(5,1) = -x * z; dshapes(5,2) = x * (1-y); // shapes[6] = x * y *z; dshapes(6,0) = y * z; dshapes(6,1) = x * z; dshapes(6,2) = x * y; // shapes[7] = (1-x)* y *z; dshapes(7,0) = -y * z; dshapes(7,1) = (1-x) * z; dshapes(7,2) = (1-x) * y; // NgProfiler::StopTimer(timer); if (info.order == 1) return; T shapes[8] = { (1-x)*(1-y)*(1-z), x *(1-y)*(1-z), x * y *(1-z), (1-x)* y *(1-z), (1-x)*(1-y)*(z), x *(1-y)*(z), x * y *(z), (1-x)* y *(z), }; T mu[8] = { (1-x)+(1-y)+(1-z), x +(1-y)+(1-z), x + y +(1-z), (1-x)+ y +(1-z), (1-x)+(1-y)+(z), x +(1-y)+(z), x + y +(z), (1-x)+ y +(z) }; T dmu[8][3] = { { -1, -1, -1 }, { 1, -1, -1 }, { 1, 1, -1 }, { -1, 1, -1 }, { -1, -1, 1 }, { 1, -1, 1 }, { 1, 1, 1 }, { -1, 1, 1 } }; ArrayMem hshapes(order+1), hdshapes(order+1); int ii = 8; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (HEX); for (int i = 0; i < 8; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcEdgeShapeDx (eorder, mu[vi1]-mu[vi2], &hshapes[0], &hdshapes[0]); T lame = shapes[vi1]+shapes[vi2]; T dlame[3] = { dshapes(vi1, 0) + dshapes(vi2, 0), dshapes(vi1, 1) + dshapes(vi2, 1), dshapes(vi1, 2) + dshapes(vi2, 2) }; for (int j = 0; j < eorder-1; j++) for (int k = 0; k < 3; k++) dshapes(ii+j, k) = lame * hdshapes[j] * (dmu[vi1][k]-dmu[vi2][k]) + dlame[k] * hshapes[j]; ii += eorder-1; } } /* *testout << "quad, dshape = " << endl << dshapes << endl; for (int i = 0; i < 2; i++) { Point<2> xil = xi, xir = xi; Vector shapesl(dshapes.Height()), shapesr(dshapes.Height()); xil(i) -= 1e-6; xir(i) += 1e-6; CalcElementShapes (info, xil, shapesl); CalcElementShapes (info, xir, shapesr); for (int j = 0; j < dshapes.Height(); j++) dshapes(j,i) = 1.0 / 2e-6 * (shapesr(j)-shapesl(j)); } *testout << "quad, num dshape = " << endl << dshapes << endl; */ break; } case HEX20: { AutoDiff<3,T> x(xi(0), 0); AutoDiff<3,T> y(xi(1), 1); AutoDiff<3,T> z(xi(2), 2); AutoDiff<3,T> ad[20]; ad[0] = (1-x)*(1-y)*(1-z); ad[1] = x *(1-y)*(1-z); ad[2] = x * y *(1-z); ad[3] = (1-x)* y *(1-z); ad[4] = (1-x)*(1-y)*(z); ad[5] = x *(1-y)*(z); ad[6] = x * y *(z); ad[7] = (1-x)* y *(z); AutoDiff<3,T> sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; static const int e[12][2] = { { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, }; for (int i = 0; i < 12; i++) { auto lame = ad[e[i][0]]+ad[e[i][1]]; auto xi = sigma[e[i][1]]-sigma[e[i][0]]; ad[8+i] = (1-xi*xi)*lame; } for (int i = 0; i < 12; i++) { ad[e[i][0]] -= 0.5 * ad[8+i]; ad[e[i][1]] -= 0.5 * ad[8+i]; } for (int i = 0; i < 20; i++) for (int j = 0; j < 3; j++) dshapes(i,j) = ad[i].DValue(j); break; } default: throw NgException("CurvedElements::CalcDShape 3d, element type not handled"); } /* DenseMatrix dshapes2 (info.ndof, 3); Vector shapesl(info.ndof); Vector shapesr(info.ndof); double eps = 1e-6; for (int i = 0; i < 3; i++) { Point<3> xl = xi; Point<3> xr = xi; xl(i) -= eps; xr(i) += eps; CalcElementShapes (info, xl, shapesl); CalcElementShapes (info, xr, shapesr); for (int j = 0; j < info.ndof; j++) dshapes2(j,i) = (shapesr(j)-shapesl(j)) / (2*eps); } (*testout) << "dshapes = " << endl << dshapes << endl; (*testout) << "dshapes2 = " << endl << dshapes2 << endl; dshapes2 -= dshapes; (*testout) << "diff = " << endl << dshapes2 << endl; */ } // extern int mappingvar; template bool CurvedElements :: EvaluateMapping (ElementInfo & info, Point<3,T> xi, Point<3,T> & mx, Mat<3,3,T> & jac) const { const Element & el = mesh[info.elnr]; if (rational && info.order >= 2) return false; // not supported AutoDiff<3,T> x(xi(0), 0); AutoDiff<3,T> y(xi(1), 1); AutoDiff<3,T> z(xi(2), 2); AutoDiff<3,T> mapped_x[3] = { T(0.0), T(0.0), T(0.0) } ; switch (el.GetType()) { case TET: { // if (info.order >= 2) return false; // not yet supported AutoDiff<3,T> lami[4] = { x, y, z, 1-x-y-z }; for (int j = 0; j < 4; j++) { Point<3> p = mesh[el[j]]; for (int k = 0; k < 3; k++) mapped_x[k] += p(k) * lami[j]; } if (info.order == 1) break; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (TET); for (int i = 0; i < 6; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int first = edgecoeffsindex[info.edgenrs[i]]; int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); CalcScaledEdgeShapeLambda (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], [&](int i, AutoDiff<3,T> shape) { Vec<3> coef = edgecoeffs[first+i]; for (int k = 0; k < 3; k++) mapped_x[k] += coef(k) * shape; }); } } const ELEMENT_FACE * faces = MeshTopology::GetFaces1 (TET); for (int i = 0; i < 4; i++) { int forder = faceorder[info.facenrs[i]]; if (forder >= 3) { int first = facecoeffsindex[info.facenrs[i]]; int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); CalcScaledTrigShapeLambda (forder, lami[fnums[1]]-lami[fnums[0]], lami[fnums[2]], lami[fnums[0]]+lami[fnums[1]]+lami[fnums[2]], [&](int i, AutoDiff<3,T> shape) { Vec<3> coef = facecoeffs[first+i]; for (int k = 0; k < 3; k++) mapped_x[k] += coef(k) * shape; }); } } break; } case HEX: { if (info.order >= 2) return false; // not yet supported AutoDiff<3,T> lami[8] = { (1-x)*(1-y)*(1-z), ( x)*(1-y)*(1-z), ( x)* y *(1-z), (1-x)* y *(1-z), (1-x)*(1-y)*(z), ( x)*(1-y)*(z), ( x)* y *(z), (1-x)* y *(z) }; for (int j = 0; j < 8; j++) { Point<3> p = mesh[el[j]]; for (int k = 0; k < 3; k++) mapped_x[k] += p(k) * lami[j]; } if (info.order == 1) break; AutoDiff<3,T> mu[8] = { (1-x)+(1-y)+(1-z), x +(1-y)+(1-z), x + y +(1-z), (1-x)+ y +(1-z), (1-x)+(1-y)+(z), x +(1-y)+(z), x + y +(z), (1-x)+ y +(z), }; // int ii = 8; const ELEMENT_EDGE * edges = MeshTopology::GetEdges1 (HEX); for (int i = 0; i < 8; i++) { int eorder = edgeorder[info.edgenrs[i]]; if (eorder >= 2) { int first = edgecoeffsindex[info.edgenrs[i]]; int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; if (el[vi1] > el[vi2]) swap (vi1, vi2); AutoDiff<3,T> lame = lami[vi1]+lami[vi2]; CalcEdgeShapeLambda (eorder, mu[vi1]-mu[vi2], [&](int i, AutoDiff<3,T> shape) { Vec<3> coef = edgecoeffs[first+i]; for (int k = 0; k < 3; k++) mapped_x[k] += coef(k) * (lame*shape); }); } } break; } default: return false; } for (int i = 0; i < 3; i++) { mx(i) = mapped_x[i].Value(); for (int j = 0; j < 3; j++) jac(i,j) = mapped_x[i].DValue(j); } return true; } void CurvedElements :: GetCoefficients (ElementInfo & info, Vec<3> * coefs) const { const Element & el = mesh[info.elnr]; for (int i = 0; i < info.nv; i++) coefs[i] = Vec<3> (mesh[el[i]]); if (info.order == 1) return; int ii = info.nv; for (int i = 0; i < info.nedges; i++) { int first = edgecoeffsindex[info.edgenrs[i]]; int next = edgecoeffsindex[info.edgenrs[i]+1]; for (int j = first; j < next; j++, ii++) coefs[ii] = edgecoeffs[j]; } for (int i = 0; i < info.nfaces; i++) { int first = facecoeffsindex[info.facenrs[i]]; int next = facecoeffsindex[info.facenrs[i]+1]; for (int j = first; j < next; j++, ii++) coefs[ii] = facecoeffs[j]; } } /* void CurvedElements :: CalcMultiPointSegmentTransformation (Array * xi, SegmentIndex segnr, Array > * x, Array > * dxdxi) { ; } */ template void CurvedElements :: CalcMultiPointSegmentTransformation (SegmentIndex elnr, int n, const T * xi, size_t sxi, T * x, size_t sx, T * dxdxi, size_t sdxdxi) { for (int ip = 0; ip < n; ip++) { Point<3,T> xg; Vec<3,T> dx; // mesh->GetCurvedElements(). CalcSegmentTransformation (xi[ip*sxi], elnr, &xg, &dx); if (x) for (int i = 0; i < DIM_SPACE; i++) x[ip*sx+i] = xg(i); if (dxdxi) for (int i=0; i (SegmentIndex elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcMultiPointSegmentTransformation<3> (SegmentIndex elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcMultiPointSegmentTransformation<2> (SegmentIndex elnr, int npts, const SIMD * xi, size_t sxi, SIMD * x, size_t sx, SIMD * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcMultiPointSegmentTransformation<3> (SegmentIndex elnr, int npts, const SIMD * xi, size_t sxi, SIMD * x, size_t sx, SIMD * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcSegmentTransformation (double xi, SegmentIndex elnr, Point<3,double> * x, Vec<3,double> * dxdxi, bool * curved); void CurvedElements :: CalcMultiPointSurfaceTransformation (Array< Point<2> > * xi, SurfaceElementIndex elnr, Array< Point<3> > * x, Array< Mat<3,2> > * dxdxi) { double * px = (x) ? &(*x)[0](0) : NULL; double * pdxdxi = (dxdxi) ? &(*dxdxi)[0](0) : NULL; CalcMultiPointSurfaceTransformation <3> (elnr, xi->Size(), &(*xi)[0](0), 2, px, 3, pdxdxi, 6); } template void CurvedElements :: CalcMultiPointSurfaceTransformation (SurfaceElementIndex elnr, int npts, const T * xi, size_t sxi, T * x, size_t sx, T * dxdxi, size_t sdxdxi) { if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; // xi umrechnen T lami[4]; TFlatVector vlami(4, lami); ArrayMem, 50> coarse_xi (npts); for (int pi = 0; pi < npts; pi++) { vlami = 0; Point<2,T> hxi(xi[pi*sxi], xi[pi*sxi+1]); mesh[elnr].GetShapeNew ( hxi, vlami); Point<2,T> cxi(0,0); for (int i = 0; i < hpref_el.np; i++) for (int j = 0; j < 2; j++) cxi(j) += hpref_el.param[i][j] * lami[i]; coarse_xi[pi] = cxi; } mesh.coarsemesh->GetCurvedElements(). CalcMultiPointSurfaceTransformation (hpref_el.coarse_elnr, npts, &coarse_xi[0](0), &coarse_xi[1](0)-&coarse_xi[0](0), x, sx, dxdxi, sdxdxi); // Mat<3,2> dxdxic; if (dxdxi) { T mem_dlami[8]; // avoid alignment problems if T is SIMD MatrixFixWidth<2,T> dlami(4, mem_dlami); dlami = T(0.0); for (int pi = 0; pi < npts; pi++) { Point<2,T> hxi(xi[pi*sxi], xi[pi*sxi+1]); mesh[elnr].GetDShapeNew ( hxi, dlami); Mat<2,2,T> trans; trans = 0; for (int k = 0; k < 2; k++) for (int l = 0; l < 2; l++) for (int i = 0; i < hpref_el.np; i++) trans(l,k) += hpref_el.param[i][l] * dlami(i, k); Mat hdxdxic, hdxdxi; for (int k = 0; k < 2*DIM_SPACE; k++) hdxdxic(k) = dxdxi[pi*sdxdxi+k]; hdxdxi = hdxdxic * trans; for (int k = 0; k < 2*DIM_SPACE; k++) dxdxi[pi*sdxdxi+k] = hdxdxi(k); // dxdxic = (*dxdxi)[pi]; // (*dxdxi)[pi] = dxdxic * trans; } } return; } const Element2d & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); SurfaceElementInfo info; info.elnr = elnr; info.order = order; switch (type) { case TRIG : info.nv = 3; break; case QUAD : info.nv = 4; break; case TRIG6: info.nv = 6; break; case QUAD8 : info.nv = 8; break; default: cerr << "undef element in CalcMultPointSurfaceTrafo" << endl; } info.ndof = info.nv; // if (info.order > 1) // { // const MeshTopology & top = mesh.GetTopology(); // top.GetSurfaceElementEdges (elnr+1, info.edgenrs); // for (int i = 0; i < info.edgenrs.Size(); i++) // info.edgenrs[i]--; // info.facenr = top.GetSurfaceElementFace (elnr+1)-1; // for (int i = 0; i < info.edgenrs.Size(); i++) // info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; // info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; // } // Michael Woopen: THESE FOLLOWING LINES ARE COPIED FROM CurvedElements::CalcSurfaceTransformation if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); top.GetSurfaceElementEdges (elnr+1, info.edgenrs); for (int i = 0; i < info.edgenrs.Size(); i++) info.edgenrs[i]--; info.facenr = top.GetSurfaceElementFace (elnr+1)-1; bool firsttry = true; bool problem = false; while(firsttry || problem) { problem = false; for (int i = 0; !problem && i < info.edgenrs.Size(); i++) { if(info.edgenrs[i]+1 >= edgecoeffsindex.Size()) problem = true; else info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; } if(info.facenr+1 >= facecoeffsindex.Size()) problem = true; else info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; if(problem && !firsttry) throw NgException("something wrong with curved elements"); if(problem) BuildCurvedElements(NULL,order,rational); firsttry = false; } } bool ok = true; for (int i = 0; i < npts; i++) { Point<2,T> _xi(xi[i*sxi], xi[i*sxi+1]); Point _x; Mat _dxdxi; if (!EvaluateMapping (info, _xi, _x, _dxdxi)) { ok = false; break; } // *testout << "x = " << _x << ", dxdxi = " << _dxdxi << endl; if (x) for (int j = 0; j < DIM_SPACE; j++) x[i*sx+j] = _x[j]; if (dxdxi) for (int j = 0; j < DIM_SPACE; j++) for (int k = 0; k < 2; k++) dxdxi[i*sdxdxi+2*j+k] = _dxdxi(j,k); } if (ok) return; // THESE LAST LINES ARE COPIED FROM CurvedElements::CalcSurfaceTransformation ArrayMem,100> coefs(info.ndof); GetCoefficients (info, coefs); ArrayMem shapes_mem(info.ndof); TFlatVector shapes(info.ndof, &shapes_mem[0]); ArrayMem dshapes_mem(info.ndof*2); MatrixFixWidth<2,T> dshapes(info.ndof,&shapes_mem[0]); if (x) { if (info.order == 1 && type == TRIG) { for (int j = 0; j < npts; j++) { Point<2,T> vxi(xi[j*sxi], xi[j*sxi+1]); Point val; for (int k = 0; k < DIM_SPACE; k++) val(k) = coefs[2](k) + (coefs[0](k)-coefs[2](k)) * vxi(0) + (coefs[1](k)-coefs[2](k)) * vxi(1); /* (coefs[2]); val += (coefs[0]-coefs[2]) * vxi(0); val += (coefs[1]-coefs[2]) * vxi(1); */ for (int k = 0; k < DIM_SPACE; k++) x[j*sx+k] = val(k); } } else for (int j = 0; j < npts; j++) { Point<2,T> vxi(xi[j*sxi], xi[j*sxi+1]); CalcElementShapes (info, vxi, shapes); Point val = T(0.0); for (int i = 0; i < coefs.Size(); i++) for (int k = 0; k < DIM_SPACE; k++) val(k) += shapes(i) * coefs[i](k); for (int k = 0; k < DIM_SPACE; k++) x[j*sx+k] = val(k); } } if (dxdxi) { if (info.order == 1 && type == TRIG) { Point<2,T> xij(xi[0], xi[1]); CalcElementDShapes (info, xij, dshapes); Mat<3,2,T> dxdxij; dxdxij = 0.0; for (int i = 0; i < coefs.Size(); i++) for (int j = 0; j < DIM_SPACE; j++) for (int k = 0; k < 2; k++) dxdxij(j,k) += dshapes(i,k) * coefs[i](j); for (int ip = 0; ip < npts; ip++) for (int j = 0; j < DIM_SPACE; j++) for (int k = 0; k < 2; k++) dxdxi[ip*sdxdxi+2*j+k] = dxdxij(j,k); } else { for (int j = 0; j < npts; j++) { Point<2,T> vxi(xi[j*sxi], xi[j*sxi+1]); CalcElementDShapes (info, vxi, dshapes); Mat ds; ds = 0.0; for (int i = 0; i < coefs.Size(); i++) for (int j = 0; j < DIM_SPACE; j++) for (int k = 0; k < 2; k++) ds(j,k) += dshapes(i,k) * coefs[i](j); // (*dxdxi)[ip] = ds; for (int k = 0; k < 2*DIM_SPACE; k++) dxdxi[j*sdxdxi+k] = ds(k); } } } } template void CurvedElements :: CalcMultiPointSurfaceTransformation<2> (SurfaceElementIndex elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcMultiPointSurfaceTransformation<3> (SurfaceElementIndex elnr, int npts, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcMultiPointSurfaceTransformation<2> (SurfaceElementIndex elnr, int npts, const SIMD * xi, size_t sxi, SIMD * x, size_t sx, SIMD * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcMultiPointSurfaceTransformation<3> (SurfaceElementIndex elnr, int npts, const SIMD * xi, size_t sxi, SIMD * x, size_t sx, SIMD * dxdxi, size_t sdxdxi); void CurvedElements :: CalcMultiPointElementTransformation (Array< Point<3> > * xi, ElementIndex elnr, Array< Point<3> > * x, Array< Mat<3,3> > * dxdxi) { double * px = (x) ? &(*x)[0](0) : NULL; double * pdxdxi = (dxdxi) ? &(*dxdxi)[0](0) : NULL; CalcMultiPointElementTransformation (elnr, xi->Size(), &(*xi)[0](0), 3, px, 3, pdxdxi, 9); return; #ifdef OLD if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; // xi umrechnen double lami[8]; FlatVector vlami(8, lami); ArrayMem, 50> coarse_xi (xi->Size()); for (int pi = 0; pi < xi->Size(); pi++) { vlami = 0; mesh[elnr].GetShapeNew ( (*xi)[pi], vlami); Point<3> cxi(0,0,0); for (int i = 0; i < hpref_el.np; i++) for (int j = 0; j < 3; j++) cxi(j) += hpref_el.param[i][j] * lami[i]; coarse_xi[pi] = cxi; } mesh.coarsemesh->GetCurvedElements(). CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi); Mat<3,3> trans, dxdxic; if (dxdxi) { MatrixFixWidth<3> dlami(8); dlami = 0; for (int pi = 0; pi < xi->Size(); pi++) { mesh[elnr].GetDShapeNew ( (*xi)[pi], dlami); trans = 0; for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) for (int i = 0; i < hpref_el.np; i++) trans(l,k) += hpref_el.param[i][l] * dlami(i, k); dxdxic = (*dxdxi)[pi]; (*dxdxi)[pi] = dxdxic * trans; } } return; } Vector shapes; MatrixFixWidth<3> dshapes; const Element & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); ElementInfo info; info.elnr = elnr; info.order = order; info.ndof = info.nv = MeshTopology::GetNPoints (type); if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); for (int i = 0; i < info.nedges; i++) info.edgenrs[i]--; info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); for (int i = 0; i < info.nfaces; i++) info.facenrs[i]--; for (int i = 0; i < info.nedges; i++) info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; for (int i = 0; i < info.nfaces; i++) info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; // info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; } Array > coefs(info.ndof); GetCoefficients (info, &coefs[0]); if (x) { for (int j = 0; j < xi->Size(); j++) { CalcElementShapes (info, (*xi)[j], shapes); (*x)[j] = 0; for (int i = 0; i < coefs.Size(); i++) (*x)[j] += shapes(i) * coefs[i]; } } if (dxdxi) { if (info.order == 1 && type == TET) { if (xi->Size() > 0) { CalcElementDShapes (info, (*xi)[0], dshapes); Mat<3,3> ds; ds = 0; for (int i = 0; i < coefs.Size(); i++) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) ds(j,k) += dshapes(i,k) * coefs[i](j); for (int ip = 0; ip < xi->Size(); ip++) (*dxdxi)[ip] = ds; } } else for (int ip = 0; ip < xi->Size(); ip++) { CalcElementDShapes (info, (*xi)[ip], dshapes); Mat<3,3> ds; ds = 0; for (int i = 0; i < coefs.Size(); i++) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) ds(j,k) += dshapes(i,k) * coefs[i](j); (*dxdxi)[ip] = ds; } } #endif } // extern int multipointtrafovar; template void CurvedElements :: CalcMultiPointElementTransformation (ElementIndex elnr, int n, const T * xi, size_t sxi, T * x, size_t sx, T * dxdxi, size_t sdxdxi) { // multipointtrafovar++; /* static int timer = NgProfiler::CreateTimer ("calcmultipointelementtrafo"); static int timer1 = NgProfiler::CreateTimer ("calcmultipointelementtrafo 1"); static int timer2 = NgProfiler::CreateTimer ("calcmultipointelementtrafo 2"); static int timer3 = NgProfiler::CreateTimer ("calcmultipointelementtrafo 3"); static int timer4 = NgProfiler::CreateTimer ("calcmultipointelementtrafo 4"); static int timer5 = NgProfiler::CreateTimer ("calcmultipointelementtrafo 5"); NgProfiler::RegionTimer reg(timer); */ // NgProfiler::StartTimer (timer); // NgProfiler::StartTimer (timer1); if (mesh.coarsemesh) { const HPRefElement & hpref_el = (*mesh.hpelements) [mesh[elnr].hp_elnr]; // xi umrechnen T lami[8]; TFlatVector vlami(8, &lami[0]); ArrayMem coarse_xi (3*n); for (int pi = 0; pi < n; pi++) { vlami = 0; Point<3,T> pxi; for (int j = 0; j < 3; j++) pxi(j) = xi[pi*sxi+j]; mesh[elnr].GetShapeNew (pxi, vlami); Point<3,T> cxi(0,0,0); for (int i = 0; i < hpref_el.np; i++) for (int j = 0; j < 3; j++) cxi(j) += hpref_el.param[i][j] * lami[i]; for (int j = 0; j < 3; j++) coarse_xi[3*pi+j] = cxi(j); } mesh.coarsemesh->GetCurvedElements(). CalcMultiPointElementTransformation (hpref_el.coarse_elnr, n, &coarse_xi[0], 3, x, sx, dxdxi, sdxdxi); Mat<3,3,T> trans, dxdxic; if (dxdxi) { MatrixFixWidth<3,T> dlami(8); dlami = T(0); for (int pi = 0; pi < n; pi++) { Point<3,T> pxi; for (int j = 0; j < 3; j++) pxi(j) = xi[pi*sxi+j]; mesh[elnr].GetDShapeNew (pxi, dlami); trans = 0; for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) for (int i = 0; i < hpref_el.np; i++) trans(l,k) += hpref_el.param[i][l] * dlami(i, k); Mat<3,3,T> mat_dxdxic, mat_dxdxi; for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) mat_dxdxic(j,k) = dxdxi[pi*sdxdxi+3*j+k]; mat_dxdxi = mat_dxdxic * trans; for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) dxdxi[pi*sdxdxi+3*j+k] = mat_dxdxi(j,k); // dxdxic = (*dxdxi)[pi]; // (*dxdxi)[pi] = dxdxic * trans; } } return; } // NgProfiler::StopTimer (timer1); // NgProfiler::StartTimer (timer2); const Element & el = mesh[elnr]; ELEMENT_TYPE type = el.GetType(); ElementInfo info; info.elnr = elnr; info.order = order; info.ndof = info.nv = MeshTopology::GetNPoints (type); if (info.order > 1) { const MeshTopology & top = mesh.GetTopology(); info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); for (int i = 0; i < info.nedges; i++) info.edgenrs[i]--; info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); for (int i = 0; i < info.nfaces; i++) info.facenrs[i]--; for (int i = 0; i < info.nedges; i++) info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; for (int i = 0; i < info.nfaces; i++) info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; // info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; } // NgProfiler::StopTimer (timer2); // NgProfiler::StartTimer (timer3); bool ok = true; for (int i = 0; i < n; i++) { Point<3,T> _xi(xi[i*sxi], xi[i*sxi+1], xi[i*sxi+2]); Point<3,T> _x; Mat<3,3,T> _dxdxi; if (!EvaluateMapping (info, _xi, _x, _dxdxi)) { ok = false; break; } // cout << "x = " << _x << ", dxdxi = " << _dxdxi << endl; if (x) for (int j = 0; j < 3; j++) x[i*sx+j] = _x[j]; if (dxdxi) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) dxdxi[i*sdxdxi+3*j+k] = _dxdxi(j,k); } if (ok) return; ArrayMem,100> coefs(info.ndof); ArrayMem shapes_mem(info.ndof); TFlatVector shapes(info.ndof, &shapes_mem[0]); ArrayMem dshapes_mem(3*info.ndof); MatrixFixWidth<3,T> dshapes(info.ndof, &dshapes_mem[0]); // NgProfiler::StopTimer (timer3); // NgProfiler::StartTimer (timer4); GetCoefficients (info, &coefs[0]); if (x) { for (int j = 0; j < n; j++) { Point<3,T> xij, xj; for (int k = 0; k < 3; k++) xij(k) = xi[j*sxi+k]; CalcElementShapes (info, xij, shapes); xj = T(0.0); for (int i = 0; i < coefs.Size(); i++) for (int k = 0; k < 3; k++) xj(k) += shapes(i) * coefs[i](k); // cout << "old, xj = " << xj << endl; for (int k = 0; k < 3; k++) x[j*sx+k] = xj(k); } } // NgProfiler::StopTimer (timer4); // NgProfiler::StartTimer (timer5); if (dxdxi) { if (info.order == 1 && type == TET) { if (n > 0) { Point<3,T> xij; for (int k = 0; k < 3; k++) xij(k) = xi[k]; CalcElementDShapes (info, xij, dshapes); Mat<3,3,T> dxdxij; dxdxij = 0.0; for (int i = 0; i < coefs.Size(); i++) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) dxdxij(j,k) += dshapes(i,k) * coefs[i](j); for (int ip = 0; ip < n; ip++) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k); } } else { for (int ip = 0; ip < n; ip++) { Point<3,T> xij; for (int k = 0; k < 3; k++) xij(k) = xi[ip*sxi+k]; CalcElementDShapes (info, xij, dshapes); Mat<3,3,T> dxdxij; dxdxij = 0.0; for (int i = 0; i < coefs.Size(); i++) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) dxdxij(j,k) += dshapes(i,k) * coefs[i](j); // cout << "old, jac = " << dxdxij << endl; for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k); /* T dxdxi00 = T(0.0); T dxdxi01 = T(0.0); T dxdxi02 = T(0.0); T dxdxi10 = T(0.0); T dxdxi11 = T(0.0); T dxdxi12 = T(0.0); T dxdxi20 = T(0.0); T dxdxi21 = T(0.0); T dxdxi22 = T(0.0); for (int i = 0; i < coefs.Size(); i++) { T ds0 = dshapes(i,0); T ds1 = dshapes(i,1); T ds2 = dshapes(i,2); T cf0 = coefs[i](0); T cf1 = coefs[i](1); T cf2 = coefs[i](2); dxdxi00 += ds0*cf0; dxdxi01 += ds1*cf0; dxdxi02 += ds2*cf0; dxdxi10 += ds0*cf1; dxdxi11 += ds1*cf1; dxdxi12 += ds2*cf1; dxdxi20 += ds0*cf2; dxdxi21 += ds1*cf2; dxdxi22 += ds2*cf2; } dxdxi[ip*sdxdxi+3*0+0] = dxdxi00; dxdxi[ip*sdxdxi+3*0+1] = dxdxi01; dxdxi[ip*sdxdxi+3*0+2] = dxdxi02; dxdxi[ip*sdxdxi+3*1+0] = dxdxi10; dxdxi[ip*sdxdxi+3*1+1] = dxdxi11; dxdxi[ip*sdxdxi+3*1+2] = dxdxi12; dxdxi[ip*sdxdxi+3*2+0] = dxdxi20; dxdxi[ip*sdxdxi+3*2+1] = dxdxi21; dxdxi[ip*sdxdxi+3*2+2] = dxdxi22; */ } } } // NgProfiler::StopTimer (timer5); // NgProfiler::StopTimer (timer); } template void CurvedElements :: CalcMultiPointElementTransformation (ElementIndex elnr, int n, const double * xi, size_t sxi, double * x, size_t sx, double * dxdxi, size_t sdxdxi); template void CurvedElements :: CalcMultiPointElementTransformation (ElementIndex elnr, int n, const SIMD * xi, size_t sxi, SIMD * x, size_t sx, SIMD * dxdxi, size_t sdxdxi); }; netgen-6.2.1905/libsrc/meshing/adfront3.hpp0000644000175000017500000001422513504650527017146 0ustar kurtkurt#ifndef FILE_ADFRONT3 #define FILE_ADFRONT3 /**************************************************************************/ /* File: adfront3.hh */ /* Author: Joachim Schoeberl */ /* Date: 01. Okt. 95 */ /**************************************************************************/ /* Advancing front class for volume meshing */ /// Point in advancing front class FrontPoint3 { /// coordinates Point<3> p; /// global node index PointIndex globalindex; /// number of faces connected to point int nfacetopoint; /// distance to original boundary int frontnr; /// int cluster; public: /// FrontPoint3 (); /// FrontPoint3 (const Point<3> & ap, PointIndex agi); /// const Point<3> & P () const { return p; } /// PointIndex GlobalIndex () const { return globalindex; } /// void AddFace () { nfacetopoint++; } /// if last face is removed, then point is invalidated void RemoveFace() { nfacetopoint--; if (nfacetopoint == 0) nfacetopoint = -1; } /// bool Valid () const { return nfacetopoint >= 0; } /// void DecFrontNr (int afrontnr) { if (frontnr > afrontnr) frontnr = afrontnr; } /// int FrontNr () const { return frontnr; } /// friend class AdFront3; }; class MiniElement2d { protected: int np; PointIndex pnum[4]; // can be global or local nums bool deleted; public: MiniElement2d () { np = 3; deleted = 0; } MiniElement2d (int anp) { np = anp; deleted = 0; } int GetNP() const { return np; } PointIndex & operator[] (int i) { return pnum[i]; } const PointIndex operator[] (int i) const { return pnum[i]; } const PointIndex PNum (int i) const { return pnum[i-1]; } PointIndex & PNum (int i) { return pnum[i-1]; } const PointIndex PNumMod (int i) const { return pnum[(i-1)%np]; } auto PNums() const { return FlatArray (np, &pnum[0]); } void Delete () { deleted = true; for (PointIndex & p : pnum) p.Invalidate(); } bool IsDeleted () const { return deleted; } }; inline ostream & operator<<(ostream & s, const MiniElement2d & el) { s << "np = " << el.GetNP(); for (int j = 0; j < el.GetNP(); j++) s << " " << el[j]; return s; } /// Face in advancing front class FrontFace { private: /// MiniElement2d f; /// int qualclass; /// char oldfront; /// int hashvalue; /// int cluster; public: /// FrontFace (); /// FrontFace (const MiniElement2d & af); /// const MiniElement2d & Face () const { return f; } /// int QualClass () const { return qualclass; } /// void IncrementQualClass () { qualclass++; } /// void ResetQualClass () { if (qualclass > 1) { qualclass = 1; oldfront = 0; } } /// bool Valid () const { return !f.IsDeleted(); } /// void Invalidate (); /// int HashValue() const { return hashvalue; } /// void SetHashValue(int hv) { hashvalue = hv; } /// friend class AdFront3; int Cluster () const { return cluster; } }; /// Advancing front, 3D. class AdFront3 { /// Array points; /// Array faces; /// Array delpointl; /// which points are connected to pi ? TABLE * connectedpairs; /// number of total front faces; int nff; /// number of quads in front int nff4; /// double vol; /// GeomSearch3d hashtable; /// int hashon; /// int hashcreated; /// counter for rebuilding internal tables int rebuildcounter; /// last base element int lasti; /// minimal selection-value of baseelements int minval; Array invpindex; Array pingroup; /// class BoxTree<3> * facetree; public: /// AdFront3 (); /// ~AdFront3 (); /// void GetPoints (Array > & apoints) const; /// int GetNP() const { return points.Size(); } /// const Point<3> & GetPoint (PointIndex pi) const { return points[pi].P(); } /// int GetNF() const { return nff; } /// const MiniElement2d & GetFace (int i) const { return faces.Get(i).Face(); } const auto & Faces() const { return faces; } /// void Print () const; /// bool Empty () const { return nff == 0; } /// bool Empty (int elnp) const { if (elnp == 4) return (nff4 == 0); return (nff - nff4 == 0); } /// int SelectBaseElement (); /// void CreateTrees (); /// void GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax, Array & ifaces) const; /// void GetFaceBoundingBox (int i, Box3d & box) const; /// int GetLocals (int baseelement, Array & locpoints, Array & locfaces, // local index Array & pindex, Array & findex, INDEX_2_HASHTABLE & connectedpairs, float xh, float relh, INDEX& facesplit); /// void GetGroup (int fi, Array & grouppoints, Array & groupelements, Array & pindex, Array & findex); /// void DeleteFace (INDEX fi); /// PointIndex AddPoint (const Point<3> & p, PointIndex globind); /// INDEX AddFace (const MiniElement2d & e); /// INDEX AddConnectedPair (const INDEX_2 & pair); /// void IncrementClass (INDEX fi) { faces.Elem(fi).IncrementQualClass(); } /// void ResetClass (INDEX fi) { faces.Elem(fi).ResetQualClass(); } /// void SetStartFront (int baseelnp = 0); /// is Point p inside Surface ? bool Inside (const Point<3> & p) const; /// both points on same side ? int SameSide (const Point<3> & lp1, const Point<3> & lp2, const Array * testfaces = NULL) const; /// PointIndex GetGlobalIndex (PointIndex pi) const { return points[pi].GlobalIndex(); } /// double Volume () const { return vol; } private: void RebuildInternalTables(); }; #endif netgen-6.2.1905/libsrc/meshing/global.cpp0000644000175000017500000000412613504650527016660 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { class TraceGlobal { string name; public: TraceGlobal(string _name) : name(_name) { cout << "init global " << name << endl; } ~TraceGlobal() { cout << "exit global " << name << endl; } }; // stringstream emptystr; // ostream * testout = &emptystr; // testout -> clear(ios::failbit); // ostream * testout = &cout; // NetgenOutStream * testout = new NetgenOutStream; ostream * mycout = &cout; ostream * myerr = &cerr; // some functions (visualization) still need a global mesh // TraceGlobal glob1("global1"); DLL_HEADER shared_ptr mesh; DLL_HEADER shared_ptr ng_geometry; // TraceGlobal glob2("global2"); // global communicator for netgen // DLL_HEADER NgMPI_Comm ng_comm; weak_ptr global_mesh; void SetGlobalMesh (shared_ptr m) { PrintMessage(5, "set global mesh"); global_mesh = m; } // true if netgen was started using the netgen executable // false if netgen.gui was imported from python DLL_HEADER bool netgen_executable_started = false; // Flags parameters; int silentflag = 0; int testmode = 0; volatile multithreadt multithread; string ngdir = "."; void Ng_PrintDest(const char * s) { if (id == 0) (*mycout) << s << flush; } DLL_HEADER void MyError(const char * ch) { cout << ch; (*testout) << "Error !!! " << ch << endl << flush; } static clock_t starttimea; void ResetTime () { starttimea = clock(); } double GetTime () { return double(clock() - starttimea) / CLOCKS_PER_SEC; } Array tets_in_qualclass; mutex tcl_todo_mutex; int h_argc = 0; char ** h_argv = NULL; multithreadt :: multithreadt() { pause =0; testmode = 0; redraw = 0; drawing = 0; terminate = 0; running = 0; percent = 0; task = ""; } DebugParameters debugparam; bool verbose = 0; size_t timestamp = 0; /* int GetTimeStamp() { return timestamp; } int NextTimeStamp() { timestamp++; return timestamp; } */ } netgen-6.2.1905/libsrc/meshing/adfront2.hpp0000644000175000017500000001275013504650527017146 0ustar kurtkurt#ifndef FILE_ADFRONT2 #define FILE_ADFRONT2 /**************************************************************************/ /* File: adfront2.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Okt. 95 */ /**************************************************************************/ /** Advancing front class for surfaces */ /// class FrontPoint2 { /// coordinates Point<3> p; /// global node index PointIndex globalindex; /// number of front lines connected to point int nlinetopoint; /// distance to original boundary int frontnr; bool onsurface; public: /// MultiPointGeomInfo * mgi; /// FrontPoint2 () { globalindex.Invalidate(); // = -1; nlinetopoint = 0; frontnr = INT_MAX-10; // attention: overflow on calculating INT_MAX + 1 mgi = NULL; onsurface = true; } /// FrontPoint2 (const Point<3> & ap, PointIndex agi, MultiPointGeomInfo * amgi, bool aonsurface = true); /// ~FrontPoint2 () { ; } /// const Point<3> & P () const { return p; } /// operator const Point<3> & () const { return p; } /// PointIndex GlobalIndex () const { return globalindex; } /// void AddLine () { nlinetopoint++; } /// void RemoveLine () { nlinetopoint--; if (nlinetopoint == 0) nlinetopoint = -1; } /// bool Valid () const { return nlinetopoint >= 0; } /// bool OnSurface() const { return onsurface; } /// void DecFrontNr (int afrontnr) { if (frontnr > afrontnr) frontnr = afrontnr; } /// int FrontNr () const { return frontnr; } }; /// class FrontLine { private: /// Point Indizes INDEX_2 l; /// quality class int lineclass; /// geometry specific data PointGeomInfo geominfo[2]; public: FrontLine () { lineclass = 1; } /// FrontLine (const INDEX_2 & al) { l = al; lineclass = 1; } /// const INDEX_2 & L () const { return l; } /// int LineClass() const { return lineclass; } /// void IncrementClass () { lineclass++; } /// void ResetClass () { lineclass = 1; } /// bool Valid () const { return l.I1() != -1; } /// void Invalidate () { l.I1() = -1; l.I2() = -1; lineclass = 1000; } void SetGeomInfo (const PointGeomInfo & gi1, const PointGeomInfo & gi2) { geominfo[0] = gi1; geominfo[1] = gi2; } const PointGeomInfo * GetGeomInfo () const { return geominfo; } const PointGeomInfo & GetGeomInfo (int endp) const { return geominfo[endp-1]; } friend class AdFront2; }; class AdFront2 { /// Array points; /// front points Array lines; /// front lines Box3d boundingbox; BoxTree<3> linesearchtree; /// search tree for lines Point3dTree pointsearchtree; /// search tree for points Point3dTree cpointsearchtree; /// search tree for cone points (not used ???) Array delpointl; /// list of deleted front points Array dellinel; /// list of deleted front lines int nfl; /// number of front lines; INDEX_2_HASHTABLE * allflines; /// all front lines ever have been Array invpindex; int minval; int starti; public: /// // AdFront2 (); AdFront2 (const Box3d & aboundingbox); /// ~AdFront2 (); /// // void GetPoints (Array > & apoints) const; /// void Print (ostream & ost) const; /// bool Empty () const { return nfl == 0; } /// int GetNFL () const { return nfl; } const FrontLine & GetLine (int nr) { return lines[nr]; } const FrontPoint2 & GetPoint (int nr) { return points[nr]; } /// int SelectBaseLine (Point<3> & p1, Point<3> & p2, const PointGeomInfo *& geominfo1, const PointGeomInfo *& geominfo2, int & qualclass); /// int GetLocals (int baseline, Array & locpoints, Array & pgeominfo, Array & loclines, // local index Array & pindex, Array & lindex, double xh); /// void DeleteLine (int li); /// int AddPoint (const Point<3> & p, PointIndex globind, MultiPointGeomInfo * mgi = NULL, bool pointonsurface = true); /// int AddLine (int pi1, int pi2, const PointGeomInfo & gi1, const PointGeomInfo & gi2); /// int ExistsLine (int gpi1, int gpi2); /// void IncrementClass (int li) { lines[li].IncrementClass(); } /// void ResetClass (int li) { lines[li].ResetClass(); } /// const PointGeomInfo & GetLineGeomInfo (int li, int lend) const { return lines[li].GetGeomInfo (lend); } /// PointIndex GetGlobalIndex (int pi) const { return points[pi].GlobalIndex(); } /// is Point p inside Surface (flat geometry only) bool Inside (const Point<2> & p) const; bool SameSide (const Point<2> & lp1, const Point<2> & lp2, const Array * /* testfaces */ = NULL) const; /* { return Inside (lp1) == Inside (lp2); } */ /// void SetStartFront (); /// void PrintOpenSegments (ostream & ost) const; }; #endif netgen-6.2.1905/libsrc/meshing/specials.cpp0000644000175000017500000000744313504650527017230 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { // A special function for Hermann Landes, Erlangen void CutOffAndCombine (Mesh & mesh, const Mesh & othermesh) { int i, j; int nse = othermesh.GetNSE(); int onp = othermesh.GetNP(); int ne = mesh.GetNE(); PrintMessage (1, "other mesh has ", othermesh.GetNP(), " points, ", othermesh.GetNSE(), " surface elements."); Array otherbounds(nse); Box3d otherbox; double maxh = 0; for (i = 1; i <= nse; i++) { const Element2d & sel = othermesh.SurfaceElement(i); sel.GetBox(othermesh.Points(), otherbounds.Elem(i)); double loch = othermesh.GetH (othermesh.Point (sel.PNum(1))); otherbounds.Elem(i).Increase(loch); if (loch > maxh) maxh = loch; } otherbox.SetPoint (othermesh.Point(1)); for (i = 1; i <= othermesh.GetNP(); i++) otherbox.AddPoint (othermesh.Point(i)); otherbox.Increase (maxh); for (i = 1; i <= ne; i++) { Box3d box; int remove = 0; const Element & el = mesh.VolumeElement(i); el.GetBox(mesh.Points(), box); if (i % 10000 == 0) cout << "+" << flush; if (box.Intersect(otherbox)) { for (j = 1; j <= nse && !remove; j++) if (box.Intersect(otherbounds.Get(j))) remove = 1; } if (remove) mesh.VolumeElement(i).Delete(); } cout << endl; BitArray connected(mesh.GetNP()); connected.Clear(); for (i = 1; i <= mesh.GetNSE(); i++) { const Element2d & el = mesh.SurfaceElement(i); for (j = 1; j <= 3; j++) connected.Set(el.PNum(j)); } bool changed; do { changed = 0; for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement(i); int has = 0, hasnot = 0; if (el[0]) { for (j = 0; j < 4; j++) { if (connected.Test(el[j])) has = 1; else hasnot = 1; } if (has && hasnot) { changed = 1; for (j = 0; j < 4; j++) connected.Set (el[j]); } } } cout << "." << flush; } while (changed); cout << endl; for (i = 1; i <= mesh.GetNE(); i++) { const Element & el = mesh.VolumeElement(i); int hasnot = 0; if (el[0]) { for (j = 0; j < 4; j++) { if (!connected.Test(el[j])) hasnot = 1; } if (hasnot) mesh.VolumeElement(i).Delete(); } } mesh.Compress(); mesh.FindOpenElements(); BitArray locked(mesh.GetNP()); locked.Set(); for (i = 1; i <= mesh.GetNOpenElements(); i++) for (j = 1; j <= 3; j++) locked.Clear (mesh.OpenElement(i).PNum(j)); for (PointIndex i (1); i <= locked.Size(); i++) if (locked.Test(i)) { mesh.AddLockedPoint (i); } Array pmat(onp); for (i = 1; i <= onp; i++) pmat.Elem(i) = mesh.AddPoint (othermesh.Point(i)); int fnum = mesh.AddFaceDescriptor (FaceDescriptor(0,0,1,0)); for (i = 1; i <= othermesh.GetNSE(); i++) { Element2d tri = othermesh.SurfaceElement(i); for (j = 1; j <= 3; j++) tri.PNum(j) = pmat.Get(tri.PNum(j)); tri.SetIndex(fnum); mesh.AddSurfaceElement (tri); } for (i = 1; i <= onp; i++) mesh.AddLockedPoint (pmat.Elem(i)); mesh.CalcSurfacesOfNode(); mesh.CalcLocalH(0.3); } void HelmholtzMesh (Mesh & mesh) { int i; double ri, ra, rinf; cout << "ri = "; cin >> ri; cout << "ra = "; cin >> ra; cout << "rinf = "; cin >> rinf; double det = ri * ra * rinf - ri * ri * rinf; double a = (ri - rinf) / det; double b = (ri*ri - ra * rinf) / det; for (i = 1; i <= mesh.GetNP(); i++) { Point<3> & p = mesh.Point(i); double rold = sqrt (sqr(p(0)) + sqr(p(1)) + sqr(p(2))); if (rold < ri) continue; double rnew = 1 / (a * rold - b); double fac = rnew / rold; p(0) *= fac; p(1) *= fac; p(2) *= fac; } } } netgen-6.2.1905/libsrc/meshing/clusters.hpp0000644000175000017500000000221213504650527017263 0ustar kurtkurt#ifndef CLUSTERS #define CLUSTERS /**************************************************************************/ /* File: clusers.hh */ /* Author: Joachim Schoeberl */ /* Date: 28. Apr. 01 */ /**************************************************************************/ /* Anisotropic clusters nodes, edges, faces, elements */ class AnisotropicClusters { const Mesh & mesh; int nv, ned, nfa, ne; // connected nodes, nodes = vertices, edges, faces, elements Array cluster_reps; public: AnisotropicClusters (const Mesh & amesh); ~AnisotropicClusters(); void Update(TaskManager tm = &DummyTaskManager, Tracer trace = &DummyTracer); int GetVertexRepresentant (int vnr) const { return cluster_reps.Get(vnr); } int GetEdgeRepresentant (int ednr) const { return cluster_reps.Get(nv+ednr); } int GetFaceRepresentant (int fnr) const { return cluster_reps.Get(nv+ned+fnr); } int GetElementRepresentant (int enr) const { return cluster_reps.Get(nv+ned+nfa+enr); } }; #endif netgen-6.2.1905/libsrc/meshing/meshclass.cpp0000644000175000017500000051645713504650527017421 0ustar kurtkurt#include #include #include "meshing.hpp" namespace netgen { static mutex buildsearchtree_mutex; Mesh :: Mesh () : topology(*this), surfarea(*this) { // volelements.SetName ("vol elements"); // surfelements.SetName ("surf elements"); // points.SetName ("meshpoints"); boundaryedges = NULL; surfelementht = NULL; segmentht = NULL; lochfunc = NULL; mglevels = 1; elementsearchtree = NULL; elementsearchtreets = NextTimeStamp(); majortimestamp = timestamp = NextTimeStamp(); hglob = 1e10; hmin = 0; numvertices = -1; dimension = 3; // topology = new MeshTopology (*this); curvedelems = new CurvedElements (*this); clusters = new AnisotropicClusters (*this); ident = new Identifications (*this); hpelements = NULL; coarsemesh = NULL; ps_startelement = 0; geomtype = NO_GEOM; bcnames.SetSize(0); cd2names.SetSize(0); // this->comm = netgen :: ng_comm; #ifdef PARALLEL paralleltop = new ParallelMeshTopology (*this); #endif } Mesh :: ~Mesh() { // cout << "******************** deleting Mesh **********" << endl; delete lochfunc; delete boundaryedges; delete surfelementht; delete segmentht; delete curvedelems; delete clusters; // delete topology; delete ident; delete elementsearchtree; delete coarsemesh; delete hpelements; for (int i = 0; i < materials.Size(); i++) delete materials[i]; for(int i = 0; i < userdata_int.Size(); i++) delete userdata_int[i]; for(int i = 0; i < userdata_double.Size(); i++) delete userdata_double[i]; for (int i = 0; i < bcnames.Size(); i++ ) delete bcnames[i]; for (int i = 0; i < cd2names.Size(); i++) delete cd2names[i]; #ifdef PARALLEL delete paralleltop; #endif } void Mesh :: SetCommunicator(NgMPI_Comm acomm) { this->comm = acomm; } Mesh & Mesh :: operator= (const Mesh & mesh2) { dimension = mesh2.dimension; points = mesh2.points; // eltyps = mesh2.eltyps; segments = mesh2.segments; surfelements = mesh2.surfelements; volelements = mesh2.volelements; lockedpoints = mesh2.lockedpoints; facedecoding = mesh2.facedecoding; dimension = mesh2.dimension; materials.SetSize( mesh2.materials.Size() ); for ( int i = 0; i < mesh2.materials.Size(); i++ ) if ( mesh2.materials[i] ) materials[i] = new string ( *mesh2.materials[i] ); else materials[i] = 0; bcnames.SetSize( mesh2.bcnames.Size() ); for ( int i = 0; i < mesh2.bcnames.Size(); i++ ) if ( mesh2.bcnames[i] ) bcnames[i] = new string ( *mesh2.bcnames[i] ); else bcnames[i] = 0; cd2names.SetSize(mesh2.cd2names.Size()); for (int i=0; i < mesh2.cd2names.Size(); i++) if (mesh2.cd2names[i]) cd2names[i] = new string(*mesh2.cd2names[i]); else cd2names[i] = 0; cd3names.SetSize(mesh2.cd3names.Size()); for (int i=0; i < mesh2.cd3names.Size(); i++) if (mesh2.cd3names[i]) cd3names[i] = new string(*mesh2.cd3names[i]); else cd3names[i] = 0; numvertices = mesh2.numvertices; return *this; } void Mesh :: DeleteMesh() { NgLock lock(mutex); lock.Lock(); points.SetSize(0); segments.SetSize(0); surfelements.SetSize(0); volelements.SetSize(0); lockedpoints.SetSize(0); // surfacesonnode.SetSize(0); delete boundaryedges; boundaryedges = NULL; openelements.SetSize(0); facedecoding.SetSize(0); delete ident; ident = new Identifications (*this); // delete topology; // topology = new MeshTopology (*this); topology = MeshTopology (*this); delete curvedelems; curvedelems = new CurvedElements (*this); delete clusters; clusters = new AnisotropicClusters (*this); for ( int i = 0; i < bcnames.Size(); i++ ) if ( bcnames[i] ) delete bcnames[i]; for (int i= 0; i< cd2names.Size(); i++) if (cd2names[i]) delete cd2names[i]; #ifdef PARALLEL delete paralleltop; paralleltop = new ParallelMeshTopology (*this); #endif lock.UnLock(); timestamp = NextTimeStamp(); } void Mesh :: ClearSurfaceElements() { surfelements.SetSize(0); for (int i = 0; i < facedecoding.Size(); i++) facedecoding[i].firstelement = -1; timestamp = NextTimeStamp(); } PointIndex Mesh :: AddPoint (const Point3d & p, int layer) { return AddPoint (p, layer, INNERPOINT); /* NgLock lock(mutex); lock.Lock(); timestamp = NextTimeStamp(); PointIndex pi = points.End(); points.Append ( MeshPoint (p, layer, INNERPOINT) ); lock.UnLock(); return pi; */ } PointIndex Mesh :: AddPoint (const Point3d & p, int layer, POINTTYPE type) { NgLock lock(mutex); lock.Lock(); timestamp = NextTimeStamp(); PointIndex pi = points.End(); points.Append ( MeshPoint (p, layer, type) ); lock.UnLock(); return pi; } /* #ifdef PARALLEL PointIndex Mesh :: AddPoint (const Point3d & p, bool isghost, int layer) { NgLock lock(mutex); lock.Lock(); timestamp = NextTimeStamp(); PointIndex pi = points.Size() + PointIndex::BASE; points.Append ( MeshPoint (p, layer, INNERPOINT) ); lock.UnLock(); return pi; } PointIndex Mesh :: AddPoint (const Point3d & p, bool isghost, int layer, POINTTYPE type) { NgLock lock(mutex); lock.Lock(); timestamp = NextTimeStamp(); PointIndex pi = points.Size() + PointIndex::BASE; points.Append ( MeshPoint (p, layer, type) ); lock.UnLock(); return pi; } #endif */ SegmentIndex Mesh :: AddSegment (const Segment & s) { NgLock lock(mutex); lock.Lock(); timestamp = NextTimeStamp(); int maxn = max2 (s[0], s[1]); maxn += 1-PointIndex::BASE; /* if (maxn > ptyps.Size()) { int maxo = ptyps.Size(); ptyps.SetSize (maxn); for (int i = maxo; i < maxn; i++) ptyps[i] = INNERPOINT; } if (ptyps[s[0]] > EDGEPOINT) ptyps[s[0]] = EDGEPOINT; if (ptyps[s[1]] > EDGEPOINT) ptyps[s[1]] = EDGEPOINT; */ if (maxn <= points.Size()) { if (points[s[0]].Type() > EDGEPOINT) points[s[0]].SetType (EDGEPOINT); if (points[s[1]].Type() > EDGEPOINT) points[s[1]].SetType (EDGEPOINT); } /* else { cerr << "edge points nrs > points.Size" << endl; } */ SegmentIndex si = segments.Size(); segments.Append (s); lock.UnLock(); return si; } SurfaceElementIndex Mesh :: AddSurfaceElement (const Element2d & el) { NgLock lock(mutex); lock.Lock(); timestamp = NextTimeStamp(); int maxn = el[0]; for (int i = 1; i < el.GetNP(); i++) if (el[i] > maxn) maxn = el[i]; maxn += 1-PointIndex::BASE; /* if (maxn > ptyps.Size()) { int maxo = ptyps.Size(); ptyps.SetSize (maxn); for (i = maxo+PointIndex::BASE; i < maxn+PointIndex::BASE; i++) ptyps[i] = INNERPOINT; } */ if (maxn <= points.Size()) { for (int i = 0; i < el.GetNP(); i++) if (points[el[i]].Type() > SURFACEPOINT) points[el[i]].SetType(SURFACEPOINT); } /* else { cerr << "surf points nrs > points.Size" << endl; } */ SurfaceElementIndex si = surfelements.Size(); surfelements.Append (el); if (el.index<=0 || el.index > facedecoding.Size()) cerr << "has no facedecoding: fd.size = " << facedecoding.Size() << ", ind = " << el.index << endl; surfelements.Last().next = facedecoding[el.index-1].firstelement; facedecoding[el.index-1].firstelement = si; if (SurfaceArea().Valid()) SurfaceArea().Add (el); lock.UnLock(); return si; } void Mesh :: SetSurfaceElement (SurfaceElementIndex sei, const Element2d & el) { int maxn = el[0]; for (int i = 1; i < el.GetNP(); i++) if (el[i] > maxn) maxn = el[i]; maxn += 1-PointIndex::BASE; if (maxn <= points.Size()) { for (int i = 0; i < el.GetNP(); i++) if (points[el[i]].Type() > SURFACEPOINT) points[el[i]].SetType(SURFACEPOINT); } surfelements[sei] = el; if (el.index > facedecoding.Size()) cerr << "has no facedecoding: fd.size = " << facedecoding.Size() << ", ind = " << el.index << endl; // add lock-free to list ... slow, call RebuildSurfaceElementLists later /* surfelements[sei].next = facedecoding[el.index-1].firstelement; auto & head = reinterpret_cast&> (facedecoding[el.index-1].firstelement); while (!head.compare_exchange_weak (surfelements[sei].next, sei)) ; */ /* if (SurfaceArea().Valid()) SurfaceArea().Add (el); */ } ElementIndex Mesh :: AddVolumeElement (const Element & el) { NgLock lock(mutex); lock.Lock(); int maxn = el[0]; for (int i = 1; i < el.GetNP(); i++) if (el[i] > maxn) maxn = el[i]; maxn += 1-PointIndex::BASE; /* if (maxn > ptyps.Size()) { int maxo = ptyps.Size(); ptyps.SetSize (maxn); for (i = maxo+PointIndex::BASE; i < maxn+PointIndex::BASE; i++) ptyps[i] = INNERPOINT; } */ /* if (maxn > points.Size()) { cerr << "add vol element before point" << endl; } */ int ve = volelements.Size(); volelements.Append (el); volelements.Last().flags.illegal_valid = 0; // while (volelements.Size() > eltyps.Size()) // eltyps.Append (FREEELEMENT); timestamp = NextTimeStamp(); lock.UnLock(); return ve; } void Mesh :: SetVolumeElement (ElementIndex ei, const Element & el) { /* int maxn = el[0]; for (int i = 1; i < el.GetNP(); i++) if (el[i] > maxn) maxn = el[i]; maxn += 1-PointIndex::BASE; */ volelements[ei] = el; volelements.Last().flags.illegal_valid = 0; } void Mesh :: Save (const string & filename) const { ostream * outfile; if (filename.find(".vol.gz")!=string::npos) outfile = new ogzstream(filename.c_str()); else if (filename.find(".vol")!=string::npos) outfile = new ofstream(filename.c_str()); else outfile = new ogzstream((filename+".vol.gz").c_str()); Save(*outfile); delete outfile; } void Mesh :: Save (ostream & outfile) const { int i, j; double scale = 1; // globflags.GetNumFlag ("scale", 1); int inverttets = 0; // globflags.GetDefineFlag ("inverttets"); int invertsurf = 0; // globflags.GetDefineFlag ("invertsurfacemesh"); outfile << "mesh3d" << "\n"; outfile << "dimension\n" << GetDimension() << "\n"; outfile << "geomtype\n" << int(geomtype) << "\n"; outfile << "\n"; outfile << "# surfnr bcnr domin domout np p1 p2 p3" << "\n"; switch (geomtype) { case GEOM_STL: outfile << "surfaceelementsgi" << "\n"; break; case GEOM_OCC: case GEOM_ACIS: outfile << "surfaceelementsuv" << "\n"; break; default: outfile << "surfaceelements" << "\n"; } outfile << GetNSE() << "\n"; SurfaceElementIndex sei; for (sei = 0; sei < GetNSE(); sei++) { if ((*this)[sei].GetIndex()) { outfile << " " << GetFaceDescriptor((*this)[sei].GetIndex ()).SurfNr()+1; outfile << " " << GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); outfile << " " << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainIn(); outfile << " " << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainOut(); } else outfile << " 0 0 0"; Element2d sel = (*this)[sei]; if (invertsurf) sel.Invert(); outfile << " " << sel.GetNP(); for (j = 0; j < sel.GetNP(); j++) outfile << " " << sel[j]; switch (geomtype) { case GEOM_STL: for (j = 1; j <= sel.GetNP(); j++) outfile << " " << sel.GeomInfoPi(j).trignum; break; case GEOM_OCC: case GEOM_ACIS: for (j = 1; j <= sel.GetNP(); j++) { outfile << " " << sel.GeomInfoPi(j).u; outfile << " " << sel.GeomInfoPi(j).v; } break; default: ; } outfile << "\n"; } outfile << "\n" << "\n"; outfile << "# matnr np p1 p2 p3 p4" << "\n"; outfile << "volumeelements" << "\n"; outfile << GetNE() << "\n"; for (ElementIndex ei = 0; ei < GetNE(); ei++) { outfile << (*this)[ei].GetIndex(); outfile << " " << (*this)[ei].GetNP(); Element el = (*this)[ei]; if (inverttets) el.Invert(); for (j = 0; j < el.GetNP(); j++) outfile << " " << el[j]; outfile << "\n"; } outfile << "\n" << "\n"; // outfile << " surf1 surf2 p1 p2" << "\n"; outfile << "# surfid 0 p1 p2 trignum1 trignum2 domin/surfnr1 domout/surfnr2 ednr1 dist1 ednr2 dist2 \n"; outfile << "edgesegmentsgi2" << "\n"; outfile << GetNSeg() << "\n"; for (i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment (i); outfile.width(8); outfile << seg.si; // 2D: bc number, 3D: wievielte Kante outfile.width(8); outfile << 0; outfile.width(8); outfile << seg[0]; outfile.width(8); outfile << seg[1]; outfile << " "; outfile.width(8); outfile << seg.geominfo[0].trignum; // stl dreiecke outfile << " "; outfile.width(8); outfile << seg.geominfo[1].trignum; // << endl; // stl dreieck if (dimension == 3) { outfile << " "; outfile.width(8); outfile << seg.surfnr1+1; outfile << " "; outfile.width(8); outfile << seg.surfnr2+1; } else { outfile << " "; outfile.width(8); outfile << seg.domin; outfile << " "; outfile.width(8); outfile << seg.domout; } outfile << " "; outfile.width(8); outfile << seg.edgenr; outfile << " "; outfile.width(12); outfile.precision(16); outfile << seg.epgeominfo[0].dist; // splineparameter (2D) outfile << " "; outfile.width(8); outfile.precision(16); outfile << seg.epgeominfo[1].edgenr; // geometry dependent outfile << " "; outfile.width(12); outfile << seg.epgeominfo[1].dist; outfile << "\n"; } outfile << "\n" << "\n"; outfile << "# X Y Z" << "\n"; outfile << "points" << "\n"; outfile << GetNP() << "\n"; outfile.precision(16); outfile.setf (ios::fixed, ios::floatfield); outfile.setf (ios::showpoint); PointIndex pi; for (pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++) { outfile.width(22); outfile << (*this)[pi](0)/scale << " "; outfile.width(22); outfile << (*this)[pi](1)/scale << " "; outfile.width(22); outfile << (*this)[pi](2)/scale << "\n"; } if (ident -> GetMaxNr() > 0) { outfile << "identifications\n"; Array identpairs; int cnt = 0; for (i = 1; i <= ident -> GetMaxNr(); i++) { ident -> GetPairs (i, identpairs); cnt += identpairs.Size(); } outfile << cnt << "\n"; for (i = 1; i <= ident -> GetMaxNr(); i++) { ident -> GetPairs (i, identpairs); for (j = 1; j <= identpairs.Size(); j++) { outfile.width (8); outfile << identpairs.Get(j).I1(); outfile.width (8); outfile << identpairs.Get(j).I2(); outfile.width (8); outfile << i << "\n"; } } outfile << "identificationtypes\n"; outfile << ident -> GetMaxNr() << "\n"; for (i = 1; i <= ident -> GetMaxNr(); i++) { int type = ident -> GetType(i); outfile << " " << type; } outfile << "\n"; } int cntmat = 0; for (i = 1; i <= materials.Size(); i++) if (materials.Get(i) && materials.Get(i)->length()) cntmat++; if (cntmat) { outfile << "materials" << endl; outfile << cntmat << endl; for (i = 1; i <= materials.Size(); i++) if (materials.Get(i) && materials.Get(i)->length()) outfile << i << " " << *materials.Get(i) << endl; } int cntbcnames = 0; for ( int ii = 0; ii < bcnames.Size(); ii++ ) if ( bcnames[ii] ) cntbcnames++; if ( cntbcnames ) { outfile << "\n\nbcnames" << endl << bcnames.Size() << endl; for ( i = 0; i < bcnames.Size(); i++ ) outfile << i+1 << "\t" << GetBCName(i) << endl; outfile << endl << endl; } int cntcd2names = 0; for (int ii = 0; ii=1.) cnt_sing++; if (cnt_sing) { outfile << "singular_points" << endl << cnt_sing << endl; for (PointIndex pi = points.Begin(); pi < points.End(); pi++) if ((*this)[pi].Singularity()>=1.) outfile << int(pi) << "\t" << (*this)[pi].Singularity() << endl; } cnt_sing = 0; for (SegmentIndex si = 0; si < GetNSeg(); si++) if ( segments[si].singedge_left ) cnt_sing++; if (cnt_sing) { outfile << "singular_edge_left" << endl << cnt_sing << endl; for (SegmentIndex si = 0; si < GetNSeg(); si++) if ( segments[si].singedge_left ) outfile << int(si) << "\t" << segments[si].singedge_left << endl; } cnt_sing = 0; for (SegmentIndex si = 0; si < GetNSeg(); si++) if ( segments[si].singedge_right ) cnt_sing++; if (cnt_sing) { outfile << "singular_edge_right" << endl << cnt_sing << endl; for (SegmentIndex si = 0; si < GetNSeg(); si++) if ( segments[si].singedge_right ) outfile << int(si) << "\t" << segments[si].singedge_right << endl; } cnt_sing = 0; for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular) cnt_sing++; if (cnt_sing) { outfile << "singular_face_inside" << endl << cnt_sing << endl; for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular) outfile << int(sei) << "\t" << GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular << endl; } cnt_sing = 0; for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular) cnt_sing++; if (cnt_sing) { outfile << "singular_face_outside" << endl << cnt_sing << endl; for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular) outfile << int(sei) << "\t" << GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular << endl; } // Philippose - 09/07/2009 // Add mesh face colours to Netgen Vol file format // The colours are saved in RGB triplets int cnt_facedesc = GetNFD(); if (cnt_facedesc) { outfile << endl << endl << "# Surfnr Red Green Blue" << endl; outfile << "face_colours" << endl << cnt_facedesc << endl; outfile.precision(8); outfile.setf(ios::fixed, ios::floatfield); outfile.setf(ios::showpoint); for(i = 1; i <= cnt_facedesc; i++) { outfile.width(8); outfile << GetFaceDescriptor(i).SurfNr()+1 << " "; outfile.width(12); outfile << GetFaceDescriptor(i).SurfColour().X() << " "; outfile.width(12); outfile << GetFaceDescriptor(i).SurfColour().Y() << " "; outfile.width(12); outfile << GetFaceDescriptor(i).SurfColour().Z(); outfile << endl; } } outfile << endl << endl << "endmesh" << endl << endl; if (geometry) geometry -> SaveToMeshFile (outfile); } void Mesh :: Load (const string & filename) { cout << "filename = " << filename << endl; istream * infile = NULL; if (filename.find(".vol.gz") != string::npos) infile = new igzstream (filename.c_str()); else infile = new ifstream (filename.c_str()); // ifstream infile(filename.c_str()); if (! (infile -> good()) ) throw NgException ("mesh file not found"); Load(*infile); delete infile; } void Mesh :: Load (istream & infile) { if (! (infile.good()) ) { cout << "cannot load mesh" << endl; throw NgException ("mesh file not found"); } int rank = GetCommunicator().Rank(); int ntasks = GetCommunicator().Size(); char str[100]; int i, n; double scale = 1; // globflags.GetNumFlag ("scale", 1); int inverttets = 0; // globflags.GetDefineFlag ("inverttets"); int invertsurf = 0; // globflags.GetDefineFlag ("invertsurfacemesh"); facedecoding.SetSize(0); bool endmesh = false; while (infile.good() && !endmesh) { infile >> str; if (strcmp (str, "dimension") == 0) { infile >> dimension; } if (strcmp (str, "geomtype") == 0) { int hi; infile >> hi; geomtype = GEOM_TYPE(hi); } if (strcmp (str, "surfaceelements") == 0 || strcmp (str, "surfaceelementsgi")==0 || strcmp (str, "surfaceelementsuv") == 0) { infile >> n; PrintMessage (3, n, " surface elements"); bool geominfo = strcmp (str, "surfaceelementsgi") == 0; bool uv = strcmp (str, "surfaceelementsuv") == 0; for (i = 1; i <= n; i++) { int surfnr, bcp, domin, domout, nep, faceind = 0; infile >> surfnr >> bcp >> domin >> domout; surfnr--; bool invert_el = false; /* if (domin == 0) { invert_el = true; Swap (domin, domout); } */ for (int j = 1; j <= facedecoding.Size(); j++) if (GetFaceDescriptor(j).SurfNr() == surfnr && GetFaceDescriptor(j).BCProperty() == bcp && GetFaceDescriptor(j).DomainIn() == domin && GetFaceDescriptor(j).DomainOut() == domout) faceind = j; // if (facedecoding.Size()) faceind = 1; // for timing if (!faceind) { faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0)); GetFaceDescriptor(faceind).SetBCProperty (bcp); } infile >> nep; if (!nep) nep = 3; Element2d tri(nep); tri.SetIndex(faceind); for (int j = 1; j <= nep; j++) infile >> tri.PNum(j); if (geominfo) for (int j = 1; j <= nep; j++) infile >> tri.GeomInfoPi(j).trignum; if (uv) for (int j = 1; j <= nep; j++) infile >> tri.GeomInfoPi(j).u >> tri.GeomInfoPi(j).v; if (invertsurf) tri.Invert(); if (invert_el) tri.Invert(); AddSurfaceElement (tri); } } if (strcmp (str, "volumeelements") == 0) { infile >> n; PrintMessage (3, n, " volume elements"); for (i = 1; i <= n; i++) { Element el(TET); int hi, nep; infile >> hi; if (hi == 0) hi = 1; el.SetIndex(hi); infile >> nep; el.SetNP(nep); el.SetCurved (nep != 4); for (int j = 0; j < nep; j++) infile >> (int&)(el[j]); if (inverttets) el.Invert(); AddVolumeElement (el); } } if (strcmp (str, "edgesegments") == 0) { infile >> n; for (i = 1; i <= n; i++) { Segment seg; int hi; infile >> seg.si >> hi >> seg[0] >> seg[1]; AddSegment (seg); } } if (strcmp (str, "edgesegmentsgi") == 0) { infile >> n; for (i = 1; i <= n; i++) { Segment seg; int hi; infile >> seg.si >> hi >> seg[0] >> seg[1] >> seg.geominfo[0].trignum >> seg.geominfo[1].trignum; AddSegment (seg); } } if (strcmp (str, "edgesegmentsgi2") == 0) { int a; infile >> a; n=a; PrintMessage (3, n, " curve elements"); for (i = 1; i <= n; i++) { Segment seg; int hi; infile >> seg.si >> hi >> seg[0] >> seg[1] >> seg.geominfo[0].trignum >> seg.geominfo[1].trignum >> seg.surfnr1 >> seg.surfnr2 >> seg.edgenr >> seg.epgeominfo[0].dist >> seg.epgeominfo[1].edgenr >> seg.epgeominfo[1].dist; seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr; seg.domin = seg.surfnr1; seg.domout = seg.surfnr2; seg.surfnr1--; seg.surfnr2--; AddSegment (seg); } } if (strcmp (str, "points") == 0) { infile >> n; PrintMessage (3, n, " points"); for (i = 1; i <= n; i++) { Point3d p; infile >> p.X() >> p.Y() >> p.Z(); p.X() *= scale; p.Y() *= scale; p.Z() *= scale; AddPoint (p); } PrintMessage (3, n, " points done"); } if (strcmp (str, "identifications") == 0) { infile >> n; PrintMessage (3, n, " identifications"); for (i = 1; i <= n; i++) { PointIndex pi1, pi2; int ind; infile >> pi1 >> pi2 >> ind; ident -> Add (pi1, pi2, ind); } } if (strcmp (str, "identificationtypes") == 0) { infile >> n; PrintMessage (3, n, " identificationtypes"); for (i = 1; i <= n; i++) { int type; infile >> type; ident -> SetType(i,Identifications::ID_TYPE(type)); } } if (strcmp (str, "materials") == 0) { infile >> n; for (i = 1; i <= n; i++) { int nr; string mat; infile >> nr >> mat; SetMaterial (nr, mat.c_str()); } } if ( strcmp (str, "bcnames" ) == 0 ) { infile >> n; Array bcnrs(n); SetNBCNames(n); for ( i = 1; i <= n; i++ ) { string nextbcname; infile >> bcnrs[i-1] >> nextbcname; bcnames[bcnrs[i-1]-1] = new string(nextbcname); } if ( GetDimension() == 2 ) { for (i = 1; i <= GetNSeg(); i++) { Segment & seg = LineSegment (i); if ( seg.si <= n ) seg.SetBCName (bcnames[seg.si-1]); else seg.SetBCName(0); } } else { for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { if ((*this)[sei].GetIndex()) { int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); if ( bcp <= n ) GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(bcnames[bcp-1]); else GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(0); } } } } if ( strcmp (str, "cd2names" ) == 0) { infile >> n; Array cd2nrs(n); SetNCD2Names(n); for( i=1; i<=n; i++) { string nextcd2name; infile >> cd2nrs[i-1] >> nextcd2name; cd2names[cd2nrs[i-1]-1] = new string(nextcd2name); } if (GetDimension() == 2) { throw NgException("co dim 2 elements not implemented for dimension 2"); } else { for (i = 1; i<= GetNSeg(); i++) { Segment & seg = LineSegment(i); if ( seg.edgenr <= n ) seg.SetBCName (cd2names[seg.edgenr-1]); else seg.SetBCName(0); } } } if (strcmp (str, "singular_points") == 0) { infile >> n; for (i = 1; i <= n; i++) { PointIndex pi; double s; infile >> pi; infile >> s; (*this)[pi].Singularity (s); } } if (strcmp (str, "singular_edge_left") == 0) { infile >> n; for (i = 1; i <= n; i++) { SegmentIndex si; double s; infile >> si; infile >> s; (*this)[si].singedge_left = s; } } if (strcmp (str, "singular_edge_right") == 0) { infile >> n; for (i = 1; i <= n; i++) { SegmentIndex si; double s; infile >> si; infile >> s; (*this)[si].singedge_right = s; } } if (strcmp (str, "singular_face_inside") == 0) { infile >> n; for (i = 1; i <= n; i++) { SurfaceElementIndex sei; double s; infile >> sei; infile >> s; GetFaceDescriptor((*this)[sei].GetIndex()).domin_singular = s; } } if (strcmp (str, "singular_face_outside") == 0) { infile >> n; for (i = 1; i <= n; i++) { SurfaceElementIndex sei; double s; infile >> sei; infile >> s; GetFaceDescriptor((*this)[sei].GetIndex()).domout_singular = s; } } // Philippose - 09/07/2009 // Add mesh face colours to Netgen Vol file format // The colours are read in as RGB triplets if (strcmp (str, "face_colours") == 0) { int cnt_facedesc = GetNFD(); infile >> n; if(n == cnt_facedesc) { for(i = 1; i <= n; i++) { int surfnr = 0; Vec3d surfcolour(0.0,1.0,0.0); infile >> surfnr >> surfcolour.X() >> surfcolour.Y() >> surfcolour.Z(); surfnr--; if(surfnr > 0) { for(int facedesc = 1; facedesc <= cnt_facedesc; facedesc++) { if(surfnr == GetFaceDescriptor(facedesc).SurfNr()) { GetFaceDescriptor(facedesc).SetSurfColour(surfcolour); } } } } } } if (strcmp (str, "endmesh") == 0) endmesh = true; strcpy (str, ""); } CalcSurfacesOfNode (); if (ntasks == 1) // sequential run only { topology.Update(); clusters -> Update(); } SetNextMajorTimeStamp(); // PrintMemInfo (cout); } void Mesh :: DoArchive (Archive & archive) { archive & dimension; archive & points; archive & surfelements; archive & volelements; archive & segments; archive & facedecoding; archive & materials & bcnames & cd2names & cd3names; archive & numvertices; archive & *ident; archive.Shallow(geometry); archive & *curvedelems; if (archive.Input()) { int rank = GetCommunicator().Rank(); int ntasks = GetCommunicator().Size(); RebuildSurfaceElementLists(); CalcSurfacesOfNode (); if (ntasks == 1) // sequential run only { topology.Update(); clusters -> Update(); } SetNextMajorTimeStamp(); } } void Mesh :: Merge (const string & filename, const int surfindex_offset) { ifstream infile(filename.c_str()); if (!infile.good()) throw NgException ("mesh file not found"); Merge(infile,surfindex_offset); } void Mesh :: Merge (istream & infile, const int surfindex_offset) { char str[100]; int i, n; int inverttets = 0; // globflags.GetDefineFlag ("inverttets"); int oldnp = GetNP(); int oldne = GetNSeg(); int oldnd = GetNDomains(); for(SurfaceElementIndex si = 0; si < GetNSE(); si++) for(int j=1; j<=(*this)[si].GetNP(); j++) (*this)[si].GeomInfoPi(j).trignum = -1; int max_surfnr = 0; for (i = 1; i <= GetNFD(); i++) max_surfnr = max2 (max_surfnr, GetFaceDescriptor(i).SurfNr()); max_surfnr++; if(max_surfnr < surfindex_offset) max_surfnr = surfindex_offset; bool endmesh = false; while (infile.good() && !endmesh) { infile >> str; if (strcmp (str, "surfaceelementsgi") == 0 || strcmp (str, "surfaceelements") == 0) { infile >> n; PrintMessage (3, n, " surface elements"); for (i = 1; i <= n; i++) { int j; int surfnr, bcp, domin, domout, nep, faceind = 0; infile >> surfnr >> bcp >> domin >> domout; surfnr--; if(domin > 0) domin += oldnd; if(domout > 0) domout += oldnd; surfnr += max_surfnr; for (j = 1; j <= facedecoding.Size(); j++) if (GetFaceDescriptor(j).SurfNr() == surfnr && GetFaceDescriptor(j).BCProperty() == bcp && GetFaceDescriptor(j).DomainIn() == domin && GetFaceDescriptor(j).DomainOut() == domout) faceind = j; if (!faceind) { faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0)); if(GetDimension() == 2) bcp++; GetFaceDescriptor(faceind).SetBCProperty (bcp); } infile >> nep; if (!nep) nep = 3; Element2d tri(nep); tri.SetIndex(faceind); for (j = 1; j <= nep; j++) { infile >> tri.PNum(j); tri.PNum(j) = tri.PNum(j) + oldnp; } if (strcmp (str, "surfaceelementsgi") == 0) for (j = 1; j <= nep; j++) { infile >> tri.GeomInfoPi(j).trignum; tri.GeomInfoPi(j).trignum = -1; } AddSurfaceElement (tri); } } if (strcmp (str, "edgesegments") == 0) { infile >> n; for (i = 1; i <= n; i++) { Segment seg; int hi; infile >> seg.si >> hi >> seg[0] >> seg[1]; seg[0] = seg[0] + oldnp; seg[1] = seg[1] + oldnp; AddSegment (seg); } } if (strcmp (str, "edgesegmentsgi") == 0) { infile >> n; for (i = 1; i <= n; i++) { Segment seg; int hi; infile >> seg.si >> hi >> seg[0] >> seg[1] >> seg.geominfo[0].trignum >> seg.geominfo[1].trignum; seg[0] = seg[0] + oldnp; seg[1] = seg[1] + oldnp; AddSegment (seg); } } if (strcmp (str, "edgesegmentsgi2") == 0) { infile >> n; PrintMessage (3, n, " curve elements"); for (i = 1; i <= n; i++) { Segment seg; int hi; infile >> seg.si >> hi >> seg[0] >> seg[1] >> seg.geominfo[0].trignum >> seg.geominfo[1].trignum >> seg.surfnr1 >> seg.surfnr2 >> seg.edgenr >> seg.epgeominfo[0].dist >> seg.epgeominfo[1].edgenr >> seg.epgeominfo[1].dist; seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr; seg.surfnr1--; seg.surfnr2--; if(seg.surfnr1 >= 0) seg.surfnr1 = seg.surfnr1 + max_surfnr; if(seg.surfnr2 >= 0) seg.surfnr2 = seg.surfnr2 + max_surfnr; seg[0] = seg[0] +oldnp; seg[1] = seg[1] +oldnp; *testout << "old edgenr: " << seg.edgenr << endl; seg.edgenr = seg.edgenr + oldne; *testout << "new edgenr: " << seg.edgenr << endl; seg.epgeominfo[1].edgenr = seg.epgeominfo[1].edgenr + oldne; AddSegment (seg); } } if (strcmp (str, "volumeelements") == 0) { infile >> n; PrintMessage (3, n, " volume elements"); for (i = 1; i <= n; i++) { Element el(TET); int hi, nep; infile >> hi; if (hi == 0) hi = 1; el.SetIndex(hi+oldnd); infile >> nep; el.SetNP(nep); for (int j = 0; j < nep; j++) { infile >> (int&)(el[j]); el[j] = el[j]+oldnp; } if (inverttets) el.Invert(); AddVolumeElement (el); } } if (strcmp (str, "points") == 0) { infile >> n; PrintMessage (3, n, " points"); for (i = 1; i <= n; i++) { Point3d p; infile >> p.X() >> p.Y() >> p.Z(); AddPoint (p); } } if (strcmp (str, "endmesh") == 0) { endmesh = true; } if (strcmp (str, "materials") == 0) { infile >> n; for (i = 1; i <= n; i++) { int nr; string mat; infile >> nr >> mat; SetMaterial (nr+oldnd, mat.c_str()); } } strcpy (str, ""); } CalcSurfacesOfNode (); topology.Update(); clusters -> Update(); SetNextMajorTimeStamp(); } bool Mesh :: TestOk () const { for (ElementIndex ei = 0; ei < volelements.Size(); ei++) { for (int j = 0; j < 4; j++) if ( (*this)[ei][j] <= PointIndex::BASE-1) { (*testout) << "El " << ei << " has 0 nodes: "; for (int k = 0; k < 4; k++) (*testout) << (*this)[ei][k]; break; } } CheckMesh3D (*this); return 1; } void Mesh :: SetAllocSize(int nnodes, int nsegs, int nsel, int nel) { points.SetAllocSize(nnodes); segments.SetAllocSize(nsegs); surfelements.SetAllocSize(nsel); volelements.SetAllocSize(nel); } void Mesh :: BuildBoundaryEdges(void) { delete boundaryedges; boundaryedges = new INDEX_2_CLOSED_HASHTABLE (3 * (GetNSE() + GetNOpenElements()) + GetNSeg() + 1); for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & sel = surfelements[sei]; if (sel.IsDeleted()) continue; // int si = sel.GetIndex(); if (sel.GetNP() <= 4) for (int j = 0; j < sel.GetNP(); j++) { INDEX_2 i2; i2.I1() = sel.PNumMod(j+1); i2.I2() = sel.PNumMod(j+2); i2.Sort(); boundaryedges->Set (i2, 1); } else if (sel.GetType()==TRIG6) { for (int j = 0; j < 3; j++) { INDEX_2 i2; i2.I1() = sel[j]; i2.I2() = sel[(j+1)%3]; i2.Sort(); boundaryedges->Set (i2, 1); } } else cerr << "illegal element for buildboundaryedges" << endl; } for (int i = 0; i < openelements.Size(); i++) { const Element2d & sel = openelements[i]; for (int j = 0; j < sel.GetNP(); j++) { INDEX_2 i2; i2.I1() = sel.PNumMod(j+1); i2.I2() = sel.PNumMod(j+2); i2.Sort(); boundaryedges->Set (i2, 1); points[sel[j]].SetType(FIXEDPOINT); } } for (int i = 0; i < GetNSeg(); i++) { const Segment & seg = segments[i]; INDEX_2 i2(seg[0], seg[1]); i2.Sort(); boundaryedges -> Set (i2, 2); //segmentht -> Set (i2, i); } } void Mesh :: CalcSurfacesOfNode () { static Timer t("Mesh::CalcSurfacesOfNode"); RegionTimer reg (t); // surfacesonnode.SetSize (GetNP()); TABLE surfacesonnode(GetNP()); delete boundaryedges; boundaryedges = NULL; delete surfelementht; surfelementht = nullptr; delete segmentht; /* surfelementht = new INDEX_3_HASHTABLE (GetNSE()/4 + 1); segmentht = new INDEX_2_HASHTABLE (GetNSeg() + 1); */ if (dimension == 3) surfelementht = new INDEX_3_CLOSED_HASHTABLE (3*GetNSE() + 1); segmentht = new INDEX_2_CLOSED_HASHTABLE (3*GetNSeg() + 1); if (dimension == 3) for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & sel = surfelements[sei]; if (sel.IsDeleted()) continue; int si = sel.GetIndex(); for (int j = 0; j < sel.GetNP(); j++) { PointIndex pi = sel[j]; if (!surfacesonnode[pi].Contains(si)) surfacesonnode.Add (pi, si); /* bool found = 0; for (int k = 0; k < surfacesonnode[pi].Size(); k++) if (surfacesonnode[pi][k] == si) { found = 1; break; } if (!found) surfacesonnode.Add (pi, si); */ } } /* for (sei = 0; sei < GetNSE(); sei++) { const Element2d & sel = surfelements[sei]; if (sel.IsDeleted()) continue; INDEX_3 i3; i3.I1() = sel.PNum(1); i3.I2() = sel.PNum(2); i3.I3() = sel.PNum(3); i3.Sort(); surfelementht -> PrepareSet (i3); } surfelementht -> AllocateElements(); */ if (dimension==3) for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & sel = surfelements[sei]; if (sel.IsDeleted()) continue; INDEX_3 i3; i3.I1() = sel.PNum(1); i3.I2() = sel.PNum(2); i3.I3() = sel.PNum(3); i3.Sort(); surfelementht -> Set (i3, sei); // war das wichtig ??? sel.GetIndex()); } // int np = GetNP(); if (dimension == 3) { for (PointIndex pi = points.Begin(); pi < points.End(); pi++) points[pi].SetType (INNERPOINT); if (GetNFD() == 0) { for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & sel = surfelements[sei]; if (sel.IsDeleted()) continue; for (int j = 0; j < sel.GetNP(); j++) { PointIndex pi = SurfaceElement(sei)[j]; points[pi].SetType(FIXEDPOINT); } } } else { for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & sel = surfelements[sei]; if (sel.IsDeleted()) continue; for (int j = 0; j < sel.GetNP(); j++) { PointIndex pi = sel[j]; int ns = surfacesonnode[pi].Size(); if (ns == 1) points[pi].SetType(SURFACEPOINT); if (ns == 2) points[pi].SetType(EDGEPOINT); if (ns >= 3) points[pi].SetType(FIXEDPOINT); } } } } for (int i = 0; i < segments.Size(); i++) { const Segment & seg = segments[i]; for (int j = 1; j <= 2; j++) { PointIndex hi = (j == 1) ? seg[0] : seg[1]; if (points[hi].Type() == INNERPOINT || points[hi].Type() == SURFACEPOINT) points[hi].SetType(EDGEPOINT); } } for (int i = 0; i < lockedpoints.Size(); i++) points[lockedpoints[i]].SetType(FIXEDPOINT); /* for (i = 0; i < openelements.Size(); i++) { const Element2d & sel = openelements[i]; for (j = 0; j < sel.GetNP(); j++) { INDEX_2 i2; i2.I1() = sel.PNumMod(j+1); i2.I2() = sel.PNumMod(j+2); i2.Sort(); boundaryedges->Set (i2, 1); points[sel[j]].SetType(FIXEDPOINT); } } */ // eltyps.SetSize (GetNE()); // eltyps = FREEELEMENT; for (int i = 0; i < GetNSeg(); i++) { const Segment & seg = segments[i]; INDEX_2 i2(seg[0], seg[1]); i2.Sort(); //boundaryedges -> Set (i2, 2); segmentht -> Set (i2, i); } } void Mesh :: FixPoints (const BitArray & fixpoints) { if (fixpoints.Size() != GetNP()) { cerr << "Mesh::FixPoints: sizes don't fit" << endl; return; } int np = GetNP(); for (int i = 1; i <= np; i++) if (fixpoints.Test(i)) { points.Elem(i).SetType (FIXEDPOINT); } } void Mesh :: FindOpenElements (int dom) { static Timer t("Mesh::FindOpenElements"); RegionTimer reg (t); int np = GetNP(); int ne = GetNE(); int nse = GetNSE(); Array numonpoint(np); numonpoint = 0; for (ElementIndex ei = 0; ei < ne; ei++) { const Element & el = (*this)[ei]; if (dom == 0 || dom == el.GetIndex()) { if (el.GetNP() == 4) { INDEX_4 i4(el[0], el[1], el[2], el[3]); i4.Sort(); numonpoint[i4.I1()]++; numonpoint[i4.I2()]++; } else for (int j = 0; j < el.GetNP(); j++) numonpoint[el[j]]++; } } TABLE elsonpoint(numonpoint); for (ElementIndex ei = 0; ei < ne; ei++) { const Element & el = (*this)[ei]; if (dom == 0 || dom == el.GetIndex()) { if (el.GetNP() == 4) { INDEX_4 i4(el[0], el[1], el[2], el[3]); i4.Sort(); elsonpoint.Add (i4.I1(), ei); elsonpoint.Add (i4.I2(), ei); } else for (int j = 0; j < el.GetNP(); j++) elsonpoint.Add (el[j], ei); } } Array hasface(GetNFD()); int i; for (i = 1; i <= GetNFD(); i++) { int domin = GetFaceDescriptor(i).DomainIn(); int domout = GetFaceDescriptor(i).DomainOut(); hasface[i] = ( dom == 0 && (domin != 0 || domout != 0) ) || ( dom != 0 && (domin == dom || domout == dom) ); } numonpoint = 0; for (SurfaceElementIndex sii = 0; sii < nse; sii++) { int ind = surfelements[sii].GetIndex(); /* if ( GetFaceDescriptor(ind).DomainIn() && (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) || GetFaceDescriptor(ind).DomainOut() && (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) ) */ if (hasface[ind]) { /* Element2d hel = surfelements[i]; hel.NormalizeNumbering(); numonpoint[hel[0]]++; */ const Element2d & hel = surfelements[sii]; int mini = 0; for (int j = 1; j < hel.GetNP(); j++) if (hel[j] < hel[mini]) mini = j; numonpoint[hel[mini]]++; } } TABLE selsonpoint(numonpoint); for (SurfaceElementIndex sii = 0; sii < nse; sii++) { int ind = surfelements[sii].GetIndex(); /* if ( GetFaceDescriptor(ind).DomainIn() && (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) || GetFaceDescriptor(ind).DomainOut() && (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) ) */ if (hasface[ind]) { /* Element2d hel = surfelements[i]; hel.NormalizeNumbering(); selsonpoint.Add (hel[0], i); */ const Element2d & hel = surfelements[sii]; int mini = 0; for (int j = 1; j < hel.GetNP(); j++) if (hel[j] < hel[mini]) mini = j; selsonpoint.Add (hel[mini], sii); } } int ii; PointIndex pi; SurfaceElementIndex sei; // Element2d hel; INDEX_3_CLOSED_HASHTABLE faceht(100); openelements.SetSize(0); for (PointIndex pi = points.Begin(); pi < points.End(); pi++) if (selsonpoint[pi].Size()+elsonpoint[pi].Size()) { faceht.SetSize (2 * selsonpoint[pi].Size() + 4 * elsonpoint[pi].Size()); FlatArray row = selsonpoint[pi]; for (ii = 0; ii < row.Size(); ii++) { Element2d hel = SurfaceElement(row[ii]); if (hel.GetType() == TRIG6) hel.SetType(TRIG); int ind = hel.GetIndex(); if (GetFaceDescriptor(ind).DomainIn() && (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) ) { hel.NormalizeNumbering(); if (hel.PNum(1) == pi) { INDEX_3 i3(hel[0], hel[1], hel[2]); INDEX_2 i2 (GetFaceDescriptor(ind).DomainIn(), (hel.GetNP() == 3) ? PointIndex (PointIndex::BASE-1) : hel.PNum(4)); faceht.Set (i3, i2); } } if (GetFaceDescriptor(ind).DomainOut() && (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) ) { hel.Invert(); hel.NormalizeNumbering(); if (hel.PNum(1) == pi) { INDEX_3 i3(hel[0], hel[1], hel[2]); INDEX_2 i2 (GetFaceDescriptor(ind).DomainOut(), (hel.GetNP() == 3) ? PointIndex (PointIndex::BASE-1) : hel.PNum(4)); faceht.Set (i3, i2); } } } FlatArray rowel = elsonpoint[pi]; for (ii = 0; ii < rowel.Size(); ii++) { const Element & el = VolumeElement(rowel[ii]); if (dom == 0 || el.GetIndex() == dom) { for (int j = 1; j <= el.GetNFaces(); j++) { Element2d hel(TRIG); el.GetFace (j, hel); hel.Invert(); hel.NormalizeNumbering(); if (hel[0] == pi) { INDEX_3 i3(hel[0], hel[1], hel[2]); if (faceht.Used (i3)) { INDEX_2 i2 = faceht.Get(i3); if (i2.I1() == el.GetIndex()) { i2.I1() = PointIndex::BASE-1; faceht.Set (i3, i2); } else { if (i2.I1() == 0) { PrintSysError ("more elements on face"); (*testout) << "more elements on face!!!" << endl; (*testout) << "el = " << el << endl; (*testout) << "hel = " << hel << endl; (*testout) << "face = " << i3 << endl; (*testout) << "points = " << endl; for (int jj = 1; jj <= 3; jj++) (*testout) << "p = " << Point(i3.I(jj)) << endl; } } } else { hel.Invert(); hel.NormalizeNumbering(); INDEX_3 i3(hel[0], hel[1], hel[2]); INDEX_2 i2(el.GetIndex(), (hel.GetNP() == 3) ? PointIndex (PointIndex::BASE-1) : hel[3]); faceht.Set (i3, i2); } } } } } for (int i = 0; i < faceht.Size(); i++) if (faceht.UsedPos (i)) { INDEX_3 i3; INDEX_2 i2; faceht.GetData (i, i3, i2); if (i2.I1() != PointIndex::BASE-1) { // Element2d tri; // tri.SetType ( (i2.I2() == PointIndex::BASE-1) ? TRIG : QUAD); Element2d tri ( (i2.I2() == PointIndex::BASE-1) ? TRIG : QUAD); for (int l = 0; l < 3; l++) tri[l] = i3.I(l+1); tri.PNum(4) = i2.I2(); tri.SetIndex (i2.I1()); // tri.Invert(); openelements.Append (tri); } } } int cnt3 = 0; for (i = 0; i < openelements.Size(); i++) if (openelements[i].GetNP() == 3) cnt3++; int cnt4 = openelements.Size() - cnt3; MyStr treequad; if (cnt4) treequad = MyStr(" (") + MyStr(cnt3) + MyStr (" + ") + MyStr(cnt4) + MyStr(")"); PrintMessage (5, openelements.Size(), treequad, " open elements"); BuildBoundaryEdges(); for (int i = 1; i <= openelements.Size(); i++) { const Element2d & sel = openelements.Get(i); if (boundaryedges) for (int j = 1; j <= sel.GetNP(); j++) { INDEX_2 i2; i2.I1() = sel.PNumMod(j); i2.I2() = sel.PNumMod(j+1); i2.Sort(); boundaryedges->Set (i2, 1); } for (int j = 1; j <= 3; j++) { PointIndex pi = sel.PNum(j); if (pi < points.End()) points[pi].SetType (FIXEDPOINT); } } /* for (i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment(i); INDEX_2 i2(seg[0], seg[1]); i2.Sort(); if (!boundaryedges->Used (i2)) cerr << "WARNING: no boundedge, but seg edge: " << i2 << endl; boundaryedges -> Set (i2, 2); segmentht -> Set (i2, i-1); } */ } bool Mesh :: HasOpenQuads () const { int no = GetNOpenElements(); for (int i = 0; i < no; i++) if (openelements[i].GetNP() == 4) return true; return false; } void Mesh :: FindOpenSegments (int surfnr) { // int i, j, k; // new version, general elements // hash index: pnum1-2 // hash data : surfnr, surfel-nr (pos) or segment nr(neg) INDEX_2_HASHTABLE faceht(4 * GetNSE()+GetNSeg()+1); PrintMessage (5, "Test Opensegments"); for (int i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment (i); if (surfnr == 0 || seg.si == surfnr) { INDEX_2 key(seg[0], seg[1]); INDEX_2 data(seg.si, -i); if (faceht.Used (key)) { cerr << "ERROR: Segment " << seg << " already used" << endl; (*testout) << "ERROR: Segment " << seg << " already used" << endl; } faceht.Set (key, data); } } for (int i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment (i); if (surfnr == 0 || seg.si == surfnr) { INDEX_2 key(seg[1], seg[0]); if (!faceht.Used(key)) { cerr << "ERROR: Segment " << seg << " brother not used" << endl; (*testout) << "ERROR: Segment " << seg << " brother not used" << endl; } } } // bool buggy = false; // ofstream bout("buggy.out"); for (int i = 1; i <= GetNSE(); i++) { const Element2d & el = SurfaceElement(i); if (el.IsDeleted()) continue; if (surfnr == 0 || el.GetIndex() == surfnr) { for (int j = 1; j <= el.GetNP(); j++) { INDEX_2 seg (el.PNumMod(j), el.PNumMod(j+1)); INDEX_2 data; if (seg.I1() < PointIndex::BASE || seg.I2() < PointIndex::BASE) cerr << "seg = " << seg << endl; if (faceht.Used(seg)) { data = faceht.Get(seg); if (data.I1() == el.GetIndex()) { data.I1() = 0; faceht.Set (seg, data); } else { // buggy = true; PrintWarning ("hash table si not fitting for segment: ", seg.I1(), "-", seg.I2(), " other = ", data.I2()); // cout << "me: index = " << el.GetIndex() << ", el = " << el << endl; /* bout << "has index = " << seg << endl; bout << "hash value = " << faceht.HashValue (seg) << endl; if (data.I2() > 0) { int io = data.I2(); cout << "other trig: index = " << SurfaceElement(io).GetIndex() << ", el = " << SurfaceElement(io) << endl; } else { cout << "other seg " << -data.I2() << ", si = " << data.I1() << endl; } bout << "me: index = " << el.GetIndex() << ", el = " << el << endl; if (data.I2() > 0) { int io = data.I2(); bout << "other trig: index = " << SurfaceElement(io).GetIndex() << ", el = " << SurfaceElement(io) << endl; } else { bout << "other seg " << -data.I2() << ", si = " << data.I1() << endl; } */ } } else { Swap (seg.I1(), seg.I2()); data.I1() = el.GetIndex(); data.I2() = i; faceht.Set (seg, data); } } } } /* if (buggy) { for (int i = 1; i <= GetNSeg(); i++) bout << "seg" << i << " " << LineSegment(i) << endl; for (int i = 1; i <= GetNSE(); i++) bout << "sel" << i << " " << SurfaceElement(i) << " ind = " << SurfaceElement(i).GetIndex() << endl; bout << "hashtable: " << endl; for (int j = 1; j <= faceht.GetNBags(); j++) { bout << "bag " << j << ":" << endl; for (int k = 1; k <= faceht.GetBagSize(j); k++) { INDEX_2 i2, data; faceht.GetData (j, k, i2, data); bout << "key = " << i2 << ", data = " << data << endl; } } exit(1); } */ (*testout) << "open segments: " << endl; opensegments.SetSize(0); for (int i = 1; i <= faceht.GetNBags(); i++) for (int j = 1; j <= faceht.GetBagSize(i); j++) { INDEX_2 i2; INDEX_2 data; faceht.GetData (i, j, i2, data); if (data.I1()) // surfnr { Segment seg; seg[0] = i2.I1(); seg[1] = i2.I2(); seg.si = data.I1(); // find geomdata: if (data.I2() > 0) { // segment due to triangle const Element2d & el = SurfaceElement (data.I2()); for (int k = 1; k <= el.GetNP(); k++) { if (seg[0] == el.PNum(k)) seg.geominfo[0] = el.GeomInfoPi(k); if (seg[1] == el.PNum(k)) seg.geominfo[1] = el.GeomInfoPi(k); } (*testout) << "trig seg: "; } else { // segment due to line const Segment & lseg = LineSegment (-data.I2()); seg.geominfo[0] = lseg.geominfo[0]; seg.geominfo[1] = lseg.geominfo[1]; (*testout) << "line seg: "; } (*testout) << seg[0] << " - " << seg[1] << " len = " << Dist (Point(seg[0]), Point(seg[1])) << endl; opensegments.Append (seg); if (seg.geominfo[0].trignum <= 0 || seg.geominfo[1].trignum <= 0) { (*testout) << "Problem with open segment: " << seg << endl; } } } PrintMessage (3, opensegments.Size(), " open segments found"); (*testout) << opensegments.Size() << " open segments found" << endl; /* ptyps.SetSize (GetNP()); for (i = 1; i <= ptyps.Size(); i++) ptyps.Elem(i) = SURFACEPOINT; for (i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment (i); ptyps.Elem(seg[0]) = EDGEPOINT; ptyps.Elem(seg[1]) = EDGEPOINT; } for (i = 1; i <= GetNOpenSegments(); i++) { const Segment & seg = GetOpenSegment (i); ptyps.Elem(seg[0]) = EDGEPOINT; ptyps.Elem(seg[1]) = EDGEPOINT; } */ for (int i = 1; i <= points.Size(); i++) points.Elem(i).SetType(SURFACEPOINT); for (int i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment (i); points[seg[0]].SetType(EDGEPOINT); points[seg[1]].SetType(EDGEPOINT); } for (int i = 1; i <= GetNOpenSegments(); i++) { const Segment & seg = GetOpenSegment (i); points[seg[0]].SetType (EDGEPOINT); points[seg[1]].SetType (EDGEPOINT); } /* for (i = 1; i <= openelements.Size(); i++) { const Element2d & sel = openelements.Get(i); if (boundaryedges) for (j = 1; j <= sel.GetNP(); j++) { INDEX_2 i2; i2.I1() = sel.PNumMod(j); i2.I2() = sel.PNumMod(j+1); i2.Sort(); boundaryedges->Set (i2, 1); } for (j = 1; j <= 3; j++) { int pi = sel.PNum(j); if (pi <= ptyps.Size()) ptyps.Elem(pi) = FIXEDPOINT; } } */ } void Mesh :: RemoveOneLayerSurfaceElements () { int np = GetNP(); FindOpenSegments(); BitArray frontpoints(np+1); // for 0- and 1-based frontpoints.Clear(); for (int i = 1; i <= GetNOpenSegments(); i++) { const Segment & seg = GetOpenSegment(i); frontpoints.Set (seg[0]); frontpoints.Set (seg[1]); } for (int i = 1; i <= GetNSE(); i++) { Element2d & sel = surfelements.Elem(i); bool remove = false; for (int j = 1; j <= sel.GetNP(); j++) if (frontpoints.Test(sel.PNum(j))) remove = true; if (remove) sel.PNum(1).Invalidate(); } for (int i = surfelements.Size(); i >= 1; i--) { if (!surfelements.Elem(i).PNum(1).IsValid()) { surfelements.Elem(i) = surfelements.Last(); surfelements.DeleteLast(); } } RebuildSurfaceElementLists (); /* for (int i = 0; i < facedecoding.Size(); i++) facedecoding[i].firstelement = -1; for (int i = surfelements.Size()-1; i >= 0; i--) { int ind = surfelements[i].GetIndex(); surfelements[i].next = facedecoding[ind-1].firstelement; facedecoding[ind-1].firstelement = i; } */ timestamp = NextTimeStamp(); // Compress(); } void Mesh :: FreeOpenElementsEnvironment (int layers) { int i, j, k; PointIndex pi; const int large = 9999; Array dist(GetNP()); dist = large; for (int i = 1; i <= GetNOpenElements(); i++) { const Element2d & face = OpenElement(i); for (j = 0; j < face.GetNP(); j++) dist[face[j]] = 1; } for (k = 1; k <= layers; k++) for (i = 1; i <= GetNE(); i++) { const Element & el = VolumeElement(i); if (el[0] == -1 || el.IsDeleted()) continue; int elmin = large; for (j = 0; j < el.GetNP(); j++) if (dist[el[j]] < elmin) elmin = dist[el[j]]; if (elmin < large) { for (j = 0; j < el.GetNP(); j++) if (dist[el[j]] > elmin+1) dist[el[j]] = elmin+1; } } int cntfree = 0; for (i = 1; i <= GetNE(); i++) { Element & el = VolumeElement(i); if (el[0] == -1 || el.IsDeleted()) continue; int elmin = large; for (j = 0; j < el.GetNP(); j++) if (dist[el[j]] < elmin) elmin = dist[el[j]]; el.flags.fixed = elmin > layers; // eltyps.Elem(i) = (elmin <= layers) ? // FREEELEMENT : FIXEDELEMENT; if (elmin <= layers) cntfree++; } PrintMessage (5, "free: ", cntfree, ", fixed: ", GetNE()-cntfree); (*testout) << "free: " << cntfree << ", fixed: " << GetNE()-cntfree << endl; for (pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++) { if (dist[pi] > layers+1) points[pi].SetType(FIXEDPOINT); } } void Mesh :: SetLocalH (netgen::Point<3> pmin, netgen::Point<3> pmax, double grading) { using netgen::Point; Point<3> c = Center (pmin, pmax); double d = max3 (pmax(0)-pmin(0), pmax(1)-pmin(1), pmax(2)-pmin(2)); d /= 2; Point<3> pmin2 = c - Vec<3> (d, d, d); Point<3> pmax2 = c + Vec<3> (d, d, d); delete lochfunc; lochfunc = new LocalH (pmin2, pmax2, grading, dimension); } void Mesh :: RestrictLocalH (const Point3d & p, double hloc) { if(hloc < hmin) hloc = hmin; //cout << "restrict h in " << p << " to " << hloc << endl; if (!lochfunc) { PrintWarning("RestrictLocalH called, creating mesh-size tree"); Point3d boxmin, boxmax; GetBox (boxmin, boxmax); SetLocalH (boxmin, boxmax, 0.8); } lochfunc -> SetH (p, hloc); } void Mesh :: RestrictLocalHLine (const Point3d & p1, const Point3d & p2, double hloc) { if(hloc < hmin) hloc = hmin; // cout << "restrict h along " << p1 << " - " << p2 << " to " << hloc << endl; int i; int steps = int (Dist (p1, p2) / hloc) + 2; Vec3d v(p1, p2); for (i = 0; i <= steps; i++) { Point3d p = p1 + (double(i)/double(steps) * v); RestrictLocalH (p, hloc); } } void Mesh :: SetMinimalH (double h) { hmin = h; } void Mesh :: SetGlobalH (double h) { hglob = h; } double Mesh :: MaxHDomain (int dom) const { if (maxhdomain.Size()) return maxhdomain.Get(dom); else return 1e10; } void Mesh :: SetMaxHDomain (const Array & mhd) { maxhdomain.SetSize(mhd.Size()); for (int i = 1; i <= mhd.Size(); i++) maxhdomain.Elem(i) = mhd.Get(i); } double Mesh :: GetH (const Point3d & p) const { double hmin = hglob; if (lochfunc) { double hl = lochfunc->GetH (p); if (hl < hglob) hmin = hl; } return hmin; } double Mesh :: GetMinH (const Point3d & pmin, const Point3d & pmax) { double hmin = hglob; if (lochfunc) { double hl = lochfunc->GetMinH (pmin, pmax); if (hl < hmin) hmin = hl; } return hmin; } double Mesh :: AverageH (int surfnr) const { int i, j, n; double hi, hsum; double maxh = 0, minh = 1e10; hsum = 0; n = 0; for (i = 1; i <= GetNSE(); i++) { const Element2d & el = SurfaceElement(i); if (surfnr == 0 || el.GetIndex() == surfnr) { for (j = 1; j <= 3; j++) { hi = Dist (Point (el.PNumMod(j)), Point (el.PNumMod(j+1))); hsum += hi; if (hi > maxh) maxh = hi; if (hi < minh) minh = hi; n++; } } } PrintMessage (5, "minh = ", minh, " avh = ", (hsum/n), " maxh = ", maxh); return (hsum / n); } void Mesh :: CalcLocalH (double grading) { static Timer t("Mesh::CalcLocalH"); RegionTimer reg(t); if (!lochfunc) { Point3d pmin, pmax; GetBox (pmin, pmax); // SetLocalH (pmin, pmax, mparam.grading); SetLocalH (pmin, pmax, grading); } PrintMessage (3, "CalcLocalH: ", GetNP(), " Points ", GetNE(), " Elements ", GetNSE(), " Surface Elements"); for (int i = 0; i < GetNSE(); i++) { const Element2d & el = surfelements[i]; int j; if (el.GetNP() == 3) { double hel = -1; for (j = 1; j <= 3; j++) { const Point3d & p1 = points[el.PNumMod(j)]; const Point3d & p2 = points[el.PNumMod(j+1)]; /* INDEX_2 i21(el.PNumMod(j), el.PNumMod(j+1)); INDEX_2 i22(el.PNumMod(j+1), el.PNumMod(j)); if (! identifiedpoints->Used (i21) && ! identifiedpoints->Used (i22) ) */ if (!ident -> UsedSymmetric (el.PNumMod(j), el.PNumMod(j+1))) { double hedge = Dist (p1, p2); if (hedge > hel) hel = hedge; // lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); // (*testout) << "trigseth, p1,2 = " << el.PNumMod(j) << ", " << el.PNumMod(j+1) // << " h = " << (2 * Dist(p1, p2)) << endl; } } if (hel > 0) { const Point3d & p1 = points[el.PNum(1)]; const Point3d & p2 = points[el.PNum(2)]; const Point3d & p3 = points[el.PNum(3)]; lochfunc->SetH (Center (p1, p2, p3), hel); } } else { { const Point3d & p1 = points[el.PNum(1)]; const Point3d & p2 = points[el.PNum(2)]; lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); } { const Point3d & p1 = points[el.PNum(3)]; const Point3d & p2 = points[el.PNum(4)]; lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); } } } for (int i = 0; i < GetNSeg(); i++) { const Segment & seg = segments[i]; const Point3d & p1 = points[seg[0]]; const Point3d & p2 = points[seg[1]]; /* INDEX_2 i21(seg[0], seg[1]); INDEX_2 i22(seg[1], seg[0]); if (identifiedpoints) if (!identifiedpoints->Used (i21) && !identifiedpoints->Used (i22)) */ if (!ident -> UsedSymmetric (seg[0], seg[1])) { lochfunc->SetH (Center (p1, p2), Dist (p1, p2)); } } /* cerr << "do vol" << endl; for (i = 1; i <= GetNE(); i++) { const Element & el = VolumeElement(i); if (el.GetType() == TET) { int j, k; for (j = 2; j <= 4; j++) for (k = 1; k < j; k++) { const Point3d & p1 = Point (el.PNum(j)); const Point3d & p2 = Point (el.PNum(k)); lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); (*testout) << "set vol h to " << (2 * Dist (p1, p2)) << endl; } } } */ /* const char * meshsizefilename = globflags.GetStringFlag ("meshsize", NULL); if (meshsizefilename) { ifstream msf(meshsizefilename); if (msf) { int nmsp; msf >> nmsp; for (i = 1; i <= nmsp; i++) { Point3d pi; double hi; msf >> pi.X() >> pi.Y() >> pi.Z(); msf >> hi; lochfunc->SetH (pi, hi); } } } */ // lochfunc -> Convexify(); // lochfunc -> PrintMemInfo (cout); } void Mesh :: CalcLocalHFromPointDistances(double grading) { PrintMessage (3, "Calculating local h from point distances"); if (!lochfunc) { Point3d pmin, pmax; GetBox (pmin, pmax); // SetLocalH (pmin, pmax, mparam.grading); SetLocalH (pmin, pmax, grading); } PointIndex i,j; double hl; for (i = PointIndex::BASE; i < GetNP()+PointIndex::BASE; i++) { for(j=i+1; j edges(3 * GetNP() + 2); INDEX_2_HASHTABLE bedges(GetNSeg() + 2); int i, j; for (i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment(i); INDEX_2 i2(seg[0], seg[1]); i2.Sort(); bedges.Set (i2, 1); } for (i = 1; i <= GetNSE(); i++) { const Element2d & sel = SurfaceElement(i); if (!sel.PNum(1)) continue; for (j = 1; j <= 3; j++) { INDEX_2 i2(sel.PNumMod(j), sel.PNumMod(j+1)); i2.Sort(); if (bedges.Used(i2)) continue; if (edges.Used(i2)) { int other = edges.Get(i2); const Element2d & elother = SurfaceElement(other); int pi3 = 1; while ( (sel.PNum(pi3) == i2.I1()) || (sel.PNum(pi3) == i2.I2())) pi3++; pi3 = sel.PNum(pi3); int pi4 = 1; while ( (elother.PNum(pi4) == i2.I1()) || (elother.PNum(pi4) == i2.I2())) pi4++; pi4 = elother.PNum(pi4); double rad = ComputeCylinderRadius (Point (i2.I1()), Point (i2.I2()), Point (pi3), Point (pi4)); RestrictLocalHLine (Point(i2.I1()), Point(i2.I2()), rad/elperr); /* (*testout) << "pi1,2, 3, 4 = " << i2.I1() << ", " << i2.I2() << ", " << pi3 << ", " << pi4 << " p1 = " << Point(i2.I1()) << ", p2 = " << Point(i2.I2()) // << ", p3 = " << Point(pi3) // << ", p4 = " << Point(pi4) << ", rad = " << rad << endl; */ } else edges.Set (i2, i); } } // Restrict h due to line segments for (i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment(i); const Point3d & p1 = Point(seg[0]); const Point3d & p2 = Point(seg[1]); RestrictLocalH (Center (p1, p2), Dist (p1, p2)); } /* int i, j; int np = GetNP(); int nseg = GetNSeg(); int nse = GetNSE(); Array normals(np); BitArray linepoint(np); linepoint.Clear(); for (i = 1; i <= nseg; i++) { linepoint.Set (LineSegment(i)[0]); linepoint.Set (LineSegment(i)[1]); } for (i = 1; i <= np; i++) normals.Elem(i) = Vec3d(0,0,0); for (i = 1; i <= nse; i++) { Element2d & el = SurfaceElement(i); Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))), Vec3d (Point (el.PNum(1)), Point(el.PNum(3)))); for (j = 1; j <= 3; j++) normals.Elem(el.PNum(j)) += nf; } for (i = 1; i <= np; i++) normals.Elem(i) /= (1e-12 + normals.Elem(i).Length()); for (i = 1; i <= nse; i++) { Element2d & el = SurfaceElement(i); Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))), Vec3d (Point (el.PNum(1)), Point(el.PNum(3)))); nf /= nf.Length(); Point3d c = Center (Point(el.PNum(1)), Point(el.PNum(2)), Point(el.PNum(3))); for (j = 1; j <= 3; j++) { if (!linepoint.Test (el.PNum(j))) { double dist = Dist (c, Point(el.PNum(j))); double dn = (nf - normals.Get(el.PNum(j))).Length(); RestrictLocalH (Point(el.PNum(j)), dist / (dn+1e-12) /elperr); } } } */ } void Mesh :: RestrictLocalH (resthtype rht, int nr, double loch) { int i; switch (rht) { case RESTRICTH_FACE: { for (i = 1; i <= GetNSE(); i++) { const Element2d & sel = SurfaceElement(i); if (sel.GetIndex() == nr) RestrictLocalH (RESTRICTH_SURFACEELEMENT, i, loch); } break; } case RESTRICTH_EDGE: { for (i = 1; i <= GetNSeg(); i++) { const Segment & seg = LineSegment(i); if (seg.edgenr == nr) RestrictLocalH (RESTRICTH_SEGMENT, i, loch); } break; } case RESTRICTH_POINT: { RestrictLocalH (Point (nr), loch); break; } case RESTRICTH_SURFACEELEMENT: { const Element2d & sel = SurfaceElement(nr); Point3d p = Center (Point(sel.PNum(1)), Point(sel.PNum(2)), Point(sel.PNum(3))); RestrictLocalH (p, loch); break; } case RESTRICTH_SEGMENT: { const Segment & seg = LineSegment(nr); RestrictLocalHLine (Point (seg[0]), Point(seg[1]), loch); break; } } } void Mesh :: LoadLocalMeshSize (const string & meshsizefilename) { // Philippose - 10/03/2009 // Improve error checking when loading and reading // the local mesh size file if (meshsizefilename.empty()) return; ifstream msf(meshsizefilename.c_str()); // Philippose - 09/03/2009 // Adding print message information in case the specified // does not exist, or does not load successfully due to // other reasons such as access rights, etc... if (!msf) { PrintMessage(3, "Error loading mesh size file: ", meshsizefilename, "....","Skipping!"); return; } PrintMessage (3, "Load local mesh-size file: ", meshsizefilename); int nmsp = 0; int nmsl = 0; msf >> nmsp; if(!msf.good()) throw NgException ("Mesh-size file error: No points found\n"); if(nmsp > 0) PrintMessage (4, "Number of mesh-size restriction points: ", nmsp); for (int i = 0; i < nmsp; i++) { Point3d pi; double hi; msf >> pi.X() >> pi.Y() >> pi.Z(); msf >> hi; if (!msf.good()) throw NgException ("Mesh-size file error: Number of points don't match specified list size\n"); RestrictLocalH (pi, hi); } msf >> nmsl; if(!msf.good()) throw NgException ("Mesh-size file error: No line definitions found\n"); if(nmsl > 0) PrintMessage (4, "Number of mesh-size restriction lines: ", nmsl); for (int i = 0; i < nmsl; i++) { Point3d p1, p2; double hi; msf >> p1.X() >> p1.Y() >> p1.Z(); msf >> p2.X() >> p2.Y() >> p2.Z(); msf >> hi; if (!msf.good()) throw NgException ("Mesh-size file error: Number of line definitions don't match specified list size\n"); RestrictLocalHLine (p1, p2, hi); } msf.close(); } void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, int dom) const { if (points.Size() == 0) { pmin = pmax = Point3d(0,0,0); return; } if (dom <= 0) { pmin = Point3d (1e10, 1e10, 1e10); pmax = Point3d (-1e10, -1e10, -1e10); for (PointIndex pi = points.Begin(); pi < points.End(); pi++) { pmin.SetToMin ( (*this) [pi] ); pmax.SetToMax ( (*this) [pi] ); } } else { int j, nse = GetNSE(); SurfaceElementIndex sei; pmin = Point3d (1e10, 1e10, 1e10); pmax = Point3d (-1e10, -1e10, -1e10); for (sei = 0; sei < nse; sei++) { const Element2d & el = (*this)[sei]; if (el.IsDeleted() ) continue; if (dom == -1 || el.GetIndex() == dom) { for (j = 0; j < 3; j++) { pmin.SetToMin ( (*this) [el[j]] ); pmax.SetToMax ( (*this) [el[j]] ); } } } } if (pmin.X() > 0.5e10) { pmin = pmax = Point3d(0,0,0); } } void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, POINTTYPE ptyp) const { if (points.Size() == 0) { pmin = pmax = Point3d(0,0,0); return; } pmin = Point3d (1e10, 1e10, 1e10); pmax = Point3d (-1e10, -1e10, -1e10); for (PointIndex pi = points.Begin(); pi < points.End(); pi++) if (points[pi].Type() <= ptyp) { pmin.SetToMin ( (*this) [pi] ); pmax.SetToMax ( (*this) [pi] ); } } double Mesh :: ElementError (int eli, const MeshingParameters & mp) const { const Element & el = volelements.Get(eli); return CalcTetBadness (points.Get(el[0]), points.Get(el[1]), points.Get(el[2]), points.Get(el[3]), -1, mp); } void Mesh :: AddLockedPoint (PointIndex pi) { lockedpoints.Append (pi); } void Mesh :: ClearLockedPoints () { lockedpoints.SetSize (0); } void Mesh :: Compress () { static Timer t("Mesh::Compress"); RegionTimer reg(t); Array op2np(GetNP()); Array hpoints; BitArrayChar pused(GetNP()); /* (*testout) << "volels: " << endl; for (i = 1; i <= volelements.Size(); i++) { for (j = 1; j <= volelements.Get(i).GetNP(); j++) (*testout) << volelements.Get(i).PNum(j) << " "; (*testout) << endl; } (*testout) << "np: " << GetNP() << endl; */ for (int i = 0; i < volelements.Size(); i++) if (volelements[i][0] <= PointIndex::BASE-1 || volelements[i].IsDeleted()) { volelements.Delete(i); i--; } for (int i = 0; i < surfelements.Size(); i++) if (surfelements[i].IsDeleted()) { surfelements.Delete(i); i--; } for (int i = 0; i < segments.Size(); i++) if (segments[i][0] <= PointIndex::BASE-1) { segments.Delete(i); i--; } for(int i=0; i < segments.Size(); i++) if(segments[i].edgenr < 0) segments.Delete(i--); pused.Clear(); for (int i = 0; i < volelements.Size(); i++) { const Element & el = volelements[i]; for (int j = 0; j < el.GetNP(); j++) pused.Set (el[j]); } for (int i = 0; i < surfelements.Size(); i++) { const Element2d & el = surfelements[i]; for (int j = 0; j < el.GetNP(); j++) pused.Set (el[j]); } for (int i = 0; i < segments.Size(); i++) { const Segment & seg = segments[i]; for (int j = 0; j < seg.GetNP(); j++) pused.Set (seg[j]); } for (int i = 0; i < openelements.Size(); i++) { const Element2d & el = openelements[i]; for (int j = 0; j < el.GetNP(); j++) pused.Set(el[j]); } for (int i = 0; i < lockedpoints.Size(); i++) pused.Set (lockedpoints[i]); /* // compress points doesn't work for identified points ! if (identifiedpoints) { for (i = 1; i <= identifiedpoints->GetNBags(); i++) if (identifiedpoints->GetBagSize(i)) { pused.Set (); break; } } */ // pused.Set(); int npi = PointIndex::BASE-1; for (PointIndex pi = points.Begin(); pi < points.End(); pi++) if (pused.Test(pi)) { npi++; op2np[pi] = npi; hpoints.Append (points[pi]); } else op2np[pi] = -1; points.SetSize(0); for (int i = 0; i < hpoints.Size(); i++) points.Append (hpoints[i]); for (int i = 1; i <= volelements.Size(); i++) { Element & el = VolumeElement(i); for (int j = 0; j < el.GetNP(); j++) el[j] = op2np[el[j]]; } for (int i = 1; i <= surfelements.Size(); i++) { Element2d & el = SurfaceElement(i); for (int j = 0; j < el.GetNP(); j++) el[j] = op2np[el[j]]; } for (int i = 0; i < segments.Size(); i++) { Segment & seg = segments[i]; for (int j = 0; j < seg.GetNP(); j++) seg[j] = op2np[seg[j]]; } for (int i = 1; i <= openelements.Size(); i++) { Element2d & el = openelements.Elem(i); for (int j = 0; j < el.GetNP(); j++) el[j] = op2np[el[j]]; } for (int i = 0; i < lockedpoints.Size(); i++) lockedpoints[i] = op2np[lockedpoints[i]]; /* for (int i = 0; i < facedecoding.Size(); i++) facedecoding[i].firstelement = -1; for (int i = surfelements.Size()-1; i >= 0; i--) { int ind = surfelements[i].GetIndex(); surfelements[i].next = facedecoding[ind-1].firstelement; facedecoding[ind-1].firstelement = i; } */ RebuildSurfaceElementLists (); CalcSurfacesOfNode(); // FindOpenElements(); timestamp = NextTimeStamp(); } void Mesh :: OrderElements() { for (auto & el : surfelements) { if (el.GetType() == TRIG) while (el[0] > el[1] || el[0] > el[2]) { // rotate element auto hp = el[0]; el[0] = el[1]; el[1] = el[2]; el[2] = hp; auto hgi = el.GeomInfoPi(1); el.GeomInfoPi(1) = el.GeomInfoPi(2); el.GeomInfoPi(2) = el.GeomInfoPi(3); el.GeomInfoPi(3) = hgi; } } for (auto & el : volelements) if (el.GetType() == TET) { // lowest index first ... int mini = 0; for (int i = 1; i < 4; i++) if (el[i] < el[mini]) mini = i; if (mini != 0) { // swap 0 with mini, and the other two ... int i3 = -1, i4 = -1; for (int i = 1; i < 4; i++) if (i != mini) { i4 = i3; i3 = i; } swap (el[0], el[mini]); swap (el[i3], el[i4]); } while (el[1] > el[2] || el[1] > el[3]) { // rotate element to move second index to second position auto hp = el[1]; el[1] = el[2]; el[2] = el[3]; el[3] = hp; } } } int Mesh :: CheckConsistentBoundary () const { int nf = GetNOpenElements(); INDEX_2_HASHTABLE edges(nf+2); INDEX_2 i2, i2s, edge; int err = 0; for (int i = 1; i <= nf; i++) { const Element2d & sel = OpenElement(i); for (int j = 1; j <= sel.GetNP(); j++) { i2.I1() = sel.PNumMod(j); i2.I2() = sel.PNumMod(j+1); int sign = (i2.I2() > i2.I1()) ? 1 : -1; i2.Sort(); if (!edges.Used (i2)) edges.Set (i2, 0); edges.Set (i2, edges.Get(i2) + sign); } } for (int i = 1; i <= edges.GetNBags(); i++) for (int j = 1; j <= edges.GetBagSize(i); j++) { int cnt = 0; edges.GetData (i, j, i2, cnt); if (cnt) { PrintError ("Edge ", i2.I1() , " - ", i2.I2(), " multiple times in surface mesh"); (*testout) << "Edge " << i2 << " multiple times in surface mesh" << endl; i2s = i2; i2s.Sort(); for (int k = 1; k <= nf; k++) { const Element2d & sel = OpenElement(k); for (int l = 1; l <= sel.GetNP(); l++) { edge.I1() = sel.PNumMod(l); edge.I2() = sel.PNumMod(l+1); edge.Sort(); if (edge == i2s) (*testout) << "edge of element " << sel << endl; } } err = 2; } } return err; } int Mesh :: CheckOverlappingBoundary () { static Timer t("Mesh::CheckOverlappingBoundary"); RegionTimer reg(t); int i, j, k; Point3d pmin, pmax; GetBox (pmin, pmax); BoxTree<3> setree(pmin, pmax); Array inters; bool overlap = 0; bool incons_layers = 0; for (i = 1; i <= GetNSE(); i++) SurfaceElement(i).badel = 0; for (i = 1; i <= GetNSE(); i++) { const Element2d & tri = SurfaceElement(i); Point3d tpmin (Point(tri[0])); Point3d tpmax (tpmin); for (k = 1; k < tri.GetNP(); k++) { tpmin.SetToMin (Point (tri[k])); tpmax.SetToMax (Point (tri[k])); } Vec3d diag(tpmin, tpmax); tpmax = tpmax + 0.1 * diag; tpmin = tpmin - 0.1 * diag; setree.Insert (tpmin, tpmax, i); } for (i = 1; i <= GetNSE(); i++) { const Element2d & tri = SurfaceElement(i); Point3d tpmin (Point(tri[0])); Point3d tpmax (tpmin); for (k = 1; k < tri.GetNP(); k++) { tpmin.SetToMin (Point (tri[k])); tpmax.SetToMax (Point (tri[k])); } setree.GetIntersecting (tpmin, tpmax, inters); for (j = 1; j <= inters.Size(); j++) { const Element2d & tri2 = SurfaceElement(inters.Get(j)); if ( (*this)[tri[0]].GetLayer() != (*this)[tri2[0]].GetLayer()) continue; if ( (*this)[tri[0]].GetLayer() != (*this)[tri[1]].GetLayer() || (*this)[tri[0]].GetLayer() != (*this)[tri[2]].GetLayer()) { incons_layers = 1; cout << "inconsistent layers in triangle" << endl; } const netgen::Point<3> *trip1[3], *trip2[3]; for (k = 1; k <= 3; k++) { trip1[k-1] = &Point (tri.PNum(k)); trip2[k-1] = &Point (tri2.PNum(k)); } if (IntersectTriangleTriangle (&trip1[0], &trip2[0])) { overlap = 1; PrintWarning ("Intersecting elements " ,i, " and ", inters.Get(j)); (*testout) << "Intersecting: " << endl; (*testout) << "openelement " << i << " with open element " << inters.Get(j) << endl; cout << "el1 = " << tri << endl; cout << "el2 = " << tri2 << endl; cout << "layer1 = " << (*this)[tri[0]].GetLayer() << endl; cout << "layer2 = " << (*this)[tri2[0]].GetLayer() << endl; for (k = 1; k <= 3; k++) (*testout) << tri.PNum(k) << " "; (*testout) << endl; for (k = 1; k <= 3; k++) (*testout) << tri2.PNum(k) << " "; (*testout) << endl; for (k = 0; k <= 2; k++) (*testout) << *trip1[k] << " "; (*testout) << endl; for (k = 0; k <= 2; k++) (*testout) << *trip2[k] << " "; (*testout) << endl; (*testout) << "Face1 = " << GetFaceDescriptor(tri.GetIndex()) << endl; (*testout) << "Face1 = " << GetFaceDescriptor(tri2.GetIndex()) << endl; /* INDEX_3 i3(tri.PNum(1), tri.PNum(2), tri.PNum(3)); i3.Sort(); for (k = 1; k <= GetNSE(); k++) { const Element2d & el2 = SurfaceElement(k); INDEX_3 i3b(el2.PNum(1), el2.PNum(2), el2.PNum(3)); i3b.Sort(); if (i3 == i3b) { SurfaceElement(k).badel = 1; } } */ SurfaceElement(i).badel = 1; SurfaceElement(inters.Get(j)).badel = 1; } } } // bug 'fix' if (incons_layers) overlap = 0; return overlap; } int Mesh :: CheckVolumeMesh () const { PrintMessage (3, "Checking volume mesh"); int ne = GetNE(); DenseMatrix dtrans(3,3); int i, j; PrintMessage (5, "elements: ", ne); for (i = 1; i <= ne; i++) { Element & el = (Element&) VolumeElement(i); el.flags.badel = 0; int nip = el.GetNIP(); for (j = 1; j <= nip; j++) { el.GetTransformation (j, Points(), dtrans); double det = dtrans.Det(); if (det > 0) { PrintError ("Element ", i , " has wrong orientation"); el.flags.badel = 1; } } } return 0; } bool Mesh :: LegalTrig (const Element2d & el) const { return 1; if ( /* hp */ 1) // needed for old, simple hp-refinement { // trigs with 2 or more segments are illegal int i; int nseg = 0; if (!segmentht) { cerr << "no segmentht allocated" << endl; return 0; } // Point3d cp(0.5, 0.5, 0.5); for (i = 1; i <= 3; i++) { INDEX_2 i2(el.PNumMod (i), el.PNumMod (i+1)); i2.Sort(); if (segmentht -> Used (i2)) nseg++; } if (nseg >= 2) return 0; } return 1; } /// bool Mesh :: LegalTet2 (Element & el) const { // static int timer1 = NgProfiler::CreateTimer ("Legaltet2"); // Test, whether 4 points have a common surface plus // at least 4 edges at the boundary if(!boundaryedges) const_cast(this)->BuildBoundaryEdges(); // non-tets are always legal if (el.GetType() != TET) { el.SetLegal (1); return 1; } POINTTYPE pointtype[4]; for(int i = 0; i < 4; i++) pointtype[i] = (*this)[el[i]].Type(); // element has at least 2 inner points ---> legal int cnti = 0; for (int j = 0; j < 4; j++) if ( pointtype[j] == INNERPOINT) { cnti++; if (cnti >= 2) { el.SetLegal (1); return 1; } } // which faces are boundary faces ? int bface[4]; for (int i = 0; i < 4; i++) { bface[i] = surfelementht->Used (INDEX_3::Sort(el[gftetfacesa[i][0]], el[gftetfacesa[i][1]], el[gftetfacesa[i][2]])); } int bedge[4][4]; int segedge[4][4]; static const int pi3map[4][4] = { { -1, 2, 1, 1 }, { 2, -1, 0, 0 }, { 1, 0, -1, 0 }, { 1, 0, 0, -1 } }; static const int pi4map[4][4] = { { -1, 3, 3, 2 }, { 3, -1, 3, 2 }, { 3, 3, -1, 1 }, { 2, 2, 1, -1 } }; for (int i = 0; i < 4; i++) for (int j = 0; j < i; j++) { bool sege = false, be = false; int pos = boundaryedges -> Position0(INDEX_2::Sort(el[i], el[j])); if (pos != -1) { be = true; if (boundaryedges -> GetData0(pos) == 2) sege = true; } segedge[j][i] = segedge[i][j] = sege; bedge[j][i] = bedge[i][j] = be; } // two boundary faces and no edge is illegal for (int i = 0; i < 3; i++) for (int j = i+1; j < 4; j++) { if (bface[i] && bface[j]) if (!segedge[pi3map[i][j]][pi4map[i][j]]) { // 2 boundary faces withoud edge in between el.SetLegal (0); return 0; } } // three boundary edges meeting in a Surface point for (int i = 0; i < 4; i++) { if ( pointtype[i] == SURFACEPOINT) { bool alledges = 1; for (int j = 0; j < 4; j++) if (j != i && !bedge[i][j]) { alledges = 0; break; } if (alledges) { // cout << "tet illegal due to unmarked node" << endl; el.SetLegal (0); return 0; } } } for (int fnr = 0; fnr < 4; fnr++) if (!bface[fnr]) for (int i = 0; i < 4; i++) if (i != fnr) { int pi1 = pi3map[i][fnr]; int pi2 = pi4map[i][fnr]; if ( pointtype[i] == SURFACEPOINT) { // two connected edges on surface, but no face if (bedge[i][pi1] && bedge[i][pi2]) { el.SetLegal (0); return 0; } } if ( pointtype[i] == EDGEPOINT) { // connected surface edge and edge edge, but no face if ( (bedge[i][pi1] && segedge[i][pi2]) || (bedge[i][pi2] && segedge[i][pi1]) ) { el.SetLegal (0); return 0; } } } el.SetLegal (1); return 1; } int Mesh :: GetNDomains() const { int ndom = 0; for (int k = 0; k < facedecoding.Size(); k++) { if (facedecoding[k].DomainIn() > ndom) ndom = facedecoding[k].DomainIn(); if (facedecoding[k].DomainOut() > ndom) ndom = facedecoding[k].DomainOut(); } return ndom; } void Mesh :: SurfaceMeshOrientation () { int i, j; int nse = GetNSE(); BitArray used(nse); used.Clear(); INDEX_2_HASHTABLE edges(nse+1); bool haschanged = 0; const Element2d & tri = SurfaceElement(1); for (j = 1; j <= 3; j++) { INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1)); edges.Set (i2, 1); } used.Set(1); bool unused; do { bool changed; do { changed = 0; for (i = 1; i <= nse; i++) if (!used.Test(i)) { Element2d & el = surfelements.Elem(i); int found = 0, foundrev = 0; for (j = 1; j <= 3; j++) { INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1)); if (edges.Used(i2)) foundrev = 1; swap (i2.I1(), i2.I2()); if (edges.Used(i2)) found = 1; } if (found || foundrev) { if (foundrev) swap (el.PNum(2), el.PNum(3)); changed = 1; for (j = 1; j <= 3; j++) { INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1)); edges.Set (i2, 1); } used.Set (i); } } if (changed) haschanged = 1; } while (changed); unused = 0; for (i = 1; i <= nse; i++) if (!used.Test(i)) { unused = 1; const Element2d & tri = SurfaceElement(i); for (j = 1; j <= 3; j++) { INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1)); edges.Set (i2, 1); } used.Set(i); break; } } while (unused); if (haschanged) timestamp = NextTimeStamp(); } void Mesh :: Split2Tets() { PrintMessage (1, "Split To Tets"); bool has_prisms = 0; int oldne = GetNE(); for (int i = 1; i <= oldne; i++) { Element el = VolumeElement(i); if (el.GetType() == PRISM) { // prism, to 3 tets // make minimal node to node 1 int minpi=0; PointIndex minpnum; minpnum = GetNP() + 1; for (int j = 1; j <= 6; j++) { if (el.PNum(j) < minpnum) { minpnum = el.PNum(j); minpi = j; } } if (minpi >= 4) { for (int j = 1; j <= 3; j++) swap (el.PNum(j), el.PNum(j+3)); minpi -= 3; } while (minpi > 1) { int hi = 0; for (int j = 0; j <= 3; j+= 3) { hi = el.PNum(1+j); el.PNum(1+j) = el.PNum(2+j); el.PNum(2+j) = el.PNum(3+j); el.PNum(3+j) = hi; } minpi--; } /* version 1: edge from pi2 to pi6, version 2: edge from pi3 to pi5, */ static const int ntets[2][12] = { { 1, 4, 5, 6, 1, 2, 3, 6, 1, 2, 5, 6 }, { 1, 4, 5, 6, 1, 2, 3, 5, 3, 1, 5, 6 } }; const int * min2pi; if (min2 (el.PNum(2), el.PNum(6)) < min2 (el.PNum(3), el.PNum(5))) { min2pi = &ntets[0][0]; // (*testout) << "version 1 "; } else { min2pi = &ntets[1][0]; // (*testout) << "version 2 "; } int firsttet = 1; for (int j = 1; j <= 3; j++) { Element nel(TET); for (int k = 1; k <= 4; k++) nel.PNum(k) = el.PNum(min2pi[4 * j + k - 5]); nel.SetIndex (el.GetIndex()); int legal = 1; for (int k = 1; k <= 3; k++) for (int l = k+1; l <= 4; l++) if (nel.PNum(k) == nel.PNum(l)) legal = 0; // (*testout) << nel << " "; if (legal) { if (firsttet) { VolumeElement(i) = nel; firsttet = 0; } else { AddVolumeElement(nel); } } } if (firsttet) cout << "no legal"; (*testout) << endl; } else if (el.GetType() == HEX) { // hex to A) 2 prisms or B) to 5 tets // make minimal node to node 1 int minpi=0; PointIndex minpnum; minpnum = GetNP() + 1; for (int j = 1; j <= 8; j++) { if (el.PNum(j) < minpnum) { minpnum = el.PNum(j); minpi = j; } } if (minpi >= 5) { for (int j = 1; j <= 4; j++) swap (el.PNum(j), el.PNum(j+4)); minpi -= 4; } while (minpi > 1) { int hi = 0; for (int j = 0; j <= 4; j+= 4) { hi = el.PNum(1+j); el.PNum(1+j) = el.PNum(2+j); el.PNum(2+j) = el.PNum(3+j); el.PNum(3+j) = el.PNum(4+j); el.PNum(4+j) = hi; } minpi--; } static const int to_prisms[3][12] = { { 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 6, 7 }, { 0, 1, 5, 3, 2, 6, 0, 5, 4, 3, 6, 7 }, { 0, 7, 4, 1, 6, 5, 0, 3, 7, 1, 2, 6 }, }; const int * min2pi = 0; if (min2 (el[4], el[6]) < min2 (el[5], el[7])) min2pi = &to_prisms[0][0]; else if (min2 (el[3], el[6]) < min2 (el[2], el[7])) min2pi = &to_prisms[1][0]; else if (min2 (el[1], el[6]) < min2 (el[2], el[5])) min2pi = &to_prisms[2][0]; if (min2pi) { has_prisms = 1; for (int j = 0; j < 2; j++) { Element nel(PRISM); for (int k = 0; k < 6; k++) nel[k] = el[min2pi[6*j + k]]; nel.SetIndex (el.GetIndex()); if (j == 0) VolumeElement(i) = nel; else AddVolumeElement(nel); } } else { // split to 5 tets static const int to_tets[20] = { 1, 2, 0, 5, 3, 0, 2, 7, 4, 5, 7, 0, 6, 7, 5, 2, 0, 2, 7, 5 }; for (int j = 0; j < 5; j++) { Element nel(TET); for (int k = 0; k < 4; k++) nel[k] = el[to_tets[4*j + k]]; nel.SetIndex (el.GetIndex()); if (j == 0) VolumeElement(i) = nel; else AddVolumeElement(nel); } } } else if (el.GetType() == PYRAMID) { // pyramid, to 2 tets // cout << "pyramid: " << el << endl; static const int ntets[2][8] = { { 1, 2, 3, 5, 1, 3, 4, 5 }, { 1, 2, 4, 5, 4, 2, 3, 5 }}; const int * min2pi; if (min2 (el[0], el[2]) < min2 (el[1], el[3])) min2pi = &ntets[0][0]; else min2pi = &ntets[1][0]; bool firsttet = 1; for (int j = 0; j < 2; j++) { Element nel(TET); for (int k = 0; k < 4; k++) nel[k] = el[min2pi[4*j + k]-1]; nel.SetIndex (el.GetIndex()); // cout << "pyramid-tet: " << nel << endl; bool legal = 1; for (int k = 0; k < 3; k++) for (int l = k+1; l < 4; l++) if (nel[k] == nel[l]) legal = 0; if (legal) { (*testout) << nel << " "; if (firsttet) VolumeElement(i) = nel; else AddVolumeElement(nel); firsttet = 0; } } if (firsttet) cout << "no legal"; (*testout) << endl; } } int oldnse = GetNSE(); for (int i = 1; i <= oldnse; i++) { Element2d el = SurfaceElement(i); if (el.GetNP() == 4) { (*testout) << "split el: " << el << " to "; static const int ntris[2][6] = { { 1, 2, 3, 1, 3, 4 }, { 1, 2, 4, 4, 2, 3 }}; const int * min2pi; if (min2 (el.PNum(1), el.PNum(3)) < min2 (el.PNum(2), el.PNum(4))) min2pi = &ntris[0][0]; else min2pi = &ntris[1][0]; for (int j = 0; j <6; j++) (*testout) << min2pi[j] << " "; int firsttri = 1; for (int j = 1; j <= 2; j++) { Element2d nel(3); for (int k = 1; k <= 3; k++) nel.PNum(k) = el.PNum(min2pi[3 * j + k - 4]); nel.SetIndex (el.GetIndex()); int legal = 1; for (int k = 1; k <= 2; k++) for (int l = k+1; l <= 3; l++) if (nel.PNum(k) == nel.PNum(l)) legal = 0; if (legal) { (*testout) << nel << " "; if (firsttri) { SurfaceElement(i) = nel; firsttri = 0; } else { AddSurfaceElement(nel); } } } (*testout) << endl; } } if (has_prisms) Split2Tets(); else { for (int i = 1; i <= GetNE(); i++) { Element & el = VolumeElement(i); const Point3d & p1 = Point (el.PNum(1)); const Point3d & p2 = Point (el.PNum(2)); const Point3d & p3 = Point (el.PNum(3)); const Point3d & p4 = Point (el.PNum(4)); double vol = (Vec3d (p1, p2) * Cross (Vec3d (p1, p3), Vec3d(p1, p4))); if (vol > 0) swap (el.PNum(3), el.PNum(4)); } UpdateTopology(); timestamp = NextTimeStamp(); } RebuildSurfaceElementLists(); } void Mesh :: BuildElementSearchTree () { if (elementsearchtreets == GetTimeStamp()) return; { std::lock_guard guard(buildsearchtree_mutex); if (elementsearchtreets != GetTimeStamp()) { NgLock lock(mutex); lock.Lock(); PrintMessage (4, "Rebuild element searchtree"); delete elementsearchtree; elementsearchtree = NULL; int ne = (dimension == 2) ? GetNSE() : GetNE(); if (dimension == 3 && !GetNE() && GetNSE()) ne = GetNSE(); if (ne) { if (dimension == 2 || (dimension == 3 && !GetNE()) ) { Box<3> box (Box<3>::EMPTY_BOX); for (SurfaceElementIndex sei = 0; sei < ne; sei++) box.Add (points[surfelements[sei].PNums()]); box.Increase (1.01 * box.Diam()); elementsearchtree = new BoxTree<3> (box); for (SurfaceElementIndex sei = 0; sei < ne; sei++) { box.Set (points[surfelements[sei].PNums()]); elementsearchtree -> Insert (box, sei+1); } } else { Box<3> box (Box<3>::EMPTY_BOX); for (ElementIndex ei = 0; ei < ne; ei++) box.Add (points[volelements[ei].PNums()]); box.Increase (1.01 * box.Diam()); elementsearchtree = new BoxTree<3> (box); for (ElementIndex ei = 0; ei < ne; ei++) { box.Set (points[volelements[ei].PNums()]); elementsearchtree -> Insert (box, ei+1); } } elementsearchtreets = GetTimeStamp(); } } } } int SolveLinearSystemLS (const Vec3d & col1, const Vec3d & col2, const Vec3d & rhs, Vec2d & sol) { double a11 = col1 * col1; double a12 = col1 * col2; double a22 = col2 * col2; double det = a11 * a22 - a12 * a12; if (det*det <= 1e-24 * a11 * a22) { sol = Vec2d (0, 0); return 1; } Vec2d aTrhs; aTrhs.X() = col1*rhs; aTrhs.Y() = col2*rhs; sol.X() = ( a22 * aTrhs.X() - a12 * aTrhs.Y()) / det; sol.Y() = (-a12 * aTrhs.X() + a11 * aTrhs.Y()) / det; return 0; } bool ValidBarCoord(double lami[3], double eps=1e-12) { return (lami[0]<=1.+eps && lami[0]>=0.-eps && lami[1]<=1.+eps && lami[1]>=0.-eps && lami[2]<=1.+eps && lami[2]>=0.-eps ); } bool Mesh :: PointContainedIn2DElement(const Point3d & p, double lami[3], const int element, bool consider3D) const { Vec3d col1, col2, col3; Vec3d rhs, sol; const double eps = 1e-6; Array loctrigs; //SZ if(SurfaceElement(element).GetType()==QUAD) { const Element2d & el = SurfaceElement(element); const Point3d & p1 = Point(el.PNum(1)); const Point3d & p2 = Point(el.PNum(2)); const Point3d & p3 = Point(el.PNum(3)); const Point3d & p4 = Point(el.PNum(4)); // Coefficients of Bilinear Mapping from Ref-Elem to global Elem // X = a + b x + c y + d x y Vec3d a = p1; Vec3d b = p2 - a; Vec3d c = p4 - a; Vec3d d = p3 - a - b - c; /*cout << "p = " << p << endl; cout << "p1 = " << p1 << endl; cout << "p2 = " << p2 << endl; cout << "p3 = " << p3 << endl; cout << "p4 = " << p4 << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; cout << "d = " << d << endl;*/ Vec3d pa = p-a; double dxb = d.X()*b.Y()-d.Y()*b.X(); double dxc = d.X()*c.Y()-d.Y()*c.X(); double bxc = b.X()*c.Y()-b.Y()*c.X(); double bxpa = b.X()*pa.Y()-b.Y()*pa.X(); double cxpa = c.X()*pa.Y()-c.Y()*pa.X(); double dxpa = d.X()*pa.Y()-d.Y()*pa.X(); /*cout << "dxb = " << dxb << endl; cout << "dxc = " << dxc << endl; cout << "bxc = " << bxc << endl; cout << "bxpa = " << bxpa << endl; cout << "cxpa = " << cxpa << endl; cout << "dxpa = " << dxpa << endl;*/ /* P = a + b x + c y + d x y 1) P1 = a1 + b1 x + c1 y + d1 x y 2) P2 = a2 + b2 x + c2 y + d2 x y -> det(x,d) = det(a,d) + det(b,d) x + det(c,d) y -> x = 1/det(b,d) *( det(P-a,d)-det(c,d) y ) -> y = 1/det(c,d) *( det(P-a,d)-det(b,d) x ) -> x = (P1 - a1 - c1 y)/(b1 + d1 y) -> det(c,d) y**2 + [det(d,P-a) + det(c,b)] y + det(b,P-a) = 0 ( same if we express x = (P2 - a2 - c2 y)/(b2 + d2 y) ) -> y = (P1 - a1 - b1 x)/(c1 + d1 x) -> det(b,d) x**2 + [det(d,P-a) + det(b,c)] x + det(c,P-a) = 0 ( same if we express y = (P2 - a2 - b2 x)/(c2 + d2 x) */ lami[2]=0.; double eps = 1.E-12; double c1,c2,r; //First check if point is "exactly" a vertex point Vec3d d1 = p-p1; Vec3d d2 = p-p2; Vec3d d3 = p-p3; Vec3d d4 = p-p4; //cout << " d1 = " << d1 << ", d2 = " << d2 << ", d3 = " << d3 << ", d4 = " << d4 << endl; if (d1.Length2() < sqr(eps)*d2.Length2() && d1.Length2() < sqr(eps)*d3.Length2() && d1.Length2() < sqr(eps)*d4.Length2()) { lami[0] = lami[1] = 0.; return true; } else if (d2.Length2() < sqr(eps)*d1.Length2() && d2.Length2() < sqr(eps)*d3.Length2() && d2.Length2() < sqr(eps)*d4.Length2()) { lami[0] = 1.; lami[1] = 0.; return true; } else if (d3.Length2() < sqr(eps)*d1.Length2() && d3.Length2() < sqr(eps)*d2.Length2() && d3.Length2() < sqr(eps)*d4.Length2()) { lami[0] = lami[1] = 1.; return true; } else if (d4.Length2() < sqr(eps)*d1.Length2() && d4.Length2() < sqr(eps)*d2.Length2() && d4.Length2() < sqr(eps)*d3.Length2()) { lami[0] = 0.; lami[1] = 1.; return true; }//if d is nearly 0: solve resulting linear system else if (d.Length2() < sqr(eps)*b.Length2() && d.Length2() < sqr(eps)*c.Length2()) { Vec2d sol; SolveLinearSystemLS (b, c, p-a, sol); lami[0] = sol.X(); lami[1] = sol.Y(); return ValidBarCoord(lami, eps); }// if dxc is nearly 0: solve resulting linear equation for y and compute x else if (fabs(dxc) < sqr(eps)) { lami[1] = -bxpa/(dxpa-bxc); lami[0] = (dxpa-dxc*lami[1])/dxb; return ValidBarCoord(lami, eps); }// if dxb is nearly 0: solve resulting linear equation for x and compute y else if (fabs(dxb) < sqr(eps)) { lami[0] = -cxpa/(dxpa+bxc); lami[1] = (dxpa-dxb*lami[0])/dxc; return ValidBarCoord(lami, eps); }//if dxb >= dxc: solve quadratic equation in y and compute x else if (fabs(dxb) >= fabs(dxc)) { c1 = (bxc-dxpa)/dxc; c2 = -bxpa/dxc; r = c1*c1/4.0-c2; //quadratic equation has only 1 (unstable) solution if (fabs(r) < eps) //not eps^2! { lami[1] = -c1/2; lami[0] = (dxpa-dxc*lami[1])/dxb; return ValidBarCoord(lami, eps); } if (r < 0) return false; lami[1] = -c1/2+sqrt(r); lami[0] = (dxpa-dxc*lami[1])/dxb; if (ValidBarCoord(lami, eps)) return true; else { lami[1] = -c1/2-sqrt(r); lami[0] = (dxpa-dxc*lami[1])/dxb; return ValidBarCoord(lami, eps); } }//if dxc > dxb: solve quadratic equation in x and compute y else { c1 = (-bxc-dxpa)/dxb; c2 = -cxpa/dxb; r = c1*c1/4.0-c2; //quadratic equation has only 1 (unstable) solution if (fabs(r) < eps) //not eps^2! { lami[0] = -c1/2; lami[1] = (dxpa-dxb*lami[0])/dxc; return ValidBarCoord(lami, eps); } if (r < 0) return false; lami[0] = -c1/2+sqrt(r); lami[1] = (dxpa-dxb*lami[0])/dxc; if (ValidBarCoord(lami, eps)) return true; else { lami[0] = -c1/2-sqrt(r); lami[1] = (dxpa-dxb*lami[0])/dxc; return ValidBarCoord(lami, eps); } } /* double dxa = d.X()*a.Y()-d.Y()*a.X(); double dxp = d.X()*p.Y()-d.Y()*p.X(); double c0,c1,c2; // ,rt; Vec3d dp13 = p3-p1; Vec3d dp24 = p4-p2; double d1 = dp13.Length2(); double d2 = dp24.Length2(); // if(fabs(d.X()) <= eps && fabs(d.Y())<= eps) //if (d.Length2() < sqr(eps)) if (d.Length2() < sqr(eps)*d1 && d.Length2() < sqr(eps)*d2) { //Solve Linear System Vec2d sol; SolveLinearSystemLS (b, c, p-a, sol); lami[0] = sol.X(); lami[1] = sol.Y(); if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; //lami[0]=(c.Y()*(p.X()-a.X())-c.X()*(p.Y()-a.Y()))/ //(b.X()*c.Y() -b.Y()*c.X()); //lami[1]=(-b.Y()*(p.X()-a.X())+b.X()*(p.Y()-a.Y()))/ // (b.X()*c.Y() -b.Y()*c.X()); } else if(fabs(dxb) <= eps*fabs(dxc)) { lami[1] = (dxp-dxa)/dxc; if(fabs(b.X()+d.X()*lami[1])>=fabs(b.Y()+d.Y()*lami[1])) lami[0] = (p.X()-a.X() - c.X()*lami[1])/(b.X()+d.X()*lami[1]); else lami[0] = (p.Y()-a.Y() - c.Y()*lami[1])/(b.Y()+d.Y()*lami[1]); if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; } else if(fabs(dxc) <= eps*fabs(dxb)) { lami[0] = (dxp-dxa)/dxb; if(fabs(c.X()+d.X()*lami[0])>=fabs(c.Y()+d.Y()*lami[0])) lami[1] = (p.X()-a.X() - b.X()*lami[0])/(c.X()+d.X()*lami[0]); else lami[1] = (p.Y()-a.Y() - b.Y()*lami[0])/(c.Y()+d.Y()*lami[0]); if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; } else //Solve quadratic equation { c2 = -d.X()*dxb; c1 = b.X()*dxc - c.X()*dxb + d.X()*(dxp-dxa); c0 = c.X()*(dxp-dxa) + (a.X()-p.X())*dxc; double rt = c1*c1 - 4*c2*c0; if (rt < 0.) return false; lami[1] = (-c1 + sqrt(rt))/2/c2; if(lami[1]<=1.+eps && lami[1]>=0.-eps) { lami[0] = (dxp - dxa -dxb*lami[1])/dxc; if(lami[0]<=1.+eps && lami[0]>=0.-eps) return true; } lami[1] = (-c1 - sqrt(rt))/2/c2; lami[0] = (dxp - dxa -dxb*lami[1])/dxc; if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; c2 = d.Y()*dxb; c1 = b.Y()*dxc - c.Y()*dxb + d.Y()*(dxp-dxa); c0 = c.Y()*(dxp -dxa) + (a.Y()-p.Y())*dxc; rt = c1*c1 - 4*c2*c0; if (rt < 0.) return false; lami[1] = (-c1 + sqrt(rt))/2/c2; if(lami[1]<=1.+eps && lami[1]>=0.-eps) { lami[0] = (dxp - dxa -dxb*lami[1])/dxc; if(lami[0]<=1.+eps && lami[0]>=0.-eps) return true; } lami[1] = (-c1 - sqrt(rt))/2/c2; lami[0] = (dxp - dxa -dxb*lami[1])/dxc; if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; c2 = -d.X()*dxc; c1 = -b.X()*dxc + c.X()*dxb + d.X()*(dxp-dxa); c0 = b.X()*(dxp -dxa) + (a.X()-p.X())*dxb; rt = c1*c1 - 4*c2*c0; if (rt < 0.) return false; lami[1] = (-c1 + sqrt(rt))/2/c2; if(lami[1]<=1.+eps && lami[1]>=0.-eps) { lami[0] = (dxp - dxa -dxc*lami[1])/dxb; if(lami[0]<=1.+eps && lami[0]>=0.-eps) return true; } lami[1] = (-c1 - sqrt(rt))/2/c2; lami[0] = (dxp - dxa -dxc*lami[1])/dxb; if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; }*/ //cout << "lam0,1 = " << lami[0] << ", " << lami[1] << endl; /*if( lami[0] <= 1.+eps && lami[0] >= -eps && lami[1]<=1.+eps && lami[1]>=-eps) { if(consider3D) { Vec3d n = Cross(b,c); lami[2] = 0; for(int i=1; i<=3; i++) lami[2] +=(p.X(i)-a.X(i)-lami[0]*b.X(i)-lami[1]*c.X(i)) * n.X(i); if(lami[2] >= -eps && lami[2] <= eps) return true; } else return true; }*/ return false; } else { // SurfaceElement(element).GetTets (loctets); loctrigs.SetSize(1); loctrigs.Elem(1) = SurfaceElement(element); for (int j = 1; j <= loctrigs.Size(); j++) { const Element2d & el = loctrigs.Get(j); const Point3d & p1 = Point(el.PNum(1)); const Point3d & p2 = Point(el.PNum(2)); const Point3d & p3 = Point(el.PNum(3)); /* Box3d box; box.SetPoint (p1); box.AddPoint (p2); box.AddPoint (p3); box.AddPoint (p4); if (!box.IsIn (p)) continue; */ col1 = p2-p1; col2 = p3-p1; col3 = Cross(col1,col2); //col3 = Vec3d(0, 0, 1); rhs = p - p1; // int retval = SolveLinearSystem (col1, col2, col3, rhs, sol); //(*testout) << "retval " << retval << endl; //(*testout) << "col1 " << col1 << " col2 " << col2 << " col3 " << col3 << " rhs " << rhs << endl; //(*testout) << "sol " << sol << endl; if (SurfaceElement(element).GetType() ==TRIG6) { netgen::Point<2> lam(1./3,1./3); Vec<3> rhs; Vec<2> deltalam; netgen::Point<3> x; Mat<3,2> Jac,Jact; double delta=1; bool retval; int i = 0; const int maxits = 30; while(delta > 1e-16 && iCalcSurfaceTransformation(lam,element-1,x,Jac); rhs = p-x; Jac.Solve(rhs,deltalam); lam += deltalam; delta = deltalam.Length2(); i++; //(*testout) << "pcie i " << i << " delta " << delta << " p " << p << " x " << x << " lam " << lam << endl; //<< "Jac " << Jac << endl; } if(i==maxits) return false; sol.X() = lam(0); sol.Y() = lam(1); } if (sol.X() >= -eps && sol.Y() >= -eps && sol.X() + sol.Y() <= 1+eps) { if(!consider3D || (sol.Z() >= -eps && sol.Z() <= eps)) { lami[0] = sol.X(); lami[1] = sol.Y(); lami[2] = sol.Z(); return true; } } } } return false; } bool Mesh :: PointContainedIn3DElement(const Point3d & p, double lami[3], const int element) const { //bool oldresult = PointContainedIn3DElementOld(p,lami,element); //(*testout) << "old result: " << oldresult // << " lam " << lami[0] << " " << lami[1] << " " << lami[2] << endl; //if(!curvedelems->IsElementCurved(element-1)) // return PointContainedIn3DElementOld(p,lami,element); const double eps = 1.e-4; const Element & el = VolumeElement(element); netgen::Point<3> lam = 0.0; if (el.GetType() == TET || el.GetType() == TET10) { lam = 0.25; } else if (el.GetType() == PRISM) { lam(0) = 0.33; lam(1) = 0.33; lam(2) = 0.5; } else if (el.GetType() == PYRAMID) { lam(0) = 0.4; lam(1) = 0.4; lam(2) = 0.2; } else if (el.GetType() == HEX) { lam = 0.5; } Vec<3> deltalam,rhs; netgen::Point<3> x; Mat<3,3> Jac,Jact; double delta=1; bool retval; int i = 0; const int maxits = 30; while(delta > 1e-16 && iCalcElementTransformation(lam,element-1,x,Jac); rhs = p-x; Jac.Solve(rhs,deltalam); lam += deltalam; delta = deltalam.Length2(); i++; //(*testout) << "pcie i " << i << " delta " << delta << " p " << p << " x " << x << " lam " << lam << endl; //<< "Jac " << Jac << endl; } if(i==maxits) return false; for(i=0; i<3; i++) lami[i] = lam(i); if (el.GetType() == TET || el.GetType() == TET10) { retval = (lam(0) > -eps && lam(1) > -eps && lam(2) > -eps && lam(0) + lam(1) + lam(2) < 1+eps); } else if (el.GetType() == PRISM || el.GetType() == PRISM15) { retval = (lam(0) > -eps && lam(1) > -eps && lam(2) > -eps && lam(2) < 1+eps && lam(0) + lam(1) < 1+eps); } else if (el.GetType() == PYRAMID || el.GetType() == PYRAMID13) { retval = (lam(0) > -eps && lam(1) > -eps && lam(2) > -eps && lam(0) + lam(2) < 1+eps && lam(1) + lam(2) < 1+eps); } else if (el.GetType() == HEX || el.GetType() == HEX20) { retval = (lam(0) > -eps && lam(0) < 1+eps && lam(1) > -eps && lam(1) < 1+eps && lam(2) > -eps && lam(2) < 1+eps); } else throw NgException("Da haun i wos vagessn"); return retval; } bool Mesh :: PointContainedIn3DElementOld(const Point3d & p, double lami[3], const int element) const { Vec3d col1, col2, col3; Vec3d rhs, sol; const double eps = 1.e-4; Array loctets; VolumeElement(element).GetTets (loctets); for (int j = 1; j <= loctets.Size(); j++) { const Element & el = loctets.Get(j); const Point3d & p1 = Point(el.PNum(1)); const Point3d & p2 = Point(el.PNum(2)); const Point3d & p3 = Point(el.PNum(3)); const Point3d & p4 = Point(el.PNum(4)); Box3d box; box.SetPoint (p1); box.AddPoint (p2); box.AddPoint (p3); box.AddPoint (p4); if (!box.IsIn (p)) continue; col1 = p2-p1; col2 = p3-p1; col3 = p4-p1; rhs = p - p1; SolveLinearSystem (col1, col2, col3, rhs, sol); if (sol.X() >= -eps && sol.Y() >= -eps && sol.Z() >= -eps && sol.X() + sol.Y() + sol.Z() <= 1+eps) { Array loctetsloc; Array > pointsloc; VolumeElement(element).GetTetsLocal (loctetsloc); VolumeElement(element).GetNodesLocalNew (pointsloc); const Element & le = loctetsloc.Get(j); Point3d pp = pointsloc.Get(le.PNum(1)) + sol.X() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(2))) + sol.Y() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(3))) + sol.Z() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(4))) ; lami[0] = pp.X(); lami[1] = pp.Y(); lami[2] = pp.Z(); return true; } } return false; } int Mesh :: GetElementOfPoint (const netgen::Point<3> & p, double lami[3], bool build_searchtree, const int index, const bool allowindex) const { if(index != -1) { Array dummy(1); dummy[0] = index; return GetElementOfPoint(p,lami,&dummy,build_searchtree,allowindex); } else return GetElementOfPoint(p,lami,NULL,build_searchtree,allowindex); } int Mesh :: GetElementOfPoint (const netgen::Point<3> & p, double lami[3], const Array * const indices, bool build_searchtree, const bool allowindex) const { // const double pointtol = 1e-12; // netgen::Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol); // netgen::Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol); if ( (dimension == 2 && !GetNSE()) || (dimension == 3 && !GetNE() && !GetNSE()) ) return -1; if (dimension == 2 || (dimension==3 && !GetNE() && GetNSE())) { int ne; int ps_startelement = 0; // disable global buffering if(ps_startelement != 0 && ps_startelement <= GetNSE() && PointContainedIn2DElement(p,lami,ps_startelement)) return ps_startelement; Array locels; if (elementsearchtree || build_searchtree) { // update if necessary: const_cast(*this).BuildElementSearchTree (); // double tol = elementsearchtree->Tolerance(); // netgen::Point<3> pmin = p - Vec<3> (tol, tol, tol); // netgen::Point<3> pmax = p + Vec<3> (tol, tol, tol); elementsearchtree->GetIntersecting (p, p, locels); ne = locels.Size(); } else ne = GetNSE(); for (int i = 1; i <= ne; i++) { int ii; if (elementsearchtree) ii = locels.Get(i); else ii = i; if(ii == ps_startelement) continue; if(indices != NULL && indices->Size() > 0) { bool contained = indices->Contains(SurfaceElement(ii).GetIndex()); if((allowindex && !contained) || (!allowindex && contained)) continue; } if(PointContainedIn2DElement(p,lami,ii)) return ii; } return 0; } else { int ps_startelement = 0; // disable global buffering // int i, j; int ne; if(ps_startelement != 0 && PointContainedIn3DElement(p,lami,ps_startelement)) return ps_startelement; Array locels; if (elementsearchtree || build_searchtree) { // update if necessary: const_cast(*this).BuildElementSearchTree (); // double tol = elementsearchtree->Tolerance(); // netgen::Point<3> pmin = p - Vec<3> (tol, tol, tol); // netgen::Point<3> pmax = p + Vec<3> (tol, tol, tol); elementsearchtree->GetIntersecting (p, p, locels); ne = locels.Size(); } else ne = GetNE(); for (int i = 1; i <= ne; i++) { int ii; if (elementsearchtree) ii = locels.Get(i); else ii = i; if(ii == ps_startelement) continue; if(indices != NULL && indices->Size() > 0) { bool contained = indices->Contains(VolumeElement(ii).GetIndex()); if((allowindex && !contained) || (!allowindex && contained)) continue; } if(PointContainedIn3DElement(p,lami,ii)) { ps_startelement = ii; return ii; } } // Not found, try uncurved variant: for (int i = 1; i <= ne; i++) { int ii; if (elementsearchtree) ii = locels.Get(i); else ii = i; if(indices != NULL && indices->Size() > 0) { bool contained = indices->Contains(VolumeElement(ii).GetIndex()); if((allowindex && !contained) || (!allowindex && contained)) continue; } if(PointContainedIn3DElementOld(p,lami,ii)) { ps_startelement = ii; (*testout) << "WARNING: found element of point " << p <<" only for uncurved mesh" << endl; return ii; } } return 0; } } int Mesh :: GetSurfaceElementOfPoint (const netgen::Point<3> & p, double lami[3], bool build_searchtree, const int index, const bool allowindex) const { if(index != -1) { Array dummy(1); dummy[0] = index; return GetSurfaceElementOfPoint(p,lami,&dummy,build_searchtree,allowindex); } else return GetSurfaceElementOfPoint(p,lami,NULL,build_searchtree,allowindex); } int Mesh :: GetSurfaceElementOfPoint (const netgen::Point<3> & p, double lami[3], const Array * const indices, bool build_searchtree, const bool allowindex) const { if (dimension == 2) { throw NgException("GetSurfaceElementOfPoint not yet implemented for 2D meshes"); } else { double vlam[3]; int velement = GetElementOfPoint(p,vlam,NULL,build_searchtree,allowindex); //(*testout) << "p " << p << endl; //(*testout) << "velement " << velement << endl; if (!GetNE() && GetNSE() ) { lami[0] = vlam[0]; lami[1] = vlam[1]; lami[2] = vlam[2]; return velement; } Array faces; topology.GetElementFaces(velement,faces); //(*testout) << "faces " << faces << endl; for(int i=0; iSize() != 0) { if(indices->Contains(SurfaceElement(faces[i]).GetIndex()) && PointContainedIn2DElement(p,lami,faces[i],true)) return faces[i]; } else { if(PointContainedIn2DElement(p,lami,faces[i],true)) { //(*testout) << "found point " << p << " in sel " << faces[i] // << ", lam " << lami[0] << ", " << lami[1] << ", " << lami[2] << endl; return faces[i]; } } } Array faces2; topology.GetElementFaces(velement,faces2); /* cout << "no matching surf element" << endl << "p = " << p << endl << "faces-orig = " << faces2 << endl << "faces = " << faces << endl << ", vol el = " << velement << ", vlam = " << vlam[0] << "," << vlam[1] << "," << vlam[2] << endl; */ } return 0; } void Mesh::GetIntersectingVolEls(const Point3d& p1, const Point3d& p2, Array & locels) const { elementsearchtree->GetIntersecting (p1, p2, locels); } void Mesh :: SplitIntoParts() { int i, j, dom; int ne = GetNE(); int np = GetNP(); int nse = GetNSE(); BitArray surfused(nse); BitArray pused (np); surfused.Clear(); dom = 0; while (1) { int cntd = 1; dom++; pused.Clear(); int found = 0; for (i = 1; i <= nse; i++) if (!surfused.Test(i)) { SurfaceElement(i).SetIndex (dom); for (j = 1; j <= 3; j++) pused.Set (SurfaceElement(i).PNum(j)); found = 1; cntd = 1; surfused.Set(i); break; } if (!found) break; int change; do { change = 0; for (i = 1; i <= nse; i++) { int is = 0, isnot = 0; for (j = 1; j <= 3; j++) if (pused.Test(SurfaceElement(i).PNum(j))) is = 1; else isnot = 1; if (is && isnot) { change = 1; for (j = 1; j <= 3; j++) pused.Set (SurfaceElement(i).PNum(j)); } if (is) { if (!surfused.Test(i)) { surfused.Set(i); SurfaceElement(i).SetIndex (dom); cntd++; } } } for (i = 1; i <= ne; i++) { int is = 0, isnot = 0; for (j = 1; j <= 4; j++) if (pused.Test(VolumeElement(i).PNum(j))) is = 1; else isnot = 1; if (is && isnot) { change = 1; for (j = 1; j <= 4; j++) pused.Set (VolumeElement(i).PNum(j)); } if (is) { VolumeElement(i).SetIndex (dom); } } } while (change); PrintMessage (3, "domain ", dom, " has ", cntd, " surfaceelements"); } /* facedecoding.SetSize (dom); for (i = 1; i <= dom; i++) { facedecoding.Elem(i).surfnr = 0; facedecoding.Elem(i).domin = i; facedecoding.Elem(i).domout = 0; } */ ClearFaceDescriptors(); for (i = 1; i <= dom; i++) AddFaceDescriptor (FaceDescriptor (0, i, 0, 0)); CalcSurfacesOfNode(); timestamp = NextTimeStamp(); } void Mesh :: SplitSeparatedFaces () { PrintMessage (3, "SplitSeparateFaces"); int fdi; int np = GetNP(); BitArray usedp(np); Array els_of_face; fdi = 1; while (fdi <= GetNFD()) { GetSurfaceElementsOfFace (fdi, els_of_face); if (els_of_face.Size() == 0) continue; SurfaceElementIndex firstel = els_of_face[0]; usedp.Clear(); for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++) usedp.Set (SurfaceElement(firstel).PNum(j)); bool changed; do { changed = false; for (int i = 0; i < els_of_face.Size(); i++) { const Element2d & el = SurfaceElement(els_of_face[i]); bool has = 0; bool hasno = 0; for (int j = 0; j < el.GetNP(); j++) { if (usedp.Test(el[j])) has = true; else hasno = true; } if (has && hasno) changed = true; if (has) for (int j = 0; j < el.GetNP(); j++) usedp.Set (el[j]); } } while (changed); int nface = 0; for (int i = 0; i < els_of_face.Size(); i++) { Element2d & el = SurfaceElement(els_of_face[i]); int hasno = 0; for (int j = 1; j <= el.GetNP(); j++) if (!usedp.Test(el.PNum(j))) hasno = 1; if (hasno) { if (!nface) { FaceDescriptor nfd = GetFaceDescriptor(fdi); nface = AddFaceDescriptor (nfd); } el.SetIndex (nface); } } // reconnect list if (nface) { facedecoding[nface-1].firstelement = -1; facedecoding[fdi-1].firstelement = -1; for (int i = 0; i < els_of_face.Size(); i++) { int ind = SurfaceElement(els_of_face[i]).GetIndex(); SurfaceElement(els_of_face[i]).next = facedecoding[ind-1].firstelement; facedecoding[ind-1].firstelement = els_of_face[i]; } } fdi++; } /* fdi = 1; while (fdi <= GetNFD()) { int firstel = 0; for (int i = 1; i <= GetNSE(); i++) if (SurfaceElement(i).GetIndex() == fdi) { firstel = i; break; } if (!firstel) continue; usedp.Clear(); for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++) usedp.Set (SurfaceElement(firstel).PNum(j)); int changed; do { changed = 0; for (int i = 1; i <= GetNSE(); i++) { const Element2d & el = SurfaceElement(i); if (el.GetIndex() != fdi) continue; int has = 0; int hasno = 0; for (int j = 1; j <= el.GetNP(); j++) { if (usedp.Test(el.PNum(j))) has = 1; else hasno = 1; } if (has && hasno) changed = 1; if (has) for (int j = 1; j <= el.GetNP(); j++) usedp.Set (el.PNum(j)); } } while (changed); int nface = 0; for (int i = 1; i <= GetNSE(); i++) { Element2d & el = SurfaceElement(i); if (el.GetIndex() != fdi) continue; int hasno = 0; for (int j = 1; j <= el.GetNP(); j++) { if (!usedp.Test(el.PNum(j))) hasno = 1; } if (hasno) { if (!nface) { FaceDescriptor nfd = GetFaceDescriptor(fdi); nface = AddFaceDescriptor (nfd); } el.SetIndex (nface); } } fdi++; } */ } void Mesh :: RebuildSurfaceElementLists () { for (int i = 0; i < facedecoding.Size(); i++) facedecoding[i].firstelement = -1; for (int i = surfelements.Size()-1; i >= 0; i--) { int ind = surfelements[i].GetIndex(); surfelements[i].next = facedecoding[ind-1].firstelement; facedecoding[ind-1].firstelement = i; } } void Mesh :: GetSurfaceElementsOfFace (int facenr, Array & sei) const { static int timer = NgProfiler::CreateTimer ("GetSurfaceElementsOfFace"); NgProfiler::RegionTimer reg (timer); /* sei.SetSize (0); for (SurfaceElementIndex i = 0; i < GetNSE(); i++) { if ( (*this)[i].GetIndex () == facenr && (*this)[i][0] >= PointIndex::BASE && !(*this)[i].IsDeleted() ) { sei.Append (i); } } */ /* Philippose - 01/10/2009 Commented out the following lines, and activated the originally commented out lines above because of a bug which causes corruption of the variable "facedecoding" when a mesh is converted to second order */ // int size1 = sei.Size(); sei.SetSize(0); SurfaceElementIndex si = facedecoding[facenr-1].firstelement; while (si != -1) { if ( (*this)[si].GetIndex () == facenr && (*this)[si][0] >= PointIndex::BASE && !(*this)[si].IsDeleted() ) { sei.Append (si); } si = (*this)[si].next; } /* // *testout << "with list = " << endl << sei << endl; if (size1 != sei.Size()) { cout << "size mismatch" << endl; exit(1); } */ } void Mesh :: CalcMinMaxAngle (double badellimit, double * retvalues) { int i, j; int lpi1, lpi2, lpi3, lpi4; double phimax = 0, phimin = 10; double facephimax = 0, facephimin = 10; int illegaltets = 0, negativetets = 0, badtets = 0; for (i = 1; i <= GetNE(); i++) { int badel = 0; Element & el = VolumeElement(i); if (el.GetType() != TET) { VolumeElement(i).flags.badel = 0; continue; } if (el.Volume(Points()) < 0) { badel = 1; negativetets++; } if (!LegalTet (el)) { badel = 1; illegaltets++; (*testout) << "illegal tet: " << i << " "; for (j = 1; j <= el.GetNP(); j++) (*testout) << el.PNum(j) << " "; (*testout) << endl; } // angles between faces for (lpi1 = 1; lpi1 <= 3; lpi1++) for (lpi2 = lpi1+1; lpi2 <= 4; lpi2++) { lpi3 = 1; while (lpi3 == lpi1 || lpi3 == lpi2) lpi3++; lpi4 = 10 - lpi1 - lpi2 - lpi3; const Point3d & p1 = Point (el.PNum(lpi1)); const Point3d & p2 = Point (el.PNum(lpi2)); const Point3d & p3 = Point (el.PNum(lpi3)); const Point3d & p4 = Point (el.PNum(lpi4)); Vec3d n(p1, p2); n /= n.Length(); Vec3d v1(p1, p3); Vec3d v2(p1, p4); v1 -= (n * v1) * n; v2 -= (n * v2) * n; double cosphi = (v1 * v2) / (v1.Length() * v2.Length()); double phi = acos (cosphi); if (phi > phimax) phimax = phi; if (phi < phimin) phimin = phi; if ((180/M_PI) * phi > badellimit) badel = 1; } // angles in faces for (j = 1; j <= 4; j++) { Element2d face(TRIG); el.GetFace (j, face); for (lpi1 = 1; lpi1 <= 3; lpi1++) { lpi2 = lpi1 % 3 + 1; lpi3 = lpi2 % 3 + 1; const Point3d & p1 = Point (el.PNum(lpi1)); const Point3d & p2 = Point (el.PNum(lpi2)); const Point3d & p3 = Point (el.PNum(lpi3)); Vec3d v1(p1, p2); Vec3d v2(p1, p3); double cosphi = (v1 * v2) / (v1.Length() * v2.Length()); double phi = acos (cosphi); if (phi > facephimax) facephimax = phi; if (phi < facephimin) facephimin = phi; if ((180/M_PI) * phi > badellimit) badel = 1; } } VolumeElement(i).flags.badel = badel; if (badel) badtets++; } if (!GetNE()) { phimin = phimax = facephimin = facephimax = 0; } if (!retvalues) { PrintMessage (1, ""); PrintMessage (1, "between planes: phimin = ", (180/M_PI) * phimin, " phimax = ", (180/M_PI) *phimax); PrintMessage (1, "inside planes: phimin = ", (180/M_PI) * facephimin, " phimax = ", (180/M_PI) * facephimax); PrintMessage (1, ""); } else { retvalues[0] = (180/M_PI) * facephimin; retvalues[1] = (180/M_PI) * facephimax; retvalues[2] = (180/M_PI) * phimin; retvalues[3] = (180/M_PI) * phimax; } PrintMessage (3, "negative tets: ", negativetets); PrintMessage (3, "illegal tets: ", illegaltets); PrintMessage (3, "bad tets: ", badtets); } int Mesh :: MarkIllegalElements () { int cnt = 0; for (auto & el : VolumeElements()) if (!LegalTet (el)) cnt++; return cnt; } // #ifdef NONE // void Mesh :: AddIdentification (int pi1, int pi2, int identnr) // { // INDEX_2 pair(pi1, pi2); // // pair.Sort(); // identifiedpoints->Set (pair, identnr); // if (identnr > maxidentnr) // maxidentnr = identnr; // timestamp = NextTimeStamp(); // } // int Mesh :: GetIdentification (int pi1, int pi2) const // { // INDEX_2 pair(pi1, pi2); // if (identifiedpoints->Used (pair)) // return identifiedpoints->Get(pair); // else // return 0; // } // int Mesh :: GetIdentificationSym (int pi1, int pi2) const // { // INDEX_2 pair(pi1, pi2); // if (identifiedpoints->Used (pair)) // return identifiedpoints->Get(pair); // pair = INDEX_2 (pi2, pi1); // if (identifiedpoints->Used (pair)) // return identifiedpoints->Get(pair); // return 0; // } // void Mesh :: GetIdentificationMap (int identnr, Array & identmap) const // { // int i, j; // identmap.SetSize (GetNP()); // for (i = 1; i <= identmap.Size(); i++) // identmap.Elem(i) = 0; // for (i = 1; i <= identifiedpoints->GetNBags(); i++) // for (j = 1; j <= identifiedpoints->GetBagSize(i); j++) // { // INDEX_2 i2; // int nr; // identifiedpoints->GetData (i, j, i2, nr); // if (nr == identnr) // { // identmap.Elem(i2.I1()) = i2.I2(); // } // } // } // void Mesh :: GetIdentificationPairs (int identnr, Array & identpairs) const // { // int i, j; // identpairs.SetSize(0); // for (i = 1; i <= identifiedpoints->GetNBags(); i++) // for (j = 1; j <= identifiedpoints->GetBagSize(i); j++) // { // INDEX_2 i2; // int nr; // identifiedpoints->GetData (i, j, i2, nr); // if (identnr == 0 || nr == identnr) // identpairs.Append (i2); // } // } // #endif void Mesh :: InitPointCurve(double red, double green, double blue) const { pointcurves_startpoint.Append(pointcurves.Size()); pointcurves_red.Append(red); pointcurves_green.Append(green); pointcurves_blue.Append(blue); } void Mesh :: AddPointCurvePoint(const Point3d & pt) const { pointcurves.Append(pt); } int Mesh :: GetNumPointCurves(void) const { return pointcurves_startpoint.Size(); } int Mesh :: GetNumPointsOfPointCurve(int curve) const { if(curve == pointcurves_startpoint.Size()-1) return (pointcurves.Size() - pointcurves_startpoint.Last()); else return (pointcurves_startpoint[curve+1]-pointcurves_startpoint[curve]); } Point3d & Mesh :: GetPointCurvePoint(int curve, int n) const { return pointcurves[pointcurves_startpoint[curve]+n]; } void Mesh :: GetPointCurveColor(int curve, double & red, double & green, double & blue) const { red = pointcurves_red[curve]; green = pointcurves_green[curve]; blue = pointcurves_blue[curve]; } void Mesh :: ComputeNVertices () { numvertices = 0; for (const Element & el : VolumeElements()) for (PointIndex v : el.Vertices()) if (v > numvertices) numvertices = v; for (const Element2d & el : SurfaceElements()) for (PointIndex v : el.Vertices()) if (v > numvertices) numvertices = v; numvertices += 1-PointIndex::BASE; } int Mesh :: GetNV () const { if (numvertices < 0) return GetNP(); else return numvertices; } void Mesh :: SetNP (int np) { points.SetSize(np); // ptyps.SetSize(np); int mlold = mlbetweennodes.Size(); mlbetweennodes.SetSize(np); if (np > mlold) for (int i = mlold+PointIndex::BASE; i < np+PointIndex::BASE; i++) { mlbetweennodes[i].I1() = PointIndex::BASE-1; mlbetweennodes[i].I2() = PointIndex::BASE-1; } GetIdentifications().SetMaxPointNr (np + PointIndex::BASE-1); } /* void Mesh :: BuildConnectedNodes () { if (PureTetMesh()) { connectedtonode.SetSize(0); return; } int i, j, k; int np = GetNP(); int ne = GetNE(); TABLE conto(np); for (i = 1; i <= ne; i++) { const Element & el = VolumeElement(i); if (el.GetType() == PRISM) { for (j = 1; j <= 6; j++) { int n1 = el.PNum (j); int n2 = el.PNum ((j+2)%6+1); // if (n1 != n2) { int found = 0; for (k = 1; k <= conto.EntrySize(n1); k++) if (conto.Get(n1, k) == n2) { found = 1; break; } if (!found) conto.Add (n1, n2); } } } else if (el.GetType() == PYRAMID) { for (j = 1; j <= 4; j++) { int n1, n2; switch (j) { case 1: n1 = 1; n2 = 4; break; case 2: n1 = 4; n2 = 1; break; case 3: n1 = 2; n2 = 3; break; case 4: n1 = 3; n2 = 2; break; } int found = 0; for (k = 1; k <= conto.EntrySize(n1); k++) if (conto.Get(n1, k) == n2) { found = 1; break; } if (!found) conto.Add (n1, n2); } } } connectedtonode.SetSize(np); for (i = 1; i <= np; i++) connectedtonode.Elem(i) = 0; for (i = 1; i <= np; i++) if (connectedtonode.Elem(i) == 0) { connectedtonode.Elem(i) = i; ConnectToNodeRec (i, i, conto); } } void Mesh :: ConnectToNodeRec (int node, int tonode, const TABLE & conto) { int i, n2; // (*testout) << "connect " << node << " to " << tonode << endl; for (i = 1; i <= conto.EntrySize(node); i++) { n2 = conto.Get(node, i); if (!connectedtonode.Get(n2)) { connectedtonode.Elem(n2) = tonode; ConnectToNodeRec (n2, tonode, conto); } } } */ bool Mesh :: PureTrigMesh (int faceindex) const { // if (!faceindex) return !mparam.quad; if (!faceindex) { for (int i = 1; i <= GetNSE(); i++) if (SurfaceElement(i).GetNP() != 3) return false; return true; } for (int i = 1; i <= GetNSE(); i++) if (SurfaceElement(i).GetIndex() == faceindex && SurfaceElement(i).GetNP() != 3) return false; return true; } bool Mesh :: PureTetMesh () const { for (ElementIndex ei = 0; ei < GetNE(); ei++) if (VolumeElement(ei).GetNP() != 4) return 0; return 1; } void Mesh :: UpdateTopology (TaskManager tm, Tracer tracer) { topology.Update(tm, tracer); (*tracer)("call update clusters", false); clusters->Update(tm, tracer); (*tracer)("call update clusters", true); #ifdef PARALLEL if (paralleltop) { paralleltop->Reset(); paralleltop->UpdateCoarseGrid(); } #endif } void Mesh :: BuildCurvedElements (const Refinement * ref, int aorder, bool arational) { GetCurvedElements().BuildCurvedElements (ref, aorder, arational); for (SegmentIndex seg = 0; seg < GetNSeg(); seg++) (*this)[seg].SetCurved (GetCurvedElements().IsSegmentCurved (seg)); for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) (*this)[sei].SetCurved (GetCurvedElements().IsSurfaceElementCurved (sei)); for (ElementIndex ei = 0; ei < GetNE(); ei++) (*this)[ei].SetCurved (GetCurvedElements().IsElementCurved (ei)); SetNextMajorTimeStamp(); } void Mesh :: BuildCurvedElements (int aorder) { if (!GetGeometry()) throw NgException ("don't have a geometry for mesh curving"); GetCurvedElements().BuildCurvedElements (&GetGeometry()->GetRefinement(), aorder, false); for (SegmentIndex seg = 0; seg < GetNSeg(); seg++) (*this)[seg].SetCurved (GetCurvedElements().IsSegmentCurved (seg)); for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) (*this)[sei].SetCurved (GetCurvedElements().IsSurfaceElementCurved (sei)); for (ElementIndex ei = 0; ei < GetNE(); ei++) (*this)[ei].SetCurved (GetCurvedElements().IsElementCurved (ei)); SetNextMajorTimeStamp(); } void Mesh :: SetMaterial (int domnr, const string & mat) { if (domnr > materials.Size()) { int olds = materials.Size(); materials.SetSize (domnr); for (int i = olds; i < domnr-1; i++) materials[i] = new string("default"); } /* materials.Elem(domnr) = new char[strlen(mat)+1]; strcpy (materials.Elem(domnr), mat); */ materials.Elem(domnr) = new string(mat); } string Mesh :: defaultmat = "default"; const string & Mesh :: GetMaterial (int domnr) const { if (domnr <= materials.Size()) return *materials.Get(domnr); static string emptystring("default"); return emptystring; } void Mesh ::SetNBCNames ( int nbcn ) { if ( bcnames.Size() ) for ( int i = 0; i < bcnames.Size(); i++) if ( bcnames[i] ) delete bcnames[i]; bcnames.SetSize(nbcn); bcnames = 0; } void Mesh ::SetBCName ( int bcnr, const string & abcname ) { if (bcnr >= bcnames.Size()) { int oldsize = bcnames.Size(); bcnames.SetSize (bcnr+1); // keeps contents for (int i = oldsize; i <= bcnr; i++) bcnames[i] = nullptr; } if ( bcnames[bcnr] ) delete bcnames[bcnr]; if ( abcname != "default" ) bcnames[bcnr] = new string ( abcname ); else bcnames[bcnr] = nullptr; for (auto & fd : facedecoding) if (fd.BCProperty() <= bcnames.Size()) fd.SetBCName (bcnames[fd.BCProperty()-1]); } const string & Mesh ::GetBCName ( int bcnr ) const { static string defaultstring = "default"; if ( !bcnames.Size() ) return defaultstring; if (bcnr < 0 || bcnr >= bcnames.Size()) throw NgException ("illegal bc-number"); if ( bcnames[bcnr] ) return *bcnames[bcnr]; else return defaultstring; } void Mesh :: SetNCD2Names( int ncd2n ) { if (cd2names.Size()) for(int i=0; i= cd2names.Size()) { int oldsize = cd2names.Size(); cd2names.SetSize(cd2nr+1); for(int i= oldsize; i<= cd2nr; i++) cd2names[i] = nullptr; } //if (cd2names[cd2nr]) delete cd2names[cd2nr]; if (abcname != "default") cd2names[cd2nr] = new string(abcname); else cd2names[cd2nr] = nullptr; } string Mesh :: cd2_default_name = "default"; string Mesh :: default_bc = "default"; const string & Mesh :: GetCD2Name (int cd2nr) const { static string defaultstring = "default"; if (!cd2names.Size()) return defaultstring; if (cd2nr < 0 || cd2nr >= cd2names.Size()) return defaultstring; if (cd2names[cd2nr]) return *cd2names[cd2nr]; else return defaultstring; } void Mesh :: SetNCD3Names( int ncd3n ) { if (cd3names.Size()) for(int i=0; i= cd3names.Size()) { int oldsize = cd3names.Size(); cd3names.SetSize(cd3nr+1); for(int i= oldsize; i<= cd3nr; i++) cd3names[i] = nullptr; } if (abcname != "default") cd3names[cd3nr] = new string(abcname); else cd3names[cd3nr] = nullptr; } string Mesh :: cd3_default_name = "default"; const string & Mesh :: GetCD3Name (int cd3nr) const { static string defaultstring = "default"; if (!cd3names.Size()) return defaultstring; if (cd3nr < 0 || cd3nr >= cd3names.Size()) return defaultstring; if (cd3names[cd3nr]) return *cd3names[cd3nr]; else return defaultstring; } void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_int.Used(id)) delete userdata_int[id]; Array * newdata = new Array(data); userdata_int.Set(id,newdata); } bool Mesh :: GetUserData(const char * id, Array & data, int shift) const { if(userdata_int.Used(id)) { if(data.Size() < (*userdata_int[id]).Size()+shift) data.SetSize((*userdata_int[id]).Size()+shift); for(int i=0; i<(*userdata_int[id]).Size(); i++) data[i+shift] = (*userdata_int[id])[i]; return true; } else { data.SetSize(0); return false; } } void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_double.Used(id)) delete userdata_double[id]; Array * newdata = new Array(data); userdata_double.Set(id,newdata); } bool Mesh :: GetUserData(const char * id, Array & data, int shift) const { if(userdata_double.Used(id)) { if(data.Size() < (*userdata_double[id]).Size()+shift) data.SetSize((*userdata_double[id]).Size()+shift); for(int i=0; i<(*userdata_double[id]).Size(); i++) data[i+shift] = (*userdata_double[id])[i]; return true; } else { data.SetSize(0); return false; } } void Mesh :: PrintMemInfo (ostream & ost) const { ost << "Mesh Mem:" << endl; ost << GetNP() << " Points, of size " << sizeof (Point3d) << " + " << sizeof(POINTTYPE) << " = " << GetNP() * (sizeof (Point3d) + sizeof(POINTTYPE)) << endl; ost << GetNSE() << " Surface elements, of size " << sizeof (Element2d) << " = " << GetNSE() * sizeof(Element2d) << endl; ost << GetNE() << " Volume elements, of size " << sizeof (Element) << " = " << GetNE() * sizeof(Element) << endl; // ost << "surfs on node:"; // surfacesonnode.PrintMemInfo (cout); ost << "boundaryedges: "; if (boundaryedges) boundaryedges->PrintMemInfo (cout); ost << "surfelementht: "; if (surfelementht) surfelementht->PrintMemInfo (cout); } } netgen-6.2.1905/libsrc/meshing/meshing2.cpp0000644000175000017500000013132313504650527017134 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { static void glrender (int wait); // global variable for visualization // static Array locpoints; // static Array legalpoints; // static Array plainpoints; // static Array plainzones; // static Array loclines; // // static int geomtrig; // //static const char * rname; // static int cntelem, trials, nfaces; // static int oldnl; // static int qualclass; Meshing2 :: Meshing2 (const MeshingParameters & mp, const Box<3> & aboundingbox) { boundingbox = aboundingbox; LoadRules (NULL, mp.quad); // LoadRules ("rules/quad.rls"); // LoadRules ("rules/triangle.rls"); adfront = new AdFront2(boundingbox); starttime = GetTime(); maxarea = -1; } Meshing2 :: ~Meshing2 () { delete adfront; for (int i = 0; i < rules.Size(); i++) delete rules[i]; } void Meshing2 :: AddPoint (const Point3d & p, PointIndex globind, MultiPointGeomInfo * mgi, bool pointonsurface) { //(*testout) << "add point " << globind << endl; adfront ->AddPoint (p, globind, mgi, pointonsurface); } void Meshing2 :: AddBoundaryElement (int i1, int i2, const PointGeomInfo & gi1, const PointGeomInfo & gi2) { // (*testout) << "add line " << i1 << " - " << i2 << endl; if (!gi1.trignum || !gi2.trignum) { PrintSysError ("addboundaryelement: illegal geominfo"); } adfront -> AddLine (i1-1, i2-1, gi1, gi2); } void Meshing2 :: StartMesh () { foundmap.SetSize (rules.Size()); canuse.SetSize (rules.Size()); ruleused.SetSize (rules.Size()); foundmap = 0; canuse = 0; ruleused = 0; // cntelem = 0; // trials = 0; } void Meshing2 :: EndMesh () { for (int i = 0; i < ruleused.Size(); i++) (*testout) << setw(4) << ruleused[i] << " times used rule " << rules[i] -> Name() << endl; } void Meshing2 :: SetStartTime (double astarttime) { starttime = astarttime; } void Meshing2 :: SetMaxArea (double amaxarea) { maxarea = amaxarea; } double Meshing2 :: CalcLocalH (const Point3d & /* p */, double gh) const { return gh; } // should be class variables !!(?) // static Vec3d ex, ey; // static Point3d globp1; void Meshing2 :: DefineTransformation (const Point3d & p1, const Point3d & p2, const PointGeomInfo * geominfo1, const PointGeomInfo * geominfo2) { globp1 = p1; ex = p2 - p1; ex /= ex.Length(); ey.X() = -ex.Y(); ey.Y() = ex.X(); ey.Z() = 0; } void Meshing2 :: TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominf, Point2d & plainpoint, double h, int & zone) { Vec3d p1p (globp1, locpoint); // p1p = locpoint - globp1; p1p /= h; plainpoint.X() = p1p * ex; plainpoint.Y() = p1p * ey; zone = 0; } int Meshing2 :: TransformFromPlain (Point2d & plainpoint, Point3d & locpoint, PointGeomInfo & gi, double h) { Vec3d p1p; gi.trignum = 1; p1p = plainpoint.X() * ex + plainpoint.Y() * ey; p1p *= h; locpoint = globp1 + p1p; return 0; } int Meshing2 :: BelongsToActiveChart (const Point3d & p, const PointGeomInfo & gi) { return 1; } int Meshing2 :: ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi) { gi.trignum = 1; return 0; } int Meshing2 :: ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, PointGeomInfo & pgi) { pgi = mpgi.GetPGI(1); return 0; } int Meshing2 :: IsLineVertexOnChart (const Point3d & p1, const Point3d & p2, int endpoint, const PointGeomInfo & geominfo) { return 1; } void Meshing2 :: GetChartBoundary (Array & points, Array & points3d, Array & lines, double h) const { points.SetSize (0); points3d.SetSize (0); lines.SetSize (0); } double Meshing2 :: Area () const { return -1; } MESHING2_RESULT Meshing2 :: GenerateMesh (Mesh & mesh, const MeshingParameters & mp, double gh, int facenr) { static Timer timer("surface meshing"); RegionTimer reg(timer); static int timer1 = NgProfiler::CreateTimer ("surface meshing1"); static int timer2 = NgProfiler::CreateTimer ("surface meshing2"); static int timer3 = NgProfiler::CreateTimer ("surface meshing3"); static int ts1 = NgProfiler::CreateTimer ("surface meshing start 1"); static int ts2 = NgProfiler::CreateTimer ("surface meshing start 2"); static int ts3 = NgProfiler::CreateTimer ("surface meshing start 3"); NgProfiler::StartTimer (ts1); Array pindex, lindex; Array delpoints, dellines; Array upgeominfo; // unique info Array mpgeominfo; // multiple info Array locelements; int z1, z2, oldnp(-1); bool found; int rulenr(-1); Point<3> p1, p2; const PointGeomInfo * blgeominfo1; const PointGeomInfo * blgeominfo2; bool morerisc; bool debugflag; double h, his, hshould; Array locpoints; Array legalpoints; Array plainpoints; Array plainzones; Array loclines; int cntelem = 0, trials = 0, nfaces = 0; int oldnl = 0; int qualclass; // test for 3d overlaps BoxTree<3> surfeltree (boundingbox.PMin(), boundingbox.PMax()); Array intersecttrias; Array critpoints; // test for doubled edges //INDEX_2_HASHTABLE doubleedge(300000); testmode = 0; StartMesh(); Array chartboundpoints; Array chartboundpoints3d; Array chartboundlines; // illegal points: points with more then 50 elements per node int maxlegalpoint(-1), maxlegalline(-1); Array trigsonnode; Array illegalpoint; trigsonnode.SetSize (mesh.GetNP()); illegalpoint.SetSize (mesh.GetNP()); trigsonnode = 0; illegalpoint = 0; double totalarea = Area (); double meshedarea = 0; // search tree for surface elements: /* for (sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & sel = mesh[sei]; if (sel.IsDeleted()) continue; if (sel.GetIndex() == facenr) { Box<3> box; box.Set ( mesh[sel[0]] ); box.Add ( mesh[sel[1]] ); box.Add ( mesh[sel[2]] ); surfeltree.Insert (box, sei); } } */ Array seia; mesh.GetSurfaceElementsOfFace (facenr, seia); for (int i = 0; i < seia.Size(); i++) { const Element2d & sel = mesh[seia[i]]; if (sel.IsDeleted()) continue; Box<3> box; box.Set ( mesh[sel[0]] ); box.Add ( mesh[sel[1]] ); box.Add ( mesh[sel[2]] ); surfeltree.Insert (box, seia[i]); } NgProfiler::StopTimer (ts1); NgProfiler::StartTimer (ts2); if (totalarea > 0 || maxarea > 0) meshedarea = mesh.SurfaceArea(); /* for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & sel = mesh[sei]; if (sel.IsDeleted()) continue; double trigarea = Cross ( mesh[sel[1]]-mesh[sel[0]], mesh[sel[2]]-mesh[sel[0]] ).Length() / 2; if (sel.GetNP() == 4) trigarea += Cross (Vec3d (mesh.Point (sel.PNum(1)), mesh.Point (sel.PNum(3))), Vec3d (mesh.Point (sel.PNum(1)), mesh.Point (sel.PNum(4)))).Length() / 2;; meshedarea += trigarea; } */ // cout << "meshedarea = " << meshedarea << " =?= " // << mesh.SurfaceArea() << endl; NgProfiler::StopTimer (ts2); NgProfiler::StartTimer (ts3); const char * savetask = multithread.task; multithread.task = "Surface meshing"; adfront ->SetStartFront (); int plotnexttrial = 999; double meshedarea_before = meshedarea; NgProfiler::StopTimer (ts3); while (!adfront ->Empty() && !multithread.terminate) { NgProfiler::RegionTimer reg1 (timer1); if (multithread.terminate) throw NgException ("Meshing stopped"); // known for STL meshing if (totalarea > 0) multithread.percent = 100 * meshedarea / totalarea; /* else multithread.percent = 0; */ locpoints.SetSize(0); loclines.SetSize(0); pindex.SetSize(0); lindex.SetSize(0); delpoints.SetSize(0); dellines.SetSize(0); locelements.SetSize(0); // plot statistics if (trials > plotnexttrial) { PrintMessage (5, "faces = ", nfaces, " trials = ", trials, " elements = ", mesh.GetNSE(), " els/sec = ", (mesh.GetNSE() / (GetTime() - starttime + 0.0001))); plotnexttrial += 1000; } // unique-pgi, multi-pgi upgeominfo.SetSize(0); mpgeominfo.SetSize(0); nfaces = adfront->GetNFL(); trials ++; if (trials % 1000 == 0) { (*testout) << "\n"; for (int i = 1; i <= canuse.Size(); i++) { (*testout) << foundmap.Get(i) << "/" << canuse.Get(i) << "/" << ruleused.Get(i) << " map/can/use rule " << rules.Get(i)->Name() << "\n"; } (*testout) << "\n"; } int baselineindex = adfront -> SelectBaseLine (p1, p2, blgeominfo1, blgeominfo2, qualclass); found = 1; his = Dist (p1, p2); Point3d pmid = Center (p1, p2); hshould = CalcLocalH (pmid, mesh.GetH (pmid)); if (gh < hshould) hshould = gh; mesh.RestrictLocalH (pmid, hshould); h = hshould; double hinner = (3 + qualclass) * max2 (his, hshould); adfront ->GetLocals (baselineindex, locpoints, mpgeominfo, loclines, pindex, lindex, 2*hinner); NgProfiler::RegionTimer reg2 (timer2); //(*testout) << "h for locals: " << 2*hinner << endl; //(*testout) << "locpoints " << locpoints << endl; if (qualclass > mp.giveuptol2d) { PrintMessage (3, "give up with qualclass ", qualclass); PrintMessage (3, "number of frontlines = ", adfront->GetNFL()); // throw NgException ("Give up 2d meshing"); break; } /* if (found && qualclass > 60) { found = 0; } */ // morerisc = ((qualclass > 20) && (qualclass % 2 == 1)); // morerisc = 1; morerisc = 0; PointIndex gpi1 = adfront -> GetGlobalIndex (pindex.Get(loclines[0].I1())); PointIndex gpi2 = adfront -> GetGlobalIndex (pindex.Get(loclines[0].I2())); debugflag = ( debugparam.haltsegment && ( ((debugparam.haltsegmentp1 == gpi1) && (debugparam.haltsegmentp2 == gpi2)) || ((debugparam.haltsegmentp1 == gpi2) && (debugparam.haltsegmentp2 == gpi1))) ) || ( debugparam.haltnode && ( (debugparam.haltsegmentp1 == gpi1) || (debugparam.haltsegmentp2 == gpi1)) ); if (debugparam.haltface && debugparam.haltfacenr == facenr) { debugflag = 1; cout << "set debugflag" << endl; } if (debugparam.haltlargequalclass && qualclass > 50) debugflag = 1; // problem recognition ! if (found && (gpi1 < illegalpoint.Size()+PointIndex::BASE) && (gpi2 < illegalpoint.Size()+PointIndex::BASE) ) { if (illegalpoint[gpi1] || illegalpoint[gpi2]) found = 0; } Point2d p12d, p22d; if (found) { oldnp = locpoints.Size(); oldnl = loclines.Size(); if (debugflag) (*testout) << "define new transformation" << endl; DefineTransformation (p1, p2, blgeominfo1, blgeominfo2); plainpoints.SetSize (locpoints.Size()); plainzones.SetSize (locpoints.Size()); // (*testout) << endl; if (debugflag) { *testout << "3d->2d transformation" << endl; *testout << "3d points: " << endl << locpoints << endl; } for (int i = 1; i <= locpoints.Size(); i++) { // (*testout) << "pindex(i) = " << pindex[i-1] << endl; TransformToPlain (locpoints.Get(i), mpgeominfo.Get(i), plainpoints.Elem(i), h, plainzones.Elem(i)); // (*testout) << mpgeominfo.Get(i).GetPGI(1).u << " " << mpgeominfo.Get(i).GetPGI(1).v << " "; // (*testout) << plainpoints.Get(i).X() << " " << plainpoints.Get(i).Y() << endl; //(*testout) << "transform " << locpoints.Get(i) << " to " << plainpoints.Get(i).X() << " " << plainpoints.Get(i).Y() << endl; } // (*testout) << endl << endl << endl; if (debugflag) *testout << "2d points: " << endl << plainpoints << endl; p12d = plainpoints.Get(1); p22d = plainpoints.Get(2); /* // last idea on friday plainzones.Elem(1) = 0; plainzones.Elem(2) = 0; */ /* // old netgen: for (i = 2; i <= loclines.Size(); i++) // don't remove first line { z1 = plainzones.Get(loclines.Get(i).I1()); z2 = plainzones.Get(loclines.Get(i).I2()); if (z1 && z2 && (z1 != z2) || (z1 == -1) || (z2 == -1) ) { loclines.DeleteElement(i); lindex.DeleteElement(i); oldnl--; i--; } } // for (i = 1; i <= plainpoints.Size(); i++) // if (plainzones.Elem(i) == -1) // plainpoints.Elem(i) = Point2d (1e4, 1e4); */ for (int i = 2; i <= loclines.Size(); i++) // don't remove first line { // (*testout) << "loclines(i) = " << loclines.Get(i).I1() << " - " << loclines.Get(i).I2() << endl; z1 = plainzones.Get(loclines.Get(i).I1()); z2 = plainzones.Get(loclines.Get(i).I2()); // one inner point, one outer if ( (z1 >= 0) != (z2 >= 0)) { int innerp = (z1 >= 0) ? 1 : 2; if (IsLineVertexOnChart (locpoints.Get(loclines.Get(i).I1()), locpoints.Get(loclines.Get(i).I2()), innerp, adfront->GetLineGeomInfo (lindex.Get(i), innerp))) // pgeominfo.Get(loclines.Get(i).I(innerp)))) { if (!morerisc) { // use one end of line int pini, pouti; Vec2d v; pini = loclines.Get(i).I(innerp); pouti = loclines.Get(i).I(3-innerp); Point2d pin (plainpoints.Get(pini)); Point2d pout (plainpoints.Get(pouti)); v = pout - pin; double len = v.Length(); if (len <= 1e-6) (*testout) << "WARNING(js): inner-outer: short vector" << endl; else v /= len; /* // don't elongate line towards base-line !! if (Vec2d (pin, p12d) * v > 0 && Vec2d (pin, p22d) * v > 0) v *= -1; */ Point2d newpout = pin + 1000 * v; newpout = pout; plainpoints.Append (newpout); Point3d pout3d = locpoints.Get(pouti); locpoints.Append (pout3d); plainzones.Append (0); pindex.Append (-1); oldnp++; loclines.Elem(i).I(3-innerp) = oldnp; } else plainzones.Elem(loclines.Get(i).I(3-innerp)) = 0; // (*testout) << "inner - outer correction" << endl; } else { // remove line loclines.DeleteElement(i); lindex.DeleteElement(i); oldnl--; i--; } } else if ( (z1 > 0 && z2 > 0 && (z1 != z2)) || ((z1 < 0) && (z2 < 0)) ) { loclines.DeleteElement(i); lindex.DeleteElement(i); oldnl--; i--; } } legalpoints.SetSize(plainpoints.Size()); for (int i = 1; i <= legalpoints.Size(); i++) legalpoints.Elem(i) = 1; double avy = 0; for (int i = 1; i <= plainpoints.Size(); i++) avy += plainpoints.Elem(i).Y(); avy *= 1./plainpoints.Size(); for (int i = 1; i <= plainpoints.Size(); i++) { if (plainzones.Elem(i) < 0) { plainpoints.Elem(i) = Point2d (1e4, 1e4); legalpoints.Elem(i) = 0; } if (pindex.Elem(i) == -1) { legalpoints.Elem(i) = 0; } if (plainpoints.Elem(i).Y() < -1e-10*avy) // changed { legalpoints.Elem(i) = 0; } } /* for (i = 3; i <= plainpoints.Size(); i++) if (sqr (plainpoints.Get(i).X()) + sqr (plainpoints.Get(i).Y()) > sqr (2 + 0.2 * qualclass)) legalpoints.Elem(i) = 0; */ /* int clp = 0; for (i = 1; i <= plainpoints.Size(); i++) if (legalpoints.Get(i)) clp++; (*testout) << "legalpts: " << clp << "/" << plainpoints.Size() << endl; // sort legal/illegal lines int lastleg = 2; int firstilleg = oldnl; while (lastleg < firstilleg) { while (legalpoints.Get(loclines.Get(lastleg).I1()) && legalpoints.Get(loclines.Get(lastleg).I2()) && lastleg < firstilleg) lastleg++; while ( ( !legalpoints.Get(loclines.Get(firstilleg).I1()) || !legalpoints.Get(loclines.Get(firstilleg).I2())) && lastleg < firstilleg) firstilleg--; if (lastleg < firstilleg) { swap (loclines.Elem(lastleg), loclines.Elem(firstilleg)); swap (lindex.Elem(lastleg), lindex.Elem(firstilleg)); } } (*testout) << "leglines " << lastleg << "/" << oldnl << endl; */ GetChartBoundary (chartboundpoints, chartboundpoints3d, chartboundlines, h); oldnp = plainpoints.Size(); maxlegalpoint = locpoints.Size(); maxlegalline = loclines.Size(); if (mp.checkchartboundary) { for (int i = 1; i <= chartboundpoints.Size(); i++) { plainpoints.Append (chartboundpoints.Get(i)); locpoints.Append (chartboundpoints3d.Get(i)); legalpoints.Append (0); } for (int i = 1; i <= chartboundlines.Size(); i++) { INDEX_2 line (chartboundlines.Get(i).I1()+oldnp, chartboundlines.Get(i).I2()+oldnp); loclines.Append (line); // (*testout) << "line: " << line.I1() << "-" << line.I2() << endl; } } oldnl = loclines.Size(); oldnp = plainpoints.Size(); } /* if (qualclass > 100) { multithread.drawing = 1; glrender(1); cout << "qualclass 100, nfl = " << adfront->GetNFL() << endl; } */ if (found) { rulenr = ApplyRules (plainpoints, legalpoints, maxlegalpoint, loclines, maxlegalline, locelements, dellines, qualclass, mp); // (*testout) << "Rule Nr = " << rulenr << endl; if (!rulenr) { found = 0; if ( debugflag || debugparam.haltnosuccess ) PrintWarning ("no rule found"); } } NgProfiler::RegionTimer reg3 (timer3); for (int i = 1; i <= locelements.Size() && found; i++) { const Element2d & el = locelements.Get(i); for (int j = 1; j <= el.GetNP(); j++) if (el.PNum(j) <= oldnp && pindex.Get(el.PNum(j)) == -1) { found = 0; PrintSysError ("meshing2, index missing"); } } if (found) { locpoints.SetSize (plainpoints.Size()); upgeominfo.SetSize(locpoints.Size()); for (int i = oldnp+1; i <= plainpoints.Size(); i++) { int err = TransformFromPlain (plainpoints.Elem(i), locpoints.Elem(i), upgeominfo.Elem(i), h); if (err) { found = 0; if ( debugflag || debugparam.haltnosuccess ) PrintSysError ("meshing2, Backtransformation failed"); break; } } } // for (i = 1; i <= oldnl; i++) // adfront -> ResetClass (lindex[i]); /* double violateminh; if (qualclass <= 10) violateminh = 3; else violateminh = 3 * qualclass; if (uselocalh && found) // && qualclass <= 10) { for (i = 1; i <= locelements.Size(); i++) { Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1)); Point3d pmax = pmin; for (j = 2; j <= 3; j++) { const Point3d & hp = locpoints.Get(locelements.Get(i).PNum(j)); pmin.SetToMin (hp); pmax.SetToMax (hp); } double minh = mesh.GetMinH (pmin, pmax); if (h > violateminh * minh) { found = 0; loclines.SetSize (oldnl); locpoints.SetSize (oldnp); } } } */ if (found) { double violateminh = 3 + 0.1 * sqr (qualclass); double minh = 1e8; double newedgemaxh = 0; for (int i = oldnl+1; i <= loclines.Size(); i++) { double eh = Dist (locpoints.Get(loclines.Get(i).I1()), locpoints.Get(loclines.Get(i).I2())); // Markus (brute force method to avoid bad elements on geometries like \_/ ) //if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I1()))) found = 0; //if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I2()))) found = 0; // Markus end if (eh > newedgemaxh) newedgemaxh = eh; } for (int i = 1; i <= locelements.Size(); i++) { Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1)); Point3d pmax = pmin; for (int j = 2; j <= locelements.Get(i).GetNP(); j++) { const Point3d & hp = locpoints.Get(locelements.Get(i).PNum(j)); pmin.SetToMin (hp); pmax.SetToMax (hp); } double eh = mesh.GetMinH (pmin, pmax); if (eh < minh) minh = eh; } for (int i = 1; i <= locelements.Size(); i++) for (int j = 1; j <= locelements.Get(i).GetNP(); j++) if (Dist2 (locpoints.Get(locelements.Get(i).PNum(j)), pmid) > hinner*hinner) found = 0; // cout << "violate = " << newedgemaxh / minh << endl; static double maxviolate = 0; if (newedgemaxh / minh > maxviolate) { maxviolate = newedgemaxh / minh; // cout << "max minhviolate = " << maxviolate << endl; } if (newedgemaxh > violateminh * minh) { found = 0; loclines.SetSize (oldnl); locpoints.SetSize (oldnp); if ( debugflag || debugparam.haltnosuccess ) PrintSysError ("meshing2, maxh too large"); } } /* // test good ComputeLineGeoInfo if (found) { // is line on chart ? for (i = oldnl+1; i <= loclines.Size(); i++) { int gisize; void *geominfo; if (ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()), locpoints.Get(loclines.Get(i).I2()), gisize, geominfo)) found = 0; } } */ // changed for OCC meshing if (found) { // take geominfo from dellines // upgeominfo.SetSize(locpoints.Size()); /* for (i = 1; i <= dellines.Size(); i++) for (j = 1; j <= 2; j++) { upgeominfo.Elem(loclines.Get(dellines.Get(i)).I(j)) = adfront -> GetLineGeomInfo (lindex.Get(dellines.Get(i)), j); } */ for (int i = 1; i <= locelements.Size(); i++) for (int j = 1; j <= locelements.Get(i).GetNP(); j++) { int pi = locelements.Get(i).PNum(j); if (pi <= oldnp) { if (ChooseChartPointGeomInfo (mpgeominfo.Get(pi), upgeominfo.Elem(pi))) { // cannot select, compute new one PrintWarning ("calc point geominfo instead of using"); if (ComputePointGeomInfo (locpoints.Get(pi), upgeominfo.Elem(pi))) { found = 0; PrintSysError ("meshing2d, geominfo failed"); } } } } /* // use upgeominfo from ProjectFromPlane for (i = oldnp+1; i <= locpoints.Size(); i++) { if (ComputePointGeomInfo (locpoints.Get(i), upgeominfo.Elem(i))) { found = 0; if ( debugflag || debugparam.haltnosuccess ) PrintSysError ("meshing2d, compute geominfo failed"); } } */ } if (found && mp.checkoverlap) { // cout << "checkoverlap" << endl; // test for overlaps Point3d hullmin(1e10, 1e10, 1e10); Point3d hullmax(-1e10, -1e10, -1e10); for (int i = 1; i <= locelements.Size(); i++) for (int j = 1; j <= locelements.Get(i).GetNP(); j++) { const Point3d & p = locpoints.Get(locelements.Get(i).PNum(j)); hullmin.SetToMin (p); hullmax.SetToMax (p); } hullmin += Vec3d (-his, -his, -his); hullmax += Vec3d ( his, his, his); surfeltree.GetIntersecting (hullmin, hullmax, intersecttrias); critpoints.SetSize (0); for (int i = oldnp+1; i <= locpoints.Size(); i++) critpoints.Append (locpoints.Get(i)); for (int i = 1; i <= locelements.Size(); i++) { const Element2d & tri = locelements.Get(i); if (tri.GetNP() == 3) { const Point3d & tp1 = locpoints.Get(tri.PNum(1)); const Point3d & tp2 = locpoints.Get(tri.PNum(2)); const Point3d & tp3 = locpoints.Get(tri.PNum(3)); Vec3d tv1 (tp1, tp2); Vec3d tv2 (tp1, tp3); double lam1, lam2; for (lam1 = 0.2; lam1 <= 0.8; lam1 += 0.2) for (lam2 = 0.2; lam2 + lam1 <= 0.8; lam2 += 0.2) { Point3d hp = tp1 + lam1 * tv1 + lam2 * tv2; critpoints.Append (hp); } } else if (tri.GetNP() == 4) { const Point3d & tp1 = locpoints.Get(tri.PNum(1)); const Point3d & tp2 = locpoints.Get(tri.PNum(2)); const Point3d & tp3 = locpoints.Get(tri.PNum(3)); const Point3d & tp4 = locpoints.Get(tri.PNum(4)); double l1, l2; for (l1 = 0.1; l1 <= 0.9; l1 += 0.1) for (l2 = 0.1; l2 <= 0.9; l2 += 0.1) { Point3d hp; hp.X() = (1-l1)*(1-l2) * tp1.X() + l1*(1-l2) * tp2.X() + l1*l2 * tp3.X() + (1-l1)*l2 * tp4.X(); hp.Y() = (1-l1)*(1-l2) * tp1.Y() + l1*(1-l2) * tp2.Y() + l1*l2 * tp3.Y() + (1-l1)*l2 * tp4.Y(); hp.Z() = (1-l1)*(1-l2) * tp1.Z() + l1*(1-l2) * tp2.Z() + l1*l2 * tp3.Z() + (1-l1)*l2 * tp4.Z(); critpoints.Append (hp); } } } /* for (i = oldnl+1; i <= loclines.Size(); i++) { Point3d hp = locpoints.Get(loclines.Get(i).I1()); Vec3d hv(hp, locpoints.Get(loclines.Get(i).I2())); int ncp = 2; for (j = 1; j <= ncp; j++) critpoints.Append ( hp + (double(j)/(ncp+1)) * hv); } */ /* for (i = oldnp+1; i <= locpoints.Size(); i++) { const Point3d & p = locpoints.Get(i); */ for (int i = 1; i <= critpoints.Size(); i++) { const Point3d & p = critpoints.Get(i); for (int jj = 0; jj < intersecttrias.Size(); jj++) { // int j = intersecttrias.Get(jj); // const Element2d & el = mesh.SurfaceElement(j); SurfaceElementIndex j = intersecttrias[jj]; const Element2d & el = mesh[j]; int ntrig = (el.GetNP() == 3) ? 1 : 2; int jl; for (jl = 1; jl <= ntrig; jl++) { Point3d tp1, tp2, tp3; if (jl == 1) { tp1 = mesh.Point(el.PNum(1)); tp2 = mesh.Point(el.PNum(2)); tp3 = mesh.Point(el.PNum(3)); } else { tp1 = mesh.Point(el.PNum(1)); tp2 = mesh.Point(el.PNum(3)); tp3 = mesh.Point(el.PNum(4)); } int onchart = 0; for (int k = 1; k <= el.GetNP(); k++) if (BelongsToActiveChart (mesh.Point(el.PNum(k)), el.GeomInfoPi(k))) onchart = 1; if (!onchart) continue; Vec3d e1(tp1, tp2); Vec3d e2(tp1, tp3); Vec3d n = Cross (e1, e2); n /= n.Length(); double lam1, lam2, lam3; lam3 = n * Vec3d (tp1, p); LocalCoordinates (e1, e2, Vec3d (tp1, p), lam1, lam2); if (fabs (lam3) < 0.1 * hshould && lam1 > 0 && lam2 > 0 && (lam1 + lam2) < 1) { #ifdef DEVELOP cout << "overlap" << endl; (*testout) << "overlap:" << endl << "tri = " << tp1 << "-" << tp2 << "-" << tp3 << endl << "point = " << p << endl << "lam1, 2 = " << lam1 << ", " << lam2 << endl << "lam3 = " << lam3 << endl; // cout << "overlap !!!" << endl; #endif for (int k = 1; k <= 5; k++) adfront -> IncrementClass (lindex.Get(1)); found = 0; if ( debugflag || debugparam.haltnosuccess ) PrintWarning ("overlapping"); if (debugparam.haltoverlap) { debugflag = 1; } /* multithread.drawing = 1; glrender(1); */ } } } } } if (found) { // check, whether new front line already exists for (int i = oldnl+1; i <= loclines.Size(); i++) { int nlgpi1 = loclines.Get(i).I1(); int nlgpi2 = loclines.Get(i).I2(); if (nlgpi1 <= pindex.Size() && nlgpi2 <= pindex.Size()) { nlgpi1 = adfront->GetGlobalIndex (pindex.Get(nlgpi1)); nlgpi2 = adfront->GetGlobalIndex (pindex.Get(nlgpi2)); int exval = adfront->ExistsLine (nlgpi1, nlgpi2); if (exval) { cout << "ERROR: new line exits, val = " << exval << endl; (*testout) << "ERROR: new line exits, val = " << exval << endl; found = 0; if (debugparam.haltexistingline) debugflag = 1; } } } } /* if (found) { // check, whether new triangles insert edges twice for (i = 1; i <= locelements.Size(); i++) for (j = 1; j <= 3; j++) { int tpi1 = locelements.Get(i).PNumMod (j); int tpi2 = locelements.Get(i).PNumMod (j+1); if (tpi1 <= pindex.Size() && tpi2 <= pindex.Size()) { tpi1 = adfront->GetGlobalIndex (pindex.Get(tpi1)); tpi2 = adfront->GetGlobalIndex (pindex.Get(tpi2)); if (doubleedge.Used (INDEX_2(tpi1, tpi2))) { if (debugparam.haltexistingline) debugflag = 1; cerr << "ERROR Insert edge " << tpi1 << " - " << tpi2 << " twice !!!" << endl; found = 0; } doubleedge.Set (INDEX_2(tpi1, tpi2), 1); } } } */ if (found) { // everything is ok, perform mesh update ruleused.Elem(rulenr)++; pindex.SetSize(locpoints.Size()); for (int i = oldnp+1; i <= locpoints.Size(); i++) { PointIndex globind = mesh.AddPoint (locpoints.Get(i)); pindex.Elem(i) = adfront -> AddPoint (locpoints.Get(i), globind); } for (int i = oldnl+1; i <= loclines.Size(); i++) { /* for (j = 1; j <= locpoints.Size(); j++) { (*testout) << j << ": " << locpoints.Get(j) << endl; } */ /* ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()), locpoints.Get(loclines.Get(i).I2()), gisize, geominfo); */ if (pindex.Get(loclines.Get(i).I1()) == -1 || pindex.Get(loclines.Get(i).I2()) == -1) { (*testout) << "pindex is 0" << endl; } if (!upgeominfo.Get(loclines.Get(i).I1()).trignum || !upgeominfo.Get(loclines.Get(i).I2()).trignum) { cout << "new el: illegal geominfo" << endl; } adfront -> AddLine (pindex.Get(loclines.Get(i).I1()), pindex.Get(loclines.Get(i).I2()), upgeominfo.Get(loclines.Get(i).I1()), upgeominfo.Get(loclines.Get(i).I2())); } for (int i = 1; i <= locelements.Size(); i++) { Element2d mtri(locelements.Get(i).GetNP()); mtri = locelements.Get(i); mtri.SetIndex (facenr); // compute triangle geominfo: // (*testout) << "triggeominfo: "; for (int j = 1; j <= locelements.Get(i).GetNP(); j++) { mtri.GeomInfoPi(j) = upgeominfo.Get(locelements.Get(i).PNum(j)); // (*testout) << mtri.GeomInfoPi(j).trignum << " "; } // (*testout) << endl; for (int j = 1; j <= locelements.Get(i).GetNP(); j++) { mtri.PNum(j) = locelements.Elem(i).PNum(j) = adfront -> GetGlobalIndex (pindex.Get(locelements.Get(i).PNum(j))); } mesh.AddSurfaceElement (mtri); cntelem++; // cout << "elements: " << cntelem << endl; Box<3> box; box.Set (mesh[mtri[0]]); box.Add (mesh[mtri[1]]); box.Add (mesh[mtri[2]]); surfeltree.Insert (box, mesh.GetNSE()-1); const Point3d & sep1 = mesh.Point (mtri.PNum(1)); const Point3d & sep2 = mesh.Point (mtri.PNum(2)); const Point3d & sep3 = mesh.Point (mtri.PNum(3)); double trigarea = Cross (Vec3d (sep1, sep2), Vec3d (sep1, sep3)).Length() / 2; if (mtri.GetNP() == 4) { const Point3d & sep4 = mesh.Point (mtri.PNum(4)); trigarea += Cross (Vec3d (sep1, sep3), Vec3d (sep1, sep4)).Length() / 2; } meshedarea += trigarea; if(maxarea > 0 && meshedarea-meshedarea_before > maxarea) { cerr << "meshed area = " << meshedarea-meshedarea_before << endl << "maximal area = " << maxarea << endl << "GIVING UP" << endl; return MESHING2_GIVEUP; } for (int j = 1; j <= locelements.Get(i).GetNP(); j++) { int gpi = locelements.Get(i).PNum(j); int oldts = trigsonnode.Size(); if (gpi >= oldts+PointIndex::BASE) { trigsonnode.SetSize (gpi+1-PointIndex::BASE); illegalpoint.SetSize (gpi+1-PointIndex::BASE); for (int k = oldts+PointIndex::BASE; k <= gpi; k++) { trigsonnode[k] = 0; illegalpoint[k] = 0; } } trigsonnode[gpi]++; if (trigsonnode[gpi] > 20) { illegalpoint[gpi] = 1; // cout << "illegal point: " << gpi << endl; (*testout) << "illegal point: " << gpi << endl; } static int mtonnode = 0; if (trigsonnode[gpi] > mtonnode) mtonnode = trigsonnode[gpi]; } // cout << "els = " << cntelem << " trials = " << trials << endl; // if (trials > 100) return; } for (int i = 1; i <= dellines.Size(); i++) adfront -> DeleteLine (lindex.Get(dellines.Get(i))); // rname = rules.Get(rulenr)->Name(); #ifdef MYGRAPH if (silentflag<3) { plotsurf.DrawPnL(locpoints, loclines); plotsurf.Plot(testmode, testmode); } #endif if (morerisc) { cout << "generated due to morerisc" << endl; // multithread.drawing = 1; // glrender(1); } if ( debugparam.haltsuccess || debugflag ) { // adfront -> PrintOpenSegments (*testout); cout << "success of rule" << rules.Get(rulenr)->Name() << endl; multithread.drawing = 1; multithread.testmode = 1; multithread.pause = 1; /* extern STLGeometry * stlgeometry; stlgeometry->ClearMarkedSegs(); for (i = 1; i <= loclines.Size(); i++) { stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()), locpoints.Get(loclines.Get(i).I2())); } */ (*testout) << "success of rule" << rules.Get(rulenr)->Name() << endl; (*testout) << "trials = " << trials << endl; (*testout) << "locpoints " << endl; for (int i = 1; i <= pindex.Size(); i++) (*testout) << adfront->GetGlobalIndex (pindex.Get(i)) << endl; (*testout) << "old number of lines = " << oldnl << endl; for (int i = 1; i <= loclines.Size(); i++) { (*testout) << "line "; for (int j = 1; j <= 2; j++) { int hi = 0; if (loclines.Get(i).I(j) >= 1 && loclines.Get(i).I(j) <= pindex.Size()) hi = adfront->GetGlobalIndex (pindex.Get(loclines.Get(i).I(j))); (*testout) << hi << " "; } (*testout) << " : " << plainpoints.Get(loclines.Get(i).I1()) << " - " << plainpoints.Get(loclines.Get(i).I2()) << " 3d: " << locpoints.Get(loclines.Get(i).I1()) << " - " << locpoints.Get(loclines.Get(i).I2()) << endl; } glrender(1); } } else { adfront -> IncrementClass (lindex.Get(1)); if ( debugparam.haltnosuccess || debugflag ) { cout << "Problem with seg " << gpi1 << " - " << gpi2 << ", class = " << qualclass << endl; (*testout) << "Problem with seg " << gpi1 << " - " << gpi2 << ", class = " << qualclass << endl; multithread.drawing = 1; multithread.testmode = 1; multithread.pause = 1; /* extern STLGeometry * stlgeometry; stlgeometry->ClearMarkedSegs(); for (i = 1; i <= loclines.Size(); i++) { stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()), locpoints.Get(loclines.Get(i).I2())); } */ for (int i = 1; i <= loclines.Size(); i++) { (*testout) << "line "; for (int j = 1; j <= 2; j++) { int hi = 0; if (loclines.Get(i).I(j) >= 1 && loclines.Get(i).I(j) <= pindex.Size()) hi = adfront->GetGlobalIndex (pindex.Get(loclines.Get(i).I(j))); (*testout) << hi << " "; } (*testout) << " : " << plainpoints.Get(loclines.Get(i).I1()) << " - " << plainpoints.Get(loclines.Get(i).I2()) << " 3d: " << locpoints.Get(loclines.Get(i).I1()) << " - " << locpoints.Get(loclines.Get(i).I2()) << endl; } /* cout << "p1gi = " << blgeominfo[0].trignum << ", p2gi = " << blgeominfo[1].trignum << endl; */ glrender(1); } #ifdef MYGRAPH if (silentflag<3) { if (testmode || trials%2 == 0) { plotsurf.DrawPnL(locpoints, loclines); plotsurf.Plot(testmode, testmode); } } #endif } } PrintMessage (3, "Surface meshing done"); adfront->PrintOpenSegments (*testout); multithread.task = savetask; EndMesh (); if (!adfront->Empty()) return MESHING2_GIVEUP; return MESHING2_OK; } } // #define OPENGL #ifdef OPENGLxx /* *********************** Draw Surface Meshing **************** */ #include #include namespace netgen { extern STLGeometry * stlgeometry; extern Mesh * mesh; VisualSceneSurfaceMeshing vssurfacemeshing; void glrender (int wait) { // cout << "plot adfront" << endl; if (multithread.drawing) { // vssurfacemeshing.Render(); Render (); if (wait || multithread.testmode) { multithread.pause = 1; } while (multithread.pause); } } VisualSceneSurfaceMeshing :: VisualSceneSurfaceMeshing () : VisualScene() { ; } VisualSceneSurfaceMeshing :: ~VisualSceneSurfaceMeshing () { ; } void VisualSceneSurfaceMeshing :: DrawScene () { int i, j, k; if (loclines.Size() != changeval) { center = Point<3>(0,0,-5); rad = 0.1; CalcTransformationMatrices(); changeval = loclines.Size(); } glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); // glEnable (GL_COLOR_MATERIAL); // glDisable (GL_SHADING); // glColor3f (0.0f, 1.0f, 1.0f); // glLineWidth (1.0f); // glShadeModel (GL_SMOOTH); // glCallList (linelists.Get(1)); // SetLight(); glPushMatrix(); glMultMatrixf (transformationmat); glShadeModel (GL_SMOOTH); // glDisable (GL_COLOR_MATERIAL); glEnable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glEnable (GL_LIGHTING); double shine = vispar.shininess; double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); /* float mat_col[] = { 0.2, 0.2, 0.8, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); float mat_colbl[] = { 0.8, 0.2, 0.2, 1 }; float mat_cololdl[] = { 0.2, 0.8, 0.2, 1 }; float mat_colnewl[] = { 0.8, 0.8, 0.2, 1 }; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (1, -1); glLineWidth (3); for (i = 1; i <= loclines.Size(); i++) { if (i == 1) { glEnable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbl); } else if (i <= oldnl) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_cololdl); else glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colnewl); int pi1 = loclines.Get(i).I1(); int pi2 = loclines.Get(i).I2(); if (pi1 >= 1 && pi2 >= 1) { Point3d p1 = locpoints.Get(pi1); Point3d p2 = locpoints.Get(pi2); glBegin (GL_LINES); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (p2.X(), p2.Y(), p2.Z()); glEnd(); } glDisable (GL_POLYGON_OFFSET_FILL); } glLineWidth (1); glPointSize (5); float mat_colp[] = { 1, 0, 0, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); glBegin (GL_POINTS); for (i = 1; i <= locpoints.Size(); i++) { Point3d p = locpoints.Get(i); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd(); glPopMatrix(); */ float mat_colp[] = { 1, 0, 0, 1 }; float mat_col2d1[] = { 1, 0.5, 0.5, 1 }; float mat_col2d[] = { 1, 1, 1, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); double scalex = 0.1, scaley = 0.1; glBegin (GL_LINES); for (i = 1; i <= loclines.Size(); i++) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); if (i == 1) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d1); int pi1 = loclines.Get(i).I1(); int pi2 = loclines.Get(i).I2(); if (pi1 >= 1 && pi2 >= 1) { Point2d p1 = plainpoints.Get(pi1); Point2d p2 = plainpoints.Get(pi2); glBegin (GL_LINES); glVertex3f (scalex * p1.X(), scaley * p1.Y(), -5); glVertex3f (scalex * p2.X(), scaley * p2.Y(), -5); glEnd(); } } glEnd (); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); glBegin (GL_POINTS); for (i = 1; i <= plainpoints.Size(); i++) { Point2d p = plainpoints.Get(i); glVertex3f (scalex * p.X(), scaley * p.Y(), -5); } glEnd(); glDisable (GL_POLYGON_OFFSET_FILL); glPopMatrix(); DrawCoordinateCross (); DrawNetgenLogo (); glFinish(); /* glDisable (GL_POLYGON_OFFSET_FILL); // cout << "draw surfacemeshing" << endl; // // if (changeval != stlgeometry->GetNT()) // BuildScene(); // changeval = stlgeometry->GetNT(); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glLoadMatrixf (transmat); glMultMatrixf (rotmat); glShadeModel (GL_SMOOTH); glDisable (GL_COLOR_MATERIAL); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float mat_spec_col[] = { 1, 1, 1, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col); double shine = vispar.shininess; double transp = vispar.transp; glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); glLogicOp (GL_COPY); float mat_col[] = { 0.2, 0.2, 0.8, transp }; float mat_colrt[] = { 0.2, 0.8, 0.8, transp }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glColor3f (1.0f, 1.0f, 1.0f); glEnable (GL_NORMALIZE); // glBegin (GL_TRIANGLES); // for (j = 1; j <= stlgeometry -> GetNT(); j++) // { // glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); // if (j == geomtrig) // glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colrt); // const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j); // glNormal3f (tria.normal.X(), // tria.normal.Y(), // tria.normal.Z()); // for (k = 0; k < 3; k++) // { // glVertex3f (tria.pts[k].X(), // tria.pts[k].Y(), // tria.pts[k].Z()); // } // } // glEnd (); glDisable (GL_POLYGON_OFFSET_FILL); float mat_colbl[] = { 0.8, 0.2, 0.2, 1 }; float mat_cololdl[] = { 0.2, 0.8, 0.2, 1 }; float mat_colnewl[] = { 0.8, 0.8, 0.2, 1 }; glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (1, -1); glLineWidth (3); for (i = 1; i <= loclines.Size(); i++) { if (i == 1) { glEnable (GL_POLYGON_OFFSET_FILL); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbl); } else if (i <= oldnl) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_cololdl); else glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colnewl); int pi1 = loclines.Get(i).I1(); int pi2 = loclines.Get(i).I2(); if (pi1 >= 1 && pi2 >= 1) { Point3d p1 = locpoints.Get(pi1); Point3d p2 = locpoints.Get(pi2); glBegin (GL_LINES); glVertex3f (p1.X(), p1.Y(), p1.Z()); glVertex3f (p2.X(), p2.Y(), p2.Z()); glEnd(); } glDisable (GL_POLYGON_OFFSET_FILL); } glLineWidth (1); glPointSize (5); float mat_colp[] = { 1, 0, 0, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); glBegin (GL_POINTS); for (i = 1; i <= locpoints.Size(); i++) { Point3d p = locpoints.Get(i); glVertex3f (p.X(), p.Y(), p.Z()); } glEnd(); glPopMatrix(); float mat_col2d1[] = { 1, 0.5, 0.5, 1 }; float mat_col2d[] = { 1, 1, 1, 1 }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); double scalex = 0.1, scaley = 0.1; glBegin (GL_LINES); for (i = 1; i <= loclines.Size(); i++) { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); if (i == 1) glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d1); int pi1 = loclines.Get(i).I1(); int pi2 = loclines.Get(i).I2(); if (pi1 >= 1 && pi2 >= 1) { Point2d p1 = plainpoints.Get(pi1); Point2d p2 = plainpoints.Get(pi2); glBegin (GL_LINES); glVertex3f (scalex * p1.X(), scaley * p1.Y(), -5); glVertex3f (scalex * p2.X(), scaley * p2.Y(), -5); glEnd(); } } glEnd (); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); glBegin (GL_POINTS); for (i = 1; i <= plainpoints.Size(); i++) { Point2d p = plainpoints.Get(i); glVertex3f (scalex * p.X(), scaley * p.Y(), -5); } glEnd(); glFinish(); */ } void VisualSceneSurfaceMeshing :: BuildScene (int zoomall) { int i, j, k; /* center = stlgeometry -> GetBoundingBox().Center(); rad = stlgeometry -> GetBoundingBox().Diam() / 2; CalcTransformationMatrices(); */ } } #else namespace netgen { void glrender (int wait) { ; } } #endif netgen-6.2.1905/libsrc/meshing/ruler3.cpp0000644000175000017500000006776613504650527016657 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { extern double minother; extern double minwithoutother; static double CalcElementBadness (const Array & points, const Element & elem) { double vol, l, l4, l5, l6; if (elem.GetNP() != 4) { if (elem.GetNP() == 5) { double z = points[elem.PNum(5)].Z(); if (z > -1e-8) return 1e8; return (-1 / z) - z; // - 2; } return 0; } Vec3d v1 = points[elem.PNum(2)] - points[elem.PNum(1)]; Vec3d v2 = points[elem.PNum(3)] - points[elem.PNum(1)]; Vec3d v3 = points[elem.PNum(4)] - points[elem.PNum(1)]; vol = - (Cross (v1, v2) * v3); l4 = Dist (points[elem.PNum(2)], points[elem.PNum(3)]); l5 = Dist (points[elem.PNum(2)], points[elem.PNum(4)]); l6 = Dist (points[elem.PNum(3)], points[elem.PNum(4)]); l = v1.Length() + v2.Length() + v3.Length() + l4 + l5 + l6; // testout << "vol = " << vol << " l = " << l << endl; if (vol < 1e-8) return 1e10; // (*testout) << "l^3/vol = " << (l*l*l / vol) << endl; double err = pow (l*l*l/vol, 1.0/3.0) / 12; return err; } int Meshing3 :: ApplyRules ( Array & lpoints, // in: local points, out: old+new local points Array & allowpoint, // in: 2 .. it is allowed to use pointi, 1..will be allowed later, 0..no means Array & lfaces, // in: local faces, out: old+new local faces INDEX lfacesplit, // for local faces in outer radius INDEX_2_HASHTABLE & connectedpairs, // connected pairs for prism-meshing Array & elements, // out: new elements Array & delfaces, // out: face indices of faces to delete int tolerance, // quality class: 1 best double sloppy, // quality strength int rotind1, // how to rotate base element float & retminerr // element error ) { static Timer t("ruler3 - all"); RegionTimer reg(t); static Timer tstart("ruler3 - rule start"); static Timer tloop("ruler3 - rule loop"); tstart.Start(); float err, minerr, teterr, minteterr; char ok, found, hc; // vnetrule * rule; Vector oldu, newu, newu1, newu2, allp; Vec3d ui; Point3d np; const MiniElement2d * locface = NULL; int loktestmode; Array pused; // point is already mapped, number of uses ArrayMem fused; // face is already mapped ArrayMem pmap; // map of reference point to local point ArrayMem pfixed; // point mapped by face-map ArrayMem fmapi; // face in reference is mapped to face nr ... ArrayMem fmapr; // face in reference is rotated to map ArrayMem transfreezone; // transformed free-zone INDEX_2_CLOSED_HASHTABLE ledges(100); // edges in local environment ArrayMem tempnewpoints; Array tempnewfaces; ArrayMem tempdelfaces; Array tempelements; ArrayMem triboxes; // bounding boxes of local faces Array pnearness; Array fnearness; static int cnt = 0; cnt++; delfaces.SetSize (0); elements.SetSize (0); // determine topological distance of faces and points to // base element pnearness.SetSize (lpoints.Size()); fnearness.SetSize (lfacesplit); pnearness = INT_MAX/10; for (PointIndex pi : lfaces[0].PNums()) pnearness[pi] = 0; NgProfiler::RegionTimer reg2(98); NgProfiler::StartTimer (90); for (int loop = 0; loop < 2; loop++) { for (int i = 0; i < lfacesplit; i++) { const MiniElement2d & hface = lfaces[i]; int minn = INT_MAX-1; for (PointIndex pi : hface.PNums()) { int hi = pnearness[pi]; if (hi < minn) minn = hi; } if (minn < INT_MAX/10) for (PointIndex pi : hface.PNums()) if (pnearness[pi] > minn+1) pnearness[pi] = minn+1; } for (int i = 1; i <= connectedpairs.GetNBags(); i++) for (int j = 1; j <= connectedpairs.GetBagSize(i); j++) { INDEX_2 edge; int val; connectedpairs.GetData (i, j, edge, val); if (pnearness[edge.I1()] > pnearness[edge.I2()] + 1) pnearness[edge.I1()] = pnearness[edge.I2()] + 1; if (pnearness[edge.I2()] > pnearness[edge.I1()] + 1) pnearness[edge.I2()] = pnearness[edge.I1()] + 1; } } for (int i : fnearness.Range()) { int sum = 0; for (PointIndex pi : lfaces[i].PNums()) sum += pnearness[pi]; fnearness[i] = sum; } NgProfiler::StopTimer (90); NgProfiler::StartTimer (91); // find bounding boxes of faces triboxes.SetSize (lfaces.Size()); // for (int i = 0; i < lfaces.Size(); i++) for (auto i : lfaces.Range()) { const MiniElement2d & face = lfaces[i]; triboxes[i].SetPoint (lpoints[face[0]]); for (int j = 1; j < face.GetNP(); j++) triboxes[i].AddPoint (lpoints[face[j]]); } NgProfiler::StopTimer (91); NgProfiler::StartTimer (92); bool useedges = false; for (int ri = 0; ri < rules.Size(); ri++) if (rules[ri]->GetNEd()) useedges = true; if (useedges) { ledges.SetSize (5 * lfacesplit); for (int j = 0; j < lfacesplit; j++) // if (fnearness[j] <= 5) { const MiniElement2d & face = lfaces[j]; int newp, oldp; newp = face[face.GetNP()-1]; for (int k = 0; k < face.GetNP(); k++) { oldp = newp; newp = face[k]; ledges.Set (INDEX_2::Sort(oldp, newp), 1); } } } NgProfiler::StopTimer (92); NgProfiler::RegionTimer reg3(99); pused.SetSize (lpoints.Size()); fused.SetSize (lfaces.Size()); found = 0; minerr = tolfak * tolerance * tolerance; minteterr = sloppy * tolerance; if (testmode) (*testout) << "cnt = " << cnt << " class = " << tolerance << endl; // impossible, if no rule can be applied at any tolerance class bool impossible = 1; // check each rule: tstart.Stop(); tloop.Start(); for (int ri = 1; ri <= rules.Size(); ri++) { int base = (lfaces[0].GetNP() == 3) ? 100 : 200; NgProfiler::RegionTimer regx1(base); NgProfiler::RegionTimer regx(base+ri); // sprintf (problems.Elem(ri), ""); *problems.Elem(ri) = '\0'; vnetrule * rule = rules.Get(ri); if (rule->GetNP(1) != lfaces[0].GetNP()) continue; if (rule->GetQuality() > tolerance) { if (rule->GetQuality() < 100) impossible = 0; if (testmode) sprintf (problems.Elem(ri), "Quality not ok"); continue; } if (testmode) sprintf (problems.Elem(ri), "no mapping found"); loktestmode = testmode || rule->TestFlag ('t') || tolerance > 5; if (loktestmode) (*testout) << "Rule " << ri << " = " << rule->Name() << endl; pmap.SetSize (rule->GetNP()); fmapi.SetSize (rule->GetNF()); fmapr.SetSize (rule->GetNF()); fused = 0; pused = 0; for (auto & p : pmap) p.Invalidate(); fmapi = 0; for (int i : fmapr.Range()) fmapr[i] = rule->GetNP(i+1); fused[0] = 1; fmapi[0] = 1; fmapr[0] = rotind1; for (int j = 1; j <= lfaces[0].GetNP(); j++) { PointIndex locpi = lfaces[0].PNumMod (j+rotind1); pmap.Set (rule->GetPointNr (1, j), locpi); pused[locpi]++; } /* map all faces nfok .. first nfok-1 faces are mapped properly */ int nfok = 2; NgProfiler::RegionTimer regfa(300); NgProfiler::RegionTimer regx2(base+50+ri); while (nfok >= 2) { if (nfok <= rule->GetNOldF()) { // not all faces mapped ok = 0; int locfi = fmapi.Get(nfok); int locfr = fmapr.Get(nfok); int actfnp = rule->GetNP(nfok); while (!ok) { locfr++; if (locfr == actfnp + 1) { locfr = 1; locfi++; if (locfi > lfacesplit) break; } if (fnearness.Get(locfi) > rule->GetFNearness (nfok) || fused.Get(locfi) || actfnp != lfaces.Get(locfi).GetNP() ) { // face not feasible in any rotation locfr = actfnp; } else { ok = 1; locface = &lfaces.Get(locfi); // reference point already mapped differently ? for (int j = 1; j <= actfnp && ok; j++) { PointIndex locpi = pmap.Get(rule->GetPointNr (nfok, j)); if (locpi.IsValid() && locpi != locface->PNumMod(j+locfr)) ok = 0; } // local point already used or point outside tolerance ? for (int j = 1; j <= actfnp && ok; j++) { int refpi = rule->GetPointNr (nfok, j); if (!pmap.Get(refpi).IsValid()) { PointIndex locpi = locface->PNumMod (j + locfr); if (pused[locpi]) ok = 0; else { const Point3d & lp = lpoints[locpi]; const Point3d & rp = rule->GetPoint(refpi); if ( Dist2 (lp, rp) * rule->PointDistFactor(refpi) > minerr) { impossible = 0; ok = 0; } } } } } } if (ok) { // map face nfok fmapi.Set (nfok, locfi); fmapr.Set (nfok, locfr); fused.Set (locfi, 1); for (int j = 1; j <= rule->GetNP (nfok); j++) { PointIndex locpi = locface->PNumMod(j+locfr); if (rule->GetPointNr (nfok, j) <= 3 && pmap.Get(rule->GetPointNr(nfok, j)) != locpi) (*testout) << "change face1 point, mark1" << endl; pmap.Set(rule->GetPointNr (nfok, j), locpi); pused[locpi]++; } nfok++; } else { // backtrack one face fmapi.Set (nfok, 0); fmapr.Set (nfok, rule->GetNP(nfok)); nfok--; fused.Set (fmapi.Get(nfok), 0); for (int j = 1; j <= rule->GetNP (nfok); j++) { int refpi = rule->GetPointNr (nfok, j); pused[pmap.Get(refpi)]--; if (pused[pmap.Get(refpi)] == 0) { // pmap.Set(refpi, 0); pmap.Elem(refpi).Invalidate(); } } } } else { NgProfiler::RegionTimer regfb(301); // all faces are mapped // now map all isolated points: if (loktestmode) { (*testout) << "Faces Ok" << endl; sprintf (problems.Elem(ri), "Faces Ok"); } int npok = 1; int incnpok = 1; pfixed.SetSize (pmap.Size()); /* for (int i = 1; i <= pmap.Size(); i++) pfixed.Set(i, (pmap.Get(i) != 0) ); */ for (int i : pmap.Range()) pfixed[i] = pmap[i].IsValid(); while (npok >= 1) { if (npok <= rule->GetNOldP()) { if (pfixed.Get(npok)) { if (incnpok) npok++; else npok--; } else { PointIndex locpi = pmap.Elem(npok); ok = 0; if (locpi.IsValid()) pused[locpi]--; while (!ok && locpi < lpoints.Size()-1+PointIndex::BASE) { ok = 1; locpi++; if (pused[locpi] || pnearness[locpi] > rule->GetPNearness(npok)) { ok = 0; } else if (allowpoint[locpi] != 2) { ok = 0; if (allowpoint[locpi] == 1) impossible = 0; } else { const Point3d & lp = lpoints[locpi]; const Point3d & rp = rule->GetPoint(npok); if ( Dist2 (lp, rp) * rule->PointDistFactor(npok) > minerr) { ok = 0; impossible = 0; } } } if (ok) { pmap.Set (npok, locpi); if (npok <= 3) (*testout) << "set face1 point, mark3" << endl; pused[locpi]++; npok++; incnpok = 1; } else { // pmap.Set (npok, 0); pmap.Elem(npok).Invalidate(); if (npok <= 3) (*testout) << "set face1 point, mark4" << endl; npok--; incnpok = 0; } } } else { NgProfiler::RegionTimer regfa2(302); // all points are mapped if (loktestmode) { (*testout) << "Mapping found!!: Rule " << rule->Name() << endl; for (auto pi : pmap) (*testout) << pi << " "; (*testout) << endl; sprintf (problems.Elem(ri), "mapping found"); (*testout) << rule->GetNP(1) << " = " << lfaces.Get(1).GetNP() << endl; } ok = 1; // check mapedges: for (int i = 1; i <= rule->GetNEd(); i++) { INDEX_2 in2(pmap.Get(rule->GetEdge(i).i1), pmap.Get(rule->GetEdge(i).i2)); in2.Sort(); if (!ledges.Used (in2)) ok = 0; } // check prism edges: for (int i = 1; i <= rule->GetNE(); i++) { const Element & el = rule->GetElement (i); if (el.GetType() == PRISM) { for (int j = 1; j <= 3; j++) { INDEX_2 in2(pmap.Get(el.PNum(j)), pmap.Get(el.PNum(j+3))); in2.Sort(); if (!connectedpairs.Used (in2)) ok = 0; } } if (el.GetType() == PYRAMID) { if (loktestmode) (*testout) << "map pyramid, rule = " << rule->Name() << endl; for (int j = 1; j <= 2; j++) { INDEX_2 in2; if (j == 1) { in2.I1() = pmap.Get(el.PNum(2)); in2.I2() = pmap.Get(el.PNum(3)); } else { in2.I1() = pmap.Get(el.PNum(1)); in2.I2() = pmap.Get(el.PNum(4)); } in2.Sort(); if (!connectedpairs.Used (in2)) { ok = 0; if (loktestmode) (*testout) << "no pair" << endl; } } } } for (int i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++) fmapi.Set(i, 0); if (ok) { foundmap.Elem(ri)++; } // deviation of existing points oldu.SetSize (3 * rule->GetNOldP()); newu.SetSize (3 * (rule->GetNP() - rule->GetNOldP())); allp.SetSize (3 * rule->GetNP()); for (int i = 1; i <= rule->GetNOldP(); i++) { const Point3d & lp = lpoints[pmap.Get(i)]; const Point3d & rp = rule->GetPoint(i); oldu (3*i-3) = lp.X()-rp.X(); oldu (3*i-2) = lp.Y()-rp.Y(); oldu (3*i-1) = lp.Z()-rp.Z(); allp (3*i-3) = lp.X(); allp (3*i-2) = lp.Y(); allp (3*i-1) = lp.Z(); } if (rule->GetNP() > rule->GetNOldP()) { newu.SetSize (rule->GetOldUToNewU().Height()); rule->GetOldUToNewU().Mult (oldu, newu); } // int idiff = 3 * (rule->GetNP()-rule->GetNOldP()); int idiff = 3 * rule->GetNOldP(); for (int i = rule->GetNOldP()+1; i <= rule->GetNP(); i++) { const Point3d & rp = rule->GetPoint(i); allp (3*i-3) = rp.X() + newu(3*i-3 - idiff); allp (3*i-2) = rp.Y() + newu(3*i-2 - idiff); allp (3*i-1) = rp.Z() + newu(3*i-1 - idiff); } rule->SetFreeZoneTransformation (allp, tolerance + int(sloppy)); if (!rule->ConvexFreeZone()) { ok = 0; sprintf (problems.Elem(ri), "Freezone not convex"); if (loktestmode) (*testout) << "Freezone not convex" << endl; } if (loktestmode) { const Array & fz = rule->GetTransFreeZone(); (*testout) << "Freezone: " << endl; for (int i = 1; i <= fz.Size(); i++) (*testout) << fz.Get(i) << endl; } // check freezone: for (int i = 1; i <= lpoints.Size(); i++) { if ( !pused.Get(i) ) { const Point3d & lp = lpoints.Get(i); if (rule->fzbox.IsIn (lp)) { if (rule->IsInFreeZone(lp)) { if (loktestmode) { (*testout) << "Point " << i << " in Freezone" << endl; sprintf (problems.Elem(ri), "locpoint %d in Freezone", i); } ok = 0; break; } } } } for (int i = 1; i <= lfaces.Size() && ok; i++) { static Array lpi(4); if (!fused.Get(i)) { int triin; const MiniElement2d & lfacei = lfaces.Get(i); if (!triboxes.Elem(i).Intersect (rule->fzbox)) triin = 0; else { int li, lj; for (li = 1; li <= lfacei.GetNP(); li++) { int lpii = 0; PointIndex pi = lfacei.PNum(li); for (lj = 1; lj <= rule->GetNOldP(); lj++) if (pmap.Get(lj) == pi) lpii = lj; lpi.Elem(li) = lpii; } if (lfacei.GetNP() == 3) { triin = rule->IsTriangleInFreeZone ( lpoints[lfacei.PNum(1)], lpoints[lfacei.PNum(2)], lpoints[lfacei.PNum(3)], lpi, 1 ); } else { triin = rule->IsQuadInFreeZone ( lpoints[lfacei.PNum(1)], lpoints[lfacei.PNum(2)], lpoints[lfacei.PNum(3)], lpoints[lfacei.PNum(4)], lpi, 1 ); } } if (triin == -1) { ok = 0; } if (triin == 1) { #ifdef TEST_JS ok = 0; if (loktestmode) { (*testout) << "El with " << lfaces.Get(i).GetNP() << " points in freezone: " << lfaces.Get(i).PNum(1) << " - " << lfaces.Get(i).PNum(2) << " - " << lfaces.Get(i).PNum(3) << " - " << lfaces.Get(i).PNum(4) << endl; for (int lj = 1; lj <= lfaces.Get(i).GetNP(); lj++) (*testout) << lpoints[lfaces.Get(i).PNum(lj)] << " "; (*testout) << endl; sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone", lfaces.Get(i).PNum(1), lfaces.Get(i).PNum(2), lfaces.Get(i).PNum(3)); } #else if (loktestmode) { if (lfacei.GetNP() == 3) { (*testout) << "Triangle in freezone: " << lfacei.PNum(1) << " - " << lfacei.PNum(2) << " - " << lfacei.PNum(3) << ", or " << lpoints[lfacei.PNum(1)] << " - " << lpoints[lfacei.PNum(2)] << " - " << lpoints[lfacei.PNum(3)] << endl; (*testout) << "lpi = " << lpi.Get(1) << ", " << lpi.Get(2) << ", " << lpi.Get(3) << endl; } else (*testout) << "Quad in freezone: " << lfacei.PNum(1) << " - " << lfacei.PNum(2) << " - " << lfacei.PNum(3) << " - " << lfacei.PNum(4) << ", or " << lpoints[lfacei.PNum(1)] << " - " << lpoints[lfacei.PNum(2)] << " - " << lpoints[lfacei.PNum(3)] << " - " << lpoints[lfacei.PNum(4)] << endl; sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone", int(lfaces.Get(i).PNum(1)), int(lfaces.Get(i).PNum(2)), int(lfaces.Get(i).PNum(3))); } hc = 0; for (int k = rule->GetNOldF() + 1; k <= rule->GetNF(); k++) { if (rule->GetPointNr(k, 1) <= rule->GetNOldP() && rule->GetPointNr(k, 2) <= rule->GetNOldP() && rule->GetPointNr(k, 3) <= rule->GetNOldP()) { for (int j = 1; j <= 3; j++) if (lfaces.Get(i).PNumMod(j ) == pmap.Get(rule->GetPointNr(k, 1)) && lfaces.Get(i).PNumMod(j+1) == pmap.Get(rule->GetPointNr(k, 3)) && lfaces.Get(i).PNumMod(j+2) == pmap.Get(rule->GetPointNr(k, 2))) { fmapi.Elem(k) = i; hc = 1; // (*testout) << "found from other side: " // << rule->Name() // << " ( " << pmap.Get (rule->GetPointNr(k, 1)) // << " - " << pmap.Get (rule->GetPointNr(k, 2)) // << " - " << pmap.Get (rule->GetPointNr(k, 3)) << " ) " // << endl; strcpy (problems.Elem(ri), "other"); } } } if (!hc) { if (loktestmode) { (*testout) << "Triangle in freezone: " << lfaces.Get(i).PNum(1) << " - " << lfaces.Get(i).PNum(2) << " - " << lfaces.Get(i).PNum(3) << endl; sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone", int (lfaces.Get(i).PNum(1)), int (lfaces.Get(i).PNum(2)), int (lfaces.Get(i).PNum(3))); } ok = 0; } #endif } } } if (ok) { err = 0; for (int i = 1; i <= rule->GetNOldP(); i++) { double hf = rule->CalcPointDist (i, lpoints[pmap.Get(i)]); if (hf > err) err = hf; } if (loktestmode) { (*testout) << "Rule ok" << endl; sprintf (problems.Elem(ri), "Rule ok, err = %f", err); } // newu = rule->GetOldUToNewU() * oldu; // set new points: int oldnp = rule->GetNOldP(); int noldlp = lpoints.Size(); int noldlf = lfaces.Size(); for (int i = oldnp + 1; i <= rule->GetNP(); i++) { np = rule->GetPoint(i); np.X() += newu (3 * (i-oldnp) - 3); np.Y() += newu (3 * (i-oldnp) - 2); np.Z() += newu (3 * (i-oldnp) - 1); lpoints.Append (np); pmap.Elem(i) = lpoints.Size()-1+PointIndex::BASE; } // Set new Faces: for (int i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++) if (!fmapi.Get(i)) { MiniElement2d nface(rule->GetNP(i)); for (int j = 1; j <= nface.GetNP(); j++) nface.PNum(j) = pmap.Get(rule->GetPointNr (i, j)); lfaces.Append (nface); } // Delete old Faces: for (int i = 1; i <= rule->GetNDelF(); i++) delfaces.Append (fmapi.Get(rule->GetDelFace(i))); for (int i = rule->GetNOldF()+1; i <= rule->GetNF(); i++) if (fmapi.Get(i)) { delfaces.Append (fmapi.Get(i)); fmapi.Elem(i) = 0; } // check orientation for (int i = 1; i <= rule->GetNO() && ok; i++) { const fourint * fouri; fouri = &rule->GetOrientation(i); Vec3d v1 (lpoints[pmap.Get(fouri->i1)], lpoints[pmap.Get(fouri->i2)]); Vec3d v2 (lpoints[pmap.Get(fouri->i1)], lpoints[pmap.Get(fouri->i3)]); Vec3d v3 (lpoints[pmap.Get(fouri->i1)], lpoints[pmap.Get(fouri->i4)]); Vec3d n; Cross (v1, v2, n); //if (n * v3 >= -1e-7*n.Length()*v3.Length()) // OR -1e-7??? if (n * v3 >= -1e-9) { if (loktestmode) { sprintf (problems.Elem(ri), "Orientation wrong"); (*testout) << "Orientation wrong ("<< n*v3 << ")" << endl; } ok = 0; } } // new points in free-zone ? for (int i = rule->GetNOldP() + 1; i <= rule->GetNP() && ok; i++) if (!rule->IsInFreeZone (lpoints.Get(pmap.Get(i)))) { if (loktestmode) { (*testout) << "Newpoint " << lpoints.Get(pmap.Get(i)) << " outside convex hull" << endl; sprintf (problems.Elem(ri), "newpoint outside convex hull"); } ok = 0; } // insert new elements for (int i = 1; i <= rule->GetNE(); i++) { elements.Append (rule->GetElement(i)); for (int j = 1; j <= elements.Get(i).NP(); j++) elements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j)); } // Calculate Element badness teterr = 0; for (int i = 1; i <= elements.Size(); i++) { double hf = CalcElementBadness (lpoints, elements.Get(i)); if (hf > teterr) teterr = hf; } /* // keine gute Erfahrung am 25.1.2000, js if (ok && teterr < 100 && (rule->TestFlag('b') || tolerance > 10) ) { (*mycout) << "Reset teterr " << rule->Name() << " err = " << teterr << endl; teterr = 1; } */ // compare edgelength if (rule->TestFlag('l')) { double oldlen = 0; double newlen = 0; for (int i = 1; i <= rule->GetNDelF(); i++) { const Element2d & face = rule->GetFace (rule->GetDelFace(i)); for (int j = 1; j <= 3; j++) { const Point3d & p1 = lpoints[pmap.Get(face.PNumMod(j))]; const Point3d & p2 = lpoints[pmap.Get(face.PNumMod(j+1))]; oldlen += Dist(p1, p2); } } for (int i = rule->GetNOldF()+1; i <= rule->GetNF(); i++) { const Element2d & face = rule->GetFace (i); for (int j = 1; j <= 3; j++) { const Point3d & p1 = lpoints[pmap.Get(face.PNumMod(j))]; const Point3d & p2 = lpoints[pmap.Get(face.PNumMod(j+1))]; newlen += Dist(p1, p2); } } if (oldlen < newlen) { ok = 0; if (loktestmode) sprintf (problems.Elem(ri), "oldlen < newlen"); } } if (loktestmode) (*testout) << "ok = " << int(ok) << "teterr = " << teterr << "minteterr = " << minteterr << endl; if (ok && teterr < tolerance) { canuse.Elem(ri) ++; /* (*testout) << "can use rule " << rule->Name() << ", err = " << teterr << endl; for (i = 1; i <= pmap.Size(); i++) (*testout) << pmap.Get(i) << " "; (*testout) << endl; */ if (strcmp (problems.Elem(ri), "other") == 0) { if (teterr < minother) minother = teterr; } else { if (teterr < minwithoutother) minwithoutother = teterr; } } if (teterr > minteterr) impossible = 0; if (ok && teterr < minteterr) { if (loktestmode) (*testout) << "use rule" << endl; found = ri; minteterr = teterr; if (testmode) { for (int i = 1; i <= rule->GetNOldP(); i++) { (*testout) << "P" << i << ": Ref: " << rule->GetPoint (i) << " is: " << lpoints.Get(pmap.Get(i)) << endl; } } tempnewpoints.SetSize (0); for (int i = noldlp+1; i <= lpoints.Size(); i++) tempnewpoints.Append (lpoints.Get(i)); tempnewfaces.SetSize (0); for (int i = noldlf+1; i <= lfaces.Size(); i++) tempnewfaces.Append (lfaces.Get(i)); tempdelfaces.SetSize (0); for (int i = 1; i <= delfaces.Size(); i++) tempdelfaces.Append (delfaces.Get(i)); tempelements.SetSize (0); for (int i = 1; i <= elements.Size(); i++) tempelements.Append (elements.Get(i)); } lpoints.SetSize (noldlp); lfaces.SetSize (noldlf); delfaces.SetSize (0); elements.SetSize (0); } npok = rule->GetNOldP(); incnpok = 0; } } nfok = rule->GetNOldF(); for (int j = 1; j <= rule->GetNP (nfok); j++) { int refpi = rule->GetPointNr (nfok, j); pused[pmap.Get(refpi)]--; if (pused[pmap.Get(refpi)] == 0) pmap.Elem(refpi).Invalidate(); } } } if (loktestmode) (*testout) << "end rule" << endl; } tloop.Stop(); if (found) { /* for (i = 1; i <= tempnewpoints.Size(); i++) lpoints.Append (tempnewpoints.Get(i)); */ for (Point3d p : tempnewpoints) lpoints.Append(p); /* for (i = 1; i <= tempnewfaces.Size(); i++) if (tempnewfaces.Get(i).PNum(1)) lfaces.Append (tempnewfaces.Get(i)); */ for (int i : tempnewfaces.Range()) if (tempnewfaces[i].PNum(1).IsValid()) lfaces.Append (tempnewfaces[i]); /* for (i = 1; i <= tempdelfaces.Size(); i++) delfaces.Append (tempdelfaces.Get(i)); */ for (int i : tempdelfaces.Range()) delfaces.Append (tempdelfaces[i]); /* for (i = 1; i <= tempelements.Size(); i++) elements.Append (tempelements.Get(i)); */ for (int i : tempelements.Range()) elements.Append (tempelements[i]); } retminerr = minerr; if (impossible && found == 0) return -1; return found; } } netgen-6.2.1905/libsrc/meshing/bcfunctions.cpp0000644000175000017500000003640013504650527017735 0ustar kurtkurt #include #include #include "bcfunctions.hpp" namespace netgen { // Default colour to be used for boundary condition number "0" #define DEFAULT_R 0.0 #define DEFAULT_G 1.0 #define DEFAULT_B 0.0 // Boundary condition number to use if a face does not have a // colour assigned to it, or if the colour is the above defined // default colour #define DEFAULT_BCNUM 1 // Default tolerance for colour matching (using Euclidean distance) #define DEFAULT_EPS 2.5e-05 /*! Philippose - 11/07/2009 Function to check if two RGB colours are equal Note#1: Currently uses unweighted Euclidean Distance for colour matching. Note#2: The tolerance used for deciding whether two colours match is defined as "eps" and is currently 2.5e-5 (for square of distance) */ bool ColourMatch(Vec3d col1, Vec3d col2, double eps) { if(eps <= 0.0) eps = DEFAULT_EPS; bool colmatch = false; if(Dist2(col1,col2) < eps) colmatch = true; return colmatch; } /*! Philippose - 11/07/2009 Function to create a list of all the unique colours available in a given mesh */ void GetFaceColours(Mesh & mesh, Array & face_colours) { face_colours.SetSize(1); face_colours.Elem(1) = mesh.GetFaceDescriptor(1).SurfColour(); for(int i = 1; i <= mesh.GetNFD(); i++) { Vec3d face_colour = mesh.GetFaceDescriptor(i).SurfColour(); bool col_found = false; for(int j = 1; j <= face_colours.Size(); j++) { if(ColourMatch(face_colours.Elem(j),face_colour)) { col_found = true; break; } } if(!col_found) face_colours.Append(face_colour); } if(printmessage_importance >= 3) { cout << endl << "-------- Face Colours --------" << endl; for( int i = 1; i <= face_colours.Size(); i++) { cout << face_colours.Elem(i) << endl; } cout << "------------------------------" << endl; } } /*! Philippose - 11/07/2009 Assign boundary condition numbers based on a user defined colour profile file. The default profile file is "netgen.ocf" If the mesh contains colours not defined in the profile, netgen automatically starts assigning each new colour a new boundary condition number starting from the highest boundary condition number specified in the profile file. */ void AutoColourAlg_UserProfile(Mesh & mesh, ifstream & ocf) { char ocf_inp[100]; bool header_found = false; // Number of colour specifications in the // user profile file int numentries = 0; while((ocf.good()) && (!header_found)) { ocf >> ocf_inp; if(strcmp(ocf_inp,"boundary_colours") == 0) header_found = true; } if(!header_found) { ocf.close(); throw NgException("AutoColourAlg_UserProfile: Invalid or empty Boundary Colour Profile file\n"); return; } // Read in the number of entries from file ocf >> numentries; if(numentries > 0) { if(!ocf.good()) { ocf.close(); throw NgException("AutoColourAlg_UserProfile: Invalid or empty Boundary Colour Profile file\n"); return; } PrintMessage(3, "Number of colour entries: ", numentries); } else { ocf.close(); PrintMessage(3, "AutoColourAlg_UserProfile: No Boundary Colour entries found.... no changes made!"); return; } // Arrays to hold the specified RGB colour triplets as well // as the associated boundary condition number Array bc_colours(numentries); Array bc_num(numentries); Array bc_used(numentries); // Actually read in the data from the file for(int i = 1; i <= numentries; i++) { int bcnum; // double col_red, col_green, col_blue; ocf >> bcnum; // Boundary condition number DEFAULT_BCNUM is reserved for // faces which have the default colour Green (0.0,1.0,0.0) // To prevent confusion, no boundary numbery below this default // are permitted if(bcnum < (DEFAULT_BCNUM + 1)) bcnum = DEFAULT_BCNUM+1; bc_num.Elem(i) = bcnum; bc_used.Elem(i) = false; ocf >> bc_colours.Elem(i).X() >> bc_colours.Elem(i).Y() >> bc_colours.Elem(i).Z(); if(!ocf.good()) { ocf.close(); throw NgException("Boundary Colour file error: Number of entries do not match specified list size!!\n"); return; } // Bound checking of the values // The RGB values should be between 0.0 and 1.0 if(bc_colours.Elem(bcnum).X() < 0.0) bc_colours.Elem(bcnum).X() = 0.0; if(bc_colours.Elem(bcnum).X() > 1.0) bc_colours.Elem(bcnum).X() = 1.0; if(bc_colours.Elem(bcnum).Y() < 0.0) bc_colours.Elem(bcnum).X() = 0.0; if(bc_colours.Elem(bcnum).Y() > 1.0) bc_colours.Elem(bcnum).X() = 1.0; if(bc_colours.Elem(bcnum).Z() < 0.0) bc_colours.Elem(bcnum).X() = 0.0; if(bc_colours.Elem(bcnum).Z() > 1.0) bc_colours.Elem(bcnum).X() = 1.0; } PrintMessage(3, "Successfully loaded Boundary Colour Profile file...."); ocf.close(); // Find the highest boundary condition number in the list // All colours in the geometry which are not specified in the // list will be given boundary condition numbers higher than this // number int max_bcnum = DEFAULT_BCNUM; for(int i = 1; i <= bc_num.Size();i++) { if(bc_num.Elem(i) > max_bcnum) max_bcnum = bc_num.Elem(i); } PrintMessage(3, "Highest boundary number in list = ",max_bcnum); Array all_colours; // Extract all the colours to see how many there are GetFaceColours(mesh,all_colours); PrintMessage(3,"\nNumber of colours defined in Mesh: ", all_colours.Size()); if(all_colours.Size() == 0) { PrintMessage(3,"No colour data detected in Mesh... no changes made!"); return; } int nfd = mesh.GetNFD(); for(int face_index = 1; face_index <= nfd; face_index++) { // Temporary container for individual face colours Vec3d face_colour; // Get the colour of the face being currently processed face_colour = mesh.GetFaceDescriptor(face_index).SurfColour(); if(!ColourMatch(face_colour,Vec3d(DEFAULT_R,DEFAULT_G,DEFAULT_B))) { // Boolean variable to check if the boundary condition was applied // or not... not applied would imply that the colour of the face // does not exist in the list of colours in the profile file bool bc_assigned = false; for(int col_index = 1; col_index <= bc_colours.Size(); col_index++) { if((ColourMatch(face_colour,bc_colours.Elem(col_index))) && (!bc_assigned)) { mesh.GetFaceDescriptor(face_index).SetBCProperty(bc_num.Elem(col_index)); bc_used.Elem(col_index) = true; bc_assigned = true; break; } } // If the colour was not found in the list, add it to the list, and assign // the next free boundary condition number to it if(!bc_assigned) { max_bcnum++; bc_num.Append(max_bcnum); bc_colours.Append(face_colour); bc_used.Append(true); mesh.GetFaceDescriptor(face_index).SetBCProperty(max_bcnum); } } else { // Set the boundary condition number to the default one mesh.GetFaceDescriptor(face_index).SetBCProperty(DEFAULT_BCNUM); } } // User Information of the results of the operation Vec3d ref_colour(0.0,1.0,0.0); PrintMessage(3,"Colour based Boundary Condition Property details:"); for(int bc_index = 0; bc_index <= bc_num.Size(); bc_index++) { if(bc_index > 0) ref_colour = bc_colours.Elem(bc_index); if(bc_index == 0) { PrintMessage(3, "BC Property: ",DEFAULT_BCNUM); PrintMessage(3, " RGB Face Colour = ",ref_colour,"","\n"); } else if(bc_used.Elem(bc_index)) { PrintMessage(3, "BC Property: ",bc_num.Elem(bc_index)); PrintMessage(3, " RGB Face Colour = ",ref_colour,"","\n"); } } } /*! Philippose - 11/07/2009 Assign boundary condition numbers based on the colours assigned to each face in the mesh using an automated algorithm. The particular algorithm used has been briefly explained in the header file "occauxfunctions.hpp" */ void AutoColourAlg_Sorted(Mesh & mesh) { Array all_colours; Array faces_sorted; Array colours_sorted; // Extract all the colours to see how many there are GetFaceColours(mesh,all_colours); // Delete the default colour from the list since it will be accounted // for automatically for(int i = 1; i <= all_colours.Size(); i++) { if(ColourMatch(all_colours.Elem(i),Vec3d(DEFAULT_R,DEFAULT_G,DEFAULT_B))) { all_colours.DeleteElement(i); break; } } PrintMessage(3,"\nNumber of colours defined in Mesh: ", all_colours.Size()); if(all_colours.Size() == 0) { PrintMessage(3,"No colour data detected in Mesh... no changes made!"); return; } // One more slot than the number of colours are required, to // account for individual faces which have no colour data // assigned to them in the CAD software faces_sorted.SetSize(all_colours.Size()+1); colours_sorted.SetSize(all_colours.Size()+1); faces_sorted = 0; // Slave Array to identify the colours the faces were assigned to, // after the bubble sort routine to sort the automatic boundary // identifiers according to the number of surface mesh elements // of a given colour for(int i = 0; i <= all_colours.Size(); i++) colours_sorted[i] = i; // Used to hold the number of surface elements without any OCC // colour definition int no_colour_faces = 0; // Index in the faces array assigned to faces without any // or the default colour definition int no_colour_index = 0; int nfd = mesh.GetNFD(); // Extract the number of surface elements having a given colour // And save this number into an array for later sorting for(int face_index = 1; face_index <= nfd; face_index++) { Array se_face; mesh.GetSurfaceElementsOfFace(face_index, se_face); Vec3d face_colour; face_colour = mesh.GetFaceDescriptor(face_index).SurfColour(); if(!ColourMatch(face_colour,Vec3d(DEFAULT_R,DEFAULT_G,DEFAULT_B))) { for(int i = 1; i <= all_colours.Size(); i++) { if(ColourMatch(face_colour, all_colours.Elem(i))) { faces_sorted[i] = faces_sorted[i] + se_face.Size(); } } } else { // Add the number of surface elements without any colour // definition separately no_colour_faces = no_colour_faces + se_face.Size(); } } // Sort the face colour indices according to the number of surface // mesh elements which have a specific colour BubbleSort(faces_sorted,colours_sorted); // Now update the array position assigned for surface elements // without any colour definition with the number of elements faces_sorted[no_colour_index] = no_colour_faces; // Now actually assign the BC Property to the respective faces for(int face_index = 1; face_index <= nfd; face_index++) { Vec3d face_colour; face_colour = mesh.GetFaceDescriptor(face_index).SurfColour(); if(!ColourMatch(face_colour,Vec3d(DEFAULT_R,DEFAULT_G,DEFAULT_B))) { for(int i = 0; i < colours_sorted.Size(); i++) { Vec3d ref_colour; if(i != no_colour_index) ref_colour = all_colours.Elem(colours_sorted[i]); if(ColourMatch(face_colour, ref_colour)) { mesh.GetFaceDescriptor(face_index).SetBCProperty(i + DEFAULT_BCNUM); } } } else { mesh.GetFaceDescriptor(face_index).SetBCProperty(DEFAULT_BCNUM); } PrintMessage(4,"Face number: ",face_index," ; BC Property = ",mesh.GetFaceDescriptor(face_index).BCProperty()); } // User Information of the results of the operation Vec3d ref_colour(0.0,1.0,0.0); PrintMessage(3,"Colour based Boundary Condition Property details:"); for(int i = 0; i < faces_sorted.Size(); i++) { if(colours_sorted[i] > 0) ref_colour = all_colours.Elem(colours_sorted[i]); PrintMessage(3, "BC Property: ",i + DEFAULT_BCNUM); PrintMessage(3, " Nr. of Surface Elements = ", faces_sorted[i]); PrintMessage(3, " Colour Index = ", colours_sorted[i]); PrintMessage(3, " RGB Face Colour = ",ref_colour,"","\n"); } } /*! Philippose - 13/07/2009 Main function implementing automated assignment of Boundary Condition numbers based on face colours This functionality is currently implemtented at the mesh level, and hence allows colour based assignment of boundary conditions for any geometry type within netgen which supports face colours */ void AutoColourBcProps(Mesh & mesh, const char * bccolourfile) { // Go directly to the alternate algorithm if no colour profile file was specified if(!bccolourfile) { PrintMessage(1,"AutoColourBcProps: Using Automatic Colour based boundary property assignment algorithm"); AutoColourAlg_Sorted(mesh); } else { ifstream ocf(bccolourfile); // If there was an error opening the Colour profile file, jump to the alternate // algorithm after printing a message if(!ocf) { PrintMessage(1,"AutoColourBcProps: Error loading Boundary Colour Profile file ", bccolourfile, " ....","Switching to Automatic Assignment algorithm!"); AutoColourAlg_Sorted(mesh); } // If the file opens successfully, call the function which assigns boundary conditions // based on the colour profile file else { PrintMessage(1, "AutoColourBcProps: Using Boundary Colour Profile file: "); PrintMessage(1, " ", bccolourfile); AutoColourAlg_UserProfile(mesh, ocf); // Make sure the file is closed before exiting the function if(ocf.is_open()) { ocf.close(); } } } } } netgen-6.2.1905/libsrc/meshing/prism2rls_2.cpp0000644000175000017500000001544113504650527017600 0ustar kurtkurtnamespace netgen { const char * prismrules2[] = { "tolfak 0.5\n",\ "\n",\ "rule \"prism on quad\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 2, 3, 6);\n",\ "(1, 5, 6, 4);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "orientations\n",\ "(1, 2, 3, 5);\n",\ "(1, 3, 4, 6);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on quad, one trig\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(1, 5, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 2, 3, 6);\n",\ "(1, 5, 6, 4);\n",\ "(4, 6, 3);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "orientations\n",\ "(1, 2, 3, 5);\n",\ "(1, 3, 4, 6);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 2 quad\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 5, 6, 4);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5 6 7;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 2 quad, one trig\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(1, 5, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 5, 6, 4);\n",\ "(4, 6, 3);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5 6 7;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 2 quada\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(5, 1, 4, 6) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 2, 3, 6);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5 6 7;\n",\ "\n",\ "freeset\n",\ "1 3 4 6;\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"fill prism\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(5, 1, 4, 6) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 3 quad, one trig\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(5, 1, 4, 6) del;\n",\ "(1, 5, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(4, 6, 3);\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"flat prism\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(0.5, 0.866, 0);\n",\ "(0, 0, -1);\n",\ "(1, 0, -1);\n",\ "(0.5, 0.866, -1);\n",\ "\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3) del;\n",\ "(5, 4, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 2, 4);\n",\ "(4, 2, 5);\n",\ "(2, 3, 5);\n",\ "(5, 3, 6);\n",\ "(3, 1, 6);\n",\ "(6, 1, 4);\n",\ "\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 5, 4, 6);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "endrule\n",\ "\n",\ 0}; } netgen-6.2.1905/libsrc/meshing/msghandler.hpp0000644000175000017500000000603413504650527017551 0ustar kurtkurt#ifndef FILE_MSGHANDLER #define FILE_MSGHANDLER /**************************************************************************/ /* File: msghandler.hh */ /* Author: Johannes Gerstmayr */ /* Date: 20. Nov. 99 */ /**************************************************************************/ namespace netgen { extern void PrintDot(char ch = '.'); //Message Pipeline: //importance: importance of message: 1=very important, 3=middle, 5=low, 7=unimportant extern DLL_HEADER void PrintMessage(int importance, const MyStr& s1, const MyStr& s2=MyStr()); extern DLL_HEADER void PrintMessage(int importance, const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4=MyStr()); extern DLL_HEADER void PrintMessage(int importance, const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6=MyStr(), const MyStr& s7=MyStr(), const MyStr& s8=MyStr()); // CR without line-feed extern DLL_HEADER void PrintMessageCR(int importance, const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void PrintFnStart(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void PrintWarning(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void PrintError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void PrintFileError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void PrintSysError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void PrintUserError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void PrintTime(const MyStr& s1="", const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); extern DLL_HEADER void SetStatMsg(const MyStr& s); extern DLL_HEADER void PushStatus(const MyStr& s); extern DLL_HEADER void PushStatusF(const MyStr& s); extern DLL_HEADER void PopStatus(); extern DLL_HEADER void SetThreadPercent(double percent); extern DLL_HEADER void GetStatus(MyStr & s, double & percentage); } #endif netgen-6.2.1905/libsrc/meshing/findip.hpp0000644000175000017500000000776313504650527016710 0ustar kurtkurt// find inner point inline void Minimize (const Array & a, const Array & c, int * act, Vec<3> & x, double & f, int * sol) { int act1[4]; Mat<3> m, inv; Vec<3> rs, xmax, center; f = 1e99; for (int j = 0; j < 5; j++) { for (int hk = 0, k = 0; hk < 4; hk++) { if (hk == j) k++; act1[hk] = act[k]; k++; } for (int k = 0; k < 3; k++) { m(k, 0) = a[act1[0]].X() - a[act1[k+1]].X(); m(k, 1) = a[act1[0]].Y() - a[act1[k+1]].Y(); m(k, 2) = a[act1[0]].Z() - a[act1[k+1]].Z(); rs(k) = c[act1[k+1]] - c[act1[0]]; } /* (*testout) << "act1 = " << act1[0] << " " << act1[1] << " " << act1[2] << " " << act1[3] << endl; (*testout) << "Det = " << Det(m) << endl; */ if (fabs (Det (m)) > 1e-10) { CalcInverse (m, inv); xmax = inv * rs; double fmax = -1e10; for (int k = 0; k < 5; k++) { double hd = xmax(0) * a[act[k]].X() + xmax(1) * a[act[k]].Y() + xmax(2) * a[act[k]].Z() + c[act[k]]; if (hd > fmax) fmax = hd; } if (fmax < f) { f = fmax; x = xmax; for (int k = 0; k < 4; k++) sol[k] = act1[k]; } } } } template inline int FindInnerPoint (POINTArray & points, FACEArray & faces, Point3d & p) { static int timer = NgProfiler::CreateTimer ("FindInnerPoint"); NgProfiler::RegionTimer reg (timer); Array a; Array c; Mat<3> m, inv; Vec<3> rs, x = 0.0, center; double f; int nf = faces.Size(); // minimize_x max_i a_i x + c_i a.SetSize (nf+4); c.SetSize (nf+4); for (int i = 0; i < nf; i++) { Point3d p1 = points.Get(faces[i][0]); a[i] = Cross (points.Get(faces[i][1]) - p1, points.Get(faces[i][2]) - p1); a[i] /= a[i].Length(); c[i] = - (a[i].X() * p1.X() + a[i].Y() * p1.Y() + a[i].Z() * p1.Z()); } /* center = 0; for (int i = 0; i < points.Size(); i++) center += Vec<3> (points[i]); center /= points.Size(); */ center = 0; for (int i = 0; i < faces.Size(); i++) for (int j = 0; j < 3; j++) center += Vec<3> (points.Get(faces[i][j])); center /= (3*faces.Size()); // (*testout) << "center = " << center << endl; double hmax = 0; for (int i = 0; i < nf; i++) { // const Element2d & el = faces[i]; // (*testout) << "el[" << i << "] = " << el << endl; for (int j = 1; j <= 3; j++) { double hi = Dist (points.Get(faces[i].PNumMod(j)), points.Get(faces[i].PNumMod(j+1))); if (hi > hmax) hmax = hi; } } // (*testout) << "hmax = " << hmax << endl; a[nf] = Vec<3> (1, 0, 0); c[nf] = -center(0) - hmax; a[nf+1] = Vec<3> (0, 1, 0); c[nf+1] = -center(1) - hmax; a[nf+2] = Vec<3> (0, 0, 1); c[nf+2] = -center(2) - hmax; a[nf+3] = Vec<3> (-1, -1, -1); c[nf+3] = center(0)+center(1)+center(2)-3*hmax; /* (*testout) << "findip, a now = " << endl << a << endl; (*testout) << "findip, c now = " << endl << c << endl; */ int act[5] = { 0, nf, nf+1, nf+2, nf+3 }; int sol[4]; while (1) { /* (*testout) << "try "; for (int j = 0; j < 5; j++) (*testout) << act[j] << " "; */ Minimize (a, c, act, x, f, sol); /* (*testout) << endl << "sol = "; for (int j = 0; j < 4; j++) (*testout) << sol[j] << " "; (*testout) << " fmin = " << f << endl; */ for (int j = 0; j < 4; j++) act[j] = sol[j]; bool found = 0; double maxval = f; for (int j = 0; j < nf; j++) { double val = x(0) * a[j].X() + x(1) * a[j].Y() + x(2) * a[j].Z() + c[j]; if (val > maxval + hmax * 1e-6) { found = 1; maxval = val; act[4] = j; } } // (*testout) << "maxval = " << maxval << endl; if (!found) break; } // cout << "converged, f = " << f << endl; p = Point3d (x(0), x(1), x(2)); // (*testout) << "findip, f = " << f << ", hmax = " << hmax << endl; return (f < -1e-5 * hmax); } netgen-6.2.1905/libsrc/meshing/prism2rls.cpp0000644000175000017500000001567413504650527017367 0ustar kurtkurtnamespace netgen { const char * prismrules2[] = { "tolfak 0.5\n",\ "\n",\ "rule \"prism on quad\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 2, 3, 6);\n",\ "(1, 5, 6, 4);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "orientations\n",\ "(1, 2, 3, 5);\n",\ "(1, 3, 4, 6);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5 6 7;\n",\ "\n",\ "freeset\n",\ "2 3 4 5 6 8;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on quad, one trig\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(1, 5, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 2, 3, 6);\n",\ "(1, 5, 6, 4);\n",\ "(4, 6, 3);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "orientations\n",\ "(1, 2, 3, 5);\n",\ "(1, 3, 4, 6);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5 6 7;\n",\ "\n",\ "freeset\n",\ "2 3 4 5 6 8;\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 2 quad\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 5, 6, 4);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5 6 7;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 2 quad, one trig\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(1, 5, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 5, 6, 4);\n",\ "(4, 6, 3);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5 6 7;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 2 quada\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(5, 1, 4, 6) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 2, 3, 6);\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5 6 7;\n",\ "\n",\ "freeset\n",\ "1 3 4 6;\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"fill prism\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(5, 1, 4, 6) del;\n",\ "(1, 5, 2) del;\n",\ "(4, 3, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"prism on 3 quad, one trig\"\n",\ "\n",\ "quality 2\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0, -0.86);\n",\ "(0.5, 1, -0.86);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 5, 6, 3) del;\n",\ "(5, 1, 4, 6) del;\n",\ "(1, 5, 2) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(4, 6, 3);\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 5, 2, 4, 6, 3);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "\n",\ "freeset\n",\ "1 2 4 5;\n",\ "\n",\ "freeset\n",\ "2 3 4 6;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"flat prism\"\n",\ "\n",\ "quality 100\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(0.5, 0.866, 0);\n",\ "(0, 0, -1);\n",\ "(1, 0, -1);\n",\ "(0.5, 0.866, -1);\n",\ "\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3) del;\n",\ "(5, 4, 6) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 2, 4);\n",\ "(4, 2, 5);\n",\ "(2, 3, 5);\n",\ "(5, 3, 6);\n",\ "(3, 1, 6);\n",\ "(6, 1, 4);\n",\ "\n",\ "\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 5, 4, 6);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "endrule\n",\ "\n",\ 0}; } netgen-6.2.1905/libsrc/meshing/meshing3.hpp0000644000175000017500000000433513504650527017144 0ustar kurtkurt#ifndef FILE_MESHING3 #define FILE_MESHING3 enum MESHING3_RESULT { MESHING3_OK = 0, MESHING3_GIVEUP = 1, MESHING3_NEGVOL = 2, MESHING3_OUTERSTEPSEXCEEDED = 3, MESHING3_TERMINATE = 4, MESHING3_BADSURFACEMESH = 5 }; /// 3d volume mesh generation class Meshing3 { /// current state of front AdFront3 * adfront; /// 3d generation rules Array rules; /// counts how often a rule is used Array ruleused, canuse, foundmap; /// describes, why a rule is not applied Array problems; /// tolerance criterion double tolfak; public: /// Meshing3 (const string & rulefilename); /// Meshing3 (const char ** rulep); /// virtual ~Meshing3 (); /// void LoadRules (const char * filename, const char ** prules); /// MESHING3_RESULT GenerateMesh (Mesh & mesh, const MeshingParameters & mp); /// int ApplyRules (Array & lpoints, Array & allowpoint, Array & lfaces, INDEX lfacesplit, INDEX_2_HASHTABLE & connectedpairs, Array & elements, Array & delfaces, int tolerance, double sloppy, int rotind1, float & retminerr); /// PointIndex AddPoint (const Point3d & p, PointIndex globind); /// void AddBoundaryElement (const Element2d & elem); /// void AddBoundaryElement (const MiniElement2d & elem); /// int AddConnectedPair (const INDEX_2 & pair); /// void BlockFill (Mesh & mesh, double gh); /// void BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp); /// uses points of adfront, and puts new elements into mesh void Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp); /// friend class PlotVolMesh; /// friend void TestRules (); }; /// status of mesh generation class MeshingStat3d { public: /// MeshingStat3d (); /// int cntsucc; /// int cnttrials; /// int cntelem; /// int nff; /// int qualclass; /// double vol0; /// double vol; /// double h; /// int problemindex; }; /* template extern int FindInnerPoint (POINTArray & grouppoints, FACEArray & groupfaces, Point3d & p); */ #endif netgen-6.2.1905/libsrc/meshing/localh.cpp0000644000175000017500000004505013504650527016663 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { GradingBox :: GradingBox (const double * ax1, const double * ax2) { h2 = 0.5 * (ax2[0] - ax1[0]); for (int i = 0; i < 3; i++) xmid[i] = 0.5 * (ax1[i] + ax2[i]); for (int i = 0; i < 8; i++) childs[i] = NULL; father = NULL; flags.cutboundary = 0; flags.isinner = 0; flags.oldcell = 0; flags.pinner = 0; hopt = 2 * h2; } BlockAllocator GradingBox :: ball(sizeof (GradingBox)); void * GradingBox :: operator new(size_t) { return ball.Alloc(); } void GradingBox :: operator delete (void * p) { ball.Free (p); } void GradingBox :: DeleteChilds() { for (int i = 0; i < 8; i++) if (childs[i]) { childs[i]->DeleteChilds(); delete childs[i]; childs[i] = NULL; } } LocalH :: LocalH (Point<3> pmin, Point<3> pmax, double agrading, int adimension) : dimension(adimension) { double x1[3], x2[3]; double hmax; boundingbox = Box<3> (pmin, pmax); grading = agrading; // a small enlargement, non-regular points double val = 0.0879; for (int i = 0; i < dimension; i++) { x1[i] = (1 + val * (i+1)) * pmin(i) - val * (i+1) * pmax(i); x2[i] = 1.1 * pmax(i) - 0.1 * pmin(i); } for (int i = dimension; i < 3; i++) x1[i] = x2[i] = 0; hmax = x2[0] - x1[0]; for (int i = 1; i < dimension; i++) hmax = max2(x2[i]-x1[i], hmax); for (int i = 0; i < dimension; i++) x2[i] = x1[i] + hmax; root = new GradingBox (x1, x2); boxes.Append (root); } LocalH :: ~LocalH () { root->DeleteChilds(); delete root; } void LocalH :: Delete () { root->DeleteChilds(); } void LocalH :: SetH (Point<3> p, double h) { if (dimension == 2) { if (fabs (p(0) - root->xmid[0]) > root->h2 || fabs (p(1) - root->xmid[1]) > root->h2) return; if (GetH(p) <= 1.2 * h) return; GradingBox * box = root; GradingBox * nbox = root; GradingBox * ngb; int childnr; double x1[3], x2[3]; while (nbox) { box = nbox; childnr = 0; if (p(0) > box->xmid[0]) childnr += 1; if (p(1) > box->xmid[1]) childnr += 2; nbox = box->childs[childnr]; }; while (2 * box->h2 > h) { childnr = 0; if (p(0) > box->xmid[0]) childnr += 1; if (p(1) > box->xmid[1]) childnr += 2; double h2 = box->h2; if (childnr & 1) { x1[0] = box->xmid[0]; x2[0] = x1[0]+h2; // box->x2[0]; } else { x2[0] = box->xmid[0]; x1[0] = x2[0]-h2; // box->x1[0]; } if (childnr & 2) { x1[1] = box->xmid[1]; x2[1] = x1[1]+h2; // box->x2[1]; } else { x2[1] = box->xmid[1]; x1[1] = x2[1]-h2; // box->x1[1]; } x1[2] = x2[2] = 0; ngb = new GradingBox (x1, x2); box->childs[childnr] = ngb; ngb->father = box; boxes.Append (ngb); box = box->childs[childnr]; } box->hopt = h; double hbox = 2 * box->h2; // box->x2[0] - box->x1[0]; double hnp = h + grading * hbox; Point<3> np; for (int i = 0; i < 2; i++) { np = p; np(i) = p(i) + hbox; SetH (np, hnp); np(i) = p(i) - hbox; SetH (np, hnp); } } else { if (fabs (p(0) - root->xmid[0]) > root->h2 || fabs (p(1) - root->xmid[1]) > root->h2 || fabs (p(2) - root->xmid[2]) > root->h2) return; if (GetH(p) <= 1.2 * h) return; GradingBox * box = root; GradingBox * nbox = root; GradingBox * ngb; int childnr; double x1[3], x2[3]; while (nbox) { box = nbox; childnr = 0; if (p(0) > box->xmid[0]) childnr += 1; if (p(1) > box->xmid[1]) childnr += 2; if (p(2) > box->xmid[2]) childnr += 4; nbox = box->childs[childnr]; }; while (2 * box->h2 > h) { childnr = 0; if (p(0) > box->xmid[0]) childnr += 1; if (p(1) > box->xmid[1]) childnr += 2; if (p(2) > box->xmid[2]) childnr += 4; double h2 = box->h2; if (childnr & 1) { x1[0] = box->xmid[0]; x2[0] = x1[0]+h2; // box->x2[0]; } else { x2[0] = box->xmid[0]; x1[0] = x2[0]-h2; // box->x1[0]; } if (childnr & 2) { x1[1] = box->xmid[1]; x2[1] = x1[1]+h2; // box->x2[1]; } else { x2[1] = box->xmid[1]; x1[1] = x2[1]-h2; // box->x1[1]; } if (childnr & 4) { x1[2] = box->xmid[2]; x2[2] = x1[2]+h2; // box->x2[2]; } else { x2[2] = box->xmid[2]; x1[2] = x2[2]-h2; // box->x1[2]; } ngb = new GradingBox (x1, x2); box->childs[childnr] = ngb; ngb->father = box; boxes.Append (ngb); box = box->childs[childnr]; } box->hopt = h; double hbox = 2 * box->h2; // box->x2[0] - box->x1[0]; double hnp = h + grading * hbox; Point<3> np; for (int i = 0; i < 3; i++) { np = p; np(i) = p(i) + hbox; SetH (np, hnp); np(i) = p(i) - hbox; SetH (np, hnp); } } } double LocalH :: GetH (Point<3> x) const { const GradingBox * box = root; if (dimension == 2) { while (1) { int childnr = 0; if (x(0) > box->xmid[0]) childnr += 1; if (x(1) > box->xmid[1]) childnr += 2; if (box->childs[childnr]) box = box->childs[childnr]; else return box->hopt; } } else { while (1) { int childnr = 0; if (x(0) > box->xmid[0]) childnr += 1; if (x(1) > box->xmid[1]) childnr += 2; if (x(2) > box->xmid[2]) childnr += 4; if (box->childs[childnr]) box = box->childs[childnr]; else return box->hopt; } } } /// minimal h in box (pmin, pmax) double LocalH :: GetMinH (Point<3> pmin, Point<3> pmax) const { Point<3> pmin2, pmax2; for (int j = 0; j < 3; j++) if (pmin(j) < pmax(j)) { pmin2(j) = pmin(j); pmax2(j) = pmax(j); } else { pmin2(j) = pmax(j); pmax2(j) = pmin(j); } return GetMinHRec (pmin2, pmax2, root); } double LocalH :: GetMinHRec (const Point3d & pmin, const Point3d & pmax, const GradingBox * box) const { if (dimension == 2) { double h2 = box->h2; if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 || pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2) return 1e8; double hmin = 2 * box->h2; // box->x2[0] - box->x1[0]; for (int i = 0; i < 8; i++) if (box->childs[i]) hmin = min2 (hmin, GetMinHRec (pmin, pmax, box->childs[i])); return hmin; } else { double h2 = box->h2; if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 || pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2 || pmax.Z() < box->xmid[2]-h2 || pmin.Z() > box->xmid[2]+h2) return 1e8; double hmin = 2 * box->h2; // box->x2[0] - box->x1[0]; for (int i = 0; i < 8; i++) if (box->childs[i]) hmin = min2 (hmin, GetMinHRec (pmin, pmax, box->childs[i])); return hmin; } } void LocalH :: CutBoundaryRec (const Point3d & pmin, const Point3d & pmax, GradingBox * box) { double h2 = box->h2; if (dimension == 2) { if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 || pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2) return; } else { if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 || pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2 || pmax.Z() < box->xmid[2]-h2 || pmin.Z() > box->xmid[2]+h2) return; } box->flags.cutboundary = 1; for (int i = 0; i < 8; i++) if (box->childs[i]) CutBoundaryRec (pmin, pmax, box->childs[i]); } void LocalH :: FindInnerBoxes (AdFront3 * adfront, int (*testinner)(const Point3d & p1)) { static int timer = NgProfiler::CreateTimer ("LocalH::FindInnerBoxes"); NgProfiler::RegionTimer reg (timer); int nf = adfront->GetNF(); for (int i = 0; i < boxes.Size(); i++) boxes[i] -> flags.isinner = 0; root->flags.isinner = 0; Point3d rpmid(root->xmid[0], root->xmid[1], root->xmid[2]); Vec3d rv(root->h2, root->h2, root->h2); Point3d rx2 = rpmid + rv; // Point3d rx1 = rpmid - rv; root->flags.pinner = !adfront->SameSide (rpmid, rx2); if (testinner) (*testout) << "inner = " << root->flags.pinner << " =?= " << testinner(Point3d(root->xmid[0], root->xmid[1], root->xmid[2])) << endl; Array faceinds(nf); Array faceboxes(nf); for (int i = 1; i <= nf; i++) { faceinds.Elem(i) = i; adfront->GetFaceBoundingBox(i, faceboxes.Elem(i)); } for (int i = 0; i < 8; i++) FindInnerBoxesRec2 (root->childs[i], adfront, faceboxes, faceinds, nf); } void LocalH :: FindInnerBoxesRec2 (GradingBox * box, class AdFront3 * adfront, Array & faceboxes, Array & faceinds, int nfinbox) { if (!box) return; GradingBox * father = box -> father; Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); Vec3d v(box->h2, box->h2, box->h2); Box3d boxc(c-v, c+v); Point3d fc(father->xmid[0], father->xmid[1], father->xmid[2]); Vec3d fv(father->h2, father->h2, father->h2); Box3d fboxc(fc-fv, fc+fv); Box3d boxcfc(c,fc); ArrayMem faceused; ArrayMem faceused2; ArrayMem facenotused; /* faceused.SetSize(0); facenotused.SetSize(0); faceused2.SetSize(0); */ for (int j = 1; j <= nfinbox; j++) { // adfront->GetFaceBoundingBox (faceinds.Get(j), facebox); const Box3d & facebox = faceboxes.Get(faceinds.Get(j)); if (boxc.Intersect (facebox)) faceused.Append(faceinds.Get(j)); else facenotused.Append(faceinds.Get(j)); if (boxcfc.Intersect (facebox)) faceused2.Append (faceinds.Get(j)); } for (int j = 1; j <= faceused.Size(); j++) faceinds.Elem(j) = faceused.Get(j); for (int j = 1; j <= facenotused.Size(); j++) faceinds.Elem(j+faceused.Size()) = facenotused.Get(j); if (!father->flags.cutboundary) { box->flags.isinner = father->flags.isinner; box->flags.pinner = father->flags.pinner; } else { Point3d cf(father->xmid[0], father->xmid[1], father->xmid[2]); if (father->flags.isinner) box->flags.pinner = 1; else { if (adfront->SameSide (c, cf, &faceused2)) box->flags.pinner = father->flags.pinner; else box->flags.pinner = 1 - father->flags.pinner; } if (box->flags.cutboundary) box->flags.isinner = 0; else box->flags.isinner = box->flags.pinner; } // cout << "faceused: " << faceused.Size() << ", " << faceused2.Size() << ", " << facenotused.Size() << endl; int nf = faceused.Size(); for (int i = 0; i < 8; i++) FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds, nf); } void LocalH :: FindInnerBoxesRec ( int (*inner)(const Point3d & p), GradingBox * box) { if (box->flags.cutboundary) { for (int i = 0; i < 8; i++) if (box->childs[i]) FindInnerBoxesRec (inner, box->childs[i]); } else { if (inner (box->PMid())) SetInnerBoxesRec (box); } } void LocalH :: FindInnerBoxes (AdFront2 * adfront, int (*testinner)(const Point<2> & p1)) { static int timer = NgProfiler::CreateTimer ("LocalH::FindInnerBoxes 2d"); NgProfiler::RegionTimer reg (timer); for (int i = 0; i < boxes.Size(); i++) boxes[i] -> flags.isinner = 0; root->flags.isinner = 0; Point<2> rpmid(root->xmid[0], root->xmid[1]); // , root->xmid[2]); Vec<2> rv(root->h2, root->h2); Point<2> rx2 = rpmid + rv; // Point<2> rx1 = rpmid - rv; root->flags.pinner = !adfront->SameSide (rpmid, rx2); if (testinner) (*testout) << "inner = " << root->flags.pinner << " =?= " << testinner(rpmid) << endl; int nf = adfront->GetNFL(); Array faceinds(nf); Array > faceboxes(nf); for (int i = 0; i < nf; i++) { faceinds[i] = i; // adfront->GetFaceBoundingBox(i, faceboxes.Elem(i)); const FrontLine & line = adfront->GetLine(i); faceboxes[i].Set (adfront->GetPoint (line.L().I1())); faceboxes[i].Add (adfront->GetPoint (line.L().I2())); } for (int i = 0; i < 8; i++) FindInnerBoxesRec2 (root->childs[i], adfront, faceboxes, faceinds, nf); } void LocalH :: FindInnerBoxesRec2 (GradingBox * box, class AdFront2 * adfront, Array > & faceboxes, Array & faceinds, int nfinbox) { if (!box) return; GradingBox * father = box -> father; Point3d c(box->xmid[0], box->xmid[1], 0); // box->xmid[2]); Vec3d v(box->h2, box->h2, box->h2); Box3d boxc(c-v, c+v); Point3d fc(father->xmid[0], father->xmid[1], 0); // father->xmid[2]); Vec3d fv(father->h2, father->h2, father->h2); Box3d fboxc(fc-fv, fc+fv); Box3d boxcfc(c,fc); ArrayMem faceused; ArrayMem faceused2; ArrayMem facenotused; for (int j = 0; j < nfinbox; j++) { // adfront->GetFaceBoundingBox (faceinds.Get(j), facebox); const Box3d & facebox = faceboxes[faceinds[j]]; if (boxc.Intersect (facebox)) faceused.Append(faceinds[j]); else facenotused.Append(faceinds[j]); if (boxcfc.Intersect (facebox)) faceused2.Append (faceinds[j]); } for (int j = 0; j < faceused.Size(); j++) faceinds[j] = faceused[j]; for (int j = 0; j < facenotused.Size(); j++) faceinds[j+faceused.Size()] = facenotused[j]; if (!father->flags.cutboundary) { box->flags.isinner = father->flags.isinner; box->flags.pinner = father->flags.pinner; } else { Point3d cf(father->xmid[0], father->xmid[1], father->xmid[2]); if (father->flags.isinner) { box->flags.pinner = 1; } else { Point<2> c2d (c.X(), c.Y()); Point<2> cf2d (cf.X(), cf.Y()); bool sameside = adfront->SameSide (c2d, cf2d, &faceused2); if (sameside) box->flags.pinner = father->flags.pinner; else box->flags.pinner = 1 - father->flags.pinner; } if (box->flags.cutboundary) box->flags.isinner = 0; else box->flags.isinner = box->flags.pinner; } // cout << "faceused: " << faceused.Size() << ", " << faceused2.Size() << ", " << facenotused.Size() << endl; int nf = faceused.Size(); for (int i = 0; i < 8; i++) FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds, nf); } void LocalH :: FindInnerBoxesRec ( int (*inner)(const Point<2> & p), GradingBox * box) { if (box->flags.cutboundary) { for (int i = 0; i < 8; i++) if (box->childs[i]) FindInnerBoxesRec (inner, box->childs[i]); } else { Point<2> p2d(box->PMid()(0), box->PMid()(1)); if (inner (p2d)) SetInnerBoxesRec (box); } } void LocalH :: SetInnerBoxesRec (GradingBox * box) { box->flags.isinner = 1; for (int i = 0; i < 8; i++) if (box->childs[i]) ClearFlagsRec (box->childs[i]); } void LocalH :: ClearFlagsRec (GradingBox * box) { box->flags.cutboundary = 0; box->flags.isinner = 0; for (int i = 0; i < 8; i++) if (box->childs[i]) ClearFlagsRec (box->childs[i]); } void LocalH :: WidenRefinement () { for (int i = 0; i < boxes.Size(); i++) { double h = boxes[i]->hopt; Point3d c = boxes[i]->PMid(); for (int i1 = -1; i1 <= 1; i1++) for (int i2 = -1; i2 <= 1; i2++) for (int i3 = -1; i3 <= 1; i3++) SetH (Point3d (c.X() + i1 * h, c.Y() + i2 * h, c.Z() + i3 * h), 1.001 * h); } } void LocalH :: GetInnerPoints (Array > & points) { if (dimension == 2) { for (int i = 0; i < boxes.Size(); i++) if (boxes[i] -> flags.isinner && boxes[i] -> HasChilds()) points.Append ( boxes[i] -> PMid() ); } else { for (int i = 0; i < boxes.Size(); i++) if (boxes[i] -> flags.isinner) points.Append ( boxes[i] -> PMid() ); } } void LocalH :: GetOuterPoints (Array > & points) { for (int i = 0; i < boxes.Size(); i++) if (!boxes[i]->flags.isinner && !boxes[i]->flags.cutboundary) points.Append ( boxes[i] -> PMid()); } void LocalH :: Convexify () { ConvexifyRec (root); } void LocalH :: ConvexifyRec (GradingBox * box) { Point<3> center = box -> PMid(); double size = 2 * box->h2; // box->x2[0] - box->x1[0]; double dx = 0.6 * size; double maxh = box->hopt; for (int i = 0; i < 3; i++) { Point<3> hp = center; hp(i) += dx; maxh = max2 (maxh, GetH(hp)); hp(i) = center(i)-dx; maxh = max2 (maxh, GetH(hp)); } if (maxh < 0.95 * box->hopt) SetH (center, maxh); for (int i = 0; i < 8; i++) if (box->childs[i]) ConvexifyRec (box->childs[i]); } void LocalH :: PrintMemInfo (ostream & ost) const { ost << "LocalH: " << boxes.Size() << " boxes of " << sizeof(GradingBox) << " bytes = " << boxes.Size()*sizeof(GradingBox) << " bytes" << endl; } } netgen-6.2.1905/libsrc/meshing/hprefinement.hpp0000644000175000017500000002022213504650527020104 0ustar kurtkurt#ifndef FILE_HPREFINEMENT #define FILE_HPREFINEMENT /**************************************************************************/ /* File: hprefinement.hh */ /* Author: Joachim Schoeberl */ /* Date: 27. Oct. 2000 */ /**************************************************************************/ /* HP Refinement */ enum HPREF_ELEMENT_TYPE { HP_NONE=0, HP_SEGM = 1, HP_SEGM_SINGCORNERL, HP_SEGM_SINGCORNERR, HP_SEGM_SINGCORNERS, HP_TRIG = 10, HP_TRIG_SINGCORNER, HP_TRIG_SINGCORNER12, HP_TRIG_SINGCORNER123, HP_TRIG_SINGCORNER123_2D, // not rotational symmetric HP_TRIG_SINGEDGE = 20, HP_TRIG_SINGEDGECORNER1, // E = 100, V = 100 HP_TRIG_SINGEDGECORNER2, // E = 100, V = 010 HP_TRIG_SINGEDGECORNER12, // E = 100, V = 110 HP_TRIG_SINGEDGECORNER3, HP_TRIG_SINGEDGECORNER13, HP_TRIG_SINGEDGECORNER23, HP_TRIG_SINGEDGECORNER123, HP_TRIG_SINGEDGES = 30, HP_TRIG_SINGEDGES2, HP_TRIG_SINGEDGES3, HP_TRIG_SINGEDGES23, HP_TRIG_3SINGEDGES = 40, HP_QUAD = 50, HP_QUAD_SINGCORNER, HP_DUMMY_QUAD_SINGCORNER, HP_QUAD_SINGEDGE, HP_QUAD_0E_2VA, // V = 1100 HP_QUAD_0E_2VB, // V = 1010 HP_QUAD_0E_3V, HP_QUAD_0E_4V, // one edge: marked edge is always edge from vertex 1 to vertex 2 (E = 1000) HP_QUAD_1E_1VA, // vertex on beginning of edge: V = 1000 HP_QUAD_1E_1VB, // vertex on end of edge: V = 0100 HP_QUAD_1E_1VC, // V = 0010 HP_QUAD_1E_1VD, // V = 0001 HP_QUAD_1E_2VA, // V = 1100 HP_QUAD_1E_2VB, // V = 1010 HP_QUAD_1E_2VC, // V = 1001 HP_QUAD_1E_2VD, // V = 0110 HP_QUAD_1E_2VE, // V = 0101 HP_QUAD_1E_2VF, // V = 0011 HP_QUAD_1E_3VA, // V = 1110 HP_QUAD_1E_3VB, // V = 1101 HP_QUAD_1E_3VC, // V = 1011 HP_QUAD_1E_3VD, // V = 0111 HP_QUAD_1E_4V, // V = 1111 HP_QUAD_2E, // E = 1001, V = 1000 HP_QUAD_2E_1VA, // E = 1001, V = 1100 HP_QUAD_2E_1VB, // E = 1001, V = 1010 HP_QUAD_2E_1VC, // E = 1001, V = 1001 HP_QUAD_2E_2VA, // E = 1001, V = 1110 HP_QUAD_2E_2VB, // E = 1001, V = 1101 HP_QUAD_2E_2VC, // E = 1001, V = 1011 HP_QUAD_2E_3V, // E = 1001, V = 1111 HP_QUAD_2EB_0V, // E = 1010, V = 0000 HP_QUAD_2EB_1VA, // E = 1010, V = 1000 HP_QUAD_2EB_1VB, // E = 1010, V = 0100 HP_QUAD_2EB_2VA, // E = 1010, V = 1100 HP_QUAD_2EB_2VB, // E = 1010, V = 1010 HP_QUAD_2EB_2VC, // E = 1010, V = 1001 HP_QUAD_2EB_2VD, // E = 1010, V = 0101 HP_QUAD_2EB_3VA, // E = 1010, V = 1110 HP_QUAD_2EB_3VB, // E = 1010, V = 1101 HP_QUAD_2EB_4V, HP_QUAD_3E, // E = 1101, V = 1100 HP_QUAD_3E_3VA, // E = 1101, V = 1110 HP_QUAD_3E_3VB, // E = 1101, V = 1101 HP_QUAD_3E_4V, // E = 1101, V = 1111 HP_QUAD_4E, HP_TET = 100, // no singular vertex/edge HP_TET_0E_1V, // V1 HP_TET_0E_2V, // V1,2 HP_TET_0E_3V, // V1,2,3 HP_TET_0E_4V, // V1,2,3,4 HP_TET_1E_0V = 200, // E1-2 HP_TET_1E_1VA, // V1 HP_TET_1E_1VB, // V3 HP_TET_1E_2VA, // V1,2 HP_TET_1E_2VB, // V1,3 HP_TET_1E_2VC, // V1,4 HP_TET_1E_2VD, // V3,4 HP_TET_1E_3VA, // V1,2,3 HP_TET_1E_3VB, // V1,3,4 HP_TET_1E_4V, // V1,2,3,4 // 2 connected edges, additionally marked Vs HP_TET_2EA_0V = 220, // E1-2, E1-3 HP_TET_2EA_1VA, // V2 HP_TET_2EA_1VB, // V3 HP_TET_2EA_1VC, // V4 HP_TET_2EA_2VA, // V2,3 HP_TET_2EA_2VB, // V2,4 HP_TET_2EA_2VC, // V3,4 HP_TET_2EA_3V, // V2,3,4 // 2 opposite edges HP_TET_2EB_0V = 230, // E1-2, E3-4 HP_TET_2EB_1V, // V1 HP_TET_2EB_2VA, // V1,2 HP_TET_2EB_2VB, // V1,3 HP_TET_2EB_2VC, // V1,4 HP_TET_2EB_3V, // V1,2,3 HP_TET_2EB_4V, // V1,2,3,4 HP_TET_3EA_0V = 400, // E1-2, E1-3, E1-4, 3 edges connected HP_TET_3EA_1V, // V2 HP_TET_3EA_2V, // V2,3 HP_TET_3EA_3V, // V2,3,4 HP_TET_3EB_0V = 420, // E1-2, E1-4, E2-3 3 edges chain HP_TET_3EB_1V, // HP_TET_3EB_2V, // HP_TET_3EC_0V = 430, // 3 edges chain, alter HP_TET_3EC_1V, // 3 edges chain, alter HP_TET_3EC_2V, // 3 edges chain, alter HP_TET_1F_0E_0V = 500, // 1 singular face HP_TET_1F_0E_1VA, // 1 sing vertex in face (V2) HP_TET_1F_0E_1VB, // 1 sing vertex not in face (V1) HP_TET_1F_1EA_0V, // 1 sing edge not in face HP_TET_1F_1EB_0V, // 1 sing edge in face HP_TET_2F_0E_0V = 600, // 2 singular faces HP_PRISM = 1000, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE_V12, HP_PRISM_SINGEDGE_H1, HP_PRISM_SINGEDGE_H12, HP_PRISM_1FA_0E_0V, // 1 singular trig face HP_PRISM_2FA_0E_0V, // 2 singular trig faces HP_PRISM_1FB_0E_0V, // 1 singular quad face 1-2-4-5 HP_PRISM_1FB_1EA_0V, // 1 singular quad face, edge is 1-2 HP_PRISM_1FA_1E_0V, HP_PRISM_2FA_1E_0V, HP_PRISM_1FA_1FB_0E_0V, HP_PRISM_2FA_1FB_0E_0V, HP_PRISM_1FA_1FB_1EA_0V, HP_PRISM_1FA_1FB_1EB_0V, HP_PRISM_2FA_1FB_1EA_0V, HP_PRISM_1FB_1EC_0V, HP_PRISM_1FA_1FB_1EC_0V, HP_PRISM_2FA_1FB_1EC_0V, HP_PRISM_1FB_2EA_0V, HP_PRISM_1FA_1FB_2EA_0V, HP_PRISM_2FA_1FB_2EA_0V, HP_PRISM_1FB_2EB_0V, HP_PRISM_1FA_1FB_2EB_0V, HP_PRISM_1FA_1FB_2EC_0V, HP_PRISM_2FA_1FB_2EB_0V, HP_PRISM_1FB_3E_0V, HP_PRISM_1FA_1FB_3E_0V, HP_PRISM_2FA_1FB_3E_0V, HP_PRISM_2FB_0E_0V, HP_PRISM_1FA_2FB_0E_0V, HP_PRISM_2FA_2FB_0E_0V, HP_PRISM_2FB_1EC_0V, HP_PRISM_1FA_2FB_1EC_0V, HP_PRISM_1FA_2FB_1EB_0V, HP_PRISM_2FA_2FB_1EC_0V, HP_PRISM_2FB_3E_0V, HP_PRISM_1FA_2FB_3E_0V, HP_PRISM_2FA_2FB_3E_0V, HP_PRISM_1FA_2E_0V, HP_PRISM_2FA_2E_0V, HP_PRISM_3E_0V, HP_PRISM_1FA_3E_0V, HP_PRISM_2FA_3E_0V, HP_PRISM_3FB_0V, HP_PRISM_1FA_3FB_0V, HP_PRISM_2FA_3FB_0V, HP_PRISM_3E_4EH, /* HP_PRISM_1FB_1EA_0V, // 1 singular quad face, edge is 1-4 HP_PRISM_1FB_1EB_0V, // 1 singular quad face, edge is 2-5 HP_PRISM_2F_0E_0V, // 2 singular quad faces */ HP_PYRAMID = 2000, HP_PYRAMID_0E_1V, HP_PYRAMID_EDGES, HP_PYRAMID_1FB_0E_1VA, // 1 trig face, top vertex HP_HEX = 3000, HP_HEX_0E_1V, HP_HEX_1E_1V, HP_HEX_1E_0V, HP_HEX_3E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V }; struct HPRef_Struct { HPREF_ELEMENT_TYPE geom; int (*splitedges)[3]; int (*splitfaces)[4]; int (*splitelements)[5]; HPREF_ELEMENT_TYPE * neweltypes; int (*newels)[8]; }; class HPRefElement { private: void Reset(void); public: HPRefElement (); HPRefElement(Element & el); HPRefElement(Element2d & el); HPRefElement(Segment & el); HPRefElement(HPRefElement & el); void SetType( HPREF_ELEMENT_TYPE t); // HPRefElement(HPRefElement & el, HPREF_ELEMENT_TYPE t); /* HPRefElement(HPRefElement & el, HPREF_ELEMENT_TYPE t) { type = t; HPRef_Struct * hprs = Get_HPRef_Struct(t); for (int i=0; igeom) { case HP_SEGM: np=2; sing_edge_left=0; sing_edge_right=0; break; case HP_QUAD: np=4; break; case HP_TRIG: np=3; break; case HP_HEX: np=8; break; case HP_PRISM: np=6; break; case HP_TET: np=4; break; case HP_PYRAMID: np=5; break; } index = el.index; levelx = el.levelx; levely = el.levely; levelz = el.levelz; type = el.type; coarse_elnr = el.coarse_elnr; singedge_left = el.singedge_left; singedge_right = el.singedge_left; } */ HPREF_ELEMENT_TYPE type; PointIndex pnums[8]; double param[8][3]; int index; int levelx; int levely; int levelz; int np; int coarse_elnr; int domin, domout; // he: needed for segment!! in 3d there should be surf1, surf2!! // int coarse_hpelnr; PointIndex & operator[](int i) { return(pnums[i]);} PointIndex & PNumMod(int i) { return pnums[(i-1) % np]; }; PointIndex & PNum(int i) {return pnums[(i-1)]; }; int GetIndex () const { return index; }; double singedge_left, singedge_right; // EdgePointGeomInfo epgeominfo[2]; }; DLL_HEADER extern void HPRefinement (Mesh & mesh, Refinement * ref, int levels, double fac1=0.125, bool setorders=true, bool ref_level = false); #endif netgen-6.2.1905/libsrc/meshing/boundarylayer.cpp0000644000175000017500000006135513504650527020307 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { void InsertVirtualBoundaryLayer (Mesh & mesh) { cout << "Insert virt. b.l." << endl; int surfid; cout << "Boundary Nr:"; cin >> surfid; int i; int np = mesh.GetNP(); cout << "Old NP: " << mesh.GetNP() << endl; cout << "Trigs: " << mesh.GetNSE() << endl; BitArray bndnodes(np); Array mapto(np); bndnodes.Clear(); for (i = 1; i <= mesh.GetNSeg(); i++) { int snr = mesh.LineSegment(i).edgenr; cout << "snr = " << snr << endl; if (snr == surfid) { bndnodes.Set (mesh.LineSegment(i)[0]); bndnodes.Set (mesh.LineSegment(i)[1]); } } for (i = 1; i <= mesh.GetNSeg(); i++) { int snr = mesh.LineSegment(i).edgenr; if (snr != surfid) { bndnodes.Clear (mesh.LineSegment(i)[0]); bndnodes.Clear (mesh.LineSegment(i)[1]); } } for (i = 1; i <= np; i++) { if (bndnodes.Test(i)) mapto.Elem(i) = mesh.AddPoint (mesh.Point (i)); else mapto.Elem(i) = 0; } for (i = 1; i <= mesh.GetNSE(); i++) { Element2d & el = mesh.SurfaceElement(i); for (int j = 1; j <= el.GetNP(); j++) if (mapto.Get(el.PNum(j))) el.PNum(j) = mapto.Get(el.PNum(j)); } int nq = 0; for (i = 1; i <= mesh.GetNSeg(); i++) { int snr = mesh.LineSegment(i).edgenr; if (snr == surfid) { int p1 = mesh.LineSegment(i)[0]; int p2 = mesh.LineSegment(i)[1]; int p3 = mapto.Get (p1); if (!p3) p3 = p1; int p4 = mapto.Get (p2); if (!p4) p4 = p2; Element2d el(QUAD); el.PNum(1) = p1; el.PNum(2) = p2; el.PNum(3) = p3; el.PNum(4) = p4; el.SetIndex (2); mesh.AddSurfaceElement (el); nq++; } } cout << "New NP: " << mesh.GetNP() << endl; cout << "Quads: " << nq << endl; } /* Philippose Rajan - 11 June 2009 Function to calculate the surface normal at a given vertex of a surface element, with respect to that surface element. This function is used by the boundary layer generation function, in order to calculate the effective direction in which the prismatic layer should grow */ void GetSurfaceNormal(Mesh & mesh, const Element2d & el, int Vertex, Vec3d & SurfaceNormal) { int Vertex_A; int Vertex_B; Vertex_A = Vertex + 1; if(Vertex_A > el.GetNP()) Vertex_A = 1; Vertex_B = Vertex - 1; if(Vertex_B <= 0) Vertex_B = el.GetNP(); Vec3d Vect_A,Vect_B; Vect_A = mesh[el.PNum(Vertex_A)] - mesh[el.PNum(Vertex)]; Vect_B = mesh[el.PNum(Vertex_B)] - mesh[el.PNum(Vertex)]; SurfaceNormal = Cross(Vect_A,Vect_B); SurfaceNormal.Normalize(); } /* Philippose Rajan - 11 June 2009 Added an initial experimental function for generating prismatic boundary layers on a given set of surfaces. The number of layers, height of the first layer and the growth / shrink factor can be specified by the user Currently, the layer height is calculated using: height = h_first_layer * (growth_factor^(num_layers - 1)) */ void GenerateBoundaryLayer (Mesh & mesh, BoundaryLayerParameters & blp) { ofstream dbg("BndLayerDebug.log"); // Angle between a surface element and a growth-vector below which // a prism is project onto that surface as a quad // (in degrees) double angleThreshold = 5.0; Array surfid (blp.surfid); int prismlayers = blp.prismlayers; double hfirst = blp.hfirst; double growthfactor = blp.growthfactor; Array heights (blp.heights); bool grow_edges = false; // grow layer at edges // Monitor and print out the number of prism and quad elements // added to the mesh int numprisms = 0; int numquads = 0; cout << "Old NP: " << mesh.GetNP() << endl; cout << "Old NSE: " << mesh.GetNSE() << endl; for(int layer = prismlayers; layer >= 1; layer--) { cout << "Generating layer: " << layer << endl; const MeshTopology& meshtopo = mesh.GetTopology(); const_cast (meshtopo).SetBuildEdges(true); const_cast (meshtopo).SetBuildFaces(true); const_cast (meshtopo).Update(); double layerht = hfirst; if(heights.Size()>0) { layerht = heights[layer-1]; } else { if(growthfactor == 1) { layerht = layer * hfirst; } else { layerht = hfirst*(pow(growthfactor,(layer+1)) - 1)/(growthfactor - 1); } } cout << "Layer Height = " << layerht << endl; // Need to store the old number of points and // surface elements because there are new points and // surface elements being added during the process int np = mesh.GetNP(); int nse = mesh.GetNSE(); int ne = mesh.GetNE(); // Safety measure to ensure no issues with mesh // consistency int nseg = mesh.GetNSeg(); // Indicate which points need to be remapped BitArray bndnodes(np+1); // big enough for 1-based array // Map of the old points to the new points Array mapto(np); // Growth vectors for the prismatic layer based on // the effective surface normal at a given point Array growthvectors(np); // Bit array to identify all the points belonging // to the surface of interest bndnodes.Clear(); // Run through all the surface elements and mark the points // belonging to those where a boundary layer has to be created. // In addition, also calculate the effective surface normal // vectors at each of those points to determine the mesh motion // direction cout << "Marking points for remapping...." << endl; for (SurfaceElementIndex si = 0; si < nse; si++) if (surfid.Contains(mesh[si].GetIndex())) { const Element2d & sel = mesh[si]; for(int j = 0; j < sel.GetNP(); j++) { // Set the bitarray to indicate that the // point is part of the required set bndnodes.Set(sel[j]); Vec3d surfacenormal; // Calculate the surface normal at the current point // with respect to the current surface element GetSurfaceNormal(mesh,sel,j+1,surfacenormal); // Add the surface normal to the already existent one // (This gives the effective normal direction at corners // and curved areas) growthvectors[sel[j]] += surfacenormal; } } if (!grow_edges) for (SegmentIndex sei = 0; sei <= nseg; sei++) { bndnodes.Clear (mesh[sei][0]); bndnodes.Clear (mesh[sei][1]); } // Add additional points into the mesh structure in order to // clone the surface elements. // Also invert the growth vectors so that they point inwards, // and normalize them cout << "Cloning points and calculating growth vectors...." << endl; for (PointIndex pi = 1; pi <= np; pi++) { if (bndnodes.Test(pi)) { mapto[pi] = mesh.AddPoint (mesh[pi]); growthvectors[pi].Normalize(); growthvectors[pi] *= -1.0; } else { mapto[pi] = 0; growthvectors[pi] = Vec3d(0,0,0); } } // Add quad surface elements at edges for surfaces which // don't have boundary layers // Bit array to keep track of segments already processed BitArray segsel(nseg); // Set them all to "1" to initially activate all segments segsel.Set(); cout << "Adding 2D Quad elements on required surfaces...." << endl; if (grow_edges) for (SegmentIndex sei = 0; sei <= nseg; sei++) { PointIndex seg_p1 = mesh[sei][0]; PointIndex seg_p2 = mesh[sei][1]; // Only go in if the segment is still active, and if both its // surface index is part of the "hit-list" if(segsel.Test(sei) && surfid.Contains(mesh[sei].si)) { // clear the bit to indicate that this segment has been processed segsel.Clear(sei); // Find matching segment pair on other surface for (SegmentIndex sej = 0; sej < nseg; sej++) { PointIndex segpair_p1 = mesh[sej][1]; PointIndex segpair_p2 = mesh[sej][0]; // Find the segment pair on the neighbouring surface element // Identified by: seg1[0] = seg_pair[1] and seg1[1] = seg_pair[0] if(segsel.Test(sej) && ((segpair_p1 == seg_p1) && (segpair_p2 == seg_p2))) { // clear bit to indicate that processing of this segment is done segsel.Clear(sej); // Only worry about those surfaces which are not in the // boundary layer list if(!surfid.Contains(mesh[sej].si)) { SurfaceElementIndex pnt_commelem = 0; Array pnt1_elems; Array pnt2_elems; meshtopo.GetVertexSurfaceElements(segpair_p1,pnt1_elems); meshtopo.GetVertexSurfaceElements(segpair_p2,pnt2_elems); for(int k = 0; k < pnt1_elems.Size(); k++) { const Element2d & pnt1_sel = mesh.SurfaceElement(pnt1_elems[k]); for(int l = 0; l < pnt2_elems.Size(); l++) { const Element2d & pnt2_sel = mesh.SurfaceElement(pnt2_elems[l]); if((pnt1_sel.GetIndex() == mesh[sej].si) && (pnt2_sel.GetIndex() == mesh[sej].si) && (pnt1_elems[k] == pnt2_elems[l])) { pnt_commelem = pnt1_elems[k]; } } } /* int pnum_commelem = 0; for(int k = 1; k <= mesh.SurfaceElement(pnt_commelem).GetNP(); k++) { if((mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p1) && (mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p2)) { pnum_commelem = mesh.SurfaceElement(pnt_commelem).PNum(k); } } */ Vec3d surfelem_vect, surfelem_vect1; const Element2d & commsel = mesh.SurfaceElement(pnt_commelem); dbg << "NP= " << commsel.GetNP() << " : "; for(int k = 1; k <= commsel.GetNP(); k++) { GetSurfaceNormal(mesh,commsel,k,surfelem_vect1); surfelem_vect += surfelem_vect1; } surfelem_vect.Normalize(); double surfangle = Angle(growthvectors.Elem(segpair_p1),surfelem_vect); dbg << "V1= " << surfelem_vect1 << " : V2= " << surfelem_vect1 << " : V= " << surfelem_vect << " : GV= " << growthvectors.Elem(segpair_p1) << " : Angle= " << surfangle * 180 / 3.141592; // remap the segments to the new points mesh[sei][0] = mapto[seg_p1]; mesh[sei][1] = mapto[seg_p2]; mesh[sej][1] = mapto[seg_p1]; mesh[sej][0] = mapto[seg_p2]; if((surfangle < (90 + angleThreshold) * 3.141592 / 180.0) && (surfangle > (90 - angleThreshold) * 3.141592 / 180.0)) { dbg << " : quad\n"; // Since the surface is lower than the threshold, change the effective // prism growth vector to match with the surface vector, so that // the Quad which is created lies on the original surface //growthvectors.Elem(segpair_p1) = surfelem_vect; // Add a quad element to account for the prism volume // element which is going to be added Element2d sel(QUAD); sel.PNum(4) = mapto[seg_p1]; sel.PNum(3) = mapto[seg_p2]; sel.PNum(2) = segpair_p2; sel.PNum(1) = segpair_p1; sel.SetIndex(mesh[sej].si); mesh.AddSurfaceElement(sel); numquads++; } else { dbg << "\n"; for (int k = 0; k < pnt1_elems.Size(); k++) { Element2d & pnt_sel = mesh.SurfaceElement(pnt1_elems[k]); if(pnt_sel.GetIndex() == mesh[sej].si) { for(int l = 0; l < pnt_sel.GetNP(); l++) { if(pnt_sel[l] == segpair_p1) pnt_sel[l] = mapto[seg_p1]; else if (pnt_sel[l] == segpair_p2) pnt_sel[l] = mapto[seg_p2]; } } } for (int k = 0; k < pnt2_elems.Size(); k++) { Element2d & pnt_sel = mesh.SurfaceElement(pnt2_elems[k]); if(pnt_sel.GetIndex() == mesh[sej].si) { for(int l = 0; l < pnt_sel.GetNP(); l++) { if(pnt_sel[l] == segpair_p1) pnt_sel[l] = mapto.Get(seg_p1); else if (pnt_sel[l] == segpair_p2) pnt_sel[l] = mapto.Get(seg_p2); } } } } // } } else { // If the code comes here, it indicates that we are at // a line segment pair which is at the intersection // of two surfaces, both of which have to grow boundary // layers.... here too, remapping the segments to the // new points is required mesh[sei][0] = mapto.Get(seg_p1); mesh[sei][1] = mapto.Get(seg_p2); mesh[sej][1] = mapto.Get(seg_p1); mesh[sej][0] = mapto.Get(seg_p2); } } } } } // Add prismatic cells at the boundaries cout << "Generating prism boundary layer volume elements...." << endl; for (SurfaceElementIndex si = 0; si < nse; si++) { Element2d & sel = mesh.SurfaceElement(si); if(surfid.Contains(sel.GetIndex())) { /* Element el(PRISM); for (int j = 0; j < sel.GetNP(); j++) { // Check (Doublecheck) if the corresponding point has a // copy available for remapping if (mapto.Get(sel[j])) { // Define the points of the newly added Prism cell el[j+3] = mapto[sel[j]]; el[j] = sel[j]; } else { el[j+3] = sel[j]; el[j] = sel[j]; } } el.SetIndex(1); el.Invert(); mesh.AddVolumeElement(el); numprisms++; */ // cout << "add element: " << endl; int classify = 0; for (int j = 0; j < 3; j++) if (mapto[sel[j]]) classify += (1 << j); // cout << "classify = " << classify << endl; ELEMENT_TYPE types[] = { PRISM, TET, TET, PYRAMID, TET, PYRAMID, PYRAMID, PRISM }; int nums[] = { sel[0], sel[1], sel[2], mapto[sel[0]], mapto[sel[1]], mapto[sel[2]] }; int vertices[][6] = { { 0, 1, 2, 0, 1, 2 }, // should not occur { 0, 2, 1, 3, 0, 0 }, { 0, 2, 1, 4, 0, 0 }, { 0, 1, 4, 3, 2, 0 }, { 0, 2, 1, 5, 0, 0 }, { 2, 0, 3, 5, 1, 0 }, { 1, 2, 5, 4, 0, 0 }, { 0, 2, 1, 3, 5, 4 } }; Element el(types[classify]); for (int i = 0; i < 6; i++) el[i] = nums[vertices[classify][i]]; if(blp.new_matnrs.Size() > 0) el.SetIndex(blp.new_matnrs[layer-1]); else el.SetIndex(blp.new_matnr); // cout << "el = " << el << endl; if (classify != 0) mesh.AddVolumeElement(el); } } // Finally switch the point indices of the surface elements // to the newly added ones cout << "Transferring boundary layer surface elements to new vertex references...." << endl; for (int i = 1; i <= nse; i++) { Element2d & sel = mesh.SurfaceElement(i); if(surfid.Contains(sel.GetIndex())) { for (int j = 1; j <= sel.GetNP(); j++) { // Check (Doublecheck) if the corresponding point has a // copy available for remapping if (mapto.Get(sel.PNum(j))) { // Map the surface elements to the new points sel.PNum(j) = mapto.Get(sel.PNum(j)); } } } } for (int i = 1; i <= ne; i++) { Element & el = mesh.VolumeElement(i); if(el.GetIndex() != blp.bulk_matnr) { for (int j = 1; j <= el.GetNP(); j++) { // Check (Doublecheck) if the corresponding point has a // copy available for remapping if (mapto.Get(el.PNum(j))) { // Map the surface elements to the new points el.PNum(j) = mapto.Get(el.PNum(j)); } } } } // Lock all the prism points so that the rest of the mesh can be // optimised without invalidating the entire mesh for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) { if(bndnodes.Test(pi)) mesh.AddLockedPoint(pi); } // Now, actually pull back the old surface points to create // the actual boundary layers cout << "Moving and optimising boundary layer points...." << endl; for (int i = 1; i <= np; i++) { Array vertelems; if(bndnodes.Test(i)) { MeshPoint pointtomove; pointtomove = mesh.Point(i); if(layer == prismlayers) { mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i)); meshtopo.GetVertexElements(i,vertelems); for(int j = 1; j <= vertelems.Size(); j++) { // double sfact = 0.9; Element volel = mesh.VolumeElement(vertelems.Elem(j)); if(((volel.GetType() == TET) || (volel.GetType() == TET10)) && (!volel.IsDeleted())) { //while((volel.Volume(mesh.Points()) <= 0.0) && (sfact >= 0.0)) //{ // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // mesh.ImproveMesh(); // // Try to move the point back by one step but // // if the volume drops to below zero, double back // mesh.Point(i).SetPoint(pointtomove + ((sfact + 0.1) * layerht * growthvectors.Elem(i))); // if(volel.Volume(mesh.Points()) <= 0.0) // { // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // } // sfact -= 0.1; //} volel.Delete(); } } } else { mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i)); } } } mesh.Compress(); } // Optimise the tet part of the volume mesh after all the modifications // to the system are completed //OptimizeVolume(mparam,mesh); cout << "New NP: " << mesh.GetNP() << endl; cout << "Num of Quads: " << numquads << endl; cout << "Num of Prisms: " << numprisms << endl; cout << "Boundary Layer Generation....Done!" << endl; dbg.close(); } } netgen-6.2.1905/libsrc/meshing/boundarylayer.hpp0000644000175000017500000000112013504650527020274 0ustar kurtkurt#ifndef FILE_BOUNDARYLAYER #define FILE_BOUNDARYLAYER /// DLL_HEADER extern void InsertVirtualBoundaryLayer (Mesh & mesh); /// Create a typical prismatic boundary layer on the given /// surfaces class BoundaryLayerParameters { public: // parameters by Philippose .. Array surfid; Array heights; Array new_matnrs; int prismlayers = 1; int bulk_matnr = 1; int new_matnr = 1; double hfirst = 0.01; double growthfactor = 1; bool optimize = true; }; DLL_HEADER extern void GenerateBoundaryLayer (Mesh & mesh, BoundaryLayerParameters & blp); #endif netgen-6.2.1905/libsrc/meshing/validate.cpp0000644000175000017500000003465613504650527017224 0ustar kurtkurt #include #include "meshing.hpp" namespace netgen { void GetPureBadness(Mesh & mesh, Array & pure_badness, const BitArray & isnewpoint) { //const int ne = mesh.GetNE(); const int np = mesh.GetNP(); pure_badness.SetSize(np+PointIndex::BASE+1); pure_badness = -1; Array< Point<3>* > backup(np); for(int i=0; i(mesh.Point(i+1)); if(isnewpoint.Test(i+PointIndex::BASE) && mesh.mlbetweennodes[i+PointIndex::BASE][0] > 0) { mesh.Point(i+1) = Center(mesh.Point(mesh.mlbetweennodes[i+PointIndex::BASE][0]), mesh.Point(mesh.mlbetweennodes[i+PointIndex::BASE][1])); } } for (ElementIndex i = 0; i < mesh.GetNE(); i++) { double bad = mesh[i].CalcJacobianBadness (mesh.Points()); for(int j=0; j pure_badness[mesh[i][j]]) pure_badness[mesh[i][j]] = bad; // save maximum if(bad > pure_badness.Last()) pure_badness.Last() = bad; } for(int i=0; i & bad_elements, const Array & pure_badness, double max_worsening, const bool uselocalworsening, Array * quality_loss) { PrintMessage(3,"!!!! Validating !!!!"); //if(max_worsening > 0) // (*testout) << "badness " << counter++ << endl; bad_elements.SetSize(0); double loc_pure_badness = -1; if(!uselocalworsening) loc_pure_badness = pure_badness.Last(); // maximum is saved at last position double worsening = -1; ElementIndex ind; if(quality_loss != NULL) quality_loss->SetSize(mesh.GetNE()); for (ElementIndex i = 0; i < mesh.GetNE(); i++) { if(uselocalworsening) { loc_pure_badness = -1; for(int j=0; j loc_pure_badness) loc_pure_badness = pure_badness[mesh[i][j]]; } double bad = mesh[i].CalcJacobianBadness (mesh.Points()); if (bad > 1e10 || (max_worsening > 0 && bad > loc_pure_badness*max_worsening)) bad_elements.Append(i); if(max_worsening > 0) { double actw = bad/loc_pure_badness; if(quality_loss != NULL) (*quality_loss)[i] = actw; if(actw > worsening) { worsening = actw; ind = i; } } } return worsening; } void GetWorkingArea(BitArray & working_elements, BitArray & working_points, const Mesh & mesh, const Array & bad_elements, const int width) { working_elements.Clear(); working_points.Clear(); for(int i=0; i & bad_elements, const BitArray & isnewpoint, const Refinement & refinement, const Array & pure_badness, double max_worsening, const bool uselocalworsening, const Array< Array* > & idmaps) { ostringstream ostrstr; const int maxtrials = 100; //bool doit; //cout << "DOIT: " << flush; //cin >> doit; int ne = mesh.GetNE(); int np = mesh.GetNP(); int numbadneighbours = 3; const int numtopimprove = 3; PrintMessage(1,"repairing"); PushStatus("Repair Bisection"); Array* > should(np); Array* > can(np); Array* > nv(np); for(int i=0; i; should[i] = new Point<3>; can[i] = new Point<3>; } BitArray isboundarypoint(np),isedgepoint(np); isboundarypoint.Clear(); isedgepoint.Clear(); for(int i = 1; i <= mesh.GetNSeg(); i++) { const Segment & seg = mesh.LineSegment(i); isedgepoint.Set(seg[0]); isedgepoint.Set(seg[1]); } Array surfaceindex(np); surfaceindex = -1; for (int i = 1; i <= mesh.GetNSE(); i++) { const Element2d & sel = mesh.SurfaceElement(i); for (int j = 1; j <= sel.GetNP(); j++) if(!isedgepoint.Test(sel.PNum(j))) { isboundarypoint.Set(sel.PNum(j)); surfaceindex[sel.PNum(j) - PointIndex::BASE] = mesh.GetFaceDescriptor(sel.GetIndex()).SurfNr(); } } Validate(mesh,bad_elements,pure_badness, ((uselocalworsening) ? (0.8*(max_worsening-1.) + 1.) : (0.1*(max_worsening-1.) + 1.)), uselocalworsening); // -> larger working area BitArray working_elements(ne); BitArray working_points(np); GetWorkingArea(working_elements,working_points,mesh,bad_elements,numbadneighbours); //working_elements.Set(); //working_points.Set(); ostrstr.str(""); ostrstr << "worsening: " << Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); PrintMessage(4,ostrstr.str()); int auxnum=0; for(int i=1; i<=np; i++) if(working_points.Test(i)) auxnum++; ostrstr.str(""); ostrstr << "Percentage working points: " << 100.*double(auxnum)/np; PrintMessage(5,ostrstr.str()); BitArray isworkingboundary(np); for(int i=1; i<=np; i++) if(working_points.Test(i) && isboundarypoint.Test(i)) isworkingboundary.Set(i); else isworkingboundary.Clear(i); for(int i=0; i 0) *can[i] = Center(*can[mesh.mlbetweennodes[i+PointIndex::BASE][0]-PointIndex::BASE], *can[mesh.mlbetweennodes[i+PointIndex::BASE][1]-PointIndex::BASE]); else *can[i] = mesh.Point(i+1); } int cnttrials = 1; double lamedge = 0.5; double lamface = 0.5; double facokedge = 0; double facokface = 0; double factryedge; double factryface = 0; double oldlamedge,oldlamface; MeshOptimize2d * optimizer2d = refinement.Get2dOptimizer(); if(!optimizer2d) { cerr << "No 2D Optimizer!" << endl; return; } while ((facokedge < 1.-1e-8 || facokface < 1.-1e-8) && cnttrials < maxtrials && multithread.terminate != 1) { (*testout) << " facokedge " << facokedge << " facokface " << facokface << " cnttrials " << cnttrials << endl << " perc. " << 95. * max2( min2(facokedge,facokface), double(cnttrials)/double(maxtrials)) << endl; SetThreadPercent(95. * max2( min2(facokedge,facokface), double(cnttrials)/double(maxtrials))); ostrstr.str(""); ostrstr << "max. worsening " << max_worsening; PrintMessage(5,ostrstr.str()); oldlamedge = lamedge; lamedge *= 6; if (lamedge > 2) lamedge = 2; if(1==1 || facokedge < 1.-1e-8) { for(int i=0; i(0,0,0); for (int i = 1; i <= mesh.GetNSE(); i++) { const Element2d & sel = mesh.SurfaceElement(i); Vec<3> auxvec = Cross(mesh.Point(sel.PNum(2))-mesh.Point(sel.PNum(1)), mesh.Point(sel.PNum(3))-mesh.Point(sel.PNum(1))); auxvec.Normalize(); for (int j = 1; j <= sel.GetNP(); j++) if(!isedgepoint.Test(sel.PNum(j))) *nv[sel.PNum(j) - PointIndex::BASE] += auxvec; } for(int i=0; iNormalize(); do // move edges { lamedge *= 0.5; cnttrials++; if(cnttrials % 10 == 0) max_worsening *= 1.1; factryedge = lamedge + (1.-lamedge) * facokedge; ostrstr.str(""); ostrstr << "lamedge = " << lamedge << ", trying: " << factryedge; PrintMessage(5,ostrstr.str()); for (int i = 1; i <= np; i++) { if (isedgepoint.Test(i)) { for (int j = 0; j < 3; j++) mesh.Point(i)(j) = lamedge * (*should.Get(i))(j) + (1.-lamedge) * (*can.Get(i))(j); } else mesh.Point(i) = *can.Get(i); } if(facokedge < 1.-1e-8) { ostrstr.str(""); ostrstr << "worsening: " << Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); PrintMessage(5,ostrstr.str()); } else Validate(mesh,bad_elements,pure_badness,-1,uselocalworsening); ostrstr.str(""); ostrstr << bad_elements.Size() << " bad elements"; PrintMessage(5,ostrstr.str()); } while (bad_elements.Size() > 0 && cnttrials < maxtrials && multithread.terminate != 1); } if(cnttrials < maxtrials && multithread.terminate != 1) { facokedge = factryedge; // smooth faces mesh.CalcSurfacesOfNode(); MeshingParameters dummymp; mesh.ImproveMeshJacobianOnSurface(dummymp,isworkingboundary,nv,OPT_QUALITY, &idmaps); for (int i = 1; i <= np; i++) *can.Elem(i) = mesh.Point(i); if(optimizer2d) optimizer2d->ProjectBoundaryPoints(surfaceindex,can,should); } oldlamface = lamface; lamface *= 6; if (lamface > 2) lamface = 2; if(cnttrials < maxtrials && multithread.terminate != 1) { do // move faces { lamface *= 0.5; cnttrials++; if(cnttrials % 10 == 0) max_worsening *= 1.1; factryface = lamface + (1.-lamface) * facokface; ostrstr.str(""); ostrstr << "lamface = " << lamface << ", trying: " << factryface; PrintMessage(5,ostrstr.str()); for (int i = 1; i <= np; i++) { if (isboundarypoint.Test(i)) { for (int j = 0; j < 3; j++) mesh.Point(i)(j) = lamface * (*should.Get(i))(j) + (1.-lamface) * (*can.Get(i))(j); } else mesh.Point(i) = *can.Get(i); } ostrstr.str(""); ostrstr << "worsening: " << Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); PrintMessage(5,ostrstr.str()); ostrstr.str(""); ostrstr << bad_elements.Size() << " bad elements"; PrintMessage(5,ostrstr.str()); } while (bad_elements.Size() > 0 && cnttrials < maxtrials && multithread.terminate != 1); } if(cnttrials < maxtrials && multithread.terminate != 1) { facokface = factryface; // smooth interior mesh.CalcSurfacesOfNode(); MeshingParameters dummymp; mesh.ImproveMeshJacobian (dummymp, OPT_QUALITY,&working_points); //mesh.ImproveMeshJacobian (OPT_WORSTCASE,&working_points); for (int i = 1; i <= np; i++) *can.Elem(i) = mesh.Point(i); } //! if((facokedge < 1.-1e-8 || facokface < 1.-1e-8) && cnttrials < maxtrials && multithread.terminate != 1) { MeshingParameters dummymp; MeshOptimize3d optmesh(dummymp); for(int i=0; iProjectBoundaryPoints(surfaceindex,can,should); for (int i = 1; i <= np; i++) if(isboundarypoint.Test(i)) for(int j=1; j<=3; j++) mesh.Point(i).X(j) = should.Get(i).X(j); } */ if(cnttrials == maxtrials) { for (int i = 1; i <= np; i++) mesh.Point(i) = *should.Get(i); Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); for(int i=0; i #include "meshing.hpp" #ifdef WIN32 #define COMMASIGN ':' #else #define COMMASIGN ',' #endif namespace netgen { void LoadMatrixLine (istream & ist, DenseMatrix & m, int line) { char ch; int pnum; float f; ist >> ch; while (ch != '}') { ist.putback (ch); ist >> f; ist >> ch; ist >> pnum; if (ch == 'x' || ch == 'X') m.Elem(line, 2 * pnum - 1) = f; if (ch == 'y' || ch == 'Y') m.Elem(line, 2 * pnum) = f; ist >> ch; if (ch == COMMASIGN) ist >> ch; } } void netrule :: LoadRule (istream & ist) { char buf[256]; char ch; Point2d p; INDEX_2 lin; int i, j; DenseMatrix tempoldutonewu(20, 20), tempoldutofreearea(20, 20), tempoldutofreearealimit(20, 20); tempoldutonewu = 0; tempoldutofreearea = 0; tempoldutofreearealimit = 0; noldp = 0; noldl = 0; ist.get (buf, sizeof(buf), '"'); ist.get (ch); ist.get (buf, sizeof(buf), '"'); ist.get (ch); // if(name != NULL) delete [] name; name = new char[strlen (buf) + 1]; strcpy (name, buf); //(*testout) << "name " << name << endl; // (*mycout) << "Rule " << name << " found." << endl; do { ist >> buf; //(*testout) << "buf " << buf << endl; if (strcmp (buf, "quality") == 0) { ist >> quality; } else if (strcmp (buf, "mappoints") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ')' points.Append (p); noldp++; tolerances.SetSize (noldp); tolerances.Elem(noldp).f1 = 1.0; tolerances.Elem(noldp).f2 = 0; tolerances.Elem(noldp).f3 = 1.0; ist >> ch; while (ch != ';') { if (ch == '{') { ist >> tolerances.Elem(noldp).f1; ist >> ch; // ',' ist >> tolerances.Elem(noldp).f2; ist >> ch; // ',' ist >> tolerances.Elem(noldp).f3; ist >> ch; // '}' } else if (ch == 'd') { // delpoints.Append (noldp); ist >> ch; // 'e' ist >> ch; // 'l' } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "maplines") == 0) { ist >> ch; while (ch == '(') { ist >> lin.I1(); ist >> ch; // ',' ist >> lin.I2(); ist >> ch; // ')' //(*testout) << "read line " << lin.I1() << " " << lin.I2() << endl; lines.Append (lin); linevecs.Append (points.Get(lin.I2()) - points.Get(lin.I1())); noldl++; linetolerances.SetSize (noldl); linetolerances.Elem(noldl).f1 = 0; linetolerances.Elem(noldl).f2 = 0; linetolerances.Elem(noldl).f3 = 0; //(*testout) << "mapl1" << endl; ist >> ch; while (ch != ';') { //(*testout) << "working on character \""<> linetolerances.Elem(noldl).f1; ist >> ch; // ',' ist >> linetolerances.Elem(noldl).f2; ist >> ch; // ',' ist >> linetolerances.Elem(noldl).f3; ist >> ch; // '}' } else if (ch == 'd') { dellines.Append (noldl); ist >> ch; // 'e' ist >> ch; // 'l' //(*testout) << "read del" << endl; } ist >> ch; //(*testout) << "read character \""<> ch; //(*testout) << "read next character \""<> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ')' points.Append (p); ist >> ch; while (ch != ';') { if (ch == '{') { LoadMatrixLine (ist, tempoldutonewu, 2 * (points.Size()-noldp) - 1); ist >> ch; // '{' LoadMatrixLine (ist, tempoldutonewu, 2 * (points.Size()-noldp)); } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "newlines") == 0) { ist >> ch; while (ch == '(') { ist >> lin.I1(); ist >> ch; // ',' ist >> lin.I2(); ist >> ch; // ')' lines.Append (lin); linevecs.Append (points.Get(lin.I2()) - points.Get(lin.I1())); ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "freearea") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ')' freezone.Append (p); freezonelimit.Append (p); ist >> ch; while (ch != ';') { if (ch == '{') { LoadMatrixLine (ist, tempoldutofreearea, 2 * freezone.Size() - 1); ist >> ch; // '{' LoadMatrixLine (ist, tempoldutofreearea, 2 * freezone.Size()); } ist >> ch; } ist >> ch; } for (i = 1; i <= tempoldutofreearealimit.Height(); i++) for (j = 1; j <= tempoldutofreearealimit.Width(); j++) tempoldutofreearealimit.Elem(i,j) = tempoldutofreearea.Elem(i,j); ist.putback (ch); } else if (strcmp (buf, "freearea2") == 0) { ist >> ch; int freepi = 0; tempoldutofreearealimit = 0; while (ch == '(') { freepi++; ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ')' freezonelimit.Elem(freepi) = p; ist >> ch; while (ch != ';') { if (ch == '{') { LoadMatrixLine (ist, tempoldutofreearealimit, 2 * freepi - 1); ist >> ch; // '{' LoadMatrixLine (ist, tempoldutofreearealimit, 2 * freepi); } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "elements") == 0) { ist >> ch; while (ch == '(') { elements.Append (Element2d(TRIG)); ist >> elements.Last().PNum(1); ist >> ch; // ',' if (ch == COMMASIGN) { ist >> elements.Last().PNum(2); ist >> ch; // ',' } if (ch == COMMASIGN) { ist >> elements.Last().PNum(3); ist >> ch; // ',' } if (ch == COMMASIGN) { elements.Last().SetType (QUAD); ist >> elements.Last().PNum(4); ist >> ch; // ',' // const Element2d & el = elements.Last(); /* orientations.Append (threeint(el.PNum(1), el.PNum(2), el.PNum(3))); orientations.Append (threeint(el.PNum(2), el.PNum(3), el.PNum(4))); orientations.Append (threeint(el.PNum(3), el.PNum(4), el.PNum(1))); orientations.Append (threeint(el.PNum(4), el.PNum(1), el.PNum(2))); */ } ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "orientations") == 0) { ist >> ch; while (ch == '(') { // threeint a = threeint(); orientations.Append (threeint()); ist >> orientations.Last().i1; ist >> ch; // ',' ist >> orientations.Last().i2; ist >> ch; // ',' ist >> orientations.Last().i3; ist >> ch; // ',' ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "endrule") != 0) { PrintSysError ("Parser error, unknown token ", buf); } } while (!ist.eof() && strcmp (buf, "endrule") != 0); oldutonewu.SetSize (2 * (points.Size() - noldp), 2 * noldp); oldutofreearea.SetSize (2 * freezone.Size(), 2 * noldp); oldutofreearealimit.SetSize (2 * freezone.Size(), 2 * noldp); for (i = 1; i <= oldutonewu.Height(); i++) for (j = 1; j <= oldutonewu.Width(); j++) oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j); for (i = 1; i <= oldutofreearea.Height(); i++) for (j = 1; j <= oldutofreearea.Width(); j++) oldutofreearea.Elem(i, j) = tempoldutofreearea.Elem(i, j); for (i = 1; i <= oldutofreearea.Height(); i++) for (j = 1; j <= oldutofreearea.Width(); j++) oldutofreearealimit.Elem(i, j) = tempoldutofreearealimit.Elem(i, j); freesetinequ.SetSize (freezone.Size()); { char ok; int minn; Array pnearness (noldp); for (i = 1; i <= pnearness.Size(); i++) pnearness.Elem(i) = 1000; for (j = 1; j <= 2; j++) pnearness.Elem(GetPointNr (1, j)) = 0; do { ok = 1; for (i = 1; i <= noldl; i++) { minn = 1000; for (j = 1; j <= 2; j++) minn = min2 (minn, pnearness.Get(GetPointNr (i, j))); for (j = 1; j <= 2; j++) if (pnearness.Get(GetPointNr (i, j)) > minn+1) { ok = 0; pnearness.Elem(GetPointNr (i, j)) = minn+1; } } } while (!ok); lnearness.SetSize (noldl); for (i = 1; i <= noldl; i++) { lnearness.Elem(i) = 0; for (j = 1; j <= 2; j++) lnearness.Elem(i) += pnearness.Get(GetPointNr (i, j)); } } oldutofreearea_i.SetSize (10); freezone_i.SetSize (10); for (i = 0; i < oldutofreearea_i.Size(); i++) { double lam1 = 1.0/(i+1); oldutofreearea_i[i] = new DenseMatrix (oldutofreearea.Height(), oldutofreearea.Width()); DenseMatrix & mati = *oldutofreearea_i[i]; for (j = 0; j < oldutofreearea.Height(); j++) for (int k = 0; k < oldutofreearea.Width(); k++) mati(j,k) = lam1 * oldutofreearea(j,k) + (1 - lam1) * oldutofreearealimit(j,k); freezone_i[i] = new Array (freezone.Size()); Array & fzi = *freezone_i[i]; for (int j = 0; j < freezone.Size(); j++) fzi[j] = freezonelimit[j] + lam1 * (freezone[j] - freezonelimit[j]); } } extern const char * triarules[]; extern const char * quadrules[]; void Meshing2 :: LoadRules (const char * filename, bool quad) { char buf[256]; istream * ist; //char *tr1 = NULL; string tr1; /* ifstream ist (filename); if (!ist.good()) { cerr << "Rule description file " << filename << " not found" << endl; exit (1); } */ if (filename) { // (*mycout) << "rule-filename = " << filename << endl; ist = new ifstream (filename); } else { /* connect tetrules to one string */ const char ** hcp; // if (!mparam.quad) if (!quad) { hcp = triarules; PrintMessage (3, "load internal triangle rules"); } else { hcp = quadrules; PrintMessage (3, "load internal quad rules"); // LoadRules ("rules/quad.rls"); } size_t len = 0; while (*hcp) { // (*testout) << "POS2 *hcp " << *hcp << endl; len += strlen (*hcp); hcp++; } //tr1 = new char[len+1]; //tr1[0] = 0; tr1.reserve(len+1); // if (!mparam.quad) if (!quad) hcp = triarules; else hcp = quadrules; //char * tt1 = tr1; while (*hcp) { //strcat (tt1, *hcp); //tt1 += strlen (*hcp); tr1.append(*hcp); hcp++; } #ifdef WIN32 // VC++ 2005 workaround for(string::size_type i=0; igood()) { cerr << "Rule description file " << filename << " not found" << endl; delete ist; exit (1); } while (!ist->eof()) { buf[0] = 0; (*ist) >> buf; if (strcmp (buf, "rule") == 0) { //(*testout) << "found rule" << endl; netrule * rule = new netrule; //(*testout) << "fr1" << endl; rule -> LoadRule(*ist); //(*testout) << "fr2" << endl; rules.Append (rule); } //(*testout) << "loop" << endl; } //(*testout) << "POS3" << endl; delete ist; //delete [] tr1; } } netgen-6.2.1905/libsrc/meshing/global.hpp0000644000175000017500000000306713504650527016670 0ustar kurtkurt#ifndef FILE_GLOBAL #define FILE_GLOBAL /**************************************************************************/ /* File: global.hh */ /* Author: Joachim Schoeberl */ /* Date: 01. Okt. 95 */ /**************************************************************************/ /* global functions and variables */ namespace netgen { /// DLL_HEADER extern double GetTime (); DLL_HEADER extern void ResetTime (); /// DLL_HEADER extern int testmode; /// calling parameters // extern Flags parameters; // extern DLL_HEADER MeshingParameters mparam; DLL_HEADER extern Array tets_in_qualclass; DLL_HEADER extern mutex tcl_todo_mutex; class DLL_HEADER multithreadt { public: int pause; int testmode; int redraw; int drawing; int terminate; int running; double percent; const char * task; bool demorunning; string * tcl_todo = new string(""); // tcl commands set from parallel thread multithreadt(); }; DLL_HEADER extern volatile multithreadt multithread; DLL_HEADER extern string ngdir; DLL_HEADER extern DebugParameters debugparam; DLL_HEADER extern bool verbose; DLL_HEADER extern int h_argc; DLL_HEADER extern char ** h_argv; DLL_HEADER extern weak_ptr global_mesh; DLL_HEADER void SetGlobalMesh (shared_ptr m); // global communicator for netgen (dummy if no MPI) // extern DLL_HEADER NgMPI_Comm ng_comm; } #endif netgen-6.2.1905/libsrc/meshing/meshtool.hpp0000644000175000017500000000362213504650527017257 0ustar kurtkurt#ifndef FILE_MESHTOOL #define FILE_MESHTOOL /// extern void MeshQuality2d (const Mesh & mesh); /// extern void MeshQuality3d (const Mesh & mesh, Array * inclass = NULL); /// extern void SaveEdges (const Mesh & mesh, const char * geomfile, double h, char * filename); /// extern void SaveSurfaceMesh (const Mesh & mesh, double h, char * filename); /* /// extern void Save2DMesh ( const Mesh & mesh2d, const Array * splines, ostream & outfile); */ class Surface; /// extern void SaveVolumeMesh ( const Array & points, const Array & elements, const Array & volelements, const Array & surfaces, char * filename); /// void SaveVolumeMesh (const Mesh & mesh, const class NetgenGeometry & geometry, char * filename); /// extern int CheckCode (); /// extern double CalcTetBadness (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, double h, const MeshingParameters & mp); /// extern double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, double h, int pi, Vec<3> & grad, const MeshingParameters & mp); /** Calculates volume of an element. The volume of the tetrahedron el is computed */ // extern double CalcVolume (const Array & points, // const Element & el); /** The total volume of all elements is computed. This function calculates the volume of the mesh */ extern double CalcVolume (const Array & points, const Array & elements); /// extern int CheckSurfaceMesh (const Mesh & mesh); /// extern int CheckSurfaceMesh2 (const Mesh & mesh); /// extern int CheckMesh3D (const Mesh & mesh); /// extern void RemoveProblem (Mesh & mesh, int domainnr); #endif netgen-6.2.1905/libsrc/meshing/adfront2.cpp0000644000175000017500000003152513504650527017142 0ustar kurtkurt/* Advancing front class for surfaces */ #include #include "meshing.hpp" namespace netgen { FrontPoint2 :: FrontPoint2 (const Point<3> & ap, PointIndex agi, MultiPointGeomInfo * amgi, bool aonsurface) { p = ap; globalindex = agi; nlinetopoint = 0; frontnr = INT_MAX-10; onsurface = aonsurface; if (amgi) { mgi = new MultiPointGeomInfo (*amgi); for (int i = 1; i <= mgi->GetNPGI(); i++) if (mgi->GetPGI(i).trignum <= 0) cout << "WARNING: Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl; } else mgi = NULL; } AdFront2 :: AdFront2 (const Box3d & aboundingbox) : boundingbox(aboundingbox), linesearchtree(boundingbox.PMin(), boundingbox.PMax()), pointsearchtree(boundingbox.PMin(), boundingbox.PMax()), cpointsearchtree(boundingbox.PMin(), boundingbox.PMax()) { nfl = 0; allflines = 0; minval = 0; starti = lines.Begin(); } AdFront2 :: ~AdFront2 () { delete allflines; } void AdFront2 :: PrintOpenSegments (ostream & ost) const { if (nfl > 0) { ost << nfl << " open front segments left:" << endl; for (int i = lines.Begin(); i < lines.End(); i++) if (lines[i].Valid()) ost << i << ": " << GetGlobalIndex (lines[i].L().I1()) << "-" << GetGlobalIndex (lines[i].L().I2()) << endl; } } /* void AdFront2 :: GetPoints (Array > & apoints) const { apoints.Append (points); // for (int i = 0; i < points.Size(); i++) // apoints.Append (points[i].P()); } */ int AdFront2 :: AddPoint (const Point<3> & p, PointIndex globind, MultiPointGeomInfo * mgi, bool pointonsurface) { // inserts at empty position or resizes array int pi; if (delpointl.Size() != 0) { pi = delpointl.Last(); delpointl.DeleteLast (); points[pi] = FrontPoint2 (p, globind, mgi, pointonsurface); } else { points.Append (FrontPoint2 (p, globind, mgi, pointonsurface)); pi = points.Size()-1; } if (mgi) cpointsearchtree.Insert (p, pi); if (pointonsurface) pointsearchtree.Insert (p, pi); return pi; } int AdFront2 :: AddLine (int pi1, int pi2, const PointGeomInfo & gi1, const PointGeomInfo & gi2) { int minfn; int li; FrontPoint2 & p1 = points[pi1]; FrontPoint2 & p2 = points[pi2]; nfl++; p1.AddLine(); p2.AddLine(); minfn = min2 (p1.FrontNr(), p2.FrontNr()); p1.DecFrontNr (minfn+1); p2.DecFrontNr (minfn+1); if (dellinel.Size() != 0) { li = dellinel.Last(); dellinel.DeleteLast (); lines[li] = FrontLine (INDEX_2(pi1, pi2)); } else { lines.Append(FrontLine (INDEX_2(pi1, pi2))); li = lines.Size()-1; } if (!gi1.trignum || !gi2.trignum) { cout << "WARNING: in AdFront::AddLine, illegal geominfo" << endl; } lines[li].SetGeomInfo (gi1, gi2); Box3d lbox; lbox.SetPoint(p1.P()); lbox.AddPoint(p2.P()); linesearchtree.Insert (lbox.PMin(), lbox.PMax(), li); if (allflines) { if (allflines->Used (INDEX_2 (GetGlobalIndex (pi1), GetGlobalIndex (pi2)))) { cerr << "ERROR Adfront2::AddLine: line exists" << endl; (*testout) << "ERROR Adfront2::AddLine: line exists" << endl; } allflines->Set (INDEX_2 (GetGlobalIndex (pi1), GetGlobalIndex (pi2)), 1); } return li; } void AdFront2 :: DeleteLine (int li) { int pi; nfl--; for (int i = 1; i <= 2; i++) { pi = lines[li].L().I(i); points[pi].RemoveLine(); if (!points[pi].Valid()) { delpointl.Append (pi); if (points[pi].mgi) { cpointsearchtree.DeleteElement (pi); delete points[pi].mgi; points[pi].mgi = NULL; } pointsearchtree.DeleteElement (pi); } } if (allflines) { allflines->Set (INDEX_2 (GetGlobalIndex (lines[li].L().I1()), GetGlobalIndex (lines[li].L().I2())), 2); } lines[li].Invalidate(); linesearchtree.DeleteElement (li); dellinel.Append (li); } int AdFront2 :: ExistsLine (int pi1, int pi2) { if (!allflines) return 0; if (allflines->Used (INDEX_2(pi1, pi2))) return allflines->Get (INDEX_2 (pi1, pi2)); else return 0; } int AdFront2 :: SelectBaseLine (Point<3> & p1, Point<3> & p2, const PointGeomInfo *& geominfo1, const PointGeomInfo *& geominfo2, int & qualclass) { int baselineindex = -1; for (int i = starti; i < lines.End(); i++) { if (lines[i].Valid()) { int hi = lines[i].LineClass() + points[lines[i].L().I1()].FrontNr() + points[lines[i].L().I2()].FrontNr(); if (hi <= minval) { minval = hi; baselineindex = i; break; } } } if (baselineindex == -1) { minval = INT_MAX; for (int i = lines.Begin(); i < lines.End(); i++) if (lines[i].Valid()) { int hi = lines[i].LineClass() + points[lines[i].L().I1()].FrontNr() + points[lines[i].L().I2()].FrontNr(); if (hi < minval) { minval = hi; baselineindex = i; } } } starti = baselineindex+1; p1 = points[lines[baselineindex].L().I1()].P(); p2 = points[lines[baselineindex].L().I2()].P(); geominfo1 = &lines[baselineindex].GetGeomInfo(1); geominfo2 = &lines[baselineindex].GetGeomInfo(2); qualclass = lines[baselineindex].LineClass(); return baselineindex; } int AdFront2 :: GetLocals (int baselineindex, Array & locpoints, Array & pgeominfo, Array & loclines, // local index Array & pindex, Array & lindex, double xh) { static int timer = NgProfiler::CreateTimer ("adfront2::GetLocals"); NgProfiler::RegionTimer reg (timer); int pstind; Point<3> midp, p0; pstind = lines[baselineindex].L().I1(); p0 = points[pstind].P(); loclines.Append(lines[baselineindex].L()); lindex.Append(baselineindex); ArrayMem nearlines(0); ArrayMem nearpoints(0); // dominating costs !! linesearchtree.GetIntersecting (p0 - Vec3d(xh, xh, xh), p0 + Vec3d(xh, xh, xh), nearlines); pointsearchtree.GetIntersecting (p0 - Vec3d(xh, xh, xh), p0 + Vec3d(xh, xh, xh), nearpoints); for (int ii = 0; ii < nearlines.Size(); ii++) { int i = nearlines[ii]; if (lines[i].Valid() && i != baselineindex) { loclines.Append(lines[i].L()); lindex.Append(i); } } // static Array invpindex; invpindex.SetSize (points.Size()); // invpindex = -1; for (int i = 0; i < nearpoints.Size(); i++) invpindex[nearpoints[i]] = -1; for (int i = 0; i < loclines.Size(); i++) { invpindex[loclines[i].I1()] = 0; invpindex[loclines[i].I2()] = 0; } for (int i = 0; i < loclines.Size(); i++) { for (int j = 0; j < 2; j++) { int pi = loclines[i][j]; if (invpindex[pi] == 0) { pindex.Append (pi); invpindex[pi] = pindex.Size(); locpoints.Append (points[pi].P()); loclines[i][j] = locpoints.Size(); } else loclines[i][j] = invpindex[pi]; } } // double xh2 = xh*xh; for (int ii = 0; ii < nearpoints.Size(); ii++) { int i = nearpoints[ii]; if (points[i].Valid() && points[i].OnSurface() && // Dist2 (points.Get(i).P(), p0) <= xh2 && invpindex[i] <= 0) { locpoints.Append (points[i].P()); invpindex[i] = locpoints.Size(); pindex.Append(i); } } /* double xh2 = xh*xh; for (i = 1; i <= points.Size(); i++) { if (points.Get(i).Valid() && points.Get(i).OnSurface() && Dist2 (points.Get(i).P(), p0) <= xh2 && invpindex.Get(i) <= 0) { invpindex.Elem(i) = locpoints.Append (points.Get(i).P()); pindex.Append(i); } } */ pgeominfo.SetSize (locpoints.Size()); for (int i = 0; i < pgeominfo.Size(); i++) pgeominfo[i].Init(); for (int i = 0; i < loclines.Size(); i++) for (int j = 0; j < 2; j++) { int lpi = loclines[i][j]; const PointGeomInfo & gi = lines[lindex[i]].GetGeomInfo (j+1); pgeominfo.Elem(lpi).AddPointGeomInfo (gi); /* if (pgeominfo.Elem(lpi).cnt == MULTIPOINTGEOMINFO_MAX) break; const PointGeomInfo & gi = lines.Get(lindex.Get(i)).GetGeomInfo (j); PointGeomInfo * pgi = pgeominfo.Elem(lpi).mgi; int found = 0; for (k = 0; k < pgeominfo.Elem(lpi).cnt; k++) if (pgi[k].trignum == gi.trignum) found = 1; if (!found) { pgi[pgeominfo.Elem(lpi).cnt] = gi; pgeominfo.Elem(lpi).cnt++; } */ } for (int i = 0; i < locpoints.Size(); i++) { int pi = pindex[i]; if (points[pi].mgi) for (int j = 1; j <= points[pi].mgi->GetNPGI(); j++) pgeominfo[i].AddPointGeomInfo (points[pi].mgi->GetPGI(j)); } if (loclines.Size() == 1) { cout << "loclines.Size = 1" << endl; (*testout) << "loclines.size = 1" << endl << " h = " << xh << endl << " nearline.size = " << nearlines.Size() << endl << " p0 = " << p0 << endl; } return lines[baselineindex].LineClass(); } void AdFront2 :: SetStartFront () { for (int i = lines.Begin(); i < lines.End(); i++) if (lines[i].Valid()) for (int j = 1; j <= 2; j++) points[lines[i].L().I(j)].DecFrontNr(0); } void AdFront2 :: Print (ostream & ost) const { ost << points.Size() << " Points: " << endl; for (int i = points.Begin(); i < points.End(); i++) if (points[i].Valid()) ost << i << " " << points[i].P() << endl; ost << nfl << " Lines: " << endl; for (int i = lines.Begin(); i < lines.End(); i++) if (lines[i].Valid()) ost << lines[i].L().I1() << " - " << lines[i].L().I2() << endl; ost << flush; } bool AdFront2 :: Inside (const Point<2> & p) const { int cnt; Vec<2> n; Vec<3> v1; DenseMatrix a(2), ainv(2); Vector b(2), u(2); // quasi-random numbers: n(0) = 0.123871; n(1) = 0.15432; cnt = 0; for (int i = 0; i < lines.Size(); i++) if (lines[i].Valid()) { const Point<3> & p1 = points[lines[i].L().I1()].P(); const Point<3> & p2 = points[lines[i].L().I2()].P(); v1 = p2 - p1; a(0, 0) = v1(0); a(1, 0) = v1(1); a(0, 1) = -n(0); a(1, 1) = -n(1); b(0) = p(0) - p1(0); b(1) = p(1) - p1(1); CalcInverse (a, ainv); ainv.Mult (b, u); if (u(0) >= 0 && u(0) <= 1 && u(1) > 0) cnt++; } return ((cnt % 2) != 0); } bool AdFront2 :: SameSide (const Point<2> & lp1, const Point<2> & lp2, const Array * testfaces) const { int cnt = 0; if (testfaces) { for (int ii = 0; ii < testfaces->Size(); ii++) if (lines[(*testfaces)[ii]].Valid()) { int i = (*testfaces)[ii]; const Point<3> & p13d = points[lines[i].L().I1()].P(); const Point<3> & p23d = points[lines[i].L().I2()].P(); Point<2> p1(p13d(0), p13d(1)); Point<2> p2(p23d(0), p23d(1)); // p1 + alpha v = lp1 + beta vl Vec<2> v = p2-p1; Vec<2> vl = lp2 - lp1; Mat<2,2> mat, inv; Vec<2> rhs, sol; mat(0,0) = v(0); mat(1,0) = v(1); mat(0,1) = -vl(0); mat(1,1) = -vl(1); rhs = lp1-p1; if (Det(mat) == 0) continue; CalcInverse (mat, inv); sol = inv * rhs; if ( (sol(0) >= 0) && (sol(0) <= 1) && (sol(1) >= 0) && (sol(1) <= 1)) { cnt++; } } } else { for (int i = 0; i < lines.Size(); i++) if (lines[i].Valid()) { const Point<3> & p13d = points[lines[i].L().I1()].P(); const Point<3> & p23d = points[lines[i].L().I2()].P(); Point<2> p1(p13d(0), p13d(1)); Point<2> p2(p23d(0), p23d(1)); // p1 + alpha v = lp1 + beta vl Vec<2> v = p2-p1; Vec<2> vl = lp2 - lp1; Mat<2,2> mat, inv; Vec<2> rhs, sol; mat(0,0) = v(0); mat(1,0) = v(1); mat(0,1) = -vl(0); mat(1,1) = -vl(1); rhs = lp1-p1; if (Det(mat) == 0) continue; CalcInverse (mat, inv); sol = inv * rhs; if ((sol(0) >= 0) && (sol(0) <= 1) && (sol(1) >= 0) && (sol(1) <= 1)) { cnt++; } } } return ((cnt % 2) == 0); } } netgen-6.2.1905/libsrc/meshing/meshtype.hpp0000644000175000017500000011321113504650527017257 0ustar kurtkurt#ifndef MESHTYPE #define MESHTYPE /**************************************************************************/ /* File: meshtype.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Okt. 95 */ /**************************************************************************/ namespace netgen { /* Classes for NETGEN */ enum ELEMENT_TYPE : unsigned char { SEGMENT = 1, SEGMENT3 = 2, TRIG = 10, QUAD=11, TRIG6 = 12, QUAD6 = 13, QUAD8 = 14, TET = 20, TET10 = 21, PYRAMID = 22, PRISM = 23, PRISM12 = 24, PRISM15 = 27, PYRAMID13 = 28, HEX = 25, HEX20 = 26 }; /* typedef int ELEMENT_EDGE[2]; // initial point, end point typedef int ELEMENT_FACE[4]; // points, last one is -1 for trig */ struct ELEMENT_EDGE { int vals[2]; int & operator[] (size_t i) { return vals[i]; } int operator[] (size_t i) const { return vals[i]; } }; struct ELEMENT_FACE { int vals[4]; int & operator[] (size_t i) { return vals[i]; } int operator[] (size_t i) const { return vals[i]; } }; #define ELEMENT_MAXPOINTS 20 #define ELEMENT2D_MAXPOINTS 8 enum POINTTYPE { FIXEDPOINT = 1, EDGEPOINT = 2, SURFACEPOINT = 3, INNERPOINT = 4 }; enum ELEMENTTYPE { FREEELEMENT, FIXEDELEMENT }; enum OPTIMIZEGOAL { OPT_QUALITY, OPT_CONFORM, OPT_REST, OPT_WORSTCASE, OPT_LEGAL }; extern DLL_HEADER size_t timestamp; inline size_t GetTimeStamp() { return timestamp; } inline size_t NextTimeStamp() { timestamp++; return timestamp; } /* extern DLL_HEADER int GetTimeStamp(); extern DLL_HEADER int NextTimeStamp(); */ class PointGeomInfo { public: int trignum; // for STL Meshing double u, v; // for OCC Meshing PointGeomInfo () = default; // : trignum(-1), u(0), v(0) { ; } PointGeomInfo (const PointGeomInfo&) = default; PointGeomInfo (PointGeomInfo &&) = default; PointGeomInfo & operator= (const PointGeomInfo&) = default; PointGeomInfo & operator= (PointGeomInfo&&) = default; }; inline ostream & operator<< (ostream & ost, const PointGeomInfo & gi) { return (ost << gi.trignum << " " << gi.u << " " << gi.v); } inline istream & operator>> (istream & ist, PointGeomInfo & gi) { return (ist >> gi.trignum >> gi.u >> gi.v); } #define MULTIPOINTGEOMINFO_MAX 100 class MultiPointGeomInfo { int cnt; PointGeomInfo mgi[MULTIPOINTGEOMINFO_MAX]; public: MultiPointGeomInfo () { cnt = 0; } int AddPointGeomInfo (const PointGeomInfo & gi); void Init () { cnt = 0; } void DeleteAll () { cnt = 0; } int GetNPGI () const { return cnt; } const PointGeomInfo & GetPGI (int i) const { return mgi[i-1]; } }; class EdgePointGeomInfo { public: int edgenr; int body; // for ACIS double dist; // for 2d meshing double u, v; // for OCC Meshing public: EdgePointGeomInfo () : edgenr(0), body(0), dist(0.0), u(0.0), v(0.0) { ; } EdgePointGeomInfo & operator= (const EdgePointGeomInfo & gi2) { edgenr = gi2.edgenr; body = gi2.body; dist = gi2.dist; u = gi2.u; v = gi2.v; return *this; } }; inline ostream & operator<< (ostream & ost, const EdgePointGeomInfo & gi) { ost << "epgi: edgnr=" << gi.edgenr << ", dist=" << gi.dist; return ost; } class PointIndex { int i; public: PointIndex () = default; PointIndex (const PointIndex&) = default; PointIndex (PointIndex &&) = default; PointIndex & operator= (const PointIndex&) = default; PointIndex & operator= (PointIndex&&) = default; PointIndex (int ai) : i(ai) { ; } // PointIndex & operator= (const PointIndex &ai) { i = ai.i; return *this; } operator int () const { return i; } PointIndex operator++ (int) { PointIndex hi(*this); i++; return hi; } PointIndex operator-- (int) { PointIndex hi(*this); i--; return hi; } PointIndex operator++ () { i++; return *this; } PointIndex operator-- () { i--; return *this; } void Invalidate() { i = PointIndex::BASE-1; } bool IsValid() const { return i != PointIndex::BASE-1; } #ifdef BASE0 enum { BASE = 0 }; #else enum { BASE = 1 }; #endif void DoArchive (Archive & ar) { ar & i; } }; inline istream & operator>> (istream & ist, PointIndex & pi) { int i; ist >> i; pi = PointIndex(i); return ist; } inline ostream & operator<< (ostream & ost, const PointIndex & pi) { return (ost << int(pi)); } template class PointIndices; template <> class PointIndices<2> : public INDEX_2 { public: PointIndices () = default; PointIndices (INDEX_2 i2) : INDEX_2(i2) { ; } PointIndices (PointIndex i1, PointIndex i2) : INDEX_2(i1,i2) { ; } PointIndex operator[] (int i) const { return PointIndex(INDEX_2::operator[](i)); } PointIndex & operator[] (int i) { return reinterpret_cast(INDEX_2::operator[](i)); } static PointIndices Sort(PointIndex i1, PointIndex i2) { return INDEX_2::Sort(i1, i2); } }; class ElementIndex { int i; public: ElementIndex () { ; } ElementIndex (int ai) : i(ai) { ; } ElementIndex & operator= (const ElementIndex & ai) { i = ai.i; return *this; } ElementIndex & operator= (int ai) { i = ai; return *this; } operator int () const { return i; } ElementIndex operator++ (int) { return ElementIndex(i++); } ElementIndex operator-- (int) { return ElementIndex(i--); } ElementIndex & operator++ () { ++i; return *this; } ElementIndex & operator-- () { --i; return *this; } }; inline istream & operator>> (istream & ist, ElementIndex & pi) { int i; ist >> i; pi = i; return ist; } inline ostream & operator<< (ostream & ost, const ElementIndex & pi) { return (ost << int(pi)); } class SurfaceElementIndex { int i; public: SurfaceElementIndex () = default; SurfaceElementIndex (int ai) : i(ai) { ; } /* SurfaceElementIndex & operator= (const SurfaceElementIndex & ai) { i = ai.i; return *this; } */ SurfaceElementIndex & operator= (const SurfaceElementIndex & ai) = default; SurfaceElementIndex & operator= (int ai) { i = ai; return *this; } operator int () const { return i; } SurfaceElementIndex operator++ (int) { SurfaceElementIndex hi(*this); i++; return hi; } SurfaceElementIndex operator-- (int) { SurfaceElementIndex hi(*this); i--; return hi; } SurfaceElementIndex & operator++ () { ++i; return *this; } SurfaceElementIndex & operator-- () { --i; return *this; } SurfaceElementIndex & operator+= (int inc) { i+=inc; return *this; } void DoArchive (Archive & ar) { ar & i; } }; inline istream & operator>> (istream & ist, SurfaceElementIndex & pi) { int i; ist >> i; pi = i; return ist; } inline ostream & operator<< (ostream & ost, const SurfaceElementIndex & pi) { return (ost << int(pi)); } class SegmentIndex { int i; public: SegmentIndex () { ; } SegmentIndex (int ai) : i(ai) { ; } SegmentIndex & operator= (const SegmentIndex & ai) { i = ai.i; return *this; } SegmentIndex & operator= (int ai) { i = ai; return *this; } operator int () const { return i; } SegmentIndex & operator++ (int) { i++; return *this; } SegmentIndex & operator-- (int) { i--; return *this; } }; inline istream & operator>> (istream & ist, SegmentIndex & pi) { int i; ist >> i; pi = i; return ist; } inline ostream & operator<< (ostream & ost, const SegmentIndex & pi) { return (ost << int(pi)); } /** Point in the mesh. Contains layer (a new feature in 4.3 for overlapping meshes. */ class MeshPoint : public Point<3> { int layer; double singular; // singular factor for hp-refinement POINTTYPE type; public: MeshPoint () { ; } MeshPoint (const Point<3> & ap, int alayer = 1, POINTTYPE apt = INNERPOINT) : Point<3> (ap), layer(alayer), singular(0.),type(apt) { ; } void SetPoint (const Point<3> & ap) { Point<3>::operator= (ap); layer = 0; singular = 0; } void Scale(double factor) { *testout << "before: " << x[0] << endl; x[0] *= factor; x[1] *= factor; x[2] *= factor; *testout << "after: " << x[0] << endl;} int GetLayer() const { return layer; } POINTTYPE Type() const { return type; } void SetType(POINTTYPE at) { type = at; } double Singularity() const { return singular; } void Singularity(double s) { singular = s; } bool IsSingular() const { return (singular != 0.0); } #ifdef PARALLEL static MPI_Datatype MyGetMPIType ( ); #endif void DoArchive (Archive & ar) { ar & x[0] & x[1] & x[2] & layer & singular; ar & (unsigned char&)(type); } }; inline ostream & operator<<(ostream & s, const MeshPoint & pt) { return (s << Point<3> (pt)); } typedef Array T_POINTS; /** Triangle element for surface mesh generation. */ class Element2d { /// point numbers PointIndex pnum[ELEMENT2D_MAXPOINTS]; /// geom info of points PointGeomInfo geominfo[ELEMENT2D_MAXPOINTS]; /// surface nr short int index; /// ELEMENT_TYPE typ; /// number of points unsigned int np:4; bool badel:1; bool refflag:1; // marked for refinement bool strongrefflag:1; bool deleted:1; // element is deleted // Philippose - 08 August 2010 // Set a new property for each element, to // control whether it is visible or not bool visible:1; // element visible bool is_curved:1; // element is (high order) curved /// order for hp-FEM unsigned int orderx:6; unsigned int ordery:6; // #ifdef PARALLEL // int partitionNumber; // #endif /// a linked list for all segments in the same face SurfaceElementIndex next; public: /// Element2d () = default; Element2d (const Element2d &) = default; Element2d (Element2d &&) = default; Element2d & operator= (const Element2d &) = default; Element2d & operator= (Element2d &&) = default; /// DLL_HEADER Element2d (int anp); /// DLL_HEADER Element2d (ELEMENT_TYPE type); /// DLL_HEADER Element2d (int pi1, int pi2, int pi3); /// DLL_HEADER Element2d (int pi1, int pi2, int pi3, int pi4); /// ELEMENT_TYPE GetType () const { return typ; } /// void SetType (ELEMENT_TYPE atyp) { typ = atyp; switch (typ) { case TRIG: np = 3; break; case QUAD: np = 4; break; case TRIG6: np = 6; break; case QUAD6: np = 6; break; case QUAD8: np = 8; break; default: PrintSysError ("Element2d::SetType, illegal type ", int(typ)); } is_curved = (np >= 4); } /// int GetNP() const { return np; } /// int GetNV() const { if (typ == TRIG || typ == TRIG6) return 3; else { #ifdef DEBUG if (typ != QUAD && typ != QUAD6 && typ != QUAD8) PrintSysError ("element2d::GetNV not implemented for typ", typ); #endif return 4; } /* switch (typ) { case TRIG: case TRIG6: return 3; case QUAD: case QUAD8: case QUAD6: return 4; default: #ifdef DEBUG PrintSysError ("element2d::GetNV not implemented for typ", typ) #endif ; } return np; */ } /// PointIndex & operator[] (int i) { return pnum[i]; } /// const PointIndex & operator[] (int i) const { return pnum[i]; } FlatArray PNums () const { return FlatArray (np, &pnum[0]); } FlatArray PNums () { return FlatArray (np, &pnum[0]); } auto Vertices() const { return FlatArray (GetNV(), &pnum[0]); } /// PointIndex & PNum (int i) { return pnum[i-1]; } /// const PointIndex & PNum (int i) const { return pnum[i-1]; } /// PointIndex & PNumMod (int i) { return pnum[(i-1) % np]; } /// const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; } /// /// PointGeomInfo & GeomInfoPi (int i) { return geominfo[i-1]; } /// const PointGeomInfo & GeomInfoPi (int i) const { return geominfo[i-1]; } /// PointGeomInfo & GeomInfoPiMod (int i) { return geominfo[(i-1) % np]; } /// const PointGeomInfo & GeomInfoPiMod (int i) const { return geominfo[(i-1) % np]; } void DoArchive (Archive & ar) { short _np, _typ; bool _curved, _vis, _deleted; if (ar.Output()) { _np = np; _typ = typ; _curved = is_curved; _vis = visible; _deleted = deleted; } ar & _np & _typ & index & _curved & _vis & _deleted; // ar & next; don't need if (ar.Input()) { np = _np; typ = ELEMENT_TYPE(_typ); is_curved = _curved; visible = _vis; deleted = _deleted; } for (size_t i = 0; i < np; i++) ar & pnum[i]; } void SetIndex (int si) { index = si; } /// int GetIndex () const { return index; } int GetOrder () const { return orderx; } void SetOrder (int aorder) { orderx = ordery = aorder; } void GetOrder (int & ox, int & oy) const { ox = orderx, oy =ordery;}; void GetOrder (int & ox, int & oy, int & oz) const { ox = orderx; oy = ordery; oz=0; } void SetOrder (int ox, int oy, int /* oz */) { orderx = ox; ordery = oy;} void SetOrder (int ox, int oy) { orderx = ox; ordery = oy;} /// void GetBox (const T_POINTS & points, Box3d & box) const; /// invert orientation inline void Invert (); /// void Invert2 (); /// first point number is smallest inline void NormalizeNumbering (); /// void NormalizeNumbering2 (); bool BadElement() const { return badel; } // friend ostream & operator<<(ostream & s, const Element2d & el); friend class Mesh; /// get number of 'integration points' int GetNIP () const; void GetIntegrationPoint (int ip, Point2d & p, double & weight) const; void GetTransformation (int ip, const Array & points, class DenseMatrix & trans) const; void GetTransformation (int ip, class DenseMatrix & pmat, class DenseMatrix & trans) const; void GetShape (const Point2d & p, class Vector & shape) const; void GetShapeNew (const Point<2> & p, class FlatVector & shape) const; template void GetShapeNew (const Point<2,T> & p, TFlatVector shape) const; /// matrix 2 * np void GetDShape (const Point2d & p, class DenseMatrix & dshape) const; template void GetDShapeNew (const Point<2,T> & p, class MatrixFixWidth<2,T> & dshape) const; /// matrix 2 * np void GetPointMatrix (const Array & points, class DenseMatrix & pmat) const; void ComputeIntegrationPointData () const; double CalcJacobianBadness (const Array & points) const; double CalcJacobianBadness (const T_POINTS & points, const Vec<3> & n) const; double CalcJacobianBadnessDirDeriv (const Array & points, int pi, Vec2d & dir, double & dd) const; void Delete () { deleted = 1; for (PointIndex & p : pnum) p.Invalidate(); } bool IsDeleted () const { #ifdef DEBUG if (pnum[0] < PointIndex::BASE && !deleted) cerr << "Surfelement has illegal pnum, but not marked as deleted" << endl; #endif return deleted; } // Philippose - 08 August 2010 // Access functions for the new property: visible void Visible(bool vis = 1) { visible = vis; } bool IsVisible () const { return visible; } void SetRefinementFlag (bool rflag = 1) { refflag = rflag; } bool TestRefinementFlag () const { return refflag; } void SetStrongRefinementFlag (bool rflag = 1) { strongrefflag = rflag; } bool TestStrongRefinementFlag () const { return strongrefflag; } bool IsCurved () const { return is_curved; } void SetCurved (bool acurved) { is_curved = acurved; } SurfaceElementIndex NextElement() { return next; } bool operator==(const Element2d & el2) const; int HasFace(const Element2d& el) const; /// int meshdocval; /// int hp_elnr; /* #ifdef PARALLEL int GetPartition () const { return partitionNumber; } void SetPartition (int nr) { partitionNumber = nr; }; #endif */ }; ostream & operator<<(ostream & s, const Element2d & el); class IntegrationPointData { public: Point<3> p; double weight; Vector shape; DenseMatrix dshape; }; /** Volume element */ class Element { private: /// point numbers PointIndex pnum[ELEMENT_MAXPOINTS]; /// ELEMENT_TYPE typ; /// number of points (4..tet, 5..pyramid, 6..prism, 8..hex, 10..quad tet, 12..quad prism) int np:6; /// class flagstruct { public: bool marked:1; // marked for refinement bool badel:1; // angles worse then limit bool reverse:1; // for refinement a la Bey bool illegal:1; // illegal, will be split or swapped bool illegal_valid:1; // is illegal-flag valid ? bool badness_valid:1; // is badness valid ? bool refflag:1; // mark element for refinement bool strongrefflag:1; bool deleted:1; // element is deleted, will be removed from array bool fixed:1; // don't change element in optimization }; /// sub-domain index short int index; /// order for hp-FEM unsigned int orderx:6; unsigned int ordery:6; unsigned int orderz:6; /* unsigned int levelx:6; unsigned int levely:6; unsigned int levelz:6; */ /// stored shape-badness of element float badness; bool is_curved:1; // element is (high order) curved // #ifdef PARALLEL /// number of partition for parallel computation // int partitionNumber; // #endif public: flagstruct flags; /// DLL_HEADER Element () = default; Element (const Element &) = default; Element (Element &&) = default; Element & operator= (const Element &) = default; Element & operator= (Element &&) = default; /// Element (int anp); /// Element (ELEMENT_TYPE type); /// // Element & operator= (const Element & el2); /// void SetNP (int anp); /// void SetType (ELEMENT_TYPE atyp); /// int GetNP () const { return np; } /// uint8_t GetNV() const { __assume(typ >= TET && typ <= PYRAMID13); switch (typ) { case TET: case TET10: return 4; case PRISM12: case PRISM15: case PRISM: return 6; case PYRAMID: case PYRAMID13: return 5; case HEX: case HEX20: return 8; default: // not a 3D element #ifdef DEBUG PrintSysError ("Element3d::GetNV not implemented for typ ", typ); #endif __assume(false); return -1; } } bool operator==(const Element & el2) const; // old style: int NP () const { return np; } /// ELEMENT_TYPE GetType () const { return typ; } /// PointIndex & operator[] (int i) { return pnum[i]; } /// const PointIndex & operator[] (int i) const { return pnum[i]; } FlatArray PNums () const { return FlatArray (np, &pnum[0]); } FlatArray Vertices() const { return { GetNV(), &pnum[0] }; } /// PointIndex & PNum (int i) { return pnum[i-1]; } /// const PointIndex & PNum (int i) const { return pnum[i-1]; } /// PointIndex & PNumMod (int i) { return pnum[(i-1) % np]; } /// const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; } void DoArchive (Archive & ar) { short _np, _typ; bool _curved; if (ar.Output()) { _np = np; _typ = typ; _curved = is_curved; } ar & _np & _typ & index & _curved; if (ar.Input()) { np = _np; typ = ELEMENT_TYPE(_typ); is_curved = _curved; } for (size_t i = 0; i < np; i++) ar & pnum[i]; } /// void SetIndex (int si) { index = si; } /// int GetIndex () const { return index; } int GetOrder () const { return orderx; } void SetOrder (const int aorder) ; void GetOrder (int & ox, int & oy, int & oz) const { ox = orderx; oy = ordery; oz = orderz; } void SetOrder (const int ox, const int oy, const int oz); // void GetLevel (int & ox, int & oy, int & oz) const { ox = levelx; oy = levely; oz = levelz; } // void SetLevel (int ox, int oy, int oz) { levelx = ox; levely = oy; levelz = oz; } /// void GetBox (const T_POINTS & points, Box3d & box) const; /// Calculates Volume of element double Volume (const T_POINTS & points) const; /// DLL_HEADER void Print (ostream & ost) const; /// int GetNFaces () const { switch (typ) { case TET: case TET10: return 4; case PYRAMID: case PYRAMID13: return 5; case PRISM: case PRISM15: case PRISM12: return 5; case HEX: case HEX20: return 6; default: #ifdef DEBUG PrintSysError ("element3d::GetNFaces not implemented for typ", typ) #endif ; } return 0; } /// inline void GetFace (int i, Element2d & face) const; /// void GetFace2 (int i, Element2d & face) const; /// void Invert (); /// split into 4 node tets void GetTets (Array & locels) const; /// split into 4 node tets, local point nrs void GetTetsLocal (Array & locels) const; /// returns coordinates of nodes // void GetNodesLocal (Array > & points) const; void GetNodesLocalNew (Array > & points) const; /// split surface into 3 node trigs void GetSurfaceTriangles (Array & surftrigs) const; /// get number of 'integration points' int GetNIP () const; void GetIntegrationPoint (int ip, Point<3> & p, double & weight) const; void GetTransformation (int ip, const T_POINTS & points, class DenseMatrix & trans) const; void GetTransformation (int ip, class DenseMatrix & pmat, class DenseMatrix & trans) const; void GetShape (const Point<3> & p, class Vector & shape) const; // void GetShapeNew (const Point<3> & p, class FlatVector & shape) const; template void GetShapeNew (const Point<3,T> & p, TFlatVector shape) const; /// matrix 2 * np void GetDShape (const Point<3> & p, class DenseMatrix & dshape) const; template void GetDShapeNew (const Point<3,T> & p, class MatrixFixWidth<3,T> & dshape) const; /// matrix 3 * np void GetPointMatrix (const T_POINTS & points, class DenseMatrix & pmat) const; void ComputeIntegrationPointData () const; double CalcJacobianBadness (const T_POINTS & points) const; double CalcJacobianBadnessDirDeriv (const T_POINTS & points, int pi, Vec<3> & dir, double & dd) const; double CalcJacobianBadnessGradient (const T_POINTS & points, int pi, Vec<3> & grad) const; /// // friend ostream & operator<<(ostream & s, const Element & el); void SetRefinementFlag (bool rflag = 1) { flags.refflag = rflag; } int TestRefinementFlag () const { return flags.refflag; } void SetStrongRefinementFlag (bool rflag = 1) { flags.strongrefflag = rflag; } int TestStrongRefinementFlag () const { return flags.strongrefflag; } int Illegal () const { return flags.illegal; } int IllegalValid () const { return flags.illegal_valid; } void SetIllegal (int aillegal) { flags.illegal = aillegal ? 1 : 0; flags.illegal_valid = 1; } void SetLegal (int alegal) { flags.illegal = alegal ? 0 : 1; flags.illegal_valid = 1; } void Delete () { flags.deleted = 1; } bool IsDeleted () const { #ifdef DEBUG if (pnum[0] < PointIndex::BASE && !flags.deleted) cerr << "Volelement has illegal pnum, but not marked as deleted" << endl; #endif return flags.deleted; } bool IsCurved () const { return is_curved; } void SetCurved (bool acurved) { is_curved = acurved; } /* #ifdef PARALLEL int GetPartition () const { return partitionNumber; } void SetPartition (int nr) { partitionNumber = nr; }; #else int GetPartition () const { return 0; } #endif */ int hp_elnr; }; ostream & operator<<(ostream & s, const Element & el); /** Edge segment. */ class Segment { public: /// DLL_HEADER Segment(); DLL_HEADER Segment (const Segment& other); ~Segment() { ; } // friend ostream & operator<<(ostream & s, const Segment & seg); PointIndex pnums[3]; // p1, p2, pmid int edgenr; /// double singedge_left; double singedge_right; /// 0.. not first segment of segs, 1..first of class, 2..first of class, inverse unsigned int seginfo:2; /// surface decoding index int si; /// co dim 2 deconding index int cd2i; /// domain number inner side int domin; /// domain number outer side int domout; /// top-level object number of surface int tlosurf; /// PointGeomInfo geominfo[2]; /// surfaces describing edge int surfnr1, surfnr2; /// EdgePointGeomInfo epgeominfo[2]; /// // int pmid; // for second order /// int meshdocval; // #ifdef PARALLEL /// number of partition for parallel computation // int partitionNumber; // #endif private: string* bcname; bool is_curved; public: /* PointIndex operator[] (int i) const { return (i == 0) ? p1 : p2; } PointIndex & operator[] (int i) { return (i == 0) ? p1 : p2; } */ Segment& operator=(const Segment & other); int hp_elnr; void SetBCName ( string * abcname ) { bcname = abcname; } string * BCNamePtr () { return bcname; } const string * BCNamePtr () const { return bcname; } const string & GetBCName () const { static string defaultstring = "default"; if (! bcname ) return defaultstring; return *bcname; } int GetNP() const { return (pnums[2] < 0) ? 2 : 3; } ELEMENT_TYPE GetType() const { return (pnums[2] < 0) ? SEGMENT : SEGMENT3; } PointIndex & operator[] (int i) { return pnums[i]; } const PointIndex & operator[] (int i) const { return pnums[i]; } bool IsCurved () const { return is_curved; } void SetCurved (bool acurved) { is_curved = acurved; } /* #ifdef PARALLEL int GetPartition () const { return partitionNumber; } void SetPartition (int nr) { partitionNumber = nr; }; #else int GetPartition () const { return 0; } #endif */ void DoArchive (Archive & ar); }; ostream & operator<<(ostream & s, const Segment & seg); class Element0d { public: PointIndex pnum; string name; int index; Element0d () = default; Element0d (PointIndex _pnum, int _index) : pnum(_pnum), index(_index) { ; } }; ostream & operator<<(ostream & s, const Element0d & el); // class Surface; // class FaceDescriptor; /// class FaceDescriptor { /// which surface, 0 if not available int surfnr; /// domain nr inside int domin; /// domain nr outside int domout; /// top level object number of surface int tlosurf; /// boundary condition property int bcprop; // Philippose - 06/07/2009 // Add capability to store surface colours along with // other face data /// surface colour (Default: R=0.0 ; G=1.0 ; B=0.0) Vec3d surfcolour; /// static string default_bcname; string * bcname = &default_bcname; /// root of linked list SurfaceElementIndex firstelement; double domin_singular; double domout_singular; public: DLL_HEADER FaceDescriptor(); DLL_HEADER FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi); DLL_HEADER FaceDescriptor(const Segment & seg); DLL_HEADER FaceDescriptor(const FaceDescriptor& other); DLL_HEADER ~FaceDescriptor() { ; } DLL_HEADER int SegmentFits (const Segment & seg); int SurfNr () const { return surfnr; } int DomainIn () const { return domin; } int DomainOut () const { return domout; } int TLOSurface () const { return tlosurf; } int BCProperty () const { return bcprop; } double DomainInSingular() const { return domin_singular; } double DomainOutSingular() const { return domout_singular; } // Philippose - 06/07/2009 // Get Surface colour Vec3d SurfColour () const { return surfcolour; } DLL_HEADER const string & GetBCName () const { return *bcname; } // string * BCNamePtr () { return bcname; } // const string * BCNamePtr () const { return bcname; } void SetSurfNr (int sn) { surfnr = sn; } void SetDomainIn (int di) { domin = di; } void SetDomainOut (int dom) { domout = dom; } void SetBCProperty (int bc) { bcprop = bc; } void SetBCName (string * bcn); // { bcname = bcn; } // Philippose - 06/07/2009 // Set the surface colour void SetSurfColour (Vec3d colour) { surfcolour = colour; } void SetDomainInSingular (double v) { domin_singular = v; } void SetDomainOutSingular (double v) { domout_singular = v; } SurfaceElementIndex FirstElement() { return firstelement; } // friend ostream & operator<<(ostream & s, const FaceDescriptor & fd); friend class Mesh; void DoArchive (Archive & ar); }; ostream & operator<< (ostream & s, const FaceDescriptor & fd); class EdgeDescriptor { int tlosurf; int surfnr[2]; public: EdgeDescriptor () : tlosurf(-1) { surfnr[0] = surfnr[1] = -1; } int SurfNr (int i) const { return surfnr[i]; } void SetSurfNr (int i, int nr) { surfnr[i] = nr; } int TLOSurface() const { return tlosurf; } void SetTLOSurface (int nr) { tlosurf = nr; } }; class DLL_HEADER MeshingParameters { public: /** 3d optimization strategy: // m .. move nodes // M .. move nodes, cheap functional // s .. swap faces // c .. combine elements // d .. divide elements // p .. plot, no pause // P .. plot, Pause // h .. Histogramm, no pause // H .. Histogramm, pause */ string optimize3d = "cmdmustm"; /// number of 3d optimization steps int optsteps3d = 3; /** 2d optimization strategy: // s .. swap, opt 6 lines/node // S .. swap, optimal elements // m .. move nodes // p .. plot, no pause // P .. plot, pause // c .. combine **/ string optimize2d = "smsmsmSmSmSm"; /// number of 2d optimization steps int optsteps2d = 3; /// power of error (to approximate max err optimization) double opterrpow = 2; /// do block filling ? int blockfill = 1; /// block filling up to distance double filldist = 0.1; /// radius of local environment (times h) double safety = 5; /// radius of active environment (times h) double relinnersafety = 3; /// use local h ? int uselocalh = 1; /// grading for local h double grading = 0.3; /// use delaunay meshing int delaunay = 1; /// maximal mesh size double maxh = 1e10; /// minimal mesh size double minh = 0.0; /// file for meshsize string meshsizefilename = ""; /// start surfacemeshing from everywhere in surface int startinsurface = 0; /// check overlapping surfaces (debug) int checkoverlap = 1; /// check overlapping surface mesh before volume meshing int checkoverlappingboundary = 1; /// check chart boundary (sometimes too restrictive) int checkchartboundary = 1; /// safety factor for curvatures (elements per radius) double curvaturesafety = 2; /// minimal number of segments per edge double segmentsperedge = 1; /// use parallel threads int parthread = 0; /// weight of element size w.r.t element shape double elsizeweight = 0.2; /// init with default values /// start at step int perfstepsstart = 0; /// end at step int perfstepsend = 6; /// from mp3: /// give up quality class, 2d meshing int giveuptol2d = 200; /// give up quality class, 3d meshing int giveuptol = 10; /// maximal outer steps int maxoutersteps = 10; /// class starting star-shape filling int starshapeclass = 5; /// if non-zero, baseelement must have baseelnp points int baseelnp = 0; /// quality tolerances are handled less careful int sloppy = 1; /// limit for max element angle (150-180) double badellimit = 175; bool check_impossible = 0; int only3D_domain_nr = 0; /// int secondorder = 0; /// high order element curvature int elementorder = 1; /// quad-dominated surface meshing int quad = 0; /// bool try_hexes = false; /// int inverttets = 0; /// int inverttrigs = 0; /// int autozrefine = 0; /// MeshingParameters (); /// MeshingParameters (const MeshingParameters & mp2) = default; MeshingParameters (MeshingParameters && mp2) = default; MeshingParameters & operator= (const MeshingParameters & mp2) = default; MeshingParameters & operator= (MeshingParameters && mp2) = default; /// void Print (ostream & ost) const; /// // void CopyFrom(const MeshingParameters & other); class MeshSizePoint { public: Point<3> pnt; double h; MeshSizePoint (Point<3> _pnt, double _h) : pnt(_pnt), h(_h) { ; } MeshSizePoint () = default; MeshSizePoint (const MeshSizePoint &) = default; MeshSizePoint (MeshSizePoint &&) = default; MeshSizePoint & operator= (const MeshSizePoint &) = default; MeshSizePoint & operator= (MeshSizePoint &&) = default; }; Array meshsize_points; void (*render_function)(bool) = NULL; void Render(bool blocking = false) { if (render_function) (*render_function)(blocking); } }; inline ostream & operator<< (ostream & ost, const MeshingParameters & mp) { mp.Print (ost); return ost; } class DebugParameters { public: /// int debugoutput; /// use slow checks int slowchecks; /// int haltsuccess; /// int haltnosuccess; /// int haltlargequalclass; /// int haltsegment; /// int haltnode; /// int haltsegmentp1; /// int haltsegmentp2; /// int haltexistingline; /// int haltoverlap; /// int haltface; /// int haltfacenr; /// DebugParameters (); }; inline void Element2d :: Invert() { if (typ == TRIG) Swap (PNum(2), PNum(3)); else Invert2(); } inline void Element2d :: NormalizeNumbering () { if (GetNP() == 3) { if (PNum(1) < PNum(2) && PNum(1) < PNum(3)) return; else { if (PNum(2) < PNum(3)) { PointIndex pi1 = PNum(2); PNum(2) = PNum(3); PNum(3) = PNum(1); PNum(1) = pi1; } else { PointIndex pi1 = PNum(3); PNum(3) = PNum(2); PNum(2) = PNum(1); PNum(1) = pi1; } } } else NormalizeNumbering2(); } static const int gftetfacesa[4][3] = { { 1, 2, 3 }, { 2, 0, 3 }, { 0, 1, 3 }, { 1, 0, 2 } }; inline void Element :: GetFace (int i, Element2d & face) const { if (typ == TET) { face.SetType(TRIG); face[0] = pnum[gftetfacesa[i-1][0]]; face[1] = pnum[gftetfacesa[i-1][1]]; face[2] = pnum[gftetfacesa[i-1][2]]; } else GetFace2 (i, face); } /** Identification of periodic surfaces, close surfaces, etc. */ class Identifications { public: enum ID_TYPE : unsigned char { UNDEFINED = 1, PERIODIC = 2, CLOSESURFACES = 3, CLOSEEDGES = 4}; private: class Mesh & mesh; /// identify points (thin layers, periodic b.c.) INDEX_2_HASHTABLE identifiedpoints; /// the same, with info about the id-nr INDEX_3_HASHTABLE identifiedpoints_nr; /// sorted by identification nr TABLE idpoints_table; Array type; /// number of identifications (or, actually used identifications ?) int maxidentnr; public: /// DLL_HEADER Identifications (class Mesh & amesh); /// DLL_HEADER ~Identifications (); DLL_HEADER void Delete (); /* Identify points pi1 and pi2, due to identification nr identnr */ DLL_HEADER void Add (PointIndex pi1, PointIndex pi2, int identnr); int Get (PointIndex pi1, PointIndex pi2) const; int GetSymmetric (PointIndex pi1, PointIndex pi2) const; bool Get (PointIndex pi1, PointIndex pi2, int identnr) const; bool GetSymmetric (PointIndex pi1, PointIndex pi2, int identnr) const; // bool HasIdentifiedPoints() const { return identifiedpoints != nullptr; } /// INDEX_2_HASHTABLE & GetIdentifiedPoints () { return identifiedpoints; } bool Used (PointIndex pi1, PointIndex pi2) { return identifiedpoints.Used (INDEX_2 (pi1, pi2)); } bool UsedSymmetric (PointIndex pi1, PointIndex pi2) { return identifiedpoints.Used (INDEX_2 (pi1, pi2)) || identifiedpoints.Used (INDEX_2 (pi2, pi1)); } /// void GetMap (int identnr, Array & identmap, bool symmetric = false) const; /// ID_TYPE GetType(int identnr) const { if(identnr <= type.Size()) return type[identnr-1]; else return UNDEFINED; } void SetType(int identnr, ID_TYPE t) { while(type.Size() < identnr) type.Append(UNDEFINED); type[identnr-1] = t; } /// void GetPairs (int identnr, Array & identpairs) const; /// int GetMaxNr () const { return maxidentnr; } /// remove secondorder void SetMaxPointNr (int maxpnum); DLL_HEADER void Print (ostream & ost) const; void DoArchive (Archive & ar); }; } #endif netgen-6.2.1905/libsrc/meshing/basegeom.hpp0000644000175000017500000000340613504650527017207 0ustar kurtkurt#ifndef FILE_BASEGEOM #define FILE_BASEGEOM /**************************************************************************/ /* File: basegeom.hpp */ /* Author: Joachim Schoeberl */ /* Date: 23. Aug. 09 */ /**************************************************************************/ struct Tcl_Interp; namespace netgen { class DLL_HEADER NetgenGeometry { public: virtual ~NetgenGeometry () { ; } virtual int GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam); virtual const Refinement & GetRefinement () const; virtual void DoArchive(Archive&) { throw NgException("DoArchive not implemented for " + Demangle(typeid(*this).name())); } virtual void Save (string filename) const; virtual void SaveToMeshFile (ostream & /* ost */) const { ; } }; class DLL_HEADER GeometryRegister { public: virtual ~GeometryRegister(); virtual NetgenGeometry * Load (string filename) const = 0; virtual NetgenGeometry * LoadFromMeshFile (istream & /* ist */) const { return NULL; } virtual class VisualScene * GetVisualScene (const NetgenGeometry * /* geom */) const { return NULL; } virtual void SetParameters (Tcl_Interp * /* interp */) { ; } }; class DLL_HEADER GeometryRegisterArray : public Array { public: virtual ~GeometryRegisterArray() { for (int i = 0; i < Size(); i++) delete (*this)[i]; } virtual shared_ptr LoadFromMeshFile (istream & ist) const; }; // extern DLL_HEADER Array geometryregister; extern DLL_HEADER GeometryRegisterArray geometryregister; } #endif netgen-6.2.1905/libsrc/meshing/hpref_tet.hpp0000644000175000017500000014164513504650527017415 0ustar kurtkurt // HP_TET int reftet_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_newelstypes[] = { HP_TET, HP_NONE, }; int reftet_newels[][8] = { { 1, 2, 3, 4 }, }; HPRef_Struct reftet = { HP_TET, reftet_splitedges, 0, 0, reftet_newelstypes, reftet_newels }; /* *********** Tet - Refinement - 0 edges *************** */ // HP_TET_0E_1V int reftet_0e_1v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_0e_1v_newelstypes[] = { HP_TET_0E_1V, HP_PRISM, HP_NONE, }; int reftet_0e_1v_newels[][8] = { { 1, 5, 6, 7 }, { 5, 6, 7, 2, 3, 4 } }; HPRef_Struct reftet_0e_1v = { HP_TET, reftet_0e_1v_splitedges, 0, 0, reftet_0e_1v_newelstypes, reftet_0e_1v_newels }; // HP_TET_0E_2V int reftet_0e_2v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_0e_2v_newelstypes[] = { HP_TET_0E_1V, HP_TET_0E_1V, HP_PRISM, HP_PRISM, HP_NONE, }; int reftet_0e_2v_newels[][8] = { { 1, 5, 6, 7 }, { 2, 10, 9, 8 }, { 5, 6, 7, 8, 9, 10 }, { 4, 10, 7, 3, 9, 6 }, }; HPRef_Struct reftet_0e_2v = { HP_TET, reftet_0e_2v_splitedges, 0, 0, reftet_0e_2v_newelstypes, reftet_0e_2v_newels }; // HP_TET_0E_3V int reftet_0e_3v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 0, 0, 0 } }; int reftet_0e_3v_splitfaces[][4] = { { 1, 2, 3, 14 }, { 2, 3, 1, 15 }, { 3, 1, 2, 16 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE reftet_0e_3v_newelstypes[] = { HP_PYRAMID_0E_1V, HP_PYRAMID_0E_1V, HP_PYRAMID_0E_1V, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_TET, HP_NONE, }; int reftet_0e_3v_newels[][8] = { { 1, 5, 14, 6, 7 }, { 2, 9, 15, 8, 10 }, { 3, 11, 16, 12, 13 }, { 5, 14, 7, 8, 15, 10 }, { 9, 15, 10, 12, 16, 13 }, { 6, 7, 14, 11, 13, 16 }, { 14, 15, 16, 7, 10, 13 }, { 7, 10, 13, 4 } }; HPRef_Struct reftet_0e_3v = { HP_TET, reftet_0e_3v_splitedges, reftet_0e_3v_splitfaces, 0, reftet_0e_3v_newelstypes, reftet_0e_3v_newels }; // HP_TET_0E_4V int reftet_0e_4v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_0e_4v_splitfaces[][4] = { { 1, 2, 3, 17 }, { 1, 2, 4, 18 }, { 1, 3, 4, 19 }, { 2, 1, 3, 20 }, { 2, 1, 4, 21 }, { 2, 3, 4, 22 }, { 3, 1, 2, 23 }, { 3, 1, 4, 24 }, { 3, 2, 4, 25 }, { 4, 1, 2, 26 }, { 4, 1, 3, 27 }, { 4, 2, 3, 28 }, { 0, 0, 0, 0 }, }; int reftet_0e_4v_splitelements[][5] = { { 1, 2, 3, 4, 29 }, { 2, 3, 4, 1, 30 }, { 3, 4, 1, 2, 31 }, { 4, 1, 2, 3, 32 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_0e_4v_newelstypes[] = { HP_HEX_0E_1V, HP_HEX_0E_1V, HP_HEX_0E_1V, HP_HEX_0E_1V, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_TET, HP_NONE, }; int reftet_0e_4v_newels[][8] = { { 1, 5, 17, 6, 7, 18, 29, 19 }, { 2, 9, 20, 8, 10, 22, 30, 21 }, { 3, 11, 23, 12, 13, 24, 31, 25 }, { 4, 15, 26, 14, 16, 28, 32, 27 }, { 5, 17, 18, 8, 20, 21 }, { 18, 17, 29, 21, 20, 30 }, { 6, 19, 17, 11, 24, 23 }, { 17, 19, 29, 23, 24, 31 }, { 7, 18, 19, 14, 26, 27 }, { 19, 18, 29, 27, 26, 32 }, { 9, 20, 22, 12, 23, 25 }, { 22, 20, 30, 25, 23, 31 }, { 10, 22, 21, 15, 28, 26 }, { 21, 22, 30, 26, 28, 32 }, { 13, 24, 25, 16, 27, 28 }, { 25, 24, 31, 28, 27, 32 }, { 17, 20, 23, 29, 30, 31 }, { 18, 26, 21, 29, 32, 30 }, { 19, 24, 27, 29, 31, 32 }, { 22, 28, 25, 30, 32, 31 }, { 29, 30, 31, 32 }, }; HPRef_Struct reftet_0e_4v = { HP_TET, reftet_0e_4v_splitedges, reftet_0e_4v_splitfaces, reftet_0e_4v_splitelements, reftet_0e_4v_newelstypes, reftet_0e_4v_newels }; /* *********** Tet - Refinement - 1 edge *************** */ // HP_TET_1E_0V int reftet_1e_0v_splitedges[][3] = { { 1, 3, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 2, 4, 8 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1e_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM, HP_NONE, }; int reftet_1e_0v_newels[][8] = { { 1, 5, 6, 2, 7, 8 }, { 7, 3, 5, 8, 4, 6 } }; HPRef_Struct reftet_1e_0v = { HP_TET, reftet_1e_0v_splitedges, 0, 0, reftet_1e_0v_newelstypes, reftet_1e_0v_newels }; // HP_TET_1E_1VA int reftet_1e_1va_splitedges[][3] = { { 1, 3, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 2, 4, 8 }, { 1, 2, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1e_1va_newelstypes[] = { HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_NONE, }; int reftet_1e_1va_newels[][8] = { { 1, 9, 5, 6 }, { 9, 5, 6, 2, 7, 8 }, { 7, 3, 5, 8, 4, 6 } }; HPRef_Struct reftet_1e_1va = { HP_TET, reftet_1e_1va_splitedges, 0, 0, reftet_1e_1va_newelstypes, reftet_1e_1va_newels }; // HP_TET_1E_1VB int reftet_1e_1vb_splitedges[][3] = { { 1, 3, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 2, 4, 8 }, { 4, 1, 9 }, { 4, 2, 10 }, { 4, 3, 11 }, { 0, 0, 0 } }; int reftet_1e_1vb_splitelements[][5] = { { 4, 1, 2, 3, 12 }, { 0 } }; HPREF_ELEMENT_TYPE reftet_1e_1vb_newelstypes[] = { HP_PRISM_SINGEDGE, HP_TET_0E_1V, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_NONE, }; int reftet_1e_1vb_newels[][8] = { { 1, 5, 6, 2, 7, 8 }, { 4, 11, 10, 9 }, { 7, 8, 10, 11, 12 }, { 3, 7, 11, 12 }, { 5, 11, 9, 6, 12 }, { 5, 3, 11, 12 }, { 6, 9, 10, 8, 12 }, { 5, 7, 3, 12 }, { 5, 6, 8, 7, 12 }, { 9, 11, 10, 12 } }; HPRef_Struct reftet_1e_1vb = { HP_TET, reftet_1e_1vb_splitedges, 0, reftet_1e_1vb_splitelements, reftet_1e_1vb_newelstypes, reftet_1e_1vb_newels }; // HP_TET_1E_2VA int reftet_1e_2va_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1e_2va_newelstypes[] = { HP_TET_1E_1VA, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_NONE, }; int reftet_1e_2va_newels[][8] = { { 1, 5, 6, 7 }, { 2, 8, 10, 9 }, { 5, 6, 7, 8, 9, 10 }, { 4, 10, 7, 3, 9, 6 }, }; HPRef_Struct reftet_1e_2va = { HP_TET, reftet_1e_2va_splitedges, 0, 0, reftet_1e_2va_newelstypes, reftet_1e_2va_newels }; // HP_TET_1E_2VB int reftet_1e_2vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 1, 10 }, { 3, 2, 11 }, { 3, 4, 12 }, { 0, 0, 0 } }; int reftet_1e_2vb_splitelements[][5] = { { 3, 4, 1, 2, 13 }, { 0 } }; HPREF_ELEMENT_TYPE reftet_1e_2vb_newelstypes[] = { HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_TET_0E_1V, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_NONE, }; int reftet_1e_2vb_newels[][8] = { { 1, 5, 6, 7 }, { 5, 6, 7, 2, 8, 9 }, { 3, 10, 11, 12 }, { 8, 9, 12, 11, 13 }, { 4, 12, 9, 13 }, { 6, 10, 12, 7, 13 }, { 4, 7, 12, 13 }, { 6, 8, 11, 10, 13 }, { 4, 9, 7, 13 }, { 6, 7, 9, 8, 13 }, { 10, 11, 12, 13 }, }; HPRef_Struct reftet_1e_2vb = { HP_TET, reftet_1e_2vb_splitedges, 0, reftet_1e_2vb_splitelements, reftet_1e_2vb_newelstypes, reftet_1e_2vb_newels }; // HP_TET_1E_2VC int reftet_1e_2vc_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 4, 1, 10 }, { 4, 2, 11 }, { 4, 3, 12 }, { 0, 0, 0 } }; int reftet_1e_2vc_splitelements[][5] = { { 4, 1, 2, 3, 13 }, { 0 } }; HPREF_ELEMENT_TYPE reftet_1e_2vc_newelstypes[] = { HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_TET_0E_1V, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_NONE, }; int reftet_1e_2vc_newels[][8] = { { 1, 5, 6, 7 }, { 5, 6, 7, 2, 8, 9 }, { 4, 11, 10, 12 }, { 8, 9, 11, 12, 13 }, { 3, 8, 12, 13 }, { 7, 6, 12, 10, 13 }, { 3, 12, 6, 13 }, { 9, 7, 10, 11, 13 }, { 3, 6, 8, 13 }, { 6, 7, 9, 8, 13 }, { 10, 12, 11, 13 } }; HPRef_Struct reftet_1e_2vc = { HP_TET, reftet_1e_2vc_splitedges, 0, reftet_1e_2vc_splitelements, reftet_1e_2vc_newelstypes, reftet_1e_2vc_newels }; /* // HP_TET_1E_2VD int reftet_1e_2vd_splitedges[][3] = { { 1, 3, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 2, 4, 8 }, { 3, 1, 9 }, { 3, 2, 10 }, { 3, 4, 11 }, { 4, 1, 12 }, { 4, 2, 13 }, { 4, 3, 14 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1e_2vd_newelstypes[] = { HP_PRISM_SINGEDGE, HP_TET_0E_1V, HP_TET_0E_1V, HP_PRISM, HP_HEX, HP_NONE, }; int reftet_1e_2vd_newels[][8] = { { 1, 5, 6, 2, 7, 8 }, { 4, 13, 12, 14 }, { 3, 10, 11, 9 }, { 14, 13, 12, 11, 10, 9 }, { 6, 12, 13, 8, 5, 9, 10, 7 }, }; HPRef_Struct reftet_1e_2vd = { HP_TET, reftet_1e_2vd_splitedges, 0, 0, reftet_1e_2vd_newelstypes, reftet_1e_2vd_newels }; */ // HP_TET_1E_2VD, // 1 v on edge int reftet_1e_2vd_splitedges[][3] = { // { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, // { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_1e_2vd_splitfaces[][4] = { { 1, 3, 4, 19 }, { 2, 3, 4, 22 }, { 3, 1, 4, 24 }, { 3, 2, 4, 25 }, { 4, 1, 3, 27 }, { 4, 2, 3, 28 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1e_2vd_newelstypes[] = { HP_PRISM_SINGEDGE, HP_TET_0E_1V, HP_TET_0E_1V, HP_PRISM, HP_HEX, HP_PYRAMID, HP_HEX, HP_PYRAMID, HP_PRISM, HP_PRISM, HP_NONE, }; int reftet_1e_2vd_newels[][8] = { { 1, 6, 7, 2, 9, 10 }, { 3, 11, 12, 13 }, { 4, 16, 15, 14 }, { 7, 6, 19, 10, 9, 22 }, { 7, 19, 27, 14, 10, 22, 28, 15 }, { 14, 15, 28, 27, 16 }, { 9, 6, 19, 22, 12, 11, 24, 25 }, { 12, 11, 24, 25, 13 }, { 19, 24, 27, 22, 25, 28 }, { 16, 28, 27, 13, 25, 24 } }; HPRef_Struct reftet_1e_2vd = { HP_TET, reftet_1e_2vd_splitedges, reftet_1e_2vd_splitfaces, 0, reftet_1e_2vd_newelstypes, reftet_1e_2vd_newels }; // HP_TET_1E_3VA int reftet_1e_3va_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 0, 0, 0 } }; int reftet_1e_3va_splitelements[][5] = { { 1, 2, 3, 4, 14 }, { 0 } }; HPREF_ELEMENT_TYPE reftet_1e_3va_newelstypes[] = { HP_PRISM_SINGEDGE, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_TET_0E_1V, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_TET, HP_NONE, }; int reftet_1e_3va_newels[][8] = { { 5, 6, 7, 8, 9, 10 }, { 1, 5, 6, 7 }, { 2, 8, 10, 9 }, { 3, 11, 12, 13 }, { 6, 7, 10, 9, 14 }, { 4, 10, 7, 14 }, { 9, 10, 13, 12, 14 }, { 4, 13, 10, 14 }, { 6, 11, 13, 7, 14 }, { 4, 7, 13, 14 }, { 6, 11, 12, 9, 14 }, { 11, 13, 12, 14 }, }; HPRef_Struct reftet_1e_3va = { HP_TET, reftet_1e_3va_splitedges, 0, reftet_1e_3va_splitelements, reftet_1e_3va_newelstypes, reftet_1e_3va_newels }; // HP_TET_1E_3VB, // 1 v on edge int reftet_1e_3vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, // { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_1e_3vb_splitfaces[][4] = { { 1, 3, 4, 19 }, { 2, 3, 4, 22 }, { 3, 1, 4, 24 }, { 3, 2, 4, 25 }, { 4, 1, 3, 27 }, { 4, 2, 3, 28 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1e_3vb_newelstypes[] = { HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_TET_0E_1V, HP_TET_0E_1V, HP_PRISM, HP_HEX, HP_PYRAMID, HP_HEX, HP_PYRAMID, HP_PRISM, HP_PRISM, HP_NONE, }; int reftet_1e_3vb_newels[][8] = { { 1, 5, 6, 7 }, { 5, 6, 7, 2, 9, 10 }, { 3, 11, 12, 13 }, { 4, 16, 15, 14 }, { 7, 6, 19, 10, 9, 22 }, { 7, 19, 27, 14, 10, 22, 28, 15 }, { 14, 15, 28, 27, 16 }, { 9, 6, 19, 22, 12, 11, 24, 25 }, { 12, 11, 24, 25, 13 }, { 19, 24, 27, 22, 25, 28 }, { 16, 28, 27, 13, 25, 24 } }; HPRef_Struct reftet_1e_3vb = { HP_TET, reftet_1e_3vb_splitedges, reftet_1e_3vb_splitfaces, 0, reftet_1e_3vb_newelstypes, reftet_1e_3vb_newels }; /* // HP_TET_1E_4V int reftet_1e_4v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_1e_4v_splitfaces[][4] = { { 1, 2, 3, 17 }, { 1, 2, 4, 18 }, { 1, 3, 4, 19 }, { 2, 1, 3, 20 }, { 2, 1, 4, 21 }, { 2, 3, 4, 22 }, { 3, 1, 2, 23 }, { 3, 1, 4, 24 }, { 3, 2, 4, 25 }, { 4, 1, 2, 26 }, { 4, 1, 3, 27 }, { 4, 2, 3, 28 }, { 0, 0, 0, 0 }, }; int reftet_1e_4v_splitelements[][5] = { { 1, 2, 3, 4, 29 }, { 2, 3, 4, 1, 30 }, { 3, 4, 1, 2, 31 }, { 4, 1, 2, 3, 32 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_1e_4v_newelstypes[] = { HP_HEX_1E_1V, HP_HEX_1E_1V, HP_HEX_0E_1V, HP_HEX_0E_1V, HP_PRISM_SINGEDGE, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_TET, HP_NONE, }; int reftet_1e_4v_newels[][8] = { { 1, 5, 17, 6, 7, 18, 29, 19 }, // { 2, 9, 20, 8, 10, 22, 30, 21 }, { 2, 8, 21, 10, 9, 20, 30, 22 }, { 3, 11, 23, 12, 13, 24, 31, 25 }, { 4, 15, 26, 14, 16, 28, 32, 27 }, { 5, 17, 18, 8, 20, 21 }, { 18, 17, 29, 21, 20, 30 }, { 6, 19, 17, 11, 24, 23 }, { 17, 19, 29, 23, 24, 31 }, { 7, 18, 19, 14, 26, 27 }, { 19, 18, 29, 27, 26, 32 }, { 9, 20, 22, 12, 23, 25 }, { 22, 20, 30, 25, 23, 31 }, { 10, 22, 21, 15, 28, 26 }, { 21, 22, 30, 26, 28, 32 }, { 13, 24, 25, 16, 27, 28 }, { 25, 24, 31, 28, 27, 32 }, { 17, 20, 23, 29, 30, 31 }, { 18, 26, 21, 29, 32, 30 }, { 19, 24, 27, 29, 31, 32 }, { 22, 28, 25, 30, 32, 31 }, { 29, 30, 31, 32 }, }; HPRef_Struct reftet_1e_4v = { HP_TET, reftet_1e_4v_splitedges, reftet_1e_4v_splitfaces, reftet_1e_4v_splitelements, reftet_1e_4v_newelstypes, reftet_1e_4v_newels }; */ // HP_TET_1E_4V int reftet_1e_4v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_1e_4v_splitfaces[][4] = { { 1, 3, 4, 17 }, { 2, 3, 4, 18 }, { 3, 1, 4, 19 }, { 3, 2, 4, 20 }, { 4, 1, 3, 21 }, { 4, 2, 3, 22 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE reftet_1e_4v_newelstypes[] = { HP_TET_1E_1VA, HP_TET_1E_1VA, // HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_HEX, HP_HEX, HP_PRISM, HP_PRISM, HP_PYRAMID, HP_TET_0E_1V, HP_PYRAMID, HP_TET_0E_1V, HP_NONE, }; int reftet_1e_4v_newels[][8] = { { 1, 5, 6, 7 }, { 2, 8, 10, 9 }, { 5, 6, 7, 8, 9, 10 }, { 7, 6, 17, 10, 9, 18 }, { 7, 10, 18, 17, 14, 15, 22, 21 }, { 9, 6, 17, 18, 12, 11, 19, 20 }, { 17, 19, 21, 18, 20, 22 }, { 16, 22, 21, 13, 20, 19 }, { 14, 15, 22, 21, 16 }, { 4, 14, 16, 15 }, { 12, 11, 19, 20, 13 }, { 3, 11, 12, 13 }, { 1, 5, 17, 6, 7, 18, 29, 19 }, // { 2, 9, 20, 8, 10, 22, 30, 21 }, { 2, 8, 21, 10, 9, 20, 30, 22 }, { 3, 11, 23, 12, 13, 24, 31, 25 }, { 4, 15, 26, 14, 16, 28, 32, 27 }, { 5, 17, 18, 8, 20, 21 }, { 18, 17, 29, 21, 20, 30 }, { 6, 19, 17, 11, 24, 23 }, { 17, 19, 29, 23, 24, 31 }, { 7, 18, 19, 14, 26, 27 }, { 19, 18, 29, 27, 26, 32 }, { 9, 20, 22, 12, 23, 25 }, { 22, 20, 30, 25, 23, 31 }, { 10, 22, 21, 15, 28, 26 }, { 21, 22, 30, 26, 28, 32 }, { 13, 24, 25, 16, 27, 28 }, { 25, 24, 31, 28, 27, 32 }, { 17, 20, 23, 29, 30, 31 }, { 18, 26, 21, 29, 32, 30 }, { 19, 24, 27, 29, 31, 32 }, { 22, 28, 25, 30, 32, 31 }, { 29, 30, 31, 32 }, }; HPRef_Struct reftet_1e_4v = { HP_TET, reftet_1e_4v_splitedges, reftet_1e_4v_splitfaces, 0, reftet_1e_4v_newelstypes, reftet_1e_4v_newels }; // HP_TET_2EA_0V, // 2 edges connected int reftet_2ea_0v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 2, 12 }, { 3, 4, 13 }, { 0, 0, 0 } }; int reftet_2ea_0v_splitfaces[][4] = { { 1, 2, 3, 17 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_0v_newelstypes[] = { HP_PYRAMID_EDGES, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM, HP_TET, HP_NONE, }; int reftet_2ea_0v_newels[][8] = { { 1, 5, 17, 6, 7 }, { 5, 17, 7, 2, 9, 10 }, { 6, 7, 17, 3, 13, 12 }, { 17, 9, 12, 7, 10, 13 }, { 7, 10, 13, 4 }, }; HPRef_Struct reftet_2ea_0v = { HP_TET, reftet_2ea_0v_splitedges, reftet_2ea_0v_splitfaces, 0, reftet_2ea_0v_newelstypes, reftet_2ea_0v_newels }; // HP_TET_2EA_1VA, // 2 edges connected int reftet_2ea_1va_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 2, 12 }, { 3, 4, 13 }, { 0, 0, 0 } }; int reftet_2ea_1va_splitfaces[][4] = { { 1, 2, 3, 17 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_1va_newelstypes[] = { HP_PYRAMID_EDGES, HP_PRISM_SINGEDGE, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_TET, HP_NONE, }; int reftet_2ea_1va_newels[][8] = { { 1, 5, 17, 6, 7 }, { 5, 17, 7, 8, 9, 10 }, { 2, 8, 10, 9 }, { 6, 7, 17, 3, 13, 12 }, { 17, 9, 12, 7, 10, 13 }, { 7, 10, 13, 4 }, }; HPRef_Struct reftet_2ea_1va = { HP_TET, reftet_2ea_1va_splitedges, reftet_2ea_1va_splitfaces, 0, reftet_2ea_1va_newelstypes, reftet_2ea_1va_newels }; // HP_TET_2EA_1VB, int reftet_2ea_1vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 0, 0, 0 } }; int reftet_2ea_1vb_splitfaces[][4] = { { 1, 2, 3, 17 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_1vb_newelstypes[] = { HP_PYRAMID_EDGES, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM, HP_TET, HP_NONE, }; int reftet_2ea_1vb_newels[][8] = { { 1, 5, 17, 6, 7 }, { 3, 11, 12, 13 }, { 5, 17, 7, 2, 9, 10 }, { 6, 7, 17, 11, 13, 12 }, { 17, 9, 12, 7, 10, 13 }, { 7, 10, 13, 4 }, }; HPRef_Struct reftet_2ea_1vb = { HP_TET, reftet_2ea_1vb_splitedges, reftet_2ea_1vb_splitfaces, 0, reftet_2ea_1vb_newelstypes, reftet_2ea_1vb_newels }; // HP_TET_2EA_1VC, // 2 edges connected int reftet_2ea_1vc_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, // { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_2ea_1vc_splitfaces[][4] = { { 1, 2, 3, 17 }, { 2, 3, 4, 18 }, { 3, 4, 2, 19 }, { 4, 2, 3, 20 }, { 0, 0, 0, 0 } }; int reftet_2ea_1vc_splitelements[][5] = { { 1, 2, 3, 4, 21 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_1vc_newelstypes[] = { HP_PYRAMID_EDGES, // HP_TET_1E_1VA, HP_TET_0E_1V, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET, HP_TET, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_TET, // HP_PRISM, // HP_PRISM, HP_NONE, }; int reftet_2ea_1vc_newels[][8] = { { 1, 5, 17, 6, 7 }, // { 3, 11, 12, 13 }, { 4, 15, 14, 16 }, { 5, 17, 7, 2, 9, 10 }, { 6, 7, 17, 3, 13, 12 }, { 9, 10, 18, 21 }, { 13, 12, 19, 21 }, { 15, 16, 20, 21 }, { 18, 20, 19, 21 }, { 10, 15, 20, 18, 21 }, { 13, 19, 20, 16, 21 }, { 9, 18, 19, 12, 21 }, { 7, 13, 16, 14, 21 }, { 7, 14, 15, 10, 21 }, { 9, 12, 17, 21 }, { 7, 10, 9, 17, 21 }, { 7, 17, 12, 13, 21 }, { 14, 16, 15, 21 }, // { 17, 9, 12, 7, 10, 13 }, // { 7, 10, 13, 14, 15, 16 }, }; HPRef_Struct reftet_2ea_1vc = { HP_TET, reftet_2ea_1vc_splitedges, reftet_2ea_1vc_splitfaces, reftet_2ea_1vc_splitelements, reftet_2ea_1vc_newelstypes, reftet_2ea_1vc_newels }; // HP_TET_2EA_2VA, int reftet_2ea_2va_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 0, 0, 0 } }; int reftet_2ea_2va_splitfaces[][4] = { { 1, 2, 3, 17 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_2va_newelstypes[] = { HP_PYRAMID_EDGES, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM, HP_TET, HP_NONE, }; int reftet_2ea_2va_newels[][8] = { { 1, 5, 17, 6, 7 }, { 3, 11, 12, 13 }, { 2, 8, 10, 9 }, { 5, 17, 7, 8, 9, 10 }, { 6, 7, 17, 11, 13, 12 }, { 17, 9, 12, 7, 10, 13 }, { 7, 10, 13, 4 }, }; HPRef_Struct reftet_2ea_2va = { HP_TET, reftet_2ea_2va_splitedges, reftet_2ea_2va_splitfaces, 0, reftet_2ea_2va_newelstypes, reftet_2ea_2va_newels }; // HP_TET_2EA_2VB, // 2 edges connected int reftet_2ea_2vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, // { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_2ea_2vb_splitfaces[][4] = { { 1, 2, 3, 17 }, { 2, 3, 4, 18 }, { 3, 4, 2, 19 }, { 4, 2, 3, 20 }, { 0, 0, 0, 0 } }; int reftet_2ea_2vb_splitelements[][5] = { { 1, 2, 3, 4, 21 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_2vb_newelstypes[] = { HP_PYRAMID_EDGES, HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_TET_0E_1V, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET, HP_TET, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_TET, // HP_PRISM, // HP_PRISM, HP_NONE, }; int reftet_2ea_2vb_newels[][8] = { { 1, 5, 17, 6, 7 }, { 2, 8, 10, 9 }, // { 3, 11, 12, 13 }, { 4, 15, 14, 16 }, { 5, 17, 7, 8, 9, 10 }, { 6, 7, 17, 3, 13, 12 }, { 9, 10, 18, 21 }, { 13, 12, 19, 21 }, { 15, 16, 20, 21 }, { 18, 20, 19, 21 }, { 10, 15, 20, 18, 21 }, { 13, 19, 20, 16, 21 }, { 9, 18, 19, 12, 21 }, { 7, 13, 16, 14, 21 }, { 7, 14, 15, 10, 21 }, { 9, 12, 17, 21 }, { 7, 10, 9, 17, 21 }, { 7, 17, 12, 13, 21 }, { 14, 16, 15, 21 }, // { 17, 9, 12, 7, 10, 13 }, // { 7, 10, 13, 14, 15, 16 }, }; HPRef_Struct reftet_2ea_2vb = { HP_TET, reftet_2ea_2vb_splitedges, reftet_2ea_2vb_splitfaces, reftet_2ea_2vb_splitelements, reftet_2ea_2vb_newelstypes, reftet_2ea_2vb_newels }; // HP_TET_2EA_2VC, // 2 edges connected int reftet_2ea_2vc_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, // { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_2ea_2vc_splitfaces[][4] = { { 1, 2, 3, 17 }, { 2, 3, 4, 18 }, { 3, 4, 2, 19 }, { 4, 2, 3, 20 }, { 0, 0, 0, 0 } }; int reftet_2ea_2vc_splitelements[][5] = { { 1, 2, 3, 4, 21 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_2vc_newelstypes[] = { HP_PYRAMID_EDGES, HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_TET_0E_1V, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET, HP_TET, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_TET, // HP_PRISM, // HP_PRISM, HP_NONE, }; int reftet_2ea_2vc_newels[][8] = { { 1, 5, 17, 6, 7 }, // { 2, 8, 10, 9 }, { 3, 11, 12, 13 }, { 4, 15, 14, 16 }, { 5, 17, 7, 2, 9, 10 }, { 6, 7, 17, 11, 13, 12 }, { 9, 10, 18, 21 }, { 13, 12, 19, 21 }, { 15, 16, 20, 21 }, { 18, 20, 19, 21 }, { 10, 15, 20, 18, 21 }, { 13, 19, 20, 16, 21 }, { 9, 18, 19, 12, 21 }, { 7, 13, 16, 14, 21 }, { 7, 14, 15, 10, 21 }, { 9, 12, 17, 21 }, { 7, 10, 9, 17, 21 }, { 7, 17, 12, 13, 21 }, { 14, 16, 15, 21 }, // { 17, 9, 12, 7, 10, 13 }, // { 7, 10, 13, 14, 15, 16 }, }; HPRef_Struct reftet_2ea_2vc = { HP_TET, reftet_2ea_2vc_splitedges, reftet_2ea_2vc_splitfaces, reftet_2ea_2vc_splitelements, reftet_2ea_2vc_newelstypes, reftet_2ea_2vc_newels }; // HP_TET_2EA_3V, // 2 edges connected int reftet_2ea_3v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_2ea_3v_splitfaces[][4] = { { 1, 2, 3, 17 }, { 2, 3, 4, 18 }, { 3, 4, 2, 19 }, { 4, 2, 3, 20 }, { 0, 0, 0, 0 } }; int reftet_2ea_3v_splitelements[][5] = { { 1, 2, 3, 4, 21 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2ea_3v_newelstypes[] = { HP_PYRAMID_EDGES, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_TET_0E_1V, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET, HP_TET, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_TET, // HP_PRISM, // HP_PRISM, HP_NONE, }; int reftet_2ea_3v_newels[][8] = { { 1, 5, 17, 6, 7 }, { 2, 8, 10, 9 }, { 3, 11, 12, 13 }, { 4, 15, 14, 16 }, { 5, 17, 7, 8, 9, 10 }, { 6, 7, 17, 11, 13, 12 }, { 9, 10, 18, 21 }, { 13, 12, 19, 21 }, { 15, 16, 20, 21 }, { 18, 20, 19, 21 }, { 10, 15, 20, 18, 21 }, { 13, 19, 20, 16, 21 }, { 9, 18, 19, 12, 21 }, { 7, 13, 16, 14, 21 }, { 7, 14, 15, 10, 21 }, { 9, 12, 17, 21 }, { 7, 10, 9, 17, 21 }, { 7, 17, 12, 13, 21 }, { 14, 16, 15, 21 }, // { 17, 9, 12, 7, 10, 13 }, // { 7, 10, 13, 14, 15, 16 }, }; HPRef_Struct reftet_2ea_3v = { HP_TET, reftet_2ea_3v_splitedges, reftet_2ea_3v_splitfaces, reftet_2ea_3v_splitelements, reftet_2ea_3v_newelstypes, reftet_2ea_3v_newels }; // HP_TET_2EB_0V, // 2 opposite edges int reftet_2eb_0v_splitedges[][3] = { { 1, 3, 5 }, { 1, 4, 6 }, { 2, 3, 7 }, { 2, 4, 8 }, { 3, 1, 9 }, { 3, 2, 10 }, { 4, 1, 11 }, { 4, 2, 12 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2eb_0v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_HEX, HP_NONE, }; int reftet_2eb_0v_newels[][8] = { { 1, 5, 6, 2, 7, 8 }, { 3, 9, 10, 4, 11, 12 }, { 6, 11, 12, 8, 5, 9, 10, 7 }, }; HPRef_Struct reftet_2eb_0v = { HP_TET, reftet_2eb_0v_splitedges, 0, 0, reftet_2eb_0v_newelstypes, reftet_2eb_0v_newels }; // HP_TET_2EB_1V, // V1 // HP_TET_2EB_1V, // 2 opposite edges, V1 int reftet_2eb_1v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2eb_1v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET_1E_1VA, // HP_TET_1E_1VA, // HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_HEX, HP_NONE, }; int reftet_2eb_1v_newels[][8] = { { 5, 6, 7, 2, 9, 10 }, { 4, 15, 14, 3, 12, 11 }, { 1, 5, 6, 7 }, // { 2, 8, 10, 9 }, // { 3, 13, 11, 12 }, // { 4, 16, 15, 14 }, { 7, 14, 15, 10, 6, 11, 12, 9 } }; HPRef_Struct reftet_2eb_1v = { HP_TET, reftet_2eb_1v_splitedges, 0, 0, reftet_2eb_1v_newelstypes, reftet_2eb_1v_newels }; // HP_TET_2EB_2VA, // 2 opposite edges, V1,2 int reftet_2eb_2va_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2eb_2va_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET_1E_1VA, HP_TET_1E_1VA, // HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_HEX, HP_NONE, }; int reftet_2eb_2va_newels[][8] = { { 5, 6, 7, 8, 9, 10 }, { 4, 15, 14, 3, 12, 11 }, { 1, 5, 6, 7 }, { 2, 8, 10, 9 }, // { 3, 13, 11, 12 }, // { 4, 16, 15, 14 }, { 7, 14, 15, 10, 6, 11, 12, 9 } }; HPRef_Struct reftet_2eb_2va = { HP_TET, reftet_2eb_2va_splitedges, 0, 0, reftet_2eb_2va_newelstypes, reftet_2eb_2va_newels }; // HP_TET_2EB_2VB, // V1,3 int reftet_2eb_2vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2eb_2vb_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_HEX, HP_NONE, }; int reftet_2eb_2vb_newels[][8] = { { 5, 6, 7, 2, 9, 10 }, { 4, 15, 14, 13, 12, 11 }, { 1, 5, 6, 7 }, // { 2, 8, 10, 9 }, { 3, 13, 11, 12 }, // { 4, 16, 15, 14 }, { 7, 14, 15, 10, 6, 11, 12, 9 } }; HPRef_Struct reftet_2eb_2vb = { HP_TET, reftet_2eb_2vb_splitedges, 0, 0, reftet_2eb_2vb_newelstypes, reftet_2eb_2vb_newels }; // HP_TET_2EB_2VC, // V1,4 int reftet_2eb_2vc_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2eb_2vc_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET_1E_1VA, // HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_TET_1E_1VA, HP_HEX, HP_NONE, }; int reftet_2eb_2vc_newels[][8] = { { 5, 6, 7, 2, 9, 10 }, { 16, 15, 14, 3, 12, 11 }, { 1, 5, 6, 7 }, // { 2, 8, 10, 9 }, // { 3, 13, 11, 12 }, { 4, 16, 15, 14 }, { 7, 14, 15, 10, 6, 11, 12, 9 } }; HPRef_Struct reftet_2eb_2vc = { HP_TET, reftet_2eb_2vc_splitedges, 0, 0, reftet_2eb_2vc_newelstypes, reftet_2eb_2vc_newels }; // HP_TET_2EB_3V, // V1,2,3 int reftet_2eb_3v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2eb_3v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_HEX, HP_NONE, }; int reftet_2eb_3v_newels[][8] = { { 5, 6, 7, 8, 9, 10 }, { 4, 15, 14, 13, 12, 11 }, { 1, 5, 6, 7 }, { 2, 8, 10, 9 }, { 3, 13, 11, 12 }, // { 4, 16, 15, 14 }, { 7, 14, 15, 10, 6, 11, 12, 9 } }; HPRef_Struct reftet_2eb_3v = { HP_TET, reftet_2eb_3v_splitedges, 0, 0, reftet_2eb_3v_newelstypes, reftet_2eb_3v_newels }; // HP_TET_2EB_4V, // 2 opposite edges int reftet_2eb_4v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2eb_4v_newelstypes[] = { HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_HEX, HP_NONE, }; int reftet_2eb_4v_newels[][8] = { { 5, 6, 7, 8, 9, 10 }, { 16, 15, 14, 13, 12, 11 }, { 1, 5, 6, 7 }, { 2, 8, 10, 9 }, { 3, 13, 11, 12 }, { 4, 16, 15, 14 }, { 7, 14, 15, 10, 6, 11, 12, 9 } }; HPRef_Struct reftet_2eb_4v = { HP_TET, reftet_2eb_4v_splitedges, 0, 0, reftet_2eb_4v_newelstypes, reftet_2eb_4v_newels }; // HP_TET_3EA_0V, int reftet_3ea_0v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 2, 10 }, { 3, 4, 11 }, { 4, 2, 12 }, { 4, 3, 13 }, { 0, 0, 0 } }; int reftet_3ea_0v_splitfaces[][4] = { { 1, 2, 3, 14 }, { 1, 2, 4, 15 }, { 1, 3, 4, 16 }, { 2, 3, 4, 17 }, { 3, 4, 2, 18 }, { 4, 2, 3, 19 }, { 0, 0, 0, 0 } }; int reftet_3ea_0v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3ea_0v_newelstypes[] = { HP_HEX_3E_0V, HP_HEX_1E_0V, HP_HEX_1E_0V, HP_HEX_1E_0V, HP_PRISM, HP_PRISM, HP_PRISM, HP_TET, HP_NONE, }; int reftet_3ea_0v_newels[][8] = { { 1, 5, 14, 6, 7, 15, 20, 16 }, { 5, 2, 8, 14, 15, 9, 17, 20 }, { 3, 6, 14, 10, 11, 16, 20, 18 }, { 7, 4, 12, 15, 16, 13, 19, 20 }, { 11, 13, 16, 18, 19, 20 }, { 15, 12, 9, 20, 19, 17 }, { 8, 10, 14, 17, 18, 20 }, { 20, 17, 18, 19 }, }; HPRef_Struct reftet_3ea_0v = { HP_TET, reftet_3ea_0v_splitedges, reftet_3ea_0v_splitfaces, reftet_3ea_0v_splitelements, reftet_3ea_0v_newelstypes, reftet_3ea_0v_newels }; // HP_TET_3EA_1V, int reftet_3ea_1v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 2, 10 }, { 3, 4, 11 }, { 4, 2, 12 }, { 4, 3, 13 }, { 2, 1, 21 }, { 3, 1, 22 }, { 4, 1, 23 }, { 0, 0, 0 } }; int reftet_3ea_1v_splitfaces[][4] = { { 1, 2, 3, 14 }, { 1, 2, 4, 15 }, { 1, 3, 4, 16 }, { 2, 3, 4, 17 }, { 3, 4, 2, 18 }, { 4, 2, 3, 19 }, { 0, 0, 0, 0 } }; int reftet_3ea_1v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3ea_1v_newelstypes[] = { HP_HEX_3E_0V, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_TET, HP_NONE, }; int reftet_3ea_1v_newels[][8] = { { 1, 5, 14, 6, 7, 15, 20, 16 }, { 2, 21, 9, 8 }, { 5, 14, 15, 21, 8, 9 }, { 15, 14, 20, 9, 8, 17 }, // { 3, 22, 10, 11 }, // { 6, 16, 14, 22, 11, 10 }, { 6, 16, 14, 3, 11, 10 }, { 14, 16, 20, 10, 11, 18 }, // { 4, 23, 13, 12 }, // { 7, 15, 16, 23, 12, 13 }, { 7, 15, 16, 4, 12, 13 }, { 16, 15, 20, 13, 12, 19 }, { 11, 13, 16, 18, 19, 20 }, { 15, 12, 9, 20, 19, 17 }, { 8, 10, 14, 17, 18, 20 }, { 20, 17, 18, 19 }, }; HPRef_Struct reftet_3ea_1v = { HP_TET, reftet_3ea_1v_splitedges, reftet_3ea_1v_splitfaces, reftet_3ea_1v_splitelements, reftet_3ea_1v_newelstypes, reftet_3ea_1v_newels }; // HP_TET_3EA_2V, int reftet_3ea_2v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 2, 10 }, { 3, 4, 11 }, { 4, 2, 12 }, { 4, 3, 13 }, { 2, 1, 21 }, { 3, 1, 22 }, { 4, 1, 23 }, { 0, 0, 0 } }; int reftet_3ea_2v_splitfaces[][4] = { { 1, 2, 3, 14 }, { 1, 2, 4, 15 }, { 1, 3, 4, 16 }, { 2, 3, 4, 17 }, { 3, 4, 2, 18 }, { 4, 2, 3, 19 }, { 0, 0, 0, 0 } }; int reftet_3ea_2v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3ea_2v_newelstypes[] = { HP_HEX_3E_0V, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_TET, HP_NONE, }; int reftet_3ea_2v_newels[][8] = { { 1, 5, 14, 6, 7, 15, 20, 16 }, { 2, 21, 9, 8 }, { 5, 14, 15, 21, 8, 9 }, { 15, 14, 20, 9, 8, 17 }, { 3, 22, 10, 11 }, { 6, 16, 14, 22, 11, 10 }, { 14, 16, 20, 10, 11, 18 }, // { 4, 23, 13, 12 }, { 7, 15, 16, 4, 12, 13 }, { 16, 15, 20, 13, 12, 19 }, { 11, 13, 16, 18, 19, 20 }, { 15, 12, 9, 20, 19, 17 }, { 8, 10, 14, 17, 18, 20 }, { 20, 17, 18, 19 }, }; HPRef_Struct reftet_3ea_2v = { HP_TET, reftet_3ea_2v_splitedges, reftet_3ea_2v_splitfaces, reftet_3ea_2v_splitelements, reftet_3ea_2v_newelstypes, reftet_3ea_2v_newels }; // HP_TET_3EA_3V, int reftet_3ea_3v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 2, 10 }, { 3, 4, 11 }, { 4, 2, 12 }, { 4, 3, 13 }, { 2, 1, 21 }, { 3, 1, 22 }, { 4, 1, 23 }, { 0, 0, 0 } }; int reftet_3ea_3v_splitfaces[][4] = { { 1, 2, 3, 14 }, { 1, 2, 4, 15 }, { 1, 3, 4, 16 }, { 2, 3, 4, 17 }, { 3, 4, 2, 18 }, { 4, 2, 3, 19 }, { 0, 0, 0, 0 } }; int reftet_3ea_3v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3ea_3v_newelstypes[] = { HP_HEX_3E_0V, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_PRISM, HP_PRISM, HP_PRISM, HP_TET, HP_NONE, }; int reftet_3ea_3v_newels[][8] = { { 1, 5, 14, 6, 7, 15, 20, 16 }, { 2, 21, 9, 8 }, { 5, 14, 15, 21, 8, 9 }, { 15, 14, 20, 9, 8, 17 }, { 3, 22, 10, 11 }, { 6, 16, 14, 22, 11, 10 }, { 14, 16, 20, 10, 11, 18 }, { 4, 23, 13, 12 }, { 7, 15, 16, 23, 12, 13 }, { 16, 15, 20, 13, 12, 19 }, { 11, 13, 16, 18, 19, 20 }, { 15, 12, 9, 20, 19, 17 }, { 8, 10, 14, 17, 18, 20 }, { 20, 17, 18, 19 }, }; HPRef_Struct reftet_3ea_3v = { HP_TET, reftet_3ea_3v_splitedges, reftet_3ea_3v_splitfaces, reftet_3ea_3v_splitelements, reftet_3ea_3v_newelstypes, reftet_3ea_3v_newels }; // HP_TET_3EV_0V, int reftet_3eb_0v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, // { 3, 2, 12 }, { 3, 4, 13 }, // { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_3eb_0v_splitfaces[][4] = { { 1, 2, 4, 17 }, { 2, 1, 3, 18 }, { 0, 0, 0, 0 } }; int reftet_3eb_0v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3eb_0v_newelstypes[] = { HP_PYRAMID_EDGES, HP_PYRAMID_EDGES, // HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_NONE, }; int reftet_3eb_0v_newels[][8] = { { 1, 7, 17, 5, 6 }, { 2, 9, 18, 8, 10 }, // { 3, 12, 13, 11 }, // { 4, 14, 16, 15 }, { 5, 6, 17, 8, 18, 10 }, { 7, 17, 6, 4, 15, 16 }, { 9, 18, 10, 3, 11, 13 }, { 10, 15, 16, 13, 20 }, { 6, 11, 13, 16, 20 }, { 10, 17, 15, 20 }, { 6, 18, 11, 20 }, { 6, 17, 10, 18, 20 }, { 6, 16, 15, 17, 20 }, { 18, 10, 13, 11, 20 }, }; HPRef_Struct reftet_3eb_0v = { HP_TET, reftet_3eb_0v_splitedges, reftet_3eb_0v_splitfaces, reftet_3eb_0v_splitelements, reftet_3eb_0v_newelstypes, reftet_3eb_0v_newels }; // HP_TET_3EV_1V, int reftet_3eb_1v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, // { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_3eb_1v_splitfaces[][4] = { { 1, 2, 4, 17 }, { 2, 1, 3, 18 }, { 0, 0, 0, 0 } }; int reftet_3eb_1v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3eb_1v_newelstypes[] = { HP_PYRAMID_EDGES, HP_PYRAMID_EDGES, HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_NONE, }; int reftet_3eb_1v_newels[][8] = { { 1, 7, 17, 5, 6 }, { 2, 9, 18, 8, 10 }, { 3, 12, 13, 11 }, // { 4, 14, 16, 15 }, { 5, 6, 17, 8, 18, 10 }, { 7, 17, 6, 4, 15, 16 }, { 9, 18, 10, 12, 11, 13 }, { 10, 15, 16, 13, 20 }, { 6, 11, 13, 16, 20 }, { 10, 17, 15, 20 }, { 6, 18, 11, 20 }, { 6, 17, 10, 18, 20 }, { 6, 16, 15, 17, 20 }, { 18, 10, 13, 11, 20 }, }; HPRef_Struct reftet_3eb_1v = { HP_TET, reftet_3eb_1v_splitedges, reftet_3eb_1v_splitfaces, reftet_3eb_1v_splitelements, reftet_3eb_1v_newelstypes, reftet_3eb_1v_newels }; // HP_TET_3EV_2V, int reftet_3eb_2v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_3eb_2v_splitfaces[][4] = { { 1, 2, 4, 17 }, { 2, 1, 3, 18 }, { 0, 0, 0, 0 } }; int reftet_3eb_2v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3eb_2v_newelstypes[] = { HP_PYRAMID_EDGES, HP_PYRAMID_EDGES, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_NONE, }; int reftet_3eb_2v_newels[][8] = { { 1, 7, 17, 5, 6 }, { 2, 9, 18, 8, 10 }, { 3, 12, 13, 11 }, { 4, 14, 16, 15 }, { 5, 6, 17, 8, 18, 10 }, { 7, 17, 6, 14, 15, 16 }, { 9, 18, 10, 12, 11, 13 }, { 10, 15, 16, 13, 20 }, { 6, 11, 13, 16, 20 }, { 10, 17, 15, 20 }, { 6, 18, 11, 20 }, { 6, 17, 10, 18, 20 }, { 6, 16, 15, 17, 20 }, { 18, 10, 13, 11, 20 }, }; HPRef_Struct reftet_3eb_2v = { HP_TET, reftet_3eb_2v_splitedges, reftet_3eb_2v_splitfaces, reftet_3eb_2v_splitelements, reftet_3eb_2v_newelstypes, reftet_3eb_2v_newels }; // HP_TET_3EC_0V, int reftet_3ec_0v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, // { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, // { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_3ec_0v_splitfaces[][4] = { { 1, 2, 3, 17 }, { 2, 1, 4, 18 }, { 0, 0, 0, 0 } }; int reftet_3ec_0v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3ec_0v_newelstypes[] = { HP_PYRAMID_EDGES, HP_PYRAMID_EDGES, // HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_NONE, }; int reftet_3ec_0v_newels[][8] = { { 1, 5, 17, 6, 7 }, { 2, 8, 18, 10, 9 }, // { 3, 11, 12, 13 }, // { 4, 15, 14, 16 }, { 5, 17, 7, 8, 9, 18 }, { 6, 7, 17, 3, 13, 12 }, { 10, 9, 18, 4, 16, 14 }, { 9, 16, 13, 12, 20 }, { 7, 13, 16, 14, 20 }, { 7, 14, 18, 20 }, { 9, 12, 17, 20 }, { 17, 7, 18, 9, 20 }, { 7, 17, 12, 13, 20 }, { 9, 18, 14, 16, 20 }, }; HPRef_Struct reftet_3ec_0v = { HP_TET, reftet_3ec_0v_splitedges, reftet_3ec_0v_splitfaces, reftet_3ec_0v_splitelements, reftet_3ec_0v_newelstypes, reftet_3ec_0v_newels }; // HP_TET_3EC_1V, int reftet_3ec_1v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, // { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_3ec_1v_splitfaces[][4] = { { 1, 2, 3, 17 }, { 2, 1, 4, 18 }, { 0, 0, 0, 0 } }; int reftet_3ec_1v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3ec_1v_newelstypes[] = { HP_PYRAMID_EDGES, HP_PYRAMID_EDGES, HP_TET_1E_1VA, // HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_NONE, }; int reftet_3ec_1v_newels[][8] = { { 1, 5, 17, 6, 7 }, { 2, 8, 18, 10, 9 }, { 3, 11, 12, 13 }, // { 4, 15, 14, 16 }, { 5, 17, 7, 8, 9, 18 }, { 6, 7, 17, 11, 13, 12 }, { 10, 9, 18, 4, 16, 14 }, { 9, 16, 13, 12, 20 }, { 7, 13, 16, 14, 20 }, { 7, 14, 18, 20 }, { 9, 12, 17, 20 }, { 17, 7, 18, 9, 20 }, { 7, 17, 12, 13, 20 }, { 9, 18, 14, 16, 20 }, }; HPRef_Struct reftet_3ec_1v = { HP_TET, reftet_3ec_1v_splitedges, reftet_3ec_1v_splitfaces, reftet_3ec_1v_splitelements, reftet_3ec_1v_newelstypes, reftet_3ec_1v_newels }; // HP_TET_3EC_2V, int reftet_3ec_2v_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 2, 3, 9 }, { 2, 4, 10 }, { 3, 1, 11 }, { 3, 2, 12 }, { 3, 4, 13 }, { 4, 1, 14 }, { 4, 2, 15 }, { 4, 3, 16 }, { 0, 0, 0 } }; int reftet_3ec_2v_splitfaces[][4] = { { 1, 2, 3, 17 }, { 2, 1, 4, 18 }, { 0, 0, 0, 0 } }; int reftet_3ec_2v_splitelements[][5] = { { 1, 2, 3, 4, 20 }, { 0 }, }; HPREF_ELEMENT_TYPE reftet_3ec_2v_newelstypes[] = { HP_PYRAMID_EDGES, HP_PYRAMID_EDGES, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PRISM_SINGEDGE, HP_PYRAMID, HP_PYRAMID, HP_TET, HP_TET, HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, HP_NONE, }; int reftet_3ec_2v_newels[][8] = { { 1, 5, 17, 6, 7 }, { 2, 8, 18, 10, 9 }, { 3, 11, 12, 13 }, { 4, 15, 14, 16 }, { 5, 17, 7, 8, 9, 18 }, { 6, 7, 17, 11, 13, 12 }, { 10, 9, 18, 15, 16, 14 }, { 9, 16, 13, 12, 20 }, { 7, 13, 16, 14, 20 }, { 7, 14, 18, 20 }, { 9, 12, 17, 20 }, { 17, 7, 18, 9, 20 }, { 7, 17, 12, 13, 20 }, { 9, 18, 14, 16, 20 }, }; HPRef_Struct reftet_3ec_2v = { HP_TET, reftet_3ec_2v_splitedges, reftet_3ec_2v_splitfaces, reftet_3ec_2v_splitelements, reftet_3ec_2v_newelstypes, reftet_3ec_2v_newels }; /* ************************ 1 singular face ******************** */ // HP_TET_1F_0E_0V int reftet_1f_0e_0v_splitedges[][3] = { { 2, 1, 5 }, { 3, 1, 6 }, { 4, 1, 7 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1f_0e_0v_newelstypes[] = { HP_PRISM_1FA_0E_0V, HP_TET, HP_NONE, }; int reftet_1f_0e_0v_newels[][8] = { { 3, 2, 4, 6, 5, 7 }, { 5, 7, 6, 1 } }; HPRef_Struct reftet_1f_0e_0v = { HP_TET, reftet_1f_0e_0v_splitedges, 0, 0, reftet_1f_0e_0v_newelstypes, reftet_1f_0e_0v_newels }; // HP_TET_1F_0E_1VA ... singular vertex in face int reftet_1f_0e_1va_splitedges[][3] = { { 2, 1, 5 }, { 2, 3, 6 }, { 2, 4, 7 }, { 3, 1, 8 }, { 4, 1, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1f_0e_1va_newelstypes[] = { HP_HEX_1F_0E_0V, HP_TET_1F_0E_1VA, HP_TET, HP_NONE, }; int reftet_1f_0e_1va_newels[][8] = { { 3, 6, 7, 4, 8, 5, 5, 9 }, { 5, 2, 6, 7 }, { 5, 9, 8, 1 }, }; HPRef_Struct reftet_1f_0e_1va = { HP_TET, reftet_1f_0e_1va_splitedges, 0, 0, reftet_1f_0e_1va_newelstypes, reftet_1f_0e_1va_newels }; // HP_TET_1F_0E_1VB ... singular vertex not in face int reftet_1f_0e_1vb_splitedges[][3] = { { 1, 2, 5 }, { 1, 3, 6 }, { 1, 4, 7 }, { 2, 1, 8 }, { 3, 1, 9 }, { 4, 1, 10 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1f_0e_1vb_newelstypes[] = { HP_PRISM_1FA_0E_0V, HP_PRISM, HP_TET_0E_1V, HP_NONE, }; int reftet_1f_0e_1vb_newels[][8] = { { 2, 4, 3, 8, 10, 9 }, { 8, 10, 9, 5, 7, 6 }, { 1, 5, 6, 7 }, }; HPRef_Struct reftet_1f_0e_1vb = { HP_TET, reftet_1f_0e_1vb_splitedges, 0, 0, reftet_1f_0e_1vb_newelstypes, reftet_1f_0e_1vb_newels }; // HP_TET_1F_1EA_0V ... sing edge is 1..2 int reftet_1f_1ea_0v_splitedges[][3] = { { 1, 3, 5 }, { 1, 4, 6 }, { 2, 1, 7 }, { 2, 3, 8 }, { 2, 4, 9 }, { 3, 1, 10 }, { 4, 1, 11 }, { 0, 0, 0 } }; int reftet_1f_1ea_0v_splitfaces[][4] = { { 2, 1, 3, 12 }, { 2, 1, 4, 13 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1f_1ea_0v_newelstypes[] = { HP_HEX_1F_0E_0V, // HP_PRISM, HP_PYRAMID_1FB_0E_1VA, HP_TET_1E_1VA, HP_PRISM_SINGEDGE, HP_PRISM, HP_NONE, }; int reftet_1f_1ea_0v_newels[][8] = { { 3, 8, 9, 4, 10, 12, 13, 11 }, // { 2, 9, 8, 7, 13, 12 }, { 8, 9, 13, 12, 2 }, { 2, 7, 13, 12 }, { 7, 13, 12, 1, 6, 5 }, { 6, 11, 13, 5, 10, 12 } }; HPRef_Struct reftet_1f_1ea_0v = { HP_TET, reftet_1f_1ea_0v_splitedges, reftet_1f_1ea_0v_splitfaces, 0, reftet_1f_1ea_0v_newelstypes, reftet_1f_1ea_0v_newels }; // HP_TET_1F_1EB_0V singular edge in face, edge is 2-3 int reftet_1f_1eb_0v_splitedges[][3] = { { 2, 1, 5 }, { 2, 4, 6 }, { 3, 1, 7 }, { 3, 4, 8 }, { 4, 1, 9 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_1f_1eb_0v_newelstypes[] = { HP_PRISM_1FB_1EA_0V, HP_PRISM_1FA_0E_0V, HP_TET, HP_NONE, }; int reftet_1f_1eb_0v_newels[][8] = { // { 2, 5, 6, 3, 7, 8 }, { 3, 8, 7, 2, 6, 5 }, { 6, 4, 8, 5, 9, 7 }, { 5, 9, 7, 1} }; HPRef_Struct reftet_1f_1eb_0v = { HP_TET, reftet_1f_1eb_0v_splitedges, 0, 0, reftet_1f_1eb_0v_newelstypes, reftet_1f_1eb_0v_newels }; /* ************************ 2 singular faces ******************** */ // HP_TET_2F_0E_0V int reftet_2f_0e_0v_splitedges[][3] = { { 1, 2, 5 }, { 2, 1, 6 }, { 3, 1, 7 }, { 3, 2, 8 }, { 4, 1, 9 }, { 4, 2, 10 }, { 0, 0, 0 } }; int reftet_2f_0e_0v_splitfaces[][4] = { { 3, 1, 2, 11 }, { 4, 1, 2, 12 }, { 0, 0, 0, 0 } }; HPREF_ELEMENT_TYPE reftet_2f_0e_0v_newelstypes[] = { HP_PRISM_1FA_0E_0V, HP_PRISM_1FA_0E_0V, HP_PRISM_1FB_1EA_0V, HP_PRISM_1FB_1EA_0V, HP_TET, HP_NONE, }; int reftet_2f_0e_0v_newels[][8] = { { 2, 10, 8, 6, 12, 11 }, { 1, 7, 9, 5, 11, 12 }, // { 3, 11, 8, 4, 12, 10 }, { 4, 10, 12, 3, 8, 11 }, { 3, 7, 11, 4, 9, 12 }, { 5, 6, 11, 12 } }; HPRef_Struct reftet_2f_0e_0v = { HP_TET, reftet_2f_0e_0v_splitedges, reftet_2f_0e_0v_splitfaces, 0, reftet_2f_0e_0v_newelstypes, reftet_2f_0e_0v_newels }; netgen-6.2.1905/libsrc/meshing/geomsearch.cpp0000644000175000017500000001610613504650527017536 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { GeomSearch3d :: GeomSearch3d() { size.i1 = 0; size.i2 = 0; size.i3 = 0; }; GeomSearch3d :: ~GeomSearch3d() { //delete old Hashtable: if (size.i1 != 0) { for (int i = 0; i < size.i1*size.i2*size.i3; i++) delete hashtable[i]; } } void GeomSearch3d :: Init (Array *pointsi, Array *facesi) { points = pointsi; faces = facesi; size.i1 = 0; size.i2 = 0; size.i3 = 0; reset = 1; hashcount = 1; } void GeomSearch3d :: ElemMaxExt(Point3d& minp, Point3d& maxp, const MiniElement2d& elem) { maxp.X()=(*points)[elem.PNum(1)].P()(0); maxp.Y()=(*points)[elem.PNum(1)].P()(1); maxp.Z()=(*points)[elem.PNum(1)].P()(2); minp.X()=(*points)[elem.PNum(1)].P()(0); minp.Y()=(*points)[elem.PNum(1)].P()(1); minp.Z()=(*points)[elem.PNum(1)].P()(2); for (int i=2; i <= 3; i++) { maxp.X()=max2((*points)[elem.PNum(i)].P()(0),maxp.X()); maxp.Y()=max2((*points)[elem.PNum(i)].P()(1),maxp.Y()); maxp.Z()=max2((*points)[elem.PNum(i)].P()(2),maxp.Z()); minp.X()=min2((*points)[elem.PNum(i)].P()(0),minp.X()); minp.Y()=min2((*points)[elem.PNum(i)].P()(1),minp.Y()); minp.Z()=min2((*points)[elem.PNum(i)].P()(2),minp.Z()); } } void GeomSearch3d :: MinCoords(const Point3d& p1, Point3d& p2) { p2.X()=min2(p1.X(),p2.X()); p2.Y()=min2(p1.Y(),p2.Y()); p2.Z()=min2(p1.Z(),p2.Z()); } void GeomSearch3d :: MaxCoords(const Point3d& p1, Point3d& p2) { p2.X()=max2(p1.X(),p2.X()); p2.Y()=max2(p1.Y(),p2.Y()); p2.Z()=max2(p1.Z(),p2.Z()); } void GeomSearch3d :: Create() { INDEX i,j,k; if (reset) { const double hashelemsizefactor = 4; reset = 0; /* minext=Point3d(MAXDOUBLE, MAXDOUBLE, MAXDOUBLE); maxext=Point3d(MINDOUBLE, MINDOUBLE, MINDOUBLE); */ ElemMaxExt(minext, maxext, faces->Get(1).Face()); Point3d maxp, minp; Vec3d midext(0,0,0); //get max Extension of Frontfaces for (i = 1; i <= faces->Size(); i++) { ElemMaxExt(minp, maxp, faces->Get(i).Face()); MinCoords(minp, minext); MaxCoords(maxp, maxext); midext+=maxp-minp; } maxextreal = maxext; maxext = maxext + 1e-4 * (maxext - minext); midext*=1./faces->Size(); Vec3d boxext = maxext - minext; //delete old Hashtable: if (size.i1 != 0) { for (i = 1; i <= size.i1*size.i2*size.i3; i++) { delete hashtable.Get(i); } } size.i1 = int (boxext.X()/midext.X()/hashelemsizefactor+1); size.i2 = int (boxext.Y()/midext.Y()/hashelemsizefactor+1); size.i3 = int (boxext.Z()/midext.Z()/hashelemsizefactor+1); // PrintMessage (5, "hashsizes = ", size.i1, ", ", size.i2, ", ", size.i3); elemsize.X()=boxext.X()/size.i1; elemsize.Y()=boxext.Y()/size.i2; elemsize.Z()=boxext.Z()/size.i3; //create Hasharrays: hashtable.SetSize(size.i1*size.i2*size.i3); for (i = 1; i <= size.i1; i++) { for (j = 1; j <= size.i2; j++) { for (k = 1; k <= size.i3; k++) { INDEX ind=i+(j-1)*size.i1+(k-1)*size.i2*size.i1; hashtable.Elem(ind) = new Array (); } } } } else { //Clear all Hash-Arrays for (i = 1; i <= size.i1; i++) { for (j = 1; j <= size.i2; j++) { for (k = 1; k <= size.i3; k++) { INDEX ind=i+(j-1)*size.i1+(k-1)*size.i2*size.i1; hashtable.Elem(ind)->SetSize(0); } } } } //Faces in Hashtable einfuegen: for (i = 1; i <= faces->Size(); i++) { AddElem(faces->Get(i).Face(),i); } } void GeomSearch3d :: AddElem(const MiniElement2d& elem, INDEX elemnum) { Point3d minp, maxp; ElemMaxExt(minp, maxp, elem); int sx = int ((minp.X()-minext.X())/elemsize.X()+1.); int ex = int ((maxp.X()-minext.X())/elemsize.X()+1.); int sy = int ((minp.Y()-minext.Y())/elemsize.Y()+1.); int ey = int ((maxp.Y()-minext.Y())/elemsize.Y()+1.); int sz = int ((minp.Z()-minext.Z())/elemsize.Z()+1.); int ez = int ((maxp.Z()-minext.Z())/elemsize.Z()+1.); for (int ix = sx; ix <= ex; ix++) for (int iy = sy; iy <= ey; iy++) for (int iz = sz; iz <= ez; iz++) { INDEX ind=ix+(iy-1)*size.i1+(iz-1)*size.i2*size.i1; if (ind < 1 || ind > size.i1 * size.i2 * size.i3) { cerr << "Illegal hash-position"; cerr << "Position: " << ix << "," << iy << "," << iz << endl; throw NgException ("Illegal position in Geomsearch"); } hashtable.Elem(ind)->Append(elemnum); } } void GeomSearch3d :: GetLocals(Array & locfaces, Array & findex, INDEX fstind, const Point3d& p0, double xh) { hashcount++; Point3d minp, maxp, midp; minp=p0-Vec3d(xh,xh,xh); //lay cube over sphere maxp=p0+Vec3d(xh,xh,xh); MaxCoords(minext,minp); //cube may not be out of hash-region MinCoords(maxextreal,maxp); int cluster = faces->Get(fstind).Cluster(); int sx = int((minp.X()-minext.X())/elemsize.X()+1.); int ex = int((maxp.X()-minext.X())/elemsize.X()+1.); int sy = int((minp.Y()-minext.Y())/elemsize.Y()+1.); int ey = int((maxp.Y()-minext.Y())/elemsize.Y()+1.); int sz = int((minp.Z()-minext.Z())/elemsize.Z()+1.); int ez = int((maxp.Z()-minext.Z())/elemsize.Z()+1.); int ix,iy,iz,i,k; int cnt1 = 0; // test, how efficient hashtable is int cnt2 = 0; int cnt3 = 0; for (ix = sx; ix <= ex; ix++) { for (iy = sy; iy <= ey; iy++) { for (iz = sz; iz <= ez; iz++) { INDEX ind=ix+(iy-1)*size.i1+(iz-1)*size.i2*size.i1; //go through all elements in one hash area const Array & area = *hashtable.Elem(ind); for (k = 1; k <= area.Size(); k++) { cnt2++; i = area.Get(k); if (faces->Get(i).Cluster() == cluster && faces->Get(i).Valid() && faces->Get(i).HashValue() != hashcount && i != fstind) { cnt1++; const MiniElement2d & face = faces->Get(i).Face(); const Point3d & p1 = (*points)[face.PNum(1)].P(); const Point3d & p2 = (*points)[face.PNum(2)].P(); const Point3d & p3 = (*points)[face.PNum(3)].P(); midp = Center (p1, p2, p3); // if (Dist2 (midp, p0) <= xh*xh) if((Dist2 (p1, p0) <= xh*xh) || (Dist2 (p2, p0) <= xh*xh) || (Dist2 (p3, p0) <= xh*xh) || (Dist2 (midp, p0) <= xh*xh) ) // by Jochen Wild { cnt3++; locfaces.Append(faces->Get(i).Face()); findex.Append(i); faces->Elem(i).SetHashValue(hashcount); } } } } } } /* if (faces->Size() != 0 && hashcount % 200 == 0) { (*mycout) << "n.o.f= " << faces->Size(); (*mycout) << ", n.o.lf= " << locfaces.Size(); (*mycout) << ", hashf= " << (double)cnt2/(double)faces->Size(); (*mycout) << " (" << (double)cnt1/(double)faces->Size(); (*mycout) << ", " << (double)cnt3/(double)faces->Size() << ")" << endl; } */ } } netgen-6.2.1905/libsrc/meshing/ruler2.hpp0000644000175000017500000000731413504650527016642 0ustar kurtkurt#ifndef FILE_NETRULE #define FILE_NETRULE /// class netrule { private: /// typedef struct tf { float f1, f2, f3; } threefloat; class threeint { public: int i1, i2, i3; threeint() { } threeint(int ai1, int ai2, int ai3) { i1 = ai1; i2 = ai2; i3 = ai3; } }; /// int quality; /// char * name; /// Array points; /// Array lines; /// Array freezone, freezonelimit; /// Array*> freezone_i; /// Array transfreezone; /// Array dellines; /// Array elements; /// Array tolerances, linetolerances; /// Array orientations; /// DenseMatrix oldutonewu, oldutofreearea, oldutofreearealimit; /// Array oldutofreearea_i; /// MatrixFixWidth<3> freesetinequ; /// Array linevecs; /// int noldp, noldl; /// float fzminx, fzmaxx, fzminy, fzmaxy; /// topological distance of line to base element Array lnearness; public: /// netrule (); /// ~netrule(); /// int GetNP () const { return points.Size(); } /// int GetNL () const { return lines.Size(); } /// int GetNE () const { return elements.Size(); } /// int GetNOldP () const { return noldp; } /// int GetNOldL () const { return noldl; } /// int GetNDelL () const { return dellines.Size(); } /// int GetNOrientations () const { return orientations.Size(); } /// int GetQuality () const { return quality; } /// int GetLNearness (int li) const { return lnearness.Get(li); } /// const Point2d & GetPoint (int i) const { return points.Get(i); } /// const INDEX_2 & GetLine (int i) const { return lines.Get(i); } /// const Element2d & GetElement (int i) const { return elements.Get(i); } /// const threeint & GetOrientation (int i) const { return orientations.Get(i); } /// int GetDelLine (int i) const { return dellines.Get(i); } /// const Array & GetDelLines() const { return dellines; } /// void GetFreeZone (Array & afreearea); /// double CalcPointDist (int pi, const Point2d & p) const { double dx = p.X() - points.Get(pi).X(); double dy = p.Y() - points.Get(pi).Y(); const threefloat * tfp = &tolerances.Get(pi); return tfp->f1 * dx * dx + tfp->f2 * dx * dy + tfp->f3 * dy * dy; } /// float CalcLineError (int li, const Vec2d & v) const; /// void SetFreeZoneTransformation (const Vector & u, int tolclass); /// bool IsInFreeZone (const Point2d & p) const { if (p.X() < fzminx || p.X() > fzmaxx || p.Y() < fzminy || p.Y() > fzmaxy) return 0; for (int i = 0; i < transfreezone.Size(); i++) { if (freesetinequ(i, 0) * p.X() + freesetinequ(i, 1) * p.Y() + freesetinequ(i, 2) > 0) return 0; } return 1; } /// int IsLineInFreeZone (const Point2d & p1, const Point2d & p2) const { if ( (p1.X() > fzmaxx && p2.X() > fzmaxx) || (p1.X() < fzminx && p2.X() < fzminx) || (p1.Y() > fzmaxy && p2.Y() > fzmaxy) || (p1.Y() < fzminy && p2.Y() < fzminy) ) return 0; return IsLineInFreeZone2 (p1, p2); } /// int IsLineInFreeZone2 (const Point2d & p1, const Point2d & p2) const; /// int ConvexFreeZone () const; /// const Array & GetTransFreeZone () { return transfreezone; } /// int GetPointNr (int ln, int endp) const { return lines.Get(ln).I(endp); } /// const DenseMatrix & GetOldUToNewU () const { return oldutonewu; } /// const DenseMatrix & GetOldUToFreeArea () const { return oldutofreearea; } /// const char * Name () const { return name; } /// void LoadRule (istream & ist); }; /** Draws 2D rules. Visual testing of 2D meshing rules */ extern void DrawRules (); #endif netgen-6.2.1905/libsrc/meshing/improve2.hpp0000644000175000017500000000541413504650527017171 0ustar kurtkurt#ifndef FILE_IMPROVE2 #define FILE_IMPROVE2 /// class MeshOptimize2d { int faceindex; int improveedges; double metricweight; int writestatus; public: /// MeshOptimize2d (); virtual ~MeshOptimize2d() { ; } /// void ImproveMesh (Mesh & mesh2d, const MeshingParameters & mp); void ImproveMeshJacobian (Mesh & mesh2d, const MeshingParameters & mp); void ImproveVolumeMesh (Mesh & mesh); void ProjectBoundaryPoints(Array & surfaceindex, const Array* > & from, Array* > & dest); void EdgeSwapping (Mesh & mesh, int usemetric); void CombineImprove (Mesh & mesh); void GenericImprove (Mesh & mesh); void SetFaceIndex (int fi) { faceindex = fi; } void SetImproveEdges (int ie) { improveedges = ie; } void SetMetricWeight (double mw) { metricweight = mw; } void SetWriteStatus (int ws) { writestatus = ws; } /// virtual void SelectSurfaceOfPoint (const Point<3> & p, const PointGeomInfo & gi); /// virtual void ProjectPoint (INDEX /* surfind */, Point<3> & /* p */) const { }; /// project point, use gi as initial value, and compute new gi virtual int ProjectPointGI (INDEX surfind, Point<3> & p, PointGeomInfo & gi) const { ProjectPoint (surfind, p); return CalcPointGeomInfo (surfind, gi, p); } /// virtual void ProjectPoint2 (INDEX /* surfind */, INDEX /* surfind2 */, Point<3> & /* p */) const { }; /// liefert zu einem 3d-Punkt die geominfo (Dreieck) und liefert 1, wenn erfolgreich, /// 0, wenn nicht (Punkt ausserhalb von chart) virtual int CalcPointGeomInfo(PointGeomInfo& gi, const Point<3> & /*p3*/) const { gi.trignum = 1; return 1;}; virtual int CalcPointGeomInfo(int /* surfind */, PointGeomInfo& gi, const Point<3> & p3) const { return CalcPointGeomInfo (gi, p3); } /// virtual void GetNormalVector(INDEX surfind, const Point<3> & p, PointGeomInfo & gi, Vec<3> & n) const; virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const; void CheckMeshApproximation (Mesh & mesh); /// friend class Opti2SurfaceMinFunction; /// friend class Opti2EdgeMinFunction; /// friend double Opti2FunctionValueGrad (const Vector & x, Vector & grad); /// friend double Opti2EdgeFunctionValueGrad (const Vector & x, Vector & grad); }; extern void CalcTriangleBadness (double x2, double x3, double y3, double metricweight, double h, double & badness, double & g1x, double & g1y); extern double CalcTriangleBadness (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, double metricweight, double h); extern double CalcTriangleBadness (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, const Vec<3> & n, double metricweight, double h); #endif netgen-6.2.1905/libsrc/meshing/pyramidrls.cpp0000644000175000017500000001003713504650527017604 0ustar kurtkurtnamespace netgen { const char * pyramidrules[] = { "tolfak 0.5\n",\ "\n",\ "rule \"Pyramid on quad\"\n",\ "\n",\ "quality 100\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.5, -0.5) \n",\ " { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ " { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ "\n",\ "newfaces\n",\ "(1, 2, 5);\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "rule \"small Pyramid on quad\"\n",\ "\n",\ "quality 100\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "\n",\ "newpoints\n",\ "(0.5, 0.5, -0.1 )\n",\ " { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ " { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ "\n",\ "newfaces\n",\ "(1, 2, 5);\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"connect pyramid\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0.5, -0.5);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(1, 2, 5);\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"pyramid with one trig\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0.5, -0.5);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 1, 5) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(2, 3, 5);\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 };\n",\ "{ 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 };\n",\ "{ 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P3 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "{ 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 };\n",\ "{ 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 };\n",\ "{ 0.333 P1, 0.333 P4, 0.334 P5, 0 P3 };\n",\ "\n",\ "orientations\n",\ "(1, 2, 3, 5);\n",\ "(1, 3, 4, 5);\n",\ "\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "freeset\n",\ "1 3 4 5;\n",\ "freeset\n",\ "2 3 5 6;\n",\ "freeset\n",\ "3 4 5 7;\n",\ "freeset \n",\ "1 4 5 8;\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"pyramid with two trig\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0);\n",\ "(1, 1, 0);\n",\ "(0, 1, 0);\n",\ "(0.5, 0.5, -0.5);\n",\ "\n",\ "mapfaces\n",\ "(1, 2, 3, 4) del;\n",\ "(2, 1, 5) del;\n",\ "(3, 2, 5) del;\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(3, 4, 5);\n",\ "(4, 1, 5);\n",\ "\n",\ "elements\n",\ "(1, 2, 3, 4, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 1 P4 };\n",\ "{ 1 P5 };\n",\ "\n",\ "freeset\n",\ "1 2 3 5;\n",\ "\n",\ "freeset\n",\ "1 3 4 5;\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ 0}; } netgen-6.2.1905/libsrc/meshing/hexarls.cpp0000644000175000017500000000757213504650527017076 0ustar kurtkurtnamespace netgen { const char * hexrules[] = { "rule \"Hexa left-right-top\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "flags t;\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0) { 1 } ;\n",\ "(1, 1, 0) { 1 } ;\n",\ "(0, 1, 0) { 1 } ;\n",\ "(0, 0, 1) { 1 } ;\n",\ "(1, 0, 1) { 1 } ;\n",\ "(1, 1, 1) { 1 } ;\n",\ "(0, 1, 1) { 1 } ;\n",\ "\n",\ "mapfaces\n",\ "(4, 3, 2, 1) del;\n",\ "(3, 7, 6, 2) del;\n",\ "(7, 8, 5, 6) del;\n",\ "(8, 4, 1, 5) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 6, 2, 1);\n",\ "(7, 8, 4, 3);\n",\ "\n",\ "elements\n",\ "(4, 3, 2, 1, 8, 7, 6, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 0.3 P1, 0.3 P2, 0.3 P5, 0.3 P6, -0.05 P3, -0.05 P4, -0.05 P7, -0.05 P8 };\n",\ "{ 0.3 P3, 0.3 P4, 0.3 P7, 0.3 P8, -0.05 P1, -0.05 P2, -0.05 P5, -0.05 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 0.25 P1, 0.25 P2, 0.25 P5, 0.25 P6, -0.0 P3, -0.0 P4, -0.0 P7, -0.0 P8 };\n",\ "{ 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 };\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "rule \"Hexa left-right-top (10)\"\n",\ "\n",\ "quality 10\n",\ "\n",\ "flags t;\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0) { 1 } ;\n",\ "(1, 1, 0) { 1 } ;\n",\ "(0, 1, 0) { 1 } ;\n",\ "(0, 0, 1) { 1 } ;\n",\ "(1, 0, 1) { 1 } ;\n",\ "(1, 1, 1) { 1 } ;\n",\ "(0, 1, 1) { 1 } ;\n",\ "\n",\ "mapfaces\n",\ "(4, 3, 2, 1) del;\n",\ "(3, 7, 6, 2) del;\n",\ "(7, 8, 5, 6) del;\n",\ "(8, 4, 1, 5) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(5, 6, 2, 1);\n",\ "(7, 8, 4, 3);\n",\ "\n",\ "elements\n",\ "(4, 3, 2, 1, 8, 7, 6, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 0.251 P1, 0.251 P2, 0.251 P5, 0.251 P6, -0.05 P3, -0.001 P4, -0.001 P7, -0.001 P8 };\n",\ "{ 0.251 P3, 0.251 P4, 0.251 P7, 0.251 P8, -0.05 P1, -0.001 P2, -0.001 P5, -0.001 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 0.25 P1, 0.25 P2, 0.25 P5, 0.25 P6, -0.0 P3, -0.0 P4, -0.0 P7, -0.0 P8 };\n",\ "{ 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 };\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Hexa left-right-top-front\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "flags t;\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0) { 1 } ;\n",\ "(1, 1, 0) { 1 } ;\n",\ "(0, 1, 0) { 1 } ;\n",\ "(0, 0, 1) { 1 } ;\n",\ "(1, 0, 1) { 1 } ;\n",\ "(1, 1, 1) { 1 } ;\n",\ "(0, 1, 1) { 1 } ;\n",\ "\n",\ "mapfaces\n",\ "(4, 3, 2, 1) del;\n",\ "(3, 7, 6, 2) del;\n",\ "(7, 8, 5, 6) del;\n",\ "(8, 4, 1, 5) del;\n",\ "(1, 2, 6, 5) del;\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "(7, 8, 4, 3);\n",\ "\n",\ "elements\n",\ "(4, 3, 2, 1, 8, 7, 6, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 0.3 P3, 0.3 P4, 0.3 P7, 0.3 P8, -0.05 P1, -0.05 P2, -0.05 P5, -0.05 P6 };\n",\ "\n",\ "freezonelimit\n",\ "{ 1 P5 };\n",\ "{ 1 P6 };\n",\ "{ 1 P2 };\n",\ "{ 1 P3 };\n",\ "{ 0.25 P3, 0.25 P4, 0.25 P7, 0.25 P8, -0.0 P1, -0.0 P1, -0.0 P5, -0.0 P6 };\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "rule \"Hexa fill\"\n",\ "\n",\ "quality 1\n",\ "\n",\ "flags t;\n",\ "\n",\ "mappoints\n",\ "(0, 0, 0);\n",\ "(1, 0, 0) { 1 } ;\n",\ "(1, 1, 0) { 1 } ;\n",\ "(0, 1, 0) { 1 } ;\n",\ "(0, 0, 1) { 1 } ;\n",\ "(1, 0, 1) { 1 } ;\n",\ "(1, 1, 1) { 1 } ;\n",\ "(0, 1, 1) { 1 } ;\n",\ "\n",\ "mapfaces\n",\ "(4, 3, 2, 1) del;\n",\ "(3, 7, 6, 2) del;\n",\ "(7, 8, 5, 6) del;\n",\ "(8, 4, 1, 5) del;\n",\ "(1, 2, 6, 5) del;\n",\ "(3, 4, 8, 7) del;\n",\ "\n",\ "newpoints\n",\ "\n",\ "newfaces\n",\ "\n",\ "elements\n",\ "(4, 3, 2, 1, 8, 7, 6, 5);\n",\ "\n",\ "freezone2\n",\ "{ 1 P1 };\n",\ "{ 1 P2 };\n",\ "{ 1 P5 };\n",\ "{ 1 P3 };\n",\ "\n",\ "\n",\ "endrule\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ "\n",\ 0}; } netgen-6.2.1905/libsrc/meshing/paralleltop.cpp0000644000175000017500000004527613504650527017752 0ustar kurtkurt#ifdef PARALLEL #include #include "paralleltop.hpp" namespace netgen { ParallelMeshTopology :: ParallelMeshTopology (const Mesh & amesh) : mesh(amesh) { is_updated = false; } ParallelMeshTopology :: ~ParallelMeshTopology () { ; } void ParallelMeshTopology :: Reset () { *testout << "ParallelMeshTopology::Reset" << endl; NgMPI_Comm comm = mesh.GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); if ( ntasks == 1 ) return; int ned = mesh.GetTopology().GetNEdges(); int nfa = mesh.GetTopology().GetNFaces(); if (glob_edge.Size() != ned) { glob_edge.SetSize(ned); glob_face.SetSize(nfa); glob_edge = -1; glob_face = -1; loc2distedge.ChangeSize (ned); loc2distface.ChangeSize (nfa); } if (glob_vert.Size() != mesh.GetNV()) { SetNV(mesh.GetNV()); SetNE(mesh.GetNE()); } } void ParallelMeshTopology :: Print() const { ; } void ParallelMeshTopology :: SetDistantFaceNum (int dest, int locnum) { for ( int i = 0; i < loc2distface[locnum-1].Size(); i+=1 ) if ( loc2distface[locnum-1][i] == dest ) return; loc2distface.Add(locnum-1, dest); } void ParallelMeshTopology :: SetDistantPNum (int dest, int locnum) { for ( int i = 0; i < loc2distvert[locnum-1].Size(); i+=1 ) if ( loc2distvert[locnum-1][i] == dest ) return; loc2distvert.Add (locnum-1, dest); } void ParallelMeshTopology :: SetDistantEdgeNum (int dest, int locnum) { for ( int i = 0; i < loc2distedge[locnum-1].Size(); i+=1 ) if ( loc2distedge[locnum-1][i] == dest ) return; loc2distedge.Add (locnum-1, dest); } void ParallelMeshTopology :: SetNV (int anv) { glob_vert.SetSize(anv); glob_vert = -1; loc2distvert.ChangeSize (anv); } void ParallelMeshTopology :: SetNE ( int ane ) { glob_el.SetSize (ane); glob_el = -1; } void ParallelMeshTopology :: SetNSE ( int anse ) { glob_surfel.SetSize(anse); glob_surfel = -1; } void ParallelMeshTopology :: SetNSegm ( int anseg ) { glob_segm.SetSize (anseg); glob_segm = -1; } void ParallelMeshTopology :: UpdateCoarseGridGlobal () { // cout << "updatecoarsegridglobal called" << endl; if (id == 0) PrintMessage ( 3, "UPDATE GLOBAL COARSEGRID STARTS" ); int timer = NgProfiler::CreateTimer ("UpdateCoarseGridGlobal"); NgProfiler::RegionTimer reg(timer); *testout << "ParallelMeshTopology :: UpdateCoarseGridGlobal" << endl; const MeshTopology & topology = mesh.GetTopology(); MPI_Comm comm = mesh.GetCommunicator(); if ( id == 0 ) { Array*> sendarrays(ntasks); for (int dest = 1; dest < ntasks; dest++) sendarrays[dest] = new Array; Array edges, faces; for (int el = 1; el <= mesh.GetNE(); el++) { topology.GetElementFaces (el, faces); topology.GetElementEdges (el, edges); const Element & volel = mesh.VolumeElement (el); // Array & sendarray = *sendarrays[volel.GetPartition()]; Array & sendarray = *sendarrays[mesh.vol_partition[el-1]]; for ( int i = 0; i < edges.Size(); i++ ) sendarray.Append (edges[i]); for ( int i = 0; i < faces.Size(); i++ ) sendarray.Append (faces[i]); } for (int el = 1; el <= mesh.GetNSE(); el++) { topology.GetSurfaceElementEdges (el, edges); const Element2d & surfel = mesh.SurfaceElement (el); // Array & sendarray = *sendarrays[surfel.GetPartition()]; Array & sendarray = *sendarrays[mesh.surf_partition[el-1]]; for ( int i = 0; i < edges.Size(); i++ ) sendarray.Append (edges[i]); sendarray.Append (topology.GetSurfaceElementFace (el)); } Array sendrequests; for (int dest = 1; dest < ntasks; dest++) sendrequests.Append (MyMPI_ISend (*sendarrays[dest], dest, MPI_TAG_MESH+10, comm)); MPI_Waitall (sendrequests.Size(), &sendrequests[0], MPI_STATUS_IGNORE); for (int dest = 1; dest < ntasks; dest++) delete sendarrays[dest]; } else { Array recvarray; MyMPI_Recv (recvarray, 0, MPI_TAG_MESH+10, comm); int ii = 0; Array faces, edges; for (int volel = 1; volel <= mesh.GetNE(); volel++) { topology.GetElementEdges ( volel, edges); for ( int i = 0; i < edges.Size(); i++) SetLoc2Glob_Edge ( edges[i], recvarray[ii++]); topology.GetElementFaces( volel, faces); for ( int i = 0; i < faces.Size(); i++) SetLoc2Glob_Face ( faces[i], recvarray[ii++]); } for (int surfel = 1; surfel <= mesh.GetNSE(); surfel++) { topology.GetSurfaceElementEdges (surfel, edges); for (int i = 0; i < edges.Size(); i++) SetLoc2Glob_Edge (edges[i], recvarray[ii++]); int face = topology.GetSurfaceElementFace (surfel); SetLoc2Glob_Face ( face, recvarray[ii++]); } } is_updated = true; } void ParallelMeshTopology :: UpdateCoarseGrid () { // cout << "UpdateCoarseGrid" << endl; // if (is_updated) return; NgMPI_Comm comm = mesh.GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); if (ntasks == 1) return; Reset(); static int timer = NgProfiler::CreateTimer ("UpdateCoarseGrid"); NgProfiler::RegionTimer reg(timer); (*testout) << "UPDATE COARSE GRID PARALLEL TOPOLOGY " << endl; if (id == 0) PrintMessage (1, "update parallel topology"); // UpdateCoarseGridGlobal(); // MPI_Barrier (MPI_COMM_WORLD); MPI_Group MPI_GROUP_comm; MPI_Group MPI_LocalGroup; MPI_Comm MPI_LocalComm; int process_ranks[] = { 0 }; MPI_Comm_group (comm, &MPI_GROUP_comm); MPI_Group_excl (MPI_GROUP_comm, 1, process_ranks, &MPI_LocalGroup); MPI_Comm_create (comm, MPI_LocalGroup, &MPI_LocalComm); if (id == 0) return; const MeshTopology & topology = mesh.GetTopology(); Array cnt_send(ntasks-1); // update new vertices after mesh-refinement if (mesh.mlbetweennodes.Size() > 0) { // cout << "UpdateCoarseGrid - vertices" << endl; int newnv = mesh.mlbetweennodes.Size(); loc2distvert.ChangeSize(mesh.mlbetweennodes.Size()); /* for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1) for (int dest = 1; dest < ntasks; dest++) if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) SetDistantPNum(dest, pi); } */ bool changed = true; while (changed) { changed = false; // build exchange vertices cnt_send = 0; for (PointIndex pi : mesh.Points().Range()) for (int dist : GetDistantPNums(pi-PointIndex::BASE)) cnt_send[dist-1]++; TABLE dest2vert(cnt_send); for (PointIndex pi : mesh.Points().Range()) for (int dist : GetDistantPNums(pi-PointIndex::BASE)) dest2vert.Add (dist-1, pi); for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1) // for (int dest = 1; dest < ntasks; dest++) for (int dest : GetDistantPNums(v1-PointIndex::BASE)) if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) cnt_send[dest-1]++; } TABLE dest2pair(cnt_send); // for (int dest = 1; dest < ntasks; dest++) for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1) for (int dest : GetDistantPNums(v1-PointIndex::BASE)) if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) dest2pair.Add (dest-1, pi); } cnt_send = 0; int v1, v2; for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1) for (int dest : GetDistantPNums(v1-PointIndex::BASE)) if (IsExchangeVert(dest, v2)) cnt_send[dest-1]+=2; } TABLE send_verts(cnt_send); Array loc2exchange(mesh.GetNV()); for (int dest = 1; dest < ntasks; dest++) if (dest != id) { loc2exchange = -1; int cnt = 0; /* for (PointIndex pi : mesh.Points().Range()) if (IsExchangeVert(dest, pi)) loc2exchange[pi] = cnt++; */ for (PointIndex pi : dest2vert[dest-1]) loc2exchange[pi] = cnt++; // for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) for (PointIndex pi : dest2pair[dest-1]) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1) if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) { send_verts.Add (dest-1, loc2exchange[v1]); send_verts.Add (dest-1, loc2exchange[v2]); } } } TABLE recv_verts(ntasks-1); MyMPI_ExchangeTable (send_verts, recv_verts, MPI_TAG_MESH+9, MPI_LocalComm); for (int dest = 1; dest < ntasks; dest++) if (dest != id) { loc2exchange = -1; int cnt = 0; /* for (PointIndex pi : mesh.Points().Range()) if (IsExchangeVert(dest, pi)) loc2exchange[pi] = cnt++; */ for (PointIndex pi : dest2vert[dest-1]) loc2exchange[pi] = cnt++; FlatArray recvarray = recv_verts[dest-1]; for (int ii = 0; ii < recvarray.Size(); ii+=2) for (PointIndex pi : dest2pair[dest-1]) // for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1) { INDEX_2 re(recvarray[ii], recvarray[ii+1]); INDEX_2 es(loc2exchange[v1], loc2exchange[v2]); if (es == re && !IsExchangeVert(dest, pi)) { SetDistantPNum(dest, pi); changed = true; } } } } } } Array sendarray, recvarray; // cout << "UpdateCoarseGrid - edges" << endl; // static int timerv = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex vertices"); static int timere = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex edges"); static int timerf = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex faces"); NgProfiler::StartTimer (timere); int nfa = topology . GetNFaces(); int ned = topology . GetNEdges(); // build exchange vertices cnt_send = 0; for (PointIndex pi : mesh.Points().Range()) for (int dist : GetDistantPNums(pi-PointIndex::BASE)) cnt_send[dist-1]++; TABLE dest2vert(cnt_send); for (PointIndex pi : mesh.Points().Range()) for (int dist : GetDistantPNums(pi-PointIndex::BASE)) dest2vert.Add (dist-1, pi); // exchange edges cnt_send = 0; int v1, v2; for (int edge = 1; edge <= ned; edge++) { topology.GetEdgeVertices (edge, v1, v2); for (int dest = 1; dest < ntasks; dest++) if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) cnt_send[dest-1]+=1; } TABLE dest2edge(cnt_send); for (int & v : cnt_send) v *= 2; TABLE send_edges(cnt_send); for (int edge = 1; edge <= ned; edge++) { topology.GetEdgeVertices (edge, v1, v2); for (int dest = 1; dest < ntasks; dest++) if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) dest2edge.Add (dest-1, edge); } Array loc2exchange(mesh.GetNV()); for (int dest = 1; dest < ntasks; dest++) { loc2exchange = -1; int cnt = 0; for (PointIndex pi : dest2vert[dest-1]) loc2exchange[pi] = cnt++; for (int edge : dest2edge[dest-1]) { topology.GetEdgeVertices (edge, v1, v2); if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) { send_edges.Add (dest-1, loc2exchange[v1]); send_edges.Add (dest-1, loc2exchange[v2]); } } } // cout << "UpdateCoarseGrid - edges mpi-exchange" << endl; TABLE recv_edges(ntasks-1); MyMPI_ExchangeTable (send_edges, recv_edges, MPI_TAG_MESH+9, MPI_LocalComm); // cout << "UpdateCoarseGrid - edges mpi-exchange done" << endl; /* for (int dest = 1; dest < ntasks; dest++) { auto ex2loc = dest2vert[dest-1]; FlatArray recvarray = recv_edges[dest-1]; for (int ii = 0; ii < recvarray.Size(); ii+=2) for (int edge : dest2edge[dest-1]) { topology.GetEdgeVertices (edge, v1, v2); INDEX_2 re(ex2loc[recvarray[ii]], ex2loc[recvarray[ii+1]]); INDEX_2 es(v1, v2); if (es == re) SetDistantEdgeNum(dest, edge); } } */ for (int dest = 1; dest < ntasks; dest++) { auto ex2loc = dest2vert[dest-1]; if (ex2loc.Size() == 0) continue; INDEX_2_CLOSED_HASHTABLE vert2edge(2*dest2edge[dest-1].Size()+10); for (int edge : dest2edge[dest-1]) { topology.GetEdgeVertices (edge, v1, v2); vert2edge.Set(INDEX_2(v1,v2), edge); } FlatArray recvarray = recv_edges[dest-1]; for (int ii = 0; ii < recvarray.Size(); ii+=2) { INDEX_2 re(ex2loc[recvarray[ii]], ex2loc[recvarray[ii+1]]); if (vert2edge.Used(re)) SetDistantEdgeNum(dest, vert2edge.Get(re)); } } NgProfiler::StopTimer (timere); // MPI_Barrier (MPI_LocalComm); // cout << "UpdateCoarseGrid - faces" << endl; if (mesh.GetDimension() == 3) { NgProfiler::StartTimer (timerf); Array verts; // exchange faces cnt_send = 0; for (int face = 1; face <= nfa; face++) { topology.GetFaceVertices (face, verts); for (int dest = 1; dest < ntasks; dest++) if (dest != id) if (IsExchangeVert (dest, verts[0]) && IsExchangeVert (dest, verts[1]) && IsExchangeVert (dest, verts[2])) cnt_send[dest-1]++; } TABLE dest2face(cnt_send); for (int face = 1; face <= nfa; face++) { topology.GetFaceVertices (face, verts); for (int dest = 1; dest < ntasks; dest++) if (dest != id) if (IsExchangeVert (dest, verts[0]) && IsExchangeVert (dest, verts[1]) && IsExchangeVert (dest, verts[2])) dest2face.Add(dest-1, face); } for (int & c : cnt_send) c*=3; TABLE send_faces(cnt_send); Array loc2exchange(mesh.GetNV()); for (int dest = 1; dest < ntasks; dest++) if (dest != id) { /* loc2exchange = -1; int cnt = 0; for (PointIndex pi : mesh.Points().Range()) if (IsExchangeVert(dest, pi)) loc2exchange[pi] = cnt++; */ if (dest2vert[dest-1].Size() == 0) continue; loc2exchange = -1; int cnt = 0; for (PointIndex pi : dest2vert[dest-1]) loc2exchange[pi] = cnt++; for (int face : dest2face[dest-1]) { topology.GetFaceVertices (face, verts); if (IsExchangeVert (dest, verts[0]) && IsExchangeVert (dest, verts[1]) && IsExchangeVert (dest, verts[2])) { send_faces.Add (dest-1, loc2exchange[verts[0]]); send_faces.Add (dest-1, loc2exchange[verts[1]]); send_faces.Add (dest-1, loc2exchange[verts[2]]); } } } // cout << "UpdateCoarseGrid - faces mpi-exchange" << endl; TABLE recv_faces(ntasks-1); MyMPI_ExchangeTable (send_faces, recv_faces, MPI_TAG_MESH+9, MPI_LocalComm); // cout << "UpdateCoarseGrid - faces mpi-exchange done" << endl; /* for (int dest = 1; dest < ntasks; dest++) if (dest != id) { loc2exchange = -1; int cnt = 0; for (PointIndex pi : dest2vert[dest-1]) loc2exchange[pi] = cnt++; FlatArray recvarray = recv_faces[dest-1]; for (int ii = 0; ii < recvarray.Size(); ii+=3) for (int face : dest2face[dest-1]) { topology.GetFaceVertices (face, verts); INDEX_3 re(recvarray[ii], recvarray[ii+1], recvarray[ii+2]); INDEX_3 es(loc2exchange[verts[0]], loc2exchange[verts[1]], loc2exchange[verts[2]]); if (es == re) SetDistantFaceNum(dest, face); } } */ for (int dest = 1; dest < ntasks; dest++) { auto ex2loc = dest2vert[dest-1]; if (ex2loc.Size() == 0) continue; INDEX_3_CLOSED_HASHTABLE vert2face(2*dest2face[dest-1].Size()+10); for (int face : dest2face[dest-1]) { topology.GetFaceVertices (face, verts); vert2face.Set(INDEX_3(verts[0], verts[1], verts[2]), face); } FlatArray recvarray = recv_faces[dest-1]; for (int ii = 0; ii < recvarray.Size(); ii+=3) { INDEX_3 re(ex2loc[recvarray[ii]], ex2loc[recvarray[ii+1]], ex2loc[recvarray[ii+2]]); if (vert2face.Used(re)) SetDistantFaceNum(dest, vert2face.Get(re)); } } /* Array glob2loc; int maxface = 0; for (int face = 1; face <= nfa; face++) maxface = max (maxface, GetGlobalFaceNum (face)); // glob2loc.SetSize (nfaglob); glob2loc.SetSize (maxface); glob2loc = -1; for (int loc = 1; loc <= nfa; loc++) glob2loc[GetGlobalFaceNum(loc)] = loc; cnt_send = 0; Array verts; for (int face = 1; face <= nfa; face++) { topology.GetFaceVertices (face, verts); for (int dest = 1; dest < ntasks; dest++) if (IsExchangeVert (dest, verts[0]) && IsExchangeVert (dest, verts[1]) && IsExchangeVert (dest, verts[2])) { cnt_send[dest-1]+=2; } } TABLE send_faces(cnt_send); for (int face = 1; face <= nfa; face++) { topology.GetFaceVertices (face, verts); for (int dest = 1; dest < ntasks; dest++) { if (IsExchangeVert (dest, verts[0]) && IsExchangeVert (dest, verts[1]) && IsExchangeVert (dest, verts[2])) { send_faces.Add (dest-1, GetGlobalFaceNum(face)); send_faces.Add (dest-1, face); } } } TABLE recv_faces(ntasks-1); MyMPI_ExchangeTable (send_faces, recv_faces, MPI_TAG_MESH+8, MPI_LocalComm); for (int sender = 1; sender < ntasks; sender ++) if (id != sender) { FlatArray recvarray = recv_faces[sender-1]; for (int ii = 0; ii < recvarray.Size(); ) { int globf = recvarray[ii++]; int distf = recvarray[ii++]; if (globf <= maxface) { int locf = glob2loc[globf]; if (locf != -1) SetDistantFaceNum (sender, locf); } } } */ NgProfiler::StopTimer (timerf); } // cout << "UpdateCoarseGrid - done" << endl; is_updated = true; } } #endif netgen-6.2.1905/libsrc/meshing/improve2gen.cpp0000644000175000017500000002644713504650527017667 0ustar kurtkurt#include #include "meshing.hpp" #include namespace netgen { class ImprovementRule { public: Array oldels; Array newels; Array deledges; Array incelsonnode; Array reused; int bonus; int onp; }; void MeshOptimize2d :: GenericImprove (Mesh & mesh) { if (!faceindex) { if (writestatus) PrintMessage (3, "Generic Improve"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) GenericImprove (mesh); faceindex = 0; } // int j, k, l, ri; int np = mesh.GetNP(); int ne = mesh.GetNSE(); // SurfaceElementIndex sei; // for (SurfaceElementIndex sei = 0; sei < ne; sei++) // { // const Element2d & el = mesh[sei]; // (*testout) << "element " << sei << ": " < rules; Array elmap; Array elrot; Array pmap; Array pgi; int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); ImprovementRule * r1; // 2 triangles to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3)); r1->oldels.Append (Element2d (3, 2, 4)); r1->newels.Append (Element2d (1, 2, 4, 3)); r1->deledges.Append (INDEX_2 (2,3)); r1->onp = 4; r1->bonus = 2; rules.Append (r1); // 2 quad to 1 quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (4, 3, 2, 5)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // swap quads r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 6, 3, 4)); r1->newels.Append (Element2d (1, 2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // three quads to 2 r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (3, 6, 7, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->newels.Append (Element2d (4, 5, 6, 7)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 7; r1->bonus = -1; rules.Append (r1); // quad + 2 connected trigs to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->oldels.Append (Element2d (3, 5, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 5)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // quad + 2 non-connected trigs to quad (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 3, 4, 5)); r1->newels.Append (Element2d (1, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 2, 4, 5)); r1->newels.Append (Element2d (4, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // two quad + trig -> one quad + trig r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (4, 3, 6)); r1->newels.Append (Element2d (1, 2, 6, 4)); r1->newels.Append (Element2d (2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 6; r1->bonus = -1; rules.Append (r1); // swap quad + trig (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (2, 5, 3, 4)); r1->newels.Append (Element2d (1, 2, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (1, 2, 5, 3)); r1->newels.Append (Element2d (1, 3, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // 2 quads to quad + 2 trigs r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 5, 6, 4)); r1->newels.Append (Element2d (1, 2, 5)); r1->newels.Append (Element2d (4, 6, 3)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; // rules.Append (r1); Array mapped(rules.Size()); Array used(rules.Size()); used = 0; mapped = 0; for (int ri = 0; ri < rules.Size(); ri++) { ImprovementRule & rule = *rules[ri]; rule.incelsonnode.SetSize (rule.onp); rule.reused.SetSize (rule.onp); for (int j = 1; j <= rule.onp; j++) { rule.incelsonnode.Elem(j) = 0; rule.reused.Elem(j) = 0; } for (int j = 1; j <= rule.oldels.Size(); j++) { const Element2d & el = rule.oldels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) rule.incelsonnode.Elem(el.PNum(k))--; } for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & el = rule.newels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) { rule.incelsonnode.Elem(el.PNum(k))++; rule.reused.Elem(el.PNum(k)) = 1; } } } TABLE elonnode(np); Array nelonnode(np); TABLE nbels(ne); nelonnode = -4; for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) elonnode.Add (el[j], sei); } if(!el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) nelonnode[el[j]]++; } } for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) { for (int k = 0; k < elonnode[el[j]].Size(); k++) { int nbel = elonnode[el[j]] [k]; bool inuse = false; for (int l = 0; l < nbels[sei].Size(); l++) if (nbels[sei][l] == nbel) inuse = true; if (!inuse) nbels.Add (sei, nbel); } } } } for (int ri = 0; ri < rules.Size(); ri++) { const ImprovementRule & rule = *rules[ri]; elmap.SetSize (rule.oldels.Size()); elrot.SetSize (rule.oldels.Size()); pmap.SetSize (rule.onp); pgi.SetSize (rule.onp); for (SurfaceElementIndex sei = 0; sei < ne; sei++) { if (multithread.terminate) break; if (mesh[sei].IsDeleted()) continue; elmap[0] = sei; FlatArray neighbours = nbels[sei]; for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++) { const Element2d & el0 = mesh[sei]; const Element2d & rel0 = rule.oldels[0]; if (el0.GetIndex() != faceindex) continue; if (el0.IsDeleted()) continue; if (el0.GetNP() != rel0.GetNP()) continue; pmap = PointIndex (-1); for (int k = 0; k < el0.GetNP(); k++) { pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1); pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1); } ok = 1; for (int i = 1; i < elmap.Size(); i++) { // try to find a mapping for reference-element i const Element2d & rel = rule.oldels[i]; bool possible = 0; for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++) { const Element2d & el = mesh[neighbours[elmap[i]]]; if (el.IsDeleted()) continue; if (el.GetNP() != rel.GetNP()) continue; for (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++) { possible = 1; for (int k = 0; k < rel.GetNP(); k++) if (pmap.Elem(rel[k]) != -1 && pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1)) possible = 0; if (possible) { for (int k = 0; k < el.GetNP(); k++) { pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1); pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1); } break; } } if (possible) break; } if (!possible) { ok = 0; break; } elmap[i] = neighbours[elmap[i]]; } for(int i=0; ok && i olddef) continue; // calc metric badness double bad1 = 0, bad2 = 0; Vec<3> n; SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1)); GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n); for (int j = 1; j <= rule.oldels.Size(); j++) bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n); // check new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); for (int k = 1; k <= rnel.GetNP(); k++) nel.PNum(k) = pmap.Get(rnel.PNum(k)); bad2 += nel.CalcJacobianBadness (mesh.Points(), n); } if (bad2 > 1e3) continue; if (newdef == olddef && bad2 > bad1) continue; // generate new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); nel.SetIndex (faceindex); for (int k = 1; k <= rnel.GetNP(); k++) { nel.PNum(k) = pmap.Get(rnel.PNum(k)); nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k)); } mesh.AddSurfaceElement(nel); } for (int j = 0; j < rule.oldels.Size(); j++) mesh.DeleteSurfaceElement ( elmap[j] ); for (int j = 1; j <= pmap.Size(); j++) nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j); used[ri]++; } } } mesh.Compress(); for (int ri = 0; ri < rules.Size(); ri++) { PrintMessage (5, "rule ", ri+1, " ", mapped[ri], "/", used[ri], " mapped/used"); } } } netgen-6.2.1905/libsrc/meshing/ruler3.hpp0000644000175000017500000001272313504650527016643 0ustar kurtkurt#ifndef FILE_RULER3 #define FILE_RULER3 /** 3D element generation rule. */ class vnetrule { private: /// rule is applicable for quality classes above this value int quality; /// name of rule char * name; /// point coordinates in reference position Array points; /// old and new faces in reference numbering Array faces; /// additional edges of rule Array edges; /// points of freezone in reference coordinates Array freezone; /// points of freezone in reference coordinates if tolcalss to infty Array freezonelimit; /// point index, if point equal to mappoint, otherwise 0 Array freezonepi; /// faces of each convex part of freezone Array*> freefaces; /// set of points of each convex part of freezone Array*> freesets; /// points of transformed freezone Array transfreezone; /// edges of each convex part of freezone Array*> freeedges; /// face numbers to be deleted Array delfaces; /// elements to be generated Array elements; /// tolerances for points and faces (used ??) Array tolerances, linetolerances; /// transformation matrix DenseMatrix oldutonewu; /// transformation matrix: deviation old point to dev. freezone DenseMatrix * oldutofreezone; /** transformation matrix: deviation old point to dev. freezone, quality class to infinity */ DenseMatrix * oldutofreezonelimit; // can be deleted: // BaseMatrix *outf, *outfl; /** a point is outside of convex part of freezone, iff mat * (point, 1) >= 0 for each component (correct ?) */ Array freefaceinequ; /// Array orientations; /** flags specified in rule-description file: t .. test rule */ Array flags; /** topological distance of face to base element non-connected: > 100 (??) */ Array fnearness; Array pnearness; int maxpnearness; /// number of old points in rule int noldp; /// number of new poitns in rule int noldf; /// box containing free-zone public: // double fzminx, fzmaxx, fzminy, fzmaxy, fzminz, fzmaxz; Box3d fzbox; public: /// vnetrule (); /// ~vnetrule (); /// int GetNP () const { return points.Size(); } /// int GetNF () const { return faces.Size(); } /// int GetNE () const { return elements.Size(); } /// int GetNO () const { return orientations.Size(); } /// int GetNEd () const { return edges.Size(); } /// int GetNOldP () const { return noldp; } /// int GetNOldF () const { return noldf; } /// int GetNDelF () const { return delfaces.Size(); } /// int GetQuality () const { return quality; } /// int GetFNearness (int fi) const { return fnearness.Get(fi); } /// int GetPNearness (int pi) const { return pnearness.Get(pi); } /// int GetMaxPNearness () const { return maxpnearness; } /// const Point3d & GetPoint (int i) const { return points.Get(i); } /// const Element2d & GetFace (int i) const { return faces.Get(i); } /// const Element & GetElement (int i) const { return elements.Get(i); } /// const twoint & GetEdge (int i) const { return edges.Get(i); } /// int GetDelFace (int i) const { return delfaces.Get(i); } /// int IsDelFace (int fn) const; /// float CalcPointDist (int pi, const Point3d & p) const; /// double PointDistFactor (int pi) const { return tolerances.Get(pi); } /// void SetFreeZoneTransformation (const Vector & allp, int tolclass); /// int IsInFreeZone (const Point3d & p) const; /** 0 not in free-zone 1 in free-zone -1 maybe */ int IsTriangleInFreeZone (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Array & pi, int newone); /// int IsQuadInFreeZone (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, const Array & pi, int newone); /// int IsTriangleInFreeSet (const Point3d & p1, const Point3d & p2, const Point3d & p3, int fs, const Array & pi, int newone); /// int IsQuadInFreeSet (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, int fs, const Array & pi, int newone); /// int ConvexFreeZone () const; /// if t1 and t2 are neighbourtriangles, NTP returns the opposite Point of t1 in t2 int NeighbourTrianglePoint (const threeint & t1, const threeint & t2) const; /// const Point3d & GetTransFreeZone (int i) { return transfreezone.Get(i); } /// int GetNP (int fn) const { return faces.Get(fn).GetNP(); } /// int GetPointNr (int fn, int endp) const { return faces.Get(fn).PNum(endp); } /// int GetPointNrMod (int fn, int endp) const { return faces.Get(fn).PNumMod(endp); } /// const fourint & GetOrientation (int i) { return orientations.Get(i); } /// int TestFlag (char flag) const; /// const DenseMatrix & GetOldUToNewU () const { return oldutonewu; } // // const DenseMatrix & GetOldUToFreeZone () const { return oldutofreezone; } // // const DenseMatrix & GetOldUToFreeZoneLimit () const // { return oldutofreezonelimit; } /// const char * Name () const { return name; } /// void LoadRule (istream & ist); /// const Array & GetTransFreeZone () { return transfreezone; } /// int TestOk () const; /// friend void TestRules (); /// // friend void Plot3DRule (const ROT3D & r, char key); }; #endif netgen-6.2.1905/libsrc/meshing/hpref_hex.hpp0000644000175000017500000001027513504650527017377 0ustar kurtkurt// SZ // HP_HEX ... no refinement int refhex_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refhex_newelstypes[] = { HP_HEX, HP_NONE, }; int refhex_newels[][8] = { { 1, 2, 3, 4, 5, 6, 7, 8 } }; HPRef_Struct refhex = { HP_HEX, refhex_splitedges, 0, 0, refhex_newelstypes, refhex_newels }; // HP_HEX_1F ... face (1 - 4 - 3 -2) singular int refhex_1f_0e_0v_splitedges[][3] = { { 1, 5, 9 }, { 2, 6, 10 }, { 3, 7, 11 }, { 4, 8, 12 }, { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refhex_1f_0e_0v_newelstypes[] = { HP_HEX, HP_HEX_1F_0E_0V, HP_NONE, }; int refhex_1f_0e_0v_newels[][8] = { { 9, 10, 11, 12, 5, 6, 7, 8 }, { 1, 2, 3, 4, 9, 10, 11, 12} }; HPRef_Struct refhex_1f_0e_0v = { HP_HEX, refhex_1f_0e_0v_splitedges, 0, 0, refhex_1f_0e_0v_newelstypes, refhex_1f_0e_0v_newels }; // HP_HEX_1FA_1FB ... face (1 - 4 - 3 -2) and face (1-2-6-5) singular int refhex_1fa_1fb_0e_0v_splitedges[][3] = { { 1, 5, 9 }, { 2, 6, 10 }, { 3, 7, 11 }, { 4, 8, 12 }, { 1, 4, 13 }, { 2, 3, 14 }, { 6, 7, 15 }, { 5, 8, 16 }, { 0, 0, 0 } }; int refhex_1fa_1fb_0e_0v_splitfaces[][4] = { { 2, 3, 6, 17 }, { 1, 4, 5, 18 }, { 0, 0, 0, 0 }, }; HPREF_ELEMENT_TYPE refhex_1fa_1fb_0e_0v_newelstypes[] = { HP_HEX, HP_HEX_1F_0E_0V, HP_HEX_1F_0E_0V, HP_HEX_1FA_1FB_0E_0V, HP_NONE, }; int refhex_1fa_1fb_0e_0v_newels[][8] = { {18, 17, 11, 12, 16, 15, 7, 8}, {13, 14, 3, 4, 18, 17, 11, 12}, { 5, 6, 10, 9, 16, 15, 17, 18}, { 1, 2, 14, 13, 9, 10, 17, 18} }; HPRef_Struct refhex_1fa_1fb_0e_0v = { HP_HEX, refhex_1fa_1fb_0e_0v_splitedges, refhex_1fa_1fb_0e_0v_splitfaces, 0, refhex_1fa_1fb_0e_0v_newelstypes, refhex_1fa_1fb_0e_0v_newels }; // Refine Dummies // HP_HEX_0E_1V int refhex_0e_1v_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refhex_0e_1v_newelstypes[] = { HP_TET_0E_1V, HP_TET, HP_TET, HP_TET, HP_TET, HP_TET, HP_NONE, }; int refhex_0e_1v_newels[][8] = { { 1, 5, 2, 4 }, { 7, 3, 6, 8 }, { 2, 8, 5, 6 }, { 2, 8, 6, 3 }, { 2, 8, 3, 4 }, { 2, 8, 4, 5 }, }; HPRef_Struct refhex_0e_1v = { HP_HEX, refhex_0e_1v_splitedges, 0, 0, refhex_0e_1v_newelstypes, refhex_0e_1v_newels }; // Refine Dummies // HP_HEX_1E_1V int refhex_1e_1v_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refhex_1e_1v_newelstypes[] = { HP_TET_1E_1VA, HP_TET, HP_TET_0E_1V, HP_TET_0E_1V, HP_TET_0E_1V, HP_TET_0E_1V, HP_NONE, }; int refhex_1e_1v_newels[][8] = { // { 1, 5, 2, 4 }, { 1, 2, 4, 5 }, { 7, 3, 6, 8 }, { 2, 8, 5, 6 }, { 2, 8, 6, 3 }, { 2, 8, 3, 4 }, { 2, 8, 4, 5 }, }; HPRef_Struct refhex_1e_1v = { HP_HEX, refhex_1e_1v_splitedges, 0, 0, refhex_1e_1v_newelstypes, refhex_1e_1v_newels }; // Refine Dummies // HP_HEX_3E_0V int refhex_3e_0v_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refhex_3e_0v_newelstypes[] = { HP_TET_1E_1VA, HP_TET_1E_1VA, HP_TET_1E_1VA, HP_TET_0E_1V, HP_TET, HP_NONE, }; int refhex_3e_0v_newels[][8] = { { 1, 2, 3, 6 }, { 1, 4, 8, 3 }, { 1, 5, 6, 8 }, { 1, 6, 3, 8 }, { 3, 8, 6, 7 }, }; HPRef_Struct refhex_3e_0v = { HP_HEX, refhex_3e_0v_splitedges, 0, 0, refhex_3e_0v_newelstypes, refhex_3e_0v_newels }; // Refine Dummies // HP_HEX_1E_0V int refhex_1e_0v_splitedges[][3] = { { 0, 0, 0 } }; HPREF_ELEMENT_TYPE refhex_1e_0v_newelstypes[] = { HP_PRISM_SINGEDGE, // HP_PRISM_SINGEDGE_H1, HP_PRISM, HP_NONE, }; int refhex_1e_0v_newels[][8] = { { 1, 4, 5, 2, 3, 6 }, { 5, 4, 8, 6, 3, 7 }, }; HPRef_Struct refhex_1e_0v = { HP_HEX, refhex_1e_0v_splitedges, 0, 0, refhex_1e_0v_newelstypes, refhex_1e_0v_newels }; netgen-6.2.1905/libsrc/meshing/meshtool.cpp0000644000175000017500000004771413504650527017264 0ustar kurtkurt#include #include "meshing.hpp" #include #include namespace netgen { int CheckSurfaceMesh (const Mesh & mesh) { PrintMessage (3, "Check Surface mesh"); int nf = mesh.GetNSE(); INDEX_2_HASHTABLE edges(nf+2); int i, j; INDEX_2 i2; int cnt1 = 0, cnt2 = 0; for (i = 1; i <= nf; i++) for (j = 1; j <= 3; j++) { i2.I1() = mesh.SurfaceElement(i).PNumMod(j); i2.I2() = mesh.SurfaceElement(i).PNumMod(j+1); if (edges.Used(i2)) { int hi; hi = edges.Get(i2); if (hi != 1) PrintSysError ("CheckSurfaceMesh, hi = ", hi); edges.Set(i2, 2); cnt2++; } else { Swap (i2.I1(), i2.I2()); edges.Set(i2, 1); cnt1++; } } if (cnt1 != cnt2) { PrintUserError ("Surface mesh not consistent"); // MyBeep(2); // (*mycout) << "cnt1 = " << cnt1 << " cnt2 = " << cnt2 << endl; return 0; } return 1; } int CheckSurfaceMesh2 (const Mesh & mesh) { int i, j, k; const Point<3> *tri1[3], *tri2[3]; for (i = 1; i <= mesh.GetNOpenElements(); i++) { PrintDot (); for (j = 1; j < i; j++) { for (k = 1; k <= 3; k++) { tri1[k-1] = &mesh.Point (mesh.OpenElement(i).PNum(k)); tri2[k-1] = &mesh.Point (mesh.OpenElement(j).PNum(k)); } if (IntersectTriangleTriangle (&tri1[0], &tri2[0])) { PrintSysError ("Surface elements are intersecting"); (*testout) << "Intersecting: " << endl; for (k = 0; k <= 2; k++) (*testout) << *tri1[k] << " "; (*testout) << endl; for (k = 0; k <= 2; k++) (*testout) << *tri2[k] << " "; (*testout) << endl; } } } return 0; } static double TriangleQualityInst (const Point3d & p1, const Point3d & p2, const Point3d & p3) { // quality 0 (worst) .. 1 (optimal) Vec3d v1, v2, v3; double s1, s2, s3; double an1, an2, an3; v1 = p2 - p1; v2 = p3 - p1; v3 = p3 - p2; an1 = Angle (v1, v2); v1 *= -1; an2 = Angle (v1, v3); an3 = Angle (v2, v3); s1 = sin (an1/2); s2 = sin (an2/2); s3 = sin (an3/2); return 8 * s1 * s2 * s3; } void MeshQuality2d (const Mesh & mesh) { int ncl = 20, cl; Array incl(ncl); INDEX i; SurfaceElementIndex sei; double qual; incl = 0; for (sei = 0; sei < mesh.GetNSE(); sei++) { qual = TriangleQualityInst (mesh[mesh[sei][0]], mesh[mesh[sei][1]], mesh[mesh[sei][2]]); cl = int ( (ncl-1e-3) * qual ) + 1; incl.Elem(cl)++; } (*testout) << endl << endl; (*testout) << "Points: " << mesh.GetNP() << endl; (*testout) << "Surface Elements: " << mesh.GetNSE() << endl; (*testout) << endl; (*testout) << "Elements in qualityclasses:" << endl; // (*testout).precision(2); (*testout) << setprecision(2); for (i = 1; i <= ncl; i++) { (*testout) << setw(4) << double (i-1)/ncl << " - " << setw(4) << double (i) / ncl << ": " << incl.Get(i) << endl; } } static double TetElementQuality (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4) { double vol, l, l4, l5, l6; Vec3d v1 = p2 - p1; Vec3d v2 = p3 - p1; Vec3d v3 = p4 - p1; vol = fabs ((Cross (v1, v2) * v3)) / 6; l4 = Dist (p2, p3); l5 = Dist (p2, p4); l6 = Dist (p3, p4); l = v1.Length() + v2.Length() + v3.Length() + l4 + l5 + l6; if (vol <= 1e-8 * l * l * l) return 1e-10; return vol/(l*l*l) * 1832.82; // 6^4 * sqrt(2) } // static double teterrpow = 2; double CalcTetBadness (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, double h, const MeshingParameters & mp) { double vol, l, ll, lll, ll1, ll2, ll3, ll4, ll5, ll6; double err; Vec3d v1 (p1, p2); Vec3d v2 (p1, p3); Vec3d v3 (p1, p4); vol = Determinant (v1, v2, v3) * (-0.166666666666666); ll1 = v1.Length2(); ll2 = v2.Length2(); ll3 = v3.Length2(); ll4 = Dist2 (p2, p3); ll5 = Dist2 (p2, p4); ll6 = Dist2 (p3, p4); ll = ll1 + ll2 + ll3 + ll4 + ll5 + ll6; l = sqrt (ll); lll = l * ll; if (vol <= 1e-24 * lll) return 1e24; err = 0.0080187537 * lll / vol; // sqrt(216) / (6^4 * sqrt(2)) if (h > 0) err += ll / (h * h) + h * h * ( 1 / ll1 + 1 / ll2 + 1 / ll3 + 1 / ll4 + 1 / ll5 + 1 / ll6 ) - 12; double teterrpow = mp.opterrpow; if(teterrpow < 1) teterrpow = 1; if (teterrpow == 1) return err; if (teterrpow == 2) return err*err; return pow (err, teterrpow); } double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, double h, int pi, Vec<3> & grad, const MeshingParameters & mp) { double vol, l, ll, lll; double err; const Point3d *pp1, *pp2, *pp3, *pp4; pp1 = &p1; pp2 = &p2; pp3 = &p3; pp4 = &p4; switch (pi) { case 2: { swap (pp1, pp2); swap (pp3, pp4); break; } case 3: { swap (pp1, pp3); swap (pp2, pp4); break; } case 4: { swap (pp1, pp4); swap (pp3, pp2); break; } } Vec3d v1 (*pp1, *pp2); Vec3d v2 (*pp1, *pp3); Vec3d v3 (*pp1, *pp4); Vec3d v4 (*pp2, *pp3); Vec3d v5 (*pp2, *pp4); Vec3d v6 (*pp3, *pp4); vol = Determinant (v1, v2, v3) * (-0.166666666666666); Vec3d gradvol; Cross (v5, v4, gradvol); gradvol *= (-1.0/6.0); double ll1 = v1.Length2(); double ll2 = v2.Length2(); double ll3 = v3.Length2(); double ll4 = v4.Length2(); double ll5 = v5.Length2(); double ll6 = v6.Length2(); ll = ll1 + ll2 + ll3 + ll4 + ll5 + ll6; l = sqrt (ll); lll = l * ll; if (vol <= 1e-24 * lll) { grad = Vec3d (0, 0, 0); return 1e24; } Vec3d gradll1 (*pp2, *pp1); Vec3d gradll2 (*pp3, *pp1); Vec3d gradll3 (*pp4, *pp1); gradll1 *= 2; gradll2 *= 2; gradll3 *= 2; Vec3d gradll (gradll1); gradll += gradll2; gradll += gradll3; /* Vec3d gradll; gradll = v1+v2+v3; gradll *= -2; */ err = 0.0080187537 * lll / vol; gradll *= (0.0080187537 * 1.5 * l / vol); Vec3d graderr(gradll); gradvol *= ( -0.0080187537 * lll / (vol * vol) ); graderr += gradvol; if (h > 0) { /* Vec3d gradll1 (*pp2, *pp1); Vec3d gradll2 (*pp3, *pp1); Vec3d gradll3 (*pp4, *pp1); gradll1 *= 2; gradll2 *= 2; gradll3 *= 2; */ err += ll / (h*h) + h*h * ( 1 / ll1 + 1 / ll2 + 1 / ll3 + 1 / ll4 + 1 / ll5 + 1 / ll6 ) - 12; graderr += (1/(h*h) - h*h/(ll1*ll1)) * gradll1; graderr += (1/(h*h) - h*h/(ll2*ll2)) * gradll2; graderr += (1/(h*h) - h*h/(ll3*ll3)) * gradll3; } double errpow; double teterrpow = mp.opterrpow; if(teterrpow < 1) teterrpow = 1; if (teterrpow == 1) { errpow = err; grad = graderr; } else if (teterrpow == 2) { errpow = err*err; grad = (2 * err) * graderr; } else { errpow = pow (err, teterrpow); grad = (teterrpow * errpow / err) * graderr; } return errpow; } /* double CalcTetBadness (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, double h) { double vol, l; double err; Vec3d v1 (p1, p2); Vec3d v2 (p1, p3); Vec3d v3 (p1, p4); vol = -Determinant (v1, v2, v3) / 6; double l1 = v1.Length(); double l2 = v2.Length(); double l3 = v3.Length(); double l4 = Dist (p2, p3); double l5 = Dist (p2, p4); double l6 = Dist (p3, p4); l = l1 + l2 + l3 + l4 + l5 + l6; // just for timing // l += 1e-40 * CalcTetBadnessNew (p1, p2, p3, p4, h); if (vol <= 1e-24 * l * l * l) { return 1e24; } err = (l*l*l) / (1832.82 * vol); // 6^4 * sqrt(2) if (h > 0) err += l / h + h * (1 / l1 + 1/l2 + 1/l3 + 1/l4 + 1/l5 + 1/l6) - 12; return pow (err, teterrpow); } double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4, double h, int pi, Vec3d & grad) { double vol, l; double err; const Point3d *pp1, *pp2, *pp3, *pp4; pp1 = &p1; pp2 = &p2; pp3 = &p3; pp4 = &p4; switch (pi) { case 2: { swap (pp1, pp2); swap (pp3, pp4); break; } case 3: { swap (pp1, pp3); swap (pp2, pp4); break; } case 4: { swap (pp1, pp4); swap (pp3, pp2); break; } } Vec3d v1 (*pp1, *pp2); Vec3d v2 (*pp1, *pp3); Vec3d v3 (*pp1, *pp4); Vec3d v4 (*pp2, *pp3); Vec3d v5 (*pp2, *pp4); Vec3d v6 (*pp3, *pp4); // Vec3d n; // Cross (v1, v2, n); // vol = - (n * v3) / 6; vol = -Determinant (v1, v2, v3) / 6; Vec3d gradvol; Cross (v5, v4, gradvol); gradvol *= (-1.0/6.0); double l1 = v1.Length(); double l2 = v2.Length(); double l3 = v3.Length(); double l4 = v4.Length(); double l5 = v5.Length(); double l6 = v6.Length(); l = l1 + l2 + l3 +l4 + l5 + l6; Vec3d gradl1 (*pp2, *pp1); Vec3d gradl2 (*pp3, *pp1); Vec3d gradl3 (*pp4, *pp1); gradl1 /= l1; gradl2 /= l2; gradl3 /= l3; Vec3d gradl (gradl1); gradl += gradl2; gradl += gradl3; if (vol <= 1e-24 * l * l * l) { grad = Vec3d (0, 0, 0); return 1e24; } double c1 = 1.0 / 1832.82; // 6^4 * sqrt(2) err = c1 * (l*l*l) / vol; gradl *= (c1 * 3 * l * l / vol); Vec3d graderr(gradl); gradvol *= ( -c1 * l * l * l / (vol * vol) ); graderr+= gradvol; if (h > 0) { err += l / h + h * ( 1 / l1 + 1 / l2 + 1 / l3 + 1 / l4 + 1 / l5 + 1 / l6 ) - 12; graderr += (1/h - h/(l1*l1)) * gradl1; graderr += (1/h - h/(l2*l2)) * gradl2; graderr += (1/h - h/(l3*l3)) * gradl3; cout << "?"; } double errpow = pow (err, teterrpow); grad = (teterrpow * errpow / err) * graderr; return errpow; } */ /* double CalcVolume (const Array & points, const Element & el) { Vec3d v1 = points.Get(el.PNum(2)) - points.Get(el.PNum(1)); Vec3d v2 = points.Get(el.PNum(3)) - points.Get(el.PNum(1)); Vec3d v3 = points.Get(el.PNum(4)) - points.Get(el.PNum(1)); return -(Cross (v1, v2) * v3) / 6; } */ double CalcVolume (const Array & points, const Array & elements) { double vol; Vec3d v1, v2, v3; vol = 0; for (int i = 0; i < elements.Size(); i++) { v1 = points.Get(elements[i][1]) - points.Get(elements[i][0]); v2 = points.Get(elements[i][2]) - points.Get(elements[i][0]); v3 = points.Get(elements[i][3]) - points.Get(elements[i][0]); vol -= (Cross (v1, v2) * v3) / 6; } return vol; } void MeshQuality3d (const Mesh & mesh, Array * inclass) { int ncl = 20; signed int cl; Array incl(ncl); INDEX i; double qual; double sum = 0; int nontet = 0; for (i = 1; i <= incl.Size(); i++) incl.Elem(i) = 0; for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) { if (mesh[ei].GetType() != TET) { nontet++; continue; } qual = TetElementQuality (mesh.Point(mesh[ei][0]), mesh.Point(mesh[ei][1]), mesh.Point(mesh[ei][2]), mesh.Point(mesh[ei][3])); if (qual > 1) qual = 1; cl = int (ncl * qual ) + 1; if (cl < 1) cl = 1; if (cl > ncl) cl = ncl; incl.Elem(cl)++; if (inclass) (*inclass)[ei] = cl; sum += 1/qual; } (*testout) << endl << endl; (*testout) << "Points: " << mesh.GetNP() << endl; (*testout) << "Volume Elements: " << mesh.GetNE() << endl; if (nontet) (*testout) << nontet << " non tetrahedral elements" << endl; (*testout) << endl; (*testout) << "Volume elements in qualityclasses:" << endl; (*testout) << setprecision(2); for (i = 1; i <= ncl; i++) { (*testout) << setw(4) << double (i-1)/ncl << " - " << setw(4) << double (i) / ncl << ": " << incl.Get(i) << endl; } (*testout) << "total error: " << sum << endl; } void SaveEdges (const Mesh & mesh, const char * geomfile, double h, char * filename) { ofstream of (filename); int i; const Segment * seg; of << "edges" << endl; of << geomfile << endl; of << h << endl; of << mesh.GetNP() << endl; for (i = 1; i <= mesh.GetNP(); i++) of << mesh.Point(i)(0) << " " << mesh.Point(i)(1) << " " << mesh.Point(i)(2) << "\n"; of << 2 * mesh.GetNSeg() << endl; for (i = 1; i <= mesh.GetNSeg(); i++) { seg = &mesh.LineSegment(i); of << (*seg)[1] << " " << (*seg)[0] << " " << seg->si << "\n"; } } void SaveSurfaceMesh (const Mesh & mesh, double h, char * filename) { INDEX i; ofstream outfile(filename); outfile << "surfacemesh" << endl; outfile << h << endl; outfile << mesh.GetNP() << endl; for (i = 1; i <= mesh.GetNP(); i++) outfile << mesh.Point(i)(0) << " " << mesh.Point(i)(1) << " " << mesh.Point(i)(2) << endl; outfile << mesh.GetNSE() << endl; for (i = 1; i <= mesh.GetNSE(); i++) { const Element2d & el = mesh.SurfaceElement(i); if (mesh.GetFaceDescriptor(el.GetIndex()).DomainOut() == 0) outfile << mesh.SurfaceElement(i).PNum(1) << " " << mesh.SurfaceElement(i).PNum(2) << " " << mesh.SurfaceElement(i).PNum(3) << endl; if (mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() == 0) outfile << mesh.SurfaceElement(i).PNum(1) << " " << mesh.SurfaceElement(i).PNum(3) << " " << mesh.SurfaceElement(i).PNum(2) << endl; } } #ifdef OLD void Save2DMesh ( const Mesh & mesh2d, const Array * splines, ostream & outfile) { int i, j; outfile.precision (6); outfile << "areamesh2" << endl; outfile << endl; outfile << mesh2d.GetNSeg() << endl; for (i = 1; i <= mesh2d.GetNSeg(); i++) outfile << mesh2d.LineSegment(i).si << " " << mesh2d.LineSegment(i)[0] << " " << mesh2d.LineSegment(i)[1] << " " << endl; outfile << mesh2d.GetNSE() << endl; for (i = 1; i <= mesh2d.GetNSE(); i++) { outfile << mesh2d.SurfaceElement(i).GetIndex() << " "; outfile << mesh2d.SurfaceElement(i).GetNP() << " "; for (j = 1; j <= mesh2d.SurfaceElement(i).GetNP(); j++) outfile << mesh2d.SurfaceElement(i).PNum(j) << " "; outfile << endl; } outfile << mesh2d.GetNP() << endl; for (i = 1; i <= mesh2d.GetNP(); i++) outfile << mesh2d.Point(i).X() << " " << mesh2d.Point(i).Y() << endl; if (splines) { outfile << splines->Size() << endl; for (i = 1; i <= splines->Size(); i++) splines->Get(i) -> PrintCoeff (outfile); } else outfile << "0" << endl; } #endif void SaveVolumeMesh (const Mesh & mesh, const NetgenGeometry & geometry, char * filename) { INDEX i; ofstream outfile(filename); outfile << "volumemesh" << endl; outfile << mesh.GetNSE() << endl; for (i = 1; i <= mesh.GetNSE(); i++) { if (mesh.SurfaceElement(i).GetIndex()) outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).SurfNr() << "\t"; else outfile << "0" << "\t"; outfile << mesh.SurfaceElement(i)[0] << " " << mesh.SurfaceElement(i)[1] << " " << mesh.SurfaceElement(i)[2] << endl; } outfile << mesh.GetNE() << endl; for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) outfile << mesh[ei].GetIndex() << "\t" << mesh[ei][0] << " " << mesh[ei][1] << " " << mesh[ei][2] << " " << mesh[ei][3] << endl; outfile << mesh.GetNP() << endl; for (i = 1; i <= mesh.GetNP(); i++) outfile << mesh.Point(i)(0) << " " << mesh.Point(i)(1) << " " << mesh.Point(i)(2) << endl; #ifdef SOLIDGEOM outfile << geometry.GetNSurf() << endl; for (i = 1; i <= geometry.GetNSurf(); i++) geometry.GetSurface(i) -> Print (outfile); #endif } int CheckCode () { return 1; /* char st[100]; ifstream ist("pw"); if (!ist.good()) return 0; ist >> st; if (strcmp (st, "JKULinz") == 0) return 1; return 0; */ } /* ******************** CheckMesh ******************************* */ /// Checks, whether mesh contains a valid 3d mesh int CheckMesh3D (const Mesh & mesh) { INDEX_3_HASHTABLE faceused(mesh.GetNE()/3); INDEX i; int j, k, l; INDEX_3 i3; int ok = 1; ElementIndex ei; for (i = 1; i <= mesh.GetNSE(); i++) { const Element2d & el = mesh.SurfaceElement(i); if (mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() == 0 || mesh.GetFaceDescriptor(el.GetIndex()).DomainOut() == 0) { for (j = 1; j <= 3; j++) i3.I(j) = el.PNum(j); i3.Sort(); faceused.Set (i3, 1); } } for (ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; for (j = 1; j <= 4; j++) { l = 0; for (k = 1; k <= 4; k++) { if (j != k) { l++; i3.I(l) = el.PNum(k); } } i3.Sort(); if (faceused.Used(i3)) faceused.Set(i3, faceused.Get(i3)+1); else faceused.Set (i3, 1); } } for (i = 1; i <= mesh.GetNSE(); i++) { const Element2d & el = mesh.SurfaceElement(i); for (j = 1; j <= 3; j++) i3.I(j) = el.PNum(j); i3.Sort(); k = faceused.Get (i3); if (k != 2) { ok = 0; (*testout) << "face " << i << " with points " << i3.I1() << "-" << i3.I2() << "-" << i3.I3() << " has " << k << " elements" << endl; } } for (ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; for (j = 1; j <= 4; j++) { l = 0; for (k = 1; k <= 4; k++) { if (j != k) { l++; i3.I(l) = el.PNum(k); } } i3.Sort(); k = faceused.Get(i3); if (k != 2) { ok = 0; (*testout) << "element " << ei << " with face " << i3.I1() << "-" << i3.I2() << "-" << i3.I3() << " has " << k << " elements" << endl; } } } /* for (i = 1; i <= faceused.GetNBags(); i++) for (j = 1; j <= faceused.GetBagSize(i); j++) { faceused.GetData(i, j, i3, k); if (k != 2) { (*testout) << "Face: " << i3.I1() << "-" << i3.I2() << "-" << i3.I3() << " has " << k << " Faces " << endl; cerr << "Face Error" << endl; ok = 0; } } */ if (!ok) { (*testout) << "surfelements: " << endl; for (i = 1; i <= mesh.GetNSE(); i++) { const Element2d & el = mesh.SurfaceElement(i); (*testout) << setw(5) << i << ":" << setw(6) << el.GetIndex() << setw(6) << el.PNum(1) << setw(4) << el.PNum(2) << setw(4) << el.PNum(3) << endl; } (*testout) << "volelements: " << endl; for (ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; (*testout) << setw(5) << i << ":" << setw(6) << el.GetIndex() << setw(6) << el[0] << setw(4) << el[1] << setw(4) << el[2] << setw(4) << el[3] << endl; } } return ok; } void RemoveProblem (Mesh & mesh, int domainnr) { int i, j, k; mesh.FindOpenElements(domainnr); int np = mesh.GetNP(); BitArrayChar ppoints(np); // int ndom = mesh.GetNDomains(); PrintMessage (3, "Elements before Remove: ", mesh.GetNE()); // for (k = 1; k <= ndom; k++) k = domainnr; { ppoints.Clear(); for (i = 1; i <= mesh.GetNOpenElements(); i++) { const Element2d & sel = mesh.OpenElement(i); if (sel.GetIndex() == k) { for (j = 1; j <= sel.GetNP(); j++) ppoints.Set (sel.PNum(j)); } } for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) { const Element & el = mesh[ei]; if (el.GetIndex() == k) { int todel = 0; for (j = 0; j < el.GetNP(); j++) if (ppoints.Test (el[j])) todel = 1; if (el.GetNP() != 4) todel = 0; if (todel) { mesh[ei].Delete(); // ei--; } } } } mesh.Compress(); PrintMessage (3, "Elements after Remove: ", mesh.GetNE()); } } netgen-6.2.1905/libsrc/meshing/geomsearch.hpp0000644000175000017500000000362613504650527017546 0ustar kurtkurt#ifndef FILE_GEOMSEARCH #define FILE_GEOMSEARCH /**************************************************************************/ /* File: geomsearch.hh */ /* Author: Johannes Gerstmayr */ /* Date: 19. Nov. 97 */ /**************************************************************************/ class FrontPoint3; class FrontFace; class MiniElement2d; /// class for quick access of 3D-elements; class cannot delete elements, but only append class GeomSearch3d { public: /// GeomSearch3d(); /// virtual ~GeomSearch3d(); /// void Init (Array *pointsi, Array *facesi); ///get elements max extension void ElemMaxExt(Point3d& minp, Point3d& maxp, const MiniElement2d& elem); ///get minimum coordinates of two points ->p2 void MinCoords(const Point3d& p1, Point3d& p2); ///get minimum coordinates of two points ->p2 void MaxCoords(const Point3d& p1, Point3d& p2); ///create a hashtable from an existing array of triangles ///sizei = number of pieces in one direction void Create(); ///add new element to Hashtable void AddElem(const MiniElement2d& elem, INDEX elemnum); ///GetLocal faces in sphere with radius xh and middlepoint p void GetLocals(Array & locfaces, Array & findex, INDEX fstind, const Point3d& p0, double xh); private: Array *faces; // Pointers to Arrays in Adfront Array *points; Array *> hashtable; Point3d minext; //extension of Hashdomain Point3d maxext; Point3d maxextreal; Vec3d elemsize; //size of one Hash-Element threeint size; // size of Hashtable in each direction int reset; int hashcount; }; #endif netgen-6.2.1905/libsrc/meshing/smoothing3.cpp0000644000175000017500000011245013504650527017512 0ustar kurtkurt#include #include "meshing.hpp" #ifdef SOLIDGEOM #include #endif #include namespace netgen { double MinFunctionSum :: Func (const Vector & x) const { double retval = 0; for(int i=0; iFunc(x); return retval; } void MinFunctionSum :: Grad (const Vector & x, Vector & g) const { g = 0.; VectorMem<3> gi; for(int i=0; iGrad(x,gi); for(int j=0; j gi; for(int i=0; iFuncGrad(x,gi); for(int j=0; jFuncDeriv(x,dir,derivi); deriv += derivi; } return retval; } double MinFunctionSum :: GradStopping (const Vector & x) const { double minfs(0), mini; for(int i=0; iGradStopping(x); if(i==0 || mini < minfs) minfs = mini; } return minfs; } void MinFunctionSum :: AddFunction(MinFunction & fun) { functions.Append(&fun); } const MinFunction & MinFunctionSum :: Function(int i) const { return *functions[i]; } MinFunction & MinFunctionSum :: Function(int i) { return *functions[i]; } PointFunction1 :: PointFunction1 (Mesh::T_POINTS & apoints, const Array & afaces, const MeshingParameters & amp, double ah) : points(apoints), faces(afaces), mp(amp) { h = ah; } double PointFunction1 :: Func (const Vector & vp) const { double badness = 0; Point<3> pp(vp(0), vp(1), vp(2)); for (int j = 0; j < faces.Size(); j++) { const INDEX_3 & el = faces[j]; double bad = CalcTetBadness (points[PointIndex (el.I1())], points[PointIndex (el.I3())], points[PointIndex (el.I2())], pp, 0, mp); badness += bad; } return badness; } double PointFunction1 :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const { VectorMem<3> hx; const double eps = 1e-6; double dirlen = dir.L2Norm(); if (dirlen < 1e-14) { deriv = 0; return Func(x); } hx.Set(1, x); hx.Add(eps * h / dirlen, dir); double fr = Func (hx); hx.Set(1, x); hx.Add(-eps * h / dirlen, dir); double fl = Func (hx); deriv = (fr - fl) / (2 * eps * h) * dirlen; return Func(x); } double PointFunction1 :: FuncGrad (const Vector & x, Vector & g) const { VectorMem<3> hx; double eps = 1e-6; hx = x; for (int i = 0; i < 3; i++) { hx(i) = x(i) + eps * h; double fr = Func (hx); hx(i) = x(i) - eps * h; double fl = Func (hx); hx(i) = x(i); g(i) = (fr - fl) / (2 * eps * h); } return Func(x); } double PointFunction1 :: GradStopping (const Vector & x) const { double f = Func(x); return 1e-8 * f * f; } /* Cheap Functional depending of inner point inside triangular surface */ // is it used ???? class CheapPointFunction1 : public MinFunction { Mesh::T_POINTS & points; const Array & faces; DenseMatrix m; double h; public: CheapPointFunction1 (Mesh::T_POINTS & apoints, const Array & afaces, double ah); virtual double Func (const Vector & x) const; virtual double FuncGrad (const Vector & x, Vector & g) const; }; CheapPointFunction1 :: CheapPointFunction1 (Mesh::T_POINTS & apoints, const Array & afaces, double ah) : points(apoints), faces(afaces) { h = ah; int nf = faces.Size(); m.SetSize (nf, 4); for (int i = 1; i <= nf; i++) { const Point3d & p1 = points[PointIndex(faces.Get(i).I1())]; const Point3d & p2 = points[PointIndex(faces.Get(i).I2())]; const Point3d & p3 = points[PointIndex(faces.Get(i).I3())]; Vec3d v1 (p1, p2); Vec3d v2 (p1, p3); Vec3d n; Cross (v1, v2, n); n /= n.Length(); m.Elem(i, 1) = n.X(); m.Elem(i, 2) = n.Y(); m.Elem(i, 3) = n.Z(); m.Elem(i, 4) = - (n.X() * p1.X() + n.Y() * p1.Y() + n.Z() * p1.Z()); } } double CheapPointFunction1 :: Func (const Vector & vp) const { /* int j; double badness = 0; Point3d pp(vp.Get(1), vp.Get(2), vp.Get(3)); for (j = 1; j <= faces.Size(); j++) { const INDEX_3 & el = faces.Get(j); double bad = CalcTetBadness (points.Get(el.I1()), points.Get(el.I3()), points.Get(el.I2()), pp, 0); badness += bad; } */ int i; double badness = 0; VectorMem<4> hv; Vector res(m.Height()); for (i = 0;i < 3; i++) hv(i) = vp(i); hv(3) = 1; m.Mult (hv, res); for (i = 1; i <= res.Size(); i++) { if (res(i-1) < 1e-10) badness += 1e24; else badness += 1 / res(i-1); } return badness; } double CheapPointFunction1 :: FuncGrad (const Vector & x, Vector & g) const { VectorMem<3> hx; double eps = 1e-6; hx = x; for (int i = 0; i < 3; i++) { hx(i) = x(i) + eps * h; double fr = Func (hx); hx(i) = x(i) - eps * h; double fl = Func (hx); hx(i) = x(i); g(i) = (fr - fl) / (2 * eps * h); } return Func(x); } /* ************* PointFunction **************************** */ class PointFunction { public: Mesh::T_POINTS & points; const Mesh::T_VOLELEMENTS & elements; TABLE elementsonpoint; const MeshingParameters & mp; PointIndex actpind; double h; public: PointFunction (Mesh::T_POINTS & apoints, const Mesh::T_VOLELEMENTS & aelements, const MeshingParameters & amp); virtual ~PointFunction () { ; } virtual void SetPointIndex (PointIndex aactpind); void SetLocalH (double ah) { h = ah; } double GetLocalH () const { return h; } virtual double PointFunctionValue (const Point<3> & pp) const; virtual double PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const; virtual double PointFunctionValueDeriv (const Point<3> & pp, const Vec<3> & dir, double & deriv) const; int MovePointToInner (); }; PointFunction :: PointFunction (Mesh::T_POINTS & apoints, const Mesh::T_VOLELEMENTS & aelements, const MeshingParameters & amp) : points(apoints), elements(aelements), elementsonpoint(apoints.Size()), mp(amp) { for (int i = 0; i < elements.Size(); i++) if (elements[i].NP() == 4) for (int j = 0; j < elements[i].NP(); j++) elementsonpoint.Add (elements[i][j], i); } void PointFunction :: SetPointIndex (PointIndex aactpind) { actpind = aactpind; } double PointFunction :: PointFunctionValue (const Point<3> & pp) const { double badness; Point<3> hp; badness = 0; hp = points[actpind]; points[actpind] = Point<3> (pp); for (int j = 0; j < elementsonpoint[actpind].Size(); j++) { const Element & el = elements[elementsonpoint[actpind][j]]; badness += CalcTetBadness (points[el[0]], points[el[1]], points[el[2]], points[el[3]], -1, mp); } points[actpind] = Point<3> (hp); return badness; } double PointFunction :: PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const { double f = 0; Point<3> hp = points[actpind]; Vec<3> vgradi, vgrad(0,0,0); points[actpind] = Point<3> (pp); for (int j = 0; j < elementsonpoint[actpind].Size(); j++) { const Element & el = elements[elementsonpoint[actpind][j]]; for (int k = 0; k < 4; k++) if (el[k] == actpind) { f += CalcTetBadnessGrad (points[el[0]], points[el[1]], points[el[2]], points[el[3]], -1, k+1, vgradi, mp); vgrad += vgradi; } } points[actpind] = Point<3> (hp); grad = vgrad; return f; } double PointFunction :: PointFunctionValueDeriv (const Point<3> & pp, const Vec<3> & dir, double & deriv) const { Vec<3> vgradi, vgrad(0,0,0); Point<3> hp = points[actpind]; points[actpind] = pp; double f = 0; for (int j = 0; j < elementsonpoint[actpind].Size(); j++) { const Element & el = elements[elementsonpoint[actpind][j]]; for (int k = 1; k <= 4; k++) if (el.PNum(k) == actpind) { f += CalcTetBadnessGrad (points[el.PNum(1)], points[el.PNum(2)], points[el.PNum(3)], points[el.PNum(4)], -1, k, vgradi, mp); vgrad += vgradi; } } points[actpind] = Point<3> (hp); deriv = dir * vgrad; return f; } int PointFunction :: MovePointToInner () { // try point movement Array faces; for (int j = 0; j < elementsonpoint[actpind].Size(); j++) { const Element & el = elements[elementsonpoint[actpind][j]]; for (int k = 1; k <= 4; k++) if (el.PNum(k) == actpind) { Element2d face(TRIG); el.GetFace (k, face); Swap (face.PNum(2), face.PNum(3)); faces.Append (face); } } Point3d hp; int hi = FindInnerPoint (points, faces, hp); if (hi) { // cout << "inner point found" << endl; points[actpind] = Point<3> (hp); } else ; // cout << "no inner point found" << endl; /* Point3d hp2; int hi2 = FindInnerPoint (points, faces, hp2); if (hi2) { cout << "new: inner point found" << endl; } else cout << "new: no inner point found" << endl; (*testout) << "hi(orig) = " << hi << ", hi(new) = " << hi2; if (hi != hi2) (*testout) << "hi different" << endl; */ return hi; } class CheapPointFunction : public PointFunction { DenseMatrix m; public: CheapPointFunction (Mesh::T_POINTS & apoints, const Mesh::T_VOLELEMENTS & aelements, const MeshingParameters & amp); virtual void SetPointIndex (PointIndex aactpind); virtual double PointFunctionValue (const Point<3> & pp) const; virtual double PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const; }; CheapPointFunction :: CheapPointFunction (Mesh::T_POINTS & apoints, const Mesh::T_VOLELEMENTS & aelements, const MeshingParameters & amp) : PointFunction (apoints, aelements, amp) { ; } void CheapPointFunction :: SetPointIndex (PointIndex aactpind) { actpind = aactpind; int ne = elementsonpoint[actpind].Size(); int i, j; PointIndex pi1, pi2, pi3; m.SetSize (ne, 4); for (i = 0; i < ne; i++) { pi1 = 0; pi2 = 0; pi3 = 0; const Element & el = elements[elementsonpoint[actpind][i]]; for (j = 1; j <= 4; j++) if (el.PNum(j) != actpind) { pi3 = pi2; pi2 = pi1; pi1 = el.PNum(j); } const Point3d & p1 = points[pi1]; Vec3d v1 (p1, points[pi2]); Vec3d v2 (p1, points[pi3]); Vec3d n; Cross (v1, v2, n); n /= n.Length(); Vec3d v (p1, points[actpind]); double c = v * n; if (c < 0) n *= -1; // n is inner normal m.Elem(i+1, 1) = n.X(); m.Elem(i+1, 2) = n.Y(); m.Elem(i+1, 3) = n.Z(); m.Elem(i+1, 4) = - (n.X() * p1.X() + n.Y() * p1.Y() + n.Z() * p1.Z()); } } double CheapPointFunction :: PointFunctionValue (const Point<3> & pp) const { VectorMem<4> p4; Vector di; int n = m.Height(); p4(0) = pp(0); p4(1) = pp(1); p4(2) = pp(2); p4(3) = 1; di.SetSize (n); m.Mult (p4, di); double sum = 0; for (int i = 0; i < n; i++) { if (di(i) > 0) sum += 1 / di(i); else return 1e16; } return sum; } double CheapPointFunction :: PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const { VectorMem<4> p4; Vector di; int n = m.Height(); p4(0) = pp(0); p4(1) = pp(1); p4(2) = pp(2); p4(3) = 1; di.SetSize (n); m.Mult (p4, di); double sum = 0; grad = 0; for (int i = 0; i < n; i++) { if (di(i) > 0) { double idi = 1 / di(i); sum += idi; grad(0) -= idi * idi * m(i, 0); grad(1) -= idi * idi * m(i, 1); grad(2) -= idi * idi * m(i, 2); } else { return 1e16; } } return sum; } class Opti3FreeMinFunction : public MinFunction { const PointFunction & pf; Point<3> sp1; public: Opti3FreeMinFunction (const PointFunction & apf); void SetPoint (const Point<3> & asp1) { sp1 = asp1; } virtual double Func (const Vector & x) const; virtual double FuncGrad (const Vector & x, Vector & g) const; virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; virtual double GradStopping (const Vector & x) const; virtual void ApproximateHesse (const Vector & x, DenseMatrix & hesse) const; }; Opti3FreeMinFunction :: Opti3FreeMinFunction (const PointFunction & apf) : pf(apf) { ; } double Opti3FreeMinFunction :: Func (const Vector & x) const { Point<3> pp; for (int j = 0; j < 3; j++) pp(j) = sp1(j) + x(j); return pf.PointFunctionValue (pp); } double Opti3FreeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const { Vec<3> vgrad; Point<3> pp; for (int j = 0; j < 3; j++) pp(j) = sp1(j) + x(j); double val = pf.PointFunctionValueGrad (pp, vgrad); for (int j = 0; j < 3; j++) grad(j) = vgrad(j); return val; } double Opti3FreeMinFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const { Point<3> pp; for (int j = 0; j < 3; j++) pp(j) = sp1(j) + x(j); Vec<3> vdir; for (int j = 0; j < 3; j++) vdir(j) = dir(j); return pf.PointFunctionValueDeriv (pp, vdir, deriv); } double Opti3FreeMinFunction :: GradStopping (const Vector & x) const { double f = Func(x); return 1e-3 * f / pf.GetLocalH(); } void Opti3FreeMinFunction :: ApproximateHesse (const Vector & x, DenseMatrix & hesse) const { int n = x.Size(); Vector hx; hx.SetSize(n); double eps = 1e-8; double f, f11, f22; //, f12, f21 f = Func(x); for (int i = 1; i <= n; i++) { for (int j = 1; j < i; j++) { /* hx = x; hx.Elem(i) = x.Get(i) + eps; hx.Elem(j) = x.Get(j) + eps; f11 = Func(hx); hx.Elem(i) = x.Get(i) + eps; hx.Elem(j) = x.Get(j) - eps; f12 = Func(hx); hx.Elem(i) = x.Get(i) - eps; hx.Elem(j) = x.Get(j) + eps; f21 = Func(hx); hx.Elem(i) = x.Get(i) - eps; hx.Elem(j) = x.Get(j) - eps; f22 = Func(hx); */ hesse.Elem(i, j) = hesse.Elem(j, i) = 0; // (f11 + f22 - f12 - f21) / (2 * eps * eps); } hx = x; hx(i-1) = x(i-1) + eps; f11 = Func(hx); hx(i-1) = x(i-1) - eps; f22 = Func(hx); hesse.Elem(i, i) = (f11 + f22 - 2 * f) / (eps * eps) + 1e-12; } } #ifdef SOLIDGEOM class Opti3SurfaceMinFunction : public MinFunction { const PointFunction & pf; Point3d sp1; const Surface * surf; Vec3d t1, t2; public: Opti3SurfaceMinFunction (const PointFunction & apf); void SetPoint (const Surface * asurf, const Point3d & asp1); void CalcNewPoint (const Vector & x, Point3d & np) const; virtual double Func (const Vector & x) const; virtual double FuncGrad (const Vector & x, Vector & g) const; }; Opti3SurfaceMinFunction :: Opti3SurfaceMinFunction (const PointFunction & apf) : MinFunction(), pf(apf) { ; } void Opti3SurfaceMinFunction :: SetPoint (const Surface * asurf, const Point3d & asp1) { Vec3d n; sp1 = asp1; surf = asurf; Vec<3> hn; surf -> GetNormalVector (sp1, hn); n = hn; n.GetNormal (t1); t1 /= t1.Length(); t2 = Cross (n, t1); } void Opti3SurfaceMinFunction :: CalcNewPoint (const Vector & x, Point3d & np) const { np.X() = sp1.X() + x.Get(1) * t1.X() + x.Get(2) * t2.X(); np.Y() = sp1.Y() + x.Get(1) * t1.Y() + x.Get(2) * t2.Y(); np.Z() = sp1.Z() + x.Get(1) * t1.Z() + x.Get(2) * t2.Z(); Point<3> hnp = np; surf -> Project (hnp); np = hnp; } double Opti3SurfaceMinFunction :: Func (const Vector & x) const { Point3d pp1; CalcNewPoint (x, pp1); return pf.PointFunctionValue (pp1); } double Opti3SurfaceMinFunction :: FuncGrad (const Vector & x, Vector & grad) const { Vec3d n, vgrad; Point3d pp1; VectorMem<3> freegrad; CalcNewPoint (x, pp1); double badness = pf.PointFunctionValueGrad (pp1, freegrad); vgrad.X() = freegrad.Get(1); vgrad.Y() = freegrad.Get(2); vgrad.Z() = freegrad.Get(3); Vec<3> hn; surf -> GetNormalVector (pp1, hn); n = hn; vgrad -= (vgrad * n) * n; grad.Elem(1) = vgrad * t1; grad.Elem(2) = vgrad * t2; return badness; } #endif #ifdef SOLIDGEOM class Opti3EdgeMinFunction : public MinFunction { const PointFunction & pf; Point3d sp1; const Surface *surf1, *surf2; Vec3d t1; public: Opti3EdgeMinFunction (const PointFunction & apf); void SetPoint (const Surface * asurf1, const Surface * asurf2, const Point3d & asp1); void CalcNewPoint (const Vector & x, Point3d & np) const; virtual double FuncGrad (const Vector & x, Vector & g) const; virtual double Func (const Vector & x) const; }; Opti3EdgeMinFunction :: Opti3EdgeMinFunction (const PointFunction & apf) : MinFunction(), pf(apf) { ; } void Opti3EdgeMinFunction :: SetPoint (const Surface * asurf1, const Surface * asurf2, const Point3d & asp1) { Vec3d n1, n2; sp1 = asp1; surf1 = asurf1; surf2 = asurf2; Vec<3> hn1, hn2; surf1 -> GetNormalVector (sp1, hn1); surf2 -> GetNormalVector (sp1, hn2); n1 = hn1; n2 = hn2; t1 = Cross (n1, n2); } void Opti3EdgeMinFunction :: CalcNewPoint (const Vector & x, Point3d & np) const { np.X() = sp1.X() + x.Get(1) * t1.X(); np.Y() = sp1.Y() + x.Get(1) * t1.Y(); np.Z() = sp1.Z() + x.Get(1) * t1.Z(); Point<3> hnp = np; ProjectToEdge (surf1, surf2, hnp); np = hnp; } double Opti3EdgeMinFunction :: Func (const Vector & x) const { Vector g(x.Size()); return FuncGrad (x, g); } double Opti3EdgeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const { Vec3d n1, n2, v1, vgrad; Point3d pp1; double badness; VectorMem<3> freegrad; CalcNewPoint (x, pp1); badness = pf.PointFunctionValueGrad (pp1, freegrad); vgrad.X() = freegrad.Get(1); vgrad.Y() = freegrad.Get(2); vgrad.Z() = freegrad.Get(3); Vec<3> hn1, hn2; surf1 -> GetNormalVector (pp1, hn1); surf2 -> GetNormalVector (pp1, hn2); n1 = hn1; n2 = hn2; v1 = Cross (n1, n2); v1 /= v1.Length(); grad.Elem(1) = (vgrad * v1) * (t1 * v1); return badness; } #endif double CalcTotalBad (const Mesh::T_POINTS & points, const Mesh::T_VOLELEMENTS & elements, const MeshingParameters & mp) { static Timer t("CalcTotalBad"); RegionTimer reg(t); double sum = 0; double elbad; tets_in_qualclass.SetSize(20); tets_in_qualclass = 0; double teterrpow = mp.opterrpow; for (int i = 1; i <= elements.Size(); i++) { elbad = pow (max2(CalcBad (points, elements.Get(i), 0, mp),1e-10), 1/teterrpow); int qualclass = int (20 / elbad + 1); if (qualclass < 1) qualclass = 1; if (qualclass > 20) qualclass = 20; tets_in_qualclass.Elem(qualclass)++; sum += elbad; } return sum; } int WrongOrientation (const Mesh::T_POINTS & points, const Element & el) { const Point3d & p1 = points[el.PNum(1)]; const Point3d & p2 = points[el.PNum(2)]; const Point3d & p3 = points[el.PNum(3)]; const Point3d & p4 = points[el.PNum(4)]; Vec3d v1(p1, p2); Vec3d v2(p1, p3); Vec3d v3(p1, p4); Vec3d n; Cross (v1, v2, n); double vol = n * v3; return (vol > 0); } /* ************* JacobianPointFunction **************************** */ // class JacobianPointFunction : public MinFunction // { // public: // Mesh::T_POINTS & points; // const Mesh::T_VOLELEMENTS & elements; // TABLE elementsonpoint; // PointIndex actpind; // public: // JacobianPointFunction (Mesh::T_POINTS & apoints, // const Mesh::T_VOLELEMENTS & aelements); // virtual void SetPointIndex (PointIndex aactpind); // virtual double Func (const Vector & x) const; // virtual double FuncGrad (const Vector & x, Vector & g) const; // virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; // }; JacobianPointFunction :: JacobianPointFunction (Mesh::T_POINTS & apoints, const Mesh::T_VOLELEMENTS & aelements) : points(apoints), elements(aelements), elementsonpoint(apoints.Size()) { INDEX i; int j; for (i = 1; i <= elements.Size(); i++) { for (j = 1; j <= elements.Get(i).NP(); j++) elementsonpoint.Add1 (elements.Get(i).PNum(j), i); } onplane = false; } void JacobianPointFunction :: SetPointIndex (PointIndex aactpind) { actpind = aactpind; } double JacobianPointFunction :: Func (const Vector & v) const { int j; double badness = 0; Point<3> hp = points.Elem(actpind); points.Elem(actpind) = hp + Vec<3> (v(0), v(1), v(2)); if(onplane) points.Elem(actpind) -= (v(0)*nv(0)+v(1)*nv(1)+v(2)*nv(2)) * nv; for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) { int eli = elementsonpoint.Get(actpind, j); badness += elements.Get(eli).CalcJacobianBadness (points); } points.Elem(actpind) = hp; return badness; } double JacobianPointFunction :: FuncGrad (const Vector & x, Vector & g) const { int j, k; int lpi; double badness = 0;//, hbad; Point<3> hp = points.Elem(actpind); points.Elem(actpind) = hp + Vec<3> (x(0), x(1), x(2)); if(onplane) points.Elem(actpind) -= (x(0)*nv(0)+x(1)*nv(1)+x(2)*nv(2)) * nv; Vec<3> hderiv; //Vec3d vdir; g.SetSize(3); g = 0; for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) { int eli = elementsonpoint.Get(actpind, j); const Element & el = elements.Get(eli); lpi = 0; for (k = 1; k <= el.GetNP(); k++) if (el.PNum(k) == actpind) lpi = k; if (!lpi) cerr << "loc point not found" << endl; badness += elements.Get(eli). CalcJacobianBadnessGradient (points, lpi, hderiv); for(k=0; k<3; k++) g(k) += hderiv(k); /* for (k = 1; k <= 3; k++) { vdir = Vec3d(0,0,0); vdir.X(k) = 1; hbad = elements.Get(eli). CalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv); //(*testout) << "hderiv " << k << ": " << hderiv << endl; g.Elem(k) += hderiv; if (k == 1) badness += hbad; } */ } if(onplane) { double scal = nv(0)*g(0) + nv(1)*g(1) + nv(2)*g(2); g(0) -= scal*nv(0); g(1) -= scal*nv(1); g(2) -= scal*nv(2); } //(*testout) << "g = " << g << endl; points.Elem(actpind) = hp; return badness; } double JacobianPointFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const { int j, k; int lpi; double badness = 0; Point<3> hp = points.Elem(actpind); points.Elem(actpind) = Point<3> (hp + Vec3d (x(0), x(1), x(2))); if(onplane) points.Elem(actpind) -= (Vec3d (x(0), x(1), x(2))*nv) * nv; double hderiv; deriv = 0; Vec<3> vdir(dir(0), dir(1), dir(2)); if(onplane) { double scal = vdir * nv; vdir -= scal*nv; } for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) { int eli = elementsonpoint.Get(actpind, j); const Element & el = elements.Get(eli); lpi = 0; for (k = 1; k <= el.GetNP(); k++) if (el.PNum(k) == actpind) lpi = k; if (!lpi) cerr << "loc point not found" << endl; badness += elements.Get(eli). CalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv); deriv += hderiv; } points.Elem(actpind) = hp; return badness; } #ifdef SOLIDGEOMxxxx void Mesh :: ImproveMesh (const CSG eometry & geometry, OPTIMIZEGOAL goal) { INDEX i, eli; int j; int typ = 1; if (!&geometry || geometry.GetNSurf() == 0) { ImproveMesh (goal); return; } const char * savetask = multithread.task; multithread.task = "Smooth Mesh"; TABLE surfelementsonpoint(points.Size()); Vector x(3), xsurf(2), xedge(1); int surf, surf1, surf2, surf3; int uselocalh = mparam.uselocalh; (*testout) << setprecision(8); (*testout) << "Improve Mesh" << "\n"; PrintMessage (3, "ImproveMesh"); // (*mycout) << "Vol = " << CalcVolume (points, volelements) << endl; for (i = 1; i <= surfelements.Size(); i++) for (j = 1; j <= 3; j++) surfelementsonpoint.Add1 (surfelements.Get(i).PNum(j), i); PointFunction * pf; if (typ == 1) pf = new PointFunction(points, volelements); else pf = new CheapPointFunction(points, volelements); // pf->SetLocalH (h); Opti3FreeMinFunction freeminf(*pf); Opti3SurfaceMinFunction surfminf(*pf); Opti3EdgeMinFunction edgeminf(*pf); OptiParameters par; par.maxit_linsearch = 20; par.maxit_bfgs = 20; int printmod = 1; char printdot = '.'; if (points.Size() > 1000) { printmod = 10; printdot = '+'; } if (points.Size() > 10000) { printmod = 100; printdot = '*'; } for (i = 1; i <= points.Size(); i++) { // if (ptyps.Get(i) == FIXEDPOINT) continue; if (ptyps.Get(i) != INNERPOINT) continue; if (multithread.terminate) throw NgException ("Meshing stopped"); /* if (multithread.terminate) break; */ multithread.percent = 100.0 * i /points.Size(); /* if (points.Size() < 1000) PrintDot (); else if (i % 10 == 0) PrintDot ('+'); */ if (i % printmod == 0) PrintDot (printdot); // (*testout) << "Now point " << i << "\n"; // (*testout) << "Old: " << points.Get(i) << "\n"; pf->SetPointIndex (i); // if (uselocalh) { double lh = GetH (points.Get(i)); pf->SetLocalH (GetH (points.Get(i))); par.typx = lh / 10; // (*testout) << "lh(" << points.Get(i) << ") = " << lh << "\n"; } surf1 = surf2 = surf3 = 0; for (j = 1; j <= surfelementsonpoint.EntrySize(i); j++) { eli = surfelementsonpoint.Get(i, j); int surfi = surfelements.Get(eli).GetIndex(); if (surfi) { surf = GetFaceDescriptor(surfi).SurfNr(); if (!surf1) surf1 = surf; else if (surf1 != surf) { if (!surf2) surf2 = surf; else if (surf2 != surf) surf3 = surf; } } else { surf1 = surf2 = surf3 = 1; // simulates corner point } } if (surf2 && !surf3) { // (*testout) << "On Edge" << "\n"; /* xedge = 0; edgeminf.SetPoint (geometry.GetSurface(surf1), geometry.GetSurface(surf2), points.Elem(i)); BFGS (xedge, edgeminf, par); edgeminf.CalcNewPoint (xedge, points.Elem(i)); */ } if (surf1 && !surf2) { // (*testout) << "In Surface" << "\n"; /* xsurf = 0; surfminf.SetPoint (geometry.GetSurface(surf1), points.Get(i)); BFGS (xsurf, surfminf, par); surfminf.CalcNewPoint (xsurf, points.Elem(i)); */ } if (!surf1) { // (*testout) << "In Volume" << "\n"; x = 0; freeminf.SetPoint (points.Elem(i)); // par.typx = BFGS (x, freeminf, par); points.Elem(i).X() += x.Get(1); points.Elem(i).Y() += x.Get(2); points.Elem(i).Z() += x.Get(3); } // (*testout) << "New Point: " << points.Elem(i) << "\n" << "\n"; } PrintDot ('\n'); // (*mycout) << "Vol = " << CalcVolume (points, volelements) << endl; multithread.task = savetask; } #endif void Mesh :: ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal) { static Timer t("Mesh::ImproveMesh"); RegionTimer reg(t); int typ = 1; (*testout) << "Improve Mesh" << "\n"; PrintMessage (3, "ImproveMesh"); int np = GetNP(); int ne = GetNE(); Array perrs(np); perrs = 1.0; double bad1 = 0; double badmax = 0; if (goal == OPT_QUALITY) { for (int i = 1; i <= ne; i++) { const Element & el = VolumeElement(i); if (el.GetType() != TET) continue; double hbad = CalcBad (points, el, 0, mp); for (int j = 0; j < 4; j++) perrs[el[j]] += hbad; bad1 += hbad; } for (int i = perrs.Begin(); i < perrs.End(); i++) if (perrs[i] > badmax) badmax = perrs[i]; badmax = 0; } if (goal == OPT_QUALITY) { bad1 = CalcTotalBad (points, volelements, mp); (*testout) << "Total badness = " << bad1 << endl; PrintMessage (5, "Total badness = ", bad1); } Vector x(3); (*testout) << setprecision(8); //int uselocalh = mparam.uselocalh; PointFunction * pf; if (typ == 1) pf = new PointFunction(points, volelements, mp); else pf = new CheapPointFunction(points, volelements, mp); // pf->SetLocalH (h); Opti3FreeMinFunction freeminf(*pf); OptiParameters par; par.maxit_linsearch = 20; par.maxit_bfgs = 20; Array pointh (points.Size()); if(lochfunc) { for (PointIndex pi : points.Range()) pointh[pi] = GetH(points[pi]); } else { pointh = 0; for (Element & el : VolumeElements()) { double h = pow(el.Volume(points),1./3.); for (PointIndex pi : el.PNums()) if (h > pointh[pi]) pointh[pi] = h; } } int printmod = 1; char printdot = '.'; if (points.Size() > 1000) { printmod = 10; printdot = '+'; } if (points.Size() > 10000) { printmod = 100; printdot = '*'; } const char * savetask = multithread.task; multithread.task = "Smooth Mesh"; for (PointIndex pi : points.Range()) if ( (*this)[pi].Type() == INNERPOINT && perrs[pi] > 0.01 * badmax) { if (multithread.terminate) throw NgException ("Meshing stopped"); multithread.percent = 100.0 * (pi+1-PointIndex::BASE) / points.Size(); if ( (pi+1-PointIndex::BASE) % printmod == 0) PrintDot (printdot); double lh = pointh[pi]; pf->SetLocalH (lh); par.typx = lh; freeminf.SetPoint (points[pi]); pf->SetPointIndex (pi); x = 0; int pok; pok = freeminf.Func (x) < 1e10; if (!pok) { pok = pf->MovePointToInner (); freeminf.SetPoint (points[pi]); pf->SetPointIndex (pi); } if (pok) { //*testout << "start BFGS, pok" << endl; BFGS (x, freeminf, par); //*testout << "BFGS complete, pok" << endl; points[pi](0) += x(0); points[pi](1) += x(1); points[pi](2) += x(2); } } PrintDot ('\n'); delete pf; multithread.task = savetask; if (goal == OPT_QUALITY) { bad1 = CalcTotalBad (points, volelements, mp); (*testout) << "Total badness = " << bad1 << endl; PrintMessage (5, "Total badness = ", bad1); } } // Improve Condition number of Jacobian, any elements void Mesh :: ImproveMeshJacobian (const MeshingParameters & mp, OPTIMIZEGOAL goal, const BitArray * usepoint) { int i, j; (*testout) << "Improve Mesh Jacobian" << "\n"; PrintMessage (3, "ImproveMesh Jacobian"); int np = GetNP(); int ne = GetNE(); Vector x(3); (*testout) << setprecision(8); JacobianPointFunction pf(points, volelements); OptiParameters par; par.maxit_linsearch = 20; par.maxit_bfgs = 20; BitArray badnodes(np); badnodes.Clear(); for (i = 1; i <= ne; i++) { const Element & el = VolumeElement(i); double bad = el.CalcJacobianBadness (Points()); if (bad > 1) for (j = 1; j <= el.GetNP(); j++) badnodes.Set (el.PNum(j)); } Array pointh (points.Size()); if(lochfunc) { for(i = 1; i<=points.Size(); i++) pointh[i] = GetH(points.Get(i)); } else { pointh = 0; for(i=0; i pointh[el.PNum(j)]) pointh[el.PNum(j)] = h; } } const char * savetask = multithread.task; multithread.task = "Smooth Mesh Jacobian"; for (PointIndex pi = points.Begin(); i < points.End(); pi++) { if ((*this)[pi].Type() != INNERPOINT) continue; if(usepoint && !usepoint->Test(i)) continue; //(*testout) << "improvejac, p = " << i << endl; if (goal == OPT_WORSTCASE && !badnodes.Test(i)) continue; // (*testout) << "smooth p " << i << endl; /* if (multithread.terminate) break; */ if (multithread.terminate) throw NgException ("Meshing stopped"); multithread.percent = 100.0 * i / points.Size(); if (points.Size() < 1000) PrintDot (); else if (i % 10 == 0) PrintDot ('+'); double lh = pointh[i]; par.typx = lh; pf.SetPointIndex (pi); x = 0; int pok = (pf.Func (x) < 1e10); if (pok) { //*testout << "start BFGS, Jacobian" << endl; BFGS (x, pf, par); //*testout << "end BFGS, Jacobian" << endl; points.Elem(i)(0) += x(0); points.Elem(i)(1) += x(1); points.Elem(i)(2) += x(2); } else { cout << "el not ok" << endl; } } PrintDot ('\n'); multithread.task = savetask; } // Improve Condition number of Jacobian, any elements void Mesh :: ImproveMeshJacobianOnSurface (const MeshingParameters & mp, const BitArray & usepoint, const Array< Vec<3>* > & nv, OPTIMIZEGOAL goal, const Array< Array* > * idmaps) { int i, j; (*testout) << "Improve Mesh Jacobian" << "\n"; PrintMessage (3, "ImproveMesh Jacobian"); int np = GetNP(); int ne = GetNE(); Vector x(3); (*testout).precision(8); JacobianPointFunction pf(points, volelements); Array< Array* > locidmaps; const Array< Array* > * used_idmaps; if(idmaps) used_idmaps = idmaps; else { used_idmaps = &locidmaps; for(i=1; i<=GetIdentifications().GetMaxNr(); i++) { if(GetIdentifications().GetType(i) == Identifications::PERIODIC) { locidmaps.Append(new Array); GetIdentifications().GetMap(i,*locidmaps.Last(),true); } } } bool usesum = (used_idmaps->Size() > 0); MinFunctionSum pf_sum; JacobianPointFunction * pf2ptr = NULL; if(usesum) { pf2ptr = new JacobianPointFunction(points, volelements); pf_sum.AddFunction(pf); pf_sum.AddFunction(*pf2ptr); } OptiParameters par; par.maxit_linsearch = 20; par.maxit_bfgs = 20; BitArray badnodes(np); badnodes.Clear(); for (i = 1; i <= ne; i++) { const Element & el = VolumeElement(i); double bad = el.CalcJacobianBadness (Points()); if (bad > 1) for (j = 1; j <= el.GetNP(); j++) badnodes.Set (el.PNum(j)); } Array pointh (points.Size()); if(lochfunc) { for(i=1; i<=points.Size(); i++) pointh[i] = GetH(points.Get(i)); } else { pointh = 0; for(i=0; i pointh[el.PNum(j)]) pointh[el.PNum(j)] = h; } } const char * savetask = multithread.task; multithread.task = "Smooth Mesh Jacobian"; for (PointIndex pi = points.Begin(); pi <= points.End(); pi++) if ( usepoint.Test(i) ) { //(*testout) << "improvejac, p = " << i << endl; if (goal == OPT_WORSTCASE && !badnodes.Test(i)) continue; // (*testout) << "smooth p " << i << endl; /* if (multithread.terminate) break; */ if (multithread.terminate) throw NgException ("Meshing stopped"); multithread.percent = 100.0 * i / points.Size(); if (points.Size() < 1000) PrintDot (); else if (i % 10 == 0) PrintDot ('+'); double lh = pointh[i];//GetH(points.Get(i)); par.typx = lh; pf.SetPointIndex (pi); PointIndex brother (-1); if(usesum) { for(j=0; brother == -1 && jSize(); j++) { if(i < (*used_idmaps)[j]->Size() + PointIndex::BASE) { brother = (*(*used_idmaps)[j])[i]; if(brother == i || brother == 0) brother = -1; } } if(brother >= i) { pf2ptr->SetPointIndex(brother); pf2ptr->SetNV(*nv[brother-1]); } } if(usesum && brother < i) continue; //pf.UnSetNV(); x = 0; //(*testout) << "before " << pf.Func(x); pf.SetNV(*nv[i-1]); x = 0; int pok = (brother == -1) ? (pf.Func (x) < 1e10) : (pf_sum.Func (x) < 1e10); if (pok) { if(brother == -1) BFGS (x, pf, par); else BFGS (x, pf_sum, par); for(j=0; j<3; j++) points.Elem(i)(j) += x(j);// - scal*nv[i-1].X(j); if(brother != -1) for(j=0; j<3; j++) points.Elem(brother)(j) += x(j);// - scal*nv[brother-1].X(j); } else { cout << "el not ok" << endl; (*testout) << "el not ok" << endl << " func " << ((brother == -1) ? pf.Func(x) : pf_sum.Func (x)) << endl; if(brother != -1) (*testout) << " func1 " << pf.Func(x) << endl << " func2 " << pf2ptr->Func(x) << endl; } } PrintDot ('\n'); delete pf2ptr; for(i=0; i #include "meshing.hpp" namespace netgen { template void QuickSortRec (FlatArray data, int left, int right) { int i = left; int j = right; T midval = data[(left+right)/2]; do { while (data[i] < midval) i++; while (midval < data[j]) j--; if (i <= j) { Swap (data[i], data[j]); i++; j--; } } while (i <= j); if (left < j) QuickSortRec (data, left, j); if (i < right) QuickSortRec (data, i, right); } template void QuickSort (FlatArray data) { if (data.Size() > 1) QuickSortRec (data, 0, data.Size()-1); } MeshTopology :: MeshTopology (const Mesh & amesh) : mesh(&amesh) { buildedges = true; buildfaces = true; timestamp = -1; } MeshTopology :: ~MeshTopology () { ; } bool MeshTopology :: NeedsUpdate() const { return (timestamp <= mesh->GetTimeStamp()); } template void LoopOverEdges (const Mesh & mesh, MeshTopology & top, PointIndex v, FUNC func) { for (ElementIndex elnr : top.GetVertexElements(v)) { const Element & el = mesh[elnr]; int neledges = MeshTopology::GetNEdges (el.GetType()); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType()); for (int k = 0; k < neledges; k++) { INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); // edge.Sort(); int edgedir = (edge.I1() > edge.I2()); if (edgedir) swap (edge.I1(), edge.I2()); if (edge.I1() != v) continue; func (edge, elnr, k, 3, edgedir); } } for (SurfaceElementIndex elnr : top.GetVertexSurfaceElements(v)) { const Element2d & el = mesh[elnr]; int neledges = MeshTopology::GetNEdges (el.GetType()); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType()); for (int k = 0; k < neledges; k++) { INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); // edge.Sort(); int edgedir = (edge.I1() > edge.I2()); if (edgedir) swap (edge.I1(), edge.I2()); if (edge.I1() != v) continue; func (edge, elnr, k, 2, edgedir); } } for (SegmentIndex elnr : top.GetVertexSegments(v)) { const Segment & el = mesh[elnr]; INDEX_2 edge(el[0], el[1]); int edgedir = (edge.I1() > edge.I2()); if (edgedir) swap (edge.I1(), edge.I2()); edge.Sort(); if (edge.I1() != v) continue; func (edge, elnr, 0, 1, edgedir); } } template void LoopOverFaces (const Mesh & mesh, MeshTopology & top, PointIndex v, FUNC func) { for (ElementIndex elnr : top.GetVertexElements(v)) { const Element & el = mesh[elnr]; int nelfaces = MeshTopology::GetNFaces (el.GetType()); const ELEMENT_FACE * elfaces = MeshTopology::GetFaces0 (el.GetType()); for (int j = 0; j < nelfaces; j++) if (elfaces[j][3] < 0) { // triangle INDEX_4 face(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]], 0); int facedir = 0; if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 1; } if (face.I2() > face.I3()) { swap (face.I2(), face.I3()); facedir += 2; } if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 4; } if (face.I1() != v) continue; func (face, elnr, j, true, facedir); } /* if (pass == 1) { if (!vert2face.Used (face)) { nfa++; vert2face.Set (face, nfa); INDEX_4 hface(face.I1(),face.I2(),face.I3(),0); face2vert.Append (hface); } } else { int facenum = vert2face.Get(face); faces[elnr][j].fnr = facenum-1; faces[elnr][j].forient = facedir; } */ else { // quad // int facenum; INDEX_4 face4(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]], el[elfaces[j][3]]); int facedir = 0; if (min2 (face4.I1(), face4.I2()) > min2 (face4.I4(), face4.I3())) { // z - flip facedir += 1; swap (face4.I1(), face4.I4()); swap (face4.I2(), face4.I3()); } if (min2 (face4.I1(), face4.I4()) > min2 (face4.I2(), face4.I3())) { // x - flip facedir += 2; swap (face4.I1(), face4.I2()); swap (face4.I3(), face4.I4()); } if (face4.I2() > face4.I4()) { // diagonal flip facedir += 4; swap (face4.I2(), face4.I4()); } if (face4.I1() != v) continue; func(face4, elnr, j, true, facedir); /* INDEX_3 face(face4.I1(), face4.I2(), face4.I3()); if (vert2face.Used (face)) { facenum = vert2face.Get(face); } else { if (pass == 2) cout << "hier in pass 2" << endl; nfa++; vert2face.Set (face, nfa); facenum = nfa; INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4()); face2vert.Append (hface); } faces[elnr][j].fnr = facenum-1; faces[elnr][j].forient = facedir; } */ } } for (SurfaceElementIndex elnr : top.GetVertexSurfaceElements(v)) { const Element2d & el = mesh.SurfaceElement (elnr); const ELEMENT_FACE * elfaces = MeshTopology::GetFaces1 (el.GetType()); if (elfaces[0][3] == 0) { // triangle // int facenum; int facedir; INDEX_4 face(el.PNum(elfaces[0][0]), el.PNum(elfaces[0][1]), el.PNum(elfaces[0][2]),0); facedir = 0; if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 1; } if (face.I2() > face.I3()) { swap (face.I2(), face.I3()); facedir += 2; } if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 4; } if (face.I1() != v) continue; func(face, elnr, 0, false, facedir); /* if (vert2face.Used (face)) facenum = vert2face.Get(face); else { nfa++; vert2face.Set (face, nfa); facenum = nfa; INDEX_4 hface(face.I1(),face.I2(),face.I3(),0); face2vert.Append (hface); } surffaces[elnr].fnr = facenum-1; surffaces[elnr].forient = facedir; */ } else { // quad // int facenum; int facedir; INDEX_4 face4(el.PNum(elfaces[0][0]), el.PNum(elfaces[0][1]), el.PNum(elfaces[0][2]), el.PNum(elfaces[0][3])); facedir = 0; if (min2 (face4.I1(), face4.I2()) > min2 (face4.I4(), face4.I3())) { // z - orientation facedir += 1; swap (face4.I1(), face4.I4()); swap (face4.I2(), face4.I3()); } if (min2 (face4.I1(), face4.I4()) > min2 (face4.I2(), face4.I3())) { // x - orientation facedir += 2; swap (face4.I1(), face4.I2()); swap (face4.I3(), face4.I4()); } if (face4.I2() > face4.I4()) { facedir += 4; swap (face4.I2(), face4.I4()); } if (face4.I1() != v) continue; func(face4, elnr, 0, false, facedir); /* INDEX_3 face(face4.I1(), face4.I2(), face4.I3()); if (vert2face.Used (face)) facenum = vert2face.Get(face); else { nfa++; vert2face.Set (face, nfa); facenum = nfa; INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4()); face2vert.Append (hface); } surffaces[elnr].fnr = facenum-1; surffaces[elnr].forient = facedir; } */ } } } void MeshTopology :: Update (TaskManager tm, Tracer tracer) { static int timer = NgProfiler::CreateTimer ("topology"); NgProfiler::RegionTimer reg (timer); #ifdef PARALLEL // ParallelMeshTopology & paralleltop = mesh.GetParallelTopology(); #endif auto id = this->mesh->GetCommunicator().Rank(); auto ntasks = this->mesh->GetCommunicator().Size(); if (timestamp > mesh->GetTimeStamp()) return; int ne = mesh->GetNE(); int nse = mesh->GetNSE(); int nseg = mesh->GetNSeg(); int np = mesh->GetNP(); int nv = mesh->GetNV(); if (id == 0) PrintMessage (3, "Update mesh topology"); (*testout) << " UPDATE MESH TOPOLOGY " << endl; (*testout) << "ne = " << ne << endl; (*testout) << "nse = " << nse << endl; (*testout) << "nseg = " << nseg << endl; (*testout) << "np = " << np << endl; (*testout) << "nv = " << nv << endl; (*tracer) ("Topology::Update setup tables", false); Array cnt(nv); Array vnums; /* generate: vertex to element vertex to surface element vertex to segment */ cnt = 0; /* for (ElementIndex ei = 0; ei < ne; ei++) { const Element & el = (*mesh)[ei]; for (int j = 0; j < el.GetNV(); j++) cnt[el[j]]++; } */ ParallelForRange (tm, ne, [&] (size_t begin, size_t end) { for (ElementIndex ei = begin; ei < end; ei++) { const Element & el = (*mesh)[ei]; for (int j = 0; j < el.GetNV(); j++) AsAtomic(cnt[el[j]])++; } }); vert2element = TABLE (cnt); /* for (ElementIndex ei = 0; ei < ne; ei++) { const Element & el = (*mesh)[ei]; for (int j = 0; j < el.GetNV(); j++) vert2element.AddSave (el[j], ei); } */ ParallelForRange (tm, ne, [&] (size_t begin, size_t end) { for (ElementIndex ei = begin; ei < end; ei++) { const Element & el = (*mesh)[ei]; for (int j = 0; j < el.GetNV(); j++) vert2element.ParallelAdd (el[j], ei); } }); cnt = 0; /* for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; for (int j = 0; j < el.GetNV(); j++) cnt[el[j]]++; } */ ParallelForRange (tm, nse, [&] (size_t begin, size_t end) { for (SurfaceElementIndex ei = begin; ei < end; ei++) { const Element2d & el = (*mesh)[ei]; for (int j = 0; j < el.GetNV(); j++) AsAtomic(cnt[el[j]])++; } }); vert2surfelement = TABLE (cnt); /* for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; for (int j = 0; j < el.GetNV(); j++) vert2surfelement.AddSave (el[j], sei); } */ ParallelForRange (tm, nse, [&] (size_t begin, size_t end) { for (SurfaceElementIndex sei = begin; sei < end; sei++) { const Element2d & el = (*mesh)[sei]; for (int j = 0; j < el.GetNV(); j++) vert2surfelement.ParallelAdd (el[j], sei); } }); cnt = 0; for (SegmentIndex si = 0; si < nseg; si++) { const Segment & seg = mesh->LineSegment(si); cnt[seg[0]]++; cnt[seg[1]]++; } vert2segment = TABLE (cnt); for (SegmentIndex si = 0; si < nseg; si++) { const Segment & seg = mesh->LineSegment(si); vert2segment.AddSave (seg[0], si); vert2segment.AddSave (seg[1], si); } cnt = 0; for (int pei = 0; pei < mesh->pointelements.Size(); pei++) { const Element0d & pointel = mesh->pointelements[pei]; cnt[pointel.pnum]++; } vert2pointelement = TABLE (cnt); for (int pei = 0; pei < mesh->pointelements.Size(); pei++) { const Element0d & pointel = mesh->pointelements[pei]; vert2pointelement.AddSave (pointel.pnum, pei); } (*tracer) ("Topology::Update setup tables", true); if (buildedges) { static int timer1 = NgProfiler::CreateTimer ("topology::buildedges"); NgProfiler::RegionTimer reg1 (timer1); if (id == 0) PrintMessage (5, "Update edges "); edges.SetSize(ne); surfedges.SetSize(nse); segedges.SetSize(nseg); for (int i = 0; i < ne; i++) for (int j = 0; j < 12; j++) edges[i][j].nr = -1; for (int i = 0; i < nse; i++) for (int j = 0; j < 4; j++) surfedges[i][j].nr = -1; // keep existing edges cnt = 0; for (int i = 0; i < edge2vert.Size(); i++) cnt[edge2vert[i][0]]++; TABLE vert2edge (cnt); for (int i = 0; i < edge2vert.Size(); i++) vert2edge.AddSave (edge2vert[i][0], i); // ensure all coarse grid and intermediate level edges cnt = 0; for (int i = mesh->mlbetweennodes.Begin(); i < mesh->mlbetweennodes.End(); i++) { INDEX_2 parents = Sort (mesh->mlbetweennodes[i]); if (parents[0] >= PointIndex::BASE) cnt[parents[0]]++; } TABLE vert2vertcoarse (cnt); for (int i = mesh->mlbetweennodes.Begin(); i < mesh->mlbetweennodes.End(); i++) { INDEX_2 parents = Sort (mesh->mlbetweennodes[i]); if (parents[0] >= PointIndex::BASE) vert2vertcoarse.AddSave (parents[0], parents[1]); } int max_edge_on_vertex = 0; for (int i = PointIndex::BASE; i < nv+PointIndex::BASE; i++) { int onv = vert2edge[i].Size() + vert2vertcoarse[i].Size() + 4*(vert2element)[i].Size() + 2*(vert2surfelement)[i].Size() + (vert2segment)[i].Size(); max_edge_on_vertex = max (onv, max_edge_on_vertex); } // count edges associated with vertices cnt = 0; ParallelForRange (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_CLOSED_HASHTABLE v2eht(2*max_edge_on_vertex+10); for (PointIndex v = begin+PointIndex::BASE; v < end+PointIndex::BASE; v++) { v2eht.DeleteData(); for (int ednr : vert2edge[v]) { int v2 = edge2vert[ednr][1]; v2eht.Set (v2, ednr); } int cnti = 0; for (int v2 : vert2vertcoarse[v]) if (!v2eht.Used(v2)) { cnti++; v2eht.Set (v2, 33); // some value } LoopOverEdges (*mesh, *this, v, [&] (INDEX_2 edge, int elnr, int loc_edge, int element_dim, int edgedir) { if (!v2eht.Used (edge.I2())) { cnti++; v2eht.Set (edge.I2(), 33); // something } }); cnt[v] = cnti; } } ); // accumulate number of edges int ned = edge2vert.Size(); // for (size_t v = 0; v < mesh->GetNV(); v++) for (size_t v : cnt.Range()) { auto hv = cnt[v]; cnt[v] = ned; ned += hv; } edge2vert.SetSize(ned); // INDEX_CLOSED_HASHTABLE v2eht(2*max_edge_on_vertex+10); // Array vertex2; // for (PointIndex v = PointIndex::BASE; v < nv+PointIndex::BASE; v++) ParallelForRange (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_CLOSED_HASHTABLE v2eht(2*max_edge_on_vertex+10); Array vertex2; for (PointIndex v = begin+PointIndex::BASE; v < end+PointIndex::BASE; v++) { int ned = cnt[v]; v2eht.DeleteData(); vertex2.SetSize (0); for (int ednr : vert2edge[v]) { int v2 = edge2vert[ednr][1]; v2eht.Set (v2, ednr); } for (int v2 : vert2vertcoarse[v]) if (!v2eht.Used(v2)) { v2eht.Set (v2, 33); // some value vertex2.Append (v2); } LoopOverEdges (*mesh, *this, v, [&](INDEX_2 edge, int elnr, int loc_edge, int element_dim, int edgedir) { if (!v2eht.Used(edge.I2())) { vertex2.Append (edge.I2()); v2eht.Set (edge.I2(), 33); } }); QuickSort (vertex2); for (int j = 0; j < vertex2.Size(); j++) { v2eht.Set (vertex2[j], ned); edge2vert[ned] = INDEX_2 (v, vertex2[j]); ned++; } LoopOverEdges (*mesh, *this, v, [&](INDEX_2 edge, int elnr, int loc_edge, int element_dim, int edgedir) { int edgenum = v2eht.Get(edge.I2()); switch (element_dim) { case 3: edges[elnr][loc_edge].nr = edgenum; // edges[elnr][loc_edge].orient = edgedir; break; case 2: surfedges[elnr][loc_edge].nr = edgenum; // surfedges[elnr][loc_edge].orient = edgedir; break; case 1: segedges[elnr].nr = edgenum; // segedges[elnr].orient = edgedir; break; } }); } } ); } // generate faces if (buildfaces) { static int timer2 = NgProfiler::CreateTimer ("topology::buildfaces"); // static int timer2a = NgProfiler::CreateTimer ("topology::buildfacesa"); // static int timer2b = NgProfiler::CreateTimer ("topology::buildfacesb"); // static int timer2b1 = NgProfiler::CreateTimer ("topology::buildfacesb1"); // static int timer2c = NgProfiler::CreateTimer ("topology::buildfacesc"); NgProfiler::RegionTimer reg2 (timer2); if (id == 0) PrintMessage (5, "Update faces "); // NgProfiler::StartTimer (timer2a); faces.SetSize(ne); surffaces.SetSize(nse); cnt = 0; for (int i = 0; i < face2vert.Size(); i++) cnt[face2vert[i][0]]++; TABLE vert2oldface(cnt); for (int i = 0; i < face2vert.Size(); i++) vert2oldface.AddSave (face2vert[i][0], i); for (int elnr = 0; elnr < ne; elnr++) for (int j = 0; j < 6; j++) faces[elnr][j].fnr = -1; int max_face_on_vertex = 0; for (int i = PointIndex::BASE; i < nv+PointIndex::BASE; i++) { int onv = vert2oldface[i].Size() + vert2element[i].Size() + vert2surfelement[i].Size(); max_face_on_vertex = max (onv, max_face_on_vertex); } // NgProfiler::StopTimer (timer2a); // NgProfiler::StartTimer (timer2b); INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); int oldnfa = face2vert.Size(); // count faces associated with vertices cnt = 0; // for (auto v : mesh.Points().Range()) // NgProfiler::StartTimer (timer2b1); ParallelForRange (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); for (PointIndex v = begin+PointIndex::BASE; v < end+PointIndex::BASE; v++) { vert2face.DeleteData(); for (int j = 0; j < vert2oldface[v].Size(); j++) { int fnr = vert2oldface[v][j]; INDEX_3 face (face2vert[fnr].I1(), face2vert[fnr].I2(), face2vert[fnr].I3()); vert2face.Set (face, 33); // something } int cnti = 0; LoopOverFaces (*mesh, *this, v, [&] (INDEX_4 i4, int elnr, int j, bool volume, int facedir) { INDEX_3 face(i4.I1(), i4.I2(), i4.I3()); if (!vert2face.Used (face)) { cnti++; vert2face.Set (face, 33); // something } }); cnt[v] = cnti; } } ); // NgProfiler::StopTimer (timer2b1); // accumulate number of faces int nfa = oldnfa; // for (auto v : Range(mesh->GetNV())) // Points().Range()) // for (size_t v = 0; v < mesh->GetNV(); v++) for (auto v : cnt.Range()) { auto hv = cnt[v]; cnt[v] = nfa; nfa += hv; } face2vert.SetSize(nfa); // for (auto v : mesh.Points().Range()) ParallelForRange (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); for (PointIndex v = begin+PointIndex::BASE; v < end+PointIndex::BASE; v++) { int first_fa = cnt[v]; int nfa = first_fa; vert2face.DeleteData(); for (int j = 0; j < vert2oldface[v].Size(); j++) { int fnr = vert2oldface[v][j]; INDEX_3 face (face2vert[fnr].I1(), face2vert[fnr].I2(), face2vert[fnr].I3()); vert2face.Set (face, fnr); } LoopOverFaces (*mesh, *this, v, [&] (INDEX_4 i4, int elnr, int j, bool volume, int facedir) { INDEX_3 face(i4.I1(), i4.I2(), i4.I3()); if (!vert2face.Used (face)) { face2vert[nfa] = i4; vert2face.Set (face, nfa); nfa++; } }); QuickSort (face2vert.Range(first_fa, nfa)); for (int j = first_fa; j < nfa; j++) { if (face2vert[j][0] == v) { INDEX_3 face (face2vert[j].I1(), face2vert[j].I2(), face2vert[j].I3()); vert2face.Set (face, j); } else break; } LoopOverFaces (*mesh, *this, v, [&] (INDEX_4 i4, int elnr, int j, bool volume, int facedir) { INDEX_3 face(i4.I1(), i4.I2(), i4.I3()); int facenum = vert2face.Get(face); if (volume) { faces[elnr][j].fnr = facenum; // faces[elnr][j].forient = facedir; } else { surffaces[elnr].fnr = facenum; // surffaces[elnr].forient = facedir; } }); } }); /* int oldnfa = face2vert.Size(); int nfa = oldnfa; INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); for (auto v : mesh.Points().Range()) { int first_fa = nfa; vert2face.DeleteData(); for (int j = 0; j < vert2oldface[v].Size(); j++) { int fnr = vert2oldface[v][j]; INDEX_3 face (face2vert[fnr].I1(), face2vert[fnr].I2(), face2vert[fnr].I3()); vert2face.Set (face, fnr+1); } for (int pass = 1; pass <= 2; pass++) { for (ElementIndex elnr : (*vert2element)[v]) { const Element & el = mesh[elnr]; int nelfaces = GetNFaces (el.GetType()); const ELEMENT_FACE * elfaces = GetFaces0 (el.GetType()); for (int j = 0; j < nelfaces; j++) if (elfaces[j][3] < 0) { // triangle INDEX_3 face(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]]); int facedir = 0; if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 1; } if (face.I2() > face.I3()) { swap (face.I2(), face.I3()); facedir += 2; } if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 4; } if (face.I1() != v) continue; if (pass == 1) { if (!vert2face.Used (face)) { nfa++; vert2face.Set (face, nfa); INDEX_4 hface(face.I1(),face.I2(),face.I3(),0); face2vert.Append (hface); } } else { int facenum = vert2face.Get(face); faces[elnr][j].fnr = facenum-1; faces[elnr][j].forient = facedir; } } else { // quad int facenum; INDEX_4Q face4(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]], el[elfaces[j][3]]); int facedir = 0; if (min2 (face4.I1(), face4.I2()) > min2 (face4.I4(), face4.I3())) { // z - flip facedir += 1; swap (face4.I1(), face4.I4()); swap (face4.I2(), face4.I3()); } if (min2 (face4.I1(), face4.I4()) > min2 (face4.I2(), face4.I3())) { // x - flip facedir += 2; swap (face4.I1(), face4.I2()); swap (face4.I3(), face4.I4()); } if (face4.I2() > face4.I4()) { // diagonal flip facedir += 4; swap (face4.I2(), face4.I4()); } INDEX_3 face(face4.I1(), face4.I2(), face4.I3()); if (face.I1() != v) continue; if (vert2face.Used (face)) { facenum = vert2face.Get(face); } else { if (pass == 2) cout << "hier in pass 2" << endl; nfa++; vert2face.Set (face, nfa); facenum = nfa; INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4()); face2vert.Append (hface); } faces[elnr][j].fnr = facenum-1; faces[elnr][j].forient = facedir; } } for (int j = 0; j < (*vert2surfelement)[v].Size(); j++) { SurfaceElementIndex elnr = (*vert2surfelement)[v][j]; const Element2d & el = mesh.SurfaceElement (elnr); const ELEMENT_FACE * elfaces = GetFaces1 (el.GetType()); if (elfaces[0][3] == 0) { // triangle int facenum; int facedir; INDEX_3 face(el.PNum(elfaces[0][0]), el.PNum(elfaces[0][1]), el.PNum(elfaces[0][2])); facedir = 0; if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 1; } if (face.I2() > face.I3()) { swap (face.I2(), face.I3()); facedir += 2; } if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 4; } if (face.I1() != v) continue; if (vert2face.Used (face)) facenum = vert2face.Get(face); else { nfa++; vert2face.Set (face, nfa); facenum = nfa; INDEX_4 hface(face.I1(),face.I2(),face.I3(),0); face2vert.Append (hface); } surffaces[elnr].fnr = facenum-1; surffaces[elnr].forient = facedir; } else { // quad int facenum; int facedir; INDEX_4Q face4(el.PNum(elfaces[0][0]), el.PNum(elfaces[0][1]), el.PNum(elfaces[0][2]), el.PNum(elfaces[0][3])); facedir = 0; if (min2 (face4.I1(), face4.I2()) > min2 (face4.I4(), face4.I3())) { // z - orientation facedir += 1; swap (face4.I1(), face4.I4()); swap (face4.I2(), face4.I3()); } if (min2 (face4.I1(), face4.I4()) > min2 (face4.I2(), face4.I3())) { // x - orientation facedir += 2; swap (face4.I1(), face4.I2()); swap (face4.I3(), face4.I4()); } if (face4.I2() > face4.I4()) { facedir += 4; swap (face4.I2(), face4.I4()); } INDEX_3 face(face4.I1(), face4.I2(), face4.I3()); if (face.I1() != v) continue; if (vert2face.Used (face)) facenum = vert2face.Get(face); else { nfa++; vert2face.Set (face, nfa); facenum = nfa; INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4()); face2vert.Append (hface); } surffaces[elnr].fnr = facenum-1; surffaces[elnr].forient = facedir; } } // sort faces if (pass == 1) { QuickSort (face2vert.Range(first_fa, nfa)); for (int j = first_fa; j < face2vert.Size(); j++) { if (face2vert[j][0] == v) { INDEX_3 face (face2vert[j].I1(), face2vert[j].I2(), face2vert[j].I3()); vert2face.Set (face, j+1); } else break; } } } } face2vert.SetAllocSize (nfa); */ // *testout << "face2vert = " << endl << face2vert << endl; // NgProfiler::StopTimer (timer2b); // NgProfiler::StartTimer (timer2c); face2surfel.SetSize (nfa); face2surfel = 0; for (int i = 1; i <= nse; i++) face2surfel.Elem(GetSurfaceElementFace(i)) = i; /* cout << "build table complete" << endl; cout << "faces = " << endl; cout << "face2vert = " << endl << face2vert << endl; cout << "surffaces = " << endl << surffaces << endl; cout << "face2surfel = " << endl << face2surfel << endl; */ surf2volelement.SetSize (nse); for (int i = 1; i <= nse; i++) { surf2volelement.Elem(i)[0] = 0; surf2volelement.Elem(i)[1] = 0; } (*tracer) ("Topology::Update build surf2vol", false); for (int i = 1; i <= ne; i++) for (int j = 0; j < 6; j++) { // int fnum = (faces.Get(i)[j]+7) / 8; int fnum = faces.Get(i)[j].fnr+1; if (fnum > 0 && face2surfel.Elem(fnum)) { int sel = face2surfel.Elem(fnum); surf2volelement.Elem(sel)[1] = surf2volelement.Elem(sel)[0]; surf2volelement.Elem(sel)[0] = i; } } (*tracer) ("Topology::Update build surf2vol", true); face2vert.SetAllocSize (face2vert.Size()); // face table complete #ifdef PARALLEL // (*testout) << " RESET Paralleltop" << endl; // paralleltop.Reset (); #endif (*tracer) ("Topology::Update count face_els", false); Array face_els(nfa), face_surfels(nfa); face_els = 0; face_surfels = 0; /* Array hfaces; for (int i = 1; i <= ne; i++) { GetElementFaces (i, hfaces); for (int j = 0; j < hfaces.Size(); j++) face_els[hfaces[j]-1]++; } */ ParallelForRange (tm, ne, [&] (size_t begin, size_t end) { Array hfaces; for (ElementIndex ei = begin; ei < end; ei++) { GetElementFaces (ei+1, hfaces); for (auto f : hfaces) AsAtomic(face_els[f-1])++; } }); for (int i = 1; i <= nse; i++) face_surfels[GetSurfaceElementFace (i)-1]++; (*tracer) ("Topology::Update count face_els", true); if (ne) { int cnt_err = 0; for (int i = 0; i < nfa; i++) { /* (*testout) << "face " << i << " has " << int(face_els[i]) << " els, " << int(face_surfels[i]) << " surfels, tot = " << face_els[i] + face_surfels[i] << endl; */ if (face_els[i] + face_surfels[i] == 1) { cnt_err++; #ifdef PARALLEL if ( ntasks > 1 ) { continue; // if ( !paralleltop.DoCoarseUpdate() ) continue; } else #endif { (*testout) << "illegal face : " << i << endl; (*testout) << "points = " << face2vert[i] << endl; (*testout) << "pos = "; for (int j = 0; j < 4; j++) if (face2vert[i].I(j+1) >= 1) (*testout) << (*mesh)[(PointIndex)face2vert[i].I(j+1)] << " "; (*testout) << endl; FlatArray vertels = GetVertexElements (face2vert[i].I(1)); for (int k = 0; k < vertels.Size(); k++) { int elfaces[10], orient[10]; int nf = GetElementFaces (vertels[k]+1, elfaces, orient); for (int l = 0; l < nf; l++) if (elfaces[l] == i) { // (*testout) << "is face of element " << vertels[k] << endl; if (mesh->coarsemesh && mesh->hpelements->Size() == mesh->GetNE() ) { const HPRefElement & hpref_el = (*mesh->hpelements) [ (*mesh)[vertels[k]].hp_elnr]; (*testout) << "coarse eleme = " << hpref_el.coarse_elnr << endl; } } } } } } if (cnt_err && ntasks == 1) cout << cnt_err << " elements are not matching !!!" << endl; } // NgProfiler::StopTimer (timer2c); } #ifdef PARALLEL if (id != 0) { // if ( paralleltop.DoCoarseUpdate() ) // paralleltop.UpdateCoarseGrid(); } #endif /* for (i = 1; i <= ne; i++) { (*testout) << "Element " << i << endl; (*testout) << "PNums " << endl; for( int l=1;l<=8;l++) *testout << mesh.VolumeElement(i).PNum(l) << "\t"; *testout << endl; (*testout) << "edges: " << endl; for (j = 0; j < 9; j++) (*testout) << edges.Elem(i)[j] << " "; (*testout) << "faces: " << endl; for (j = 0; j < 6; j++)m (*testout) << faces.Elem(i)[j] << " "; } for (i = 1; i <= nse; i++) { (*testout) << "SElement " << i << endl; (*testout) << "PNums " << endl; for( int l=1;l<=4;l++) *testout << mesh.SurfaceElement(i).PNum(l) << "\t"; *testout << endl; } */ timestamp = NextTimeStamp(); } const Point3d * MeshTopology :: GetVertices (ELEMENT_TYPE et) { static Point3d segm_points [] = { Point3d (1, 0, 0), Point3d (0, 0, 0) }; static Point3d trig_points [] = { Point3d ( 1, 0, 0 ), Point3d ( 0, 1, 0 ), Point3d ( 0, 0, 0 ) }; static Point3d quad_points [] = { Point3d ( 0, 0, 0 ), Point3d ( 1, 0, 0 ), Point3d ( 1, 1, 0 ), Point3d ( 0, 1, 0 ) }; static Point3d tet_points [] = { Point3d ( 1, 0, 0 ), Point3d ( 0, 1, 0 ), Point3d ( 0, 0, 1 ), Point3d ( 0, 0, 0 ) }; static Point3d pyramid_points [] = { Point3d ( 0, 0, 0 ), Point3d ( 1, 0, 0 ), Point3d ( 1, 1, 0 ), Point3d ( 0, 1, 0 ), Point3d ( 0, 0, 1-1e-7 ), }; static Point3d prism_points[] = { Point3d ( 1, 0, 0 ), Point3d ( 0, 1, 0 ), Point3d ( 0, 0, 0 ), Point3d ( 1, 0, 1 ), Point3d ( 0, 1, 1 ), Point3d ( 0, 0, 1 ) }; static Point3d hex_points [] = { Point3d ( 0, 0, 0 ), Point3d ( 1, 0, 0 ), Point3d ( 1, 1, 0 ), Point3d ( 0, 1, 0 ), Point3d ( 0, 0, 1 ), Point3d ( 1, 0, 1 ), Point3d ( 1, 1, 1 ), Point3d ( 0, 1, 1 ) }; switch (et) { case SEGMENT: case SEGMENT3: return segm_points; case TRIG: case TRIG6: return trig_points; case QUAD: case QUAD6: case QUAD8: return quad_points; case TET: case TET10: return tet_points; case PYRAMID: return pyramid_points; case PRISM: case PRISM12: return prism_points; case HEX: return hex_points; default: cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; } return 0; } void MeshTopology :: GetElementEdges (int elnr, Array & eledges) const { int ned = GetNEdges (mesh->VolumeElement(elnr).GetType()); eledges.SetSize (ned); for (int i = 0; i < ned; i++) eledges[i] = edges.Get(elnr)[i].nr+1; // eledges[i] = abs (edges.Get(elnr)[i]); } void MeshTopology :: GetElementFaces (int elnr, Array & elfaces, bool withorientation) const { int nfa = GetNFaces (mesh->VolumeElement(elnr).GetType()); elfaces.SetSize (nfa); if (!withorientation) for (int i = 1; i <= nfa; i++) { // elfaces.Elem(i) = (faces.Get(elnr)[i-1]-1) / 8 + 1; elfaces.Elem(i) = faces.Get(elnr)[i-1].fnr+1; } else { cerr << "GetElementFaces with orientation currently not supported" << endl; /* for (int i = 1; i <= nfa; i++) { elfaces.Elem(i) = (faces.Get(elnr)[i-1]-1) / 8 + 1; int orient = (faces.Get(elnr)[i-1]-1) % 8; if(orient == 1 || orient == 2 || orient == 4 || orient == 7) elfaces.Elem(i) *= -1; } */ } } void MeshTopology :: GetElementEdgeOrientations (int elnr, Array & eorient) const { int ned = GetNEdges (mesh->VolumeElement(elnr).GetType()); eorient.SetSize (ned); for (int i = 1; i <= ned; i++) // eorient.Elem(i) = (edges.Get(elnr)[i-1] > 0) ? 1 : -1; // eorient.Elem(i) = (edges.Get(elnr)[i-1].orient) ? -1 : 1; eorient.Elem(i) = GetElementEdgeOrientation (elnr, i-1) ? -1 : 1; } void MeshTopology :: GetElementFaceOrientations (int elnr, Array & forient) const { int nfa = GetNFaces (mesh->VolumeElement(elnr).GetType()); forient.SetSize (nfa); for (int i = 1; i <= nfa; i++) // forient.Elem(i) = faces.Get(elnr)[i-1].forient; // forient.Elem(i) = (faces.Get(elnr)[i-1]-1) % 8; forient.Elem(i) = GetElementFaceOrientation(elnr, i-1); } int MeshTopology :: GetElementEdges (int elnr, int * eledges, int * orient) const { // int ned = GetNEdges (mesh.VolumeElement(elnr).GetType()); if (mesh->GetDimension()==3 || 1) { if (orient) { for (int i = 0; i < 12; i++) { /* if (!edges.Get(elnr)[i]) return i; eledges[i] = abs (edges.Get(elnr)[i]); orient[i] = (edges.Get(elnr)[i] > 0 ) ? 1 : -1; */ if (edges.Get(elnr)[i].nr == -1) return i; eledges[i] = edges.Get(elnr)[i].nr+1; // orient[i] = edges.Get(elnr)[i].orient ? -1 : 1; orient[i] = GetElementEdgeOrientation(elnr, i) ? -1 : 1; } } else { for (int i = 0; i < 12; i++) { // if (!edges.Get(elnr)[i]) return i; // eledges[i] = abs (edges.Get(elnr)[i]); if (edges.Get(elnr)[i].nr == -1) return i; eledges[i] = edges.Get(elnr)[i].nr+1; } } return 12; } else { throw NgException("rethink implementation"); /* if (orient) { for (i = 0; i < 4; i++) { if (!surfedges.Get(elnr)[i]) return i; eledges[i] = abs (surfedges.Get(elnr)[i]); orient[i] = (surfedges.Get(elnr)[i] > 0 ) ? 1 : -1; } } else { if (!surfedges.Get(elnr)[i]) return i; for (i = 0; i < 4; i++) eledges[i] = abs (surfedges.Get(elnr)[i]); } */ return 4; // return GetSurfaceElementEdges (elnr, eledges, orient); } } int MeshTopology :: GetElementFaces (int elnr, int * elfaces, int * orient) const { // int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType()); if (orient) { for (int i = 0; i < 6; i++) { /* if (!faces.Get(elnr)[i]) return i; elfaces[i] = (faces.Get(elnr)[i]-1) / 8 + 1; orient[i] = (faces.Get(elnr)[i]-1) % 8; */ if (faces.Get(elnr)[i].fnr == -1) return i; elfaces[i] = faces.Get(elnr)[i].fnr+1; // orient[i] = faces.Get(elnr)[i].forient; orient[i] = GetElementFaceOrientation (elnr, i); } } else { for (int i = 0; i < 6; i++) { // if (!faces.Get(elnr)[i]) return i; // elfaces[i] = (faces.Get(elnr)[i]-1) / 8 + 1; if (faces.Get(elnr)[i].fnr == -1) return i; elfaces[i] = faces.Get(elnr)[i].fnr+1; } } return 6; } void MeshTopology :: GetSurfaceElementEdges (int elnr, Array & eledges) const { int ned = GetNEdges (mesh->SurfaceElement(elnr).GetType()); eledges.SetSize (ned); for (int i = 0; i < ned; i++) // eledges[i] = abs (surfedges.Get(elnr)[i]); eledges[i] = surfedges.Get(elnr)[i].nr+1; } void MeshTopology :: GetEdges (SurfaceElementIndex elnr, Array & eledges) const { int ned = GetNEdges ( (*mesh)[elnr].GetType()); eledges.SetSize (ned); for (int i = 0; i < ned; i++) // eledges[i] = abs (surfedges[elnr][i])-1; eledges[i] = surfedges[elnr][i].nr; } int MeshTopology :: GetSurfaceElementFace (int elnr) const { return surffaces.Get(elnr).fnr+1; } /* int MeshTopology :: GetFace (SurfaceElementIndex elnr) const { return surffaces[elnr].fnr; } */ void MeshTopology :: GetSurfaceElementEdgeOrientations (int elnr, Array & eorient) const { int ned = GetNEdges (mesh->SurfaceElement(elnr).GetType()); eorient.SetSize (ned); for (int i = 0; i < ned; i++) // eorient[i] = (surfedges.Get(elnr)[i] > 0) ? 1 : -1; // eorient[i] = (surfedges.Get(elnr)[i].orient) ? -1 : 1; eorient[i] = GetSurfaceElementEdgeOrientation(elnr, i) ? -1 : 1; } int MeshTopology :: GetSurfaceElementFaceOrientation (int elnr) const { // return (surffaces.Get(elnr)-1) % 8; // return surffaces.Get(elnr).forient; return GetSurfaceElementFaceOrientation2(elnr); } int MeshTopology :: GetSurfaceElementEdges (int elnr, int * eledges, int * orient) const { int i; if (mesh->GetDimension() == 3 || 1) { if (orient) { for (i = 0; i < 4; i++) { /* if (!surfedges.Get(elnr)[i]) return i; eledges[i] = abs (surfedges.Get(elnr)[i]); orient[i] = (surfedges.Get(elnr)[i] > 0 ) ? 1 : -1; */ if (surfedges.Get(elnr)[i].nr == -1) return i; eledges[i] = surfedges.Get(elnr)[i].nr+1; // orient[i] = (surfedges.Get(elnr)[i].orient) ? -1 : 1; orient[i] = GetSurfaceElementEdgeOrientation(elnr, i) ? -1 : 1; } } else { for (i = 0; i < 4; i++) { /* if (!surfedges.Get(elnr)[i]) return i; eledges[i] = abs (surfedges.Get(elnr)[i]); */ if (surfedges.Get(elnr)[i].nr == -1) return i; eledges[i] = surfedges.Get(elnr)[i].nr+1; } } return 4; } else { /* eledges[0] = abs (segedges.Get(elnr)); if (orient) orient[0] = segedges.Get(elnr) > 0 ? 1 : -1; */ eledges[0] = segedges.Get(elnr).nr+1; if (orient) // orient[0] = segedges.Get(elnr).orient ? -1 : 1; orient[0] = GetSegmentEdgeOrientation(elnr) ? -1 : 1; } return 1; } int MeshTopology :: GetElementEdgeOrientation (int elnr, int locedgenr) const { const Element & el = mesh->VolumeElement (elnr); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType()); int k = locedgenr; INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); int edgedir = (edge.I1() > edge.I2()); return edgedir; } int MeshTopology :: GetElementFaceOrientation (int elnr, int locfacenr) const { const Element & el = mesh->VolumeElement (elnr); const ELEMENT_FACE * elfaces = MeshTopology::GetFaces0 (el.GetType()); int j = locfacenr; if (elfaces[j][3] < 0) { // triangle INDEX_4 face(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]], 0); int facedir = 0; if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 1; } if (face.I2() > face.I3()) { swap (face.I2(), face.I3()); facedir += 2; } if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 4; } return facedir; } else { // quad // int facenum; INDEX_4 face4(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]], el[elfaces[j][3]]); int facedir = 0; if (min2 (face4.I1(), face4.I2()) > min2 (face4.I4(), face4.I3())) { // z - flip facedir += 1; swap (face4.I1(), face4.I4()); swap (face4.I2(), face4.I3()); } if (min2 (face4.I1(), face4.I4()) > min2 (face4.I2(), face4.I3())) { // x - flip facedir += 2; swap (face4.I1(), face4.I2()); swap (face4.I3(), face4.I4()); } if (face4.I2() > face4.I4()) { // diagonal flip facedir += 4; swap (face4.I2(), face4.I4()); } return facedir; } } int MeshTopology :: GetSurfaceElementEdgeOrientation (int elnr, int locedgenr) const { const Element2d & el = mesh->SurfaceElement (elnr); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType()); int k = locedgenr; INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); int edgedir = (edge.I1() > edge.I2()); return edgedir; } int MeshTopology :: GetSurfaceElementFaceOrientation2 (int elnr) const { const Element2d & el = mesh->SurfaceElement (elnr); const ELEMENT_FACE * elfaces = MeshTopology::GetFaces0 (el.GetType()); int j = 0; if (elfaces[j][3] < 0) { // triangle INDEX_4 face(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]], 0); int facedir = 0; if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 1; } if (face.I2() > face.I3()) { swap (face.I2(), face.I3()); facedir += 2; } if (face.I1() > face.I2()) { swap (face.I1(), face.I2()); facedir += 4; } return facedir; } else { // quad // int facenum; INDEX_4 face4(el[elfaces[j][0]], el[elfaces[j][1]], el[elfaces[j][2]], el[elfaces[j][3]]); int facedir = 0; if (min2 (face4.I1(), face4.I2()) > min2 (face4.I4(), face4.I3())) { // z - flip facedir += 1; swap (face4.I1(), face4.I4()); swap (face4.I2(), face4.I3()); } if (min2 (face4.I1(), face4.I4()) > min2 (face4.I2(), face4.I3())) { // x - flip facedir += 2; swap (face4.I1(), face4.I2()); swap (face4.I3(), face4.I4()); } if (face4.I2() > face4.I4()) { // diagonal flip facedir += 4; swap (face4.I2(), face4.I4()); } return facedir; } } int MeshTopology :: GetSegmentEdgeOrientation (int elnr) const { const Segment & el = mesh->LineSegment (elnr); const ELEMENT_EDGE * eledges = MeshTopology::GetEdges0 (el.GetType()); int k = 0; INDEX_2 edge(el[eledges[k][0]], el[eledges[k][1]]); int edgedir = (edge.I1() > edge.I2()); return edgedir; } void MeshTopology :: GetFaceVertices (int fnr, Array & vertices) const { vertices.SetSize(4); for (int i = 0; i < 4; i++) vertices[i] = face2vert.Get(fnr)[i]; if (vertices[3] == 0) vertices.SetSize(3); } void MeshTopology :: GetFaceVertices (int fnr, int * vertices) const { for (int i = 0; i <= 3; i++) vertices[i] = face2vert.Get(fnr)[i]; } void MeshTopology :: GetEdgeVertices (int ednr, int & v1, int & v2) const { // cout << "id = " << id << "getedgevertices, ednr = " << ednr << ", ned = " << edge2vert.Size() << "&v1 = " << &v1 << endl; if (ednr < 1 || ednr > edge2vert.Size()) cerr << "illegal edge nr: " << ednr << ", numedges = " << edge2vert.Size() << " id = " << id << endl; v1 = edge2vert.Get(ednr)[0]; v2 = edge2vert.Get(ednr)[1]; } void MeshTopology :: GetEdgeVertices (int ednr, PointIndex & v1, PointIndex & v2) const { v1 = edge2vert.Get(ednr)[0]; v2 = edge2vert.Get(ednr)[1]; } void MeshTopology :: GetFaceEdges (int fnr, Array & fedges, bool withorientation) const { ArrayMem pi(4); ArrayMem eledges; fedges.SetSize (0); GetFaceVertices(fnr, pi); // Sort Edges according to global vertex numbers // e1 = fmax, f2 // e2 = fmax, f1 // e3 = op e1(f2,f3) // e4 = op e2(f1,f3) /* ArrayMem fp; fp[0] = pi[0]; for(int k=1;kfp[0]) swap(fp[k],fp[0]); fp[1] = fp[0]+ */ // GetVertexElements (pi[0], els); FlatArray els = GetVertexElements (pi[0]); // find one element having all vertices of the face for (int i = 0; i < els.Size(); i++) { const Element & el = (*mesh)[els[i]]; int nref_faces = GetNFaces (el.GetType()); const ELEMENT_FACE * ref_faces = GetFaces1 (el.GetType()); int nfa_ref_edges = GetNEdges (GetFaceType(fnr)); int cntv = 0,fa=-1; for(int m=0;m0;j++) for(int k=0;k=0) { const ELEMENT_EDGE * fa_ref_edges = GetEdges1 (GetFaceType(fnr)); fedges.SetSize(nfa_ref_edges); GetElementEdges (els[i]+1, eledges); for (int j = 0; j < eledges.Size(); j++) { int vi1, vi2; GetEdgeVertices (eledges[j], vi1, vi2); bool has1 = 0; bool has2 = 0; for (int k = 0; k < pi.Size(); k++) { if (vi1 == pi[k]) has1 = 1; if (vi2 == pi[k]) has2 = 1; } if (has1 && has2) // eledges[j] is on face { // fedges.Append (eledges[j]); for(int k=0;k & elements) const { if (vert2element.Size()) { int ne = vert2element.EntrySize(vnr); elements.SetSize(ne); for (int i = 1; i <= ne; i++) elements.Elem(i) = vert2element.Get(vnr, i); } } /* FlatArray MeshTopology :: GetVertexElements (int vnr) const { if (vert2element) return (*vert2element)[vnr]; return FlatArray (0,0); } FlatArray MeshTopology :: GetVertexSurfaceElements (int vnr) const { if (vert2surfelement) return (*vert2surfelement)[vnr]; return FlatArray (0,0); } FlatArray MeshTopology :: GetVertexSegments (int vnr) const { if (vert2segment) return (*vert2segment)[vnr]; return FlatArray (0,0); } */ void MeshTopology :: GetVertexSurfaceElements( int vnr, Array & elements ) const { if (vert2surfelement.Size()) { int i; int ne = vert2surfelement.EntrySize(vnr); elements.SetSize(ne); for (i = 1; i <= ne; i++) elements.Elem(i) = vert2surfelement.Get(vnr, i); } } int MeshTopology :: GetVerticesEdge ( int v1, int v2 ) const { Array elements_v1; Array elementedges; GetVertexElements ( v1, elements_v1); int edv1, edv2; for ( int i = 0; i < elements_v1.Size(); i++ ) { GetElementEdges( elements_v1[i]+1, elementedges ); for ( int ed = 0; ed < elementedges.Size(); ed ++) { GetEdgeVertices( elementedges[ed], edv1, edv2 ); if ( ( edv1 == v1 && edv2 == v2 ) || ( edv1 == v2 && edv2 == v1 ) ) return elementedges[ed]; } } return -1; } void MeshTopology :: GetSegmentVolumeElements ( int segnr, Array & volels ) const { int v1, v2; GetEdgeVertices ( GetSegmentEdge (segnr), v1, v2 ); Array volels1, volels2; GetVertexElements ( v1, volels1 ); GetVertexElements ( v2, volels2 ); volels.SetSize(0); for ( int eli1=1; eli1 <= volels1.Size(); eli1++) if ( volels2.Contains( volels1.Elem(eli1) ) ) volels.Append ( volels1.Elem(eli1) ); } void MeshTopology :: GetSegmentSurfaceElements (int segnr, Array & els) const { int v1, v2; GetEdgeVertices ( GetSegmentEdge (segnr), v1, v2 ); Array els1, els2; GetVertexSurfaceElements ( v1, els1 ); GetVertexSurfaceElements ( v2, els2 ); els.SetSize(0); for ( int eli1=1; eli1 <= els1.Size(); eli1++) if ( els2.Contains( els1.Elem(eli1) ) ) els.Append ( els1.Elem(eli1) ); } } netgen-6.2.1905/libsrc/meshing/ruler2.cpp0000644000175000017500000003752313504650527016642 0ustar kurtkurt#include #include "meshing.hpp" namespace netgen { static double CalcElementBadness (const Array & points, const Element2d & elem) { // badness = sqrt(3) /36 * circumference^2 / area - 1 + // h / li + li / h - 2 Vec2d v12, v13, v23; double l12, l13, l23, cir, area; static const double c = sqrt(3.0) / 36; v12 = points.Get(elem.PNum(2)) - points.Get(elem.PNum(1)); v13 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(1)); v23 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(2)); l12 = v12.Length(); l13 = v13.Length(); l23 = v23.Length(); cir = l12 + l13 + l23; area = 0.5 * (v12.X() * v13.Y() - v12.Y() * v13.X()); if (area < 1e-6) { return 1e8; } if (testmode) { (*testout) << "l = " << l12 << " + " << l13 << " + " << l23 << " = " << cir << ", area = " << area << endl; (*testout) << "shapeerr = " << 10 * (c * cir * cir / area - 1) << endl << "sizeerr = " << 1/l12 + l12 + 1/l13 + l13 + 1/l23 + l23 - 6 << endl; } return 10 * (c * cir * cir / area - 1) + 1/l12 + l12 + 1/l13 + l13 + 1/l23 + l23 - 6; } int Meshing2 ::ApplyRules (Array & lpoints, Array & legalpoints, int maxlegalpoint, Array & llines1, int maxlegalline, Array & elements, Array & dellines, int tolerance, const MeshingParameters & mp) { static int timer = NgProfiler::CreateTimer ("meshing2::ApplyRules"); NgProfiler::RegionTimer reg (timer); double maxerr = 0.5 + 0.3 * tolerance; double minelerr = 2 + 0.5 * tolerance * tolerance; int noldlp = lpoints.Size(); int noldll = llines1.Size(); ArrayMem pused(maxlegalpoint), lused(maxlegalline); ArrayMem pnearness(noldlp), lnearness(llines1.Size()); ArrayMem pmap, pfixed, lmap; ArrayMem tempnewpoints; ArrayMem tempnewlines; ArrayMem tempdellines; ArrayMem tempelements; elements.SetSize (0); dellines.SetSize (0); testmode = debugparam.debugoutput; #ifdef LOCDEBUG int loctestmode = testmode; if (loctestmode) { (*testout) << endl << endl << "Check new environment" << endl; (*testout) << "tolerance = " << tolerance << endl; for (int i = 1; i <= lpoints.Size(); i++) (*testout) << "P" << i << " = " << lpoints.Get(i) << endl; (*testout) << endl; for (int i = 1; i <= llines1.Size(); i++) (*testout) << "(" << llines1.Get(i).I1() << "-" << llines1.Get(i).I2() << ")" << endl; } #endif // check every rule int found = 0; // rule number pnearness = 1000; for (int j = 0; j < 2; j++) pnearness.Set(llines1[0][j], 0); enum { MAX_NEARNESS = 3 }; for (int cnt = 0; cnt < MAX_NEARNESS; cnt++) { bool ok = true; for (int i = 0; i < maxlegalline; i++) { const INDEX_2 & hline = llines1[i]; int minn = min2 (pnearness.Get(hline[0]), pnearness.Get(hline[1])); for (int j = 0; j < 2; j++) if (pnearness.Get(hline[j]) > minn+1) { ok = false; pnearness.Set(hline[j], minn+1); } } if (!ok) break; } for (int i = 0; i < maxlegalline; i++) lnearness[i] = pnearness.Get(llines1[i][0]) + pnearness.Get(llines1[i][1]); // resort lines after lnearness Array llines(llines1.Size()); Array sortlines(llines1.Size()); int lnearness_class[MAX_NEARNESS]; for (int j = 0; j < MAX_NEARNESS; j++) lnearness_class[j] = 0; for (int i = 0; i < maxlegalline; i++) if (lnearness[i] < MAX_NEARNESS) lnearness_class[lnearness[i]]++; int cumm = 0; for (int j = 0; j < MAX_NEARNESS; j++) { int hcnt = lnearness_class[j]; lnearness_class[j] = cumm; cumm += hcnt; } for (int i = 0; i < maxlegalline; i++) if (lnearness[i] < MAX_NEARNESS) { llines[lnearness_class[lnearness[i]]] = llines1[i]; sortlines[lnearness_class[lnearness[i]]] = i+1; lnearness_class[lnearness[i]]++; } else { llines[cumm] = llines1[i]; sortlines[cumm] = i+1; cumm++; } for (int i = maxlegalline; i < llines1.Size(); i++) { llines[cumm] = llines1[i]; sortlines[cumm] = i+1; cumm++; } for (int i = 0; i < maxlegalline; i++) lnearness[i] = pnearness.Get(llines[i][0]) + pnearness.Get(llines[i][1]); static bool firsttime = true; // static int timers[100]; // static int timers2[100]; // static int timers3[100]; if (firsttime) { /* for (int ri = 0; ri < rules.Size(); ri++) timers[ri] = NgProfiler::CreateTimer (string("netrule ")+rules[ri]->Name()); for (int ri = 0; ri < rules.Size(); ri++) timers2[ri] = NgProfiler::CreateTimer (string("netrule,mapped ")+rules[ri]->Name()); for (int ri = 0; ri < rules.Size(); ri++) timers3[ri] = NgProfiler::CreateTimer (string("netrule,lines mapped ")+rules[ri]->Name()); */ firsttime = false; } lused = 0; pused = 0; static int timer1 = NgProfiler::CreateTimer ("meshing2::ApplyRules 1"); NgProfiler::RegionTimer reg1 (timer1); for (int ri = 1; ri <= rules.Size(); ri++) { // NgProfiler::RegionTimer reg(timers[ri-1]); netrule * rule = rules.Get(ri); #ifdef LOCDEBUG if (loctestmode) (*testout) << "Rule " << rule->Name() << endl; #endif if (rule->GetQuality() > tolerance) continue; pmap.SetSize (rule->GetNP()); lmap.SetSize (rule->GetNL()); pmap = 0; lmap = 0; lused[0] = 1; lmap[0] = 1; for (int j = 0; j < 2; j++) { pmap.Elem(rule->GetLine(1)[j]) = llines[0][j]; pused.Elem(llines[0][j])++; } int nlok = 2; bool ok = false; while (nlok >= 2) { if (nlok <= rule->GetNOldL()) { ok = 0; int maxline = (rule->GetLNearness(nlok) < MAX_NEARNESS) ? lnearness_class[rule->GetLNearness(nlok)] : maxlegalline; // int maxline = maxlegalline; while (!ok && lmap.Get(nlok) < maxline) { lmap.Elem(nlok)++; int locli = lmap.Get(nlok); if (lnearness.Get(locli) > rule->GetLNearness (nlok) ) continue; if (lused.Get(locli)) continue; ok = 1; INDEX_2 loclin = llines.Get(locli); Vec2d linevec = lpoints.Get(loclin.I2()) - lpoints.Get(loclin.I1()); if (rule->CalcLineError (nlok, linevec) > maxerr) { ok = 0; #ifdef LOCDEBUG if(loctestmode) (*testout) << "not ok pos1" << endl; #endif continue; } for (int j = 0; j < 2; j++) { int refpi = rule->GetLine(nlok)[j]; if (pmap.Get(refpi) != 0) { if (pmap.Get(refpi) != loclin[j]) { ok = 0; #ifdef LOCDEBUG if(loctestmode) (*testout) << "not ok pos2" << endl; #endif break; } } else { if (rule->CalcPointDist (refpi, lpoints.Get(loclin[j])) > maxerr || !legalpoints.Get(loclin[j]) || pused.Get(loclin[j])) { ok = 0; #ifdef LOCDEBUG if(loctestmode) { (*testout) << "nok pos3" << endl; //if(rule->CalcPointDist (refpi, lpoints.Get(loclin[j])) > maxerr) //(*testout) << "r1" << endl; //if(!legalpoints.Get(loclin[j])) //(*testout) << "r2 legalpoints " << legalpoints << " loclin " << loclin << " j " << j << endl; //if(pused.Get(loclin[j])) //(*testout) << "r3" << endl; } #endif break; } } } } if (ok) { int locli = lmap.Get(nlok); INDEX_2 loclin = llines.Get(locli); lused.Elem (locli) = 1; for (int j = 0; j < 2; j++) { pmap.Set(rule->GetLine (nlok)[j], loclin[j]); pused.Elem(loclin[j])++; } nlok++; } else { lmap.Elem(nlok) = 0; nlok--; lused.Elem (lmap.Get(nlok)) = 0; for (int j = 0; j < 2; j++) { pused.Elem(llines.Get(lmap.Get(nlok))[j]) --; if (! pused.Get (llines.Get (lmap.Get (nlok))[j])) pmap.Set (rule->GetLine (nlok)[j], 0); } } } else { // NgProfiler::RegionTimer reg(timers3[ri-1]); // all lines are mapped !! // map also all points: int npok = 1; int incnpok = 1; pfixed.SetSize (pmap.Size()); for (int i = 0; i < pmap.Size(); i++) pfixed[i] = (pmap[i] >= 1); while (npok >= 1) { if (npok <= rule->GetNOldP()) { if (pfixed.Get(npok)) { if (incnpok) npok++; else npok--; } else { ok = 0; if (pmap.Get(npok)) pused.Elem(pmap.Get(npok))--; while (!ok && pmap.Get(npok) < maxlegalpoint) { ok = 1; pmap.Elem(npok)++; if (pused.Get(pmap.Get(npok))) { ok = 0; } else { if (rule->CalcPointDist (npok, lpoints.Get(pmap.Get(npok))) > maxerr || !legalpoints.Get(pmap.Get(npok))) ok = 0; } } if (ok) { pused.Elem(pmap.Get(npok))++; npok++; incnpok = 1; } else { pmap.Elem(npok) = 0; npok--; incnpok = 0; } } } else { // NgProfiler::RegionTimer reg(timers2[ri-1]); npok = rule->GetNOldP(); incnpok = 0; if (ok) foundmap.Elem(ri)++; #ifdef LOCDEBUG if (loctestmode) (*testout) << "lines and points mapped" << endl; #endif ok = 1; // check orientations for (int i = 1; i <= rule->GetNOrientations(); i++) { if (CW (lpoints.Get(pmap.Get(rule->GetOrientation(i).i1)), lpoints.Get(pmap.Get(rule->GetOrientation(i).i2)), lpoints.Get(pmap.Get(rule->GetOrientation(i).i3))) ) { ok = 0; #ifdef LOCDEBUG if (loctestmode) (*testout) << "Orientation " << i << " not ok" << endl; #endif break; } } if (!ok) continue; Vector oldu (2 * rule->GetNOldP()); for (int i = 1; i <= rule->GetNOldP(); i++) { Vec2d ui(rule->GetPoint(i), lpoints.Get(pmap.Get(i))); oldu (2*i-2) = ui.X(); oldu (2*i-1) = ui.Y(); } rule -> SetFreeZoneTransformation (oldu, tolerance); if (!ok) continue; if (!rule->ConvexFreeZone()) { ok = 0; #ifdef LOCDEBUG if (loctestmode) (*testout) << "freezone not convex" << endl; #endif /* static int cnt = 0; cnt++; if (cnt % 100 == 0) { cout << "freezone not convex, cnt = " << cnt << "; rule = " << rule->Name() << endl; (*testout) << "freezone not convex, cnt = " << cnt << "; rule = " << rule->Name() << endl; (*testout) << "tol = " << tolerance << endl; (*testout) << "maxerr = " << maxerr << "; minerr = " << minelerr << endl; (*testout) << "freezone = " << rule->GetTransFreeZone() << endl; } */ } // check freezone: if (!ok) continue; for (int i = 1; i <= maxlegalpoint && ok; i++) { if ( !pused.Get(i) && rule->IsInFreeZone (lpoints.Get(i)) ) { ok = 0; #ifdef LOCDEBUG if (loctestmode) (*testout) << "Point " << i << " in freezone" << endl; #endif break; } } if (!ok) continue; for (int i = maxlegalpoint+1; i <= lpoints.Size(); i++) { if ( rule->IsInFreeZone (lpoints.Get(i)) ) { ok = 0; #ifdef LOCDEBUG if (loctestmode) (*testout) << "Point " << i << " in freezone" << endl; #endif break; } } if (!ok) continue; for (int i = 1; i <= maxlegalline; i++) { if (!lused.Get(i) && rule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()), lpoints.Get(llines.Get(i).I2()))) { ok = 0; #ifdef LOCDEBUG if (loctestmode) (*testout) << "line " << llines.Get(i).I1() << "-" << llines.Get(i).I2() << " in freezone" << endl; #endif break; } } if (!ok) continue; for (int i = maxlegalline+1; i <= llines.Size(); i++) { if (rule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()), lpoints.Get(llines.Get(i).I2()))) { ok = 0; #ifdef LOCDEBUG if (loctestmode) (*testout) << "line " << llines.Get(i).I1() << "-" << llines.Get(i).I2() << " in freezone" << endl; #endif break; } } /* // check orientations for (i = 1; i <= rule->GetNOrientations() && ok; i++) { if (CW (lpoints.Get(pmap.Get(rule->GetOrientation(i).i1)), lpoints.Get(pmap.Get(rule->GetOrientation(i).i2)), lpoints.Get(pmap.Get(rule->GetOrientation(i).i3))) ) { ok = 0; if (loctestmode) (*testout) << "Orientation " << i << " not ok" << endl; } } */ if (!ok) continue; #ifdef LOCDEBUG if (loctestmode) (*testout) << "rule ok" << endl; #endif // Setze neue Punkte: if (rule->GetNOldP() < rule->GetNP()) { Vector newu(rule->GetOldUToNewU().Height()); rule->GetOldUToNewU().Mult (oldu, newu); int oldnp = rule->GetNOldP(); for (int i = oldnp + 1; i <= rule->GetNP(); i++) { Point2d np = rule->GetPoint(i); np.X() += newu (2 * (i-oldnp) - 2); np.Y() += newu (2 * (i-oldnp) - 1); lpoints.Append (np); pmap.Elem(i) = lpoints.Size(); } } // Setze neue Linien: for (int i = rule->GetNOldL() + 1; i <= rule->GetNL(); i++) { llines.Append (INDEX_2 (pmap.Get(rule->GetLine (i)[0]), pmap.Get(rule->GetLine (i)[1]))); } // delete old lines: for (int i = 1; i <= rule->GetNDelL(); i++) dellines.Append (sortlines.Elem (lmap.Get(rule->GetDelLine(i)))); // dellines.Append (lmap.Get(rule->GetDelLine(i)))); // dellines.Append (lmap.Elem(rule->GetDelLines())); // lmap[rule->GetDelLines()]; // insert new elements: for (int i = 1; i <= rule->GetNE(); i++) { elements.Append (rule->GetElement(i)); for (int j = 1; j <= elements.Get(i).GetNP(); j++) elements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j)); } double elerr = 0; for (int i = 1; i <= elements.Size(); i++) { double hf; if (!mp.quad) hf = CalcElementBadness (lpoints, elements.Get(i)); else hf = elements.Get(i).CalcJacobianBadness (lpoints) * 5; #ifdef LOCDEBUG if (loctestmode) (*testout) << "r " << rule->Name() << "bad = " << hf << endl; #endif if (hf > elerr) elerr = hf; } #ifdef LOCDEBUG if (loctestmode) (*testout) << "error = " << elerr; #endif canuse.Elem(ri) ++; if (elerr < 0.99*minelerr) { #ifdef LOCDEBUG if (loctestmode) { (*testout) << "rule = " << rule->Name() << endl; (*testout) << "class = " << tolerance << endl; (*testout) << "lpoints: " << endl; for (int i = 1; i <= lpoints.Size(); i++) (*testout) << lpoints.Get(i) << endl; (*testout) << "llines: " << endl; for (int i = 1; i <= llines.Size(); i++) (*testout) << llines.Get(i).I1() << " " << llines.Get(i).I2() << endl; (*testout) << "Freezone: "; for (int i = 1; i <= rule -> GetTransFreeZone().Size(); i++) (*testout) << rule->GetTransFreeZone().Get(i) << endl; } #endif minelerr = elerr; found = ri; tempnewpoints = lpoints.Range (noldlp, lpoints.Size()); tempnewlines = llines.Range (noldll, llines.Size()); tempdellines = dellines; tempelements = elements; } lpoints.SetSize (noldlp); llines.SetSize (noldll); dellines.SetSize (0); elements.SetSize (0); ok = 0; } } nlok = rule->GetNOldL(); lused.Set (lmap.Get(nlok), 0); for (int j = 1; j <= 2; j++) { int refpi = rule->GetPointNr (nlok, j); pused.Elem(pmap.Get(refpi))--; if (pused.Get(pmap.Get(refpi)) == 0) pmap.Set(refpi, 0); } } } } if (found) { lpoints.Append (tempnewpoints); llines1.Append (tempnewlines); dellines.Append (tempdellines); elements.Append (tempelements); } return found; } } netgen-6.2.1905/libsrc/meshing/msghandler.cpp0000644000175000017500000001246413504650527017550 0ustar kurtkurt//File for handling warnings, errors, messages #include namespace netgen { int printmessage_importance = 5; int printwarnings = 1; int printerrors = 1; int printdots = 1; int printfnstart = 0; // extern void Ng_PrintDest(const MyStr& s); extern void Ng_PrintDest(const char * s); //the dots for progression of program void PrintDot(char ch) { // if (printdots) if (printmessage_importance >= 4) { char st[2]; st[0] = ch; st[1] = 0; Ng_PrintDest(st); } } void PrintMessage(int importance, const MyStr& s1, const MyStr& s2) { if (importance <= printmessage_importance) { Ng_PrintDest(MyStr(" ")+s1+s2+MyStr("\n")); } } void PrintMessage(int importance, const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4) { if (importance <= printmessage_importance) { Ng_PrintDest(MyStr(" ")+s1+s2+s3+s4+MyStr("\n")); } } void PrintMessage(int importance, const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (importance <= printmessage_importance) { Ng_PrintDest(MyStr(" ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } } void PrintMessageCR(int importance, const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (importance <= printmessage_importance) { Ng_PrintDest(MyStr(" ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\r")); } } void PrintFnStart(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (printfnstart) Ng_PrintDest(MyStr(" Start Function: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } void PrintWarning(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (printwarnings) Ng_PrintDest(MyStr(" WARNING: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } void PrintError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (printerrors) Ng_PrintDest(MyStr(" ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } void PrintFileError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (printerrors) Ng_PrintDest(MyStr(" FILE ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } void PrintUserError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { Ng_PrintDest(MyStr(" USER ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } void PrintSysError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (printerrors) Ng_PrintDest(MyStr(" SYSTEM ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } void PrintTime(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) { if (printmessage_importance >= 3) Ng_PrintDest(MyStr(" Time = ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); } static Array msgstatus_stack(0); static Array threadpercent_stack(0); static MyStr msgstatus = ""; void ResetStatus() { SetStatMsg("idle"); for (int i = 0; i < msgstatus_stack.Size(); i++) delete msgstatus_stack[i]; msgstatus_stack.SetSize(0); threadpercent_stack.SetSize(0); // multithread.task = ""; multithread.percent = 100.; } void PushStatus(const MyStr& s) { msgstatus_stack.Append(new MyStr (s)); SetStatMsg(s); threadpercent_stack.Append(0); } void PushStatusF(const MyStr& s) { msgstatus_stack.Append(new MyStr (s)); SetStatMsg(s); threadpercent_stack.Append(0); PrintFnStart(s); } void PopStatus() { if (msgstatus_stack.Size()) { if (msgstatus_stack.Size() > 1) // SetStatMsg (*msgstatus_stack.Last()); SetStatMsg (*msgstatus_stack[msgstatus_stack.Size()-2]); else SetStatMsg (""); delete msgstatus_stack.Last(); msgstatus_stack.DeleteLast(); threadpercent_stack.DeleteLast(); if(threadpercent_stack.Size() > 0) multithread.percent = threadpercent_stack.Last(); else multithread.percent = 100.; } else { PrintSysError("PopStatus failed"); } } /* void SetStatMsgF(const MyStr& s) { PrintFnStart(s); SetStatMsg(s); } */ void SetStatMsg(const MyStr& s) { msgstatus = s; multithread.task = msgstatus.c_str(); } void SetThreadPercent(double percent) { multithread.percent = percent; if(threadpercent_stack.Size() > 0) threadpercent_stack.Last() = percent; } void GetStatus(MyStr & s, double & percentage) { if(threadpercent_stack.Size() > 0) percentage = threadpercent_stack.Last(); else percentage = multithread.percent; if ( msgstatus_stack.Size() ) s = *msgstatus_stack.Last(); else s = "idle"; } /* #ifdef SMALLLIB #define SMALLLIBORNOTCL #endif #ifdef NOTCL #define SMALLLIBORNOTCL #endif #ifdef SMALLLIBORNOTCL void Ng_PrintDest(const char * s){cout << s < #include "meshing.hpp" // not yet working .... namespace netgen { class DelaunayTrig { PointIndex pnums[3]; Point<3> c; double r; double rad2; public: DelaunayTrig () { ; } DelaunayTrig (int p1, int p2, int p3) { pnums[0] = p1; pnums[1] = p2; pnums[2] = p3; } PointIndex & operator[] (int j) { return pnums[j]; } const PointIndex & operator[] (int j) const { return pnums[j]; } void CalcCenter (Mesh & mesh) { Point<3> p1 = mesh[pnums[0]]; Point<3> p2 = mesh[pnums[1]]; Point<3> p3 = mesh[pnums[2]]; Vec<3> v1 = p2-p1; Vec<3> v2 = p3-p1; Mat<2,2> mat, inv; mat(0,0) = v1*v1; mat(0,1) = v1*v2; mat(1,0) = v2*v1; mat(1,1) = v2*v2; Vec<2> rhs, sol; rhs(0) = 0.5 * v1*v1; rhs(1) = 0.5 * v2*v2; CalcInverse (mat, inv); sol = inv * rhs; c = p1 + sol(0) * v1 + sol(1) * v2; rad2 = Dist2(c, p1); r = sqrt(rad2); } Point<3> Center() const { return c; } double Radius2() const { return rad2; } Box<3> BoundingBox() const { return Box<3> (c-Vec<3>(r,r,0.1), c+Vec<3>(r,r,0.1)); } }; ostream & operator<< (ostream & ost, DelaunayTrig trig) { ost << trig[0] << "-" << trig[1] << "-" << trig[2] << endl; return ost; } void Meshing2 :: BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp) { static int timer = NgProfiler::CreateTimer ("Meshing2::BlockFill"); static int timer1 = NgProfiler::CreateTimer ("Meshing2::BlockFill 1"); static int timer2 = NgProfiler::CreateTimer ("Meshing2::BlockFill 2"); static int timer3 = NgProfiler::CreateTimer ("Meshing2::BlockFill 3"); static int timer4 = NgProfiler::CreateTimer ("Meshing2::BlockFill 4"); NgProfiler::RegionTimer reg (timer); NgProfiler::StartTimer (timer1); double filldist = mp.filldist; cout << "blockfill local h" << endl; cout << "rel filldist = " << filldist << endl; PrintMessage (3, "blockfill local h"); Array > npoints; // adfront -> CreateTrees(); Box<3> bbox ( Box<3>::EMPTY_BOX ); double maxh = 0; for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine (i); const Point<3> & p1 = adfront->GetPoint(line.L().I1()); const Point<3> & p2 = adfront->GetPoint(line.L().I2()); maxh = max (maxh, Dist (p1, p2)); bbox.Add (p1); bbox.Add (p2); } cout << "bbox = " << bbox << endl; // Point<3> mpc = bbox.Center(); bbox.Increase (bbox.Diam()/2); Box<3> meshbox = bbox; NgProfiler::StopTimer (timer1); NgProfiler::StartTimer (timer2); LocalH loch2 (bbox, 1, 2); if (mp.maxh < maxh) maxh = mp.maxh; bool changed; do { mesh.LocalHFunction().ClearFlags(); for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine(i); Box<3> bbox (adfront->GetPoint (line.L().I1())); bbox.Add (adfront->GetPoint (line.L().I2())); double filld = filldist * bbox.Diam(); bbox.Increase (filld); mesh.LocalHFunction().CutBoundary (bbox); } mesh.LocalHFunction().FindInnerBoxes (adfront, NULL); npoints.SetSize(0); mesh.LocalHFunction().GetInnerPoints (npoints); changed = false; for (int i = 0; i < npoints.Size(); i++) { if (mesh.LocalHFunction().GetH(npoints[i]) > 1.2 * maxh) { mesh.LocalHFunction().SetH (npoints[i], maxh); changed = true; } } } while (changed); NgProfiler::StopTimer (timer2); NgProfiler::StartTimer (timer3); if (debugparam.slowchecks) (*testout) << "Blockfill with points: " << endl; *testout << "loch = " << mesh.LocalHFunction() << endl; *testout << "npoints = " << endl << npoints << endl; for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn (npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint (npoints.Get(i)); adfront->AddPoint (npoints.Get(i), gpnum); if (debugparam.slowchecks) { (*testout) << npoints.Get(i) << endl; Point<2> p2d (npoints.Get(i)(0), npoints.Get(i)(1)); if (!adfront->Inside(p2d)) { cout << "add outside point" << endl; (*testout) << "outside" << endl; } } } } NgProfiler::StopTimer (timer3); NgProfiler::StartTimer (timer4); // find outer points loch2.ClearFlags(); for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine(i); Box<3> bbox (adfront->GetPoint (line.L().I1())); bbox.Add (adfront->GetPoint (line.L().I2())); loch2.SetH (bbox.Center(), bbox.Diam()); } for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine(i); Box<3> bbox (adfront->GetPoint (line.L().I1())); bbox.Add (adfront->GetPoint (line.L().I2())); bbox.Increase (filldist * bbox.Diam()); loch2.CutBoundary (bbox); } loch2.FindInnerBoxes (adfront, NULL); // outer points : smooth mesh-grading npoints.SetSize(0); loch2.GetOuterPoints (npoints); for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn (npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint (npoints.Get(i)); adfront->AddPoint (npoints.Get(i), gpnum); } } NgProfiler::StopTimer (timer4); } void Meshing2 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp) { static int timer = NgProfiler::CreateTimer ("Meshing2::Delaunay - total"); static int timerstart = NgProfiler::CreateTimer ("Meshing2::Delaunay - start"); static int timerfinish = NgProfiler::CreateTimer ("Meshing2::Delaunay - finish"); static int timer1 = NgProfiler::CreateTimer ("Meshing2::Delaunay - incremental"); static int timer1a = NgProfiler::CreateTimer ("Meshing2::Delaunay - incremental a"); static int timer1b = NgProfiler::CreateTimer ("Meshing2::Delaunay - incremental b"); static int timer1c = NgProfiler::CreateTimer ("Meshing2::Delaunay - incremental c"); static int timer1d = NgProfiler::CreateTimer ("Meshing2::Delaunay - incremental d"); NgProfiler::RegionTimer reg (timer); cout << "2D Delaunay meshing (in progress)" << endl; BlockFillLocalH (mesh, mp); NgProfiler::StartTimer (timerstart); // do the delaunay // face bounding box: Box<3> bbox (Box<3>::EMPTY_BOX); for (int i = 0; i < adfront->GetNFL(); i++) { const FrontLine & line = adfront->GetLine(i); bbox.Add (Point<3> (adfront->GetPoint (line.L()[0]))); bbox.Add (Point<3> (adfront->GetPoint (line.L()[1]))); } for (int i = 0; i < mesh.LockedPoints().Size(); i++) bbox.Add (mesh.Point (mesh.LockedPoints()[i])); cout << "bbox = " << bbox << endl; // external point Vec<3> vdiag = bbox.PMax()-bbox.PMin(); auto old_points = mesh.Points().Range(); DelaunayTrig startel; startel[0] = mesh.AddPoint (bbox.PMin() + Vec<3> (-8*vdiag(0), -8*vdiag(1), 0)); startel[1] = mesh.AddPoint (bbox.PMin() + Vec<3> (+8*vdiag(0), -8*vdiag(1), 0)); startel[2] = mesh.AddPoint (bbox.PMin() + Vec<3> (0, 8*vdiag(1), 0)); Box<3> hbox; hbox.Set (mesh[startel[0]]); hbox.Add (mesh[startel[1]]); hbox.Add (mesh[startel[2]]); Point<3> hp = mesh[startel[0]]; hp(2) = 1; hbox.Add (hp); hp(2) = -1; hbox.Add (hp); BoxTree<3> searchtree(hbox); Array tempels; startel.CalcCenter (mesh); tempels.Append (startel); searchtree.Insert(startel.BoundingBox(), 0); Array closeels; Array intersecting; Array edges; // reorder points Array mixed(old_points.Size()); int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 }; int prim; { int i = 0; while (old_points.Size() % prims[i] == 0) i++; prim = prims[i]; } for (PointIndex pi : old_points) mixed[pi] = PointIndex ( (prim * pi) % old_points.Size() + PointIndex::BASE ); NgProfiler::StopTimer (timerstart); NgProfiler::StartTimer (timer1); for (PointIndex i1 : old_points) { PointIndex i = mixed[i1]; NgProfiler::StartTimer (timer1a); Point<3> newp = mesh[i]; intersecting.SetSize(0); edges.SetSize(0); searchtree.GetIntersecting (newp, newp, closeels); // for (int jj = 0; jj < closeels.Size(); jj++) // for (int j = 0; j < tempels.Size(); j++) for (int j : closeels) { if (tempels[j][0] < 0) continue; Point<3> c = tempels[j].Center(); double r2 = tempels[j].Radius2(); bool inside = Dist2(mesh[i], c) < r2; if (inside) intersecting.Append (j); } NgProfiler::StopTimer (timer1a); NgProfiler::StartTimer (timer1b); // find outer edges for (auto j : intersecting) { const DelaunayTrig & trig = tempels[j]; for (int k = 0; k < 3; k++) { int p1 = trig[k]; int p2 = trig[(k+1)%3]; INDEX_2 edge(p1,p2); edge.Sort(); bool found = false; for (int l = 0; l < edges.Size(); l++) if (edges[l] == edge) { edges.Delete(l); found = true; break; } if (!found) edges.Append (edge); } } NgProfiler::StopTimer (timer1b); NgProfiler::StartTimer (timer1c); /* for (int j = intersecting.Size()-1; j >= 0; j--) tempels.Delete (intersecting[j]); */ for (int j : intersecting) { searchtree.DeleteElement (j); tempels[j][0] = -1; tempels[j][1] = -1; tempels[j][2] = -1; } NgProfiler::StopTimer (timer1c); NgProfiler::StartTimer (timer1d); for (auto edge : edges) { DelaunayTrig trig (edge[0], edge[1], i); trig.CalcCenter (mesh); tempels.Append (trig); searchtree.Insert(trig.BoundingBox(), tempels.Size()-1); } NgProfiler::StopTimer (timer1d); } NgProfiler::StopTimer (timer1); NgProfiler::StartTimer (timerfinish); for (DelaunayTrig & trig : tempels) { if (trig[0] < 0) continue; Point<3> c = Center (mesh[trig[0]], mesh[trig[1]], mesh[trig[2]]); if (!adfront->Inside (Point<2> (c(0),c(1)))) continue; Vec<3> n = Cross (mesh[trig[1]]-mesh[trig[0]], mesh[trig[2]]-mesh[trig[0]]); if (n(2) < 0) Swap (trig[1], trig[2]); Element2d el(trig[0], trig[1], trig[2]); el.SetIndex (domainnr); mesh.AddSurfaceElement (el); } for (PointIndex pi : mesh.Points().Range()) *testout << pi << ": " << mesh[pi].Type() << endl; NgProfiler::StopTimer (timerfinish); } } netgen-6.2.1905/libsrc/meshing/bisect.hpp0000644000175000017500000000463713504650527016705 0ustar kurtkurt#ifndef BISECT #define BISECT class BisectionOptions { public: const char * outfilename; const char * mlfilename; const char * refinementfilename; const char * femcode; int maxlevel; int usemarkedelements; bool refine_hp; bool refine_p; TaskManager task_manager = &DummyTaskManager; Tracer tracer = &DummyTracer; DLL_HEADER BisectionOptions (); }; class ZRefinementOptions { public: int minref; DLL_HEADER ZRefinementOptions(); }; DLL_HEADER extern void BisectTetsCopyMesh (Mesh &, const NetgenGeometry *, BisectionOptions & opt); DLL_HEADER extern void ZRefinement (Mesh &, const class NetgenGeometry *, ZRefinementOptions & opt); class DLL_HEADER Refinement { MeshOptimize2d * optimizer2d; public: Refinement (); virtual ~Refinement (); void Refine (Mesh & mesh) const; void Refine (Mesh & mesh); void Bisect (Mesh & mesh, class BisectionOptions & opt, Array * quality_loss = NULL) const; void MakeSecondOrder (Mesh & mesh) const; void MakeSecondOrder (Mesh & mesh); virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, Point<3> & newp, PointGeomInfo & newgi) const; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, Point<3> & newp, EdgePointGeomInfo & newgi) const; virtual Vec<3> GetTangent (const Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const; virtual Vec<3> GetNormal (const Point<3> & p, int surfi1, const PointGeomInfo & gi) const; virtual void ProjectToSurface (Point<3> & p, int surfi) const; virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & /* gi */) const { ProjectToSurface (p, surfi); } virtual void ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const; void ValidateSecondOrder (Mesh & mesh); void ValidateRefinedMesh (Mesh & mesh, Array & parents); MeshOptimize2d * Get2dOptimizer(void) const { return optimizer2d; } void Set2dOptimizer(MeshOptimize2d * opti) { optimizer2d = opti; } virtual void LocalizeEdgePoints(Mesh & /* mesh */) const {;} }; #endif netgen-6.2.1905/libsrc/meshing/paralleltop.hpp0000644000175000017500000000701413504650527017743 0ustar kurtkurt#ifndef FILE_PARALLELTOP #define FILE_PARALLELTOP namespace netgen { class ParallelMeshTopology { const Mesh & mesh; /** mapping from local to distant vertex number each row of the table corresponds to one vertex each row contains a list of pairs (procnr, dist_vnum) */ TABLE loc2distvert, loc2distedge, loc2distface; Array glob_vert, glob_edge, glob_face; Array glob_el, glob_surfel, glob_segm; bool is_updated; public: ParallelMeshTopology (const Mesh & amesh); ~ParallelMeshTopology (); void Reset (); void Print() const; void UpdateCoarseGrid(); void UpdateCoarseGridGlobal(); // bool DoCoarseUpdate() const { return !coarseupdate; } /// set number of local vertices, reset sizes of loc2dist_vert, isexchangevert... void SetNV (int anv); void SetNE (int ane); void SetNSE (int anse); void SetNSegm (int anseg); void SetLoc2Glob_Vert (int locnum, int globnum) { glob_vert[locnum-1] = globnum; } void SetLoc2Glob_Edge (int locnum, int globnum) { glob_edge[locnum-1] = globnum; } void SetLoc2Glob_Face (int locnum, int globnum) { glob_face[locnum-1] = globnum; } void SetLoc2Glob_VolEl (int locnum, int globnum) { glob_el[locnum-1] = globnum; } void SetLoc2Glob_SurfEl (int locnum, int globnum) { glob_surfel[locnum-1] = globnum; } void SetLoc2Glob_Segm (int locnum, int globnum) { glob_segm[locnum-1] = globnum; } int GetGlobalPNum (int locnum) const { return glob_vert[locnum-1]; } int GetGlobalEdgeNum (int locnum) const { return glob_edge[locnum-1]; } int GetGlobalFaceNum (int locnum) const { return glob_face[locnum-1]; } int GetGlobalElNum (int locnum) const { return glob_el[locnum-1]; } int GetGlobalSElNum (int locnum) const { return glob_surfel[locnum-1]; } void SetDistantFaceNum (int dest, int locnum); void SetDistantPNum (int dest, int locnum); void SetDistantEdgeNum (int dest, int locnum); int GetNDistantPNums (int locpnum) const { return loc2distvert[locpnum-1].Size(); } int GetNDistantFaceNums (int locfacenum) const { return loc2distface[locfacenum-1].Size(); } int GetNDistantEdgeNums ( int locedgenum) const { return loc2distedge[locedgenum-1].Size(); } void GetDistantPNums (int locpnum, int * distpnums ) const { for (int i = 0; i < loc2distvert[locpnum-1].Size(); i++ ) distpnums[i] = loc2distvert[locpnum-1][i]; } void GetDistantFaceNums (int locfacenum, int * distfacenums ) const { for ( int i = 0; i < loc2distface[locfacenum-1].Size(); i++ ) distfacenums[i] = loc2distface[locfacenum-1][i]; } void GetDistantFaceNums (int locfacenum, Array & distfacenums ) const { distfacenums = loc2distface[locfacenum-1]; } void GetDistantEdgeNums (int locedgenum, int * distedgenums ) const { for (int i = 0; i < loc2distedge[locedgenum-1].Size(); i++ ) distedgenums[i] = loc2distedge[locedgenum-1][i]; } void GetDistantEdgeNums (int locedgenum, Array & distedgenums ) const { distedgenums = loc2distedge[locedgenum-1]; } FlatArray GetDistantPNums (int locnum) const { return loc2distvert[locnum]; } FlatArray GetDistantFaceNums (int locnum) const { return loc2distface[locnum]; } FlatArray GetDistantEdgeNums (int locnum) const { return loc2distedge[locnum]; } bool IsExchangeVert (int dest, int vnum) const { return loc2distvert[vnum-1].Contains (dest); } }; } #endif netgen-6.2.1905/libsrc/meshing/parser3.cpp0000644000175000017500000005261113504650527017001 0ustar kurtkurt#include #include "meshing.hpp" #ifdef WIN32 #define COMMASIGN ':' #else #define COMMASIGN ',' #endif namespace netgen { extern const char * tetrules[]; void LoadVMatrixLine (istream & ist, DenseMatrix & m, int line) { char ch; int pnum; float f; ist >> ch; while (ch != '}') { ist.putback (ch); ist >> f; ist >> ch; ist >> pnum; if (ch == 'x' || ch == 'X') m.Elem(line, 3 * pnum - 2) = f; if (ch == 'y' || ch == 'Y') m.Elem(line, 3 * pnum - 1) = f; if (ch == 'z' || ch == 'Z') m.Elem(line, 3 * pnum ) = f; if (ch == 'p' || ch == 'P') { m.Elem(line , 3 * pnum-2) = f; m.Elem(line+1, 3 * pnum-1) = f; m.Elem(line+2, 3 * pnum ) = f; } ist >> ch; if (ch == COMMASIGN) ist >> ch; } } int vnetrule :: NeighbourTrianglePoint (const threeint & t1, const threeint & t2) const { Array tr1(3); Array tr2(3); tr1.Elem(1)=t1.i1; tr1.Elem(2)=t1.i2; tr1.Elem(3)=t1.i3; tr2.Elem(1)=t2.i1; tr2.Elem(2)=t2.i2; tr2.Elem(3)=t2.i3; int ret=0; for (int i=1; i<=3; i++) { for (int j=1; j<=3; j++) { if ((tr1.Get(i)==tr2.Get(j) && tr1.Get((i%3)+1)==tr2.Get((j%3)+1)) || (tr1.Get(i)==tr2.Get((j%3)+1) && tr1.Get((i%3)+1)==tr2.Get(j))) {ret = tr2.Get((j+1)%3+1);} } } return ret; } void vnetrule :: LoadRule (istream & ist) { char buf[256]; char ch, ok; Point3d p; Element2d face(TRIG); int i, j, i1, i2, i3, fs, ii, ii1, ii2, ii3; twoint edge; DenseMatrix tempoldutonewu(30, 20), tempoldutofreezone(30, 20), tempoldutofreezonelimit(30, 20), tfz(20, 20), tfzl(20, 20); tempoldutonewu = 0; tempoldutofreezone = 0; tfz = 0; tfzl = 0; noldp = 0; noldf = 0; ist.get (buf, sizeof(buf), '"'); ist.get (ch); ist.get (buf, sizeof(buf), '"'); ist.get (ch); delete [] name; name = new char[strlen (buf) + 1]; strcpy (name, buf); // (*mycout) << "Rule " << name << " found." << endl; do { ist >> buf; if (strcmp (buf, "quality") == 0) { ist >> quality; } else if (strcmp (buf, "flags") == 0) { ist >> ch; while (ch != ';') { flags.Append (ch); ist >> ch; } } else if (strcmp (buf, "mappoints") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ',' ist >> p.Z(); ist >> ch; // ')' points.Append (p); noldp++; tolerances.SetSize (noldp); tolerances.Elem(noldp) = 1; ist >> ch; while (ch != ';') { if (ch == '{') { ist >> tolerances.Elem(noldp); ist >> ch; // '}' } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "mapfaces") == 0) { ist >> ch; while (ch == '(') { face.SetType(TRIG); ist >> face.PNum(1); ist >> ch; // ',' ist >> face.PNum(2); ist >> ch; // ',' ist >> face.PNum(3); ist >> ch; // ')' or ',' if (ch == COMMASIGN) { face.SetType(QUAD); ist >> face.PNum(4); ist >> ch; // ')' } faces.Append (face); noldf++; ist >> ch; while (ch != ';') { if (ch == 'd') { delfaces.Append (noldf); ist >> ch; // 'e' ist >> ch; // 'l' } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "mapedges") == 0) { ist >> ch; while (ch == '(') { ist >> edge.i1; ist >> ch; // ',' ist >> edge.i2; ist >> ch; // ')' edges.Append (edge); ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "newpoints") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ',' ist >> p.Z(); ist >> ch; // ')' points.Append (p); ist >> ch; while (ch != ';') { if (ch == '{') { LoadVMatrixLine (ist, tempoldutonewu, 3 * (points.Size()-noldp) - 2); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutonewu, 3 * (points.Size()-noldp) - 1); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutonewu, 3 * (points.Size()-noldp) ); } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "newfaces") == 0) { ist >> ch; while (ch == '(') { face.SetType(TRIG); ist >> face.PNum(1); ist >> ch; // ',' ist >> face.PNum(2); ist >> ch; // ',' ist >> face.PNum(3); ist >> ch; // ')' or ',' if (ch == COMMASIGN) { face.SetType(QUAD); ist >> face.PNum(4); ist >> ch; // ')' } faces.Append (face); ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "freezone") == 0) { ist >> ch; while (ch == '(') { ist >> p.X(); ist >> ch; // ',' ist >> p.Y(); ist >> ch; // ',' ist >> p.Z(); ist >> ch; // ')' freezone.Append (p); ist >> ch; while (ch != ';') { if (ch == '{') { LoadVMatrixLine (ist, tempoldutofreezone, 3 * freezone.Size() - 2); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutofreezone, 3 * freezone.Size() - 1); ist >> ch; // '{' LoadVMatrixLine (ist, tempoldutofreezone, 3 * freezone.Size() ); } ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "freezone2") == 0) { int k, nfp; nfp = 0; ist >> ch; DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50); hm3 = 0; while (ch == '{') { hm1 = 0; nfp++; LoadVMatrixLine (ist, hm1, 1); for (i = 1; i <= points.Size(); i++) tfz.Elem(nfp, i) = hm1.Get(1, 3*i-2); p.X() = p.Y() = p.Z() = 0; for (i = 1; i <= points.Size(); i++) { p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X(); p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y(); p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z(); } freezone.Append (p); freezonelimit.Append (p); hm2 = 0; for (i = 1; i <= 3 * noldp; i++) hm2.Elem(i, i) = 1; for (i = 1; i <= 3 * noldp; i++) for (j = 1; j <= 3 * (points.Size() - noldp); j++) hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i); for (i = 1; i <= 3; i++) for (j = 1; j <= 3 * noldp; j++) { double sum = 0; for (k = 1; k <= 3 * points.Size(); k++) sum += hm1.Get(i, k) * hm2.Get(k, j); hm3.Elem(i + 3 * (nfp-1), j) = sum; } // (*testout) << "freepoint: " << p << endl; while (ch != ';') ist >> ch; ist >> ch; } tfzl = tfz; tempoldutofreezone = hm3; tempoldutofreezonelimit = hm3; ist.putback(ch); } else if (strcmp (buf, "freezonelimit") == 0) { int k, nfp; nfp = 0; ist >> ch; DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50); hm3 = 0; while (ch == '{') { hm1 = 0; nfp++; LoadVMatrixLine (ist, hm1, 1); for (i = 1; i <= points.Size(); i++) tfzl.Elem(nfp, i) = hm1.Get(1, 3*i-2); p.X() = p.Y() = p.Z() = 0; for (i = 1; i <= points.Size(); i++) { p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X(); p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y(); p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z(); } freezonelimit.Elem(nfp) = p; hm2 = 0; for (i = 1; i <= 3 * noldp; i++) hm2.Elem(i, i) = 1; for (i = 1; i <= 3 * noldp; i++) for (j = 1; j <= 3 * (points.Size() - noldp); j++) hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i); for (i = 1; i <= 3; i++) for (j = 1; j <= 3 * noldp; j++) { double sum = 0; for (k = 1; k <= 3 * points.Size(); k++) sum += hm1.Get(i, k) * hm2.Get(k, j); hm3.Elem(i + 3 * (nfp-1), j) = sum; } // (*testout) << "freepoint: " << p << endl; while (ch != ';') ist >> ch; ist >> ch; } tempoldutofreezonelimit = hm3; ist.putback(ch); } else if (strcmp (buf, "freeset") == 0) { freesets.Append (new Array); ist >> ch; while (ch != ';') { ist.putback (ch); ist >> i; freesets.Last()->Append(i); ist >> ch; } } else if (strcmp (buf, "elements") == 0) { ist >> ch; while (ch == '(') { elements.Append (Element(TET)); // elements.Last().SetNP(1); ist >> elements.Last().PNum(1); ist >> ch; // ',' if (ch == COMMASIGN) { // elements.Last().SetNP(2); ist >> elements.Last().PNum(2); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(3); ist >> elements.Last().PNum(3); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(4); elements.Last().SetType(TET); ist >> elements.Last().PNum(4); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(5); elements.Last().SetType(PYRAMID); ist >> elements.Last().PNum(5); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(6); elements.Last().SetType(PRISM); ist >> elements.Last().PNum(6); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(6); elements.Last().SetType(HEX); ist >> elements.Last().PNum(7); ist >> ch; // ',' } if (ch == COMMASIGN) { // elements.Last().SetNP(6); elements.Last().SetType(HEX); ist >> elements.Last().PNum(8); ist >> ch; // ',' } /* orientations.Append (fourint()); orientations.Last().i1 = elements.Last().PNum(1); orientations.Last().i2 = elements.Last().PNum(2); orientations.Last().i3 = elements.Last().PNum(3); orientations.Last().i4 = elements.Last().PNum(4); */ ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "orientations") == 0) { ist >> ch; while (ch == '(') { // fourint a = fourint(); orientations.Append (fourint()); ist >> orientations.Last().i1; ist >> ch; // ',' ist >> orientations.Last().i2; ist >> ch; // ',' ist >> orientations.Last().i3; ist >> ch; // ',' ist >> orientations.Last().i4; ist >> ch; // ',' ist >> ch; while (ch != ';') { ist >> ch; } ist >> ch; } ist.putback (ch); } else if (strcmp (buf, "endrule") != 0) { PrintSysError ("Parser3d, unknown token " , buf); } } while (!ist.eof() && strcmp (buf, "endrule") != 0); // (*testout) << endl; // (*testout) << Name() << endl; // (*testout) << "no1 = " << GetNO() << endl; oldutonewu.SetSize (3 * (points.Size() - noldp), 3 * noldp); oldutonewu = 0; for (i = 1; i <= oldutonewu.Height(); i++) for (j = 1; j <= oldutonewu.Width(); j++) oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j); /* oldutofreezone = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp); oldutofreezonelimit = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp); oldutofreezone -> SetSymmetric(0); oldutofreezonelimit -> SetSymmetric(0); */ /* oldutofreezone = new DenseMatrix (3 * freezone.Size(), 3 * noldp); oldutofreezonelimit = new DenseMatrix (3 * freezone.Size(), 3 * noldp); for (i = 1; i <= oldutofreezone->Height(); i++) for (j = 1; j <= oldutofreezone->Width(); j++) // if (j == 4 || j >= 7) { if (tempoldutofreezone.Elem(i, j)) (*oldutofreezone)(i, j) = tempoldutofreezone(i, j); if (tempoldutofreezonelimit.Elem(i, j)) (*oldutofreezonelimit)(i, j) = tempoldutofreezonelimit(i, j); } */ oldutofreezone = new DenseMatrix (freezone.Size(), points.Size()); oldutofreezonelimit = new DenseMatrix (freezone.Size(), points.Size()); // oldutofreezone = new SparseMatrixFlex (freezone.Size(), points.Size()); // oldutofreezonelimit = new SparseMatrixFlex (freezone.Size(), points.Size()); for (i = 1; i <= freezone.Size(); i++) for (j = 1; j <= points.Size(); j++) { if (tfz.Elem(i, j)) (*oldutofreezone).Elem(i, j) = tfz.Elem(i, j); if (tfzl.Elem(i, j)) (*oldutofreezonelimit).Elem(i, j) = tfzl.Elem(i, j); } /* (*testout) << "Rule " << Name() << endl; (*testout) << "oldutofreezone = " << (*oldutofreezone) << endl; (*testout) << "oldutofreezonelimit = " << (*oldutofreezonelimit) << endl; */ freezonepi.SetSize (freezone.Size()); for (i = 1; i <= freezonepi.Size(); i++) freezonepi.Elem(i) = 0; for (i = 1; i <= freezone.Size(); i++) for (j = 1; j <= noldp; j++) if (Dist (freezone.Get(i), points.Get(j)) < 1e-8) freezonepi.Elem(i) = j; for (i = 1; i <= elements.Size(); i++) { if (elements.Elem(i).GetNP() == 4) { orientations.Append (fourint()); orientations.Last().i1 = elements.Get(i).PNum(1); orientations.Last().i2 = elements.Get(i).PNum(2); orientations.Last().i3 = elements.Get(i).PNum(3); orientations.Last().i4 = elements.Get(i).PNum(4); } if (elements.Elem(i).GetNP() == 5) { orientations.Append (fourint()); orientations.Last().i1 = elements.Get(i).PNum(1); orientations.Last().i2 = elements.Get(i).PNum(2); orientations.Last().i3 = elements.Get(i).PNum(3); orientations.Last().i4 = elements.Get(i).PNum(5); orientations.Append (fourint()); orientations.Last().i1 = elements.Get(i).PNum(1); orientations.Last().i2 = elements.Get(i).PNum(3); orientations.Last().i3 = elements.Get(i).PNum(4); orientations.Last().i4 = elements.Get(i).PNum(5); } } if (freesets.Size() == 0) { freesets.Append (new Array); for (i = 1; i <= freezone.Size(); i++) freesets.Elem(1)->Append(i); } // testout << "Freezone: " << endl; // for (i = 1; i <= freezone.Size(); i++) // (*testout) << "freepoint: " << freezone.Get(i) << endl; Vector vp(points.Size()), vfp(freezone.Size()); if (quality < 100) { for (int i = 1; i <= 3; i++) { for (int j = 1; j <= points.Size(); j++) vp(j-1) = points.Get(j).X(i); oldutofreezone->Mult(vp, vfp); for (int j = 1; j <= freezone.Size(); j++) freezone.Elem(j).X(i) = vfp(j-1); } // for (i = 1; i <= freezone.Size(); i++) // (*testout) << "freepoint: " << freezone.Get(i) << endl; } for (fs = 1; fs <= freesets.Size(); fs++) { freefaces.Append (new Array); Array & freeset = *freesets.Elem(fs); Array & freesetfaces = *freefaces.Last(); for (ii1 = 1; ii1 <= freeset.Size(); ii1++) for (ii2 = 1; ii2 <= freeset.Size(); ii2++) for (ii3 = 1; ii3 <= freeset.Size(); ii3++) if (ii1 < ii2 && ii1 < ii3 && ii2 != ii3) { i1 = freeset.Get(ii1); i2 = freeset.Get(ii2); i3 = freeset.Get(ii3); Vec3d v1, v2, n; v1 = freezone.Get(i3) - freezone.Get(i1); v2 = freezone.Get(i2) - freezone.Get(i1); n = Cross (v1, v2); n /= n.Length(); // (*testout) << "i1,2,3 = " << i1 << ", " << i2 << ", " << i3 << endl; // (*testout) << "v1 = " << v1 << " v2 = " << v2 << " n = " << n << endl; ok = 1; for (ii = 1; ii <= freeset.Size(); ii++) { i = freeset.Get(ii); // (*testout) << "i = " << i << endl; if (i != i1 && i != i2 && i != i3) if ( (freezone.Get(i) - freezone.Get(i1)) * n < 0 ) ok = 0; } if (ok) { freesetfaces.Append (threeint()); freesetfaces.Last().i1 = i1; freesetfaces.Last().i2 = i2; freesetfaces.Last().i3 = i3; } } } for (fs = 1; fs <= freesets.Size(); fs++) { freefaceinequ.Append (new DenseMatrix (freefaces.Get(fs)->Size(), 4)); } { int minn; // Array pnearness (noldp); pnearness.SetSize (noldp); for (i = 1; i <= pnearness.Size(); i++) pnearness.Elem(i) = INT_MAX/10; for (j = 1; j <= GetNP(1); j++) pnearness.Elem(GetPointNr (1, j)) = 0; do { ok = 1; for (i = 1; i <= noldf; i++) { minn = INT_MAX/10; for (j = 1; j <= GetNP(i); j++) minn = min2 (minn, pnearness.Get(GetPointNr (i, j))); for (j = 1; j <= GetNP(i); j++) if (pnearness.Get(GetPointNr (i, j)) > minn+1) { ok = 0; pnearness.Elem(GetPointNr (i, j)) = minn+1; } } for (i = 1; i <= edges.Size(); i++) { int pi1 = edges.Get(i).i1; int pi2 = edges.Get(i).i2; if (pnearness.Get(pi1) > pnearness.Get(pi2)+1) { ok = 0; pnearness.Elem(pi1) = pnearness.Get(pi2)+1; } if (pnearness.Get(pi2) > pnearness.Get(pi1)+1) { ok = 0; pnearness.Elem(pi2) = pnearness.Get(pi1)+1; } } for (i = 1; i <= elements.Size(); i++) if (elements.Get(i).GetNP() == 6) // prism rule { for (j = 1; j <= 3; j++) { int pi1 = elements.Get(i).PNum(j); int pi2 = elements.Get(i).PNum(j+3); if (pnearness.Get(pi1) > pnearness.Get(pi2)+1) { ok = 0; pnearness.Elem(pi1) = pnearness.Get(pi2)+1; } if (pnearness.Get(pi2) > pnearness.Get(pi1)+1) { ok = 0; pnearness.Elem(pi2) = pnearness.Get(pi1)+1; } } } } while (!ok); maxpnearness = 0; for (i = 1; i <= pnearness.Size(); i++) maxpnearness = max2 (maxpnearness, pnearness.Get(i)); fnearness.SetSize (noldf); for (i = 1; i <= noldf; i++) { fnearness.Elem(i) = 0; for (j = 1; j <= GetNP(i); j++) fnearness.Elem(i) += pnearness.Get(GetPointNr (i, j)); } // (*testout) << "rule " << name << ", pnear = " << pnearness << endl; } //Table of edges: for (fs = 1; fs <= freesets.Size(); fs++) { freeedges.Append (new Array); // Array & freeset = *freesets.Get(fs); Array & freesetedges = *freeedges.Last(); Array & freesetfaces = *freefaces.Get(fs); int k,l; INDEX ind; for (k = 1; k <= freesetfaces.Size(); k++) { // threeint tr = freesetfaces.Get(k); for (l = k+1; l <= freesetfaces.Size(); l++) { ind = NeighbourTrianglePoint(freesetfaces.Get(k), freesetfaces.Get(l)); if (!ind) continue; INDEX_3 f1(freesetfaces.Get(k).i1, freesetfaces.Get(k).i2, freesetfaces.Get(k).i3); INDEX_3 f2(freesetfaces.Get(l).i1, freesetfaces.Get(l).i2, freesetfaces.Get(l).i3); INDEX_2 ed(0, 0); for (int f11 = 1; f11 <= 3; f11++) for (int f12 = 1; f12 <= 3; f12++) if (f11 != f12) for (int f21 = 1; f21 <= 3; f21++) for (int f22 = 1; f22 <= 3; f22++) if (f1.I(f11) == f2.I(f21) && f1.I(f12) == f2.I(f22)) { ed.I(1) = f1.I(f11); ed.I(2) = f1.I(f12); } // (*testout) << "ed = " << ed.I(1) << "-" << ed.I(2) << endl; // (*testout) << "ind = " << ind << " ed = " << ed << endl; for (int eli = 1; eli <= GetNOldF(); eli++) { if (GetNP(eli) == 4) { for (int elr = 1; elr <= 4; elr++) { if (GetPointNrMod (eli, elr) == ed.I(1) && GetPointNrMod (eli, elr+2) == ed.I(2)) { /* (*testout) << "ed is diagonal of rectangle" << endl; (*testout) << "ed = " << ed.I(1) << "-" << ed.I(2) << endl; (*testout) << "ind = " << ind << endl; */ ind = 0; } } } } if (ind) { /* (*testout) << "new edge from face " << k << " = (" << freesetfaces.Get(k).i1 << ", " << freesetfaces.Get(k).i2 << ", " << freesetfaces.Get(k).i3 << "), point " << ind << endl; */ freesetedges.Append(twoint(k,ind)); } } } } } void Meshing3 :: LoadRules (const char * filename, const char ** prules) { char buf[256]; istream * ist; char *tr1 = NULL; if (filename) { PrintMessage (3, "rule-filename = ", filename); ist = new ifstream (filename); } else { /* connect tetrules to one string */ PrintMessage (3, "Use internal rules"); if (!prules) prules = tetrules; const char ** hcp = prules; size_t len = 0; while (*hcp) { len += strlen (*hcp); hcp++; } tr1 = new char[len+1]; tr1[0] = 0; hcp = prules; // tetrules; char * tt1 = tr1; while (*hcp) { strcat (tt1, *hcp); tt1 += strlen (*hcp); hcp++; } #ifdef WIN32 // VC++ 2005 workaround for(size_t i=0; igood()) { cerr << "Rule description file " << filename << " not found" << endl; delete ist; exit (1); } while (!ist->eof()) { buf[0] = 0; (*ist) >> buf; if (strcmp (buf, "rule") == 0) { vnetrule * rule = new vnetrule; rule -> LoadRule(*ist); rules.Append (rule); if (!rule->TestOk()) { PrintSysError ("Parser3d: Rule ", rules.Size(), " not ok"); exit (1); } } else if (strcmp (buf, "tolfak") == 0) { (*ist) >> tolfak; } } delete ist; delete [] tr1; } } netgen-6.2.1905/libsrc/meshing/bcfunctions.hpp0000644000175000017500000000423513504650527017743 0ustar kurtkurt#ifndef FILE_BCFUNCTIONS #define FILE_BCFUNCTIONS // Philippose - 14/03/2009 // Auxiliary functions for OCC Geometry // Use this file and the corresponding ".cpp" // file to add miscellaneous functionality // to the OpenCascade Geometry support in Netgen namespace netgen { /*! \brief Automatically assign boundary conditions for meshes This function allows the boundary condition numbers of a mesh created in Netgen to be automatically assigned based on the colours of each face. Currently, two algorithms are utilised to assign the BC Properties: 1. Automatic assignment using a user defined colour profile file which defines which RGB colours are to be assigned to which BC Property number - A default profile file exists in the Netgen folder called "netgen.ocf" 2. The second algorithm uses the following automated algorithm: - Extract all the colours present in the mesh - Use colour index 0 (zero) for all faces with no colour defined - Calculate the number of faces of the surface mesh for each colour - Sort the number of surface elements in ascending order, with the colour indices as a slave - Use the indices of the sorted array as the BC property number Example: If there are 3 colours, present in the mesh and the number of surface elements for each colour are: - Colour 0: 8500 - Colour 1: 120 - Colour 2: 2200 - Colour 3: 575 The above is sorted in ascending order and assigned as BC Properties: - BC Prop 0: 120 : Colour 1 - BC Prop 1: 575 : Colour 3 - BC Prop 2: 2200 : Colour 2 - BC Prop 3: 8500 : Colour 0 (no colour defined) */ //extern void OCCAutoColourBcProps(Mesh & mesh, OCCGeometry & occgeometry, const char *occcolourfile); extern DLL_HEADER void AutoColourBcProps(Mesh & mesh, const char *bccolourfile); extern DLL_HEADER void GetFaceColours(Mesh & mesh, Array & face_colours); extern DLL_HEADER bool ColourMatch(Vec3d col1, Vec3d col2, double eps = 2.5e-05); } #endif netgen-6.2.1905/libsrc/meshing/CMakeLists.txt0000644000175000017500000000364413504650527017460 0ustar kurtkurtadd_definitions(-DNGINTERFACE_EXPORTS) add_library(mesh ${NG_LIB_TYPE} adfront2.cpp adfront3.cpp bisect.cpp boundarylayer.cpp clusters.cpp curvedelems.cpp delaunay.cpp delaunay2d.cpp geomsearch.cpp global.cpp hprefinement.cpp improve2.cpp improve2gen.cpp improve3.cpp localh.cpp meshclass.cpp meshfunc.cpp meshfunc2d.cpp meshing2.cpp meshing3.cpp meshtool.cpp meshtype.cpp msghandler.cpp netrule2.cpp netrule3.cpp parser2.cpp parser3.cpp prism2rls.cpp pyramid2rls.cpp pyramidrls.cpp quadrls.cpp refine.cpp ruler2.cpp ruler3.cpp secondorder.cpp smoothing2.5.cpp smoothing2.cpp smoothing3.cpp specials.cpp tetrarls.cpp topology.cpp triarls.cpp validate.cpp bcfunctions.cpp parallelmesh.cpp paralleltop.cpp paralleltop.hpp basegeom.cpp python_mesh.cpp hexarls.cpp ../../ng/onetcl.cpp ${mesh_object_libs} ) if(APPLE) set_target_properties( mesh PROPERTIES SUFFIX ".so") endif(APPLE) target_link_libraries( mesh PUBLIC ngcore PRIVATE gprim la gen ) target_link_libraries( mesh PUBLIC ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) if(NOT WIN32) install( TARGETS mesh ${NG_INSTALL_DIR}) endif(NOT WIN32) install(FILES adfront2.hpp adfront3.hpp basegeom.hpp bcfunctions.hpp bisect.hpp boundarylayer.hpp classifyhpel.hpp clusters.hpp curvedelems.hpp findip2.hpp findip.hpp geomsearch.hpp global.hpp hpref_hex.hpp hprefinement.hpp hpref_prism.hpp hpref_pyramid.hpp hpref_quad.hpp hpref_segm.hpp hpref_tet.hpp hpref_trig.hpp improve2.hpp improve3.hpp localh.hpp meshclass.hpp meshfunc.hpp meshing2.hpp meshing3.hpp meshing.hpp meshtool.hpp meshtype.hpp msghandler.hpp paralleltop.hpp ruler2.hpp ruler3.hpp specials.hpp topology.hpp validate.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/meshing COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/gprim/0000755000175000017500000000000013504650527014375 5ustar kurtkurtnetgen-6.2.1905/libsrc/gprim/geom3d.hpp0000644000175000017500000004471113504650527016273 0ustar kurtkurt#ifndef FILE_GEOM3D #define FILE_GEOM3D /* *************************************************************************/ /* File: geom3d.hh */ /* Author: Joachim Schoeberl */ /* Date: 5. Aug. 95 */ /* *************************************************************************/ namespace netgen { extern DLL_HEADER void MyError (const char * ch); class Point3d; class Vec3d; inline Vec3d operator- (const Point3d & p1, const Point3d & p2); inline Point3d operator- (const Point3d & p1, const Vec3d & v); inline Point3d operator+ (const Point3d & p1, const Vec3d & v); Point3d & Add (double d, const Vec3d & v); Point3d & Add2 (double d, const Vec3d & v, double d2, const Vec3d & v2); inline Point3d Center (const Point3d & p1, const Point3d & p2); inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3); inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4); ostream & operator<<(ostream & s, const Point3d & p); inline Vec3d operator- (const Vec3d & p1, const Vec3d & v); inline Vec3d operator+ (const Vec3d & p1, const Vec3d & v); inline Vec3d operator* (double scal, const Vec3d & v); inline double operator* (const Vec3d & v1, const Vec3d & v2); inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2); inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod); double Angle (const Vec3d & v); double FastAngle (const Vec3d & v); double Angle (const Vec3d & v1, const Vec3d & v2); double FastAngle (const Vec3d & v1, const Vec3d & v2); ostream & operator<<(ostream & s, const Vec3d & v); void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3); int SolveLinearSystem (const Vec3d & col1, const Vec3d & col2, const Vec3d & col3, const Vec3d & rhs, Vec3d & sol); int SolveLinearSystemLS (const Vec3d & col1, const Vec3d & col2, const Vec2d & rhs, Vec3d & sol); int SolveLinearSystemLS2 (const Vec3d & col1, const Vec3d & col2, const Vec2d & rhs, Vec3d & sol, double & x, double & y); int PseudoInverse (const Vec3d & col1, const Vec3d & col2, Vec3d & inv1, Vec3d & inv2); double Determinant (const Vec3d & col1, const Vec3d & col2, const Vec3d & col3); inline double Dist2 (const Point3d & p1, const Point3d & p2); /// Point in R3 class Point3d { protected: /// double x[3]; public: /// Point3d () { x[0] = x[1] = x[2] = 0; } /// Point3d(double ax, double ay, double az) { x[0] = ax; x[1] = ay; x[2] = az; } /// Point3d(double ax[3]) { x[0] = ax[0]; x[1] = ax[1]; x[2] = ax[2]; } /// Point3d(const Point3d & p2) { x[0] = p2.x[0]; x[1] = p2.x[1]; x[2] = p2.x[2]; } Point3d (const Point<3> & p2) { for (int i = 0; i < 3; i++) x[i] = p2(i); } /// Point3d & operator= (const Point3d & p2) { x[0] = p2.x[0]; x[1] = p2.x[1]; x[2] = p2.x[2]; return *this; } /// int operator== (const Point3d& p) const { return (x[0] == p.x[0] && x[1] == p.x[1] && x[2] == p.x[2]); } /// double & X() { return x[0]; } /// double & Y() { return x[1]; } /// double & Z() { return x[2]; } /// double X() const { return x[0]; } /// double Y() const { return x[1]; } /// double Z() const { return x[2]; } /// double & X(int i) { return x[i-1]; } /// double X(int i) const { return x[i-1]; } /// const Point3d & SetToMin (const Point3d & p2) { if (p2.x[0] < x[0]) x[0] = p2.x[0]; if (p2.x[1] < x[1]) x[1] = p2.x[1]; if (p2.x[2] < x[2]) x[2] = p2.x[2]; return *this; } /// const Point3d & SetToMax (const Point3d & p2) { if (p2.x[0] > x[0]) x[0] = p2.x[0]; if (p2.x[1] > x[1]) x[1] = p2.x[1]; if (p2.x[2] > x[2]) x[2] = p2.x[2]; return *this; } /// friend inline Vec3d operator- (const Point3d & p1, const Point3d & p2); /// friend inline Point3d operator- (const Point3d & p1, const Vec3d & v); /// friend inline Point3d operator+ (const Point3d & p1, const Vec3d & v); /// inline Point3d & operator+= (const Vec3d & v); inline Point3d & operator-= (const Vec3d & v); /// inline Point3d & Add (double d, const Vec3d & v); /// inline Point3d & Add2 (double d, const Vec3d & v, double d2, const Vec3d & v2); /// friend inline double Dist (const Point3d & p1, const Point3d & p2) { return sqrt ( (p1.x[0]-p2.x[0]) * (p1.x[0]-p2.x[0]) + (p1.x[1]-p2.x[1]) * (p1.x[1]-p2.x[1]) + (p1.x[2]-p2.x[2]) * (p1.x[2]-p2.x[2])); } /// inline friend double Dist2 (const Point3d & p1, const Point3d & p2) { return ( (p1.x[0]-p2.x[0]) * (p1.x[0]-p2.x[0]) + (p1.x[1]-p2.x[1]) * (p1.x[1]-p2.x[1]) + (p1.x[2]-p2.x[2]) * (p1.x[2]-p2.x[2])); } /// friend inline Point3d Center (const Point3d & p1, const Point3d & p2); /// friend inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3); /// friend inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4); /// friend ostream & operator<<(ostream & s, const Point3d & p); /// friend class Vec3d; /// friend class Box3d; operator Point<3> () const { return Point<3> (x[0], x[1], x[2]); } }; /// class Vec3d { protected: /// double x[3]; public: /// inline Vec3d() { x[0] = x[1] = x[2] = 0; } /// inline Vec3d(double ax, double ay, double az) { x[0] = ax; x[1] = ay; x[2] = az; } /// Vec3d(double ax[3]) { x[0] = ax[0]; x[1] = ax[1]; x[2] = ax[2]; } /// inline Vec3d(const Vec3d & v2) { x[0] = v2.x[0]; x[1] = v2.x[1]; x[2] = v2.x[2]; } /// inline Vec3d(const Point3d & p1, const Point3d & p2) { x[0] = p2.x[0] - p1.x[0]; x[1] = p2.x[1] - p1.x[1]; x[2] = p2.x[2] - p1.x[2]; } /// inline Vec3d(const Point3d & p1) { x[0] = p1.x[0]; x[1] = p1.x[1]; x[2] = p1.x[2]; } Vec3d (const Vec<3> & v2) { for (int i = 0; i < 3; i++) x[i] = v2(i); } operator Vec<3> () const { return Vec<3> (x[0], x[1], x[2]); } Vec3d & operator= (const Vec3d & v2) { x[0] = v2.x[0]; x[1] = v2.x[1]; x[2] = v2.x[2]; return *this; } /// Vec3d & operator= (double val) { x[0] = x[1] = x[2] = val; return *this; } /// double & X() { return x[0]; } /// double & Y() { return x[1]; } /// double & Z() { return x[2]; } /// double & X(int i) { return x[i-1]; } /// double X() const { return x[0]; } /// double Y() const { return x[1]; } /// double Z() const { return x[2]; } /// double X(int i) const { return x[i-1]; } /// double Length() const { return sqrt (x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); } /// double Length2() const { return x[0] * x[0] + x[1] * x[1] + x[2] * x[2]; } /// inline friend double Dist (const Vec3d & v1, const Vec3d & v2) { return sqrt ( (v1.x[0]-v2.x[0]) * (v1.x[0]-v2.x[0]) + (v1.x[1]-v2.x[1]) * (v1.x[1]-v2.x[1]) + (v1.x[2]-v2.x[2]) * (v1.x[2]-v2.x[2])); } /// inline friend double Dist2 (const Vec3d & v1, const Vec3d & v2) { return ( (v1.x[0]-v2.x[0]) * (v1.x[0]-v2.x[0]) + (v1.x[1]-v2.x[1]) * (v1.x[1]-v2.x[1]) + (v1.x[2]-v2.x[2]) * (v1.x[2]-v2.x[2])); } /// Vec3d & operator+= (const Vec3d & v2); /// Vec3d & operator-= (const Vec3d & v2); /// Vec3d & operator*= (double s); /// Vec3d & operator/= (double s); /// inline Vec3d & Add (double d, const Vec3d & v); /// inline Vec3d & Add2 (double d, const Vec3d & v, double d2, const Vec3d & v2); /// friend inline Vec3d operator- (const Point3d & p1, const Point3d & p2); /// friend inline Point3d operator- (const Point3d & p1, const Vec3d & v); /// friend inline Point3d operator+ (const Point3d & p1, const Vec3d & v); /// friend inline Vec3d operator- (const Vec3d & p1, const Vec3d & v); /// friend inline Vec3d operator+ (const Vec3d & p1, const Vec3d & v); /// friend inline Vec3d operator* (double scal, const Vec3d & v); /// friend inline double operator* (const Vec3d & v1, const Vec3d & v2); /// friend inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2); /// friend inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod); /// Returns one normal-vector to n void GetNormal (Vec3d & n) const; /// friend double Angle (const Vec3d & v); /// friend double FastAngle (const Vec3d & v); /// friend double Angle (const Vec3d & v1, const Vec3d & v2); /// friend double FastAngle (const Vec3d & v1, const Vec3d & v2); void Normalize() { double len = (x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); if (len == 0) return; len = sqrt (len); x[0] /= len; x[1] /= len; x[2] /= len; } /// friend ostream & operator<<(ostream & s, const Vec3d & v); /// friend class Point3d; friend void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3); friend int SolveLinearSystem (const Vec3d & col1, const Vec3d & col2, const Vec3d & col3, const Vec3d & rhs, Vec3d & sol); friend int SolveLinearSystemLS (const Vec3d & col1, const Vec3d & col2, const Vec2d & rhs, Vec3d & sol); friend int SolveLinearSystemLS2 (const Vec3d & col1, const Vec3d & col2, const Vec2d & rhs, Vec3d & sol, double & x, double & y); friend int PseudoInverse (const Vec3d & col1, const Vec3d & col2, Vec3d & inv1, Vec3d & inv2); friend double Determinant (const Vec3d & col1, const Vec3d & col2, const Vec3d & col3); }; class QuadraticFunction3d { double c0, cx, cy, cz; double cxx, cyy, czz, cxy, cxz, cyz; public: QuadraticFunction3d (const Point3d & p, const Vec3d & v); double Eval (const Point3d & p) { return c0 + p.X() * (cx + cxx * p.X() + cxy * p.Y() + cxz * p.Z()) + p.Y() * (cy + cyy * p.Y() + cyz * p.Z()) + p.Z() * (cz + czz * p.Z()); } }; inline Point3d Center (const Point3d & p1, const Point3d & p2) { return Point3d (0.5 * (p1.x[0] + p2.x[0]), 0.5 * (p1.x[1] + p2.x[1]), 0.5 * (p1.x[2] + p2.x[2])); } inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3) { return Point3d (1.0/3.0 * (p1.x[0] + p2.x[0] + p3.x[0]), 1.0/3.0 * (p1.x[1] + p2.x[1] + p3.x[1]), 1.0/3.0 * (p1.x[2] + p2.x[2] + p3.x[2])); } inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4) { return Point3d (0.25 * (p1.x[0] + p2.x[0] + p3.x[0] + p4.x[0]), 0.25 * (p1.x[1] + p2.x[1] + p3.x[1] + p4.x[1]), 0.25 * (p1.x[2] + p2.x[2] + p3.x[2] + p4.x[2])); } inline Vec3d & Vec3d :: operator+= (const Vec3d & v2) { x[0] += v2.x[0]; x[1] += v2.x[1]; x[2] += v2.x[2]; return *this; } inline Vec3d & Vec3d :: operator-= (const Vec3d & v2) { x[0] -= v2.x[0]; x[1] -= v2.x[1]; x[2] -= v2.x[2]; return *this; } inline Vec3d & Vec3d :: operator*= (double s) { x[0] *= s; x[1] *= s; x[2] *= s; return *this; } inline Vec3d & Vec3d :: operator/= (double s) { if (s != 0) { x[0] /= s; x[1] /= s; x[2] /= s; } #ifdef DEBUG else { cerr << "Vec div by 0, v = " << (*this) << endl; // MyError ("Vec3d::operator /=: Divisioin by zero"); } #endif return *this; } inline Vec3d & Vec3d::Add (double d, const Vec3d & v) { x[0] += d * v.x[0]; x[1] += d * v.x[1]; x[2] += d * v.x[2]; return *this; } inline Vec3d & Vec3d::Add2 (double d, const Vec3d & v, double d2, const Vec3d & v2) { x[0] += d * v.x[0] + d2 * v2.x[0]; x[1] += d * v.x[1] + d2 * v2.x[1]; x[2] += d * v.x[2] + d2 * v2.x[2]; return *this; } inline Vec3d operator- (const Point3d & p1, const Point3d & p2) { return Vec3d (p1.x[0] - p2.x[0], p1.x[1] - p2.x[1],p1.x[2] - p2.x[2]); } inline Point3d operator- (const Point3d & p1, const Vec3d & v) { return Point3d (p1.x[0] - v.x[0], p1.x[1] - v.x[1],p1.x[2] - v.x[2]); } inline Point3d operator+ (const Point3d & p1, const Vec3d & v) { return Point3d (p1.x[0] + v.x[0], p1.x[1] + v.x[1],p1.x[2] + v.x[2]); } inline Point3d & Point3d::operator+= (const Vec3d & v) { x[0] += v.x[0]; x[1] += v.x[1]; x[2] += v.x[2]; return *this; } inline Point3d & Point3d::operator-= (const Vec3d & v) { x[0] -= v.x[0]; x[1] -= v.x[1]; x[2] -= v.x[2]; return *this; } inline Point3d & Point3d::Add (double d, const Vec3d & v) { x[0] += d * v.x[0]; x[1] += d * v.x[1]; x[2] += d * v.x[2]; return *this; } inline Point3d & Point3d::Add2 (double d, const Vec3d & v, double d2, const Vec3d & v2) { x[0] += d * v.x[0] + d2 * v2.x[0]; x[1] += d * v.x[1] + d2 * v2.x[1]; x[2] += d * v.x[2] + d2 * v2.x[2]; return *this; } inline Vec3d operator- (const Vec3d & v1, const Vec3d & v2) { return Vec3d (v1.x[0] - v2.x[0], v1.x[1] - v2.x[1],v1.x[2] - v2.x[2]); } inline Vec3d operator+ (const Vec3d & v1, const Vec3d & v2) { return Vec3d (v1.x[0] + v2.x[0], v1.x[1] + v2.x[1],v1.x[2] + v2.x[2]); } inline Vec3d operator* (double scal, const Vec3d & v) { return Vec3d (scal * v.x[0], scal * v.x[1], scal * v.x[2]); } inline double operator* (const Vec3d & v1, const Vec3d & v2) { return v1.x[0] * v2.x[0] + v1.x[1] * v2.x[1] + v1.x[2] * v2.x[2]; } inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2) { return Vec3d ( v1.x[1] * v2.x[2] - v1.x[2] * v2.x[1], v1.x[2] * v2.x[0] - v1.x[0] * v2.x[2], v1.x[0] * v2.x[1] - v1.x[1] * v2.x[0]); } inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod) { prod.x[0] = v1.x[1] * v2.x[2] - v1.x[2] * v2.x[1]; prod.x[1] = v1.x[2] * v2.x[0] - v1.x[0] * v2.x[2]; prod.x[2] = v1.x[0] * v2.x[1] - v1.x[1] * v2.x[0]; } inline double Determinant (const Vec3d & col1, const Vec3d & col2, const Vec3d & col3) { return col1.x[0] * ( col2.x[1] * col3.x[2] - col2.x[2] * col3.x[1]) + col1.x[1] * ( col2.x[2] * col3.x[0] - col2.x[0] * col3.x[2]) + col1.x[2] * ( col2.x[0] * col3.x[1] - col2.x[1] * col3.x[0]); } /// class Box3d { protected: /// double minx[3], maxx[3]; public: /// Box3d () { }; /// Box3d ( double aminx, double amaxx, double aminy, double amaxy, double aminz, double amaxz ); /// Box3d ( const Box3d & b2 ); /// Box3d (const Point3d& p1, const Point3d& p2); /// Box3d (const Box<3> & b2); /// double MinX () const { return minx[0]; } /// double MaxX () const { return maxx[0]; } /// double MinY () const { return minx[1]; } /// double MaxY () const { return maxx[1]; } /// double MinZ () const { return minx[2]; } /// double MaxZ () const { return maxx[2]; } /// double Mini (int i) const { return minx[i-1]; } /// double Maxi (int i) const { return maxx[i-1]; } /// Point3d PMin () const { return Point3d(minx[0], minx[1], minx[2]); } /// Point3d PMax () const { return Point3d(maxx[0], maxx[1], maxx[2]); } /// void GetPointNr (int i, Point3d & point) const; /// increase Box at each side with dist void Increase (double dist); /// increase Box by factor rel void IncreaseRel (double rel); /// return 1 if closures are intersecting int Intersect (const Box3d & box2) const { if (minx[0] > box2.maxx[0] || maxx[0] < box2.minx[0] || minx[1] > box2.maxx[1] || maxx[1] < box2.minx[1] || minx[2] > box2.maxx[2] || maxx[2] < box2.minx[2]) return 0; return 1; } /// return 1 if point p in closure int IsIn (const Point3d & p) const { if (minx[0] <= p.x[0] && maxx[0] >= p.x[0] && minx[1] <= p.x[1] && maxx[1] >= p.x[1] && minx[2] <= p.x[2] && maxx[2] >= p.x[2]) return 1; return 0; } /// inline void SetPoint (const Point3d & p) { minx[0] = maxx[0] = p.X(); minx[1] = maxx[1] = p.Y(); minx[2] = maxx[2] = p.Z(); } /// inline void AddPoint (const Point3d & p) { if (p.x[0] < minx[0]) minx[0] = p.x[0]; if (p.x[0] > maxx[0]) maxx[0] = p.x[0]; if (p.x[1] < minx[1]) minx[1] = p.x[1]; if (p.x[1] > maxx[1]) maxx[1] = p.x[1]; if (p.x[2] < minx[2]) minx[2] = p.x[2]; if (p.x[2] > maxx[2]) maxx[2] = p.x[2]; } /// const Box3d& operator+=(const Box3d& b); /// Point3d MaxCoords() const; /// Point3d MinCoords() const; /// Make a negative sized box; // void CreateNegMinMaxBox(); /// Point3d CalcCenter () const { return Point3d(0.5*(minx[0] + maxx[0]), 0.5*(minx[1] + maxx[1]), 0.5*(minx[2] + maxx[2])); } /// double CalcDiam () const { return sqrt(sqr(maxx[0]-minx[0])+ sqr(maxx[1]-minx[1])+ sqr(maxx[2]-minx[2])); } /// void WriteData(ofstream& fout) const; /// void ReadData(ifstream& fin); }; class Box3dSphere : public Box3d { protected: /// double diam, inner; /// Point3d c; public: /// Box3dSphere () { }; /// Box3dSphere ( double aminx, double amaxx, double aminy, double amaxy, double aminz, double amaxz); /// const Point3d & Center () const { return c; } /// double Diam () const { return diam; } /// double Inner () const { return inner; } /// void GetSubBox (int i, Box3dSphere & sbox) const; // private: /// void CalcDiamCenter (); }; /// class referencetransform { /// Vec3d ex, ey, ez; /// Vec3d exh, eyh, ezh; /// Vec3d ex_h, ey_h, ez_h; /// Point3d rp; /// double h; public: /// void Set (const Point3d & p1, const Point3d & p2, const Point3d & p3, double ah); /// void ToPlain (const Point3d & p, Point3d & pp) const; /// void ToPlain (const Array & p, Array & pp) const; /// void FromPlain (const Point3d & pp, Point3d & p) const; }; } #endif netgen-6.2.1905/libsrc/gprim/spline.cpp0000644000175000017500000003047113504650527016400 0ustar kurtkurt/* Spline curve for Mesh generator */ #include #include #include #include "spline.hpp" namespace netgen { // just for testing (JS) template void ProjectTrivial (const SplineSeg3 & seg, const Point point, Point & point_on_curve, double & t) { double mindist = -1; for (int i = 0; i <= 1000; i++) { double ht = double(i)/1000; Point p = seg.GetPoint(ht); double dist = Dist2 (p, point); if (i == 0 || dist < mindist) { mindist = dist; t = ht; } } point_on_curve = seg.GetPoint(t); } template <> void CircleSeg<3> :: LineIntersections (const double a, const double b, const double c, Array < Point<3> > & points, const double eps) const { cerr << "CircleSeg<3>::LineIntersections not implemented" << endl; } template <> void CircleSeg<2> :: LineIntersections (const double a, const double b, const double c, Array < Point<2> > & points, const double eps) const { points.SetSize(0); double px=0,py=0; if(fabs(b) > 1e-20) py = -c/b; else px = -c/a; const double c1 = a*a + b*b; const double c2 = 2. * ( a*(py-pm(1)) - b*(px-pm(0))); const double c3 = pow(px-pm(0),2) + pow(py-pm(1),2) - pow(Radius(),2); const double discr = c2*c2 - 4*c1*c3; if(discr < 0) return; Array t; if(fabs(discr) < 1e-20) t.Append(-0.5*c2/c1); else { t.Append((-c2+sqrt(discr))/(2.*c1)); t.Append((-c2-sqrt(discr))/(2.*c1)); } for(int i=0; i p (px-t[i]*b,py+t[i]*a); double angle = atan2(p(1),p(0))+M_PI; if(angle > StartAngle()-eps && angle < EndAngle()+eps) points.Append(p); } } template SplineSeg3 :: SplineSeg3 (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3) : p1(ap1), p2(ap2), p3(ap3) { weight = Dist (p1, p3) / sqrt (0.5 * (Dist2 (p1, p2) + Dist2 (p2, p3))); // weight = sqrt(2); // cout << "weight = " << weight << endl; proj_latest_t = 0.5; } template Point SplineSeg3 :: GetPoint (double t) const { double b1, b2, b3; b1 = (1-t)*(1-t); b2 = weight * t * (1-t); b3 = t * t; Vec hp = b1 * Vec(p1) + b2 * Vec(p2) + b3 * Vec(p3); double w = b1+b2+b3; return Point ((1.0/w)*hp); /* double x, y, w; x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3; y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3; w = b1 + b2 + b3; if(D==3) { double z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3; return Point (x/w, y/w, z/w); } else return Point (x/w, y/w); */ } template Vec SplineSeg3 :: GetTangent (const double t) const { const double b1 = (1.-t)*((weight-2.)*t-weight); const double b2 = weight*(1.-2.*t); const double b3 = t*((weight-2)*t+2.); Vec retval; for(int i=0; i void SplineSeg3 :: GetCoeff (Vector & u) const { DenseMatrix a(6, 6); DenseMatrix ata(6, 6); Vector f(6); u.SetSize(6); // ata.SetSymmetric(1); double t = 0; for (int i = 0; i < 5; i++, t += 0.25) { Point p = GetPoint (t); a(i, 0) = p(0) * p(0); a(i, 1) = p(1) * p(1); a(i, 2) = p(0) * p(1); a(i, 3) = p(0); a(i, 4) = p(1); a(i, 5) = 1; } a(5, 0) = 1; CalcAtA (a, ata); u = 0; u(5) = 1; a.MultTrans (u, f); ata.Solve (f, u); // the sign Point p0 = GetPoint(0); Vec ht = GetTangent(0); Vec<2> tang(ht(0), ht(1)); double gradx = 2.*u(0)*p0(0) + u(2)*p0(1) + u(3); double grady = 2.*u(1)*p0(1) + u(2)*p0(0) + u(4); Vec<2> gradn (grady, -gradx); if (tang * gradn < 0) u *= -1; } template void SplineSeg3 :: GetCoeff (Vector & u, Point pref) const { DenseMatrix a(6, 6); DenseMatrix ata(6, 6); Vector f(6); u.SetSize(6); // ata.SetSymmetric(1); double t = 0; for (int i = 0; i < 5; i++, t += 0.25) { Vec p = GetPoint (t)-pref; a(i, 0) = p(0) * p(0); a(i, 1) = p(1) * p(1); a(i, 2) = p(0) * p(1); a(i, 3) = p(0); a(i, 4) = p(1); a(i, 5) = 1; } a(5, 0) = 1; CalcAtA (a, ata); u = 0; u(5) = 1; a.MultTrans (u, f); ata.Solve (f, u); // the sign // Point p0 = GetPoint(0); Vec ht = GetTangent(0); Vec<2> tang(ht(0), ht(1)); double gradx = u(3); double grady = u(4); // double gradx = 2.*u(0)*p0(0) + u(2)*p0(1) + u(3); // double grady = 2.*u(1)*p0(1) + u(2)*p0(0) + u(4); Vec<2> gradn (grady, -gradx); if (tang * gradn < 0) u *= -1; } template void SplineSeg3 :: Project (const Point point, Point & point_on_curve, double & t) const { double t_old = -1; /* if(proj_latest_t > 0. && proj_latest_t < 1.) t = proj_latest_t; else t = 0.5; */ double tmin = 1; double dist_min2 = Dist2 (GetPoint(tmin), point); for (double ti = 0; ti < 0.99; ti += 0.25) { double di = Dist2(GetPoint(ti), point); if (di < dist_min2) { tmin = ti; dist_min2 = di; } } t = tmin; Point phi; Vec phip,phipp,phimp; int i=0; while(t > -0.5 && t < 1.5 && i<20 && fabs(t-t_old) > 1e-15 ) { GetDerivatives(t,phi,phip,phipp); t_old = t; phimp = phi-point; //t = min2(max2(t-(phip*phimp)/(phipp*phimp + phip*phip),0.),1.); t -= (phip*phimp)/(phipp*phimp + phip*phip); i++; } //if(i<10 && t > 0. && t < 1.) if(i<20 && t > -0.4 && t < 1.4) { if(t < 0) { t = 0.; } if(t > 1) { t = 1.; } point_on_curve = SplineSeg3::GetPoint(t); double dist = Dist(point,point_on_curve); phi = SplineSeg3 ::GetPoint(0); double auxdist = Dist(phi,point); if(auxdist < dist) { t = 0.; point_on_curve = phi; dist = auxdist; } phi = SplineSeg3 ::GetPoint(1); auxdist = Dist(phi,point); if(auxdist < dist) { t = 1.; point_on_curve = phi; dist = auxdist; } } else { double t0 = 0; double t1 = 0.5; double t2 = 1.; double d0,d1,d2; //(*testout) << "newtonersatz" << endl; while(t2-t0 > 1e-8) { phi = SplineSeg3 ::GetPoint(t0); d0 = Dist(phi,point); phi = SplineSeg3 ::GetPoint(t1); d1 = Dist(phi,point); phi = SplineSeg3 ::GetPoint(t2); d2 = Dist(phi,point); double a = (2.*d0 - 4.*d1 +2.*d2)/pow(t2-t0,2); if(a <= 0) { if(d0 < d2) t2 -= 0.3*(t2-t0); else t0 += 0.3*(t2-t0); t1 = 0.5*(t2+t0); } else { double b = (d1-d0-a*(t1*t1-t0*t0))/(t1-t0); double auxt1 = -0.5*b/a; if(auxt1 < t0) { t2 -= 0.4*(t2-t0); t0 = max2(0.,t0-0.1*(t2-t0)); } else if (auxt1 > t2) { t0 += 0.4*(t2-t0); t2 = min2(1.,t2+0.1*(t2-t0)); } else { t1 = auxt1; auxt1 = 0.25*(t2-t0); t0 = max2(0.,t1-auxt1); t2 = min2(1.,t1+auxt1); } t1 = 0.5*(t2+t0); } } phi = SplineSeg3 ::GetPoint(t0); d0 = Dist(phi,point); phi = SplineSeg3 ::GetPoint(t1); d1 = Dist(phi,point); phi = SplineSeg3 ::GetPoint(t2); d2 = Dist(phi,point); double mind = d0; t = t0; if(d1 < mind) { t = t1; mind = d1; } if(d2 < mind) { t = t2; mind = d2; } point_on_curve = SplineSeg3 ::GetPoint(t); } //(*testout) << " latest_t " << proj_latest_t << " t " << t << endl; proj_latest_t = t; /* // test it by trivial sampling double ht; Point hp; ProjectTrivial (*this, point, hp, ht); if (fabs (t-ht) > 1e-3) { // if (Dist2 (point, hp) < Dist2 (point, point_on_curve)) cout << "project is wrong" << endl; cout << "t = " << t << ", ht = " << ht << endl; cout << "dist org = " << Dist(point, point_on_curve) << endl; cout << "dist trivial = " << Dist(point, hp) << endl; } */ } template void SplineSeg3 :: GetDerivatives (const double t, Point & point, Vec & first, Vec & second) const { Vec v1(p1), v2(p2), v3(p3); double b1 = (1.-t)*(1.-t); double b2 = weight*t*(1.-t); double b3 = t*t; double w = b1+b2+b3; b1 *= 1./w; b2 *= 1./w; b3 *= 1./w; double b1p = 2.*(t-1.); double b2p = weight*(1.-2.*t); double b3p = 2.*t; const double wp = b1p+b2p+b3p; const double fac1 = wp/w; b1p *= 1./w; b2p *= 1./w; b3p *= 1./w; const double b1pp = 2.; const double b2pp = -2.*weight; const double b3pp = 2.; const double wpp = b1pp+b2pp+b3pp; const double fac2 = (wpp*w-2.*wp*wp)/(w*w); for(int i=0; i double SplineSeg3<2> :: MaxCurvature(void) const { Vec<2> v1 = p1-p2; Vec<2> v2 = p3-p2; double l1 = v1.Length(); double l2 = v2.Length(); double cosalpha = (v1*v2)/(l1*l2); return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha)); } template<> double SplineSeg3<3> :: MaxCurvature(void) const { Vec<3> v1 = p1-p2; Vec<3> v2 = p3-p2; double l1 = v1.Length(); double l2 = v2.Length(); double cosalpha = v1*v2/(l1*l2); return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha)); } template void SplineSeg3 :: LineIntersections (const double a, const double b, const double c, Array < Point > & points, const double eps) const { points.SetSize(0); double t; const double c1 = a*p1(0) - weight*a*p2(0) + a*p3(0) + b*p1(1) - weight*b*p2(1) + b*p3(1) + (2.-weight)*c; const double c2 = -2.*a*p1(0) + weight*a*p2(0) -2.*b*p1(1) + weight*b*p2(1) + (weight-2.)*c; const double c3 = a*p1(0) + b*p1(1) + c; if(fabs(c1) < 1e-20) { if(fabs(c2) < 1e-20) return; t = -c3/c2; if((t > -eps) && (t < 1.+eps)) points.Append(GetPoint(t)); return; } const double discr = c2*c2-4.*c1*c3; if(discr < 0) return; if(fabs(discr/(c1*c1)) < 1e-14) { t = -0.5*c2/c1; if((t > -eps) && (t < 1.+eps)) points.Append(GetPoint(t)); return; } t = (-c2 + sqrt(discr))/(2.*c1); if((t > -eps) && (t < 1.+eps)) points.Append(GetPoint(t)); t = (-c2 - sqrt(discr))/(2.*c1); if((t > -eps) && (t < 1.+eps)) points.Append(GetPoint(t)); } template < int D > void SplineSeg3 :: GetRawData (Array & data) const { data.Append(3); for(int i=0; i; template class SplineSeg3<3>; RegisterClassForArchive> regss2; RegisterClassForArchive> regss3; RegisterClassForArchive, SplineSeg<2>> regls2; RegisterClassForArchive, SplineSeg<3>> regls3; RegisterClassForArchive, SplineSeg<2>> regsss2; RegisterClassForArchive, SplineSeg<3>> regsss3; } netgen-6.2.1905/libsrc/gprim/geomfuncs.hpp0000644000175000017500000000737313504650527017106 0ustar kurtkurt#ifndef FILE_GEOMFUNCS #define FILE_GEOMFUNCS /* *************************************************************************/ /* File: geomfuncs.hpp */ /* Author: Joachim Schoeberl */ /* Date: 20. Jul. 02 */ /* *************************************************************************/ namespace netgen { template inline double Abs (const Vec & v) { double sum = 0; for (int i = 0; i < D; i++) sum += v(i) * v(i); return sqrt (sum); } template inline double Abs2 (const Vec & v) { double sum = 0; for (int i = 0; i < D; i++) sum += v(i) * v(i); return sum; } template inline double Dist (const Point & a, const Point & b) { return Abs (a-b); } template inline double Dist2 (const Point & a, const Point & b) { return Abs2 (a-b); } template inline Point Center (const Point & a, const Point & b) { Point res; for (int i = 0; i < D; i++) res(i) = 0.5 * (a(i) + b(i)); return res; } template inline Point Center (const Point & a, const Point & b, const Point & c) { Point res; for (int i = 0; i < D; i++) res(i) = (1.0/3.0) * (a(i) + b(i) + c(i)); return res; } template inline Point Center (const Point & a, const Point & b, const Point & c, const Point & d) { Point res; for (int i = 0; i < D; i++) res(i) = (1.0/4.0) * (a(i) + b(i) + c(i) + d(i)); return res; } /* new wrong code problem with MSVC2010: using Cross ( & , & ) computes wrong cross-product, problem arises in Surface::DefineTangentialPlane, e.g. with example boxcyl.geo */ // inline Vec<3> Cross (const Vec<3> & v1, const Vec<3> & v2) template inline Vec<3,T> Cross (Vec<3,T> v1, Vec<3,T> v2) { return Vec<3,T> ( v1(1) * v2(2) - v1(2) * v2(1), v1(2) * v2(0) - v1(0) * v2(2), v1(0) * v2(1) - v1(1) * v2(0) ); } inline double Determinant (const Vec<3> & col1, const Vec<3> & col2, const Vec<3> & col3) { return col1(0) * ( col2(1) * col3(2) - col2(2) * col3(1)) + col1(1) * ( col2(2) * col3(0) - col2(0) * col3(2)) + col1(2) * ( col2(0) * col3(1) - col2(1) * col3(0)); } template <> inline Vec<2> Vec<2> :: GetNormal () const { return Vec<2> (-x[1], x[0]); } template <> inline Vec<3> Vec<3> :: GetNormal () const { if (fabs (x[0]) > fabs (x[2])) return Vec<3> (-x[1], x[0], 0); else return Vec<3> (0, x[2], -x[1]); } // template inline void CalcInverse (const Mat<2,2> & m, Mat<2,2> & inv) { double det = m(0,0) * m(1,1) - m(0,1) * m(1,0); if (det == 0) { inv = 0; return; } double idet = 1.0 / det; inv(0,0) = idet * m(1,1); inv(0,1) = -idet * m(0,1); inv(1,0) = -idet * m(1,0); inv(1,1) = idet * m(0,0); } void CalcInverse (const Mat<3,3> & m, Mat<3,3> & inv); inline void CalcInverse (const Mat<2,3> & m, Mat<3,2> & inv) { Mat<2,2> a = m * Trans (m); Mat<2,2> ainv; CalcInverse (a, ainv); inv = Trans (m) * ainv; } void CalcInverse (const Mat<3,2> & m, Mat<2,3> & inv); inline void CalcInverse (const Mat<3,2> & m, Mat<2,3> & inv) { Mat<2,2> a = Trans (m) * m; Mat<2,2> ainv; CalcInverse (a, ainv); inv = ainv * Trans (m); } double Det (const Mat<2,2> & m); double Det (const Mat<3,3> & m); // eigenvalues of a symmetric matrix void EigenValues (const Mat<3,3> & m, Vec<3> & ev); void EigenValues (const Mat<2,2> & m, Vec<3> & ev); } #endif netgen-6.2.1905/libsrc/gprim/adtree.hpp0000644000175000017500000002475613504650527016370 0ustar kurtkurt#ifndef FILE_ADTREE #define FILE_ADTREE /* *************************************************************************/ /* File: adtree.hh */ /* Author: Joachim Schoeberl */ /* Date: 16. Feb. 98 */ /* Redesigned by Wolfram Muehlhuber, May 1998 */ /* *************************************************************************/ namespace netgen { /** Alternating Digital Tree */ // #include "../include/mystdlib.h" // #include "../include/myadt.hpp" class ADTreeNode { public: ADTreeNode *left, *right, *father; int dim; float sep; float *data; float *boxmin; float *boxmax; int pi; int nchilds; ADTreeNode (int adim); ~ADTreeNode (); friend class ADTree; }; class ADTreeCriterion { public: ADTreeCriterion() { } virtual int Eval (const ADTreeNode * node) const = 0; }; class ADTree { int dim; ADTreeNode * root; float *cmin, *cmax; Array ela; const ADTreeCriterion * criterion; Array stack; Array stackdir; int stackindex; public: ADTree (int adim, const float * acmin, const float * acmax); ~ADTree (); void Insert (const float * p, int pi); // void GetIntersecting (const float * bmin, const float * bmax, // Array & pis) const; void SetCriterion (ADTreeCriterion & acriterion); void Reset (); int Next (); void GetMatch (Array & matches); void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } void PrintRec (ostream & ost, const ADTreeNode * node) const; }; class ADTreeNode3 { public: ADTreeNode3 *left, *right, *father; float sep; float data[3]; int pi; int nchilds; ADTreeNode3 (); void DeleteChilds (); friend class ADTree3; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; class ADTree3 { ADTreeNode3 * root; float cmin[3], cmax[3]; Array ela; public: ADTree3 (const float * acmin, const float * acmax); ~ADTree3 (); void Insert (const float * p, int pi); void GetIntersecting (const float * bmin, const float * bmax, Array & pis) const; void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } void PrintRec (ostream & ost, const ADTreeNode3 * node) const; }; /* // divide each direction #define ADTN_DIV 10 class ADTreeNode3Div { public: ADTreeNode3Div *father; ADTreeNode3Div *childs[ADTN_DIV]; float minx, dist; float data[3]; int pi; int nchilds; ADTreeNode3Div (); void DeleteChilds (); friend class ADTree3Div; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; class ADTree3Div { ADTreeNode3Div * root; float cmin[3], cmax[3]; Array ela; public: ADTree3Div (const float * acmin, const float * acmax); ~ADTree3Div (); void Insert (const float * p, int pi); void GetIntersecting (const float * bmin, const float * bmax, Array & pis) const; void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } void PrintRec (ostream & ost, const ADTreeNode3Div * node) const; }; #define ADTN_SIZE 10 // multiple entries class ADTreeNode3M { public: ADTreeNode3M *left, *right, *father; float sep; float data[ADTN_SIZE][3]; int pi[ADTN_SIZE]; int nchilds; ADTreeNode3M (); void DeleteChilds (); friend class ADTree3M; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; class ADTree3M { ADTreeNode3M * root; float cmin[3], cmax[3]; Array ela; public: ADTree3M (const float * acmin, const float * acmax); ~ADTree3M (); void Insert (const float * p, int pi); void GetIntersecting (const float * bmin, const float * bmax, Array & pis) const; void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } void PrintRec (ostream & ost, const ADTreeNode3M * node) const; }; class ADTreeNode3F { public: ADTreeNode3F *father; ADTreeNode3F *childs[8]; float sep[3]; float data[3]; int pi; int nchilds; ADTreeNode3F (); void DeleteChilds (); friend class ADTree3F; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; // fat tree class ADTree3F { ADTreeNode3F * root; float cmin[3], cmax[3]; Array ela; public: ADTree3F (const float * acmin, const float * acmax); ~ADTree3F (); void Insert (const float * p, int pi); void GetIntersecting (const float * bmin, const float * bmax, Array & pis) const; void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } void PrintRec (ostream & ost, const ADTreeNode3F * node) const; }; class ADTreeNode3FM { public: ADTreeNode3FM *father; ADTreeNode3FM *childs[8]; float sep[3]; float data[ADTN_SIZE][3]; int pi[ADTN_SIZE]; int nchilds; ADTreeNode3FM (); void DeleteChilds (); friend class ADTree3FM; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; // fat tree class ADTree3FM { ADTreeNode3FM * root; float cmin[3], cmax[3]; Array ela; public: ADTree3FM (const float * acmin, const float * acmax); ~ADTree3FM (); void Insert (const float * p, int pi); void GetIntersecting (const float * bmin, const float * bmax, Array & pis) const; void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } void PrintRec (ostream & ost, const ADTreeNode3FM * node) const; }; */ class ADTreeNode6 { public: ADTreeNode6 *left, *right, *father; float sep; float data[6]; int pi; int nchilds; ADTreeNode6 (); void DeleteChilds (); friend class ADTree6; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; class ADTree6 { ADTreeNode6 * root; float cmin[6], cmax[6]; Array ela; public: ADTree6 (const float * acmin, const float * acmax); ~ADTree6 (); void Insert (const float * p, int pi); void GetIntersecting (const float * bmin, const float * bmax, Array & pis) const; void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } int Depth () const { return DepthRec (root); } int Elements () const { return ElementsRec (root); } void PrintRec (ostream & ost, const ADTreeNode6 * node) const; int DepthRec (const ADTreeNode6 * node) const; int ElementsRec (const ADTreeNode6 * node) const; void PrintMemInfo (ostream & ost) const; }; template class T_ADTreeNode { public: T_ADTreeNode *left, *right, *father; float sep; // float data[DIM]; Point data; T pi; int nchilds; T_ADTreeNode () { // pi = -1; SetInvalid(pi); left = NULL; right = NULL; father = NULL; nchilds = 0; } void DeleteChilds () { if (left) { left->DeleteChilds(); delete left; left = NULL; } if (right) { right->DeleteChilds(); delete right; right = NULL; } } // friend class T_ADTree; static BlockAllocator ball; void * operator new(size_t) { return ball.Alloc(); } void operator delete (void * p) { ball.Free(p); } }; template class T_ADTree { T_ADTreeNode * root; // float cmin[dim], cmax[dim]; Point cmin, cmax; // Array*> ela; ClosedHashTable*> ela; public: T_ADTree (Point acmin, Point acmax); ~T_ADTree (); void Insert (Point p, T pi); void GetIntersecting (Point bmin, Point bmax, Array & pis) const; void DeleteElement (T pi); void Print (ostream & ost) const { PrintRec (ost, root); } int Depth () const { return DepthRec (root); } int Elements () const { return ElementsRec (root); } void PrintRec (ostream & ost, const T_ADTreeNode * node) const; int DepthRec (const T_ADTreeNode * node) const; int ElementsRec (const T_ADTreeNode * node) const; void PrintMemInfo (ostream & ost) const; }; /* class ADTreeNode6F { public: ADTreeNode6F * father; ADTreeNode6F * childs[64]; float sep[6]; float data[6]; int pi; int nchilds; ADTreeNode6F (); void DeleteChilds (); friend class ADTree6F; static BlockAllocator ball; void * operator new(size_t); void operator delete (void *); }; class ADTree6F { ADTreeNode6F * root; float cmin[6], cmax[6]; Array ela; public: ADTree6F (const float * acmin, const float * acmax); ~ADTree6F (); void Insert (const float * p, int pi); void GetIntersecting (const float * bmin, const float * bmax, Array & pis) const; void DeleteElement (int pi); void Print (ostream & ost) const { PrintRec (ost, root); } int Depth () const { return DepthRec (root); } void PrintRec (ostream & ost, const ADTreeNode6F * node) const; int DepthRec (const ADTreeNode6F * node) const; }; */ class Point3dTree { ADTree3 * tree; public: DLL_HEADER Point3dTree (const Point<3> & pmin, const Point<3> & pmax); DLL_HEADER ~Point3dTree (); DLL_HEADER void Insert (const Point<3> & p, int pi); void DeleteElement (int pi) { tree->DeleteElement(pi); } DLL_HEADER void GetIntersecting (const Point<3> & pmin, const Point<3> & pmax, Array & pis) const; const ADTree3 & Tree() const { return *tree; }; }; template class BoxTree { T_ADTree<2*dim,T> * tree; Point boxpmin, boxpmax; public: BoxTree (const Box & abox); BoxTree (const Point & apmin, const Point & apmax); ~BoxTree (); void Insert (const Point & bmin, const Point & bmax, T pi); void Insert (const Box & box, T pi) { Insert (box.PMin(), box.PMax(), pi); } void DeleteElement (T pi) { tree->DeleteElement(pi); } void GetIntersecting (const Point & pmin, const Point & pmax, Array & pis) const; double Tolerance() const { return 1e-7 * Dist(boxpmax, boxpmin); } // single precision const auto & Tree() const { return *tree; }; auto & Tree() { return *tree; }; }; } #endif netgen-6.2.1905/libsrc/gprim/geom2d.cpp0000644000175000017500000002251213504650527016260 0ustar kurtkurt#include #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif namespace netgen { ostream & operator<<(ostream & s, const Point2d & p) { return s << "(" << p.px << ", " << p.py << ")"; } ostream & operator<<(ostream & s, const Vec2d & v) { return s << "(" << v.vx << ", " << v.vy << ")"; } #ifdef none ostream & operator<<(ostream & s, const Line2d & l) { return s << l.p1 << "-" << l.p2; } ostream & operator<<(ostream & s, const TRIANGLE2D & t) { return s << t.p1 << "-" << t.p2 << "-" << t.p3; } #endif double Fastatan2 (double x, double y) { if (y > 0) { if (x > 0) return y / (x+y); else return 1 - x / (y-x); } else if (y < 0) { if (x < 0) return 2 + y / (x+y); else return 3 - x / (y-x); } else { if (x >= 0) return 0; else return 2; } } double Angle (const Vec2d & v) { if (v.X() == 0 && v.Y() == 0) return 0; double ang = atan2 (v.Y(), v.X()); if (ang < 0) ang+= 2 * M_PI; return ang; } double FastAngle (const Vec2d & v) { return Fastatan2 (v.X(), v.Y()); } double Angle (const Vec2d & v1, const Vec2d & v2) { double ang = Angle(v2) - Angle(v1); if (ang < 0) ang += 2 * M_PI; return ang; } double FastAngle (const Vec2d & v1, const Vec2d & v2) { double ang = FastAngle(v2) - FastAngle(v1); if (ang < 0) ang += 4; return ang; } /* int CW (const Point2d & p1,const Point2d & p2,const Point2d & p3) { return Cross (p2 - p1, p3 - p2) < 0; } int CCW (const Point2d & p1,const Point2d & p2,const Point2d & p3) { return Cross (p2 - p1, p3 - p2) > 0; } */ double Dist2(const Line2d & g, const Line2d & h ) { double dd = 0.0, d1,d2,d3,d4; Point2d cp = CrossPoint(g,h); if ( Parallel(g,h) || !IsOnLine(g,cp) || !IsOnLine(h,cp) ) { d1 = Dist2(g.P1(),h.P1()); d2 = Dist2(g.P1(),h.P2()); d3 = Dist2(g.P2(),h.P1()); d4 = Dist2(g.P2(),h.P2()); if (d1= -heps * len2 && c2 <= heps * len2 && d <= heps * len2; } #ifdef none int IsOnLine (const PLine2d & l, const Point2d & p, double heps) { double c1 = (p - l.P1()) * l.Delta(); double c2 = (p - l.P2()) * l.Delta(); double d = fabs (Cross ( (p - l.P1()), l.Delta())); double len2 = l.Length2(); return c1 >= -heps * len2 && c2 <= heps * len2 && d <= heps * len2; } int IsOnLongLine (const Line2d & l, const Point2d & p) { double d = fabs (Cross ( (p - l.P1()), l.Delta())); return d <= EPSGEOM * l.Length(); } int Hit (const Line2d & l1, const Line2d & l2, double heps) { double den = Cross ( (l1.P2() - l1.P1()), (l2.P1() - l2.P2())); double num1 = Cross ( (l2.P1() - l1.P1()), (l2.P1() - l2.P2())); double num2 = Cross ( (l1.P2() - l1.P1()), (l2.P1() - l1.P1())); num1 *= sgn (den); num2 *= sgn (den); den = fabs (den); int ch = (-den * heps <= num1 && num1 <= den * (1 + heps) && -den * heps <= num2 && num2 <= den * (1 + heps)); return ch; } void Line2d :: GetNormal (Line2d & n) const { double ax = P2().X()-P1().X(), ay = P2().Y()-P1().Y(); Point2d mid(P1().X()+.5*ax, P1().Y()+.5*ay); n=Line2d(mid,Point2d(mid.X()+ay,mid.Y()-ax)) ; } Vec2d Line2d :: NormalDelta () const { Line2d tmp; GetNormal(tmp); return tmp.Delta(); } int TRIANGLE2D :: IsOn (const Point2d & p) const { return IsOnLine (Line2d (p1, p2), p) || IsOnLine (Line2d (p1, p3), p) || IsOnLine (Line2d (p2, p3), p); } int TRIANGLE2D :: IsIn (const Point2d & p) const { return ::CW(p, p1, p2) == ::CW(p, p2, p3) && ::CW(p, p1, p2) == ::CW(p, p3, p1); } int PTRIANGLE2D :: IsOn (const Point2d & p) const { return IsOnLine (Line2d (*p1, *p2), p) || IsOnLine (Line2d (*p1, *p3), p) || IsOnLine (Line2d (*p2, *p3), p); } int PTRIANGLE2D :: IsIn (const Point2d & p) const { return ::CW(p, *p1, *p2) == ::CW(p, *p2, *p3) && ::CW(p, *p1, *p2) == ::CW(p, *p3, *p1); } #endif Polygon2d :: Polygon2d () { ; } Polygon2d :: ~Polygon2d () { ; } void Polygon2d :: AddPoint (const Point2d & p) { points.Append(p); } double Polygon2d :: HArea () const { int i; double ar = 0; for (i = 1; i <= points.Size(); i++) { const Point2d & p1 = points.Get(i); const Point2d & p2 = points.Get(i%points.Size()+1); ar += (p2.X()-p1.X()) * p1.Y() - (p2.Y()-p1.Y()) * p1.X(); } return ar/2; /* CURSOR c; double ar = 0; Point2d * p1, * p2, p0 = Point2d(0, 0); Vec2d v1, v2 = Vec2d(1, 0); p2 = points[points.Last()]; for (c = points.First(); c != points.Head(); c++) { p1 = p2; p2 = points[c]; ar += Cross ( (*p2-*p1), (*p1 - p0)); } return ar / 2; */ } int Polygon2d :: IsOn (const Point2d & p) const { int i; for (i = 1; i <= points.Size(); i++) { const Point2d & p1 = points.Get(i); const Point2d & p2 = points.Get(i%points.Size()+1); if (IsOnLine (Line2d(p1, p2), p)) return 1; } return 0; /* CURSOR c; Point2d * p1, * p2; p2 = points[points.Last()]; for (c = points.First(); c != points.Head(); c++) { p1 = p2; p2 = points[c]; if (IsOnLine (Line2d(*p1, *p2), p)) return 1; } return 0; */ } int Polygon2d :: IsIn (const Point2d & p) const { int i; double sum = 0, ang; for (i = 1; i <= points.Size(); i++) { const Point2d & p1 = points.Get(i); const Point2d & p2 = points.Get(i%points.Size()+1); ang = Angle ( (p1 - p), (p2 - p) ); if (ang > M_PI) ang -= 2 * M_PI; sum += ang; } return fabs(sum) > M_PI; /* CURSOR c; Point2d * p1, * p2; double sum = 0, ang; p2 = points[points.Last()]; for (c = points.First(); c != points.Head(); c++) { p1 = p2; p2 = points[c]; ang = Angle ( (*p1 - p), (*p2 - p) ); if (ang > M_PI) ang -= 2 * M_PI; sum += ang; } return fabs(sum) > M_PI; */ } int Polygon2d :: IsConvex () const { /* Point2d *p, *pold, *pnew; char cw; CURSOR c; if (points.Length() < 3) return 0; c = points.Last(); p = points[c]; c--; pold = points[c]; pnew = points[points.First()]; cw = ::CW (*pold, *p, *pnew); for (c = points.First(); c != points.Head(); c++) { pnew = points[c]; if (cw != ::CW (*pold, *p, *pnew)) return 0; pold = p; p = pnew; } */ return 0; } int Polygon2d :: IsStarPoint (const Point2d & p) const { /* Point2d *pnew, *pold; char cw; CURSOR c; if (points.Length() < 3) return 0; pold = points[points.Last()]; pnew = points[points.First()]; cw = ::CW (p, *pold, *pnew); for (c = points.First(); c != points.Head(); c++) { pnew = points[c]; if (cw != ::CW (p, *pold, *pnew)) return 0; pold = pnew; } return 1; */ return 0; } Point2d Polygon2d :: Center () const { /* double ai, a = 0, x = 0, y = 0; Point2d * p, *p2; Point2d p0 = Point2d(0, 0); CURSOR c; p2 = points[points.Last()]; for (c = points.First(); c != points.Head(); c++) { p = points[c]; ai = Cross (*p2 - p0, *p - p0); x += ai / 3 * (p2->X() + p->X()); y += ai / 3 * (p2->Y() + p->Y()); a+= ai; p2 = p; } if (a != 0) return Point2d (x / a, y / a); else return Point2d (0, 0); */ return Point2d (0, 0); } Point2d Polygon2d :: EqualAreaPoint () const { /* double a11 = 0, a12 = 0, a21= 0, a22 = 0; double b1 = 0, b2 = 0, dx, dy; double det; Point2d * p, *p2; CURSOR c; p = points[points.Last()]; for (c = points.First(); c != points.Head(); c++) { p2 = p; p = points[c]; dx = p->X() - p2->X(); dy = p->Y() - p2->Y(); a11 += sqr (dy); a12 -= dx * dy; a21 -= dx * dy; a22 += sqr (dx); b1 -= dy * (p->X() * p2->Y() - p2->X() * p->Y()); b2 -= dx * (p->Y() * p2->X() - p2->Y() * p->X()); } det = a11 * a22 - a21 * a12; if (det != 0) return Point2d ( (b1 * a22 - b2 * a12) / det, (a11 * b2 - a21 * b1) / det); else return Point2d (0, 0); */ return Point2d (0, 0); } } netgen-6.2.1905/libsrc/gprim/geomtest3d.hpp0000644000175000017500000000565013504650527017172 0ustar kurtkurt#ifndef FILE_GEOMTEST3D #define FILE_GEOMTEST3D /* *************************************************************************/ /* File: geomtest3d.hh */ /* Author: Joachim Schoeberl */ /* Date: 13. Feb. 98 */ /* *************************************************************************/ namespace netgen { extern int IntersectTriangleLine (const Point<3> ** tri, const Point<3> ** line); /** Returns 0, iff closure (tet) cup closure (tri) is empty, one corner point of tet, one edge of tet or one face of tet */ extern int IntersectTetTriangle (const Point<3> ** tet, const Point<3> ** tri, const int * tetpi = NULL, const int * tripi = NULL); /** Same test as above, but tet int reference position (0, ex, ey, ez), tetpi = 1, 2, 4, 5 */ extern int IntersectTetTriangleRef (const Point3d ** tri, const int * tripi = NULL); // 1, iff not regular triangulation extern int IntersectTriangleTriangle (const Point<3> ** tri1, const Point<3> ** tri2); extern void LocalCoordinates (const Vec3d & e1, const Vec3d & e2, const Vec3d & v, double & lam1, double & lam2); /// return 1 = degenerated sphere extern int CalcSphereCenter (const Point<3> ** pts, Point<3> & c); /// return 1 = degenerated triangle extern int CalcTriangleCenter (const Point3d ** pts, Point3d & c); /* Compute radius of cylinder fitting 4 points. cylinder axis is in the direction of p1-p2 */ extern double ComputeCylinderRadius (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4); /* Two triangles T1 and T2 have normals n1 and n2. The height over the common edge is h1, and h2. Radius of cylinder fitting both triangles */ extern double ComputeCylinderRadius (const Vec3d & n1, const Vec3d & n2, double h1, double h2); /// Minimal distance of point p to the line segment [lp1,lp2] extern double MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p); /// Minimal distance of point p to the line segment [lp1,lp2] extern double MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p); /// Minimal distance of point p to the triangle segment [tp1,tp2,pt3] extern double MinDistTP2 (const Point3d & tp1, const Point3d & tp2, const Point3d & tp3, const Point3d & p); inline double MinDistTP2 (const Point<2> & tp1, const Point<2> & tp2, const Point<2> & tp3, const Point<2> & p) { return MinDistTP2 (Point<3> (tp1(0), tp1(1),0), Point<3> (tp2(0), tp2(1),0), Point<3> (tp3(0), tp3(1),0), Point<3> (p(0), p(1),0)); } /// Minimal distance of the 2 lines [l1p1,l1p2] and [l2p1,l2p2] extern double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2, const Point3d & l2p1, const Point3d & l2p2); } #endif netgen-6.2.1905/libsrc/gprim/geomops2.hpp0000644000175000017500000001602313504650527016643 0ustar kurtkurt#ifndef FILE_GEOMOPS #define FILE_GEOMOPS /* *************************************************************************/ /* File: geomops.hpp */ /* Author: Joachim Schoeberl */ /* Date: 20. Jul. 02 */ /* *************************************************************************/ /* Point - Vector operations */ template class SumExpr : public VecExpr > { const TA a; const TB b; public: SumExpr (const TA aa, const TB ab) : a(aa), b(ab) { ; } double operator() (int i) const { return a(i) + b(i); } }; template inline SumExpr operator+ (const VecExpr & a, const VecExpr & b) { return SumExpr (static_cast (a), static_cast (b)); } /* template inline SumExpr&, const Vec&> operator+ (const Vec & a, const Vec & b) { return SumExpr&, const Vec&> (a, b); } */ /* template inline Vec operator+ (const Vec & a, const Vec & b) { Vec res; for (int i = 0; i < D; i++) res(i) = a(i) + b(i); return res; } */ template inline Point operator+ (const Point & a, const Vec & b) { Point res; for (int i = 0; i < D; i++) res(i) = a(i) + b(i); return res; } template inline Vec operator- (const Point & a, const Point & b) { Vec res; for (int i = 0; i < D; i++) res(i) = a(i) - b(i); return res; } template inline Point operator- (const Point & a, const Vec & b) { Point res; for (int i = 0; i < D; i++) res(i) = a(i) - b(i); return res; } template inline Vec operator- (const Vec & a, const Vec & b) { Vec res; for (int i = 0; i < D; i++) res(i) = a(i) - b(i); return res; } template inline Vec operator* (double s, const Vec & b) { Vec res; for (int i = 0; i < D; i++) res(i) = s * b(i); return res; } template inline double operator* (const Vec & a, const Vec & b) { double sum = 0; for (int i = 0; i < D; i++) sum += a(i) * b(i); return sum; } template inline Vec operator- (const Vec & b) { Vec res; for (int i = 0; i < D; i++) res(i) = -b(i); return res; } template inline Point & operator+= (Point & a, const Vec & b) { for (int i = 0; i < D; i++) a(i) += b(i); return a; } template inline Point & operator+= (Point & a, const VecExpr & b) { for (int i = 0; i < D; i++) a(i) += b(i); return a; } template inline Vec & operator+= (Vec & a, const Vec & b) { for (int i = 0; i < D; i++) a(i) += b(i); return a; } template inline Point & operator-= (Point & a, const Vec & b) { for (int i = 0; i < D; i++) a(i) -= b(i); return a; } template inline Point & operator-= (Point & a, const VecExpr & b) { for (int i = 0; i < D; i++) a(i) -= b(i); return a; } template inline Vec & operator-= (Vec & a, const Vec & b) { for (int i = 0; i < D; i++) a(i) -= b(i); return a; } template inline Vec & operator*= (Vec & a, double s) { for (int i = 0; i < D; i++) a(i) *= s; return a; } template inline Vec & operator/= (Vec & a, double s) { for (int i = 0; i < D; i++) a(i) /= s; return a; } // Matrix - Vector operations /* template inline Vec operator* (const Mat & m, const Vec & v) { Vec res; for (int i = 0; i < H; i++) { res(i) = 0; for (int j = 0; j < W; j++) res(i) += m(i,j) * v(j); } return res; } */ // thanks to VC60 partial template specialization features !!! inline Vec<2> operator* (const Mat<2,2> & m, const Vec<2> & v) { Vec<2> res; for (int i = 0; i < 2; i++) { res(i) = 0; for (int j = 0; j < 2; j++) res(i) += m(i,j) * v(j); } return res; } inline Vec<2> operator* (const Mat<2,3> & m, const Vec<3> & v) { Vec<2> res; for (int i = 0; i < 2; i++) { res(i) = 0; for (int j = 0; j < 3; j++) res(i) += m(i,j) * v(j); } return res; } inline Vec<3> operator* (const Mat<3,2> & m, const Vec<2> & v) { Vec<3> res; for (int i = 0; i < 3; i++) { res(i) = 0; for (int j = 0; j < 2; j++) res(i) += m(i,j) * v(j); } return res; } inline Vec<3> operator* (const Mat<3,3> & m, const Vec<3> & v) { Vec<3> res; for (int i = 0; i < 3; i++) { res(i) = 0; for (int j = 0; j < 3; j++) res(i) += m(i,j) * v(j); } return res; } /* template inline Mat operator* (const Mat & a, const Mat & b) { Mat m; for (int i = 0; i < H1; i++) for (int j = 0; j < W2; j++) { double sum = 0; for (int k = 0; k < W1; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } */ inline Mat<2,2> operator* (const Mat<2,2> & a, const Mat<2,2> & b) { Mat<2,2> m; for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) { double sum = 0; for (int k = 0; k < 2; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } inline Mat<2,2> operator* (const Mat<2,3> & a, const Mat<3,2> & b) { Mat<2,2> m; for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) { double sum = 0; for (int k = 0; k < 3; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } inline Mat<3,2> operator* (const Mat<3,2> & a, const Mat<2,2> & b) { Mat<3,2> m; for (int i = 0; i < 3; i++) for (int j = 0; j < 2; j++) { double sum = 0; for (int k = 0; k < 2; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } inline Mat<3,3> operator* (const Mat<3,3> & a, const Mat<3,3> & b) { Mat<3,3> m; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { double sum = 0; for (int k = 0; k < 3; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } template inline Mat Trans (const Mat & m) { Mat res; for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) res(j,i) = m(i,j); return res; } template inline ostream & operator<< (ostream & ost, const Vec & a) { ost << "("; for (int i = 0; i < D-1; i++) ost << a(i) << ", "; ost << a(D-1) << ")"; return ost; } template inline ostream & operator<< (ostream & ost, const Point & a) { ost << "("; for (int i = 0; i < D-1; i++) ost << a(i) << ", "; ost << a(D-1) << ")"; return ost; } template inline ostream & operator<< (ostream & ost, const Box & b) { ost << b.PMin() << " - " << b.PMax(); return ost; } template inline ostream & operator<< (ostream & ost, const Mat & m) { ost << "("; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) ost << m(i,j) << " "; ost << endl; } return ost; } #endif netgen-6.2.1905/libsrc/gprim/geomops.hpp0000644000175000017500000001575113504650527016570 0ustar kurtkurt#ifndef FILE_GEOMOPS #define FILE_GEOMOPS /* *************************************************************************/ /* File: geomops.hpp */ /* Author: Joachim Schoeberl */ /* Date: 20. Jul. 02 */ /* *************************************************************************/ namespace netgen { /* Point - Vector operations */ template inline Vec operator+ (Vec a, Vec b) { Vec res; for (int i = 0; i < D; i++) res(i) = a(i) + b(i); return res; } template inline Point operator+ (Point a, Vec b) { Point res; for (int i = 0; i < D; i++) res(i) = a(i) + b(i); return res; } template inline Vec operator- (Point a, Point b) { Vec res; for (int i = 0; i < D; i++) res(i) = a(i) - b(i); return res; } template inline Point operator- (Point a, Vec b) { Point res; for (int i = 0; i < D; i++) res(i) = a(i) - b(i); return res; } template inline Vec operator- (Vec a, Vec b) { Vec res; for (int i = 0; i < D; i++) res(i) = a(i) - b(i); return res; } template inline Vec operator* (T s, Vec b) { Vec res; for (int i = 0; i < D; i++) res(i) = s * b(i); return res; } template inline double operator* (Vec a, Vec b) { double sum = 0; for (int i = 0; i < D; i++) sum += a(i) * b(i); return sum; } template inline Vec operator- (Vec b) { Vec res; for (int i = 0; i < D; i++) res(i) = -b(i); return res; } template inline Point & operator+= (Point & a, Vec b) { for (int i = 0; i < D; i++) a(i) += b(i); return a; } template inline Vec & operator+= (Vec & a, Vec b) { for (int i = 0; i < D; i++) a(i) += b(i); return a; } template inline Point & operator-= (Point & a, const Vec & b) { for (int i = 0; i < D; i++) a(i) -= b(i); return a; } template inline Vec & operator-= (Vec & a, const Vec & b) { for (int i = 0; i < D; i++) a(i) -= b(i); return a; } template inline Vec & operator*= (Vec & a, T2 s) { for (int i = 0; i < D; i++) a(i) *= s; return a; } template inline Vec & operator/= (Vec & a, double s) { for (int i = 0; i < D; i++) a(i) /= s; return a; } // Matrix - Vector operations /* template inline Vec operator* (const Mat & m, const Vec & v) { Vec res; for (int i = 0; i < H; i++) { res(i) = 0; for (int j = 0; j < W; j++) res(i) += m(i,j) * v(j); } return res; } */ // thanks to VC60 partial template specialization features !!! inline Vec<2> operator* (const Mat<2,2> & m, const Vec<2> & v) { Vec<2> res; for (int i = 0; i < 2; i++) { res(i) = 0; for (int j = 0; j < 2; j++) res(i) += m(i,j) * v(j); } return res; } inline Vec<2> operator* (const Mat<2,3> & m, const Vec<3> & v) { Vec<2> res; for (int i = 0; i < 2; i++) { res(i) = 0; for (int j = 0; j < 3; j++) res(i) += m(i,j) * v(j); } return res; } inline Vec<3> operator* (const Mat<3,2> & m, const Vec<2> & v) { Vec<3> res; for (int i = 0; i < 3; i++) { res(i) = 0; for (int j = 0; j < 2; j++) res(i) += m(i,j) * v(j); } return res; } inline Vec<3> operator* (const Mat<3,3> & m, const Vec<3> & v) { Vec<3> res; for (int i = 0; i < 3; i++) { res(i) = 0; for (int j = 0; j < 3; j++) res(i) += m(i,j) * v(j); } return res; } /* template inline Mat operator* (const Mat & a, const Mat & b) { Mat m; for (int i = 0; i < H1; i++) for (int j = 0; j < W2; j++) { double sum = 0; for (int k = 0; k < W1; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } */ template inline Mat<2,2,T> operator* (const Mat<2,2,T> & a, const Mat<2,2,T> & b) { Mat<2,2,T> m; for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) { T sum(0); for (int k = 0; k < 2; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } inline Mat<2,2> operator* (const Mat<2,3> & a, const Mat<3,2> & b) { Mat<2,2> m; for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) { double sum = 0; for (int k = 0; k < 3; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } template inline Mat<3,2,T> operator* (const Mat<3,2,T> & a, const Mat<2,2,T> & b) { Mat<3,2,T> m; for (int i = 0; i < 3; i++) for (int j = 0; j < 2; j++) { T sum(0.0); for (int k = 0; k < 2; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } inline Mat<2,3> operator* (const Mat<2,2> & a, const Mat<2,3> & b) { Mat<2,3> m; for (int i = 0; i < 2; i++) for (int j = 0; j < 3; j++) { double sum = 0; for (int k = 0; k < 2; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } template inline Mat<3,3,T> operator* (const Mat<3,3,T> & a, const Mat<3,3,T> & b) { Mat<3,3,T> m; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { T sum = T(0); for (int k = 0; k < 3; k++) sum += a(i,k) * b(k, j); m(i,j) = sum; } return m; } template inline Mat Trans (const Mat & m) { Mat res; for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) res(j,i) = m(i,j); return res; } template inline ostream & operator<< (ostream & ost, const Vec & a) { ost << "("; for (int i = 0; i < D-1; i++) ost << a(i) << ", "; ost << a(D-1) << ")"; return ost; } template inline ostream & operator<< (ostream & ost, const Point & a) { ost << "("; for (int i = 0; i < D-1; i++) ost << a(i) << ", "; ost << a(D-1) << ")"; return ost; } template inline ostream & operator<< (ostream & ost, const Box & b) { ost << b.PMin() << " - " << b.PMax(); return ost; } template inline ostream & operator<< (ostream & ost, const Mat & m) { ost << "("; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) ost << m(i,j) << " "; ost << endl; } return ost; } } #endif netgen-6.2.1905/libsrc/gprim/geomobjects.hpp0000644000175000017500000002127313504650527017414 0ustar kurtkurt#ifndef FILE_OBJECTS #define FILE_OBJECTS /* *************************************************************************/ /* File: geomobjects.hpp */ /* Author: Joachim Schoeberl */ /* Date: 20. Jul. 02 */ /* *************************************************************************/ namespace netgen { template class Vec; template class Point; template class Point : public ngsimd::AlignedAlloc> { protected: T x[D]; public: Point () { ; } Point (T ax) { for (int i = 0; i < D; i++) x[i] = ax; } Point (T ax, T ay) { // static_assert(D==2, "Point constructor with 2 args called"); x[0] = ax; x[1] = ay; } Point (T ax, T ay, T az) { // static_assert(D==3, "Point constructor with 3 args called"); x[0] = ax; x[1] = ay; x[2] = az; } Point (T ax, T ay, T az, T au) { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au;} template Point (const Point & p2) { for (int i = 0; i < D; i++) x[i] = p2(i); } explicit Point (const Vec & v) { for (int i = 0; i < D; i++) x[i] = v(i); } template Point & operator= (const Point & p2) { for (int i = 0; i < D; i++) x[i] = p2(i); return *this; } Point & operator= (T val) { for (int i = 0; i < D; i++) x[i] = val; return *this; } T & operator() (int i) { return x[i]; } const T & operator() (int i) const { return x[i]; } operator const T* () const { return x; } void DoArchive(Archive& archive) { for(int i=0; i class Vec : public ngsimd::AlignedAlloc> { protected: T x[D]; public: Vec () { ; } // for (int i = 0; i < D; i++) x[i] = 0; } Vec (T ax) { for (int i = 0; i < D; i++) x[i] = ax; } Vec (T ax, T ay) { // static_assert(D==2, "Vec constructor with 2 args called"); x[0] = ax; x[1] = ay; } Vec (T ax, T ay, T az) { // static_assert(D==3, "Vec constructor with 3 args called"); x[0] = ax; x[1] = ay; x[2] = az; } Vec (T ax, T ay, T az, T au) { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au; } Vec (const Vec & p2) { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } explicit Vec (const Point & p) { for (int i = 0; i < D; i++) x[i] = p(i); } Vec (const Vec & p1, const Vec & p2) { for(int i=0; i Vec & operator= (const Vec & p2) { for (int i = 0; i < D; i++) x[i] = p2(i); return *this; } Vec & operator= (T s) { for (int i = 0; i < D; i++) x[i] = s; return *this; } T & operator() (int i) { return x[i]; } const T & operator() (int i) const { return x[i]; } operator const T* () const { return x; } void DoArchive(Archive& archive) { for(int i=0; i GetNormal () const; }; template class Mat : public ngsimd::AlignedAlloc> { protected: T x[H*W]; public: Mat () { ; } Mat (const Mat & b) { for (int i = 0; i < H*W; i++) x[i] = b.x[i]; } Mat & operator= (T s) { for (int i = 0; i < H*W; i++) x[i] = s; return *this; } Mat & operator= (const Mat & b) { for (int i = 0; i < H*W; i++) x[i] = b.x[i]; return *this; } T & operator() (int i, int j) { return x[i*W+j]; } const T & operator() (int i, int j) const { return x[i*W+j]; } T & operator() (int i) { return x[i]; } const T & operator() (int i) const { return x[i]; } Vec Col (int i) const { Vec hv; for (int j = 0; j < H; j++) hv(j) = x[j*W+i]; return hv; } Vec Row (int i) const { Vec hv; for (int j = 0; j < W; j++) hv(j) = x[i*W+j]; return hv; } void Solve (const Vec & rhs, Vec & sol) const { Mat inv; CalcInverse (*this, inv); sol = inv * rhs; } }; template class Box { protected: Point pmin, pmax; public: Box () { ; } Box ( const Point & p1) { for (int i = 0; i < D; i++) pmin(i) = pmax(i) = p1(i); } Box ( const Point & p1, const Point & p2) { for (int i = 0; i < D; i++) { pmin(i) = min2(p1(i), p2(i)); pmax(i) = max2(p1(i), p2(i)); } } Box (const Point & p1, const Point & p2, const Point & p3) : Box(p1,p2) { Add (p3); } enum EB_TYPE { EMPTY_BOX = 1 }; Box ( EB_TYPE et ) { for (int i = 0; i < D; i++) { pmin(i) = 1e99; pmax(i) = -1e99; } // pmin = Point (1e99, 1e99, 1e99); // pmax = Point (-1e99, -1e99, -1e99); } const Point & PMin () const { return pmin; } const Point & PMax () const { return pmax; } void Set (const Point & p) { pmin = pmax = p; } void Add (const Point & p) { for (int i = 0; i < D; i++) { if (p(i) < pmin(i)) pmin(i) = p(i); /* else */ if (p(i) > pmax(i)) pmax(i) = p(i); // optimization invalid for empty-box ! } } template void Set (const IndirectArray & points) { Set (points[points.Begin()]); for (int i = points.Begin()+1; i < points.End(); i++) Add (points[i]); } template void Add (const IndirectArray & points) { for (int i = points.Begin(); i < points.End(); i++) Add (points[i]); } Point Center () const { Point c; for (int i = 0; i < D; i++) c(i) = 0.5 * (pmin(i)+pmax(i)); return c; } double Diam () const { return Abs (pmax-pmin); } Point GetPointNr (int nr) const { Point p; for (int i = 0; i < D; i++) { p(i) = (nr & 1) ? pmax(i) : pmin(i); nr >>= 1; } return p; } bool Intersect (const Box & box2) const { for (int i = 0; i < D; i++) if (pmin(i) > box2.pmax(i) || pmax(i) < box2.pmin(i)) return 0; return 1; } bool IsIn (const Point & p) const { for (int i = 0; i < D; i++) if (p(i) < pmin(i) || p(i) > pmax(i)) return 0; return 1; } void Increase (double dist) { for (int i = 0; i < D; i++) { pmin(i) -= dist; pmax(i) += dist; } } void DoArchive(Archive& archive) { archive & pmin & pmax; } }; template class BoxSphere : public Box { protected: /// Point c; /// double diam; /// double inner; public: /// BoxSphere () { }; /// BoxSphere (const Box & box) : Box (box) { CalcDiamCenter(); }; /// BoxSphere ( Point apmin, Point apmax ) : Box (apmin, apmax) { CalcDiamCenter(); } /// const Point & Center () const { return c; } /// double Diam () const { return diam; } /// double Inner () const { return inner; } /// void GetSubBox (int nr, BoxSphere & sbox) const { for (int i = 0; i < D; i++) { if (nr & 1) { sbox.pmin(i) = c(i); sbox.pmax(i) = this->pmax(i); } else { sbox.pmin(i) = this->pmin(i); sbox.pmax(i) = c(i); } sbox.c(i) = 0.5 * (sbox.pmin(i) + sbox.pmax(i)); nr >>= 1; } sbox.diam = 0.5 * diam; sbox.inner = 0.5 * inner; } /// void CalcDiamCenter () { c = Box::Center (); diam = Dist (this->pmin, this->pmax); inner = this->pmax(0) - this->pmin(0); for (int i = 1; i < D; i++) if (this->pmax(i) - this->pmin(i) < inner) inner = this->pmax(i) - this->pmin(i); } }; #ifdef PARALLEL template <> inline MPI_Datatype MyGetMPIType > () { static MPI_Datatype MPI_T = 0; if (!MPI_T) { MPI_Type_contiguous ( 3, MPI_DOUBLE, &MPI_T); MPI_Type_commit ( &MPI_T ); } return MPI_T; }; #endif } #endif netgen-6.2.1905/libsrc/gprim/adtree.cpp0000644000175000017500000012554013504650527016354 0ustar kurtkurt#include #include // class DenseMatrix; #include namespace netgen { /* ******************************* ADTree ******************************* */ ADTreeNode :: ADTreeNode(int adim) { pi = -1; left = NULL; right = NULL; father = NULL; nchilds = 0; dim = adim; data = new float [dim]; boxmin = NULL; boxmax = NULL; } ADTreeNode :: ~ADTreeNode() { delete data; } ADTree :: ADTree (int adim, const float * acmin, const float * acmax) : ela(0), stack(1000), stackdir(1000) { dim = adim; cmin = new float [dim]; cmax = new float [dim]; memcpy (cmin, acmin, dim * sizeof(float)); memcpy (cmax, acmax, dim * sizeof(float)); root = new ADTreeNode (dim); root->sep = (cmin[0] + cmax[0]) / 2; root->boxmin = new float [dim]; root->boxmax = new float [dim]; memcpy (root->boxmin, cmin, dim * sizeof(float)); memcpy (root->boxmax, cmax, dim * sizeof(float)); } ADTree :: ~ADTree () { ; } void ADTree :: Insert (const float * p, int pi) { ADTreeNode *node(NULL); ADTreeNode *next; int dir; int lr(1); float * bmin = new float [dim]; float * bmax = new float [dim]; memcpy (bmin, cmin, dim * sizeof(float)); memcpy (bmax, cmax, dim * sizeof(float)); next = root; dir = 0; while (next) { node = next; if (node->pi == -1) { memcpy (node->data, p, dim * sizeof(float)); node->pi = pi; if (ela.Size() < pi+1) ela.SetSize (pi+1); ela[pi] = node; return; } if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } dir++; if (dir == dim) dir = 0; } next = new ADTreeNode(dim); memcpy (next->data, p, dim * sizeof(float)); next->pi = pi; next->sep = (bmin[dir] + bmax[dir]) / 2; next->boxmin = bmin; next->boxmax = bmax; if (ela.Size() < pi+1) ela.SetSize (pi+1); ela[pi] = next; if (lr) node->right = next; else node->left = next; next -> father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree :: DeleteElement (int pi) { ADTreeNode * node = ela[pi]; node->pi = -1; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree :: SetCriterion (ADTreeCriterion & acriterion) { criterion = & acriterion; } void ADTree :: Reset () { stack.Elem(1) = root; stackdir.Elem(1) = 0; stackindex = 1; } int ADTree:: Next () { ADTreeNode *node; int dir; if (stackindex == 0) return -1; do { node = stack.Get(stackindex); dir = stackdir.Get(stackindex); stackindex --; if (criterion -> Eval(node)) { int ndir = dir + 1; if (ndir == dim) ndir = 0; if (node -> left && criterion -> Eval (node->left)) { stackindex ++; stack.Elem(stackindex) = node -> left; stackdir.Elem(stackindex) = ndir; } if (node->right && criterion -> Eval (node -> right)) { stackindex++; stack.Elem(stackindex) = node->right; stackdir.Elem(stackindex) = ndir; } if (node -> pi != -1) return node->pi; } } while (stackindex > 0); return -1; } void ADTree :: GetMatch (Array & matches) { int nodenr; Reset(); while ( (nodenr = Next()) != -1) matches.Append (nodenr); } void ADTree :: PrintRec (ostream & ost, const ADTreeNode * node) const { if (node->data) { ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (int i = 0; i < dim; i++) ost << node->data[i] << " "; ost << endl; } if (node->left) { ost << "l "; PrintRec (ost, node->left); } if (node->right) { ost << "r "; PrintRec (ost, node->right); } } /* ******************************* ADTree3 ******************************* */ ADTreeNode3 :: ADTreeNode3() { pi = -1; left = NULL; right = NULL; father = NULL; nchilds = 0; } void ADTreeNode3 :: DeleteChilds () { if (left) { left->DeleteChilds(); delete left; left = NULL; } if (right) { right->DeleteChilds(); delete right; right = NULL; } } BlockAllocator ADTreeNode3 :: ball(sizeof (ADTreeNode3)); void * ADTreeNode3 :: operator new(size_t s) { return ball.Alloc(); } void ADTreeNode3 :: operator delete (void * p) { ball.Free (p); } ADTree3 :: ADTree3 (const float * acmin, const float * acmax) : ela(0) { memcpy (cmin, acmin, 3 * sizeof(float)); memcpy (cmax, acmax, 3 * sizeof(float)); root = new ADTreeNode3; root->sep = (cmin[0] + cmax[0]) / 2; } ADTree3 :: ~ADTree3 () { root->DeleteChilds(); delete root; } void ADTree3 :: Insert (const float * p, int pi) { ADTreeNode3 *node(NULL); ADTreeNode3 *next; int dir; int lr(0); float bmin[3]; float bmax[3]; memcpy (bmin, cmin, 3 * sizeof(float)); memcpy (bmax, cmax, 3 * sizeof(float)); next = root; dir = 0; while (next) { node = next; if (node->pi == -1) { memcpy (node->data, p, 3 * sizeof(float)); node->pi = pi; if (ela.Size() < pi+1) ela.SetSize (pi+1); ela[pi] = node; return; } if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } dir++; if (dir == 3) dir = 0; } next = new ADTreeNode3; memcpy (next->data, p, 3 * sizeof(float)); next->pi = pi; next->sep = (bmin[dir] + bmax[dir]) / 2; if (ela.Size() < pi+1) ela.SetSize (pi+1); ela[pi] = next; if (lr) node->right = next; else node->left = next; next -> father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree3 :: DeleteElement (int pi) { ADTreeNode3 * node = ela[pi]; node->pi = -1; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree3 :: GetIntersecting (const float * bmin, const float * bmax, Array & pis) const { static Array stack(1000); static Array stackdir(1000); ADTreeNode3 * node; int dir, stacks; stack.SetSize (1000); stackdir.SetSize(1000); pis.SetSize(0); stack.Elem(1) = root; stackdir.Elem(1) = 0; stacks = 1; while (stacks) { node = stack.Get(stacks); dir = stackdir.Get(stacks); stacks--; if (node->pi != -1) { if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) pis.Append (node->pi); } int ndir = dir+1; if (ndir == 3) ndir = 0; if (node->left && bmin[dir] <= node->sep) { stacks++; stack.Elem(stacks) = node->left; stackdir.Elem(stacks) = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack.Elem(stacks) = node->right; stackdir.Elem(stacks) = ndir; } } } void ADTree3 :: PrintRec (ostream & ost, const ADTreeNode3 * node) const { // if (node->data) // true anyway { ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (int i = 0; i < 3; i++) ost << node->data[i] << " "; ost << endl; } if (node->left) PrintRec (ost, node->left); if (node->right) PrintRec (ost, node->right); } #ifdef ABC /* ******************************* ADTree3Div ******************************* */ ADTreeNode3Div :: ADTreeNode3Div() { pi = 0; int i; for (i = 0; i < ADTN_DIV; i++) childs[i] = NULL; father = NULL; nchilds = 0; minx = 0; dist = 1; } void ADTreeNode3Div :: DeleteChilds () { int i; for (i = 0; i < ADTN_DIV; i++) if (childs[i]) { childs[i]->DeleteChilds(); delete childs[i]; childs[i] = NULL; } } BlockAllocator ADTreeNode3Div :: ball(sizeof (ADTreeNode3Div)); void * ADTreeNode3Div :: operator new(size_t) { return ball.Alloc(); } void ADTreeNode3Div :: operator delete (void * p) { ball.Free (p); } ADTree3Div :: ADTree3Div (const float * acmin, const float * acmax) : ela(0) { memcpy (cmin, acmin, 3 * sizeof(float)); memcpy (cmax, acmax, 3 * sizeof(float)); root = new ADTreeNode3Div; root->minx = cmin[0]; root->dist = (cmax[0] - cmin[0]) / ADTN_DIV; // root->sep = (cmin[0] + cmax[0]) / 2; } ADTree3Div :: ~ADTree3Div () { root->DeleteChilds(); delete root; } void ADTree3Div :: Insert (const float * p, int pi) { ADTreeNode3Div *node; ADTreeNode3Div *next; int dir; int bag; float bmin[3]; float bmax[3]; memcpy (bmin, cmin, 3 * sizeof(float)); memcpy (bmax, cmax, 3 * sizeof(float)); next = root; dir = 0; while (next) { node = next; if (!node->pi) { memcpy (node->data, p, 3 * sizeof(float)); node->pi = pi; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = node; return; } double dx = (bmax[dir] - bmin[dir]) / ADTN_DIV; bag = int ((p[dir]-bmin[dir]) / dx); // (*testout) << "insert, bag = " << bag << endl; if (bag < 0) bag = 0; if (bag >= ADTN_DIV) bag = ADTN_DIV-1; double nbmin = bmin[dir] + bag * dx; double nbmax = bmin[dir] + (bag+1) * dx; /* (*testout) << "bmin, max = " << bmin[dir] << "-" << bmax[dir] << " p = " << p[dir]; */ next = node->childs[bag]; bmin[dir] = nbmin; bmax[dir] = nbmax; // (*testout) << "new bmin, max = " << bmin[dir] << "-" << bmax[dir] << endl; /* if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } */ dir++; if (dir == 3) dir = 0; } next = new ADTreeNode3Div; memcpy (next->data, p, 3 * sizeof(float)); next->pi = pi; next->minx = bmin[dir]; next->dist = (bmax[dir] - bmin[dir]) / ADTN_DIV; // next->sep = (bmin[dir] + bmax[dir]) / 2; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = next; node->childs[bag] = next; next -> father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree3Div :: DeleteElement (int pi) { ADTreeNode3Div * node = ela.Get(pi); node->pi = 0; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree3Div :: GetIntersecting (const float * bmin, const float * bmax, Array & pis) const { static Array stack(1000); static Array stackdir(1000); ADTreeNode3Div * node; int dir, i, stacks; stack.SetSize (1000); stackdir.SetSize(1000); pis.SetSize(0); stack.Elem(1) = root; stackdir.Elem(1) = 0; stacks = 1; while (stacks) { node = stack.Get(stacks); dir = stackdir.Get(stacks); stacks--; if (node->pi) { if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) pis.Append (node->pi); } int ndir = dir+1; if (ndir == 3) ndir = 0; int mini = int ( (bmin[dir] - node->minx) / node->dist ); int maxi = int ( (bmax[dir] - node->minx) / node->dist ); // (*testout) << "get int, mini, maxi = " << mini << ", " << maxi << endl; if (mini < 0) mini = 0; if (maxi >= ADTN_DIV) maxi = ADTN_DIV-1; for (i = mini; i <= maxi; i++) if (node->childs[i]) { stacks++; stack.Elem(stacks) = node->childs[i]; stackdir.Elem(stacks) = ndir; } /* if (node->left && bmin[dir] <= node->sep) { stacks++; stack.Elem(stacks) = node->left; stackdir.Elem(stacks) = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack.Elem(stacks) = node->right; stackdir.Elem(stacks) = ndir; } */ } } void ADTree3Div :: PrintRec (ostream & ost, const ADTreeNode3Div * node) const { if (node->data) { ost << node->pi << ": "; ost << node->nchilds << " childs, "; ost << " from " << node->minx << " - " << node->minx + node->dist*ADTN_DIV << " "; for (int i = 0; i < 3; i++) ost << node->data[i] << " "; ost << endl; } int i; for (i = 0; i < ADTN_DIV; i++) if (node->childs[i]) PrintRec (ost, node->childs[i]); } /* ******************************* ADTree3M ******************************* */ ADTreeNode3M :: ADTreeNode3M() { int i; for (i = 0; i < ADTN_SIZE; i++) pi[i] = 0; left = NULL; right = NULL; father = NULL; nchilds = 0; } void ADTreeNode3M :: DeleteChilds () { if (left) { left->DeleteChilds(); delete left; left = NULL; } if (right) { right->DeleteChilds(); delete right; right = NULL; } } BlockAllocator ADTreeNode3M :: ball(sizeof (ADTreeNode3M)); void * ADTreeNode3M :: operator new(size_t) { return ball.Alloc(); } void ADTreeNode3M :: operator delete (void * p) { ball.Free (p); } ADTree3M :: ADTree3M (const float * acmin, const float * acmax) : ela(0) { memcpy (cmin, acmin, 3 * sizeof(float)); memcpy (cmax, acmax, 3 * sizeof(float)); root = new ADTreeNode3M; root->sep = (cmin[0] + cmax[0]) / 2; } ADTree3M :: ~ADTree3M () { root->DeleteChilds(); delete root; } void ADTree3M :: Insert (const float * p, int pi) { ADTreeNode3M *node; ADTreeNode3M *next; int dir; int lr; int i; float bmin[3]; float bmax[3]; memcpy (bmin, cmin, 3 * sizeof(float)); memcpy (bmax, cmax, 3 * sizeof(float)); next = root; dir = 0; while (next) { node = next; for (i = 0; i < ADTN_SIZE; i++) if (!node->pi[i]) { memcpy (node->data[i], p, 3 * sizeof(float)); node->pi[i] = pi; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = node; return; } if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } dir++; if (dir == 3) dir = 0; } next = new ADTreeNode3M; memcpy (next->data[0], p, 3 * sizeof(float)); next->pi[0] = pi; next->sep = (bmin[dir] + bmax[dir]) / 2; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = next; if (lr) node->right = next; else node->left = next; next -> father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree3M :: DeleteElement (int pi) { ADTreeNode3M * node = ela.Get(pi); int i; for (i = 0; i < ADTN_SIZE; i++) if (node->pi[i] == pi) node->pi[i] = 0; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree3M :: GetIntersecting (const float * bmin, const float * bmax, Array & pis) const { static Array stack(1000); static Array stackdir(1000); ADTreeNode3M * node; int dir, i, stacks; stack.SetSize (1000); stackdir.SetSize(1000); pis.SetSize(0); stack.Elem(1) = root; stackdir.Elem(1) = 0; stacks = 1; while (stacks) { node = stack.Get(stacks); dir = stackdir.Get(stacks); stacks--; int * hpi = node->pi; for (i = 0; i < ADTN_SIZE; i++) if (hpi[i]) { float * datai = &node->data[i][0]; if (datai[0] >= bmin[0] && datai[0] <= bmax[0] && datai[1] >= bmin[1] && datai[1] <= bmax[1] && datai[2] >= bmin[2] && datai[2] <= bmax[2]) pis.Append (node->pi[i]); } int ndir = dir+1; if (ndir == 3) ndir = 0; if (node->left && bmin[dir] <= node->sep) { stacks++; stack.Elem(stacks) = node->left; stackdir.Elem(stacks) = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack.Elem(stacks) = node->right; stackdir.Elem(stacks) = ndir; } } } void ADTree3M :: PrintRec (ostream & ost, const ADTreeNode3M * node) const { if (node->data) { // ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (int i = 0; i < 3; i++) ost << node->data[i] << " "; ost << endl; } if (node->left) PrintRec (ost, node->left); if (node->right) PrintRec (ost, node->right); } /* ******************************* ADTree3F ******************************* */ ADTreeNode3F :: ADTreeNode3F() { pi = 0; father = NULL; nchilds = 0; int i; for (i = 0; i < 8; i++) childs[i] = NULL; } void ADTreeNode3F :: DeleteChilds () { int i; for (i = 0; i < 8; i++) { if (childs[i]) childs[i]->DeleteChilds(); delete childs[i]; childs[i] = NULL; } } BlockAllocator ADTreeNode3F :: ball(sizeof (ADTreeNode3F)); void * ADTreeNode3F :: operator new(size_t) { return ball.Alloc(); } void ADTreeNode3F :: operator delete (void * p) { ball.Free (p); } ADTree3F :: ADTree3F (const float * acmin, const float * acmax) : ela(0) { memcpy (cmin, acmin, 3 * sizeof(float)); memcpy (cmax, acmax, 3 * sizeof(float)); root = new ADTreeNode3F; for (int i = 0; i < 3; i++) root->sep[i] = (cmin[i] + cmax[i]) / 2; } ADTree3F :: ~ADTree3F () { root->DeleteChilds(); delete root; } void ADTree3F :: Insert (const float * p, int pi) { ADTreeNode3F *node; ADTreeNode3F *next; int lr; float bmin[3]; float bmax[3]; int i, dir; memcpy (bmin, cmin, 3 * sizeof(float)); memcpy (bmax, cmax, 3 * sizeof(float)); next = root; while (next) { node = next; if (!node->pi) { memcpy (node->data, p, 3 * sizeof(float)); node->pi = pi; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = node; return; } dir = 0; for (i = 0; i < 3; i++) { if (node->sep[i] > p[i]) { bmax[i] = node->sep[i]; } else { bmin[i] = node->sep[i]; dir += (1 << i); } } next = node->childs[dir]; /* if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } */ } next = new ADTreeNode3F; memcpy (next->data, p, 3 * sizeof(float)); next->pi = pi; for (i = 0; i < 3; i++) next->sep[i] = (bmin[i] + bmax[i]) / 2; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = next; node->childs[dir] = next; next->father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree3F :: DeleteElement (int pi) { ADTreeNode3F * node = ela.Get(pi); node->pi = 0; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree3F :: GetIntersecting (const float * bmin, const float * bmax, Array & pis) const { static Array stack(1000); ADTreeNode3F * node; int dir, i, stacks; stack.SetSize (1000); pis.SetSize(0); stack.Elem(1) = root; stacks = 1; while (stacks) { node = stack.Get(stacks); stacks--; if (node->pi) { if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) pis.Append (node->pi); } int i1min = (bmin[0] <= node->sep[0]) ? 0 : 1; int i1max = (bmax[0] < node->sep[0]) ? 0 : 1; int i2min = (bmin[1] <= node->sep[1]) ? 0 : 1; int i2max = (bmax[1] < node->sep[1]) ? 0 : 1; int i3min = (bmin[2] <= node->sep[2]) ? 0 : 1; int i3max = (bmax[2] < node->sep[2]) ? 0 : 1; int i1, i2, i3; for (i1 = i1min; i1 <= i1max; i1++) for (i2 = i2min; i2 <= i2max; i2++) for (i3 = i3min; i3 <= i3max; i3++) { i = i1+2*i2+4*i3; if (node->childs[i]) { stacks++; stack.Elem(stacks) = node->childs[i]; } } /* if (node->left && bmin[dir] <= node->sep) { stacks++; stack.Elem(stacks) = node->left; stackdir.Elem(stacks) = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack.Elem(stacks) = node->right; stackdir.Elem(stacks) = ndir; } */ } } void ADTree3F :: PrintRec (ostream & ost, const ADTreeNode3F * node) const { int i; if (node->data) { ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (i = 0; i < 3; i++) ost << node->data[i] << " "; ost << endl; } for (i = 0; i < 8; i++) if (node->childs[i]) PrintRec (ost, node->childs[i]); } /* ******************************* ADTree3FM ******************************* */ ADTreeNode3FM :: ADTreeNode3FM() { father = NULL; nchilds = 0; int i; for (i = 0; i < ADTN_SIZE; i++) pi[i] = 0; for (i = 0; i < 8; i++) childs[i] = NULL; } void ADTreeNode3FM :: DeleteChilds () { int i; for (i = 0; i < 8; i++) { if (childs[i]) childs[i]->DeleteChilds(); delete childs[i]; childs[i] = NULL; } } BlockAllocator ADTreeNode3FM :: ball(sizeof (ADTreeNode3FM)); void * ADTreeNode3FM :: operator new(size_t) { return ball.Alloc(); } void ADTreeNode3FM :: operator delete (void * p) { ball.Free (p); } ADTree3FM :: ADTree3FM (const float * acmin, const float * acmax) : ela(0) { memcpy (cmin, acmin, 3 * sizeof(float)); memcpy (cmax, acmax, 3 * sizeof(float)); root = new ADTreeNode3FM; for (int i = 0; i < 3; i++) root->sep[i] = (cmin[i] + cmax[i]) / 2; } ADTree3FM :: ~ADTree3FM () { root->DeleteChilds(); delete root; } void ADTree3FM :: Insert (const float * p, int pi) { ADTreeNode3FM *node; ADTreeNode3FM *next; int lr; float bmin[3]; float bmax[3]; int i, dir; memcpy (bmin, cmin, 3 * sizeof(float)); memcpy (bmax, cmax, 3 * sizeof(float)); next = root; while (next) { node = next; for (i = 0; i < ADTN_SIZE; i++) if (!node->pi[i]) { memcpy (node->data[i], p, 3 * sizeof(float)); node->pi[i] = pi; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = node; return; } dir = 0; for (i = 0; i < 3; i++) { if (node->sep[i] > p[i]) { bmax[i] = node->sep[i]; } else { bmin[i] = node->sep[i]; dir += (1 << i); } } next = node->childs[dir]; /* if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } */ } next = new ADTreeNode3FM; memcpy (next->data[0], p, 3 * sizeof(float)); next->pi[0] = pi; for (i = 0; i < 3; i++) next->sep[i] = (bmin[i] + bmax[i]) / 2; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = next; node->childs[dir] = next; next->father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree3FM :: DeleteElement (int pi) { ADTreeNode3FM * node = ela.Get(pi); int i; for (i = 0; i < ADTN_SIZE; i++) if (node->pi[i] == pi) node->pi[i] = 0; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree3FM :: GetIntersecting (const float * bmin, const float * bmax, Array & pis) const { static Array stack(1000); ADTreeNode3FM * node; int dir, i, stacks; stack.SetSize (1000); pis.SetSize(0); stack.Elem(1) = root; stacks = 1; while (stacks) { node = stack.Get(stacks); stacks--; int * hpi = node->pi; for (i = 0; i < ADTN_SIZE; i++) if (hpi[i]) { float * datai = &node->data[i][0]; if (datai[0] >= bmin[0] && datai[0] <= bmax[0] && datai[1] >= bmin[1] && datai[1] <= bmax[1] && datai[2] >= bmin[2] && datai[2] <= bmax[2]) pis.Append (node->pi[i]); } /* if (node->pi) { if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) pis.Append (node->pi); } */ int i1min = (bmin[0] <= node->sep[0]) ? 0 : 1; int i1max = (bmax[0] < node->sep[0]) ? 0 : 1; int i2min = (bmin[1] <= node->sep[1]) ? 0 : 1; int i2max = (bmax[1] < node->sep[1]) ? 0 : 1; int i3min = (bmin[2] <= node->sep[2]) ? 0 : 1; int i3max = (bmax[2] < node->sep[2]) ? 0 : 1; int i1, i2, i3; for (i1 = i1min; i1 <= i1max; i1++) for (i2 = i2min; i2 <= i2max; i2++) for (i3 = i3min; i3 <= i3max; i3++) { i = i1+2*i2+4*i3; if (node->childs[i]) { stacks++; stack.Elem(stacks) = node->childs[i]; } } /* if (node->left && bmin[dir] <= node->sep) { stacks++; stack.Elem(stacks) = node->left; stackdir.Elem(stacks) = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack.Elem(stacks) = node->right; stackdir.Elem(stacks) = ndir; } */ } } void ADTree3FM :: PrintRec (ostream & ost, const ADTreeNode3FM * node) const { int i; if (node->data) { ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (i = 0; i < 3; i++) ost << node->data[i] << " "; ost << endl; } for (i = 0; i < 8; i++) if (node->childs[i]) PrintRec (ost, node->childs[i]); } #endif /* ******************************* ADTree6 ******************************* */ ADTreeNode6 :: ADTreeNode6() { pi = -1; left = NULL; right = NULL; father = NULL; nchilds = 0; } void ADTreeNode6 :: DeleteChilds () { if (left) { left->DeleteChilds(); delete left; left = NULL; } if (right) { right->DeleteChilds(); delete right; right = NULL; } } BlockAllocator ADTreeNode6 :: ball (sizeof (ADTreeNode6)); void * ADTreeNode6 :: operator new(size_t s) { return ball.Alloc(); } void ADTreeNode6 :: operator delete (void * p) { ball.Free (p); } ADTree6 :: ADTree6 (const float * acmin, const float * acmax) : ela(0) { memcpy (cmin, acmin, 6 * sizeof(float)); memcpy (cmax, acmax, 6 * sizeof(float)); root = new ADTreeNode6; root->sep = (cmin[0] + cmax[0]) / 2; } ADTree6 :: ~ADTree6 () { root->DeleteChilds(); delete root; } void ADTree6 :: Insert (const float * p, int pi) { ADTreeNode6 *node(NULL); ADTreeNode6 *next; int dir; int lr(0); float bmin[6]; float bmax[6]; memcpy (bmin, cmin, 6 * sizeof(float)); memcpy (bmax, cmax, 6 * sizeof(float)); next = root; dir = 0; while (next) { node = next; if (node->pi == -1) { memcpy (node->data, p, 6 * sizeof(float)); node->pi = pi; if (ela.Size() < pi+1) ela.SetSize (pi+1); ela[pi] = node; return; } if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } dir++; if (dir == 6) dir = 0; } next = new ADTreeNode6; memcpy (next->data, p, 6 * sizeof(float)); next->pi = pi; next->sep = (bmin[dir] + bmax[dir]) / 2; if (ela.Size() < pi+1) ela.SetSize (pi+1); ela[pi] = next; if (lr) node->right = next; else node->left = next; next -> father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree6 :: DeleteElement (int pi) { ADTreeNode6 * node = ela[pi]; node->pi = -1; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree6 :: PrintMemInfo (ostream & ost) const { ost << Elements() << " elements a " << sizeof(ADTreeNode6) << " Bytes = " << Elements() * sizeof(ADTreeNode6) << endl; ost << "maxind = " << ela.Size() << " = " << sizeof(ADTreeNode6*) * ela.Size() << " Bytes" << endl; } class inttn6 { public: int dir; ADTreeNode6 * node; }; void ADTree6 :: GetIntersecting (const float * bmin, const float * bmax, Array & pis) const { // static Array stack(10000); // stack.SetSize (10000); ArrayMem stack(10000); pis.SetSize(0); stack[0].node = root; stack[0].dir = 0; int stacks = 0; while (stacks >= 0) { ADTreeNode6 * node = stack[stacks].node; int dir = stack[stacks].dir; stacks--; if (node->pi != -1) { if (node->data[0] > bmax[0] || node->data[1] > bmax[1] || node->data[2] > bmax[2] || node->data[3] < bmin[3] || node->data[4] < bmin[4] || node->data[5] < bmin[5]) ; else { pis.Append (node->pi); } } int ndir = (dir+1) % 6; if (node->left && bmin[dir] <= node->sep) { stacks++; stack[stacks].node = node->left; stack[stacks].dir = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack[stacks].node = node->right; stack[stacks].dir = ndir; } } } void ADTree6 :: PrintRec (ostream & ost, const ADTreeNode6 * node) const { // if (node->data) // true anyway { ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (int i = 0; i < 6; i++) ost << node->data[i] << " "; ost << endl; } if (node->left) PrintRec (ost, node->left); if (node->right) PrintRec (ost, node->right); } int ADTree6 :: DepthRec (const ADTreeNode6 * node) const { int ldepth = 0; int rdepth = 0; if (node->left) ldepth = DepthRec(node->left); if (node->right) rdepth = DepthRec(node->right); return 1 + max2 (ldepth, rdepth); } int ADTree6 :: ElementsRec (const ADTreeNode6 * node) const { int els = 1; if (node->left) els += ElementsRec(node->left); if (node->right) els += ElementsRec(node->right); return els; } template T_ADTree :: T_ADTree (Point acmin, Point acmax) // : ela(0) { cmin = acmin; cmax = acmax; root = new T_ADTreeNode; root->sep = (cmin[0] + cmax[0]) / 2; } template T_ADTree :: ~T_ADTree () { root->DeleteChilds(); delete root; } template void T_ADTree :: Insert (Point p, T pi) { T_ADTreeNode *node(NULL); T_ADTreeNode *next; int dir; int lr(0); Point bmin = cmin; Point bmax = cmax; next = root; dir = 0; while (next) { node = next; if (IsInvalid(node->pi)) { // memcpy (node->data, p, dim * sizeof(float)); node->data = p; node->pi = pi; // if (ela.Size() < pi+1) // ela.SetSize (pi+1); ela[pi] = node; return; } if (node->sep > p[dir]) { next = node->left; bmax(dir) = node->sep; lr = 0; } else { next = node->right; bmin(dir) = node->sep; lr = 1; } dir++; if (dir == dim) dir = 0; } next = new T_ADTreeNode; // memcpy (next->data, p, dim * sizeof(float)); next->data = p; next->pi = pi; next->sep = (bmin[dir] + bmax[dir]) / 2; // if (ela.Size() < pi+1) // ela.SetSize (pi+1); ela[pi] = next; if (lr) node->right = next; else node->left = next; next -> father = node; while (node) { node->nchilds++; node = node->father; } } template void T_ADTree :: DeleteElement (T pi) { T_ADTreeNode * node = ela[pi]; ela.Delete(pi); SetInvalid(node->pi); // = -1; node = node->father; while (node) { node->nchilds--; node = node->father; } } template void T_ADTree :: PrintMemInfo (ostream & ost) const { ost << Elements() << " elements a " << sizeof(ADTreeNode6) << " Bytes = " << Elements() * sizeof(T_ADTreeNode) << endl; ost << "maxind = " << ela.Size() << " = " << sizeof(T_ADTreeNode*) * ela.Size() << " Bytes" << endl; } template class inttn { public: int dir; T_ADTreeNode * node; }; template void T_ADTree :: GetIntersecting (Point bmin, Point bmax, Array & pis) const { // static Array stack(10000); // stack.SetSize (10000); ArrayMem,10000> stack(10000); pis.SetSize(0); stack[0].node = root; stack[0].dir = 0; int stacks = 0; while (stacks >= 0) { T_ADTreeNode * node = stack[stacks].node; int dir = stack[stacks].dir; stacks--; if (!IsInvalid(node->pi)) // != -1) { bool found = true; for (int i = 0; i < dim/2; i++) if (node->data[i] > bmax[i]) found = false; for (int i = dim/2; i < dim; i++) if (node->data[i] < bmin[i]) found = false; if (found) pis.Append (node->pi); /* if (node->data[0] > bmax[0] || node->data[1] > bmax[1] || node->data[2] > bmax[2] || node->data[3] < bmin[3] || node->data[4] < bmin[4] || node->data[5] < bmin[5]) ; else { pis.Append (node->pi); } */ } int ndir = (dir+1) % dim; if (node->left && bmin[dir] <= node->sep) { stacks++; stack[stacks].node = node->left; stack[stacks].dir = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack[stacks].node = node->right; stack[stacks].dir = ndir; } } } template void T_ADTree :: PrintRec (ostream & ost, const T_ADTreeNode * node) const { // if (node->data) // true anyway { ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (int i = 0; i < dim; i++) ost << node->data[i] << " "; ost << endl; } if (node->left) PrintRec (ost, node->left); if (node->right) PrintRec (ost, node->right); } template int T_ADTree :: DepthRec (const T_ADTreeNode * node) const { int ldepth = 0; int rdepth = 0; if (node->left) ldepth = DepthRec(node->left); if (node->right) rdepth = DepthRec(node->right); return 1 + max2 (ldepth, rdepth); } template int T_ADTree :: ElementsRec (const T_ADTreeNode * node) const { int els = 1; if (node->left) els += ElementsRec(node->left); if (node->right) els += ElementsRec(node->right); return els; } #ifdef ABC /* ******************************* ADTree6F ******************************* */ ADTreeNode6F :: ADTreeNode6F() { pi = 0; father = NULL; nchilds = 0; int i; for (i = 0; i < 64; i++) childs[i] = NULL; } void ADTreeNode6F :: DeleteChilds () { int i; for (i = 0; i < 64; i++) { if (childs[i]) childs[i]->DeleteChilds(); delete childs[i]; childs[i] = NULL; } } BlockAllocator ADTreeNode6F :: ball(sizeof (ADTreeNode6F)); void * ADTreeNode6F :: operator new(size_t) { return ball.Alloc(); } void ADTreeNode6F :: operator delete (void * p) { ball.Free (p); } ADTree6F :: ADTree6F (const float * acmin, const float * acmax) : ela(0) { memcpy (cmin, acmin, 6 * sizeof(float)); memcpy (cmax, acmax, 6 * sizeof(float)); root = new ADTreeNode6F; for (int i = 0; i < 6; i++) root->sep[i] = (cmin[i] + cmax[i]) / 2; } ADTree6F :: ~ADTree6F () { root->DeleteChilds(); delete root; } void ADTree6F :: Insert (const float * p, int pi) { ADTreeNode6F *node; ADTreeNode6F *next; int lr; float bmin[6]; float bmax[6]; int i, dir; memcpy (bmin, cmin, 6 * sizeof(float)); memcpy (bmax, cmax, 6 * sizeof(float)); next = root; while (next) { node = next; if (!node->pi) { memcpy (node->data, p, 6 * sizeof(float)); node->pi = pi; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = node; return; } dir = 0; for (i = 0; i < 6; i++) { if (node->sep[i] > p[i]) { bmax[i] = node->sep[i]; } else { bmin[i] = node->sep[i]; dir += (1 << i); } } next = node->childs[dir]; /* if (node->sep > p[dir]) { next = node->left; bmax[dir] = node->sep; lr = 0; } else { next = node->right; bmin[dir] = node->sep; lr = 1; } */ } next = new ADTreeNode6F; memcpy (next->data, p, 6 * sizeof(float)); next->pi = pi; for (i = 0; i < 6; i++) next->sep[i] = (bmin[i] + bmax[i]) / 2; if (ela.Size() < pi) ela.SetSize (pi); ela.Elem(pi) = next; node->childs[dir] = next; next->father = node; while (node) { node->nchilds++; node = node->father; } } void ADTree6F :: DeleteElement (int pi) { ADTreeNode6F * node = ela.Get(pi); node->pi = 0; node = node->father; while (node) { node->nchilds--; node = node->father; } } void ADTree6F :: GetIntersecting (const float * bmin, const float * bmax, Array & pis) const { static Array stack(1000); ADTreeNode6F * node; int dir, i, stacks; stack.SetSize (1000); pis.SetSize(0); stack.Elem(1) = root; stacks = 1; while (stacks) { node = stack.Get(stacks); stacks--; if (node->pi) { if ( node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && node->data[2] >= bmin[2] && node->data[2] <= bmax[2] && node->data[3] >= bmin[3] && node->data[3] <= bmax[3] && node->data[4] >= bmin[4] && node->data[4] <= bmax[4] && node->data[5] >= bmin[5] && node->data[5] <= bmax[5] ) pis.Append (node->pi); } int i1min = (bmin[0] <= node->sep[0]) ? 0 : 1; int i1max = (bmax[0] < node->sep[0]) ? 0 : 1; int i2min = (bmin[1] <= node->sep[1]) ? 0 : 1; int i2max = (bmax[1] < node->sep[1]) ? 0 : 1; int i3min = (bmin[2] <= node->sep[2]) ? 0 : 1; int i3max = (bmax[2] < node->sep[2]) ? 0 : 1; int i4min = (bmin[3] <= node->sep[3]) ? 0 : 1; int i4max = (bmax[3] < node->sep[3]) ? 0 : 1; int i5min = (bmin[4] <= node->sep[4]) ? 0 : 1; int i5max = (bmax[4] < node->sep[4]) ? 0 : 1; int i6min = (bmin[5] <= node->sep[5]) ? 0 : 1; int i6max = (bmax[5] < node->sep[5]) ? 0 : 1; int i1, i2, i3, i4, i5, i6; for (i1 = i1min; i1 <= i1max; i1++) for (i2 = i2min; i2 <= i2max; i2++) for (i3 = i3min; i3 <= i3max; i3++) for (i4 = i4min; i4 <= i4max; i4++) for (i5 = i5min; i5 <= i5max; i5++) for (i6 = i6min; i6 <= i6max; i6++) { i = i1 + 2*i2 + 4*i3 + 8*i4 + 16*i5 +32*i6; if (node->childs[i]) { stacks++; stack.Elem(stacks) = node->childs[i]; } } /* if (node->left && bmin[dir] <= node->sep) { stacks++; stack.Elem(stacks) = node->left; stackdir.Elem(stacks) = ndir; } if (node->right && bmax[dir] >= node->sep) { stacks++; stack.Elem(stacks) = node->right; stackdir.Elem(stacks) = ndir; } */ } } void ADTree6F :: PrintRec (ostream & ost, const ADTreeNode6F * node) const { int i; if (node->data) { ost << node->pi << ": "; ost << node->nchilds << " childs, "; for (i = 0; i < 6; i++) ost << node->data[i] << " "; ost << endl; } for (i = 0; i < 64; i++) if (node->childs[i]) PrintRec (ost, node->childs[i]); } #endif /* ************************************* Point3dTree ********************** */ Point3dTree :: Point3dTree (const Point<3> & pmin, const Point<3> & pmax) { float pmi[3], pma[3]; for (int i = 0; i < 3; i++) { pmi[i] = pmin(i); pma[i] = pmax(i); } tree = new ADTree3 (pmi, pma); } Point3dTree :: ~Point3dTree () { delete tree; } void Point3dTree :: Insert (const Point<3> & p, int pi) { float pd[3]; pd[0] = p(0); pd[1] = p(1); pd[2] = p(2); tree->Insert (pd, pi); } void Point3dTree :: GetIntersecting (const Point<3> & pmin, const Point<3> & pmax, Array & pis) const { float pmi[3], pma[3]; for (int i = 0; i < 3; i++) { pmi[i] = pmin(i); pma[i] = pmax(i); } tree->GetIntersecting (pmi, pma, pis); } template BoxTree :: BoxTree (const Box & abox) { boxpmin = abox.PMin(); boxpmax = abox.PMax(); Point<2*dim> tpmin, tpmax; for (int i = 0; i < dim; i++) { tpmin(i) = tpmin(i+dim) = boxpmin(i); tpmax(i) = tpmax(i+dim) = boxpmax(i); } tree = new T_ADTree<2*dim,T> (tpmin, tpmax); } template BoxTree :: BoxTree (const Point & apmin, const Point & apmax) { boxpmin = apmin; boxpmax = apmax; Point<2*dim> tpmin, tpmax; for (int i = 0; i < dim; i++) { tpmin(i) = tpmin(i+dim) = boxpmin(i); tpmax(i) = tpmax(i+dim) = boxpmax(i); } tree = new T_ADTree<2*dim,T> (tpmin, tpmax); } template BoxTree :: ~BoxTree () { delete tree; } template void BoxTree :: Insert (const Point & bmin, const Point & bmax, T pi) { Point<2*dim> tp; for (size_t i = 0; i < dim; i++) { tp(i) = bmin(i); tp(i+dim) = bmax(i); } tree->Insert (tp, pi); } template void BoxTree ::GetIntersecting (const Point & pmin, const Point & pmax, Array & pis) const { Point<2*dim> tpmin, tpmax; double tol = Tolerance(); for (size_t i = 0; i < dim; i++) { tpmin(i) = boxpmin(i); tpmax(i) = pmax(i)+tol; tpmin(i+dim) = pmin(i)-tol; tpmax(i+dim) = boxpmax(i); } tree->GetIntersecting (tpmin, tpmax, pis); } template<> BlockAllocator T_ADTreeNode<4,INDEX> :: ball(sizeof (T_ADTreeNode<4,INDEX>)); template class T_ADTree<4,INDEX>; template class BoxTree<2,INDEX>; template<> BlockAllocator T_ADTreeNode<4,INDEX_2> :: ball(sizeof (T_ADTreeNode<4,INDEX_2>)); template class T_ADTree<4,INDEX_2>; template class BoxTree<2,INDEX_2>; template<> BlockAllocator T_ADTreeNode<6,INDEX> :: ball(sizeof (T_ADTreeNode<6,INDEX>)); template class T_ADTree<6,INDEX>; template class BoxTree<3,INDEX>; } netgen-6.2.1905/libsrc/gprim/transform3d.cpp0000644000175000017500000001026313504650527017345 0ustar kurtkurt#include #include #include #include namespace netgen { Transformation3d :: Transformation3d () { for (int i = 0; i < 3; i++) { offset[i] = 0; for (int j = 0; j < 3; j++) lin[i][j] = 0; } } Transformation3d :: Transformation3d (const Vec3d & translate) { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) lin[i][j] = 0; for (int i = 0; i < 3; i++) { offset[i] = translate.X(i+1); lin[i][i] = 1; } } Transformation3d :: Transformation3d (const Point3d & c, double alpha, double beta, double gamma) { // total = T_c x Rot_0 x T_c^{-1} // Use Euler angles, see many books from tech mech, e.g. // Shabana "multibody systems" Transformation3d tc(c); Transformation3d tcinv; tc.CalcInverse (tcinv); Transformation3d r1, r2, r3, ht, ht2; r1.SetAxisRotation (3, alpha); r2.SetAxisRotation (1, beta); r3.SetAxisRotation (3, gamma); ht.Combine (tc, r3); ht2.Combine (ht, r2); ht.Combine (ht2, r1); Combine (ht, tcinv); // cout << "Rotation - Transformation:" << (*this) << endl; // (*testout) << "Rotation - Transformation:" << (*this) << endl; } Transformation3d :: Transformation3d (const Point3d ** pp) { for (int i = 1; i <= 3; i++) { offset[i-1] = (*pp[0]).X(i); for (int j = 1; j <= 3; j++) lin[i-1][j-1] = (*pp[j]).X(i) - (*pp[0]).X(i); } } Transformation3d :: Transformation3d (const Point3d pp[]) { for (int i = 1; i <= 3; i++) { offset[i-1] = pp[0].X(i); for (int j = 1; j <= 3; j++) lin[i-1][j-1] = pp[j].X(i) - pp[0].X(i); } } void Transformation3d :: CalcInverse (Transformation3d & inv) const { static DenseMatrix a(3), inva(3); static Vector b(3), sol(3); for (int i = 0; i < 3; i++) { b(i) = offset[i]; for (int j = 0; j < 3; j++) a(i, j) = lin[i][j]; } ::netgen::CalcInverse (a, inva); inva.Mult (b, sol); for (int i = 0; i < 3; i++) { inv.offset[i] = -sol(i); for (int j = 0; j < 3; j++) inv.lin[i][j] = inva(i, j); } } void Transformation3d:: Combine (const Transformation3d & ta, const Transformation3d & tb) { // o = o_a+ m_a o_b // m = m_a m_b for (int i = 0; i <= 2; i++) { offset[i] = ta.offset[i]; for (int j = 0; j <= 2; j++) offset[i] += ta.lin[i][j] * tb.offset[j]; } for (int i = 0; i <= 2; i++) for (int j = 0; j <= 2; j++) { lin[i][j] = 0; for (int k = 0; k <= 2; k++) lin[i][j] += ta.lin[i][k] * tb.lin[k][j]; } } void Transformation3d :: SetAxisRotation (int dir, double alpha) { double co = cos(alpha); double si = sin(alpha); dir--; int pos1 = (dir+1) % 3; int pos2 = (dir+2) % 3; int i, j; for (i = 0; i <= 2; i++) { offset[i] = 0; for (j = 0; j <= 2; j++) lin[i][j] = 0; } lin[dir][dir] = 1; lin[pos1][pos1] = co; lin[pos2][pos2] = co; lin[pos1][pos2] = si; lin[pos2][pos1] = -si; } ostream & operator<< (ostream & ost, Transformation3d & trans) { ost << "offset = "; for (int i = 0; i <= 2; i++) ost << trans.offset[i] << " "; ost << endl << "linear = " << endl; for (int i = 0; i <= 2; i++) { for (int j = 0; j <= 2; j++) ost << trans.lin[i][j] << " "; ost << endl; } return ost; } template <> Transformation<3> :: Transformation (const Point<3> & c, const Vec<3> & axes, double angle) { Vec<3> vc(c); Transformation<3> tc(vc); Transformation<3> tcinv(-vc); Transformation<3> r, ht, ht2; // r.SetAxisRotation (3, alpha); Vec<3> naxes = axes; naxes.Normalize(); Vec<3> n1 = naxes.GetNormal(); Vec<3> n2 = Cross(naxes, n1); r.v = Vec<3>(0,0,0); double co = cos(angle); double si = sin(angle); for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) r.m(i,j) = naxes(i)*naxes(j) + co*(n1(i)*n1(j)+n2(i)*n2(j)) + si*( (n2(i)*n1(j)-n2(j)*n1(i)) ); ht.Combine (tc, r); Combine (ht, tcinv); } template Transformation :: Transformation (const Point * pp) { v = Vec (pp[0]); for (int i = 0; i < D; i++) for (int j = 0; j < D; j++) m(j,i) = pp[i+1](j)-pp[0](j); } template class Transformation<3>; } netgen-6.2.1905/libsrc/gprim/geomfuncs.cpp0000644000175000017500000000425113504650527017071 0ustar kurtkurt#include #include #include namespace netgen { /* // template <> inline void CalcInverse (const Mat<2,2> & m, Mat<2,2> & inv) { double det = m(0,0) * m(1,1) - m(0,1) * m(1,0); if (det == 0) { inv = 0; return; } double idet = 1.0 / det; inv(0,0) = idet * m(1,1); inv(0,1) = -idet * m(0,1); inv(1,0) = -idet * m(1,0); inv(1,1) = idet * m(0,0); } */ // template <> void CalcInverse (const Mat<3,3> & m, Mat<3,3> & inv) { double det = Det (m); if (det == 0) { inv = 0; return; } double idet = 1.0 / det; inv(0,0) = idet * (m(1,1) * m(2,2) - m(1,2) * m(2,1)); inv(1,0) = -idet * (m(1,0) * m(2,2) - m(1,2) * m(2,0)); inv(2,0) = idet * (m(1,0) * m(2,1) - m(1,1) * m(2,0)); inv(0,1) = -idet * (m(0,1) * m(2,2) - m(0,2) * m(2,1)); inv(1,1) = idet * (m(0,0) * m(2,2) - m(0,2) * m(2,0)); inv(2,1) = -idet * (m(0,0) * m(2,1) - m(0,1) * m(2,0)); inv(0,2) = idet * (m(0,1) * m(1,2) - m(0,2) * m(1,1)); inv(1,2) = -idet * (m(0,0) * m(1,2) - m(0,2) * m(1,0)); inv(2,2) = idet * (m(0,0) * m(1,1) - m(0,1) * m(1,0)); } /* // template <> void CalcInverse (const Mat<2,3> & m, Mat<3,2> & inv) { Mat<2,2> a = m * Trans (m); Mat<2,2> ainv; CalcInverse (a, ainv); inv = Trans (m) * ainv; } */ double Det (const Mat<2,2> & m) { return m(0,0) * m(1,1) - m(0,1) * m(1,0); } double Det (const Mat<3,3> & m) { return m(0,0) * m(1,1) * m(2,2) + m(1,0) * m(2,1) * m(0,2) + m(2,0) * m(0,1) * m(1,2) - m(0,0) * m(2,1) * m(1,2) - m(1,0) * m(0,1) * m(2,2) - m(2,0) * m(1,1) * m(0,2); } void EigenValues (const Mat<3,3> & m, Vec<3> & ev) { const double pi = 3.141592; double a, b, c, d; double p, q; double arg; a = -1.; b = m(0,0) + m(1,1) + m(2,2); c = -( m(0,0)*m(2,2) + m(1,1)*m(2,2) + m(0,0)*m(1,1) - sqr(m(0,1)) - sqr(m(0,2)) - sqr(m(1,2)) ); d = Det (m); p = 3.*a*c - sqr(b); q = 27.*sqr(a)*d - 9.*a*b*c + 2.*sqr(b)*b; arg = acos((-q/2)/sqrt(-(p*p*p))); ev(0) = (2. * sqrt(-p) * cos(arg/3.) - b) / 3.*a; ev(1) = (-2. * sqrt(-p) * cos(arg/3.+pi/3) - b) / 3.*a; ev(2) = (-2. * sqrt(-p) * cos(arg/3.-pi/3)- b) / 3.*a; } } netgen-6.2.1905/libsrc/gprim/geomobjects2.hpp0000644000175000017500000001516713504650527017503 0ustar kurtkurt#ifndef FILE_OBJECTS #define FILE_OBJECTS /* *************************************************************************/ /* File: geomobjects.hpp */ /* Author: Joachim Schoeberl */ /* Date: 20. Jul. 02 */ /* *************************************************************************/ template class VecExpr { public: VecExpr () { ; } double operator() (int i) const { return static_cast (*this) (i); } }; template class Vec; template class Point; template class Point : public VecExpr > { protected: double x[D]; public: Point () { ; } Point (double ax) { x[0] = ax; } Point (double ax, double ay) { x[0] = ax; x[1] = ay; } Point (double ax, double ay, double az) { x[0] = ax; x[1] = ay; x[2] = az; } Point (double ax, double ay, double az, double au) { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au;} Point (const Point & p2) { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } explicit Point (const Vec & v) { for (int i = 0; i < D; i++) x[i] = v(i); } template explicit Point (const VecExpr & expr) { for (int i = 0; i < D; i++) x[i] = expr(i); } Point & operator= (const Point & p2) { for (int i = 0; i < D; i++) x[i] = p2.x[i]; return *this; } template Point & operator= (const VecExpr & expr) { for (int i = 0; i < D; i++) x[i] = expr(i); return *this; } double & operator() (int i) { return x[i]; } const double & operator() (int i) const { return x[i]; } operator const double* () const { return x; } }; template class Vec : public VecExpr > { protected: double x[D]; public: Vec () { ; } Vec (double ax) { for (int i = 0; i < D; i++) x[i] = ax; } Vec (double ax, double ay) { x[0] = ax; x[1] = ay; } Vec (double ax, double ay, double az) { x[0] = ax; x[1] = ay; x[2] = az; } Vec (double ax, double ay, double az, double au) { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au; } Vec (const Vec & p2) { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } explicit Vec (const Point & p) { for (int i = 0; i < D; i++) x[i] = p(i); } template explicit Vec (const VecExpr & expr) { for (int i = 0; i < D; i++) x[i] = expr(i); } Vec & operator= (const Vec & p2) { for (int i = 0; i < D; i++) x[i] = p2.x[i]; return *this; } template Vec & operator= (const VecExpr & expr) { for (int i = 0; i < D; i++) x[i] = expr(i); return *this; } Vec & operator= (double s) { for (int i = 0; i < D; i++) x[i] = s; return *this; } double & operator() (int i) { return x[i]; } const double & operator() (int i) const { return x[i]; } operator const double* () const { return x; } double Length () const { double l = 0; for (int i = 0; i < D; i++) l += x[i] * x[i]; return sqrt (l); } double Length2 () const { double l = 0; for (int i = 0; i < D; i++) l += x[i] * x[i]; return l; } const Vec & Normalize () { double l = Length(); if (l != 0) for (int i = 0; i < D; i++) x[i] /= l; return *this; } Vec GetNormal () const; }; template class Mat { protected: double x[H*W]; public: Mat () { ; } Mat (const Mat & b) { for (int i = 0; i < H*W; i++) x[i] = b.x[i]; } Mat & operator= (double s) { for (int i = 0; i < H*W; i++) x[i] = s; return *this; } Mat & operator= (const Mat & b) { for (int i = 0; i < H*W; i++) x[i] = b.x[i]; return *this; } double & operator() (int i, int j) { return x[i*W+j]; } const double & operator() (int i, int j) const { return x[i*W+j]; } Vec Col (int i) const { Vec hv; for (int j = 0; j < H; j++) hv(j) = x[j*W+i]; return hv; } Vec Row (int i) const { Vec hv; for (int j = 0; j < W; j++) hv(j) = x[i*W+j]; return hv; } void Solve (const Vec & rhs, Vec & sol) const { Mat inv; CalcInverse (*this, inv); sol = inv * rhs; } }; template class Box { protected: Point pmin, pmax; public: Box () { ; } Box ( const Point & p1, const Point & p2) { for (int i = 0; i < D; i++) { pmin(i) = min2(p1(i), p2(i)); pmax(i) = max2(p1(i), p2(i)); } } const Point & PMin () const { return pmin; } const Point & PMax () const { return pmax; } void Set (const Point & p) { pmin = pmax = p; } void Add (const Point & p) { for (int i = 0; i < D; i++) { if (p(i) < pmin(i)) pmin(i) = p(i); else if (p(i) > pmax(i)) pmax(i) = p(i); } } Point Center () const { Point c; for (int i = 0; i < D; i++) c(i) = 0.5 * (pmin(i)+pmax(i)); return c; } double Diam () const { return Abs (pmax-pmin); } Point GetPointNr (int nr) const { Point p; for (int i = 0; i < D; i++) { p(i) = (nr & 1) ? pmax(i) : pmin(i); nr >>= 1; } return p; } bool Intersect (const Box & box2) const { for (int i = 0; i < D; i++) if (pmin(i) > box2.pmax(i) || pmax(i) < box2.pmin(i)) return 0; return 1; } bool IsIn (const Point & p) const { for (int i = 0; i < D; i++) if (p(i) < pmin(i) || p(i) > pmax(i)) return 0; return 1; } void Increase (double dist) { for (int i = 0; i < D; i++) { pmin(i) -= dist; pmax(i) += dist; } } }; template class BoxSphere : public Box { protected: /// Point c; /// double diam; /// double inner; public: /// BoxSphere () { }; /// BoxSphere ( Point pmin, Point pmax ) : Box (pmin, pmax) { CalcDiamCenter(); } /// const Point & Center () const { return c; } /// double Diam () const { return diam; } /// double Inner () const { return inner; } /// void GetSubBox (int nr, BoxSphere & sbox) const { for (int i = 0; i < D; i++) { if (nr & 1) { sbox.pmin(i) = c(i); sbox.pmax(i) = this->pmax(i); } else { sbox.pmin(i) = this->pmin(i); sbox.pmax(i) = c(i); } sbox.c(i) = 0.5 * (sbox.pmin(i) + sbox.pmax(i)); nr >>= 1; } sbox.diam = 0.5 * diam; sbox.inner = 0.5 * inner; } /// void CalcDiamCenter () { c = Box::Center (); diam = Dist (this->pmin, this->pmax); inner = this->pmax(0) - this->pmin(0); for (int i = 1; i < D; i++) if (this->pmax(i) - this->pmin(i) < inner) inner = this->pmax(i) - this->pmin(i); } }; #endif netgen-6.2.1905/libsrc/gprim/geomtest3d.cpp0000644000175000017500000005441313504650527017166 0ustar kurtkurt#include #include #include #include namespace netgen { int IntersectTriangleLine (const Point<3> ** tri, const Point<3> ** line) { Vec3d vl(*line[0], *line[1]); Vec3d vt1(*tri[0], *tri[1]); Vec3d vt2(*tri[0], *tri[2]); Vec3d vrs(*tri[0], *line[0]); // static DenseMatrix a(3), ainv(3); // static Vector rs(3), lami(3); Mat<3,3> a, ainv; Vec<3> rs, lami; int i; /* (*testout) << "Tri-Line inters: " << endl << "tri = " << *tri[0] << ", " << *tri[1] << ", " << *tri[2] << endl << "line = " << *line[0] << ", " << *line[1] << endl; */ for (i = 0; i < 3; i++) { a(i, 0) = -vl.X(i+1); a(i, 1) = vt1.X(i+1); a(i, 2) = vt2.X(i+1); rs(i) = vrs.X(i+1); } // double det = a.Det(); double det = Det(a); double arel = vl.Length() * vt1.Length() * vt2.Length(); /* double amax = 0; for (i = 1; i <= 9; i++) if (fabs (a.Get(i)) > amax) amax = fabs(a.Get(i)); */ // new !!!! if (fabs (det) <= 1e-10 * arel) { #ifdef DEVELOP // line parallel to triangle ! // cout << "ERROR: IntersectTriangleLine degenerated" << endl; // (*testout) << "WARNING: IntersectTriangleLine degenerated\n"; /* (*testout) << "lin-tri intersection: " << endl << "line = " << *line[0] << " - " << *line[1] << endl << "tri = " << *tri[0] << " - " << *tri[1] << " - " << *tri[2] << endl << "lami = " << lami << endl << "pc = " << ( *line[0] + lami.Get(1) * vl ) << endl << " = " << ( *tri[0] + lami.Get(2) * vt1 + lami.Get(3) * vt2) << endl << " a = " << a << endl << " ainv = " << ainv << endl << " det(a) = " << det << endl << " rs = " << rs << endl; */ #endif return 0; } CalcInverse (a, ainv); // ainv.Mult (rs, lami); lami = ainv * rs; // (*testout) << "lami = " << lami << endl; double eps = 1e-6; if ( (lami(0) >= -eps && lami(0) <= 1+eps && lami(1) >= -eps && lami(2) >= -eps && lami(1) + lami(2) <= 1+eps) && ! (lami(0) >= eps && lami(0) <= 1-eps && lami(1) >= eps && lami(2) >= eps && lami(1) + lami(2) <= 1-eps) ) { #ifdef DEVELOP // cout << "WARNING: IntersectTriangleLine degenerated" << endl; (*testout) << "WARNING: IntersectTriangleLine numerical inexact" << endl; (*testout) << "lin-tri intersection: " << endl << "line = " << *line[0] << " - " << *line[1] << endl << "tri = " << *tri[0] << " - " << *tri[1] << " - " << *tri[2] << endl << "lami = " << lami << endl << "pc = " << ( *line[0] + lami(0) * vl ) << endl << " = " << ( *tri[0] + lami(1) * vt1 + lami(2) * vt2) << endl << " a = " << a << endl << " ainv = " << ainv << endl << " det(a) = " << det << endl << " rs = " << rs << endl; #endif } if (lami(0) >= 0 && lami(0) <= 1 && lami(1) >= 0 && lami(2) >= 0 && lami(1) + lami(2) <= 1) { return 1; } return 0; } int IntersectTetTriangle (const Point<3> ** tet, const Point<3> ** tri, const int * tetpi, const int * tripi) { int i, j; double diam = Dist (*tri[0], *tri[1]); double epsrel = 1e-8; double eps = diam * epsrel; double eps2 = eps * eps; int cnt = 0; int tetp1 = -1, tetp2 = -1; int trip1 = -1, trip2 = -1; int tetp3, tetp4, trip3; /* for (i = 0; i < 4; i++) loctetpi[i] = -1; */ if (!tetpi) { for (i = 0; i <= 2; i++) { // loctripi[i] = -1; for (j = 0; j <= 3; j++) { if (Dist2 (*tet[j], *tri[i]) < eps2) { // loctripi[i] = j; // loctetpi[j] = i; cnt++; tetp2 = tetp1; tetp1 = j; trip2 = trip1; trip1 = i; break; } } } } else { for (i = 0; i <= 2; i++) { // loctripi[i] = -1; for (j = 0; j <= 3; j++) { if (tetpi[j] == tripi[i]) { // loctripi[i] = j; // loctetpi[j] = i; cnt++; tetp2 = tetp1; tetp1 = j; trip2 = trip1; trip1 = i; break; } } } } // (*testout) << "cnt = " << cnt << endl; // (*testout) << "tet-trig inters, cnt = " << cnt << endl; // cnt .. number of common points switch (cnt) { case 0: { Vec3d no, n; int inpi[3]; // check, if some trigpoint is in tet: for (j = 0; j < 3; j++) inpi[j] = 1; for (i = 1; i <= 4; i++) { int pi1 = i % 4; int pi2 = (i+1) % 4; int pi3 = (i+2) % 4; int pi4 = (i+3) % 4; Vec3d v1 (*tet[pi1], *tet[pi2]); Vec3d v2 (*tet[pi1], *tet[pi3]); Vec3d v3 (*tet[pi1], *tet[pi4]); Cross (v1, v2, n); // n /= n.Length(); double nl = n.Length(); if (v3 * n > 0) n *= -1; int outeri = 1; for (j = 0; j < 3; j++) { Vec3d v(*tet[pi1], *tri[j]); if ( v * n < eps * nl) outeri = 0; else inpi[j] = 0; } if (outeri) return 0; } if (inpi[0] || inpi[1] || inpi[2]) { return 1; } // check, if some tet edge intersects triangle: const Point<3> * line[2], *tetf[3]; for (i = 0; i <= 2; i++) for (j = i+1; j <= 3; j++) { line[0] = tet[i]; line[1] = tet[j]; if (IntersectTriangleLine (tri, &line[0])) return 1; } // check, if triangle line intersects tet face: for (i = 0; i <= 3; i++) { for (j = 0; j <= 2; j++) tetf[j] = tet[(i+j) % 4]; for (j = 0; j <= 2; j++) { line[0] = tri[j]; line[1] = tri[(j+1) % 3]; if (IntersectTriangleLine (&tetf[0], &line[0])) return 1; } } return 0; //GH break; } case 1: { trip2 = 0; while (trip2 == trip1) trip2++; trip3 = 3 - trip1 - trip2; tetp2 = 0; while (tetp2 == tetp1) tetp2++; tetp3 = 0; while (tetp3 == tetp1 || tetp3 == tetp2) tetp3++; tetp4 = 6 - tetp1 - tetp2 - tetp3; Vec3d vtri1 = *tri[trip2] - *tri[trip1]; Vec3d vtri2 = *tri[trip3] - *tri[trip1]; Vec3d ntri; Cross (vtri1, vtri2, ntri); // tri durch tet ? // fehlt noch // test 3 tet-faces: for (i = 1; i <= 3; i++) { Vec3d vtet1, vtet2; switch (i) { case 1: { vtet1 = *tet[tetp2] - *tet[tetp1]; vtet2 = *tet[tetp3] - *tet[tetp1]; break; } case 2: { vtet1 = *tet[tetp3] - *tet[tetp1]; vtet2 = *tet[tetp4] - *tet[tetp1]; break; } case 3: { vtet1 = *tet[tetp4] - *tet[tetp1]; vtet2 = *tet[tetp2] - *tet[tetp1]; break; } } Vec3d ntet; Cross (vtet1, vtet2, ntet); Vec3d crline = Cross (ntri, ntet); double lcrline = crline.Length(); if (lcrline < eps * eps * eps * eps) // new change ! continue; if (vtri1 * crline + vtri2 * crline < 0) crline *= -1; crline /= lcrline; double lam1, lam2, lam3, lam4; LocalCoordinates (vtri1, vtri2, crline, lam1, lam2); LocalCoordinates (vtet1, vtet2, crline, lam3, lam4); if (lam1 > -epsrel && lam2 > -epsrel && lam3 > -epsrel && lam4 > -epsrel) { /* (*testout) << "lcrline = " << lcrline << " eps = " << eps << " diam = " << diam << endl; (*testout) << "hit, cnt == 1 " << "lam1,2,3,4 = " << lam1 << ", " << lam2 << ", " << lam3 << ", " << lam4 << "\n"; */ return 1; } } return 0; //GH break; } case 2: { // common edge tetp3 = 0; while (tetp3 == tetp1 || tetp3 == tetp2) tetp3++; tetp4 = 6 - tetp1 - tetp2 - tetp3; trip3 = 3 - trip1 - trip2; // (*testout) << "trip1,2,3 = " << trip1 << ", " << trip2 << ", " << trip3 << endl; // (*testout) << "tetp1,2,3,4 = " << tetp1 << ", " << tetp2 // << ", " << tetp3 << ", " << tetp4 << endl; Vec3d vtri = *tri[trip3] - *tri[trip1]; Vec3d vtet1 = *tet[tetp3] - *tri[trip1]; Vec3d vtet2 = *tet[tetp4] - *tri[trip1]; Vec3d n = *tri[trip2] - *tri[trip1]; n /= n.Length(); vtet1 -= (n * vtet1) * n; vtet2 -= (n * vtet2) * n; double lam1, lam2; LocalCoordinates (vtet1, vtet2, vtri, lam1, lam2); if (lam1 < -epsrel || lam2 < -epsrel) return 0; else { /* (*testout) << "vtet1 = " << vtet1 << endl; (*testout) << "vtet2 = " << vtet2 << endl; (*testout) << "vtri = " << vtri << endl; (*testout) << "lam1 = " << lam1 << " lam2 = " << lam2 << endl; (*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2)) << " = " << (vtet1 * vtri) << endl; (*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2)) << " = " << (vtet2 * vtri) << endl; (*testout) << "tet = "; for (j = 0; j < 4; j++) (*testout) << (*tet[j]) << " "; (*testout) << endl; (*testout) << "tri = "; for (j = 0; j < 3; j++) (*testout) << (*tri[j]) << " "; (*testout) << endl; (*testout) << "hit, cnt == 2" << endl; */ return 1; } break; } case 3: { // common face return 0; } } (*testout) << "hit, cnt = " << cnt << endl; return 1; } int IntersectTetTriangleRef (const Point<3> ** tri, const int * tripi) { int i, j; double eps = 1e-8; // double eps2 = eps * eps; static Point<3> rtetp1(0, 0, 0); static Point<3> rtetp2(1, 0, 0); static Point<3> rtetp3(0, 1, 0); static Point<3> rtetp4(0, 0, 1); static const Point<3> * tet[] = { &rtetp1, &rtetp2, &rtetp3, &rtetp4 }; static int tetpi[] = { 1, 2, 3, 4 }; // return IntersectTetTriangle (tet, tri, tetpi, tripi); int cnt = 0; int tetp1 = -1, tetp2 = -1; int trip1 = -1, trip2 = -1; int tetp3, tetp4, trip3; /* if (!tetpi) { for (i = 0; i <= 2; i++) { for (j = 0; j <= 3; j++) { if (Dist2 (*tet[j], *tri[i]) < eps2) { cnt++; tetp2 = tetp1; tetp1 = j; trip2 = trip1; trip1 = i; break; } } } } else */ { for (i = 0; i <= 2; i++) { for (j = 0; j <= 3; j++) { if (tetpi[j] == tripi[i]) { cnt++; tetp2 = tetp1; tetp1 = j; trip2 = trip1; trip1 = i; break; } } } } // (*testout) << "cnt = " << cnt << endl; switch (cnt) { case 0: { Vec3d no, n; // int inpi[3]; int pside[3][4]; for (j = 0; j < 3; j++) { pside[j][0] = (*tri[j])(0) > -eps; pside[j][1] = (*tri[j])(1) > -eps; pside[j][2] = (*tri[j])(2) > -eps; pside[j][3] = (*tri[j])(0) + (*tri[j])(1) + (*tri[j])(2) < 1+eps; } for (j = 0; j < 4; j++) { if (!pside[0][j] && !pside[1][j] && !pside[2][j]) return 0; } for (j = 0; j < 3; j++) { if (pside[j][0] && pside[j][1] && pside[j][2] && pside[j][3]) return 1; } const Point<3> * line[2], *tetf[3]; for (i = 0; i <= 2; i++) for (j = i+1; j <= 3; j++) { line[0] = tet[i]; line[1] = tet[j]; if (IntersectTriangleLine (tri, &line[0])) return 1; } for (i = 0; i <= 3; i++) { for (j = 0; j <= 2; j++) tetf[j] = tet[(i+j) % 4]; for (j = 0; j <= 2; j++) { line[0] = tri[j]; line[1] = tri[(j+1) % 3]; if (IntersectTriangleLine (&tetf[0], &line[0])) return 1; } } return 0; break; } case 1: { trip2 = 0; if (trip2 == trip1) trip2++; trip3 = 3 - trip1 - trip2; tetp2 = 0; while (tetp2 == tetp1) tetp2++; tetp3 = 0; while (tetp3 == tetp1 || tetp3 == tetp2) tetp3++; tetp4 = 6 - tetp1 - tetp2 - tetp3; Vec3d vtri1 = *tri[trip2] - *tri[trip1]; Vec3d vtri2 = *tri[trip3] - *tri[trip1]; Vec3d ntri; Cross (vtri1, vtri2, ntri); // tri durch tet ? /* Vec3d vtet1(*tet[tetp1], *tet[tetp2]); Vec3d vtet2(*tet[tetp1], *tet[tetp3]); Vec3d vtet3(*tet[tetp1], *tet[tetp4]); Vec3d sol; SolveLinearSystem (vtet1, vtet2, vtet3, vtri1, sol); if (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0) return 1; SolveLinearSystem (vtet1, vtet2, vtet3, vtri2, sol); if (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0) return 1; */ // test 3 tet-faces: for (i = 1; i <= 3; i++) { Vec3d vtet1, vtet2; switch (i) { case 1: { vtet1 = *tet[tetp2] - *tet[tetp1]; vtet2 = *tet[tetp3] - *tet[tetp1]; break; } case 2: { vtet1 = *tet[tetp3] - *tet[tetp1]; vtet2 = *tet[tetp4] - *tet[tetp1]; break; } case 3: { vtet1 = *tet[tetp4] - *tet[tetp1]; vtet2 = *tet[tetp2] - *tet[tetp1]; break; } } Vec3d ntet; Cross (vtet1, vtet2, ntet); Vec3d crline = Cross (ntri, ntet); double lcrline = crline.Length(); if (lcrline < eps * eps) continue; if (vtri1 * crline + vtri2 * crline < 0) crline *= -1; double lam1, lam2, lam3, lam4; LocalCoordinates (vtri1, vtri2, crline, lam1, lam2); LocalCoordinates (vtet1, vtet2, crline, lam3, lam4); if (lam1 > -eps && lam2 > -eps && lam3 > -eps && lam4 > -eps) { // (*testout) << "hit, cnt == 1" << "\n"; return 1; } } return 0; break; } case 2: { // common edge tetp3 = 0; while (tetp3 == tetp1 || tetp3 == tetp2) tetp3++; tetp4 = 6 - tetp1 - tetp2 - tetp3; trip3 = 3 - trip1 - trip2; // (*testout) << "trip1,2,3 = " << trip1 << ", " << trip2 << ", " << trip3 << endl; // (*testout) << "tetp1,2,3,4 = " << tetp1 << ", " << tetp2 // << ", " << tetp3 << ", " << tetp4 << endl; Vec3d vtri = *tri[trip3] - *tri[trip1]; Vec3d vtet1 = *tet[tetp3] - *tri[trip1]; Vec3d vtet2 = *tet[tetp4] - *tri[trip1]; Vec3d n = *tri[trip2] - *tri[trip1]; n /= n.Length(); vtet1 -= (n * vtet1) * n; vtet2 -= (n * vtet2) * n; double lam1, lam2; LocalCoordinates (vtet1, vtet2, vtri, lam1, lam2); if (lam1 < -eps || lam2 < -eps) return 0; else { // (*testout) << "vtet1 = " << vtet1 << endl; // (*testout) << "vtet2 = " << vtet2 << endl; // (*testout) << "vtri = " << vtri << endl; // (*testout) << "lam1 = " << lam1 << " lam2 = " << lam2 << endl; // (*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2)) // << " = " << (vtet1 * vtri) << endl; // (*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2)) // << " = " << (vtet2 * vtri) << endl; // (*testout) << "tet = "; // for (j = 0; j < 4; j++) // (*testout) << (*tet[j]) << " "; // (*testout) << endl; // (*testout) << "tri = "; // for (j = 0; j < 3; j++) // (*testout) << (*tri[j]) << " "; // (*testout) << endl; // (*testout) << "hit, cnt == 2" << endl; return 1; } break; } case 3: { // common face return 0; } } (*testout) << "hit, cnt = " << cnt << endl; return 1; } int IntersectTriangleTriangle (const Point<3> ** tri1, const Point<3> ** tri2) { int i, j; double diam = Dist (*tri1[0], *tri1[1]); double epsrel = 1e-8; double eps = diam * epsrel; double eps2 = eps * eps; int cnt = 0; /* int tri1pi[3]; int tri2pi[3]; */ // int tri1p1 = -1; /// int tri1p2 = -1; // int tri2p1 = -1; // int tri2p2 = -1; // int tri1p3, tri2p3; /* for (i = 0; i < 3; i++) tri1pi[i] = -1; */ for (i = 0; i <= 2; i++) { // tri2pi[i] = -1; for (j = 0; j <= 2; j++) { if (Dist2 (*tri1[j], *tri2[i]) < eps2) { // tri2pi[i] = j; // tri1pi[j] = i; cnt++; // tri1p2 = tri1p1; // tri1p1 = j; // tri2p2 = tri2p1; // tri2p1 = i; break; } } } switch (cnt) { case 0: { const Point<3> * line[2]; for (i = 0; i <= 2; i++) { line[0] = tri2[i]; line[1] = tri2[(i+1)%3]; if (IntersectTriangleLine (tri1, &line[0])) { (*testout) << "int1, line = " << *line[0] << " - " << *line[1] << endl; return 1; } } for (i = 0; i <= 2; i++) { line[0] = tri1[i]; line[1] = tri1[(i+1)%3]; if (IntersectTriangleLine (tri2, &line[0])) { (*testout) << "int2, line = " << *line[0] << " - " << *line[1] << endl; return 1; } } break; } default: return 0; } return 0; } void LocalCoordinates (const Vec3d & e1, const Vec3d & e2, const Vec3d & v, double & lam1, double & lam2) { double m11 = e1 * e1; double m12 = e1 * e2; double m22 = e2 * e2; double rs1 = v * e1; double rs2 = v * e2; double det = m11 * m22 - m12 * m12; lam1 = (rs1 * m22 - rs2 * m12)/det; lam2 = (m11 * rs2 - m12 * rs1)/det; } int CalcSphereCenter (const Point<3> ** pts, Point<3> & c) { Vec3d row1 (*pts[0], *pts[1]); Vec3d row2 (*pts[0], *pts[2]); Vec3d row3 (*pts[0], *pts[3]); Vec3d rhs(0.5 * (row1*row1), 0.5 * (row2*row2), 0.5 * (row3*row3)); Transpose (row1, row2, row3); Vec3d sol; if (SolveLinearSystem (row1, row2, row3, rhs, sol)) { (*testout) << "CalcSphereCenter: degenerated" << endl; return 1; } c = *pts[0] + sol; return 0; } int CalcTriangleCenter (const Point3d ** pts, Point3d & c) { static DenseMatrix a(2), inva(2); static Vector rs(2), sol(2); double h = Dist(*pts[0], *pts[1]); Vec3d v1(*pts[0], *pts[1]); Vec3d v2(*pts[0], *pts[2]); rs(0) = v1 * v1; rs(1) = v2 * v2; a(0,0) = 2 * rs(0); a(0,1) = a(1,0) = 2 * (v1 * v2); a(1,1) = 2 * rs(1); if (fabs (a.Det()) <= 1e-12 * h * h) { (*testout) << "CalcTriangleCenter: degenerated" << endl; return 1; } CalcInverse (a, inva); inva.Mult (rs, sol); c = *pts[0]; v1 *= sol(0); v2 *= sol(1); c += v1; c += v2; return 0; } double ComputeCylinderRadius (const Point3d & p1, const Point3d & p2, const Point3d & p3, const Point3d & p4) { Vec3d v12(p1, p2); Vec3d v13(p1, p3); Vec3d v14(p1, p4); Vec3d n1 = Cross (v12, v13); Vec3d n2 = Cross (v14, v12); double n1l = n1.Length(); double n2l = n2.Length(); n1 /= n1l; n2 /= n2l; double v12len = v12.Length(); double h1 = n1l / v12len; double h2 = n2l / v12len; /* (*testout) << "n1 = " << n1 << " n2 = " << n2 << "h1 = " << h1 << " h2 = " << h2 << endl; */ return ComputeCylinderRadius (n1, n2, h1, h2); } /* Two triangles T1 and T2 have normals n1 and n2. The height over the common edge is h1, and h2. */ double ComputeCylinderRadius (const Vec3d & n1, const Vec3d & n2, double h1, double h2) { Vec3d t1, t2; double n11 = n1 * n1; double n12 = n1 * n2; double n22 = n2 * n2; double det = n11 * n22 - n12 * n12; if (fabs (det) < 1e-14 * n11 * n22) return 1e20; // a biorthogonal bases (ti * nj) = delta_ij: t1 = (n22/det) * n1 + (-n12/det) * n2; t2 = (-n12/det) * n1 + (n11/det) * n2; // normalize: t1 /= t1.Length(); t2 /= t2.Length(); /* vector to center point has form v = lam1 n1 + lam2 n2 and fulfills t2 v = h1/2 t1 v = h2/2 */ double lam1 = 0.5 * h2 / (n1 * t1); double lam2 = 0.5 * h1 / (n2 * t2); double rad = (lam1 * n1 + lam2 * n2).Length(); /* (*testout) << "n1 = " << n1 << " n2 = " << n2 << " t1 = " << t1 << " t2 = " << t2 << " rad = " << rad << endl; */ return rad; } double MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p) { Vec2d v(lp1, lp2); Vec2d vlp(lp1, p); // dist(lam) = \| vlp \|^2 - 2 lam (v1p, v) + lam^2 \| v \|^2 // lam = (v * vlp) / (v * v); // if (lam < 0) lam = 0; // if (lam > 1) lam = 1; double num = v*vlp; double den = v*v; if (num <= 0) return Dist2 (lp1, p); if (num >= den) return Dist2 (lp2, p); if (den > 0) { return vlp.Length2() - num * num /den; } else return vlp.Length2(); } double MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p) { Vec3d v(lp1, lp2); Vec3d vlp(lp1, p); // dist(lam) = \| vlp \|^2 - 2 lam (v1p, v) + lam^2 \| v \|^2 // lam = (v * vlp) / (v * v); // if (lam < 0) lam = 0; // if (lam > 1) lam = 1; double num = v*vlp; double den = v*v; if (num <= 0) return Dist2 (lp1, p); if (num >= den) return Dist2 (lp2, p); if (den > 0) { return vlp.Length2() - num * num /den; } else return vlp.Length2(); } double MinDistTP2 (const Point3d & tp1, const Point3d & tp2, const Point3d & tp3, const Point3d & p) { double lam1, lam2; double res; LocalCoordinates (Vec3d (tp1, tp2), Vec3d (tp1, tp3), Vec3d (tp1, p), lam1, lam2); int in1 = lam1 >= 0; int in2 = lam2 >= 0; int in3 = lam1+lam2 <= 1; if (in1 && in2 && in3) { Point3d pp = tp1 + lam1 * Vec3d(tp1, tp2) + lam2 * Vec3d (tp1, tp3); res = Dist2 (p, pp); } else { res = Dist2 (tp1, p); if (!in1) { double hv = MinDistLP2 (tp1, tp3, p); if (hv < res) res = hv; } if (!in2) { double hv = MinDistLP2 (tp1, tp2, p); if (hv < res) res = hv; } if (!in3) { double hv = MinDistLP2 (tp2, tp3, p); if (hv < res) res = hv; } /* double d1 = MinDistLP2 (tp1, tp2, p); double d2 = MinDistLP2 (tp1, tp3, p); double d3 = MinDistLP2 (tp2, tp3, p); res = min3 (d1, d2, d3); */ } return res; Vec3d pp1(tp1, p); Vec3d v1(tp1, tp2), v2(tp1, tp3); double c = pp1.Length2(); double cx = -2 * (pp1 * v1); double cy = -2 * (pp1 * v2); double cxx = v1.Length2(); double cxy = 2 * (v1 * v2); double cyy = v2.Length2(); QuadraticPolynomial2V pol (-c, -cx, -cy, -cxx, -cxy, -cyy); double res2 = - pol.MaxUnitTriangle (); if (fabs (res - res2) > 1e-8) cout << "res and res2 differ: " << res << " != " << res2 << endl; return res2; } // 0 checks !!! double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2, const Point3d & l2p1, const Point3d & l2p2) { // dist(lam1,lam2) = \| l2p1+lam2v2 - (l1p1+lam1 v1) \| // min ! Vec3d l1l2 (l1p1, l2p1); Vec3d v1 (l1p1, l1p2); Vec3d v2 (l2p1, l2p2); double a11, a12, a22, rs1, rs2; double lam1, lam2, det; a11 = v1*v1; a12 = -(v1*v2); a22 = v2*v2; rs1 = l1l2 * v1; rs2 = - (l1l2 * v2); det = a11 * a22 - a12 * a12; if (det < 1e-14 * a11 * a22) det = 1e-14 * a11 * a22; // regularization should be stable if (det < 1e-20) det = 1e-20; lam1 = (a22 * rs1 - a12 * rs2) / det; lam2 = (-a12 * rs1 + a11 * rs2) / det; if (lam1 >= 0 && lam2 >= 0 && lam1 <= 1 && lam2 <= 1) { Vec3d v = l1l2 + (-lam1) * v1 + lam2 * v2; return v.Length2(); } double minv, hv; minv = MinDistLP2 (l1p1, l1p2, l2p1); hv = MinDistLP2 (l1p1, l1p2, l2p2); if (hv < minv) minv = hv; hv = MinDistLP2 (l2p1, l2p2, l1p1); if (hv < minv) minv = hv; hv = MinDistLP2 (l2p1, l2p2, l1p2); if (hv < minv) minv = hv; return minv; } } netgen-6.2.1905/libsrc/gprim/geom2d.hpp0000644000175000017500000005222713504650527016273 0ustar kurtkurt#ifndef FILE_GEOM2D #define FILE_GEOM2D /* *************************************************************************/ /* File: geom2d.hh */ /* Author: Joachim Schoeberl */ /* Date: 5. Aug. 95 */ /* *************************************************************************/ namespace netgen { /* Geometric Algorithms */ #define EPSGEOM 1E-5 // extern void MyError (const char * ch); class Point2d; class Vec2d; class LINE2D; class Line2d; class PLine2d; class TRIANGLE2D; class PTRIANGLE2D; inline Vec2d operator- (const Point2d & p1, const Point2d & p2); inline Point2d operator- (const Point2d & p1, const Vec2d & v); inline Point2d operator+ (const Point2d & p1, const Vec2d & v); inline Point2d Center (const Point2d & p1, const Point2d & p2); inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2); inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v); ostream & operator<<(ostream & s, const Point2d & p); inline Vec2d operator- (const Point2d & p1, const Point2d & p2); inline Point2d operator- (const Point2d & p1, const Vec2d & v); inline Point2d operator+ (const Point2d & p1, const Vec2d & v); inline Vec2d operator- (const Vec2d & p1, const Vec2d & v); inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v); inline Vec2d operator* (double scal, const Vec2d & v); DLL_HEADER double Angle (const Vec2d & v); DLL_HEADER double FastAngle (const Vec2d & v); DLL_HEADER double Angle (const Vec2d & v1, const Vec2d & v2); DLL_HEADER double FastAngle (const Vec2d & v1, const Vec2d & v2); ostream & operator<<(ostream & s, const Vec2d & v); double Dist2(const Line2d & g, const Line2d & h ); // GH int Near (const Point2d & p1, const Point2d & p2, const double eps); int Parallel (const Line2d & l1, const Line2d & l2, double peps = EPSGEOM); int IsOnLine (const Line2d & l, const Point2d & p, double heps = EPSGEOM); int IsOnLongLine (const Line2d & l, const Point2d & p); int Hit (const Line2d & l1, const Line2d & l2, double heps = EPSGEOM); ostream & operator<<(ostream & s, const Line2d & l); DLL_HEADER Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2); DLL_HEADER Point2d CrossPoint (const Line2d & l1, const Line2d & l2); int Parallel (const PLine2d & l1, const PLine2d & l2, double peps = EPSGEOM); int IsOnLine (const PLine2d & l, const Point2d & p, double heps = EPSGEOM); int IsOnLongLine (const PLine2d & l, const Point2d & p); int Hit (const PLine2d & l1, const Line2d & l2, double heps = EPSGEOM); ostream & operator<<(ostream & s, const Line2d & l); ostream & operator<<(ostream & s, const TRIANGLE2D & t); ostream & operator<<(ostream & s, const PTRIANGLE2D & t); double Dist2 (const Point2d & p1, const Point2d & p2); /// class Point2d { /// friend class Vec2d; protected: /// double px, py; public: /// Point2d() { /* px = py = 0; */ } /// Point2d(double ax, double ay) { px = ax; py = ay; } /// Point2d(const Point2d & p2) { px = p2.px; py = p2.py; } Point2d (const Point<2> & p2) { px = p2(0); py = p2(1); } /// Point2d & operator= (const Point2d & p2) { px = p2.px; py = p2.py; return *this; } /// int operator== (const Point2d & p2) const // GH { return (px == p2.px && py == p2.py) ; } /// double & X() { return px; } /// double & Y() { return py; } /// double X() const { return px; } /// double Y() const { return py; } operator Point<2> () const { return Point<2> (px, py); } /// friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2); /// friend inline Point2d operator- (const Point2d & p1, const Vec2d & v); /// friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v); /// friend inline Point2d Center (const Point2d & p1, const Point2d & p2); const Point2d & SetToMin (const Point2d & p2) { if (p2.px < px) px = p2.px; if (p2.py < py) py = p2.py; return *this; } /// const Point2d & SetToMax (const Point2d & p2) { if (p2.px > px) px = p2.px; if (p2.py > py) py = p2.py; return *this; } /// friend double Dist (const Point2d & p1, const Point2d & p2) { return sqrt ( (p1.px - p2.px) * (p1.px - p2.px) + (p1.py - p2.py) * (p1.py - p2.py) ); } // { return sqrt ( sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ); } /// friend double Dist2 (const Point2d & p1, const Point2d & p2) { return ( (p1.px - p2.px) * (p1.px - p2.px) + (p1.py - p2.py) * (p1.py - p2.py) ); } // { return sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ; } /** Points clock-wise ? Are the points (p1, p2, p3) clock-wise ? */ friend inline int CW (const Point2d & p1, const Point2d & p2, const Point2d & p3) { // return Cross (p2 - p1, p3 - p2) < 0; return (p2.px - p1.px) * (p3.py - p2.py) - (p2.py - p1.py) * (p3.px - p2.px) < 0; } /** Points counter-clock-wise ? Are the points (p1, p2, p3) counter-clock-wise ? */ friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3) { // return Cross (p2 - p1, p3 - p2) > 0; return (p2.px - p1.px) * (p3.py - p2.py) - (p2.py - p1.py) * (p3.px - p2.px) > 0; } /** Points counter-clock-wise ? Are the points (p1, p2, p3) counter-clock-wise ? */ friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3, double eps) { // return Cross (p2 - p1, p3 - p2) > 0; double ax = p2.px - p1.px; double ay = p2.py - p1.py; double bx = p3.px - p2.px; double by = p3.py - p2.py; return ax*by - ay*bx > eps*eps*max2(ax*ax+ay*ay,bx*bx+by*by); } /// friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2); /// friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v); /// friend ostream & operator<<(ostream & s, const Point2d & p); }; inline int Near (const Point2d & p1, const Point2d & p2, const double eps = 1e-4 ) { return Dist2(p1,p2) <= eps*eps; } /// class Vec2d { protected: /// double vx, vy; public: /// Vec2d() { /* vx = vy = 0; */ } /// Vec2d(double ax, double ay) { vx = ax; vy = ay; } /// Vec2d(const Vec2d & v2) { vx = v2.vx; vy = v2.vy; } /// explicit Vec2d(const Vec<2> & v2) { vx = v2(0); vy = v2(1); } /// Vec2d(const Point2d & p1, const Point2d & p2) { vx = p2.px - p1.px; vy = p2.py - p1.py; } /// Vec2d & operator= (const Vec2d & p2) { vx = p2.vx; vy = p2.vy; return *this; } /// double & X() { return vx; } /// double & Y() { return vy; } /// double X() const { return vx; } /// double Y() const { return vy; } /// double Length() const { return sqrt (vx * vx + vy * vy); } /// double Length2() const { return vx * vx + vy * vy; } void GetNormal (Vec2d & n) const { n.vx=-vy; n.vy=vx; } // GH /// inline Vec2d & operator+= (const Vec2d & v2); /// inline Vec2d & operator-= (const Vec2d & v2); /// inline Vec2d & operator*= (double s); /// inline Vec2d & operator/= (double s); /// friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2); /// friend inline Point2d operator- (const Point2d & p1, const Vec2d & v); /// friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v); /// friend inline Vec2d operator- (const Vec2d & p1, const Vec2d & v); /// friend inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v); /// friend inline Vec2d operator* (double scal, const Vec2d & v); /// friend double operator* (const Vec2d & v1, const Vec2d & v2) { return v1.X() * v2.X() + v1.Y() * v2.Y(); } /// friend double Cross (const Vec2d & v1, const Vec2d & v2) { return double(v1.X()) * double(v2.Y()) - double(v1.Y()) * double(v2.X()); } /// friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2); /// friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v); /// Angle in [0,2*PI) /// friend DLL_HEADER double Angle (const Vec2d & v); /// friend DLL_HEADER double FastAngle (const Vec2d & v); /// friend DLL_HEADER double Angle (const Vec2d & v1, const Vec2d & v2); /// friend DLL_HEADER double FastAngle (const Vec2d & v1, const Vec2d & v2); /// friend ostream & operator<<(ostream & s, const Vec2d & v); }; /// class Line2d { protected: /// Point2d p1, p2; public: /// Line2d() : p1(), p2() { }; /// Line2d(const Point2d & ap1, const Point2d & ap2) { p1 = ap1; p2 = ap2; } /// Line2d & operator= (const Line2d & l2) { p1 = l2.p1; p2 = l2.p2; return *this;} /// Point2d & P1() { return p1; } /// Point2d & P2() { return p2; } /// const Point2d & P1() const { return p1; } /// const Point2d & P2() const { return p2; } /// double XMax() const { return max2 (p1.X(), p2.X()); } /// double YMax() const { return max2 (p1.Y(), p2.Y()); } /// double XMin() const { return min2 (p1.X(), p2.X()); } /// double YMin() const { return min2 (p1.Y(), p2.Y()); } /// Vec2d Delta () const { return Vec2d (p2.X()-p1.X(), p2.Y()-p1.Y()); } /// double Length () const { return Delta().Length(); } /// double Length2 () const { return sqr (p1.X() - p2.X()) + sqr (p1.Y() - p2.Y()); } void GetNormal (Line2d & n) const; // GH Vec2d NormalDelta () const; // GH /// square of the distance between two 2d-lines. friend double Dist2(const Line2d & g, const Line2d & h ); // GH /// friend DLL_HEADER Point2d CrossPoint (const Line2d & l1, const Line2d & l2); /// returns 1 iff parallel friend int CrossPointBarycentric (const Line2d & l1, const Line2d & l2, double & lam1, double & lam2); /// friend int Parallel (const Line2d & l1, const Line2d & l2, double peps); /// friend int IsOnLine (const Line2d & l, const Point2d & p, double heps); /// friend int IsOnLongLine (const Line2d & l, const Point2d & p); /// friend int Hit (const Line2d & l1, const Line2d & l2, double heps); /// friend ostream & operator<<(ostream & s, const Line2d & l); }; #ifdef NONE /// class PLine2d { protected: /// Point2d const * p1, *p2; public: /// PLine2d() { }; /// PLine2d(Point2d const * ap1, Point2d const * ap2) { p1 = ap1; p2 = ap2; } /// PLine2d & operator= (const PLine2d & l2) { p1 = l2.p1; p2 = l2.p2; return *this;} /// const Point2d *& P1() { return p1; } /// const Point2d *& P2() { return p2; } /// const Point2d & P1() const { return *p1; } /// const Point2d & P2() const { return *p2; } /// double XMax() const { return max2 (p1->X(), p2->X()); } /// double YMax() const { return max2 (p1->Y(), p2->Y()); } /// double XMin() const { return min2 (p1->X(), p2->X()); } /// double YMin() const { return min2 (p1->Y(), p2->Y()); } /// Vec2d Delta () const { return Vec2d (p2->X()-p1->X(), p2->Y()-p1->Y()); } /// double Length () const { return Delta().Length(); } /// double Length2 () const { return sqr (p1->X() - p2->X()) + sqr (p1->Y() - p2->Y()); } /// friend Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2); /// friend int Parallel (const PLine2d & l1, const PLine2d & l2, double peps); /// friend int IsOnLine (const PLine2d & l, const Point2d & p, double heps); /// friend int IsOnLongLine (const PLine2d & l, const Point2d & p); /// friend int Hit (const PLine2d & l1, const Line2d & l2, double heps); /// friend ostream & operator<<(ostream & s, const Line2d & l); }; /// class ILINE { /// INDEX i[2]; public: /// ILINE() {}; /// ILINE(INDEX i1, INDEX i2) { i[0] = i1; i[1] = i2; } /// ILINE(const ILINE & l) { i[0] = l.i[0]; i[1] = l.i[1]; } /// ILINE & operator= (const ILINE & l) { i[0] = l.i[0]; i[1] = l.i[1]; return *this; } /// const INDEX & I(int ai) const { return i[ai-1]; } /// const INDEX & X() const { return i[0]; } /// const INDEX & Y() const { return i[1]; } /// const INDEX & I1() const { return i[0]; } /// const INDEX & I2() const { return i[1]; } /// INDEX & I(int ai) { return i[ai-1]; } /// INDEX & X() { return i[0]; } /// INDEX & Y() { return i[1]; } /// INDEX & I1() { return i[0]; } /// INDEX & I2() { return i[1]; } }; /// class TRIANGLE2D { private: /// Point2d p1, p2, p3; public: /// TRIANGLE2D() { }; /// TRIANGLE2D (const Point2d & ap1, const Point2d & ap2, const Point2d & ap3) { p1 = ap1; p2 = ap2; p3 = ap3;} /// TRIANGLE2D & operator= (const TRIANGLE2D & t2) { p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; } /// Point2d & P1() { return p1; } /// Point2d & P2() { return p2; } /// Point2d & P3() { return p3; } /// const Point2d & P1() const { return p1; } /// const Point2d & P2() const { return p2; } /// const Point2d & P3() const { return p3; } /// double XMax() const { return max3 (p1.X(), p2.X(), p3.X()); } /// double YMax() const { return max3 (p1.Y(), p2.Y(), p3.Y()); } /// double XMin() const { return min3 (p1.X(), p2.X(), p3.X()); } /// double YMin() const { return min3 (p1.Y(), p2.Y(), p3.Y()); } /// inline Point2d Center () const { return Point2d( (p1.X()+p2.X()+p3.X())/3, (p1.Y()+p2.Y()+p3.Y())/3); } /// int Regular() const; /// int CW () const; /// int CCW () const; /// int IsOn (const Point2d & p) const; /// int IsIn (const Point2d & p) const; /// friend ostream & operator<<(ostream & s, const TRIANGLE2D & t); }; /// class PTRIANGLE2D { private: /// Point2d const *p1, *p2, *p3; public: /// PTRIANGLE2D() { }; /// PTRIANGLE2D (const Point2d * ap1, const Point2d * ap2, const Point2d * ap3) { p1 = ap1; p2 = ap2; p3 = ap3;} /// PTRIANGLE2D & operator= (const PTRIANGLE2D & t2) { p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; } /// const Point2d *& P1() { return p1; } /// const Point2d *& P2() { return p2; } /// const Point2d *& P3() { return p3; } /// const Point2d * P1() const { return p1; } /// const Point2d * P2() const { return p2; } /// const Point2d * P3() const { return p3; } /// double XMax() const { return max3 (p1->X(), p2->X(), p3->X()); } /// double YMax() const { return max3 (p1->Y(), p2->Y(), p3->Y()); } /// double XMin() const { return min3 (p1->X(), p2->X(), p3->X()); } /// double YMin() const { return min3 (p1->Y(), p2->Y(), p3->Y()); } /// Point2d Center () const { return Point2d( (p1->X()+p2->X()+p3->X())/3, (p1->Y()+p2->Y()+p3->Y())/3); } /// int Regular() const; /// int CW () const; /// int CCW () const; /// int IsOn (const Point2d & p) const; /// int IsIn (const Point2d & p) const; /// friend ostream & operator<<(ostream & s, const PTRIANGLE2D & t); }; #endif class Polygon2d { protected: Array points; public: Polygon2d (); ~Polygon2d (); void AddPoint (const Point2d & p); int GetNP() const { return points.Size(); } void GetPoint (int i, Point2d & p) const { p = points.Get(i); } void GetLine (int i, Point2d & p1, Point2d & p2) const { p1 = points.Get(i); p2 = points.Get(i%points.Size()+1); } double Area () const { return fabs (HArea()); } int CW () const { return HArea() > 0; } int CCW () const { return HArea() < 0; } int IsOn (const Point2d & p) const; int IsIn (const Point2d & p) const; int IsConvex () const; int IsStarPoint (const Point2d & p) const; Point2d Center() const; Point2d EqualAreaPoint () const; private: double HArea () const; }; /** Cheap approximation to atan2. A monotone function of atan2(x,y) is computed. */ extern double Fastatan2 (double x, double y); inline Vec2d & Vec2d :: operator+= (const Vec2d & v2) { vx += v2.vx; vy += v2.vy; return *this; } inline Vec2d & Vec2d :: operator-= (const Vec2d & v2) { vx -= v2.vx; vy -= v2.vy; return *this; } inline Vec2d & Vec2d :: operator*= (double s) { vx *= s; vy *= s; return *this; } inline Vec2d & Vec2d :: operator/= (double s) { if (s != 0) { vx /= s; vy /= s; } else { MyError ("Vec2d::operator /=: Division by zero"); } return *this; } inline Vec2d operator- (const Point2d & p1, const Point2d & p2) { return Vec2d (p1.X() - p2.X(), p1.Y() - p2.Y()); } inline Point2d operator- (const Point2d & p1, const Vec2d & v) { return Point2d (p1.X() - v.X(), p1.Y() - v.Y()); } inline Point2d operator+ (const Point2d & p1, const Vec2d & v) { return Point2d (p1.X() + v.X(), p1.Y() + v.Y()); } inline Point2d Center (const Point2d & p1, const Point2d & p2) { return Point2d ((p1.X() + p2.X()) / 2, (p1.Y() + p2.Y()) / 2); } inline Vec2d operator- (const Vec2d & v1, const Vec2d & v2) { return Vec2d (v1.X() - v2.X(), v1.Y() - v2.Y()); } inline Vec2d operator+ (const Vec2d & v1, const Vec2d & v2) { return Vec2d (v1.X() + v2.X(), v1.Y() + v2.Y()); } inline Vec2d operator* (double scal, const Vec2d & v) { return Vec2d (scal * v.X(), scal * v.Y()); } inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2) { p2.X() = p1.X() + s * v.X(); p2.Y() = p1.Y() + s * v.Y(); } inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v) { v.X() = p1.X() - p2.X(); v.Y() = p1.Y() - p2.Y(); } #ifdef none inline int TRIANGLE2D :: Regular() const { return fabs(Cross ( p2 - p1, p3 - p2)) > EPSGEOM; } inline int TRIANGLE2D :: CW () const { return Cross ( p2 - p1, p3 - p2) < 0; } inline int TRIANGLE2D :: CCW () const { return Cross ( p2 - p1, p3 - p2) > 0; } inline int PTRIANGLE2D :: Regular() const { return fabs(Cross ( *p2 - *p1, *p3 - *p2)) > EPSGEOM; } inline int PTRIANGLE2D :: CW () const { return Cross ( *p2 - *p1, *p3 - *p2) < 0; } inline int PTRIANGLE2D :: CCW () const { return Cross ( *p2 - *p1, *p3 - *p2) > 0; } #endif /// class Mat2d { protected: /// double coeff[4]; public: /// Mat2d() { coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0; } /// Mat2d(double a11, double a12, double a21, double a22) { coeff[0] = a11; coeff[1] = a12; coeff[2] = a21; coeff[3] = a22; } /// Mat2d(const Mat2d & m2) { for (int i = 0; i < 4; i++) coeff[i] = m2.Get(i); } /// double & Elem (INDEX i, INDEX j) { return coeff[2*(i-1)+j-1]; } /// double & Elem (INDEX i) {return coeff[i]; } /// double Get (INDEX i, INDEX j) const { return coeff[2*(i-1)+j-1]; } /// double Get (INDEX i) const {return coeff[i]; } /// double Det () const { return coeff[0] * coeff[3] - coeff[1] * coeff[2]; } /// void Mult (const Vec2d & v, Vec2d & prod) const; /// void MultTrans (const Vec2d & v , Vec2d & prod) const; /// void Solve (const Vec2d & rhs, Vec2d & x) const; /// Solves mat * x = rhs, but using a positive definite matrix instead of mat void SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const; /// add a term \alpha * v * v^T void AddDiadicProduct (double alpha, Vec2d & v); }; inline void Mat2d :: Mult (const Vec2d & v, Vec2d & prod) const { prod.X() = coeff[0] * v.X() + coeff[1] * v.Y(); prod.Y() = coeff[2] * v.X() + coeff[3] * v.Y(); } inline void Mat2d :: MultTrans (const Vec2d & v, Vec2d & prod) const { prod.X() = coeff[0] * v.X() + coeff[2] * v.Y(); prod.Y() = coeff[1] * v.X() + coeff[3] * v.Y(); } inline void Mat2d :: Solve (const Vec2d & rhs, Vec2d & x) const { double det = Det(); if (det == 0) MyError ("Mat2d::Solve: zero determinant"); else { x.X() = (coeff[3] * rhs.X() - coeff[1] * rhs.Y()) / det; x.Y() = (-coeff[2] * rhs.X() + coeff[0] * rhs.Y()) / det; } } inline void Mat2d :: SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const { double a = max2(coeff[0], 1e-8); double b = coeff[1] / a; double c = coeff[2] / a; double d = max2(coeff[3] - a *b * c, 1e-8); x.X() = (rhs.X() - b * rhs.Y()) / a; x.Y() = rhs.Y() / d - c * x.X(); } inline void Mat2d :: AddDiadicProduct (double alpha, Vec2d & v) { coeff[0] += alpha * v.X() * v.X(); coeff[1] += alpha * v.X() * v.Y(); coeff[2] += alpha * v.Y() * v.X(); coeff[3] += alpha * v.Y() * v.Y(); } } #endif netgen-6.2.1905/libsrc/gprim/spline.hpp0000644000175000017500000004264013504650527016406 0ustar kurtkurt#ifndef FILE_SPLINE_HPP #define FILE_SPLINE_HPP /**************************************************************************/ /* File: spline.hpp */ /* Author: Joachim Schoeberl */ /* Date: 24. Jul. 96 */ /**************************************************************************/ namespace netgen { /* Spline curves for 2D mesh generation */ /// Geometry point template < int D > class GeomPoint : public Point { public: /// refinement factor at point double refatpoint; /// max mesh-size at point double hmax; /// hp-refinement double hpref; /// string name; /// GeomPoint () { ; } /// GeomPoint (const Point & ap, double aref = 1, double ahpref=0) : Point(ap), refatpoint(aref), hmax(1e99), hpref(ahpref) { ; } void DoArchive(Archive& ar) { Point::DoArchive(ar); ar & refatpoint & hmax & hpref; } }; /// base class for 2d - segment template < int D > class SplineSeg { public: SplineSeg () { ; } /// virtual ~SplineSeg() { ; } /// calculates length of curve virtual double Length () const; /// returns point at curve, 0 <= t <= 1 virtual Point GetPoint (double t) const = 0; /// returns a (not necessarily unit-length) tangent vector for 0 <= t <= 1 virtual Vec GetTangent (const double t) const { cerr << "GetTangent not implemented for spline base-class" << endl; Vec dummy; return dummy; } virtual void GetDerivatives (const double t, Point & point, Vec & first, Vec & second) const { double eps = 1e-6; point = GetPoint (t); Point pl = GetPoint (t-eps); Point pr = GetPoint (t+eps); first = 1.0/(2*eps) * (pr-pl); second = 1.0/sqr(eps) * ( (pr-point)+(pl-point)); } virtual void DoArchive(Archive& ar) = 0; /// returns initial point on curve virtual const GeomPoint & StartPI () const = 0; /// returns terminal point on curve virtual const GeomPoint & EndPI () const = 0; /** writes curve description for fepp: for implicitly given quadratic curves, the 6 coefficients of the polynomial $$ a x^2 + b y^2 + c x y + d x + e y + f = 0 $$ are written to ost */ void PrintCoeff (ostream & ost) const; virtual void GetCoeff (Vector & coeffs) const = 0; virtual void GetCoeff (Vector & coeffs, Point p0) const { ; } virtual void GetPoints (int n, Array > & points) const; /** calculates (2D) lineintersections: for lines $$ a x + b y + c = 0 $$ the interecting points are calculated and stored in points */ virtual void LineIntersections (const double a, const double b, const double c, Array < Point > & points, const double eps) const {points.SetSize(0);} // is the point in the convex hull (increased by eps) of the spline ? virtual bool InConvexHull (Point p, double eps) const = 0; virtual double MaxCurvature(void) const = 0; virtual string GetType(void) const {return "splinebase";} virtual void Project (const Point point, Point & point_on_curve, double & t) const { cerr << "Project not implemented for spline base-class" << endl;} virtual void GetRawData (Array & data) const { cerr << "GetRawData not implemented for spline base-class" << endl;} }; /// Straight line form p1 to p2 template< int D > class LineSeg : public SplineSeg { /// GeomPoint p1, p2; public: /// LineSeg (const GeomPoint & ap1, const GeomPoint & ap2); /// // default constructor for archive LineSeg() {} virtual void DoArchive(Archive& ar) { ar & p1 & p2; } virtual double Length () const; /// inline virtual Point GetPoint (double t) const; /// virtual Vec GetTangent (const double t) const; virtual void GetDerivatives (const double t, Point & point, Vec & first, Vec & second) const; /// virtual const GeomPoint & StartPI () const { return p1; }; /// virtual const GeomPoint & EndPI () const { return p2; } /// virtual void GetCoeff (Vector & coeffs) const; virtual void GetCoeff (Vector & coeffs, Point p0) const; virtual string GetType(void) const {return "line";} virtual void LineIntersections (const double a, const double b, const double c, Array < Point > & points, const double eps) const; virtual bool InConvexHull (Point p, double eps) const { return MinDistLP2 (p1, p2, p) < sqr(eps); } virtual double MaxCurvature(void) const {return 0;} virtual void Project (const Point point, Point & point_on_curve, double & t) const; virtual void GetRawData (Array & data) const; }; /// curve given by a rational, quadratic spline (including ellipses) template< int D > class SplineSeg3 : public SplineSeg { /// GeomPoint p1, p2, p3; double weight; mutable double proj_latest_t; public: /// SplineSeg3 (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); // default constructor for archive SplineSeg3() {} /// virtual void DoArchive(Archive& ar) { ar & p1 & p2 & p3 & weight & proj_latest_t; } virtual Point GetPoint (double t) const; /// virtual Vec GetTangent (const double t) const; DLL_HEADER virtual void GetDerivatives (const double t, Point & point, Vec & first, Vec & second) const; /// virtual const GeomPoint & StartPI () const { return p1; }; /// virtual const GeomPoint & EndPI () const { return p3; } /// virtual void GetCoeff (Vector & coeffs) const; virtual void GetCoeff (Vector & coeffs, Point p0) const; virtual string GetType(void) const {return "spline3";} const GeomPoint & TangentPoint (void) const { return p2; } DLL_HEADER virtual void LineIntersections (const double a, const double b, const double c, Array < Point > & points, const double eps) const; virtual bool InConvexHull (Point p, double eps) const { return MinDistTP2 (p1, p2, p3, p) < sqr(eps); } DLL_HEADER virtual double MaxCurvature(void) const; DLL_HEADER virtual void Project (const Point point, Point & point_on_curve, double & t) const; DLL_HEADER virtual void GetRawData (Array & data) const; }; // Gundolf Haase 8/26/97 /// A circle template < int D > class CircleSeg : public SplineSeg { /// private: GeomPoint p1, p2, p3; //const GeomPoint &p1, &p2, &p3; Point pm; double radius, w1,w3; public: /// CircleSeg (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); // default constructor for archive CircleSeg() {} virtual void DoArchive(Archive& ar) { ar & p1 & p2 & p3 & pm & radius & w1 & w3; } /// virtual Point GetPoint (double t) const; /// virtual const GeomPoint & StartPI () const { return p1; } /// virtual const GeomPoint & EndPI () const { return p3; } /// virtual void GetCoeff (Vector & coeffs) const; /// double Radius() const { return radius; } /// double StartAngle() const { return w1; } /// double EndAngle() const { return w3; } /// const Point & MidPoint(void) const {return pm; } virtual string GetType(void) const {return "circle";} virtual void LineIntersections (const double a, const double b, const double c, Array < Point > & points, const double eps) const; virtual bool InConvexHull (Point p, double eps) const { return (Dist2 (p, pm) < sqr(radius+eps)); } virtual double MaxCurvature(void) const {return 1./radius;} }; /// template class DiscretePointsSeg : public SplineSeg { Array > pts; GeomPoint p1n, p2n; public: /// DiscretePointsSeg (const Array > & apts); // default constructor for archive DiscretePointsSeg() {} virtual void DoArchive(Archive& ar) { ar & pts & p1n & p2n; } /// virtual ~DiscretePointsSeg (); /// virtual Point GetPoint (double t) const; /// virtual const GeomPoint & StartPI () const { return p1n; }; /// virtual const GeomPoint & EndPI () const { return p2n; } /// virtual void GetCoeff (Vector & coeffs) const {;} virtual double MaxCurvature(void) const {return 1;} // needs implementation ... virtual bool InConvexHull (Point p, double eps) const { return true; } }; // calculates length of spline-curve template double SplineSeg :: Length () const { int n = 100; double dt = 1.0 / n; Point pold = GetPoint (0); double l = 0; for (int i = 1; i <= n; i++) { Point p = GetPoint (i * dt); l += Dist (p, pold); pold = p; } return l; } template void SplineSeg :: GetPoints (int n, Array > & points) const { points.SetSize (n); if (n >= 2) for (int i = 0; i < n; i++) points[i] = GetPoint(double(i) / (n-1)); } template void SplineSeg :: PrintCoeff (ostream & ost) const { Vector u(6); GetCoeff(u); for ( int i=0; i<6; i++) ost << u[i] << " "; ost << endl; } /* Implementation of line-segment from p1 to p2 */ template LineSeg :: LineSeg (const GeomPoint & ap1, const GeomPoint & ap2) : p1(ap1), p2(ap2) { ; } template inline Point LineSeg :: GetPoint (double t) const { return p1 + t * (p2 - p1); } template Vec LineSeg :: GetTangent (const double t) const { return p2-p1; } template void LineSeg :: GetDerivatives (const double t, Point & point, Vec & first, Vec & second) const { first = p2 - p1; point = p1 + t * first; second = 0; } template double LineSeg :: Length () const { return Dist (p1, p2); } template void LineSeg :: GetCoeff (Vector & coeffs) const { coeffs.SetSize(6); double dx = p2(0) - p1(0); double dy = p2(1) - p1(1); coeffs[0] = coeffs[1] = coeffs[2] = 0; coeffs[3] = -dy; coeffs[4] = dx; coeffs[5] = -dx * p1(1) + dy * p1(0); } template void LineSeg :: GetCoeff (Vector & coeffs, Point p) const { coeffs.SetSize(6); double dx = p2(0) - p1(0); double dy = p2(1) - p1(1); coeffs[0] = coeffs[1] = coeffs[2] = 0; coeffs[3] = -dy; coeffs[4] = dx; coeffs[5] = -dx * (p1(1)-p(1)) + dy * (p1(0)-p(0)); } template void LineSeg :: LineIntersections (const double a, const double b, const double c, Array < Point > & points, const double eps) const { points.SetSize(0); double denom = -a*p2(0)+a*p1(0)-b*p2(1)+b*p1(1); if(fabs(denom) < 1e-20) return; double t = (a*p1(0)+b*p1(1)+c)/denom; if((t > -eps) && (t < 1.+eps)) points.Append(GetPoint(t)); } template void LineSeg :: Project (const Point point, Point & point_on_curve, double & t) const { Vec v = p2-p1; double l = v.Length(); v *= 1./l; t = (point-p1)*v; if(t<0) t = 0; if(t>l) t = l; point_on_curve = p1+t*v; t *= 1./l; } template void LineSeg :: GetRawData (Array & data) const { data.Append(2); for(int i=0; i double SplineSeg3 :: MaxCurvature(void) const { Vec v1 = p1-p2; Vec v2 = p3-p2; double l1 = v1.Length(); double l2 = v2.Length(); (*testout) << "v1 " << v1 << " v2 " << v2 << endl; double cosalpha = v1*v2/(l1*l2); (*testout) << "cosalpha " << cosalpha << endl; return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha)); } */ //######################################################################## // circlesegment template CircleSeg :: CircleSeg (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3) : p1(ap1), p2(ap2), p3(ap3) { Vec v1,v2; v1 = p1 - p2; v2 = p3 - p2; Point p1t(p1+v1); Point p2t(p3+v2); // works only in 2D!!!!!!!!! Line2d g1t,g2t; g1t.P1() = Point<2>(p1(0),p1(1)); g1t.P2() = Point<2>(p1t(0),p1t(1)); g2t.P1() = Point<2>(p3(0),p3(1)); g2t.P2() = Point<2>(p2t(0),p2t(1)); Point<2> mp = CrossPoint (g1t,g2t); pm(0) = mp(0); pm(1) = mp(1); radius = Dist(pm,StartPI()); Vec2d auxv; auxv.X() = p1(0)-pm(0); auxv.Y() = p1(1)-pm(1); w1 = Angle(auxv); auxv.X() = p3(0)-pm(0); auxv.Y() = p3(1)-pm(1); w3 = Angle(auxv); if ( fabs(w3-w1) > M_PI ) { if ( w3>M_PI ) w3 -= 2*M_PI; if ( w1>M_PI ) w1 -= 2*M_PI; } } /* template Point CircleSeg :: GetPoint (double t) const { if (t >= 1.0) { return p3; } double phi = StartAngle() + t*(EndAngle()-StartAngle()); Vec tmp(cos(phi),sin(phi)); return pm + Radius()*tmp; } */ template<> inline Point<3> CircleSeg<3> :: GetPoint (double t) const { // not really useful, but keep it as it was ... if (t >= 1.0) { return p3; } double phi = StartAngle() + t*(EndAngle()-StartAngle()); Vec<3> tmp(cos(phi),sin(phi),0); return pm + Radius()*tmp; } template<> inline Point<2> CircleSeg<2> :: GetPoint (double t) const { if (t >= 1.0) { return p3; } double phi = StartAngle() + t*(EndAngle()-StartAngle()); Vec<2> tmp(cos(phi),sin(phi)); return pm + Radius()*tmp; } template void CircleSeg :: GetCoeff (Vector & coeff) const { coeff[0] = coeff[1] = 1.0; coeff[2] = 0.0; coeff[3] = -2.0 * pm[0]; coeff[4] = -2.0 * pm[1]; coeff[5] = sqr(pm[0]) + sqr(pm[1]) - sqr(Radius()); } template DiscretePointsSeg :: DiscretePointsSeg (const Array > & apts) : pts (apts) { for(int i=0; i DiscretePointsSeg :: ~DiscretePointsSeg () { ; } template Point DiscretePointsSeg :: GetPoint (double t) const { double t1 = t * (pts.Size()-1); int segnr = int(t1); if (segnr < 0) segnr = 0; if (segnr >= pts.Size()) segnr = pts.Size()-1; double rest = t1 - segnr; return pts[segnr] + rest*Vec(pts[segnr+1]-pts[segnr]); } // ************************************* // Template for B-Splines of order ORDER // thx to Gerhard Kitzler // ************************************* template class BSplineSeg : public SplineSeg { Array > pts; GeomPoint p1n, p2n; Array ti; public: /// BSplineSeg (const Array > & apts); /// //default constructor for archive BSplineSeg() {} virtual ~BSplineSeg(); /// virtual void DoArchive(Archive& ar) { ar & pts & p1n & p2n & ti; } virtual Point GetPoint (double t) const; /// virtual const GeomPoint & StartPI () const { return p1n; }; /// virtual const GeomPoint & EndPI () const { return p2n; } /// virtual void GetCoeff (Vector & coeffs) const {;} virtual double MaxCurvature(void) const {return 1;} // needs implementation ... virtual bool InConvexHull (Point p, double eps) const { return true; } }; // Constructor template BSplineSeg :: BSplineSeg (const Array > & apts) : pts (apts) { /* for(int i=0; i BSplineSeg :: ~BSplineSeg () { ; } // GetPoint Method...(evaluation of BSpline Curve) template Point BSplineSeg :: GetPoint (double t_in) const { int m=pts.Size()+ORDER; double t = t_in * (m-2*ORDER+1); double b[ORDER]; int interval_nr = int(t)+ORDER-1; if (interval_nr < ORDER-1) interval_nr = ORDER-1; if (interval_nr > m-ORDER-1) interval_nr = m-ORDER-1; b[ORDER-1] = 1.0; for(int degree=1;degree p = 0.0; for(int i=0; i < ORDER; i++) p += b[i] * Vec (pts[i+interval_nr-ORDER+1]); return p; } } #endif netgen-6.2.1905/libsrc/gprim/transform3d.hpp0000644000175000017500000001073113504650527017352 0ustar kurtkurt#ifndef FILE_TRANSFORM3D #define FILE_TRANSFORM3D /* *************************************************************************/ /* File: transform3d.hh */ /* Author: Joachim Schoeberl */ /* Date: 22. Mar. 98 */ /* *************************************************************************/ /* Affine - Linear mapping in 3D space */ namespace netgen { class Transformation3d; ostream & operator<< (ostream & ost, Transformation3d & trans); class Transformation3d { double lin[3][3]; double offset[3]; public: /// Transformation3d (); /// Unit tet is mapped to tet described by pp Transformation3d (const Point3d ** pp); /// Unit tet is mapped to tet described by pp Transformation3d (const Point3d pp[]); /// translation Transformation3d (const Vec3d & translate); /// rotation with ... Transformation3d (const Point3d & c, double alpha, double beta, double gamma); /// void CalcInverse (Transformation3d & inv) const; /// this = ta x tb void Combine (const Transformation3d & ta, const Transformation3d & tb); /// dir = 1..3 (== x..z) void SetAxisRotation (int dir, double alpha); /// void Transform (const Point3d & from, Point3d & to) const { for (int i = 1; i <= 3; i++) { to.X(i) = offset[i-1] + lin[i-1][0] * from.X(1) + lin[i-1][1] * from.X(2) + lin[i-1][2] * from.X(3); } } /// void Transform (Point3d & p) const { Point3d hp; Transform (p, hp); p = hp; } /// transform vector, apply only linear part, not offset void Transform (const Vec3d & from, Vec3d & to) const { for (int i = 1; i <= 3; i++) { to.X(i) = lin[i-1][0] * from.X(1) + lin[i-1][1] * from.X(2) + lin[i-1][2] * from.X(3); } } friend ostream & operator<< (ostream & ost, Transformation3d & trans); }; template class Transformation { Mat m; Vec v; public: /// Transformation () { m = 0; v = 0; } /// Unit tet is mapped to tet described by pp Transformation (const Point * pp); /// translation Transformation (const Vec & translate) { v = translate; m = 0; for (int i = 0; i < D; i++) m(i,i) = 1; } Transformation (const Point & c, const Vec<3> & axes, double angle); // rotation with ... Transformation (const Point & c, double alpha, double beta, double gamma) { // total = T_c x Rot_0 x T_c^{-1} // Use Euler angles, see many books from tech mech, e.g. // Shabana "multibody systems" Vec vc(c); Transformation tc(vc); Transformation tcinv(-vc); // tc.CalcInverse (tcinv); Transformation r1, r2, r3, ht, ht2; r1.SetAxisRotation (3, alpha); r2.SetAxisRotation (1, beta); r3.SetAxisRotation (3, gamma); ht.Combine (tc, r3); ht2.Combine (ht, r2); ht.Combine (ht2, r1); Combine (ht, tcinv); // cout << "Rotation - Transformation:" << (*this) << endl; // (*testout) << "Rotation - Transformation:" << (*this) << endl; } /// Transformation CalcInverse () const { Transformation inv; // inv.m = Inv(m); ::netgen::CalcInverse (m, inv.m); inv.v = inv.m * (-v); return inv; } /// this = ta x tb void Combine (const Transformation & ta, const Transformation & tb) { v = ta.v + ta.m * tb.v; m = ta.m * tb.m; } /// dir = 1..3 (== x..z) void SetAxisRotation (int dir, double alpha) { double co = cos(alpha); double si = sin(alpha); dir--; int pos1 = (dir+1) % 3; int pos2 = (dir+2) % 3; int i, j; for (i = 0; i <= 2; i++) { v(i) = 0; for (j = 0; j <= 2; j++) m(i,j) = 0; } m(dir,dir) = 1; m(pos1, pos1) = co; m(pos2, pos2) = co; m(pos1, pos2) = si; m(pos2, pos1) = -si; } /// void Transform (const Point & from, Point & to) const { to = Point (v + m * Vec(from)); } void Transform (Point & p) const { p = Point (v + m * Vec(p)); } /// transform vector, apply only linear part, not offset void Transform (const Vec & from, Vec & to) const { to = m * from; } Point operator() (Point from) const { Point to; Transform(from, to); return to; } Vec operator() (Vec from) const { Vec to; Transform(from, to); return to; } }; template ostream & operator<< (ostream & ost, Transformation & trans); } #endif netgen-6.2.1905/libsrc/gprim/splinegeometry.hpp0000644000175000017500000000321213504650527020152 0ustar kurtkurt/* JS, Nov 2007 The 2D/3D template-base classes should go into the libsrc/gprim directory in geom2d only 2D - Geometry classes (with material properties etc.) */ #include "spline.hpp" #ifndef _FILE_SPLINEGEOMETRY #define _FILE_SPLINEGEOMETRY namespace netgen { template < int D > class SplineGeometry { // protected: public: Array < GeomPoint > geompoints; Array < SplineSeg* > splines; SplineGeometry() : geompoints{}, splines{} { ; } DLL_HEADER ~SplineGeometry(); DLL_HEADER int Load (const Array & raw_data, const int startpos = 0); virtual void DoArchive(Archive& ar) { ar & geompoints & splines; } DLL_HEADER void GetRawData (Array & raw_data) const; const Array*> & GetSplines () const { return splines; } int GetNSplines (void) const { return splines.Size(); } string GetSplineType (const int i) const { return splines[i]->GetType(); } SplineSeg & GetSpline (const int i) {return *splines[i];} const SplineSeg & GetSpline (const int i) const {return *splines[i];} DLL_HEADER void GetBoundingBox (Box & box) const; Box GetBoundingBox () const { Box box; GetBoundingBox (box); return box; } int GetNP () const { return geompoints.Size(); } const GeomPoint & GetPoint(int i) const { return geompoints[i]; } // void SetGrading (const double grading); DLL_HEADER void AppendPoint (const Point & p, const double reffac = 1., const bool hpref = false); void AppendSegment(SplineSeg * spline) { splines.Append (spline); } }; } #endif // _FILE_SPLINEGEOMETRY netgen-6.2.1905/libsrc/gprim/geom3d.cpp0000644000175000017500000003715513504650527016272 0ustar kurtkurt#include #include #include #include namespace netgen { ostream & operator<<(ostream & s, const Point3d & p) { return s << "(" << p.x[0] << ", " << p.x[1] << ", " << p.x[2] << ")"; } ostream & operator<<(ostream & s, const Vec3d & v) { return s << "(" << v.x[0] << ", " << v.x[1] << ", " << v.x[2] << ")"; } double Angle (const Vec3d & v1, const Vec3d & v2) { double co = (v1 * v2) / (v1.Length() * v2.Length()); if (co > 1) co = 1; if (co < -1) co = -1; return acos ( co ); } void Vec3d :: GetNormal (Vec3d & n) const { if (fabs (X()) > fabs (Z())) { n.X() = -Y(); n.Y() = X(); n.Z() = 0; } else { n.X() = 0; n.Y() = Z(); n.Z() = -Y(); } double len = n.Length(); if (len == 0) { n.X() = 1; n.Y() = n.Z() = 0; } else n /= len; } /* ostream & operator<<(ostream & s, const ROTDenseMatrix3D & r) { return s << "{ (" << r.txx << ", " << r.txy << ", " << r.txz << ") , (" << r.tyx << ", " << r.tyy << ", " << r.tyz << ") , (" << r.tzx << ", " << r.tzy << ", " << r.tzz << ") }"; } */ /* Vec3d operator- (const Point3d & p1, const Point3d & p2) { return Vec3d (p1.X() - p2.X(), p1.Y() - p2.Y(),p1.Z() - p2.Z()); } Point3d operator- (const Point3d & p1, const Vec3d & v) { return Point3d (p1.X() - v.X(), p1.Y() - v.Y(),p1.Z() - v.Z()); } Point3d operator+ (const Point3d & p1, const Vec3d & v) { return Point3d (p1.X() + v.X(), p1.Y() + v.Y(),p1.Z() + v.Z()); } Vec3d operator- (const Vec3d & v1, const Vec3d & v2) { return Vec3d (v1.X() - v2.X(), v1.Y() - v2.Y(),v1.Z() - v2.Z()); } Vec3d operator+ (const Vec3d & v1, const Vec3d & v2) { return Vec3d (v1.X() + v2.X(), v1.Y() + v2.Y(),v1.Z() + v2.Z()); } Vec3d operator* (double scal, const Vec3d & v) { return Vec3d (scal * v.X(), scal * v.Y(), scal * v.Z()); } */ /* double operator* (const Vec3d & v1, const Vec3d & v2) { return v1.X() * v2.X() + v1.Y() * v2.Y() + v1.Z() * v2.Z(); } double Cross (const Vec3d & v1, const Vec3d & v2) { return v1.X() * v2.Y() - v1.Y() * v2.X(); } */ /* void ROTDenseMatrix3D :: CalcRotMat(double ag, double bg, double lg, double size2, Vec3d r) { size = size2; txx=size * ( cos(bg) * cos(lg) ); txy=size * ( cos(bg) * sin(lg) ); txz=size * (-sin(bg) ); tyx=size * ( sin(ag) * sin(bg) * cos(lg) - cos(ag) * sin(lg) ); tyy=size * ( sin(ag) * sin(bg) * sin(lg) + cos(ag) * cos(lg) ); tyz=size * ( sin(ag) * cos(bg) ); tzx=size * ( cos(ag) * sin(bg) * cos(lg) + sin(ag) * sin(lg) ); tzy=size * ( cos(ag) * sin(bg) * sin(lg) - sin(ag) * cos(lg) ); tzz=size * ( cos(ag) * cos(bg) ); deltaR=r; } ROTDenseMatrix3D :: ROTDenseMatrix3D(double ag, double bg, double lg, double size2, Vec3d r) {CalcRotMat(ag, bg, lg, size2, r); } ROTDenseMatrix3D :: ROTDenseMatrix3D(Vec3d rot2) { Vec3d r2(0,0,0); CalcRotMat(rot2.X(), rot2.Y(), rot2.Z(), 1, r2); } ROTDenseMatrix3D ROTDenseMatrix3D :: INV() { ROTDenseMatrix3D rinv(txx/sqr(size),tyx/sqr(size),tzx/sqr(size), txy/sqr(size),tyy/sqr(size),tzy/sqr(size), txz/sqr(size),tyz/sqr(size),tzz/sqr(size), 1/size,deltaR); return rinv; } Vec3d operator* (const ROTDenseMatrix3D & r, const Vec3d & v) { return Vec3d (r.XX() * v.X() + r.XY() * v.Y() + r.XZ() * v.Z(), r.YX() * v.X() + r.YY() * v.Y() + r.YZ() * v.Z(), r.ZX() * v.X() + r.ZY() * v.Y() + r.ZZ() * v.Z() ); } Point3d operator* (const ROTDenseMatrix3D & r, const Point3d & p) { return Point3d (r.XX() * p.X() + r.XY() * p.Y() + r.XZ() * p.Z(), r.YX() * p.X() + r.YY() * p.Y() + r.YZ() * p.Z(), r.ZX() * p.X() + r.ZY() * p.Y() + r.ZZ() * p.Z() ); } */ Box3d :: Box3d ( double aminx, double amaxx, double aminy, double amaxy, double aminz, double amaxz ) { minx[0] = aminx; maxx[0] = amaxx; minx[1] = aminy; maxx[1] = amaxy; minx[2] = aminz; maxx[2] = amaxz; } Box3d :: Box3d ( const Box3d & b2 ) { for (int i = 0; i < 3; i++) { minx[i] = b2.minx[i]; maxx[i] = b2.maxx[i]; } } Box3d :: Box3d ( const Box<3> & b2 ) { for (int i = 0; i < 3; i++) { minx[i] = b2.PMin()(i); maxx[i] = b2.PMax()(i); } } /* int Box3d :: Intersect (const Box3d & box2) const { int i; for (i = 0; i <= 2; i++) if (minx[i] > box2.maxx[i] || maxx[i] < box2.minx[i]) return 0; return 1; } */ /* void Box3d :: SetPoint (const Point3d & p) { minx[0] = maxx[0] = p.X(); minx[1] = maxx[1] = p.Y(); minx[2] = maxx[2] = p.Z(); } void Box3d :: AddPoint (const Point3d & p) { if (p.X() < minx[0]) minx[0] = p.X(); if (p.X() > maxx[0]) maxx[0] = p.X(); if (p.Y() < minx[1]) minx[1] = p.Y(); if (p.Y() > maxx[1]) maxx[1] = p.Y(); if (p.Z() < minx[2]) minx[2] = p.Z(); if (p.Z() > maxx[2]) maxx[2] = p.Z(); } */ void Box3d :: GetPointNr (int i, Point3d & point) const { i--; point.X() = (i & 1) ? maxx[0] : minx[0]; point.Y() = (i & 2) ? maxx[1] : minx[1]; point.Z() = (i & 4) ? maxx[2] : minx[2]; } void Box3d :: Increase (double d) { for (int i = 0; i <= 2; i++) { minx[i] -= d; maxx[i] += d; } } void Box3d :: IncreaseRel (double /* rel */) { for (int i = 0; i <= 2; i++) { double d = 0.5 * (maxx[i] - minx[i]); minx[i] -= d; maxx[i] += d; } } Box3d :: Box3d (const Point3d& p1, const Point3d& p2) { minx[0] = min2 (p1.X(), p2.X()); minx[1] = min2 (p1.Y(), p2.Y()); minx[2] = min2 (p1.Z(), p2.Z()); maxx[0] = max2 (p1.X(), p2.X()); maxx[1] = max2 (p1.Y(), p2.Y()); maxx[2] = max2 (p1.Z(), p2.Z()); } const Box3d& Box3d :: operator+=(const Box3d& b) { minx[0] = min2 (minx[0], b.minx[0]); minx[1] = min2 (minx[1], b.minx[1]); minx[2] = min2 (minx[2], b.minx[2]); maxx[0] = max2 (maxx[0], b.maxx[0]); maxx[1] = max2 (maxx[1], b.maxx[1]); maxx[2] = max2 (maxx[2], b.maxx[2]); return *this; } Point3d Box3d :: MaxCoords() const { return Point3d(maxx[0], maxx[1], maxx[2]); } Point3d Box3d :: MinCoords() const { return Point3d(minx[0], minx[1], minx[2]); } /* void Box3d :: CreateNegMinMaxBox() { minx[0] = MAXDOUBLE; minx[1] = MAXDOUBLE; minx[2] = MAXDOUBLE; maxx[0] = MINDOUBLE; maxx[1] = MINDOUBLE; maxx[2] = MINDOUBLE; } */ void Box3d :: WriteData(ofstream& fout) const { for(int i = 0; i < 3; i++) { fout << minx[i] << " " << maxx[i] << " "; } fout << "\n"; } void Box3d :: ReadData(ifstream& fin) { for(int i = 0; i < 3; i++) { fin >> minx[i]; fin >> maxx[i]; } } Box3dSphere :: Box3dSphere ( double aminx, double amaxx, double aminy, double amaxy, double aminz, double amaxz ) : Box3d (aminx, amaxx, aminy, amaxy, aminz, amaxz) { CalcDiamCenter (); } void Box3dSphere :: CalcDiamCenter () { diam = sqrt( sqr (maxx[0] - minx[0]) + sqr (maxx[1] - minx[1]) + sqr (maxx[2] - minx[2])); c.X() = 0.5 * (minx[0] + maxx[0]); c.Y() = 0.5 * (minx[1] + maxx[1]); c.Z() = 0.5 * (minx[2] + maxx[2]); inner = min2 ( min2 (maxx[0] - minx[0], maxx[1] - minx[1]), maxx[2] - minx[2]) / 2; } void Box3dSphere :: GetSubBox (int i, Box3dSphere & sbox) const { i--; if (i & 1) { sbox.minx[0] = c.X(); sbox.maxx[0] = maxx[0]; } else { sbox.minx[0] = minx[0]; sbox.maxx[0] = c.X(); } if (i & 2) { sbox.minx[1] = c.Y(); sbox.maxx[1] = maxx[1]; } else { sbox.minx[1] = minx[1]; sbox.maxx[1] = c.Y(); } if (i & 4) { sbox.minx[2] = c.Z(); sbox.maxx[2] = maxx[2]; } else { sbox.minx[2] = minx[2]; sbox.maxx[2] = c.Z(); } // sbox.CalcDiamCenter (); sbox.c.X() = 0.5 * (sbox.minx[0] + sbox.maxx[0]); sbox.c.Y() = 0.5 * (sbox.minx[1] + sbox.maxx[1]); sbox.c.Z() = 0.5 * (sbox.minx[2] + sbox.maxx[2]); sbox.diam = 0.5 * diam; sbox.inner = 0.5 * inner; } /* double Determinant (const Vec3d & col1, const Vec3d & col2, const Vec3d & col3) { return col1.x[0] * ( col2.x[1] * col3.x[2] - col2.x[2] * col3.x[1]) + col1.x[1] * ( col2.x[2] * col3.x[0] - col2.x[0] * col3.x[2]) + col1.x[2] * ( col2.x[0] * col3.x[1] - col2.x[1] * col3.x[0]); } */ void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3) { Swap (v1.Y(), v2.X()); Swap (v1.Z(), v3.X()); Swap (v2.Z(), v3.Y()); } /* gcc4.8.3 warning: array subscript is above array bounds [-Warray-bounds] */ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Warray-bounds" #endif int SolveLinearSystem (const Vec3d & col1, const Vec3d & col2, const Vec3d & col3, const Vec3d & rhs, Vec3d & sol) { // changed by MW double matrix[3][3]; double locrhs[3]; int retval = 0; for(int i=0; i<3; i++) { matrix[i][0] = col1.X(i+1); matrix[i][1] = col2.X(i+1); matrix[i][2] = col3.X(i+1); locrhs[i] = rhs.X(i+1); } for(int i=0; i<2; i++) { int pivot = i; double maxv = fabs(matrix[i][i]); for(int j=i+1; j<3; j++) if(fabs(matrix[j][i]) > maxv) { maxv = fabs(matrix[j][i]); pivot = j; } if(fabs(maxv) > 1e-40) { if(pivot != i) { swap(matrix[i][0],matrix[pivot][0]); swap(matrix[i][1],matrix[pivot][1]); swap(matrix[i][2],matrix[pivot][2]); swap(locrhs[i],locrhs[pivot]); } for(int j=i+1; j<3; j++) { double fac = matrix[j][i] / matrix[i][i]; for(int k=i+1; k<3; k++) matrix[j][k] -= fac*matrix[i][k]; locrhs[j] -= fac*locrhs[i]; } } else retval = 1; } if(fabs(matrix[2][2]) < 1e-40) retval = 1; if(retval != 0) return retval; for(int i=2; i>=0; i--) { double sum = locrhs[i]; for(int j=2; j>i; j--) sum -= matrix[i][j]*sol.X(j+1); sol.X(i+1) = sum/matrix[i][i]; } return 0; /* double det = Determinant (col1, col2, col3); if (fabs (det) < 1e-40) return 1; sol.X() = Determinant (rhs, col2, col3) / det; sol.Y() = Determinant (col1, rhs, col3) / det; sol.Z() = Determinant (col1, col2, rhs) / det; return 0; */ /* Vec3d cr; Cross (col1, col2, cr); double det = cr * col3; if (fabs (det) < 1e-40) return 1; if (fabs(cr.Z()) > 1e-12) { // solve for 3. component sol.Z() = (cr * rhs) / det; // 2x2 system for 1. and 2. component double res1 = rhs.X() - sol.Z() * col3.X(); double res2 = rhs.Y() - sol.Z() * col3.Y(); sol.X() = (col2.Y() * res1 - col2.X() * res2) / cr.Z(); sol.Y() = (col1.X() * res2 - col1.Y() * res1) / cr.Z(); } else { det = Determinant (col1, col2, col3); if (fabs (det) < 1e-40) return 1; sol.X() = Determinant (rhs, col2, col3) / det; sol.Y() = Determinant (col1, rhs, col3) / det; sol.Z() = Determinant (col1, col2, rhs) / det; } return 0; */ } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif int SolveLinearSystemLS (const Vec3d & col1, const Vec3d & col2, const Vec2d & rhs, Vec3d & sol) { double a11 = col1 * col1; double a12 = col1 * col2; double a22 = col2 * col2; double det = a11 * a22 - a12 * a12; if (det*det <= 1e-24 * a11 * a22) { sol = Vec3d (0, 0, 0); return 1; } Vec2d invrhs; invrhs.X() = ( a22 * rhs.X() - a12 * rhs.Y()) / det; invrhs.Y() = (-a12 * rhs.X() + a11 * rhs.Y()) / det; sol.X() = invrhs.X() * col1.X() + invrhs.Y() * col2.X(); sol.Y() = invrhs.X() * col1.Y() + invrhs.Y() * col2.Y(); sol.Z() = invrhs.X() * col1.Z() + invrhs.Y() * col2.Z(); return 0; /* Vec3d inv1, inv2; int err = PseudoInverse (col1, col2, inv1, inv2); sol = rhs.X() * inv1 + rhs.Y() * inv2; return err; */ } int SolveLinearSystemLS2 (const Vec3d & col1, const Vec3d & col2, const Vec2d & rhs, Vec3d & sol, double & x, double & y) { double a11 = col1 * col1; double a12 = col1 * col2; double a22 = col2 * col2; double det = a11 * a22 - a12 * a12; if (fabs (det) <= 1e-12 * col1.Length() * col2.Length() || col1.Length2() == 0 || col2.Length2() == 0) { sol = Vec3d (0, 0, 0); x = 0; y = 0; return 1; } Vec2d invrhs; invrhs.X() = ( a22 * rhs.X() - a12 * rhs.Y()) / det; invrhs.Y() = (-a12 * rhs.X() + a11 * rhs.Y()) / det; sol.X() = invrhs.X() * col1.X() + invrhs.Y() * col2.X(); sol.Y() = invrhs.X() * col1.Y() + invrhs.Y() * col2.Y(); sol.Z() = invrhs.X() * col1.Z() + invrhs.Y() * col2.Z(); x = invrhs.X(); y = invrhs.Y(); return 0; /* Vec3d inv1, inv2; int err = PseudoInverse (col1, col2, inv1, inv2); sol = rhs.X() * inv1 + rhs.Y() * inv2; return err; */ } int PseudoInverse (const Vec3d & col1, const Vec3d & col2, Vec3d & inv1, Vec3d & inv2) { double a11 = col1 * col1; double a12 = col1 * col2; double a22 = col2 * col2; double det = a11 * a22 - a12 * a12; if (fabs (det) < 1e-12 * col1.Length() * col2.Length()) { inv1 = Vec3d (0, 0, 0); inv2 = Vec3d (0, 0, 0); return 1; } double ia11 = a22 / det; double ia12 = -a12 / det; double ia22 = a11 / det; inv1 = ia11 * col1 + ia12 * col2; inv2 = ia12 * col1 + ia22 * col2; return 0; } QuadraticFunction3d :: QuadraticFunction3d (const Point3d & p, const Vec3d & v) { Vec3d hv(v); hv /= (hv.Length() + 1e-12); Vec3d t1, t2; hv.GetNormal (t1); Cross (hv, t1, t2); double t1p = t1.X() * p.X() + t1.Y() * p.Y() + t1.Z() * p.Z(); double t2p = t2.X() * p.X() + t2.Y() * p.Y() + t2.Z() * p.Z(); c0 = sqr (t1p) + sqr (t2p); cx = -2 * (t1p * t1.X() + t2p * t2.X()); cy = -2 * (t1p * t1.Y() + t2p * t2.Y()); cz = -2 * (t1p * t1.Z() + t2p * t2.Z()); cxx = t1.X() * t1.X() + t2.X() * t2.X(); cyy = t1.Y() * t1.Y() + t2.Y() * t2.Y(); czz = t1.Z() * t1.Z() + t2.Z() * t2.Z(); cxy = 2 * t1.X() * t1.Y() + 2 * t2.X() * t2.Y(); cxz = 2 * t1.X() * t1.Z() + 2 * t2.X() * t2.Z(); cyz = 2 * t1.Y() * t1.Z() + 2 * t2.Y() * t2.Z(); /* (*testout) << "c0 = " << c0 << " clin = " << cx << " " << cy << " " << cz << " cq = " << cxx << " " << cyy << " " << czz << cxy << " " << cyz << " " << cyz << endl; */ } // QuadraticFunction3d gqf (Point3d (0,0,0), Vec3d (1, 0, 0)); void referencetransform :: Set (const Point3d & p1, const Point3d & p2, const Point3d & p3, double ah) { ex = p2 - p1; ex /= ex.Length(); ey = p3 - p1; ey -= (ex * ey) * ex; ey /= ey.Length(); ez = Cross (ex, ey); rp = p1; h = ah; exh = ah * ex; eyh = ah * ey; ezh = ah * ez; ah = 1 / ah; ex_h = ah * ex; ey_h = ah * ey; ez_h = ah * ez; } void referencetransform :: ToPlain (const Point3d & p, Point3d & pp) const { Vec3d v; v = p - rp; pp.X() = (ex_h * v); pp.Y() = (ey_h * v); pp.Z() = (ez_h * v); } void referencetransform :: ToPlain (const Array & p, Array & pp) const { Vec3d v; int i; pp.SetSize (p.Size()); for (i = 1; i <= p.Size(); i++) { v = p.Get(i) - rp; pp.Elem(i).X() = (ex_h * v); pp.Elem(i).Y() = (ey_h * v); pp.Elem(i).Z() = (ez_h * v); } } void referencetransform :: FromPlain (const Point3d & pp, Point3d & p) const { Vec3d v; // v = (h * pp.X()) * ex + (h * pp.Y()) * ey + (h * pp.Z()) * ez; // p = rp + v; v.X() = pp.X() * exh.X() + pp.Y() * eyh.X() + pp.Z() * ezh.X(); v.Y() = pp.X() * exh.Y() + pp.Y() * eyh.Y() + pp.Z() * ezh.Y(); v.Z() = pp.X() * exh.Z() + pp.Y() * eyh.Z() + pp.Z() * ezh.Z(); p.X() = rp.X() + v.X(); p.Y() = rp.Y() + v.Y(); p.Z() = rp.Z() + v.Z(); } } netgen-6.2.1905/libsrc/gprim/gprim.hpp0000644000175000017500000000134213504650527016224 0ustar kurtkurt#ifndef FILE_GPRIM #define FILE_GPRIM /* *************************************************************************/ /* File: gprim.hpp */ /* Author: Joachim Schoeberl */ /* Date: 14. Aug. 97 */ /* *************************************************************************/ #include #include #include "geomobjects.hpp" #include "geomops.hpp" #include "geomfuncs.hpp" #include "geom2d.hpp" #include "geom3d.hpp" #include "geomtest3d.hpp" #include "transform3d.hpp" #include "adtree.hpp" #include "spline.hpp" #include "splinegeometry.hpp" #endif netgen-6.2.1905/libsrc/gprim/splinegeometry.cpp0000644000175000017500000000463213504650527020154 0ustar kurtkurt/* 2d Spline curve for Mesh generator */ #include #include #include #include "splinegeometry.hpp" namespace netgen { template SplineGeometry :: ~SplineGeometry() { for(int i = 0; i < splines.Size(); i++) delete splines[i]; } template void SplineGeometry :: GetRawData (Array & raw_data) const { raw_data.Append(D); // raw_data.Append(elto0); raw_data.Append(splines.Size()); for(int i=0; iGetRawData(raw_data); } template int SplineGeometry :: Load (const Array & raw_data, const int startpos) { int pos = startpos; if(raw_data[pos] != D) throw NgException("wrong dimension of spline raw_data"); pos++; // elto0 = raw_data[pos]; pos++; splines.SetSize(int(raw_data[pos])); pos++; Array< Point > pts(3); for(int i=0; i(GeomPoint(pts[0],1), GeomPoint(pts[1],1)); } else if (type == 3) { splines[i] = new SplineSeg3(GeomPoint(pts[0],1), GeomPoint(pts[1],1), GeomPoint(pts[2],1)); } else throw NgException("something wrong with spline raw data"); } return pos; } template void SplineGeometry :: GetBoundingBox (Box & box) const { if (!splines.Size()) { Point auxp = 0.; box.Set (auxp); return; } Array > points; for (int i = 0; i < splines.Size(); i++) { splines[i]->GetPoints (20, points); if (i == 0) box.Set(points[0]); for (int j = 0; j < points.Size(); j++) box.Add (points[j]); } } /* template void SplineGeometry :: SetGrading (const double grading) { elto0 = grading; } */ template void SplineGeometry :: AppendPoint (const Point & p, const double reffac, const bool hpref) { geompoints.Append (GeomPoint(p, reffac)); geompoints.Last().hpref = hpref; } template class SplineGeometry<2>; template class SplineGeometry<3>; static RegisterClassForArchive> regsp2; static RegisterClassForArchive> regsp3; } netgen-6.2.1905/libsrc/gprim/CMakeLists.txt0000644000175000017500000000113313504650527017133 0ustar kurtkurtadd_definitions(-DNGINTERFACE_EXPORTS) add_library(gprim INTERFACE) set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) target_sources(gprim INTERFACE ${sdir}/adtree.cpp ${sdir}/geom2d.cpp ${sdir}/geom3d.cpp ${sdir}/geomfuncs.cpp ${sdir}/geomtest3d.cpp ${sdir}/transform3d.cpp ${sdir}/spline.cpp ${sdir}/splinegeometry.cpp ) install(FILES adtree.hpp geom2d.hpp geom3d.hpp geomfuncs.hpp geomobjects2.hpp geomobjects.hpp geomops2.hpp geomops.hpp geomtest3d.hpp gprim.hpp splinegeometry.hpp spline.hpp transform3d.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/gprim COMPONENT netgen_devel ) netgen-6.2.1905/libsrc/CMakeLists.txt0000644000175000017500000000046213504650527016021 0ustar kurtkurtadd_subdirectory(core) add_subdirectory(general) add_subdirectory(gprim) add_subdirectory(linalg) add_subdirectory(include) add_subdirectory(meshing) add_subdirectory(visualization) add_subdirectory(csg) add_subdirectory(geom2d) add_subdirectory(occ) add_subdirectory(stlgeom) add_subdirectory(interface) netgen-6.2.1905/cmake/0000755000175000017500000000000013504650527013061 5ustar kurtkurtnetgen-6.2.1905/cmake/mic.cmake0000644000175000017500000000072013504650527014632 0ustar kurtkurtset(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR k1om) set(CMAKE_SYSTEM_VERSION 1) # specify the cross compiler set(CMAKE_C_COMPILER icc) set(CMAKE_CXX_COMPILER icpc) set(MPI_C_COMPILER mpiicc) set(_CMAKE_TOOLCHAIN_PREFIX x86_64-k1om-linux-) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmic") set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -limf -lsvml -lirng -lintlc") # where is the target environment set(CMAKE_FIND_ROOT_PATH /usr/linux-k1om-4.7) netgen-6.2.1905/cmake/cmake_uninstall.cmake.in0000644000175000017500000000201313504650527017635 0ustar kurtkurtif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif(NOT "${rm_retval}" STREQUAL 0) else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") endforeach(file) netgen-6.2.1905/cmake/netgen_fixup.cmake0000644000175000017500000000275213504650527016564 0ustar kurtkurtinclude(BundleUtilities) function(netgen_fixup_bundle app libs dirs) message(STATUS "fixup_bundle") message(STATUS " app='${app}'") message(STATUS " libs='${libs}'") message(STATUS " dirs='${dirs}'") get_bundle_and_executable("${app}" bundle executable valid) if(valid) get_filename_component(exepath "${executable}" PATH) message(STATUS "fixup_bundle: preparing...") get_bundle_keys("${app}" "${libs}" "${dirs}" keys) message(STATUS "fixup_bundle: copying...") list(LENGTH keys n) math(EXPR n ${n}*2) set(i 0) foreach(key ${keys}) math(EXPR i ${i}+1) if(${${key}_COPYFLAG}) set(item "${${key}_ITEM}") if(item MATCHES "[^/]+\\.framework/") copy_resolved_framework_into_bundle("${${key}_RESOLVED_ITEM}" "${${key}_RESOLVED_EMBEDDED_ITEM}") else() copy_resolved_item_into_bundle("${${key}_RESOLVED_ITEM}" "${${key}_RESOLVED_EMBEDDED_ITEM}") endif() endif() endforeach() message(STATUS "fixup_bundle: fixing...") foreach(key ${keys}) math(EXPR i ${i}+1) message(STATUS "${i}/${n}: fixing up '${${key}_RESOLVED_EMBEDDED_ITEM}'") fixup_bundle_item("${${key}_RESOLVED_EMBEDDED_ITEM}" "${exepath}" "${dirs}") endforeach() message(STATUS "fixup_bundle: cleaning up...") clear_bundle_keys(keys) else() message(SEND_ERROR "error: fixup_bundle: not a valid bundle") endif() message(STATUS "fixup_bundle: done") endfunction() netgen-6.2.1905/cmake/cmake_modules/0000755000175000017500000000000013504650527015671 5ustar kurtkurtnetgen-6.2.1905/cmake/cmake_modules/FindFFMPEG.cmake0000644000175000017500000000523413504650527020444 0ustar kurtkurt# - Try to find ffmpeg libraries (libavcodec, libavformat, libavutil and swscale) # Once done this will define # # FFMPEG_FOUND - system has ffmpeg or libav # FFMPEG_INCLUDE_DIR - the ffmpeg include directory # FFMPEG_LIBRARIES - Link these to use ffmpeg # FFMPEG_LIBAVCODEC # FFMPEG_LIBAVFORMAT # FFMPEG_LIBAVUTIL # FFMPEG_SWSCALE # # Copyright (c) 2008 Andreas Schneider # Modified for other libraries by Lasse Kärkkäinen # Modified for Hedgewars by Stepik777 # Modified for Netgen by Christoph Lehrenfeld (2015) (current version) # # Redistribution and use is allowed according to the terms of the New # BSD license. # if (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) # in cache already set(FFMPEG_FOUND TRUE) else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(_FFMPEG_AVCODEC libavcodec) pkg_check_modules(_FFMPEG_AVFORMAT libavformat) pkg_check_modules(_FFMPEG_AVUTIL libavutil) pkg_check_modules(SWSCALE libswscale) endif (PKG_CONFIG_FOUND) find_path(FFMPEG_AVCODEC_INCLUDE_DIR NAMES libavcodec/avcodec.h PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} /usr/include /usr/local/include /opt/local/include /sw/include PATH_SUFFIXES ffmpeg libav ) find_library(FFMPEG_LIBAVCODEC NAMES avcodec PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(FFMPEG_LIBAVFORMAT NAMES avformat PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(FFMPEG_LIBAVUTIL NAMES avutil PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(FFMPEG_SWSCALE NAMES swscale PATHS ${SWSCALE_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) if (FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT) set(FFMPEG_FOUND TRUE) endif() if (FFMPEG_FOUND) set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) set(FFMPEG_LIBRARIES ${FFMPEG_LIBAVCODEC} ${FFMPEG_LIBAVFORMAT} ${FFMPEG_LIBAVUTIL} ${FFMPEG_SWSCALE} ) endif (FFMPEG_FOUND) if (FFMPEG_FOUND) if (NOT FFMPEG_FIND_QUIETLY) message(STATUS "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") endif (NOT FFMPEG_FIND_QUIETLY) else (FFMPEG_FOUND) if (FFMPEG_FIND_REQUIRED) message(FATAL_ERROR "Could not find libavcodec or libavformat or libavutil") endif (FFMPEG_FIND_REQUIRED) endif (FFMPEG_FOUND) endif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) netgen-6.2.1905/cmake/cmake_modules/FindOpenCasCade.cmake0000644000175000017500000000500613504650527021602 0ustar kurtkurt# Try to find OCC # Once done this will define # # OCC_FOUND - system has OCC - OpenCASCADE # OCC_INCLUDE_DIR - where the OCC include directory can be found # OCC_LIBRARY_DIR - where the OCC library directory can be found # OCC_LIBRARIES - Link this to use OCC if(WIN32) find_path(OCC_INCLUDE_DIR Standard_Version.hxx PATH_SUFFIXES inc ../inc) find_library(OCC_LIBRARY TKernel) else(WIN32) find_path(OCC_INCLUDE_DIR Standard_Version.hxx /usr/include/opencascade /usr/local/include/opencascade /usr/include/oce /usr/local/include/oce /opt/opencascade/include /opt/opencascade/inc ) find_library(OCC_LIBRARY TKernel /usr/lib /usr/local/lib /opt/opencascade/lib ) endif(WIN32) if(OCC_LIBRARY) get_filename_component(OCC_LIBRARY_DIR ${OCC_LIBRARY} PATH) endif(OCC_LIBRARY) if(OCC_INCLUDE_DIR) file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAJOR REGEX "#define OCC_VERSION_MAJOR.*" ) string(REGEX MATCH "[0-9]+" OCC_MAJOR ${OCC_MAJOR}) file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MINOR REGEX "#define OCC_VERSION_MINOR.*" ) string(REGEX MATCH "[0-9]+" OCC_MINOR ${OCC_MINOR}) file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAINT REGEX "#define OCC_VERSION_MAINTENANCE.*" ) string(REGEX MATCH "[0-9]+" OCC_MAINT ${OCC_MAINT}) set(OCC_VERSION_STRING "${OCC_MAJOR}.${OCC_MINOR}.${OCC_MAINT}") endif(OCC_INCLUDE_DIR) set(OCC_LIBRARY_NAMES TKBO TKBool TKBRep TKCAF TKCDF TKernel TKG2d TKG3d TKGeomAlgo TKGeomBase TKHLR TKIGES TKLCAF TKMath TKMesh TKOffset TKPrim TKService TKShHealing TKSTEP TKSTEP209 TKSTEPAttr TKSTEPBase TKSTL TKTopAlgo TKV3d TKXCAF TKXDEIGES TKXDESTEP TKXSBase ) foreach( libname ${OCC_LIBRARY_NAMES} ) find_library( ${libname} ${libname} ${OCC_LIBRARY_DIR} ) set(OCC_LIBRARIES ${OCC_LIBRARIES} ${${libname}}) endforeach() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OCC REQUIRED_VARS OCC_INCLUDE_DIR VERSION_VAR OCC_VERSION_STRING ${OCC_LIBRARIY_NAMES}) if(OCC_FOUND) message(STATUS "-- Found OpenCASCADE version: ${OCC_VERSION_STRING}") message(STATUS "-- OpenCASCADE include directory: ${OCC_INCLUDE_DIR}") message(STATUS "-- OpenCASCADE shared libraries directory: ${OCC_LIBRARY_DIR}") message(STATUS "-- OpenCASCADE shared libraries :\n ${OCC_LIBRARIES}") endif(OCC_FOUND) netgen-6.2.1905/cmake/cmake_modules/FindMETIS.cmake0000644000175000017500000001030713504650527020356 0ustar kurtkurt# -*- mode: cmake -*- # # METIS Find Module for MSTK # Shamelessly stolen from Amanzi open source code https://software.lanl.gov/ascem/trac # # Usage: # Control the search through METIS_DIR or setting environment variable # METIS_ROOT to the METIS installation prefix. # # This module does not search default paths! # # Following variables are set: # METIS_FOUND (BOOL) Flag indicating if METIS was found # METIS_INCLUDE_DIR (PATH) Path to the METIS include file # METIS_INCLUDE_DIRS (LIST) List of all required include files # METIS_LIBRARY_DIR (PATH) Path to the METIS library # METIS_LIBRARY (FILE) METIS library # METIS_LIBRARIES (LIST) List of all required METIS libraries # # ############################################################################# # Standard CMake modules see CMAKE_ROOT/Modules include(FindPackageHandleStandardArgs) # Amanzi CMake functions see /tools/cmake for source # include(PrintVariable) if ( METIS_LIBRARIES AND METIS_INCLUDE_DIRS ) # Do nothing. Variables are set. No need to search again else(METIS_LIBRARIES AND METIS_INCLUDE_DIRS) # Cache variables if(METIS_DIR) set(METIS_DIR "${METIS_DIR}" CACHE PATH "Path to search for METIS include and library files") endif() if(METIS_INCLUDE_DIR) set(METIS_INCLUDE_DIR "${METIS_INCLUDE_DIR}" CACHE PATH "Path to search for METIS include files") endif() if(METIS_LIBRARY_DIR) set(METIS_LIBRARY_DIR "${METIS_LIBRARY_DIR}" CACHE PATH "Path to search for METIS library files") endif() # Search for include files # Search order preference: # (1) METIS_INCLUDE_DIR - check existence of path AND if the include files exist # (2) METIS_DIR/ # (3) Default CMake paths See cmake --html-help=out.html file for more information. # set(metis_inc_names "metis.h") if (METIS_INCLUDE_DIR) if (EXISTS "${METIS_INCLUDE_DIR}") find_path(metis_test_include_path NAMES ${metis_inc_names} HINTS ${METIS_INCLUDE_DIR} NO_DEFAULT_PATH) set(METIS_INCLUDE_DIR "${metis_test_include_path}") endif() else() # Metis sometimes puts the include files in a subdir called Lib set(metis_inc_suffixes "include" "Lib") if(METIS_DIR) if (EXISTS "${METIS_DIR}" ) find_path(METIS_INCLUDE_DIR NAMES ${metis_inc_names} HINTS ${METIS_DIR} PATH_SUFFIXES ${metis_inc_suffixes} NO_DEFAULT_PATH) endif() else() find_path(METIS_INCLUDE_DIR NAMES ${metis_inc_names} PATH_SUFFIXES ${metis_inc_suffixes}) endif() endif() # Search for libraries # Search order preference: # (1) METIS_LIBRARY_DIR - check existence of path AND if the library file exists # (2) METIS_DIR/ # (3) Default CMake paths See cmake --html-help=out.html file for more information. # set(metis_lib_names "metis5" "metis") if (METIS_LIBRARY_DIR) if (EXISTS "${METIS_LIBRARY_DIR}") find_library(METIS_LIBRARY NAMES ${metis_lib_names} HINTS ${METIS_LIBRARY_DIR} NO_DEFAULT_PATH) endif() else() list(APPEND metis_lib_suffixes "lib" "Lib") if(METIS_DIR) if (EXISTS "${METIS_DIR}" ) find_library(METIS_LIBRARY NAMES ${metis_lib_names} HINTS ${METIS_DIR} PATH_SUFFIXES ${metis_lib_suffixes} NO_DEFAULT_PATH) endif() else() find_library(METIS_LIBRARY NAMES ${metis_lib_names} PATH_SUFFIXES ${metis_lib_suffixes}) endif() endif() # Define prerequisite packages set(METIS_INCLUDE_DIRS ${METIS_INCLUDE_DIR}) set(METIS_LIBRARIES ${METIS_LIBRARY}) endif(METIS_LIBRARIES AND METIS_INCLUDE_DIRS ) # Send useful message if everything is found find_package_handle_standard_args(METIS DEFAULT_MSG METIS_LIBRARIES METIS_INCLUDE_DIRS) # find_package_handle_standard_args should set METIS_FOUND but it does not! if ( METIS_LIBRARIES AND METIS_INCLUDE_DIRS) set(METIS_FOUND TRUE) else() set(METIS_FOUND FALSE) endif() # Define the version mark_as_advanced( METIS_INCLUDE_DIR METIS_INCLUDE_DIRS METIS_LIBRARY METIS_LIBRARIES METIS_LIBRARY_DIR ) netgen-6.2.1905/cmake/NetgenConfig.cmake.in0000644000175000017500000000564413504650527017047 0ustar kurtkurtset(NETGEN_VERSION "@NETGEN_VERSION@") get_filename_component(NETGEN_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) get_filename_component(NETGEN_DIR "${NETGEN_CMAKE_DIR}/@NETGEN_DIR@" ABSOLUTE) set(NETGEN_COMPILE_DEFINITIONS "@NETGEN_COMPILE_DEFINITIONS@") get_filename_component(NETGEN_INCLUDE_DIR "${NETGEN_CMAKE_DIR}/@NETGEN_INCLUDE_DIR@" ABSOLUTE) get_filename_component(NETGEN_BINARY_DIR "${NETGEN_CMAKE_DIR}/@NETGEN_BINARY_DIR@" ABSOLUTE) get_filename_component(NETGEN_LIBRARY_DIR "${NETGEN_CMAKE_DIR}/@NETGEN_LIBRARY_DIR@" ABSOLUTE) get_filename_component(NETGEN_PYTHON_DIR "${NETGEN_CMAKE_DIR}/@NETGEN_PYTHON_DIR@" ABSOLUTE) get_filename_component(NETGEN_RESOURCE_DIR "${NETGEN_CMAKE_DIR}/@NETGEN_RESOURCE_DIR@" ABSOLUTE) set(NETGEN_SOURCE_DIR "@PROJECT_SOURCE_DIR@") set(NETGEN_INCLUDE_DIRS "${NETGEN_INCLUDE_DIR}/include;${NETGEN_INCLUDE_DIR}") set(NETGEN_CMAKE_THREAD_LIBS_INIT "@CMAKE_THREAD_LIBS_INIT@") set(NETGEN_FFMPEG_LIBRARIES "@FFMPEG_LIBRARIES@") set(NETGEN_JPEG_INCLUDE_DIR "@JPEG_INCLUDE_DIR@") set(NETGEN_JPEG_LIBRARIES "@JPEG_LIBRARIES@") set(NETGEN_LIBTOGL "@LIBTOGL@") set(NETGEN_METIS_INCLUDE_DIR "@METIS_INCLUDE_DIR@") set(NETGEN_METIS_LIBRARY "@METIS_LIBRARY@") set(NETGEN_MKL_LIBRARIES "@MKL_LIBRARIES@") set(NETGEN_MPI_CXX_INCLUDE_PATH "@MPI_CXX_INCLUDE_PATH@") set(NETGEN_MPI_CXX_LIBRARIES "@MPI_CXX_LIBRARIES@") set(NETGEN_OCC_INCLUDE_DIR "@OCC_INCLUDE_DIR@") set(NETGEN_OCC_LIBRARIES_BIN "@OCC_LIBRARIES_BIN@") set(NETGEN_OCC_LIBRARIES "@OCC_LIBRARIES@") set(NETGEN_OCC_LIBRARY_DIR "@OCC_LIBRARY_DIR@") set(NETGEN_OPENGL_LIBRARIES "@OPENGL_LIBRARIES@") set(NETGEN_PYTHON_EXECUTABLE "@PYTHON_EXECUTABLE@") set(NETGEN_PYTHON_INCLUDE_DIRS "@PYTHON_INCLUDE_DIRS@") set(NETGEN_PYTHON_LIBRARIES "@PYTHON_LIBRARIES@") set(NETGEN_TCL_INCLUDE_PATH "@TCL_INCLUDE_PATH@") set(NETGEN_TCL_LIBRARY "@TCL_LIBRARY@") set(NETGEN_TK_DND_LIBRARY "@TK_DND_LIBRARY@") set(NETGEN_TK_INCLUDE_PATH "@TK_INCLUDE_PATH@") set(NETGEN_TK_LIBRARY "@TK_LIBRARY@") set(NETGEN_X11_X11_LIB "@X11_X11_LIB@") set(NETGEN_X11_Xmu_LIB "@X11_Xmu_LIB@") set(NETGEN_ZLIB_INCLUDE_DIRS "@ZLIB_INCLUDE_DIRS@") set(NETGEN_ZLIB_LIBRARIES "@ZLIB_LIBRARIES@") set(NETGEN_USE_GUI @USE_GUI@) set(NETGEN_USE_PYTHON @USE_PYTHON@) set(NETGEN_USE_MPI @USE_MPI@) set(NETGEN_USE_OCC @USE_OCC@) set(NETGEN_USE_JPEG @USE_JPEG@) set(NETGEN_USE_MPEG @USE_MPEG@) set(NETGEN_INTEL_MIC @INTEL_MIC@) set(NETGEN_INSTALL_PROFILES @INSTALL_PROFILES@) set(NETGEN_USE_CCACHE @USE_CCACHE@) set(NETGEN_PYTHON_RPATH "@NETGEN_PYTHON_RPATH@") set(NETGEN_RPATH_TOKEN "@NG_RPATH_TOKEN@") set(NETGEN_INSTALL_DIR_PYTHON @NG_INSTALL_DIR_PYTHON@) set(NETGEN_INSTALL_DIR_BIN @NG_INSTALL_DIR_BIN@) set(NETGEN_INSTALL_DIR_LIB @NG_INSTALL_DIR_LIB@) set(NETGEN_INSTALL_DIR_INCLUDE @NG_INSTALL_DIR_INCLUDE@) set(NETGEN_INSTALL_DIR_CMAKE @NG_INSTALL_DIR_CMAKE@) set(NETGEN_INSTALL_DIR_RES @NG_INSTALL_DIR_RES@) include(${CMAKE_CURRENT_LIST_DIR}/netgen-targets.cmake) message(STATUS "Found Netgen: ${CMAKE_CURRENT_LIST_DIR}") netgen-6.2.1905/cmake/check_submodules.cmake0000644000175000017500000000115613504650527017405 0ustar kurtkurtexecute_process(COMMAND git submodule status --recursive WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/../" OUTPUT_VARIABLE git_status_output) string(REPLACE "\n" ";" git_status_output "${git_status_output}") foreach( a ${git_status_output}) if(NOT ${a} MATCHES " [a-f,0-9]* external_dependencies[.]*") message(WARNING "***************************************************************** WARNING: The git submodules are out of sync! Please run git submodule update --init --recursive in your source directory *****************************************************************") endif() endforeach() netgen-6.2.1905/cmake/tk_macosx.patch0000644000175000017500000000567413504650527016106 0ustar kurtkurtdiff --git a/macosx/GNUmakefile b/macosx/GNUmakefile index 02240ed..aac1d4c 100644 --- a/macosx/GNUmakefile +++ b/macosx/GNUmakefile @@ -133,9 +133,7 @@ override EMBEDDED_BUILD := endif INSTALL_TARGETS = install-binaries install-libraries -ifeq (${EMBEDDED_BUILD},) INSTALL_TARGETS += install-private-headers install-headers install-demos -endif ifeq (${INSTALL_BUILD}_${EMBEDDED_BUILD}_${BUILD_STYLE},1__Deployment) INSTALL_TARGETS += html-tk ifneq (${INSTALL_MANPAGES},) @@ -253,43 +251,6 @@ ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_) @cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" && \ ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug" endif -ifeq (${TK_X11},) -ifeq (${EMBEDDED_BUILD},) -# install Wish.app link in APPLICATION_INSTALL_PATH and setup 'Wish Shell' compatibility links - @cd "${TOP_DIR}" && if [ -n "${APP_DIR}" ]; then mkdir -p "./${APP_DIR}" && rm -rf "./${APP_DIR}/Wish.app" && \ - ln -fsh "./$$(echo "${APP_DIR}" | sed -e 's#/[^/][^/]*#/..#g')/${FMWK_DIR}/${PRODUCT_NAME}.framework/Resources/Wish.app" "./${APP_DIR}" && \ - ln -fsh Wish.app "./${APP_DIR}/Wish Shell.app"; fi && \ - ln -fsh Wish.app "./${TK_FMWK_DIR}/Resources/Wish Shell.app" && \ - ln -fsh Wish "./${TK_FMWK_DIR}/Resources/Wish.app/Contents/MacOS/Wish Shell" -else -# if we are embedding frameworks, move them into the app and fix their install names - @cd "${TOP_DIR}" && \ - rm -rf "./${APP_DIR}/Wish.app" && mkdir -p "./${APP_DIR}" && \ - mv -f "./${TK_FMWK_DIR}/Resources/Wish.app" "./${APP_DIR}" && \ - ln -fsh Wish.app "./${APP_DIR}/Wish Shell.app" && \ - rm -rf "./${APP_DIR}/Wish.app/Contents/Frameworks" && \ - mkdir -p "./${APP_DIR}/Wish.app/Contents/Frameworks" && \ - ${CPPROG} -RH "./${FMWK_DIR}"/T{cl,k}.framework "./${APP_DIR}/Wish.app/Contents/Frameworks" && \ - cd "./${APP_DIR}/Wish.app/Contents" && \ - rm -rf Frameworks/Tcl.framework/{,/Versions/${TCL_VERSION}}/{Headers,PrivateHeaders,*_debug,lib*.a,*Config.sh} && \ - rm -rf Frameworks/Tk.framework/{,/Versions/${VERSION}}/{Headers,PrivateHeaders,*_debug,lib*.a,*Config.sh} && \ - fix_install_id ( ) { \ - chmod -RH a+w "$$1"; \ - install_name_tool -id $$(otool -L "$$1" | awk "/$$2\.framework.*[^:]\$$/ {sub(\"^.*/Frameworks\",\"@executable_path/../Frameworks\",\$$1); print \$$1}") "$$1"; \ - chmod -RH a-w "$$1"; \ - } && \ - fix_install_name ( ) { \ - chmod -RH a+w "$$1"; \ - install_name_tool -change $$(otool -L "$$1" | awk "/$$2\.framework.*[^:]\$$/ {print \$$1; sub(\"^.*/Frameworks\",\"@executable_path/../Frameworks\",\$$1); print \$$1}") "$$1"; \ - chmod -RH a-w "$$1"; \ - } && \ - fix_install_id Frameworks/Tcl.framework/Tcl Tcl && fix_install_id Frameworks/Tk.framework/Tk Tk && \ - fix_install_name MacOS/Wish Tcl && fix_install_name MacOS/Wish Tk -ifeq (${INSTALL_BUILD},1) - @cd "${TOP_DIR}" && rm -rf "./${FMWK_DIR}"/T{cl,k}.framework && rmdir -p "./${FMWK_DIR}" 2>&- || true -endif -endif -endif clean-${PROJECT}: %-${PROJECT}: ${DO_MAKE} netgen-6.2.1905/cmake/external_projects/0000755000175000017500000000000013504650527016614 5ustar kurtkurtnetgen-6.2.1905/cmake/external_projects/zlib.cmake0000644000175000017500000000055413504650527020562 0ustar kurtkurtif(WIN32) ExternalProject_Add(project_win_zlib URL ${ZLIB_DOWNLOAD_URL_WIN} UPDATE_COMMAND "" # Disable update BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX} LOG_DOWNLOAD 1 ) list(APPEND NETGEN_DEPENDENCIES project_win_zlib) endif(WIN32) netgen-6.2.1905/cmake/external_projects/tcltk.cmake0000644000175000017500000000704513504650527020745 0ustar kurtkurtif(APPLE) # use system tcl/tk if((${PYTHON_VERSION_STRING} VERSION_EQUAL "3.7") OR (${PYTHON_VERSION_STRING} VERSION_GREATER "3.7")) # fetch tcl/tk sources to match the one used in Python 3.7 ExternalProject_Add(project_tcl URL "https://prdownloads.sourceforge.net/tcl/tcl8.6.8-src.tar.gz" URL_MD5 81656d3367af032e0ae6157eff134f89 DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies UPDATE_COMMAND "" # Disable update CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) ExternalProject_Add(project_tk URL "https://prdownloads.sourceforge.net/tcl/tk8.6.8-src.tar.gz" URL_MD5 5e0faecba458ee1386078fb228d008ba DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies UPDATE_COMMAND "" # Disable update CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) get_filename_component(PYTHON_LIB_DIR ${PYTHON_LIBRARY} DIRECTORY) find_library(TCL_LIBRARY libtcl8.6.dylib PATHS ${PYTHON_LIB_DIR} NO_DEFAULT_PATH) find_library(TK_LIBRARY libtk8.6.dylib PATHS ${PYTHON_LIB_DIR} NO_DEFAULT_PATH) set(TCL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tcl) set(TK_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tk) set(TCL_INCLUDE_PATH "${TCL_DIR}/generic;${TCL_DIR}/macosx") set(TK_INCLUDE_PATH "${TK_DIR}/generic;${TK_DIR}/macosx;${TK_DIR}/xlib") string(REPLACE ";" "$" TCL_INC "${TCL_INCLUDE_PATH}") string(REPLACE ";" "$" TK_INC "${TK_INCLUDE_PATH}") ExternalProject_Add(project_tkdnd URL "http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz" URL_MD5 a6d47a996ea957416469b12965d4db91 DEPENDS project_tcl project_tk DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies PATCH_COMMAND patch < ${CMAKE_CURRENT_LIST_DIR}/tkdnd_macosx.patch UPDATE_COMMAND "" # Disable update BUILD_IN_SOURCE 1 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS -DTCL_INCLUDE_PATH=${TCL_INC} -DTK_INCLUDE_PATH=${TK_INC} -DTK_LIBRARY=${TK_LIBRARY} -DTCL_LIBRARY=${TCL_LIBRARY} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 ) list(APPEND NETGEN_DEPENDENCIES project_tkdnd) else() find_package(TCL 8.5 REQUIRED) endif() elseif(WIN32) ExternalProject_Add(project_win_tcltk URL ${TCLTK_DOWNLOAD_URL_WIN} UPDATE_COMMAND "" # Disable update BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX} LOG_DOWNLOAD 1 ) set (TK_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/include) set (TCL_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/include) set (TCL_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tcl86t.lib) set (TK_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tk86t.lib) list(APPEND NETGEN_DEPENDENCIES project_win_tcltk) else(WIN32) find_package(TCL 8.5 REQUIRED) # ExternalProject_Add(project_tkdnd # GIT_REPOSITORY https://github.com/petasis/tkdnd.git # GIT_TAG d7cfd96087b248255da5349086ef70cc4bbfb619 # PREFIX ${CMAKE_CURRENT_BINARY_DIR}/tkdnd # CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/lib # UPDATE_COMMAND "" # LOG_DOWNLOAD 1 # LOG_BUILD 1 # LOG_INSTALL 1 # ) # list(APPEND NETGEN_DEPENDENCIES project_tkdnd) endif(APPLE) # Propagate settings to Netgen subproject set_vars(NETGEN_CMAKE_ARGS TCL_INCLUDE_PATH TCL_LIBRARY TK_LIBRARY TK_INCLUDE_PATH TCL_TCLSH TK_WISH) netgen-6.2.1905/cmake/external_projects/tkdnd_macosx.patch0000644000175000017500000000457413504650527022325 0ustar kurtkurt--- CMakeLists.txt 19:24:32.000000000 +0200 +++ CMakeLists.txt 2018-12-05 11:34:59.000000000 +0100 @@ -43,17 +43,18 @@ ELSE ( WIN32 ) ## Unix and OS X... IF ( APPLE ) - SET ( CMAKE_OSX_ARCHITECTURES "x86_64;i386" ) + SET ( CMAKE_OSX_ARCHITECTURES "x86_64") + SET( TK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../project_tk/) + SET( TCL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../project_tcl/) FIND_LIBRARY ( COCOA_LIBRARY Cocoa ) INCLUDE_DIRECTORIES ( macosx ) - INCLUDE_DIRECTORIES ( /Library/Frameworks/Tk.framework/Versions/8.6/PrivateHeaders ) - INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) - INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) + INCLUDE_DIRECTORIES ( ${TCL_DIR}/macosx ${TCL_DIR}/generic ) + INCLUDE_DIRECTORIES ( ${TK_DIR}/macosx ${TK_DIR}/generic ${TK_DIR}/xlib ) ADD_DEFINITIONS ( -DMAC_TK_COCOA -DMAC_OSX_TK) ADD_DEFINITIONS ( -DMAC_OSX_TK ) ADD_DEFINITIONS ( -std=gnu99 ) ADD_DEFINITIONS ( -x objective-c ) - ADD_DEFINITIONS ( -fobjc-gc ) +# ADD_DEFINITIONS ( -fobjc-gc ) ADD_DEFINITIONS ( -fno-objc-arc ) # ADD_DEFINITIONS ( -fobjc-arc ) LINK_LIBRARIES ( ${COCOA_LIBRARY} ) @@ -125,8 +126,8 @@ ## Locate Tcl/Tk ## =========================================================================== MESSAGE ( STATUS "Searching for Tcl/Tk..." ) -FIND_PACKAGE ( TCL REQUIRED ) -FIND_PACKAGE ( TclStub REQUIRED ) +#FIND_PACKAGE ( TCL REQUIRED ) +#FIND_PACKAGE ( TclStub REQUIRED ) ## Tcl/Tk info (useful for debug purposes)... # MESSAGE ( STATUS " TCL_TCLSH: " ${TCL_TCLSH} ) @@ -139,13 +140,13 @@ # MESSAGE ( STATUS " TK_LIBRARY: " ${TK_LIBRARY} ) ## Enable Tcl/Tk stubs globally... -ADD_DEFINITIONS ( -DUSE_TCL_STUBS ) -ADD_DEFINITIONS ( -DUSE_TK_STUBS ) +#ADD_DEFINITIONS ( -DUSE_TCL_STUBS ) +#ADD_DEFINITIONS ( -DUSE_TK_STUBS ) ADD_DEFINITIONS ( -DTCL_THREADS ) INCLUDE_DIRECTORIES ( ${TCL_INCLUDE_PATH} ) INCLUDE_DIRECTORIES ( ${TK_INCLUDE_PATH} ) -LINK_LIBRARIES ( ${TCL_STUB_LIBRARY} ) -LINK_LIBRARIES ( ${TK_STUB_LIBRARY} ) +LINK_LIBRARIES ( ${TCL_LIBRARY} ) +LINK_LIBRARIES ( ${TK_LIBRARY} ) IF ( WIN32 AND NO_MSVCRT ) STRING ( REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} ) netgen-6.2.1905/cmake/external_projects/spdlog.cmake0000644000175000017500000000065113504650527021110 0ustar kurtkurtinclude(ExternalProject) find_program(GIT_EXECUTABLE git) ExternalProject_Add( project_spdlog PREFIX ${CMAKE_BINARY_DIR}/spdlog GIT_REPOSITORY https://github.com/gabime/spdlog.git GIT_TAG v1.2.1 TIMEOUT 01 UPDATE_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" LOG_DOWNLOAD ON ) ExternalProject_Get_Property(project_spdlog source_dir) set(SPDLOG_INCLUDE_DIR ${source_dir}/include) netgen-6.2.1905/cmake/external_projects/catch.cmake0000644000175000017500000000111513504650527020676 0ustar kurtkurtinclude (ExternalProject) find_program(GIT_EXECUTABLE git) ExternalProject_Add( project_catch PREFIX ${CMAKE_BINARY_DIR}/catch GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG v2.0.1 TIMEOUT 10 UPDATE_COMMAND "" # ${GIT_EXECUTABLE} pull CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" LOG_DOWNLOAD ON ) # Expose required variable (CATCH_INCLUDE_DIR) to parent scope ExternalProject_Get_Property(project_catch source_dir) set(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL "Path to include folder for Catch") netgen-6.2.1905/cmake/external_projects/metis.cmake0000644000175000017500000000141013504650527020733 0ustar kurtkurtset(METIS_SRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_metis) set(METIS_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/metis) ExternalProject_Add(project_metis PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies URL https://bitbucket.org/petsc/pkg-metis/get/v5.1.0-p6.tar.gz URL_MD5 55fc654bb838846b856ba898795143f1 DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies CMAKE_ARGS -DGKLIB_PATH=${METIS_SRC_DIR}/GKlib -DCMAKE_INSTALL_PREFIX=${METIS_DIR} -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} UPDATE_COMMAND "" # Disable update BUILD_IN_SOURCE 1 ) set_vars( NETGEN_CMAKE_ARGS METIS_DIR ) list(APPEND NETGEN_DEPENDENCIES project_metis) netgen-6.2.1905/cmake/SuperBuild.cmake0000644000175000017500000001637313504650527016153 0ustar kurtkurtinclude (ExternalProject) set_property (DIRECTORY PROPERTY EP_PREFIX dependencies) set (NETGEN_DEPENDENCIES) set (LAPACK_DEPENDENCIES) set (NETGEN_CMAKE_ARGS "" CACHE INTERNAL "") macro(set_vars VAR_OUT) foreach(varname ${ARGN}) if(NOT "${${varname}}" STREQUAL "") string(REPLACE ";" "$" varvalue "${${varname}}" ) set(${VAR_OUT} ${${VAR_OUT}};-D${varname}=${varvalue} CACHE INTERNAL "") endif() endforeach() endmacro() ####################################################################### if(WIN32) set (DEPS_DOWNLOAD_URL "https://github.com/NGSolve/ngsolve_dependencies/releases/download/v1.0.0" CACHE STRING INTERNAL) set (OCC_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/occ_win64.zip" CACHE STRING INTERNAL) set (TCLTK_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/tcltk_win64.zip" CACHE STRING INTERNAL) set (ZLIB_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/zlib_win64.zip" CACHE STRING INTERNAL) if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel") string(REGEX REPLACE "/W[0-4]" "/W0" CMAKE_CXX_FLAGS_NEW ${CMAKE_CXX_FLAGS}) set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS_NEW} CACHE STRING "compile flags" FORCE) string(REGEX REPLACE "/W[0-4]" "/W0" CMAKE_CXX_FLAGS_NEW ${CMAKE_CXX_FLAGS_RELEASE}) set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_NEW} CACHE STRING "compile flags" FORCE) string(REGEX REPLACE "/W[0-4]" "/W0" CMAKE_SHARED_LINKER_FLAGS_NEW ${CMAKE_SHARED_LINKER_FLAGS}) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_NEW} /IGNORE:4217,4049" CACHE STRING "compile flags" FORCE) string(REGEX REPLACE "/W[0-4]" "/W0" CMAKE_EXE_LINKER_FLAGS_NEW ${CMAKE_EXE_LINKER_FLAGS}) set(CMAKE_EXE_LINKER_FLAGS"${CMAKE_EXE_LINKER_FLAGS_NEW}/IGNORE:4217,4049" CACHE STRING "compile flags" FORCE) endif(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel") endif(WIN32) if(UNIX) message("Checking for write permissions in install directory...") execute_process(COMMAND mkdir -p ${CMAKE_INSTALL_PREFIX}) execute_process(COMMAND test -w ${CMAKE_INSTALL_PREFIX} RESULT_VARIABLE res) if(res) message(WARNING "No write access at install directory, please set correct permissions") endif() endif(UNIX) if(NOT WIN32) find_package(ZLIB REQUIRED) set_vars(NETGEN_CMAKE_ARGS ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES) endif(NOT WIN32) ####################################################################### if (USE_PYTHON) find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies/pybind11/include NO_DEFAULT_PATH) set(NG_INSTALL_PYBIND ON) if( NOT PYBIND_INCLUDE_DIR ) # if the pybind submodule is missing, try to initialize and update all submodules execute_process(COMMAND git submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h PATHS ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies/pybind11/include NO_DEFAULT_PATH) endif( NOT PYBIND_INCLUDE_DIR ) if( PYBIND_INCLUDE_DIR ) message("-- Found Pybind11: ${PYBIND_INCLUDE_DIR}") else( PYBIND_INCLUDE_DIR ) message(FATAL_ERROR "Could NOT find pybind11!") endif( PYBIND_INCLUDE_DIR ) find_package(PythonInterp 3 REQUIRED) find_package(PythonLibs 3 REQUIRED) set_vars(NETGEN_CMAKE_ARGS PYTHON_INCLUDE_DIRS PYTHON_LIBRARIES PYTHON_EXECUTABLE PYTHON_VERSION PYBIND_INCLUDE_DIR NG_INSTALL_PYBIND ) endif (USE_PYTHON) ####################################################################### if(USE_OCC AND WIN32 AND NOT OCC_INCLUDE_DIR) ExternalProject_Add(win_download_occ PREFIX ${CMAKE_CURRENT_BINARY_DIR}/tcl URL ${OCC_DOWNLOAD_URL_WIN} UPDATE_COMMAND "" # Disable update BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX} LOG_DOWNLOAD 1 ) list(APPEND NETGEN_DEPENDENCIES win_download_occ) endif(USE_OCC AND WIN32 AND NOT OCC_INCLUDE_DIR) ####################################################################### include(cmake/external_projects/zlib.cmake) if(USE_GUI) include(cmake/external_projects/tcltk.cmake) endif(USE_GUI) ####################################################################### if(USE_MPI) if(UNIX) find_package(METIS QUIET) if(NOT METIS_FOUND) message(STATUS "Could not find METIS, it will be built from source") include(cmake/external_projects/metis.cmake) endif() else(UNIX) find_package(METIS REQUIRED) endif(UNIX) endif(USE_MPI) ####################################################################### # propagate cmake variables to Netgen subproject set_vars( NETGEN_CMAKE_ARGS CMAKE_CXX_COMPILER CMAKE_BUILD_TYPE CMAKE_SHARED_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS_RELEASE CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT USE_GUI USE_PYTHON USE_MPI USE_VT USE_VTUNE USE_NUMA USE_CCACHE USE_NATIVE_ARCH USE_OCC USE_MPEG USE_JPEG USE_INTERNAL_TCL INSTALL_PROFILES INTEL_MIC CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX ENABLE_UNIT_TESTS ENABLE_CPP_CORE_GUIDELINES_CHECK USE_SPDLOG DEBUG_LOG CHECK_RANGE ) # propagate all variables set on the command line using cmake -DFOO=BAR # to Netgen subproject get_cmake_property(CACHE_VARS CACHE_VARIABLES) foreach(CACHE_VAR ${CACHE_VARS}) get_property(CACHE_VAR_HELPSTRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING) if(CACHE_VAR_HELPSTRING STREQUAL "No help, variable specified on the command line.") get_property(CACHE_VAR_TYPE CACHE ${CACHE_VAR} PROPERTY TYPE) set(NETGEN_CMAKE_ARGS ${NETGEN_CMAKE_ARGS};-D${CACHE_VAR}:${CACHE_VAR_TYPE}=${${CACHE_VAR}} CACHE INTERNAL "") endif() endforeach() if(${CMAKE_GENERATOR} STREQUAL "Unix Makefiles") set(NETGEN_BUILD_COMMAND $(MAKE) --silent ) else() set(NETGEN_BUILD_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/netgen --config ${CMAKE_BUILD_TYPE}) endif() ExternalProject_Add (netgen DEPENDS ${NETGEN_DEPENDENCIES} SOURCE_DIR ${PROJECT_SOURCE_DIR} CMAKE_ARGS -DUSE_SUPERBUILD=OFF ${NETGEN_CMAKE_ARGS} INSTALL_COMMAND "" BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/netgen BUILD_COMMAND ${NETGEN_BUILD_COMMAND} STEP_TARGETS build ) # Check if the git submodules (i.e. pybind11) are up to date # in case, something is wrong, emit a warning but continue ExternalProject_Add_Step(netgen check_submodules COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_submodules.cmake DEPENDERS install # Steps on which this step depends ) # Due to 'ALWAYS 1', this step is always run which also forces a build of # the Netgen subproject ExternalProject_Add_Step(netgen check_submodules1 COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_submodules.cmake DEPENDEES configure # Steps on which this step depends DEPENDERS build # Steps that depend on this step ALWAYS 1 # No stamp file, step always runs ) install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" --build . --target install --config ${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/netgen)") add_custom_target(test_netgen ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/netgen --target test --config ${CMAKE_BUILD_TYPE} ) netgen-6.2.1905/.gitmodules0000644000175000017500000000020313504650527014151 0ustar kurtkurt[submodule "external_dependencies/pybind11"] path = external_dependencies/pybind11 url = https://github.com/ngsolve/pybind11.git netgen-6.2.1905/AUTHORS0000644000175000017500000000006313504650527013050 0ustar kurtkurtJoachim Schoeberl netgen-6.2.1905/ng/0000755000175000017500000000000013504650527012405 5ustar kurtkurtnetgen-6.2.1905/ng/ngpkg.cpp0000644000175000017500000022751113504650527014227 0ustar kurtkurt/* The interface between the GUI and the netgen library */ #include #include #include #include #include #include #include #ifdef SOCKETS #include "../libsrc/sockets/sockets.hpp" #include "../libsrc/sockets/socketmanager.hpp" #endif // to be sure to include the 'right' togl-version #include "Togl2.1/togl.h" // EXTERN int Togl_PixelScale (const Togl * togl); #include "fonts.hpp" extern bool nodisplay; #include #include "../libsrc/interface/writeuser.hpp" namespace netgen { DLL_HEADER extern MeshingParameters mparam; DLL_HEADER extern void ImportSolution2(const char * filename); #include "demoview.hpp" } #ifdef ACIS #include "ng_acis.hpp" #endif #ifdef JPEGLIB #include #endif #ifdef FFMPEG #include "encoding.hpp" #endif #ifdef NGSOLVE extern "C" void NGSolve_Exit(); #endif // extern void * ngsolve_handle; namespace netgen { extern Flags parameters; /* NetgenOutStream operator<< ( ostream & ost, Imp imp ) { return ( NetgenOutStream ( &ost, imp ) ); } NetgenOutStream operator<< ( ostream & ost, Proc proc ) { return ( NetgenOutStream ( &ost, proc ) ); } NetgenOutStream operator<< ( ostream & ost, Procs & procs ) { return ( NetgenOutStream ( &ost, procs ) ); } */ DLL_HEADER extern std::shared_ptr ng_geometry; DLL_HEADER extern std::shared_ptr mesh; Tcl_Interp * tcl_interp; #ifdef SOCKETS AutoPtr clientsocket; ServerSocketManager serversocketmanager; //Array< AutoPtr < ServerInfo > > servers; Array< ServerInfo* > servers; AutoPtr serversocketusernetgen; #endif // visualization scenes, pointer vs selects which one is drawn: static VisualScene vscross; DLL_HEADER extern VisualSceneSurfaceMeshing vssurfacemeshing; DLL_HEADER extern VisualSceneMeshDoctor vsmeshdoc; static VisualSceneSpecPoints vsspecpoints; VisualScene *vs = &vscross; extern char * err_needsmesh;// = (char*) "This operation needs a mesh"; extern char * err_jobrunning;// = (char*) "Meshing Job already running"; #ifndef SMALLLIB // // Destination for messages, errors, ... #ifndef WIN32 DLL_HEADER void Ng_PrintDest(const char * s) { /* #ifdef PARALLEL int id, ntasks; MPI_Comm_size(MPI_COMM_WORLD, &ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &id); #else int id = 0; int ntasks = 1; #endif */ if (id == 0) (*mycout) << s << flush; /* if ( ntasks == 1 ) (*mycout) << s << flush; else (*mycout) << "p" << id << ": " << s << flush ; */ } #endif void MyError2(const char * ch) { cout << ch; (*testout) << "Error !!! " << ch << endl << flush; } #endif static clock_t starttimea; void ResetTime2 () { starttimea = clock(); } #ifndef SMALLLIB double GetTime2 () { return double(clock() - starttimea) / CLOCKS_PER_SEC; } #endif // file handling .. int Ng_New (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (strcmp (argv[1], "mesh") == 0) mesh.reset(); if (strcmp (argv[1], "geom") == 0) { /* delete ng_geometry; ng_geometry = new NetgenGeometry; */ ng_geometry = make_shared(); } return TCL_OK; } int Ng_ImportMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]); int Ng_LoadMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { string filename (argv[1]); if (filename.find(".vol") == string::npos) { return Ng_ImportMesh(clientData,interp,argc,argv); } PrintMessage (1, "load mesh from file ", filename); mesh = make_shared(); try { istream * infile; // if (filename.substr (filename.length()-3, 3) == ".gz") if (filename.find(".vol.gz") != string::npos) infile = new igzstream (filename.c_str()); else infile = new ifstream (filename.c_str()); // ifstream infile(filename.c_str()); mesh -> Load(*infile); // vsmesh.SetMesh (mesh); SetGlobalMesh (mesh); #ifdef PARALLEL MyMPI_SendCmd ("mesh"); mesh -> Distribute(); #endif for (int i = 0; i < geometryregister.Size(); i++) { NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (*infile); if (hgeom) { ng_geometry = shared_ptr(hgeom); break; } } delete infile; /* string auxstring; if(infile.good()) { infile >> auxstring; if(auxstring == "csgsurfaces") { CSGeometry * geometry = new CSGeometry (""); geometry -> LoadSurfaces(infile); delete ng_geometry; ng_geometry = geometry; } } */ } catch (NgException e) { PrintMessage (3, e.What()); return TCL_ERROR; } PrintMessage (2, mesh->GetNP(), " Points, ", mesh->GetNE(), " Elements."); return TCL_OK; } int Ng_SaveMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } string filename (argv[1]); PrintMessage (1, "Save mesh to file ", filename, ".... Please Wait!"); ostream * outfile; if (filename.substr (filename.length()-3, 3) == ".gz") outfile = new ogzstream (filename.c_str()); else outfile = new ofstream (filename.c_str()); mesh -> Save (*outfile); // *outfile << endl << endl << "endmesh" << endl << endl; if (ng_geometry && !mesh->GetGeometry()) ng_geometry -> SaveToMeshFile (*outfile); delete outfile; PrintMessage (1, "Save mesh to file .... DONE!"); return TCL_OK; } int Ng_MergeMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { string filename (argv[1]); PrintMessage (1, "merge with mesh from file ", filename); try { CSGeometry * geometry = dynamic_cast (ng_geometry.get()); //mesh -> Merge (filename); ifstream infile(filename.c_str()); const int offset = (geometry) ? geometry->GetNSurf() : 0; mesh -> Merge(infile,offset); string auxstring; if(infile.good()) { infile >> auxstring; if(geometry && auxstring == "csgsurfaces") geometry -> LoadSurfaces(infile); } } catch (NgException e) { PrintMessage (3, e.What()); return TCL_ERROR; } PrintMessage (2, mesh->GetNP(), " Points, ", mesh->GetNSE(), " Surface Elements."); return TCL_OK; } int Ng_ExportMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } string filename (argv[1]); string filetype (argv[2]); PrintMessage (1, "Export mesh to file ", filename, ".... Please Wait!"); // CSGeometry * geometry = dynamic_cast (ng_geometry); if (WriteUserFormat (filetype, *mesh, /* *ng_geometry, */ filename)) { ostringstream ost; ost << "Sorry, nothing known about file format " << filetype << endl; Tcl_SetResult (interp, (char*)ost.str().c_str(), TCL_VOLATILE); return TCL_ERROR; } PrintMessage (1, "Export mesh to file .... DONE!"); return TCL_OK; } int Ng_ImportMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { const string filename (argv[1]); PrintMessage (1, "import mesh from ", filename); mesh = make_shared(); ReadFile (*mesh, filename); PrintMessage (2, mesh->GetNP(), " Points, ", mesh->GetNE(), " Elements."); mesh->SetGlobalH (mparam.maxh); mesh->CalcLocalH(mparam.grading); return TCL_OK; } int Ng_ImportSolution (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } const char * filename = argv[1]; PrintMessage (1, "Import solution from file ", filename); ImportSolution2 (filename); return TCL_OK; } static DemoView * demoview = 0; int Ng_ShowDemo (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { const char * filename = argv[1]; PrintMessage (1, "Show demo ", filename); demoview = new DemoView (filename); return TCL_OK; } int Ng_DemoSetTime (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { cout << "demosettime, time = " << argv[1] << endl; int result = -1; static char strminusone[] = "-1"; static char str0[] = "0"; if (demoview) result = demoview->SetTime (atof (argv[1])); if (result == -1) Tcl_SetResult (interp, strminusone, TCL_STATIC); else Tcl_SetResult (interp, str0, TCL_STATIC); return TCL_OK; } int Ng_SaveSolution (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } const char * filename = argv[1]; PrintMessage (1, "Save solution to file ", filename); netgen::GetVSSolution().SaveSolutionData (filename); return TCL_OK; } int Ng_SetNextTimeStamp (ClientData clientData, Tcl_Interp * interp, int argqc, tcl_const char *argv[]) { if (mesh) mesh -> SetNextTimeStamp(); return TCL_OK; } int Ng_LoadGeometry (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } tcl_const char * lgfilename = argv[1]; #ifdef LOG_STREAM (*logout) << "Load geometry file: " << lgfilename << endl; #endif #ifdef STAT_STREAM (*statout) << lgfilename << " & " << endl; #endif try { for (int i = 0; i < geometryregister.Size(); i++) { NetgenGeometry * hgeom = geometryregister[i]->Load (lgfilename); if (hgeom) { // delete ng_geometry; // ng_geometry = hgeom; ng_geometry = shared_ptr (hgeom); mesh.reset(); return TCL_OK; } } ifstream infile(lgfilename); if (strlen(lgfilename) < 4) { cout << "ERROR: cannot recognise file format!" << endl; } else { if ((strcmp (&lgfilename[strlen(lgfilename)-4], "iges") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "igs") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "IGS") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "IGES") == 0)) { Tcl_SetResult (interp, (char*)"IGES import requires the OpenCascade geometry kernel. " "Please install OpenCascade as described in the Netgen-website", TCL_STATIC); return TCL_ERROR; } else if (strcmp (&lgfilename[strlen(lgfilename)-3], "sat") == 0) { #ifdef ACIS PrintMessage (1, "Load ACIS geometry file ", lgfilename); acisgeometry = netgen::LoadACIS_SAT (lgfilename); #endif } else if ((strcmp (&lgfilename[strlen(lgfilename)-4], "step") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "stp") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-3], "STP") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "STEP") == 0)) { #ifdef ACISxxx PrintMessage (1, "Load STEP geometry file ", lgfilename); acisgeometry = netgen::LoadACIS_STEP (lgfilename); #else Tcl_SetResult (interp, (char*)"IGES import requires the OpenCascade geometry kernel. " "Please install OpenCascade as described in the Netgen-website", TCL_STATIC); return TCL_ERROR; #endif } else if ((strcmp (&lgfilename[strlen(lgfilename)-4], "brep") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "Brep") == 0) || (strcmp (&lgfilename[strlen(lgfilename)-4], "BREP") == 0)) { Tcl_SetResult (interp, (char*)"BREP import requires the OpenCascade geometry kernel. " "Please install OpenCascade as described in the Netgen-website", TCL_STATIC); return TCL_ERROR; } } } catch (NgException e) { Tcl_SetResult (interp, const_cast (e.What().c_str()), TCL_VOLATILE); return TCL_ERROR; } mesh.reset(); return TCL_OK; } int Ng_SaveGeometry (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (argc == 2) { const char * cfilename = argv[1]; try { ng_geometry -> Save (string (cfilename)); } catch (NgException e) { Tcl_SetResult (interp, const_cast (e.What().c_str()), TCL_VOLATILE); return TCL_ERROR; } PrintMessage (1, "Save geometry to file ", cfilename); if (strlen(cfilename) < 4) {cout << "ERROR: can not recognise file format!!!" << endl;} else { #ifdef ACIS if (acisgeometry) { char * filename = const_cast (argv[1]); if (strcmp (&filename[strlen(filename)-3], "sat") == 0) { acisgeometry -> SaveSATFile (filename); } } #endif /* if (strcmp (&cfilename[strlen(cfilename)-3], "ngg") == 0) { CSGeometry * geometry = dynamic_cast (ng_geometry); if (geometry) { ofstream of(cfilename); geometry->Save (of); } } */ } } return TCL_OK; } int Ng_ReadStatus (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { char buf[20], lstring[200]; if (mesh) { sprintf (buf, "%u", unsigned(mesh->GetNP())); Tcl_SetVar (interp, "::status_np", buf, 0); sprintf (buf, "%u", unsigned(mesh->GetNE())); Tcl_SetVar (interp, "::status_ne", buf, 0); sprintf (buf, "%u", unsigned(mesh->GetNSE())); Tcl_SetVar (interp, "::status_nse", buf, 0); } else { Tcl_SetVar (interp, "::status_np", "0", 0); Tcl_SetVar (interp, "::status_ne", "0", 0); Tcl_SetVar (interp, "::status_nse", "0", 0); } if (multithread.running) Tcl_SetVar (interp, "::status_working", "working", 0); else Tcl_SetVar (interp, "::status_working", " ", 0); Tcl_SetVar (interp, "::status_task", const_cast(multithread.task), 0); sprintf (buf, "%lf", multithread.percent); Tcl_SetVar (interp, "::status_percent", buf, 0); lstring[0] = 0; for (int i = 1; i <= tets_in_qualclass.Size(); i++) { sprintf (buf, " %d", tets_in_qualclass.Get(i)); strcat (lstring, buf); } for (int i = tets_in_qualclass.Size()+1; i <= 20; i++) strcat (lstring, " 0"); Tcl_SetVar (interp, "::status_tetqualclasses", lstring, 0); { lock_guard guard(tcl_todo_mutex); if (multithread.tcl_todo->length()) { Tcl_Eval (interp, multithread.tcl_todo->c_str()); *multithread.tcl_todo = ""; } } return TCL_OK; } int Ng_MemInfo (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) {/* if (argc < 2) return TCL_ERROR; if (strcmp (argv[1], "usedmb") == 0) { // returns string of 512 '0' or '1' static char usedmb[513]; for (int i = 0; i < 512; i++) usedmb[i] = (i % 7 == 0) ? '1' : '0'; usedmb[512] = 0; BaseDynamicMem::GetUsed (512, usedmb); Tcl_SetResult (interp, usedmb, TCL_STATIC); return TCL_OK; } */ return TCL_ERROR; } int Ng_BCProp (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { static char buf[100]; if (argc < 2) { Tcl_SetResult (interp, (char*)"Ng_BCProp needs arguments", TCL_STATIC); return TCL_ERROR; } if (strcmp (argv[1], "setbc") == 0) { int facenr = atoi (argv[2]); int bcnr = atoi (argv[3]); if (mesh && facenr >= 1 && facenr <= mesh->GetNFD()) mesh->GetFaceDescriptor (facenr).SetBCProperty (bcnr); } if (strcmp (argv[1], "setall") == 0) { int bcnr = atoi (argv[2]); if (mesh) { int nfd = mesh->GetNFD(); for (int i = 1; i <= nfd; i++) mesh->GetFaceDescriptor (i).SetBCProperty (bcnr); } } if (strcmp (argv[1], "getbc") == 0) { int facenr = atoi (argv[2]); if (mesh && facenr >= 1 && facenr <= mesh->GetNFD()) { sprintf (buf, "%d", mesh->GetFaceDescriptor(facenr).BCProperty()); } else { strcpy (buf, "0"); } Tcl_SetResult (interp, buf, TCL_STATIC); } if (strcmp (argv[1], "getbcname") == 0) { int facenr = atoi (argv[2]); if (mesh && facenr >= 1 && facenr <= mesh->GetNFD()) { sprintf (buf, "%s", mesh->GetFaceDescriptor(facenr).GetBCName().c_str()); } else { strcpy (buf, "-"); } Tcl_SetResult (interp, buf, TCL_STATIC); } if (strcmp (argv[1], "getactive") == 0) { sprintf (buf, "%d", vsmesh.SelectedFace()); Tcl_SetResult (interp, buf, TCL_STATIC); } if (strcmp (argv[1], "setactive") == 0) { int facenr = atoi (argv[2]); if (mesh && facenr >= 1 && facenr <= mesh->GetNFD()) { vsmesh.SetSelectedFace (facenr); } } if (strcmp (argv[1], "getnfd") == 0) { if (mesh) sprintf (buf, "%d", mesh->GetNFD()); else sprintf (buf, "0"); Tcl_SetResult (interp, buf, TCL_STATIC); } return TCL_OK; } int Ng_Refine (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } #ifdef ACIS if (acisgeometry) { ACISRefinementSurfaces ref (*acisgeometry); ACISMeshOptimize2dSurfaces opt(*acisgeometry); ref.Set2dOptimizer(&opt); ref.Refine (*mesh); } else #endif { // ng_geometry -> GetRefinement().Refine(*mesh); mesh->GetGeometry()->GetRefinement().Refine(*mesh); } //redo second order refinement if desired if (mparam.secondorder) const_cast (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder(*mesh); return TCL_OK; } int Ng_SecondOrder (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } const_cast (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder (*mesh); return TCL_OK; } void * HighOrderDummy (void *) { // mparam.elementorder = atoi (Tcl_GetVar (interp, "options.elementorder", 0)); const char * savetask = multithread.task; Refinement & ref = const_cast (mesh->GetGeometry()->GetRefinement()); mesh -> GetCurvedElements().BuildCurvedElements (&ref, mparam.elementorder); multithread.task = savetask; multithread.running = 0; multithread.terminate = 1; mesh -> SetNextMajorTimeStamp(); return 0; } int Ng_HighOrder (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } multithread.running = 1; multithread.terminate = 0; mparam.elementorder = atoi(argv[1]); HighOrderDummy(NULL); return TCL_OK; } void * ValidateDummy (void *) { Refinement & ref = const_cast (mesh->GetGeometry()->GetRefinement()); ref.ValidateSecondOrder (*mesh); multithread.running = 0; return NULL; } int Ng_ValidateSecondOrder (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } multithread.running = 1; RunParallel (ValidateDummy, NULL); return TCL_OK; } int Ng_ZRefinement (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } ZRefinementOptions opt; opt.minref = 5; if (argc >= 2) opt.minref = atoi (argv[1]); ZRefinement (*mesh, ng_geometry.get(), opt); return TCL_OK; } int Ng_HPRefinement (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } int levels = atoi (argv[1]); Refinement & ref = const_cast (mesh->GetGeometry()->GetRefinement()); HPRefinement (*mesh, &ref, levels); return TCL_OK; } int Ng_LoadMeshSize (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } mesh->LoadLocalMeshSize(argv[1]); return TCL_OK; } int Ng_MeshSizeFromSurfaceMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } mesh->SetGlobalH (mparam.maxh); mesh->CalcLocalH(mparam.grading); return TCL_OK; } // Philippose Rajan - 13 June 2009 // Added a new TCL function call for the generation // of prismatic boundary layers int Ng_GenerateBoundaryLayer (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if(multithread.running) { Tcl_SetResult(interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } cout << "Generate Prismatic Boundary Layers (Experimental)...." << endl; // Use an array to support creation of boundary // layers for multiple surfaces in the future... Array surfid; int surfinp = 0; int prismlayers = 1; double hfirst = 0.01; double growthfactor = 1.0; while(surfinp >= 0) { cout << "Enter Surface ID (-1 to end list): "; cin >> surfinp; if(surfinp >= 0) surfid.Append(surfinp); } cout << "Number of surfaces entered = " << surfid.Size() << endl; cout << "Selected surfaces are:" << endl; for(int i = 1; i <= surfid.Size(); i++) cout << "Surface " << i << ": " << surfid.Elem(i) << endl; cout << endl << "Enter number of prism layers: "; cin >> prismlayers; if(prismlayers < 1) prismlayers = 1; cout << "Enter height of first layer: "; cin >> hfirst; if(hfirst <= 0.0) hfirst = 0.01; cout << "Enter layer growth / shrink factor: "; cin >> growthfactor; if(growthfactor <= 0.0) growthfactor = 0.5; BoundaryLayerParameters blp; blp.surfid = surfid; blp.prismlayers = prismlayers; blp.hfirst = blp.hfirst; blp.growthfactor = growthfactor; GenerateBoundaryLayer (*mesh, blp); return TCL_OK; } int Ng_InsertVirtualBL (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } InsertVirtualBoundaryLayer (*mesh); return TCL_OK; } int Ng_CutOffAndCombine (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { Mesh othermesh; othermesh.Load (argv[1]); othermesh.SetGlobalH (mparam.maxh); othermesh.CalcLocalH(mparam.grading); CutOffAndCombine (*mesh, othermesh); return TCL_OK; } int Ng_HelmholtzMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { HelmholtzMesh (*mesh); return TCL_OK; } int Ng_SetMeshingParameters (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { mparam.maxh = atof (Tcl_GetVar (interp, "::options.meshsize", 0)); mparam.minh = atof (Tcl_GetVar (interp, "::options.minmeshsize", 0)); mparam.meshsizefilename = Tcl_GetVar (interp, "::options.meshsizefilename", 0); // if (!strlen (mparam.meshsizefilename)) mparam.meshsizefilename = NULL; mparam.curvaturesafety = atof (Tcl_GetVar (interp, "::options.curvaturesafety", 0)); mparam.segmentsperedge = atof (Tcl_GetVar (interp, "::options.segmentsperedge", 0)); mparam.badellimit = atof (Tcl_GetVar (interp, "::options.badellimit", 0)); mparam.secondorder = atoi (Tcl_GetVar (interp, "::options.secondorder", 0)); mparam.elementorder = atoi (Tcl_GetVar (interp, "::options.elementorder", 0)); mparam.quad = atoi (Tcl_GetVar (interp, "::options.quad", 0)); mparam.try_hexes = atoi (Tcl_GetVar (interp, "::options.try_hexes", 0)); mparam.inverttets = atoi (Tcl_GetVar (interp, "::options.inverttets", 0)); mparam.inverttrigs = atoi (Tcl_GetVar (interp, "::options.inverttrigs", 0)); mparam.uselocalh = atoi (Tcl_GetVar (interp, "::options.localh", 0)); mparam.grading = atof (Tcl_GetVar (interp, "::options.grading", 0)); mparam.delaunay = atoi (Tcl_GetVar (interp, "::options.delaunay", 0)); mparam.checkoverlap = atoi (Tcl_GetVar (interp, "::options.checkoverlap", 0)); mparam.checkoverlappingboundary = atoi (Tcl_GetVar (interp, "::options.checkoverlappingboundary", 0)); mparam.checkchartboundary = atoi (Tcl_GetVar (interp, "::options.checkchartboundary", 0)); mparam.optsteps3d = atoi (Tcl_GetVar (interp, "::options.optsteps3d", 0)); mparam.optsteps2d = atoi (Tcl_GetVar (interp, "::options.optsteps2d", 0)); mparam.opterrpow = atof (Tcl_GetVar (interp, "::options.opterrpow", 0)); mparam.parthread = atoi (Tcl_GetVar (interp, "::options.parthread", 0)); mparam.elsizeweight = atof (Tcl_GetVar (interp, "::options.elsizeweight", 0)); mparam.autozrefine = atoi (Tcl_GetVar (interp, "::options.autozrefine", 0)); extern int printmessage_importance; extern int printdots; printmessage_importance = atoi (Tcl_GetVar (interp, "::options.printmsg", 0)); printdots = (printmessage_importance >= 4); //BaseMoveableMem::totalsize = 0; // 1048576 * atoi (Tcl_GetVar (interp, "::options.memory", 0)); if (mesh) { mesh->SetGlobalH (mparam.maxh); mesh->SetMinimalH (mparam.minh); } #ifdef PARALLELGL MyMPI_SendCmd ("bcastparthread"); MyMPI_Bcast (mparam.parthread, MPI_COMM_WORLD); #endif return TCL_OK; } int Ng_SetDebugParameters (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { debugparam.slowchecks = atoi (Tcl_GetVar (interp, "::debug.slowchecks", 0)); debugparam.debugoutput = atoi (Tcl_GetVar (interp, "::debug.debugoutput", 0)); debugparam.haltexistingline = atoi (Tcl_GetVar (interp, "::debug.haltexistingline", 0)); debugparam.haltoverlap = atoi (Tcl_GetVar (interp, "::debug.haltoverlap", 0)); debugparam.haltsuccess = atoi (Tcl_GetVar (interp, "::debug.haltsuccess", 0)); debugparam.haltnosuccess = atoi (Tcl_GetVar (interp, "::debug.haltnosuccess", 0)); debugparam.haltlargequalclass = atoi (Tcl_GetVar (interp, "::debug.haltlargequalclass", 0)); debugparam.haltsegment = atoi (Tcl_GetVar (interp, "::debug.haltsegment", 0)); debugparam.haltnode = atoi (Tcl_GetVar (interp, "::debug.haltnode", 0)); debugparam.haltface = atoi (Tcl_GetVar (interp, "::debug.haltface", 0)); debugparam.haltsegmentp1 = atoi (Tcl_GetVar (interp, "::debug.haltsegmentp1", 0)); debugparam.haltsegmentp2 = atoi (Tcl_GetVar (interp, "::debug.haltsegmentp2", 0)); debugparam.haltfacenr = atoi (Tcl_GetVar (interp, "::debug.haltfacenr", 0)); return TCL_OK; } int Ng_GetCommandLineParameter (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (argc != 2) { Tcl_SetResult (interp, (char*)"Ng_GetCommandLineParameter needs 1 parameter", TCL_STATIC); return TCL_ERROR; } static char buf[10]; if (parameters.StringFlagDefined (argv[1])) Tcl_SetResult (interp, (char*)parameters.GetStringFlag (argv[1], NULL), TCL_STATIC); else if (parameters.NumFlagDefined (argv[1])) { sprintf (buf, "%lf", parameters.GetNumFlag (argv[1], 0)); Tcl_SetResult (interp, buf, TCL_STATIC); } else if (parameters.GetDefineFlag (argv[1])) Tcl_SetResult (interp, (char*)"defined", TCL_STATIC); else Tcl_SetResult (interp, (char*)"undefined", TCL_STATIC); return TCL_OK; } static int perfstepsstart; static int perfstepsend; static char* optstring = NULL; static char* optstringcsg = NULL; void * MeshingDummy (void *) { const char * savetask = multithread.task; multithread.task = "Generate Mesh"; ResetTime(); try { #ifdef LOG_STREAM (*logout) << "Start meshing" << endl; (*logout) << "Meshing parameters:" << endl; mparam.Print (*logout); #endif #ifdef ACIS if (acisgeometry) { ACISGenerateMesh(*acisgeometry, mesh.Ptr(), perfstepsstart, perfstepsend, optstring); } else #endif if (ng_geometry) { mesh = make_shared (); // vsmesh.SetMesh (mesh); SetGlobalMesh (mesh); mesh -> SetGeometry(ng_geometry); mparam.perfstepsstart = perfstepsstart; mparam.perfstepsend = perfstepsend; int res = ng_geometry -> GenerateMesh (mesh, mparam); if (res != MESHING3_OK) { multithread.task = savetask; multithread.running = 0; return 0; } } else // no ng_geometry { multithread.task = savetask; multithread.running = 0; return 0; } if (mparam.autozrefine) { ZRefinementOptions opt; opt.minref = 5; ZRefinement (*mesh, ng_geometry.get(), opt); mesh -> SetNextMajorTimeStamp(); } if (mparam.secondorder) { const_cast (mesh->GetGeometry()->GetRefinement()).MakeSecondOrder (*mesh); mesh -> SetNextMajorTimeStamp(); } if (mparam.elementorder > 1) { mesh -> GetCurvedElements().BuildCurvedElements (&const_cast (mesh->GetGeometry()->GetRefinement()), mparam.elementorder); mesh -> SetNextMajorTimeStamp(); } PrintMessage (1, "Meshing done, time = ", GetTime(), " sec"); } catch (NgException e) { cout << e.What() << endl; } multithread.task = savetask; multithread.running = 0; #ifdef OCCGEOMETRYorig // currently not active OCCGeometry * occgeometry = dynamic_cast (ng_geometry); if (occgeometry && occgeometry->ErrorInSurfaceMeshing()) { char script[] = "rebuildoccdialog"; Tcl_GlobalEval (tcl_interp, script); } #endif return NULL; } int MeshingVal(tcl_const char* str) { if (strcmp(str, "ag") == 0) {return MESHCONST_ANALYSE;} if (strcmp(str, "me") == 0) {return MESHCONST_MESHEDGES;} if (strcmp(str, "ms") == 0) {return MESHCONST_MESHSURFACE;} if (strcmp(str, "os") == 0) {return MESHCONST_OPTSURFACE;} if (strcmp(str, "mv") == 0) {return MESHCONST_MESHVOLUME;} if (strcmp(str, "ov") == 0) {return MESHCONST_OPTVOLUME;} cout << "TCL TK ERROR, wrong meshing value, return='" << str << "'" << endl; return 0; } int Ng_GenerateMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } multithread.running = 1; multithread.terminate = 0; extern void Render(bool blocking); mparam.render_function = &Render; for (int i = 0; i < geometryregister.Size(); i++) geometryregister[i] -> SetParameters (interp); Ng_SetMeshingParameters (clientData, interp, 0, argv); perfstepsstart = 1; perfstepsend = 6; if (optstringcsg) delete optstringcsg; optstringcsg = NULL; if (optstring) delete optstring; optstring = NULL; if (argc == 2) { perfstepsstart = 1; perfstepsend = MeshingVal(argv[1]); } else if (argc == 3) { perfstepsstart = MeshingVal(argv[1]); perfstepsend = MeshingVal(argv[2]); } else if (argc == 4) { perfstepsstart = MeshingVal(argv[1]); perfstepsend = MeshingVal(argv[2]); optstring = new char[strlen(argv[3])+1]; strcpy(optstring, argv[3]); optstringcsg = new char[strlen(argv[3])+1]; strcpy(optstringcsg, argv[3]); } RunParallel (MeshingDummy, NULL); return TCL_OK; } int Ng_StopMeshing (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { multithread.terminate = 1; return TCL_OK; } int Ng_MeshInfo (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } ostringstream str; if (argc >= 2 && strcmp (argv[1], "dim") == 0) str << mesh->GetDimension(); else if (argc >= 2 && strcmp (argv[1], "np") == 0) str << mesh->GetNP(); else if (argc >= 2 && strcmp (argv[1], "ne") == 0) str << mesh->GetNE(); else if (argc >= 2 && strcmp (argv[1], "nse") == 0) str << mesh->GetNSE(); else if (argc >= 2 && strcmp (argv[1], "nseg") == 0) str << mesh->GetNSeg(); else if (argc >= 2 && strcmp (argv[1], "bbox") == 0) { Point3d pmin, pmax; mesh->GetBox (pmin, pmax); str << pmin.X() << " " << pmax.X() << " " << pmin.Y() << " " << pmax.Y() << " " << pmin.Z() << " " << pmax.Z() << endl; } else { cout << "argv[1] = " << argv[1] << endl; Tcl_SetResult (interp, (char*)"Ng_MeshInfo requires an argument out of \n dim np ne", TCL_STATIC); return TCL_ERROR; } Tcl_SetResult (interp, (char*)str.str().c_str(), TCL_VOLATILE); return TCL_OK; } int Ng_MeshQuality (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } double angles[4]; char buf[10]; if (mesh) mesh->CalcMinMaxAngle(mparam.badellimit, angles); else { angles[0] = angles[1] = angles[2] = angles[3] = 0; } sprintf (buf, "%5.1lf", angles[0]); Tcl_SetVar (interp, argv[1], buf, 0); sprintf (buf, "%5.1lf", angles[1]); Tcl_SetVar (interp, argv[2], buf, 0); sprintf (buf, "%5.1lf", angles[2]); Tcl_SetVar (interp, argv[3], buf, 0); sprintf (buf, "%5.1lf", angles[3]); Tcl_SetVar (interp, argv[4], buf, 0); return TCL_OK; } int Ng_CheckSurfaceMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } mesh->FindOpenElements(); if (mesh->CheckConsistentBoundary()) { PrintMessage (1, "surface mesh not consistent, trying orientation"); mesh->SurfaceMeshOrientation(); } else { PrintMessage (1, "surface mesh consistent"); } mesh->CheckOverlappingBoundary(); return TCL_OK; } int Ng_CheckVolumeMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } mesh->CheckVolumeMesh(); return TCL_OK; } int Ng_DeleteVolMesh (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (mesh) mesh->ClearVolumeElements(); return TCL_OK; } int Ng_SplitSeparatedFaces (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (mesh) mesh->SplitSeparatedFaces (); return TCL_OK; } int Ng_RestrictH (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } if (argc != 3) return TCL_OK; if (!mesh) return TCL_OK; double loch = atof (argv[2]); if (strcmp (argv[1], "face") == 0) { cout << "Restrict h at face to " << loch << endl; mesh -> RestrictLocalH (RESTRICTH_FACE, vsmesh.SelectedFace(), loch); } if (strcmp (argv[1], "edge") == 0) { cout << "Restrict h at edge to " << loch << endl; mesh -> RestrictLocalH (RESTRICTH_EDGE, vsmesh.SelectedEdge(), loch); } if (strcmp (argv[1], "point") == 0) { cout << "Restrict h at point to " << loch << endl; mesh -> RestrictLocalH (RESTRICTH_POINT, vsmesh.SelectedPoint(), loch); } return TCL_OK; } int Ng_Anisotropy (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } if (argc != 2) return TCL_OK; if (!mesh) return TCL_OK; if (strcmp (argv[1], "edge") == 0) { int edgenr = vsmesh.SelectedEdge(); for (int i = 1; i <= mesh->GetNSeg(); i++) { Segment & seg = mesh->LineSegment(i); if (seg.edgenr == edgenr) { seg.singedge_left = 1 - seg.singedge_left; seg.singedge_right = 1 - seg.singedge_right; } } } return TCL_OK; } BisectionOptions biopt; void * BisectDummy (void *) { const Refinement & ref = mesh->GetGeometry()->GetRefinement(); MeshOptimize2d * opt = NULL; /* #ifdef ACIS if (acisgeometry) { // ref = new ACISRefinementSurfaces(*acisgeometry); opt = new ACISMeshOptimize2dSurfaces(*acisgeometry); ref->Set2dOptimizer(opt); } #endif else { ref = new RefinementSurfaces(*geometry); opt = new MeshOptimize2dSurfaces(*geometry); ref->Set2dOptimizer(opt); } */ if(!mesh->LocalHFunctionGenerated()) mesh->CalcLocalH(mparam.grading); mesh->LocalHFunction().SetGrading (mparam.grading); ref . Bisect (*mesh, biopt); mesh -> UpdateTopology(); mesh -> GetCurvedElements().BuildCurvedElements (&ref, mparam.elementorder); multithread.running = 0; delete opt; return NULL; } int Ng_Bisect (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { cout << "Thread alrad running" << endl; return TCL_OK; } multithread.running = 1; biopt.outfilename = NULL; // "ngfepp.vol"; biopt.femcode = "fepp"; biopt.refinementfilename = NULL; if (argc >= 2) biopt.refinementfilename = argv[1]; BisectDummy (0); /* extern void BisectTets (Mesh &, const CSGeometry *); BisectTets (*mesh, geometry); */ return TCL_OK; } // int Ng_BisectCopyMesh (ClientData clientData, // Tcl_Interp * interp, // int argc, tcl_const char *argv[]) // { // if (!mesh) // { // Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); // return TCL_ERROR; // } // if (multithread.running) // { // Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); // return TCL_ERROR; // } // BisectTetsCopyMesh (*mesh, geometry.Ptr(), biopt); // return TCL_OK; // } int Ng_Split2Tets (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } if (multithread.running) { Tcl_SetResult (interp, err_jobrunning, TCL_STATIC); return TCL_ERROR; } mesh->Split2Tets (); return TCL_OK; } extern int Ng_MeshDoctor (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]); SymbolTable & GetVisualizationScenes () { static SymbolTable vss; return vss; } void AddVisualizationScene (const string & name, VisualScene * avs) { GetVisualizationScenes().Set (name.c_str(), avs); } void SetVisualScene (Tcl_Interp * interp) { const char * vismode = vispar.selectvisual; // Tcl_GetVar (interp, "selectvisual", 0); vs = &vscross; if (GetVisualizationScenes().Used(vismode)) { vs = GetVisualizationScenes()[vismode]; } else if (vismode) { if (strcmp (vismode, "geometry") == 0) { for (int i = 0; i < geometryregister.Size(); i++) { VisualScene * hvs = geometryregister[i]->GetVisualScene (ng_geometry.get()); if (hvs) { vs = hvs; return; } } #ifdef ACIS else if (acisgeometry) vs = &vsacisgeom; #endif // ACIS } if (strcmp (vismode, "mesh") == 0) { if (!meshdoctor.active) vs = &vsmesh; else vs = &vsmeshdoc; } // if (strcmp (vismode, "surfmeshing") == 0) vs = &vssurfacemeshing; if (strcmp (vismode, "specpoints") == 0) vs = &vsspecpoints; if (strcmp (vismode, "solution") == 0) vs = &netgen::GetVSSolution(); } } Font * font = nullptr; Togl * togl = NULL; void MyOpenGLText_GUI (const char * text) { glListBase (font->getDisplayListsBase()); glCallLists (GLsizei(strlen(text)), GL_UNSIGNED_BYTE, text); } static int Ng_ToglVersion(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_SetResult (interp, (char*)"2", TCL_STATIC); return TCL_OK; } static int init(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { // cout << "call init" << endl; if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) return TCL_ERROR; // possible values: 12,14,16,18,20,22,24,28,32 font = selectFont(18); LoadOpenGLFunctionPointers(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); SetVisualScene (Togl_Interp(togl)); vs->DrawScene(); Set_OpenGLText_Callback (&MyOpenGLText_GUI); return TCL_OK; } static int zap(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return TCL_OK; } static int draw(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { SetVisualScene (interp); glPushMatrix(); glLoadIdentity(); vs->DrawScene(); Togl_SwapBuffers(togl); glPopMatrix(); return TCL_OK; } static int reshape(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int w = Togl_Width (togl); int h = Togl_Height (togl); // glViewport(0, 0, w, h); int res[4]; glGetIntegerv(GL_VIEWPORT, res); // cout << "w = " << w << " h = " << h << endl; w = res[2]; h = res[3]; /* cout << "viewport: " << res[0] << " " << res[1] << " " << res[2] << " " << res[3] << endl; */ // change font size according to window width font = selectFont(w/80); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // OpenGL near and far clipping planes double pnear = 0.1; double pfar = 10; gluPerspective(20.0f, double(w) / h, pnear, pfar); glMatrixMode(GL_MODELVIEW); return TCL_OK; } static int Ng_SnapShot(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const *argv) { struct Togl *togl; if (Togl_GetToglFromObj(interp, argv[1], &togl) != TCL_OK) return TCL_ERROR; const char * filename = Tcl_GetString(argv[2]); int len = strlen(filename); int w = Togl_PixelScale(togl)*Togl_Width (togl); int h = Togl_PixelScale(togl)*Togl_Height (togl); Array buffer(w*h*3); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glPixelStorei(GL_PACK_ALIGNMENT,1); glReadPixels (0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &buffer[0]); #ifdef JPEGLIB if (strcmp ("jpg", filename+len-3) == 0) { cout << "Snapshot to file '" << filename << "'" << endl; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; FILE *outfile = fopen(filename,"wb"); JSAMPROW row_pointer[1]; int row_stride, quality = 100; // 1...100 cinfo.err = jpeg_std_error( &jerr ); jpeg_create_compress( &cinfo ); jpeg_stdio_dest( &cinfo, outfile ); cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults( &cinfo ); jpeg_set_quality( &cinfo, quality, FALSE ); // TRUE jpeg_start_compress( &cinfo, TRUE ); row_stride = 3*w; while( cinfo.next_scanline < cinfo.image_height ) { row_pointer[0] = &buffer[ (h-1-cinfo.next_scanline) * row_stride ]; (void)jpeg_write_scanlines( &cinfo, row_pointer, 1 ); } jpeg_finish_compress( &cinfo ); fclose( outfile ); jpeg_destroy_compress( &cinfo ); fprintf( stdout, "done [ok]\n" ); fflush( stdout ); return TCL_OK; } #endif // JPEGLIB { string command; string filename2; filename2 = filename; if(filename2.substr(len-3) != ".ppm") filename2 += ".ppm"; cout << "Snapshot to file '" << filename << endl; // int w = Togl_Width (togl); // int h = Togl_Height (togl); ofstream outfile(filename2); outfile << "P6" << endl << "# CREATOR: Netgen" << endl << w << " " << h << endl << "255" << endl; for (int i = 0; i < h; i++) for (int j = 0; j < w; j++) for (int k = 0; k < 3; k++) outfile.put (buffer[k+3*j+3*w*(h-i-1)]); outfile << flush; if (filename2 == string(filename)) return TCL_OK; else { // convert image file (Unix/Linux only): command = string("convert -quality 100 ") + filename2 + " " + filename; int err = system(command.c_str()); if (err != 0) { Tcl_SetResult (Togl_Interp(togl), (char*)"Cannot convert image file, stored as .ppm", TCL_VOLATILE); return TCL_ERROR; } command = string("rm ") + filename2; err = system(command.c_str()); if (err != 0) { Tcl_SetResult (Togl_Interp(togl), (char*)"Cannot delete temporary file", TCL_VOLATILE); return TCL_ERROR; } return TCL_OK; } } } #ifdef FFMPEG static int Ng_VideoClip(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const *argv) { static Mpeg mpeg; struct Togl *togl; if (Togl_GetToglFromObj(interp, argv[1], &togl) != TCL_OK) return TCL_ERROR; if (strcmp (Tcl_GetString(argv[2]), "init") == 0) { // Can't initialize when running: //------------------------------- if( mpeg.IsStarted() ) { cout << "cannot initialize: already running" << endl; return TCL_ERROR; } const char * filename = Tcl_GetString(argv[3]); mpeg.Start(filename); return TCL_OK; } else if (strcmp (Tcl_GetString(argv[2]), "addframe") == 0) { if(mpeg.AddFrame()) return TCL_ERROR; } else if (strcmp (Tcl_GetString(argv[2]), "finalize") == 0) { mpeg.Stop(); } return TCL_OK; } #else // FFMPEG static int Ng_VideoClip(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const *argv) { Tcl_SetResult (Togl_Interp(togl), (char*)"Video not available, Netgen was not compiled with FFMPEG library", TCL_STATIC); return TCL_ERROR; } #endif // FFMPEG int Ng_MouseMove (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { int oldx, oldy; int newx, newy; oldx = atoi (argv[1]); oldy = atoi (argv[2]); newx = atoi (argv[3]); newy = atoi (argv[4]); SetVisualScene(interp); vs->MouseMove (oldx, oldy, newx, newy, argv[5][0]); return TCL_OK; } int Ng_MouseDblClick (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { int px = Togl_PixelScale(togl)*atoi (argv[1]); int py = Togl_PixelScale(togl)*atoi (argv[2]); SetVisualScene(interp); vs->MouseDblClick (px, py); return TCL_OK; } int Ng_ZoomAll (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { SetVisualScene(interp); vs->BuildScene (1); return TCL_OK; } int Ng_Center (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { SetVisualScene(interp); vs->BuildScene (2); return TCL_OK; } int Ng_StandardRotation (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { SetVisualScene(interp); vs->StandardRotation (argv[1]); return TCL_OK; } int Ng_ArbitraryRotation (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { SetVisualScene(interp); Array alpha; Array vec; for(int i=1; iArbitraryRotation (alpha,vec); return TCL_OK; } int Ng_Metis (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { #ifdef PARALLEL if (!mesh) { Tcl_SetResult (interp, err_needsmesh, TCL_STATIC); return TCL_ERROR; } int nparts = atoi (argv[1]); ntasks = nparts+1; cout << "calling metis ... " << flush; mesh->ParallelMetis(); cout << "done" << endl; ntasks = 1; // for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) // (*mesh)[ei].SetIndex ( (*mesh)[ei].GetPartition() ); return TCL_OK; #else Tcl_SetResult (interp, (char*)"metis not available", TCL_STATIC); return TCL_ERROR; #endif #ifdef OLDOLD // METIS Partitioning if (mesh->GetDimension() == 3) { using namespace metis; int ne = mesh->GetNE(); if (ne < 3) { Tcl_SetResult (interp, "This operation needs a volume mesh", TCL_STATIC); return TCL_ERROR; } int nn = mesh->GetNP(); ELEMENT_TYPE elementtype = mesh->VolumeElement(1).GetType(); int npe = mesh->VolumeElement(1).GetNP(); for (int i = 2; i<=ne; i++) if (mesh->VolumeElement(i).GetType() != elementtype) { Tcl_SetResult (interp, "Works in 3D only uniformal tet or hex meshes", TCL_STATIC); return TCL_ERROR; } idxtype *elmnts; elmnts = new idxtype[ne*npe]; int etype; if (elementtype == TET) etype = 2; else if (elementtype == HEX) etype = 3; else { Tcl_SetResult (interp, "Works in 3D only uniformal tet or hex meshes", TCL_STATIC); return TCL_ERROR; } for (int i=1; i<=ne; i++) for (int j=1; j<=npe; j++) elmnts[(i-1)*npe+(j-1)] = mesh->VolumeElement(i).PNum(j)-1; int numflag = 0; int nparts = atoi (argv[1]); int edgecut; idxtype *epart, *npart; epart = new idxtype[ne]; npart = new idxtype[nn]; cout << "Starting Metis (" << ne << " Elements, " << nn << " Nodes, " << nparts << " Partitions) ... " << flush; METIS_PartMeshNodal (&ne, &nn, elmnts, &etype, &numflag, &nparts, &edgecut, epart, npart); cout << "done" << endl; cout << "edge-cut: " << edgecut << ", balance: " << ComputeElementBalance(ne, nparts, epart) << endl; for (int i=1; i<=ne; i++) mesh->VolumeElement(i).SetPartition(epart[i-1]); mesh->SetNextTimeStamp(); } #endif return TCL_OK; } void SelectFaceInOCCDialogTree (int facenr) { char script[50]; sprintf (script, "selectentity {Face %i}", facenr); Tcl_GlobalEval (tcl_interp, script); } #ifndef ACIS int Ng_ACISCommand (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (argc >= 2) { if (strcmp (argv[1], "isACISavailable") == 0) { Tcl_SetResult (interp, (char*)"no", TCL_STATIC); return TCL_OK; } } Tcl_SetResult (interp, (char*)"undefined ACiS command", TCL_STATIC); return TCL_ERROR; } #endif // from ng_interface void Ng_SetVisualizationParameter (const char * name, const char * value) { // #ifdef OPENGL // #ifndef NOTCL char buf[100]; sprintf (buf, "visoptions.%s", name); if (printmessage_importance>0) { cout << "name = " << name << ", value = " << value << endl; cout << "set tcl-variable " << buf << " to " << value << endl; } Tcl_SetVar (tcl_interp, buf, const_cast (value), 0); Tcl_Eval (tcl_interp, "Ng_Vis_Set parameters;"); // #endif // #endif } } using namespace netgen; void Ng_SetMouseEventHandler (netgen::MouseEventHandler * handler) { vsmesh.SetMouseEventHandler (handler); } void Ng_SetUserVisualizationObject (netgen::UserVisualizationObject * vis) { netgen::GetVSSolution().AddUserVisualizationObject (vis); } namespace netgen { int firsttime = 1; int animcnt = 0; void PlayAnimFile(const char* name, int speed, int maxcnt) { //extern Mesh * mesh; /* if (mesh) mesh->DeleteMesh(); if (!mesh) mesh = new Mesh(); */ mesh = make_shared(); int ne, np, i; char str[80]; char str2[80]; //int tend = 5000; // for (ti = 1; ti <= tend; ti++) //{ int rti = (animcnt%(maxcnt-1)) + 1; animcnt+=speed; sprintf(str2,"%05i.sol",rti); strcpy(str,"mbssol/"); strcat(str,name); strcat(str,str2); if (printmessage_importance>0) cout << "read file '" << str << "'" << endl; ifstream infile(str); infile >> ne; for (i = 1; i <= ne; i++) { int j; Element2d tri(TRIG); tri.SetIndex(1); //faceind for (j = 1; j <= 3; j++) infile >> tri.PNum(j); infile >> np; for (i = 1; i <= np; i++) { Point3d p; infile >> p.X() >> p.Y() >> p.Z(); if (firsttime) mesh->AddPoint (p); else mesh->Point(i) = Point<3> (p); } //firsttime = 0; Ng_Redraw(); } } int Ng_SetVisParameters (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (!Tcl_GetVar (interp, "::viewoptions.light.amb", TCL_GLOBAL_ONLY)) return TCL_ERROR; vispar.lightamb = atof (Tcl_GetVar (interp, "::viewoptions.light.amb", TCL_GLOBAL_ONLY)); vispar.lightdiff = atof (Tcl_GetVar (interp, "::viewoptions.light.diff", TCL_GLOBAL_ONLY)); vispar.lightspec = atof (Tcl_GetVar (interp, "::viewoptions.light.spec", TCL_GLOBAL_ONLY)); vispar.shininess = atof (Tcl_GetVar (interp, "::viewoptions.mat.shininess", TCL_GLOBAL_ONLY)); vispar.locviewer = atoi (Tcl_GetVar (interp, "::viewoptions.light.locviewer", TCL_GLOBAL_ONLY)); vispar.transp = atof (Tcl_GetVar (interp, "::viewoptions.mat.transp", TCL_GLOBAL_ONLY)); VisualizationParameters::Clipping hclip; hclip.normal.X() = atof (Tcl_GetVar (interp, "::viewoptions.clipping.nx", TCL_GLOBAL_ONLY)); hclip.normal.Y() = atof (Tcl_GetVar (interp, "::viewoptions.clipping.ny", TCL_GLOBAL_ONLY)); hclip.normal.Z() = atof (Tcl_GetVar (interp, "::viewoptions.clipping.nz", TCL_GLOBAL_ONLY)); hclip.dist = atof (Tcl_GetVar (interp, "::viewoptions.clipping.dist", TCL_GLOBAL_ONLY)); hclip.dist2 = atof (Tcl_GetVar (interp, "::viewoptions.clipping.dist2", TCL_GLOBAL_ONLY)); hclip.enable = atoi (Tcl_GetVar (interp, "::viewoptions.clipping.enable", TCL_GLOBAL_ONLY)); vispar.clipdomain = atoi (Tcl_GetVar (interp, "::viewoptions.clipping.onlydomain", TCL_GLOBAL_ONLY)); vispar.donotclipdomain = atoi (Tcl_GetVar (interp, "::viewoptions.clipping.notdomain", TCL_GLOBAL_ONLY)); if ( ! (hclip == vispar.clipping) ) { vispar.clipping = hclip; vispar.clipping.timestamp = NextTimeStamp(); } vispar.whitebackground = atoi (Tcl_GetVar (interp, "::viewoptions.whitebackground", TCL_GLOBAL_ONLY)); vispar.drawcoordinatecross = atoi (Tcl_GetVar (interp, "::viewoptions.drawcoordinatecross", TCL_GLOBAL_ONLY)); vispar.drawcolorbar = atoi (Tcl_GetVar (interp, "::viewoptions.drawcolorbar", TCL_GLOBAL_ONLY)); vispar.drawnetgenlogo = atoi (Tcl_GetVar (interp, "::viewoptions.drawnetgenlogo", TCL_GLOBAL_ONLY)); vispar.stereo = atoi (Tcl_GetVar (interp, "::viewoptions.stereo", TCL_GLOBAL_ONLY)); vispar.colormeshsize = atoi (Tcl_GetVar (interp, "::viewoptions.colormeshsize", TCL_GLOBAL_ONLY)); VisualScene :: SetBackGroundColor (vispar.whitebackground ? 1 : 0); strcpy (vispar.selectvisual, Tcl_GetVar (interp, "::selectvisual", TCL_GLOBAL_ONLY)); // vispar.showstltrias = atoi (Tcl_GetVar (interp, "::viewoptions.stl.showtrias", TCL_GLOBAL_ONLY)); vispar.stlshowtrias = atoi (Tcl_GetVar (interp, "::stloptions.showtrias", TCL_GLOBAL_ONLY)); vispar.stlshowfilledtrias = atoi (Tcl_GetVar (interp, "::stloptions.showfilledtrias", TCL_GLOBAL_ONLY)); vispar.stlshowedges = atoi (Tcl_GetVar (interp, "::stloptions.showedges", TCL_GLOBAL_ONLY)); vispar.stlshowmarktrias = atoi (Tcl_GetVar (interp, "::stloptions.showmarktrias", TCL_GLOBAL_ONLY)); vispar.stlshowactivechart = atoi (Tcl_GetVar (interp, "::stloptions.showactivechart", TCL_GLOBAL_ONLY)); vispar.stlchartnumber = atoi (Tcl_GetVar (interp, "::stloptions.chartnumber", TCL_GLOBAL_ONLY)); vispar.stlchartnumberoffset = atoi (Tcl_GetVar (interp, "::stloptions.chartnumberoffset", TCL_GLOBAL_ONLY)); vispar.occshowsurfaces = atoi (Tcl_GetVar (interp, "::occoptions.showsurfaces", TCL_GLOBAL_ONLY)); vispar.occshowedges = atoi (Tcl_GetVar (interp, "::occoptions.showedges", TCL_GLOBAL_ONLY)); vispar.drawoutline = atoi (Tcl_GetVar (interp, "::viewoptions.drawoutline", TCL_GLOBAL_ONLY)); vispar.drawfilledtrigs = atoi (Tcl_GetVar (interp, "::viewoptions.drawfilledtrigs", TCL_GLOBAL_ONLY)); vispar.subdivisions = atoi (Tcl_GetVar (interp, "::visoptions.subdivisions", TCL_GLOBAL_ONLY)); vispar.drawbadels = atoi (Tcl_GetVar (interp, "::viewoptions.drawbadels", TCL_GLOBAL_ONLY)); vispar.drawedges = atoi (Tcl_GetVar (interp, "::viewoptions.drawedges", TCL_GLOBAL_ONLY)); vispar.drawtetsdomain = atoi (Tcl_GetVar (interp, "::viewoptions.drawtetsdomain", TCL_GLOBAL_ONLY)); vispar.drawtets = atoi (Tcl_GetVar (interp, "::viewoptions.drawtets", TCL_GLOBAL_ONLY)); vispar.drawprisms = atoi (Tcl_GetVar (interp, "::viewoptions.drawprisms", TCL_GLOBAL_ONLY)); vispar.drawpyramids = atoi (Tcl_GetVar (interp, "::viewoptions.drawpyramids", TCL_GLOBAL_ONLY)); vispar.drawhexes = atoi (Tcl_GetVar (interp, "::viewoptions.drawhexes", TCL_GLOBAL_ONLY)); /* vispar.shrink = atof (Tcl_GetVar (interp, "::viewoptions.shrink", TCL_GLOBAL_ONLY)); */ double hshrink = atof (Tcl_GetVar (interp, "::viewoptions.shrink", TCL_GLOBAL_ONLY)); if (hshrink != vispar.shrink) { vispar.shrink = hshrink; vispar.clipping.timestamp = NextTimeStamp();} vispar.drawidentified = atoi (Tcl_GetVar (interp, "::viewoptions.drawidentified", TCL_GLOBAL_ONLY)); vispar.drawpointnumbers = atoi (Tcl_GetVar (interp, "::viewoptions.drawpointnumbers", TCL_GLOBAL_ONLY)); vispar.drawedgenumbers = atoi (Tcl_GetVar (interp, "::viewoptions.drawedgenumbers", TCL_GLOBAL_ONLY)); vispar.drawfacenumbers = atoi (Tcl_GetVar (interp, "::viewoptions.drawfacenumbers", TCL_GLOBAL_ONLY)); vispar.drawelementnumbers = atoi (Tcl_GetVar (interp, "::viewoptions.drawelementnumbers", TCL_GLOBAL_ONLY)); vispar.drawdomainsurf = atoi (Tcl_GetVar (interp, "::viewoptions.drawdomainsurf", TCL_GLOBAL_ONLY)); vispar.drawededges = atoi (Tcl_GetVar (interp, "::viewoptions.drawededges", TCL_GLOBAL_ONLY)); vispar.drawedpoints = atoi (Tcl_GetVar (interp, "::viewoptions.drawedpoints", TCL_GLOBAL_ONLY)); vispar.drawedpointnrs = atoi (Tcl_GetVar (interp, "::viewoptions.drawedpointnrs", TCL_GLOBAL_ONLY)); vispar.drawedtangents = atoi (Tcl_GetVar (interp, "::viewoptions.drawedtangents", TCL_GLOBAL_ONLY)); vispar.drawededgenrs = atoi (Tcl_GetVar (interp, "::viewoptions.drawededgenrs", TCL_GLOBAL_ONLY)); vispar.drawcurveproj = atoi (Tcl_GetVar (interp, "::viewoptions.drawcurveproj", TCL_GLOBAL_ONLY)); vispar.drawcurveprojedge = atoi (Tcl_GetVar (interp, "::viewoptions.drawcurveprojedge", TCL_GLOBAL_ONLY)); vispar.centerpoint = atoi (Tcl_GetVar (interp, "::viewoptions.centerpoint", TCL_GLOBAL_ONLY)); vispar.use_center_coords = atoi (Tcl_GetVar (interp, "::viewoptions.usecentercoords", TCL_GLOBAL_ONLY)) > 0; vispar.centerx = atof (Tcl_GetVar (interp, "::viewoptions.centerx", TCL_GLOBAL_ONLY)); vispar.centery = atof (Tcl_GetVar (interp, "::viewoptions.centery", TCL_GLOBAL_ONLY)); vispar.centerz = atof (Tcl_GetVar (interp, "::viewoptions.centerz", TCL_GLOBAL_ONLY)); vispar.drawelement = atoi (Tcl_GetVar (interp, "::viewoptions.drawelement", TCL_GLOBAL_ONLY)); vispar.drawmetispartition = atoi (Tcl_GetVar (interp, "::viewoptions.drawmetispartition", TCL_GLOBAL_ONLY)); vispar.drawspecpoint = atoi (Tcl_GetVar (interp, "::viewoptions.drawspecpoint", TCL_GLOBAL_ONLY)); vispar.specpointx = atof (Tcl_GetVar (interp, "::viewoptions.specpointx", TCL_GLOBAL_ONLY)); vispar.specpointy = atof (Tcl_GetVar (interp, "::viewoptions.specpointy", TCL_GLOBAL_ONLY)); vispar.specpointz = atof (Tcl_GetVar (interp, "::viewoptions.specpointz", TCL_GLOBAL_ONLY)); vsspecpoints.len = atof (Tcl_GetVar (interp, "::viewoptions.specpointvlen", TCL_GLOBAL_ONLY)); vispar.occdeflection = pow(10.0,-1-atof (Tcl_GetVar (interp, "::occoptions.deflection", TCL_GLOBAL_ONLY))); #ifdef PARALLELGL vsmesh.Broadcast (); #endif return TCL_OK; } int Ng_BuildFieldLines (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { netgen::GetVSSolution().BuildFieldLinesPlot(); return TCL_OK; } int Ng_Exit (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { /* #ifdef PARALLEL int id, rc, ntasks; MPI_Comm_size(MPI_COMM_WORLD, &ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &id); if ( id != 0 ) return TCL_OK; #endif */ /* if (ngsolve_handle) { void (*ngs_exit)(); ngs_exit = ( void (*)() ) dlsym (ngsolve_handle, "NGSolve_Exit"); if (ngs_exit) (*ngs_exit)(); } */ #ifdef NGSOLVE NGSolve_Exit (); #endif #ifdef ACIS outcome res; res = api_terminate_faceter(); if(!res.ok()) cerr << "problem with terminating acis faceter" << endl; res = api_terminate_constructors(); if(!res.ok()) cerr << "problem with terminating acis constructors" << endl; res = api_terminate_kernel(); if(!res.ok()) cerr << "problem with terminating acis kernel" << endl; res = api_stop_modeller(); if(!res.ok()) cerr << "problem with terminating acis modeller" << endl; //cout << "stopped acis, outcome = " << res.ok() << endl; #endif #ifdef PARALLELGL if (id == 0) MyMPI_SendCmd ("end"); MPI_Finalize(); #endif mesh.reset(); ng_geometry.reset(); if (testout != &cout) delete testout; return TCL_OK; } #ifdef SOCKETS void * ServerSocketManagerRunDummy ( void * nix ) { serversocketmanager.Run(); return NULL; } extern "C" int Ng_ServerSocketManagerRun( void ); int Ng_ServerSocketManagerRun( void ) { if(mparam.parthread) RunParallel(ServerSocketManagerRunDummy,NULL); else serversocketmanager.Run(); return TCL_OK; } extern "C" int Ng_ServerSocketManagerInit(int port); int Ng_ServerSocketManagerInit(int port) { serversocketmanager.Init(port); return TCL_OK; } #endif //SOCKETS extern "C" int Ng_Init (Tcl_Interp * interp); extern "C" int Ng_CSG_Init (Tcl_Interp * interp); extern "C" int Ng_stl_Init (Tcl_Interp * interp); extern "C" int Ng_geom2d_Init (Tcl_Interp * interp); #ifdef OCCGEOMETRY extern "C" int Ng_occ_Init (Tcl_Interp * interp); #endif // extern "C" int Ng_Geom2d_Init (Tcl_Interp * interp); // int main_Eero (ClientData clientData, // Tcl_Interp * interp, // int argc, tcl_const char *argv[]); int Ng_Init (Tcl_Interp * interp) { #ifdef SOCKETS if(serversocketmanager.Good()) serversocketusernetgen.Reset(new ServerSocketUserNetgen (serversocketmanager, mesh, geometry)); #endif Ng_CSG_Init(interp); Ng_stl_Init(interp); Ng_geom2d_Init (interp); #ifdef OCCGEOMETRY Ng_occ_Init (interp); #endif // Ng_Geom2d_Init(interp); tcl_interp = interp; // Tcl_CreateCommand (interp, "Ng_Eero", main_Eero, // (ClientData)NULL, // (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_New", Ng_New, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); // Tcl_CreateCommand (interp, "Ng_Lock", Ng_Lock, // (ClientData)NULL, // (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_LoadGeometry", Ng_LoadGeometry, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SaveGeometry", Ng_SaveGeometry, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_LoadMesh", Ng_LoadMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SaveMesh", Ng_SaveMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MergeMesh", Ng_MergeMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ExportMesh", Ng_ExportMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ImportMesh", Ng_ImportMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ImportSolution", Ng_ImportSolution, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ShowDemo", Ng_ShowDemo, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_DemoSetTime", Ng_DemoSetTime, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SaveSolution", Ng_SaveSolution, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); // meshing Tcl_CreateCommand (interp, "Ng_GenerateMesh", Ng_GenerateMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_StopMeshing", Ng_StopMeshing, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MeshInfo", Ng_MeshInfo, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MeshQuality", Ng_MeshQuality, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_CheckSurfaceMesh", Ng_CheckSurfaceMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_CheckVolumeMesh", Ng_CheckVolumeMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_DeleteVolMesh", Ng_DeleteVolMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SplitSeparatedFaces", Ng_SplitSeparatedFaces, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SetNextTimeStamp", Ng_SetNextTimeStamp, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Refine", Ng_Refine, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SecondOrder", Ng_SecondOrder, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_HighOrder", Ng_HighOrder, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ValidateSecondOrder", Ng_ValidateSecondOrder, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_RestrictH", Ng_RestrictH, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Anisotropy", Ng_Anisotropy, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Bisect", Ng_Bisect, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); // Tcl_CreateCommand (interp, "Ng_BisectCopyMesh", Ng_BisectCopyMesh, // (ClientData)NULL, // (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Split2Tets", Ng_Split2Tets, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ZRefinement", Ng_ZRefinement, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_HPRefinement", Ng_HPRefinement, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_LoadMeshSize", Ng_LoadMeshSize, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MeshSizeFromSurfaceMesh", Ng_MeshSizeFromSurfaceMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GenerateBoundaryLayer", Ng_GenerateBoundaryLayer, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_InsertVirtualBL", Ng_InsertVirtualBL, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_CutOffAndCombine", Ng_CutOffAndCombine, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_HelmholtzMesh", Ng_HelmholtzMesh, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ReadStatus", Ng_ReadStatus, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MemInfo", Ng_MemInfo, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MeshDoctor", Ng_MeshDoctor, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_BCProp", Ng_BCProp, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ACISCommand", Ng_ACISCommand, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MouseMove", Ng_MouseMove, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_MouseDblClick", Ng_MouseDblClick, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ZoomAll", Ng_ZoomAll, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Center", Ng_Center, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_StandardRotation", Ng_StandardRotation, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_ArbitraryRotation", Ng_ArbitraryRotation, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SetVisParameters", Ng_SetVisParameters, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SetMeshingParameters", Ng_SetMeshingParameters, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_SetDebugParameters", Ng_SetDebugParameters, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_GetCommandLineParameter", Ng_GetCommandLineParameter, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Exit", Ng_Exit, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_Metis", Ng_Metis, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); Tcl_CreateCommand (interp, "Ng_BuildFieldLines", Ng_BuildFieldLines, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); /* * Specify the C callback functions for widget creation, display, * and reshape. */ Tcl_CreateObjCommand(interp, "Ng_GetToglVersion", Ng_ToglVersion, NULL, NULL); if (!nodisplay) { if (Togl_Init(interp) == TCL_ERROR) return TCL_ERROR; Tcl_CreateObjCommand(interp, "init", init, NULL, NULL); Tcl_CreateObjCommand(interp, "zap", zap, NULL, NULL); Tcl_CreateObjCommand(interp, "draw", draw, NULL, NULL); Tcl_CreateObjCommand(interp, "reshape", reshape, NULL, NULL); // Togl_TimerFunc( idle ); Tcl_CreateObjCommand(interp, "Ng_SnapShot", Ng_SnapShot, NULL, NULL); Tcl_CreateObjCommand(interp, "Ng_VideoClip", Ng_VideoClip, NULL, NULL); } multithread.pause = 0; multithread.testmode = 0; multithread.redraw = 0; multithread.drawing = 1; multithread.terminate = 0; multithread.running = 0; multithread.task = ""; multithread.percent = 20; Tcl_LinkVar (interp, "multithread_pause", (char*)&multithread.pause, TCL_LINK_INT); Tcl_LinkVar (interp, "multithread_testmode", (char*)&multithread.testmode, TCL_LINK_INT); Tcl_LinkVar (interp, "multithread_redraw", (char*)&multithread.redraw, TCL_LINK_INT); Tcl_LinkVar (interp, "multithread_drawing", (char*)&multithread.drawing, TCL_LINK_INT); Tcl_LinkVar (interp, "multithread_terminate", (char*)&multithread.terminate, TCL_LINK_INT); Tcl_LinkVar (interp, "multithread_running", (char*)&multithread.running, TCL_LINK_INT); //testout->setstate(ios_base::badbit); myerr = &cerr; extern ostream * mycout; mycout = &cout; testmode = 0; #ifdef ACIS outcome res; res = api_start_modeller (0); if(!res.ok()) cerr << "problem with starting acis modeller" << endl; #ifdef ACIS_R17 unlock_spatial_products_661(); #endif res = api_initialize_kernel(); if(!res.ok()) cerr << "problem with starting acis kernel" << endl; res = api_initialize_constructors(); if(!res.ok()) cerr << "problem with starting acis constructors" << endl; res = api_initialize_faceter(); if(!res.ok()) cerr << "problem with starting acis faceter" << endl; #endif return TCL_OK; } } netgen-6.2.1905/ng/netgenpy.cpp0000644000175000017500000000327513504650527014751 0ustar kurtkurt// a wrapper to load netgen-dll into python #include #include <../general/ngpython.hpp> #ifdef WIN32 #define DLL_HEADER __declspec(dllimport) #else #define DLL_HEADER #endif void DLL_HEADER ExportNetgenMeshing(py::module &m); void DLL_HEADER ExportMeshVis(py::module &m); void DLL_HEADER ExportCSG(py::module &m); void DLL_HEADER ExportCSGVis(py::module &m); void DLL_HEADER ExportGeom2d(py::module &m); void DLL_HEADER ExportSTL(py::module &m); void DLL_HEADER ExportSTLVis(py::module &m); #ifdef OCCGEOMETRY void DLL_HEADER ExportNgOCC(py::module &m); #endif // OCCGEOMETRY PYBIND11_MODULE(libngpy, ngpy) { py::module meshing = ngpy.def_submodule("_meshing", "pybind meshing module"); ExportNetgenMeshing(meshing); py::module csg = ngpy.def_submodule("_csg", "pybind csg module"); ExportCSG(csg); py::module geom2d = ngpy.def_submodule("_geom2d", "pybind geom2d module"); ExportGeom2d(geom2d); py::module stl = ngpy.def_submodule("_stl", "pybind stl module"); ExportSTL(stl); #ifdef OCCGEOMETRY py::module NgOCC = ngpy.def_submodule("_NgOCC", "pybind NgOCC module"); ExportNgOCC(NgOCC); #endif // OCCGEOMETRY #ifdef OPENGL py::module meshvis = ngpy.def_submodule("meshvis", "pybind meshvis module"); ExportMeshVis(meshvis); py::module csgvis = ngpy.def_submodule("csgvis", "pybind csgvis module"); ExportCSGVis(csgvis); py::module stlvis = ngpy.def_submodule("stlvis", "pybind stlvis module"); ExportSTLVis(stlvis); #endif // OPENGL } // Force linking libnglib to libnetgenpy namespace netgen { void MyBeep (int i); void MyDummyToForceLinkingNGLib() { MyBeep(0); } } netgen-6.2.1905/ng/ng.tcl0000644000175000017500000001553713504650527013530 0ustar kurtkurtcatch {lappend auto_path $env(NETGENDIR) } catch {lappend auto_path $env(NETGENDIR)/../lib } if {[catch {Ng_GetCommandLineParameter batchmode} result ]} { load libgui[info sharedlibextension] gui } set batchmode [Ng_GetCommandLineParameter batchmode] if {$batchmode=="undefined"} { # if {[catch {package require Tix } result ]} { # puts "cannot load package Tix" # puts "error : $result" # } if {[catch {package require tkdnd } result ]} { # puts "cannot load package tkdnd" # puts "error : $result" } } # if {[catch {package require Togl 2.0 } result ]} { # puts "cannot load package Togl 2.0" # puts "error : $result" # } # load [file dirname [info script]]/gears[info sharedlibextension] # puts "load togl lib" # load /Users/joachim/tcl_native3/Togl2.1/libTogl2.1.dylib # puts "have togl lib" # if {[catch {package require Togl 2.0 } result ]} { # puts "cannot load package Togl 2.0" # puts "error : $result" # } # userlevel 1..standard user 2..power-user 3..developer set userlevel 3 if { [Ng_GetCommandLineParameter expert]=="defined" } { set userlevel 3 } set progname "NETGEN" set ngdir "" if { [lsearch [array names env] NETGENDIR] != -1 } { set ngdir $env(NETGENDIR) } if { [string length $ngdir] == 0 } { set ngdir "." } set nguserdir "" if { [lsearch [array names env] NETGEN_USER_DIR] != -1 } { set nguserdir $env(NETGEN_USER_DIR) } if { [string length $nguserdir] == 0 } { set nguserdir "." } set batchmode [Ng_GetCommandLineParameter batchmode] set solvemode 0 if { [Ng_GetCommandLineParameter solve] != "undefined" || \ [Ng_GetCommandLineParameter recent] == "defined" } { set solvemode defined } set shellmode [Ng_GetCommandLineParameter shellmode] if { $shellmode == "defined" } { set batchmode "defined" } if { $batchmode != "defined" } { catch { wm withdraw . wm title . $progname wm geometry . =850x600 wm minsize . 400 300 } } source ${ngdir}/variables.tcl source ${ngdir}/parameters.tcl if { $batchmode != "defined" } { catch { source ${ngdir}/menustat.tcl } } catch { source ${ngdir}/dialog.tcl } catch { source ${ngdir}/drawing.tcl } # if { [catch { load libgeom2dvis[info sharedlibextension] Ng_Geom2d } result ] } { # puts "cannot load 2d meshing module" # puts "error: $result" # } catch { source ${ngdir}/csgeom.tcl } catch { source ${ngdir}/stlgeom.tcl } set hasocc no catch { source ${ngdir}/occgeom.tcl } source ${ngdir}/acisgeom.tcl catch { source ${ngdir}/nghelp.tcl } catch { source ${ngdir}/ngvisual.tcl } catch { source ${ngdir}/sockets.tcl } catch { source ${ngdir}/acis.tcl } set zugstange 0 catch { source ${ngdir}/trafo/menu.tcl } setgranularity ${meshoptions.fineness} Ng_SetMeshingParameters Ng_SetVisParameters Ng_SetDebugParameters Ng_STLDoctor Ng_GeometryOptions set if { $hasocc == "yes" } { Ng_SetOCCVisParameters } if { $batchmode != "defined" } { catch { wm protocol . WM_DELETE_WINDOW { .ngmenu.file invoke "Quit" } wm deiconify . } } set trafoapp 0 catch { source ${ngdir}/trafoapp/trafoapp.tcl } set geofilename [Ng_GetCommandLineParameter geofile] if { $geofilename != "undefined" && [info exists trafo] == 0 && $zugstange == 0} { if { [ catch { Ng_LoadGeometry $geofilename } errstring] == 0 } { if { $batchmode != "defined" } { AddRecentFile $geofilename } Ng_ParseGeometry if { $batchmode != "defined" } { set selectvisual geometry Ng_SetVisParameters redraw wm title . [concat "$progname - " $geofilename] } set dirname [file dirname $geofilename] set basefilename [file tail [file rootname $geofilename]] } { puts "Problem with input file:" puts "$errstring" } } set cnt 0 foreach { gran } { verycoarse coarse moderate fine veryfine } { set cnt [expr $cnt + 1] if { [Ng_GetCommandLineParameter $gran] == "defined" } { set meshoptions.fineness $cnt setgranularity ${meshoptions.fineness} } } set meshfilename [Ng_GetCommandLineParameter meshfile] if { $meshfilename == "undefined" } { set meshfilename out.mesh } set meshfiletype [Ng_GetCommandLineParameter meshfiletype] if { $meshfiletype == "undefined" } { set meshfiletype netgen } set inputmeshfilename [Ng_GetCommandLineParameter inputmeshfile] set mergemeshfilename [Ng_GetCommandLineParameter mergefile] set meshsizefilename [Ng_GetCommandLineParameter meshsizefile] if { $meshsizefilename != "undefined" } { set options.meshsizefilename $meshsizefilename } set refinementfilename [Ng_GetCommandLineParameter refinementfile] if { $batchmode == "defined" && $solvemode != "defined"} { set options.parthread 0 if { $shellmode == "undefined" } { # old batchmode: only processes commandline arguments set selectvisual mesh Ng_SetVisParameters set meshsize [Ng_GetCommandLineParameter meshsize] if {$meshsize != "undefined"} { set options.meshsize $meshsize } if { $inputmeshfilename == "undefined" } { Ng_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep} } else { Ng_LoadMesh $inputmeshfilename if { $mergemeshfilename != "undefined" } { Ng_MergeMesh $mergemeshfilename } } if { $refinementfilename != "undefined" } { Ng_Bisect $refinementfilename } if { $meshfiletype == "netgen" } { Ng_SaveMesh $meshfilename } else { if { [catch { Ng_ExportMesh $meshfilename $meshfiletype } ] == 1 } { puts "Unknown file format $meshfiletype" } } Ng_Exit; exit } else { set code [catch { source ${ngdir}/ngshell.tcl } errcode] if {$code} { puts "error: $errcode" } set code [ catch {Ng_RunShell} errcode] if {$code} { puts "error: $errcode" } Ng_Exit; exit } } set stereo [Ng_GetCommandLineParameter stereo] if { $stereo == "defined" } { set viewoptions.stereo 1 puts "use stereo mode" Ng_SetVisParameters; redraw } set ngsolve_loaded 0 catch { source ${ngdir}/ngsolve.tcl; set ngsolve_loaded 1 } # try to find ngsolve.tcl in PATH set pathlist [split $::env(PATH) \ [expr {$::tcl_platform(platform) == "windows" ? ";" : ":"}]] foreach dir $pathlist { if { $ngsolve_loaded != 1 } { catch { source ${dir}/ngsolve.tcl set ngsolve_loaded 1 } } } set scriptfilename [Ng_GetCommandLineParameter script] if { $scriptfilename != "undefined" } { if { [catch { source $scriptfilename } errstring] == 1 } { puts "Error in input: $errstring" } } if { [Ng_GetCommandLineParameter help]=="defined" } { if { $zugstange == 1 } { print_zug_commandline_help exit; } { if { $trafoapp == 1 } { print_trafo_commandline_help; } { print_commandline_help; Ng_Exit; exit } } } if { [file exists startup.tcl] } { source startup.tcl } catch { source ${ngdir}/demoapp.tcl } catch { source ${ngdir}/dropsexp.tcl } netgen-6.2.1905/ng/ngvisual.tcl0000644000175000017500000017514313504650527014754 0ustar kurtkurtNg_Vis_Set parameters set viscnt 0 proc snapshottimer { } { after 2000 { snapshottimer } global viscnt set viscnt [expr $viscnt+1] set s1 0000$viscnt # puts $s1 set cnt [string range $s1 [expr [string length $s1]-4] end] set filename "p$cnt.jpg" # puts "cnt = $cnt" # puts "filename = $filename" # .ndraw Ng_SnapShot pictures/$filename } snapshottimer proc redrawtimer { } { global visoptions.autoredraw global visoptions.autoredrawtime set delay [expr int(${visoptions.autoredrawtime}*1000)] if { ${visoptions.autoredraw} == 1 } { redraw; } after $delay { redrawtimer } } redrawtimer set perstarttime [clock clicks -millisecond] proc redrawperiodic { } { global visoptions.redrawperiodic global perstarttime set curtime [clock clicks -millisecond] # puts "redraw periodic, time = $curtime" Ng_Vis_Set time [expr ($curtime - $perstarttime) / 5] redraw if { ${visoptions.redrawperiodic} == 1 } { after 30 { redrawperiodic } }; } proc addplotline { identifier datax datay plotinfo {color black}} { set c $identifier.c set xstart [lindex $plotinfo 0] set ystart [lindex $plotinfo 1] set xmin [lindex $plotinfo 2] set ymin [lindex $plotinfo 3] set unitx [lindex $plotinfo 4] set unity [lindex $plotinfo 5] set latestx [expr ([lindex $datax 0]-$xmin)*$unitx + $xstart] set latesty [expr ([lindex $datay 0]-$ymin)*$unity + $ystart] for {set i 1} {$i < [llength $datax]} {incr i} { set xpos [expr ([lindex $datax $i]-$xmin)*$unitx + $xstart] set ypos [expr ([lindex $datay $i]-$ymin)*$unity + $ystart] $c create line $latestx $latesty $xpos $ypos -width 1 -fill $color set latestx $xpos set latesty $ypos } } proc createlineplot { width height identifier title xmin xmax ymin ymax plotinfo} { set thiswidth $width set thisheight $height if { $thiswidth < 275 } { set thiswidth 275 } if { $thisheight < 225 } { seth thisheight 225 } set w $identifier if {[winfo exists $w] == 1} { wm withdraw $w wm deiconify $w focus $w } { toplevel $w set c $w.c canvas $c -relief raised -width $thiswidth -height $thisheight pack $w.c -side top -fill x set titleFont {Helvetica 18} set smallFont {Helvetica 12} set xstart 100 set xend [expr $thiswidth-75] set ystart [expr $thisheight-75] set yend 75 $c create line $xstart $ystart $xstart $yend -width 2 $c create line $xstart $ystart $xend $ystart -width 2 set unitx [expr double($xend-$xstart)/($xmax-$xmin)] set unity [expr double($yend-$ystart)/($ymax-$ymin)] for {set i 0} {$i <= 1} {set i [expr $i+0.2]} { $c create line [expr $xstart+$i*($xend-$xstart)] [expr $ystart] [expr $xstart+$i*($xend-$xstart)] [expr $ystart+5] -width 2 $c create text [expr $xstart+$i*($xend-$xstart)] [expr $ystart+7] -anchor n -font $smallFont \ -text [format "%.3g" [expr $xmin+$i*($xmax-$xmin)]] $c create line [expr $xstart] [expr $ystart+$i*($yend-$ystart)] [expr $xstart-7] [expr $ystart+$i*($yend-$ystart)] -width 2 $c create text [expr $xstart-9] [expr $ystart+$i*($yend-$ystart)] -anchor e -font $smallFont \ -text [format "%.3g" [expr $ymin+$i*($ymax-$ymin)]] } upvar $plotinfo ploti set ploti "$xstart $ystart $xmin $ymin $unitx $unity" button $w.close -text "Close" -command "destroy $w" pack $w.close wm withdraw $w wm geom $w +100+100 wm deiconify $w wm title $w $title focus $w } } proc getlineplotdata { datax datay xmini xmaxi ymini ymaxi} { upvar $datax datx upvar $datay daty upvar $xmini xmin upvar $xmaxi xmax upvar $ymini ymin upvar $ymaxi ymax global visoptions.lineplotusingx global visoptions.lineplotusingy global visoptions.lineplotsource global visoptions.lineplotfile set datx "" set daty "" set xmin 1e20 set xmax -1e20 set ymin 1e20 set ymax -1e20 if {${visoptions.lineplotsource} == "file"} { set fileId [open ${visoptions.lineplotfile} r] set line "" while {[gets $fileId line] >= 0} { if { [string index [lindex $line 0] 0] != "\#" } { if { ${visoptions.lineplotusingx} < [llength $line] } { lappend datx [lindex $line ${visoptions.lineplotusingx}] if { [lindex $datx end] < $xmin } {set xmin [lindex $datx end]} if { [lindex $datx end] > $xmax } {set xmax [lindex $datx end]} } { lappend datx 0 } if { ${visoptions.lineplotusingy} < [llength $line] } { lappend daty [lindex $line ${visoptions.lineplotusingy}] if { [lindex $daty end] < $ymin } {set ymin [lindex $daty end]} if { [lindex $daty end] > $ymax } {set ymax [lindex $daty end]} } { lappend daty 0 } } } close $fileId } } proc lineplotdialog { } { set w .lineplot_dlg if {[winfo exists .lineplot_dlg] == 1} { wm withdraw $w wm deiconify $w focus $w } { toplevel $w ttk::frame $w.filesettings -relief groove -borderwidth 3 ttk::frame $w.filesettings.title ttk::radiobutton $w.filesettings.title.choose -variable visoptions.lineplotsource \ -value file -text "Data from File" pack $w.filesettings.title.choose -side left pack $w.filesettings.title global visoptions.lineplotselectedeval global visoptions.lineplotfile global visoptions.evaluatefilenames global visoptions.evaluatefiledescriptions set evdata [NGS_GetData evaluatefiles] set visoptions.evaluatefilenames none set visoptions.evaluatefiledescriptions none for {set i 0} {[expr $i+1] < [llength $evdata]} {incr i 2} { lappend visoptions.evaluatefilenames [lindex $evdata $i] lappend visoptions.evaluatefiledescriptions [lindex $evdata [expr $i+1]] } # tixOptionMenu $w.filesettings.latestevals -label "Use Evaluate Results: " \ # -options { # label.width 25 # label.anchor e # menubutton.width 40 # } # for {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} { # $w.filesettings.latestevals add command $i \ # -label "[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])" # } # $w.filesettings.latestevals config -variable visoptions.lineplotselectedeval # pack $w.filesettings.latestevals ttk::frame $w.filesettings.latestevals ttk::label $w.filesettings.latestevals.lab -text "Use Evaluate Results: " ttk::menubutton $w.filesettings.latestevals.but -menu $w.filesettings.latestevals.menu -text "coarse" -width 40 menu $w.filesettings.latestevals.menu -tearoff 0 for {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} { $w.filesettings.latestevals.menu add command -label $i\ -command "set visoptions.lineplotselectedeval $i ; $w.filesettings.latestevals.but configure -text \"[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])\"" } $w.filesettings.latestevals.menu invoke ${visoptions.lineplotselectedeval} grid $w.filesettings.latestevals.lab $w.filesettings.latestevals.but -sticky nw pack $w.filesettings.latestevals ttk::frame $w.filesettings.sfn ttk::button $w.filesettings.sfn.bb -text "Browse" \ -command { set visoptions.lineplotfile [tk_getOpenFile] } ttk::entry $w.filesettings.sfn.fn -width 50 \ -textvariable visoptions.lineplotfile pack $w.filesettings.sfn.bb $w.filesettings.sfn.fn -side left pack $w.filesettings.sfn ttk::button $w.filesettings.refresh -text "Refresh" -command { if { ${visoptions.lineplotselectedeval} != 0} { set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}] } set saveusingx ${visoptions.lineplotusingx} set saveusingy ${visoptions.lineplotusingy} for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } { ${visoptions.lineplotxcoordselector} delete $i } for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } { ${visoptions.lineplotycoordselector} delete $i } set fileId [open ${visoptions.lineplotfile} r] set line "" gets $fileId line close $fileId if { [lindex $line 0] == "\#nglineplotinfo" } { set visoptions.lineplotdatadescr [lrange $line 1 end] } { set visoptions.lineplotdatadescr "" for { set i 0 } { $i < [llength $line] } { incr i } { lappend visoptions.lineplotdatadescr "data[expr $i+1]" } } for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } { ${visoptions.lineplotxcoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i] } for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } { ${visoptions.lineplotycoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i] } if { $saveusingx < [llength ${visoptions.lineplotdatadescr}] } { set visoptions.lineplotusingx $saveusingx } { set visoptions.lineplotusingx 0 } if { $saveusingy < [llength ${visoptions.lineplotdatadescr}] } { set visoptions.lineplotusingy $saveusingy } { set visoptions.lineplotusingy 1 } } pack $w.filesettings.refresh ttk::frame $w.filesettings.using global visoptions.lineplotdatadescr # tixOptionMenu $w.filesettings.using.xco -label "X-Coord:"\ # -options { # label.width 8 # label.anchor e # menubutton.width 15 # } # for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } { # $w.filesettings.using.xco add command $i -label [lindex ${visoptions.lineplotdatadescr} $i] # } ttk::frame $w.filesettings.using.xco ttk::label $w.filesettings.using.xco.lab -text "X-Coord:" ttk::menubutton $w.filesettings.using.xco.but -menu $w.filesettings.using.xco.menu -text "" -width 15 menu $w.filesettings.using.xco.menu -tearoff 0 for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} { $w.filesettings.using.xco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\ -command "set visoptions.lineplotusingx $i ; $w.filesettings.using.xco.but configure -text \"[lindex ${visoptions.lineplotdatadescr} $i]\"" } $w.filesettings.using.xco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0] grid $w.filesettings.using.xco.lab $w.filesettings.using.xco.but -sticky nw #pack $w.filesettings.using.xco # $w.filesettings.using.xco config -variable visoptions.lineplotusingx # tixOptionMenu $w.filesettings.using.yco -label "Y-Coord:"\ # -options { # label.width 8 # label.anchor e # menubutton.width 15 # } # for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } { # $w.filesettings.using.yco add command $i -label [lindex ${visoptions.lineplotdatadescr} $i] # } # $w.filesettings.using.yco config -variable visoptions.lineplotusingy ttk::frame $w.filesettings.using.yco ttk::label $w.filesettings.using.yco.lab -text "Y-Coord:" ttk::menubutton $w.filesettings.using.yco.but -menu $w.filesettings.using.yco.menu -text "" -width 15 menu $w.filesettings.using.yco.menu -tearoff 0 for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} { $w.filesettings.using.yco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\ -command "set visoptions.lineplotusingy $i ; $w.filesettings.using.yco.but configure -text \"[lindex ${visoptions.lineplotdatadescr} $i]\"" } $w.filesettings.using.yco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0] grid $w.filesettings.using.yco.lab $w.filesettings.using.yco.but -sticky nw global visoptions.lineplotxcoordselector global visoptions.lineplotycoordselector set visoptions.lineplotxcoordselector $w.filesettings.using.xco set visoptions.lineplotycoordselector $w.filesettings.using.yco pack $w.filesettings.using.xco $w.filesettings.using.yco -side left pack $w.filesettings.using pack $w.filesettings -fill x -ipady 3 ttk::frame $w.settings -relief groove -borderwidth 3 ttk::label $w.settings.title -text "\nSettings\n" pack $w.settings.title ttk::frame $w.settings.minmax ttk::checkbutton $w.settings.minmax.autoscale -text "Autoscale" -variable visoptions.lineplotautoscale # tixControl $w.settings.minmax.xmin -label "Min. x: " \ # -integer false -variable visoptions.lineplotxmin \ # -options { # entry.width 6 # label.width 8 # label.anchor e # } ttk::frame $w.settings.minmax.xmin ttk::label $w.settings.minmax.xmin.label -text "Min. x: " ttk::spinbox $w.settings.minmax.xmin.sp -textvariable visoptions.lineplotxmin -width 6 -increment 0.1 -validate focus -validatecommand "my_validatespinbox %W %P 3" \ -invalidcommand "my_invalidspinbox %W" -from -1e9 -to 1e9 # tixControl $w.settings.minmax.xmax -label "Max. x: " \ # -integer false -variable visoptions.lineplotxmax \ # -options { # entry.width 6 # label.width 8 # label.anchor e # } ttk::frame $w.settings.minmax.xmax ttk::label $w.settings.minmax.xmax.label -text "Max. x: " ttk::spinbox $w.settings.minmax.xmax.sp -textvariable visoptions.lineplotxmax -width 6 -increment 0.1 -validate focus -validatecommand "my_validatespinbox %W %P 3" \ -invalidcommand "my_invalidspinbox %W" -from -1e9 -to 1e9 # tixControl $w.settings.minmax.ymin -label "Min. y: " \ # -integer false -variable visoptions.lineplotymin \ # -options { # entry.width 6 # label.width 8 # label.anchor e # } ttk::frame $w.settings.minmax.ymin ttk::label $w.settings.minmax.ymin.label -text "Min. y: " ttk::spinbox $w.settings.minmax.ymin.sp -textvariable visoptions.lineplotymin -width 6 -increment 0.1 -validate focus -validatecommand "my_validatespinbox %W %P 3" \ -invalidcommand "my_invalidspinbox %W" -from -1e9 -to 1e9 # tixControl $w.settings.minmax.ymax -label "Max. y: " \ # -integer false -variable visoptions.lineplotymax \ # -options { # entry.width 6 # label.width 8 # label.anchor e # } ttk::frame $w.settings.minmax.ymax ttk::label $w.settings.minmax.ymax.label -text "Max. y: " ttk::spinbox $w.settings.minmax.ymax.sp -textvariable visoptions.lineplotymax -width 6 -increment 0.1 -validate focus -validatecommand "my_validatespinbox %W %P 3" \ -invalidcommand "my_invalidspinbox %W" -from -1e9 -to 1e9 pack $w.settings.minmax.xmin.label $w.settings.minmax.xmin.sp pack $w.settings.minmax.xmax.label $w.settings.minmax.xmax.sp pack $w.settings.minmax.ymin.label $w.settings.minmax.ymin.sp pack $w.settings.minmax.ymax.label $w.settings.minmax.ymax.sp pack $w.settings.minmax.autoscale $w.settings.minmax.xmin $w.settings.minmax.xmax \ $w.settings.minmax.ymin $w.settings.minmax.ymax -side left pack $w.settings.minmax ttk::label $w.settings.empty1 -text "" pack $w.settings.empty1 ttk::frame $w.settings.plotsize # tixControl $w.settings.plotsize.xsize -label "Plotsize x: "\ # -integer true -variable visoptions.lineplotsizex \ # -options { # entry.width 6 # label.width 13 # label.anchor e # } ttk::frame $w.settings.plotsize.xsize ttk::label $w.settings.plotsize.xsize.label -text "Plotsize x: " ttk::spinbox $w.settings.plotsize.xsize.sp -textvariable visoptions.lineplotsizex -width 6 -increment 1 -validate focus -validatecommand "my_validatespinbox %W %P 0" \ -invalidcommand "my_invalidspinbox %W" -from -1e9 -to 1e9 pack $w.settings.plotsize.xsize.label $w.settings.plotsize.xsize.sp # tixControl $w.settings.plotsize.ysize -label "y: "\ # -integer true -variable visoptions.lineplotsizey \ # -options { # entry.width 6 # label.width 3 # label.anchor e # } ttk::frame $w.settings.plotsize.ysize ttk::label $w.settings.plotsize.ysize.label -text "Plotsize y: " ttk::spinbox $w.settings.plotsize.ysize.sp -textvariable visoptions.lineplotsizey -width 6 -increment 1 -validate focus -validatecommand "my_validatespinbox %W %P 0" \ -invalidcommand "my_invalidspinbox %W" -from -1e9 -to 1e9 pack $w.settings.plotsize.ysize.label $w.settings.plotsize.ysize.sp pack $w.settings.plotsize.xsize $w.settings.plotsize.ysize -side left pack $w.settings.plotsize ttk::label $w.settings.empty2 -text "" pack $w.settings.empty2 # tixOptionMenu $w.settings.color -label "Linecolor: " \ # -options { # label.width 19 # label.anchor e # menubutton.width 15 # } # foreach step { red black blue green yellow } { # $w.settings.color add command $step -label $step # } # $w.settings.color config -variable visoptions.lineplotcolor ttk::frame $w.settings.color ttk::label $w.settings.color.lab -text "Linecolor: " ttk::menubutton $w.settings.color.but -menu $w.settings.color.menu -text "" -width 15 menu $w.settings.color.menu -tearoff 0 foreach step { red black blue green yellow } { $w.settings.color.menu add command -label $step -command "set visoptions.lineplotcolor $step; $w.settings.color.but configure -text \"$step\"" } # for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} { # $w.filesettings.using.yco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\ # -command "set visoptions.lineplotusingy $i ; $w.filesettings.using.yco.but configure -text \"[lindex ${visoptions.lineplotdatadescr} $i]\"" # } $w.settings.color.menu invoke "red" grid $w.settings.color.lab $w.settings.color.but -sticky nw pack $w.settings.color pack $w.settings -fill x set datax "" set datay "" set xmin 0 set xmax 0 set ymin 0 set ymax 0 ttk::frame $w.plots -relief groove -borderwidth 3 # tixOptionMenu $w.plots.selplot -label "Selected Plot: " \ # -options { # label.width 19 # label.anchor e # menubutton.width 15 # } # $w.plots.selplot add command none -label "None" # $w.plots.selplot config -variable visoptions.lineplotselected ttk::frame $w.plots.selplot ttk::label $w.plots.selplot.lab -text "Linecolor: " ttk::menubutton $w.plots.selplot.but -menu $w.plots.selplot.menu -text "" -width 15 menu $w.plots.selplot.menu -tearoff 0 $w.plots.selplot.menu add command -label "None" -command "set visoptions.lineplotselected \"None\"; $w.plots.selplot.but configure -text \"None\"" grid $w.plots.selplot.lab $w.plots.selplot.but -sticky nw $w.plots.selplot.menu invoke "None" global visoptions.lineplotselector set visoptions.lineplotselector $w.plots.selplot.menu ttk::button $w.plots.new -text "Generate New Plot" -command { if { ${visoptions.lineplotselectedeval} != 0} { set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}] } getlineplotdata datax datay xmin xmax ymin ymax puts stdout "xmin $xmin xmax $xmax ymin $ymin ymax $ymax" global visoptions.lineplotautoscale if {! ${visoptions.lineplotautoscale}} { puts "using set min/max values" set xmin ${visoptions.lineplotxmin} set xmax ${visoptions.lineplotxmax} set ymin ${visoptions.lineplotymin} set ymax ${visoptions.lineplotymax} } incr visoptions.lineplotcurrentnum set ident .newplot${visoptions.lineplotcurrentnum} set plotinfo "" createlineplot ${visoptions.lineplotsizex} ${visoptions.lineplotsizey} \ $ident "Lineplot ${visoptions.lineplotcurrentnum}" \ $xmin $xmax $ymin $ymax plotinfo lappend visoptions.lineplotinfos $plotinfo ${visoptions.lineplotselector} add command ${visoptions.lineplotcurrentnum} -label "Lineplot ${visoptions.lineplotcurrentnum}" addplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor} } ttk::button $w.plots.addto -text "Add to Selected Plot" -command { if { ${visoptions.lineplotselectedeval} != 0} { set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}] } if { ${visoptions.lineplotselected} != "none" } { getlineplotdata datax datay xmin xmax ymin ymax set ident .newplot${visoptions.lineplotselected} set plotinfo [lindex ${visoptions.lineplotinfos} ${visoptions.lineplotselected}] addplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor} } } pack $w.plots.new $w.plots.addto $w.plots.selplot pack $w.plots -fill x -ipady 3 ttk::button $w.close -text "Close" -command "destroy $w" pack $w.close wm withdraw $w wm geom $w +200+100 wm deiconify $w wm title $w "2D Lineplots" focus $w } } set fieldlinesdialog_pop1 0 proc fieldlinesdialog { } { set w .fieldlines_dlg global fieldlinesdialog_pop1 set fieldlinesdialog_pop1 1 if {[winfo exists .fieldlines_dlg] == 1} { wm withdraw $w wm deiconify $w focus $w } { toplevel $w #tixNoteBook $w.nb -ipadx 6 -ipady 6 pack [ttk::notebook $w.nb] -fill both -side top -ipadx 6 -ipady 6 $w.nb add [ttk::frame $w.nb.draw] -text "Draw" -underline 0 $w.nb add [ttk::frame $w.nb.settings] -text "Settings" -underline 0 #$w.nb add draw -label "Draw" #$w.nb add settings -label "Settings" #pack $w.nb -expand yes -fill both -padx 5 -pady 5 -side top # Main Window set f $w.nb.draw ttk::labelframe $f.general -text "General settings" -relief groove -borderwidth 3 ttk::checkbutton $f.general.enable -text "Enable Fieldlines" \ -variable visoptions.drawfieldlines \ -command { # set visoptions.redrawperiodic ${visoptions.drawfieldlines} # redrawperiodic # redrawperiodic # sonst Ng_Vis_Set parameters; redraw } ttk::label $f.general.numl -text "num:" ttk::spinbox $f.general.num -from 0 -to 100 -increment 1 \ -textvariable visoptions.numfieldlines -width 4 #tixControl $f.general.num -label "Num: " -integer true \ -variable visoptions.numfieldlines \ -command { Ng_Vis_Set parameters; redraw } \ -options { # entry.width 6 # label.width 12 # label.anchor e # } grid $f.general.enable -sticky nw -padx 4 -pady 2 grid x $f.general.numl $f.general.num -rowspan 3 -sticky w -padx 4 -row 0 -pady 2 grid anchor $f.general center pack $f.general -pady 15 -fill x -ipady 3 ttk::label $f.labe0 -text " " pack $f.labe0 #ttk::frame $f.general1 ttk::checkbutton $f.general.randomstart -text "Field dependent density " \ -variable visoptions.fieldlinesrandomstart \ -command { Ng_Vis_Set parameters; redraw} ttk::checkbutton $f.general.redrawperiodic -text "Animate periodic" \ -variable visoptions.redrawperiodic \ -command { redrawperiodic Ng_Vis_Set parameters; redraw } grid $f.general.randomstart -sticky nw -padx 4 -row 1 grid $f.general.redrawperiodic -sticky nw -padx 4 -row 2 #pack $f.general1 ttk::label $f.lab0 -text " " pack $f.lab0 # tixOptionMenu $f.vecfun -label "Vector Function: " \ # -options { # label.width 18 # label.anchor e # menubutton.width 12 # } # $f.vecfun add command none -label None # for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } { # set fname [Ng_Vis_Field getfieldname $i] # set fcomp [Ng_Vis_Field getfieldcomponents $i] # set iscomplex [Ng_Vis_Field iscomplex $i] # set sdim [Ng_Vis_Field getdimension] # if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] } # if { ($fcomp == $sdim) || ($fcomp == 3) } { # $f.vecfun add command $fname -label $fname # } # } # $f.vecfun configure -variable visoptions.fieldlinesvecfunction # $f.vecfun configure -command { Ng_Vis_Set parameters; redraw } ttk::frame $f.vecfun ttk::label $f.vecfun.lab -text "Vector Function: " ttk::menubutton $f.vecfun.but -menu $f.vecfun.menu -text "" -width 12 menu $f.vecfun.menu -tearoff 0 # for {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} { # $w.filesettings.latestevals.menu add command -label $i\ # -command "set visoptions.lineplotselectedeval $i ; $w.filesettings.latestevals.but configure -text \"[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])\"" # } for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } { set fname [Ng_Vis_Field getfieldname $i] set fcomp [Ng_Vis_Field getfieldcomponents $i] set iscomplex [Ng_Vis_Field iscomplex $i] set sdim [Ng_Vis_Field getdimension] if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] } if { ($fcomp == $sdim) || ($fcomp == 3) } { $f.vecfun.menu add command -label $fname -command "set visoptions.fieldlinesvecfunction $fname;Ng_Vis_Set parameters; redraw;$f.vecfun.but configure -text \"$fname\" " } } grid $f.vecfun.lab $f.vecfun.but -sticky nw pack $f.vecfun ttk::label $f.lab00 -text " " pack $f.lab00 ttk::frame $f.phasesettings ttk::checkbutton $f.phasesettings.onephase -text "Fix Phase" -variable visoptions.fieldlinesonlyonephase # scale $f.phasesettings.phase -orient horizontal -length 300 -from 0 -to 360 \ # -label "phi" \ # -resolution 1 \ # -variable visoptions.fieldlinesphase \ # -command { popupcheckredraw3 fieldlinesdialog_pop1 } ttk::frame $f.phasesettings.phase ttk::label $f.phasesettings.phase.lab -text "phi" ttk::scale $f.phasesettings.phase.sc -orient horizontal -length 100 -from 0 -to 360 -variable visoptions.fieldlinesphase \ -command "roundscale $f.phasesettings.phase.sc 0; popupcheckredraw3 fieldlinesdialog_pop1" ttk::entry $f.phasesettings.phase.ent -width 4 -textvariable visoptions.fieldlinesphase -validate focus -takefocus 0 \ -validatecommand "popupcheckredraw3 fieldlinesdialog_pop1;my_validate %W 0 1 %P 0" \ -invalidcommand "my_invalid %W;popupcheckredraw3 fieldlinesdialog_pop1" grid $f.phasesettings.phase.lab $f.phasesettings.phase.sc $f.phasesettings.phase.ent -sticky nw -ipadx 4 pack $f.phasesettings.onephase $f.phasesettings.phase -side left pack $f.phasesettings ttk::label $f.lab1 -text " " pack $f.lab1 ttk::frame $f.boxsettings -relief groove -borderwidth 3 ttk::frame $f.boxsettings.title ttk::radiobutton $f.boxsettings.title.choose -variable visoptions.fieldlinesstartarea \ -value box -text "Startpoints in Box" pack $f.boxsettings.title.choose -side left pack $f.boxsettings.title ttk::frame $f.boxsettings.points ttk::label $f.boxsettings.points.lab2 -text "Pmin"; ttk::entry $f.boxsettings.points.ent1x -width 8 \ -textvariable visoptions.fieldlinesstartareap1x ttk::entry $f.boxsettings.points.ent1y -width 8 \ -textvariable visoptions.fieldlinesstartareap1y ttk::entry $f.boxsettings.points.ent1z -width 8 \ -textvariable visoptions.fieldlinesstartareap1z ttk::label $f.boxsettings.points.lab3 -text " Pmax"; ttk::entry $f.boxsettings.points.ent2x -width 8 \ -textvariable visoptions.fieldlinesstartareap2x ttk::entry $f.boxsettings.points.ent2y -width 8 \ -textvariable visoptions.fieldlinesstartareap2y ttk::entry $f.boxsettings.points.ent2z -width 8 \ -textvariable visoptions.fieldlinesstartareap2z pack $f.boxsettings.points pack $f.boxsettings.points.lab2 $f.boxsettings.points.ent1x $f.boxsettings.points.ent1y $f.boxsettings.points.ent1z -side left pack $f.boxsettings.points.lab3 $f.boxsettings.points.ent2x $f.boxsettings.points.ent2y $f.boxsettings.points.ent2z -side left ttk::button $f.boxsettings.settobb -text "Bounding Box" -command { set bbox [Ng_MeshInfo bbox] set visoptions.fieldlinesstartareap1x [lindex $bbox 0] set visoptions.fieldlinesstartareap2x [lindex $bbox 1] set visoptions.fieldlinesstartareap1y [lindex $bbox 2] set visoptions.fieldlinesstartareap2y [lindex $bbox 3] set visoptions.fieldlinesstartareap1z [lindex $bbox 4] set visoptions.fieldlinesstartareap2z [lindex $bbox 5] } pack $f.boxsettings.settobb pack $f.boxsettings -fill x -ipady 3 ttk::frame $f.facesettings -relief groove -borderwidth 3 ttk::frame $f.facesettings.title ttk::radiobutton $f.facesettings.title.choose -variable visoptions.fieldlinesstartarea \ -value face -text "Startpoints on Face" pack $f.facesettings.title.choose -side left pack $f.facesettings.title ttk::frame $f.facesettings.index ttk::label $f.facesettings.index.lab -text "face index:" ttk::label $f.facesettings.index.ent -text 1;# -padx 4 pack $f.facesettings.index.lab $f.facesettings.index.ent -side left pack $f.facesettings.index pack $f.facesettings -fill x -ipady 3 global visoptions.fieldlinesfilename ttk::frame $f.filesettings -relief groove -borderwidth 3 ttk::frame $f.filesettings.title ttk::radiobutton $f.filesettings.title.choose -variable visoptions.fieldlinesstartarea \ -value file -text "Startpoints from File" pack $f.filesettings.title.choose -side left pack $f.filesettings.title ttk::frame $f.filesettings.sfn ttk::button $f.filesettings.sfn.bb -text "Browse" \ -command { set types { { "Netgen Fieldlines" {.nef} } } set visoptions.fieldlinesfilename [tk_getOpenFile -filetypes $types -defaultextension ".nef"] } ttk::entry $f.filesettings.sfn.fn -width 50 \ -textvariable visoptions.fieldlinesfilename pack $f.filesettings.sfn.bb $f.filesettings.sfn.fn -side left pack $f.filesettings.sfn pack $f.filesettings -fill x -ipady 3 # Settings set g $w.nb.settings ttk::frame $g.linesettings -relief groove -borderwidth 3 ttk::label $g.linesettings.title -text "\nLine Settings\n" # tixControl $g.linesettings.length -label "rel. Length: " -integer false \ # -variable visoptions.fieldlineslength -min 0.00001 -max 10000 -step 0.1 \ # -options { # entry.width 6 # label.width 25 # label.anchor e # } ttk::frame $g.linesettings.length ttk::label $g.linesettings.length.lab -text "rel. Length: " ttk::spinbox $g.linesettings.length.sp -textvariable visoptions.fieldlineslength -width 6 -increment 0.1 -validate focus -validatecommand "my_validatespinbox %W %P 5" \ -invalidcommand "my_invalidspinbox %W" -from 0.00001 -to 10000 grid $g.linesettings.length.lab $g.linesettings.length.sp -sticky nw # tixControl $g.linesettings.maxpoints -label "max. Points: " -integer true \ # -variable visoptions.fieldlinesmaxpoints -min 0 -max 10000 -step 1 \ # -options { # entry.width 6 # label.width 25 # label.anchor e # } ttk::frame $g.linesettings.maxpoints ttk::label $g.linesettings.maxpoints.lab -text "max. Points: " ttk::spinbox $g.linesettings.maxpoints.sp -textvariable visoptions.fieldlinesmaxpoints -width 6 -increment 1 -validate focus -validatecommand "my_validatespinbox %W %P 0" \ -invalidcommand "my_invalidspinbox %W" -from 0 -to 10000 grid $g.linesettings.maxpoints.lab $g.linesettings.maxpoints.sp -sticky nw # tixControl $g.linesettings.thick -label "rel. Thickness: " -integer false \ # -variable visoptions.fieldlinesthickness -min 1e-10 -max 0.5 -step 0.001 \ # -options { # entry.width 6 # label.width 25 # label.anchor e # } ttk::frame $g.linesettings.thick ttk::label $g.linesettings.thick.lab -text "rel. Thickness: " ttk::spinbox $g.linesettings.thick.sp -textvariable visoptions.fieldlinesthickness -width 6 -increment 0.001 -validate focus -validatecommand "my_validatespinbox %W %P 6" \ -invalidcommand "my_invalidspinbox %W" -from 1e-10 -to 0.5 grid $g.linesettings.thick.lab $g.linesettings.thick.sp -stick nw pack $g.linesettings.title $g.linesettings.length $g.linesettings.maxpoints $g.linesettings.thick pack $g.linesettings -fill x -ipady 3 global visoptions.fieldlinestolerance ttk::frame $g.odesettings -relief groove -borderwidth 3 ttk::label $g.odesettings.title -text "\nODE Settings\n" # tixControl $g.odesettings.tol -label "rel. Tolerance: " -integer false \ # -variable visoptions.fieldlinestolerance -min 0.00001 -max 1 -step 0.01 \ # -options { # entry.width 6 # label.width 25 # label.anchor e # } ttk::frame $g.odesettings.tol ttk::label $g.odesettings.tol.lab -text "rel. Thickness: " ttk::spinbox $g.odesettings.tol.sp -textvariable visoptions.fieldlinestolerance -width 6 -increment 0.01 -validate focus -validatecommand "my_validatespinbox %W %P 5" \ -invalidcommand "my_invalidspinbox %W" -from 0.00001 -to 1 grid $g.odesettings.tol.lab $g.odesettings.tol.sp -stick nw # tixOptionMenu $g.odesettings.rktype -label "RK-Type " \ # -options { # label.width 20 # label.anchor e # menubutton.width 25 # } # $g.odesettings.rktype add command euler -label "Euler, order 1" # $g.odesettings.rktype add command eulercauchy -label "Euler-Cauchy, order 2" # $g.odesettings.rktype add command simpson -label "Simpson, order 3" # $g.odesettings.rktype add command crungekutta -label "classical Runge-Kutta, order 4" # $g.odesettings.rktype configure -variable visoptions.fieldlinesrktype # $g.odesettings.rktype configure -command { Ng_Vis_Set parameters; redraw } ttk::frame $g.odesettings.rktype ttk::label $g.odesettings.rktype.lab -text "RK-Type " ttk::menubutton $g.odesettings.rktype.but -menu $g.odesettings.rktype.menu -text "" -width 25 menu $g.odesettings.rktype.menu -tearoff 0 $g.odesettings.rktype.menu add command -label "Euler, order 1" -command "set visoptions.fieldlinesrktype \"euler\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \"Euler,order 1\" " $g.odesettings.rktype.menu add command -label "Euler-Cauchy, order 2" -command "set visoptions.fieldlinesrktype \"eulercauchy\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \"Euler-Cauchy,order 2\" " $g.odesettings.rktype.menu add command -label "Simpson, order 3" -command "set visoptions.fieldlinesrktype \"simpson\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \"Simpson,order 3\"" $g.odesettings.rktype.menu add command -label "classical Runge-Kutta, order 4" -command "set visoptions.fieldlinesrktype \"crungekutta\" ;Ng_Vis_Set parameters; redraw; $g.odesettings.rktype.but configure -text \"classical Runge-Kutta,order 4\"" $g.odesettings.rktype.menu invoke "classical Runge-Kutta, order 4" grid $g.odesettings.rktype.lab $g.odesettings.rktype.but -sticky nw pack $g.odesettings.title $g.odesettings.tol $g.odesettings.rktype pack $g.odesettings -fill x -ipady 3 # buttons ttk::frame $w.bu pack $w.bu -fill x -ipady 3 ttk::button $w.bu.calc -text "Build Fieldlines" -command { if { ${visoptions.fieldlinesvecfunction} == "none" } { bgerror "Please select the vector function first!" } { set visoptions.drawfieldlines 1 Ng_Vis_Set parameters Ng_BuildFieldLines redraw } } ttk::button $w.bu.help -text "Help" -command { if {[winfo exists .fieldlines_help] == 1} { wm withdraw .fieldlines_help wm deiconify .fieldlines_help focus .fieldlines_help } { toplevel .fieldlines_help set f [frame .fieldlines_help.ht] #ttk::scrollbar $f.hsb -orient horizontal -command [list $f.t xview] ttk::scrollbar $f.vsb -orient vertical -command [list $f.t yview] text $f.t -yscrollcommand [list $f.vsb set] grid $f.t -row 0 -column 0 -sticky nsew grid $f.vsb -row 0 -column 1 -sticky nsew grid columnconfigure $f 0 -weight 1 grid rowconfigure $f 0 -weight 1 #tixScrolledText .fieldlines_help.ht -scrollbar y set text $f.t $text configure -setgrid true -wrap word $text tag configure bold -font *-*-bold-*-*-*-* $text insert end \ "Draw menu\n \n" bold $text insert end \ "Enable Fieldlines\n To turn on and off the calculated fieldlines. (Has to be turned on to start the calculation)\n" $text insert end \ "Num\n Number of fieldlines to calculate. (May not be used exactly.)" $text insert end \ "Field dependent density\n There will be more fieldline startpoints where the field is stronger\n\n" $text insert end \ "Animate periodic\n (for quasistationary fields) The fieldlines of the different phase angles are animated.\n ATTENTION: \"Fix Phase\" has to be turned off\n\n" $text insert end \ "Vector Function\n The function fixing the direction of the lines\n\n" $text insert end \ "Fix Phase\n (for quasistationary fields) Only calculate and draw fieldlines for one special phase angle.\n\n" $text insert end \ "Startpoints in Box\n Set the startpoints inside the box \[Pmin1,Pmax1\] x \[Pmin2,Pmax2\] x \[Pmin3,Pmax3\]\n" $text insert end \ " With the button \"Bounding Box\" the whole bounding box of the geometry is selected.\n\n" $text insert end \ "Startpoints on Face\n All startpoints will be set on one face. This face is selected by double-clicking with the mouse.\n\n" $text insert end \ "Startpoints from File\n The startpoint information will be read from the selected file.\n The entries in the file can be as follows:\n" $text insert end \ " point \n set a (potential) startpoint\n" $text insert end \ " line \n set n (potential) startpoints on the line from (x1,y1,z1) to (x2,y2,z2)\n" $text insert end \ " box \n set n (potential) startpoints inside the box \[x1,x2\] x \[y1,y2\] x \[z1,z2\]\n" $text insert end \ " ATTENTION: These are potential startpoints.\n The total number of startpoints will be bounded by the \"Num\"-parameter.\n \n \n \n" $text insert end \ "Settings Menu\n \n" bold $text insert end \ "rel. Length\n The maximal length of a fieldline relative to the diameter of the geometry.\n\n" $text insert end \ "max. Points\n The maximum number of Runge-Kutta steps.\n\n" $text insert end \ "rel. Thickness\n The thickness of the fieldlines relative to the diameter of the geometry.\n\n" $text insert end \ "rel. Tolerance\n The tolerance for the step-length control of the Runge-Kutta method.\n\n" $text insert end \ "RK-Type\n Which Runge-Kutta scheme to use\n \n \n \n" $text insert end \ "Button \"Build Fieldlines\"\n" bold $text insert end \ " Build the fieldlines." $text configure -state disabled pack .fieldlines_help.ht -expand yes -fill both wm withdraw .fieldlines_help wm geom .fieldlines_help +300+200 wm deiconify .fieldlines_help wm title .fieldlines_help "Fieldlines Help" focus .fieldlines_help } } ttk::button $w.bu.cancel -text "Done" -command "destroy $w" grid $w.bu.calc $w.bu.help $w.bu.cancel -sticky nw -padx 4 grid anchor $w.bu center wm withdraw $w wm geom $w +200+100 wm deiconify $w wm title $w "Fieldlines" # grab $w focus $w } global visoptions.fieldlinesstartface set f $w.nb.draw set visoptions.fieldlinesstartface [Ng_BCProp getactive] $f.facesettings.index.ent configure -text ${visoptions.fieldlinesstartface} } #proc popupcheckredraw { vari { x 0 } } { # upvar $vari varname # if { $varname == 1 } { # set varname 0 # } { # Ng_Vis_Set parameters # redraw # } #} set visual_dialog_pop1 0 set visual_dialog_pop2 0 set visual_dialog_pop3 0 set visual_dialog_pop4 0 set visual_dialog_pop5 0 set visual_dialog_pop6 0 set visual_dialog_pop7 0 proc visual_dialog { } { set w .visoptions_dlg global visual_dialog_pop1 global visual_dialog_pop2 global visual_dialog_pop3 global visual_dialog_pop4 global visual_dialog_pop5 global visual_dialog_pop6 global visual_dialog_pop7 set visual_dialog_pop1 1 set visual_dialog_pop2 1 set visual_dialog_pop3 1 set visual_dialog_pop4 1 set visual_dialog_pop5 1 set visual_dialog_pop6 1 set visual_dialog_pop7 1 if {[winfo exists .visoptions_dlg] == 1} { wm withdraw $w wm deiconify $w focus $w } { toplevel $w #ttk::frame $w.grid -relief groove -borderwidth 0 # change to: max gridsize 200 #scale $w.grid.size -orient horizontal -length 100 -from 1 -to 200 \ -label "Grid" \ -resolution 1 \ -variable visoptions.gridsize \ -command { popupcheckredraw visual_dialog_pop2 } # x- and y- offset #scale $w.grid.xoffset -orient horizontal -length 80 -from 0 -to 1 \ -label "x-Offset" \ -resolution 0.05 \ -variable visoptions.xoffset \ -command { popupcheckredraw visual_dialog_pop3 } ttk::frame $w.main pack $w.main -fill x set w $w.main ttk::frame $w.upperfr ;# -relief groove -borderwidth 3 -height 10 pack $w.upperfr -fill x;# -ipady 8 ttk::labelframe $w.upperfr.size -text "Grid" -relief groove -borderwidth 3 ttk::entry $w.upperfr.size.ent -width 3 -textvariable visoptions.gridsize -validate focus -takefocus 0 -validatecommand "popupcheckredraw visual_dialog_pop2;my_validate %W 0 200 %P 0" \ -invalidcommand "my_invalid %W;popupcheckredraw visual_dialog_pop2" ttk::scale $w.upperfr.size.sc -orient horizontal -length 100 -from 1 -to 200 -variable visoptions.gridsize\ -command "roundscale $w.upperfr.size.sc 0;popupcheckredraw visual_dialog_pop2" ttk::labelframe $w.upperfr.offsets -text "x / y offsets" -relief groove -borderwidth 3 ttk::label $w.upperfr.offsets.xlab -text "x" ttk::label $w.upperfr.offsets.ylab -text "y" ttk::scale $w.upperfr.offsets.xoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.xoffset \ -command "roundscale $w.upperfr.offsets.xoffset 2; popupcheckredraw visual_dialog_pop3" ttk::scale $w.upperfr.offsets.yoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.yoffset \ -command "roundscale $w.upperfr.offsets.yoffset 2; popupcheckredraw visual_dialog_pop4" ttk::entry $w.upperfr.offsets.entx -width 4 -textvariable visoptions.xoffset -validate focus -takefocus 0 \ -validatecommand "popupcheckredraw visual_dialog_pop3;my_validate %W 0 1 %P 2" \ -invalidcommand "my_invalid %W;popupcheckredraw visual_dialog_pop3" ttk::entry $w.upperfr.offsets.enty -width 4 -textvariable visoptions.yoffset -validate focus -takefocus 0 \ -validatecommand "popupcheckredraw visual_dialog_pop4;my_validate %W 0 1 %P 2" \ -invalidcommand "my_invalid %W;popupcheckredraw visual_dialog_pop4" # pack $w.showclipsolution pack $w.upperfr.size.sc $w.upperfr.size.ent -padx 4 -pady 12 -side left grid $w.upperfr.offsets.xoffset $w.upperfr.offsets.entx $w.upperfr.offsets.xlab -sticky nw -padx 4 grid $w.upperfr.offsets.yoffset $w.upperfr.offsets.enty $w.upperfr.offsets.ylab -sticky nw -padx 4 grid $w.upperfr.size $w.upperfr.offsets -sticky nw -pady 7 -padx 10 grid anchor $w.upperfr center # pack $w.lineartexture $w.numcols ttk::labelframe $w.deform -relief groove -borderwidth 3 -text "Deformation settings" ttk::checkbutton $w.deform.cb -text "Deformation" \ -variable visoptions.deformation \ -command { Ng_Vis_Set parameters; redraw } ttk::label $w.deform.l -text "Scale: " ttk::spinbox $w.deform.sc1 -from 0 -to 1e99 -textvariable visoptions.scaledeform1 -width 5 \ -command { Ng_Vis_Set parameters; redraw } \ -validate focusout -validatecommand { Ng_Vis_Set parameters; redraw; string is double %P } \ -invalidcommand { puts "invalid value, %P %s"; set visoptions.scaledeform1 1; } # tixControl $w.deform.sc1 -label "Scale: " -integer false \ # -variable visoptions.scaledeform1 \ # -command { Ng_Vis_Set parameters; redraw } \ # -options { # entry.width 6 # label.width 7 # label.anchor e # } ttk::scale $w.deform.sc2 -orient horizontal -length 100 -from 0 -to 1 \ -variable visoptions.scaledeform2 \ -command { popupcheckredraw visual_dialog_pop5 } pack $w.deform -fill x -ipady 2 -pady 4 -ipady 3 grid $w.deform.cb $w.deform.l $w.deform.sc1 $w.deform.sc2 -sticky nw -padx 4;# -side left -expand yes -anchor center -padx 4 grid anchor $w.deform center grid columnconfigure $w.deform 0 -pad 20 grid columnconfigure $w.deform 2 -pad 20 ttk::labelframe $w.as -relief groove -borderwidth 3 -text "Scaling options" ttk::checkbutton $w.as.autoscale -text "Autoscale" \ -variable visoptions.autoscale \ -command { Ng_Vis_Set parameters; redraw } ttk::label $w.as.lmin -text "Min-value" ttk::spinbox $w.as.smin -textvariable visoptions.mminval -width 5 -validate focus \ -validatecommand "my_validatespinbox %W %P 10" \ -command "Ng_Vis_Set parameters; redraw;" \ -invalidcommand "my_invalidspinbox %W" -from -1e10 -to 1e10 -increment 0.001 ttk::label $w.as.lmax -text "Max-value" ttk::spinbox $w.as.smax -textvariable visoptions.mmaxval -width 5 -validate focus \ -validatecommand "Ng_Vis_Set parameters; redraw;my_validatespinbox %W %P 10" \ -command "Ng_Vis_Set parameters; redraw;" \ -invalidcommand "my_invalidspinbox %W;Ng_Vis_Set parameters; redraw" -from -1e10 -to 1e10 -increment 0.001 #tixControl $w.as.minval -label "Min-value: " -integer false \ -variable visoptions.mminval \ -command { Ng_Vis_Set parametersrange; redraw } \ -options { # entry.width 6 # label.width 12 # label.anchor e # } #tixControl $w.as.maxval -label "Max-value: " -integer false \ -variable visoptions.mmaxval \ -command { Ng_Vis_Set parametersrange; redraw } \ -options { # entry.width 6 # label.width 12 # label.anchor e # } pack $w.as -fill x -pady 5 -ipady 3 grid $w.as.autoscale $w.as.lmin $w.as.smin $w.as.lmax $w.as.smax -sticky nw -padx 4 grid columnconfigure $w.as 0 -pad 20 grid columnconfigure $w.as 2 -pad 20 grid anchor $w.as center ttk::frame $w.iso; #-relief groove -borderwidth 0 pack $w.iso -anchor center;# -ipady 3 ttk::labelframe $w.iso.cb -relief groove -borderwidth 3 -text "Iso lines / surfaces" pack $w.iso.cb -side left -pady 7 -fill y ttk::checkbutton $w.iso.cb.isolines -text "Iso-lines" \ -variable visoptions.isolines \ -command { Ng_Vis_Set parameters; redraw } #pack $w.iso.cb.isolines -side top -anchor w ttk::checkbutton $w.iso.cb.isosurf -text "Iso-Surface" \ -variable visoptions.isosurf \ -command { Ng_Vis_Set parameters; redraw } #pack $w.iso.cb.isosurf -side top -anchor w ttk::label $w.iso.cb.numisol -text "amount" ttk::scale $w.iso.cb.numiso -orient horizontal -length 100 -from 2 -to 50 \ -variable visoptions.numiso \ -command "roundscale $w.iso.cb.numiso 0;popupcheckredraw visual_dialog_pop6" ttk::entry $w.iso.cb.entry -textvariable visoptions.numiso -width 3 \ -validate focus -validatecommand "popupcheckredraw visual_dialog_pop6;\ my_validate %W [$w.iso.cb.numiso cget -from] [$w.iso.cb.numiso cget -to] %P 0" \ -invalidcommand "my_invalid %W;popupcheckredraw visual_dialog_pop6" # -resolution 1 \ # -label "" \ grid $w.iso.cb.isolines $w.iso.cb.numisol $w.iso.cb.entry -sticky nw -padx 4 grid $w.iso.cb.isosurf -sticky nw -padx 4 grid $w.iso.cb.numiso -sticky nw -padx 4 -columnspan 2 -column 1 -row 1 #pack $w.iso.cb.numisol $w.iso.cb.numiso -anchor n # scale $w.iso.subdiv -orient horizontal -length 100 -from 0 -to 5 \ # -label "subdivision" \ # -resolution 1 \ # -variable visoptions.subdivisions \ # -command { popupcheckredraw visual_dialog_pop7 } # # -command { puts "subdiv-vis"; Ng_Vis_Set parameters; puts "cal redraw"; redraw } ttk::labelframe $w.iso.subdiv -text "Subdivision" -relief groove -borderwidth 3 ttk::radiobutton $w.iso.subdiv.zero -text "0" -variable visoptions.subdivisions -value 0 \ -command { #set visoptions.subdivisions 1; Ng_Vis_Set parameters; redraw; } ttk::radiobutton $w.iso.subdiv.one -text "1" -variable visoptions.subdivisions -value 1 \ -command { #set visoptions.subdivisions 1; Ng_Vis_Set parameters; redraw; } ttk::radiobutton $w.iso.subdiv.two -text "2" -variable visoptions.subdivisions -value 2 \ -command { #set visoptions.subdivisions 2; Ng_Vis_Set parameters; redraw; } ttk::radiobutton $w.iso.subdiv.three -text "3" -variable visoptions.subdivisions -value 3 \ -command { #set visoptions.subdivisions 3; Ng_Vis_Set parameters; redraw; } ttk::radiobutton $w.iso.subdiv.four -text "4" -variable visoptions.subdivisions -value 4 \ -command { #set visoptions.subdivisions 4; Ng_Vis_Set parameters; redraw; } ttk::radiobutton $w.iso.subdiv.five -text "5" -variable visoptions.subdivisions -value 5 \ -command { #set visoptions.subdivisions 5; Ng_Vis_Set parameters; redraw; } ttk::label $w.iso.subdiv.text -text "subdivision" pack $w.iso.subdiv -side right -fill y -padx 4 -pady 7 # ; Ng_SetNextTimeStamp #pack $w.iso.subdiv.text -side top #pack $w.iso.subdiv.zero -side left #pack $w.iso.subdiv.one -side left #pack $w.iso.subdiv.two -side left #pack $w.iso.subdiv.three -side left #pack $w.iso.subdiv.four -side left #pack $w.iso.subdiv.five -side left grid $w.iso.subdiv.zero $w.iso.subdiv.one $w.iso.subdiv.two $w.iso.subdiv.three $w.iso.subdiv.four $w.iso.subdiv.five grid anchor $w.iso.subdiv center # scale $w.iso.zpos -orient horizontal -length 100 -from 0 -to 1 \ # -label "z-position" \ # -resolution 0.01 \ # -variable visoptions.zposition \ # -command { # catch {NGS_Set zpos ${visoptions.zposition};} # redraw } # pack $w.iso.zpos -side right ttk::labelframe $w.redraw -relief groove -borderwidth 3 -text "Auto-redraw" ttk::checkbutton $w.redraw.auto -text "Auto-redraw after (sec)" \ -variable visoptions.autoredraw # tixControl $w.redraw.val -integer false \ # -variable visoptions.autoredrawtime \ # -options { # entry.width 6 # label.width 0 # label.anchor w # } ttk::spinbox $w.redraw.val -textvariable visoptions.autoredrawtime -from 0 -to 100 -width 3 pack $w.redraw -fill x -ipady 3 -pady 7 grid $w.redraw.auto $w.redraw.val -sticky nw grid anchor $w.redraw center ttk::labelframe $w.lowerframe -text "Additional viewing options" -relief groove -borderwidth 3 pack $w.lowerframe -fill x set w $w.lowerframe #pack [frame $w.f] -fill x #pack [ttk::frame $w.f1] -expand yes ttk::frame $w.f1 set f [ttk::frame $w.f1.clipsol] pack $f -anchor e menu $f.m ttk::menubutton $f.b -menu $f.m -width 12 ttk::label $f.l -text "Clipping Plane Sol: " global visoptions.clipsolution set clipsollabs(none) "None" set clipsollabs(scal) "Scalar Function" set clipsollabs(vec) "Vector Function" foreach i { none scal vec } { set textval $clipsollabs($i) $f.m add command -label "$textval" -command \ "$f.b configure -text \"$textval\" ; set visoptions.clipsolution $i ; Ng_Vis_Set parameters ; redraw " } pack $f.b $f.l -side right $f.m invoke $clipsollabs(${visoptions.clipsolution}) # pack [ttk::frame $w.f1.scalfun] -anchor e set f [ttk::frame $w.f1.scalfun] pack $f -anchor e menu $f.m ttk::menubutton $f.b -menu $f.m -width 12 ttk::label $f.l -text "Scalar Function: " set scalentries [list none None] for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } { set fname [Ng_Vis_Field getfieldname $i] set fcomp [Ng_Vis_Field getfieldcomponents $i] if { $fcomp == 1 } { lappend scalentries $fname:1 $fname } { for { set j 1 } { $j <= $fcomp } { incr j } { lappend scalentries $fname:$j "$fname ($j)" } lappend scalentries $fname:0 "func ($fname)" } } global visoptions.scalfunction foreach { name textval } $scalentries { $f.m add command -label "$textval" -command \ "$f.b configure -text \"$textval\" ; set visoptions.scalfunction $name ; Ng_Vis_Set parameters ; redraw ; " } pack $f.b $f.l -side right foreach { name textval } $scalentries { if { ${visoptions.scalfunction} == $name } { $f.m invoke $textval } } set f [ttk::frame $w.f1.vecfun] pack $f -anchor e menu $f.m ttk::menubutton $f.b -menu $f.m -width 12 ttk::label $f.l -text "Vector Function: " set vecentries [list none None] for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } { set fname [Ng_Vis_Field getfieldname $i] set fcomp [Ng_Vis_Field getfieldcomponents $i] set iscomplex [Ng_Vis_Field iscomplex $i] set sdim [Ng_Vis_Field getdimension] if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] } if { ($fcomp == $sdim) || ($fcomp == 3) } { lappend vecentries $fname $fname } } global visoptions.vecfunction foreach { name textval } $vecentries { $f.m add command -label "$textval" -command \ "$f.b configure -text \"$textval\" ; set visoptions.vecfunction $name ; Ng_Vis_Set parameters ; redraw ; " } pack $f.b $f.l -side right foreach { name textval } $vecentries { if { ${visoptions.vecfunction} == $name } { $f.m invoke $textval } } set f [ttk::frame $w.f1.evaluate] pack $f -anchor e menu $f.m ttk::menubutton $f.b -menu $f.m -width 12 ttk::label $f.l -text "Evaluate: " global visoptions.evaluate set evallabs(abs) "| |" set evallabs(abstens) "|tensor|" set evallabs(mises) "Mises" set evallabs(main) "Main" foreach i { abs abstens mises main } { set textval $evallabs($i) $f.m add command -label "$textval" -command \ "$f.b configure -text \"$textval\" ; set visoptions.evaluate $i ; " } pack $f.b $f.l -side right $f.m invoke $evallabs(${visoptions.evaluate}) pack [ttk::frame $w.f1.multidim] -fill x set f [ttk::frame $w.f1.multidim.f] pack $f -anchor e ttk::label $f.l1 -text "multidim-component: " ttk::spinbox $f.sb1 -from 0 -to 1e99 -textvariable visoptions.multidimcomponent -width 3 \ -command { Ng_Vis_Set parameters; redraw } pack $f.l1 $f.sb1 -side left ttk::frame $w.fcb # the 2 main frames grid $w.f1 $w.fcb -sticky nw -padx 7 -ipady 3 grid anchor $w center #pack $w.fcb ttk::frame $w.fcb.cb pack $w.fcb.cb ttk::checkbutton $w.fcb.cb.showsurfsolution -text "Draw Surface Vectors" \ -variable visoptions.showsurfacesolution \ -command { Ng_Vis_Set parameters; redraw } ttk::checkbutton $w.fcb.cb.showcurves -text "Show Curves" \ -variable visoptions.drawpointcurves \ -command { Ng_Vis_Set parameters; redraw } ttk::checkbutton $w.fcb.cb.imaginary -text "Imaginary Part" \ -variable visoptions.imaginary \ -command { Ng_Vis_Set parameters; redraw } ttk::checkbutton $w.fcb.cb.logscale -text "Log Scale" \ -variable visoptions.logscale \ -command { Ng_Vis_Set parameters; redraw } ttk::checkbutton $w.fcb.cb.invcolor -text "Inverse Color" \ -variable visoptions.invcolor \ -command { Ng_Vis_Set parametersrange; redraw } ttk::frame $w.fcb.cb.texframe ttk::checkbutton $w.fcb.cb.texframe.usetexture -text "Use Textures (" \ -variable visoptions.usetexture \ -command { Ng_Vis_Set parameters; redraw } ttk::checkbutton $w.fcb.cb.texframe.lintexture -text "Linear )" \ -variable visoptions.lineartexture \ -command { Ng_Vis_Set parametersrange; redraw } ttk::checkbutton $w.fcb.cb.lineartexture -text "Use Linear Texture" \ -variable visoptions.lineartexture \ -command { Ng_Vis_Set parameters; redraw } scale $w.numcols -orient horizontal -length 100 -from 0 -to 50 \ -resolution 1 \ -variable visoptions.numtexturecols \ -command { popupcheckredraw visual_dialog_pop1 } ttk::checkbutton $w.fcb.cb.showclipsolution -text "Draw Clipping Plane Solution" \ -variable visoptions.showclipsolution \ -command { Ng_Vis_Set parameters; redraw } ttk::checkbutton $w.fcb.cb.redrawperiodic -text "Animate periodic" \ -variable visoptions.redrawperiodic \ -command { redrawperiodic Ng_Vis_Set parameters; redraw } #pack $w.fcb.cb.showsurfsolution $w.fcb.cb.showcurves -anchor w #pack $w.fcb.cb.imaginary $w.fcb.cb.logscale $w.fcb.cb.texframe $w.fcb.cb.invcolor $w.fcb.cb.redrawperiodic -side top -anchor w #pack $w.fcb.cb.texframe.usetexture $w.fcb.cb.texframe.lintexture -side left -expand yes grid $w.fcb.cb.showsurfsolution -sticky nw grid $w.fcb.cb.showcurves -sticky nw grid $w.fcb.cb.imaginary -sticky nw grid $w.fcb.cb.logscale -sticky nw grid $w.fcb.cb.texframe -sticky nw grid $w.fcb.cb.invcolor -sticky nw grid $w.fcb.cb.redrawperiodic -sticky nw pack $w.fcb.cb.texframe.usetexture $w.fcb.cb.texframe.lintexture -side left -expand yes set w .visoptions_dlg.main ttk::frame $w.bu;# -relief groove -borderwidth 3 pack $w.bu -pady 5 -padx 4 ttk::button $w.bu.showsol -text "Show Solution" -command { set selectvisual solution Ng_SetVisParameters redraw } ttk::button $w.bu.clipping -text "Clipping" -command { clippingdialog; } ttk::button $w.bu.fieldlines -text "Fieldlines" -command { fieldlinesdialog; } ttk::button $w.bu.lineplot -text "2D Lineplot" -command { lineplotdialog; } ttk::button $w.bu.done -text "Close" -command { destroy .visoptions_dlg } pack $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes set w .visoptions_dlg wm withdraw $w wm geom $w +100+100 wm deiconify $w wm title $w "Visualization" } } # proc reset_visual_dialog { } { # set w .visoptions_dlg # if {[winfo exists .visoptions_dlg] == 1} { # destroy $w.scalfun $w.vecfun $w.evaluate $w.multidimcomp # destroy $w.imaginary $w.logscale $w.texframe.usetexture $w.texframe.lintexture # destroy $w.texframe # destroy $w.invcolor $w.redrawperiodic # destroy $w.bu -pady 5 # destroy $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes # checkbutton $w.imaginary -text "Imaginary Part" \ # -variable visoptions.imaginary \ # -command { Ng_Vis_Set parameters; redraw } # frame $w.texframe # checkbutton $w.texframe.usetexture -text "Use Textures (" \ # -variable visoptions.usetexture \ # -command { Ng_Vis_Set parameters; redraw } # checkbutton $w.texframe.lintexture -text "Linear )" \ # -variable visoptions.lineartexture \ # -command { Ng_Vis_Set parameters; redraw } # checkbutton $w.invcolor -text "Inverse Color" \ # -variable visoptions.invcolor \ # -command { Ng_Vis_Set parameters; redraw } # checkbutton $w.logscale -text "Log Scale" \ # -variable visoptions.logscale \ # -command { Ng_Vis_Set parameters; redraw } # checkbutton $w.redrawperiodic -text "Animate periodic" \ # -variable visoptions.redrawperiodic \ # -command { # redrawperiodic # Ng_Vis_Set parameters; # redraw # } # tixOptionMenu $w.scalfun -label "Scalar Function: " \ # -options { # label.width 18 # label.anchor e # menubutton.width 12 # } # tixOptionMenu $w.vecfun -label "Vector Function: " \ # -options { # label.width 18 # label.anchor e # menubutton.width 12 # } # $w.scalfun add command none -label None # for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } { # set fname [Ng_Vis_Field getfieldname $i] # set fcomp [Ng_Vis_Field getfieldcomponents $i] # if { $fcomp == 1 } { # $w.scalfun add command $fname.1 -label $fname # } { # for { set j 1 } { $j <= $fcomp } { incr j } { # $w.scalfun add command $fname.$j -label "$fname ($j)" # } # $w.scalfun add command $fname.0 -label "func ($fname)" # } # } # $w.vecfun add command none -label None # for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } { # set fname [Ng_Vis_Field getfieldname $i] # set fcomp [Ng_Vis_Field getfieldcomponents $i] # set iscomplex [Ng_Vis_Field iscomplex $i] # set sdim [Ng_Vis_Field getdimension] # if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] } # if { ($fcomp == $sdim) || ($fcomp == 3) } { # $w.vecfun add command $fname -label $fname # } # } # $w.scalfun configure -variable visoptions.scalfunction # $w.scalfun configure -command { Ng_Vis_Set parameters; redraw } # $w.vecfun configure -variable visoptions.vecfunction # $w.vecfun configure -command { Ng_Vis_Set parameters; redraw } # # puts "sclfunction = ${visoptions.scalfunction}" # tixOptionMenu $w.evaluate -label "Evaluate: " \ # -options { # label.width 18 # label.anchor e # menubutton.width 12 # } # $w.evaluate add command abs -label "|.|" # $w.evaluate add command abstens -label "|tensor|" # $w.evaluate add command mises -label "Mises" # $w.evaluate add command main -label "Main" # $w.evaluate configure -variable visoptions.evaluate # $w.evaluate configure -command { # Ng_Vis_Set parameters; # redraw # } # pack $w.scalfun $w.vecfun $w.evaluate # tixControl $w.multidimcomp -label "multidim-component: " -integer true \ # -variable visoptions.multidimcomponent -min 0 \ # -command { Ng_Vis_Set parameters; redraw } \ # -options { # entry.width 6 # label.width 18 # label.anchor e # } # pack $w.multidimcomp # pack $w.imaginary $w.logscale $w.texframe $w.invcolor $w.redrawperiodic # pack $w.texframe.usetexture $w.texframe.lintexture -side left -expand yes # frame $w.bu # pack $w.bu -pady 5 # button $w.bu.showsol -text "Show Solution" -command { # set selectvisual solution # Ng_SetVisParameters # redraw # } # button $w.bu.clipping -text "Clipping" -command { # clippingdialog; # } # button $w.bu.fieldlines -text "Fieldlines" -command { # fieldlinesdialog; # } # button $w.bu.lineplot -text "2D Lineplot" -command { # lineplotdialog; # } # button $w.bu.done -text "Close" -command { # destroy .visoptions_dlg # } # pack $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes # wm withdraw $w # wm deiconify $w # } # } netgen-6.2.1905/ng/netgen.ocf0000644000175000017500000000134313504650527014357 0ustar kurtkurt# Netgen Mesher # Boundary Condition Colour Profile # # Name: netgen.ocf # # Description: Netgen default colour # profile file for colour based automatic # assignment of boundary condition numbers # # Format: # [boundary_colours] (mandatory keyword) # # # # .... # .... # NOTE: # * Currently, the default Boundary # Condition number assigned to faces without # any colour defined is "1" # * Boundary Condition number "0" is invalid, # and should not be used boundary_colours 7 2 0.0000 0.0000 0.0000 3 1.0000 0.0000 0.0000 4 0.0000 0.0000 1.0000 5 1.0000 1.0000 0.0000 6 0.0000 1.0000 1.0000 7 1.0000 0.0000 1.0000 8 1.0000 1.0000 1.0000 netgen-6.2.1905/ng/demoview.cpp0000644000175000017500000002042713504650527014735 0ustar kurtkurt/*********************************************************************/ /* File: demoview.cpp */ /* Author: Robert, Joachim */ /* Date: 6. Mar. 2003 */ /*********************************************************************/ #include //#include #include #include #include #include #include #include #include #include "inctcl.hpp" #include namespace netgen { extern VisualScene *vs; #include "demoview.hpp" /* static demokwstruct defkw[] = { { TOK_TIME, "t" }, { TOK_CAMPOS, "camerapos" }, { TOK_CAMPOINT, "camerapointto" }, { TOK_CAMUP, "cameraup" } }; */ static demoview_kwstruct demoview_defkw[] = { { DTOK_TIME, "t" }, { DTOK_CAMPOS, "camerapos" }, { DTOK_CAMPOINT, "camerapointto" }, { DTOK_CAMUP, "cameraup" } }; DemoScanner :: DemoScanner (ifstream & ascanin) { scanin = &ascanin; token = DTOK_END; num_value = 0; linenum = 1; } void DemoScanner :: ReadNext () { char ch; // whitespaces ueberspringen do { scanin->get(ch); if (ch == '\n') linenum++; // end of file reached if (scanin->eof()) { token = DTOK_END; return; } // skip comment line if (ch == '#') { while (ch != '\n') { scanin->get(ch); if (scanin->eof()) { token = DTOK_END; return; } } linenum++; } } while (isspace(ch)); switch (ch) { case '(': case ')': case '[': case ']': case '-': case ':': case '=': case ',': case ';': case '+': { token = DEMOVIEW_TOKEN_TYPE (ch); break; } default: { if (isdigit (ch) || ch == '.') { scanin->putback (ch); (*scanin) >> num_value; token = DTOK_NUM; return; } if (isalpha (ch)) { string_value = string (1, ch); scanin->get(ch); while (isalnum(ch)) { string_value += ch; scanin->get(ch); } scanin->putback (ch); } int nr = 0; while (demoview_defkw[nr].kw) { if (string_value == demoview_defkw[nr].name) { token = demoview_defkw[nr].kw; return; } nr++; } token = DTOK_STRING; } } } void DemoScanner :: Error (const string & err) { stringstream errstr; errstr << "Parsing error in line " << linenum << ": " << endl << err << endl; throw string(errstr.str()); } void ParseChar (DemoScanner & scan, char ch) { char str[2]; str[0] = ch; str[1] = 0; if (scan.GetToken() != DEMOVIEW_TOKEN_TYPE(ch)) scan.Error (string ("token '") + string(str) + string("' expected")); scan.ReadNext(); } double ParseNumber(DemoScanner & scan) { if (scan.GetToken() == '-') { scan.ReadNext(); return -ParseNumber (scan); } if (scan.GetToken() != DTOK_NUM) scan.Error ("number expected"); double val = scan.GetNumValue(); scan.ReadNext(); return val; } Vec<3> ParseVector (DemoScanner & scan) { Vec<3> s; s(0) = ParseNumber (scan); ParseChar (scan, ','); s(1) = ParseNumber (scan); ParseChar (scan, ','); s(2) = ParseNumber (scan); return s; } void ParseConstLineOrSpline (DemoScanner & scan, double * t, Vec<3> * s) { int np = 1; scan.ReadNext(); ParseChar (scan, '('); t[0] = ParseNumber (scan)*1000; ParseChar (scan, ':'); s[0] = ParseVector (scan); if (scan.GetToken() != DTOK_RP && scan.GetToken() != DTOK_SEMICOLON) scan.Error (") or ; expected"); if (scan.GetToken() == DTOK_SEMICOLON) { np++; scan.ReadNext(); t[1] = ParseNumber (scan)*1000; ParseChar (scan, ':'); s[1] = ParseVector (scan); if (scan.GetToken() != DTOK_RP && scan.GetToken() != DTOK_SEMICOLON) scan.Error (") or ; expected"); if (scan.GetToken() == DTOK_SEMICOLON) { np++; scan.ReadNext(); t[2] = ParseNumber (scan)*1000; ParseChar (scan, ':'); s[2] = ParseVector (scan); ParseChar (scan, ')'); ParseChar (scan, ';'); } else if (scan.GetToken() == DTOK_RP) { scan.ReadNext(); ParseChar (scan, ';'); } } else if (scan.GetToken() == DTOK_RP) { scan.ReadNext(); ParseChar (scan, ';'); } if (np == 1) // constant spline { t[1] = t[2] = t[0]; s[1] = s[2] = s[0]; } if (np == 2) // linear spline { t[2] = t[1]; t[1] = 0.5*(t[0] + t[2]); s[2] = s[1]; s[1] = 0.5*(s[0] + s[2]); } } template void InterpolationSpline :: AddSpline(double t1, double t2, double t3, S s1, S s2, S s3) { int pos, i, j; // find pos to insert interpotation point for (pos = 0; pos < ip.Size() && ip[pos][0].GetT() < t1; pos++) ; ip.SetSize( ip.Size()+1 ); for (i = ip.Size()-2; i >= pos; i--) for (j = 0; j < 3; j++) ip[i+1][j] = ip[i][j]; ip[pos][0].SetTS (t1, s1); ip[pos][1].SetTS (t2, s2); ip[pos][2].SetTS (t3, s3); } template S InterpolationSpline :: Evaluate (double t) { if (t < ip[0][0].GetT()) return (ip[0][0].GetS()); if (t > ip[ip.Size()-1][2].GetT()) { finished = 1; return (ip[ip.Size()-1][2].GetS()); } int pos; for (pos = 0; pos < ip.Size() && t >= ip[pos][0].GetT(); pos++) ; pos--; if (t >= ip[pos][0].GetT() && t <= ip[pos][2].GetT()) { double t0 = ip[pos][0].GetT(); double t1 = ip[pos][2].GetT(); double t01 = (t-t0)/(t1-t0); double b1, b2, b3, w; b1 = (1-t01)*(1-t01); b2 = sqrt(2.0) * t01 * (1-t01); b3 = t01 * t01; w = b1 + b2 + b3; return ( (1/w) * (b1 * ip[pos][0].GetS() + b2 * ip[pos][1].GetS() + b3 * ip[pos][2].GetS()) ); } else return (ip[pos][2].GetS()); } DemoView :: DemoView (const char * filename) : campos( Vec<3>(5,0,0) ), campoint ( Vec<3>(0,0,0) ), camup ( Vec<3>(0,0,1) ) { double time = 0; ifstream istr; istr.open(filename); DemoScanner scan(istr); double t[3]; Vec<3> s[3]; scan.ReadNext(); try { while (1) { if (scan.GetToken() == DTOK_END) break; if (scan.GetToken() == DTOK_CAMPOS) { ParseConstLineOrSpline (scan, &t[0], &s[0]); campos.AddSpline (time+t[0], time+t[1], time+t[2], s[0], s[1], s[2]); } else if (scan.GetToken() == DTOK_CAMUP) { ParseConstLineOrSpline (scan, &t[0], &s[0]); camup.AddSpline (time+t[0], time+t[1], time+t[2], s[0], s[1], s[2]); } else if (scan.GetToken() == DTOK_CAMPOINT) { ParseConstLineOrSpline (scan, &t[0], &s[0]); campoint.AddSpline (time+t[0], time+t[1], time+t[2], s[0], s[1], s[2]); } else if (scan.GetToken() == DTOK_TIME) { scan.ReadNext(); if (scan.GetToken() != DTOK_EQU && scan.GetToken() != DTOK_PLUS) scan.Error ("= or += expected"); if (scan.GetToken() == DTOK_EQU) { scan.ReadNext(); time = ParseNumber (scan)*1000; ParseChar (scan, ';'); } else if (scan.GetToken() == DTOK_PLUS) { scan.ReadNext(); ParseChar (scan, '='); time += ParseNumber (scan)*1000; ParseChar (scan, ';'); } } else { cout << "read unidentified token " << scan.GetToken() << " string = " << scan.GetStringValue() << endl; scan.ReadNext(); } } } catch (string errstr) { cout << "caught error " << errstr << endl; } } DemoView :: ~DemoView () { ; } int DemoView :: SetTime (double time) { /* cout << "time = " << time << endl; cout << "campos : " << campos.Evaluate (time) << endl; cout << "campoint: " << campoint.Evaluate (time) << endl; cout << "camup : " << camup.Evaluate (time) << endl; */ vs -> LookAt ( Point<3>( campos.Evaluate (time)), Point<3>(campoint.Evaluate (time)), Point<3>( camup.Evaluate (time)) ); if (campos.IsFinished() && campoint.IsFinished() && camup.IsFinished()) { return -1; } return 0; } } netgen-6.2.1905/ng/fonts.hpp0000644000175000017500000051322213504650527014254 0ustar kurtkurt#define font12_width 591 #define font12_height 12 static unsigned char font12_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x84, 0x44, 0x10, 0x88, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0E, 0xE1, 0x38, 0xD0, 0xE7, 0x7C, 0x8E, 0x03, 0x00, 0x00, 0x00, 0x38, 0x8E, 0xF3, 0x38, 0xC7, 0xF7, 0x39, 0x91, 0xC3, 0x45, 0x41, 0x14, 0x39, 0x8F, 0xF3, 0x38, 0x5F, 0x14, 0x45, 0x51, 0xF4, 0x39, 0x82, 0xA3, 0x00, 0x00, 0x10, 0x00, 0x10, 0x80, 0x01, 0x01, 0x01, 0x09, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x60, 0x84, 0x51, 0x01, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x4E, 0xA5, 0x10, 0x04, 0x01, 0x00, 0x00, 0x00, 0x40, 0x91, 0x11, 0x45, 0x58, 0x10, 0x40, 0x51, 0x04, 0x00, 0x10, 0x20, 0x44, 0x51, 0x14, 0x45, 0x49, 0x10, 0x44, 0x11, 0x81, 0x24, 0xC1, 0x16, 0x45, 0x51, 0x14, 0x45, 0x44, 0x14, 0x45, 0x51, 0x04, 0x09, 0x02, 0x12, 0x01, 0x00, 0x10, 0x00, 0x10, 0x40, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x92, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7C, 0x95, 0xA2, 0x00, 0x02, 0xA2, 0x10, 0x00, 0x00, 0x20, 0x19, 0x11, 0x41, 0x54, 0x10, 0x40, 0x51, 0x44, 0x10, 0xC8, 0x47, 0x44, 0x59, 0x14, 0x05, 0x51, 0x10, 0x04, 0x11, 0x81, 0x14, 0x41, 0x35, 0x45, 0x51, 0x14, 0x05, 0x44, 0x14, 0x45, 0x8A, 0x82, 0x08, 0x04, 0x02, 0x00, 0x80, 0xF3, 0x38, 0x9E, 0xE3, 0x78, 0x8F, 0x81, 0x49, 0xC4, 0xF3, 0x38, 0x8F, 0xD7, 0x79, 0x4E, 0x14, 0x45, 0x51, 0xF4, 0x11, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x05, 0x42, 0x00, 0x02, 0x42, 0x10, 0x00, 0x00, 0x20, 0x15, 0x01, 0x31, 0xD2, 0xF3, 0x20, 0x4E, 0x44, 0x10, 0x04, 0x80, 0x20, 0x55, 0xF4, 0x04, 0xD1, 0xF3, 0x04, 0x1F, 0x81, 0x0C, 0x41, 0x55, 0x45, 0x51, 0x14, 0x39, 0x44, 0xA4, 0x44, 0x84, 0x42, 0x08, 0x04, 0x02, 0x00, 0x00, 0x14, 0x45, 0x51, 0x44, 0x44, 0x11, 0x01, 0x29, 0x44, 0x15, 0x45, 0x51, 0x34, 0x04, 0x44, 0x14, 0x45, 0x4A, 0x84, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x0E, 0x61, 0x01, 0x02, 0xF2, 0x7D, 0xC0, 0x07, 0x10, 0x13, 0x81, 0x40, 0x11, 0x14, 0x21, 0x91, 0x07, 0x00, 0x02, 0x00, 0x11, 0xD5, 0x17, 0x05, 0x51, 0x10, 0x74, 0x11, 0x81, 0x0C, 0x41, 0x94, 0x45, 0x4F, 0xF4, 0x40, 0x44, 0xA4, 0x54, 0x04, 0x21, 0x08, 0x08, 0x02, 0x00, 0x80, 0x17, 0x05, 0xD1, 0x47, 0x44, 0x11, 0x01, 0x19, 0x44, 0x15, 0x45, 0x51, 0x14, 0x38, 0x44, 0xA4, 0x54, 0x44, 0x44, 0x10, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x14, 0x95, 0x00, 0x02, 0x42, 0x10, 0x00, 0x00, 0x10, 0x11, 0x41, 0x40, 0x1F, 0x14, 0x11, 0x11, 0x04, 0x00, 0xC4, 0x87, 0x00, 0x59, 0x14, 0x05, 0x51, 0x10, 0x44, 0x11, 0x91, 0x14, 0x41, 0x14, 0x45, 0x41, 0x54, 0x40, 0x44, 0xA4, 0x54, 0x0A, 0x11, 0x08, 0x08, 0x02, 0x00, 0x40, 0x14, 0x05, 0x51, 0x40, 0x44, 0x11, 0x01, 0x19, 0x44, 0x15, 0x45, 0x51, 0x14, 0x40, 0x44, 0xA4, 0x54, 0x44, 0x24, 0x10, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x95, 0x9A, 0x00, 0x04, 0xA1, 0x10, 0x04, 0x40, 0x08, 0x11, 0x21, 0x44, 0x50, 0x14, 0x11, 0x11, 0x44, 0x10, 0x08, 0x40, 0x10, 0x41, 0x14, 0x45, 0x49, 0x10, 0x44, 0x11, 0x91, 0x24, 0x41, 0x14, 0x45, 0x41, 0x95, 0x44, 0x44, 0x44, 0x6C, 0x11, 0x11, 0x08, 0x10, 0x02, 0x00, 0x40, 0x14, 0x45, 0x51, 0x40, 0x44, 0x11, 0x01, 0x29, 0x44, 0x15, 0x45, 0x51, 0x14, 0x40, 0x44, 0x44, 0x54, 0x4A, 0x14, 0x10, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x8E, 0x64, 0x01, 0x88, 0x00, 0x00, 0x04, 0x40, 0x08, 0x8E, 0xF3, 0x39, 0x90, 0xE3, 0x10, 0x8E, 0x43, 0x10, 0x10, 0x20, 0x10, 0x5E, 0xF4, 0x38, 0xC7, 0x17, 0x38, 0x91, 0x63, 0x44, 0x5F, 0x14, 0x39, 0x81, 0x13, 0x39, 0x84, 0x43, 0x44, 0x11, 0xF1, 0x39, 0x90, 0x03, 0x00, 0x80, 0xF7, 0x38, 0x9E, 0x47, 0x78, 0x91, 0x03, 0x49, 0x4E, 0x15, 0x39, 0x8F, 0x17, 0x3C, 0x98, 0x47, 0x38, 0x91, 0xF7, 0x61, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font14_width 789 #define font14_height 14 static unsigned char font14_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x36, 0x08, 0x66, 0x1C, 0x18, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3E, 0x18, 0x3E, 0x3E, 0x60, 0x7F, 0x3C, 0x7F, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3E, 0x3E, 0x3F, 0x3E, 0x1F, 0x7F, 0x7F, 0x3E, 0x63, 0x3C, 0x78, 0x63, 0x03, 0x41, 0x63, 0x3E, 0x3F, 0x3E, 0x3F, 0x3E, 0xFF, 0x63, 0x63, 0x63, 0x63, 0xC3, 0x7F, 0x3C, 0x06, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x78, 0x00, 0x03, 0x18, 0x60, 0x03, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x0E, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x36, 0x3E, 0x6B, 0x36, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x63, 0x1C, 0x63, 0x63, 0x70, 0x03, 0x06, 0x60, 0x63, 0x63, 0x00, 0x00, 0x60, 0x00, 0x06, 0x63, 0x63, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x63, 0x03, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x18, 0x63, 0x63, 0x63, 0x63, 0xC3, 0x60, 0x0C, 0x06, 0x30, 0x66, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, 0x03, 0x18, 0x60, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x6B, 0x36, 0x36, 0x00, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x63, 0x1E, 0x63, 0x63, 0x78, 0x03, 0x03, 0x60, 0x63, 0x63, 0x00, 0x00, 0x30, 0x00, 0x0C, 0x63, 0x73, 0x63, 0x63, 0x63, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x33, 0x03, 0x77, 0x63, 0x63, 0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, 0x66, 0x60, 0x0C, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7F, 0x0B, 0x30, 0x1C, 0x00, 0x0C, 0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x30, 0x73, 0x18, 0x60, 0x60, 0x6C, 0x03, 0x03, 0x30, 0x63, 0x63, 0x18, 0x18, 0x18, 0x7F, 0x18, 0x63, 0x6B, 0x63, 0x63, 0x03, 0x63, 0x03, 0x03, 0x03, 0x63, 0x18, 0x30, 0x1B, 0x03, 0x7F, 0x67, 0x63, 0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, 0x66, 0x30, 0x0C, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x3E, 0x7E, 0x3E, 0x3F, 0x7E, 0x3F, 0x1C, 0x70, 0x63, 0x18, 0x3F, 0x3F, 0x3E, 0x3F, 0x7E, 0x7B, 0x7E, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x0B, 0x18, 0x6E, 0x00, 0x0C, 0x30, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x18, 0x7B, 0x18, 0x30, 0x3C, 0x66, 0x3F, 0x3F, 0x30, 0x3E, 0x63, 0x18, 0x18, 0x0C, 0x00, 0x30, 0x30, 0x6B, 0x63, 0x3F, 0x03, 0x63, 0x1F, 0x1F, 0x03, 0x7F, 0x18, 0x30, 0x0F, 0x03, 0x6B, 0x6F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x18, 0x63, 0x63, 0x63, 0x1C, 0x3C, 0x18, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x60, 0x63, 0x63, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x0F, 0x03, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x63, 0x30, 0x06, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x3E, 0x18, 0x3B, 0x00, 0x0C, 0x30, 0x7F, 0x7E, 0x00, 0x7F, 0x00, 0x18, 0x6F, 0x18, 0x18, 0x60, 0x63, 0x60, 0x63, 0x18, 0x63, 0x7E, 0x00, 0x00, 0x06, 0x00, 0x60, 0x18, 0x6B, 0x7F, 0x63, 0x03, 0x63, 0x03, 0x03, 0x7B, 0x63, 0x18, 0x30, 0x0F, 0x03, 0x63, 0x7B, 0x63, 0x3F, 0x63, 0x3F, 0x60, 0x18, 0x63, 0x36, 0x6B, 0x1C, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7E, 0x63, 0x03, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x07, 0x03, 0x0C, 0x63, 0x63, 0x6B, 0x36, 0x63, 0x18, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7F, 0x68, 0x0C, 0x33, 0x00, 0x0C, 0x30, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x67, 0x18, 0x0C, 0x60, 0x7F, 0x60, 0x63, 0x18, 0x63, 0x60, 0x00, 0x00, 0x0C, 0x7F, 0x30, 0x18, 0x6B, 0x63, 0x63, 0x03, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x1B, 0x03, 0x63, 0x73, 0x63, 0x03, 0x63, 0x0F, 0x60, 0x18, 0x63, 0x36, 0x7F, 0x36, 0x18, 0x06, 0x0C, 0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, 0x7F, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x0F, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x3E, 0x0C, 0x63, 0x36, 0x6B, 0x1C, 0x63, 0x0C, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x68, 0x6C, 0x33, 0x00, 0x0C, 0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x63, 0x18, 0x06, 0x63, 0x60, 0x60, 0x63, 0x0C, 0x63, 0x60, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x73, 0x63, 0x63, 0x63, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x33, 0x33, 0x03, 0x63, 0x63, 0x63, 0x03, 0x63, 0x1B, 0x63, 0x18, 0x63, 0x36, 0x77, 0x36, 0x18, 0x03, 0x0C, 0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, 0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x60, 0x0C, 0x63, 0x36, 0x6B, 0x36, 0x63, 0x06, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x6B, 0xD6, 0x3B, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x18, 0x06, 0x63, 0x18, 0x03, 0x63, 0x60, 0x63, 0x63, 0x0C, 0x63, 0x30, 0x18, 0x18, 0x30, 0x00, 0x0C, 0x18, 0x03, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, 0x63, 0x63, 0x18, 0x33, 0x63, 0x03, 0x63, 0x63, 0x63, 0x03, 0x7B, 0x33, 0x63, 0x18, 0x63, 0x1C, 0x63, 0x63, 0x18, 0x03, 0x0C, 0x60, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x60, 0x0C, 0x63, 0x1C, 0x6B, 0x63, 0x63, 0x03, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x3E, 0x66, 0x6E, 0x00, 0x30, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x18, 0x06, 0x3E, 0x7E, 0x7F, 0x3E, 0x60, 0x3E, 0x3E, 0x0C, 0x3E, 0x1E, 0x18, 0x18, 0x60, 0x00, 0x06, 0x18, 0x7E, 0x63, 0x3F, 0x3E, 0x1F, 0x7F, 0x03, 0x3E, 0x63, 0x3C, 0x1E, 0x63, 0x7F, 0x63, 0x63, 0x3E, 0x03, 0x3E, 0x63, 0x3E, 0x18, 0x3E, 0x1C, 0x41, 0x63, 0x18, 0x7F, 0x3C, 0x60, 0x3C, 0x00, 0x00, 0x00, 0x7E, 0x3F, 0x3E, 0x7E, 0x3E, 0x0C, 0x7E, 0x63, 0x3C, 0x66, 0x63, 0x3C, 0x6B, 0x63, 0x3E, 0x3F, 0x7E, 0x03, 0x3F, 0x78, 0x7E, 0x1C, 0x3E, 0x63, 0x7E, 0x7F, 0x38, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font16_width 789 #define font16_height 16 static unsigned char font16_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x36, 0x08, 0x66, 0x1C, 0x18, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3E, 0x18, 0x3E, 0x3E, 0x60, 0x7F, 0x3C, 0x7F, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3E, 0x3E, 0x3F, 0x3E, 0x1F, 0x7F, 0x7F, 0x3E, 0x63, 0x3C, 0x78, 0x63, 0x03, 0x41, 0x63, 0x3E, 0x3F, 0x3E, 0x3F, 0x3E, 0xFF, 0x63, 0x63, 0x63, 0x63, 0xC3, 0x7F, 0x3C, 0x06, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x78, 0x00, 0x03, 0x18, 0x60, 0x03, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x0E, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x36, 0x3E, 0x6B, 0x36, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x63, 0x1C, 0x63, 0x63, 0x70, 0x03, 0x06, 0x60, 0x63, 0x63, 0x00, 0x00, 0x60, 0x00, 0x06, 0x63, 0x63, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x63, 0x03, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x18, 0x63, 0x63, 0x63, 0x63, 0xC3, 0x60, 0x0C, 0x06, 0x30, 0x66, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, 0x03, 0x18, 0x60, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x6B, 0x36, 0x36, 0x00, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x63, 0x1E, 0x63, 0x63, 0x78, 0x03, 0x03, 0x60, 0x63, 0x63, 0x00, 0x00, 0x30, 0x00, 0x0C, 0x63, 0x73, 0x63, 0x63, 0x63, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x33, 0x03, 0x77, 0x63, 0x63, 0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, 0x66, 0x60, 0x0C, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7F, 0x0B, 0x30, 0x1C, 0x00, 0x0C, 0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x30, 0x73, 0x18, 0x60, 0x60, 0x6C, 0x03, 0x03, 0x30, 0x63, 0x63, 0x18, 0x18, 0x18, 0x7F, 0x18, 0x63, 0x6B, 0x63, 0x63, 0x03, 0x63, 0x03, 0x03, 0x03, 0x63, 0x18, 0x30, 0x1B, 0x03, 0x7F, 0x67, 0x63, 0x63, 0x63, 0x63, 0x03, 0x18, 0x63, 0x63, 0x63, 0x36, 0x66, 0x30, 0x0C, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x3E, 0x7E, 0x3E, 0x3F, 0x7E, 0x3F, 0x1C, 0x70, 0x63, 0x18, 0x3F, 0x3F, 0x3E, 0x3F, 0x7E, 0x7B, 0x7E, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x0B, 0x18, 0x6E, 0x00, 0x0C, 0x30, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x18, 0x7B, 0x18, 0x30, 0x3C, 0x66, 0x3F, 0x3F, 0x30, 0x3E, 0x63, 0x18, 0x18, 0x0C, 0x00, 0x30, 0x30, 0x6B, 0x63, 0x3F, 0x03, 0x63, 0x1F, 0x1F, 0x03, 0x7F, 0x18, 0x30, 0x0F, 0x03, 0x6B, 0x6F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x18, 0x63, 0x63, 0x63, 0x1C, 0x3C, 0x18, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x60, 0x63, 0x63, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x0F, 0x03, 0x0C, 0x63, 0x63, 0x63, 0x63, 0x63, 0x30, 0x06, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x3E, 0x18, 0x3B, 0x00, 0x0C, 0x30, 0x7F, 0x7E, 0x00, 0x7F, 0x00, 0x18, 0x6F, 0x18, 0x18, 0x60, 0x63, 0x60, 0x63, 0x18, 0x63, 0x7E, 0x00, 0x00, 0x06, 0x00, 0x60, 0x18, 0x6B, 0x7F, 0x63, 0x03, 0x63, 0x03, 0x03, 0x7B, 0x63, 0x18, 0x30, 0x0F, 0x03, 0x63, 0x7B, 0x63, 0x3F, 0x63, 0x3F, 0x60, 0x18, 0x63, 0x36, 0x6B, 0x1C, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7E, 0x63, 0x03, 0x63, 0x63, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x07, 0x03, 0x0C, 0x63, 0x63, 0x6B, 0x36, 0x63, 0x18, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7F, 0x68, 0x0C, 0x33, 0x00, 0x0C, 0x30, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x67, 0x18, 0x0C, 0x60, 0x7F, 0x60, 0x63, 0x18, 0x63, 0x60, 0x00, 0x00, 0x0C, 0x7F, 0x30, 0x18, 0x6B, 0x63, 0x63, 0x03, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x30, 0x1B, 0x03, 0x63, 0x73, 0x63, 0x03, 0x63, 0x0F, 0x60, 0x18, 0x63, 0x36, 0x7F, 0x36, 0x18, 0x06, 0x0C, 0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, 0x7F, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x0F, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x3E, 0x0C, 0x63, 0x36, 0x6B, 0x1C, 0x63, 0x0C, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x68, 0x6C, 0x33, 0x00, 0x0C, 0x30, 0x36, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x63, 0x18, 0x06, 0x63, 0x60, 0x60, 0x63, 0x0C, 0x63, 0x60, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x73, 0x63, 0x63, 0x63, 0x63, 0x03, 0x03, 0x63, 0x63, 0x18, 0x33, 0x33, 0x03, 0x63, 0x63, 0x63, 0x03, 0x63, 0x1B, 0x63, 0x18, 0x63, 0x36, 0x77, 0x36, 0x18, 0x03, 0x0C, 0x30, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x03, 0x63, 0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x1B, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x60, 0x0C, 0x63, 0x36, 0x6B, 0x36, 0x63, 0x06, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x6B, 0xD6, 0x3B, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x18, 0x06, 0x63, 0x18, 0x03, 0x63, 0x60, 0x63, 0x63, 0x0C, 0x63, 0x30, 0x18, 0x18, 0x30, 0x00, 0x0C, 0x18, 0x03, 0x63, 0x63, 0x63, 0x33, 0x03, 0x03, 0x63, 0x63, 0x18, 0x33, 0x63, 0x03, 0x63, 0x63, 0x63, 0x03, 0x7B, 0x33, 0x63, 0x18, 0x63, 0x1C, 0x63, 0x63, 0x18, 0x03, 0x0C, 0x60, 0x30, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x03, 0x0C, 0x63, 0x63, 0x18, 0x60, 0x33, 0x18, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x03, 0x60, 0x0C, 0x63, 0x1C, 0x6B, 0x63, 0x63, 0x03, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x36, 0x3E, 0x66, 0x6E, 0x00, 0x30, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x18, 0x06, 0x3E, 0x7E, 0x7F, 0x3E, 0x60, 0x3E, 0x3E, 0x0C, 0x3E, 0x1E, 0x18, 0x18, 0x60, 0x00, 0x06, 0x18, 0x7E, 0x63, 0x3F, 0x3E, 0x1F, 0x7F, 0x03, 0x3E, 0x63, 0x3C, 0x1E, 0x63, 0x7F, 0x63, 0x63, 0x3E, 0x03, 0x3E, 0x63, 0x3E, 0x18, 0x3E, 0x1C, 0x41, 0x63, 0x18, 0x7F, 0x3C, 0x60, 0x3C, 0x00, 0x00, 0x00, 0x7E, 0x3F, 0x3E, 0x7E, 0x3E, 0x0C, 0x7E, 0x63, 0x3C, 0x60, 0x63, 0x3C, 0x6B, 0x63, 0x3E, 0x3F, 0x7E, 0x03, 0x3F, 0x78, 0x7E, 0x1C, 0x3E, 0x63, 0x7E, 0x7F, 0x38, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font18_width 987 #define font18_height 18 static unsigned char font18_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x0C, 0x33, 0x30, 0x38, 0xC3, 0x03, 0x0C, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFC, 0xC0, 0xC0, 0x0F, 0x3F, 0x80, 0xF9, 0x87, 0x8F, 0x7F, 0xFC, 0xF0, 0x03, 0x00, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x1E, 0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0x7E, 0xF8, 0xE7, 0x1F, 0x3F, 0x86, 0xE1, 0x01, 0x9E, 0x61, 0x06, 0x04, 0x64, 0x18, 0x3F, 0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0xFE, 0x19, 0x66, 0xD8, 0x60, 0x86, 0x19, 0xE6, 0x1F, 0x1E, 0x06, 0xE0, 0xC1, 0x0C, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x1E, 0x00, 0x06, 0xC0, 0x00, 0x8C, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x30, 0x70, 0x60, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x0C, 0x33, 0xFC, 0x28, 0x63, 0x06, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x86, 0xE1, 0x60, 0x98, 0x61, 0xC0, 0x19, 0xC0, 0x80, 0x61, 0x86, 0x19, 0x06, 0x00, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x33, 0x83, 0x19, 0x66, 0x98, 0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x61, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x61, 0x30, 0x18, 0x66, 0xD8, 0x60, 0x86, 0x19, 0x06, 0x18, 0x06, 0x06, 0x80, 0x61, 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0xC0, 0x00, 0x8C, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0xC0, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB6, 0xB9, 0x61, 0x06, 0x00, 0x30, 0xC0, 0x60, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xF1, 0x60, 0x98, 0x61, 0xE0, 0x19, 0x60, 0x80, 0x61, 0x86, 0x19, 0x06, 0x00, 0x00, 0x30, 0x00, 0x80, 0x81, 0x61, 0x83, 0x19, 0x66, 0x98, 0x61, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x06, 0x1C, 0x67, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x61, 0x30, 0x18, 0x66, 0xD8, 0x60, 0xCC, 0x18, 0x06, 0x18, 0x06, 0x0C, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0x7F, 0x36, 0x80, 0x61, 0x06, 0x00, 0x18, 0x80, 0xC1, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC6, 0xC1, 0x60, 0x18, 0x60, 0xB0, 0x19, 0x60, 0x00, 0x60, 0x86, 0x19, 0x06, 0x03, 0x0C, 0x18, 0xF8, 0x07, 0x83, 0x61, 0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x06, 0xBC, 0xE7, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0x66, 0xD8, 0x60, 0xCC, 0x30, 0x03, 0x0C, 0x06, 0x0C, 0x80, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xE3, 0x0F, 0x3F, 0xFC, 0xF1, 0xC3, 0x0F, 0x7F, 0xFE, 0xE0, 0x00, 0x8E, 0x61, 0x30, 0xF8, 0xE3, 0x0F, 0x3F, 0xFE, 0xF0, 0x67, 0x1F, 0x3F, 0x7E, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x1F, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0x36, 0xC0, 0xC0, 0x03, 0x00, 0x18, 0x80, 0x81, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xE6, 0xC1, 0x00, 0x18, 0x60, 0x98, 0x19, 0x60, 0x00, 0x30, 0x86, 0x19, 0x06, 0x03, 0x0C, 0x0C, 0x00, 0x00, 0x06, 0x60, 0x9B, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x06, 0xEC, 0xE6, 0x99, 0x61, 0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0xC6, 0xCC, 0x60, 0x78, 0x30, 0x03, 0x06, 0x06, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x81, 0x61, 0x18, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x18, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0x36, 0xC0, 0xC0, 0x19, 0x00, 0x18, 0x80, 0xF1, 0x9F, 0x7F, 0x00, 0xF8, 0x07, 0x00, 0x0C, 0xB6, 0xC1, 0x00, 0x0C, 0x3E, 0x8C, 0xF9, 0xE3, 0x0F, 0x30, 0xFC, 0x18, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x30, 0x9B, 0x19, 0xE6, 0x8F, 0x01, 0x86, 0xF9, 0xE1, 0x87, 0x01, 0xFE, 0xC1, 0x00, 0x8C, 0x07, 0x06, 0x4C, 0x66, 0x9B, 0x61, 0x86, 0x19, 0x66, 0x18, 0x3F, 0x30, 0x18, 0xC6, 0xCC, 0x60, 0x30, 0xE0, 0x01, 0x03, 0x06, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x66, 0x98, 0x01, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x80, 0x01, 0x18, 0x18, 0x66, 0x98, 0x61, 0xCC, 0x18, 0x06, 0x0C, 0x07, 0x30, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xFC, 0x60, 0x60, 0x1B, 0x00, 0x18, 0x80, 0x81, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x06, 0x9E, 0xC1, 0x00, 0x06, 0x60, 0x86, 0x01, 0x66, 0x18, 0x18, 0x86, 0xF1, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x18, 0x9B, 0xF9, 0x67, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x79, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x06, 0x0C, 0x66, 0x9E, 0x61, 0xFE, 0x18, 0xE6, 0x0F, 0x60, 0x30, 0x18, 0xC6, 0xCC, 0x64, 0x30, 0xC0, 0x80, 0x01, 0x06, 0x30, 0x80, 0x01, 0x00, 0x00, 0x00, 0xF0, 0x67, 0x98, 0x01, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x80, 0x01, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x78, 0x18, 0x06, 0x06, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB0, 0x61, 0x30, 0x0E, 0x00, 0x18, 0x80, 0xC1, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8E, 0xC1, 0x00, 0x03, 0x60, 0x86, 0x01, 0x66, 0x18, 0x18, 0x86, 0x01, 0x06, 0x00, 0x00, 0x0C, 0xF8, 0x07, 0x06, 0x0C, 0x9B, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x06, 0x0C, 0x66, 0x9C, 0x61, 0x06, 0x18, 0xE6, 0x01, 0x60, 0x30, 0x18, 0xC6, 0xCC, 0x6E, 0x78, 0xC0, 0xC0, 0x00, 0x06, 0x30, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0xF9, 0x07, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x3F, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x30, 0x18, 0x06, 0x03, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0xB0, 0x31, 0x30, 0x0C, 0x00, 0x18, 0x80, 0x61, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x03, 0x86, 0xC1, 0x80, 0x01, 0x60, 0xFE, 0x01, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x06, 0x00, 0x00, 0x18, 0x00, 0x00, 0x03, 0x0C, 0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x19, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x18, 0x66, 0x03, 0x60, 0x30, 0x18, 0x86, 0xC7, 0x7B, 0xCC, 0xC0, 0x60, 0x00, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0x19, 0x00, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x60, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x78, 0x18, 0x86, 0x01, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xB0, 0xB1, 0x33, 0x0C, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x86, 0xC1, 0xC0, 0x80, 0x61, 0x80, 0x19, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x06, 0x03, 0x0C, 0x30, 0x00, 0x80, 0x01, 0x00, 0x03, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x31, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x18, 0x66, 0x86, 0x61, 0x30, 0x18, 0x86, 0xC7, 0x71, 0xCC, 0xC0, 0x60, 0x00, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0x19, 0x00, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x60, 0x18, 0x18, 0x86, 0x87, 0x6D, 0xCC, 0x18, 0xC6, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB6, 0x99, 0x62, 0x1E, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x83, 0x01, 0x86, 0xC1, 0x60, 0x80, 0x61, 0x80, 0x19, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x03, 0x03, 0x0C, 0x60, 0x00, 0xC0, 0x00, 0x0C, 0x03, 0x18, 0x66, 0x98, 0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x61, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x98, 0x67, 0x8C, 0x61, 0x30, 0x18, 0x06, 0xC3, 0x60, 0x86, 0xC1, 0x60, 0x00, 0x06, 0xC0, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x80, 0x61, 0x18, 0x18, 0x06, 0x83, 0x6D, 0x86, 0x19, 0x66, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xFC, 0x98, 0xC3, 0x1B, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x83, 0x01, 0xFC, 0xF0, 0xE3, 0x1F, 0x3F, 0x80, 0xF1, 0xC3, 0x0F, 0x0C, 0xFC, 0xF0, 0x01, 0x00, 0x0C, 0xC0, 0x00, 0x60, 0x00, 0x0C, 0xFE, 0x19, 0xE6, 0x0F, 0x3F, 0x7E, 0xF8, 0x67, 0x00, 0x3F, 0x86, 0xE1, 0xC1, 0x87, 0x61, 0xFE, 0x0D, 0x66, 0x18, 0x3F, 0x06, 0xF0, 0x63, 0x18, 0x3F, 0x30, 0xF0, 0x03, 0x43, 0x40, 0x86, 0xC1, 0xE0, 0x1F, 0x1E, 0xC0, 0xE0, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xE7, 0x0F, 0x3F, 0xFC, 0xF1, 0x03, 0x03, 0x7F, 0x86, 0xE1, 0x01, 0x8C, 0x61, 0x78, 0xD8, 0x66, 0x18, 0x3F, 0xFE, 0xF0, 0x67, 0x00, 0x3F, 0xF0, 0xF0, 0x07, 0x03, 0x3F, 0x86, 0xF1, 0xE7, 0x1F, 0x38, 0x30, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font20_width 987 #define font20_height 20 static unsigned char font20_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x0C, 0x33, 0x30, 0x00, 0xC0, 0x03, 0x0C, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x0F, 0x3F, 0x80, 0xF9, 0x87, 0x8F, 0x7F, 0xFC, 0xF0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x60, 0x00, 0x1E, 0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0x7E, 0xF8, 0xE7, 0x1F, 0x3F, 0x86, 0xE1, 0x01, 0x9E, 0x61, 0x06, 0x04, 0x64, 0x18, 0x3F, 0xFE, 0xF0, 0xE3, 0x0F, 0x3F, 0xFE, 0x19, 0x66, 0xD8, 0x60, 0x86, 0x19, 0xE6, 0x1F, 0x1E, 0x00, 0xE0, 0xC1, 0x0C, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x1E, 0x00, 0x06, 0xC0, 0x00, 0x8C, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x30, 0x70, 0x60, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x0C, 0x33, 0xFC, 0x38, 0x63, 0x06, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x86, 0xE1, 0x60, 0x98, 0x61, 0xC0, 0x19, 0xC0, 0x80, 0x61, 0x86, 0x19, 0x06, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x33, 0x83, 0x19, 0x66, 0x98, 0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x61, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x61, 0x30, 0x18, 0x66, 0xD8, 0x60, 0x86, 0x19, 0x06, 0x18, 0x06, 0x06, 0x80, 0x61, 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0xC0, 0x00, 0x8C, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0xC0, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB6, 0x29, 0x63, 0x06, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x86, 0xF1, 0x60, 0x98, 0x61, 0xE0, 0x19, 0x60, 0x80, 0x61, 0x86, 0x19, 0x06, 0x00, 0x00, 0x60, 0x00, 0x80, 0x81, 0x61, 0x83, 0x19, 0x66, 0x98, 0x61, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x06, 0x1C, 0x67, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x61, 0x30, 0x18, 0x66, 0xD8, 0x60, 0x86, 0x19, 0x06, 0x18, 0x06, 0x06, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0x36, 0xB8, 0x61, 0x06, 0x00, 0x18, 0x80, 0x61, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xC1, 0x60, 0x18, 0x60, 0xB0, 0x19, 0x60, 0x00, 0x60, 0x86, 0x19, 0x06, 0x00, 0x00, 0x30, 0x00, 0x00, 0x83, 0x61, 0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x06, 0xBC, 0x67, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0x66, 0xD8, 0x60, 0xCC, 0x30, 0x03, 0x18, 0x06, 0x0C, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0x7F, 0x36, 0x80, 0xC1, 0x03, 0x00, 0x18, 0x80, 0xC1, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC6, 0xC1, 0x00, 0x18, 0x60, 0x98, 0x19, 0x60, 0x00, 0x30, 0x86, 0x19, 0x06, 0x03, 0x0C, 0x18, 0xF8, 0x07, 0x06, 0x60, 0x9B, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x06, 0xEC, 0xE6, 0x98, 0x61, 0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0x66, 0xD8, 0x60, 0xCC, 0x30, 0x03, 0x0C, 0x06, 0x0C, 0x80, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xE3, 0x0F, 0x3F, 0xFC, 0xF1, 0xC3, 0x0F, 0x7F, 0xFE, 0xE0, 0x00, 0x8E, 0x61, 0x30, 0xF8, 0xE3, 0x0F, 0x3F, 0xFE, 0xF0, 0x67, 0x1F, 0x3F, 0x7E, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x1F, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0x36, 0xC0, 0x80, 0x01, 0x00, 0x18, 0x80, 0x81, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xE6, 0xC1, 0x00, 0x18, 0x60, 0x8C, 0xF9, 0xE3, 0x0F, 0x30, 0x86, 0x19, 0x06, 0x03, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x30, 0x9B, 0x19, 0xE6, 0x8F, 0x01, 0x86, 0x19, 0x60, 0x80, 0x01, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x06, 0x4C, 0xE6, 0x99, 0x61, 0x86, 0x19, 0x66, 0x98, 0x01, 0x30, 0x18, 0xC6, 0xCC, 0x60, 0x78, 0x30, 0x03, 0x06, 0x06, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x81, 0x61, 0x18, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x18, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xFC, 0xC0, 0xC0, 0x19, 0x00, 0x18, 0x80, 0xF1, 0x9F, 0x7F, 0x00, 0xF8, 0x07, 0x00, 0x0C, 0xB6, 0xC1, 0x00, 0x0C, 0x3E, 0x86, 0x01, 0x66, 0x18, 0x18, 0xFC, 0x18, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x18, 0x18, 0x9B, 0xF9, 0x67, 0x98, 0x01, 0x86, 0xF9, 0xE1, 0x87, 0x79, 0xFE, 0xC1, 0x00, 0x8C, 0x03, 0x06, 0x0C, 0x66, 0x9B, 0x61, 0xFE, 0x18, 0xE6, 0x0F, 0x3F, 0x30, 0x18, 0xC6, 0xCC, 0x60, 0x30, 0xE0, 0x01, 0x03, 0x06, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x66, 0x98, 0x01, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0xE6, 0x80, 0x01, 0x18, 0x18, 0x66, 0x98, 0x61, 0xCC, 0x18, 0x06, 0x0C, 0x07, 0x30, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xB0, 0x61, 0x60, 0x1B, 0x00, 0x18, 0x80, 0x81, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x06, 0x9E, 0xC1, 0x00, 0x06, 0x60, 0x86, 0x01, 0x66, 0x18, 0x18, 0x86, 0xF1, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x9B, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x06, 0x0C, 0x66, 0x9E, 0x61, 0x06, 0x18, 0xE6, 0x01, 0x60, 0x30, 0x18, 0xC6, 0xCC, 0x64, 0x78, 0xC0, 0x80, 0x01, 0x06, 0x30, 0x80, 0x01, 0x00, 0x00, 0x00, 0xF0, 0x67, 0x98, 0x01, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x80, 0x01, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x78, 0x18, 0x06, 0x06, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0x7F, 0xB0, 0x61, 0x30, 0x0E, 0x00, 0x18, 0x80, 0xC1, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8E, 0xC1, 0x00, 0x03, 0x60, 0x86, 0x01, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x06, 0x00, 0x00, 0x18, 0xF8, 0x07, 0x06, 0x0C, 0x9B, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x06, 0x0C, 0x66, 0x9C, 0x61, 0x06, 0x18, 0x66, 0x03, 0x60, 0x30, 0x18, 0xC6, 0xCC, 0x6E, 0xCC, 0xC0, 0xC0, 0x00, 0x06, 0x30, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0xF9, 0x07, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x07, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x3F, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x30, 0x18, 0x06, 0x03, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xB0, 0x31, 0x30, 0x0C, 0x00, 0x18, 0x80, 0x61, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x03, 0x86, 0xC1, 0x80, 0x01, 0x60, 0xFE, 0x01, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x06, 0x00, 0x00, 0x30, 0x00, 0x00, 0x03, 0x00, 0xF3, 0x19, 0x66, 0x98, 0x01, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x19, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x18, 0x66, 0x06, 0x60, 0x30, 0x18, 0x86, 0xC7, 0x7B, 0xCC, 0xC0, 0x60, 0x00, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0x19, 0x00, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x0D, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x60, 0x18, 0x18, 0xC6, 0x8C, 0x6D, 0x78, 0x18, 0x86, 0x01, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xB6, 0xB1, 0x33, 0x0C, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x86, 0xC1, 0xC0, 0x80, 0x61, 0x80, 0x19, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x06, 0x03, 0x0C, 0x60, 0x00, 0x80, 0x01, 0x00, 0x03, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x31, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x18, 0x66, 0x8C, 0x61, 0x30, 0x18, 0x86, 0xC7, 0x71, 0x86, 0xC1, 0x60, 0x00, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x01, 0x86, 0x19, 0x00, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x19, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x00, 0x60, 0x18, 0x18, 0x86, 0x87, 0x6D, 0xCC, 0x18, 0xC6, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0xFC, 0x98, 0x62, 0x1E, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x83, 0x01, 0x86, 0xC1, 0x60, 0x80, 0x61, 0x80, 0x19, 0x66, 0x18, 0x0C, 0x86, 0x01, 0x03, 0x03, 0x0C, 0xC0, 0x00, 0xC0, 0x00, 0x0C, 0x03, 0x18, 0x66, 0x98, 0x61, 0xC6, 0x18, 0x60, 0x80, 0x61, 0x86, 0xC1, 0x60, 0x8C, 0x61, 0x06, 0x0C, 0x66, 0x98, 0x61, 0x06, 0x98, 0x67, 0x98, 0x61, 0x30, 0x18, 0x06, 0xC3, 0x60, 0x86, 0xC1, 0x60, 0x00, 0x06, 0xC0, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x66, 0x98, 0x61, 0x86, 0x19, 0x06, 0x83, 0x61, 0x86, 0xC1, 0x00, 0x8C, 0x31, 0x30, 0xD8, 0x66, 0x98, 0x61, 0x86, 0x19, 0x66, 0x80, 0x61, 0x18, 0x18, 0x06, 0x83, 0x6D, 0x86, 0x19, 0x66, 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x33, 0x30, 0x98, 0xC3, 0x1B, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x83, 0x01, 0xFC, 0xF0, 0xE3, 0x1F, 0x3F, 0x80, 0xF1, 0xC3, 0x0F, 0x0C, 0xFC, 0xF0, 0x01, 0x00, 0x0C, 0x80, 0x01, 0x60, 0x00, 0x0C, 0xFE, 0x19, 0xE6, 0x0F, 0x3F, 0x7E, 0xF8, 0x67, 0x00, 0x3F, 0x86, 0xE1, 0xC1, 0x87, 0x61, 0xFE, 0x0D, 0x66, 0x18, 0x3F, 0x06, 0xF0, 0x63, 0x18, 0x3F, 0x30, 0xF0, 0x03, 0x43, 0x40, 0x86, 0xC1, 0xE0, 0x1F, 0x1E, 0xC0, 0xE0, 0x01, 0x00, 0x00, 0x00, 0xF0, 0xE7, 0x0F, 0x3F, 0xFC, 0xF1, 0x03, 0x03, 0x7F, 0x86, 0xE1, 0x01, 0x8C, 0x61, 0x78, 0xD8, 0x66, 0x18, 0x3F, 0xFE, 0xF0, 0x67, 0x00, 0x3F, 0xF0, 0xF0, 0x07, 0x03, 0x3F, 0x86, 0xF1, 0xE7, 0x1F, 0x38, 0x30, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font22_width 1086 #define font22_height 22 static unsigned char font22_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x33, 0x98, 0x01, 0x03, 0xC7, 0xF0, 0x01, 0x06, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xF8, 0x00, 0x03, 0x3E, 0xF0, 0x01, 0x30, 0xFF, 0xE1, 0xC7, 0x7F, 0xF8, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1F, 0xFC, 0xC0, 0x87, 0x3F, 0xF0, 0xE1, 0x0F, 0xFF, 0xF9, 0x0F, 0x1F, 0x06, 0xE3, 0x07, 0xF8, 0x0D, 0x66, 0x80, 0x00, 0x19, 0x0C, 0x1F, 0xFE, 0xC0, 0x87, 0x3F, 0xF0, 0xF1, 0x3F, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x1B, 0x98, 0xFF, 0xF0, 0x61, 0x00, 0x7C, 0x60, 0x03, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x30, 0x00, 0x80, 0x0F, 0x00, 0x06, 0x00, 0x03, 0x60, 0x18, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x03, 0x0E, 0x98, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x33, 0x98, 0xC1, 0x8F, 0xCD, 0x18, 0x03, 0x06, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x8C, 0x81, 0x03, 0x63, 0x18, 0x03, 0x38, 0x03, 0x30, 0xC0, 0x60, 0x8C, 0x61, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x30, 0x80, 0x31, 0x86, 0x61, 0x8C, 0x61, 0x18, 0x63, 0x18, 0x03, 0x18, 0x80, 0x31, 0x06, 0x83, 0x01, 0x60, 0x0C, 0x66, 0x80, 0x81, 0x19, 0x8C, 0x31, 0x86, 0x61, 0x8C, 0x61, 0x18, 0x03, 0x03, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x1B, 0x18, 0xC0, 0x30, 0x60, 0x00, 0x60, 0x30, 0x06, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x06, 0x00, 0x03, 0x60, 0x18, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x03, 0x18, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x33, 0x98, 0x61, 0x9B, 0x6D, 0x18, 0x03, 0x06, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0xC3, 0x83, 0xC1, 0x0C, 0x06, 0x3C, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x33, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0xC0, 0x60, 0x03, 0x33, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x01, 0x60, 0x0C, 0x63, 0x80, 0xC3, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0xC1, 0x0C, 0x06, 0x03, 0x83, 0x19, 0x6C, 0x60, 0x8C, 0x31, 0x0C, 0xC0, 0x30, 0xC0, 0x00, 0x60, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x06, 0x00, 0x03, 0x60, 0x18, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0x31, 0x33, 0x67, 0x18, 0x03, 0x00, 0x30, 0x00, 0x83, 0x61, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x63, 0x83, 0xC1, 0x00, 0x06, 0x36, 0x03, 0x18, 0x00, 0x60, 0x06, 0x33, 0x18, 0x0C, 0x60, 0x00, 0x03, 0x00, 0xC0, 0xC0, 0x60, 0xE3, 0x33, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x01, 0x60, 0x8C, 0x61, 0x80, 0xE7, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0xC1, 0x0C, 0x00, 0x03, 0x83, 0x19, 0x6C, 0x60, 0x8C, 0x31, 0x0C, 0xC0, 0x30, 0xC0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xFE, 0x37, 0x03, 0x30, 0xB0, 0x01, 0x00, 0x18, 0x00, 0x06, 0x33, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x86, 0x03, 0x83, 0xC1, 0x00, 0x06, 0x33, 0x03, 0x18, 0x00, 0x30, 0x06, 0x33, 0x18, 0x0C, 0x60, 0x80, 0x01, 0xFF, 0x81, 0x01, 0x60, 0x33, 0x33, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x00, 0x06, 0x83, 0x01, 0x60, 0xCC, 0x60, 0x80, 0xBD, 0x39, 0xCC, 0x60, 0x06, 0x33, 0x98, 0xC1, 0x0C, 0x00, 0x03, 0x83, 0x19, 0x6C, 0x60, 0xD8, 0x60, 0x06, 0x60, 0x30, 0x80, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x87, 0x3F, 0xF0, 0x81, 0x3F, 0x7C, 0xF8, 0x07, 0x7F, 0xFE, 0xC0, 0x03, 0x78, 0x18, 0x06, 0x86, 0x7F, 0xF8, 0x03, 0x1F, 0xFE, 0xC0, 0x9F, 0xF9, 0xF8, 0xE3, 0x1F, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x33, 0x98, 0xFF, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0x31, 0x03, 0x30, 0xE0, 0x00, 0x00, 0x18, 0x00, 0x06, 0x1E, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC6, 0x03, 0x03, 0xC0, 0x00, 0x83, 0x31, 0x7F, 0xF8, 0x03, 0x30, 0x8C, 0x31, 0x18, 0x0C, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x30, 0x1B, 0x33, 0x98, 0x61, 0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x00, 0x06, 0x83, 0x01, 0x60, 0x6C, 0x60, 0x80, 0x99, 0x79, 0xCC, 0x60, 0x06, 0x33, 0x98, 0xC1, 0x18, 0x00, 0x03, 0x83, 0x31, 0x66, 0x60, 0xD8, 0x60, 0x06, 0x30, 0x30, 0x80, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x61, 0x18, 0xC3, 0x30, 0xC6, 0xC0, 0x80, 0x61, 0x86, 0x01, 0x03, 0x60, 0x18, 0x03, 0x86, 0xD9, 0x18, 0x86, 0x31, 0x86, 0x61, 0x98, 0x0D, 0x0C, 0x06, 0x03, 0x83, 0x19, 0x6C, 0x60, 0x06, 0x33, 0x18, 0xC0, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0x61, 0x03, 0x18, 0xF0, 0x00, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x66, 0x03, 0x03, 0x60, 0xE0, 0xC1, 0x30, 0xC0, 0x18, 0x06, 0x18, 0xF8, 0x30, 0x18, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x18, 0x1B, 0x33, 0x98, 0x3F, 0x0C, 0x60, 0x30, 0x7F, 0xF8, 0xC3, 0x00, 0xFE, 0x83, 0x01, 0x60, 0x3C, 0x60, 0x80, 0x81, 0xD9, 0xCC, 0x60, 0x86, 0x31, 0x98, 0x61, 0xF0, 0x01, 0x03, 0x83, 0x31, 0x66, 0x60, 0x70, 0xC0, 0x03, 0x18, 0x30, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x83, 0xC1, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0x98, 0x01, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x07, 0x0C, 0x00, 0x03, 0x83, 0x19, 0x6C, 0x60, 0x8C, 0x31, 0x18, 0x60, 0x38, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0xC1, 0x0F, 0x18, 0x98, 0x0D, 0x00, 0x18, 0x00, 0xC6, 0xFF, 0xFE, 0x07, 0x00, 0xFF, 0x01, 0x00, 0x06, 0x36, 0x03, 0x03, 0x30, 0x00, 0x63, 0x30, 0x80, 0x19, 0x0C, 0x18, 0x8C, 0x61, 0x18, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x0C, 0x1B, 0xF3, 0x9F, 0x61, 0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x7C, 0x06, 0x83, 0x01, 0x60, 0x3C, 0x60, 0x80, 0x81, 0x99, 0xCD, 0x60, 0xFE, 0x30, 0x98, 0x3F, 0x00, 0x03, 0x03, 0x83, 0x31, 0x66, 0x66, 0x70, 0xC0, 0x03, 0x0C, 0x30, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x83, 0xC1, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0xD8, 0x00, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x03, 0x0C, 0x00, 0x03, 0x83, 0x31, 0x66, 0x66, 0xD8, 0x30, 0x18, 0x30, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0x01, 0x1B, 0x0C, 0x0C, 0x0F, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1E, 0x03, 0x03, 0x18, 0x00, 0x66, 0x30, 0x80, 0x19, 0x0C, 0x0C, 0x06, 0xC3, 0x1F, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x1B, 0x33, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x01, 0x60, 0x6C, 0x60, 0x80, 0x81, 0x19, 0xCF, 0x60, 0x06, 0x30, 0x98, 0x07, 0x00, 0x06, 0x03, 0x83, 0x31, 0x66, 0x66, 0xD8, 0x80, 0x01, 0x06, 0x30, 0x00, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x9F, 0xC1, 0x0C, 0x60, 0x30, 0xFF, 0xC1, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0x78, 0x00, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x01, 0xF8, 0x03, 0x03, 0x83, 0x31, 0x66, 0x66, 0x70, 0x30, 0x18, 0x18, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x33, 0x0C, 0x0C, 0x06, 0x00, 0x18, 0x00, 0x06, 0x1E, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x03, 0x03, 0x0C, 0x00, 0x66, 0x30, 0x80, 0x19, 0x0C, 0x0C, 0x06, 0x03, 0x18, 0x00, 0x00, 0x80, 0x01, 0xFF, 0x81, 0x01, 0x00, 0x33, 0x33, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x81, 0x61, 0xCC, 0x60, 0x80, 0x81, 0x19, 0xCE, 0x60, 0x06, 0x30, 0x98, 0x0D, 0x00, 0x06, 0x03, 0x83, 0x61, 0x63, 0x6F, 0xD8, 0x80, 0x01, 0x03, 0x30, 0x00, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, 0xC0, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0x78, 0x00, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x01, 0x00, 0x06, 0x03, 0x83, 0x31, 0x66, 0x66, 0x70, 0x30, 0x18, 0x0C, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x33, 0xE6, 0x0C, 0x06, 0x00, 0x30, 0x00, 0x03, 0x33, 0x60, 0x00, 0x03, 0x00, 0x00, 0x80, 0x01, 0x06, 0x03, 0x03, 0x06, 0x00, 0xE6, 0x3F, 0x83, 0x19, 0x0C, 0x06, 0x06, 0x03, 0x18, 0x0C, 0x60, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x33, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x81, 0x61, 0x8C, 0x61, 0x80, 0x81, 0x19, 0xCC, 0x60, 0x06, 0x30, 0x98, 0x19, 0x00, 0x06, 0x03, 0x83, 0x61, 0xE3, 0x79, 0x8C, 0x81, 0x81, 0x01, 0x30, 0x00, 0x0C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0xC1, 0x0C, 0x60, 0x30, 0x03, 0xC0, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0xD8, 0x00, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x01, 0x00, 0x06, 0x03, 0x83, 0x61, 0x63, 0x66, 0xD8, 0x30, 0x18, 0x06, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0x31, 0x33, 0xB6, 0x0D, 0x06, 0x00, 0x30, 0x00, 0x83, 0x61, 0x60, 0x00, 0x03, 0x00, 0xC0, 0x80, 0x01, 0x06, 0x03, 0x03, 0x03, 0x0C, 0x06, 0x30, 0x83, 0x19, 0x0C, 0x06, 0x06, 0x03, 0x18, 0x0C, 0x60, 0x00, 0x06, 0x00, 0x60, 0x00, 0x0C, 0x03, 0x30, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, 0x18, 0xC0, 0x60, 0x06, 0x83, 0x81, 0x61, 0x0C, 0x63, 0x80, 0x81, 0x19, 0xCC, 0x60, 0x06, 0x30, 0x98, 0x31, 0x0C, 0x06, 0x03, 0x83, 0xC1, 0xE1, 0x70, 0x8C, 0x81, 0x81, 0x01, 0x30, 0x00, 0x0C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0xC1, 0x0C, 0x66, 0x30, 0x03, 0xC0, 0xC0, 0x60, 0x06, 0x03, 0x03, 0x60, 0x98, 0x01, 0x86, 0x99, 0x19, 0xCC, 0x60, 0x06, 0x33, 0x98, 0x01, 0x00, 0x06, 0x03, 0x83, 0x61, 0x63, 0x66, 0x8C, 0x31, 0x18, 0x03, 0x60, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0x61, 0x1B, 0xB3, 0x19, 0x0F, 0x00, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0xC0, 0xC0, 0x00, 0x8C, 0x01, 0x83, 0x01, 0x18, 0x03, 0x30, 0xC6, 0x30, 0x06, 0x06, 0x8C, 0x01, 0x0C, 0x0C, 0x60, 0x00, 0x0C, 0x00, 0x30, 0x00, 0x0C, 0x06, 0x30, 0x98, 0x61, 0x18, 0x63, 0x18, 0x03, 0x18, 0x80, 0x31, 0x06, 0x83, 0x01, 0x33, 0x0C, 0x66, 0x80, 0x81, 0x19, 0x8C, 0x31, 0x06, 0x60, 0x8F, 0x61, 0x18, 0x03, 0x03, 0xC6, 0xC0, 0x61, 0x60, 0x06, 0x83, 0x81, 0x01, 0x30, 0x00, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0x61, 0x18, 0xC3, 0x30, 0x86, 0xC1, 0x80, 0x61, 0x06, 0x03, 0x03, 0x60, 0x18, 0x03, 0x86, 0x99, 0x19, 0x8C, 0x31, 0x86, 0x61, 0x98, 0x01, 0x0C, 0x06, 0x03, 0x86, 0xC1, 0x61, 0x66, 0x06, 0x63, 0x98, 0x01, 0xC0, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x98, 0xC1, 0x0F, 0xE3, 0xF0, 0x0D, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xC0, 0xC0, 0x00, 0xF8, 0xE0, 0x9F, 0xFF, 0xF0, 0x01, 0x30, 0x7C, 0xE0, 0x03, 0x06, 0xF8, 0xE0, 0x07, 0x00, 0x60, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0C, 0xFC, 0x33, 0x98, 0x3F, 0xF0, 0xE1, 0x0F, 0xFF, 0x19, 0x00, 0x1F, 0x06, 0xE3, 0x07, 0x1E, 0x0C, 0xE6, 0xBF, 0x81, 0x19, 0x0C, 0x1F, 0x06, 0xC0, 0x87, 0xC1, 0xF0, 0x01, 0x03, 0x7C, 0xC0, 0x21, 0x40, 0x06, 0x83, 0x81, 0xFF, 0xF0, 0x01, 0x18, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x9F, 0x3F, 0xF0, 0x81, 0x3F, 0xFC, 0xC0, 0x00, 0x7F, 0x06, 0xC3, 0x0F, 0x60, 0x18, 0x86, 0x9F, 0x99, 0x19, 0x0C, 0x1F, 0xFE, 0xC0, 0x9F, 0x01, 0xF8, 0x03, 0x3E, 0xFC, 0xC1, 0xC1, 0x3F, 0x06, 0xC3, 0x9F, 0xFF, 0x80, 0x03, 0x03, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font24_width 1185 #define font24_height 24 static unsigned char font24_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x98, 0x81, 0x19, 0x60, 0x00, 0x00, 0x70, 0x00, 0x06, 0xC0, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x06, 0xF8, 0x81, 0x1F, 0x00, 0xE6, 0x7F, 0xF8, 0xE3, 0x7F, 0xF8, 0x81, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 0x80, 0x1F, 0xFC, 0x81, 0x1F, 0xFE, 0x81, 0x1F, 0xFE, 0xE1, 0x7F, 0xFE, 0x87, 0x1F, 0x06, 0x86, 0x1F, 0xC0, 0x6F, 0x60, 0x06, 0x10, 0x40, 0x06, 0x86, 0x1F, 0xFE, 0x81, 0x1F, 0xFE, 0x81, 0x1F, 0xFE, 0x67, 0x60, 0x06, 0x36, 0x60, 0x06, 0x66, 0x60, 0xFE, 0x87, 0x0F, 0x00, 0x80, 0x0F, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0xC0, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0xC3, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x60, 0xC0, 0x01, 0x66, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x98, 0x81, 0x19, 0xF8, 0xC1, 0x31, 0xD8, 0x00, 0x06, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0C, 0x03, 0x07, 0x0C, 0xC3, 0x30, 0x00, 0x67, 0x00, 0x0C, 0x60, 0x60, 0x0C, 0xC3, 0x30, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0C, 0xC0, 0x30, 0x06, 0xC3, 0x30, 0x06, 0xC3, 0x30, 0x06, 0x63, 0x00, 0x06, 0xC0, 0x30, 0x06, 0x06, 0x06, 0x00, 0x63, 0x30, 0x06, 0x30, 0x60, 0x06, 0xC6, 0x30, 0x06, 0xC3, 0x30, 0x06, 0xC3, 0x30, 0x60, 0x60, 0x60, 0x06, 0x36, 0x60, 0x06, 0x66, 0x60, 0x00, 0x86, 0x01, 0x0C, 0x00, 0x0C, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xC3, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x03, 0xC6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x98, 0x81, 0x19, 0x6C, 0x63, 0x33, 0x8C, 0x01, 0x06, 0x30, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x86, 0x07, 0x06, 0x66, 0x60, 0x80, 0x67, 0x00, 0x06, 0x60, 0x60, 0x06, 0x66, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x18, 0x60, 0x60, 0x03, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0x63, 0x18, 0x06, 0x70, 0x70, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x60, 0x60, 0x60, 0x06, 0x36, 0x60, 0x0C, 0xC3, 0x30, 0x00, 0x86, 0x01, 0x0C, 0x00, 0x0C, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xC3, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x66, 0x66, 0x1B, 0x8C, 0x01, 0x00, 0x30, 0x00, 0x06, 0x06, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0xC6, 0x06, 0x06, 0x06, 0x60, 0xC0, 0x66, 0x00, 0x06, 0x00, 0x60, 0x06, 0x66, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x60, 0x60, 0xC3, 0x67, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0x63, 0x0C, 0x06, 0xF0, 0x78, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x06, 0x36, 0x60, 0x0C, 0xC3, 0x30, 0x00, 0x86, 0x01, 0x18, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xE0, 0x7F, 0x66, 0xC0, 0x19, 0x8C, 0x01, 0x00, 0x18, 0x00, 0x0C, 0x8C, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x07, 0x06, 0x06, 0x06, 0x60, 0x60, 0x66, 0x00, 0x06, 0x00, 0x30, 0x06, 0x66, 0x60, 0x60, 0x00, 0x06, 0x30, 0x00, 0x00, 0x60, 0x60, 0x60, 0x63, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x00, 0x06, 0x06, 0x06, 0x00, 0x63, 0x06, 0x06, 0xB0, 0x6D, 0x0E, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x0C, 0x33, 0x60, 0x98, 0x81, 0x19, 0x00, 0x83, 0x01, 0x18, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0xFE, 0x81, 0x1F, 0xF8, 0x87, 0x1F, 0xFC, 0x83, 0x7F, 0xFE, 0x81, 0x07, 0xC0, 0xC3, 0x60, 0x60, 0xE0, 0x1F, 0xFE, 0x81, 0x1F, 0xFE, 0x81, 0x7F, 0xE6, 0xC7, 0x3F, 0xFE, 0x61, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0xFE, 0x07, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x66, 0x00, 0x0C, 0xD8, 0x00, 0x00, 0x18, 0x00, 0x0C, 0xD8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x86, 0x07, 0x06, 0x00, 0x06, 0x60, 0x30, 0x66, 0x00, 0x06, 0x00, 0x30, 0x06, 0x66, 0x60, 0x60, 0x00, 0x06, 0x18, 0xE0, 0x7F, 0xC0, 0x00, 0x30, 0x33, 0x66, 0x60, 0x06, 0x63, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x00, 0x06, 0x06, 0x06, 0x00, 0x63, 0x03, 0x06, 0x30, 0x67, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x0C, 0x33, 0x60, 0x98, 0x81, 0x19, 0x80, 0x81, 0x01, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0xC3, 0x30, 0x0C, 0xC6, 0x30, 0x60, 0xC0, 0x60, 0x06, 0x03, 0x06, 0x00, 0xC3, 0x30, 0x60, 0x60, 0x36, 0x06, 0xC3, 0x30, 0x06, 0xC3, 0x60, 0x36, 0x60, 0x60, 0x30, 0x60, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x00, 0x06, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x6C, 0x00, 0x0C, 0x70, 0x00, 0x00, 0x18, 0x00, 0x0C, 0x70, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC6, 0x06, 0x06, 0x00, 0x03, 0x30, 0x18, 0xE6, 0x1F, 0xFE, 0x01, 0x18, 0x0C, 0x63, 0x60, 0x60, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x80, 0x01, 0x18, 0x33, 0x66, 0x60, 0xFE, 0x61, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x00, 0x06, 0x06, 0x06, 0x00, 0xE3, 0x01, 0x06, 0x30, 0x62, 0x36, 0x66, 0x60, 0x06, 0x63, 0x60, 0x06, 0xC3, 0x00, 0x60, 0x60, 0x60, 0x0C, 0x33, 0x60, 0xF0, 0x00, 0x0F, 0xC0, 0x80, 0x01, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x18, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x1E, 0x60, 0x00, 0x30, 0x60, 0x60, 0x06, 0x66, 0x60, 0x0C, 0x63, 0x60, 0x00, 0x03, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0xF8, 0x01, 0x06, 0x78, 0x06, 0x00, 0x18, 0x00, 0x0C, 0xFF, 0xE7, 0x7F, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x06, 0x66, 0x06, 0x06, 0x80, 0x01, 0x1F, 0x0C, 0x06, 0x30, 0x06, 0x03, 0x18, 0xF8, 0xC1, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x33, 0x66, 0x60, 0x06, 0x63, 0x00, 0x06, 0xE6, 0x1F, 0xFE, 0x61, 0x7C, 0xFE, 0x07, 0x06, 0x00, 0xE3, 0x00, 0x06, 0x30, 0x60, 0x66, 0x66, 0x60, 0xFE, 0x61, 0x60, 0xFE, 0x81, 0x1F, 0x60, 0x60, 0x60, 0x0C, 0x33, 0x60, 0x60, 0x00, 0x0F, 0x60, 0x80, 0x01, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x60, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x0C, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x0E, 0x60, 0x00, 0x30, 0x60, 0x60, 0x0C, 0x63, 0x60, 0x98, 0x61, 0x60, 0x80, 0xC1, 0x01, 0x60, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x60, 0x03, 0x06, 0xCC, 0x06, 0x00, 0x18, 0x00, 0x0C, 0x70, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x36, 0x06, 0x06, 0xC0, 0x00, 0x30, 0x06, 0x06, 0x60, 0x06, 0x06, 0x0C, 0x0C, 0x83, 0x7F, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x80, 0x01, 0x06, 0x33, 0xE6, 0x7F, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xE3, 0x01, 0x06, 0x30, 0x60, 0xC6, 0x66, 0x60, 0x06, 0x60, 0x60, 0x1E, 0x00, 0x30, 0x60, 0x60, 0x60, 0x98, 0x31, 0x62, 0xF0, 0x00, 0x06, 0x30, 0x80, 0x01, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x06, 0x66, 0x00, 0x06, 0x66, 0x60, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x06, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x60, 0x00, 0x30, 0x60, 0x60, 0x0C, 0x63, 0x66, 0xF0, 0x60, 0x60, 0xC0, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x60, 0x06, 0x03, 0x86, 0x03, 0x00, 0x18, 0x00, 0x0C, 0xD8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1E, 0x06, 0x06, 0x60, 0x00, 0x60, 0x06, 0x06, 0x60, 0x06, 0x06, 0x0C, 0x06, 0x06, 0x60, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xC0, 0x00, 0x06, 0x33, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0x63, 0x03, 0x06, 0x30, 0x60, 0x86, 0x67, 0x60, 0x06, 0x60, 0x60, 0x36, 0x00, 0x60, 0x60, 0x60, 0x60, 0x98, 0x31, 0x67, 0x98, 0x01, 0x06, 0x18, 0x80, 0x01, 0xC0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x06, 0x66, 0x00, 0x06, 0xE6, 0x7F, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x03, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0xC0, 0x3F, 0x30, 0x60, 0x60, 0x98, 0x61, 0x66, 0x60, 0x60, 0x60, 0x60, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0x60, 0x06, 0x03, 0x06, 0x03, 0x00, 0x18, 0x00, 0x0C, 0x8C, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x06, 0x06, 0x30, 0x00, 0x60, 0x06, 0x06, 0x60, 0x06, 0x06, 0x06, 0x06, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0xE0, 0x7F, 0x60, 0x00, 0x00, 0x63, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x06, 0x63, 0x06, 0x06, 0x30, 0x60, 0x06, 0x67, 0x60, 0x06, 0x60, 0x60, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x98, 0xB1, 0x6D, 0x98, 0x01, 0x06, 0x0C, 0x80, 0x01, 0xC0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x06, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x00, 0x60, 0x30, 0x60, 0x60, 0x98, 0x61, 0x66, 0xF0, 0x60, 0x60, 0x30, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x19, 0x66, 0x86, 0x39, 0x06, 0x03, 0x00, 0x30, 0x00, 0x06, 0x06, 0x03, 0x06, 0x60, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x06, 0x06, 0x18, 0x00, 0x60, 0xFE, 0x07, 0x60, 0x06, 0x06, 0x06, 0x06, 0x06, 0x60, 0x60, 0x00, 0x06, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC3, 0x67, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x06, 0x63, 0x0C, 0x06, 0x30, 0x60, 0x06, 0x66, 0x60, 0x06, 0x60, 0x60, 0xC6, 0x00, 0x60, 0x60, 0x60, 0x60, 0xF0, 0xF0, 0x78, 0x0C, 0x03, 0x06, 0x06, 0x80, 0x01, 0x80, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x06, 0x66, 0x00, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x0C, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x00, 0x60, 0x30, 0x60, 0x60, 0xF0, 0x60, 0x66, 0x98, 0x61, 0x60, 0x18, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x6C, 0x83, 0x6D, 0x86, 0x03, 0x00, 0x30, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x80, 0x01, 0x06, 0x06, 0x06, 0x0C, 0x60, 0x60, 0x00, 0x66, 0x60, 0x06, 0x06, 0x06, 0x06, 0x06, 0x60, 0x60, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x18, 0x00, 0x06, 0x03, 0x60, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x06, 0x60, 0x60, 0x06, 0x06, 0x06, 0x06, 0x63, 0x18, 0x06, 0x30, 0x60, 0x06, 0x66, 0x60, 0x06, 0x60, 0x66, 0x86, 0x61, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x70, 0x70, 0x0C, 0x03, 0x06, 0x06, 0x80, 0x01, 0x80, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x18, 0x60, 0x60, 0x66, 0x06, 0x66, 0x60, 0x06, 0x66, 0x60, 0x06, 0x00, 0x60, 0x30, 0x60, 0x60, 0xF0, 0x60, 0x66, 0x0C, 0x63, 0x60, 0x0C, 0x00, 0x03, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0xF8, 0xC1, 0x6C, 0xCC, 0x06, 0x00, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0xC0, 0x00, 0x0C, 0x03, 0x06, 0x06, 0xC0, 0x30, 0x00, 0xC6, 0x30, 0x0C, 0x03, 0x06, 0x0C, 0x03, 0x30, 0x60, 0x00, 0x06, 0x80, 0x01, 0x00, 0x0C, 0x00, 0x06, 0x06, 0x60, 0x60, 0x06, 0xC3, 0x30, 0x06, 0x63, 0x00, 0x06, 0xC0, 0x30, 0x06, 0x06, 0x06, 0x8C, 0x61, 0x30, 0x06, 0x30, 0x60, 0x06, 0xC6, 0x30, 0x06, 0xC0, 0x3C, 0x06, 0xC3, 0x30, 0x60, 0xC0, 0x30, 0x60, 0x30, 0x60, 0x06, 0x06, 0x06, 0x06, 0x80, 0x01, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x06, 0xC3, 0x30, 0x0C, 0xC6, 0x60, 0x60, 0xC0, 0x70, 0x06, 0x06, 0x06, 0x00, 0xC3, 0x30, 0x60, 0x60, 0x66, 0x06, 0xC6, 0x30, 0x06, 0xC3, 0x60, 0x06, 0x60, 0x60, 0x30, 0xC0, 0x60, 0x60, 0x60, 0x66, 0x06, 0xC6, 0x70, 0x06, 0x00, 0x06, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x19, 0x60, 0xC0, 0x38, 0x78, 0x06, 0x00, 0xC0, 0x80, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0xC0, 0x00, 0xF8, 0xC1, 0x3F, 0xFE, 0x87, 0x1F, 0x00, 0x86, 0x1F, 0xF8, 0x01, 0x06, 0xF8, 0xC1, 0x1F, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0xFC, 0x67, 0x60, 0xFE, 0x81, 0x1F, 0xFE, 0xE1, 0x7F, 0x06, 0x80, 0x1F, 0x06, 0x86, 0x1F, 0xF8, 0x60, 0x60, 0xFE, 0x37, 0x60, 0x06, 0x86, 0x1F, 0x06, 0x80, 0x1F, 0x06, 0x86, 0x1F, 0x60, 0x80, 0x1F, 0x60, 0x10, 0x40, 0x06, 0x06, 0x06, 0xFE, 0x87, 0x0F, 0x00, 0x83, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0xFE, 0x81, 0x1F, 0xF8, 0x87, 0x3F, 0x60, 0x80, 0x7F, 0x06, 0x86, 0x1F, 0x00, 0xC3, 0x60, 0xF8, 0x61, 0x66, 0x06, 0x86, 0x1F, 0xFE, 0x81, 0x7F, 0x06, 0xC0, 0x3F, 0xE0, 0x83, 0x7F, 0x60, 0xC0, 0x3F, 0x06, 0x86, 0x7F, 0xFE, 0x07, 0x1C, 0x60, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font28_width 1383 #define font28_height 28 static unsigned char font28_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x31, 0x60, 0x0C, 0xC0, 0x00, 0x0F, 0x03, 0x0F, 0x00, 0x03, 0x80, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xF8, 0x03, 0x30, 0x80, 0x3F, 0xE0, 0x0F, 0x00, 0x8C, 0xFF, 0x83, 0x7F, 0xF8, 0x3F, 0xF8, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0xF8, 0x07, 0xFE, 0xE0, 0x3F, 0xE0, 0x0F, 0xFE, 0x80, 0xFF, 0xE3, 0xFF, 0xE0, 0x0F, 0x06, 0x0C, 0xFC, 0x00, 0xF8, 0x19, 0x30, 0x06, 0x80, 0x01, 0x66, 0xC0, 0xE0, 0x0F, 0xFE, 0x03, 0xFE, 0xE0, 0x3F, 0xE0, 0x0F, 0xFE, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x06, 0x8C, 0x01, 0xE6, 0xFF, 0xC0, 0x0F, 0x0C, 0x00, 0xFC, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x06, 0x00, 0x30, 0x00, 0x60, 0x30, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xC0, 0x00, 0x0E, 0x60, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x31, 0x60, 0x0C, 0xF8, 0x87, 0x1F, 0x83, 0x1F, 0x00, 0x03, 0xC0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFC, 0x07, 0x38, 0xC0, 0x7F, 0xF0, 0x1F, 0x00, 0x8E, 0xFF, 0xC3, 0x7F, 0xF8, 0x3F, 0xFC, 0x07, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0xF0, 0x1F, 0xFC, 0x0F, 0xFF, 0xE1, 0x7F, 0xF0, 0x1F, 0xFE, 0x83, 0xFF, 0xE3, 0xFF, 0xF0, 0x1F, 0x06, 0x0C, 0xFC, 0x00, 0xF8, 0x19, 0x38, 0x06, 0x80, 0x01, 0x66, 0xC0, 0xF0, 0x1F, 0xFE, 0x07, 0xFF, 0xE1, 0x7F, 0xF0, 0x1F, 0xFE, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x06, 0x8C, 0x01, 0xE6, 0xFF, 0xC0, 0x0F, 0x0C, 0x00, 0xFC, 0x80, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x06, 0x00, 0x30, 0x00, 0x60, 0x30, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x1E, 0x60, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x31, 0x60, 0x0C, 0xFC, 0x8F, 0x99, 0xC1, 0x39, 0x00, 0x03, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0E, 0x0E, 0x3C, 0xE0, 0xE0, 0x38, 0x38, 0x00, 0x8F, 0x01, 0xE0, 0x00, 0x18, 0x30, 0x0E, 0x8E, 0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x38, 0x38, 0x0E, 0x9C, 0x83, 0x63, 0xE0, 0x38, 0x38, 0x06, 0x87, 0x01, 0x60, 0x00, 0x38, 0x38, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x18, 0x1C, 0x06, 0x80, 0x03, 0x67, 0xC0, 0x38, 0x38, 0x06, 0x8E, 0x83, 0x63, 0xE0, 0x38, 0x38, 0xC0, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x0C, 0x06, 0x03, 0x03, 0xC0, 0xC0, 0x00, 0x18, 0x00, 0xC0, 0xC0, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x30, 0x00, 0x60, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xC0, 0x00, 0x38, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x31, 0x60, 0x0C, 0xCE, 0x9C, 0x9F, 0xC1, 0x30, 0x00, 0x03, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x0C, 0x3E, 0x60, 0xC0, 0x18, 0x30, 0x80, 0x8F, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x03, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x18, 0x30, 0x06, 0x98, 0x01, 0x63, 0xC0, 0x18, 0x30, 0x06, 0x86, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x18, 0x0E, 0x06, 0x80, 0x87, 0x67, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, 0x18, 0x30, 0xC0, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x0C, 0x06, 0x03, 0x03, 0xC0, 0xC0, 0x00, 0x18, 0x00, 0xC0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x3F, 0xC6, 0x18, 0xCF, 0xC0, 0x30, 0x00, 0x00, 0x30, 0x00, 0x60, 0xC0, 0x71, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x0E, 0x30, 0x60, 0xC0, 0x00, 0x30, 0xC0, 0x8D, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x07, 0x18, 0x30, 0x86, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x18, 0x07, 0x06, 0x80, 0xCF, 0xE7, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, 0x18, 0x00, 0xC0, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0x18, 0x03, 0x86, 0x01, 0xE0, 0xC0, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x3F, 0xC6, 0x00, 0xC0, 0xC0, 0x39, 0x00, 0x00, 0x30, 0x00, 0x60, 0x80, 0x3B, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x0F, 0x30, 0x60, 0xC0, 0x00, 0x30, 0xE0, 0x8C, 0x01, 0x60, 0x00, 0x00, 0x18, 0x06, 0x8C, 0x01, 0x03, 0x0C, 0x00, 0x03, 0xE0, 0x80, 0xFF, 0x03, 0x0E, 0x18, 0x30, 0xC6, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x98, 0x03, 0x06, 0x80, 0xFD, 0xE6, 0xC1, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, 0x18, 0x00, 0xC0, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0x18, 0x03, 0x86, 0x01, 0x70, 0xC0, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE0, 0x3F, 0xE0, 0x0F, 0xF8, 0x0F, 0xFE, 0xC0, 0x3F, 0xE0, 0x3F, 0xFE, 0x03, 0x3C, 0x00, 0x78, 0x30, 0x38, 0xC0, 0x80, 0xFF, 0xE1, 0x3F, 0xE0, 0x0F, 0xFE, 0x03, 0xFE, 0x63, 0xFE, 0xE0, 0x0F, 0xFC, 0x83, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x06, 0x8C, 0x01, 0xE3, 0xFF, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xC6, 0x00, 0x60, 0x80, 0x1F, 0x00, 0x00, 0x30, 0x00, 0x60, 0x00, 0x1F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x86, 0x0F, 0x30, 0x00, 0xC0, 0x00, 0x30, 0x70, 0x8C, 0x01, 0x60, 0x00, 0x00, 0x18, 0x06, 0x8C, 0x01, 0x03, 0x0C, 0x00, 0x03, 0x70, 0x80, 0xFF, 0x03, 0x1C, 0x00, 0x38, 0xE6, 0x98, 0x01, 0x63, 0x60, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xD8, 0x01, 0x06, 0x80, 0x79, 0xE6, 0xC3, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, 0x18, 0x00, 0xC0, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0xB0, 0x01, 0xCC, 0x00, 0x38, 0xC0, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE1, 0x7F, 0xF0, 0x1F, 0xFC, 0x0F, 0xFF, 0xC1, 0x3F, 0xF0, 0x3F, 0xFE, 0x07, 0x3C, 0x00, 0x78, 0x30, 0x1C, 0xC0, 0x80, 0xFF, 0xE3, 0x7F, 0xF0, 0x1F, 0xFE, 0x07, 0xFF, 0x63, 0xFF, 0xF0, 0x1F, 0xFC, 0x83, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x06, 0x8C, 0x01, 0xE3, 0xFF, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xCE, 0x00, 0x60, 0x00, 0x0F, 0x00, 0x00, 0x30, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xC6, 0x0D, 0x30, 0x00, 0xE0, 0x00, 0x38, 0x38, 0x8C, 0xFF, 0xE0, 0x3F, 0x00, 0x0C, 0x0E, 0x8E, 0x01, 0x03, 0x0C, 0x00, 0x03, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x1C, 0x66, 0x98, 0x01, 0xE3, 0x3F, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x00, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF8, 0x00, 0x06, 0x80, 0x31, 0x66, 0xC7, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0xC0, 0x38, 0x00, 0xC0, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0xB0, 0x01, 0xCC, 0x00, 0x1C, 0xC0, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x63, 0xE0, 0x38, 0x38, 0x0E, 0x8C, 0x83, 0x03, 0x06, 0x38, 0x30, 0x06, 0x0E, 0x30, 0x00, 0x60, 0x30, 0x0E, 0xC0, 0x80, 0x31, 0x67, 0xE0, 0x38, 0x38, 0x06, 0x8E, 0x03, 0xE3, 0x03, 0x38, 0x38, 0x60, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x60, 0x0E, 0x8E, 0x01, 0x03, 0xE0, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xFC, 0x07, 0x30, 0x00, 0x07, 0x00, 0x00, 0x30, 0x00, 0x60, 0xE0, 0xFF, 0xF8, 0x7F, 0x00, 0x80, 0xFF, 0x03, 0x00, 0x00, 0x03, 0xE6, 0x0C, 0x30, 0x00, 0x70, 0xC0, 0x1F, 0x1C, 0x8C, 0xFF, 0xE1, 0x7F, 0x00, 0x0C, 0xFC, 0x87, 0x03, 0x03, 0x0C, 0x00, 0x03, 0x1C, 0x00, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x66, 0x98, 0x01, 0xE3, 0x3F, 0x18, 0x00, 0x06, 0x8C, 0x7F, 0xE0, 0x1F, 0x18, 0x3F, 0xFE, 0x0F, 0x30, 0x00, 0x60, 0x78, 0x00, 0x06, 0x80, 0x01, 0x66, 0xCE, 0x18, 0x30, 0x06, 0x8E, 0x01, 0x63, 0xE0, 0xF0, 0x0F, 0xC0, 0x80, 0x01, 0x83, 0x31, 0x18, 0x60, 0xE0, 0x00, 0x78, 0x00, 0x0E, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x03, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x30, 0x07, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0xE3, 0x01, 0x18, 0x00, 0x60, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x60, 0x1C, 0x87, 0x01, 0x03, 0x70, 0xE0, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xF8, 0x0F, 0x30, 0x80, 0x8F, 0x01, 0x00, 0x30, 0x00, 0x60, 0xE0, 0xFF, 0xF8, 0x7F, 0x00, 0x80, 0xFF, 0x03, 0x00, 0x00, 0x03, 0x76, 0x0C, 0x30, 0x00, 0x38, 0xC0, 0x1F, 0x0E, 0x0C, 0x80, 0x63, 0xE0, 0x00, 0x06, 0xFC, 0x07, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x66, 0x98, 0xFF, 0x63, 0x60, 0x18, 0x00, 0x06, 0x8C, 0x7F, 0xE0, 0x1F, 0x18, 0x3F, 0xFE, 0x0F, 0x30, 0x00, 0x60, 0x78, 0x00, 0x06, 0x80, 0x01, 0x66, 0xDC, 0x18, 0x30, 0xFE, 0x87, 0x01, 0xE3, 0x7F, 0xE0, 0x1F, 0xC0, 0x80, 0x01, 0x83, 0x31, 0x18, 0x60, 0xE0, 0x00, 0x78, 0x00, 0x07, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x03, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xB0, 0x03, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0xE3, 0x00, 0x38, 0x00, 0x60, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x63, 0xB8, 0x83, 0x01, 0x03, 0x38, 0xE0, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xC0, 0x1C, 0x18, 0xC0, 0xDD, 0x01, 0x00, 0x30, 0x00, 0x60, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x3E, 0x0C, 0x30, 0x00, 0x1C, 0x00, 0x38, 0x06, 0x0C, 0x00, 0x63, 0xC0, 0x00, 0x06, 0x0E, 0x0E, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, 0x66, 0x98, 0xFF, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF8, 0x00, 0x06, 0x80, 0x01, 0x66, 0xF8, 0x18, 0x30, 0xFE, 0x83, 0x01, 0xE3, 0x3F, 0x00, 0x38, 0xC0, 0x80, 0x01, 0x83, 0x31, 0x18, 0x63, 0xB0, 0x01, 0x30, 0x80, 0x03, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0xFF, 0x03, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF0, 0x01, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0xF0, 0x0F, 0x60, 0x80, 0x01, 0xC3, 0x60, 0x18, 0x63, 0xF0, 0x81, 0x01, 0x03, 0x1C, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xC0, 0x18, 0x18, 0xE0, 0xF8, 0x00, 0x00, 0x30, 0x00, 0x60, 0x00, 0x1F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x1E, 0x0C, 0x30, 0x00, 0x0E, 0x00, 0x30, 0x06, 0x0C, 0x00, 0x63, 0xC0, 0x00, 0x03, 0x06, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x80, 0xFF, 0x03, 0x38, 0x00, 0x03, 0xE6, 0x98, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xD8, 0x01, 0x06, 0x80, 0x01, 0x66, 0xF0, 0x18, 0x30, 0x06, 0x80, 0x01, 0xE3, 0x03, 0x00, 0x30, 0xC0, 0x80, 0x01, 0x83, 0x31, 0x98, 0x67, 0xB0, 0x01, 0x30, 0xC0, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0xFF, 0x03, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF0, 0x00, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0xE0, 0x1F, 0x60, 0x80, 0x01, 0x83, 0x31, 0x18, 0x63, 0xE0, 0x80, 0x01, 0x03, 0x0E, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xC0, 0x18, 0x0C, 0x60, 0x70, 0x00, 0x00, 0x30, 0x00, 0x60, 0x80, 0x3B, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x0E, 0x0C, 0x30, 0x00, 0x07, 0x00, 0x30, 0xFE, 0x0F, 0x00, 0x63, 0xC0, 0x00, 0x03, 0x06, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x80, 0xFF, 0x03, 0x1C, 0x00, 0x00, 0xC6, 0x9F, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x60, 0x60, 0x98, 0x03, 0x06, 0x80, 0x01, 0x66, 0xE0, 0x18, 0x30, 0x06, 0x80, 0x01, 0x63, 0x07, 0x00, 0x30, 0xC0, 0x80, 0x01, 0x03, 0x1B, 0xD8, 0x6F, 0x18, 0x03, 0x30, 0xE0, 0x00, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x00, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xF0, 0x01, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0x00, 0x38, 0x60, 0x80, 0x01, 0x83, 0x31, 0x18, 0x63, 0xF0, 0x81, 0x01, 0x03, 0x07, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xC6, 0x18, 0xCC, 0x63, 0x70, 0x00, 0x00, 0x30, 0x00, 0x60, 0xC0, 0x71, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x06, 0x0C, 0x30, 0x80, 0x03, 0x00, 0x30, 0xFE, 0x0F, 0x00, 0x63, 0xC0, 0x00, 0x03, 0x06, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x86, 0x97, 0x01, 0x63, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x60, 0x60, 0x18, 0x07, 0x06, 0x80, 0x01, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x80, 0x01, 0x63, 0x0E, 0x00, 0x30, 0xC0, 0x80, 0x01, 0x03, 0x1B, 0xF8, 0x7C, 0x18, 0x03, 0x30, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x00, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0xB0, 0x03, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0x00, 0x30, 0x60, 0x80, 0x01, 0x83, 0x31, 0x18, 0x63, 0xB8, 0x83, 0x01, 0x83, 0x03, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xCE, 0x1C, 0xE6, 0x67, 0x70, 0x00, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x00, 0x06, 0x0C, 0x30, 0xC0, 0x01, 0x18, 0x30, 0x00, 0x8C, 0x01, 0x63, 0xC0, 0x00, 0x03, 0x06, 0x0C, 0x00, 0x03, 0x0C, 0x00, 0x03, 0xC0, 0x01, 0x00, 0x00, 0x07, 0x00, 0x03, 0x06, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x30, 0x06, 0x86, 0x01, 0x60, 0x00, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x60, 0x60, 0x18, 0x0E, 0x06, 0x80, 0x01, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x80, 0x71, 0x63, 0x1C, 0x18, 0x30, 0xC0, 0x80, 0x01, 0x03, 0x1B, 0x78, 0x78, 0x0C, 0x06, 0x30, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x63, 0xC0, 0x18, 0x00, 0x06, 0x8C, 0x01, 0x00, 0x06, 0x18, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x30, 0x07, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x18, 0x30, 0x06, 0x8C, 0x01, 0x63, 0x00, 0x00, 0x30, 0x60, 0x80, 0x01, 0x03, 0x1B, 0x18, 0x63, 0x1C, 0x87, 0x01, 0xC3, 0x01, 0x80, 0x01, 0xC0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xFC, 0x0F, 0x66, 0xE6, 0xF8, 0x00, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x00, 0x0E, 0x0E, 0x30, 0xE0, 0x00, 0x38, 0x38, 0x00, 0x8C, 0x83, 0xE3, 0xE0, 0x00, 0x03, 0x0E, 0x0E, 0x80, 0x03, 0x0C, 0x00, 0x03, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x03, 0x0E, 0x80, 0x01, 0x63, 0xE0, 0x38, 0x38, 0x06, 0x87, 0x01, 0x60, 0x00, 0x38, 0x38, 0x06, 0x0C, 0x30, 0xE0, 0x70, 0x18, 0x1C, 0x06, 0x80, 0x01, 0x66, 0xC0, 0x38, 0x38, 0x06, 0x80, 0xE3, 0x63, 0x38, 0x38, 0x38, 0xC0, 0x80, 0x83, 0x03, 0x0E, 0x38, 0x70, 0x0C, 0x06, 0x30, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x63, 0xE0, 0x38, 0x38, 0x0E, 0x8C, 0x83, 0x03, 0x06, 0x38, 0x30, 0x06, 0x0C, 0x30, 0x00, 0x60, 0x30, 0x0E, 0xC0, 0x80, 0x31, 0x66, 0xC0, 0x38, 0x38, 0x06, 0x8E, 0x03, 0x63, 0x00, 0x38, 0x38, 0x60, 0x80, 0x03, 0x03, 0x1B, 0x38, 0x73, 0x0E, 0x8E, 0x03, 0xE3, 0x00, 0x80, 0x03, 0xC0, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xF8, 0x07, 0xE3, 0xC7, 0xDF, 0x01, 0x00, 0xC0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x00, 0xFC, 0x07, 0xFE, 0xE1, 0xFF, 0xF0, 0x1F, 0x00, 0x0C, 0xFF, 0xC1, 0x7F, 0x00, 0x03, 0xFC, 0x07, 0xFF, 0x01, 0x0C, 0x00, 0x03, 0x00, 0x07, 0x00, 0xC0, 0x01, 0x00, 0x03, 0xFC, 0x9F, 0x01, 0xE3, 0x7F, 0xF0, 0x1F, 0xFE, 0x83, 0xFF, 0x63, 0x00, 0xF0, 0x1F, 0x06, 0x0C, 0xFC, 0xC0, 0x3F, 0x18, 0x38, 0xFE, 0x8F, 0x01, 0x66, 0xC0, 0xF0, 0x1F, 0x06, 0x00, 0xFF, 0x61, 0x70, 0xF0, 0x1F, 0xC0, 0x00, 0xFF, 0x01, 0x0E, 0x18, 0x60, 0x06, 0x0C, 0x30, 0xE0, 0xFF, 0xC0, 0x0F, 0x00, 0x0C, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE3, 0x7F, 0xF0, 0x1F, 0xFC, 0x0F, 0xFF, 0x01, 0x06, 0xF0, 0x3F, 0x06, 0x0C, 0xFC, 0x00, 0x60, 0x30, 0x1C, 0xF0, 0x83, 0x31, 0x66, 0xC0, 0xF0, 0x1F, 0xFE, 0x07, 0xFF, 0x63, 0x00, 0xF0, 0x1F, 0xE0, 0x07, 0xFF, 0x03, 0x0E, 0xF0, 0x3F, 0x06, 0x0C, 0xFF, 0xE3, 0xFF, 0x00, 0x0F, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x0C, 0xC0, 0x00, 0xC3, 0x83, 0x8F, 0x01, 0x00, 0x80, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x00, 0xF8, 0x03, 0xFE, 0xE1, 0xFF, 0xE0, 0x0F, 0x00, 0x0C, 0xFE, 0x80, 0x3F, 0x00, 0x03, 0xF8, 0x03, 0xFF, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0x00, 0x03, 0xF8, 0x9F, 0x01, 0xE3, 0x3F, 0xE0, 0x0F, 0xFE, 0x80, 0xFF, 0x63, 0x00, 0xE0, 0x0F, 0x06, 0x0C, 0xFC, 0x80, 0x1F, 0x18, 0x30, 0xFE, 0x8F, 0x01, 0x66, 0xC0, 0xE0, 0x0F, 0x06, 0x00, 0xFE, 0x61, 0xE0, 0xE0, 0x0F, 0xC0, 0x00, 0xFE, 0x00, 0x0E, 0x18, 0x60, 0x06, 0x0C, 0x30, 0xE0, 0xFF, 0xC0, 0x0F, 0x00, 0x0C, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE3, 0x3F, 0xE0, 0x0F, 0xF8, 0x0F, 0xFE, 0x00, 0x06, 0xE0, 0x3F, 0x06, 0x0C, 0xFC, 0x00, 0x60, 0x30, 0x38, 0xF0, 0x83, 0x31, 0x66, 0xC0, 0xE0, 0x0F, 0xFE, 0x03, 0xFE, 0x63, 0x00, 0xE0, 0x0F, 0xC0, 0x07, 0xFE, 0x03, 0x0E, 0xE0, 0x1F, 0x06, 0x0C, 0xFE, 0xE3, 0xFF, 0x00, 0x0E, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #define font32_width 1581 #define font32_height 32 static unsigned char font32_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, 0x38, 0x0E, 0xC0, 0x01, 0xF8, 0x38, 0xF0, 0x03, 0xC0, 0x01, 0x00, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xF8, 0x0F, 0xC0, 0x01, 0xF8, 0x0F, 0xF8, 0x0F, 0x00, 0x38, 0xFE, 0x3F, 0xF8, 0x1F, 0xFE, 0x3F, 0xF8, 0x0F, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0xF8, 0x0F, 0xF8, 0x1F, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x03, 0xFE, 0x3F, 0xFE, 0x3F, 0xF8, 0x0F, 0x0E, 0x38, 0xF0, 0x07, 0x00, 0x7F, 0x0E, 0x30, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x3F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0xFE, 0x3F, 0xF0, 0x0F, 0x1C, 0x00, 0xF0, 0x0F, 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xC0, 0x01, 0x7C, 0x00, 0xEE, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, 0x38, 0x0E, 0xF8, 0x0F, 0xFC, 0x39, 0xF8, 0x07, 0xC0, 0x01, 0x80, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xFC, 0x1F, 0xE0, 0x01, 0xFC, 0x1F, 0xFC, 0x1F, 0x00, 0x3C, 0xFE, 0x3F, 0xFC, 0x1F, 0xFE, 0x3F, 0xFC, 0x1F, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0xFC, 0x1F, 0xFC, 0x3F, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x0F, 0xFE, 0x3F, 0xFE, 0x3F, 0xFC, 0x1F, 0x0E, 0x38, 0xF0, 0x07, 0x00, 0x7F, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x3F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0xFE, 0x3F, 0xF0, 0x0F, 0x1C, 0x00, 0xF0, 0x0F, 0x38, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0xC0, 0x01, 0xFC, 0x00, 0xCE, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, 0x38, 0x0E, 0xFC, 0x1F, 0xDC, 0x1D, 0x1C, 0x0E, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1E, 0x3C, 0xF0, 0x01, 0x1E, 0x3C, 0x1E, 0x3C, 0x00, 0x3E, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x38, 0x1E, 0x3C, 0x1E, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x1E, 0x3C, 0x1E, 0x70, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x3C, 0x0E, 0x1E, 0x0E, 0x00, 0x0E, 0x00, 0x1E, 0x3C, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x0E, 0x1C, 0x0E, 0x00, 0x1E, 0x78, 0x0E, 0x38, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x3C, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x1C, 0x1C, 0x0E, 0x38, 0x00, 0x38, 0x70, 0x00, 0x38, 0x00, 0x00, 0x0E, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xE0, 0x01, 0x8E, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x0E, 0x38, 0x0E, 0xDE, 0x3D, 0xDC, 0x1D, 0x1C, 0x0E, 0xC0, 0x01, 0xE0, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0E, 0x38, 0xF8, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x3F, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x38, 0x0E, 0x60, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x0E, 0x0E, 0x0E, 0x00, 0x3E, 0x7C, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x38, 0x70, 0x00, 0x38, 0x00, 0x00, 0x0E, 0x0E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xCE, 0x39, 0xFC, 0x0F, 0x1C, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x80, 0x03, 0x1C, 0x1C, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x38, 0xF8, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0x80, 0x3B, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x8E, 0x7F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x0E, 0x07, 0x0E, 0x00, 0x7E, 0x7E, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x38, 0x0E, 0x1C, 0x1C, 0x00, 0x38, 0x70, 0x00, 0x70, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xFE, 0x3F, 0xCE, 0x01, 0xF8, 0x0E, 0x1C, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0x38, 0x0E, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x3C, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0xC0, 0x39, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x1C, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x03, 0x0E, 0x38, 0xCE, 0x7F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x8E, 0x03, 0x0E, 0x00, 0x7E, 0x7E, 0x1E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x1C, 0x70, 0x00, 0x70, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xFE, 0x3F, 0xCE, 0x01, 0x00, 0x07, 0x1C, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0x70, 0x07, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0E, 0x3E, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0xE0, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0xFE, 0x3F, 0x00, 0x07, 0x0E, 0x38, 0xEE, 0x71, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xCE, 0x01, 0x0E, 0x00, 0xEE, 0x77, 0x3E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0x70, 0x07, 0x38, 0x0E, 0x00, 0x0E, 0x70, 0x00, 0xE0, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0xFE, 0x0F, 0xF8, 0x0F, 0xF8, 0x3F, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8, 0x3F, 0xFE, 0x0F, 0xF0, 0x01, 0x00, 0x1F, 0x1C, 0x38, 0xC0, 0x01, 0xFE, 0x0F, 0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x3F, 0xCE, 0x3F, 0xF8, 0x0F, 0xFE, 0x0F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xFE, 0x3F, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xCE, 0x01, 0x00, 0x07, 0x38, 0x07, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0E, 0x3F, 0xC0, 0x01, 0x00, 0x38, 0x00, 0x38, 0x70, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0x70, 0x00, 0xFE, 0x3F, 0x00, 0x0E, 0x00, 0x1C, 0xEE, 0x70, 0x0E, 0x38, 0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xEE, 0x00, 0x0E, 0x00, 0xCE, 0x73, 0x7E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0x70, 0x07, 0x70, 0x07, 0x00, 0x07, 0x70, 0x00, 0xE0, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, 0xFC, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, 0xFE, 0x1F, 0xF0, 0x01, 0x00, 0x1F, 0x1C, 0x1C, 0xC0, 0x01, 0xFE, 0x1F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x3F, 0xEE, 0x3F, 0xFC, 0x1F, 0xFE, 0x0F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xFE, 0x3F, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xDE, 0x01, 0x80, 0x03, 0xF0, 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x8E, 0x3B, 0xC0, 0x01, 0x00, 0x1C, 0x00, 0x3C, 0x38, 0x38, 0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x0E, 0x1E, 0x3C, 0x0E, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x0E, 0xEE, 0x70, 0x0E, 0x38, 0xFE, 0x0F, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x7E, 0x00, 0x0E, 0x00, 0xCE, 0x73, 0xEE, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0xE0, 0x03, 0x70, 0x07, 0x80, 0x03, 0x70, 0x00, 0xC0, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x0E, 0x3C, 0x1E, 0x3C, 0x1E, 0x38, 0x1E, 0x3C, 0xC0, 0x01, 0x1E, 0x38, 0x0E, 0x3C, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x0E, 0xC0, 0x01, 0xCE, 0x3D, 0x0E, 0x3C, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x38, 0x7E, 0x00, 0x1E, 0x3C, 0xE0, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x00, 0x1C, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xFC, 0x0F, 0x80, 0x03, 0xF0, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xFE, 0x3F, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x80, 0x03, 0xCE, 0x39, 0xC0, 0x01, 0x00, 0x0E, 0xF0, 0x1F, 0x1C, 0x38, 0xFE, 0x1F, 0xFE, 0x1F, 0x00, 0x07, 0xFC, 0x1F, 0x1E, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x07, 0xEE, 0x70, 0x0E, 0x38, 0xFE, 0x0F, 0x0E, 0x00, 0x0E, 0x38, 0xFE, 0x07, 0xFE, 0x07, 0x8E, 0x3F, 0xFE, 0x3F, 0xC0, 0x01, 0x00, 0x1C, 0x3E, 0x00, 0x0E, 0x00, 0x8E, 0x71, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x3C, 0x0E, 0x38, 0x0E, 0x3C, 0xFC, 0x0F, 0xC0, 0x01, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x70, 0xE0, 0x03, 0xE0, 0x03, 0xC0, 0x01, 0x70, 0x00, 0xC0, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x07, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x3E, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x38, 0x00, 0x0E, 0x7C, 0x00, 0xC0, 0x01, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xF8, 0x1F, 0xC0, 0x01, 0xF8, 0x73, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xFE, 0x3F, 0xFE, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0xC0, 0x01, 0xEE, 0x38, 0xC0, 0x01, 0x00, 0x07, 0xF0, 0x1F, 0x0E, 0x38, 0x00, 0x3C, 0x0E, 0x3C, 0x00, 0x07, 0xFC, 0x1F, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x38, 0x80, 0x03, 0xEE, 0x70, 0xFE, 0x3F, 0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x38, 0xFE, 0x07, 0xFE, 0x07, 0x8E, 0x3F, 0xFE, 0x3F, 0xC0, 0x01, 0x00, 0x1C, 0x3E, 0x00, 0x0E, 0x00, 0x0E, 0x70, 0x8E, 0x3B, 0x0E, 0x38, 0xFE, 0x1F, 0x0E, 0x38, 0xFE, 0x1F, 0xF8, 0x1F, 0xC0, 0x01, 0x0E, 0x38, 0x38, 0x0E, 0x8E, 0x71, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x00, 0x70, 0x00, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x9C, 0x03, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1E, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0x0E, 0x38, 0x1C, 0x1C, 0xCE, 0x39, 0x38, 0x0E, 0x0E, 0x38, 0x00, 0x07, 0x7C, 0x00, 0xC0, 0x01, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xC0, 0x3D, 0xC0, 0x01, 0x1C, 0x77, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x7E, 0x38, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x3C, 0x0E, 0x38, 0x00, 0x38, 0x0E, 0x38, 0x80, 0x03, 0x1E, 0x3C, 0xF8, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xC0, 0x01, 0xEE, 0x70, 0xFE, 0x3F, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x7E, 0x00, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x3F, 0x0E, 0x38, 0xFE, 0x0F, 0x0E, 0x38, 0xFE, 0x0F, 0x00, 0x3C, 0xC0, 0x01, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x73, 0xE0, 0x03, 0xC0, 0x01, 0x70, 0x00, 0x70, 0x00, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xDC, 0x01, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x1E, 0x00, 0xE0, 0x00, 0x0E, 0x38, 0x1C, 0x1C, 0xCE, 0x39, 0x70, 0x07, 0x0E, 0x38, 0x80, 0x03, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xC0, 0x39, 0xE0, 0x00, 0x0E, 0x3E, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x3E, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x38, 0x0E, 0x38, 0x00, 0x38, 0x0E, 0x38, 0x80, 0x03, 0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xFE, 0x3F, 0x00, 0x0E, 0xC0, 0x01, 0xEE, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xEE, 0x00, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x3E, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x7E, 0x00, 0x00, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x73, 0x70, 0x07, 0xC0, 0x01, 0x38, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0xFE, 0x3F, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xFC, 0x00, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xFC, 0x0F, 0xE0, 0x00, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x39, 0xE0, 0x03, 0x0E, 0x38, 0xC0, 0x01, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0xC0, 0x39, 0xE0, 0x00, 0x0E, 0x1C, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0x70, 0x07, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x1E, 0x38, 0xC0, 0x01, 0xE0, 0x00, 0x00, 0x38, 0xFE, 0x3F, 0x00, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xFE, 0x3F, 0x00, 0x07, 0xC0, 0x01, 0xEE, 0x79, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xCE, 0x01, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x3C, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0xEE, 0x00, 0x00, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x38, 0x0E, 0xEE, 0x77, 0x70, 0x07, 0xC0, 0x01, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0xFE, 0x3F, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xFC, 0x00, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xF8, 0x1F, 0xE0, 0x00, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x39, 0xE0, 0x03, 0x0E, 0x38, 0xE0, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0xC0, 0x39, 0x70, 0x1F, 0x0E, 0x1C, 0x00, 0x00, 0x70, 0x00, 0x00, 0x07, 0x38, 0x0E, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x70, 0x00, 0x00, 0x38, 0xFE, 0x3F, 0x00, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0xCE, 0x7F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x1C, 0x8E, 0x03, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0xCE, 0x01, 0x00, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x70, 0x07, 0x7E, 0x7E, 0x38, 0x0E, 0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0xDC, 0x01, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x00, 0x3C, 0xE0, 0x00, 0x0E, 0x38, 0x38, 0x0E, 0xCE, 0x39, 0x70, 0x07, 0x0E, 0x38, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0xCE, 0x39, 0xF0, 0x3F, 0x0E, 0x1C, 0x00, 0x00, 0xE0, 0x00, 0x80, 0x03, 0x1C, 0x1C, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x38, 0x00, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x8E, 0x6F, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x1C, 0x0E, 0x07, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x8E, 0x03, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x70, 0x07, 0x7E, 0x7E, 0x38, 0x0E, 0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x9C, 0x03, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x0E, 0x38, 0x70, 0x07, 0xCE, 0x39, 0x38, 0x0E, 0x0E, 0x38, 0x38, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xDE, 0x3D, 0xB8, 0x3B, 0x0E, 0x1C, 0x00, 0x00, 0xE0, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x00, 0x0E, 0x38, 0xC0, 0x01, 0x1C, 0x00, 0x0E, 0x38, 0x00, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x00, 0x38, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x1C, 0x0E, 0x0E, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xCE, 0x39, 0x0E, 0x07, 0x0E, 0x38, 0xC0, 0x01, 0x0E, 0x38, 0x70, 0x07, 0x3E, 0x7C, 0x1C, 0x1C, 0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0xC0, 0x01, 0x0E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x07, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x0E, 0x38, 0x70, 0x07, 0xCE, 0x39, 0x1C, 0x1C, 0x0E, 0x38, 0x1C, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xFC, 0x1F, 0xB8, 0x3B, 0x1E, 0x3E, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x38, 0x00, 0x1E, 0x3C, 0xC0, 0x01, 0x0E, 0x00, 0x1E, 0x3C, 0x00, 0x38, 0x1E, 0x38, 0x1E, 0x3C, 0xC0, 0x01, 0x1E, 0x3C, 0x00, 0x3C, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x70, 0x00, 0xC0, 0x01, 0x1E, 0x00, 0x0E, 0x38, 0x0E, 0x3C, 0x1E, 0x3C, 0x0E, 0x1E, 0x0E, 0x00, 0x0E, 0x00, 0x1E, 0x3C, 0x0E, 0x38, 0xC0, 0x01, 0x1E, 0x1E, 0x0E, 0x1C, 0x0E, 0x00, 0x0E, 0x70, 0x0E, 0x38, 0x1E, 0x3C, 0x0E, 0x00, 0x9E, 0x3F, 0x0E, 0x0E, 0x1E, 0x3C, 0xC0, 0x01, 0x1E, 0x3C, 0xE0, 0x03, 0x1E, 0x78, 0x1C, 0x1C, 0xC0, 0x01, 0x0E, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x38, 0x0E, 0x3C, 0x1E, 0x3C, 0x1E, 0x38, 0x1E, 0x38, 0xC0, 0x01, 0x1E, 0x38, 0x0E, 0x38, 0xC0, 0x01, 0x00, 0x1C, 0x1C, 0x0E, 0xC0, 0x01, 0xCE, 0x39, 0x0E, 0x38, 0x1E, 0x3C, 0x0E, 0x3C, 0x1E, 0x38, 0x0E, 0x00, 0x1E, 0x3C, 0xE0, 0x01, 0x1E, 0x38, 0xE0, 0x03, 0xDE, 0x3D, 0x0E, 0x38, 0x1E, 0x38, 0x0E, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xF8, 0x0F, 0x9C, 0x3F, 0xFC, 0x77, 0x00, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x1C, 0x00, 0xFC, 0x1F, 0xF8, 0x0F, 0xFE, 0x3F, 0xFC, 0x1F, 0x00, 0x38, 0xFC, 0x1F, 0xFC, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xFC, 0x1F, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0xC0, 0x01, 0xFC, 0x7F, 0x0E, 0x38, 0xFE, 0x1F, 0xFC, 0x1F, 0xFE, 0x0F, 0xFE, 0x3F, 0x0E, 0x00, 0xFC, 0x1F, 0x0E, 0x38, 0xF0, 0x07, 0xFC, 0x0F, 0x0E, 0x38, 0xFE, 0x3F, 0x0E, 0x70, 0x0E, 0x38, 0xFC, 0x1F, 0x0E, 0x00, 0xFC, 0x1F, 0x0E, 0x1C, 0xFC, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xE0, 0x03, 0x0E, 0x70, 0x0E, 0x38, 0xC0, 0x01, 0xFE, 0x3F, 0xF0, 0x0F, 0x00, 0x38, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x3F, 0xFC, 0x3F, 0xC0, 0x01, 0xFC, 0x3F, 0x0E, 0x38, 0xF0, 0x07, 0x00, 0x1C, 0x1C, 0x1C, 0xF0, 0x07, 0xCE, 0x39, 0x0E, 0x38, 0xFC, 0x1F, 0xFE, 0x1F, 0xFC, 0x3F, 0x0E, 0x00, 0xFC, 0x1F, 0xC0, 0x3F, 0xFC, 0x3F, 0xE0, 0x03, 0xFC, 0x1F, 0x0E, 0x38, 0xFC, 0x3F, 0xFE, 0x3F, 0xC0, 0x0F, 0xC0, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x38, 0x0E, 0xC0, 0x01, 0x1C, 0x1F, 0xF8, 0x73, 0x00, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x1C, 0x00, 0xF8, 0x0F, 0xF8, 0x0F, 0xFE, 0x3F, 0xF8, 0x0F, 0x00, 0x38, 0xF8, 0x0F, 0xF8, 0x0F, 0xC0, 0x01, 0xF8, 0x0F, 0xFC, 0x0F, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0xC0, 0x01, 0xF8, 0x7F, 0x0E, 0x38, 0xFE, 0x0F, 0xF8, 0x0F, 0xFE, 0x03, 0xFE, 0x3F, 0x0E, 0x00, 0xF8, 0x0F, 0x0E, 0x38, 0xF0, 0x07, 0xF8, 0x07, 0x0E, 0x30, 0xFE, 0x3F, 0x0E, 0x70, 0x0E, 0x38, 0xF8, 0x0F, 0x0E, 0x00, 0xF8, 0x0F, 0x0E, 0x38, 0xF8, 0x0F, 0xC0, 0x01, 0xF8, 0x0F, 0xE0, 0x03, 0x0E, 0x70, 0x0E, 0x38, 0xC0, 0x01, 0xFE, 0x3F, 0xF0, 0x0F, 0x00, 0x38, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xFE, 0x0F, 0xF8, 0x0F, 0xF8, 0x3F, 0xF8, 0x1F, 0xC0, 0x01, 0xF8, 0x3F, 0x0E, 0x38, 0xF0, 0x07, 0x00, 0x1C, 0x1C, 0x38, 0xF0, 0x07, 0xCE, 0x39, 0x0E, 0x38, 0xF8, 0x0F, 0xFE, 0x0F, 0xF8, 0x3F, 0x0E, 0x00, 0xF8, 0x0F, 0x80, 0x3F, 0xF8, 0x3F, 0xE0, 0x03, 0xF8, 0x0F, 0x0E, 0x38, 0xF8, 0x3F, 0xFE, 0x3F, 0x80, 0x0F, 0xC0, 0x01, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; namespace netgen { class Font { // opengl display list index (-1 if not initialized) int list_base; // width and height of font in pixels int w; int h; // raw data to draw for opengl unsigned char *char_bitmaps; // size of one character in bitmap (in bytes) int char_length; int char_w; int char_h; // first and last+1 character in bitmap font static constexpr char char_first = ' '; static constexpr char char_next = '~'+1; void setBit( char c, int x, int y) { unsigned char *cbits = getCharBitmap(c); int offset = x/8+(h-1-y)*char_w; int bit_nr = 7-x%8; cbits[offset] |= 1UL<-1) glDeleteLists(list_base, char_next-char_first); delete[] char_bitmaps; } unsigned char *getCharBitmap(char c) { return char_bitmaps + (c-char_first)*char_length; } int getDisplayListsBase() { // already initialized if(list_base>-1) return list_base; list_base = glGenLists(char_next-char_first) - char_first; for (char c=char_first; c 1.5 } { # On some Linux systems, the scaling setting is only applied after # overwriting some default font settings. # This is a workaround to scale up fonts on high resolution displays. font create ngFont -family Helvetica option add *font ngFont ttk::style configure "." -font ngFont } # netgen menus: menu .ngmenu -tearoff 0 -relief raised -bd 2 . configure -menu .ngmenu .ngmenu add cascade -label "File" -menu .ngmenu.file -underline 0 .ngmenu add cascade -label "Geometry" -menu .ngmenu.geometry -underline 0 .ngmenu add cascade -label "Mesh" -menu .ngmenu.mesh -underline 0 .ngmenu add cascade -label "View" -menu .ngmenu.view -underline 0 .ngmenu add cascade -label "Refinement" -menu .ngmenu.meshsize -underline 5 if { $userlevel == 3} { .ngmenu add cascade -label "Special" -menu .ngmenu.special -underline 3 } .ngmenu add cascade -label "Help" -menu .ngmenu.help -underline 0 ##################################################### # # # Menu File # # # ##################################################### menu .ngmenu.file .ngmenu.file add command -label "Load Geometry..." -accelerator "" \ -command { set types { {"All Geometry types" { .stl .stlb .step .stp .geo .in2d .igs .iges .brep .sat} } {"IGES Geometry" {.igs .iges} } {"BREP OpenCascade Geometry" {.brep} } {"STL Geometry" {.stl} } {"Binary STL Geometry" {.stlb} } {"STEP Geometry" {.step .stp} } {"Geometry file" {.geo} } {"2D Geometry" {.in2d } } } set ACISavailable [Ng_ACISCommand isACISavailable] if {$ACISavailable == "yes" } { lappend types {"ACIS Geometry" {.sat} } } if {[catch { set file [tk_getOpenFile -filetypes $types -initialdir $dirname -typevariable loadgeomtypevar] }]} { set file [tk_getOpenFile -filetypes $types -initialdir $dirname] } if {$file != ""} { AddRecentFile $file Ng_LoadGeometry $file Ng_ParseGeometry # if { [Ng_STLInfo status]=="ERROR" } { # tk_messageBox -message "STL ERROR: \n [Ng_STLInfo statustext]" -type ok # } set selectvisual geometry Ng_SetVisParameters redraw wm title . [concat "$progname - " $file] set dirname [file dirname $file] set basefilename [file tail [file rootname $file]] if { $hasocc == "yes" } { rebuildoccdialog } } } .ngmenu.file add command -label "Save Geometry..." \ -command { set occgeometryloaded [Ng_OCCCommand isoccgeometryloaded] puts $occgeometryloaded if {$occgeometryloaded == 1 } { set types { {"IGES Geometry file" {.igs} } {"STEP Geometry file" {.stp} } {"STL Geometry file" {.stl} } {"STL BIN Geometry file" {.stlb} } } } { set types { {"STL Geometry file" {.stl} } {"STL BIN Geometry file" {.stlb} } } } set ACISavailable [Ng_ACISCommand isACISavailable] puts $ACISavailable if {$ACISavailable == "yes" } { lappend types {"ACIS Geometry" {.sat} } } set file [tk_getSaveFile -filetypes $types -initialdir $dirname -initialfile $basefilename ] if {$file != ""} { Ng_SaveGeometry $file } } .ngmenu.file add cascade -label "Recent Files" -menu .ngmenu.file.recent menu .ngmenu.file.recent -tearoff 0 proc AddRecentFile { filename } { global progname global dirname catch { [.ngmenu.file.recent delete $filename] } .ngmenu.file.recent insert 0 command -label $filename \ -command "AddRecentFile {$filename}; Ng_LoadGeometry {$filename}; Ng_ParseGeometry; set selectvisual geometry; Ng_SetVisParameters; redraw; wm title . [concat \" $progname - $filename \"]; set dirname {[file dirname $filename]}; set basefilename {[file tail [file rootname $filename]]}; rebuildoccdialog;" if { [.ngmenu.file.recent index last] >= 6 } { .ngmenu.file.recent delete last } saveinifile; } loadinifile; .ngmenu.file add separator .ngmenu.file add command -label "Load Mesh..." -accelerator "" \ -command { set types { {"Mesh file" {.vol .vol.gz} } } set file [tk_getOpenFile -filetypes $types -defaultextension ".vol"] if {$file != ""} { AddRecentMeshFile $file; Ng_LoadMesh $file; set selectvisual mesh Ng_SetVisParameters redraw Ng_ReadStatus; # Ng_MeshSizeFromSurfaceMesh wm title . [concat "$progname - " $file] set dirname [file dirname $file] set basefilename [file tail [file rootname $file]] } } # astrid .ngmenu.file add cascade -label "Recent Meshes" -menu .ngmenu.file.recentmesh menu .ngmenu.file.recentmesh proc AddRecentMeshFile { filename } { global progname global dirname catch { [.ngmenu.file.recentmesh delete $filename] } .ngmenu.file.recentmesh insert 0 command -label $filename \ -command "AddRecentMeshFile {$filename}; Ng_LoadMesh {$filename}; set selectvisual mesh; Ng_SetVisParameters; redraw; wm title . [concat \" $progname - $filename \"]; set dirname {[file dirname $filename]}; set basefilename {[file tail [file rootname $filename]]}; rebuildoccdialog;" if { [.ngmenu.file.recentmesh index last] >= 6 } { .ngmenu.file.recentmesh delete last } savemeshinifile; } loadmeshinifile; # astrid ende .ngmenu.file add command -label "Save Mesh..." -accelerator "" \ -command { set types { {"Mesh file" {.vol .vol.gz} } } set file [tk_getSaveFile -filetypes $types -defaultextension ".vol.gz" -initialfile $basefilename -initialdir $dirname ] if {$file != ""} { Ng_SaveMesh $file } AddRecentMeshFile $file; } .ngmenu.file add command -label "Merge Mesh..." \ -command { set types { {"Mesh file" {.vol} } } set file [tk_getOpenFile -filetypes $types -defaultextension ".vol"] if {$file != ""} { Ng_MergeMesh $file; set selectvisual mesh Ng_SetVisParameters redraw Ng_ReadStatus; } } .ngmenu.file add command -label "Import Mesh..." \ -command { set types { {"Neutral format" {.mesh .emt} } {"Surface mesh format" {.surf} } {"Universal format" {.unv} } {"Olaf format" {.emt} } {"TET format" {.tet} } {"Pro/ENGINEER neutral format" {.fnf} } } set file [tk_getOpenFile -filetypes $types ] if {$file != ""} { Ng_ImportMesh $file set selectvisual mesh Ng_SetVisParameters redraw Ng_ReadStatus; } } .ngmenu.file add command -label "Export Mesh..." \ -command { # global meshexportformats foreach exportformat $meshexportformats { if { [lindex $exportformat 0] == $exportfiletype } { set extension [lindex $exportformat 1] } } if { $exportfiletype == "Elmer Format"} { set file [file nativename [tk_chooseDirectory -title "Elmer Mesh Export - Select Directory"]] } elseif { $exportfiletype == "OpenFOAM 1.5+ Format"} { set file [file nativename [tk_chooseDirectory -title "OpenFOAM 1.5+ Mesh Export - Select Case Directory"]] } elseif { $exportfiletype == "OpenFOAM 1.5+ Compressed"} { set file [file nativename [tk_chooseDirectory -title "OpenFOAM 1.5+ Mesh Export - Select Case Directory"]] } else { # set file [tk_getSaveFile -filetypes "{ \"$exportfiletype\" {$extension} }" ] set file [tk_getSaveFile -filetypes "{ \"$exportfiletype\" {*}}" ] } if {$file != ""} { Ng_ExportMesh $file $exportfiletype } } .ngmenu.file add cascade -label "Export Filetype" -menu .ngmenu.file.filetype menu .ngmenu.file.filetype .ngmenu.file add separator .ngmenu.file add command -label "Save Solution..." \ -command { set types { {"Solution File" {.sol} } {"VTK File" {.vtk} } } set file [tk_getSaveFile -filetypes $types ] if {$file != ""} { Ng_SaveSolution $file } } #-defaultextension ".sol" ] .ngmenu.file add command -label "Import Solution..." \ -command { set types { {"Solution File" {.sol} } } set file [tk_getOpenFile -filetypes $types -defaultextension ".sol" ] if {$file != ""} { Ng_ImportSolution $file set selectvisual solution Ng_SetVisParameters redraw } } set demostarttime [clock clicks -millisecond] set stopdemo 0 proc demoredraw { } { global demostarttime global stopdemo set curtime [clock clicks -millisecond] set result [ Ng_DemoSetTime [expr $curtime - $demostarttime] ] redraw global videoactive if { $videoactive == 1 } { puts "addframe" Ng_VideoClip .ndraw addframe } if { $result == 0 && $stopdemo == 0 } { after 1 { demoredraw } } } .ngmenu.file add command -label "Show Demo..." \ -command { set types { {"Demo File" {.dem} } } set file [tk_getOpenFile -filetypes $types -defaultextension ".dem" ] if {$file != ""} { Ng_ShowDemo $file set demostarttime [clock clicks -millisecond] set stopdemo 0 demoredraw } } .ngmenu.file add separator .ngmenu.file add command -label "Snapshot..." \ -command { set types { {"JPG file" {.jpg} } {"GIF file" {.gif} } {"PPM file" {.ppm} } } set file [tk_getSaveFile -filetypes $types] # -defaultextension ".ppm"] if {$file != ""} { Ng_SnapShot .ndraw $file } } .ngmenu.file add cascade -label "Video clip" -menu .ngmenu.file.video menu .ngmenu.file.video set videoactive 0 .ngmenu.file.video add command -label "start..." \ -command { set types { {"MPG file" {.mpg} } } set file [tk_getSaveFile -filetypes $types] if {$file != ""} { Ng_VideoClip .ndraw init $file global videoactive set videoactive 1 } } .ngmenu.file.video add command -label "add frame..." \ -command {Ng_VideoClip .ndraw addframe } .ngmenu.file.video add command -label "one cycle" \ -command { set visoptions.redrawperiodic 1 for { set j 0 } { $j < 100 } { incr j } { puts "j = $j" Ng_Vis_Set time [expr (1000 * $j / 100)] redraw Ng_VideoClip .ndraw addframe after 200 } } .ngmenu.file.video add command -label "finalize..." \ -command { Ng_VideoClip .ndraw finalize global videoactive set videoactive 0 } .ngmenu.file add command -label "Save Options" \ -command { saveoptions } .ngmenu.file add separator ## herbert tcl load menu # .ngmenu.file add command -label "Run tests ..." \ \# -command { runtestdialog } ## # .ngmenu.file add separator .ngmenu.file add command -label "Quit" -accelerator "" \ -command { puts "Thank you for using $progname"; if { [catch { unload libngsolve[info sharedlibextension] ngsolve } result ] } { # puts "cannot unload ngsolve" # puts "error: $result" } after cancel { timer2 } Ng_Exit; destroy . } # exit ##################################################### # # # Menu Mesh # # # ##################################################### menu .ngmenu.mesh .ngmenu.mesh add command -label "Generate Mesh" -accelerator "" \ -command { set selectvisual mesh Ng_SetVisParameters Ng_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep} Ng_ReadStatus redraw } .ngmenu.mesh add command -label "Stop Meshing" \ -command { Ng_StopMeshing } .ngmenu.mesh add command -label "Meshing Options..." \ -command meshingoptionsdialog .ngmenu.mesh add separator .ngmenu.mesh add command -label "Delete Mesh" \ -command { Ng_New mesh; Ng_ReadStatus; redraw } .ngmenu.mesh add command -label "Delete Vol Mesh" \ -command { Ng_DeleteVolMesh; Ng_ReadStatus; redraw } .ngmenu.mesh add command -label "Mesh Info" \ -command { set dim [Ng_MeshInfo dim] set np [Ng_MeshInfo np] set ne [Ng_MeshInfo ne] set nse [Ng_MeshInfo nse] set nseg [Ng_MeshInfo nseg] set bbox [Ng_MeshInfo bbox] tk_messageBox -message "Dimension: $dim\nPoints: $np\nElements: $ne\nSurface Els: $nse\nSegments: $nseg\nxmin [lindex $bbox 0] xmax [lindex $bbox 1]\nymin [lindex $bbox 2] ymax [lindex $bbox 3]\nzmin [lindex $bbox 4] zmax [lindex $bbox 5]" } .ngmenu.mesh add command -label "Mesh Quality" \ -command { set inplanemin 0 set inplanemax 0 set betplanemin 0 set betplanemax 0 Ng_MeshQuality inplanemin inplanemax betplanemin betplanemax puts "Triangle angles : $inplanemin - $inplanemax" puts "Tet angles : $betplanemin - $betplanemax" tk_messageBox -message "Triangle angles : $inplanemin - $inplanemax \n Tet angles : $betplanemin - $betplanemax" } # .ngmenu.mesh add command -label "Quality Plot" \ # -command { qualityviewdialog 1 } .ngmenu.mesh add command -label "Check Surface Mesh" \ -command { Ng_CheckSurfaceMesh } .ngmenu.mesh add command -label "Check Volume Mesh" \ -command { Ng_CheckVolumeMesh } .ngmenu.mesh add command -label "Edit Boundary Conditions..." \ -command { bcpropdialog } if { $userlevel == 3 } { .ngmenu.mesh add command -label "Mesh Doctor..." \ -command { meshdoctordialog } } .ngmenu.mesh add command -label "METIS Mesh Partitioning..." \ -command { METISdialog } .ngmenu.mesh add separator .ngmenu.mesh add command -label "Analyze Geometry" \ -command { Ng_GenerateMesh ag ag; Ng_ReadStatus; redraw } .ngmenu.mesh add command -label "Mesh Edges" \ -command { Ng_GenerateMesh me me; Ng_ReadStatus; redraw } .ngmenu.mesh add command -label "Mesh Surface" \ -command { set selectvisual mesh; Ng_SetVisParameters; \ Ng_GenerateMesh ms ms; Ng_ReadStatus; redraw } .ngmenu.mesh add command -label "Optimize Surface" \ -command { Ng_GenerateMesh os os cmsmSm; redraw } .ngmenu.mesh add cascade -label "Surface Optim. Step" -menu .ngmenu.mesh.surfoptstep menu .ngmenu.mesh.surfoptstep .ngmenu.mesh.surfoptstep add command -label "Mesh Smoothing" \ -command { Ng_GenerateMesh os os m; redraw} .ngmenu.mesh.surfoptstep add command -label "Edge swapping (topologic)" \ -command { Ng_GenerateMesh os os s; redraw} .ngmenu.mesh.surfoptstep add command -label "Edge swapping (metric)" \ -command { Ng_GenerateMesh os os S; redraw} .ngmenu.mesh.surfoptstep add command -label "Combine points" \ -command { Ng_GenerateMesh os os c; redraw} .ngmenu.mesh add separator .ngmenu.mesh add command -label "Mesh Volume" \ -command { Ng_GenerateMesh mv mv; Ng_ReadStatus } .ngmenu.mesh add command -label "Optimize Volume" \ -command { Ng_GenerateMesh ov ov; Ng_ReadStatus } .ngmenu.mesh add command -label "Smooth Opt Volume" \ -command { Ng_GenerateMesh ov ov m; Ng_ReadStatus } .ngmenu.mesh add command -label "Smooth Opt Volume Jacobian" \ -command { Ng_GenerateMesh ov ov j; Ng_ReadStatus } ##################################################### # # # Menu Geometry # # # ##################################################### menu .ngmenu.geometry ##################################################### # # # Menu View # # # ##################################################### menu .ngmenu.view .ngmenu.view add command -label "Zoom all" \ -command { Ng_ZoomAll; redraw } .ngmenu.view add command -label "Center" \ -command { Ng_Center; redraw } .ngmenu.view add command -label "x-y plane" \ -command { Ng_StandardRotation xy; redraw } .ngmenu.view add command -label "y-x plane" \ -command { Ng_StandardRotation yx; redraw } .ngmenu.view add command -label "x-z plane" \ -command { Ng_StandardRotation xz; redraw } .ngmenu.view add command -label "z-x plane" \ -command { Ng_StandardRotation zx; redraw } .ngmenu.view add command -label "y-z plane" \ -command { Ng_StandardRotation yz; redraw } .ngmenu.view add command -label "z-y plane" \ -command { Ng_StandardRotation zy; redraw } .ngmenu.view add command -label "Viewing Options..." \ -command { viewingoptionsdialog; redraw } .ngmenu.view add command -label "Clipping Plane..." \ -command { clippingdialog; redraw } .ngmenu.view add command -label "Solution Data..." \ -command { visual_dialog; redraw } .ngmenu.view add checkbutton -variable viewqualityplot \ -label "Quality Plot" \ -command { qualityviewdialog $viewqualityplot } .ngmenu.view add checkbutton -variable memuseplot \ -label "Memory Usage" \ -command { memusedialog $memuseplot } ##################################################### # # # Menu Refinement # # # ##################################################### # # Mesh size menu # menu .ngmenu.meshsize .ngmenu.meshsize add command -label "Refine uniform" \ -command { Ng_Refine; Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw } .ngmenu.meshsize add command -label "Second Order" \ -command { Ng_SecondOrder; Ng_ReadStatus; redraw } .ngmenu.meshsize add command -label "Validate Second Order" \ -command { Ng_ValidateSecondOrder; Ng_ReadStatus; redraw } .ngmenu.meshsize add command -label "High Order" \ -command { Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw } .ngmenu.meshsize add separator .ngmenu.meshsize add command -label "Refinement Dialog..." \ -command { refinementdialog } .ngmenu.meshsize add command -label "Load Meshsize..." \ -command { set types { {"Meshsize file" {.msz} } } set file [tk_getOpenFile -filetypes $types] if {$file != ""} { Ng_LoadMeshSize $file; } } .ngmenu.meshsize add command -label "MS from Surf Mesh" \ -command { Ng_MeshSizeFromSurfaceMesh } if { $userlevel == 3 } { .ngmenu.meshsize add command -label "Singular point ms" \ -command { Ng_SingularPointMS; } .ngmenu.meshsize add command -label "Singular edge ms" \ -command { Ng_SingularEdgeMS; } .ngmenu.meshsize add separator set bisectfilename ""; .ngmenu.meshsize add command -label "Bisection" \ -command { Ng_ReadStatus; set oldnp 0; set newnp $status_np; # Ng_BisectCopyMesh; # Ng_Split2Tets; Ng_ReadStatus; while { $oldnp < $newnp } { # if { $level == 0 } { # Ng_ExportMesh feppmesh.vol fepp; # } { # Ng_ExportMesh feppmesh$level feppml # } set level [expr $level+1] if { $bisectfilename == ""} { Ng_Bisect; } else { Ng_Bisect $bisectfilename; } # Ng_HighOrder ${options.elementorder} "noparallel" # Ng_Split2Tets; Ng_ReadStatus; redraw; if { $bisectfilename == ""} { set oldnp $newnp; set newnp $status_np; puts "oldnp $oldnp newnp $newnp"; } else { set oldnp $newnp; } } } # -command { Ng_Bisect; Ng_ReadStatus; redraw } # -command { exec netgen abc >outfile 2>errfile; Ng_ReadStatus; redraw } } .ngmenu.meshsize add command -label "Load Refinement Info..." \ -command { set types { {"Refinement info" {.refine} }} set bisectfilename [tk_getOpenFile -filetypes $types] } .ngmenu.meshsize add command -label "Z-Refinement" \ -command { Ng_ZRefinement 2; Ng_ReadStatus; redraw } # .ngmenu.meshsize add command -label "hp-Refinement" \ \# -command { Ng_HPRefinement 4; Ng_ReadStatus; redraw } .ngmenu.meshsize add cascade -label "hp-Refinement" -menu .ngmenu.meshsize.hpref menu .ngmenu.meshsize.hpref .ngmenu.meshsize.hpref add command -label "1 Level" \ -command { Ng_HPRefinement 1; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "2 Levels" \ -command { Ng_HPRefinement 2; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "3 Levels" \ -command { Ng_HPRefinement 3; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "4 Levels" \ -command { Ng_HPRefinement 4; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "5 Levels" \ -command { Ng_HPRefinement 5; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "6 Levels" \ -command { Ng_HPRefinement 6; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "7 Levels" \ -command { Ng_HPRefinement 7; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "8 Levels" \ -command { Ng_HPRefinement 8; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "9 Levels" \ -command { Ng_HPRefinement 9; Ng_ReadStatus; redraw } .ngmenu.meshsize.hpref add command -label "10 Levels" \ -command { Ng_HPRefinement 10; Ng_ReadStatus; redraw } .ngmenu.meshsize add command -label "Split to Tets" \ -command { Ng_Split2Tets; Ng_ReadStatus; redraw } ##################################################### # # # Menu Special # # # ##################################################### menu .ngmenu.special .ngmenu.special add command -label "Prismatic Boundary Layer" \ -command { Ng_GenerateBoundaryLayer; redraw } .ngmenu.special add command -label "Insert virtual boundary layer" \ -command { Ng_InsertVirtualBL; redraw } .ngmenu.special add command -label "Cut off and combine with other" \ -command { set types { {"Mesh file" {.vol} } } set file [tk_getOpenFile -filetypes $types] if {$file != ""} { Ng_CutOffAndCombine $file; } redraw } .ngmenu.special add command -label "Helmholtz Mesh grading" \ -command { Ng_HelmholtzMesh; } .ngmenu.special add cascade -label "Colour-based boundary conditions" -menu .ngmenu.special.colbndcond menu .ngmenu.special.colbndcond .ngmenu.special.colbndcond add command -label "Inspect Colours in mesh" \ -command { currmeshcoloursdialog } .ngmenu.special.colbndcond add separator .ngmenu.special.colbndcond add command -label "Automatic Assignment" \ -command { Ng_AutoColourBcProps auto; redraw } .ngmenu.special.colbndcond add separator set ocffile [file join ${ngdir} netgen.ocf]; .ngmenu.special.colbndcond add command -label "Select Colour Profile file" \ -command { set types { {"Colour Profile file" {.ocf} } } set ocffile [tk_getOpenFile -filetypes $types] if {$ocffile == ""} { set ocffile [file join ${ngdir} netgen.ocf]; } } .ngmenu.special.colbndcond add command -label "Profile based Assignment" \ -command { Ng_AutoColourBcProps profile ${ocffile}; redraw } # menu .mbar.stl.menu # .mbar.stl.menu add command -label "STL options" \ # -command { stloptionsdialog; } #.mbar.stl.menu add command -label "STL Doctor" \ # -command { stldoctordialog; } ##################################################### # # # Menu Help # # # ##################################################### menu .ngmenu.help # .ngmenu.help add command -label "Ng Help..." \ \# -command { help_main } # .ngmenu.view add checkbutton -variable showsensitivehelp \ # -label "Sensitive Help" \ # -command { sensitivehelpdialog $showsensitivehelp } .ngmenu.view add checkbutton -label "Help Line" -variable showhelpline \ -command { if { $showhelpline == 1} { pack .helpline -before .statbar -side bottom -fill x -padx 3p } { pack forget .helpline } } .ngmenu.help add command -label "About..." \ -command { tk_messageBox -message "This is NETGEN \nmainly written by \nJoachim Schoeberl \nthanks to \nRobert Gaisbauer, Johannes Gerstmayr, Philippose Rajan" } # tk_menuBar .mbar .mbar.file .mbar.mesh .mbar.test .mbar.help # focus .mbar ##################################################### # # # Button bar # # # ##################################################### ttk::frame .bubar # -relief raised #-relief raised -bd 2 pack .bubar -side top -fill x ttk::button .bubar.testb -text "Test" -command { Ng_SaveGeometry } ttk::button .bubar.surfm -text "Generate Mesh" -command \ { .ngmenu.mesh invoke "Generate Mesh"; # set selectvisual mesh; # Ng_SetVisParameters; # Ng_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep} # redraw } ttk::button .bubar.stopm -text "Stop" -command \ { # Ng_StopMeshing; set multithread_terminate 1; set stopdemo 1; } ttk::button .bubar.exitb -text "Quit" \ -command { set ans [tk_messageBox -title "Quit Netgen?" -message "Do you really want to quit Netgen?" -type yesno -default "no" -icon question] if { $ans == "yes" } { .ngmenu.file invoke "Quit"; } } pack .bubar.exitb .bubar.surfm .bubar.stopm -side left #button .bubar.scan -text "Scan" \ # -command { Ng_ParseGeometry; set selectvisual geometry; Ng_SetVisParameters; redraw } ttk::button .bubar.zoomall -text "Zoom All" \ -command { Ng_ZoomAll; redraw } ttk::button .bubar.center -text "Center" \ -command { Ng_Center; redraw } # tk_optionMenu .bubar.modesel drawmode "rotate" "move " "zoom " # tixOptionMenu .bubar.modesel \ # -options { # label.width 0 # label.anchor e # menubutton.width 6 # } \ # -variable drawmode # .bubar.modesel add command rotate -label Rotate # .bubar.modesel add command move -label Move # .bubar.modesel add command zoom -label Zoom ttk::menubutton .bubar.modesel -menu .bubar.modesel.menu -text "" -width 6 menu .bubar.modesel.menu -tearoff 0 .bubar.modesel.menu add command -label "Rotate" -command "set drawmode \"rotate\" ;.bubar.modesel configure -text \"Rotate\"" .bubar.modesel.menu add command -label "Move" -command "set drawmode \"move\" ;.bubar.modesel configure -text \"Move\"" .bubar.modesel.menu add command -label "Zoom" -command "set drawmode \"zoom\" ;.bubar.modesel configure -text \"Zoom\"" .bubar.modesel.menu invoke "Rotate" set viewvals { geometry specpoints mesh solution} if { $userlevel == 3} { set viewvals { geometry mesh specpoints surfmeshing modelview solution} } set viewvallabs(cross) "Cross" set viewvallabs(geometry) "Geometry" set viewvallabs(mesh) "Mesh" set viewvallabs(specpoints) "Edges" set viewvallabs(surfmeshing) "Mesh Gen" set viewvallabs(modelview) "Modeller" set viewvallabs(solution) "Solution" # tixOptionMenu .bubar.selview \ # -options { # label.width 0 # label.anchor e # menubutton.width 10 # } \ # foreach viewv $viewvals { # .bubar.selview add command $viewv -label $viewvallabs($viewv) # } # .bubar.selview config -variable selectvisual # .bubar.selview config -command { Ng_SetVisParameters; redraw } # pack .bubar.modesel -side right # pack forget .bubar.modesel pack .bubar.center .bubar.zoomall -side right # pack .bubar.selview -side right .ngmenu.view add checkbutton -variable viewrotatebutton \ -label "Enable LeftButton Selection" \ -command { if { $viewrotatebutton } { pack .bubar.modesel -side right } { pack forget .bubar.modesel } } menu .bubar.selviewmenu ttk::menubutton .bubar.selview1 -menu .bubar.selviewmenu -text "Geometry" foreach viewv $viewvals { .bubar.selviewmenu add command -label $viewvallabs($viewv) -command \ ".bubar.selview1 configure -text \"$viewvallabs($viewv)\" ; set selectvisual $viewv ; Ng_SetVisParameters; redraw" } pack .bubar.selview1 -side right # .bubar.selviewmenu invoke $viewvallabs($selectvisual) trace add variable selectvisual write selvis_monitor proc selvis_monitor { name args } { global selectvisual viewvallabs .bubar.selviewmenu invoke $viewvallabs($selectvisual) } # set selectvisual solution ##################################################### # # # Status bar # # # ##################################################### ttk::label .helpline -text "None" pack forget .helpline -side bottom -fill x ttk::frame .statbar -relief flat # -bd 2 pack .statbar -side bottom -fill x ttk::label .statbar.ptslabel -text " Points: " ttk::label .statbar.ptsval -textvariable status_np ttk::label .statbar.elslabel -text " Elements: " ttk::label .statbar.elsval -textvariable status_ne ttk::label .statbar.selslabel -text " Surf Elements: " ttk::label .statbar.selsval -textvariable status_nse # label .statbar.memlabel -text " Mem: " # label .statbar.memval -textvariable mem_moveable ttk::label .statbar.task -textvariable status_task pack .statbar.ptslabel .statbar.ptsval -side left -ipady 3p pack .statbar.elslabel .statbar.elsval -side left -ipady 3p pack .statbar.selslabel .statbar.selsval -side left -ipady 3p # if { $userlevel == 3 } { # pack .statbar.memlabel .statbar.memval -side left -ipady 3p # } #tixMeter .statbar.per -value 0 -text 0% ttk::progressbar .statbar.per -value 0 -maximum 1 #.statbar.per configure -fillcolor blue pack .statbar.per -side right pack .statbar.task -side right -ipady 4 set qualbaraxis(0) 0 set qualbar(0) 0 set qualbarnull(0) 0 proc timer2 { } { global status_np global status_ne global status_nse global multithread_running global multithread_redraw global status_working global status_task global status_percent global status_tetqualclasses Ng_ReadStatus if { $multithread_redraw == 1 } { # non-blocking redraw set multithread_redraw 0; redraw; global videoactive if { $videoactive == 1 } { puts "addframe" Ng_VideoClip .ndraw addframe } } if { $multithread_redraw == 2 } { # blocking redraw redraw; set multithread_redraw 0; global videoactive if { $videoactive == 1 } { puts "addframe" Ng_VideoClip .ndraw addframe } after 1 { timer2 } return } # global mem_moveable # set mem_moveable [Ng_MemInfo moveable] .statbar.per configure -value [expr $status_percent/100] # -text [format %2.1f [expr 0.1*int(10*$status_percent)]]% if { $multithread_running } { pack .statbar.per -side right -before .statbar.task -padx 6 } { pack forget .statbar.per } # tet quality if {[winfo exists .qualityview_dlg] == 1} { global qualbar global qualbarnull global qualbaraxis set maxval 0 for {set i 0} {$i < 20} {incr i} { if {[lindex $status_tetqualclasses $i] > $maxval} { set maxval [lindex $status_tetqualclasses $i] } } set ubound 1 while { $ubound < $maxval } { set ubound [expr {10 * $ubound}] } if { $ubound/5 > $maxval } { set ubound [expr $ubound/5] } if { $ubound/2 > $maxval } { set ubound [expr $ubound/2] } for {set i 1} {$i <= 5} {incr i} { # global qualbaraxis($i) set value [expr { $i * $ubound / 5 }] .qualityview_dlg.c dchars $qualbaraxis($i) 0 end .qualityview_dlg.c insert $qualbaraxis($i) end $value } for {set i 0} {$i < 20} {incr i} { set x1 [expr {100 + ($i*15) + 2}] set x2 [expr {$x1+10}] set nbrs [lindex $status_tetqualclasses $i] set y [expr (249 - (200 * $nbrs / $ubound ) )] # global qualbar($i) .qualityview_dlg.c coords $qualbar($i) $x1 250 $x2 $y # global qualbarnull($i) if { $nbrs == 0 } { .qualityview_dlg.c itemconfigure $qualbarnull($i) -text 0 } { .qualityview_dlg.c itemconfigure $qualbarnull($i) -text "" } } } if {[winfo exists .memuse_dlg] == 1} { global memmark set usemb [Ng_MemInfo usedmb] for {set i 0} {$i < [string length $usemb] } {incr i} { if { [string index $usemb $i] == 0 } { .memuse_dlg.c coords $memmark($i) [expr 50+$i] 68 [expr 50+$i] 70 } { .memuse_dlg.c coords $memmark($i) [expr 50+$i] 50 [expr 50+$i] 70 } } } after 10 { timer2 } } # after 1000 { timer2 } timer2 proc bgerror { error } { global errorInfo userlevel if { $userlevel == 3} { puts "ERROR: $error" puts "errinfo: $errorInfo" } tk_messageBox -title "Error Message" -message $error -type ok } proc smh2 { menuitem } { if {[catch {$menuitem entrycget active -label} name]} { set name " " } show_menu_help $name update idletasks } bind .ngmenu <> { smh2 %W } bind .ngmenu.file <> { smh2 %W } bind .ngmenu.geometry <> { smh2 %W } bind .ngmenu.mesh <> { smh2 %W } bind .ngmenu.view <> { smh2 %W } bind .ngmenu.meshsize <> { smh2 %W } bind .ngmenu.special <> { smh2 %W } bind .ngmenu.help <> { smh2 %W } # command bindings bind . { .ngmenu.file invoke "Quit" } bind . { .ngmenu.file invoke "Load Geometry..." } ; bind . { .ngmenu.file invoke "Load Mesh..." } ; bind . { .ngmenu.file invoke "Save Mesh..." } ; bind . { .ngmenu.file activate "Recent Files" } ; bind .

{ newprimitivedialog } ; # bind .

{ editprimitivedialog } bind . { newsoliddialog } bind . { .ngmenu.mesh invoke "Generate Mesh" } ; netgen-6.2.1905/ng/csgeom.tcl0000644000175000017500000003636213504650527014400 0ustar kurtkurt.ngmenu.geometry add command -label "Scan CSG Geometry" -command { Ng_ParseGeometry } .ngmenu.geometry add command -label "CSG Options..." -command geometryoptionsdialog # only intern version ! # .ngmenu.geometry add separator # .ngmenu.geometry add command -label "New Primitive" \ # -command newprimitivedialog -accelerator "

" # .ngmenu.geometry add command -label "Edit Primitive" \ # -command editprimitivedialog -accelerator "

" # .ngmenu.geometry add command -label "Edit Solid" \ # -command newsoliddialog -accelerator "" # .ngmenu.geometry add command -label "Choose Top Level " \ # -command topleveldialog # .ngmenu.geometry add command -label "Identify" \ # -command identifydialog .ngmenu.geometry add command -label "CSG Properties..." \ -command topleveldialog2 proc geometryoptionsdialog { } { set w .geometry_dlg if {[winfo exists .geometry_dlg] == 1} { wm withdraw $w wm deiconify $w focus $w } { toplevel $w global geooptions Ng_GeometryOptions get checkbutton $w.drawcsg -text "Draw Geometry" \ -variable geooptions.drawcsg pack $w.drawcsg frame $w.fac pack $w.fac -pady 5 ttk::label $w.fac.lab -text "Facets:"; entry $w.fac.ent -width 8 -relief sunken \ -textvariable geooptions.facets pack $w.fac.lab $w.fac.ent -side left frame $w.det pack $w.det -pady 5 ttk::label $w.det.lab -text "Detail:"; entry $w.det.ent -width 8 -relief sunken \ -textvariable geooptions.detail pack $w.det.lab $w.det.ent -side left frame $w.cox pack $w.cox -pady 5 ttk::label $w.cox.lab -text "min/max x:"; entry $w.cox.ent1 -width 8 -relief sunken \ -textvariable geooptions.minx entry $w.cox.ent2 -width 8 -relief sunken \ -textvariable geooptions.maxx pack $w.cox.lab $w.cox.ent1 \ $w.cox.ent2 -side left frame $w.coy pack $w.coy -pady 5 ttk::label $w.coy.lab -text "min/max y:"; entry $w.coy.ent1 -width 8 -relief sunken \ -textvariable geooptions.miny entry $w.coy.ent2 -width 8 -relief sunken \ -textvariable geooptions.maxy pack $w.coy.lab $w.coy.ent1 \ $w.coy.ent2 -side left frame $w.coz pack $w.coz -pady 5 ttk::label $w.coz.lab -text "min/max z:"; entry $w.coz.ent1 -width 8 -relief sunken \ -textvariable geooptions.minz entry $w.coz.ent2 -width 8 -relief sunken \ -textvariable geooptions.maxz pack $w.coz.lab $w.coz.ent1 \ $w.coz.ent2 -side left # tixButtonBox $w.bbox -orientation horizontal # $w.bbox add ok -text Apply -underline 0 -width 5 \ # -command { Ng_GeometryOptions set } # $w.bbox add close -text Done -underline 0 -width 5 \ # -command { # Ng_GeometryOptions set # destroy .geometry_dlg # } # pack $w.bbox -side bottom -fill x frame $w.bu pack $w.bu -fill x -ipady 3 ttk::button $w.bu.app -text "Apply" -command { Ng_GeometryOptions set } ttk::button $w.bu.ok -text "Done" -command { Ng_GeometryOptions set destroy .geometry_dlg } pack $w.bu.app $w.bu.ok -side left -expand yes wm withdraw $w wm geom $w +100+100 wm deiconify $w wm title $w "Geometry options" focus $w } } # # # Edit primitive # # proc editprimitivedialog2 { name } { global w classname set w .ep_dlg toplevel .$w Ng_GetPrimitiveData $name classname valuelist ttk::label $w.lab1 -text "Primitive Name: $name"; ttk::label $w.lab2 -text "Primitive Class: $classname"; pack $w.lab1 $w.lab2 -fill x -pady 1m -padx 5m frame $w.specific -relief groove global spec set spec(sphere) { cx cy cz rad } set spec(cylinder) { ax ay az bx by bz rad } set spec(plane) { px py pz nx ny nz } set spec(cone) { ax ay az bx by bz ra rb } set spec(brick) { p1x p1y p1z p2x p2y p2z p3x p3y p3z p4x p4y p4z } set cnt 0 foreach field $spec($classname) { frame $w.specific.f$cnt pack $w.specific.f$cnt -side top -anchor ne ttk::label $w.specific.f$cnt.lab -text "$field" entry $w.specific.f$cnt.ent -textvariable dataval($cnt) \ -width 6 -relief sunken pack $w.specific.f$cnt.ent $w.specific.f$cnt.lab -side right $w.specific.f$cnt.ent delete 0 end $w.specific.f$cnt.ent insert 0 [lindex $valuelist $cnt] set cnt [expr $cnt + 1] } pack $w.specific ttk::button $w.cancel -text "cancel" -command { destroy $w } ttk::button $w.ok -text "ok" -command { set valuelist "" set cnt 0 foreach field $spec($classname) { lappend valuelist $dataval($cnt) set cnt [expr $cnt + 1] } Ng_SetPrimitiveData $name $valuelist destroy $w } pack $w.cancel $w.ok -side left -expand yes bind $w { $w.ok invoke} bind $w { $w.cancel invoke} wm withdraw $w wm geom $w +100+100 wm deiconify $w # grab $w focus $w.specific.f0.ent } # # # Select primitve to edit # # proc editprimitivedialog { } { global w set w .ep_dlg toplevel $w frame $w.frame -borderwidth 5m pack $w.frame -side top -expand yes -fill y listbox $w.frame.list -yscroll "$w.frame.scroll set" -setgrid 1 -height 12 scrollbar $w.frame.scroll -command "$w.frame.list yview" pack $w.frame.scroll -side right -fill y pack $w.frame.list -side left -expand 1 -fill both Ng_GetPrimitiveList primlist foreach el $primlist { $w.frame.list insert end $el } ttk::button $w.cancel -text "cancel" -command { destroy $w } ttk::button $w.ok -text "ok" -command { set name [.ep_dlg.frame.list get active] puts "name=($name)" destroy $w if { $name != "" } { editprimitivedialog2 $name } } bind $w { $w.cancel invoke } bind $w { $w.ok invoke } pack $w.cancel $w.ok -side left -expand yes wm withdraw $w wm geom $w +100+100 wm deiconify $w # grab $w focus $w.frame.list } # # # Create new primitive # # proc newprimitivedialog { } { global w name set w .ap_dlg toplevel $w set name "" frame $w.f1 pack $w.f1 -pady 2m ttk::label $w.f1.lab -text "Primitive Name: "; entry $w.f1.ent -width 5 -relief sunken \ -textvariable name pack $w.f1.lab $w.f1.ent -side left frame $w.frame -borderwidth .5c pack $w.frame -side top -expand yes -fill y listbox $w.frame.list -yscroll "$w.frame.scroll set" -setgrid 1 -height 8 scrollbar $w.frame.scroll -command "$w.frame.list yview" pack $w.frame.scroll -side right -fill y pack $w.frame.list -side left -expand 1 -fill both $w.frame.list insert 0 sphere cylinder plane cone brick $w.frame.list activate 0 ttk::button $w.ok -text "ok" -command { Ng_CreatePrimitive [$w.frame.list get active] $name destroy $w editprimitivedialog2 $name } ttk::button $w.cancel -text "cancel" -command { destroy $w } pack $w.cancel $w.ok -side left -expand yes -pady 2m bind $w { $w.cancel invoke } bind $w { $w.ok invoke } wm withdraw $w wm geom $w +100+100 wm deiconify $w # grab $w focus $w.f1.ent } proc newsoliddialog { } { global w name val sollist set w .ns_dlg toplevel $w set name "" frame $w.f1 ttk::label $w.f1.lab -text "Solid Name: "; entry $w.f1.ent -width 5 -relief sunken \ -textvariable name $w.f1.ent delete 0 end ttk::button $w.f1.getsel -text "Get Selected" -command { $w.f1.ent delete 0 end $w.f1.ent insert 0 [$w.f3.list get active] $w.bu.get invoke } pack $w.f1.getsel -side bottom pack $w.f1.ent $w.f1.lab -side right frame $w.f3 -borderwidth .5c listbox $w.f3.list -yscroll "$w.f3.scroll set" -setgrid 1 -height 12 scrollbar $w.f3.scroll -command "$w.f3.list yview" pack $w.f3.scroll -side right -fill y pack $w.f3.list -side left -expand 1 -fill both Ng_GetSolidList sollist foreach el $sollist { $w.f3.list insert end $el } frame $w.f2 ttk::label $w.f2.lab -text "Solid Description: "; pack $w.f2.lab entry $w.f2.ent -width 100 -relief sunken \ -textvariable val -xscrollcommand "$w.f2.scr set" scrollbar $w.f2.scr -relief sunken -orient horiz -command \ "$w.f2.ent xview" $w.f2.ent delete 0 end pack $w.f2.ent $w.f2.scr -fill x frame $w.bu ttk::button $w.bu.close -text "close" -command { destroy $w } ttk::button $w.bu.get -text "get data" -command { Ng_GetSolidData $name val } ttk::button $w.bu.set -text "set data" -command { Ng_SetSolidData $name $val } pack $w.bu.get $w.bu.set $w.bu.close -side left pack $w.bu -pady 5 -side bottom ;# buttons pack $w.f2 -pady 5 -side bottom ;# edit field pack $w.f1 -pady 5 -side left ;# name pack $w.f3 -side left -expand yes -fill y ;# listbox bind $w { $w.bu.close invoke } wm withdraw $w wm geom $w +100+100 wm deiconify $w # grab $w focus $w } # # Edit top level objects # # proc toplevelproperties { w solname surfname } { global properties Ng_TopLevel getprop $solname $surfname properties set w .tlprop_dlg if {[winfo exists $w] == 1} { wm withdraw $w wm deiconify $w focus $w } { toplevel $w ttk::label $w.lab1 -text "Red" scale $w.scale1 -orient horizontal -length 300 -from 0 -to 1 \ -resolution 0.01 -tickinterval 0.2 \ -command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable properties(red) ttk::label $w.lab2 -text "Green" scale $w.scale2 -orient horizontal -length 300 -from 0 -to 1 \ -resolution 0.01 -tickinterval 0.2 \ -command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable properties(green) ttk::label $w.lab3 -text "Blue" scale $w.scale3 -orient horizontal -length 300 -from 0 -to 1 \ -resolution 0.01 -tickinterval 0.2 \ -command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable properties(blue) pack $w.lab1 $w.scale1 $w.lab2 $w.scale2 $w.lab3 $w.scale3 checkbutton $w.cb4 -text "Visible" \ -command { Ng_TopLevel setprop $solname $surfname properties; redraw } \ -variable properties(visible) checkbutton $w.cb5 -text "Transparent" \ -command { Ng_TopLevel setprop $solname $surfname properties; redraw } \ -variable properties(transp) pack $w.cb4 $w.cb5 frame $w.bu pack $w.bu -fill x ttk::button $w.bu.ok -text "Ok" -command "destroy .tlprop_dlg" pack $w.bu.ok -expand yes wm withdraw $w wm geom $w +100+100 wm deiconify $w focus $w } wm title $w "Properties $solname $surfname" } proc topleveldialog { } { global w name val sollist set w .tl_dlg toplevel $w frame $w.sol -borderwidth .5c listbox $w.sol.list -yscroll "$w.sol.scroll set" -setgrid 1 -height 12 scrollbar $w.sol.scroll -command "$w.sol.list yview" pack $w.sol.scroll -side right -fill y pack $w.sol.list -side left -expand 1 -fill both Ng_GetSolidList sollist foreach el $sollist { $w.sol.list insert end $el } Ng_GetPrimitiveList sollist foreach el $sollist { $w.sol.list insert end $el } frame $w.sul -borderwidth .5c listbox $w.sul.list -yscroll "$w.sul.scroll set" -setgrid 1 -height 12 scrollbar $w.sul.scroll -command "$w.sul.list yview" pack $w.sul.scroll -side right -fill y pack $w.sul.list -side left -expand 1 -fill both Ng_GetSurfaceList sollist foreach el $sollist { $w.sul.list insert end $el } frame $w.topl -borderwidth .5c listbox $w.topl.list -yscroll "$w.topl.scroll set" -setgrid 1 -height 12 \ -command { puts hi } scrollbar $w.topl.scroll -command "$w.topl.list yview" pack $w.topl.scroll -side right -fill y pack $w.topl.list -side left -expand 1 -fill both Ng_TopLevel getlist sollist puts $sollist foreach el $sollist { set hel "[ lindex $el 0 ]" if { [ llength $el ] == 2 } { set hel "[ lindex $el 1 ] on [ lindex $el 0 ]" } $w.topl.list insert end $hel } frame $w.bu ttk::button $w.bu.close -text "close" -command { destroy $w } ttk::button $w.bu.addsol -text "Add Solid" -command { set solname [$w.sol.list get active] Ng_TopLevel set $solname "" Ng_ParseGeometry $w.topl.list insert end $solname } ttk::button $w.bu.addsurf -text "Add Surface" -command { set solname [$w.sol.list get active] set surfname [$w.sul.list get active] Ng_TopLevel set $solname $surfname Ng_ParseGeometry puts "$solname on $surfname" $w.topl.list insert end "$surfname on $solname" } ttk::button $w.bu.remsol -text "Remove" -command { set solname [$w.topl.list get active] set surfname "" if { [llength $solname] == 3 } { set surfname [lindex $solname 0] set solname [lindex $solname 2] } Ng_TopLevel remove $solname $surfname Ng_ParseGeometry $w.topl.list delete active } ttk::button $w.bu.prop -text "Properties" -command { set solname [$w.topl.list get active] set surfname "" if { [llength $solname] == 3 } { set surfname [lindex $solname 0] set solname [lindex $solname 2] } toplevelproperties tlp $solname $surfname } pack $w.bu.close $w.bu.addsol $w.bu.addsurf $w.bu.remsol $w.bu.prop -side left pack $w.bu -side bottom pack $w.sol -side left -expand yes -fill y ;# listbox pack $w.sul -side left -expand yes -fill y ;# listbox pack $w.topl -side left -expand yes -fill y ;# listbox bind $w { $w.bu.close invoke } wm withdraw $w wm geom $w +100+100 wm deiconify $w # grab $w focus $w } proc topleveldialog2 { } { set w .tl2_dlg if {[winfo exists .tl2_dlg] == 1} { wm withdraw $w wm deiconify $w focus $w } { toplevel $w global name val sollist frame $w.topl -borderwidth .5c listbox $w.topl.list -yscroll "$w.topl.scroll set" -setgrid 1 -height 12 scrollbar $w.topl.scroll -command "$w.topl.list yview" pack $w.topl.scroll -side right -fill y pack $w.topl.list -side left -expand 1 -fill both Ng_TopLevel getlist sollist puts $sollist set i 1 foreach el $sollist { set hel "$i: [ lindex $el 0 ]" if { [ llength $el ] == 2 } { set hel "$i: [ lindex $el 1 ] on [ lindex $el 0 ]" } incr i $w.topl.list insert end $hel } frame $w.bu ttk::button $w.bu.close -text "close" -command { destroy .tl2_dlg } ttk::button $w.bu.prop -text "Properties" -command { set solname [.tl2_dlg.topl.list get active] set surfname "" if { [llength $solname] == 2 } { set solname [lindex $solname 1] } if { [llength $solname] == 4 } { set surfname [lindex $solname 1] set solname [lindex $solname 3] } toplevelproperties tlp $solname $surfname } pack $w.bu.close $w.bu.prop -side left pack $w.bu -side bottom pack $w.topl -side left -expand yes -fill y ;# listbox bind .tl2_dlg.topl.list { set solname [.tl2_dlg.topl.list get @%x,%y] set surfname "" if { [llength $solname] == 2 } { set solname [lindex $solname 1] } if { [llength $solname] == 4 } { set surfname [lindex $solname 1] set solname [lindex $solname 3] } toplevelproperties tlp $solname $surfname } bind .tl2_dlg { .tl2_dlg.bu.close invoke } wm withdraw $w wm geom $w +100+100 wm deiconify $w wm title $w "Top-Level Options" focus $w } } netgen-6.2.1905/ng/drawing.tcl0000644000175000017500000001236413504650527014552 0ustar kurtkurt# # Creates a drawing frame, and binds mouse events # set oldmousex 0 set oldmousey 0 # # if { 1 } { # use this one for Togl 2.0 #if {[catch {togl .ndraw -width 400 -height 300 -rgba true -double true -depth true -privatecmap false -stereo false -indirect false }] } { # if {[catch {togl .ndraw -width 400 -height 300 -rgba true -double true -depth true -privatecmap false -stereo false -indirect false -create init -display draw -reshape reshape }] } { # puts "no OpenGL" # } { set toglversion [Ng_GetToglVersion] puts "togl-version : $toglversion" set toglok 0 if { [Ng_GetToglVersion] == 2 } { # Togl 2.x if {[catch {togl .ndraw -width 400 -height 300 -rgba true -double true -depth true -privatecmap false -stereo false -indirect false -create init -display draw -reshape reshape }] } { puts "no OpenGL" } { # puts "have Togl 2.1" set toglok 1 } } { # Togl 1.7 if {[catch {togl .ndraw -width 400 -height 300 -rgba true -double true -depth true -privatecmap false -stereo false -indirect false }] } { puts "no OpenGL" } { # puts "have Togl 1.7" set toglok 1 } } if { $toglok == 1} { # pack .ndraw -expand true -fill both -padx 10 -pady 10 catch { tkdnd::drop_target register .ndraw DND_Files } # bind .ndraw { set oldmousex %x; set oldmousey %y; } bind .ndraw { set oldmousex %x; set oldmousey %y; } bind .ndraw { set oldmousex %x; set oldmousey %y; } bind .ndraw { Ng_MouseMove $oldmousex $oldmousey %x %y $drawmode .ndraw render set oldmousex %x; set oldmousey %y; } bind .ndraw { Ng_MouseDblClick %x %y .ndraw render if { [winfo exists .bcprop_dlg] } { bcpropdialog } if { [winfo exists .surfacemeshsize_dlg] } { surfacemeshsizedialog } if { [winfo exists .fieldlines_dlg] } { fieldlinesdialog } } bind .ndraw { Ng_MouseMove $oldmousex $oldmousey %x %y move .ndraw render set oldmousex %x; set oldmousey %y; } bind .ndraw { if { $tcl_platform(os) == "Darwin" } { Ng_MouseMove $oldmousex $oldmousey %x %y move } { Ng_MouseMove $oldmousex $oldmousey %x %y zoom } .ndraw render set oldmousex %x; set oldmousey %y; } } proc popupcheckredraw { vari { x 0 } } { upvar $vari varname if { $varname == 1 } { set varname 0 } { # puts "popup-redraw $vari" Ng_Vis_Set parameters redraw } } proc popupcheckredraw2 { vari boolvar { x 0 } } { upvar $vari varname if { $varname == 1 } { set varname 0 } { Ng_SetVisParameters Ng_Vis_Set parameters if { $boolvar == 1 } { redraw } Ng_SetVisParameters } } proc popupcheckredraw3 { vari { x 0 } } { upvar $vari varname if { $varname == 1 } { set varname 0 } { Ng_Vis_Set parameters } } proc redraw { {x 0} } { if {[winfo exists .ndraw]} { .ndraw render } } bind . { Ng_MouseMove 0 0 -10 0 rotate; redraw } bind . { Ng_MouseMove 0 0 10 0 rotate; redraw } bind . { Ng_MouseMove 0 0 0 -10 rotate; redraw } bind . { Ng_MouseMove 0 0 0 10 rotate; redraw } bind . { Ng_MouseMove 0 0 -10 0 move; redraw } bind . { Ng_MouseMove 0 0 10 0 move; redraw } bind . { Ng_MouseMove 0 0 0 -10 move; redraw } bind . { Ng_MouseMove 0 0 0 10 move; redraw } bind . { Ng_MouseMove 0 0 0 -10 zoom; redraw } bind . { Ng_MouseMove 0 0 0 10 zoom; redraw } bind . \ {event generate [focus -displayof %W] -delta 120} bind . \ {event generate [focus -displayof %W] -delta -120} bind . { Ng_MouseMove 0 0 0 [expr {%D/-5}] zoom; redraw } # Drop callbacks: bind .ndraw <> { #tk_messageBox -message "Dropped files: \"[join %D {, }]\"" set filename [join %D " "] #%W state !active set index [string last . $filename] #tk_messageBox -message $index set type [string range $filename $index+1 end] # tk_messageBox -message $type set ispde [string match -nocase $type "pde"] set isgeo [expr max([string match -nocase $type "geo"],[string match -nocase $type "in2d"])] set ismesh [expr max([string match -nocase $type "vol"],[string match -nocase $type "vol.gz"])] set ispy [string match -nocase $type "py"] if {$ispde == 1} { AddRecentNGSFile $filename; NGS_LoadPDE $filename; SetNumProcHelpMenu set selectvisual mesh; Ng_SetVisParameters } if {$ispy == 1} { AddRecentPYNGSFile $filename; NGS_LoadPy $filename; } if {$isgeo == 1} { AddRecentFile $filename; Ng_LoadGeometry $filename; Ng_ParseGeometry set selectvisual geometry Ng_SetVisParameters redraw wm title . [concat "$progname - " $filename] set dirname [file dirname $filename] set basefilename [file tail [file rootname $filename]] } if {$ismesh == 1} { AddRecentMeshFile $filename; Ng_LoadMesh $filename; set selectvisual mesh Ng_SetVisParameters redraw Ng_ReadStatus; wm title . [concat "$progname - " %D] set dirname [file dirname %D] set basefilename [file tail [file rootname %D]] } return %A } netgen-6.2.1905/ng/ngappinit.cpp0000644000175000017500000002165313504650527015111 0ustar kurtkurt/* The main function of netgen. This file is a modification of tkAppInit.c from the Tcl/Tk package */ #include #include #include #ifdef PARALLEL #include extern void ParallelRun(); namespace netgen { MPI_Comm mesh_comm; } #endif #include "../libsrc/interface/writeuser.hpp" namespace netgen { DLL_HEADER extern Flags parameters; DLL_HEADER extern bool netgen_executable_started; } DLL_HEADER extern bool nodisplay; using netgen::parameters; using netgen::ngdir; using netgen::verbose; using netgen::Array; using netgen::RegisterUserFormats; /* * The following variable is a special hack that is needed in order for * Sun shared libraries to be used for Tcl. */ // extern "C" int matherr(); // int *tclDummyMathPtr = (int *) matherr; extern "C" int Ng_ServerSocketManagerInit (int port); extern "C" int Ng_ServerSocketManagerRun (void); bool shellmode = false; /* * * The Netgen main function * */ int main(int argc, char ** argv) { netgen::netgen_executable_started = true; #ifdef PARALLEL int mpi_required = MPI_THREAD_MULTIPLE; #ifdef VTRACE mpi_required = MPI_THREAD_SINGLE; #endif int mpi_provided; MPI_Init_thread(&argc, &argv, mpi_required, &mpi_provided); MPI_Comm_size(MPI_COMM_WORLD, &netgen::ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &netgen::id); if(netgen::ntasks!=1) throw ngcore::Exception("Netgen GUI cannot run MPI-parallel"); // MPI_COMM_WORLD is just a local communicator // netgen::ng_comm = ngcore::NgMPI_Comm{MPI_COMM_WORLD, false}; #endif if ( netgen::id == 0 ) { cout << "NETGEN-" << PACKAGE_VERSION << endl; cout << "Developed by Joachim Schoeberl at" << endl << "2010-xxxx Vienna University of Technology" << endl << "2006-2010 RWTH Aachen University" << endl << "1996-2006 Johannes Kepler University Linz" << endl; #ifdef OCCGEOMETRY cout << "Including OpenCascade geometry kernel" << endl; #endif #ifdef ACIS cout << "Including ACIS geometry kernel" << endl; #endif #ifdef LINUX //feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); //feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW); //cout << "Handle Floating Point Exceptions: " << fegetexcept() << endl; #endif #ifdef DEBUG cout << "You are running the debug version !" << endl; #endif #ifdef PARALLEL cout << "Including MPI version " << MPI_VERSION << '.' << MPI_SUBVERSION << endl; #endif } netgen::h_argc = argc; netgen::h_argv = argv; // command line arguments: for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') parameters.SetCommandLineFlag (argv[i]); else { if (strstr(argv[i], ".py")) parameters.SetFlag ("py", argv[i]); else parameters.SetFlag ("geofile", argv[i]); } } if (getenv ("NETGENDIR") && strlen (getenv ("NETGENDIR"))) ngdir = getenv ("NETGENDIR"); else ngdir = "."; verbose = parameters.GetDefineFlag ("V"); if (verbose) cout << "NETGENDIR = " << ngdir << endl; if ( netgen::id == 0 ) { if (parameters.StringFlagDefined ("testout")) { delete ngcore::testout; ngcore::testout = new ofstream (parameters.GetStringFlag ("testout", "test.out")); } #ifdef SOCKETS Ng_ServerSocketManagerInit(static_cast(parameters.GetNumFlag("serversocket",-1))); if(parameters.GetNumFlag("serversocket",-1) > 0 && !parameters.GetDefineFlag("display")) nodisplay = true; #endif if(parameters.GetDefineFlag("batchmode")) nodisplay = true; if(parameters.GetDefineFlag("shellmode")) { nodisplay = true; shellmode = true; } Tcl_FindExecutable(NULL); // initialize application Tcl_Interp * myinterp = Tcl_CreateInterp (); if (Tcl_AppInit (myinterp) == TCL_ERROR) { cerr << "Exit Netgen due to initialization problem" << endl; exit (1); } // parse tcl-script int errcode; bool internaltcl = INTERNAL_TCL_DEFAULT; if (shellmode) internaltcl = false; if (verbose) { cout << "Tcl header version = " << TCL_PATCH_LEVEL << endl; Tcl_Eval (myinterp, "puts \"Tcl runtime version = [info patchlevel] \";"); } if (parameters.GetDefineFlag ("internaltcl")) internaltcl=true; if (parameters.GetDefineFlag ("externaltcl")) internaltcl=false; if (internaltcl) { if (verbose) cout << "using internal Tcl-script" << endl; // connect to one string extern const char * ngscript[]; const char ** hcp = ngscript; int len = 0; while (*hcp) len += strlen (*hcp++); char * tr1 = new char[len+1]; *tr1 = 0; hcp = ngscript; char * tt1 = tr1; while (*hcp) { strcat (tt1, *hcp); tt1 += strlen (*hcp++); } errcode = Tcl_Eval (myinterp, tr1); delete [] tr1; } else { string startfile = ngdir + "/ng.tcl"; if (verbose) cout << "Load Tcl-script from " << startfile << endl; errcode = Tcl_EvalFile (myinterp, (char*)startfile.c_str()); } if (errcode) { cout << "Error in Tcl-Script:" << endl; // cout << "result = " << myinterp->result << endl; cout << "result = " << Tcl_GetStringResult (myinterp) << endl; // cout << "in line " << myinterp->errorLine << endl; cout << "\nMake sure to set environment variable NETGENDIR to directory containing ng.tcl" << endl; exit (1); } // lookup user file formats and insert into format list: Array userformats; Array extensions; RegisterUserFormats (userformats, extensions); ostringstream fstr; tcl_const char * exportft = Tcl_GetVar (myinterp, "exportfiletype", 0); for (int i = 1; i <= userformats.Size(); i++) { fstr << ".ngmenu.file.filetype add radio -label \"" << userformats.Get(i) << "\" -variable exportfiletype\n"; fstr << "lappend meshexportformats { {" << userformats.Get(i) << "} {" << extensions.Get(i) << "} }\n"; } Tcl_Eval (myinterp, (char*)fstr.str().c_str()); Tcl_SetVar (myinterp, "exportfiletype", exportft, 0); #ifdef SOCKETS Ng_ServerSocketManagerRun(); #endif // start event-loop Tk_MainLoop(); Tcl_DeleteInterp (myinterp); Tcl_Exit(0); } #ifdef PARALLEL else { ParallelRun(); MPI_Finalize(); } #endif return 0; } /* extern "C" int Tix_Init (Tcl_Interp * interp); extern "C" int Itcl_Init (Tcl_Interp * interp); extern "C" int Itk_Init (Tcl_Interp * interp); */ extern "C" int Ng_Init (Tcl_Interp * interp); extern "C" int Ng_Vis_Init (Tcl_Interp * interp); // extern Tcl_PackageInitProc * Tk_SafeInit; /* * * Initialize packages * */ // extern "C" int NGSolve_Init (Tcl_Interp * interp); int Tcl_AppInit(Tcl_Interp * interp) { if (Tcl_Init(interp) == TCL_ERROR) { cerr << "Problem in Tcl_Init: " << endl; cout << "result = " << Tcl_GetStringResult (interp) << endl; // cerr << interp->result << endl; // return TCL_ERROR; } if (!nodisplay && Tk_Init(interp) == TCL_ERROR) { cerr << "Problem in Tk_Init: " << endl; cout << "result = " << Tcl_GetStringResult (interp) << endl; // cerr << interp->result << endl; // return TCL_ERROR; } #ifdef TRAFO // extern int Trafo_Init (Tcl_Interp * interp); // if (Trafo_Init(interp) == TCL_ERROR) // { // cerr << "Problem in Trafo_Init: " << endl; // cerr << interp->result << endl; // return TCL_ERROR; // } #endif #ifdef EBGELAST extern int EBGElast_Init (Tcl_Interp * interp); if(EBGElast_Init(interp) == TCL_ERROR) { cerr << "Problem in EBGElast_Init: " << endl; cerr << interp->result << endl; return TCL_ERROR; } #endif #ifdef SMALLTRAFO extern int SmallModels_Init (Tcl_Interp * interp); if(SmallModels_Init(interp) == TCL_ERROR) { cerr << "Problem in SmallModel_Init: " << endl; cerr << interp->result << endl; return TCL_ERROR; } #endif #ifdef SOCKETS extern int Ng_Socket_Init (Tcl_Interp * interp); if ( Ng_Socket_Init(interp) == TCL_ERROR) { cerr << "Problem in Ng_Socket_Init: " << endl; cerr << interp->result << endl; return TCL_ERROR; } #endif #ifdef ZUGSTANGE extern int Zugstange_Init (Tcl_Interp * interp); if (Zugstange_Init(interp) == TCL_ERROR) { cerr << "Problem in Zugstange_Init: " << endl; cerr << interp->result << endl; return TCL_ERROR; } #endif Tcl_StaticPackage(interp, "Tk", Tk_Init, 0); return TCL_OK; } netgen-6.2.1905/ng/encoding.hpp0000644000175000017500000001601613504650527014710 0ustar kurtkurt#ifndef ENCODING_HPP_INCLUDED__ #define ENCODING_HPP_INCLUDED__ #ifdef FFMPEG extern "C" { #include #include #include #include #include #include #include #include #include } constexpr int BITRATE = 50000000; class Mpeg { private: bool is_started =false; int framerate = 25; AVOutputFormat *fmt; AVFormatContext *oc; AVStream *st; AVCodecContext *enc; AVFrame *frame; AVFrame *rgb_frame; uint8_t *rgb_buffer; struct SwsContext *sws_ctx; AVFrame *alloc_picture(enum AVPixelFormat pix_fmt) { AVFrame *picture; picture = av_frame_alloc(); if (!picture) return NULL; picture->format = pix_fmt; picture->width = width; picture->height = height; av_frame_get_buffer(picture, 32); return picture; } public: int width; int height; bool IsStarted() { return is_started; } int AddFrame() { int ret; int got_packet = 0; AVPacket pkt = { 0 }; glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb_buffer); av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, rgb_buffer, AV_PIX_FMT_RGB24, width, height, 1); if (av_frame_make_writable(frame) < 0) return 1; // The picture is upside down - flip it: auto data = rgb_frame->data[0] + 3*width*height; uint8_t *flipped_data[4] = { data, data, data, data }; int flipped_stride[4] = { -rgb_frame->linesize[0], -rgb_frame->linesize[1], -rgb_frame->linesize[2], -rgb_frame->linesize[3] }; sws_scale(sws_ctx, flipped_data, flipped_stride, 0, enc->height, frame->data, frame->linesize); av_init_packet(&pkt); got_packet = 0; ret = avcodec_send_frame(enc, frame); if (ret < 0) { cerr << "Error encoding video frame: " << endl; return(1); } ret = avcodec_receive_packet(enc, &pkt); if (!ret) got_packet = 1; if (ret == AVERROR(EAGAIN)) return 0; if (ret < 0) { cerr << "Error encoding video frame: " << endl; return 1; } if (got_packet) { /* rescale output packet timestamp values from codec to stream timebase */ av_packet_rescale_ts(&pkt, enc->time_base, st->time_base); pkt.stream_index = st->index; /* Write the compressed frame to the media file. */ ret = av_interleaved_write_frame(oc, &pkt); } else { ret = 0; } if (ret < 0) { cerr << "Error while writing video frame: " << endl; return(1); } return 0; } int Start(string filename) { AVCodec *video_codec; if(is_started) { cerr << "Stream already started" << endl; return 1; } is_started = true; GLint dims[4] = {0}; glGetIntegerv(GL_VIEWPORT, dims); width = dims[2]; height= dims[3]; width = int((width+1)/4)*4+4; height = 2 * (height/2); int ret; int i; av_register_all(); avformat_alloc_output_context2(&oc, NULL, NULL, filename.c_str()); // oc->preload= (int)(0.5*AV_TIME_BASE); oc->max_delay= (int)(0.7*AV_TIME_BASE); fmt = oc->oformat; if (fmt->video_codec != AV_CODEC_ID_NONE) { /* find the encoder */ video_codec = avcodec_find_encoder(fmt->video_codec); if (!(video_codec)) { cerr << "Could not find encoder for '" << avcodec_get_name(fmt->video_codec) << "'" << endl; return 1; } st = avformat_new_stream(oc, NULL); if (!st) { cerr << "Could not allocate stream\n"; return 1; } st->id = oc->nb_streams-1; enc = avcodec_alloc_context3(video_codec); if (!enc) { cerr << "Could not alloc an encoding context\n"; return 1; } enc->codec_id = fmt->video_codec; enc->bit_rate = BITRATE; enc->width = width; enc->height = height; AVRational tb; tb.num=1; tb.den=framerate; st->time_base = tb; enc->time_base = st->time_base; enc->gop_size = 200; enc->pix_fmt = AV_PIX_FMT_YUV420P; if (enc->codec_id == AV_CODEC_ID_MPEG2VIDEO) { enc->max_b_frames = 3; } if (enc->codec_id == AV_CODEC_ID_MPEG1VIDEO) { enc->mb_decision = 2; } if (oc->oformat->flags & AVFMT_GLOBALHEADER) enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // enc->flags |= CODEC_FLAG_QSCALE; // enc->global_quality = 1180; } else { cerr << "could not init codecs!" << endl; return 1; } AVDictionary *opt = NULL; /* open the codec */ ret = avcodec_open2(enc, video_codec, &opt); av_dict_free(&opt); if (ret < 0) { cerr << "Could not open video codec" << endl; return 1; } /* allocate and init a re-usable frame */ frame = alloc_picture(enc->pix_fmt); if (!frame) { cerr << "Could not allocate video frame\n"; return 1; } /* copy the stream parameters to the muxer */ ret = avcodec_parameters_from_context(st->codecpar, enc); if (ret < 0) { cerr << "Could not copy the stream parameters\n"; return 1; } av_dump_format(oc, 0, filename.c_str(), 1); if (!(fmt->flags & AVFMT_NOFILE)) { ret = avio_open(&oc->pb, filename.c_str(), AVIO_FLAG_WRITE); if (ret < 0) { cerr << "Could not open " << filename << " : " << endl; return 1; } } ret = avformat_write_header(oc, &opt); if (ret < 0) { cerr << "Error occurred when opening output file: " << endl;; return 1; } rgb_frame = alloc_picture(AV_PIX_FMT_RGB24); rgb_buffer = new uint8_t[width*height*4]; sws_ctx = sws_getContext( width, height, AV_PIX_FMT_RGB24, width, height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL ); } void Stop() { av_write_trailer(oc); avcodec_free_context(&enc); av_frame_free(&frame); sws_freeContext(sws_ctx); if (!(fmt->flags & AVFMT_NOFILE)) avio_closep(&oc->pb); avformat_free_context(oc); delete [] rgb_buffer; is_started = false; } }; #endif // FFMPEG #endif // ENCODING_HPP_INCLUDED__ netgen-6.2.1905/ng/ngicon.tcl0000644000175000017500000001000413504650527014361 0ustar kurtkurtset icon_data { /* XPM */ static char *icon2[] = { /* width height num_colors chars_per_pixel */ " 60 60 6 1", /* colors */ ". c #000000", "# c #008000", "a c #00b700", "b c #00c700", "c c #00ff00", "d s c None c None", /* pixels */ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "dddddddddddddddd..........dddddddddddddddddddddddddddddddddd", "ddddddddddddddd.c..cc#####................dddddddddddddddddd", "ddddddddddddd..cccc..ccccccccccccccccc...#...............ddd", "dddddddddddd.cccccccc..cccccccccccc...ccc..cccccccccc###..dd", "ddddddddddd.ccccccccccc..ccccccccc.cccccccc.ccccccccccc...dd", "dddddddddd.cccccccccccccc.cccccc..cccccccccc.ccccccccc.b..dd", "ddddddddd.cccccccccccccccc..ccc.ccccccccccccc..cccccc.bb..dd", "ddddddd........................cccccccccccccccc.cccc.bbb..dd", "dddddd.ccc.ccccccccccccccccc..#..............ccc.c..bbbb..dd", "dddd..ccccc..cccccccccccccc.#..##############.....bbbbb.b.dd", "ddd.ccccccccc..ccccccccccc.##.#.#################.bbbbb.b.dd", "dd.cccccccccccc..cccccccc.###.##.################.bbbbb.b.dd", "d..cccccccccccccc..ccccc.####.###.###############.bbbbb.b.dd", "d.a..............cc..cc.#####.####.##############.bbbb.bb.dd", "d..aaaaaaaaaaaaaa......######.#####.#############.bbbb.bb.dd", "d.a.aaaaaaaaaaaaaaaaa...#####.######..###########.bbbb.bb.dd", "d.aa.aaaaaaaaaaaaaaaa...#####.########.##########.bbbb.bb.dd", "d.aaa.aaaaaaaaaaaaaaa..#.####.#########.##########..b.bbb.dd", "d.aaaa.aaaaaaaaaaaaaa..#.####.##########.#########..b.bbb.dd", "d.aaaaa..aaaaaaaaaaaa..##.###.###########.########..b.bbb.dd", "d.aaaaaaa.aaaaaaaaaaa..###.###.###########.#######..b.bbb.dd", "d.aaaaaaaa.aaaaaaaaaa..###.###.############.######..b.bbb#.d", "d.aaaaaaaaa.aaaaaaaaa..####.##.#############.#####...bbbb#.d", "d.aaaaaaaaaa.aaaaaaaa..#####.#.##############.####...bbbb#.d", "d.aaaaaaaaaaa.aaaaaaa..#####.#.###############.###...bbbb#.d", "d.aaaaaaaaaaaa.aaaaaa..######..################.##...bbbb#.d", "d.aaaaaaaaaaaaa.aaaaaaa.#####..#################.#..bbbbb#.d", "d.aaaaaaaaaaaaaa.aaaaaa.#####.............#######...bbbbb#.d", "d.aaaaaaaaaaaaaaa.aaaaa.####.###.#########..........bbbbbb.d", "dd.aaaaaaaaaaaaaaa.aaaa.###.#####..##############...bbbbbb.d", "dd.aaaaaaaaaaaaaaaa.aaa.##.########.############.b...bbbbb.d", "dd.aaaaaaaaaaaaaaaaa.aa.#.##########...########.b.bbb.bbbb.d", "dd.aaaaaaaaaaaaaaaaaa....##############.######.bb.bbb.bbbb.d", "dd.aaaaaaaaaaaaaaaaaaaa...##############..###.bbb.bbbb.bbb.d", "dd.aaaaaaaaaaaaaaaaaa..a.a..............##.#.bbbb.bbbb.bbb.d", "dd.aaaaaaaaaaaaaaaaa.aaaa.aaaaaaaaaaaaaa....bbbb.bbbbbb.bb.d", "dd.aaaaaaaaaaaaaaaa.aaaaa.aaaaaaaaaaaaaaaaa.bbbb.bbbbbbb.b.d", "dd.aaaaaaaaaaaaaaa.aaaaaaa.aaaaaaaaaaaaaaaa.bbbb.bbbbbbb.b.d", "dd.aaaaaaaaaaaaaa.aaaaaaaaa.aaaaaaaaaaaaaaa.bbbb.bbbbbbbb..d", "dd.aaaaaaaaaaaaa.aaaaaaaaaaa.aaaaaaaaaaaaaa.bbb.bbbbbbbbb..d", "dd.aaaaaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaa.bbb.bbbbbbbbbb.d", "dd.aaaaaaaaaaa.aaaaaaaaaaaaaaa.aaaaaaaaaaaa.bbb.bbbbbbbbbb.d", "dd.aaaaaaaaaa.aaaaaaaaaaaaaaaaa.aaaaaaaaaaaa.bb.bbbbbbbbb.dd", "dd.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa.aaaaaaaaaaa.bb.bbbbbbbb.ddd", "dd.aaaaaaaa.aaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaa.b.bbbbbbbb.dddd", "dd.aaaaaaa.aaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaa.b.bbbbbbb.ddddd", "dd.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa.b.bbbbbb.dddddd", "dd.aaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa.b.bbbbb.ddddddd", "ddd.aa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaa..bbbb..dddddddd", "ddd.a.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaa..bbb.dddddddddd", "ddd..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaa..bb.ddddddddddd", "ddd........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aa..b.dddddddddddd", "ddddddddddd.............aaaaaaaaaaaaaaaaaa.a...ddddddddddddd", "dddddddddddddddddddddddd............aaaaaaa...dddddddddddddd", "dddddddddddddddddddddddddddddddddddd.........ddddddddddddddd", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" }; } netgen-6.2.1905/ng/parallelfunc.hpp0000644000175000017500000000035113504650527015565 0ustar kurtkurtdas braucht keiner mehr #ifndef FILE_PARALLELFUNC #define FILE_PARALLELFUNC void ParallelRun(); void LoadPDEParallel ( const char* filename ); #ifdef NGSOLVE // void NGS_ParallelRun ( const string & message); #endif #endif netgen-6.2.1905/ng/ng_acis.hpp0000644000175000017500000001247213504650527014527 0ustar kurtkurt#include #ifdef ACIS_R17 extern void unlock_spatial_products_661(); #endif namespace netgen { ACISGeometry * acisgeometry = NULL; static VisualSceneACISGeometry vsacisgeom; extern int ACISGenerateMesh (ACISGeometry & geometry, Mesh*& mesh, int perfstepsstart, int perfstepsend, char* optstring); int Ng_ACISCommand (ClientData /* clientData */, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { if (argc >= 2) { if (strcmp (argv[1], "isACISavailable") == 0) { Tcl_SetResult (interp, (char*)"yes", TCL_STATIC); return TCL_OK; } } if (!acisgeometry) { Tcl_SetResult (interp, (char*)"This operation needs an ACIS geometry", TCL_STATIC); return TCL_ERROR; } if (argc >= 2 && strcmp (argv[1], "getentities") == 0) { stringstream str; const ENTITY_LIST & entlist = acisgeometry -> entlist; ENTITY_LIST cellList; api_ct_get_all_cells( entlist, cellList ); for(int j=0; jattrib(); int k = 0; while (ap) { ATTRIB_GEN_INTEGER * aip = dynamic_cast(ap); if (aip) str << "cell" << j << "/attrib" << k << " { name = " << aip->name() << " val = " << aip->value() << "} \n"; else str << "cell" << j << "/attrib" << k << " { typename = " << ap->type_name() << "} \n"; ap = ap->next(); k++; } } for (int i = 0; i < entlist.count(); i++) { str << "entity" << i << " {Entity " << i << "} \n"; ENTITY_LIST faceList; ENTITY_LIST edgeList; api_get_faces_from_all_entities(entlist[i], faceList); for(int j=0; jattrib(); int k = 0; while (ap) { ATTRIB_GEN_INTEGER * aip = dynamic_cast(ap); if (aip) str << "entity" << i << "/face" << j << "/attrib" << k << " { name = " << aip->name() << " val = " << aip->value() << "} \n"; else str << "entity" << i << "/face" << j << "/attrib" << k << " { typename = " << ap->type_name() << "} \n"; ap = ap->next(); k++; } SPAbox * box = face->bound(); str << "entity" << i << "/face" << j << "/bbox" << " { BBox (" << box->low().x() << ", " << box->low().y() << ", " << box->low().z() << ";" << box->high().x() << ", " << box->high().y() << ", " << box->high().z() << ")" << " }\n"; } api_get_edges_from_all_entities(entlist[i], edgeList); for(int j=0; j= 2 && strcmp (argv[1], "selectentity") == 0) { int ientry = -1, iface = -1; string select = argv[2]; cout << "ACIS selectentity: " << select << endl; int pos_ent1 = select.find("entity", 0); int pos_ent2 = select.find("/", pos_ent1); if (pos_ent1 != -1 && pos_ent2 == -1) pos_ent2 = select.length(); if (pos_ent1 != -1) ientry = atoi (select.substr(pos_ent1+6, pos_ent2).c_str()); int pos_face1 = select.find("face", 0); int pos_face2 = select.find("/", pos_face1); if (pos_face1 != -1 && pos_face2 == -1) pos_face2 = select.length(); if (pos_face1 != -1) iface = atoi (select.substr(pos_face1+4, pos_face2).c_str()); cout << "entry = " << ientry << ", face = " << iface << endl; const ENTITY_LIST & entlist = acisgeometry -> entlist; if (ientry != -1 && iface == -1) vsacisgeom.SelectEntity (entlist[ientry]); if (iface != -1) { ENTITY_LIST faceList; api_get_faces_from_all_entities(entlist[ientry], faceList); vsacisgeom.SelectEntity (faceList[iface]); } } if (argc >= 2 && strcmp (argv[1], "createct") == 0) { acisgeometry -> CreateCT(); } if (argc >= 2 && strcmp (argv[1], "combineall") == 0) { cout << "combineall " << endl; acisgeometry -> Combine(); } if (argc >= 4) { if (strcmp (argv[1], "subtract") == 0) { cout << "subtract " << argv[2] << " minus " << argv[3] << endl; acisgeometry -> Subtract (atoi (argv[2])-1, atoi (argv[3])-1); } } return TCL_OK; } } netgen-6.2.1905/ng/variables.tcl0000644000175000017500000006757713504650527015107 0ustar kurtkurt# netgen global tcl-variables set drawmode rotate set selectvisual geometry set dirname . set loadgeomtypevar "All Geometry types" set basefilename filename set meshoptions.fineness 3 set meshoptions.firststep ag set meshoptions.laststep ov set options.memory 0 set options.localh 1 set options.delaunay 1 set options.checkoverlap 1 set options.checkoverlappingboundary 0 set options.checkchartboundary 1 set options.startinsurface 0 set options.blockfill 1 set options.debugmode 0 set options.dooptimize 1 set options.parthread 1 set options.elsizeweight 0.2 set options.secondorder 0 set options.elementorder 1 set options.quad 0 set options.try_hexes 0 set options.inverttets 0 set options.inverttrigs 0 set options.autozrefine 0 set options.meshsize 1000 set options.minmeshsize 0 set options.curvaturesafety 2 set options.segmentsperedge 2 set options.meshsizefilename "" set options.badellimit 175 set options.optsteps2d 3 set options.optsteps3d 5 set options.opterrpow 2 set options.grading 0.5 set options.printmsg 2 set debug.slowchecks 0 set debug.debugoutput 0 set debug.haltexistingline 0 set debug.haltoverlap 0 set debug.haltsuccess 0 set debug.haltnosuccess 0 set debug.haltlargequalclass 0 set debug.haltsegment 0 set debug.haltnode 0 set debug.haltface 0 set debug.haltfacenr 0 set debug.haltsegmentp1 0 set debug.haltsegmentp2 0 set geooptions.drawcsg 1 set geooptions.detail 0.001 set geooptions.accuracy 1e-6 set geooptions.facets 20 set geooptions.minx -1000 set geooptions.miny -1000 set geooptions.minz -1000 set geooptions.maxx 1000 set geooptions.maxy 1000 set geooptions.maxz 1000 set viewqualityplot 0 set memuseplot 0 set viewrotatebutton 0 set showsensitivehelp 0 set showhelpline 0 set viewoptions.specpointvlen 0.3 set viewoptions.light.amb 0.3 set viewoptions.light.diff 0.7 set viewoptions.light.spec 1 set viewoptions.light.locviewer 0 set viewoptions.mat.shininess 50 set viewoptions.mat.transp 0.3 set viewoptions.colormeshsize 0 set viewoptions.whitebackground 1 set viewoptions.drawcoordinatecross 1 set viewoptions.drawcolorbar 1 set viewoptions.drawnetgenlogo 1 set viewoptions.stereo 0 set viewoptions.shrink 1 set viewoptions.drawfilledtrigs 1 set viewoptions.drawedges 0 set viewoptions.drawbadels 0 set viewoptions.centerpoint 0 set viewoptions.drawelement 0 set viewoptions.drawoutline 1 set viewoptions.drawtets 0 set viewoptions.drawtetsdomain 0 set viewoptions.drawprisms 0 set viewoptions.drawpyramids 0 set viewoptions.drawhexes 0 set viewoptions.drawidentified 0 set viewoptions.drawpointnumbers 0 set viewoptions.drawedgenumbers 0 set viewoptions.drawfacenumbers 0 set viewoptions.drawelementnumbers 0 set viewoptions.drawdomainsurf 0 set viewoptions.drawededges 1 set viewoptions.drawedpoints 1 set viewoptions.drawedpointnrs 0 set viewoptions.drawedtangents 0 set viewoptions.drawededgenrs 0 set viewoptions.drawmetispartition 0 set viewoptions.drawcurveproj 0 set viewoptions.drawcurveprojedge 1 set viewoptions.clipping.nx 0 set viewoptions.clipping.ny 1 set viewoptions.clipping.nz 0 set viewoptions.clipping.dist 0 set viewoptions.clipping.dist2 0 set viewoptions.clipping.enable 0 set viewoptions.clipping.onlydomain 0 set viewoptions.clipping.notdomain 0 set viewoptions.usecentercoords 0 set viewoptions.centerx 0 set viewoptions.centery 0 set viewoptions.centerz 0 set viewoptions.drawspecpoint 0 set viewoptions.specpointx 0 set viewoptions.specpointy 0 set viewoptions.specpointz 0 set stloptions.showtrias 0 set stloptions.showfilledtrias 1 set stloptions.showedges 1 set stloptions.showmarktrias 0 set stloptions.showactivechart 0 set stloptions.yangle 30 set stloptions.contyangle 20 set stloptions.edgecornerangle 60 set stloptions.chartangle 15 set stloptions.outerchartangle 70 set stloptions.usesearchtree 0 set stloptions.chartnumber 1 set stloptions.charttrignumber 1 set stloptions.chartnumberoffset 0 set stloptions.atlasminh 0.1 set stloptions.resthsurfcurvfac 2 set stloptions.resthsurfcurvenable 0 set stloptions.resthatlasfac 2 set stloptions.resthatlasenable 1 set stloptions.resthchartdistfac 1.2 set stloptions.resthchartdistenable 1 set stloptions.resthlinelengthfac 0.5 set stloptions.resthlinelengthenable 1 set stloptions.resthcloseedgefac 1 set stloptions.resthcloseedgeenable 1 set stloptions.resthminedgelen 0.01 set stloptions.resthminedgelenenable 1 set stloptions.resthedgeanglefac 1 set stloptions.resthedgeangleenable 0 set stloptions.resthsurfmeshcurvfac 1 set stloptions.resthsurfmeshcurvenable 0 set stloptions.recalchopt 1 set stldoctor.drawmeshededges 1 set stldoctor.geom_tol_fact 0.000001 set stldoctor.useexternaledges 0 set stldoctor.showfaces 0 set stldoctor.conecheck 1 set stldoctor.spiralcheck 1 set stldoctor.selecttrig 0 set stldoctor.selectmode 1 set stldoctor.longlinefact 0 set stldoctor.showexcluded 1 set stldoctor.edgeselectmode 0 set stldoctor.nodeofseltrig 1 set stldoctor.showtouchedtrigchart 0 set stldoctor.showedgecornerpoints 0 set stldoctor.showmarkedtrigs 1 set stldoctor.dirtytrigfact 0.01 set stldoctor.smoothangle 90 set stldoctor.selectwithmouse 1 set stldoctor.showvicinity 0 set stldoctor.vicinity 50 set stldoctor.smoothnormalsweight 0.2 set occoptions.showvolumenr 0 set occoptions.showsurfaces 1 set occoptions.showedges 1 set occoptions.showsolidnr 0 set occoptions.showsolidnr2 0 set occoptions.visproblemfaces 0 set occoptions.zoomtohighlightedentity 0 set occoptions.deflection 1 set occoptions.tolerance 1e-3 set occoptions.fixsmalledges 1 set occoptions.fixspotstripfaces 1 set occoptions.sewfaces 1 set occoptions.makesolids 1 set occoptions.splitpartitions 0 set meshdoctor.active 0 set meshdoctor.markedgedist 1 # variablenname mit punkt problematisch! set status_np 0 set status_ne 0 set status_nse 0 set status_working " " set status_task " " set status_percent 0 set status_filename 0 set status_tetqualclasses "10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40" set exportfiletype "Neutral Format" set preproc.facenr 0 set preproc.selectmode query set preproc.numtrig 0 set mem_moveable 0 set multithread_pause 0 set multithread_testmode 0 set multithread_redraw 0 set multithread_drawing 0 set multithread_terminate 0 set multithread_running 0 set level 0 set tablesforoutput {} set optlist { options.localh options.delaunay options.checkoverlap options.startinsurface options.blockfill options.dooptimize options.elsizeweight options.meshsize options.minmeshsize options.curvaturesafety options.optsteps2d options.optsteps3d options.secondorder } set visoptions.usetexture 1 set visoptions.invcolor 0 set visoptions.imaginary 0 set visoptions.lineartexture 0 set visoptions.numtexturecols 16 set visoptions.showclipsolution 1 set visoptions.showsurfacesolution 0 set visoptions.drawfieldlines 0 set visoptions.drawpointcurves 1 set visoptions.numfieldlines 100 set visoptions.fieldlinesrandomstart 0 set visoptions.fieldlinesstartarea box set visoptions.fieldlinesstartareap1x 1 set visoptions.fieldlinesstartareap1y 1 set visoptions.fieldlinesstartareap1z 1 set visoptions.fieldlinesstartareap2x 0 set visoptions.fieldlinesstartareap2y 0 set visoptions.fieldlinesstartareap2z 0 set visoptions.fieldlinesstartface -1 set visoptions.fieldlinesfilename none set visoptions.fieldlinestolerance 0.0005 set visoptions.fieldlinesrktype crungekutta set visoptions.fieldlineslength 0.5 set visoptions.fieldlinesmaxpoints 500 set visoptions.fieldlinesthickness 0.0015 set visoptions.fieldlinesvecfunction none set visoptions.fieldlinesphase 0 set visoptions.fieldlinesonlyonephase 1 set visoptions.lineplotfile empty set visoptions.lineplotsource file set visoptions.lineplotusingx 0 set visoptions.lineplotusingy 1 set visoptions.lineplotautoscale 1 set visoptions.lineplotxmin 0 set visoptions.lineplotxmax 1 set visoptions.lineplotymin 0 set visoptions.lineplotymax 1 set visoptions.lineplotcurrentnum -1 set visoptions.lineplotinfos "" set visoptions.lineplotselected none set visoptions.lineplotselector "" set visoptions.lineplotcolor red set visoptions.lineplotsizex 500 set visoptions.lineplotsizey 400 set visoptions.lineplotselectedeval 0 set visoptions.lineplotdatadescr "column1 column2 column3" set visoptions.lineplotxcoordselector "" set visoptions.lineplotycoordselector "" set visoptions.evaluatefilenames none set visoptions.evaluatefiledescriptions none set visoptions.clipsolution none set visoptions.scalfunction none set visoptions.vecfunction none set visoptions.evaluate abs set visoptions.gridsize 20 set visoptions.xoffset 0 set visoptions.yoffset 0 set visoptions.autoscale 1 set visoptions.redrawperiodic 0 set visoptions.logscale 0 set visoptions.mminval 0 set visoptions.mmaxval 1 set visoptions.isolines 0 set visoptions.isosurf 0 set visoptions.subdivisions 1 set visoptions.numiso 10 set visoptions.autoredraw 0 set visoptions.autoredrawtime 2 set visoptions.simulationtime 0 set visoptions.multidimcomponent 0 # deform by vector function set visoptions.deformation 0 set visoptions.scaledeform1 1 set visoptions.scaledeform2 1 set parallel_netgen 0 set optfilename [file join $nguserdir ng.opt] set inifilename [file join $nguserdir ng.ini] set meshinifilename [file join $nguserdir ngmesh.ini] global env if { [llength [array names env NG_OPT]] == 1 } { if { [string length $env(NG_OPT)] > 0 } { set optfilename $env(NG_OPT) } } if { [file exists $optfilename] == 1 } { set datei [open $optfilename r] while { [gets $datei line] >= 0 } { set [lindex $line 0] [lindex $line 1] } close $datei } { puts "optfile $optfilename does not exist - using default values" } proc saveoptions { } { uplevel 1 { set file $optfilename if {$file != ""} { set datei [open $file w] puts $datei "dirname ${dirname}" puts $datei "loadgeomtypevar \"${loadgeomtypevar}\"" puts $datei "exportfiletype \"${exportfiletype}\"" puts $datei "meshoptions.fineness ${meshoptions.fineness}" puts $datei "meshoptions.firststep ${meshoptions.firststep}" puts $datei "meshoptions.laststep ${meshoptions.laststep}" puts $datei "options.localh ${options.localh}" puts $datei "options.delaunay ${options.delaunay}" puts $datei "options.checkoverlap ${options.checkoverlap}" puts $datei "options.checkchartboundary ${options.checkchartboundary}" puts $datei "options.startinsurface ${options.startinsurface}" puts $datei "options.blockfill ${options.blockfill}" puts $datei "options.debugmode ${options.debugmode}" puts $datei "options.dooptimize ${options.dooptimize}" puts $datei "options.parthread ${options.parthread}" puts $datei "options.elsizeweight ${options.elsizeweight}" puts $datei "options.secondorder ${options.secondorder}" puts $datei "options.elementorder ${options.elementorder}" # puts $datei "options.memory ${options.memory}" puts $datei "options.quad ${options.quad}" puts $datei "options.try_hexes ${options.try_hexes}" puts $datei "options.inverttets ${options.inverttets}" puts $datei "options.inverttrigs ${options.inverttrigs}" puts $datei "options.autozrefine ${options.autozrefine}" puts $datei "options.meshsize ${options.meshsize}" puts $datei "options.minmeshsize ${options.minmeshsize}" puts $datei "options.curvaturesafety ${options.curvaturesafety}" puts $datei "options.segmentsperedge ${options.segmentsperedge}" puts $datei "options.meshsizefilename ${options.meshsizefilename}" puts $datei "options.badellimit ${options.badellimit}" puts $datei "options.optsteps2d ${options.optsteps2d}" puts $datei "options.optsteps3d ${options.optsteps3d}" puts $datei "options.opterrpow ${options.opterrpow}" puts $datei "options.grading ${options.grading}" puts $datei "options.printmsg ${options.printmsg}" puts $datei "geooptions.drawcsg ${geooptions.drawcsg}" puts $datei "geooptions.detail ${geooptions.detail}" puts $datei "geooptions.accuracy ${geooptions.accuracy}" puts $datei "geooptions.facets ${geooptions.facets}" puts $datei "geooptions.minx ${geooptions.minx}" puts $datei "geooptions.miny ${geooptions.miny}" puts $datei "geooptions.minz ${geooptions.minz}" puts $datei "geooptions.maxx ${geooptions.maxx}" puts $datei "geooptions.maxy ${geooptions.maxy}" puts $datei "geooptions.maxz ${geooptions.maxz}" puts $datei "viewoptions.specpointvlen ${viewoptions.specpointvlen}" puts $datei "viewoptions.light.amb ${viewoptions.light.amb}" puts $datei "viewoptions.light.diff ${viewoptions.light.diff}" puts $datei "viewoptions.light.spec ${viewoptions.light.spec}" puts $datei "viewoptions.light.locviewer ${viewoptions.light.locviewer}" puts $datei "viewoptions.mat.shininess ${viewoptions.mat.shininess}" puts $datei "viewoptions.mat.transp ${viewoptions.mat.transp}" puts $datei "viewoptions.colormeshsize ${viewoptions.colormeshsize}" puts $datei "viewoptions.whitebackground ${viewoptions.whitebackground}" puts $datei "viewoptions.drawcolorbar ${viewoptions.drawcolorbar}" puts $datei "viewoptions.drawcoordinatecross ${viewoptions.drawcoordinatecross}" puts $datei "viewoptions.drawnetgenlogo ${viewoptions.drawnetgenlogo}" puts $datei "viewoptions.stereo ${viewoptions.stereo}" puts $datei "viewoptions.drawfilledtrigs ${viewoptions.drawfilledtrigs}" puts $datei "viewoptions.drawedges ${viewoptions.drawedges}" puts $datei "viewoptions.drawbadels ${viewoptions.drawbadels}" puts $datei "viewoptions.centerpoint ${viewoptions.centerpoint}" puts $datei "viewoptions.drawelement ${viewoptions.drawelement}" puts $datei "viewoptions.drawoutline ${viewoptions.drawoutline}" puts $datei "viewoptions.drawtets ${viewoptions.drawtets}" puts $datei "viewoptions.drawprisms ${viewoptions.drawprisms}" puts $datei "viewoptions.drawpyramids ${viewoptions.drawpyramids}" puts $datei "viewoptions.drawhexes ${viewoptions.drawhexes}" puts $datei "viewoptions.drawidentified ${viewoptions.drawidentified}" puts $datei "viewoptions.drawpointnumbers ${viewoptions.drawpointnumbers}" puts $datei "viewoptions.drawededges ${viewoptions.drawededges}" puts $datei "viewoptions.drawedpoints ${viewoptions.drawedpoints}" puts $datei "viewoptions.drawedpointnrs ${viewoptions.drawedpointnrs}" puts $datei "viewoptions.drawedtangents ${viewoptions.drawedtangents}" puts $datei "viewoptions.shrink ${viewoptions.shrink}" puts $datei "stloptions.showtrias ${stloptions.showtrias}" puts $datei "stloptions.showfilledtrias ${stloptions.showfilledtrias}" puts $datei "stloptions.showedges ${stloptions.showedges}" puts $datei "stloptions.showmarktrias ${stloptions.showmarktrias}" puts $datei "stloptions.showactivechart ${stloptions.showactivechart}" puts $datei "stloptions.yangle ${stloptions.yangle}" puts $datei "stloptions.contyangle ${stloptions.contyangle}" puts $datei "stloptions.edgecornerangle ${stloptions.edgecornerangle}" puts $datei "stloptions.chartangle ${stloptions.chartangle}" puts $datei "stloptions.outerchartangle ${stloptions.outerchartangle}" puts $datei "stloptions.usesearchtree ${stloptions.usesearchtree}" puts $datei "stloptions.chartnumber ${stloptions.chartnumber}" puts $datei "stloptions.charttrignumber ${stloptions.charttrignumber}" puts $datei "stloptions.chartnumberoffset ${stloptions.chartnumberoffset}" puts $datei "stloptions.atlasminh ${stloptions.atlasminh}" puts $datei "stloptions.resthsurfcurvfac ${stloptions.resthsurfcurvfac}" puts $datei "stloptions.resthsurfcurvenable ${stloptions.resthsurfcurvenable}" puts $datei "stloptions.resthatlasfac ${stloptions.resthatlasfac}" puts $datei "stloptions.resthatlasenable ${stloptions.resthatlasenable}" puts $datei "stloptions.resthchartdistfac ${stloptions.resthchartdistfac}" puts $datei "stloptions.resthchartdistenable ${stloptions.resthchartdistenable}" puts $datei "stloptions.resthlinelengthfac ${stloptions.resthlinelengthfac}" puts $datei "stloptions.resthlinelengthenable ${stloptions.resthlinelengthenable}" puts $datei "stloptions.resthminedgelen ${stloptions.resthminedgelen}" puts $datei "stloptions.resthminedgelenenable ${stloptions.resthminedgelenenable}" puts $datei "stloptions.resthcloseedgefac ${stloptions.resthcloseedgefac}" puts $datei "stloptions.resthcloseedgeenable ${stloptions.resthcloseedgeenable}" puts $datei "stloptions.resthedgeanglefac ${stloptions.resthedgeanglefac}" puts $datei "stloptions.resthedgeangleenable ${stloptions.resthedgeangleenable}" puts $datei "stloptions.resthsurfmeshcurvfac ${stloptions.resthsurfmeshcurvfac}" puts $datei "stloptions.resthsurfmeshcurvenable ${stloptions.resthsurfmeshcurvenable}" puts $datei "stloptions.recalchopt ${stloptions.recalchopt}" puts $datei "visoptions.subdivisions ${visoptions.subdivisions}" puts $datei "visoptions.autoredraw ${visoptions.autoredraw}" puts $datei "visoptions.autoredrawtime ${visoptions.autoredrawtime}" # trafo options # if exist trafooptions then ... if { [info exists trafooptions.solver] == 1 } { puts $datei "trafooptions.solver ${trafooptions.solver}" puts $datei "trafooptions.levels ${trafooptions.levels}" puts $datei "trafooptions.linits ${trafooptions.linits}" puts $datei "trafooptions.nonlinits ${trafooptions.nonlinits}" puts $datei "trafooptions.stabcurrent ${trafooptions.stabcurrent}" puts $datei "trafooptions.checkcond ${trafooptions.checkcond}" puts $datei "trafooptions.maxdirect ${trafooptions.maxdirect}" puts $datei "trafooptions.secondorder ${trafooptions.secondorder}" puts $datei "trafooptions.homogenizedcore ${trafooptions.homogenizedcore}" puts $datei "trafooptions.ordercore ${trafooptions.ordercore}" puts $datei "trafooptions.simplecurrents ${trafooptions.simplecurrents}" puts $datei "trafooptions.assemblecomplexmatrix ${trafooptions.assemblecomplexmatrix}" puts $datei "trafooptions.meshcasing ${trafooptions.meshcasing}" puts $datei "trafooptions.meshcore ${trafooptions.meshcore}" puts $datei "trafooptions.meshclumps ${trafooptions.meshclumps}" puts $datei "trafooptions.meshshields ${trafooptions.meshshields}" puts $datei "trafooptions.meshcoils ${trafooptions.meshcoils}" puts $datei "trafooptions.bcmdirectory ${trafooptions.bcmdirectory}" puts $datei "trafooptions.lossdensityfile ${trafooptions.lossdensityfile}" } if { [info exists smalltrafomodell.tankheight] == 1 } { puts $datei "smalltrafomodell.tankheight ${smalltrafomodell.tankheight}" puts $datei "smalltrafomodell.tankwidth ${smalltrafomodell.tankwidth}" puts $datei "smalltrafomodell.tanklength ${smalltrafomodell.tanklength}" puts $datei "smalltrafomodell.corewidth ${smalltrafomodell.corewidth}" puts $datei "smalltrafomodell.windowheight ${smalltrafomodell.windowheight}" puts $datei "smalltrafomodell.limbdistance ${smalltrafomodell.limbdistance}" puts $datei "smalltrafomodell.xposcore ${smalltrafomodell.xposcore}" puts $datei "smalltrafomodell.yposcore ${smalltrafomodell.yposcore}" puts $datei "smalltrafomodell.zposcore ${smalltrafomodell.zposcore}" puts $datei "smalltrafomodell.leakagefluxguidethickness ${smalltrafomodell.leakagefluxguidethickness}" puts $datei "smalltrafomodell.leakagefluxguidewidth ${smalltrafomodell.leakagefluxguidewidth}" puts $datei "smalltrafomodell.leakagefluxguidezposition ${smalltrafomodell.leakagefluxguidezposition}" puts $datei "smalltrafomodell.limbcoil.1 ${smalltrafomodell.limbcoil.1}" puts $datei "smalltrafomodell.ricoil.1 ${smalltrafomodell.ricoil.1}" puts $datei "smalltrafomodell.rocoil.1 ${smalltrafomodell.rocoil.1}" puts $datei "smalltrafomodell.zposcoil.1 ${smalltrafomodell.zposcoil.1}" puts $datei "smalltrafomodell.heightcoil.1 ${smalltrafomodell.heightcoil.1}" puts $datei "smalltrafomodell.currentcoil.1 ${smalltrafomodell.currentcoil.1}" puts $datei "smalltrafomodell.nturnscoil.1 ${smalltrafomodell.nturnscoil.1}" puts $datei "smalltrafomodell.limbcoil.2 ${smalltrafomodell.limbcoil.2}" puts $datei "smalltrafomodell.ricoil.2 ${smalltrafomodell.ricoil.2}" puts $datei "smalltrafomodell.rocoil.2 ${smalltrafomodell.rocoil.2}" puts $datei "smalltrafomodell.zposcoil.2 ${smalltrafomodell.zposcoil.2}" puts $datei "smalltrafomodell.heightcoil.2 ${smalltrafomodell.heightcoil.2}" puts $datei "smalltrafomodell.currentcoil.2 ${smalltrafomodell.currentcoil.2}" puts $datei "smalltrafomodell.nturnscoil.2 ${smalltrafomodell.nturnscoil.2}" puts $datei "smalltrafomodell.limbcoil.3 ${smalltrafomodell.limbcoil.3}" puts $datei "smalltrafomodell.ricoil.3 ${smalltrafomodell.ricoil.3}" puts $datei "smalltrafomodell.rocoil.3 ${smalltrafomodell.rocoil.3}" puts $datei "smalltrafomodell.zposcoil.3 ${smalltrafomodell.zposcoil.3}" puts $datei "smalltrafomodell.heightcoil.3 ${smalltrafomodell.heightcoil.3}" puts $datei "smalltrafomodell.currentcoil.3 ${smalltrafomodell.currentcoil.3}" puts $datei "smalltrafomodell.nturnscoil.3 ${smalltrafomodell.nturnscoil.3}" puts $datei "smalltrafomodell.limbcoil.4 ${smalltrafomodell.limbcoil.4}" puts $datei "smalltrafomodell.ricoil.4 ${smalltrafomodell.ricoil.4}" puts $datei "smalltrafomodell.rocoil.4 ${smalltrafomodell.rocoil.4}" puts $datei "smalltrafomodell.zposcoil.4 ${smalltrafomodell.zposcoil.4}" puts $datei "smalltrafomodell.heightcoil.4 ${smalltrafomodell.heightcoil.4}" puts $datei "smalltrafomodell.currentcoil.4 ${smalltrafomodell.currentcoil.4}" puts $datei "smalltrafomodell.nturnscoil.4 ${smalltrafomodell.nturnscoil.4}" puts $datei "smalltrafomodell.limbcoil.5 ${smalltrafomodell.limbcoil.5}" puts $datei "smalltrafomodell.ricoil.5 ${smalltrafomodell.ricoil.5}" puts $datei "smalltrafomodell.rocoil.5 ${smalltrafomodell.rocoil.5}" puts $datei "smalltrafomodell.zposcoil.5 ${smalltrafomodell.zposcoil.5}" puts $datei "smalltrafomodell.heightcoil.5 ${smalltrafomodell.heightcoil.5}" puts $datei "smalltrafomodell.currentcoil.5 ${smalltrafomodell.currentcoil.5}" puts $datei "smalltrafomodell.nturnscoil.5 ${smalltrafomodell.nturnscoil.5}" puts $datei "smalltrafomodell.limbcoil.6 ${smalltrafomodell.limbcoil.6}" puts $datei "smalltrafomodell.ricoil.6 ${smalltrafomodell.ricoil.6}" puts $datei "smalltrafomodell.rocoil.6 ${smalltrafomodell.rocoil.6}" puts $datei "smalltrafomodell.zposcoil.6 ${smalltrafomodell.zposcoil.6}" puts $datei "smalltrafomodell.heightcoil.6 ${smalltrafomodell.heightcoil.6}" puts $datei "smalltrafomodell.currentcoil.6 ${smalltrafomodell.currentcoil.6}" puts $datei "smalltrafomodell.nturnscoil.6 ${smalltrafomodell.nturnscoil.6}" puts $datei "smalltrafomodell.limbtest.1 ${smalltrafomodell.limbtest.1}" puts $datei "smalltrafomodell.heighttest.1 ${smalltrafomodell.heighttest.1}" puts $datei "smalltrafomodell.widthtest.1 ${smalltrafomodell.widthtest.1}" puts $datei "smalltrafomodell.rtest.1 ${smalltrafomodell.rtest.1}" puts $datei "smalltrafomodell.zpostest.1 ${smalltrafomodell.zpostest.1}" puts $datei "smalltrafomodell.edgeradiustest.1 ${smalltrafomodell.edgeradiustest.1}" puts $datei "smalltrafomodell.finetest.1 ${smalltrafomodell.finetest.1}" puts $datei "smalltrafomodell.conductivetest.1 ${smalltrafomodell.conductivetest.1}" puts $datei "smalltrafomodell.limbtest.2 ${smalltrafomodell.limbtest.2}" puts $datei "smalltrafomodell.heighttest.2 ${smalltrafomodell.heighttest.2}" puts $datei "smalltrafomodell.widthtest.2 ${smalltrafomodell.widthtest.2}" puts $datei "smalltrafomodell.rtest.2 ${smalltrafomodell.rtest.2}" puts $datei "smalltrafomodell.zpostest.2 ${smalltrafomodell.zpostest.2}" puts $datei "smalltrafomodell.edgeradiustest.2 ${smalltrafomodell.edgeradiustest.2}" puts $datei "smalltrafomodell.finetest.2 ${smalltrafomodell.finetest.2}" puts $datei "smalltrafomodell.conductivetest.2 ${smalltrafomodell.conductivetest.2}" puts $datei "smalltrafomodell.limbtest.3 ${smalltrafomodell.limbtest.3}" puts $datei "smalltrafomodell.heighttest.3 ${smalltrafomodell.heighttest.3}" puts $datei "smalltrafomodell.widthtest.3 ${smalltrafomodell.widthtest.3}" puts $datei "smalltrafomodell.rtest.3 ${smalltrafomodell.rtest.3}" puts $datei "smalltrafomodell.zpostest.3 ${smalltrafomodell.zpostest.3}" puts $datei "smalltrafomodell.edgeradiustest.3 ${smalltrafomodell.edgeradiustest.3}" puts $datei "smalltrafomodell.finetest.3 ${smalltrafomodell.finetest.3}" puts $datei "smalltrafomodell.conductivetest.3 ${smalltrafomodell.conductivetest.3}" puts $datei "smalltrafomodell.limbtest.4 ${smalltrafomodell.limbtest.4}" puts $datei "smalltrafomodell.heighttest.4 ${smalltrafomodell.heighttest.4}" puts $datei "smalltrafomodell.widthtest.4 ${smalltrafomodell.widthtest.4}" puts $datei "smalltrafomodell.rtest.4 ${smalltrafomodell.rtest.4}" puts $datei "smalltrafomodell.zpostest.4 ${smalltrafomodell.zpostest.4}" puts $datei "smalltrafomodell.edgeradiustest.4 ${smalltrafomodell.edgeradiustest.4}" puts $datei "smalltrafomodell.finetest.4 ${smalltrafomodell.finetest.4}" puts $datei "smalltrafomodell.conductivetest.4 ${smalltrafomodell.conductivetest.4}" puts $datei "smalltrafomodell.nperitest ${smalltrafomodell.nperitest}" puts $datei "smalltrafomodell.filename ${smalltrafomodell.filename}" puts $datei "smalltrafomodell.murlfguide ${smalltrafomodell.murlfguide}" puts $datei "smalltrafomodell.murtestwire ${smalltrafomodell.murtestwire}" puts $datei "smalltrafomodell.murcore ${smalltrafomodell.murcore}" puts $datei "smalltrafomodell.kappalfguide ${smalltrafomodell.kappalfguide}" puts $datei "smalltrafomodell.kappatestwire ${smalltrafomodell.kappatestwire}" puts $datei "smalltrafomodell.kappacore ${smalltrafomodell.kappacore}" } close $datei } } } # the ini file is saved on demand : proc saveinifile { } { global inifilename if {[catch { set datei [open $inifilename w] } result ]} { puts "cannot write file $inifilename" } { for { set i [.ngmenu.file.recent index last] } { $i >= 0 } { incr i -1 } { puts $datei "recentfile \"[.ngmenu.file.recent entrycget $i -label]\"" } close $datei } } proc savemeshinifile { } { global meshinifilename if {[catch { set datei [open $meshinifilename w] } result ]} { puts "cannot write file $meshinifilename" } { for { set i [.ngmenu.file.recentmesh index last] } { $i >= 1 } { incr i -1 } { puts $datei "recentfile \"[.ngmenu.file.recentmesh entrycget $i -label]\"" } close $datei } } proc loadinifile { } { global inifilename if { [file exists $inifilename] == 1 } { set datei [open $inifilename r] while { [gets $datei line] >= 0 } { if {[lindex $line 0] == "recentfile"} { set filename [lindex $line 1] if { [file exists $filename] == 1 } { AddRecentFile $filename } } } close $datei } } proc loadmeshinifile { } { global meshinifilename if { [file exists $meshinifilename] == 1 } { set datei [open $meshinifilename r] while { [gets $datei line] >= 0 } { if {[lindex $line 0] == "recentfile"} { set filename [lindex $line 1] if { [file exists $filename] == 1 } { AddRecentMeshFile $filename } } } close $datei } } set cmdindex {} set hlpindex {} set secindex {} netgen-6.2.1905/ng/ngtesting.tcl0000644000175000017500000001332213504650527015114 0ustar kurtkurt # tests.tcl proc Ng_TestMeshing { infile outfile logfile} { if { ![file exists $infile]} { puts $logfile "error: file $infile does not exist" } else { puts -nonewline $logfile " loading geometry: "; ngtic; Ng_LoadGeometry "$infile"; ngtoc $logfile puts -nonewline $logfile " parsing geometry: "; ngtic; Ng_ParseGeometry; ngtoc $logfile puts -nonewline $logfile " generating mesh: "; ngtic; Ng_GenerateMesh; ngtoc $logfile puts -nonewline $logfile " saving mesh: "; ngtic; Ng_SaveMesh "$outfile"; ngtoc $logfile flush $logfile } } # tests.tcl proc Ngs_TestPDE { infile {nsolves 1} logfile } { if { ![file exists $infile]} { puts $logfile "error: file $infile does not exist" } else { puts -nonewline $logfile " loading PDE file: "; ngtic; ngsloadpde "$infile"; ngtoc $logfile for {set i 1} {$i<=$nsolves} {incr i 1} { puts -nonewline $logfile " solve PDE level $i: "; ngtic; ngssolvepde; ngtoc $logfile } flush $logfile } } proc ngtest { {t all} {f ""}} { ngset printmsg 0 if {$f == "" } { set logfile stdout } else { set logfile [open $f "w"] } global options.parthread set options.parthread 0 Ng_SetMeshingParameters if {$t == "all"} { ngtest in2d $f ngtest geo $f ngtest stl $f ngtest pde $f return } elseif {$t == "in2d"} { puts "\n*** performing in2d file tests ***" puts " ** writing results to $f" puts "\n ** testing in2d files in examples/ **" set testdir "$::ngdir/../examples" set in2dfiles { beam2d hyperbolic piezo2dround rectangle squareincl squareinsquare } foreach {tfile} $in2dfiles { if {$f != ""} { puts " * meshing file examples/$tfile.in2d..." } puts $logfile "\n * meshing file examples/$tfile.in2d..."; flush $logfile Ng_TestMeshing "$testdir/$tfile.in2d" "$testdir/$tfile.vol" $logfile } puts "\n ** testing in2d files in tutorials/ **" set testdir "$::ngdir/../share/netgen" set in2dfiles { demo2d newin2d square v2in2d } foreach {tfile} $in2dfiles { if {$f != ""} { puts " * meshing file tutorials/$tfile.in2d..." } puts $logfile "\n * meshing file tutorials/$tfile.in2d..."; flush $logfile Ng_TestMeshing "$testdir/$tfile.in2d" "$testdir/$tfile.vol" $logfile } puts "*** in2d tests complete" } elseif {$t == "geo"} { puts "\n*** performing geo file tests ***" puts " ** writing results to $f" puts "\n ** testing geo files in examples/ **" set testdir "$::ngdir/../examples" set geofiles { beam cylsphere rboxcyl thinc boxcyl fichera period saw_3d thinplate coilshield gamm3d plate shaft tripelpendel cube halfsphere poly shell twocubes cylinder kaese quarter3d skew_prisms } foreach {tfile} $geofiles { if {$f != ""} { puts " * meshing file examples/$tfile.geo..."; flush $logfile } puts $logfile "\n * meshing file examples/$tfile.geo..."; flush $logfile Ng_TestMeshing "$testdir/$tfile.geo" "$testdir/$tfile.vol" $logfile } puts "\n ** testing geo files in tutorials/ **" set testdir "$::ngdir/../share/netgen" set geofiles { boxcyl cubemcyl extrusion revolution trafo circle_on_cube cubemsphere fichera sculpture twobricks cone cylinder lshape3d shaft twocubes cubeandring cylsphere manyholes sphere twocyl cubeandspheres ellipsoid matrix sphereincube cube ellipticcyl period torus } foreach {tfile} $geofiles { if {$f != ""} { puts " * meshing file $tfile.geo..." } puts $logfile "\n * meshing file $tfile.geo..."; flush $logfile Ng_TestMeshing "$testdir/$tfile.geo" "$testdir/$tfile.vol" $logfile } } elseif {$t == "stl"} { puts "\n*** performing stl file tests ***" # set logfile [open stltest.log "w"] puts " ** writing results to $f" puts "\n ** testing stl files in examples/ **" set testdir "$::ngdir/../examples" set stlfiles { crankshaft hinge1 } foreach {tfile} $stlfiles { if {$f != ""} { puts " * meshing file examples/$tfile.stl..." } puts $logfile "\n * meshing file examples/$tfile.stl..."; flush $logfile Ng_TestMeshing "$testdir/$tfile.stl" "$testdir/$tfile.vol" $logfile } puts "\n ** testing stl files in tutorials/ **" set testdir "$::ngdir/../tutorials" set stlfiles { hinge part1 } foreach {tfile} $stlfiles { if {$f != ""} { puts " * meshing file tutorials/$tfile.stl..." } puts $logfile "\n * meshing file tutorials/$tfile.stl..."; flush $logfile Ng_TestMeshing "$testdir/$tfile.stl" "$testdir/$tfile.vol" $logfile } puts "*** stl tests complete" } elseif {$t == "pde"} { puts "\n*** preforming pde tests ***" # set logfile [open pdetest.log "w"] puts " ** writing results to $f" puts "\n ** testing pde files in ngsolve/pde_tutorial/ **" set testdir "$::ngdir/../ngsolve/pde_tutorial" set pdefiles { d1_square.pde d2_chip.pde d3_helmholtz.pde d4_cube.pde d5_beam.pde d6_shaft.pde d7_coil.pde d8_coilshield.pde } foreach {tfile} $pdefiles { if {$f != ""} { puts " * testing ngsolve/pde_tutorial/$tfile..." } puts $logfile "\n * testing ngsolve/pde_tutorial/$tfile..."; flush $logfile Ngs_TestPDE "$testdir/$tfile" 1 $logfile } puts "*** pde tests complete" } else { puts $logfile "error: unknown test program '$t'"; flush $logfile } puts "" } Ng_RegisterCmd "ngtest" "netgen" "ngtest" "perform ng standard tests: all in2d geo stl" netgen-6.2.1905/ng/stlgeom.tcl0000644000175000017500000000137513504650527014571 0ustar kurtkurt#if { [catch { load libstlvis[info sharedlibextension] Ng_STL } result ] } { # puts "cannot load stl" # puts "error: $result" #} .ngmenu.geometry add separator .ngmenu.geometry add command -label "STL Doctor..." \ -command { stldoctordialog; } .ngmenu.geometry add command -label "STL Info" \ -command { set notriangles 0 set minx 0 set maxx 0 set miny 0 set maxy 0 set minz 0 set maxz 0 set trigscons 0 Ng_STLInfo notriangles minx maxx miny maxy minz maxz trigscons set msgtext "NO STL-Triangles : $notriangles\nGeometry:\nX = $minx - $maxx\nY = $miny - $maxy\nZ = $minz - $maxz\nConsistency Check = $trigscons\n" set msgtext "$msgtext Status: [Ng_STLInfo status]" tk_messageBox -title "STL Info" -message $msgtext -type ok } netgen-6.2.1905/ng/nghelp.tcl0000644000175000017500000002732213504650527014374 0ustar kurtkurtproc print_commandline_help { } { puts "Usage: ng { options }" puts "-geofile=filename Input geometry file (alternative: ng filename)" puts "-meshfile=filename Output mesh file" puts "-verycoarse, -coarse, -moderate, -fine, -veryfine" puts " Automatic mesh-size selection" puts "-meshsizefile=filename Load mesh-size file with local mesh sizes" puts "-meshfiletype={\"Neutral Format\", ...}" puts " Filetype of output file, default is netgen file" puts "-batchmode Run Netgen in batchmode" puts "-inputmeshfile=filename" puts " Input mesh file (batchmode only)" puts "-mergefile=filename Merge with mesh file (batchmode only)" puts "-refinementfile=filename" puts " Use refinementinfo from file (batchmode only)" puts "-serversocket=\#num Start a Netgen server with port \#num" puts "-V Print additional information" puts "-testout=filename file for test output" if { [catch { NGS_GetData } ] == 0 } { puts "\nNGSolve parameters:" puts "-pdefile=filename Load pde input file" puts "-solve Solve pde once" puts "-solve=n Solve pde by n adaptive refinement steps" puts "-recent Load and solve most recently loaded pde" } } proc set_menu_help { entry helpmsg } { global menuhelps set menuhelps($entry) $helpmsg } proc show_menu_help { entry } { global menuhelps if {[catch {set helptext $menuhelps($entry)}]} { set helptext "no help available " } .helpline configure -text $helptext if {[winfo exists .senshelp_dlg]==1} { .senshelp_dlg.text delete 1.0 end .senshelp_dlg.text insert end "Menu item: $entry\n\n" .senshelp_dlg.text insert end $helptext } } #tixBalloon .balloon -statusbar .helpline proc set_control_help { control helpmsg } { bind $control "show_control_help {$helpmsg}" bind $control "show_control_help {None}" .balloon bind $control -balloonmsg $helpmsg -statusmsg $helpmsg # puts "Add Help to $control" } proc show_control_help { helpmsg } { .helpline configure -text $helpmsg if {[winfo exists .senshelp_dlg]==1} { .senshelp_dlg.text delete 1.0 end .senshelp_dlg.text insert end $helpmsg } } proc sensitivehelpdialog { show } { set w .senshelp_dlg if {[winfo exists .senshelp_dlg] == 1} { if { $show == 1 } { wm withdraw .senshelp_dlg wm deiconify $w focus $w } { wm withdraw $w } } { toplevel $w # wm minsize $w 200 150 global senshelptext text $w.text -yscrollcommand "$w.scroll set" -setgrid true \ -width 40 -height 10 -wrap word scrollbar $w.scroll -command "$w.text yview" pack $w.scroll -side right -fill y pack $w.text -expand yes -fill both ttk::frame $w.bu pack $w.bu # -fill x ttk::button $w.close -text "Close" \ -command { wm withdraw .senshelp_dlg set showsensitivehelp 0 } pack $w.close if { $show == 1 } { wm withdraw $w wm geom $w +100+100 wm deiconify $w wm title $w "Help" focus $w } } } set_menu_help "File" "In File menu you can load and store geometries, meshes etc." set_menu_help "New Geometry" "Deletes current geometry" set_menu_help "Load Geometry" "Loads Geometry file in one of the formats STL (ASCII or binary), Constructive Solid Geometry (.geo) or 2D geometry. Please have a look into Netgen User's manuel for more details." set_menu_help "Save Geometry" "Saves STL Geometry in in either ASCII or binary STL format." set_menu_help "Load Mesh" "Loads surface and volume mesh in Netgen internal format." set_menu_help "Save Mesh" "Saves surface and volume mesh in Netgen internal format." set_menu_help "Write EPS File" "Dumps OpenGL rendering to EPS File." set_menu_help "Save Options" "Saves current options in file \"ng.opt\". These options will be loaded again when starting ng in the same directory." set_menu_help "Export Mesh" "Exports mesh in format defined by Export Filetype." set_menu_help "Export Filetype" "Selects file format for exporting mesh. Please have a look into the Netgen User's manual for more information." set_menu_help "Import Mesh" "Imports surface or volume mesh in exchange format." set_menu_help "Quit" "Quits Netgen" set_menu_help "Geometry" "Preparing geometries, visualiztion of geometries." set_menu_help "Scan CSG Geometry" "Generates surface triangulation for rendering" set_menu_help "CSG Options" "Sets Options for CSG visualization (bounding box, detail size, number of facets)." set_menu_help "CSG Properties" "Defines appearance of current CSG geometry (color, visibility, transparency)" set_menu_help "STL Doctor" "Calls STL Doctor for preprocessing STL geometry files." set_menu_help "STL Info" "Retrieves information about current STL geometry." set_menu_help "Mesh" "Menu for mesh generation" set_menu_help "Generate Mesh" "Generates mesh from geometry, same as Button \"Generate Mesh\"" set_menu_help "Stop Meshing" "Terminates meshgeneration. It may take a while until meshing terminates, please be patient." set_menu_help "Meshing Options" "Set options for mesh generation." set_menu_help "Delete Mesh" "Deletes mesh. Not necessary before generation of new mesh." set_menu_help "Delete Vol Mesh" "Deletes only volume mesh." set_menu_help "Mesh Quality" "Computs element shape measures. Triangle angles are inner angles of all triangles (faces of tetrahedra). Tet angles are angles between faces of tetrahedra." set_menu_help "Check Surface Mesh" "Checks consistency and overlap of surface mesh. Marks overlapping elements as bad elements, please enable visualization of bad elements in View->Mesh." set_menu_help "Check Volume Mesh" "Checks conformity of volume mesh." set_menu_help "Edit Boundary Conditions" "Open dialog for setting boundary condition numbers for individual faces." set_menu_help "Analyze Geometry" "Perform only first step in mesh generation. Action depends on geometry type, e.g. generates charts for STL mesh, find vertices in CSG geometries." set_menu_help "Mesh Edges" "Meshes edges" set_menu_help "Mesh Surface" "Generates surface mesh. Includes already surface optimization for some geometry types." set_menu_help "Optimize Surface" "Optimizes surface mesh." set_menu_help "Surface Optim. Step" "Performs a specific surface optimiztion step. Mesh smoothing moves nodes. edge swapping swaps the diagonal of a quadrilateral built by two triangles, criterion either by number of nodes, or anlges. Combine points eliminates triangles by combining points (in the center of gravity)." set_menu_help "Mesh Volume" "Performs volume meshing. Algorithm is a combination of Delaunay and Rule-based Advancing Front" set_menu_help "Optimize Volume" "Performs additional volume optimization steps" set_menu_help "Smooth Opt Volume" "Performs optimization steps by smoothing iterations" set_menu_help "Smooth Opt Volume Jacobian" "Volume optimization by smoothing iterations. Criterion is optimization of Jacobi determinants. This optimization step is also available for 10-node tetrahedra." set_menu_help "View" "Sets viewing options" set_menu_help "Zoom all" "Zooms scene to show whole object" set_menu_help "Center" "Defines center of rotation" set_menu_help "Viewing Options" "Sets viewing options for geometry, mesh, lighting" set_menu_help "Clipping Plane" "Introduces clipping plane. The clipping plane is defined by the normal vector, and a scaled offset. Clipping of performed by OpenGl rendering" set_menu_help "Quality Plot" "Shows the element quality distribution histogram. Measure is volume scaled by edge-length to the third. Optimal elements have measure 1." set_menu_help "Sensitive Help" "Shows this help window" set_menu_help "Mesh-size" "Manipulations of existing mesh" set_menu_help "Refine uniform" "Refines mesh by splitting elements into eight childs (algorithm of J. Bey)" set_menu_help "Second Order" "Converts 4 node elements to 10 node elements. Edge-midpoitns are projected to the geometry." set_menu_help "Refinement Dialog" "Controls local mesh refinement" set_menu_help "Load Meshsize" "Loads mesh-size file for local mesh refinement." set_menu_help "MS from Surf Mesh" "Defines mesh-size by the surface mesh." set f .options_dlg.nb.nbframe.general # set_control_help $f "General meshing page" set_control_help $f.fine "Controls relative mesh size.\nThis control affects other mesh-size controls in common" set_control_help $f.first "First step in mesh generation. Usually, meshing starts from \"analyze geometry\". If the surface mesh is already available \"First step\" should be set to \"mesh volume\"" set_control_help $f.last "Last step in mesh generation. If only the surface mesh is required, please set \"Last Step\" to \"Optimize Surface\"" set_control_help .bubar.surfm "Start mesh generation" set_control_help .bubar.stopm "Stop mesh generation" proc help_item { helptext } {p puts $helptext } proc show_help { } { set w .help if {[winfo exists .help] == 1} { wm withdraw $w wm deiconif $w focus $w } { toplevel $w frame $w.buttons pack $w.buttons -side bottom -fill x -pady 2m button $w.buttons.done -text Done -command "destroy $w" pack $w.buttons.done -side left -expand 1 text $w.text -yscrollcommand "$w.scroll set" -setgrid true \ -width 60 -height 24 -wrap word scrollbar $w.scroll -command "$w.text yview" pack $w.scroll -side right -fill y pack $w.text -expand yes -fill both } $w.text configure -state normal $w.text delete 1.0 end } set bold "-background #43ce80 -relief raised -borderwidth 1" set normal "-background {} -relief flat" proc help_main { } { show_help; set w .help global bold global normal $w.text insert 0.0 \ {NETGEN Help} $w.text insert end \n\n $w.text insert end \ {1. General} d1 $w.text insert end \n\n $w.text insert end \ {2. Menu items } d2 $w.text insert end \n\n foreach tag {d1 d2} { $w.text tag bind $tag "$w.text tag configure $tag $bold" $w.text tag bind $tag "$w.text tag configure $tag $normal" } $w.text tag bind d1 <1> { puts "general"; help_general } $w.text tag bind d2 <1> { help_menus } $w.text configure -state disabled } proc help_general { } { show_help; set w .help global bold global normal puts "general called" $w.text insert 0.0 \ {NETGEN is an automatic three dimensional tetrahedral mesh generation system. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STEP or STL file format. NETGEN contains modules for mesh optimization and hierarchical mesh refinement.} $w.text configure -state disabled } proc help_menus { } { show_help; set w .help global bold global normal $w.text insert 0.0 \ {The NETGEN Menu items are} $w.text insert end \n\n $w.text insert end \ {1. File} d1 $w.text insert end \n\n $w.text insert end \ {2. Geometry } d2 $w.text insert end \n\n $w.text insert end \ {3. Mesh } d3 $w.text insert end \n\n $w.text insert end \ {4. View } d4 $w.text insert end \n\n $w.text insert end \ {5. Mesh-size } d5 $w.text insert end \n\n $w.text insert end \ {6. STL } d6 foreach tag {d1 d2 d3 d4 d5 d6} { $w.text tag bind $tag "$w.text tag configure $tag $bold" $w.text tag bind $tag "$w.text tag configure $tag $normal" } $w.text tag bind d1 <1> {puts "File menu"} $w.text tag bind d2 <1> {puts "Geometry menu"} $w.text tag bind d3 <1> {puts "Mesh menu"} $w.text tag bind d4 <1> {puts "View menu"} $w.text tag bind d5 <1> {puts "Mesh-size menu"} $w.text tag bind d6 <1> {puts "STL menu"} $w.text configure -state disabled } netgen-6.2.1905/ng/onetcl.cpp0000644000175000017500000100576213504650527014410 0ustar kurtkurtconst char * ngscript[] = {"" ,"catch {lappend auto_path $env(NETGENDIR) }\n" ,"catch {lappend auto_path $env(NETGENDIR)/../lib }\n" ,"if {[catch {Ng_GetCommandLineParameter batchmode} result ]} {\n" ,"load libgui[info sharedlibextension] gui\n" ,"}\n" ,"set batchmode [Ng_GetCommandLineParameter batchmode]\n" ,"if {$batchmode==\"undefined\"} {\n" ,"if {[catch {package require tkdnd } result ]} {\n" ,"}\n" ,"}\n" ,"set userlevel 3\n" ,"if { [Ng_GetCommandLineParameter expert]==\"defined\" } {\n" ,"set userlevel 3\n" ,"}\n" ,"set progname \"NETGEN\"\n" ,"set ngdir \"\"\n" ,"if { [lsearch [array names env] NETGENDIR] != -1 } {\n" ,"set ngdir $env(NETGENDIR)\n" ,"}\n" ,"if { [string length $ngdir] == 0 } {\n" ,"set ngdir \".\"\n" ,"}\n" ,"set nguserdir \"\"\n" ,"if { [lsearch [array names env] NETGEN_USER_DIR] != -1 } {\n" ,"set nguserdir $env(NETGEN_USER_DIR)\n" ,"}\n" ,"if { [string length $nguserdir] == 0 } {\n" ,"set nguserdir \".\"\n" ,"}\n" ,"set batchmode [Ng_GetCommandLineParameter batchmode]\n" ,"set solvemode 0\n" ,"if { [Ng_GetCommandLineParameter solve] != \"undefined\" || \\\n" ,"[Ng_GetCommandLineParameter recent] == \"defined\" } {\n" ,"set solvemode defined\n" ,"}\n" ,"set shellmode [Ng_GetCommandLineParameter shellmode]\n" ,"if { $shellmode == \"defined\" } {\n" ,"set batchmode \"defined\"\n" ,"}\n" ,"if { $batchmode != \"defined\" } {\n" ,"catch {\n" ,"wm withdraw .\n" ,"wm title . $progname\n" ,"wm geometry . =850x600\n" ,"wm minsize . 400 300\n" ,"}\n" ,"}\n" ,"set drawmode rotate\n" ,"set selectvisual geometry\n" ,"set dirname .\n" ,"set loadgeomtypevar \"All Geometry types\"\n" ,"set basefilename filename\n" ,"set meshoptions.fineness 3\n" ,"set meshoptions.firststep ag\n" ,"set meshoptions.laststep ov\n" ,"set options.memory 0\n" ,"set options.localh 1\n" ,"set options.delaunay 1\n" ,"set options.checkoverlap 1\n" ,"set options.checkoverlappingboundary 0\n" ,"set options.checkchartboundary 1\n" ,"set options.startinsurface 0\n" ,"set options.blockfill 1\n" ,"set options.debugmode 0\n" ,"set options.dooptimize 1\n" ,"set options.parthread 1\n" ,"set options.elsizeweight 0.2\n" ,"set options.secondorder 0\n" ,"set options.elementorder 1\n" ,"set options.quad 0\n" ,"set options.try_hexes 0\n" ,"set options.inverttets 0\n" ,"set options.inverttrigs 0\n" ,"set options.autozrefine 0\n" ,"set options.meshsize 1000\n" ,"set options.minmeshsize 0\n" ,"set options.curvaturesafety 2\n" ,"set options.segmentsperedge 2\n" ,"set options.meshsizefilename \"\"\n" ,"set options.badellimit 175\n" ,"set options.optsteps2d 3\n" ,"set options.optsteps3d 5\n" ,"set options.opterrpow 2\n" ,"set options.grading 0.5\n" ,"set options.printmsg 2\n" ,"set debug.slowchecks 0\n" ,"set debug.debugoutput 0\n" ,"set debug.haltexistingline 0\n" ,"set debug.haltoverlap 0\n" ,"set debug.haltsuccess 0\n" ,"set debug.haltnosuccess 0\n" ,"set debug.haltlargequalclass 0\n" ,"set debug.haltsegment 0\n" ,"set debug.haltnode 0\n" ,"set debug.haltface 0\n" ,"set debug.haltfacenr 0\n" ,"set debug.haltsegmentp1 0\n" ,"set debug.haltsegmentp2 0\n" ,"set geooptions.drawcsg 1\n" ,"set geooptions.detail 0.001\n" ,"set geooptions.accuracy 1e-6\n" ,"set geooptions.facets 20\n" ,"set geooptions.minx -1000\n" ,"set geooptions.miny -1000\n" ,"set geooptions.minz -1000\n" ,"set geooptions.maxx 1000\n" ,"set geooptions.maxy 1000\n" ,"set geooptions.maxz 1000\n" ,"set viewqualityplot 0\n" ,"set memuseplot 0\n" ,"set viewrotatebutton 0\n" ,"set showsensitivehelp 0\n" ,"set showhelpline 0\n" ,"set viewoptions.specpointvlen 0.3\n" ,"set viewoptions.light.amb 0.3\n" ,"set viewoptions.light.diff 0.7\n" ,"set viewoptions.light.spec 1\n" ,"set viewoptions.light.locviewer 0\n" ,"set viewoptions.mat.shininess 50\n" ,"set viewoptions.mat.transp 0.3\n" ,"set viewoptions.colormeshsize 0\n" ,"set viewoptions.whitebackground 1\n" ,"set viewoptions.drawcoordinatecross 1\n" ,"set viewoptions.drawcolorbar 1\n" ,"set viewoptions.drawnetgenlogo 1\n" ,"set viewoptions.stereo 0\n" ,"set viewoptions.shrink 1\n" ,"set viewoptions.drawfilledtrigs 1\n" ,"set viewoptions.drawedges 0\n" ,"set viewoptions.drawbadels 0\n" ,"set viewoptions.centerpoint 0\n" ,"set viewoptions.drawelement 0\n" ,"set viewoptions.drawoutline 1\n" ,"set viewoptions.drawtets 0\n" ,"set viewoptions.drawtetsdomain 0\n" ,"set viewoptions.drawprisms 0\n" ,"set viewoptions.drawpyramids 0\n" ,"set viewoptions.drawhexes 0\n" ,"set viewoptions.drawidentified 0\n" ,"set viewoptions.drawpointnumbers 0\n" ,"set viewoptions.drawedgenumbers 0\n" ,"set viewoptions.drawfacenumbers 0\n" ,"set viewoptions.drawelementnumbers 0\n" ,"set viewoptions.drawdomainsurf 0\n" ,"set viewoptions.drawededges 1\n" ,"set viewoptions.drawedpoints 1\n" ,"set viewoptions.drawedpointnrs 0\n" ,"set viewoptions.drawedtangents 0\n" ,"set viewoptions.drawededgenrs 0\n" ,"set viewoptions.drawmetispartition 0\n" ,"set viewoptions.drawcurveproj 0\n" ,"set viewoptions.drawcurveprojedge 1\n" ,"set viewoptions.clipping.nx 0\n" ,"set viewoptions.clipping.ny 1\n" ,"set viewoptions.clipping.nz 0\n" ,"set viewoptions.clipping.dist 0\n" ,"set viewoptions.clipping.dist2 0\n" ,"set viewoptions.clipping.enable 0\n" ,"set viewoptions.clipping.onlydomain 0\n" ,"set viewoptions.clipping.notdomain 0\n" ,"set viewoptions.usecentercoords 0\n" ,"set viewoptions.centerx 0\n" ,"set viewoptions.centery 0\n" ,"set viewoptions.centerz 0\n" ,"set viewoptions.drawspecpoint 0\n" ,"set viewoptions.specpointx 0\n" ,"set viewoptions.specpointy 0\n" ,"set viewoptions.specpointz 0\n" ,"set stloptions.showtrias 0\n" ,"set stloptions.showfilledtrias 1\n" ,"set stloptions.showedges 1\n" ,"set stloptions.showmarktrias 0\n" ,"set stloptions.showactivechart 0\n" ,"set stloptions.yangle 30\n" ,"set stloptions.contyangle 20\n" ,"set stloptions.edgecornerangle 60\n" ,"set stloptions.chartangle 15\n" ,"set stloptions.outerchartangle 70\n" ,"set stloptions.usesearchtree 0\n" ,"set stloptions.chartnumber 1\n" ,"set stloptions.charttrignumber 1\n" ,"set stloptions.chartnumberoffset 0\n" ,"set stloptions.atlasminh 0.1\n" ,"set stloptions.resthsurfcurvfac 2\n" ,"set stloptions.resthsurfcurvenable 0\n" ,"set stloptions.resthatlasfac 2\n" ,"set stloptions.resthatlasenable 1\n" ,"set stloptions.resthchartdistfac 1.2\n" ,"set stloptions.resthchartdistenable 1\n" ,"set stloptions.resthlinelengthfac 0.5\n" ,"set stloptions.resthlinelengthenable 1\n" ,"set stloptions.resthcloseedgefac 1\n" ,"set stloptions.resthcloseedgeenable 1\n" ,"set stloptions.resthminedgelen 0.01\n" ,"set stloptions.resthminedgelenenable 1\n" ,"set stloptions.resthedgeanglefac 1\n" ,"set stloptions.resthedgeangleenable 0\n" ,"set stloptions.resthsurfmeshcurvfac 1\n" ,"set stloptions.resthsurfmeshcurvenable 0\n" ,"set stloptions.recalchopt 1\n" ,"set stldoctor.drawmeshededges 1\n" ,"set stldoctor.geom_tol_fact 0.000001\n" ,"set stldoctor.useexternaledges 0\n" ,"set stldoctor.showfaces 0\n" ,"set stldoctor.conecheck 1\n" ,"set stldoctor.spiralcheck 1\n" ,"set stldoctor.selecttrig 0\n" ,"set stldoctor.selectmode 1\n" ,"set stldoctor.longlinefact 0\n" ,"set stldoctor.showexcluded 1\n" ,"set stldoctor.edgeselectmode 0\n" ,"set stldoctor.nodeofseltrig 1\n" ,"set stldoctor.showtouchedtrigchart 0\n" ,"set stldoctor.showedgecornerpoints 0\n" ,"set stldoctor.showmarkedtrigs 1\n" ,"set stldoctor.dirtytrigfact 0.01\n" ,"set stldoctor.smoothangle 90\n" ,"set stldoctor.selectwithmouse 1\n" ,"set stldoctor.showvicinity 0\n" ,"set stldoctor.vicinity 50\n" ,"set stldoctor.smoothnormalsweight 0.2\n" ,"set occoptions.showvolumenr 0\n" ,"set occoptions.showsurfaces 1\n" ,"set occoptions.showedges 1\n" ,"set occoptions.showsolidnr 0\n" ,"set occoptions.showsolidnr2 0\n" ,"set occoptions.visproblemfaces 0\n" ,"set occoptions.zoomtohighlightedentity 0\n" ,"set occoptions.deflection 1\n" ,"set occoptions.tolerance 1e-3\n" ,"set occoptions.fixsmalledges 1\n" ,"set occoptions.fixspotstripfaces 1\n" ,"set occoptions.sewfaces 1\n" ,"set occoptions.makesolids 1\n" ,"set occoptions.splitpartitions 0\n" ,"set meshdoctor.active 0\n" ,"set meshdoctor.markedgedist 1\n" ,"set status_np 0\n" ,"set status_ne 0\n" ,"set status_nse 0\n" ,"set status_working \" \"\n" ,"set status_task \" \"\n" ,"set status_percent 0\n" ,"set status_filename 0\n" ,"set status_tetqualclasses \"10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40\"\n" ,"set exportfiletype \"Neutral Format\"\n" ,"set preproc.facenr 0\n" ,"set preproc.selectmode query\n" ,"set preproc.numtrig 0\n" ,"set mem_moveable 0\n" ,"set multithread_pause 0\n" ,"set multithread_testmode 0\n" ,"set multithread_redraw 0\n" ,"set multithread_drawing 0\n" ,"set multithread_terminate 0\n" ,"set multithread_running 0\n" ,"set level 0\n" ,"set tablesforoutput {}\n" ,"set optlist {\n" ,"options.localh\n" ,"options.delaunay\n" ,"options.checkoverlap\n" ,"options.startinsurface\n" ,"options.blockfill\n" ,"options.dooptimize\n" ,"options.elsizeweight\n" ,"options.meshsize\n" ,"options.minmeshsize\n" ,"options.curvaturesafety\n" ,"options.optsteps2d\n" ,"options.optsteps3d\n" ,"options.secondorder\n" ,"}\n" ,"set visoptions.usetexture 1\n" ,"set visoptions.invcolor 0\n" ,"set visoptions.imaginary 0\n" ,"set visoptions.lineartexture 0\n" ,"set visoptions.numtexturecols 16\n" ,"set visoptions.showclipsolution 1\n" ,"set visoptions.showsurfacesolution 0\n" ,"set visoptions.drawfieldlines 0\n" ,"set visoptions.drawpointcurves 1\n" ,"set visoptions.numfieldlines 100\n" ,"set visoptions.fieldlinesrandomstart 0\n" ,"set visoptions.fieldlinesstartarea box\n" ,"set visoptions.fieldlinesstartareap1x 1\n" ,"set visoptions.fieldlinesstartareap1y 1\n" ,"set visoptions.fieldlinesstartareap1z 1\n" ,"set visoptions.fieldlinesstartareap2x 0\n" ,"set visoptions.fieldlinesstartareap2y 0\n" ,"set visoptions.fieldlinesstartareap2z 0\n" ,"set visoptions.fieldlinesstartface -1\n" ,"set visoptions.fieldlinesfilename none\n" ,"set visoptions.fieldlinestolerance 0.0005\n" ,"set visoptions.fieldlinesrktype crungekutta\n" ,"set visoptions.fieldlineslength 0.5\n" ,"set visoptions.fieldlinesmaxpoints 500\n" ,"set visoptions.fieldlinesthickness 0.0015\n" ,"set visoptions.fieldlinesvecfunction none\n" ,"set visoptions.fieldlinesphase 0\n" ,"set visoptions.fieldlinesonlyonephase 1\n" ,"set visoptions.lineplotfile empty\n" ,"set visoptions.lineplotsource file\n" ,"set visoptions.lineplotusingx 0\n" ,"set visoptions.lineplotusingy 1\n" ,"set visoptions.lineplotautoscale 1\n" ,"set visoptions.lineplotxmin 0\n" ,"set visoptions.lineplotxmax 1\n" ,"set visoptions.lineplotymin 0\n" ,"set visoptions.lineplotymax 1\n" ,"set visoptions.lineplotcurrentnum -1\n" ,"set visoptions.lineplotinfos \"\"\n" ,"set visoptions.lineplotselected none\n" ,"set visoptions.lineplotselector \"\"\n" ,"set visoptions.lineplotcolor red\n" ,"set visoptions.lineplotsizex 500\n" ,"set visoptions.lineplotsizey 400\n" ,"set visoptions.lineplotselectedeval 0\n" ,"set visoptions.lineplotdatadescr \"column1 column2 column3\"\n" ,"set visoptions.lineplotxcoordselector \"\"\n" ,"set visoptions.lineplotycoordselector \"\"\n" ,"set visoptions.evaluatefilenames none\n" ,"set visoptions.evaluatefiledescriptions none\n" ,"set visoptions.clipsolution none\n" ,"set visoptions.scalfunction none\n" ,"set visoptions.vecfunction none\n" ,"set visoptions.evaluate abs\n" ,"set visoptions.gridsize 20\n" ,"set visoptions.xoffset 0\n" ,"set visoptions.yoffset 0\n" ,"set visoptions.autoscale 1\n" ,"set visoptions.redrawperiodic 0\n" ,"set visoptions.logscale 0\n" ,"set visoptions.mminval 0\n" ,"set visoptions.mmaxval 1\n" ,"set visoptions.isolines 0\n" ,"set visoptions.isosurf 0\n" ,"set visoptions.subdivisions 1\n" ,"set visoptions.numiso 10\n" ,"set visoptions.autoredraw 0\n" ,"set visoptions.autoredrawtime 2\n" ,"set visoptions.simulationtime 0\n" ,"set visoptions.multidimcomponent 0\n" ,"set visoptions.deformation 0\n" ,"set visoptions.scaledeform1 1\n" ,"set visoptions.scaledeform2 1\n" ,"set parallel_netgen 0\n" ,"set optfilename [file join $nguserdir ng.opt]\n" ,"set inifilename [file join $nguserdir ng.ini]\n" ,"set meshinifilename [file join $nguserdir ngmesh.ini]\n" ,"global env\n" ,"if { [llength [array names env NG_OPT]] == 1 } {\n" ,"if { [string length $env(NG_OPT)] > 0 } {\n" ,"set optfilename $env(NG_OPT)\n" ,"}\n" ,"}\n" ,"if { [file exists $optfilename] == 1 } {\n" ,"set datei [open $optfilename r]\n" ,"while { [gets $datei line] >= 0 } {\n" ,"set [lindex $line 0] [lindex $line 1]\n" ,"}\n" ,"close $datei\n" ,"} {\n" ,"puts \"optfile $optfilename does not exist - using default values\"\n" ,"}\n" ,"proc saveoptions { } {\n" ,"uplevel 1 {\n" ,"set file $optfilename\n" ,"if {$file != \"\"} {\n" ,"set datei [open $file w]\n" ,"puts $datei \"dirname ${dirname}\"\n" ,"puts $datei \"loadgeomtypevar \\\"${loadgeomtypevar}\\\"\"\n" ,"puts $datei \"exportfiletype \\\"${exportfiletype}\\\"\"\n" ,"puts $datei \"meshoptions.fineness ${meshoptions.fineness}\"\n" ,"puts $datei \"meshoptions.firststep ${meshoptions.firststep}\"\n" ,"puts $datei \"meshoptions.laststep ${meshoptions.laststep}\"\n" ,"puts $datei \"options.localh ${options.localh}\"\n" ,"puts $datei \"options.delaunay ${options.delaunay}\"\n" ,"puts $datei \"options.checkoverlap ${options.checkoverlap}\"\n" ,"puts $datei \"options.checkchartboundary ${options.checkchartboundary}\"\n" ,"puts $datei \"options.startinsurface ${options.startinsurface}\"\n" ,"puts $datei \"options.blockfill ${options.blockfill}\"\n" ,"puts $datei \"options.debugmode ${options.debugmode}\"\n" ,"puts $datei \"options.dooptimize ${options.dooptimize}\"\n" ,"puts $datei \"options.parthread ${options.parthread}\"\n" ,"puts $datei \"options.elsizeweight ${options.elsizeweight}\"\n" ,"puts $datei \"options.secondorder ${options.secondorder}\"\n" ,"puts $datei \"options.elementorder ${options.elementorder}\"\n" ,"puts $datei \"options.quad ${options.quad}\"\n" ,"puts $datei \"options.try_hexes ${options.try_hexes}\"\n" ,"puts $datei \"options.inverttets ${options.inverttets}\"\n" ,"puts $datei \"options.inverttrigs ${options.inverttrigs}\"\n" ,"puts $datei \"options.autozrefine ${options.autozrefine}\"\n" ,"puts $datei \"options.meshsize ${options.meshsize}\"\n" ,"puts $datei \"options.minmeshsize ${options.minmeshsize}\"\n" ,"puts $datei \"options.curvaturesafety ${options.curvaturesafety}\"\n" ,"puts $datei \"options.segmentsperedge ${options.segmentsperedge}\"\n" ,"puts $datei \"options.meshsizefilename ${options.meshsizefilename}\"\n" ,"puts $datei \"options.badellimit ${options.badellimit}\"\n" ,"puts $datei \"options.optsteps2d ${options.optsteps2d}\"\n" ,"puts $datei \"options.optsteps3d ${options.optsteps3d}\"\n" ,"puts $datei \"options.opterrpow ${options.opterrpow}\"\n" ,"puts $datei \"options.grading ${options.grading}\"\n" ,"puts $datei \"options.printmsg ${options.printmsg}\"\n" ,"puts $datei \"geooptions.drawcsg ${geooptions.drawcsg}\"\n" ,"puts $datei \"geooptions.detail ${geooptions.detail}\"\n" ,"puts $datei \"geooptions.accuracy ${geooptions.accuracy}\"\n" ,"puts $datei \"geooptions.facets ${geooptions.facets}\"\n" ,"puts $datei \"geooptions.minx ${geooptions.minx}\"\n" ,"puts $datei \"geooptions.miny ${geooptions.miny}\"\n" ,"puts $datei \"geooptions.minz ${geooptions.minz}\"\n" ,"puts $datei \"geooptions.maxx ${geooptions.maxx}\"\n" ,"puts $datei \"geooptions.maxy ${geooptions.maxy}\"\n" ,"puts $datei \"geooptions.maxz ${geooptions.maxz}\"\n" ,"puts $datei \"viewoptions.specpointvlen ${viewoptions.specpointvlen}\"\n" ,"puts $datei \"viewoptions.light.amb ${viewoptions.light.amb}\"\n" ,"puts $datei \"viewoptions.light.diff ${viewoptions.light.diff}\"\n" ,"puts $datei \"viewoptions.light.spec ${viewoptions.light.spec}\"\n" ,"puts $datei \"viewoptions.light.locviewer ${viewoptions.light.locviewer}\"\n" ,"puts $datei \"viewoptions.mat.shininess ${viewoptions.mat.shininess}\"\n" ,"puts $datei \"viewoptions.mat.transp ${viewoptions.mat.transp}\"\n" ,"puts $datei \"viewoptions.colormeshsize ${viewoptions.colormeshsize}\"\n" ,"puts $datei \"viewoptions.whitebackground ${viewoptions.whitebackground}\"\n" ,"puts $datei \"viewoptions.drawcolorbar ${viewoptions.drawcolorbar}\"\n" ,"puts $datei \"viewoptions.drawcoordinatecross ${viewoptions.drawcoordinatecross}\"\n" ,"puts $datei \"viewoptions.drawnetgenlogo ${viewoptions.drawnetgenlogo}\"\n" ,"puts $datei \"viewoptions.stereo ${viewoptions.stereo}\"\n" ,"puts $datei \"viewoptions.drawfilledtrigs ${viewoptions.drawfilledtrigs}\"\n" ,"puts $datei \"viewoptions.drawedges ${viewoptions.drawedges}\"\n" ,"puts $datei \"viewoptions.drawbadels ${viewoptions.drawbadels}\"\n" ,"puts $datei \"viewoptions.centerpoint ${viewoptions.centerpoint}\"\n" ,"puts $datei \"viewoptions.drawelement ${viewoptions.drawelement}\"\n" ,"puts $datei \"viewoptions.drawoutline ${viewoptions.drawoutline}\"\n" ,"puts $datei \"viewoptions.drawtets ${viewoptions.drawtets}\"\n" ,"puts $datei \"viewoptions.drawprisms ${viewoptions.drawprisms}\"\n" ,"puts $datei \"viewoptions.drawpyramids ${viewoptions.drawpyramids}\"\n" ,"puts $datei \"viewoptions.drawhexes ${viewoptions.drawhexes}\"\n" ,"puts $datei \"viewoptions.drawidentified ${viewoptions.drawidentified}\"\n" ,"puts $datei \"viewoptions.drawpointnumbers ${viewoptions.drawpointnumbers}\"\n" ,"puts $datei \"viewoptions.drawededges ${viewoptions.drawededges}\"\n" ,"puts $datei \"viewoptions.drawedpoints ${viewoptions.drawedpoints}\"\n" ,"puts $datei \"viewoptions.drawedpointnrs ${viewoptions.drawedpointnrs}\"\n" ,"puts $datei \"viewoptions.drawedtangents ${viewoptions.drawedtangents}\"\n" ,"puts $datei \"viewoptions.shrink ${viewoptions.shrink}\"\n" ,"puts $datei \"stloptions.showtrias ${stloptions.showtrias}\"\n" ,"puts $datei \"stloptions.showfilledtrias ${stloptions.showfilledtrias}\"\n" ,"puts $datei \"stloptions.showedges ${stloptions.showedges}\"\n" ,"puts $datei \"stloptions.showmarktrias ${stloptions.showmarktrias}\"\n" ,"puts $datei \"stloptions.showactivechart ${stloptions.showactivechart}\"\n" ,"puts $datei \"stloptions.yangle ${stloptions.yangle}\"\n" ,"puts $datei \"stloptions.contyangle ${stloptions.contyangle}\"\n" ,"puts $datei \"stloptions.edgecornerangle ${stloptions.edgecornerangle}\"\n" ,"puts $datei \"stloptions.chartangle ${stloptions.chartangle}\"\n" ,"puts $datei \"stloptions.outerchartangle ${stloptions.outerchartangle}\"\n" ,"puts $datei \"stloptions.usesearchtree ${stloptions.usesearchtree}\"\n" ,"puts $datei \"stloptions.chartnumber ${stloptions.chartnumber}\"\n" ,"puts $datei \"stloptions.charttrignumber ${stloptions.charttrignumber}\"\n" ,"puts $datei \"stloptions.chartnumberoffset ${stloptions.chartnumberoffset}\"\n" ,"puts $datei \"stloptions.atlasminh ${stloptions.atlasminh}\"\n" ,"puts $datei \"stloptions.resthsurfcurvfac ${stloptions.resthsurfcurvfac}\"\n" ,"puts $datei \"stloptions.resthsurfcurvenable ${stloptions.resthsurfcurvenable}\"\n" ,"puts $datei \"stloptions.resthatlasfac ${stloptions.resthatlasfac}\"\n" ,"puts $datei \"stloptions.resthatlasenable ${stloptions.resthatlasenable}\"\n" ,"puts $datei \"stloptions.resthchartdistfac ${stloptions.resthchartdistfac}\"\n" ,"puts $datei \"stloptions.resthchartdistenable ${stloptions.resthchartdistenable}\"\n" ,"puts $datei \"stloptions.resthlinelengthfac ${stloptions.resthlinelengthfac}\"\n" ,"puts $datei \"stloptions.resthlinelengthenable ${stloptions.resthlinelengthenable}\"\n" ,"puts $datei \"stloptions.resthminedgelen ${stloptions.resthminedgelen}\"\n" ,"puts $datei \"stloptions.resthminedgelenenable ${stloptions.resthminedgelenenable}\"\n" ,"puts $datei \"stloptions.resthcloseedgefac ${stloptions.resthcloseedgefac}\"\n" ,"puts $datei \"stloptions.resthcloseedgeenable ${stloptions.resthcloseedgeenable}\"\n" ,"puts $datei \"stloptions.resthedgeanglefac ${stloptions.resthedgeanglefac}\"\n" ,"puts $datei \"stloptions.resthedgeangleenable ${stloptions.resthedgeangleenable}\"\n" ,"puts $datei \"stloptions.resthsurfmeshcurvfac ${stloptions.resthsurfmeshcurvfac}\"\n" ,"puts $datei \"stloptions.resthsurfmeshcurvenable ${stloptions.resthsurfmeshcurvenable}\"\n" ,"puts $datei \"stloptions.recalchopt ${stloptions.recalchopt}\"\n" ,"puts $datei \"visoptions.subdivisions ${visoptions.subdivisions}\"\n" ,"puts $datei \"visoptions.autoredraw ${visoptions.autoredraw}\"\n" ,"puts $datei \"visoptions.autoredrawtime ${visoptions.autoredrawtime}\"\n" ,"if { [info exists trafooptions.solver] == 1 } {\n" ,"puts $datei \"trafooptions.solver ${trafooptions.solver}\"\n" ,"puts $datei \"trafooptions.levels ${trafooptions.levels}\"\n" ,"puts $datei \"trafooptions.linits ${trafooptions.linits}\"\n" ,"puts $datei \"trafooptions.nonlinits ${trafooptions.nonlinits}\"\n" ,"puts $datei \"trafooptions.stabcurrent ${trafooptions.stabcurrent}\"\n" ,"puts $datei \"trafooptions.checkcond ${trafooptions.checkcond}\"\n" ,"puts $datei \"trafooptions.maxdirect ${trafooptions.maxdirect}\"\n" ,"puts $datei \"trafooptions.secondorder ${trafooptions.secondorder}\"\n" ,"puts $datei \"trafooptions.homogenizedcore ${trafooptions.homogenizedcore}\"\n" ,"puts $datei \"trafooptions.ordercore ${trafooptions.ordercore}\"\n" ,"puts $datei \"trafooptions.simplecurrents ${trafooptions.simplecurrents}\"\n" ,"puts $datei \"trafooptions.assemblecomplexmatrix ${trafooptions.assemblecomplexmatrix}\"\n" ,"puts $datei \"trafooptions.meshcasing ${trafooptions.meshcasing}\"\n" ,"puts $datei \"trafooptions.meshcore ${trafooptions.meshcore}\"\n" ,"puts $datei \"trafooptions.meshclumps ${trafooptions.meshclumps}\"\n" ,"puts $datei \"trafooptions.meshshields ${trafooptions.meshshields}\"\n" ,"puts $datei \"trafooptions.meshcoils ${trafooptions.meshcoils}\"\n" ,"puts $datei \"trafooptions.bcmdirectory ${trafooptions.bcmdirectory}\"\n" ,"puts $datei \"trafooptions.lossdensityfile ${trafooptions.lossdensityfile}\"\n" ,"}\n" ,"if { [info exists smalltrafomodell.tankheight] == 1 } {\n" ,"puts $datei \"smalltrafomodell.tankheight ${smalltrafomodell.tankheight}\"\n" ,"puts $datei \"smalltrafomodell.tankwidth ${smalltrafomodell.tankwidth}\"\n" ,"puts $datei \"smalltrafomodell.tanklength ${smalltrafomodell.tanklength}\"\n" ,"puts $datei \"smalltrafomodell.corewidth ${smalltrafomodell.corewidth}\"\n" ,"puts $datei \"smalltrafomodell.windowheight ${smalltrafomodell.windowheight}\"\n" ,"puts $datei \"smalltrafomodell.limbdistance ${smalltrafomodell.limbdistance}\"\n" ,"puts $datei \"smalltrafomodell.xposcore ${smalltrafomodell.xposcore}\"\n" ,"puts $datei \"smalltrafomodell.yposcore ${smalltrafomodell.yposcore}\"\n" ,"puts $datei \"smalltrafomodell.zposcore ${smalltrafomodell.zposcore}\"\n" ,"puts $datei \"smalltrafomodell.leakagefluxguidethickness ${smalltrafomodell.leakagefluxguidethickness}\"\n" ,"puts $datei \"smalltrafomodell.leakagefluxguidewidth ${smalltrafomodell.leakagefluxguidewidth}\"\n" ,"puts $datei \"smalltrafomodell.leakagefluxguidezposition ${smalltrafomodell.leakagefluxguidezposition}\"\n" ,"puts $datei \"smalltrafomodell.limbcoil.1 ${smalltrafomodell.limbcoil.1}\"\n" ,"puts $datei \"smalltrafomodell.ricoil.1 ${smalltrafomodell.ricoil.1}\"\n" ,"puts $datei \"smalltrafomodell.rocoil.1 ${smalltrafomodell.rocoil.1}\"\n" ,"puts $datei \"smalltrafomodell.zposcoil.1 ${smalltrafomodell.zposcoil.1}\"\n" ,"puts $datei \"smalltrafomodell.heightcoil.1 ${smalltrafomodell.heightcoil.1}\"\n" ,"puts $datei \"smalltrafomodell.currentcoil.1 ${smalltrafomodell.currentcoil.1}\"\n" ,"puts $datei \"smalltrafomodell.nturnscoil.1 ${smalltrafomodell.nturnscoil.1}\"\n" ,"puts $datei \"smalltrafomodell.limbcoil.2 ${smalltrafomodell.limbcoil.2}\"\n" ,"puts $datei \"smalltrafomodell.ricoil.2 ${smalltrafomodell.ricoil.2}\"\n" ,"puts $datei \"smalltrafomodell.rocoil.2 ${smalltrafomodell.rocoil.2}\"\n" ,"puts $datei \"smalltrafomodell.zposcoil.2 ${smalltrafomodell.zposcoil.2}\"\n" ,"puts $datei \"smalltrafomodell.heightcoil.2 ${smalltrafomodell.heightcoil.2}\"\n" ,"puts $datei \"smalltrafomodell.currentcoil.2 ${smalltrafomodell.currentcoil.2}\"\n" ,"puts $datei \"smalltrafomodell.nturnscoil.2 ${smalltrafomodell.nturnscoil.2}\"\n" ,"puts $datei \"smalltrafomodell.limbcoil.3 ${smalltrafomodell.limbcoil.3}\"\n" ,"puts $datei \"smalltrafomodell.ricoil.3 ${smalltrafomodell.ricoil.3}\"\n" ,"puts $datei \"smalltrafomodell.rocoil.3 ${smalltrafomodell.rocoil.3}\"\n" ,"puts $datei \"smalltrafomodell.zposcoil.3 ${smalltrafomodell.zposcoil.3}\"\n" ,"puts $datei \"smalltrafomodell.heightcoil.3 ${smalltrafomodell.heightcoil.3}\"\n" ,"puts $datei \"smalltrafomodell.currentcoil.3 ${smalltrafomodell.currentcoil.3}\"\n" ,"puts $datei \"smalltrafomodell.nturnscoil.3 ${smalltrafomodell.nturnscoil.3}\"\n" ,"puts $datei \"smalltrafomodell.limbcoil.4 ${smalltrafomodell.limbcoil.4}\"\n" ,"puts $datei \"smalltrafomodell.ricoil.4 ${smalltrafomodell.ricoil.4}\"\n" ,"puts $datei \"smalltrafomodell.rocoil.4 ${smalltrafomodell.rocoil.4}\"\n" ,"puts $datei \"smalltrafomodell.zposcoil.4 ${smalltrafomodell.zposcoil.4}\"\n" ,"puts $datei \"smalltrafomodell.heightcoil.4 ${smalltrafomodell.heightcoil.4}\"\n" ,"puts $datei \"smalltrafomodell.currentcoil.4 ${smalltrafomodell.currentcoil.4}\"\n" ,"puts $datei \"smalltrafomodell.nturnscoil.4 ${smalltrafomodell.nturnscoil.4}\"\n" ,"puts $datei \"smalltrafomodell.limbcoil.5 ${smalltrafomodell.limbcoil.5}\"\n" ,"puts $datei \"smalltrafomodell.ricoil.5 ${smalltrafomodell.ricoil.5}\"\n" ,"puts $datei \"smalltrafomodell.rocoil.5 ${smalltrafomodell.rocoil.5}\"\n" ,"puts $datei \"smalltrafomodell.zposcoil.5 ${smalltrafomodell.zposcoil.5}\"\n" ,"puts $datei \"smalltrafomodell.heightcoil.5 ${smalltrafomodell.heightcoil.5}\"\n" ,"puts $datei \"smalltrafomodell.currentcoil.5 ${smalltrafomodell.currentcoil.5}\"\n" ,"puts $datei \"smalltrafomodell.nturnscoil.5 ${smalltrafomodell.nturnscoil.5}\"\n" ,"puts $datei \"smalltrafomodell.limbcoil.6 ${smalltrafomodell.limbcoil.6}\"\n" ,"puts $datei \"smalltrafomodell.ricoil.6 ${smalltrafomodell.ricoil.6}\"\n" ,"puts $datei \"smalltrafomodell.rocoil.6 ${smalltrafomodell.rocoil.6}\"\n" ,"puts $datei \"smalltrafomodell.zposcoil.6 ${smalltrafomodell.zposcoil.6}\"\n" ,"puts $datei \"smalltrafomodell.heightcoil.6 ${smalltrafomodell.heightcoil.6}\"\n" ,"puts $datei \"smalltrafomodell.currentcoil.6 ${smalltrafomodell.currentcoil.6}\"\n" ,"puts $datei \"smalltrafomodell.nturnscoil.6 ${smalltrafomodell.nturnscoil.6}\"\n" ,"puts $datei \"smalltrafomodell.limbtest.1 ${smalltrafomodell.limbtest.1}\"\n" ,"puts $datei \"smalltrafomodell.heighttest.1 ${smalltrafomodell.heighttest.1}\"\n" ,"puts $datei \"smalltrafomodell.widthtest.1 ${smalltrafomodell.widthtest.1}\"\n" ,"puts $datei \"smalltrafomodell.rtest.1 ${smalltrafomodell.rtest.1}\"\n" ,"puts $datei \"smalltrafomodell.zpostest.1 ${smalltrafomodell.zpostest.1}\"\n" ,"puts $datei \"smalltrafomodell.edgeradiustest.1 ${smalltrafomodell.edgeradiustest.1}\"\n" ,"puts $datei \"smalltrafomodell.finetest.1 ${smalltrafomodell.finetest.1}\"\n" ,"puts $datei \"smalltrafomodell.conductivetest.1 ${smalltrafomodell.conductivetest.1}\"\n" ,"puts $datei \"smalltrafomodell.limbtest.2 ${smalltrafomodell.limbtest.2}\"\n" ,"puts $datei \"smalltrafomodell.heighttest.2 ${smalltrafomodell.heighttest.2}\"\n" ,"puts $datei \"smalltrafomodell.widthtest.2 ${smalltrafomodell.widthtest.2}\"\n" ,"puts $datei \"smalltrafomodell.rtest.2 ${smalltrafomodell.rtest.2}\"\n" ,"puts $datei \"smalltrafomodell.zpostest.2 ${smalltrafomodell.zpostest.2}\"\n" ,"puts $datei \"smalltrafomodell.edgeradiustest.2 ${smalltrafomodell.edgeradiustest.2}\"\n" ,"puts $datei \"smalltrafomodell.finetest.2 ${smalltrafomodell.finetest.2}\"\n" ,"puts $datei \"smalltrafomodell.conductivetest.2 ${smalltrafomodell.conductivetest.2}\"\n" ,"puts $datei \"smalltrafomodell.limbtest.3 ${smalltrafomodell.limbtest.3}\"\n" ,"puts $datei \"smalltrafomodell.heighttest.3 ${smalltrafomodell.heighttest.3}\"\n" ,"puts $datei \"smalltrafomodell.widthtest.3 ${smalltrafomodell.widthtest.3}\"\n" ,"puts $datei \"smalltrafomodell.rtest.3 ${smalltrafomodell.rtest.3}\"\n" ,"puts $datei \"smalltrafomodell.zpostest.3 ${smalltrafomodell.zpostest.3}\"\n" ,"puts $datei \"smalltrafomodell.edgeradiustest.3 ${smalltrafomodell.edgeradiustest.3}\"\n" ,"puts $datei \"smalltrafomodell.finetest.3 ${smalltrafomodell.finetest.3}\"\n" ,"puts $datei \"smalltrafomodell.conductivetest.3 ${smalltrafomodell.conductivetest.3}\"\n" ,"puts $datei \"smalltrafomodell.limbtest.4 ${smalltrafomodell.limbtest.4}\"\n" ,"puts $datei \"smalltrafomodell.heighttest.4 ${smalltrafomodell.heighttest.4}\"\n" ,"puts $datei \"smalltrafomodell.widthtest.4 ${smalltrafomodell.widthtest.4}\"\n" ,"puts $datei \"smalltrafomodell.rtest.4 ${smalltrafomodell.rtest.4}\"\n" ,"puts $datei \"smalltrafomodell.zpostest.4 ${smalltrafomodell.zpostest.4}\"\n" ,"puts $datei \"smalltrafomodell.edgeradiustest.4 ${smalltrafomodell.edgeradiustest.4}\"\n" ,"puts $datei \"smalltrafomodell.finetest.4 ${smalltrafomodell.finetest.4}\"\n" ,"puts $datei \"smalltrafomodell.conductivetest.4 ${smalltrafomodell.conductivetest.4}\"\n" ,"puts $datei \"smalltrafomodell.nperitest ${smalltrafomodell.nperitest}\"\n" ,"puts $datei \"smalltrafomodell.filename ${smalltrafomodell.filename}\"\n" ,"puts $datei \"smalltrafomodell.murlfguide ${smalltrafomodell.murlfguide}\"\n" ,"puts $datei \"smalltrafomodell.murtestwire ${smalltrafomodell.murtestwire}\"\n" ,"puts $datei \"smalltrafomodell.murcore ${smalltrafomodell.murcore}\"\n" ,"puts $datei \"smalltrafomodell.kappalfguide ${smalltrafomodell.kappalfguide}\"\n" ,"puts $datei \"smalltrafomodell.kappatestwire ${smalltrafomodell.kappatestwire}\"\n" ,"puts $datei \"smalltrafomodell.kappacore ${smalltrafomodell.kappacore}\"\n" ,"}\n" ,"close $datei\n" ,"}\n" ,"}\n" ,"}\n" ,"proc saveinifile { } {\n" ,"global inifilename\n" ,"if {[catch { set datei [open $inifilename w] } result ]} {\n" ,"puts \"cannot write file $inifilename\"\n" ,"} {\n" ,"for { set i [.ngmenu.file.recent index last] } { $i >= 0 } { incr i -1 } {\n" ,"puts $datei \"recentfile \\\"[.ngmenu.file.recent entrycget $i -label]\\\"\"\n" ,"}\n" ,"close $datei\n" ,"}\n" ,"}\n" ,"proc savemeshinifile { } {\n" ,"global meshinifilename\n" ,"if {[catch { set datei [open $meshinifilename w] } result ]} {\n" ,"puts \"cannot write file $meshinifilename\"\n" ,"} {\n" ,"for { set i [.ngmenu.file.recentmesh index last] } { $i >= 1 } { incr i -1 } {\n" ,"puts $datei \"recentfile \\\"[.ngmenu.file.recentmesh entrycget $i -label]\\\"\"\n" ,"}\n" ,"close $datei\n" ,"}\n" ,"}\n" ,"proc loadinifile { } {\n" ,"global inifilename\n" ,"if { [file exists $inifilename] == 1 } {\n" ,"set datei [open $inifilename r]\n" ,"while { [gets $datei line] >= 0 } {\n" ,"if {[lindex $line 0] == \"recentfile\"} {\n" ,"set filename [lindex $line 1]\n" ,"if { [file exists $filename] == 1 } {\n" ,"AddRecentFile $filename\n" ,"}\n" ,"}\n" ,"}\n" ,"close $datei\n" ,"}\n" ,"}\n" ,"proc loadmeshinifile { } {\n" ,"global meshinifilename\n" ,"if { [file exists $meshinifilename] == 1 } {\n" ,"set datei [open $meshinifilename r]\n" ,"while { [gets $datei line] >= 0 } {\n" ,"if {[lindex $line 0] == \"recentfile\"} {\n" ,"set filename [lindex $line 1]\n" ,"if { [file exists $filename] == 1 } {\n" ,"AddRecentMeshFile $filename\n" ,"}\n" ,"}\n" ,"}\n" ,"close $datei\n" ,"}\n" ,"}\n" ,"set cmdindex {}\n" ,"set hlpindex {}\n" ,"set secindex {}\n" ,"proc setgranularity { gran } {\n" ,"if {$gran == 6} { return }\n" ,"set gran [expr $gran - 1]\n" ,"global options.curvaturesafety\n" ,"set surfcurvlist { 1 1.5 2 3 5 }\n" ,"set options.curvaturesafety [lindex $surfcurvlist $gran]\n" ,"global options.segmentsperedge\n" ,"set spelist { 0.3 0.5 1 2 3 }\n" ,"set options.segmentsperedge [lindex $spelist $gran]\n" ,"global stloptions.resthsurfcurvfac\n" ,"set surfcurvfaclist { 0.25 0.5 1 1.5 3 }\n" ,"set stloptions.resthsurfcurvfac [lindex $surfcurvfaclist $gran]\n" ,"global stloptions.resthchartdistfac\n" ,"set chartdistfaclist { 0.8 1 1.5 2 5 }\n" ,"set stloptions.resthchartdistfac [lindex $chartdistfaclist $gran]\n" ,"global stloptions.resthlinelengthfac\n" ,"set linelengthfaclist { 0.2 0.35 0.5 1.5 3 }\n" ,"set stloptions.resthlinelengthfac [lindex $linelengthfaclist $gran]\n" ,"global stloptions.resthcloseedgefac\n" ,"set closeedgefaclist { 0.5 1 2 3.5 5 }\n" ,"set stloptions.resthcloseedgefac [lindex $closeedgefaclist $gran]\n" ,"global stloptions.resthminedgelen\n" ,"set minedgelenlist { 0.002 0.02 0.2 1.0 2.0 5.0 10.0 }\n" ,"set stloptions.resthminedgelen [lindex $minedgelenlist $gran]\n" ,"global stloptions.resthedgeanglefac\n" ,"set edgeanglefaclist { 0.25 0.5 1 1.5 3 }\n" ,"set stloptions.resthedgeanglefac [lindex $edgeanglefaclist $gran]\n" ,"global stloptions.resthsurfmeshcurvfac\n" ,"set surfmeshcurvlist { 1 1.5 2 3 5 }\n" ,"set stloptions.resthsurfmeshcurvfac [lindex $surfmeshcurvlist $gran]\n" ,"global options.grading\n" ,"set gradinglist { 0.7 0.5 0.3 0.2 0.1 }\n" ,"set options.grading [lindex $gradinglist $gran]\n" ,"}\n" ,"if { $batchmode != \"defined\" } {\n" ,"catch {\n" ,"if { $tcl_platform(os) eq \"Linux\" && [tk scaling] > 1.5 } {\n" ,"font create ngFont -family Helvetica\n" ,"option add *font ngFont\n" ,"ttk::style configure \".\" -font ngFont\n" ,"}\n" ,"menu .ngmenu -tearoff 0 -relief raised -bd 2\n" ,". configure -menu .ngmenu\n" ,".ngmenu add cascade -label \"File\" -menu .ngmenu.file -underline 0\n" ,".ngmenu add cascade -label \"Geometry\" -menu .ngmenu.geometry -underline 0\n" ,".ngmenu add cascade -label \"Mesh\" -menu .ngmenu.mesh -underline 0\n" ,".ngmenu add cascade -label \"View\" -menu .ngmenu.view -underline 0\n" ,".ngmenu add cascade -label \"Refinement\" -menu .ngmenu.meshsize -underline 5\n" ,"if { $userlevel == 3} {\n" ,".ngmenu add cascade -label \"Special\" -menu .ngmenu.special -underline 3\n" ,"}\n" ,".ngmenu add cascade -label \"Help\" -menu .ngmenu.help -underline 0\n" ,"menu .ngmenu.file\n" ,".ngmenu.file add command -label \"Load Geometry...\" -accelerator \"\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"All Geometry types\" { .stl .stlb .step .stp .geo .in2d .igs .iges .brep .sat} }\n" ,"{\"IGES Geometry\" {.igs .iges} }\n" ,"{\"BREP OpenCascade Geometry\" {.brep} }\n" ,"{\"STL Geometry\" {.stl} }\n" ,"{\"Binary STL Geometry\" {.stlb} }\n" ,"{\"STEP Geometry\" {.step .stp} }\n" ,"{\"Geometry file\" {.geo} }\n" ,"{\"2D Geometry\" {.in2d } }\n" ,"}\n" ,"set ACISavailable [Ng_ACISCommand isACISavailable]\n" ,"if {$ACISavailable == \"yes\" } {\n" ,"lappend types {\"ACIS Geometry\" {.sat} }\n" ,"}\n" ,"if {[catch {\n" ,"set file [tk_getOpenFile -filetypes $types -initialdir $dirname -typevariable loadgeomtypevar]\n" ,"}]} {\n" ,"set file [tk_getOpenFile -filetypes $types -initialdir $dirname]\n" ,"}\n" ,"if {$file != \"\"} {\n" ,"AddRecentFile $file\n" ,"Ng_LoadGeometry $file\n" ,"Ng_ParseGeometry\n" ,"set selectvisual geometry\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"wm title . [concat \"$progname - \" $file]\n" ,"set dirname [file dirname $file]\n" ,"set basefilename [file tail [file rootname $file]]\n" ,"if { $hasocc == \"yes\" } {\n" ,"rebuildoccdialog\n" ,"}\n" ,"}\n" ,"}\n" ,".ngmenu.file add command -label \"Save Geometry...\" \\\n" ,"-command {\n" ,"set occgeometryloaded [Ng_OCCCommand isoccgeometryloaded]\n" ,"puts $occgeometryloaded\n" ,"if {$occgeometryloaded == 1 } {\n" ,"set types {\n" ,"{\"IGES Geometry file\" {.igs} }\n" ,"{\"STEP Geometry file\" {.stp} }\n" ,"{\"STL Geometry file\" {.stl} }\n" ,"{\"STL BIN Geometry file\" {.stlb} }\n" ,"}\n" ,"} {\n" ,"set types {\n" ,"{\"STL Geometry file\" {.stl} }\n" ,"{\"STL BIN Geometry file\" {.stlb} }\n" ,"}\n" ,"}\n" ,"set ACISavailable [Ng_ACISCommand isACISavailable]\n" ,"puts $ACISavailable\n" ,"if {$ACISavailable == \"yes\" } {\n" ,"lappend types {\"ACIS Geometry\" {.sat} }\n" ,"}\n" ,"set file [tk_getSaveFile -filetypes $types -initialdir $dirname -initialfile $basefilename ]\n" ,"if {$file != \"\"} {\n" ,"Ng_SaveGeometry $file\n" ,"}\n" ,"}\n" ,".ngmenu.file add cascade -label \"Recent Files\" -menu .ngmenu.file.recent\n" ,"menu .ngmenu.file.recent -tearoff 0\n" ,"proc AddRecentFile { filename } {\n" ,"global progname\n" ,"global dirname\n" ,"catch { [.ngmenu.file.recent delete $filename] }\n" ,".ngmenu.file.recent insert 0 command -label $filename \\\n" ,"-command \"AddRecentFile {$filename};\n" ,"Ng_LoadGeometry {$filename};\n" ,"Ng_ParseGeometry;\n" ,"set selectvisual geometry;\n" ,"Ng_SetVisParameters;\n" ,"redraw;\n" ,"wm title . [concat \\\" $progname - $filename \\\"];\n" ,"set dirname {[file dirname $filename]};\n" ,"set basefilename {[file tail [file rootname $filename]]};\n" ,"rebuildoccdialog;\"\n" ,"if { [.ngmenu.file.recent index last] >= 6 } {\n" ,".ngmenu.file.recent delete last }\n" ,"saveinifile;\n" ,"}\n" ,"loadinifile;\n" ,".ngmenu.file add separator\n" ,".ngmenu.file add command -label \"Load Mesh...\" -accelerator \"\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Mesh file\" {.vol .vol.gz} } }\n" ,"set file [tk_getOpenFile -filetypes $types -defaultextension \".vol\"]\n" ,"if {$file != \"\"} {\n" ,"AddRecentMeshFile $file;\n" ,"Ng_LoadMesh $file;\n" ,"set selectvisual mesh\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"Ng_ReadStatus;\n" ,"wm title . [concat \"$progname - \" $file]\n" ,"set dirname [file dirname $file]\n" ,"set basefilename [file tail [file rootname $file]]\n" ,"}\n" ,"}\n" ,".ngmenu.file add cascade -label \"Recent Meshes\" -menu .ngmenu.file.recentmesh\n" ,"menu .ngmenu.file.recentmesh\n" ,"proc AddRecentMeshFile { filename } {\n" ,"global progname\n" ,"global dirname\n" ,"catch { [.ngmenu.file.recentmesh delete $filename] }\n" ,".ngmenu.file.recentmesh insert 0 command -label $filename \\\n" ,"-command \"AddRecentMeshFile {$filename};\n" ,"Ng_LoadMesh {$filename};\n" ,"set selectvisual mesh;\n" ,"Ng_SetVisParameters;\n" ,"redraw;\n" ,"wm title . [concat \\\" $progname - $filename \\\"];\n" ,"set dirname {[file dirname $filename]};\n" ,"set basefilename {[file tail [file rootname $filename]]};\n" ,"rebuildoccdialog;\"\n" ,"if { [.ngmenu.file.recentmesh index last] >= 6 } {\n" ,".ngmenu.file.recentmesh delete last }\n" ,"savemeshinifile;\n" ,"}\n" ,"loadmeshinifile;\n" ,".ngmenu.file add command -label \"Save Mesh...\" -accelerator \"\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Mesh file\" {.vol .vol.gz} } }\n" ,"set file [tk_getSaveFile -filetypes $types -defaultextension \".vol.gz\" -initialfile $basefilename -initialdir $dirname ]\n" ,"if {$file != \"\"} {\n" ,"Ng_SaveMesh $file }\n" ,"AddRecentMeshFile $file;\n" ,"}\n" ,".ngmenu.file add command -label \"Merge Mesh...\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Mesh file\" {.vol} } }\n" ,"set file [tk_getOpenFile -filetypes $types -defaultextension \".vol\"]\n" ,"if {$file != \"\"} {\n" ,"Ng_MergeMesh $file;\n" ,"set selectvisual mesh\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"Ng_ReadStatus;\n" ,"}\n" ,"}\n" ,".ngmenu.file add command -label \"Import Mesh...\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Neutral format\" {.mesh .emt} }\n" ,"{\"Surface mesh format\" {.surf} }\n" ,"{\"Universal format\" {.unv} }\n" ,"{\"Olaf format\" {.emt} }\n" ,"{\"TET format\" {.tet} }\n" ,"{\"Pro/ENGINEER neutral format\" {.fnf} }\n" ,"}\n" ,"set file [tk_getOpenFile -filetypes $types ]\n" ,"if {$file != \"\"} {\n" ,"Ng_ImportMesh $file\n" ,"set selectvisual mesh\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"Ng_ReadStatus;\n" ,"}\n" ,"}\n" ,".ngmenu.file add command -label \"Export Mesh...\" \\\n" ,"-command {\n" ,"foreach exportformat $meshexportformats {\n" ,"if { [lindex $exportformat 0] == $exportfiletype } {\n" ,"set extension [lindex $exportformat 1]\n" ,"}\n" ,"}\n" ,"if { $exportfiletype == \"Elmer Format\"} {\n" ,"set file [file nativename [tk_chooseDirectory -title \"Elmer Mesh Export - Select Directory\"]]\n" ,"} elseif { $exportfiletype == \"OpenFOAM 1.5+ Format\"} {\n" ,"set file [file nativename [tk_chooseDirectory -title \"OpenFOAM 1.5+ Mesh Export - Select Case Directory\"]]\n" ,"} elseif { $exportfiletype == \"OpenFOAM 1.5+ Compressed\"} {\n" ,"set file [file nativename [tk_chooseDirectory -title \"OpenFOAM 1.5+ Mesh Export - Select Case Directory\"]]\n" ,"} else {\n" ,"set file [tk_getSaveFile -filetypes \"{ \\\"$exportfiletype\\\" {*}}\" ]\n" ,"}\n" ,"if {$file != \"\"} {\n" ,"Ng_ExportMesh $file $exportfiletype\n" ,"}\n" ,"}\n" ,".ngmenu.file add cascade -label \"Export Filetype\" -menu .ngmenu.file.filetype\n" ,"menu .ngmenu.file.filetype\n" ,".ngmenu.file add separator\n" ,".ngmenu.file add command -label \"Save Solution...\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Solution File\" {.sol} }\n" ,"{\"VTK File\" {.vtk} }\n" ,"}\n" ,"set file [tk_getSaveFile -filetypes $types ]\n" ,"if {$file != \"\"} {\n" ,"Ng_SaveSolution $file\n" ,"}\n" ,"}\n" ,".ngmenu.file add command -label \"Import Solution...\" \\\n" ,"-command {\n" ,"set types { {\"Solution File\" {.sol} } }\n" ,"set file [tk_getOpenFile -filetypes $types -defaultextension \".sol\" ]\n" ,"if {$file != \"\"} {\n" ,"Ng_ImportSolution $file\n" ,"set selectvisual solution\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"}\n" ,"}\n" ,"set demostarttime [clock clicks -millisecond]\n" ,"set stopdemo 0\n" ,"proc demoredraw { } {\n" ,"global demostarttime\n" ,"global stopdemo\n" ,"set curtime [clock clicks -millisecond]\n" ,"set result [ Ng_DemoSetTime [expr $curtime - $demostarttime] ]\n" ,"redraw\n" ,"global videoactive\n" ,"if { $videoactive == 1 } {\n" ,"puts \"addframe\"\n" ,"Ng_VideoClip .ndraw addframe\n" ,"}\n" ,"if { $result == 0 && $stopdemo == 0 } {\n" ,"after 1 { demoredraw }\n" ,"}\n" ,"}\n" ,".ngmenu.file add command -label \"Show Demo...\" \\\n" ,"-command {\n" ,"set types { {\"Demo File\" {.dem} } }\n" ,"set file [tk_getOpenFile -filetypes $types -defaultextension \".dem\" ]\n" ,"if {$file != \"\"} {\n" ,"Ng_ShowDemo $file\n" ,"set demostarttime [clock clicks -millisecond]\n" ,"set stopdemo 0\n" ,"demoredraw\n" ,"}\n" ,"}\n" ,".ngmenu.file add separator\n" ,".ngmenu.file add command -label \"Snapshot...\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"JPG file\" {.jpg} }\n" ,"{\"GIF file\" {.gif} }\n" ,"{\"PPM file\" {.ppm} }\n" ,"}\n" ,"set file [tk_getSaveFile -filetypes $types]\n" ,"if {$file != \"\"} {\n" ,"Ng_SnapShot .ndraw $file }\n" ,"}\n" ,".ngmenu.file add cascade -label \"Video clip\" -menu .ngmenu.file.video\n" ,"menu .ngmenu.file.video\n" ,"set videoactive 0\n" ,".ngmenu.file.video add command -label \"start...\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"MPG file\" {.mpg} }\n" ,"}\n" ,"set file [tk_getSaveFile -filetypes $types]\n" ,"if {$file != \"\"} {\n" ,"Ng_VideoClip .ndraw init $file\n" ,"global videoactive\n" ,"set videoactive 1\n" ,"}\n" ,"}\n" ,".ngmenu.file.video add command -label \"add frame...\" \\\n" ,"-command {Ng_VideoClip .ndraw addframe }\n" ,".ngmenu.file.video add command -label \"one cycle\" \\\n" ,"-command {\n" ,"set visoptions.redrawperiodic 1\n" ,"for { set j 0 } { $j < 100 } { incr j } {\n" ,"puts \"j = $j\"\n" ,"Ng_Vis_Set time [expr (1000 * $j / 100)]\n" ,"redraw\n" ,"Ng_VideoClip .ndraw addframe\n" ,"after 200\n" ,"}\n" ,"}\n" ,".ngmenu.file.video add command -label \"finalize...\" \\\n" ,"-command {\n" ,"Ng_VideoClip .ndraw finalize\n" ,"global videoactive\n" ,"set videoactive 0\n" ,"}\n" ,".ngmenu.file add command -label \"Save Options\" \\\n" ,"-command { saveoptions }\n" ,".ngmenu.file add separator\n" ,".ngmenu.file add command -label \"Quit\" -accelerator \"\" \\\n" ,"-command {\n" ,"puts \"Thank you for using $progname\";\n" ,"if { [catch { unload libngsolve[info sharedlibextension] ngsolve } result ] } {\n" ,"}\n" ,"after cancel { timer2 }\n" ,"Ng_Exit;\n" ,"destroy .\n" ,"}\n" ,"menu .ngmenu.mesh\n" ,".ngmenu.mesh add command -label \"Generate Mesh\" -accelerator \"\" \\\n" ,"-command {\n" ,"set selectvisual mesh\n" ,"Ng_SetVisParameters\n" ,"Ng_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep}\n" ,"Ng_ReadStatus\n" ,"redraw\n" ,"}\n" ,".ngmenu.mesh add command -label \"Stop Meshing\" \\\n" ,"-command { Ng_StopMeshing }\n" ,".ngmenu.mesh add command -label \"Meshing Options...\" \\\n" ,"-command meshingoptionsdialog\n" ,".ngmenu.mesh add separator\n" ,".ngmenu.mesh add command -label \"Delete Mesh\" \\\n" ,"-command { Ng_New mesh; Ng_ReadStatus; redraw }\n" ,".ngmenu.mesh add command -label \"Delete Vol Mesh\" \\\n" ,"-command { Ng_DeleteVolMesh; Ng_ReadStatus; redraw }\n" ,".ngmenu.mesh add command -label \"Mesh Info\" \\\n" ,"-command {\n" ,"set dim [Ng_MeshInfo dim]\n" ,"set np [Ng_MeshInfo np]\n" ,"set ne [Ng_MeshInfo ne]\n" ,"set nse [Ng_MeshInfo nse]\n" ,"set nseg [Ng_MeshInfo nseg]\n" ,"set bbox [Ng_MeshInfo bbox]\n" ,"tk_messageBox -message \"Dimension: $dim\\nPoints: $np\\nElements: $ne\\nSurface Els: $nse\\nSegments: $nseg\\nxmin [lindex $bbox 0] xmax [lindex $bbox 1]\\nymin [lindex $bbox 2] ymax [lindex $bbox 3]\\nzmin [lindex $bbox 4] zmax [lindex $bbox 5]\"\n" ,"}\n" ,".ngmenu.mesh add command -label \"Mesh Quality\" \\\n" ,"-command {\n" ,"set inplanemin 0\n" ,"set inplanemax 0\n" ,"set betplanemin 0\n" ,"set betplanemax 0\n" ,"Ng_MeshQuality inplanemin inplanemax betplanemin betplanemax\n" ,"puts \"Triangle angles : $inplanemin - $inplanemax\"\n" ,"puts \"Tet angles : $betplanemin - $betplanemax\"\n" ,"tk_messageBox -message \"Triangle angles : $inplanemin - $inplanemax \\n Tet angles : $betplanemin - $betplanemax\"\n" ,"}\n" ,".ngmenu.mesh add command -label \"Check Surface Mesh\" \\\n" ,"-command { Ng_CheckSurfaceMesh }\n" ,".ngmenu.mesh add command -label \"Check Volume Mesh\" \\\n" ,"-command { Ng_CheckVolumeMesh }\n" ,".ngmenu.mesh add command -label \"Edit Boundary Conditions...\" \\\n" ,"-command { bcpropdialog }\n" ,"if { $userlevel == 3 } {\n" ,".ngmenu.mesh add command -label \"Mesh Doctor...\" \\\n" ,"-command { meshdoctordialog }\n" ,"}\n" ,".ngmenu.mesh add command -label \"METIS Mesh Partitioning...\" \\\n" ,"-command { METISdialog }\n" ,".ngmenu.mesh add separator\n" ,".ngmenu.mesh add command -label \"Analyze Geometry\" \\\n" ,"-command { Ng_GenerateMesh ag ag; Ng_ReadStatus; redraw }\n" ,".ngmenu.mesh add command -label \"Mesh Edges\" \\\n" ,"-command { Ng_GenerateMesh me me; Ng_ReadStatus; redraw }\n" ,".ngmenu.mesh add command -label \"Mesh Surface\" \\\n" ,"-command { set selectvisual mesh; Ng_SetVisParameters; \\\n" ,"Ng_GenerateMesh ms ms; Ng_ReadStatus; redraw }\n" ,".ngmenu.mesh add command -label \"Optimize Surface\" \\\n" ,"-command { Ng_GenerateMesh os os cmsmSm; redraw }\n" ,".ngmenu.mesh add cascade -label \"Surface Optim. Step\" -menu .ngmenu.mesh.surfoptstep\n" ,"menu .ngmenu.mesh.surfoptstep\n" ,".ngmenu.mesh.surfoptstep add command -label \"Mesh Smoothing\" \\\n" ,"-command { Ng_GenerateMesh os os m; redraw}\n" ,".ngmenu.mesh.surfoptstep add command -label \"Edge swapping (topologic)\" \\\n" ,"-command { Ng_GenerateMesh os os s; redraw}\n" ,".ngmenu.mesh.surfoptstep add command -label \"Edge swapping (metric)\" \\\n" ,"-command { Ng_GenerateMesh os os S; redraw}\n" ,".ngmenu.mesh.surfoptstep add command -label \"Combine points\" \\\n" ,"-command { Ng_GenerateMesh os os c; redraw}\n" ,".ngmenu.mesh add separator\n" ,".ngmenu.mesh add command -label \"Mesh Volume\" \\\n" ,"-command { Ng_GenerateMesh mv mv; Ng_ReadStatus }\n" ,".ngmenu.mesh add command -label \"Optimize Volume\" \\\n" ,"-command { Ng_GenerateMesh ov ov; Ng_ReadStatus }\n" ,".ngmenu.mesh add command -label \"Smooth Opt Volume\" \\\n" ,"-command { Ng_GenerateMesh ov ov m; Ng_ReadStatus }\n" ,".ngmenu.mesh add command -label \"Smooth Opt Volume Jacobian\" \\\n" ,"-command { Ng_GenerateMesh ov ov j; Ng_ReadStatus }\n" ,"menu .ngmenu.geometry\n" ,"menu .ngmenu.view\n" ,".ngmenu.view add command -label \"Zoom all\" \\\n" ,"-command { Ng_ZoomAll; redraw }\n" ,".ngmenu.view add command -label \"Center\" \\\n" ,"-command { Ng_Center; redraw }\n" ,".ngmenu.view add command -label \"x-y plane\" \\\n" ,"-command { Ng_StandardRotation xy; redraw }\n" ,".ngmenu.view add command -label \"y-x plane\" \\\n" ,"-command { Ng_StandardRotation yx; redraw }\n" ,".ngmenu.view add command -label \"x-z plane\" \\\n" ,"-command { Ng_StandardRotation xz; redraw }\n" ,".ngmenu.view add command -label \"z-x plane\" \\\n" ,"-command { Ng_StandardRotation zx; redraw }\n" ,".ngmenu.view add command -label \"y-z plane\" \\\n" ,"-command { Ng_StandardRotation yz; redraw }\n" ,".ngmenu.view add command -label \"z-y plane\" \\\n" ,"-command { Ng_StandardRotation zy; redraw }\n" ,".ngmenu.view add command -label \"Viewing Options...\" \\\n" ,"-command { viewingoptionsdialog; redraw }\n" ,".ngmenu.view add command -label \"Clipping Plane...\" \\\n" ,"-command { clippingdialog; redraw }\n" ,".ngmenu.view add command -label \"Solution Data...\" \\\n" ,"-command { visual_dialog; redraw }\n" ,".ngmenu.view add checkbutton -variable viewqualityplot \\\n" ,"-label \"Quality Plot\" \\\n" ,"-command { qualityviewdialog $viewqualityplot }\n" ,".ngmenu.view add checkbutton -variable memuseplot \\\n" ,"-label \"Memory Usage\" \\\n" ,"-command { memusedialog $memuseplot }\n" ,"menu .ngmenu.meshsize\n" ,".ngmenu.meshsize add command -label \"Refine uniform\" \\\n" ,"-command { Ng_Refine; Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize add command -label \"Second Order\" \\\n" ,"-command { Ng_SecondOrder; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize add command -label \"Validate Second Order\" \\\n" ,"-command { Ng_ValidateSecondOrder; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize add command -label \"High Order\" \\\n" ,"-command { Ng_HighOrder ${options.elementorder}; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize add separator\n" ,".ngmenu.meshsize add command -label \"Refinement Dialog...\" \\\n" ,"-command { refinementdialog }\n" ,".ngmenu.meshsize add command -label \"Load Meshsize...\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Meshsize file\" {.msz} } }\n" ,"set file [tk_getOpenFile -filetypes $types]\n" ,"if {$file != \"\"} {\n" ,"Ng_LoadMeshSize $file;\n" ,"}\n" ,"}\n" ,".ngmenu.meshsize add command -label \"MS from Surf Mesh\" \\\n" ,"-command { Ng_MeshSizeFromSurfaceMesh }\n" ,"if { $userlevel == 3 } {\n" ,".ngmenu.meshsize add command -label \"Singular point ms\" \\\n" ,"-command { Ng_SingularPointMS; }\n" ,".ngmenu.meshsize add command -label \"Singular edge ms\" \\\n" ,"-command { Ng_SingularEdgeMS; }\n" ,".ngmenu.meshsize add separator\n" ,"set bisectfilename \"\";\n" ,".ngmenu.meshsize add command -label \"Bisection\" \\\n" ,"-command { Ng_ReadStatus; set oldnp 0; set newnp $status_np;\n" ,"Ng_ReadStatus;\n" ,"while { $oldnp < $newnp } {\n" ,"set level [expr $level+1]\n" ,"if { $bisectfilename == \"\"} {\n" ,"Ng_Bisect;\n" ,"} else {\n" ,"Ng_Bisect $bisectfilename;\n" ,"}\n" ,"Ng_ReadStatus;\n" ,"redraw;\n" ,"if { $bisectfilename == \"\"} {\n" ,"set oldnp $newnp;\n" ,"set newnp $status_np;\n" ,"puts \"oldnp $oldnp newnp $newnp\";\n" ,"} else {\n" ,"set oldnp $newnp;\n" ,"}\n" ,"}\n" ,"}\n" ,"}\n" ,".ngmenu.meshsize add command -label \"Load Refinement Info...\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Refinement info\" {.refine} }}\n" ,"set bisectfilename [tk_getOpenFile -filetypes $types]\n" ,"}\n" ,".ngmenu.meshsize add command -label \"Z-Refinement\" \\\n" ,"-command { Ng_ZRefinement 2; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize add cascade -label \"hp-Refinement\" -menu .ngmenu.meshsize.hpref\n" ,"menu .ngmenu.meshsize.hpref\n" ,".ngmenu.meshsize.hpref add command -label \"1 Level\" \\\n" ,"-command { Ng_HPRefinement 1; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"2 Levels\" \\\n" ,"-command { Ng_HPRefinement 2; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"3 Levels\" \\\n" ,"-command { Ng_HPRefinement 3; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"4 Levels\" \\\n" ,"-command { Ng_HPRefinement 4; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"5 Levels\" \\\n" ,"-command { Ng_HPRefinement 5; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"6 Levels\" \\\n" ,"-command { Ng_HPRefinement 6; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"7 Levels\" \\\n" ,"-command { Ng_HPRefinement 7; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"8 Levels\" \\\n" ,"-command { Ng_HPRefinement 8; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"9 Levels\" \\\n" ,"-command { Ng_HPRefinement 9; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize.hpref add command -label \"10 Levels\" \\\n" ,"-command { Ng_HPRefinement 10; Ng_ReadStatus; redraw }\n" ,".ngmenu.meshsize add command -label \"Split to Tets\" \\\n" ,"-command { Ng_Split2Tets; Ng_ReadStatus; redraw }\n" ,"menu .ngmenu.special\n" ,".ngmenu.special add command -label \"Prismatic Boundary Layer\" \\\n" ,"-command { Ng_GenerateBoundaryLayer; redraw }\n" ,".ngmenu.special add command -label \"Insert virtual boundary layer\" \\\n" ,"-command { Ng_InsertVirtualBL; redraw }\n" ,".ngmenu.special add command -label \"Cut off and combine with other\" \\\n" ,"-command {\n" ,"set types { {\"Mesh file\" {.vol} } }\n" ,"set file [tk_getOpenFile -filetypes $types]\n" ,"if {$file != \"\"} {\n" ,"Ng_CutOffAndCombine $file; }\n" ,"redraw\n" ,"}\n" ,".ngmenu.special add command -label \"Helmholtz Mesh grading\" \\\n" ,"-command { Ng_HelmholtzMesh; }\n" ,".ngmenu.special add cascade -label \"Colour-based boundary conditions\" -menu .ngmenu.special.colbndcond\n" ,"menu .ngmenu.special.colbndcond\n" ,".ngmenu.special.colbndcond add command -label \"Inspect Colours in mesh\" \\\n" ,"-command { currmeshcoloursdialog }\n" ,".ngmenu.special.colbndcond add separator\n" ,".ngmenu.special.colbndcond add command -label \"Automatic Assignment\" \\\n" ,"-command { Ng_AutoColourBcProps auto; redraw }\n" ,".ngmenu.special.colbndcond add separator\n" ,"set ocffile [file join ${ngdir} netgen.ocf];\n" ,".ngmenu.special.colbndcond add command -label \"Select Colour Profile file\" \\\n" ,"-command {\n" ,"set types { {\"Colour Profile file\" {.ocf} } }\n" ,"set ocffile [tk_getOpenFile -filetypes $types]\n" ,"if {$ocffile == \"\"} {\n" ,"set ocffile [file join ${ngdir} netgen.ocf]; }\n" ,"}\n" ,".ngmenu.special.colbndcond add command -label \"Profile based Assignment\" \\\n" ,"-command { Ng_AutoColourBcProps profile ${ocffile}; redraw }\n" ,"menu .ngmenu.help\n" ,".ngmenu.view add checkbutton -label \"Help Line\" -variable showhelpline \\\n" ,"-command {\n" ,"if { $showhelpline == 1} {\n" ,"pack .helpline -before .statbar -side bottom -fill x -padx 3p\n" ,"} {\n" ,"pack forget .helpline\n" ,"}\n" ,"}\n" ,".ngmenu.help add command -label \"About...\" \\\n" ,"-command {\n" ,"tk_messageBox -message \"This is NETGEN \\nmainly written by \\nJoachim Schoeberl \\nthanks to \\nRobert Gaisbauer, Johannes Gerstmayr, Philippose Rajan\"\n" ,"}\n" ,"ttk::frame .bubar\n" ,"pack .bubar -side top -fill x\n" ,"ttk::button .bubar.testb -text \"Test\" -command { Ng_SaveGeometry }\n" ,"ttk::button .bubar.surfm -text \"Generate Mesh\" -command \\\n" ,"{\n" ,".ngmenu.mesh invoke \"Generate Mesh\";\n" ,"}\n" ,"ttk::button .bubar.stopm -text \"Stop\" -command \\\n" ,"{\n" ,"set multithread_terminate 1;\n" ,"set stopdemo 1;\n" ,"}\n" ,"ttk::button .bubar.exitb -text \"Quit\" \\\n" ,"-command {\n" ,"set ans [tk_messageBox -title \"Quit Netgen?\" -message \"Do you really want to quit Netgen?\" -type yesno -default \"no\" -icon question]\n" ,"if { $ans == \"yes\" } {\n" ,".ngmenu.file invoke \"Quit\";\n" ,"}\n" ,"}\n" ,"pack .bubar.exitb .bubar.surfm .bubar.stopm -side left\n" ,"ttk::button .bubar.zoomall -text \"Zoom All\" \\\n" ,"-command { Ng_ZoomAll; redraw }\n" ,"ttk::button .bubar.center -text \"Center\" \\\n" ,"-command { Ng_Center; redraw }\n" ,"ttk::menubutton .bubar.modesel -menu .bubar.modesel.menu -text \"\" -width 6\n" ,"menu .bubar.modesel.menu -tearoff 0\n" ,".bubar.modesel.menu add command -label \"Rotate\" -command \"set drawmode \\\"rotate\\\" ;.bubar.modesel configure -text \\\"Rotate\\\"\"\n" ,".bubar.modesel.menu add command -label \"Move\" -command \"set drawmode \\\"move\\\" ;.bubar.modesel configure -text \\\"Move\\\"\"\n" ,".bubar.modesel.menu add command -label \"Zoom\" -command \"set drawmode \\\"zoom\\\" ;.bubar.modesel configure -text \\\"Zoom\\\"\"\n" ,".bubar.modesel.menu invoke \"Rotate\"\n" ,"set viewvals { geometry specpoints mesh solution}\n" ,"if { $userlevel == 3} {\n" ,"set viewvals { geometry mesh specpoints surfmeshing modelview solution}\n" ,"}\n" ,"set viewvallabs(cross) \"Cross\"\n" ,"set viewvallabs(geometry) \"Geometry\"\n" ,"set viewvallabs(mesh) \"Mesh\"\n" ,"set viewvallabs(specpoints) \"Edges\"\n" ,"set viewvallabs(surfmeshing) \"Mesh Gen\"\n" ,"set viewvallabs(modelview) \"Modeller\"\n" ,"set viewvallabs(solution) \"Solution\"\n" ,"pack .bubar.center .bubar.zoomall -side right\n" ,".ngmenu.view add checkbutton -variable viewrotatebutton \\\n" ,"-label \"Enable LeftButton Selection\" \\\n" ,"-command {\n" ,"if { $viewrotatebutton } {\n" ,"pack .bubar.modesel -side right\n" ,"} {\n" ,"pack forget .bubar.modesel\n" ,"}\n" ,"}\n" ,"menu .bubar.selviewmenu\n" ,"ttk::menubutton .bubar.selview1 -menu .bubar.selviewmenu -text \"Geometry\"\n" ,"foreach viewv $viewvals {\n" ,".bubar.selviewmenu add command -label $viewvallabs($viewv) -command \\\n" ,"\".bubar.selview1 configure -text \\\"$viewvallabs($viewv)\\\" ; set selectvisual $viewv ; Ng_SetVisParameters; redraw\"\n" ,"}\n" ,"pack .bubar.selview1 -side right\n" ,"trace add variable selectvisual write selvis_monitor\n" ,"proc selvis_monitor { name args } {\n" ,"global selectvisual viewvallabs\n" ,".bubar.selviewmenu invoke $viewvallabs($selectvisual)\n" ,"}\n" ,"ttk::label .helpline -text \"None\"\n" ,"pack forget .helpline -side bottom -fill x\n" ,"ttk::frame .statbar -relief flat\n" ,"pack .statbar -side bottom -fill x\n" ,"ttk::label .statbar.ptslabel -text \" Points: \"\n" ,"ttk::label .statbar.ptsval -textvariable status_np\n" ,"ttk::label .statbar.elslabel -text \" Elements: \"\n" ,"ttk::label .statbar.elsval -textvariable status_ne\n" ,"ttk::label .statbar.selslabel -text \" Surf Elements: \"\n" ,"ttk::label .statbar.selsval -textvariable status_nse\n" ,"ttk::label .statbar.task -textvariable status_task\n" ,"pack .statbar.ptslabel .statbar.ptsval -side left -ipady 3p\n" ,"pack .statbar.elslabel .statbar.elsval -side left -ipady 3p\n" ,"pack .statbar.selslabel .statbar.selsval -side left -ipady 3p\n" ,"ttk::progressbar .statbar.per -value 0 -maximum 1\n" ,"pack .statbar.per -side right\n" ,"pack .statbar.task -side right -ipady 4\n" ,"set qualbaraxis(0) 0\n" ,"set qualbar(0) 0\n" ,"set qualbarnull(0) 0\n" ,"proc timer2 { } {\n" ,"global status_np\n" ,"global status_ne\n" ,"global status_nse\n" ,"global multithread_running\n" ,"global multithread_redraw\n" ,"global status_working\n" ,"global status_task\n" ,"global status_percent\n" ,"global status_tetqualclasses\n" ,"Ng_ReadStatus\n" ,"if { $multithread_redraw == 1 } {\n" ,"set multithread_redraw 0;\n" ,"redraw;\n" ,"global videoactive\n" ,"if { $videoactive == 1 } {\n" ,"puts \"addframe\"\n" ,"Ng_VideoClip .ndraw addframe\n" ,"}\n" ,"}\n" ,"if { $multithread_redraw == 2 } {\n" ,"redraw;\n" ,"set multithread_redraw 0;\n" ,"global videoactive\n" ,"if { $videoactive == 1 } {\n" ,"puts \"addframe\"\n" ,"Ng_VideoClip .ndraw addframe\n" ,"}\n" ,"after 1 { timer2 }\n" ,"return\n" ,"}\n" ,".statbar.per configure -value [expr $status_percent/100]\n" ,"if { $multithread_running } {\n" ,"pack .statbar.per -side right -before .statbar.task -padx 6\n" ,"} {\n" ,"pack forget .statbar.per\n" ,"}\n" ,"if {[winfo exists .qualityview_dlg] == 1} {\n" ,"global qualbar\n" ,"global qualbarnull\n" ,"global qualbaraxis\n" ,"set maxval 0\n" ,"for {set i 0} {$i < 20} {incr i} {\n" ,"if {[lindex $status_tetqualclasses $i] > $maxval} {\n" ,"set maxval [lindex $status_tetqualclasses $i]\n" ,"}\n" ,"}\n" ,"set ubound 1\n" ,"while { $ubound < $maxval } {\n" ,"set ubound [expr {10 * $ubound}]\n" ,"}\n" ,"if { $ubound/5 > $maxval } {\n" ,"set ubound [expr $ubound/5]\n" ,"}\n" ,"if { $ubound/2 > $maxval } {\n" ,"set ubound [expr $ubound/2]\n" ,"}\n" ,"for {set i 1} {$i <= 5} {incr i} {\n" ,"set value [expr { $i * $ubound / 5 }]\n" ,".qualityview_dlg.c dchars $qualbaraxis($i) 0 end\n" ,".qualityview_dlg.c insert $qualbaraxis($i) end $value\n" ,"}\n" ,"for {set i 0} {$i < 20} {incr i} {\n" ,"set x1 [expr {100 + ($i*15) + 2}]\n" ,"set x2 [expr {$x1+10}]\n" ,"set nbrs [lindex $status_tetqualclasses $i]\n" ,"set y [expr (249 - (200 * $nbrs / $ubound ) )]\n" ,".qualityview_dlg.c coords $qualbar($i) $x1 250 $x2 $y\n" ,"if { $nbrs == 0 } {\n" ,".qualityview_dlg.c itemconfigure $qualbarnull($i) -text 0\n" ,"} {\n" ,".qualityview_dlg.c itemconfigure $qualbarnull($i) -text \"\"\n" ,"}\n" ,"}\n" ,"}\n" ,"if {[winfo exists .memuse_dlg] == 1} {\n" ,"global memmark\n" ,"set usemb [Ng_MemInfo usedmb]\n" ,"for {set i 0} {$i < [string length $usemb] } {incr i} {\n" ,"if { [string index $usemb $i] == 0 } {\n" ,".memuse_dlg.c coords $memmark($i) [expr 50+$i] 68 [expr 50+$i] 70\n" ,"} {\n" ,".memuse_dlg.c coords $memmark($i) [expr 50+$i] 50 [expr 50+$i] 70\n" ,"}\n" ,"}\n" ,"}\n" ,"after 10 { timer2 }\n" ,"}\n" ,"timer2\n" ,"proc bgerror { error } {\n" ,"global errorInfo userlevel\n" ,"if { $userlevel == 3} {\n" ,"puts \"ERROR: $error\"\n" ,"puts \"errinfo: $errorInfo\"\n" ,"}\n" ,"tk_messageBox -title \"Error Message\" -message $error -type ok\n" ,"}\n" ,"proc smh2 { menuitem } {\n" ,"if {[catch {$menuitem entrycget active -label} name]} {\n" ,"set name \" \"\n" ,"}\n" ,"show_menu_help $name\n" ,"update idletasks\n" ,"}\n" ,"bind .ngmenu <> { smh2 %W }\n" ,"bind .ngmenu.file <> { smh2 %W }\n" ,"bind .ngmenu.geometry <> { smh2 %W }\n" ,"bind .ngmenu.mesh <> { smh2 %W }\n" ,"bind .ngmenu.view <> { smh2 %W }\n" ,"bind .ngmenu.meshsize <> { smh2 %W }\n" ,"bind .ngmenu.special <> { smh2 %W }\n" ,"bind .ngmenu.help <> { smh2 %W }\n" ,"bind . { .ngmenu.file invoke \"Quit\" }\n" ,"bind . { .ngmenu.file invoke \"Load Geometry...\" } ;\n" ,"bind . { .ngmenu.file invoke \"Load Mesh...\" } ;\n" ,"bind . { .ngmenu.file invoke \"Save Mesh...\" } ;\n" ,"bind . { .ngmenu.file activate \"Recent Files\" } ;\n" ,"bind .

{ newprimitivedialog } ; \n" ,"bind .

{ editprimitivedialog }\n" ,"bind . { newsoliddialog }\n" ,"bind . { .ngmenu.mesh invoke \"Generate Mesh\" } ;\n" ,"}\n" ,"}\n" ,"catch {\n" ,"proc meshingoptionsdialog { } {\n" ,"set w .options_dlg\n" ,"if {[winfo exists .options_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"pack [ttk::notebook $w.nb] -fill both -side top\n" ,"$w.nb add [ttk::frame $w.nb.general] -text \"General\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.meshsize] -text \"Mesh Size\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.chartopt] -text \"STL Charts\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.optimizer] -text \"Optimizer\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.debug] -text \"Debug\" -underline 0\n" ,"set f $w.nb.general\n" ,"ttk::frame $f.background\n" ,"pack $f.background -fill both\n" ,"set f $f.background\n" ,"ttk::labelframe $f.f2 -relief groove -borderwidth 3 -text \"General meshing options\"\n" ,"pack $f.f2 -pady 15 -fill x\n" ,"set f $f.f2\n" ,"set finevals { 1 2 3 4 5 6 }\n" ,"set finelabs(1) \"very coarse\"\n" ,"set finelabs(2) \"coarse\"\n" ,"set finelabs(3) \"moderate\"\n" ,"set finelabs(4) \"fine\"\n" ,"set finelabs(5) \"very fine\"\n" ,"set finelabs(6) \"user defined\"\n" ,"global meshoptions.fineness\n" ,"ttk::label $f.fine2l -text \"Mesh granularity: \"\n" ,"ttk::menubutton $f.fine2c -menu $f.fine2m -text \"coarse\" -width 16\n" ,"menu $f.fine2m -tearoff 0\n" ,"foreach finev { 1 2 3 4 5 6 } {\n" ,"$f.fine2m add command -label $finelabs($finev) \\\n" ,"-command \"set meshoptions.fineness $finev ; setgranularity $finev; $f.fine2c configure -text \\\"$finelabs($finev)\\\"\"\n" ,"}\n" ,"$f.fine2m invoke $finelabs(${meshoptions.fineness})\n" ,"grid $f.fine2l $f.fine2c -sticky nw\n" ,"set mgsteps { ag me ms os mv ov }\n" ,"set mgsteplabel(ag) \"Analyze Geometry\"\n" ,"set mgsteplabel(me) \"Mesh Edges\"\n" ,"set mgsteplabel(ms) \"Mesh Surface\"\n" ,"set mgsteplabel(os) \"Optimize Surface\"\n" ,"set mgsteplabel(mv) \"Mesh Volume\"\n" ,"set mgsteplabel(ov) \"Optimize Volume\"\n" ,"global meshoptions.firststep\n" ,"ttk::label $f.first2l -text \"First Step: \"\n" ,"ttk::menubutton $f.first2c -menu $f.first2m -width 16\n" ,"menu $f.first2m -tearoff 0\n" ,"foreach i $mgsteps {\n" ,"$f.first2m add command -label $mgsteplabel($i) -command \"set meshoptions.firststep $i ; $f.first2c configure -text \\\"$mgsteplabel($i)\\\"\"\n" ,"}\n" ,"$f.first2m invoke $mgsteplabel(${meshoptions.firststep})\n" ,"grid $f.first2l $f.first2c -sticky nw\n" ,"global meshoptions.laststep\n" ,"ttk::label $f.last2l -text \"Last Step: \"\n" ,"ttk::menubutton $f.last2c -menu $f.last2m -width 16\n" ,"menu $f.last2m -tearoff 0\n" ,"foreach i $mgsteps {\n" ,"$f.last2m add command -label $mgsteplabel($i) -command \"set meshoptions.laststep $i ; $f.last2c configure -text \\\"$mgsteplabel($i)\\\"\"\n" ,"}\n" ,"$f.last2m invoke $mgsteplabel(${meshoptions.laststep})\n" ,"grid $f.last2l $f.last2c -sticky nw\n" ,"grid anchor $f center\n" ,"set msg(0) \"None\"\n" ,"set msg(1) \"Least\"\n" ,"set msg(2) \"Little\"\n" ,"set msg(3) \"Moderate\"\n" ,"set msg(4) \"Much\"\n" ,"set msg(5) \"Most\"\n" ,"global options.printmsg\n" ,"ttk::label $f.msg2l -text \"Print Messages: \"\n" ,"menu $f.msg2m -tearoff 0\n" ,"ttk::menubutton $f.msg2c -menu $f.msg2m -width 16\n" ,"foreach step {0 1 2 3 4 5 } {\n" ,"$f.msg2m add command -label $msg($step) -command \"set options.printmsg $step ; $f.msg2c configure -text $msg($step)\"\n" ,"}\n" ,"$f.msg2m invoke ${options.printmsg}\n" ,"grid $f.msg2l $f.msg2c -sticky nw\n" ,"set f $w.nb.general\n" ,"ttk::labelframe $f.bts -borderwidth 3 -relief groove -text \"Additional meshing options\"\n" ,"pack $f.bts -fill x -pady 15\n" ,"ttk::frame $f.bts.btnframe\n" ,"ttk::checkbutton $f.bts.btnframe.parthread -text \"Parallel meshing thread\" \\\n" ,"-variable options.parthread\n" ,"ttk::checkbutton $f.bts.btnframe.second -text \"Second order elements\" \\\n" ,"-variable options.secondorder\n" ,"ttk::checkbutton $f.bts.btnframe.quad -text \"Quad dominated\" \\\n" ,"-variable options.quad -command {\n" ,"if { ${options.quad} } {\n" ,"set meshoptions.laststep os\n" ,"}\n" ,"}\n" ,"ttk::checkbutton $f.bts.btnframe.invtets -text \"Invert volume elements\" \\\n" ,"-variable options.inverttets\n" ,"ttk::checkbutton $f.bts.btnframe.invtrigs -text \"Invert surface elements\" \\\n" ,"-variable options.inverttrigs\n" ,"ttk::checkbutton $f.bts.btnframe.azref -text \"Automatic Z-refinement\" \\\n" ,"-variable options.autozrefine\n" ,"pack $f.bts.btnframe -anchor center\n" ,"pack $f.bts.btnframe.parthread $f.bts.btnframe.second $f.bts.btnframe.quad $f.bts.btnframe.invtets $f.bts.btnframe.invtrigs $f.bts.btnframe.azref -anchor w\n" ,"ttk::label $f.bts.btnframe.l -text \"Element order\"\n" ,"ttk::spinbox $f.bts.btnframe.elementorder2 -from 1 -to 20 -textvariable options.elementorder -width 2\n" ,"pack $f.bts.btnframe.elementorder2 $f.bts.btnframe.l -anchor w -side left\n" ,"set f $w.nb.meshsize\n" ,"ttk::frame $f.f2\n" ,"pack $f.f2 -pady 10\n" ,"set f $f.f2\n" ,"ttk::frame $f.meshsize\n" ,"ttk::label $f.meshsize.l -text \"max mesh-size\"\n" ,"ttk::spinbox $f.meshsize.s -from 1e-9 -to 1e9 -textvariable options.meshsize -width 5 -validate focus -validatecommand \"my_validatespinbox %W %P 10\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"pack $f.meshsize -fill x\n" ,"pack $f.meshsize.s $f.meshsize.l -side right\n" ,"ttk::frame $f.minmeshsize\n" ,"ttk::label $f.minmeshsize.l -text \"min mesh-size\"\n" ,"ttk::spinbox $f.minmeshsize.s -from 0 -to 1e9 -textvariable options.minmeshsize -width 5 -validate focus -validatecommand \"my_validatespinbox %W %P 10\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"pack $f.minmeshsize -fill x\n" ,"pack $f.minmeshsize.s $f.minmeshsize.l -side right\n" ,"ttk::frame $f.grading\n" ,"ttk::label $f.grading.l -text \"mesh-size grading\"\n" ,"ttk::spinbox $f.grading.s -from 0.1 -to 1.0 -textvariable options.grading -width 5 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"pack $f.grading -fill x\n" ,"pack $f.grading.s $f.grading.l -side right\n" ,"set f $w.nb.meshsize\n" ,"ttk::labelframe $f.msf -text \"mesh-size file:\" -relief groove -borderwidth 3\n" ,"pack $f.msf\n" ,"ttk::entry $f.msf.ent -textvariable options.meshsizefilename -width 30\n" ,"ttk::button $f.msf.btn -text \"Browse\" -command {\n" ,"global options.meshsizefilename\n" ,"set types {\n" ,"{\"Meshsize file\" {.msz} } }\n" ,"set options.meshsizefilename [tk_getOpenFile -filetypes $types -initialfile ${options.meshsizefilename}]\n" ,"}\n" ,"pack $f.msf.ent -side left -expand yes -fill x -anchor s -padx 4 -pady 4\n" ,"pack $f.msf.btn -side left -anchor s -padx 4 -pady 4\n" ,"ttk::label $f.lab -text \"Additional mesh size restrictions:\"\n" ,"ttk::labelframe $f.csg -relief groove -borderwidth 3 -text \"CSG mesh-size\"\n" ,"pack $f.csg -fill x\n" ,"proc test {a} {puts $a}\n" ,"ttk::scale $f.csg.curvsc -orient horizontal -length 150 -from 0.2 -to 5 \\\n" ,"-variable options.curvaturesafety -takefocus 0 -command \"roundscale $f.csg.curvsc 1\"\n" ,"ttk::entry $f.csg.curve -textvariable options.curvaturesafety -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.csg.curvsc cget -from] [$f.csg.curvsc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::label $f.csg.curvla -text \"Elements per curvature radius\"\n" ,"grid $f.csg.curvsc $f.csg.curve $f.csg.curvla -sticky nw -padx 4\n" ,"ttk::scale $f.csg.elensc -orient horizontal -length 150 -from 0.2 -to 5 \\\n" ,"-variable options.segmentsperedge -takefocus 0 -command \"roundscale $f.csg.elensc 1\"\n" ,"ttk::entry $f.csg.elene -textvariable options.segmentsperedge -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.csg.elensc cget -from] [$f.csg.elensc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::label $f.csg.elenla -text \"Elements per edge\"\n" ,"grid $f.csg.elensc $f.csg.elene $f.csg.elenla -sticky nw -padx 4\n" ,"grid anchor $f.csg center\n" ,"ttk::labelframe $f.stl -relief groove -borderwidth 3 -text \"STL mesh-size\"\n" ,"pack $f.stl -fill x\n" ,"ttk::scale $f.stl.r2sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n" ,"-variable stloptions.resthchartdistfac -takefocus 0 -command \"roundscale $f.stl.r2sc 1\"\n" ,"ttk::entry $f.stl.r2e -textvariable stloptions.resthchartdistfac -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.stl.r2sc cget -from] [$f.stl.r2sc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::checkbutton $f.stl.r2bu -text \"STL - chart distance\" \\\n" ,"-variable stloptions.resthchartdistenable\n" ,"grid $f.stl.r2sc $f.stl.r2e $f.stl.r2bu -sticky nw -padx 4\n" ,"ttk::scale $f.stl.r6sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n" ,"-variable stloptions.resthlinelengthfac -takefocus 0 -command \"roundscale $f.stl.r6sc 1\"\n" ,"ttk::entry $f.stl.r6e -textvariable stloptions.resthlinelengthfac -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.stl.r6sc cget -from] [$f.stl.r6sc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::checkbutton $f.stl.r6bu -text \"STL - line length\" \\\n" ,"-variable stloptions.resthlinelengthenable\n" ,"grid $f.stl.r6sc $f.stl.r6e $f.stl.r6bu -sticky nw -padx 4\n" ,"ttk::scale $f.stl.r3sc -orient horizontal -length 150 -from 0.2 -to 8 \\\n" ,"-variable stloptions.resthcloseedgefac -takefocus 0 -command \"roundscale $f.stl.r3sc 1\"\n" ,"ttk::entry $f.stl.r3e -textvariable stloptions.resthcloseedgefac -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.stl.r3sc cget -from] [$f.stl.r3sc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::checkbutton $f.stl.r3bu -text \"STL/IGES/STEP - close edges\" \\\n" ,"-variable stloptions.resthcloseedgeenable\n" ,"grid $f.stl.r3sc $f.stl.r3e $f.stl.r3bu -sticky nw -padx 4\n" ,"ttk::scale $f.stl.r1sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n" ,"-variable stloptions.resthsurfcurvfac -takefocus 0 -command \"roundscale $f.stl.r1sc 1\"\n" ,"ttk::entry $f.stl.r1e -textvariable stloptions.resthsurfcurvfac -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.stl.r1sc cget -from] [$f.stl.r1sc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::checkbutton $f.stl.r1bu -text \"STL - surface curvature\" \\\n" ,"-variable stloptions.resthsurfcurvenable\n" ,"grid $f.stl.r1sc $f.stl.r1e $f.stl.r1bu -sticky nw -padx 4\n" ,"ttk::scale $f.stl.r3bsc -orient horizontal -length 150 -from 0.2 -to 5 \\\n" ,"-variable stloptions.resthedgeanglefac -takefocus 0 -command \"roundscale $f.stl.r3bsc 1\"\n" ,"ttk::entry $f.stl.r3be -textvariable stloptions.resthedgeanglefac -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.stl.r3bsc cget -from] [$f.stl.r3bsc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::checkbutton $f.stl.r3bbu -text \"STL - edge angle\" \\\n" ,"-variable stloptions.resthedgeangleenable\n" ,"grid $f.stl.r3bsc $f.stl.r3be $f.stl.r3bbu -sticky nw -padx 4\n" ,"ttk::scale $f.stl.r5sc -orient horizontal -length 150 -from 0.2 -to 5 \\\n" ,"-variable stloptions.resthsurfmeshcurvfac -takefocus 0 -command \"roundscale $f.stl.r5sc 1\"\n" ,"ttk::entry $f.stl.r5e -textvariable stloptions.resthsurfmeshcurvfac -width 3 \\\n" ,"-validatecommand \"my_validate %W [$f.stl.r5sc cget -from] [$f.stl.r5sc cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\" -validate focus\n" ,"ttk::checkbutton $f.stl.r5bu -text \"STL - surface mesh curv\" \\\n" ,"-variable stloptions.resthsurfmeshcurvenable\n" ,"grid $f.stl.r5sc $f.stl.r5e $f.stl.r5bu -sticky nw -padx 4\n" ,"ttk::checkbutton $f.stl.recalch -text \"STL - Recalc mesh size for surface optimization\" \\\n" ,"-variable stloptions.recalchopt\n" ,"grid $f.stl.recalch -sticky n -columnspan 3 -column 0\n" ,"ttk::button $f.stl.calch -text \"Calc New H\" -command { redraw; Ng_STLCalcLocalH }\n" ,"grid $f.stl.calch -columnspan 3 -column 0\n" ,"grid anchor $f.stl center\n" ,"proc roundscale {w n_digits args} {\n" ,"set val [$w get]\n" ,"global [$w cget -variable]\n" ,"if {$n_digits == 0 } {\n" ,"set [$w cget -variable] [tcl::mathfunc::round $val]\n" ,"} else {\n" ,"set [$w cget -variable] [format \"%.[append n_digits \"f\"]\" $val]\n" ,"}\n" ,"}\n" ,"global last_accepted_sc\n" ,"proc my_validate {w mini maxi val n_digits} {\n" ,"global last_accepted_sc [$w cget -textvariable]\n" ,"if {[string length $val] == 0} {return 0}\n" ,"if {[string is double $val] == 1} {\n" ,"if { $n_digits == 0 } {\n" ,"set val [tcl::mathfunc::max $mini [tcl::mathfunc::min $maxi [tcl::mathfunc::round $val]]]\n" ,"} else {\n" ,"if { $n_digits < 9 } {\n" ,"set val [tcl::mathfunc::max $mini [tcl::mathfunc::min $maxi [format \"%.[append n_digits \"f\"]\" $val]]]\n" ,"}\n" ,"}\n" ,"set last_accepted_sc $val\n" ,"set [$w cget -textvariable] $val\n" ,"return 1\n" ,"} else {\n" ,"return 0\n" ,"}\n" ,"}\n" ,"proc my_invalid {w} {\n" ,"global last_accepted_sc [$w cget -textvariable]\n" ,"set [$w cget -textvariable] $last_accepted_sc\n" ,"}\n" ,"set f $w.nb.chartopt\n" ,"ttk::labelframe $f.mainframe -text \"STL angles\" -relief groove -borderwidth 3\n" ,"pack $f.mainframe -fill x -pady 15\n" ,"set f $f.mainframe\n" ,"ttk::label $f.labYangles -text \"Yellow Edges Angle ()\"\n" ,"ttk::scale $f.scale1 -orient horizontal -length 150 -from 0 -to 90 -variable stloptions.yangle -takefocus 0 -command \"roundscale $f.scale1 1\"\n" ,"ttk::entry $f.entry1 -textvariable stloptions.yangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale1 cget -from] [$f.scale1 cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.scale1 $f.entry1 $f.labYangles -sticky nw -padx 4 -pady 6\n" ,"ttk::label $f.labEangles -text \"Edge Corner Angle ()\"\n" ,"ttk::scale $f.scale2 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.edgecornerangle -takefocus 0 -command \"roundscale $f.scale2 1\"\n" ,"ttk::entry $f.entry2 -textvariable stloptions.edgecornerangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale2 cget -from] [$f.scale2 cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.scale2 $f.entry2 $f.labEangles -sticky nw -padx 4 -pady 6\n" ,"ttk::label $f.lab31 -text \"Chart Angle ()\"\n" ,"ttk::scale $f.scale3 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.chartangle -takefocus 0 -command \"roundscale $f.scale3 1\"\n" ,"ttk::entry $f.entry3 -textvariable stloptions.chartangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale3 cget -from] [$f.scale3 cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.scale3 $f.entry3 $f.lab31 -sticky nw -padx 4 -pady 6\n" ,"ttk::label $f.lab41 -text \"Outer Chart Angle ()\"\n" ,"ttk::scale $f.scale4 -orient horizontal -length 150 -from 0 -to 180 -variable stloptions.outerchartangle -takefocus 0 -command \"roundscale $f.scale4 1\"\n" ,"ttk::entry $f.entry4 -textvariable stloptions.outerchartangle -width 5 -validate focus -takefocus 0 -validatecommand \"my_validate %W [$f.scale4 cget -from] [$f.scale4 cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.scale4 $f.entry4 $f.lab41 -sticky nw -padx 4 -pady 6\n" ,"grid anchor $f center\n" ,"global last_accepted_sp\n" ,"proc my_validatespinbox {w val n_digits} {\n" ,"global last_accepted_sp\n" ,"if {[string length $val] == 0} {return 0}\n" ,"if {[string is double $val] == 1} {\n" ,"if { $n_digits == 0 } {\n" ,"if { $n_digits < 9 } {\n" ,"set val [tcl::mathfunc::round $val] } else { set val [format \"%.[append n_digits \"f\"]\" $val]\n" ,"}\n" ,"}\n" ,"$w set [tcl::mathfunc::max [$w cget -from] [tcl::mathfunc::min [$w cget -to] $val]]\n" ,"set last_accepted_sp $val\n" ,"return 1\n" ,"} else {\n" ,"return 0\n" ,"}\n" ,"}\n" ,"proc my_invalidspinbox {w} {\n" ,"global last_accepted_sp\n" ,"$w set $last_accepted_sp\n" ,"}\n" ,"set f $w.nb.optimizer\n" ,"ttk::labelframe $f.optframe -text \"Optimization settings\" -relief groove -borderwidth 3\n" ,"pack $f.optframe -fill x -pady 15\n" ,"ttk::label $f.optframe.sosl -text \"Surface opt steps\"\n" ,"ttk::spinbox $f.optframe.soss -from 0 -to 99 -textvariable options.optsteps2d -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"grid $f.optframe.sosl $f.optframe.soss -sticky nw;\n" ,"ttk::label $f.optframe.vosl -text \"Volume opt steps\"\n" ,"ttk::spinbox $f.optframe.voss -from 0 -to 99 -textvariable options.optsteps3d -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"grid $f.optframe.vosl $f.optframe.voss -sticky nw;\n" ,"ttk::label $f.optframe.eswl -text \"Element size weight\"\n" ,"ttk::spinbox $f.optframe.esws -from 0 -to 1 -textvariable options.elsizeweight -width 5 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 1\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"grid $f.optframe.eswl $f.optframe.esws -sticky nw;\n" ,"ttk::label $f.optframe.weml -text \"Worst element measure\"\n" ,"ttk::spinbox $f.optframe.wems -from 1 -to 10 -textvariable options.opterrpow -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"grid $f.optframe.weml $f.optframe.wems -sticky nw;\n" ,"grid anchor $f.optframe center\n" ,"proc roundscale_helper_osx {w val} {\n" ,"global [$w cget -variable] options.badellimit\n" ,"set [$w cget -variable] [tcl::mathfunc::round $val]\n" ,"set options.badellimit [expr [tcl::mathfunc::round $val]+160]\n" ,"}\n" ,"proc my_validate_helper_osx {w val} {\n" ,"if {[string length $val] == 0} {return 0}\n" ,"if {[string is double $val] == 1} {\n" ,"set scale_loc [lindex [winfo children [winfo parent $w]] [lsearch [winfo children [winfo parent $w]] *scale]]\n" ,"global [$scale_loc cget -variable] options.badellimit\n" ,"set [$scale_loc cget -variable] [tcl::mathfunc::max [$scale_loc cget -from] [tcl::mathfunc::min [$scale_loc cget -to] [expr [tcl::mathfunc::round $val]-160]]]\n" ,"set options.badellimit [tcl::mathfunc::max [expr [$scale_loc cget -from]+160] [tcl::mathfunc::min [expr [$scale_loc cget -to]+160] [tcl::mathfunc::round $val]]]\n" ,"return 1\n" ,"} else {\n" ,"return 0\n" ,"}\n" ,"}\n" ,"proc my_invalid_helper_osx {w} {\n" ,"global options.badellimit\n" ,"set scale_loc [lindex [winfo children [winfo parent $w]] [lsearch [winfo children [winfo parent $w]] *scale]]\n" ,"global [$scale_loc cget -variable]\n" ,"set [$scale_loc cget -variable] [tcl::mathfunc::round [$scale_loc get]]\n" ,"set options.badellimit [expr [tcl::mathfunc::round [$scale_loc get]]+160]\n" ,"}\n" ,"global dummy_badellimit\n" ,"set dummy_badellimit 15\n" ,"ttk::labelframe $f.optframe2 -text \"Bad elements\" -relief groove -borderwidth 3\n" ,"pack $f.optframe2 -fill x -pady 15 -ipady 5\n" ,"ttk::frame $f.optframe2.badellimit\n" ,"ttk::label $f.optframe2.lab -text \"bad element criterion\";\n" ,"ttk::scale $f.optframe2.scale -orient horizontal -length 100 -from 00 -to 20 -variable dummy_badellimit -takefocus 0 -command \"roundscale_helper_osx $f.optframe2.scale\"\n" ,"ttk::entry $f.optframe2.entry -textvariable options.badellimit -width 3 -validate focusout -takefocus 0 -validatecommand \"my_validate_helper_osx %W %P\" \\\n" ,"-invalidcommand \"my_invalid_helper_osx %W\"\n" ,"grid $f.optframe2.scale $f.optframe2.entry $f.optframe2.lab -padx 4 -sticky nw\n" ,"grid anchor $f.optframe2 center\n" ,"set f $w.nb.debug\n" ,"ttk::labelframe $f.f2 -text \"Advanced options\" -borderwidth 3 -relief groove\n" ,"pack $f.f2 -fill x -pady 15\n" ,"set f $f.f2\n" ,"ttk::checkbutton $f.localh -text \"Use Local Meshsize\" \\\n" ,"-variable options.localh\n" ,"ttk::checkbutton $f.delauney -text \"Use Delaunay\" \\\n" ,"-variable options.delaunay\n" ,"ttk::checkbutton $f.checkoverlap -text \"Check Overlapping\" \\\n" ,"-variable options.checkoverlap\n" ,"ttk::checkbutton $f.checkcb -text \"Check Chart Boundary\" \\\n" ,"-variable options.checkchartboundary\n" ,"ttk::checkbutton $f.blockfill -text \"Do Blockfilling\" \\\n" ,"-variable options.blockfill\n" ,"grid $f.localh $f.delauney -sticky nw\n" ,"grid $f.checkoverlap $f.blockfill -sticky nw\n" ,"grid $f.checkcb -sticky nw\n" ,"grid anchor $f center\n" ,"set f $w.nb.debug\n" ,"proc enable_cb {w1 w2 w3} {\n" ,"Ng_SetDebugParameters\n" ,"if {[string match *selected* [$w1 state]] == 1 } {\n" ,"$w2 configure -state normal\n" ,"$w3 configure -state normal\n" ,"} else {\n" ,"$w2 configure -state disabled\n" ,"$w3 configure -state disabled\n" ,"}\n" ,"}\n" ,"ttk::labelframe $f.cb1 -text \"Debugging options\" -borderwidth 3 -relief groove\n" ,"pack $f.cb1 -fill x -pady 15\n" ,"ttk::checkbutton $f.cb1.slowchecks -text \"Slow checks\" \\\n" ,"-variable debug.slowchecks -command { Ng_SetDebugParameters }\n" ,"ttk::checkbutton $f.cb1.debugoutput -text \"Debugging outout\" \\\n" ,"-variable debug.debugoutput -command { Ng_SetDebugParameters }\n" ,"ttk::checkbutton $f.cb1.haltexline -text \"Halt on existing line\" \\\n" ,"-variable debug.haltexistingline -command { Ng_SetDebugParameters }\n" ,"ttk::checkbutton $f.cb1.haltoverlap -text \"Halt on Overlap\" \\\n" ,"-variable debug.haltoverlap -command { Ng_SetDebugParameters }\n" ,"ttk::checkbutton $f.cb1.haltsuc -text \"Halt on success\" \\\n" ,"-variable debug.haltsuccess -command { Ng_SetDebugParameters }\n" ,"ttk::checkbutton $f.cb1.haltnosuc -text \"Halt on no success\" \\\n" ,"-variable debug.haltnosuccess -command { Ng_SetDebugParameters }\n" ,"ttk::checkbutton $f.cb1.haltlargequal -text \"Halt on large quality class\" \\\n" ,"-variable debug.haltlargequalclass -command { Ng_SetDebugParameters }\n" ,"ttk::checkbutton $f.cb1.haltseg -text \"Halt on Segment:\" \\\n" ,"-variable debug.haltsegment -command \"enable_cb %W $f.cb1.segs.ent1 $f.cb1.segs.ent2\"\n" ,"ttk::checkbutton $f.cb1.haltnode -text \"Halt on Node:\" \\\n" ,"-variable debug.haltnode -command \"enable_cb %W $f.cb1.segs.ent1 $f.cb1.segs.ent2\"\n" ,"ttk::frame $f.cb1.fr\n" ,"ttk::checkbutton $f.cb1.fr.cb -text \"Halt on Face:\" \\\n" ,"-variable debug.haltface -command \"enable_cb %W $f.cb1.fr.ent $f.cb1.fr.ent\"\n" ,"ttk::entry $f.cb1.fr.ent -textvariable debug.haltfacenr -width 3 -state disabled\n" ,"pack $f.cb1.fr.cb $f.cb1.fr.ent -side left\n" ,"ttk::frame $f.cb1.segs\n" ,"ttk::label $f.cb1.segs.lab1 -text \"P1:\"\n" ,"ttk::entry $f.cb1.segs.ent1 -width 6 \\\n" ,"-textvariable debug.haltsegmentp1 -state disabled\n" ,"ttk::label $f.cb1.segs.lab2 -text \"P2:\"\n" ,"ttk::entry $f.cb1.segs.ent2 -width 6 \\\n" ,"-textvariable debug.haltsegmentp2 -state disabled\n" ,"pack $f.cb1.segs.lab1 $f.cb1.segs.ent1 $f.cb1.segs.lab2 $f.cb1.segs.ent2 -side left\n" ,"grid $f.cb1.slowchecks $f.cb1.debugoutput -sticky nw\n" ,"grid $f.cb1.haltexline $f.cb1.haltoverlap -sticky nw\n" ,"grid $f.cb1.haltsuc $f.cb1.haltnosuc -sticky nw\n" ,"grid $f.cb1.haltlargequal $f.cb1.fr -sticky nw\n" ,"grid $f.cb1.haltnode -sticky nw\n" ,"grid $f.cb1.haltseg -stick nw\n" ,"grid $f.cb1.segs -stick w -row 4 -rowspan 2 -column 1\n" ,"grid rowconfigure $f.cb1 3 -pad 8\n" ,"grid anchor $f.cb1 center\n" ,"ttk::checkbutton $f.cb1.showactivechart -text \"Show Active Meshing-Chart\" -variable stloptions.showactivechart -command { Ng_SetVisParameters; redraw }\n" ,"grid $f.cb1.showactivechart\n" ,"grid rowconfigure $f.cb1 3 -pad 8\n" ,"grid rowconfigure $f.cb1 5 -pad 8\n" ,"set f $w.nb.debug\n" ,"ttk::labelframe $f.cont -relief groove -borderwidth 3 -text \"Debugging visualization\"\n" ,"pack $f.cont -fill x -pady 15\n" ,"ttk::checkbutton $f.cont.multidrawing -text \"Draw Meshing\" -variable multithread_drawing\n" ,"ttk::checkbutton $f.cont.multitestmode -text \"Meshing Testmode\" -variable multithread_testmode\n" ,"ttk::button $f.cont.goon -text \"Go On\" -command { set multithread_pause 0 }\n" ,"grid $f.cont.multidrawing -sticky nw\n" ,"grid $f.cont.multitestmode -sticky nw\n" ,"grid $f.cont.goon -row 0 -rowspan 2 -column 1 -sticky w\n" ,"grid columnconfigure $f.cont 0 -pad 30\n" ,"grid columnconfigure $f.cont 1 -pad 20\n" ,"grid anchor $f.cont center\n" ,"global userlevel\n" ,"if { $userlevel < 3} {\n" ,"$w.nb delete insider\n" ,"$w.nb delete debug\n" ,"}\n" ,"ttk::frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.apl -text \"Apply\" -command {\n" ,"Ng_SetMeshingParameters\n" ,"Ng_SetDebugParameters\n" ,"}\n" ,"ttk::button $w.bu.ok -text \"Done\" -command {\n" ,"Ng_SetMeshingParameters\n" ,"Ng_SetDebugParameters\n" ,"wm withdraw .options_dlg\n" ,"}\n" ,"pack $w.bu.apl $w.bu.ok -side left -expand yes\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Meshing Options\"\n" ,"focus .options_dlg\n" ,"}\n" ,"}\n" ,"meshingoptionsdialog\n" ,"wm withdraw .options_dlg\n" ,"proc viewingoptionsdialog { } {\n" ,"global userlevel\n" ,"set w .viewopts_dlg\n" ,"if {[winfo exists .viewopts_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"pack [ttk::notebook $w.nb] -fill both -fill both -side top\n" ,"$w.nb add [ttk::frame $w.nb.general] -text \"General\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.stl] -text \"STL\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.occ] -text \"IGES/STEP\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.mesh] -text \"Mesh\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.light] -text \"Light\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.edges] -text \"Edges\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.misc] -text \"Misc.\" -underline 3\n" ,"set f $w.nb.general\n" ,"ttk::labelframe $f.gvop -text \"General viewing options\" -relief groove -borderwidth 3\n" ,"pack $f.gvop -fill x -pady 15\n" ,"set f $f.gvop\n" ,"ttk::checkbutton $f.backcol -text \"White Background\" \\\n" ,"-variable viewoptions.whitebackground \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.cross -text \"Draw Coordinate Cross\" \\\n" ,"-variable viewoptions.drawcoordinatecross \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.color -text \"Draw Color-bar\" \\\n" ,"-variable viewoptions.drawcolorbar \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.netgen -text \"Draw Netgen-logo\" \\\n" ,"-variable viewoptions.drawnetgenlogo \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"grid $f.backcol -sticky nw\n" ,"grid $f.cross -stick nw\n" ,"grid $f.color -sticky nw\n" ,"grid $f.netgen -sticky nw\n" ,"menu $f.stylemenu\n" ,"ttk::menubutton $f.style -menu $f.stylemenu -width 10 -text [ttk::style theme use]\n" ,"grid $f.style -sticky nw\n" ,"grid anchor $f center\n" ,"foreach theme [ttk::themes] {\n" ,"$f.stylemenu add command -label $theme \\\n" ,"-command \" $f.style configure -text $theme; puts $theme ; ttk::setTheme $theme\"\n" ,"}\n" ,"set f $w.nb.stl\n" ,"ttk::labelframe $f.show -relief groove -borderwidth 3 -text \"STL viewing options\"\n" ,"pack $f.show -fill x -pady 15\n" ,"ttk::checkbutton $f.show.showtrias -text \"Show STL-Triangles\" \\\n" ,"-variable stloptions.showtrias -command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.show.showfilledtrias -text \"Show Filled Triangles\" \\\n" ,"-variable stloptions.showfilledtrias -command { Ng_SetVisParameters; redraw }\n" ,"grid $f.show.showtrias $f.show.showfilledtrias -sticky nw\n" ,"ttk::checkbutton $f.show.showactivechart -text \"Show Active Meshing-Chart\" \\\n" ,"-variable stloptions.showactivechart -command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.show.showedges -text \"Show Edges\" \\\n" ,"-variable stloptions.showedges -command { Ng_SetVisParameters; redraw }\n" ,"grid $f.show.showactivechart $f.show.showedges -sticky nw\n" ,"grid anchor $f.show center\n" ,"ttk::checkbutton $f.show.showmarktrias -text \"Show Chart Triangles\" \\\n" ,"-variable stloptions.showmarktrias \\\n" ,"-command {set stldoctor.showfaces 0; Ng_STLDoctor; Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.show.showfaces -text \"Show Faces\" \\\n" ,"-variable stldoctor.showfaces \\\n" ,"-command {set stloptions.showmarktrias 0; Ng_STLDoctor; Ng_SetVisParameters; redraw}\n" ,"grid $f.show.showmarktrias $f.show.showfaces -sticky nw\n" ,"ttk::labelframe $f.fn -relief groove -borderwidth 3 -text \"Chart/Face number\"\n" ,"pack $f.fn -fill x\n" ,"ttk::label $f.fn.lab3 -text \"Chart/Face number\"\n" ,"ttk::scale $f.fn.scale3 -orient horizontal -length 150 -from 0 -to 200 \\\n" ,"-variable stloptions.chartnumber -command \"Ng_SetVisParameters; redraw;roundscale $f.fn.scale3 0\"\n" ,"ttk::entry $f.fn.ent3 -textvariable stloptions.chartnumber -width 3 -validate focus -takefocus 0 \\\n" ,"-validatecommand \"Ng_SetVisParameters; redraw;my_validate %W [$f.fn.scale3 cget -from] [$f.fn.scale3 cget -to] %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n" ,"grid $f.fn.scale3 $f.fn.ent3 $f.fn.lab3 -sticky nw -padx 4\n" ,"tk::label $f.fn.lab -text \"Chart/Face Offset:\";\n" ,"ttk::entry $f.fn.ent -width 3 \\\n" ,"-textvariable stloptions.chartnumberoffset -validate focus -takefocus 0 \\\n" ,"-validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.fn.lab -sticky ne -padx 4\n" ,"grid $f.fn.ent -sticky nw -padx 4 -row 1 -column 1\n" ,"grid anchor $f.fn center\n" ,"ttk::labelframe $f.advstl -text \"Advanced STL options\" -relief groove -borderwidth 3\n" ,"pack $f.advstl -fill x -pady 15\n" ,"ttk::checkbutton $f.advstl.bu1 -text \"Show Marked (Dirty) Triangles\" \\\n" ,"-variable stldoctor.showmarkedtrigs \\\n" ,"-command {Ng_STLDoctor; redraw}\n" ,"ttk::checkbutton $f.advstl.bu2 -text \"show edge corner points\" \\\n" ,"-variable stldoctor.showedgecornerpoints \\\n" ,"-command {Ng_STLDoctor; redraw}\n" ,"ttk::checkbutton $f.advstl.bu3 -text \"show touched triangle chart\" \\\n" ,"-variable stldoctor.showtouchedtrigchart \\\n" ,"-command {set stldoctor.showfaces 0; set stloptions.showmarktrias 1; \\\n" ,"Ng_STLDoctor; Ng_SetVisParameters; redraw}\n" ,"ttk::checkbutton $f.advstl.bu4 -text \"draw meshed edges\" \\\n" ,"-variable stldoctor.drawmeshededges \\\n" ,"-command {Ng_STLDoctor;}\n" ,"ttk::checkbutton $f.advstl.bu5 -text \"select with mouse\" \\\n" ,"-variable stldoctor.selectwithmouse\n" ,"grid $f.advstl.bu1 -stick nw\n" ,"grid $f.advstl.bu2 -sticky nw\n" ,"grid $f.advstl.bu3 -stick nw\n" ,"grid $f.advstl.bu4 -stick nw\n" ,"grid $f.advstl.bu5 -stick nw\n" ,"grid anchor $f.advstl center\n" ,"ttk::frame $f.advstl.tbn\n" ,"ttk::label $f.advstl.tbn.lab -text \"Select triangle by number\";\n" ,"ttk::entry $f.advstl.tbn.ent -width 5 \\\n" ,"-textvariable stldoctor.selecttrig\n" ,"pack $f.advstl.tbn.lab $f.advstl.tbn.ent -padx 4 -side left\n" ,"grid $f.advstl.tbn -sticky nw\n" ,"grid anchor $f.advstl center\n" ,"grid rowconfigure $f.advstl 4 -pad 8\n" ,"ttk::labelframe $f.vc -relief groove -borderwidth 3 -text \"Vicinity options\"\n" ,"pack $f.vc -fill x -pady 15\n" ,"ttk::checkbutton $f.vc.bu -text \"show vicinity\" \\\n" ,"-variable stldoctor.showvicinity \\\n" ,"-command {Ng_STLDoctor vicinity; redraw}\n" ,"ttk::label $f.vc.lab -text \"vicinity size\";\n" ,"ttk::scale $f.vc.scale -orient horizontal -length 150 -from 0 -to 200 \\\n" ,"-variable stldoctor.vicinity \\\n" ,"-takefocus 0 \\\n" ,"-command \"roundscale $f.vc.scale 0; Ng_STLDoctor vicinity; redraw\"\n" ,"ttk::entry $f.vc.ent -width 4 -textvariable stldoctor.vicinity -validate focus \\\n" ,"-takefocus 0 -validatecommand \"Ng_STLDoctor vicinity; redraw;my_validate %W [$f.vc.scale cget -from] [$f.vc.scale cget -to] %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_STLDoctor vicinity; redraw\"\n" ,"grid $f.vc.bu -stick nw -columnspan 3 -column 0\n" ,"grid $f.vc.scale $f.vc.ent $f.vc.lab -sticky nw -padx 4\n" ,"grid anchor $f.vc center\n" ,"set f $w.nb.occ\n" ,"ttk::labelframe $f.occframe -text \"IGES/STEP options\" -relief groove -borderwidth 3\n" ,"pack $f.occframe -fill x -pady 15 -ipady 8\n" ,"ttk::checkbutton $f.occframe.occshowsurfaces -text \"Show surfaces \" \\\n" ,"-variable occoptions.showsurfaces \\\n" ,"-command { Ng_SetOCCVisParameters; redraw }\n" ,"ttk::checkbutton $f.occframe.occshowedges -text \"Show edges \" \\\n" ,"-variable occoptions.showedges \\\n" ,"-command { Ng_SetOCCVisParameters; redraw }\n" ,"grid $f.occframe.occshowsurfaces $f.occframe.occshowedges -sticky nw -padx 4\n" ,"grid anchor $f.occframe center\n" ,"ttk::button $f.occframe.btn -text \"Rebuild visualization data\" \\\n" ,"-command {\n" ,"Ng_SetOCCVisParameters\n" ,"Ng_OCCCommand buildvisualizationmesh\n" ,"redraw\n" ,"}\n" ,"ttk::frame $f.occframe.vssm\n" ,"ttk::label $f.occframe.vssm.lab -text \"Visulization smoothness\"\n" ,"ttk::spinbox $f.occframe.vssm.sp -textvariable occoptions.deflection \\\n" ,"-from 0.1 -to 3 -increment 0.1 -width 4 -command { catch Ng_SetOCCVisParameters } \\\n" ,"-validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"pack $f.occframe.vssm.lab $f.occframe.vssm.sp -side left -padx 4\n" ,"grid $f.occframe.vssm -sticky nw -columnspan 2 -column 0 -pady 8\n" ,"grid $f.occframe.btn -columnspan 2 -column 0 -sticky n\n" ,"ttk::labelframe $f.occframe1 -relief groove -borderwidth 3 -text \"ACIS visulization / construction\"\n" ,"pack $f.occframe1 -fill x -pady 15 -ipady 8\n" ,"ttk::label $f.occframe1.lab1 -text \"Show solid (0 for all)\"\n" ,"ttk::spinbox $f.occframe1.sp1 -textvariable occoptions.showsolidnr \\\n" ,"-from 0 -to 999 -increment 1 -width 4 -command { catch Ng_SetOCCVisParameters;redraw } \\\n" ,"-validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"ttk::label $f.occframe1.lab2 -text \"Show solid 2\"\n" ,"ttk::spinbox $f.occframe1.sp2 -textvariable occoptions.showsolidnr2 \\\n" ,"-from 0 -to 999 -increment 1 -width 4 -command { catch Ng_SetOCCVisParameters;redraw } \\\n" ,"-validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"ttk::button $f.occframe1.subtract -text \"Subtract (2 minus 1)\" \\\n" ,"-command {\n" ,"Ng_ACISCommand subtract ${occoptions.showsolidnr} ${occoptions.showsolidnr2}\n" ,"redraw\n" ,"}\n" ,"ttk::button $f.occframe1.combine -text \"Combine all\" \\\n" ,"-command {\n" ,"Ng_ACISCommand combineall\n" ,"redraw\n" ,"}\n" ,"grid $f.occframe1.lab1 -row 0 -column 0 -sticky ne\n" ,"grid $f.occframe1.sp1 -row 0 -column 1 -sticky nw\n" ,"grid $f.occframe1.lab2 -row 1 -column 0 -sticky ne\n" ,"grid $f.occframe1.sp2 -row 1 -column 1 -sticky nw\n" ,"grid $f.occframe1.combine -columnspan 2 -column 0 -sticky n\n" ,"grid anchor $f.occframe1 center\n" ,"set f $w.nb.mesh\n" ,"ttk::labelframe $f.center -relief groove -borderwidth 3 -text \"how shall i name you?\"\n" ,"pack $f.center -fill x -pady 15\n" ,"ttk::button $f.center.lab1 -text \"Set Center Point\" \\\n" ,"-command { Ng_SetVisParameters; Ng_Center; redraw }\n" ,"ttk::entry $f.center.ent1 -width 5 \\\n" ,"-textvariable viewoptions.centerpoint -validate focus \\\n" ,"-validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.center.ent1 $f.center.lab1 -padx 4 -pady 4 -sticky nw\n" ,"ttk::button $f.center.lab2 -text \"Draw Element\" \\\n" ,"-command { Ng_SetVisParameters; Ng_ZoomAll; redraw }\n" ,"ttk::entry $f.center.ent2 -width 5 \\\n" ,"-textvariable viewoptions.drawelement -validate focus \\\n" ,"-validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.center.ent2 $f.center.lab2 -padx 4 -pady 4 -sticky nw\n" ,"grid anchor $f.center center\n" ,"ttk::labelframe $f.meshframe -text \"Mesh visualization options\" -relief groove -borderwidth 3\n" ,"pack $f.meshframe -fill x -pady 15\n" ,"set f $f.meshframe\n" ,"ttk::checkbutton $f.showcolor -text \"Meshsize Visualization\" \\\n" ,"-variable viewoptions.colormeshsize \\\n" ,"-command { Ng_SetVisParameters;redraw; }\n" ,"ttk::checkbutton $f.showfilledtrigs -text \"Show filled triangles\" \\\n" ,"-variable viewoptions.drawfilledtrigs \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showedges -text \"Show edges\" \\\n" ,"-variable viewoptions.drawedges \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showoutline -text \"Show Triangle Outline\" \\\n" ,"-variable viewoptions.drawoutline \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showbadels -text \"Show bad elements\" \\\n" ,"-variable viewoptions.drawbadels \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showprisms -text \"Show prisms\" \\\n" ,"-variable viewoptions.drawprisms \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showpyramids -text \"Show pyramids\" \\\n" ,"-variable viewoptions.drawpyramids \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showhexes -text \"Show hexes\" \\\n" ,"-variable viewoptions.drawhexes \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showidentified -text \"Show identified points\" \\\n" ,"-variable viewoptions.drawidentified \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showmetispartition -text \"Show METIS Partition\" \\\n" ,"-variable viewoptions.drawmetispartition \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showpointnumbers -text \"Show Point-numbers\" \\\n" ,"-variable viewoptions.drawpointnumbers \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showedgenumbers -text \"Show Edge-numbers\" \\\n" ,"-variable viewoptions.drawedgenumbers \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showfacenumbers -text \"Show Face-numbers\" \\\n" ,"-variable viewoptions.drawfacenumbers \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showelementnumbers -text \"Show Element-numbers\" \\\n" ,"-variable viewoptions.drawelementnumbers \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::frame $f.frametets\n" ,"ttk::checkbutton $f.frametets.showtets -text \"\" \\\n" ,"-variable viewoptions.drawtets \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::label $f.frametets.label -text \"\\Show Tets\\rin domain\"\n" ,"ttk::spinbox $f.frametets.showtetsdomain -from 0 -to 500 -increment 1 -width 3 \\\n" ,"-textvariable viewoptions.drawtetsdomain -validate focus \\\n" ,"-command \"Ng_SetVisParameters; redraw;\" \\\n" ,"-validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"ttk::label $f.frametets.label1 -text \"Subdivision\"\n" ,"ttk::spinbox $f.frametets.subdiv -from 0 -to 8 -increment 1 -width 3 \\\n" ,"-textvariable visoptions.subdivisions -validate focus \\\n" ,"-command { Ng_SetVisParameters; Ng_Vis_Set parameters; Ng_SetNextTimeStamp; redraw } \\\n" ,"-validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"ttk::label $f.frametets.label2 -text \"Show surface\\rof domain\"\n" ,"ttk::spinbox $f.frametets.showdomain -from 0 -to 50 -increment 1 -width 3 \\\n" ,"-textvariable viewoptions.drawdomainsurf -validate focus \\\n" ,"-command { Ng_SetVisParameters; Ng_Vis_Set parameters; redraw } \\\n" ,"-validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"grid $f.frametets.showtets $f.frametets.label $f.frametets.showtetsdomain -sticky w\n" ,"grid x $f.frametets.label2 $f.frametets.showdomain -stick w\n" ,"grid x $f.frametets.label1 $f.frametets.subdiv -sticky w\n" ,"grid $f.showfilledtrigs $f.showoutline -sticky nw\n" ,"grid $f.showedges $f.showbadels -sticky nw\n" ,"grid $f.showpointnumbers $f.showedgenumbers -sticky nw\n" ,"grid $f.showfacenumbers $f.showelementnumbers -sticky nw\n" ,"grid $f.showmetispartition $f.showidentified -sticky nw\n" ,"grid $f.showcolor $f.showpyramids -sticky nw\n" ,"grid $f.showprisms $f.showhexes -sticky nw\n" ,"grid $f.frametets -sticky n -columnspan 2 -column 0 -pady 8\n" ,"grid anchor $f center\n" ,"set f $w.nb.mesh\n" ,"ttk::labelframe $f.fshrink -text \"Element visualization\" -relief groove -borderwidth 3\n" ,"ttk::label $f.fshrink.lab -text \"Shrink elements\"\n" ,"ttk::scale $f.fshrink.scale -orient horizontal -length 200 -from 0 -to 1.0001 \\\n" ,"-command \"roundscale $f.fshrink.scale 2;Ng_SetVisParameters; after idle redraw\" \\\n" ,"-variable viewoptions.shrink\n" ,"ttk::entry $f.fshrink.entry -textvariable viewoptions.shrink -width 4 -validate focus \\\n" ,"-takefocus 0 -validatecommand \"Ng_SetVisParameters; after idle redraw;my_validate %W [$f.fshrink.scale cget -from] [$f.fshrink.scale cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetVisParameters; after idle redraw;\"\n" ,"pack $f.fshrink -fill x -ipady 8\n" ,"grid $f.fshrink.scale $f.fshrink.entry $f.fshrink.lab -padx 4\n" ,"grid anchor $f.fshrink center\n" ,"set f $w.nb.light\n" ,"ttk::labelframe $f.main -text \"Lighting options\" -relief groove -borderwidth 3\n" ,"pack $f.main -fill x -pady 15\n" ,"set f $f.main\n" ,"ttk::label $f.lab1 -text \"Ambient Light\"\n" ,"ttk::scale $f.scale1 -orient horizontal -length 200 -from 0 -to 1 \\\n" ,"-command \"roundscale $f.scale1 2; Ng_SetVisParameters; redraw\" \\\n" ,"-variable viewoptions.light.amb\n" ,"ttk::entry $f.ent1 -textvariable viewoptions.light.amb -validate focus -width 4 \\\n" ,"-validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale1 cget -from] [$f.scale1 cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n" ,"ttk::label $f.lab2 -text \"Diffuse Light\"\n" ,"ttk::scale $f.scale2 -orient horizontal -length 200 -from 0 -to 1 \\\n" ,"-command \"roundscale $f.scale2 2; Ng_SetVisParameters; redraw \" \\\n" ,"-variable viewoptions.light.diff\n" ,"ttk::entry $f.ent2 -textvariable viewoptions.light.diff -validate focus -width 4 \\\n" ,"-validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale2 cget -from] [$f.scale2 cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n" ,"ttk::label $f.lab3 -text \"Specular Light\"\n" ,"ttk::scale $f.scale3 -orient horizontal -length 200 -from 0 -to 1 \\\n" ,"-command \"roundscale $f.scale3 2; Ng_SetVisParameters; redraw \" \\\n" ,"-variable viewoptions.light.spec\n" ,"ttk::entry $f.ent3 -textvariable viewoptions.light.spec -validate focus -width 4 \\\n" ,"-validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale3 cget -from] [$f.scale3 cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n" ,"grid $f.scale1 $f.ent1 $f.lab1 -sticky nw -padx 4 -pady 8\n" ,"grid $f.scale2 $f.ent2 $f.lab2 -sticky nw -padx 4 -pady 8\n" ,"grid $f.scale3 $f.ent3 $f.lab3 -sticky nw -padx 4 -pady 8\n" ,"grid anchor $f center\n" ,"set f $w.nb.light\n" ,"ttk::labelframe $f.main1 -text \"Material options\" -relief groove -borderwidth 3\n" ,"pack $f.main1 -fill x -pady 15\n" ,"set f $f.main1\n" ,"ttk::label $f.lab4 -text \"Material Shininess\"\n" ,"ttk::scale $f.scale4 -orient horizontal -length 200 -from 0 -to 128 \\\n" ,"-command \"roundscale $f.scale4 0; Ng_SetVisParameters; redraw \" \\\n" ,"-variable viewoptions.mat.shininess\n" ,"ttk::entry $f.ent4 -textvariable viewoptions.mat.shininess -validate focus -width 4 \\\n" ,"-validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale4 cget -from] [$f.scale4 cget -to] %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n" ,"ttk::label $f.lab5 -text \"Material Transparency\"\n" ,"ttk::scale $f.scale5 -orient horizontal -length 200 -from 0 -to 1 \\\n" ,"-command \"roundscale $f.scale5 2; Ng_SetVisParameters; redraw \" \\\n" ,"-variable viewoptions.mat.transp\n" ,"ttk::entry $f.ent5 -textvariable viewoptions.mat.transp -validate focus -width 4 \\\n" ,"-validatecommand \" Ng_SetVisParameters; redraw;my_validate %W [$f.scale5 cget -from] [$f.scale5 cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetVisParameters; redraw;\"\n" ,"grid $f.scale4 $f.ent4 $f.lab4 -sticky nw -padx 4 -pady 8\n" ,"grid $f.scale5 $f.ent5 $f.lab5 -sticky nw -padx 4 -pady 8\n" ,"grid anchor $f center\n" ,"set f $w.nb.edges\n" ,"ttk::labelframe $f.main -text \"Edge viewing options\" -relief groove -borderwidth 3\n" ,"pack $f.main -fill x -pady 15\n" ,"set f $f.main\n" ,"ttk::frame $f.helper\n" ,"pack $f.helper -anchor center\n" ,"set f $f.helper\n" ,"ttk::checkbutton $f.showedges -text \"Show Edges\" \\\n" ,"-variable viewoptions.drawededges \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showpoints -text \"Show Points\" \\\n" ,"-variable viewoptions.drawedpoints \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showpointnrs -text \"Show Points Nrs\" \\\n" ,"-variable viewoptions.drawedpointnrs \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.showtang -text \"Show CP Tangents\" \\\n" ,"-variable viewoptions.drawedtangents \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.drawedgenrs -text \"Show Edge Nrs\" \\\n" ,"-variable viewoptions.drawededgenrs \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"pack $f.showedges $f.showpoints $f.showpointnrs $f.showtang $f.drawedgenrs -anchor w\n" ,"set f $w.nb.edges\n" ,"ttk::labelframe $f.main1 -text \"Center point\" -relief groove -borderwidth 3\n" ,"pack $f.main1 -fill x -pady 15\n" ,"set f $f.main1\n" ,"ttk::frame $f.center\n" ,"pack $f.center -anchor center\n" ,"ttk::button $f.center.btn -text \"Set Center Point\" \\\n" ,"-command { Ng_SetVisParameters; Ng_Center; redraw }\n" ,"ttk::entry $f.center.ent -width 5 -textvariable viewoptions.centerpoint -validate focus \\\n" ,"-validatecommand \"my_validate %W 0 1e9 %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.center.ent $f.center.btn -sticky nw -padx 4\n" ,"ttk::label $f.center.lab1 -text \"SpecPoint Veclen\"\n" ,"ttk::entry $f.center.ent1 -width 5 -textvariable viewoptions.specpointvlen -validate focus \\\n" ,"-validatecommand \"my_validate %W 0 1e9 %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.center.ent1 $f.center.lab1 -sticky nw -padx 4\n" ,"set f $w.nb.misc\n" ,"ttk::labelframe $f.point -relief groove -borderwidth 3 -text \"Special point\"\n" ,"ttk::frame $f.point.dp\n" ,"ttk::checkbutton $f.point.dp.drawpoint -text \"Draw Point\" \\\n" ,"-variable viewoptions.drawspecpoint \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::entry $f.point.dp.px -width 8 -textvariable viewoptions.specpointx -validate focus \\\n" ,"-validatecommand \"my_validate %W -1e9 1e9 %P 10\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"ttk::entry $f.point.dp.py -width 8 -textvariable viewoptions.specpointy -validate focus \\\n" ,"-validatecommand \"my_validate %W -1e9 1e9 %P 10\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"ttk::entry $f.point.dp.pz -width 8 -textvariable viewoptions.specpointz -validate focus \\\n" ,"-validatecommand \"my_validate %W -1e9 1e9 %P 10\" \\\n" ,"-invalidcommand \"my_invalid %W\"\n" ,"grid $f.point.dp.drawpoint $f.point.dp.px $f.point.dp.py $f.point.dp.pz -sticky nw -padx 4;\n" ,"ttk::checkbutton $f.point.dp.center -text \"Use as Center\" \\\n" ,"-variable viewoptions.usecentercoords \\\n" ,"-command {\n" ,"if { ${viewoptions.usecentercoords} } {\n" ,"set viewoptions.centerx ${viewoptions.specpointx}\n" ,"set viewoptions.centery ${viewoptions.specpointy}\n" ,"set viewoptions.centerz ${viewoptions.specpointz}\n" ,"Ng_SetVisParameters; Ng_Center\n" ,"redraw\n" ,"} {\n" ,"Ng_SetVisParameters\n" ,"}\n" ,"}\n" ,"grid $f.point.dp.center -sticky nw -padx 4\n" ,"pack $f.point.dp\n" ,"pack $f.point -fill x -ipady 3 -pady 15\n" ,"ttk::frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.done -text \"Done\" -command {\n" ,"Ng_SetVisParameters;\n" ,"redraw\n" ,"destroy .viewopts_dlg\n" ,"}\n" ,"ttk::button $w.bu.apply -text \"Apply\" -command {\n" ,"Ng_SetVisParameters;\n" ,"redraw\n" ,"}\n" ,"pack $w.bu.apply $w.bu.done -expand yes -side left\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Viewing options\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc clipplanecommand { { optionalvar 0 } } {\n" ,"Ng_SetVisParameters\n" ,"after idle redraw\n" ,"}\n" ,"set clippingdialog_pop1 0\n" ,"set clippingdialog_pop2 0\n" ,"set clippingdialog_pop3 0\n" ,"set clippingdialog_pop4 0\n" ,"proc clippingdialog { } {\n" ,"global clippingdialog_pop1\n" ,"global clippingdialog_pop2\n" ,"global clippingdialog_pop3\n" ,"global clippingdialog_pop4\n" ,"set clippingdialog_pop1 1\n" ,"set clippingdialog_pop2 1\n" ,"set clippingdialog_pop3 1\n" ,"set clippingdialog_pop4 1\n" ,"set w .clipping_dlg\n" ,"if {[winfo exists .clipping_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"ttk::frame $w.background\n" ,"pack $w.background -fill x -fill y\n" ,"set w $w.background\n" ,"ttk::labelframe $w.main -text \"Visual clipping\" -relief groove -borderwidth 3\n" ,"pack $w.main -fill x -pady 15\n" ,"set w $w.main\n" ,"ttk::label $w.lab1 -text \"Normal x\"\n" ,"ttk::scale $w.scale1 -orient horizontal -length 300 -from -1 -to 1 \\\n" ,"-variable viewoptions.clipping.nx \\\n" ,"-command \"roundscale $w.scale1 2; clipplanecommand \"\n" ,"ttk::entry $w.entry1 -width 5 -textvariable viewoptions.clipping.nx \\\n" ,"-validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale1 cget -from] [$w.scale1 cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W; clipplanecommand\"\n" ,"ttk::label $w.lab2 -text \"Normal y\"\n" ,"ttk::scale $w.scale2 -orient horizontal -length 300 -from -1 -to 1 \\\n" ,"-variable viewoptions.clipping.ny \\\n" ,"-command \"roundscale $w.scale2 2; clipplanecommand \"\n" ,"ttk::entry $w.entry2 -width 5 -textvariable viewoptions.clipping.ny \\\n" ,"-validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale2 cget -from] [$w.scale2 cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid $w.entry2;clipplanecommand\"\n" ,"ttk::label $w.lab3 -text \"Normal z\"\n" ,"ttk::scale $w.scale3 -orient horizontal -length 300 -from -1 -to 1 \\\n" ,"-variable viewoptions.clipping.nz \\\n" ,"-command \"roundscale $w.scale3 2; clipplanecommand \"\n" ,"ttk::entry $w.entry3 -width 5 -textvariable viewoptions.clipping.nz \\\n" ,"-validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale3 cget -from] [$w.scale3 cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;clipplanecommand\"\n" ,"ttk::label $w.lab4 -text \"Distance\"\n" ,"ttk::scale $w.scale4 -orient horizontal -length 300 -from -1 -to 1.001 \\\n" ,"-variable viewoptions.clipping.dist \\\n" ,"-command \"roundscale $w.scale4 3; clipplanecommand \"\n" ,"ttk::entry $w.entry4 -width 5 -textvariable viewoptions.clipping.dist \\\n" ,"-validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale4 cget -from] [$w.scale4 cget -to] %P 3\" \\\n" ,"-invalidcommand \"my_invalid %W;clipplanecommand\"\n" ,"proc my_Press {w x y} {\n" ,"set inc [expr {([$w get $x $y] <= [$w get]) ? -1 : 1}]\n" ,"ttk::Repeatedly ttk::scale::Increment $w [expr 0.001*$inc]\n" ,"}\n" ,"bind $w.scale4 { if { [string match *slider [%W identify %x %y]] == 0 } { my_Press %W %x %y;break } }\n" ,"bind $w.scale4 {ttk::scale::Release %W %x %y}\n" ,"ttk::label $w.lab5 -text \"Additional\\rDistance\"\n" ,"ttk::scale $w.scale5 -orient horizontal -length 300 -from -1 -to 1.001 \\\n" ,"-variable viewoptions.clipping.dist2 \\\n" ,"-command \"roundscale $w.scale5 3; clipplanecommand \"\n" ,"ttk::entry $w.entry5 -width 5 -textvariable viewoptions.clipping.dist2 \\\n" ,"-validate focus -validatecommand \" clipplanecommand;my_validate %W [$w.scale5 cget -from] [$w.scale5 cget -to] %P 3\" \\\n" ,"-invalidcommand \"my_invalid %W;clipplanecommand\"\n" ,"bind $w.scale5 { if { [string match *slider [%W identify %x %y]] == 0 } { my_Press %W %x %y;break } }\n" ,"bind $w.scale5 {ttk::scale::Release %W %x %y}\n" ,"ttk::label $w.clipdomainlabel -text \"Clip only domain\"\n" ,"ttk::spinbox $w.clipdomainspinb -from 0 -to 500 -increment 1 -width 3 \\\n" ,"-textvariable viewoptions.clipping.onlydomain -validate focus \\\n" ,"-command {clipplanecommand;} \\\n" ,"-validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"ttk::label $w.donotclipdomainlabel -text \"Do not clip domain\"\n" ,"ttk::spinbox $w.donotclipdomainspinb -from 0 -to 500 -increment 1 -width 3 \\\n" ,"-textvariable viewoptions.clipping.notdomain -validate focus \\\n" ,"-command \"clipplanecommand\" \\\n" ,"-validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\"\n" ,"grid $w.scale1 $w.entry1 $w.lab1 -sticky nw -padx 4 -pady 14\n" ,"grid $w.scale2 $w.entry2 $w.lab2 -sticky nw -padx 4 -pady 14\n" ,"grid $w.scale3 $w.entry3 $w.lab3 -sticky nw -padx 4 -pady 14\n" ,"grid $w.scale4 $w.entry4 $w.lab4 -sticky nw -padx 4 -pady 14\n" ,"grid $w.scale5 $w.entry5 $w.lab5 -sticky w -padx 4 -pady 14\n" ,"grid $w.clipdomainlabel -sticky ne -padx 4 -pady 14\n" ,"grid $w.clipdomainspinb -sticky nw -padx 4 -pady 14 -column 1 -row 5\n" ,"grid $w.donotclipdomainlabel -sticky ne -padx 4 -pady 14\n" ,"grid $w.donotclipdomainspinb -sticky nw -padx 4 -pady 14 -column 1 -row 6\n" ,"grid anchor $w center\n" ,"set w .clipping_dlg.background.main\n" ,"ttk::checkbutton $w.cb1 -text \"Enable clipping\" \\\n" ,"-variable viewoptions.clipping.enable \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"grid $w.cb1 -columnspan 2 -sticky ne\n" ,"ttk::frame $w.bu\n" ,"grid $w.bu;\n" ,"ttk::button $w.cancle -text \"Done\" -command \"destroy .clipping_dlg\"\n" ,"grid $w.cancle -columnspan 3 -pady 16\n" ,"set w .clipping_dlg\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Clipping Plane\"\n" ,"focus $w\n" ,"clipplanecommand\n" ,"}\n" ,"}\n" ,"proc refinementdialog { } {\n" ,"set w .refinement_dlg\n" ,"if {[winfo exists .refinement_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"global localh\n" ,"set localh 1\n" ,"ttk::frame $w.meshsize\n" ,"ttk::label $w.meshsize.l1 -text \"max mesh-size: \"\n" ,"ttk::spinbox $w.meshsize.sp1 -from 1e-6 -to 1e6 -textvariable options.meshsize -validate focus -validatecommand \"my_validatespinbox %W %P 4\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -width 6 -increment 0.1\n" ,"ttk::frame $w.meshsizeloc\n" ,"ttk::label $w.meshsizeloc.l1 -text \"local mesh-size: \"\n" ,"ttk::spinbox $w.meshsizeloc.sp1 -from 1e-6 -to 1e6 -textvariable localh -validate focus -validatecommand \"my_validatespinbox %W %P 4\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -width 6 -increment 0.1\n" ,"pack $w.meshsize\n" ,"pack $w.meshsizeloc\n" ,"grid $w.meshsize.l1 $w.meshsize.sp1\n" ,"grid $w.meshsizeloc.l1 $w.meshsizeloc.sp1\n" ,"ttk::button $w.restface -text \"Restrict H at face\" \\\n" ,"-command {\n" ,".refinement_dlg.meshsize invoke\n" ,".refinement_dlg.loch invoke\n" ,"Ng_RestrictH face $localh\n" ,"}\n" ,"ttk::button $w.restedge -text \"Restrict H at edge\" \\\n" ,"-command {\n" ,".refinement_dlg.meshsize invoke\n" ,".refinement_dlg.loch invoke\n" ,"Ng_RestrictH edge $localh\n" ,"}\n" ,"ttk::button $w.restelement -text \"Restrict H at element\" \\\n" ,"-command {\n" ,".refinement_dlg.meshsize invoke\n" ,".refinement_dlg.loch invoke\n" ,"Ng_RestrictH element $localh\n" ,"}\n" ,"ttk::button $w.restpoint -text \"Restrict H at point\" \\\n" ,"-command {\n" ,".refinement_dlg.meshsize invoke\n" ,".refinement_dlg.loch invoke\n" ,"Ng_RestrictH point $localh\n" ,"}\n" ,"pack $w.restface $w.restedge $w.restelement $w.restpoint\n" ,"ttk::button $w.anisoedge -text \"Declare Anisotropic edge\" \\\n" ,"-command {\n" ,"Ng_Anisotropy edge\n" ,"}\n" ,"pack $w.anisoedge\n" ,"frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.cancle -text \"Done\" -command \"destroy .refinement_dlg\"\n" ,"ttk::button $w.bu.refine -text \"Refine\" \\\n" ,"-command {\n" ,"set oldnp 0; set newnp $status_np;\n" ,"while { $oldnp < $newnp } {\n" ,"set level [expr $level+1]\n" ,"Ng_Bisect;\n" ,"Ng_HighOrder ${options.elementorder}\n" ,"Ng_ReadStatus;\n" ,"redraw;\n" ,"set oldnp $newnp\n" ,"set newnp $status_np\n" ,"puts \"oldnp $oldnp newnp $newnp\"\n" ,"}\n" ,"}\n" ,"ttk::button $w.bu.zrefine -text \"Z-Refine\" \\\n" ,"-command { Ng_ZRefinement; Ng_ReadStatus; redraw; }\n" ,"pack $w.bu.zrefine $w.bu.refine $w.bu.cancle -expand yes -side left\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Select Refinement\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc bcpropdialog { } {\n" ,"set w .bcprop_dlg\n" ,"if {[winfo exists .bcprop_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"} {\n" ,"toplevel $w\n" ,"ttk::frame $w.face -borderwidth 3\n" ,"pack $w.face -fill x\n" ,"ttk::label $w.face.lab -text \"face index:\"\n" ,"ttk::label $w.face.ent -text 1\n" ,"ttk::button $w.face.next -text \"next\" -command {\n" ,"set w .bcprop_dlg;\n" ,"set facenr [$w.face.ent cget -text]\n" ,"if {$facenr == [Ng_BCProp getnfd]} {\n" ,"set facenr 1\n" ,"} {\n" ,"set facenr [expr $facenr + 1]\n" ,"}\n" ,"$w.face.ent configure -text $facenr\n" ,"Ng_BCProp setactive $facenr\n" ,"set bcnr [Ng_BCProp getbc $facenr]\n" ,"$w.bc.ent delete 0 end\n" ,"$w.bc.ent insert 0 $bcnr\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.face.prev -text \"prev\" -command {\n" ,"set w .bcprop_dlg;\n" ,"set facenr [$w.face.ent cget -text]\n" ,"if {$facenr == 1} {\n" ,"set facenr [Ng_BCProp getnfd]\n" ,"} {\n" ,"set facenr [expr $facenr - 1]\n" ,"}\n" ,"$w.face.ent configure -text $facenr\n" ,"Ng_BCProp setactive $facenr\n" ,"set bcnr [Ng_BCProp getbc $facenr]\n" ,"$w.bc.ent delete 0 end\n" ,"$w.bc.ent insert 0 $bcnr\n" ,"redraw\n" ,"}\n" ,"pack $w.face.lab $w.face.ent $w.face.prev $w.face.next -side left\n" ,"ttk::frame $w.bc -borderwidth 3\n" ,"pack $w.bc -fill x\n" ,"ttk::label $w.bc.lab -text \"bc property:\"\n" ,"entry $w.bc.ent -width 5 -relief sunken\n" ,"ttk::button $w.bc.but -text \"change\" -command {\n" ,"set w .bcprop_dlg;\n" ,"Ng_BCProp setbc [$w.face.ent cget -text] [$w.bc.ent get];\n" ,"}\n" ,"ttk::button $w.bc.but2 -text \"all\" -command {\n" ,"set w .bcprop_dlg;\n" ,"Ng_BCProp setall [$w.bc.ent get];\n" ,"}\n" ,"pack $w.bc.lab $w.bc.ent $w.bc.but $w.bc.but2 -side left -expand yes\n" ,"ttk::frame $w.bcname -borderwidth 3\n" ,"pack $w.bcname -fill x\n" ,"ttk::label $w.bcname.lab -text \"bc name:\"\n" ,"ttk::label $w.bcname.ent -text \"-\"\n" ,"pack $w.bcname.lab $w.bcname.ent -side left -expand yes\n" ,"ttk::frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.close -text \"Close\" -command { destroy .bcprop_dlg }\n" ,"pack $w.bu.close -expand yes -side left\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Boundary Conditions\"\n" ,"}\n" ,"focus $w\n" ,"set facenr [Ng_BCProp getactive]\n" ,"$w.face.ent configure -text $facenr\n" ,"set bcnr [Ng_BCProp getbc $facenr]\n" ,"$w.bc.ent delete 0 end\n" ,"$w.bc.ent insert 0 $bcnr\n" ,"set bcname [Ng_BCProp getbcname $facenr]\n" ,"$w.bcname.ent configure -text $bcname\n" ,"}\n" ,"proc currmeshcoloursdialog { } {\n" ,"set w .currmeshcolours_dlg\n" ,"if {[winfo exists .currmeshcolours_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"global facecolslist\n" ,"frame $w.facecols -borderwidth 3\n" ,"listbox $w.facecols.list -yscroll \"$w.facecols.scroll set\" -selectmode single -setgrid 1 -width 32 -height 12\n" ,"scrollbar $w.facecols.scroll -command \"$w.facecols.list yview\"\n" ,"pack $w.facecols.scroll -side right -fill y\n" ,"pack $w.facecols.list -side left -expand yes -fill both\n" ,"Ng_CurrentFaceColours getcolours facecolslist\n" ,"set i 1\n" ,"foreach el $facecolslist {\n" ,"set hel [format \"%d: (%.4f %.4f %.4f)\" $i [ lindex $el 0 ] [ lindex $el 1 ] [ lindex $el 2 ]]\n" ,"incr i\n" ,"$w.facecols.list insert end $hel }\n" ,"frame $w.bu1 -borderwidth 3\n" ,"ttk::button $w.bu1.showonly -text \"show only\" -command {\n" ,"Ng_CurrentFaceColours showonly [.currmeshcolours_dlg.facecols.list curselection]\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.bu1.hideonly -text \"hide only\" -command {\n" ,"Ng_CurrentFaceColours hideonly [.currmeshcolours_dlg.facecols.list curselection]\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.bu1.showalso -text \"show\" -command {\n" ,"Ng_CurrentFaceColours showalso [.currmeshcolours_dlg.facecols.list curselection]\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.bu1.hidealso -text \"hide\" -command {\n" ,"Ng_CurrentFaceColours hidealso [.currmeshcolours_dlg.facecols.list curselection]\n" ,"redraw\n" ,"}\n" ,"pack $w.bu1.showonly $w.bu1.hideonly $w.bu1.showalso $w.bu1.hidealso -expand yes -fill x -padx 2 -pady 2 -side left\n" ,"frame $w.bu2\n" ,"ttk::button $w.bu2.showall -text \"show all\" -command {\n" ,"Ng_CurrentFaceColours showall\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.bu2.hideall -text \"hide all\" -command {\n" ,"Ng_CurrentFaceColours hideall\n" ,"redraw\n" ,"}\n" ,"pack $w.bu2.showall $w.bu2.hideall -expand yes -fill x -padx 2 -pady 2 -side left\n" ,"frame $w.bu3\n" ,"ttk::button $w.bu3.close -text \"close\" -command {\n" ,"destroy .currmeshcolours_dlg\n" ,"}\n" ,"pack $w.bu3.close -expand yes -fill x -pady 3 -side right\n" ,"pack $w.facecols -side top -expand yes -fill x -fill y\n" ,"pack $w.bu3 -side bottom\n" ,"pack $w.bu2 -side bottom\n" ,"pack $w.bu1 -expand yes -fill x -side left\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Inspect Mesh Colours\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc surfacemeshsizedialog { } {\n" ,"set w .surfacemeshsize_dlg\n" ,"if {[winfo exists .surfacemeshsize_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"} {\n" ,"toplevel $w\n" ,"frame $w.face -borderwidth 3\n" ,"pack $w.face -fill x -padx 5\n" ,"ttk::label $w.face.lab -text \"face index:\"\n" ,"ttk::label $w.face.ent -text 1\n" ,"ttk::button $w.face.next -text \"next\" -command {\n" ,"set w .surfacemeshsize_dlg;\n" ,"set facenr [$w.face.ent cget -text]\n" ,"if {$facenr == [Ng_SurfaceMeshSize getnfd]} {\n" ,"set facenr 1\n" ,"} {\n" ,"set facenr [expr $facenr + 1]\n" ,"}\n" ,"$w.face.ent configure -text $facenr\n" ,"Ng_SurfaceMeshSize setactive $facenr\n" ,"set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\n" ,"$w.sms.ent delete 0 end\n" ,"$w.sms.ent insert 0 $surfms\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.face.prev -text \"prev\" -command {\n" ,"set w .surfacemeshsize_dlg;\n" ,"set facenr [$w.face.ent cget -text]\n" ,"if {$facenr == 1} {\n" ,"set facenr [Ng_SurfaceMeshSize getnfd]\n" ,"} {\n" ,"set facenr [expr $facenr - 1]\n" ,"}\n" ,"$w.face.ent configure -text $facenr\n" ,"Ng_SurfaceMeshSize setactive $facenr\n" ,"set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\n" ,"$w.sms.ent delete 0 end\n" ,"$w.sms.ent insert 0 $surfms\n" ,"redraw\n" ,"}\n" ,"pack $w.face.lab $w.face.ent $w.face.prev $w.face.next -side left\n" ,"frame $w.sms -borderwidth 3\n" ,"pack $w.sms -fill x\n" ,"ttk::label $w.sms.lab -text \"max mesh size:\"\n" ,"entry $w.sms.ent -width 8 -relief sunken\n" ,"ttk::button $w.sms.but -text \"change\" -command {\n" ,"set w .surfacemeshsize_dlg;\n" ,"Ng_SurfaceMeshSize setsurfms [$w.face.ent cget -text] [$w.sms.ent get];\n" ,"}\n" ,"ttk::button $w.sms.but2 -text \"all\" -command {\n" ,"set w .surfacemeshsize_dlg;\n" ,"Ng_SurfaceMeshSize setall [$w.sms.ent get];\n" ,"}\n" ,"pack $w.sms.lab $w.sms.ent $w.sms.but $w.sms.but2 -side left -padx 5 -expand yes\n" ,"frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.close -text \"Close\" -command { destroy .surfacemeshsize_dlg }\n" ,"pack $w.bu.close -expand yes -side left\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Edit Surface Mesh Size\"\n" ,"}\n" ,"focus $w\n" ,"set facenr [Ng_SurfaceMeshSize getactive]\n" ,"$w.face.ent configure -text $facenr\n" ,"set surfms [Ng_SurfaceMeshSize getsurfms $facenr]\n" ,"$w.sms.ent delete 0 end\n" ,"$w.sms.ent insert 0 $surfms\n" ,"}\n" ,"proc METISdialog { } {\n" ,"set w .metis_dlg\n" ,"set w.parts 64\n" ,"if {[winfo exists .metis_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"} {\n" ,"toplevel $w\n" ,"frame $w.a -borderwidth 0\n" ,"frame $w.b -borderwidth 0\n" ,"pack $w.a $w.b\n" ,"ttk::label $w.a.lab -text \"Number of partitions:\"\n" ,"entry $w.a.ent -textvariable w.parts -width 4 -relief sunken\n" ,"ttk::button $w.b.start -text \"Start METIS\" -command {\n" ,"Ng_Metis ${w.parts}\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.b.cancel -text \"Cancel\" -command { destroy .metis_dlg }\n" ,"pack $w.a.lab $w.a.ent -side left -expand yes\n" ,"pack $w.b.start $w.b.cancel -side left\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"METIS Partitioning\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc stloptionsdialog { } {\n" ,"set w .stlopts_dlg\n" ,"if {[winfo exists .stlopts_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"pack [ttk::notebook $w.nb] -fill both -fill both -side top\n" ,"frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.apply -text \"Apply\" -command { redraw; Ng_GenerateMesh 1 2}\n" ,"ttk::button $w.bu.cancle -text \"Done\" -command { destroy .stlopts_dlg }\n" ,"pack $w.bu.cancle $w.bu.apply -side left -expand yes\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"STL Options\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc stldoctordialog { } {\n" ,"Ng_STLDoctor 0 0\n" ,"set wd .stldoctor_dlg\n" ,"if {[winfo exists .stldoctor_dlg] == 1} {\n" ,"wm withdraw $wd\n" ,"wm deiconify $wd\n" ,"focus $wd\n" ,"} {\n" ,"toplevel $wd\n" ,"pack [ttk::notebook $wd.nb] -fill both -fill both -side top\n" ,"$wd.nb add [ttk::frame $wd.nb.general] -text \"General\" -underline 0\n" ,"$wd.nb add [ttk::frame $wd.nb.topology] -text \"Edit Topology\" -underline 5\n" ,"$wd.nb add [ttk::frame $wd.nb.edges] -text \"Edit Edges\" -underline 5\n" ,"$wd.nb add [ttk::frame $wd.nb.normals] -text \"Edit Normals\" -underline 5\n" ,"$wd.nb add [ttk::frame $wd.nb.advanced] -text \"Advanced\" -underline 0\n" ,"set f $wd.nb.general\n" ,"ttk::frame $f.selectframe -borderwidth 0\n" ,"ttk::checkbutton $f.selectframe.showtrias -text \"Show STL-Triangles\" \\\n" ,"-variable stloptions.showtrias -command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $f.selectframe.showfilledtrias -text \"Show Filled Triangles\" \\\n" ,"-variable stloptions.showfilledtrias -command { Ng_SetVisParameters; redraw }\n" ,"set selmodevals { 0 1 2 3 4 }\n" ,"set selmodelabs(0) \"triangle\"\n" ,"set selmodelabs(1) \"edge\"\n" ,"set selmodelabs(2) \"point\"\n" ,"set selmodelabs(3) \"line\"\n" ,"set selmodelabs(4) \"line cluster\"\n" ,"global stldoctor.selectmode\n" ,"ttk::label $f.selectframe.dblcsellab -text \"Double Click selects : \"\n" ,"ttk::menubutton $f.selectframe.dblcselbut -menu $f.selectframe.dblcselmen -text \"triangle\" -width 16\n" ,"menu $f.selectframe.dblcselmen -tearoff 0\n" ,"foreach selmode { 0 1 2 3 4 } {\n" ,"$f.selectframe.dblcselmen add command -label $selmodelabs($selmode) \\\n" ,"-command \"set stldoctor.selectmode $selmode ; Ng_STLDoctor ; $f.selectframe.dblcselbut configure -text \\\"$selmodelabs($selmode)\\\"\"\n" ,"}\n" ,"$f.selectframe.dblcselmen invoke $selmodelabs(${stldoctor.selectmode})\n" ,"pack $f.selectframe\n" ,"grid $f.selectframe.showtrias -sticky nw\n" ,"grid $f.selectframe.showfilledtrias -sticky nw\n" ,"grid $f.selectframe.dblcsellab $f.selectframe.dblcselbut -sticky nw\n" ,"ttk::frame $f.sm\n" ,"pack $f.sm -fill x\n" ,"ttk::checkbutton $f.sm.bu -text \"select with mouse\" \\\n" ,"-variable stldoctor.selectwithmouse\n" ,"pack $f.sm.bu\n" ,"ttk::frame $f.st -relief groove -borderwidth 3\n" ,"pack $f.st -fill x\n" ,"ttk::label $f.st.lab -text \"Select triangle by number\";\n" ,"ttk::entry $f.st.ent -width 5 \\\n" ,"-textvariable stldoctor.selecttrig\n" ,"pack $f.st.ent $f.st.lab -side left -expand yes\n" ,"ttk::frame $f.vc -relief groove -borderwidth 3\n" ,"pack $f.vc -fill x\n" ,"ttk::checkbutton $f.vc.bu -text \"show vicinity\" \\\n" ,"-variable stldoctor.showvicinity \\\n" ,"-command {Ng_STLDoctor vicinity; redraw}\n" ,"ttk::label $f.vc.lab -text \"vicinity size\";\n" ,"ttk::frame $f.vc.sc\n" ,"ttk::scale $f.vc.sc.scale -orient horizontal -length 200 -from 0 -to 200 \\\n" ,"-variable stldoctor.vicinity -takefocus 0 -command \"Ng_STLDoctor vicinity; redraw; roundscale $f.vc.sc.scale 0\"\n" ,"ttk::entry $f.vc.sc.entry -textvariable stldoctor.vicinity -width 3 \\\n" ,"-validatecommand \"Ng_STLDoctor vicinity; redraw; my_validate %W [$f.vc.sc.scale cget -from] [$f.vc.sc.scale cget -to] %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_STLDoctor vicinity; redraw;\" -validate focus\n" ,"ttk::label $f.vc.sc.lab -text \"vicinity size\"\n" ,"grid $f.vc.sc.scale $f.vc.sc.entry $f.vc.sc.lab -sticky nw -padx 4\n" ,"pack $f.vc.bu $f.vc.lab $f.vc.sc -expand yes\n" ,"ttk::frame $f.ge -relief groove -borderwidth 0\n" ,"pack $f.ge -expand yes\n" ,"ttk::button $f.ge.neighbourangles -text \"calc neighbourangles\" -command {Ng_STLDoctor neighbourangles}\n" ,"ttk::button $f.ge.showcoords -text \"show coords of touched triangle\" -command {Ng_STLDoctor showcoords}\n" ,"ttk::button $f.ge.moveptm -text \"move point to middle of trianglepoints\" -command {Ng_STLDoctor movepointtomiddle; redraw}\n" ,"ttk::button $f.ge.destroy0trigs -text \"destroy 0-volume triangles\" -command {Ng_STLDoctor destroy0trigs}\n" ,"grid $f.ge.neighbourangles -sticky nw -padx 4 -pady 4\n" ,"grid $f.ge.showcoords -sticky nw -padx 4 -pady 4\n" ,"grid $f.ge.moveptm -sticky nw -padx 4 -pady 4\n" ,"grid $f.ge.destroy0trigs -sticky nw -padx 4 -pady 4\n" ,"ttk::button $f.ge.cancle -text \"Done\" -command {destroy .stldoctor_dlg }\n" ,"grid $f.ge.cancle -sticky nw\n" ,"set f $wd.nb.topology\n" ,"ttk::frame $f.oc -relief groove -borderwidth 3\n" ,"pack $f.oc -pady 3 -ipady 3 -fill y -fill x\n" ,"ttk::frame $f.oc.oc1 -borderwidth 0\n" ,"pack $f.oc.oc1\n" ,"ttk::button $f.oc.oc1.bu -text \"invert orientation \\n of selected trig\" -command {Ng_STLDoctor invertselectedtrig; redraw }\n" ,"ttk::button $f.oc.oc1.bu2 -text \"orient after \\n selected trig\" -command {Ng_STLDoctor orientafterselectedtrig; redraw }\n" ,"ttk::button $f.oc.oc1.toperr -text \"mark inconsistent triangles\" -command {Ng_STLDoctor marktoperrortrigs; redraw }\n" ,"ttk::button $f.oc.oc1.deltrig -text \"delete selected triangle\" -command {Ng_STLDoctor deleteselectedtrig; redraw }\n" ,"ttk::button $f.oc.oc1.geosmooth -text \"geometric smoothing\" -command {Ng_STLDoctor smoothgeometry; redraw }\n" ,"grid $f.oc.oc1.bu x $f.oc.oc1.bu2 -sticky nw -padx 4 -pady 4\n" ,"grid $f.oc.oc1.toperr - x -sticky nw -padx 4 -pady 4\n" ,"grid $f.oc.oc1.deltrig - x -sticky nw -padx 4 -pady 4\n" ,"grid $f.oc.oc1.geosmooth - x -sticky nw -padx 4 -pady 4\n" ,"set f $wd.nb.edges\n" ,"ttk::frame $f.be -relief groove -borderwidth 3\n" ,"pack $f.be -fill x\n" ,"ttk::frame $f.be.frame\n" ,"pack $f.be.frame -ipady 4 -pady 4\n" ,"ttk::label $f.be.frame.lab -text \"build edges with yellow angle:\";\n" ,"ttk::scale $f.be.frame.scale -orient horizontal -length 200 -from 0 -to 200 \\\n" ,"-variable stloptions.yangle -takefocus 0 -command \"roundscale $f.be.frame.scale 1; Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\"\n" ,"ttk::entry $f.be.frame.entry -textvariable stloptions.yangle -width 5 \\\n" ,"-validatecommand \"Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw;my_validate %W [$f.be.frame.scale cget -from] [$f.be.frame.scale cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\" -validate focus\n" ,"grid $f.be.frame.lab - -sticky nw -padx 4\n" ,"grid $f.be.frame.scale $f.be.frame.entry -sticky nw -padx 4\n" ,"ttk::label $f.be.frame.lab2 -text \"continue edges with yellow angle:\";\n" ,"ttk::scale $f.be.frame.scale2 -orient horizontal -length 200 -from 0 -to 100 \\\n" ,"-variable stloptions.contyangle -takefocus 0 -command \"roundscale $f.be.frame.scale2 1; Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\"\n" ,"ttk::entry $f.be.frame.entry2 -textvariable stloptions.contyangle -width 5 \\\n" ,"-validatecommand \"Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw;my_validate %W [$f.be.frame.scale2 cget -from] [$f.be.frame.scale2 cget -to] %P 1\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetSTLParameters; Ng_STLDoctor buildedges; redraw\" -validate focus\n" ,"grid $f.be.frame.lab2 - -sticky nw -padx 4\n" ,"grid $f.be.frame.scale2 $f.be.frame.entry2 -sticky nw -padx 4\n" ,"ttk::button $f.be.frame.buildedges -text \"Build Edges\" -command {Ng_STLDoctor buildedges; redraw}\n" ,"grid $f.be.frame.buildedges - -sticky n -padx 4 -pady 4\n" ,"ttk::frame $f.se -relief groove -borderwidth 3\n" ,"pack $f.se -fill x\n" ,"ttk::checkbutton $f.se.bu -text \"show excluded\" \\\n" ,"-variable stldoctor.showexcluded \\\n" ,"-command {Ng_STLDoctor; redraw}\n" ,"pack $f.se.bu\n" ,"set edgeselmodevals { 0 1 2 3 4 }\n" ,"set edgeselmodelabs(0) \"no change\"\n" ,"set edgeselmodelabs(1) \"undefined\"\n" ,"set edgeselmodelabs(2) \"confirmed\"\n" ,"set edgeselmodelabs(3) \"candidate\"\n" ,"set edgeselmodelabs(4) \"excluded\"\n" ,"global stldoctor.edgeselectmode\n" ,"ttk::frame $f.scaleframe -relief groove -borderwidth 0\n" ,"pack $f.scaleframe -ipadx 4 -pady 4 -expand yes\n" ,"ttk::label $f.scaleframe.dblcedgelab -text \"Double Click sets edge :\"\n" ,"ttk::menubutton $f.scaleframe.dblcledgebut -menu $f.scaleframe.dblcledgem -text \"coarse\" -width 16\n" ,"menu $f.scaleframe.dblcledgem -tearoff 0\n" ,"foreach selectmode { 0 1 2 3 4 } {\n" ,"$f.scaleframe.dblcledgem add command -label $edgeselmodelabs($selectmode) \\\n" ,"-command \"set stldoctor.edgeselectmode $selectmode ; $f.scaleframe.dblcledgebut configure -text \\\"$edgeselmodelabs($selectmode)\\\"\"\n" ,"}\n" ,"$f.scaleframe.dblcledgem invoke $edgeselmodelabs(${stldoctor.edgeselectmode})\n" ,"grid $f.scaleframe.dblcedgelab $f.scaleframe.dblcledgebut -sticky n -ipadx 4\n" ,"ttk::frame $f.edg -relief groove -borderwidth 3\n" ,"pack $f.edg -fill x -ipadx 4 -ipady 4\n" ,"ttk::frame $f.edg.f0\n" ,"pack $f.edg.f0\n" ,"ttk::button $f.edg.f0.confirmedge -text \"confirm\" -command {Ng_STLDoctor confirmedge; redraw}\n" ,"ttk::button $f.edg.f0.candidateedge -text \"candidate\" -command {Ng_STLDoctor candidateedge; redraw}\n" ,"ttk::button $f.edg.f0.excludeedge -text \"exclude\" -command {Ng_STLDoctor excludeedge; redraw}\n" ,"ttk::button $f.edg.f0.undefinededge -text \"undefined\" -command {Ng_STLDoctor undefinededge; redraw}\n" ,"pack $f.edg.f0.confirmedge $f.edg.f0.candidateedge $f.edg.f0.excludeedge $f.edg.f0.undefinededge -side left\n" ,"ttk::frame $f.edg.fa\n" ,"pack $f.edg.fa\n" ,"ttk::button $f.edg.fa.setallundefined -text \"all undefined\" -command {Ng_STLDoctor setallundefinededges; redraw}\n" ,"ttk::button $f.edg.fa.erasecandidates -text \"candidates to undefined\" -command {Ng_STLDoctor erasecandidateedges; redraw}\n" ,"pack $f.edg.fa.setallundefined $f.edg.fa.erasecandidates -side left\n" ,"ttk::frame $f.edg.fb\n" ,"pack $f.edg.fb\n" ,"ttk::button $f.edg.fb.confirmcandidates -text \"candidates to confirmed\" -command {Ng_STLDoctor confirmcandidateedges; redraw}\n" ,"ttk::button $f.edg.fb.confirmedtocandidates -text \"confirmed to candidates\" -command {Ng_STLDoctor confirmedtocandidateedges; redraw}\n" ,"pack $f.edg.fb.confirmcandidates $f.edg.fb.confirmedtocandidates -side left\n" ,"ttk::frame $f.edg.f1\n" ,"ttk::frame $f.edg.f2\n" ,"ttk::frame $f.edg.f3\n" ,"ttk::frame $f.edg.f4\n" ,"pack $f.edg.f1 $f.edg.f2 $f.edg.f3 $f.edg.f4\n" ,"ttk::button $f.edg.f1.exportedges -text \"export edges\" -command {Ng_STLDoctor exportedges}\n" ,"ttk::button $f.edg.f1.importedges -text \"import edges\" -command {Ng_STLDoctor importedges; redraw}\n" ,"ttk::button $f.edg.f1.saveedgedata -text \"save edgedata\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Netgen Edgedata\" {.ned} }\n" ,"}\n" ,"set file [tk_getSaveFile -filetypes $types -defaultextension \".ned\"]\n" ,"if {$file != \"\"} {\n" ,"Ng_STLDoctor saveedgedata $file\n" ,"}\n" ,"}\n" ,"ttk::button $f.edg.f1.loadedgedata -text \"load edgedata\" \\\n" ,"-command {\n" ,"set types {\n" ,"{\"Netgen Edgedata\" {.ned} }\n" ,"}\n" ,"set file [tk_getOpenFile -filetypes $types -defaultextension \".ned\"]\n" ,"if {$file != \"\"} {\n" ,"Ng_STLDoctor loadedgedata $file\n" ,"puts \"loading done\"\n" ,"redraw\n" ,"}\n" ,"}\n" ,"ttk::button $f.edg.f1.importAVLedges -text \"import AVL edges\" \\\n" ,"-command {\n" ,"set types {{\"Edge file\" {.edg }}}\n" ,"set file [tk_getOpenFile -filetypes $types -defaultextension \".edg\"]\n" ,"if {$file != \"\"} {\n" ,"Ng_STLDoctor importexternaledges $file;\n" ,"}\n" ,"}\n" ,"pack $f.edg.f1.importAVLedges $f.edg.f1.loadedgedata $f.edg.f1.saveedgedata -side left\n" ,"ttk::frame $f.edg2 -relief groove -borderwidth 3\n" ,"pack $f.edg2 -fill x\n" ,"ttk::label $f.edg2.lab -text \"length (%):\"\n" ,"scale $f.edg2.sc -orient horizontal -length 200 -from 0 -to 100 \\\n" ,"-resolution 0.5 \\\n" ,"-variable stldoctor.longlinefact\n" ,"ttk::button $f.edg2.undoedge -text \"undo last edge change\" -command {Ng_STLDoctor undoedgechange; redraw}\n" ,"pack $f.edg2.undoedge -expand yes\n" ,"set f $wd.nb.normals\n" ,"ttk::frame $f.dt -relief groove -borderwidth 3\n" ,"pack $f.dt -fill x\n" ,"ttk::label $f.dt.lab -text \"dirty triangle factor\";\n" ,"ttk::entry $f.dt.ent -width 5 \\\n" ,"-textvariable stldoctor.dirtytrigfact -validatecommand \"Ng_SetSTLParameters;my_validate %W -1e9 1e9 %P 3\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetSTLParameters\" -validate focus\n" ,"pack $f.dt.ent $f.dt.lab -side left -expand yes -pady 8\n" ,"ttk::frame $f.srt -relief groove -borderwidth 3\n" ,"pack $f.srt -fill x\n" ,"ttk::button $f.srt.bu -text \"smooth reverted triangles geometric\" -command {Ng_STLDoctor smoothrevertedtrigs; redraw }\n" ,"ttk::entry $f.srt.ent -width 5 \\\n" ,"-textvariable stldoctor.smoothangle -validatecommand \"Ng_SetSTLParameters;my_validate %W -1e9 1e9 %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetSTLParameters\" -validate focus\n" ,"pack $f.srt.ent $f.srt.bu -side left -expand yes -pady 8\n" ,"ttk::frame $f.bdt -relief groove -borderwidth 3\n" ,"pack $f.bdt -fill x\n" ,"ttk::button $f.bdt.bu -text \"mark dirty triangles\" -command {Ng_STLDoctor markdirtytrigs; redraw }\n" ,"ttk::button $f.bdt.bu2 -text \"smooth dirty triangles normal\" -command {Ng_STLDoctor smoothdirtytrigs; redraw }\n" ,"pack $f.bdt.bu $f.bdt.bu2 -side left -expand yes -pady 8\n" ,"ttk::frame $f.sno -relief groove -borderwidth 3\n" ,"pack $f.sno -fill x\n" ,"ttk::frame $f.sno.snoframe -borderwidth 0\n" ,"ttk::button $f.sno.smoothnormals -text \"smooth normals\" -command { Ng_STLDoctor smoothnormals; redraw}\n" ,"ttk::scale $f.sno.snoframe.scale -orient horizontal -length 100 -from 0.0 -to 0.8 \\\n" ,"-variable stldoctor.smoothnormalsweight -takefocus 0 -command \"roundscale $f.sno.snoframe.scale 2;Ng_SetSTLParameters\"\n" ,"ttk::entry $f.sno.snoframe.entry -textvariable stldoctor.smoothnormalsweight -width 4 \\\n" ,"-validatecommand \"Ng_SetSTLParameters;my_validate %W [$f.sno.snoframe.scale cget -from] [$f.sno.snoframe.scale cget -to] %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;Ng_SetSTLParameters\" -validate focus\n" ,"ttk::label $f.sno.snoframe.labrough -text \"rough\"\n" ,"ttk::label $f.sno.snoframe.labsmooth -text \"smooth\"\n" ,"grid $f.sno.snoframe.labrough $f.sno.snoframe.scale $f.sno.snoframe.labsmooth $f.sno.snoframe.entry -sticky nw -padx 4\n" ,"pack $f.sno.snoframe $f.sno.smoothnormals -side left -padx 5 -pady 8\n" ,"ttk::frame $f.no -relief groove -borderwidth 3\n" ,"pack $f.no -fill x\n" ,"ttk::button $f.no.marknonsmoothnormals -text \"mark non-smooth triangles\" -command {Ng_STLDoctor marknonsmoothnormals; redraw}\n" ,"ttk::button $f.no.calcnormals -text \"calculate normals from geometry\" -command {Ng_STLDoctor calcnormals; redraw}\n" ,"pack $f.no.marknonsmoothnormals $f.no.calcnormals -expand yes -pady 8\n" ,"set f $wd.nb.advanced\n" ,"ttk::frame $f.sc\n" ,"pack $f.sc -fill x\n" ,"ttk::checkbutton $f.sc.bu -text \"spiral check\" \\\n" ,"-variable stldoctor.spiralcheck \\\n" ,"-command {Ng_STLDoctor;}\n" ,"ttk::checkbutton $f.sc.bu2 -text \"cone check\" \\\n" ,"-variable stldoctor.conecheck \\\n" ,"-command {Ng_STLDoctor;}\n" ,"pack $f.sc.bu $f.sc.bu2\n" ,"ttk::spinbox $f.gtol -from 1 -to 20 -textvariable stldoctor.geom_tol_fact -width 8\n" ,"pack $f.gtol\n" ,"ttk::button $f.adap -text \"Apply\" -command {\n" ,".stldoctor_dlg.nb.advanced.gtol invoke\n" ,"Ng_STLDoctor;\n" ,"}\n" ,"pack $f.adap -expand yes\n" ,"wm withdraw $wd\n" ,"wm geom $wd +100+100\n" ,"wm deiconify $wd\n" ,"wm title $wd \"STL Doctor\"\n" ,"focus $wd\n" ,"}\n" ,"}\n" ,"proc meshdoctordialog { } {\n" ,"set w .meshdoc_dlg\n" ,"global meshdoctor.active\n" ,"if {[winfo exists .meshdoc_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"set meshdoctor.active 1\n" ,"Ng_MeshDoctor;\n" ,"ttk::frame $w.vis -relief groove -borderwidth 3\n" ,"pack $w.vis\n" ,"ttk::checkbutton $w.vis.showfilledtrigs -text \"Show filled triangles\" \\\n" ,"-variable viewoptions.drawfilledtrigs \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $w.vis.showedges -text \"Show edges\" \\\n" ,"-variable viewoptions.drawedges \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"ttk::checkbutton $w.vis.showoutline -text \"Show Triangle Outline\" \\\n" ,"-variable viewoptions.drawoutline \\\n" ,"-command { Ng_SetVisParameters; redraw }\n" ,"pack $w.vis.showfilledtrigs $w.vis.showoutline $w.vis.showedges\n" ,"ttk::frame $w.markedgedist\n" ,"ttk::label $w.markedgedist.l -text \"Mark edge dist: \"\n" ,"ttk::spinbox $w.markedgedist.s -from 0 -to 999 -width 5 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -command {Ng_MeshDoctor markedgedist ${meshdoc.markedgedist};redraw} -textvariable meshdoc.markedgedist\n" ,"pack $w.markedgedist.l $w.markedgedist.s -side left\n" ,"pack $w.markedgedist\n" ,"ttk::button $w.deledge -text \"Delete marked segments\" -command {\n" ,"Ng_MeshDoctor deletemarkedsegments\n" ,"redraw\n" ,"}\n" ,"pack $w.deledge\n" ,"ttk::button $w.close -text \"Close\" -command {\n" ,"set meshdoctor.active 0;\n" ,"Ng_MeshDoctor;\n" ,"destroy .meshdoc_dlg\n" ,"}\n" ,"pack $w.close -expand yes\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Mesh Doctor\"\n" ,"}\n" ,"}\n" ,"proc qualityviewdialog { show } {\n" ,"set w .qualityview_dlg\n" ,"if {[winfo exists .qualityview_dlg] == 1} {\n" ,"if { $show == 1 } {\n" ,"wm withdraw .qualityview_dlg\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"wm withdraw $w\n" ,"}\n" ,"} {\n" ,"toplevel $w\n" ,"set c $w.c\n" ,"canvas $c -relief raised -width 450 -height 300\n" ,"pack $w.c -side top -fill x\n" ,"set plotFont {Helvetica 12}\n" ,"set smallFont {Helvetica 12}\n" ,"$c create line 100 250 400 250 -width 2\n" ,"$c create line 100 250 100 50 -width 2\n" ,"for {set i 0} {$i <= 10} {incr i} {\n" ,"set x [expr {100 + ($i*30)}]\n" ,"$c create line $x 250 $x 245 -width 2\n" ,"if { [expr {$i % 2}] == 0 } {\n" ,"$c create text $x 254 -text [format %1.1f [expr 0.1*$i]] -anchor n -font $plotFont\n" ,"}\n" ,"}\n" ,"global qualbar\n" ,"global qualbarnull\n" ,"global qualbaraxis\n" ,"for {set i 0} {$i <= 5} {incr i} {\n" ,"set y [expr {250 - ($i*40)}]\n" ,"$c create line 100 $y 105 $y -width 2\n" ,"set qualbaraxis($i) \\\n" ,"[$c create text 96 $y -text [expr $i*50].0 -anchor e -font $plotFont]\n" ,"}\n" ,"for {set i 0} {$i < 20} {incr i} {\n" ,"set x1 [expr {100 + ($i*15) + 2}]\n" ,"set x2 [expr {$x1+10}]\n" ,"set y [expr {250 - 10 * $i}]\n" ,"set qualbar($i) [$c create rectangle $x1 250 $x2 245 -fill blue]\n" ,"set qualbarnull($i) [$c create text [expr {($x1+$x2)/2}] 245 -text 0 -anchor s -font $smallFont -fill blue]\n" ,"}\n" ,"frame $w.bu\n" ,"pack $w.bu\n" ,"ttk::button $w.close -text \"Close\" \\\n" ,"-command {\n" ,"wm withdraw .qualityview_dlg\n" ,"set viewqualityplot 0\n" ,"}\n" ,"pack $w.close\n" ,"if { $show == 1 } {\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Mesh Quality\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"}\n" ,"proc memusedialog { show } {\n" ,"set w .memuse_dlg\n" ,"if {[winfo exists .memuse_dlg] == 1} {\n" ,"if { $show == 1 } {\n" ,"wm withdraw .memuse_dlg\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"wm withdraw $w\n" ,"}\n" ,"} {\n" ,"toplevel $w\n" ,"set c $w.c\n" ,"canvas $c -relief raised -width 600 -height 300\n" ,"pack $w.c -side top -fill x\n" ,"set plotFont {Helvetica 18}\n" ,"set smallFont {Helvetica 12}\n" ,"global memmark\n" ,"for {set i 0} {$i < 512} { incr i } {\n" ,"set memmark($i) [$c create line [expr 50+$i] 50 [expr 50+$i] 70 -fill blue]\n" ,"}\n" ,"set plotFont {Helvetica 18}\n" ,"set smallFont {Helvetica 12}\n" ,"$c create text 50 90 -text \"0 GB\" -anchor n -font $plotFont\n" ,"$c create text 178 90 -text \"1 GB\" -anchor n -font $plotFont\n" ,"$c create text 306 90 -text \"2 GB\" -anchor n -font $plotFont\n" ,"$c create text 434 90 -text \"3 GB\" -anchor n -font $plotFont\n" ,"$c create text 562 90 -text \"4 GB\" -anchor n -font $plotFont\n" ,"ttk::frame $w.bu\n" ,"pack $w.bu\n" ,"ttk::button $w.close -text \"Close\" \\\n" ,"-command {\n" ,"wm withdraw .memuse_dlg\n" ,"set memuseplot 0\n" ,"}\n" ,"pack $w.close\n" ,"if { $show == 1 } {\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Memory Usage\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"}\n" ,"proc STLinfodialog { show } {\n" ,"set w .STLinfo_dlg\n" ,"if {[winfo exists .STLinfo_dlg] == 1} {\n" ,"if { $show == 1 } {\n" ,"wm withdraw .STLinfo_dlg\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"wm withdraw $w\n" ,"}\n" ,"} {\n" ,"toplevel $w\n" ,"set c $w.c\n" ,"canvas $c -relief raised -width 450 -height 300\n" ,"pack $w.c -side top -fill x\n" ,"set plotFont {Helvetica 18}\n" ,"set smallFont {Helvetica 12}\n" ,"$c create line 100 250 400 250 -width 2\n" ,"$c create line 100 250 100 50 -width 2\n" ,"ttk::frame $w.bu\n" ,"pack $w.bu\n" ,"ttk::button $w.close -text \"Close\" \\\n" ,"-command {\n" ,"wm withdraw .STLinfo_dlg\n" ,"}\n" ,"pack $w.close\n" ,"if { $show == 1 } {\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"STL Geometry Info\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"}\n" ,"proc logwindow { } {\n" ,"set w .logwindow\n" ,"if {[winfo exists .logwindow] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"text $w.edit -yscroll \"$w.scrolly set\" -setgrid 1 -height 12\n" ,"scrollbar $w.scrolly -command \"$w.edit yview\"\n" ,"pack $w.edit -side left -fill both -expand 1\n" ,"pack $w.scrolly -side left -fill both -expand 0\n" ,".logwindow.edit insert end \"Netgen Log Window\\n\"\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Netgen Log\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc printtable { tablevar } {\n" ,"set w newtcltable\n" ,"while {[winfo exists .$w] == 1} {set w 1$w}\n" ,"set w .$w\n" ,"toplevel $w\n" ,"for {set i 0} {$i < [lindex $tablevar 2]} { incr i } {\n" ,"frame $w.col$i\n" ,"for {set j 0} {$j < [lindex $tablevar 1]} { incr j } {\n" ,"frame $w.col$i.row$j\n" ,"message $w.col$i.row$j.txt -aspect 10000000 -text [lindex $tablevar [expr 3+[lindex $tablevar 2]*$j+$i]]\n" ,"pack $w.col$i.row$j.txt\n" ,"pack $w.col$i.row$j -side top\n" ,"}\n" ,"pack $w.col$i -side left\n" ,"}\n" ,"wm withdraw $w\n" ,"wm geom $w +200+100; wm deiconify $w\n" ,"wm title $w [lindex $tablevar 0]\n" ,"focus $w\n" ,"}\n" ,"set latestwarning 0\n" ,"proc printwarning { textvar } {\n" ,"global latestwarning\n" ,"set latestwarning $textvar\n" ,"set w warning\n" ,"while {[winfo exists .$w] == 1} {set w 1$w}\n" ,"set w .$w\n" ,"toplevel $w\n" ,"message $w.mes -aspect 2000 -text \"WARNING:\\n$textvar\"\n" ,"ttk::button $w.done -text \"Done\" -command \"destroy $w\"\n" ,"pack $w.mes\n" ,"pack $w.done\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"wm title $w \"Warning\"\n" ,"focus $w\n" ,"}\n" ,"proc printlatestwarning { } {\n" ,"global latestwarning\n" ,"if {$latestwarning != 0} {printwarning $latestwarning}\n" ,"}\n" ,"}\n" ,"catch {\n" ,"set oldmousex 0\n" ,"set oldmousey 0\n" ,"set toglversion [Ng_GetToglVersion]\n" ,"puts \"togl-version : $toglversion\"\n" ,"set toglok 0\n" ,"if { [Ng_GetToglVersion] == 2 } {\n" ,"if {[catch {togl .ndraw -width 400 -height 300 -rgba true -double true -depth true -privatecmap false -stereo false -indirect false -create init -display draw -reshape reshape }] } {\n" ,"puts \"no OpenGL\"\n" ,"} {\n" ,"set toglok 1\n" ,"}\n" ,"} {\n" ,"if {[catch {togl .ndraw -width 400 -height 300 -rgba true -double true -depth true -privatecmap false -stereo false -indirect false }] } {\n" ,"puts \"no OpenGL\"\n" ,"} {\n" ,"set toglok 1\n" ,"}\n" ,"}\n" ,"if { $toglok == 1} {\n" ,"pack .ndraw -expand true -fill both -padx 10 -pady 10\n" ,"catch { tkdnd::drop_target register .ndraw DND_Files }\n" ,"bind .ndraw {\n" ,"set oldmousex %x; set oldmousey %y;\n" ,"}\n" ,"bind .ndraw {\n" ,"set oldmousex %x; set oldmousey %y;\n" ,"}\n" ,"bind .ndraw {\n" ,"set oldmousex %x; set oldmousey %y;\n" ,"}\n" ,"bind .ndraw {\n" ,"Ng_MouseMove $oldmousex $oldmousey %x %y $drawmode\n" ,".ndraw render\n" ,"set oldmousex %x; set oldmousey %y;\n" ,"}\n" ,"bind .ndraw {\n" ,"Ng_MouseDblClick %x %y\n" ,".ndraw render\n" ,"if { [winfo exists .bcprop_dlg] } { bcpropdialog }\n" ,"if { [winfo exists .surfacemeshsize_dlg] } { surfacemeshsizedialog }\n" ,"if { [winfo exists .fieldlines_dlg] } { fieldlinesdialog }\n" ,"}\n" ,"bind .ndraw {\n" ,"Ng_MouseMove $oldmousex $oldmousey %x %y move\n" ,".ndraw render\n" ,"set oldmousex %x; set oldmousey %y;\n" ,"}\n" ,"bind .ndraw {\n" ,"if { $tcl_platform(os) == \"Darwin\" } {\n" ,"Ng_MouseMove $oldmousex $oldmousey %x %y move\n" ,"} {\n" ,"Ng_MouseMove $oldmousex $oldmousey %x %y zoom\n" ,"}\n" ,".ndraw render\n" ,"set oldmousex %x; set oldmousey %y;\n" ,"}\n" ,"}\n" ,"proc popupcheckredraw { vari { x 0 } } {\n" ,"upvar $vari varname\n" ,"if { $varname == 1 } {\n" ,"set varname 0\n" ,"} {\n" ,"Ng_Vis_Set parameters\n" ,"redraw\n" ,"}\n" ,"}\n" ,"proc popupcheckredraw2 { vari boolvar { x 0 } } {\n" ,"upvar $vari varname\n" ,"if { $varname == 1 } {\n" ,"set varname 0\n" ,"} {\n" ,"Ng_SetVisParameters\n" ,"Ng_Vis_Set parameters\n" ,"if { $boolvar == 1 } { redraw }\n" ,"Ng_SetVisParameters\n" ,"}\n" ,"}\n" ,"proc popupcheckredraw3 { vari { x 0 } } {\n" ,"upvar $vari varname\n" ,"if { $varname == 1 } {\n" ,"set varname 0\n" ,"} {\n" ,"Ng_Vis_Set parameters\n" ,"}\n" ,"}\n" ,"proc redraw { {x 0} } {\n" ,"if {[winfo exists .ndraw]} { .ndraw render }\n" ,"}\n" ,"bind . { Ng_MouseMove 0 0 -10 0 rotate; redraw }\n" ,"bind . { Ng_MouseMove 0 0 10 0 rotate; redraw }\n" ,"bind . { Ng_MouseMove 0 0 0 -10 rotate; redraw }\n" ,"bind . { Ng_MouseMove 0 0 0 10 rotate; redraw }\n" ,"bind . { Ng_MouseMove 0 0 -10 0 move; redraw }\n" ,"bind . { Ng_MouseMove 0 0 10 0 move; redraw }\n" ,"bind . { Ng_MouseMove 0 0 0 -10 move; redraw }\n" ,"bind . { Ng_MouseMove 0 0 0 10 move; redraw }\n" ,"bind . { Ng_MouseMove 0 0 0 -10 zoom; redraw }\n" ,"bind . { Ng_MouseMove 0 0 0 10 zoom; redraw }\n" ,"bind . \\\n" ,"{event generate [focus -displayof %W] -delta 120}\n" ,"bind . \\\n" ,"{event generate [focus -displayof %W] -delta -120}\n" ,"bind . { Ng_MouseMove 0 0 0 [expr {%D/-5}] zoom; redraw }\n" ,"bind .ndraw <> {\n" ,"set filename [join %D \" \"]\n" ,"set index [string last . $filename]\n" ,"set type [string range $filename $index+1 end]\n" ,"set ispde [string match -nocase $type \"pde\"]\n" ,"set isgeo [expr max([string match -nocase $type \"geo\"],[string match -nocase $type \"in2d\"])]\n" ,"set ismesh [expr max([string match -nocase $type \"vol\"],[string match -nocase $type \"vol.gz\"])]\n" ,"set ispy [string match -nocase $type \"py\"]\n" ,"if {$ispde == 1} {\n" ,"AddRecentNGSFile $filename;\n" ,"NGS_LoadPDE $filename;\n" ,"SetNumProcHelpMenu\n" ,"set selectvisual mesh;\n" ,"Ng_SetVisParameters\n" ,"}\n" ,"if {$ispy == 1} {\n" ,"AddRecentPYNGSFile $filename;\n" ,"NGS_LoadPy $filename;\n" ,"}\n" ,"if {$isgeo == 1} {\n" ,"AddRecentFile $filename;\n" ,"Ng_LoadGeometry $filename;\n" ,"Ng_ParseGeometry\n" ,"set selectvisual geometry\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"wm title . [concat \"$progname - \" $filename]\n" ,"set dirname [file dirname $filename]\n" ,"set basefilename [file tail [file rootname $filename]]\n" ,"}\n" ,"if {$ismesh == 1} {\n" ,"AddRecentMeshFile $filename;\n" ,"Ng_LoadMesh $filename;\n" ,"set selectvisual mesh\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"Ng_ReadStatus;\n" ,"wm title . [concat \"$progname - \" %D]\n" ,"set dirname [file dirname %D]\n" ,"set basefilename [file tail [file rootname %D]]\n" ,"}\n" ,"return %A\n" ,"}\n" ,"}\n" ,"catch { .ngmenu.geometry add command -label \"Scan CSG Geometry\" -command { Ng_ParseGeometry }\n" ,".ngmenu.geometry add command -label \"CSG Options...\" -command geometryoptionsdialog\n" ,".ngmenu.geometry add command -label \"CSG Properties...\" \\\n" ,"-command topleveldialog2\n" ,"proc geometryoptionsdialog { } {\n" ,"set w .geometry_dlg\n" ,"if {[winfo exists .geometry_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"global geooptions\n" ,"Ng_GeometryOptions get\n" ,"checkbutton $w.drawcsg -text \"Draw Geometry\" \\\n" ,"-variable geooptions.drawcsg\n" ,"pack $w.drawcsg\n" ,"frame $w.fac\n" ,"pack $w.fac -pady 5\n" ,"ttk::label $w.fac.lab -text \"Facets:\";\n" ,"entry $w.fac.ent -width 8 -relief sunken \\\n" ,"-textvariable geooptions.facets\n" ,"pack $w.fac.lab $w.fac.ent -side left\n" ,"frame $w.det\n" ,"pack $w.det -pady 5\n" ,"ttk::label $w.det.lab -text \"Detail:\";\n" ,"entry $w.det.ent -width 8 -relief sunken \\\n" ,"-textvariable geooptions.detail\n" ,"pack $w.det.lab $w.det.ent -side left\n" ,"frame $w.cox\n" ,"pack $w.cox -pady 5\n" ,"ttk::label $w.cox.lab -text \"min/max x:\";\n" ,"entry $w.cox.ent1 -width 8 -relief sunken \\\n" ,"-textvariable geooptions.minx\n" ,"entry $w.cox.ent2 -width 8 -relief sunken \\\n" ,"-textvariable geooptions.maxx\n" ,"pack $w.cox.lab $w.cox.ent1 \\\n" ,"$w.cox.ent2 -side left\n" ,"frame $w.coy\n" ,"pack $w.coy -pady 5\n" ,"ttk::label $w.coy.lab -text \"min/max y:\";\n" ,"entry $w.coy.ent1 -width 8 -relief sunken \\\n" ,"-textvariable geooptions.miny\n" ,"entry $w.coy.ent2 -width 8 -relief sunken \\\n" ,"-textvariable geooptions.maxy\n" ,"pack $w.coy.lab $w.coy.ent1 \\\n" ,"$w.coy.ent2 -side left\n" ,"frame $w.coz\n" ,"pack $w.coz -pady 5\n" ,"ttk::label $w.coz.lab -text \"min/max z:\";\n" ,"entry $w.coz.ent1 -width 8 -relief sunken \\\n" ,"-textvariable geooptions.minz\n" ,"entry $w.coz.ent2 -width 8 -relief sunken \\\n" ,"-textvariable geooptions.maxz\n" ,"pack $w.coz.lab $w.coz.ent1 \\\n" ,"$w.coz.ent2 -side left\n" ,"frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.app -text \"Apply\" -command {\n" ,"Ng_GeometryOptions set\n" ,"}\n" ,"ttk::button $w.bu.ok -text \"Done\" -command {\n" ,"Ng_GeometryOptions set\n" ,"destroy .geometry_dlg\n" ,"}\n" ,"pack $w.bu.app $w.bu.ok -side left -expand yes\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Geometry options\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc editprimitivedialog2 { name } {\n" ,"global w classname\n" ,"set w .ep_dlg\n" ,"toplevel .$w\n" ,"Ng_GetPrimitiveData $name classname valuelist\n" ,"ttk::label $w.lab1 -text \"Primitive Name: $name\";\n" ,"ttk::label $w.lab2 -text \"Primitive Class: $classname\";\n" ,"pack $w.lab1 $w.lab2 -fill x -pady 1m -padx 5m\n" ,"frame $w.specific -relief groove\n" ,"global spec\n" ,"set spec(sphere) { cx cy cz rad }\n" ,"set spec(cylinder) { ax ay az bx by bz rad }\n" ,"set spec(plane) { px py pz nx ny nz }\n" ,"set spec(cone) { ax ay az bx by bz ra rb }\n" ,"set spec(brick) { p1x p1y p1z p2x p2y p2z p3x p3y p3z p4x p4y p4z }\n" ,"set cnt 0\n" ,"foreach field $spec($classname) {\n" ,"frame $w.specific.f$cnt\n" ,"pack $w.specific.f$cnt -side top -anchor ne\n" ,"ttk::label $w.specific.f$cnt.lab -text \"$field\"\n" ,"entry $w.specific.f$cnt.ent -textvariable dataval($cnt) \\\n" ,"-width 6 -relief sunken\n" ,"pack $w.specific.f$cnt.ent $w.specific.f$cnt.lab -side right\n" ,"$w.specific.f$cnt.ent delete 0 end\n" ,"$w.specific.f$cnt.ent insert 0 [lindex $valuelist $cnt]\n" ,"set cnt [expr $cnt + 1]\n" ,"}\n" ,"pack $w.specific\n" ,"ttk::button $w.cancel -text \"cancel\" -command {\n" ,"destroy $w\n" ,"}\n" ,"ttk::button $w.ok -text \"ok\" -command {\n" ,"set valuelist \"\"\n" ,"set cnt 0\n" ,"foreach field $spec($classname) {\n" ,"lappend valuelist $dataval($cnt)\n" ,"set cnt [expr $cnt + 1]\n" ,"}\n" ,"Ng_SetPrimitiveData $name $valuelist\n" ,"destroy $w\n" ,"}\n" ,"pack $w.cancel $w.ok -side left -expand yes\n" ,"bind $w { $w.ok invoke}\n" ,"bind $w { $w.cancel invoke}\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"focus $w.specific.f0.ent\n" ,"}\n" ,"proc editprimitivedialog { } {\n" ,"global w\n" ,"set w .ep_dlg\n" ,"toplevel $w\n" ,"frame $w.frame -borderwidth 5m\n" ,"pack $w.frame -side top -expand yes -fill y\n" ,"listbox $w.frame.list -yscroll \"$w.frame.scroll set\" -setgrid 1 -height 12\n" ,"scrollbar $w.frame.scroll -command \"$w.frame.list yview\"\n" ,"pack $w.frame.scroll -side right -fill y\n" ,"pack $w.frame.list -side left -expand 1 -fill both\n" ,"Ng_GetPrimitiveList primlist\n" ,"foreach el $primlist {\n" ,"$w.frame.list insert end $el }\n" ,"ttk::button $w.cancel -text \"cancel\" -command { destroy $w }\n" ,"ttk::button $w.ok -text \"ok\" -command {\n" ,"set name [.ep_dlg.frame.list get active]\n" ,"puts \"name=($name)\"\n" ,"destroy $w\n" ,"if { $name != \"\" } { editprimitivedialog2 $name }\n" ,"}\n" ,"bind $w { $w.cancel invoke }\n" ,"bind $w { $w.ok invoke }\n" ,"pack $w.cancel $w.ok -side left -expand yes\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"focus $w.frame.list\n" ,"}\n" ,"proc newprimitivedialog { } {\n" ,"global w name\n" ,"set w .ap_dlg\n" ,"toplevel $w\n" ,"set name \"\"\n" ,"frame $w.f1\n" ,"pack $w.f1 -pady 2m\n" ,"ttk::label $w.f1.lab -text \"Primitive Name: \";\n" ,"entry $w.f1.ent -width 5 -relief sunken \\\n" ,"-textvariable name\n" ,"pack $w.f1.lab $w.f1.ent -side left\n" ,"frame $w.frame -borderwidth .5c\n" ,"pack $w.frame -side top -expand yes -fill y\n" ,"listbox $w.frame.list -yscroll \"$w.frame.scroll set\" -setgrid 1 -height 8\n" ,"scrollbar $w.frame.scroll -command \"$w.frame.list yview\"\n" ,"pack $w.frame.scroll -side right -fill y\n" ,"pack $w.frame.list -side left -expand 1 -fill both\n" ,"$w.frame.list insert 0 sphere cylinder plane cone brick\n" ,"$w.frame.list activate 0\n" ,"ttk::button $w.ok -text \"ok\" -command {\n" ,"Ng_CreatePrimitive [$w.frame.list get active] $name\n" ,"destroy $w\n" ,"editprimitivedialog2 $name\n" ,"}\n" ,"ttk::button $w.cancel -text \"cancel\" -command {\n" ,"destroy $w\n" ,"}\n" ,"pack $w.cancel $w.ok -side left -expand yes -pady 2m\n" ,"bind $w { $w.cancel invoke }\n" ,"bind $w { $w.ok invoke }\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"focus $w.f1.ent\n" ,"}\n" ,"proc newsoliddialog { } {\n" ,"global w name val sollist\n" ,"set w .ns_dlg\n" ,"toplevel $w\n" ,"set name \"\"\n" ,"frame $w.f1\n" ,"ttk::label $w.f1.lab -text \"Solid Name: \";\n" ,"entry $w.f1.ent -width 5 -relief sunken \\\n" ,"-textvariable name\n" ,"$w.f1.ent delete 0 end\n" ,"ttk::button $w.f1.getsel -text \"Get Selected\" -command {\n" ,"$w.f1.ent delete 0 end\n" ,"$w.f1.ent insert 0 [$w.f3.list get active]\n" ,"$w.bu.get invoke\n" ,"}\n" ,"pack $w.f1.getsel -side bottom\n" ,"pack $w.f1.ent $w.f1.lab -side right\n" ,"frame $w.f3 -borderwidth .5c\n" ,"listbox $w.f3.list -yscroll \"$w.f3.scroll set\" -setgrid 1 -height 12\n" ,"scrollbar $w.f3.scroll -command \"$w.f3.list yview\"\n" ,"pack $w.f3.scroll -side right -fill y\n" ,"pack $w.f3.list -side left -expand 1 -fill both\n" ,"Ng_GetSolidList sollist\n" ,"foreach el $sollist {\n" ,"$w.f3.list insert end $el }\n" ,"frame $w.f2\n" ,"ttk::label $w.f2.lab -text \"Solid Description: \";\n" ,"pack $w.f2.lab\n" ,"entry $w.f2.ent -width 100 -relief sunken \\\n" ,"-textvariable val -xscrollcommand \"$w.f2.scr set\"\n" ,"scrollbar $w.f2.scr -relief sunken -orient horiz -command \\\n" ,"\"$w.f2.ent xview\"\n" ,"$w.f2.ent delete 0 end\n" ,"pack $w.f2.ent $w.f2.scr -fill x\n" ,"frame $w.bu\n" ,"ttk::button $w.bu.close -text \"close\" -command {\n" ,"destroy $w\n" ,"}\n" ,"ttk::button $w.bu.get -text \"get data\" -command {\n" ,"Ng_GetSolidData $name val\n" ,"}\n" ,"ttk::button $w.bu.set -text \"set data\" -command {\n" ,"Ng_SetSolidData $name $val\n" ,"}\n" ,"pack $w.bu.get $w.bu.set $w.bu.close -side left\n" ,"pack $w.bu -pady 5 -side bottom ;\n" ,"pack $w.f2 -pady 5 -side bottom ;\n" ,"pack $w.f1 -pady 5 -side left ;\n" ,"pack $w.f3 -side left -expand yes -fill y ;\n" ,"bind $w { $w.bu.close invoke }\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"}\n" ,"proc toplevelproperties { w solname surfname } {\n" ,"global properties\n" ,"Ng_TopLevel getprop $solname $surfname properties\n" ,"set w .tlprop_dlg\n" ,"if {[winfo exists $w] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"ttk::label $w.lab1 -text \"Red\"\n" ,"scale $w.scale1 -orient horizontal -length 300 -from 0 -to 1 \\\n" ,"-resolution 0.01 -tickinterval 0.2 \\\n" ,"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable properties(red)\n" ,"ttk::label $w.lab2 -text \"Green\"\n" ,"scale $w.scale2 -orient horizontal -length 300 -from 0 -to 1 \\\n" ,"-resolution 0.01 -tickinterval 0.2 \\\n" ,"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable properties(green)\n" ,"ttk::label $w.lab3 -text \"Blue\"\n" ,"scale $w.scale3 -orient horizontal -length 300 -from 0 -to 1 \\\n" ,"-resolution 0.01 -tickinterval 0.2 \\\n" ,"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } -variable properties(blue)\n" ,"pack $w.lab1 $w.scale1 $w.lab2 $w.scale2 $w.lab3 $w.scale3\n" ,"checkbutton $w.cb4 -text \"Visible\" \\\n" ,"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } \\\n" ,"-variable properties(visible)\n" ,"checkbutton $w.cb5 -text \"Transparent\" \\\n" ,"-command { Ng_TopLevel setprop $solname $surfname properties; redraw } \\\n" ,"-variable properties(transp)\n" ,"pack $w.cb4 $w.cb5\n" ,"frame $w.bu\n" ,"pack $w.bu -fill x\n" ,"ttk::button $w.bu.ok -text \"Ok\" -command \"destroy .tlprop_dlg\"\n" ,"pack $w.bu.ok -expand yes\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"}\n" ,"wm title $w \"Properties $solname $surfname\"\n" ,"}\n" ,"proc topleveldialog { } {\n" ,"global w name val sollist\n" ,"set w .tl_dlg\n" ,"toplevel $w\n" ,"frame $w.sol -borderwidth .5c\n" ,"listbox $w.sol.list -yscroll \"$w.sol.scroll set\" -setgrid 1 -height 12\n" ,"scrollbar $w.sol.scroll -command \"$w.sol.list yview\"\n" ,"pack $w.sol.scroll -side right -fill y\n" ,"pack $w.sol.list -side left -expand 1 -fill both\n" ,"Ng_GetSolidList sollist\n" ,"foreach el $sollist {\n" ,"$w.sol.list insert end $el }\n" ,"Ng_GetPrimitiveList sollist\n" ,"foreach el $sollist {\n" ,"$w.sol.list insert end $el }\n" ,"frame $w.sul -borderwidth .5c\n" ,"listbox $w.sul.list -yscroll \"$w.sul.scroll set\" -setgrid 1 -height 12\n" ,"scrollbar $w.sul.scroll -command \"$w.sul.list yview\"\n" ,"pack $w.sul.scroll -side right -fill y\n" ,"pack $w.sul.list -side left -expand 1 -fill both\n" ,"Ng_GetSurfaceList sollist\n" ,"foreach el $sollist {\n" ,"$w.sul.list insert end $el }\n" ,"frame $w.topl -borderwidth .5c\n" ,"listbox $w.topl.list -yscroll \"$w.topl.scroll set\" -setgrid 1 -height 12 \\\n" ,"-command { puts hi }\n" ,"scrollbar $w.topl.scroll -command \"$w.topl.list yview\"\n" ,"pack $w.topl.scroll -side right -fill y\n" ,"pack $w.topl.list -side left -expand 1 -fill both\n" ,"Ng_TopLevel getlist sollist\n" ,"puts $sollist\n" ,"foreach el $sollist {\n" ,"set hel \"[ lindex $el 0 ]\"\n" ,"if { [ llength $el ] == 2 } {\n" ,"set hel \"[ lindex $el 1 ] on [ lindex $el 0 ]\"\n" ,"}\n" ,"$w.topl.list insert end $hel\n" ,"}\n" ,"frame $w.bu\n" ,"ttk::button $w.bu.close -text \"close\" -command {\n" ,"destroy $w\n" ,"}\n" ,"ttk::button $w.bu.addsol -text \"Add Solid\" -command {\n" ,"set solname [$w.sol.list get active]\n" ,"Ng_TopLevel set $solname \"\"\n" ,"Ng_ParseGeometry\n" ,"$w.topl.list insert end $solname\n" ,"}\n" ,"ttk::button $w.bu.addsurf -text \"Add Surface\" -command {\n" ,"set solname [$w.sol.list get active]\n" ,"set surfname [$w.sul.list get active]\n" ,"Ng_TopLevel set $solname $surfname\n" ,"Ng_ParseGeometry\n" ,"puts \"$solname on $surfname\"\n" ,"$w.topl.list insert end \"$surfname on $solname\"\n" ,"}\n" ,"ttk::button $w.bu.remsol -text \"Remove\" -command {\n" ,"set solname [$w.topl.list get active]\n" ,"set surfname \"\"\n" ,"if { [llength $solname] == 3 } {\n" ,"set surfname [lindex $solname 0]\n" ,"set solname [lindex $solname 2]\n" ,"}\n" ,"Ng_TopLevel remove $solname $surfname\n" ,"Ng_ParseGeometry\n" ,"$w.topl.list delete active\n" ,"}\n" ,"ttk::button $w.bu.prop -text \"Properties\" -command {\n" ,"set solname [$w.topl.list get active]\n" ,"set surfname \"\"\n" ,"if { [llength $solname] == 3 } {\n" ,"set surfname [lindex $solname 0]\n" ,"set solname [lindex $solname 2]\n" ,"}\n" ,"toplevelproperties tlp $solname $surfname\n" ,"}\n" ,"pack $w.bu.close $w.bu.addsol $w.bu.addsurf $w.bu.remsol $w.bu.prop -side left\n" ,"pack $w.bu -side bottom\n" ,"pack $w.sol -side left -expand yes -fill y ;\n" ,"pack $w.sul -side left -expand yes -fill y ;\n" ,"pack $w.topl -side left -expand yes -fill y ;\n" ,"bind $w { $w.bu.close invoke }\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"}\n" ,"proc topleveldialog2 { } {\n" ,"set w .tl2_dlg\n" ,"if {[winfo exists .tl2_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"global name val sollist\n" ,"frame $w.topl -borderwidth .5c\n" ,"listbox $w.topl.list -yscroll \"$w.topl.scroll set\" -setgrid 1 -height 12\n" ,"scrollbar $w.topl.scroll -command \"$w.topl.list yview\"\n" ,"pack $w.topl.scroll -side right -fill y\n" ,"pack $w.topl.list -side left -expand 1 -fill both\n" ,"Ng_TopLevel getlist sollist\n" ,"puts $sollist\n" ,"set i 1\n" ,"foreach el $sollist {\n" ,"set hel \"$i: [ lindex $el 0 ]\"\n" ,"if { [ llength $el ] == 2 } {\n" ,"set hel \"$i: [ lindex $el 1 ] on [ lindex $el 0 ]\"\n" ,"}\n" ,"incr i\n" ,"$w.topl.list insert end $hel }\n" ,"frame $w.bu\n" ,"ttk::button $w.bu.close -text \"close\" -command {\n" ,"destroy .tl2_dlg\n" ,"}\n" ,"ttk::button $w.bu.prop -text \"Properties\" -command {\n" ,"set solname [.tl2_dlg.topl.list get active]\n" ,"set surfname \"\"\n" ,"if { [llength $solname] == 2 } {\n" ,"set solname [lindex $solname 1]\n" ,"}\n" ,"if { [llength $solname] == 4 } {\n" ,"set surfname [lindex $solname 1]\n" ,"set solname [lindex $solname 3]\n" ,"}\n" ,"toplevelproperties tlp $solname $surfname\n" ,"}\n" ,"pack $w.bu.close $w.bu.prop -side left\n" ,"pack $w.bu -side bottom\n" ,"pack $w.topl -side left -expand yes -fill y ;\n" ,"bind .tl2_dlg.topl.list {\n" ,"set solname [.tl2_dlg.topl.list get @%x,%y]\n" ,"set surfname \"\"\n" ,"if { [llength $solname] == 2 } {\n" ,"set solname [lindex $solname 1]\n" ,"}\n" ,"if { [llength $solname] == 4 } {\n" ,"set surfname [lindex $solname 1]\n" ,"set solname [lindex $solname 3]\n" ,"}\n" ,"toplevelproperties tlp $solname $surfname\n" ,"}\n" ,"bind .tl2_dlg { .tl2_dlg.bu.close invoke }\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Top-Level Options\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"}\n" ,"catch { \n" ,".ngmenu.geometry add separator\n" ,".ngmenu.geometry add command -label \"STL Doctor...\" \\\n" ,"-command { stldoctordialog; }\n" ,".ngmenu.geometry add command -label \"STL Info\" \\\n" ,"-command {\n" ,"set notriangles 0\n" ,"set minx 0\n" ,"set maxx 0\n" ,"set miny 0\n" ,"set maxy 0\n" ,"set minz 0\n" ,"set maxz 0\n" ,"set trigscons 0\n" ,"Ng_STLInfo notriangles minx maxx miny maxy minz maxz trigscons\n" ,"set msgtext \"NO STL-Triangles : $notriangles\\nGeometry:\\nX = $minx - $maxx\\nY = $miny - $maxy\\nZ = $minz - $maxz\\nConsistency Check = $trigscons\\n\"\n" ,"set msgtext \"$msgtext Status: [Ng_STLInfo status]\"\n" ,"tk_messageBox -title \"STL Info\" -message $msgtext -type ok\n" ,"}\n" ,"}\n" ,"set hasocc no\n" ,"catch { if { [catch { load liboccvis[info sharedlibextension] Ng_OCC } result ] } {\n" ,"}\n" ,"if { [catch { Ng_OCCCommand isoccgeometryloaded }] } {\n" ,"proc rebuildoccdialog { } { }\n" ,"} {\n" ,"puts \"OCC module loaded\"\n" ,"set hasocc yes\n" ,".ngmenu.geometry add separator\n" ,".ngmenu.geometry add command -label \"IGES/STEP Topology Explorer/Doctor...\" \\\n" ,"-command { occdialog; }\n" ,".ngmenu.geometry add command -label \"Edit Face Mesh Size...\" \\\n" ,"-command { surfacemeshsizedialog }\n" ,"set entities [ ]\n" ,"proc occdialogbuildtree {} {\n" ,"global entities\n" ,"set w .occ_dlg\n" ,"set entities [Ng_GetOCCData getentities]\n" ,"set nrentities [expr [llength $entities]]\n" ,"if {$nrentities != 0} {\n" ,"$w.tree insert {Topology} end -id \"CompSolids\" -text \"Composite Solids\"\n" ,"$w.tree insert {Topology} end -id \"FreeSolids\" -text \"Free Solids\"\n" ,"$w.tree insert {Topology} end -id \"FreeShells\" -text \"Free Shells\"\n" ,"$w.tree insert {Topology} end -id \"FreeFaces\" -text \"Free Faces\"\n" ,"$w.tree insert {Topology} end -id \"FreeWires\" -text \"Free Wires\"\n" ,"$w.tree insert {Topology} end -id \"FreeEdges\" -text \"Free Edges\"\n" ,"$w.tree insert {Topology} end -id \"FreeVertices\" -text \"Free Vertices\"\n" ,"$w.tree item \"Topology\" -open true\n" ,"set i [expr 0]\n" ,"while {$i < $nrentities} {\n" ,"set entity [lindex $entities [expr $i]]\n" ,"incr i 1\n" ,"set entityname [lindex $entities [expr $i]]\n" ,"set myroot [string range $entity 0 [string last / $entity]-1]\n" ,"$w.tree insert $myroot end -id $entity -text $entityname -value 1\n" ,"incr i 1\n" ,"}\n" ,"set i [expr 0]\n" ,"while {$i < $nrentities} {\n" ,"set entity [lindex $entities [expr $i]]\n" ,"$w.tree item $entity -open false\n" ,"incr i 2\n" ,"}\n" ,"set faces [Ng_OCCCommand getunmeshedfaceinfo]\n" ,"set nrfaces [expr [llength $faces]]\n" ,"if {$nrfaces >= 2} {\n" ,"$w.tree insert {} -id ErrorFaces -text \"Faces with surface meshing error\"\n" ,"$w.tree item ErrorFaces -open true\n" ,"set i [expr 0]\n" ,"while {$i < $nrfaces} {\n" ,"set entity [lindex $faces [expr $i]]\n" ,"set myroot [string range $entity 0 [string last / $entity]-1]\n" ,"if { [string length $myroot] == 0 } {\n" ,"set myroot ErrorFaces\n" ,"}\n" ,"incr i 1\n" ,"set entityname [lindex $faces [expr $i]]\n" ,"$w.tree insert {myroot} end -id $entity -text $entityname -value 0\n" ,"incr i 1\n" ,"}\n" ,"}\n" ,"set faces [Ng_OCCCommand getnotdrawablefaces]\n" ,"set nrfaces [expr [llength $faces]]\n" ,"if {$nrfaces >= 2} {\n" ,"$w.tree insert {} -id NotDrawableFaces -text \"Faces impossible to visualize\"\n" ,"$w.tree item NotDrawableFaces -open true\n" ,"set i [expr 0]\n" ,"while {$i < $nrfaces} {\n" ,"set entity [lindex $faces [expr $i]]\n" ,"set myroot [string range $entity 0 [string last / $entity]-1]\n" ,"if { [string length $myroot ] == 0 } {\n" ,"set myroot NotDrawableFaces\n" ,"}\n" ,"incr i 1\n" ,"set entityname [lindex $faces [expr $i]]\n" ,"$w.tree insert $myroot end -id $entity -text $entityname -value 0\n" ,"incr i 1\n" ,"}\n" ,"}\n" ,"puts \"done\"\n" ,"}\n" ,"}\n" ,"proc rebuildoccdialog {} {\n" ,"if {[winfo exists .occ_dlg] == 1} {\n" ,".occ_dlg.tree delete [.occ_dlg.tree children Topology]\n" ,"occdialogbuildtree\n" ,"}\n" ,"}\n" ,"proc checkoccloaded { } {\n" ,"set isoccgeometryloaded [Ng_OCCCommand isoccgeometryloaded]\n" ,"if {$isoccgeometryloaded == 0} {\n" ,"puts \"no IGES/STEP geometry loaded\"\n" ,"destroy .occ_dlg\n" ,"}\n" ,"}\n" ,"proc selectentity { entityname } {\n" ,"global entities\n" ,"set nrentities [expr [llength $entities]]\n" ,"set i [expr 0]\n" ,"while {$i < $nrentities} {\n" ,"set entitylength []\n" ,"set entity2 [lindex $entities [expr $i]]\n" ,"incr i 1\n" ,"set entityname2 [lindex $entities [expr $i]]\n" ,"incr i 1\n" ,"set entityname2 [string range $entityname2 0 [expr [string length $entityname]-1]]\n" ,"if {$entityname == $entityname2} {\n" ,".occ_dlg.tree see $entity2\n" ,".occ_dlg.tree selection set $entity2\n" ,"}\n" ,"}\n" ,"}\n" ,"proc occdialog { } {\n" ,"uplevel 1 {\n" ,"global entities\n" ,"set selectvisual geometry\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"set w .occ_dlg\n" ,"if {[winfo exists .occ_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"ttk::treeview $w.tree\n" ,"$w.tree insert {} end -id \"Topology\" -text \"Topology\"\n" ,"pack $w.tree -fill both -expand yes\n" ,"occdialogbuildtree\n" ,"bind $w.tree {\n" ,"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n" ,"set rootname \"\"\n" ,"if {[.occ_dlg.tree item [.occ_dlg.tree selection] -value] == 1 } {\n" ,"set rootname \"Topology\"\n" ,"}\n" ,"set spacepos [string first \" \" $entityname]\n" ,"set entitytype [string range $entityname 0 [expr $spacepos-1]]\n" ,"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n" ,"set spacepos2 [string first \" \" $helpstring]\n" ,"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n" ,"if {$rootname == \"Topology\"} {\n" ,"Ng_OCCCommand highlightentity $entitytype $entitynumber\n" ,"set selectvisual geometry\n" ,"redraw\n" ,"} {\n" ,"set brackpos [string first \" (\" $entityname]\n" ,"if {$brackpos != -1} {\n" ,"set entityname [string range $entityname 0 $brackpos]\n" ,"}\n" ,"selectentity $entityname\n" ,"}\n" ,"}\n" ,"ttk::button $w.cl -text \"Close\" -command {\n" ,"destroy .occ_dlg\n" ,"}\n" ,"ttk::button $w.show -text \"Show\" -command {\n" ,"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n" ,"set spacepos [string first \" \" $entityname]\n" ,"set entitytype [string range $entityname 0 [expr $spacepos-1]]\n" ,"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n" ,"set spacepos2 [string first \" \" $helpstring]\n" ,"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n" ,"Ng_OCCCommand show $entitytype $entitynumber\n" ,"set selectvisual geometry\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.hide -text \"Hide\" -command {\n" ,"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n" ,"set spacepos [string first \" \" $entityname]\n" ,"set entitytype [string range $entityname 0 [expr $spacepos-1]]\n" ,"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n" ,"set spacepos2 [string first \" \" $helpstring]\n" ,"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n" ,"Ng_OCCCommand hide $entitytype $entitynumber\n" ,"set selectvisual geometry\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.swaporientation -text \"Swap orientation\" -command {\n" ,"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n" ,"set spacepos [string first \" \" $entityname]\n" ,"set entitytype [string range $entityname 0 [expr $spacepos-1]]\n" ,"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n" ,"set spacepos2 [string first \" \" $helpstring]\n" ,"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n" ,"Ng_OCCCommand swaporientation $entitytype $entitynumber\n" ,"set selectvisual geometry\n" ,"redraw\n" ,".occ_dlg.tree delete [.occ_dlg.tree children Topology]\n" ,"occdialogbuildtree\n" ,"}\n" ,"ttk::button $w.marksingular -text \"Mark/Unmark as singular\" -command {\n" ,"set entityname [.occ_dlg.tree item [.occ_dlg.tree selection] -text ]\n" ,"set spacepos [string first \" \" $entityname]\n" ,"if { $spacepos != 0 } {\n" ,"set entitytype [string range $entityname 0 [expr $spacepos-1]]\n" ,"set helpstring [string range $entityname [expr $spacepos+1] [expr [string length $entityname]-1]]\n" ,"set spacepos2 [string first \" \" $helpstring]\n" ,"if { $spacepos2 != 0 } {\n" ,"set entitynumber [string range $helpstring 0 [expr $spacepos2-1]]\n" ,"puts $entitytype\n" ,"puts $entitynumber\n" ,"global ismarkedsingular\n" ,"Ng_OCCCommand marksingular $entitytype $entitynumber\n" ,"if { $ismarkedsingular == 0 } {\n" ,".occ_dlg.tree tag remove \"Color\" [.occ_dlg.tree selection]\n" ,"} {\n" ,".occ_dlg.tree tag add \"Color\" [.occ_dlg.tree selection]\n" ,".occ_dlg.tree tag configure \"Color\" -foreground \"red\"\n" ,".occ_dlg.tree tag configure \"Color\" -background \"blue\"\n" ,"}\n" ,"}\n" ,"}\n" ,"}\n" ,"ttk::checkbutton $w.zoomtohighlightedentity -text \"Zoom to highlighted entity\" \\\n" ,"-variable occoptions.zoomtohighlightedentity \\\n" ,"-command {\n" ,"Ng_SetOCCVisParameters\n" ,"if { ${occoptions.zoomtohighlightedentity} == 1} {\n" ,"set selectvisual geometry\n" ,"Ng_OCCCommand redrawstatus 1\n" ,"redraw\n" ,"} {\n" ,"Ng_OCCCommand redrawstatus 0\n" ,"}\n" ,"}\n" ,"ttk::frame $w.healing -relief groove -borderwidth 3\n" ,"ttk::button $w.healing.checkentities -text \"Analyze geometry\" -command {\n" ,"set irregent [Ng_OCCCommand findsmallentities]\n" ,"set w .occ_dlg\n" ,"set nritems [expr [llength $irregent]]\n" ,"set i [expr 0]\n" ,"if {$nritems > 0 } {\n" ,"if { [.occ_dlg.tree exists ProblematicEntities] == 1 } {\n" ,"$w.tree delete ProblematicEntities\n" ,"}\n" ,"$w.tree insert {} end -id ProblematicEntities -text \"Problematic Entities\"\n" ,"}\n" ,"while {$i < $nritems} {\n" ,"set entity [lindex $irregent [expr $i]]\n" ,"incr i 1\n" ,"set entityname [lindex $irregent [expr $i]]\n" ,"set myroot [string range $entity 0 [string last / $entity]-1]\n" ,"if { [string length $myroot] == 0 } {\n" ,"set myroot ProblematicEntities\n" ,"}\n" ,"$w.tree insert $myroot end -id $entity -text $entityname\n" ,"incr i 1\n" ,"}\n" ,"$w.tree item ProblematicEntities -open true\n" ,"}\n" ,"ttk::frame $w.healing.tolerance\n" ,"ttk::label $w.healing.tolerance.label -text \"Healing tolerance: \"\n" ,"ttk::spinbox $w.healing.tolerance.sp -textvariable occoptions.tolerance -width 6 -increment 0.01 -validate focus -validatecommand \"my_validatespinbox %W %P 12\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e-9 -to 1e6\n" ,"grid $w.healing.tolerance.label $w.healing.tolerance.sp\n" ,"ttk::checkbutton $w.healing.fixsmalledges -text \"Fix small edges\" \\\n" ,"-variable occoptions.fixsmalledges\n" ,"ttk::checkbutton $w.healing.fixspotstripfaces -text \"Fix spot/strip faces\" \\\n" ,"-variable occoptions.fixspotstripfaces\n" ,"ttk::checkbutton $w.healing.sewfaces -text \"Sew faces\" \\\n" ,"-variable occoptions.sewfaces\n" ,"ttk::checkbutton $w.healing.makesolids -text \"Make solids\" \\\n" ,"-variable occoptions.makesolids\n" ,"ttk::checkbutton $w.healing.splitpartitions -text \"Split partitions\" \\\n" ,"-variable occoptions.splitpartitions\n" ,"ttk::button $w.healing.heal -text \"Heal geometry\" -command {\n" ,"Ng_OCCCommand shapehealing\n" ,"redraw\n" ,".occ_dlg.tree delete [.occ_dlg.tree children Topology]\n" ,"occdialogbuildtree\n" ,"}\n" ,"pack $w.healing.checkentities\n" ,"pack $w.healing.tolerance $w.healing.fixsmalledges \\\n" ,"$w.healing.fixspotstripfaces $w.healing.sewfaces \\\n" ,"$w.healing.makesolids $w.healing.splitpartitions -anchor w\n" ,"pack $w.healing.heal\n" ,"pack $w.show $w.hide\n" ,"pack $w.zoomtohighlightedentity -anchor w\n" ,"pack $w.swaporientation\n" ,"pack $w.marksingular\n" ,"pack $w.healing -fill x\n" ,"pack $w.cl\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"IGES/STEP Topology Explorer/Doctor\"\n" ,"focus .occ_dlg\n" ,"}\n" ,"}\n" ,"}\n" ,"} }\n" ,"if { [Ng_ACISCommand isACISavailable] == \"yes\" } {\n" ,".ngmenu.geometry add command -label \"ACIS Topology Explorer...\" \\\n" ,"-command { acisdialog; }\n" ,".ngmenu.geometry add command -label \"ACIS combine all\" \\\n" ,"-command { Ng_ACISCommand combineall }\n" ,".ngmenu.geometry add command -label \"ACIS Create CT\" \\\n" ,"-command { Ng_ACISCommand createct }\n" ,"}\n" ,"catch { proc print_commandline_help { } {\n" ,"puts \"Usage: ng { options }\"\n" ,"puts \"-geofile=filename Input geometry file (alternative: ng filename)\"\n" ,"puts \"-meshfile=filename Output mesh file\"\n" ,"puts \"-verycoarse, -coarse, -moderate, -fine, -veryfine\"\n" ,"puts \" Automatic mesh-size selection\"\n" ,"puts \"-meshsizefile=filename Load mesh-size file with local mesh sizes\"\n" ,"puts \"-meshfiletype={\\\"Neutral Format\\\", ...}\"\n" ,"puts \" Filetype of output file, default is netgen file\"\n" ,"puts \"-batchmode Run Netgen in batchmode\"\n" ,"puts \"-inputmeshfile=filename\"\n" ,"puts \" Input mesh file (batchmode only)\"\n" ,"puts \"-mergefile=filename Merge with mesh file (batchmode only)\"\n" ,"puts \"-refinementfile=filename\"\n" ,"puts \" Use refinementinfo from file (batchmode only)\"\n" ,"puts \"-serversocket=\\\n" ,"puts \"-V Print additional information\"\n" ,"puts \"-testout=filename file for test output\"\n" ,"if { [catch { NGS_GetData } ] == 0 } {\n" ,"puts \"\\nNGSolve parameters:\"\n" ,"puts \"-pdefile=filename Load pde input file\"\n" ,"puts \"-solve Solve pde once\"\n" ,"puts \"-solve=n Solve pde by n adaptive refinement steps\"\n" ,"puts \"-recent Load and solve most recently loaded pde\"\n" ,"}\n" ,"}\n" ,"proc set_menu_help { entry helpmsg } {\n" ,"global menuhelps\n" ,"set menuhelps($entry) $helpmsg\n" ,"}\n" ,"proc show_menu_help { entry } {\n" ,"global menuhelps\n" ,"if {[catch {set helptext $menuhelps($entry)}]} {\n" ,"set helptext \"no help available \"\n" ,"}\n" ,".helpline configure -text $helptext\n" ,"if {[winfo exists .senshelp_dlg]==1} {\n" ,".senshelp_dlg.text delete 1.0 end\n" ,".senshelp_dlg.text insert end \"Menu item: $entry\\n\\n\"\n" ,".senshelp_dlg.text insert end $helptext\n" ,"}\n" ,"}\n" ,"proc set_control_help { control helpmsg } {\n" ,"bind $control \"show_control_help {$helpmsg}\"\n" ,"bind $control \"show_control_help {None}\"\n" ,".balloon bind $control -balloonmsg $helpmsg -statusmsg $helpmsg\n" ,"}\n" ,"proc show_control_help { helpmsg } {\n" ,".helpline configure -text $helpmsg\n" ,"if {[winfo exists .senshelp_dlg]==1} {\n" ,".senshelp_dlg.text delete 1.0 end\n" ,".senshelp_dlg.text insert end $helpmsg\n" ,"}\n" ,"}\n" ,"proc sensitivehelpdialog { show } {\n" ,"set w .senshelp_dlg\n" ,"if {[winfo exists .senshelp_dlg] == 1} {\n" ,"if { $show == 1 } {\n" ,"wm withdraw .senshelp_dlg\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"wm withdraw $w\n" ,"}\n" ,"} {\n" ,"toplevel $w\n" ,"global senshelptext\n" ,"text $w.text -yscrollcommand \"$w.scroll set\" -setgrid true \\\n" ,"-width 40 -height 10 -wrap word\n" ,"scrollbar $w.scroll -command \"$w.text yview\"\n" ,"pack $w.scroll -side right -fill y\n" ,"pack $w.text -expand yes -fill both\n" ,"ttk::frame $w.bu\n" ,"pack $w.bu\n" ,"ttk::button $w.close -text \"Close\" \\\n" ,"-command {\n" ,"wm withdraw .senshelp_dlg\n" ,"set showsensitivehelp 0\n" ,"}\n" ,"pack $w.close\n" ,"if { $show == 1 } {\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Help\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"}\n" ,"set_menu_help \"File\" \"In File menu you can load and store geometries, meshes etc.\"\n" ,"set_menu_help \"New Geometry\" \"Deletes current geometry\"\n" ,"set_menu_help \"Load Geometry\" \"Loads Geometry file in one of the formats STL (ASCII or binary), Constructive Solid Geometry (.geo) or 2D geometry. Please have a look into Netgen User's manuel for more details.\"\n" ,"set_menu_help \"Save Geometry\" \"Saves STL Geometry in in either ASCII or binary STL format.\"\n" ,"set_menu_help \"Load Mesh\" \"Loads surface and volume mesh in Netgen internal format.\"\n" ,"set_menu_help \"Save Mesh\" \"Saves surface and volume mesh in Netgen internal format.\"\n" ,"set_menu_help \"Write EPS File\" \"Dumps OpenGL rendering to EPS File.\"\n" ,"set_menu_help \"Save Options\" \"Saves current options in file \\\"ng.opt\\\". These options will be loaded again when starting ng in the same directory.\"\n" ,"set_menu_help \"Export Mesh\" \"Exports mesh in format defined by Export Filetype.\"\n" ,"set_menu_help \"Export Filetype\" \"Selects file format for exporting mesh. Please have a look into the Netgen User's manual for more information.\"\n" ,"set_menu_help \"Import Mesh\" \"Imports surface or volume mesh in exchange format.\"\n" ,"set_menu_help \"Quit\" \"Quits Netgen\"\n" ,"set_menu_help \"Geometry\" \"Preparing geometries, visualiztion of geometries.\"\n" ,"set_menu_help \"Scan CSG Geometry\" \"Generates surface triangulation for rendering\"\n" ,"set_menu_help \"CSG Options\" \"Sets Options for CSG visualization (bounding box, detail size, number of facets).\"\n" ,"set_menu_help \"CSG Properties\" \"Defines appearance of current CSG geometry (color, visibility, transparency)\"\n" ,"set_menu_help \"STL Doctor\" \"Calls STL Doctor for preprocessing STL geometry files.\"\n" ,"set_menu_help \"STL Info\" \"Retrieves information about current STL geometry.\"\n" ,"set_menu_help \"Mesh\" \"Menu for mesh generation\"\n" ,"set_menu_help \"Generate Mesh\" \"Generates mesh from geometry, same as Button \\\"Generate Mesh\\\"\"\n" ,"set_menu_help \"Stop Meshing\" \"Terminates meshgeneration. It may take a while until meshing terminates, please be patient.\"\n" ,"set_menu_help \"Meshing Options\" \"Set options for mesh generation.\"\n" ,"set_menu_help \"Delete Mesh\" \"Deletes mesh. Not necessary before generation of new mesh.\"\n" ,"set_menu_help \"Delete Vol Mesh\" \"Deletes only volume mesh.\"\n" ,"set_menu_help \"Mesh Quality\" \"Computs element shape measures. Triangle angles are inner angles of all triangles (faces of tetrahedra). Tet angles are angles between faces of tetrahedra.\"\n" ,"set_menu_help \"Check Surface Mesh\" \"Checks consistency and overlap of surface mesh. Marks overlapping elements as bad elements, please enable visualization of bad elements in View->Mesh.\"\n" ,"set_menu_help \"Check Volume Mesh\" \"Checks conformity of volume mesh.\"\n" ,"set_menu_help \"Edit Boundary Conditions\" \"Open dialog for setting boundary condition numbers for individual faces.\"\n" ,"set_menu_help \"Analyze Geometry\" \"Perform only first step in mesh generation. Action depends on geometry type, e.g. generates charts for STL mesh, find vertices in CSG geometries.\"\n" ,"set_menu_help \"Mesh Edges\" \"Meshes edges\"\n" ,"set_menu_help \"Mesh Surface\" \"Generates surface mesh. Includes already surface optimization for some geometry types.\"\n" ,"set_menu_help \"Optimize Surface\" \"Optimizes surface mesh.\"\n" ,"set_menu_help \"Surface Optim. Step\" \"Performs a specific surface optimiztion step. Mesh smoothing moves nodes. edge swapping swaps the diagonal of a quadrilateral built by two triangles, criterion either by number of nodes, or anlges. Combine points eliminates triangles by combining points (in the center of gravity).\"\n" ,"set_menu_help \"Mesh Volume\" \"Performs volume meshing. Algorithm is a combination of Delaunay and Rule-based Advancing Front\"\n" ,"set_menu_help \"Optimize Volume\" \"Performs additional volume optimization steps\"\n" ,"set_menu_help \"Smooth Opt Volume\" \"Performs optimization steps by smoothing iterations\"\n" ,"set_menu_help \"Smooth Opt Volume Jacobian\" \"Volume optimization by smoothing iterations. Criterion is optimization of Jacobi determinants. This optimization step is also available for 10-node tetrahedra.\"\n" ,"set_menu_help \"View\" \"Sets viewing options\"\n" ,"set_menu_help \"Zoom all\" \"Zooms scene to show whole object\"\n" ,"set_menu_help \"Center\" \"Defines center of rotation\"\n" ,"set_menu_help \"Viewing Options\" \"Sets viewing options for geometry, mesh, lighting\"\n" ,"set_menu_help \"Clipping Plane\" \"Introduces clipping plane. The clipping plane is defined by the normal vector, and a scaled offset. Clipping of performed by OpenGl rendering\"\n" ,"set_menu_help \"Quality Plot\" \"Shows the element quality distribution histogram. Measure is volume scaled by edge-length to the third. Optimal elements have measure 1.\"\n" ,"set_menu_help \"Sensitive Help\" \"Shows this help window\"\n" ,"set_menu_help \"Mesh-size\" \"Manipulations of existing mesh\"\n" ,"set_menu_help \"Refine uniform\" \"Refines mesh by splitting elements into eight childs (algorithm of J. Bey)\"\n" ,"set_menu_help \"Second Order\" \"Converts 4 node elements to 10 node elements. Edge-midpoitns are projected to the geometry.\"\n" ,"set_menu_help \"Refinement Dialog\" \"Controls local mesh refinement\"\n" ,"set_menu_help \"Load Meshsize\" \"Loads mesh-size file for local mesh refinement.\"\n" ,"set_menu_help \"MS from Surf Mesh\" \"Defines mesh-size by the surface mesh.\"\n" ,"set f .options_dlg.nb.nbframe.general\n" ,"set_control_help $f.fine \"Controls relative mesh size.\\nThis control affects other mesh-size controls in common\"\n" ,"set_control_help $f.first \"First step in mesh generation. Usually, meshing starts from \\\"analyze geometry\\\". If the surface mesh is already available \\\"First step\\\" should be set to \\\"mesh volume\\\"\"\n" ,"set_control_help $f.last \"Last step in mesh generation. If only the surface mesh is required, please set \\\"Last Step\\\" to \\\"Optimize Surface\\\"\"\n" ,"set_control_help .bubar.surfm \"Start mesh generation\"\n" ,"set_control_help .bubar.stopm \"Stop mesh generation\"\n" ,"proc help_item { helptext } {p\n" ,"puts $helptext\n" ,"}\n" ,"proc show_help { } {\n" ,"set w .help\n" ,"if {[winfo exists .help] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconif $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"frame $w.buttons\n" ,"pack $w.buttons -side bottom -fill x -pady 2m\n" ,"button $w.buttons.done -text Done -command \"destroy $w\"\n" ,"pack $w.buttons.done -side left -expand 1\n" ,"text $w.text -yscrollcommand \"$w.scroll set\" -setgrid true \\\n" ,"-width 60 -height 24 -wrap word\n" ,"scrollbar $w.scroll -command \"$w.text yview\"\n" ,"pack $w.scroll -side right -fill y\n" ,"pack $w.text -expand yes -fill both\n" ,"}\n" ,"$w.text configure -state normal\n" ,"$w.text delete 1.0 end\n" ,"}\n" ,"set bold \"-background \n" ,"set normal \"-background {} -relief flat\"\n" ,"proc help_main { } {\n" ,"show_help;\n" ,"set w .help\n" ,"global bold\n" ,"global normal\n" ,"$w.text insert 0.0 \\\n" ,"{NETGEN Help}\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{1. General} d1\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{2. Menu items } d2\n" ,"$w.text insert end \\n\\n\n" ,"foreach tag {d1 d2} {\n" ,"$w.text tag bind $tag \"$w.text tag configure $tag $bold\"\n" ,"$w.text tag bind $tag \"$w.text tag configure $tag $normal\"\n" ,"}\n" ,"$w.text tag bind d1 <1> { puts \"general\"; help_general }\n" ,"$w.text tag bind d2 <1> { help_menus }\n" ,"$w.text configure -state disabled\n" ,"}\n" ,"proc help_general { } {\n" ,"show_help;\n" ,"set w .help\n" ,"global bold\n" ,"global normal\n" ,"puts \"general called\"\n" ,"$w.text insert 0.0 \\\n" ,"{NETGEN is an automatic three dimensional tetrahedral mesh generation system. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STEP or STL file format. NETGEN contains modules for mesh optimization and hierarchical mesh refinement.}\n" ,"$w.text configure -state disabled\n" ,"}\n" ,"proc help_menus { } {\n" ,"show_help;\n" ,"set w .help\n" ,"global bold\n" ,"global normal\n" ,"$w.text insert 0.0 \\\n" ,"{The NETGEN Menu items are}\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{1. File} d1\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{2. Geometry } d2\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{3. Mesh } d3\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{4. View } d4\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{5. Mesh-size } d5\n" ,"$w.text insert end \\n\\n\n" ,"$w.text insert end \\\n" ,"{6. STL } d6\n" ,"foreach tag {d1 d2 d3 d4 d5 d6} {\n" ,"$w.text tag bind $tag \"$w.text tag configure $tag $bold\"\n" ,"$w.text tag bind $tag \"$w.text tag configure $tag $normal\"\n" ,"}\n" ,"$w.text tag bind d1 <1> {puts \"File menu\"}\n" ,"$w.text tag bind d2 <1> {puts \"Geometry menu\"}\n" ,"$w.text tag bind d3 <1> {puts \"Mesh menu\"}\n" ,"$w.text tag bind d4 <1> {puts \"View menu\"}\n" ,"$w.text tag bind d5 <1> {puts \"Mesh-size menu\"}\n" ,"$w.text tag bind d6 <1> {puts \"STL menu\"}\n" ,"$w.text configure -state disabled\n" ,"}\n" ,"}\n" ,"catch { Ng_Vis_Set parameters\n" ,"set viscnt 0\n" ,"proc snapshottimer { } {\n" ,"after 2000 { snapshottimer }\n" ,"global viscnt\n" ,"set viscnt [expr $viscnt+1]\n" ,"set s1 0000$viscnt\n" ,"set cnt [string range $s1 [expr [string length $s1]-4] end]\n" ,"set filename \"p$cnt.jpg\"\n" ,"}\n" ,"snapshottimer\n" ,"proc redrawtimer { } {\n" ,"global visoptions.autoredraw\n" ,"global visoptions.autoredrawtime\n" ,"set delay [expr int(${visoptions.autoredrawtime}*1000)]\n" ,"if { ${visoptions.autoredraw} == 1 } { redraw; }\n" ,"after $delay { redrawtimer }\n" ,"}\n" ,"redrawtimer\n" ,"set perstarttime [clock clicks -millisecond]\n" ,"proc redrawperiodic { } {\n" ,"global visoptions.redrawperiodic\n" ,"global perstarttime\n" ,"set curtime [clock clicks -millisecond]\n" ,"Ng_Vis_Set time [expr ($curtime - $perstarttime) / 5]\n" ,"redraw\n" ,"if { ${visoptions.redrawperiodic} == 1 } { after 30 { redrawperiodic } };\n" ,"}\n" ,"proc addplotline { identifier datax datay plotinfo {color black}} {\n" ,"set c $identifier.c\n" ,"set xstart [lindex $plotinfo 0]\n" ,"set ystart [lindex $plotinfo 1]\n" ,"set xmin [lindex $plotinfo 2]\n" ,"set ymin [lindex $plotinfo 3]\n" ,"set unitx [lindex $plotinfo 4]\n" ,"set unity [lindex $plotinfo 5]\n" ,"set latestx [expr ([lindex $datax 0]-$xmin)*$unitx + $xstart]\n" ,"set latesty [expr ([lindex $datay 0]-$ymin)*$unity + $ystart]\n" ,"for {set i 1} {$i < [llength $datax]} {incr i} {\n" ,"set xpos [expr ([lindex $datax $i]-$xmin)*$unitx + $xstart]\n" ,"set ypos [expr ([lindex $datay $i]-$ymin)*$unity + $ystart]\n" ,"$c create line $latestx $latesty $xpos $ypos -width 1 -fill $color\n" ,"set latestx $xpos\n" ,"set latesty $ypos\n" ,"}\n" ,"}\n" ,"proc createlineplot { width height identifier title xmin xmax ymin ymax plotinfo} {\n" ,"set thiswidth $width\n" ,"set thisheight $height\n" ,"if { $thiswidth < 275 } { set thiswidth 275 }\n" ,"if { $thisheight < 225 } { seth thisheight 225 }\n" ,"set w $identifier\n" ,"if {[winfo exists $w] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"set c $w.c\n" ,"canvas $c -relief raised -width $thiswidth -height $thisheight\n" ,"pack $w.c -side top -fill x\n" ,"set titleFont {Helvetica 18}\n" ,"set smallFont {Helvetica 12}\n" ,"set xstart 100\n" ,"set xend [expr $thiswidth-75]\n" ,"set ystart [expr $thisheight-75]\n" ,"set yend 75\n" ,"$c create line $xstart $ystart $xstart $yend -width 2\n" ,"$c create line $xstart $ystart $xend $ystart -width 2\n" ,"set unitx [expr double($xend-$xstart)/($xmax-$xmin)]\n" ,"set unity [expr double($yend-$ystart)/($ymax-$ymin)]\n" ,"for {set i 0} {$i <= 1} {set i [expr $i+0.2]} {\n" ,"$c create line [expr $xstart+$i*($xend-$xstart)] [expr $ystart] [expr $xstart+$i*($xend-$xstart)] [expr $ystart+5] -width 2\n" ,"$c create text [expr $xstart+$i*($xend-$xstart)] [expr $ystart+7] -anchor n -font $smallFont \\\n" ,"-text [format \"%.3g\" [expr $xmin+$i*($xmax-$xmin)]]\n" ,"$c create line [expr $xstart] [expr $ystart+$i*($yend-$ystart)] [expr $xstart-7] [expr $ystart+$i*($yend-$ystart)] -width 2\n" ,"$c create text [expr $xstart-9] [expr $ystart+$i*($yend-$ystart)] -anchor e -font $smallFont \\\n" ,"-text [format \"%.3g\" [expr $ymin+$i*($ymax-$ymin)]]\n" ,"}\n" ,"upvar $plotinfo ploti\n" ,"set ploti \"$xstart $ystart $xmin $ymin $unitx $unity\"\n" ,"button $w.close -text \"Close\" -command \"destroy $w\"\n" ,"pack $w.close\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w $title\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"proc getlineplotdata { datax datay xmini xmaxi ymini ymaxi} {\n" ,"upvar $datax datx\n" ,"upvar $datay daty\n" ,"upvar $xmini xmin\n" ,"upvar $xmaxi xmax\n" ,"upvar $ymini ymin\n" ,"upvar $ymaxi ymax\n" ,"global visoptions.lineplotusingx\n" ,"global visoptions.lineplotusingy\n" ,"global visoptions.lineplotsource\n" ,"global visoptions.lineplotfile\n" ,"set datx \"\"\n" ,"set daty \"\"\n" ,"set xmin 1e20\n" ,"set xmax -1e20\n" ,"set ymin 1e20\n" ,"set ymax -1e20\n" ,"if {${visoptions.lineplotsource} == \"file\"} {\n" ,"set fileId [open ${visoptions.lineplotfile} r]\n" ,"set line \"\"\n" ,"while {[gets $fileId line] >= 0} {\n" ,"if { [string index [lindex $line 0] 0] != \"\\\n" ,"if { ${visoptions.lineplotusingx} < [llength $line] } {\n" ,"lappend datx [lindex $line ${visoptions.lineplotusingx}]\n" ,"if { [lindex $datx end] < $xmin } {set xmin [lindex $datx end]}\n" ,"if { [lindex $datx end] > $xmax } {set xmax [lindex $datx end]}\n" ,"} {\n" ,"lappend datx 0\n" ,"}\n" ,"if { ${visoptions.lineplotusingy} < [llength $line] } {\n" ,"lappend daty [lindex $line ${visoptions.lineplotusingy}]\n" ,"if { [lindex $daty end] < $ymin } {set ymin [lindex $daty end]}\n" ,"if { [lindex $daty end] > $ymax } {set ymax [lindex $daty end]}\n" ,"} {\n" ,"lappend daty 0\n" ,"}\n" ,"}\n" ,"}\n" ,"close $fileId\n" ,"}\n" ,"}\n" ,"proc lineplotdialog { } {\n" ,"set w .lineplot_dlg\n" ,"if {[winfo exists .lineplot_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"ttk::frame $w.filesettings -relief groove -borderwidth 3\n" ,"ttk::frame $w.filesettings.title\n" ,"ttk::radiobutton $w.filesettings.title.choose -variable visoptions.lineplotsource \\\n" ,"-value file -text \"Data from File\"\n" ,"pack $w.filesettings.title.choose -side left\n" ,"pack $w.filesettings.title\n" ,"global visoptions.lineplotselectedeval\n" ,"global visoptions.lineplotfile\n" ,"global visoptions.evaluatefilenames\n" ,"global visoptions.evaluatefiledescriptions\n" ,"set evdata [NGS_GetData evaluatefiles]\n" ,"set visoptions.evaluatefilenames none\n" ,"set visoptions.evaluatefiledescriptions none\n" ,"for {set i 0} {[expr $i+1] < [llength $evdata]} {incr i 2} {\n" ,"lappend visoptions.evaluatefilenames [lindex $evdata $i]\n" ,"lappend visoptions.evaluatefiledescriptions [lindex $evdata [expr $i+1]]\n" ,"}\n" ,"ttk::frame $w.filesettings.latestevals\n" ,"ttk::label $w.filesettings.latestevals.lab -text \"Use Evaluate Results: \"\n" ,"ttk::menubutton $w.filesettings.latestevals.but -menu $w.filesettings.latestevals.menu -text \"coarse\" -width 40\n" ,"menu $w.filesettings.latestevals.menu -tearoff 0\n" ,"for {set i 0} {$i < [llength ${visoptions.evaluatefilenames}]} {incr i} {\n" ,"$w.filesettings.latestevals.menu add command -label $i\\\n" ,"-command \"set visoptions.lineplotselectedeval $i ; $w.filesettings.latestevals.but configure -text \\\"[lindex ${visoptions.evaluatefiledescriptions} $i] ([lindex ${visoptions.evaluatefilenames} $i])\\\"\"\n" ,"}\n" ,"$w.filesettings.latestevals.menu invoke ${visoptions.lineplotselectedeval}\n" ,"grid $w.filesettings.latestevals.lab $w.filesettings.latestevals.but -sticky nw\n" ,"pack $w.filesettings.latestevals\n" ,"ttk::frame $w.filesettings.sfn\n" ,"ttk::button $w.filesettings.sfn.bb -text \"Browse\" \\\n" ,"-command { set visoptions.lineplotfile [tk_getOpenFile] }\n" ,"ttk::entry $w.filesettings.sfn.fn -width 50 \\\n" ,"-textvariable visoptions.lineplotfile\n" ,"pack $w.filesettings.sfn.bb $w.filesettings.sfn.fn -side left\n" ,"pack $w.filesettings.sfn\n" ,"ttk::button $w.filesettings.refresh -text \"Refresh\" -command {\n" ,"if { ${visoptions.lineplotselectedeval} != 0} {\n" ,"set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\n" ,"}\n" ,"set saveusingx ${visoptions.lineplotusingx}\n" ,"set saveusingy ${visoptions.lineplotusingy}\n" ,"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n" ,"${visoptions.lineplotxcoordselector} delete $i\n" ,"}\n" ,"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n" ,"${visoptions.lineplotycoordselector} delete $i\n" ,"}\n" ,"set fileId [open ${visoptions.lineplotfile} r]\n" ,"set line \"\"\n" ,"gets $fileId line\n" ,"close $fileId\n" ,"if { [lindex $line 0] == \"\\\n" ,"set visoptions.lineplotdatadescr [lrange $line 1 end]\n" ,"} {\n" ,"set visoptions.lineplotdatadescr \"\"\n" ,"for { set i 0 } { $i < [llength $line] } { incr i } {\n" ,"lappend visoptions.lineplotdatadescr \"data[expr $i+1]\"\n" ,"}\n" ,"}\n" ,"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n" ,"${visoptions.lineplotxcoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\n" ,"}\n" ,"for { set i 0 } { $i < [llength ${visoptions.lineplotdatadescr}] } { incr i } {\n" ,"${visoptions.lineplotycoordselector} add command $i -label [lindex ${visoptions.lineplotdatadescr} $i]\n" ,"}\n" ,"if { $saveusingx < [llength ${visoptions.lineplotdatadescr}] } {\n" ,"set visoptions.lineplotusingx $saveusingx\n" ,"} {\n" ,"set visoptions.lineplotusingx 0\n" ,"}\n" ,"if { $saveusingy < [llength ${visoptions.lineplotdatadescr}] } {\n" ,"set visoptions.lineplotusingy $saveusingy\n" ,"} {\n" ,"set visoptions.lineplotusingy 1\n" ,"}\n" ,"}\n" ,"pack $w.filesettings.refresh\n" ,"ttk::frame $w.filesettings.using\n" ,"global visoptions.lineplotdatadescr\n" ,"ttk::frame $w.filesettings.using.xco\n" ,"ttk::label $w.filesettings.using.xco.lab -text \"X-Coord:\"\n" ,"ttk::menubutton $w.filesettings.using.xco.but -menu $w.filesettings.using.xco.menu -text \"\" -width 15\n" ,"menu $w.filesettings.using.xco.menu -tearoff 0\n" ,"for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} {\n" ,"$w.filesettings.using.xco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\\\n" ,"-command \"set visoptions.lineplotusingx $i ; $w.filesettings.using.xco.but configure -text \\\"[lindex ${visoptions.lineplotdatadescr} $i]\\\"\"\n" ,"}\n" ,"$w.filesettings.using.xco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0]\n" ,"grid $w.filesettings.using.xco.lab $w.filesettings.using.xco.but -sticky nw\n" ,"ttk::frame $w.filesettings.using.yco\n" ,"ttk::label $w.filesettings.using.yco.lab -text \"Y-Coord:\"\n" ,"ttk::menubutton $w.filesettings.using.yco.but -menu $w.filesettings.using.yco.menu -text \"\" -width 15\n" ,"menu $w.filesettings.using.yco.menu -tearoff 0\n" ,"for {set i 0} {$i < [llength ${visoptions.lineplotdatadescr}]} {incr i} {\n" ,"$w.filesettings.using.yco.menu add command -label [lindex ${visoptions.lineplotdatadescr} $i]\\\n" ,"-command \"set visoptions.lineplotusingy $i ; $w.filesettings.using.yco.but configure -text \\\"[lindex ${visoptions.lineplotdatadescr} $i]\\\"\"\n" ,"}\n" ,"$w.filesettings.using.yco.menu invoke [lindex ${visoptions.lineplotdatadescr} 0]\n" ,"grid $w.filesettings.using.yco.lab $w.filesettings.using.yco.but -sticky nw\n" ,"global visoptions.lineplotxcoordselector\n" ,"global visoptions.lineplotycoordselector\n" ,"set visoptions.lineplotxcoordselector $w.filesettings.using.xco\n" ,"set visoptions.lineplotycoordselector $w.filesettings.using.yco\n" ,"pack $w.filesettings.using.xco $w.filesettings.using.yco -side left\n" ,"pack $w.filesettings.using\n" ,"pack $w.filesettings -fill x -ipady 3\n" ,"ttk::frame $w.settings -relief groove -borderwidth 3\n" ,"ttk::label $w.settings.title -text \"\\nSettings\\n\"\n" ,"pack $w.settings.title\n" ,"ttk::frame $w.settings.minmax\n" ,"ttk::checkbutton $w.settings.minmax.autoscale -text \"Autoscale\" -variable visoptions.lineplotautoscale\n" ,"ttk::frame $w.settings.minmax.xmin\n" ,"ttk::label $w.settings.minmax.xmin.label -text \"Min. x: \"\n" ,"ttk::spinbox $w.settings.minmax.xmin.sp -textvariable visoptions.lineplotxmin -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n" ,"ttk::frame $w.settings.minmax.xmax\n" ,"ttk::label $w.settings.minmax.xmax.label -text \"Max. x: \"\n" ,"ttk::spinbox $w.settings.minmax.xmax.sp -textvariable visoptions.lineplotxmax -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n" ,"ttk::frame $w.settings.minmax.ymin\n" ,"ttk::label $w.settings.minmax.ymin.label -text \"Min. y: \"\n" ,"ttk::spinbox $w.settings.minmax.ymin.sp -textvariable visoptions.lineplotymin -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n" ,"ttk::frame $w.settings.minmax.ymax\n" ,"ttk::label $w.settings.minmax.ymax.label -text \"Max. y: \"\n" ,"ttk::spinbox $w.settings.minmax.ymax.sp -textvariable visoptions.lineplotymax -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 3\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n" ,"pack $w.settings.minmax.xmin.label $w.settings.minmax.xmin.sp\n" ,"pack $w.settings.minmax.xmax.label $w.settings.minmax.xmax.sp\n" ,"pack $w.settings.minmax.ymin.label $w.settings.minmax.ymin.sp\n" ,"pack $w.settings.minmax.ymax.label $w.settings.minmax.ymax.sp\n" ,"pack $w.settings.minmax.autoscale $w.settings.minmax.xmin $w.settings.minmax.xmax \\\n" ,"$w.settings.minmax.ymin $w.settings.minmax.ymax -side left\n" ,"pack $w.settings.minmax\n" ,"ttk::label $w.settings.empty1 -text \"\"\n" ,"pack $w.settings.empty1\n" ,"ttk::frame $w.settings.plotsize\n" ,"ttk::frame $w.settings.plotsize.xsize\n" ,"ttk::label $w.settings.plotsize.xsize.label -text \"Plotsize x: \"\n" ,"ttk::spinbox $w.settings.plotsize.xsize.sp -textvariable visoptions.lineplotsizex -width 6 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n" ,"pack $w.settings.plotsize.xsize.label $w.settings.plotsize.xsize.sp\n" ,"ttk::frame $w.settings.plotsize.ysize\n" ,"ttk::label $w.settings.plotsize.ysize.label -text \"Plotsize y: \"\n" ,"ttk::spinbox $w.settings.plotsize.ysize.sp -textvariable visoptions.lineplotsizey -width 6 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e9 -to 1e9\n" ,"pack $w.settings.plotsize.ysize.label $w.settings.plotsize.ysize.sp\n" ,"pack $w.settings.plotsize.xsize $w.settings.plotsize.ysize -side left\n" ,"pack $w.settings.plotsize\n" ,"ttk::label $w.settings.empty2 -text \"\"\n" ,"pack $w.settings.empty2\n" ,"ttk::frame $w.settings.color\n" ,"ttk::label $w.settings.color.lab -text \"Linecolor: \"\n" ,"ttk::menubutton $w.settings.color.but -menu $w.settings.color.menu -text \"\" -width 15\n" ,"menu $w.settings.color.menu -tearoff 0\n" ,"foreach step { red black blue green yellow } {\n" ,"$w.settings.color.menu add command -label $step -command \"set visoptions.lineplotcolor $step; $w.settings.color.but configure -text \\\"$step\\\"\"\n" ,"}\n" ,"$w.settings.color.menu invoke \"red\"\n" ,"grid $w.settings.color.lab $w.settings.color.but -sticky nw\n" ,"pack $w.settings.color\n" ,"pack $w.settings -fill x\n" ,"set datax \"\"\n" ,"set datay \"\"\n" ,"set xmin 0\n" ,"set xmax 0\n" ,"set ymin 0\n" ,"set ymax 0\n" ,"ttk::frame $w.plots -relief groove -borderwidth 3\n" ,"ttk::frame $w.plots.selplot\n" ,"ttk::label $w.plots.selplot.lab -text \"Linecolor: \"\n" ,"ttk::menubutton $w.plots.selplot.but -menu $w.plots.selplot.menu -text \"\" -width 15\n" ,"menu $w.plots.selplot.menu -tearoff 0\n" ,"$w.plots.selplot.menu add command -label \"None\" -command \"set visoptions.lineplotselected \\\"None\\\"; $w.plots.selplot.but configure -text \\\"None\\\"\"\n" ,"grid $w.plots.selplot.lab $w.plots.selplot.but -sticky nw\n" ,"$w.plots.selplot.menu invoke \"None\"\n" ,"global visoptions.lineplotselector\n" ,"set visoptions.lineplotselector $w.plots.selplot.menu\n" ,"ttk::button $w.plots.new -text \"Generate New Plot\" -command {\n" ,"if { ${visoptions.lineplotselectedeval} != 0} {\n" ,"set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\n" ,"}\n" ,"getlineplotdata datax datay xmin xmax ymin ymax\n" ,"puts stdout \"xmin $xmin xmax $xmax ymin $ymin ymax $ymax\"\n" ,"global visoptions.lineplotautoscale\n" ,"if {! ${visoptions.lineplotautoscale}} {\n" ,"puts \"using set min/max values\"\n" ,"set xmin ${visoptions.lineplotxmin}\n" ,"set xmax ${visoptions.lineplotxmax}\n" ,"set ymin ${visoptions.lineplotymin}\n" ,"set ymax ${visoptions.lineplotymax}\n" ,"}\n" ,"incr visoptions.lineplotcurrentnum\n" ,"set ident .newplot${visoptions.lineplotcurrentnum}\n" ,"set plotinfo \"\"\n" ,"createlineplot ${visoptions.lineplotsizex} ${visoptions.lineplotsizey} \\\n" ,"$ident \"Lineplot ${visoptions.lineplotcurrentnum}\" \\\n" ,"$xmin $xmax $ymin $ymax plotinfo\n" ,"lappend visoptions.lineplotinfos $plotinfo\n" ,"${visoptions.lineplotselector} add command ${visoptions.lineplotcurrentnum} -label \"Lineplot ${visoptions.lineplotcurrentnum}\"\n" ,"addplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor}\n" ,"}\n" ,"ttk::button $w.plots.addto -text \"Add to Selected Plot\" -command {\n" ,"if { ${visoptions.lineplotselectedeval} != 0} {\n" ,"set visoptions.lineplotfile [lindex ${visoptions.evaluatefilenames} ${visoptions.lineplotselectedeval}]\n" ,"}\n" ,"if { ${visoptions.lineplotselected} != \"none\" } {\n" ,"getlineplotdata datax datay xmin xmax ymin ymax\n" ,"set ident .newplot${visoptions.lineplotselected}\n" ,"set plotinfo [lindex ${visoptions.lineplotinfos} ${visoptions.lineplotselected}]\n" ,"addplotline $ident $datax $datay $plotinfo ${visoptions.lineplotcolor}\n" ,"}\n" ,"}\n" ,"pack $w.plots.new $w.plots.addto $w.plots.selplot\n" ,"pack $w.plots -fill x -ipady 3\n" ,"ttk::button $w.close -text \"Close\" -command \"destroy $w\"\n" ,"pack $w.close\n" ,"wm withdraw $w\n" ,"wm geom $w +200+100\n" ,"wm deiconify $w\n" ,"wm title $w \"2D Lineplots\"\n" ,"focus $w\n" ,"}\n" ,"}\n" ,"set fieldlinesdialog_pop1 0\n" ,"proc fieldlinesdialog { } {\n" ,"set w .fieldlines_dlg\n" ,"global fieldlinesdialog_pop1\n" ,"set fieldlinesdialog_pop1 1\n" ,"if {[winfo exists .fieldlines_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"pack [ttk::notebook $w.nb] -fill both -side top -ipadx 6 -ipady 6\n" ,"$w.nb add [ttk::frame $w.nb.draw] -text \"Draw\" -underline 0\n" ,"$w.nb add [ttk::frame $w.nb.settings] -text \"Settings\" -underline 0\n" ,"set f $w.nb.draw\n" ,"ttk::labelframe $f.general -text \"General settings\" -relief groove -borderwidth 3\n" ,"ttk::checkbutton $f.general.enable -text \"Enable Fieldlines\" \\\n" ,"-variable visoptions.drawfieldlines \\\n" ,"-command {\n" ,"Ng_Vis_Set parameters;\n" ,"redraw\n" ,"}\n" ,"ttk::label $f.general.numl -text \"num:\"\n" ,"ttk::spinbox $f.general.num -from 0 -to 100 -increment 1 \\\n" ,"-textvariable visoptions.numfieldlines -width 4\n" ,"grid $f.general.enable -sticky nw -padx 4 -pady 2\n" ,"grid x $f.general.numl $f.general.num -rowspan 3 -sticky w -padx 4 -row 0 -pady 2\n" ,"grid anchor $f.general center\n" ,"pack $f.general -pady 15 -fill x -ipady 3\n" ,"ttk::label $f.labe0 -text \" \"\n" ,"pack $f.labe0\n" ,"ttk::checkbutton $f.general.randomstart -text \"Field dependent density \" \\\n" ,"-variable visoptions.fieldlinesrandomstart \\\n" ,"-command { Ng_Vis_Set parameters; redraw}\n" ,"ttk::checkbutton $f.general.redrawperiodic -text \"Animate periodic\" \\\n" ,"-variable visoptions.redrawperiodic \\\n" ,"-command {\n" ,"redrawperiodic\n" ,"Ng_Vis_Set parameters;\n" ,"redraw\n" ,"}\n" ,"grid $f.general.randomstart -sticky nw -padx 4 -row 1\n" ,"grid $f.general.redrawperiodic -sticky nw -padx 4 -row 2\n" ,"ttk::label $f.lab0 -text \" \"\n" ,"pack $f.lab0\n" ,"ttk::frame $f.vecfun\n" ,"ttk::label $f.vecfun.lab -text \"Vector Function: \"\n" ,"ttk::menubutton $f.vecfun.but -menu $f.vecfun.menu -text \"\" -width 12\n" ,"menu $f.vecfun.menu -tearoff 0\n" ,"for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n" ,"set fname [Ng_Vis_Field getfieldname $i]\n" ,"set fcomp [Ng_Vis_Field getfieldcomponents $i]\n" ,"set iscomplex [Ng_Vis_Field iscomplex $i]\n" ,"set sdim [Ng_Vis_Field getdimension]\n" ,"if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] }\n" ,"if { ($fcomp == $sdim) || ($fcomp == 3) } {\n" ,"$f.vecfun.menu add command -label $fname -command \"set visoptions.fieldlinesvecfunction $fname;Ng_Vis_Set parameters; redraw;$f.vecfun.but configure -text \\\"$fname\\\" \" }\n" ,"}\n" ,"grid $f.vecfun.lab $f.vecfun.but -sticky nw\n" ,"pack $f.vecfun\n" ,"ttk::label $f.lab00 -text \" \"\n" ,"pack $f.lab00\n" ,"ttk::frame $f.phasesettings\n" ,"ttk::checkbutton $f.phasesettings.onephase -text \"Fix Phase\" -variable visoptions.fieldlinesonlyonephase\n" ,"ttk::frame $f.phasesettings.phase\n" ,"ttk::label $f.phasesettings.phase.lab -text \"phi\"\n" ,"ttk::scale $f.phasesettings.phase.sc -orient horizontal -length 100 -from 0 -to 360 -variable visoptions.fieldlinesphase \\\n" ,"-command \"roundscale $f.phasesettings.phase.sc 0; popupcheckredraw3 fieldlinesdialog_pop1\"\n" ,"ttk::entry $f.phasesettings.phase.ent -width 4 -textvariable visoptions.fieldlinesphase -validate focus -takefocus 0 \\\n" ,"-validatecommand \"popupcheckredraw3 fieldlinesdialog_pop1;my_validate %W 0 1 %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W;popupcheckredraw3 fieldlinesdialog_pop1\"\n" ,"grid $f.phasesettings.phase.lab $f.phasesettings.phase.sc $f.phasesettings.phase.ent -sticky nw -ipadx 4\n" ,"pack $f.phasesettings.onephase $f.phasesettings.phase -side left\n" ,"pack $f.phasesettings\n" ,"ttk::label $f.lab1 -text \" \"\n" ,"pack $f.lab1\n" ,"ttk::frame $f.boxsettings -relief groove -borderwidth 3\n" ,"ttk::frame $f.boxsettings.title\n" ,"ttk::radiobutton $f.boxsettings.title.choose -variable visoptions.fieldlinesstartarea \\\n" ,"-value box -text \"Startpoints in Box\"\n" ,"pack $f.boxsettings.title.choose -side left\n" ,"pack $f.boxsettings.title\n" ,"ttk::frame $f.boxsettings.points\n" ,"ttk::label $f.boxsettings.points.lab2 -text \"Pmin\";\n" ,"ttk::entry $f.boxsettings.points.ent1x -width 8 \\\n" ,"-textvariable visoptions.fieldlinesstartareap1x\n" ,"ttk::entry $f.boxsettings.points.ent1y -width 8 \\\n" ,"-textvariable visoptions.fieldlinesstartareap1y\n" ,"ttk::entry $f.boxsettings.points.ent1z -width 8 \\\n" ,"-textvariable visoptions.fieldlinesstartareap1z\n" ,"ttk::label $f.boxsettings.points.lab3 -text \" Pmax\";\n" ,"ttk::entry $f.boxsettings.points.ent2x -width 8 \\\n" ,"-textvariable visoptions.fieldlinesstartareap2x\n" ,"ttk::entry $f.boxsettings.points.ent2y -width 8 \\\n" ,"-textvariable visoptions.fieldlinesstartareap2y\n" ,"ttk::entry $f.boxsettings.points.ent2z -width 8 \\\n" ,"-textvariable visoptions.fieldlinesstartareap2z\n" ,"pack $f.boxsettings.points\n" ,"pack $f.boxsettings.points.lab2 $f.boxsettings.points.ent1x $f.boxsettings.points.ent1y $f.boxsettings.points.ent1z -side left\n" ,"pack $f.boxsettings.points.lab3 $f.boxsettings.points.ent2x $f.boxsettings.points.ent2y $f.boxsettings.points.ent2z -side left\n" ,"ttk::button $f.boxsettings.settobb -text \"Bounding Box\" -command {\n" ,"set bbox [Ng_MeshInfo bbox]\n" ,"set visoptions.fieldlinesstartareap1x [lindex $bbox 0]\n" ,"set visoptions.fieldlinesstartareap2x [lindex $bbox 1]\n" ,"set visoptions.fieldlinesstartareap1y [lindex $bbox 2]\n" ,"set visoptions.fieldlinesstartareap2y [lindex $bbox 3]\n" ,"set visoptions.fieldlinesstartareap1z [lindex $bbox 4]\n" ,"set visoptions.fieldlinesstartareap2z [lindex $bbox 5]\n" ,"}\n" ,"pack $f.boxsettings.settobb\n" ,"pack $f.boxsettings -fill x -ipady 3\n" ,"ttk::frame $f.facesettings -relief groove -borderwidth 3\n" ,"ttk::frame $f.facesettings.title\n" ,"ttk::radiobutton $f.facesettings.title.choose -variable visoptions.fieldlinesstartarea \\\n" ,"-value face -text \"Startpoints on Face\"\n" ,"pack $f.facesettings.title.choose -side left\n" ,"pack $f.facesettings.title\n" ,"ttk::frame $f.facesettings.index\n" ,"ttk::label $f.facesettings.index.lab -text \"face index:\"\n" ,"ttk::label $f.facesettings.index.ent -text 1;\n" ,"pack $f.facesettings.index.lab $f.facesettings.index.ent -side left\n" ,"pack $f.facesettings.index\n" ,"pack $f.facesettings -fill x -ipady 3\n" ,"global visoptions.fieldlinesfilename\n" ,"ttk::frame $f.filesettings -relief groove -borderwidth 3\n" ,"ttk::frame $f.filesettings.title\n" ,"ttk::radiobutton $f.filesettings.title.choose -variable visoptions.fieldlinesstartarea \\\n" ,"-value file -text \"Startpoints from File\"\n" ,"pack $f.filesettings.title.choose -side left\n" ,"pack $f.filesettings.title\n" ,"ttk::frame $f.filesettings.sfn\n" ,"ttk::button $f.filesettings.sfn.bb -text \"Browse\" \\\n" ,"-command {\n" ,"set types {\n" ,"{ \"Netgen Fieldlines\" {.nef} }\n" ,"}\n" ,"set visoptions.fieldlinesfilename [tk_getOpenFile -filetypes $types -defaultextension \".nef\"]\n" ,"}\n" ,"ttk::entry $f.filesettings.sfn.fn -width 50 \\\n" ,"-textvariable visoptions.fieldlinesfilename\n" ,"pack $f.filesettings.sfn.bb $f.filesettings.sfn.fn -side left\n" ,"pack $f.filesettings.sfn\n" ,"pack $f.filesettings -fill x -ipady 3\n" ,"set g $w.nb.settings\n" ,"ttk::frame $g.linesettings -relief groove -borderwidth 3\n" ,"ttk::label $g.linesettings.title -text \"\\nLine Settings\\n\"\n" ,"ttk::frame $g.linesettings.length\n" ,"ttk::label $g.linesettings.length.lab -text \"rel. Length: \"\n" ,"ttk::spinbox $g.linesettings.length.sp -textvariable visoptions.fieldlineslength -width 6 -increment 0.1 -validate focus -validatecommand \"my_validatespinbox %W %P 5\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from 0.00001 -to 10000\n" ,"grid $g.linesettings.length.lab $g.linesettings.length.sp -sticky nw\n" ,"ttk::frame $g.linesettings.maxpoints\n" ,"ttk::label $g.linesettings.maxpoints.lab -text \"max. Points: \"\n" ,"ttk::spinbox $g.linesettings.maxpoints.sp -textvariable visoptions.fieldlinesmaxpoints -width 6 -increment 1 -validate focus -validatecommand \"my_validatespinbox %W %P 0\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from 0 -to 10000\n" ,"grid $g.linesettings.maxpoints.lab $g.linesettings.maxpoints.sp -sticky nw\n" ,"ttk::frame $g.linesettings.thick\n" ,"ttk::label $g.linesettings.thick.lab -text \"rel. Thickness: \"\n" ,"ttk::spinbox $g.linesettings.thick.sp -textvariable visoptions.fieldlinesthickness -width 6 -increment 0.001 -validate focus -validatecommand \"my_validatespinbox %W %P 6\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from 1e-10 -to 0.5\n" ,"grid $g.linesettings.thick.lab $g.linesettings.thick.sp -stick nw\n" ,"pack $g.linesettings.title $g.linesettings.length $g.linesettings.maxpoints $g.linesettings.thick\n" ,"pack $g.linesettings -fill x -ipady 3\n" ,"global visoptions.fieldlinestolerance\n" ,"ttk::frame $g.odesettings -relief groove -borderwidth 3\n" ,"ttk::label $g.odesettings.title -text \"\\nODE Settings\\n\"\n" ,"ttk::frame $g.odesettings.tol\n" ,"ttk::label $g.odesettings.tol.lab -text \"rel. Thickness: \"\n" ,"ttk::spinbox $g.odesettings.tol.sp -textvariable visoptions.fieldlinestolerance -width 6 -increment 0.01 -validate focus -validatecommand \"my_validatespinbox %W %P 5\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from 0.00001 -to 1\n" ,"grid $g.odesettings.tol.lab $g.odesettings.tol.sp -stick nw\n" ,"ttk::frame $g.odesettings.rktype\n" ,"ttk::label $g.odesettings.rktype.lab -text \"RK-Type \"\n" ,"ttk::menubutton $g.odesettings.rktype.but -menu $g.odesettings.rktype.menu -text \"\" -width 25\n" ,"menu $g.odesettings.rktype.menu -tearoff 0\n" ,"$g.odesettings.rktype.menu add command -label \"Euler, order 1\" -command \"set visoptions.fieldlinesrktype \\\"euler\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\"Euler,order 1\\\" \"\n" ,"$g.odesettings.rktype.menu add command -label \"Euler-Cauchy, order 2\" -command \"set visoptions.fieldlinesrktype \\\"eulercauchy\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\"Euler-Cauchy,order 2\\\" \"\n" ,"$g.odesettings.rktype.menu add command -label \"Simpson, order 3\" -command \"set visoptions.fieldlinesrktype \\\"simpson\\\" ;Ng_Vis_Set parameters; redraw;$g.odesettings.rktype.but configure -text \\\"Simpson,order 3\\\"\"\n" ,"$g.odesettings.rktype.menu add command -label \"classical Runge-Kutta, order 4\" -command \"set visoptions.fieldlinesrktype \\\"crungekutta\\\" ;Ng_Vis_Set parameters; redraw; $g.odesettings.rktype.but configure -text \\\"classical Runge-Kutta,order 4\\\"\"\n" ,"$g.odesettings.rktype.menu invoke \"classical Runge-Kutta, order 4\"\n" ,"grid $g.odesettings.rktype.lab $g.odesettings.rktype.but -sticky nw\n" ,"pack $g.odesettings.title $g.odesettings.tol $g.odesettings.rktype\n" ,"pack $g.odesettings -fill x -ipady 3\n" ,"ttk::frame $w.bu\n" ,"pack $w.bu -fill x -ipady 3\n" ,"ttk::button $w.bu.calc -text \"Build Fieldlines\" -command {\n" ,"if { ${visoptions.fieldlinesvecfunction} == \"none\" } {\n" ,"bgerror \"Please select the vector function first!\"\n" ,"} {\n" ,"set visoptions.drawfieldlines 1\n" ,"Ng_Vis_Set parameters\n" ,"Ng_BuildFieldLines\n" ,"redraw\n" ,"}\n" ,"}\n" ,"ttk::button $w.bu.help -text \"Help\" -command {\n" ,"if {[winfo exists .fieldlines_help] == 1} {\n" ,"wm withdraw .fieldlines_help\n" ,"wm deiconify .fieldlines_help\n" ,"focus .fieldlines_help\n" ,"} {\n" ,"toplevel .fieldlines_help\n" ,"set f [frame .fieldlines_help.ht]\n" ,"ttk::scrollbar $f.vsb -orient vertical -command [list $f.t yview]\n" ,"text $f.t -yscrollcommand [list $f.vsb set]\n" ,"grid $f.t -row 0 -column 0 -sticky nsew\n" ,"grid $f.vsb -row 0 -column 1 -sticky nsew\n" ,"grid columnconfigure $f 0 -weight 1\n" ,"grid rowconfigure $f 0 -weight 1\n" ,"set text $f.t\n" ,"$text configure -setgrid true -wrap word\n" ,"$text tag configure bold -font *-*-bold-*-*-*-*\n" ,"$text insert end \\\n" ,"\"Draw menu\\n \\n\" bold\n" ,"$text insert end \\\n" ,"\"Enable Fieldlines\\n To turn on and off the calculated fieldlines. (Has to be turned on to start the calculation)\\n\"\n" ,"$text insert end \\\n" ,"\"Num\\n Number of fieldlines to calculate. (May not be used exactly.)\"\n" ,"$text insert end \\\n" ,"\"Field dependent density\\n There will be more fieldline startpoints where the field is stronger\\n\\n\"\n" ,"$text insert end \\\n" ,"\"Animate periodic\\n (for quasistationary fields) The fieldlines of the different phase angles are animated.\\n ATTENTION: \\\"Fix Phase\\\" has to be turned off\\n\\n\"\n" ,"$text insert end \\\n" ,"\"Vector Function\\n The function fixing the direction of the lines\\n\\n\"\n" ,"$text insert end \\\n" ,"\"Fix Phase\\n (for quasistationary fields) Only calculate and draw fieldlines for one special phase angle.\\n\\n\"\n" ,"$text insert end \\\n" ,"\"Startpoints in Box\\n Set the startpoints inside the box \\[Pmin1,Pmax1\\] x \\[Pmin2,Pmax2\\] x \\[Pmin3,Pmax3\\]\\n\"\n" ,"$text insert end \\\n" ,"\" With the button \\\"Bounding Box\\\" the whole bounding box of the geometry is selected.\\n\\n\"\n" ,"$text insert end \\\n" ,"\"Startpoints on Face\\n All startpoints will be set on one face. This face is selected by double-clicking with the mouse.\\n\\n\"\n" ,"$text insert end \\\n" ,"\"Startpoints from File\\n The startpoint information will be read from the selected file.\\n The entries in the file can be as follows:\\n\"\n" ,"$text insert end \\\n" ,"\" point \\n set a (potential) startpoint\\n\"\n" ,"$text insert end \\\n" ,"\" line \\n set n (potential) startpoints on the line from (x1,y1,z1) to (x2,y2,z2)\\n\"\n" ,"$text insert end \\\n" ,"\" box \\n set n (potential) startpoints inside the box \\[x1,x2\\] x \\[y1,y2\\] x \\[z1,z2\\]\\n\"\n" ,"$text insert end \\\n" ,"\" ATTENTION: These are potential startpoints.\\n The total number of startpoints will be bounded by the \\\"Num\\\"-parameter.\\n \\n \\n \\n\"\n" ,"$text insert end \\\n" ,"\"Settings Menu\\n \\n\" bold\n" ,"$text insert end \\\n" ,"\"rel. Length\\n The maximal length of a fieldline relative to the diameter of the geometry.\\n\\n\"\n" ,"$text insert end \\\n" ,"\"max. Points\\n The maximum number of Runge-Kutta steps.\\n\\n\"\n" ,"$text insert end \\\n" ,"\"rel. Thickness\\n The thickness of the fieldlines relative to the diameter of the geometry.\\n\\n\"\n" ,"$text insert end \\\n" ,"\"rel. Tolerance\\n The tolerance for the step-length control of the Runge-Kutta method.\\n\\n\"\n" ,"$text insert end \\\n" ,"\"RK-Type\\n Which Runge-Kutta scheme to use\\n \\n \\n \\n\"\n" ,"$text insert end \\\n" ,"\"Button \\\"Build Fieldlines\\\"\\n\" bold\n" ,"$text insert end \\\n" ,"\" Build the fieldlines.\"\n" ,"$text configure -state disabled\n" ,"pack .fieldlines_help.ht -expand yes -fill both\n" ,"wm withdraw .fieldlines_help\n" ,"wm geom .fieldlines_help +300+200\n" ,"wm deiconify .fieldlines_help\n" ,"wm title .fieldlines_help \"Fieldlines Help\"\n" ,"focus .fieldlines_help\n" ,"}\n" ,"}\n" ,"ttk::button $w.bu.cancel -text \"Done\" -command \"destroy $w\"\n" ,"grid $w.bu.calc $w.bu.help $w.bu.cancel -sticky nw -padx 4\n" ,"grid anchor $w.bu center\n" ,"wm withdraw $w\n" ,"wm geom $w +200+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Fieldlines\"\n" ,"focus $w\n" ,"}\n" ,"global visoptions.fieldlinesstartface\n" ,"set f $w.nb.draw\n" ,"set visoptions.fieldlinesstartface [Ng_BCProp getactive]\n" ,"$f.facesettings.index.ent configure -text ${visoptions.fieldlinesstartface}\n" ,"}\n" ,"set visual_dialog_pop1 0\n" ,"set visual_dialog_pop2 0\n" ,"set visual_dialog_pop3 0\n" ,"set visual_dialog_pop4 0\n" ,"set visual_dialog_pop5 0\n" ,"set visual_dialog_pop6 0\n" ,"set visual_dialog_pop7 0\n" ,"proc visual_dialog { } {\n" ,"set w .visoptions_dlg\n" ,"global visual_dialog_pop1\n" ,"global visual_dialog_pop2\n" ,"global visual_dialog_pop3\n" ,"global visual_dialog_pop4\n" ,"global visual_dialog_pop5\n" ,"global visual_dialog_pop6\n" ,"global visual_dialog_pop7\n" ,"set visual_dialog_pop1 1\n" ,"set visual_dialog_pop2 1\n" ,"set visual_dialog_pop3 1\n" ,"set visual_dialog_pop4 1\n" ,"set visual_dialog_pop5 1\n" ,"set visual_dialog_pop6 1\n" ,"set visual_dialog_pop7 1\n" ,"if {[winfo exists .visoptions_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"ttk::frame $w.main\n" ,"pack $w.main -fill x\n" ,"set w $w.main\n" ,"ttk::frame $w.upperfr ;\n" ,"pack $w.upperfr -fill x;\n" ,"ttk::labelframe $w.upperfr.size -text \"Grid\" -relief groove -borderwidth 3\n" ,"ttk::entry $w.upperfr.size.ent -width 3 -textvariable visoptions.gridsize -validate focus -takefocus 0 -validatecommand \"popupcheckredraw visual_dialog_pop2;my_validate %W 0 200 %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop2\"\n" ,"ttk::scale $w.upperfr.size.sc -orient horizontal -length 100 -from 1 -to 200 -variable visoptions.gridsize\\\n" ,"-command \"roundscale $w.upperfr.size.sc 0;popupcheckredraw visual_dialog_pop2\"\n" ,"ttk::labelframe $w.upperfr.offsets -text \"x / y offsets\" -relief groove -borderwidth 3\n" ,"ttk::label $w.upperfr.offsets.xlab -text \"x\"\n" ,"ttk::label $w.upperfr.offsets.ylab -text \"y\"\n" ,"ttk::scale $w.upperfr.offsets.xoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.xoffset \\\n" ,"-command \"roundscale $w.upperfr.offsets.xoffset 2; popupcheckredraw visual_dialog_pop3\"\n" ,"ttk::scale $w.upperfr.offsets.yoffset -orient horizontal -length 100 -from 0 -to 1 -variable visoptions.yoffset \\\n" ,"-command \"roundscale $w.upperfr.offsets.yoffset 2; popupcheckredraw visual_dialog_pop4\"\n" ,"ttk::entry $w.upperfr.offsets.entx -width 4 -textvariable visoptions.xoffset -validate focus -takefocus 0 \\\n" ,"-validatecommand \"popupcheckredraw visual_dialog_pop3;my_validate %W 0 1 %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop3\"\n" ,"ttk::entry $w.upperfr.offsets.enty -width 4 -textvariable visoptions.yoffset -validate focus -takefocus 0 \\\n" ,"-validatecommand \"popupcheckredraw visual_dialog_pop4;my_validate %W 0 1 %P 2\" \\\n" ,"-invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop4\"\n" ,"pack $w.upperfr.size.sc $w.upperfr.size.ent -padx 4 -pady 12 -side left\n" ,"grid $w.upperfr.offsets.xoffset $w.upperfr.offsets.entx $w.upperfr.offsets.xlab -sticky nw -padx 4\n" ,"grid $w.upperfr.offsets.yoffset $w.upperfr.offsets.enty $w.upperfr.offsets.ylab -sticky nw -padx 4\n" ,"grid $w.upperfr.size $w.upperfr.offsets -sticky nw -pady 7 -padx 10\n" ,"grid anchor $w.upperfr center\n" ,"ttk::labelframe $w.deform -relief groove -borderwidth 3 -text \"Deformation settings\"\n" ,"ttk::checkbutton $w.deform.cb -text \"Deformation\" \\\n" ,"-variable visoptions.deformation \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::label $w.deform.l -text \"Scale: \"\n" ,"ttk::spinbox $w.deform.sc1 -from 0 -to 1e99 -textvariable visoptions.scaledeform1 -width 5 \\\n" ,"-command { Ng_Vis_Set parameters; redraw } \\\n" ,"-validate focusout -validatecommand { Ng_Vis_Set parameters; redraw; string is double %P } \\\n" ,"-invalidcommand { puts \"invalid value, %P %s\"; set visoptions.scaledeform1 1; }\n" ,"ttk::scale $w.deform.sc2 -orient horizontal -length 100 -from 0 -to 1 \\\n" ,"-variable visoptions.scaledeform2 \\\n" ,"-command { popupcheckredraw visual_dialog_pop5 }\n" ,"pack $w.deform -fill x -ipady 2 -pady 4 -ipady 3\n" ,"grid $w.deform.cb $w.deform.l $w.deform.sc1 $w.deform.sc2 -sticky nw -padx 4;\n" ,"grid anchor $w.deform center\n" ,"grid columnconfigure $w.deform 0 -pad 20\n" ,"grid columnconfigure $w.deform 2 -pad 20\n" ,"ttk::labelframe $w.as -relief groove -borderwidth 3 -text \"Scaling options\"\n" ,"ttk::checkbutton $w.as.autoscale -text \"Autoscale\" \\\n" ,"-variable visoptions.autoscale \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::label $w.as.lmin -text \"Min-value\"\n" ,"ttk::spinbox $w.as.smin -textvariable visoptions.mminval -width 5 -validate focus \\\n" ,"-validatecommand \"my_validatespinbox %W %P 10\" \\\n" ,"-command \"Ng_Vis_Set parameters; redraw;\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W\" -from -1e10 -to 1e10 -increment 0.001\n" ,"ttk::label $w.as.lmax -text \"Max-value\"\n" ,"ttk::spinbox $w.as.smax -textvariable visoptions.mmaxval -width 5 -validate focus \\\n" ,"-validatecommand \"Ng_Vis_Set parameters; redraw;my_validatespinbox %W %P 10\" \\\n" ,"-command \"Ng_Vis_Set parameters; redraw;\" \\\n" ,"-invalidcommand \"my_invalidspinbox %W;Ng_Vis_Set parameters; redraw\" -from -1e10 -to 1e10 -increment 0.001\n" ,"pack $w.as -fill x -pady 5 -ipady 3\n" ,"grid $w.as.autoscale $w.as.lmin $w.as.smin $w.as.lmax $w.as.smax -sticky nw -padx 4\n" ,"grid columnconfigure $w.as 0 -pad 20\n" ,"grid columnconfigure $w.as 2 -pad 20\n" ,"grid anchor $w.as center\n" ,"ttk::frame $w.iso; \n" ,"pack $w.iso -anchor center;\n" ,"ttk::labelframe $w.iso.cb -relief groove -borderwidth 3 -text \"Iso lines / surfaces\"\n" ,"pack $w.iso.cb -side left -pady 7 -fill y\n" ,"ttk::checkbutton $w.iso.cb.isolines -text \"Iso-lines\" \\\n" ,"-variable visoptions.isolines \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::checkbutton $w.iso.cb.isosurf -text \"Iso-Surface\" \\\n" ,"-variable visoptions.isosurf \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::label $w.iso.cb.numisol -text \"amount\"\n" ,"ttk::scale $w.iso.cb.numiso -orient horizontal -length 100 -from 2 -to 50 \\\n" ,"-variable visoptions.numiso \\\n" ,"-command \"roundscale $w.iso.cb.numiso 0;popupcheckredraw visual_dialog_pop6\"\n" ,"ttk::entry $w.iso.cb.entry -textvariable visoptions.numiso -width 3 \\\n" ,"-validate focus -validatecommand \"popupcheckredraw visual_dialog_pop6;\\\n" ,"my_validate %W [$w.iso.cb.numiso cget -from] [$w.iso.cb.numiso cget -to] %P 0\" \\\n" ,"-invalidcommand \"my_invalid %W;popupcheckredraw visual_dialog_pop6\"\n" ,"grid $w.iso.cb.isolines $w.iso.cb.numisol $w.iso.cb.entry -sticky nw -padx 4\n" ,"grid $w.iso.cb.isosurf -sticky nw -padx 4\n" ,"grid $w.iso.cb.numiso -sticky nw -padx 4 -columnspan 2 -column 1 -row 1\n" ,"ttk::labelframe $w.iso.subdiv -text \"Subdivision\" -relief groove -borderwidth 3\n" ,"ttk::radiobutton $w.iso.subdiv.zero -text \"0\" -variable visoptions.subdivisions -value 0 \\\n" ,"-command {\n" ,"Ng_Vis_Set parameters; redraw;\n" ,"}\n" ,"ttk::radiobutton $w.iso.subdiv.one -text \"1\" -variable visoptions.subdivisions -value 1 \\\n" ,"-command {\n" ,"Ng_Vis_Set parameters; redraw;\n" ,"}\n" ,"ttk::radiobutton $w.iso.subdiv.two -text \"2\" -variable visoptions.subdivisions -value 2 \\\n" ,"-command {\n" ,"Ng_Vis_Set parameters; redraw;\n" ,"}\n" ,"ttk::radiobutton $w.iso.subdiv.three -text \"3\" -variable visoptions.subdivisions -value 3 \\\n" ,"-command {\n" ,"Ng_Vis_Set parameters; redraw;\n" ,"}\n" ,"ttk::radiobutton $w.iso.subdiv.four -text \"4\" -variable visoptions.subdivisions -value 4 \\\n" ,"-command {\n" ,"Ng_Vis_Set parameters; redraw;\n" ,"}\n" ,"ttk::radiobutton $w.iso.subdiv.five -text \"5\" -variable visoptions.subdivisions -value 5 \\\n" ,"-command {\n" ,"Ng_Vis_Set parameters; redraw;\n" ,"}\n" ,"ttk::label $w.iso.subdiv.text -text \"subdivision\"\n" ,"pack $w.iso.subdiv -side right -fill y -padx 4 -pady 7\n" ,"grid $w.iso.subdiv.zero $w.iso.subdiv.one $w.iso.subdiv.two $w.iso.subdiv.three $w.iso.subdiv.four $w.iso.subdiv.five\n" ,"grid anchor $w.iso.subdiv center\n" ,"ttk::labelframe $w.redraw -relief groove -borderwidth 3 -text \"Auto-redraw\"\n" ,"ttk::checkbutton $w.redraw.auto -text \"Auto-redraw after (sec)\" \\\n" ,"-variable visoptions.autoredraw\n" ,"ttk::spinbox $w.redraw.val -textvariable visoptions.autoredrawtime -from 0 -to 100 -width 3\n" ,"pack $w.redraw -fill x -ipady 3 -pady 7\n" ,"grid $w.redraw.auto $w.redraw.val -sticky nw\n" ,"grid anchor $w.redraw center\n" ,"ttk::labelframe $w.lowerframe -text \"Additional viewing options\" -relief groove -borderwidth 3\n" ,"pack $w.lowerframe -fill x\n" ,"set w $w.lowerframe\n" ,"ttk::frame $w.f1\n" ,"set f [ttk::frame $w.f1.clipsol]\n" ,"pack $f -anchor e\n" ,"menu $f.m\n" ,"ttk::menubutton $f.b -menu $f.m -width 12\n" ,"ttk::label $f.l -text \"Clipping Plane Sol: \"\n" ,"global visoptions.clipsolution\n" ,"set clipsollabs(none) \"None\"\n" ,"set clipsollabs(scal) \"Scalar Function\"\n" ,"set clipsollabs(vec) \"Vector Function\"\n" ,"foreach i { none scal vec } {\n" ,"set textval $clipsollabs($i)\n" ,"$f.m add command -label \"$textval\" -command \\\n" ,"\"$f.b configure -text \\\"$textval\\\" ; set visoptions.clipsolution $i ; Ng_Vis_Set parameters ; redraw \"\n" ,"}\n" ,"pack $f.b $f.l -side right\n" ,"$f.m invoke $clipsollabs(${visoptions.clipsolution})\n" ,"set f [ttk::frame $w.f1.scalfun]\n" ,"pack $f -anchor e\n" ,"menu $f.m\n" ,"ttk::menubutton $f.b -menu $f.m -width 12\n" ,"ttk::label $f.l -text \"Scalar Function: \"\n" ,"set scalentries [list none None]\n" ,"for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n" ,"set fname [Ng_Vis_Field getfieldname $i]\n" ,"set fcomp [Ng_Vis_Field getfieldcomponents $i]\n" ,"if { $fcomp == 1 } {\n" ,"lappend scalentries $fname:1 $fname\n" ,"} {\n" ,"for { set j 1 } { $j <= $fcomp } { incr j } {\n" ,"lappend scalentries $fname:$j \"$fname ($j)\"\n" ,"}\n" ,"lappend scalentries $fname:0 \"func ($fname)\"\n" ,"}\n" ,"}\n" ,"global visoptions.scalfunction\n" ,"foreach { name textval } $scalentries {\n" ,"$f.m add command -label \"$textval\" -command \\\n" ,"\"$f.b configure -text \\\"$textval\\\" ; set visoptions.scalfunction $name ; Ng_Vis_Set parameters ; redraw ; \"\n" ,"}\n" ,"pack $f.b $f.l -side right\n" ,"foreach { name textval } $scalentries {\n" ,"if { ${visoptions.scalfunction} == $name } {\n" ,"$f.m invoke $textval\n" ,"}\n" ,"}\n" ,"set f [ttk::frame $w.f1.vecfun]\n" ,"pack $f -anchor e\n" ,"menu $f.m\n" ,"ttk::menubutton $f.b -menu $f.m -width 12\n" ,"ttk::label $f.l -text \"Vector Function: \"\n" ,"set vecentries [list none None]\n" ,"for { set i 1 } { $i <= [Ng_Vis_Field getnfieldnames] } { incr i } {\n" ,"set fname [Ng_Vis_Field getfieldname $i]\n" ,"set fcomp [Ng_Vis_Field getfieldcomponents $i]\n" ,"set iscomplex [Ng_Vis_Field iscomplex $i]\n" ,"set sdim [Ng_Vis_Field getdimension]\n" ,"if { $iscomplex == 1 } { set fcomp [expr $fcomp / 2] }\n" ,"if { ($fcomp == $sdim) || ($fcomp == 3) } {\n" ,"lappend vecentries $fname $fname\n" ,"}\n" ,"}\n" ,"global visoptions.vecfunction\n" ,"foreach { name textval } $vecentries {\n" ,"$f.m add command -label \"$textval\" -command \\\n" ,"\"$f.b configure -text \\\"$textval\\\" ; set visoptions.vecfunction $name ; Ng_Vis_Set parameters ; redraw ; \"\n" ,"}\n" ,"pack $f.b $f.l -side right\n" ,"foreach { name textval } $vecentries {\n" ,"if { ${visoptions.vecfunction} == $name } {\n" ,"$f.m invoke $textval\n" ,"}\n" ,"}\n" ,"set f [ttk::frame $w.f1.evaluate]\n" ,"pack $f -anchor e\n" ,"menu $f.m\n" ,"ttk::menubutton $f.b -menu $f.m -width 12\n" ,"ttk::label $f.l -text \"Evaluate: \"\n" ,"global visoptions.evaluate\n" ,"set evallabs(abs) \"| |\"\n" ,"set evallabs(abstens) \"|tensor|\"\n" ,"set evallabs(mises) \"Mises\"\n" ,"set evallabs(main) \"Main\"\n" ,"foreach i { abs abstens mises main } {\n" ,"set textval $evallabs($i)\n" ,"$f.m add command -label \"$textval\" -command \\\n" ,"\"$f.b configure -text \\\"$textval\\\" ; set visoptions.evaluate $i ; \"\n" ,"}\n" ,"pack $f.b $f.l -side right\n" ,"$f.m invoke $evallabs(${visoptions.evaluate})\n" ,"pack [ttk::frame $w.f1.multidim] -fill x\n" ,"set f [ttk::frame $w.f1.multidim.f]\n" ,"pack $f -anchor e\n" ,"ttk::label $f.l1 -text \"multidim-component: \"\n" ,"ttk::spinbox $f.sb1 -from 0 -to 1e99 -textvariable visoptions.multidimcomponent -width 3 \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"pack $f.l1 $f.sb1 -side left\n" ,"ttk::frame $w.fcb\n" ,"grid $w.f1 $w.fcb -sticky nw -padx 7 -ipady 3\n" ,"grid anchor $w center\n" ,"ttk::frame $w.fcb.cb\n" ,"pack $w.fcb.cb\n" ,"ttk::checkbutton $w.fcb.cb.showsurfsolution -text \"Draw Surface Vectors\" \\\n" ,"-variable visoptions.showsurfacesolution \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::checkbutton $w.fcb.cb.showcurves -text \"Show Curves\" \\\n" ,"-variable visoptions.drawpointcurves \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::checkbutton $w.fcb.cb.imaginary -text \"Imaginary Part\" \\\n" ,"-variable visoptions.imaginary \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::checkbutton $w.fcb.cb.logscale -text \"Log Scale\" \\\n" ,"-variable visoptions.logscale \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::checkbutton $w.fcb.cb.invcolor -text \"Inverse Color\" \\\n" ,"-variable visoptions.invcolor \\\n" ,"-command { Ng_Vis_Set parametersrange; redraw }\n" ,"ttk::frame $w.fcb.cb.texframe\n" ,"ttk::checkbutton $w.fcb.cb.texframe.usetexture -text \"Use Textures (\" \\\n" ,"-variable visoptions.usetexture \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::checkbutton $w.fcb.cb.texframe.lintexture -text \"Linear )\" \\\n" ,"-variable visoptions.lineartexture \\\n" ,"-command { Ng_Vis_Set parametersrange; redraw }\n" ,"ttk::checkbutton $w.fcb.cb.lineartexture -text \"Use Linear Texture\" \\\n" ,"-variable visoptions.lineartexture \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"scale $w.numcols -orient horizontal -length 100 -from 0 -to 50 \\\n" ,"-resolution 1 \\\n" ,"-variable visoptions.numtexturecols \\\n" ,"-command { popupcheckredraw visual_dialog_pop1 }\n" ,"ttk::checkbutton $w.fcb.cb.showclipsolution -text \"Draw Clipping Plane Solution\" \\\n" ,"-variable visoptions.showclipsolution \\\n" ,"-command { Ng_Vis_Set parameters; redraw }\n" ,"ttk::checkbutton $w.fcb.cb.redrawperiodic -text \"Animate periodic\" \\\n" ,"-variable visoptions.redrawperiodic \\\n" ,"-command {\n" ,"redrawperiodic\n" ,"Ng_Vis_Set parameters;\n" ,"redraw\n" ,"}\n" ,"grid $w.fcb.cb.showsurfsolution -sticky nw\n" ,"grid $w.fcb.cb.showcurves -sticky nw\n" ,"grid $w.fcb.cb.imaginary -sticky nw\n" ,"grid $w.fcb.cb.logscale -sticky nw\n" ,"grid $w.fcb.cb.texframe -sticky nw\n" ,"grid $w.fcb.cb.invcolor -sticky nw\n" ,"grid $w.fcb.cb.redrawperiodic -sticky nw\n" ,"pack $w.fcb.cb.texframe.usetexture $w.fcb.cb.texframe.lintexture -side left -expand yes\n" ,"set w .visoptions_dlg.main\n" ,"ttk::frame $w.bu;\n" ,"pack $w.bu -pady 5 -padx 4\n" ,"ttk::button $w.bu.showsol -text \"Show Solution\" -command {\n" ,"set selectvisual solution\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"}\n" ,"ttk::button $w.bu.clipping -text \"Clipping\" -command {\n" ,"clippingdialog;\n" ,"}\n" ,"ttk::button $w.bu.fieldlines -text \"Fieldlines\" -command {\n" ,"fieldlinesdialog;\n" ,"}\n" ,"ttk::button $w.bu.lineplot -text \"2D Lineplot\" -command {\n" ,"lineplotdialog;\n" ,"}\n" ,"ttk::button $w.bu.done -text \"Close\" -command {\n" ,"destroy .visoptions_dlg\n" ,"}\n" ,"pack $w.bu.showsol $w.bu.clipping $w.bu.fieldlines $w.bu.lineplot $w.bu.done -side left -expand yes\n" ,"set w .visoptions_dlg\n" ,"wm withdraw $w\n" ,"wm geom $w +100+100\n" ,"wm deiconify $w\n" ,"wm title $w \"Visualization\"\n" ,"}\n" ,"}\n" ,"}\n" ,"catch { set sockets.serverport 0\n" ,"set sockets.serverhost \"localhost\"\n" ,"set sockets.serverlistbox 0\n" ,"set sockets.queuelistbox 0\n" ,"set sockets.currentjoblistbox 0\n" ,"set sockets.answerlistbox 0\n" ,"set sockets.myidlabel -1\n" ,"proc updateserverlist { } {\n" ,"global sockets.serverlistbox\n" ,"set retval [Ng_Socket getserverlist]\n" ,"${sockets.serverlistbox} delete 0 end\n" ,"for {set i 0} {$i < [llength $retval]} {incr i 3} {\n" ,"${sockets.serverlistbox} insert end \\\n" ,"[format \"%-16s %6i %6i\" [lindex $retval $i] [lindex $retval [expr $i+1]] [lindex $retval [expr $i+2]]]\n" ,"}\n" ,"}\n" ,"proc clientsocketdialog { } {\n" ,"set w .clientsock_dlg\n" ,"if {[winfo exists .clientsock_dlg] == 1} {\n" ,"wm withdraw $w\n" ,"wm deiconify $w\n" ,"focus $w\n" ,"} {\n" ,"toplevel $w\n" ,"global sockets.serverhost\n" ,"global sockets.serverport\n" ,"ttk::frame $w.general\n" ,"ttk::frame $w.host\n" ,"ttk::label $w.host.lab -text \"Serverhost: \"\n" ,"ttk::entry $w.host.name -width 30 -textvariable sockets.serverhost\n" ,"pack $w.host.lab $w.host.name -side left\n" ,"pack $w.host\n" ,"ttk::frame $w.ports\n" ,"ttk::label $w.ports.lab1 -text \"Serverport: \"\n" ,"ttk::entry $w.ports.statport -width 6 -textvariable sockets.serverport\n" ,"pack $w.ports.lab1 $w.ports.statport -side left\n" ,"pack $w.ports\n" ,"ttk::frame $w.listboxes\n" ,"ttk::frame $w.listboxes.choosesocketframe\n" ,"tixScrolledListBox $w.listboxes.choosesocketframe.choosesocket -scrollbar auto\n" ,"global sockets.serverlistbox\n" ,"set sockets.serverlistbox [$w.listboxes.choosesocketframe.choosesocket subwidget listbox]\n" ,"${sockets.serverlistbox} configure -width 35\n" ,"${sockets.serverlistbox} configure -selectmode browse\n" ,"${sockets.serverlistbox} configure -exportselection false\n" ,"ttk::button $w.addserver -text \"Add ServerSocket\" -command {\n" ,"Ng_Socket addserver ${sockets.serverport} ${sockets.serverhost}\n" ,"updateserverlist\n" ,"}\n" ,"pack $w.addserver\n" ,"ttk::label $w.linefeed -text \"\\n\"\n" ,"pack $w.linefeed\n" ,"ttk::frame $w.clientidframe\n" ,"ttk::label $w.clientidframe.lab -text \"Client ID: \";\n" ,"global sockets.myidlabel\n" ,"ttk::entry $w.clientidframe.val -width 5 -textvariable sockets.myidlabel\n" ,"ttk::button $w.clientidframe.but -text \"Set\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"Ng_Socket setid $opserver ${sockets.myidlabel}\n" ,"updateserverlist\n" ,"}\n" ,"}\n" ,"pack $w.clientidframe.lab $w.clientidframe.val $w.clientidframe.but -side left\n" ,"pack $w.clientidframe\n" ,"ttk::label $w.listboxes.choosesocketframe.chooselab -text [format \"\\n\\n%-16s %6s %6s \" Host Socket MyID ]\n" ,"pack $w.listboxes.choosesocketframe.chooselab\n" ,"pack $w.listboxes.choosesocketframe.choosesocket\n" ,"ttk::frame $w.listboxes.choosesocketframe.serverbuttons\n" ,"ttk::button $w.listboxes.choosesocketframe.serverbuttons.save -text \"Save\" -command {\n" ,"Ng_Socket saveserverlist\n" ,"}\n" ,"global sockets.serverlist\n" ,"Ng_Socket loadserverlist\n" ,"updateserverlist\n" ,"ttk::button $w.listboxes.choosesocketframe.serverbuttons.delete -text \"Delete\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"Ng_Socket deletesocket [lindex $opsel 0]\n" ,"updateserverlist\n" ,"}\n" ,"}\n" ,"pack $w.listboxes.choosesocketframe.serverbuttons.save $w.listboxes.choosesocketframe.serverbuttons.delete -side left\n" ,"pack $w.listboxes.choosesocketframe.serverbuttons\n" ,"ttk::frame $w.listboxes.statusframe\n" ,"ttk::label $w.listboxes.statusframe.statuslabel1 -text \"\\n\\njobqueue\"\n" ,"tixScrolledListBox $w.listboxes.statusframe.queuestatus -scrollbar auto\n" ,"ttk::label $w.listboxes.statusframe.statuslabel2 -text \"\\ncurrent job\"\n" ,"tixScrolledListBox $w.listboxes.statusframe.currentjobstatus -scrollbar auto\n" ,"ttk::label $w.listboxes.statusframe.statuslabel3 -text \"\\nanswers\"\n" ,"tixScrolledListBox $w.listboxes.statusframe.answers -scrollbar auto\n" ,"global sockets.queuelistbox\n" ,"global sockets.currentjoblistbox\n" ,"global sockets.answerlistbox\n" ,"set sockets.queuelistbox [$w.listboxes.statusframe.queuestatus subwidget listbox]\n" ,"set sockets.currentjoblistbox [$w.listboxes.statusframe.currentjobstatus subwidget listbox]\n" ,"set sockets.answerlistbox [$w.listboxes.statusframe.answers subwidget listbox]\n" ,"${sockets.queuelistbox} configure -width 50\n" ,"${sockets.queuelistbox} configure -height 5\n" ,"${sockets.queuelistbox} configure -selectmode browse\n" ,"${sockets.queuelistbox} configure -exportselection false\n" ,"${sockets.currentjoblistbox} configure -width 50\n" ,"${sockets.currentjoblistbox} configure -height 1\n" ,"${sockets.currentjoblistbox} configure -selectmode browse\n" ,"${sockets.currentjoblistbox} configure -exportselection false\n" ,"${sockets.answerlistbox} configure -width 50\n" ,"${sockets.answerlistbox} configure -height 5\n" ,"${sockets.answerlistbox} configure -selectmode browse\n" ,"${sockets.answerlistbox} configure -exportselection false\n" ,"ttk::button $w.listboxes.statusframe.updatebutton -text \"Update\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [Ng_Socket sendqueuestatus $opserver]\n" ,"${sockets.queuelistbox} delete 0 end\n" ,"if {[lindex $retval 0] > 0} {\n" ,"${sockets.queuelistbox} insert end [format \"Blocked for user %i\" [lindex $retval 0]]\n" ,"} {\n" ,"${sockets.queuelistbox} insert end \"Not blocked\"\n" ,"}\n" ,"for {set i 2} {$i < [expr 2*[lindex $retval 1]+2]} {incr i 2} {\n" ,"${sockets.queuelistbox} insert end [format \"client %i, command %s\" [lindex $retval $i] [lindex $retval [expr $i+1]]]\n" ,"}\n" ,"${sockets.answerlistbox} delete 0 end\n" ,"for {set i [expr 2*[lindex $retval 1]+3]} {$i < [llength $retval]} {incr i 2} {\n" ,"${sockets.answerlistbox} insert end [format \"client %i, command %s\" [lindex $retval $i] [lindex $retval [expr $i+1]]]\n" ,"}\n" ,"${sockets.currentjoblistbox} delete 0 end\n" ,"set retval [Ng_Socket sendjobstatus $opserver]\n" ,"if {[lindex $retval 0] != 0} {\n" ,"${sockets.currentjoblistbox} insert end [format \"client %i, command %s: %s\" [lindex $retval 0] [lindex $retval 1] [lrange $retval 2 end]]\n" ,"}\n" ,"}\n" ,"}\n" ,"pack $w.listboxes.statusframe.statuslabel1 $w.listboxes.statusframe.queuestatus \\\n" ,"$w.listboxes.statusframe.statuslabel2 $w.listboxes.statusframe.currentjobstatus \\\n" ,"$w.listboxes.statusframe.statuslabel3 $w.listboxes.statusframe.answers \\\n" ,"$w.listboxes.statusframe.updatebutton\n" ,"pack $w.listboxes.choosesocketframe $w.listboxes.statusframe -side left\n" ,"pack $w.listboxes\n" ,"ttk::label $w.lab1 -text \"\\n\"\n" ,"pack $w.lab1\n" ,"ttk::frame $w.buttons1\n" ,"ttk::frame $w.buttons2\n" ,"ttk::button $w.buttons1.getid -text \"Get ID\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [Ng_Socket getid $opserver]\n" ,"updateserverlist\n" ,"set sockets.myidlabel $retval\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons1.killjob -text \"Kill Cur. Job\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"Ng_Socket killcurrentjob $opserver\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons2.sendmesh -text \"Send Mesh\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [Ng_Socket sendmesh $opserver]\n" ,"set sockets.meshsent 1\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons2.sendpde -text \"Send PDE\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [NGS_Socket sendpdefile $opserver]\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons2.solvepde -text \"Solve PDE\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [NGS_Socket solvepde $opserver]\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons2.writesol -text \"Write Solution\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [NGS_Socket writesolution $opserver]\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons2.sendsol -text \"Receive Solution\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [NGS_Socket sendsolution $opserver]\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons1.blockserver -text \"Block Server\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [Ng_Socket blockserver $opserver]\n" ,"}\n" ,"}\n" ,"ttk::button $w.buttons1.unblockserver -text \"UnBlock Server\" -command {\n" ,"set opsel [${sockets.serverlistbox} curselection]\n" ,"if {[llength $opsel] > 0} {\n" ,"set opserver [lindex $opsel 0]\n" ,"set retval [Ng_Socket unblockserver $opserver]\n" ,"}\n" ,"}\n" ,"pack $w.buttons1.getid $w.buttons1.blockserver $w.buttons1.unblockserver $w.buttons1.killjob -side left\n" ,"pack $w.buttons2.sendmesh $w.buttons2.sendpde $w.buttons2.solvepde $w.buttons2.writesol $w.buttons2.sendsol -side left\n" ,"pack $w.buttons1 $w.buttons2\n" ,"wm withdraw $w\n" ,"wm geom $w +200+200\n" ,"wm deiconify $w\n" ,"wm title $w \"Client Socket\"\n" ,"focus .options_dlg\n" ,"}\n" ,"}\n" ,"}\n" ,"catch { source ${ngdir}/acis.tcl }\n" ,"set zugstange 0\n" ,"catch { source ${ngdir}/trafo/menu.tcl }\n" ,"setgranularity ${meshoptions.fineness}\n" ,"Ng_SetMeshingParameters\n" ,"Ng_SetVisParameters\n" ,"Ng_SetDebugParameters\n" ,"Ng_STLDoctor\n" ,"Ng_GeometryOptions set\n" ,"if { $hasocc == \"yes\" } {\n" ,"Ng_SetOCCVisParameters\n" ,"}\n" ,"if { $batchmode != \"defined\" } {\n" ,"catch {\n" ,"wm protocol . WM_DELETE_WINDOW { .ngmenu.file invoke \"Quit\" }\n" ,"wm deiconify .\n" ,"}\n" ,"}\n" ,"set trafoapp 0\n" ,"catch { source ${ngdir}/trafoapp/trafoapp.tcl }\n" ,"set geofilename [Ng_GetCommandLineParameter geofile]\n" ,"if { $geofilename != \"undefined\" &&\n" ,"[info exists trafo] == 0 && $zugstange == 0} {\n" ,"if { [ catch { Ng_LoadGeometry $geofilename } errstring] == 0 } {\n" ,"if { $batchmode != \"defined\" } {\n" ,"AddRecentFile $geofilename\n" ,"}\n" ,"Ng_ParseGeometry\n" ,"if { $batchmode != \"defined\" } {\n" ,"set selectvisual geometry\n" ,"Ng_SetVisParameters\n" ,"redraw\n" ,"wm title . [concat \"$progname - \" $geofilename]\n" ,"}\n" ,"set dirname [file dirname $geofilename]\n" ,"set basefilename [file tail [file rootname $geofilename]]\n" ,"} {\n" ,"puts \"Problem with input file:\"\n" ,"puts \"$errstring\"\n" ,"}\n" ,"}\n" ,"set cnt 0\n" ,"foreach { gran } { verycoarse coarse moderate fine veryfine } {\n" ,"set cnt [expr $cnt + 1]\n" ,"if { [Ng_GetCommandLineParameter $gran] == \"defined\" } {\n" ,"set meshoptions.fineness $cnt\n" ,"setgranularity ${meshoptions.fineness}\n" ,"}\n" ,"}\n" ,"set meshfilename [Ng_GetCommandLineParameter meshfile]\n" ,"if { $meshfilename == \"undefined\" } {\n" ,"set meshfilename out.mesh\n" ,"}\n" ,"set meshfiletype [Ng_GetCommandLineParameter meshfiletype]\n" ,"if { $meshfiletype == \"undefined\" } {\n" ,"set meshfiletype netgen\n" ,"}\n" ,"set inputmeshfilename [Ng_GetCommandLineParameter inputmeshfile]\n" ,"set mergemeshfilename [Ng_GetCommandLineParameter mergefile]\n" ,"set meshsizefilename [Ng_GetCommandLineParameter meshsizefile]\n" ,"if { $meshsizefilename != \"undefined\" } {\n" ,"set options.meshsizefilename $meshsizefilename\n" ,"}\n" ,"set refinementfilename [Ng_GetCommandLineParameter refinementfile]\n" ,"if { $batchmode == \"defined\" && $solvemode != \"defined\"} {\n" ,"set options.parthread 0\n" ,"if { $shellmode == \"undefined\" } {\n" ,"set selectvisual mesh\n" ,"Ng_SetVisParameters\n" ,"set meshsize [Ng_GetCommandLineParameter meshsize]\n" ,"if {$meshsize != \"undefined\"} { set options.meshsize $meshsize }\n" ,"if { $inputmeshfilename == \"undefined\" } {\n" ,"Ng_GenerateMesh ${meshoptions.firststep} ${meshoptions.laststep}\n" ,"} else {\n" ,"Ng_LoadMesh $inputmeshfilename\n" ,"if { $mergemeshfilename != \"undefined\" } {\n" ,"Ng_MergeMesh $mergemeshfilename\n" ,"}\n" ,"}\n" ,"if { $refinementfilename != \"undefined\" } {\n" ,"Ng_Bisect $refinementfilename\n" ,"}\n" ,"if { $meshfiletype == \"netgen\" } {\n" ,"Ng_SaveMesh $meshfilename\n" ,"} else {\n" ,"if { [catch { Ng_ExportMesh $meshfilename $meshfiletype } ] == 1 } {\n" ,"puts \"Unknown file format $meshfiletype\"\n" ,"}\n" ,"}\n" ,"Ng_Exit;\n" ,"exit\n" ,"} else {\n" ,"set code [catch { \n" ,"proc dotest {} {\n" ,"source ngtest.tcl\n" ,"}\n" ,"proc Ng_RunShell {} {\n" ,"puts \"Wellcome to NG Shell mode\"\n" ,"set line 1\n" ,"while { 1 } {\n" ,"puts -nonewline \"$line: \"\n" ,"flush stdout\n" ,"set cmdline [gets stdin]\n" ,"if { [catch $cmdline errcode] } {\n" ,"puts \"$errcode\"\n" ,"}\n" ,"incr line 1\n" ,"}\n" ,"}\n" ,"proc Ng_PrintCmdIndex { } {\n" ,"global cmdindex\n" ,"foreach { lst } $cmdindex {\n" ,"puts $lst\n" ,"}\n" ,"}\n" ,"proc Ng_PrintHlpIndex { } {\n" ,"global hlpindex\n" ,"global secindex\n" ,"foreach {sec} $secindex {\n" ,"puts \"\\n * $sec:\"\n" ,"foreach {lst} $hlpindex {\n" ,"if {$sec == [lindex $lst 1]} {\n" ,"puts \" * [lindex $lst 2]: [lindex $lst 3]\"\n" ,"}\n" ,"}\n" ,"}\n" ,"}\n" ,"proc Ng_RegisterCmd { cmd section syntax {help \"\"} } {\n" ,"global hlpindex\n" ,"global cmdindex\n" ,"global secindex\n" ,"puts \"register command $cmd\"\n" ,"if { [lsearch $cmdindex cmd] != -1 } {\n" ,"puts \"command '$cmd' already defined\"\n" ,"} else {\n" ,"lappend cmdindex $cmd\n" ,"lappend hlpindex [list $cmd $section $syntax $help]\n" ,"if {[lsearch $secindex $section]==-1} {\n" ,"lappend secindex $section\n" ,"}\n" ,"}\n" ,"}\n" ,"Ng_RegisterCmd \"exit\" \"general\" \"exit\" \"exit Netgen shell mode\"\n" ,"proc nghelp { {sec \"\"} } {\n" ,"global secindex\n" ,"global hlpindex\n" ,"global cmdindex\n" ,"if { $sec == \"\" } {\n" ,"Ng_PrintHlpIndex\n" ,"puts \"\\n type help 'section'\\n\"\n" ,"return\n" ,"}\n" ,"if { [lsearch $secindex $sec] != -1} {\n" ,"foreach {lst} $hlpindex {\n" ,"if {[lindex $lst 1] == $sec } {\n" ,"puts \" * [lindex $lst 2]: [lindex $lst 3]\"\n" ,"}\n" ,"}\n" ,"return\n" ,"}\n" ,"set ind [lsearch $cmdindex $sec]\n" ,"if {$ind != -1} {\n" ,"set lst [lindex $hlpindex $ind]\n" ,"puts \" * [lindex $lst 2]: [lindex $lst 3]\"\n" ,"return\n" ,"}\n" ,"puts \" unknown section or command $sec\"\n" ,"}\n" ,"set ngtimer 0\n" ,"proc nggettimer {} {\n" ,"return [clock clicks -milliseconds]\n" ,"}\n" ,"proc ngtic {} {\n" ,"set ::ngtimer [nggettimer]\n" ,"}\n" ,"proc ngtoc { {logfile stdout} } {\n" ,"set end [nggettimer]\n" ,"set tim [expr ($end - $::ngtimer)/1000.0]\n" ,"puts $logfile \"$tim s\"\n" ,"}\n" ,"proc ngloadgeometry { fname } {\n" ,"if { ![file exists $fname] } {\n" ,"puts \"error: file $fname does not exist\"\n" ,"} else {\n" ,"set err [catch {Ng_LoadGeometry $fname}]\n" ,"if {$err != 0} {\n" ,"puts \"error: loading geometry failed\"\n" ,"}\n" ,"}\n" ,"}\n" ,"Ng_RegisterCmd \"ngloadgeometry\" \"netgen\" \"ngloadgeometry \" \"load geometry file\"\n" ,"proc ngparsegeometry {} {\n" ,"set err [catch {Ng_ParseGeometry}]\n" ,"if {$err} {\n" ,"puts \"error: parsing geometry failed\"\n" ,"}\n" ,"}\n" ,"Ng_RegisterCmd \"ngparsegeometry\" \"netgen\" \"ngparsegeometry\" \"parse geometry\"\n" ,"proc nggeneratemesh {} {\n" ,"set err [catch {Ng_GenerateMesh}]\n" ,"if {$err} {\n" ,"puts \"error: mesh generation failed\"\n" ,"}\n" ,"}\n" ,"Ng_RegisterCmd \"nggeneratemesh\" \"netgen\" \"nggeneratemesh\" \"generate mesh\"\n" ,"proc ngsavemesh { fname } {\n" ,"if { [file exists $fname]} {\n" ,"puts \"warning: existing file $fname overwritten\"\n" ,"} else {\n" ,"set err [catch {Ng_SaveMesh $fname}]\n" ,"if {$err != 0} {\n" ,"puts \"error: saving mesh failed\"\n" ,"}\n" ,"}\n" ,"}\n" ,"Ng_RegisterCmd \"ngsavemesh\" \"netgen\" \"ngsavemesh \" \"save mesh to file\"\n" ,"proc ngset { opt {val 0} } {\n" ,"if {$opt == \"meshsize\"} {\n" ,"set ::options.meshsize $val\n" ,"Ng_SetMeshingParameters\n" ,"} elseif {$opt == \"printmsg\"} {\n" ,"set ::options.printmsg $val\n" ,"Ng_SetMeshingParameters\n" ,"} else {\n" ,"puts \"error: unknown option $opt\";\n" ,"}\n" ,"}\n" ,"Ng_RegisterCmd \"ngset\" \"netgen\" \"ngset